Here is a little trick that may help you to target items on scene right after a gotoAndStop/gotoAndPlay
Here is an annoying thing i faced today :
I used to program clips or buttons with several labels, and populate items at each label content when needed.
But in AS3, there is no way to do such things :
button_mc.gotoAndPlay("over");
button_mc.tf_over.text = "rollover text";
does not work at all.
I found a trick that used the Event.RENDER event which occurs after an enterframe : http://www.kirupa.com/forum/showthread.php?p=1914687
But i did not wanted to use an enterframe, and i found a second trick on Senocular site which uses the stage.invalidate()
The invalidate method forces the current displayObject to render itself immediately.
So to sum up the trick, we have to :
- go the new frame using gotoAndStop/gotoAndPlay
- add a listener on stage with Event.RENDER event
- create a function that will populate the new frame
So here is an example where a button needs to go to the "over" frame and fill a text which exists on this frame :
// set a clip as a button
button_mc.buttonMode = true;
// add a mouse rollover listener
button_mc.addEventListener(MouseEvent.MOUSE_OVER, onOver);
// let's go for the trick
function onOver(evt:MouseEvent):void{
// go to the new frame
button_mc.gotoAndStop("on");
// add a new listener on the stage to get the next render event
stage.addEventListener( Event.RENDER, onButtonRollOver, false, 0, true );
// force the current displayObject to trigger the Render event
stage.invalidate();
}
// populate the rollOver frame
function onButtonRollOver(evt:Event):void{
trace("render rollover");
button_mc.tf_on.text = "RollOver text";
// important : remove the listener
stage.removeEventListener( Event.RENDER, onButtonRollOver);
}
I was quite happy to find this trick, but unfortunately there seems to be a deeper problem with the RENDER event : I managed my button with 2 listeners like above (one for rollOver, and another for rollOut).
All seems to be ok, but when I drag the mouse over and out the button quickly, the RENDER is triggered while the targeted textfield is not yet available.
SO, use this trick in your production if you don't intend to move the playhead of the displayObject too quickly. Or else, just wait for another trick....
août 5th, 2008 at 20 h 52 min
Hello
I prefere use my personnal button class FrameLabelButton :
http://www.ekameleon.net/vegas/d...
More easy, you can add the "up", "down", "disabled", "over", "release", "over_selected", "out_selected", …. frames in your movieclip and the class work for you
EKA+
août 7th, 2008 at 9 h 11 min
EKA always ahead…
I will need some time to get around you great framework !
Finally i have chosen an old as2 way to solve this : create a Waiter class.
So i can call the function :
doNext(cb:Function, scope:*, nbFrames:int = 1)
– cb : the callback function called after waiting
– scope : the class/object where the function is
– nbFrames : number of frames to wait
Here is the class code :
————————————————
package net.lecrabe.tools.timer {
import flash.events.TimerEvent;
import flash.utils.Timer;
/**
* @author arthy / http://www.lecrabe.net
*/
public class Waiter {
private static var _callback:Function;
private static var _scope:*;
private static var _myTimer : Timer;
private static var _stageFPS : int = 1;
public function Waiter() {
}
// Init Waiter class framerate first (with stage.frameRate)
public static function initFPS(fps:int){
_stageFPS = fps;
}
// call main function to wait for nb frames until executing the callback function
public static function doNext(cb:Function, scope:*, nbFrames:int = 1) : void {
if (_stageFPS==0) trace("WARNING : Waiter fps=1, please call Waiter.init(fps);");
_callback = cb;
_scope = scope;
var wait:int = int(1000/_stageFPS)*nbFrames;
_myTimer = new Timer(wait, 1);
_myTimer.addEventListener(TimerEvent.TIMER, timerHandler, false, 0, true);
_myTimer.start();
}
// executes callback function
private static function timerHandler(event:TimerEvent):void {
_myTimer.removeEventListener(TimerEvent.TIMER, timerHandler);
_callback.apply(_scope);
}
}
}
————————————————
And finally i just have to write this :
import net.lecrabe.tools.timer.Waiter;
// need to set the right fps to the class
Waiter.init(stage.frameRate);
// move to the new label
gotoAndStop("myNewLabel");
// wait for 1 frame
Waiter.doNext(onPopulateMyClip, this);
function onPopulateMyClip():void{
// timeline playhead is stopped, i can populate the movieclip
}
I know there may be others way, but finally this one is quite simple i think.
septembre 30th, 2009 at 17 h 07 min
ils sont mignons à parler anglais
kiss & love
janvier 12th, 2010 at 12 h 54 min
By the way, this problem no longer exists on Flash Player 10 (even 9 as far as i remember)