Abstracting Assets from Actionscript in AS3.0 – Asset Libraries and DuplicateMovieClip
Nov 16, 2007 Articles
Introduction
I write this article because it seems to me that quite a few people still have no idea how to duplicate external assets (such as duplicating MovieClips, for example). Thus, I decided to take this opportunity despite there being quite a few articles that document this. If I haven’t bored your by now, read on!
First, Some History
Assets in Flash are normally quite coupled with the SWF. This is probably a result of the long years of timeline scripting that has been burnt into our memories. In Actionscript 2.0, however, the process of abstracting Assets from Actionscript was slightly alleviated through the copious use of duplicateMovieClip(). I too, used to be an avid user of duplicateMovieClip(), until I made the transition to Actionscript 3.0, But before then, duplicateMovieClip() was my quick and dirty solution to many situations I came across in Flash.
Abstracting Assets from Actionscript in Actionscipt 2.0 was relatively simple. One need only separate his/her assets into separate swf files, and simply loadClip() them into the SWF, and employ the use of duplicateMovieClip(). In Actionscript 3.0, however, this situation has changed as Adobe saw fit to remove (or shall we say, omit) the duplicateMovieClip() method.
Now, Adobe recommends the use of the “new” keyword to instantiate multiple instances of a Class. From the Actionscript 2.0 Migration reference:
In ActionScript 3.0, use the new operator to create a new instance.
This doesn’t really help us abstract our Assets from Actionscript. Most of us who have played around enough in Actionscript 3.0 would know that this requires that the Class be part of the SWF calling it, and in facts forces us to embed our assets within the SWF. Using the Loader class to import external SWFs does not expose any classes that we may use to invoke the “new” operation. At least, not obviously, as we shall see later.
Asset Libraries
Today we will go through a step-by-step process on how to create an Asset Library. Note, of course, that this isn’t the only way to handle External Assets, but this is the way I like to do it.
Creating an Asset
First things first, we create an Asset. This can be anything from a Shape to a Sprite.
At this point you need to note the “Class” field. This field is important as it is how you will be referencing this class externally.
Next, click OK, and ignore the prompt that pops up when you do. Now, you may export your SWF (Lets call it “circle.swf”). Once that is done, start another SWF, which is where we will try to load our external Asset.
Loading an Asset
Now we get to the nitty gritty of it all. First we need to create some code that will load our Circle, so that we can duplicate it. Let us create an event handler too, to handle Event.COMPLETE.
Above you see some code for loading external SWFs using the Loader class. So now what we are going to do is use what is called the ApplicationDomain to get the class definitions from within Circle.swf!
Lets explain what we did there. We accessed the ApplicationDomain of the SWF we loaded, and then we got the definition of the Class we wanted, in this case the Circle class we did in the first SWF. Note that the name of the definition has to be exactly the same.
Now let us compile, and see what we get!
Closing
Using this technique, it is simple to create a library of assets, that you can load into your main SWF and duplicate them! While this isn’t the only technique, nor the only method of utilising the ApplicationDomain, this is (in my humble opinion) the best way to go about Abstracting Assets from Actionscript.
Links
Here are some links if you want more information, as well as a zip of source code so that you may look at the code directly.
http://blogs.adobe.com/rgonzalez/2006/06/applicationdomain.html
http://livedocs.adobe.com/flex/2/langref/flash/system/ApplicationDomain.html
Asset Libraries Tutorial Files
Tags: actionscript, AS3, assets, copies, duplicate, duplicateMovieClip, Flash, getDefinition, libraries, movieclip, swf











