PDA

View Full Version : Event.RENDER fires before all on stage objects are instantiated???


abeall
07-29-2007, 03:25 AM
I have an application that has several "view states", and I made the mistake of approaching the project the way it was done in AS2: I put each view on its own frame. It was too late when I discovered that gotoAndStop() no longer is immediate -- a staggering problem on many levels.

So, since I need to add event listeners and such to many(several dozen) interface elements on those frames, I've attempted to use the RENDER event to ensure the objects have all been instantiated on the frame before I access them. In other words, something like this(not actual code, there is a lot of code in my project):

function MyApp extends MovieClip(){
stage.addEventListener(Event.RENDER,onRender);
}
function changeView(viewState){
gotoAndStop(viewState);
stage.invalidate();
}
function onRender(evt){
myMovieClipOnStage.x = 5;
}


The problem is that onRender is called before myMovieClipOnStage has been instantiate by Flash. I know because Flash throws a "Cannot access a property or method of a null object reference." error, and trace(myMovieClipOnStage) outputs "null." The problem is also intermittent -- it seems that if I change states rapidly or the player window is large(so I guess render times take longer) is when it happens most often. What should I do?

And although I'm not keen on rebuilding this thing, how should have I approached multiple view states in a Flash AS3 project? There are some shared elements and some not shared.

I've also noticed that if I addEventListeners to on stage objects, even when I navigate off the frame so they no longer exist, the event keeps firing, even though I set them as weakReferences.

senocular
07-29-2007, 02:38 PM
This is a big problem that was not given enough attention during development. a) AS3 was catered to Flex (no frames). b) AS3 is still fairly new and see point a).

I have found that the RENDER event (what should be our savior for these related gotoAndPlay issues) is not dependable. Two cases include RENDER firing prematurely as the result of other events, such as CLICK or COMPLETE and the fact that (bug) if you use ref.removeEventListener(Event.RENDER, ...) you will in fact remove all RENDER event listeners. Since Flash CS3 components do this... you're in a bit of a pickle.

Solutions: For basic display object usage, you can work on using the ADDED event instead of render to determine class instantiation - checking specifically in ADDED for the instance(s) you're looking for. If timing is not a super big deal, you can also use the ENTER_FRAME event to wait a frame to where you know you can be sure your instances are created. You can also go Flex-esque and not use frames for states (as inconvenient as that can be sometimes). Then you are in specific control of instantiation and would know when each instance is available and not. So instead of having something happening on different frames in your main timeline, each state would be its own movie clip symbol in the library and you would just add/remove them to the main timeline when needed or navigated to.
: )

abeall
07-29-2007, 08:53 PM
Interesting. I hope this gets ironed out a little bit more in the next version. At any rate, the multiple frame route was providing no joy after a lot of tinkering, so I decided to just scrap that approach altogether and now I'm just doing a hide-and-seek routine with all interface elements on one frame -- switching views in my app simply sets the visibility to be appropriate for all display elements involved. That's quite dirty, though, as now my stage in the IDE looks like a mess with all elements visible(trying to organize layers, but still), and all the hidden display elements at runtime are still consuming resources, though invisible. It would be a lot involved to change the structure so elements are added/removed at runtime, and putting everything in a container clip poses some challenges with the current architecture. It's a small enough app I'm willing to say "it works" but I'm definitely going to have to come up with a different workflow in the future. I'll probably make each view state a MovieClip with a base class of "ViewState" and handle it from there... designing is not going to be as fun, but I might be able to put instances on the stage at design time just for reference, perhaps on a guide layer.

I wish I could get into Flex. :-/

Flash Gordon
07-29-2007, 09:04 PM
It was too late when I discovered that gotoAndStop() no longer is immediate -- a staggering problem on many levels.
Interesting. What do you mean by that?

abeall
07-29-2007, 09:29 PM
Interesting. What do you mean by that?

Imagine a timeline in Flash, where on frame 1 you have a preloader, on frame 2 you have "alpha_mc," and on frame 3 you have "bravo_mc." In AS2 you can do this:

// after preloader is done on frame 1
gotoAndStop(2);
alpha_mc._x = 55;
gotoAndStop(3);
bravo_mc._x = 100;
// etc


In AS3, you get this:

// after preloader is done on frame 1
gotoAndStop(2);
trace(alpha_mc); // outputs "null"


In other words, after you gotoAndStop(2), alpha_mc is not yet instantiated by Flash, so alpha_mc is null, so you can't modify its x value. You have to set up some sort of asynchronous(uuggh how I loathe asynchronous events that should be synchronous) to try and catch when the on stage elements have been instantiated. In my case I was using RENDER, which to my understanding was supposed to happen at the end of a frame when Flash is about to draw everything. Yet somehow, RENDER was firing before everything on the frame instantiated. Apparently its buggy, as senocular pointed out in several ways.

Flash Gordon
07-29-2007, 09:37 PM
Alrighy, thank you for taking the time to explain what you meant.

Cheers
:)

