Nov 30, 2007

AS3: Linked MovieClips from remote SWFs.

We've had a situation here. It's irritating. It's annoying. It happens over and over. It is as follows:

- SWF A wants to load SWF B.
- SWF B has a linked MovieClip in the library. This is a simple extension of MovieClip, nothing fancy. Let's call it Foo.
- SWF A wants to call new Foo(); and add it to the stage.
- Compiler hates us.

Daniel, Josh and I sat together and had a pow-wow and came up with this:


import flash.utils.getDefinitionByName;
function getAsset($str:String):MovieClip
{
var c:Class = Class(getDefinitionByName($str));
return new c();
};


(Amazingly, it worked out so that I typed lines 1 and 2, Daniel typed lines 3 4 and and Josh lines 5 and 6. Therefore, we all share joint credit in this astounding revelation.)
This function will comb for a class by string, assume it's a MovieClip and return it. Now we just agreed on a simple convention: All linked movieclips will begin with "lib.".

So I can easily write:


var myFoo:MovieClip = getAsset("lib.Foo");
addChild(myFoo);


from SWF A once SWF B is loaded. Presto!

Daniel is going to build this into a nice, pretty utility class. When he does, rest assured that we'll distribute it here.

Share this Post


                           

Comments


Jelospode     Oct 05, 2009
Intresting, this was actually a very great read! thanks































Watch Movies Online Now

numediaweb     Jan 22, 2009
a complete version of bouth bigspaceship and darylteo:

// utility to get external swf library classes
function getAsset ($obj:Object, $str:String):MovieClip {
var c:Class = $obj.applicationDomain.getDefinition($str);
return new c();
}
// a usage example
// test.swf contains an MC with class name _dump
// i will load it inside my current main.swf
function assetLoaded (e:Event):void {
trace (e.target);
var temp:DisplayObject = getAsset(e.target, "_dump");
addChild (temp);
}
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener (Event.COMPLETE, assetLoaded, false, 0, true);
loader.load (new URLRequest("test.swf"));


LouisTovar     May 24, 2008
Just so you know, using this method and having the asset loaded as a child for more than 2 frames makes the loaded swf impossible to garbage collect. T_T

JohnBailey     Apr 25, 2008
While there are others out there and that take nice usage of Singletons and so forth, this is a fine tutorial and a simple foundation showing that this technique can be done. Moreover, sometimes "stronger" techniques can be more difficult to get running, but that's just me. This is just what I've been looking for. Thanks and thanks for everyone posting other examples. :D

catalin     Apr 16, 2008
I have the same problem like Jarrod, does anyone know a solution for this? Thx.

Jarrod     Jan 06, 2008
Hey guys, i've got a remote swf problem.... heres what happens:

- main.swf loads assets.swf
- it then adds a new Nav() from the assets.swf
- the Nav then adds a new NavItem()
- NavItem has box_mc in it
- box_mc should stop on frame 1 - but it doesnt!!

The first frame doesn't trace() either. A stop() on the second frame works - but not the first :(

Here's an example: http://www.thirstboards.com/StopExample.zip

Could anyone give advice? a workaround? Or maybe an alternative method for working with classes across multiple swfs?

Thanks very much :)

Jesse Freeman     Dec 27, 2007
Not to beat a dead horse but I have a class that does what you are talking about as well. I just added it to my blog over at flashartofwar.com (here). This singleton class lets you get a library asset by Class Name then pass it a config Object as well. The library class should extend a class that accepts the config Object but other then that it is really simple to do and works great for skinnable applications.

Kevin     Dec 06, 2007
Didn't Ted Patrick cover this here?
http://www.onflex.org/ted/2007/11/creating-class-instances-dynamically.php

Ben Cline     Dec 01, 2007
I like to do this with a return type of just DisplayObject that way you can define the variable as whatever display object you want to be using it as, that's just how i've been doing it anyways.

Moshe     Dec 01, 2007
Thanks guys. I was just looking at this the other day. as Daryl said, If you want to instantiate a class you wrote at runtime you will have to force the compiler to compile it but this method will work. all you need to do is importing the class and define a dummy variable:

import com.myPackage.MyClass

private var dummyVar:MyClass

function getInstanceByName( str:String ):* {
var c:Class = getDefinitionByName( str ) as Class;
return new c();
};

Daryl Teo     Dec 01, 2007
I've written something similar to this in the past, and have blogged about it. Its definitely not a revelation to most people, but this technique isn't getting as much publicity as I'd hope.
Here is my post (bit of a self-advert here, hope you don't mind :) )
http://darylteo.com/blog/2007/11/16/abstracting-assets-from-actionscript-in-as30-asset-libraries/

An important thing to note also is that if you have a class but do not force the compiler to compile it, your loaded swf will not contain the class definition, and thus this method does not work. :)

joshspoon     Nov 30, 2007
Man a buddy of mine showed me this a few months ago. I wish i'd have know you were having that problem. I feel your pain. I haven't gotten around to making a utility for it, so I'll be looking forward to the post.

Jamie     Nov 30, 2007
@Unformatt:

I'd keep two versions: the getAsset version and one like yours. For that matter, I think I would probably rename it createDisplayAsset and createInstanceByName. Ah nomenclature!

The reason I like createDisplayAsset is that it assumes a MovieClip or DisplayObject of some sort is being returned. Most of the issues I've struggled with in this fashion relate to swf a loading an asset from swf b, so unless I was say... creating a dynamic class from an XML file (which I personally try to avoid), I wouldn't use createInstanceByName very often.

Pal ferrie     Nov 30, 2007
Fantastic guys.
Well done, I have also had this problem in the past so i can appreciate how cool it is.
You would have thought with AS3 that Adobe would have resolved this one.

Unformatt     Nov 30, 2007
Should probably make this even more generic, since it doesn't just apply to Library assets or MovieClips.

function getInstanceByName( str:String ):* {
var c:Class = getDefinitionByName( str ) as Class;
return new c();
};


Speak






Submit »