November 20th, 2007 at 3:32 am
Nice article, been trying to sort that out for a while now.
Is it possible to access an asset as a shape insted of a movieclip?
You can only access the linkage panel of a symbol if it is a movieclip not a graphic so you can’t set the class for the shape. I need my assets to be as lightweight as possible as I have lots of them so having all the baggage of the movieclip class when all I need is flash.display.Shape is far from ideal. Even exporting as a sprite would be better than movieclip.
I tried setting the base class to flash.display.Shape but it just changes it back to movieclip again. However when I set it to sprite it works. However i’m not quite sure if flash is exporting it as a movieclip cast to a sprite or if it really is a sprite without all the movieclip baggage.
November 20th, 2007 at 3:59 am
Unfortunately the Flash IDE doesn’t even let you export to Shape at all. Shapes are vastly different from Sprites and MovieClips.
Everything created in Flash IDE is a DisplayContainer (as in they can hold other DisplayObjects as well) which a Shape is not. Therefore it is not possible (as far as I can see).
Quoted from the AS3.0 Reference:
The Shape class is used to create lightweight shapes by using the ActionScript drawing application program interface (API). The Shape class includes a graphics property, which lets you access methods from the Graphics class.
Therefore the only reason why you would use Shape is to use the Drawing API. This means you can just as easily create a class definition that extends Shape and draws using the API.
Hope that helps! Let me know how it goes
November 20th, 2007 at 12:19 pm
Thanks a lot for posting this daryl. I’ve had a lot of trouble finding how to access the library from a loaded SWF.
November 20th, 2007 at 12:28 pm
Glad you like it
December 10th, 2007 at 6:45 pm
Why can’t people just read the documentation? It’s pretty clear in there.
December 10th, 2007 at 7:47 pm
If people were reading the documentation and understanding it, I wouldn’t be seeing this question asked on a regular basis
January 8th, 2008 at 12:50 pm
hi,
i have two questions- does it have to be load external swfs? can it be a movieclip in the library?
would this work if i want to make these duplicated circles as mask?
bear me that i am new to as 3. i did my_mc.mask = loader; and didn’t work.
i know i must have missed something.
January 8th, 2008 at 1:02 pm
update: i tried
var mask_mc0:MovieClip = new MovieClip();
mask_mc0.addChild(loader);
but only one circle did the masking, the rest shown as shapes.
January 9th, 2008 at 2:44 pm
@pei: there is no point in using this method to handle Internal assets. To duplicate Internal assets you use the “New” keyword.
For your other question… the problem is you’re using the Loader to mask. Using this method, you are using 1 Loader so of course you will only have 1 masked.
What we are doing above is duplicating a specific asset from an external library (that 1 Loader). So you need to be working with the instances that are created, not the Loader.
January 11th, 2008 at 8:46 am
Hi Daryl,
thanks for your reply.
what i want to do is having circles duplicated more and more, so the mask becomes bigger and bigger.
do you mean, if i want to have the mask with duplicated shapes, i should use “new” instead of loading external swf into a loader? thanks!
January 13th, 2008 at 10:08 am
hi,
would that work with a component in the targeted external swf’s library
January 13th, 2008 at 10:10 am
how would you then reference it in the linkage id
and then call it back in the document class ?
January 14th, 2008 at 5:02 am
not too sure about that, cooljack.
Sorry.
January 30th, 2008 at 2:26 pm
Hey, helpful. I found the adobe docs on this a little confusing myself and the part I thought made sense didn’t work
. Now what if one where in a situation where they had a lot of published swfs that were done in as 3.0, but there was no way to go and assign linkages in the library.
In other words can you suggest a way to load a .swf file, and knowing nothing about what’s inside, create a new instance of that .swf?
January 31st, 2008 at 6:54 am
Hi fishTacoGuy:
the easiest solution would be to just … Load it again.
February 3rd, 2008 at 8:29 am
So are you saying it’s impossible, or just not easy?
February 3rd, 2008 at 2:51 pm
It is “impossible” to do so with the method above, unless you have assigned a DocumentClass to your .swf. But that would require you to know the inside of your .swf.
Another method you might want to look at is a deep-copy using ByteArray.
But seriously, just load it again, and save yourself a ton of pain.
February 7th, 2008 at 1:54 pm
FYI, You can have a library of symbols and export each out of the Library by right clicking each one and exporting a SWF from there.
Helpful if you have a large .fla and only want a few of the assets.
February 11th, 2008 at 11:22 pm
thanks…
might i suggest a standard i hope to put in place in my work
of encapsulating all content of any external loaded swfs in a MovieClip called _content
and setting its export to _content, that way a single swfLoader class can always look for _content… and that would be the only strict requirement of the swfs
i would then make a separate new swfLoader for each type of object i load, and refer back to it when ever i need a duplicate of it
a method could also be made to account for when _content does not exsist, and then have it just load a new swf each time a new copy is requested… for my purposes i would have it also trace an alert in such cases however, because this would never be the desired result in my applications.
thank you for this insight on how to duplicate movieClips Daryl. it has been difficult for me to locate such an article in the past.
February 14th, 2008 at 12:54 am
I don’t exactly agree with that. The beauty of this thing is that we don’t have to use multiple swfs for each asset! We can work with just 1 swf, and work from there.
I’m glad the article was helpful
That was my goal when I wrote it.
February 15th, 2008 at 12:23 pm
Hey daryl,
how can i access the linked movie clip in a buttton state? im currently using tweenlite and just wanted some basic interactivity but it seems it can only be fired at runtime, and not on a button handler.
function assetLoaded(e:Event):void {
var circle:Class = e.target.applicationDomain.getDefinition(”Circle”);
var temp:DisplayObject = new circle();
this.addChild(temp);
TweenLite.to(temp,.5,{y:100, delay:1});
}
function toggled(event:MouseEvent):void {
trace(”hit”);
TweenLite.to(temp,.5,{y:10, delay:1});
}
February 18th, 2008 at 5:22 am
Hi Jeff,
I’m unsure what your question is? What is a MovieClip in a Button State?
I’m also not familiar with tweenlite, so I’m afraid I cannot help you there.
March 21st, 2008 at 12:38 pm
Hi guys
quick question, how would you deal with abstract classes ??
March 21st, 2008 at 5:41 pm
Abstract classes are not supported in AS3.0. Your best bet at implementing some sort of abstract functions would be to use Interfaces.
March 21st, 2008 at 6:30 pm
sorry, just meant classes that are not linked from library. Would having them imported in the loaded swf make them available in the same manner?
March 21st, 2008 at 10:45 pm
If the Class is compiled, then yes. It does not necessarily need to be a DisplayObject.
Cheers
Daryl
April 19th, 2008 at 1:01 am
Nice explaination! Thank you!
What is the purpose/goal that you set the parameter useWeakReference on TRUE?
Regards
Cor
April 19th, 2008 at 2:30 am
Hi Cor.
The UseWeakReference simply means that the EventListener does not count as a reference to the Object. This means you don’t need to remove the event listener for Garbage Collection to occur.
Just makes things easier for me
Daryl
May 25th, 2008 at 1:44 am
Just want to say, I’m brand spangly new to actionscript scripting, but knowing roughly the possibilities of as1-2 and have landed myself a big project at work.
The duplicateMovieClip function is one of the last little bits I needed to work out before finishing it so spectacular thanks on a extremely well written article (it’s filled in innumerate other holes in my understanding).
May 26th, 2008 at 8:12 am
Hi,
I have a website (http://designwithoutsleep.co/random) where I need to mask duplicated moveclips so they appear within a white rectangle on the stage.
I am pretty confused with this article due to my beginner level of Flash 8. Any ideas what I should do?
June 19th, 2008 at 7:49 am
Cheers for the article, i really wish adobe hadn’t bought marcomedia, somehow i don’t think they would of pulled this kind of stuff…
Alas anyway cheers for the article it was very useful
September 8th, 2008 at 12:55 am
Thanks Daryl.
And Jerry==fail.
January 9th, 2009 at 3:53 pm
Thanks for the article Daryl,
I have a problem however where in my external swf my clip uses a custom base class. This base class extends MovieClip but adds extra functions that I require for my project.
When I load the class into my main swf I can use it as a MovieClip quite fine, however I cannot cast it as my custom base class or use any of its methods.
Do you have any ideas on what I can try?
January 11th, 2009 at 10:22 pm
Is there a reason why you cannot cast?
If all else fails, then I believe you can access its properties via associative notation.
YourDuplicatedMovieClip["yourMethodName"]();
Its been awhile since I’ve worked with Flash so please tell me if that helps.
Cheers
Daryl
January 22nd, 2009 at 8:52 pm
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"));
January 25th, 2009 at 5:50 pm
[...] http://darylteo.com/blog/2007/11/16/abstracting-assets-from-actionscript-in-as30-asset-libraries/#mo... [...]
February 16th, 2009 at 2:20 am
And then the smart way of duplicating or clone a movieclip
var dClip:MovieClip = this;
var new_mc = new dClip.constructor();
this.addChild(new_mc);
Have fun
February 16th, 2009 at 2:25 am
First thing is : this post was written 2 years ago. I am sure someone would have found a better way to do it by now. So don’t need to act “smart”
2ndly, yours doesn’t work. You’re cloning “this” and adding the new clip to “this”.
3rdly, doesn’t solve the problem of what to do if your assets were loaded externally.
4thly, since you have access to the constructor() method, that would mean you had access to the class itself anyway. So you would have been better off using “new classname” instead, since you wouldn’t be achieving anything else extra.
By the way, the link in the trackback above yours is very informative.
Thanks for the input though.
Cheers
Daryl
March 31st, 2009 at 6:06 am
Thanks for your post Daryl!
I’ve got one question maybe you can help me with. Your example wotks perfectly.
I’ve got external swf loaded into the class that is called from the Document class of the main swf movie.
During compiling time I receive constant error in the line of code :
var tempClass:Class = mc.loaderInfo.applicationDomain.getDefinition(”className”) as Class;
The error message is:
“ReferenceError: Error #1065: Variable className is not defined.”
But, if I go through the code step by step via Debugger, it works ok, and throws no error.
If I lauch creater swf, no error as well, and the movieClip is duplicated.
It seems compliler somehow evaluetes, loaded classes before execute it.
March 31st, 2009 at 11:03 pm
Is it an error or a warning?
I suppose there might have been a change with the new compilers, with stricter compile-time checks.
I’ve been too busy working with .NET I haven’t had time to play around with Flash anymore, which is a pity.
April 1st, 2009 at 4:07 am
It is and error.
When I test the movie (ctrl+enter), it appears.
When I launch compiled swf, sometimes it works ok.
Sometimes is looking for Debuger running.
The most interesting thing, when I run Debug movie (ctr+shift+enter), compilation goes perfectly.
Flash CS3 Pro.
April 1st, 2009 at 5:48 am
I managed to get rid of this error. Maybe it willbe usefull for someone else.
Add two lines of code before calling load method of the Loader() class. And pass context as parameter.
var context:LoaderContext = new LoaderContext();
context.applicationDomain = new ApplicationDomain();
loader.load(load(new URLRequest(path), context)
May 12th, 2009 at 11:31 pm
For some reason, I can’t download the sourcecode…it just takes me to the main blog page.
Also, the pictures of the code snippets are blocked on my network. Is there a place that has them in actual text? then again…being able to download that sourcecode may help.
May 13th, 2009 at 12:56 am
Hi gid,
thanks for alerting me to the issues.
The images are all embedded from Flickr. That is the best I can do for now.
The source files are mysteriously… not working. I think a link in the background is missing, or I may have lost it. I’ll see if I can dig it up again, but I wouldn’t hold your breath.
There have been bigger advancements in this area so I encourage you to look for them
Cheers
Daryl