abeall
07-29-2007, 09:58 PM
No problem. And by "a staggering problem" I just meant that the way Flash apps were almost always done(placing different major view states on separate frames and navigating between them at runtime) is no longer a reasonable way to do things.

senocular
07-29-2007, 11:51 PM
No problem. And by "a staggering problem" I just meant that the way Flash apps were almost always done(placing different major view states on separate frames and navigating between them at runtime) is no longer a reasonable way to do things.

I've heard of a few projects that started off as AS3 but went back to AS2 because of this, and this is something I've been continuously struggling with for my Mii Editor. I have a couple of hacked solutions, but nothing is really ironed out yet.

Flash Gordon
07-30-2007, 04:52 AM
So this this something adobe plans on addressing or is it just a way of life now?

Mazoonist
07-30-2007, 04:56 AM
Help me out here... is it my imagination, or....

It seems like in AS2 you could say:
gotoAndPlay('label");

and even if there was a stop() on that frame, the player would go to that frame and start playing.

Now, however, with AS3, when you say gotoAndPlay("label"), if there's a stop() command on that frame, it'll go there and stop.

Flash Gordon
07-30-2007, 05:04 AM
running a simply test suggest it is your imagination....

Assertnfailure
07-30-2007, 05:20 AM
People always did that? I never used frames for laying out different view states. I'd imagine it would be a lot cleaner to just have each view state in its own movieclip container and just attach the container of the state you want to display.

abeall
07-30-2007, 06:48 AM
People always did that? I never used frames for laying out different view states. I'd imagine it would be a lot cleaner to just have each view state in its own movieclip container and just attach the container of the state you want to display.

:) I knew someone was going to say this, which is why I said "almost always" -- and yes, to answer your question, most people do it that way.

Yes, it looks like container MCs will be the second best solution for now. It just requires more setting up, in some cases a lot more setting up(imagine view states within view states within view states -- gets ugly when each view state needs its own container which you have to hard code in). Like I think I mentioned, I'll probably end up still laying everything out on the timeline in frames, only each frame will have the corresponding MovieClip, and I'll guide those layers out, basically use it as a reference and direct access to the visual layout, so design time is easier.

Flash Gordon
07-30-2007, 07:25 AM
@abeall, I tried what you mentioned about the AS2 vs. AS3 I couldn't repeat the problems you are now experiencing. Do you think it would be possible to zip up a sample AS2 of what you mean vs the same thing as AS3 that doesn't work?

senocular
07-30-2007, 01:01 PM
So this this something adobe plans on addressing or is it just a way of life now?

Fact of life now. The issues are known, but when they are going to be fixed, I can't say. I am pretty adamant about getting these things fixed, though. I hate that they exist and that no one did anything about it earlier.

And though everyone might not do this, frames for states is very common. Not only is it common, but easy to use. Benefits include having accessible backgrounds that extend through all states, and using tweens to easily distribute highlights and things like that (I mentioned the Mii Editor before, but if you go there ( http://www.miieditor.com/ ) and click through the tabs at the top, the green tab highlight is actually a tween from left to right going through the frames - a lot easier then the alternative; the background is also one set of graphics stretched across all frames)

I make some examples showing some frame navigation/render issues if you want.

senocular
07-30-2007, 02:46 PM
I've uploaded some examples of navigation/render event issues in a zip:
http://www.senocular.com/pub/asorg/AS3NavigationIssues.zip

They rely on traces so you'll need to test them in Flash CS3. Also are some related AS2 comparisons showing how they did (and are expected now to) work.

The first one to start with should be basic nav access - it sets up the core issue with frame navigation (since it is not immediate with AS3)

senocular
08-01-2007, 03:25 AM
Did those examples help anyone?

abeall
08-03-2007, 06:36 PM
I downloaded the files and took a look, I think it illustrates the various problems well. There are really a lot of situations that cause problems. I hope you are throwing this around internally :) Where's the petition I can sign to get this addressed? ;)

senocular
08-03-2007, 06:49 PM
I have raised a stink about this issue and will be working to make sure they get addressed. If you find anything else, just let me know and I will put it on my list of things to look out for. : )

blakflag
09-15-2007, 09:46 PM
:mad: Oh my god.. I can't believe that Adobe released Flash CS3 with this problem. I use Flex at work (and it IS awesome), but I still wanted to be able to use Flash for my older projects, and like so many others I use different frames to lay out different screens in my app.

So I pony up for CS3 and now I have to deal with this???

So far the best solution I have come up with is something like:

public function goNewScreen():void
{
gotoAndStop("newscreen");

addEventListener(Event.ENTER_FRAME, _doEnterFrame);

function _doEnterFrame():void
{
if (!myMovieclip) return; // wait for it... wait for it...
// now do it!
removeEventListener(Event.ENTER_FRAME,_doEnterFram e);
myMovieclip.doWhatever()
}
}

But this is hardly an elegant solution on a large scale. I guess I'll join the herd and use attached clips for my states. Or maybe laying each state on its own layer and turning on and off the visibility. BLEEEECH!!!!

I still love Actionscript 3 but this is really an awful drawback.