Stop() on timeline for native targets

Hi everybody,

When I developed in flash I used to call the stop() function on the timeline to indicate where an animation ends and I triggered animations using goToAndPlay(). I believe that’s the standard way and how everybody does it.

Now, in OpenFL I’m targeting native platforms and as it’s not possible (AFAIK) to put haxe code on the timeline I don’t know how to properly trigger animations as they won’t end at the right frame if I simply call goToAndPlay().

I know that a dirty hack like giving the stop frames special names and animating by stepping trough each frame manually inside a for loop where I check the frame’s name is possible, but that’s considerably harder then the workflow I had in flash.

How do you guys do this?

EDIT:
Forgot to mention, I author my SWFs in Flash Professional and load them with the SWF library.

It’s a good question, parsing the AS bytecode is complex (though theoretically possible), I don’t think custom frame script support is available through the custom platform SDK, yet, in Flash CC. Open to ideas or contributions on the subject

I took a look at the the custom platform SDK’s API and this seems to me like it could help (IFrame::GetScript()): http://helpx.adobe.com/flash/CPSDevKit/APIDocs/class_d_o_m_1_1_i_frame.html#ad153591df5021e442335924014b3ea5d

“This function gets a string that represents the frame script associated with this frame.”

As far as I understand, it allows you to get the code that’s on the frame as a string.

Also, in a CreateJS project in Flash Pro adding javascript code to the timeline is possible and that’s an extension too (at least used to be), so you should have access to the same stuff they do.

I hope I didn’t sound demanding, I’m actually trying to help :slight_smile:

Hi Joshua,

I think I have the perfect solution for this. I haven’t tested this code and some of it might not be 100% valid haxe code, but I think it’s totally doable.

Only a couple very minor additions to the MovieClip class are necessary:
private var frameScripts:Map<Int, Function>;

And these two lines inside stage_onEnterFrame’s for loop:

var script:Function = clip.frameScripts.get(clip.get_currentFrame());
if(script != null) script.invoke();

Here’s how you would add a script to a frame:

frameScripts.set(1, function():void { // The code of the script goes into the anonymous function stop(); } );

That can be written manually like so and would probably work fine, but the main purpose is to be used with the openfl flash plugin which would generate such code based on what it finds inside symbol’s timeline’s frames.

So the idea on the plugin’s side is that the plugin generates a haxe class for every symbol inside the swf exactly like the SWF library does nowadays, but also generates lines like the one above, where it assigns functions to the function map.

Here’s an example of what a class generated by the openfl flash plugin would look like (I based this on the MovieClip.mtt template and left in the keywords that need to be replaced to not lead to confusion as to how I got those values):

Here’s a link as it’s badly formatted below.

class ::CLASS_NAME:: extends MovieClip { // exactly the same as before public function new () {
	// This is the same as earlier
	if (!SWF.instances.exists ("::SWF_ID::")) {
				
				SWF.instances.set ("::SWF_ID::", new SWF (Assets.getBytes ("::SWF_ID::")));
				
			}
			
			var swf = SWF.instances.get ("::SWF_ID::");
			var symbol = swf.data.getCharacter (::SYMBOL_ID::);
			
			super (cast symbol);
	}
	
	// Now here's where the frameScript map population would happen. All the code below is
	// generated by the openfl flash plugin
	
	// frames 1, 17 and 29 are random values. Real values would be determined by the openfl
	// flash plugin based on which frames actually have code on them
	
	frameScripts.set(1, function():void {
		// The code inside the anonymous function is literally a copied string of text that was
		// in the frame inside Flash Professional. I think that the string of the frame's content
		// can be gotten by the getScript() function in the SDK.
		stop();
	} );
	
	frameScripts.set(17, function():void {
		// Maybe this frame has some different code
		goToAndStop(1);
	} );
	
	frameScripts.set(29, function():void {
		// Maybe this frame has some haxe code that isn't valid actionscript code
		if(FileSystem.exists("myDir") == false) {
			FileSystem.createDirectory("myDir");
		}
	} );
	
}

};

The best thing about this approach (as opposed to embedding the code inside an SWF and parsing it later) is that, as you can see, the necessary changes are very small.

Another benefit is that it would be possible to put any haxe code in the frames (inside the Flash Professional tool), code that doesn’t have to be valid in actionscript too.

What do you thing? Could you implement something like this so that we can put haxe code on frames in Flash Professional?

I heard today that frame script is supported by custom plugins in Flash CC, just no highlighting or code completion, but that’s more than good enough for a simple stop. I think this would be very excited (though I wish I had more time to work on this myself)

So you’re thinking we do a private frameScripts field, which we could add to, possibly, using the addFrameScript method?

http://www.as3dp.com/2009/09/a-closer-look-using-movieclipaddframescript/

It would be super exciting if this integrated with Flash CC plugin output

Yes, that would be great, I’m really glad it’s possible :smile:

