Abstracting Assets from Actionscript in AS3.0 – Asset Libraries and DuplicateMovieClip

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.

AssetLibraries 1

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.

AssetLibraries 2

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!

AssetLibraries 3

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.

AssetLibraries 4

Now let us compile, and see what we get!

AssetLibraries 5

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

Share this post: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Facebook
  • Google Bookmarks

44 Responses to “Abstracting Assets from Actionscript in AS3.0 – Asset Libraries and DuplicateMovieClip”

  1. 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.

  2. 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 :)

  3. Thanks a lot for posting this daryl. I’ve had a lot of trouble finding how to access the library from a loaded SWF.

  4. Glad you like it :)

  5. Why can’t people just read the documentation? It’s pretty clear in there.

  6. If people were reading the documentation and understanding it, I wouldn’t be seeing this question asked on a regular basis :)

  7. 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.

  8. 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.

  9. @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.

  10. 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!

  11. hi,

    would that work with a component in the targeted external swf’s library

  12. how would you then reference it in the linkage id
    and then call it back in the document class ?

  13. not too sure about that, cooljack. :( Sorry.

  14. fishTacoGuy Says:

    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?

  15. Hi fishTacoGuy:

    the easiest solution would be to just … Load it again.

  16. fistTacoGuy Says:

    So are you saying it’s impossible, or just not easy?

  17. 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.

  18. 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.

  19. 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.

  20. 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.

  21. 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});

    }

  22. 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.

  23. Hi guys
    quick question, how would you deal with abstract classes ??

  24. Abstract classes are not supported in AS3.0. Your best bet at implementing some sort of abstract functions would be to use Interfaces.

  25. 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?

  26. If the Class is compiled, then yes. It does not necessarily need to be a DisplayObject.

    Cheers
    Daryl

  27. Nice explaination! Thank you!

    What is the purpose/goal that you set the parameter useWeakReference on TRUE?

    Regards
    Cor

  28. 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

  29. 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).

  30. 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?

  31. 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

  32. Thanks Daryl.
    And Jerry==fail.

  33. 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?

  34. 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

  35. a complete version of bouth bigspaceship and darylteo:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 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"));
  36. And then the smart way of duplicating or clone a movieclip

    1
    2
    3
    var dClip:MovieClip = this;
    var new_mc = new dClip.constructor();
    this.addChild(new_mc);

    Have fun :D

  37. 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

  38. 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.

  39. 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.

  40. 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.

  41. 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)

  42. 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.

  43. 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

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>