But there’s also something else to my suggestion:
Maybe I’m not very informed on the subject, but as far as I know, the way flash does it is they take code that’s on the timeline, transform it into AS bytecode and write that in the .swf file. Parsing those Actionscript tags is also necessary on runtime. Maybe we could skip that whole thing and the plugin could simply output the frame code to the classes it generates (by literally copying and pasting the text) like in the example class I posted. I assume embedding code into the swf would not allow us to call functions that are defined in some external .hx file (would it?), but generating the classes would, I guess. I also don’t see a reason why the code would need to be embedded in the SWF as SWFs are not end results like they used to be in flash, but just an asset that gets used by the application. (They are end results for the flash target, but that’s not the same swf, that’s a new one generated later) Take this with a pinch of salt, maybe I’m completely missing something.

Maybe you noticed this idea in my previous post, but I thought I should emphasize it.

I also have another suggestion regarding generated classes. I haven’t used the openfl flash plugin yet, so maybe it already does it like this, but I have noticed that when the SWF library generates classes, they all extend the MovieClip class and the “base class” value from Flash Professional (in the “export for actionscript” dialog) is ignored. I looked into it and found out that that information is not embedded (afaik) in the SymbolClass tag in the SWF, so I guess reading the base class name from the swf was impossible. But with the custom platform extension you probably have access to the value from the “base class” field and I suggest the plugin should use it when it generates classes of symbols. The base classes would be in external .hx files of course.

I believe this is pretty important as it would allow for the swf to contain instances that actually have some functionality instead of just assets (MovieClips). I know adding instances with logic that extend these symbol classes is already possible in code, but then the swf is used just as an asset container and can’t be used as an application layout too. I’m sure other use-cases exist. There are probably lots of other reasons why adding base classes in Flash Pro was possible with Actionscript.

This is probably even more important than code on frames :smile:

Can you implement this too?

BTW, I feel it’s great that you are active on the forums helping people out and taking their suggestions.

I think this is a great list of why having custom plugins for Flash CC really starts to open up horizons, I wanted to get a proof-of-concept using any SWF, but afterward, I think there is a lot more nuance that can be supported when we’re working closely with the editor.

I don’t have bandwidth to work on the plugin much right now, but am supporting standard SWF. I agree that parsing ActionScript Bytecode after the fact is pretty messy, though handling even simple things like stop() or gotoAndPlay() would be nice, but long-term – having Haxe-based frame scripts, and pushing this into a Haxe compile to be attached to the clips when the are generated is 100% the best, as this is much more robust, and the direction Flash CC is heading with the custom frame script support

I suppose the best first step would be proof of concept, perhaps embedded in the SWFLite code

and I try, working together is fun :slight_smile:

Hi, I’m tinkering a bit with the flash plugin trying to generate .hx classes for every symbol in the FLA document. So far I successfully wrote a for loop that writes to the console the symbol name, symbol class and symbol base class for every symbol in the document. There’s one problem I ran into though: Flash Pro doesn’t let the user enter the base class (for a symbol) whose Actionscript class doesn’t exist. Do you know of any way to disable that check (maybe via the plugin) or, even better, to customize the checking behavior so that it checks .hx files for classes?

EDIT: Also, can you tell me how to debug the plugin while it’s running in Flash Pro? I don’t think I’ll get very far without debugging. I’m currently using Visual Studio only for code editing (can’t find headers in which “Dl_info” and “dladdr” are) and the provided .bat script to initiate compiling. I wouldn’t mind switching to a different IDE if I could debug with it.

If you’re interested in helping, I could put you in contact with the guys I’ve been talking to, to help sort out technical issues. That one sounds like an edge case that might not be supported, but we could ask. Feel free to send me a DM with your email if you want :slight_smile:

Hi, two years after, is any solution for stopping a movieclip at his end ?
For the moment, i use :

this.addEventListener(Event.ENTER_FRAME, finAnimAide);
		
private function finAnimAide(evt : Event) : Void {
	if (aide.currentFrame == aide.totalFrames) {
		aide.stop();
		this.removeEventListener(Event.ENTER_FRAME, finAnimAide);
		}
	}

but i think it could be better! :slight_smile: and i t works half of the time cause of the frame rate, sometimes, it overpasses the right frame number and it loops!

clip.addFrameScript (frame - 1, function () {
    clip.stop ();
});

Let me know if it works :slight_smile:

Having basic stop gotoandplay etc parsed from the swf in the timeline would be awsome.
However; since this is probably not going to happen… (yet?), i’m using a different approach…

In my OpenFL based framework, i have a system for automaticly parsing the displaylist each frame.
From this information i acutally do a lot but one of the things is to check for frameLabels when a movieclip is added to the stage. And when i find code marked with “@:” in a label i will analyze the label for a script and add it using addFrameScript for the corresponding frame…

So this means i can write basic instructions/code in framelabels.
( @:stop , @:gotoAndPlay(10), @:this.parent.play() etc… ) … its perhaps not the ultimate solution, since there could be a little overhead if the displaylist is really big but it works pretty good and is the closest i can get to scripts in the timeline at the moment :slight_smile:

1 Like