Embedding Resources with AS3

Someone recently asked about “code injection” using AS3. Code injection comes from MTASC, where the byte code is added to an existing SWF. The person wanted to create a Flash 9 SWF with the Flash 9 AS3 preview IDE, and use mxmlc.exe to inject code into it.

This is not possible, but there are some equally powerful alternatives using embedding in AS3. As this whole AS3 thing is fairly new to many, I thought I’d explore it a bit and post some info.

Using the AS3 compiler, you obviously don’t have a library for storing movie clips, graphics, text field, bitmaps, etc. So how do you get these into a SWF? Using the Embed tag. Here’s how that looks:

[as]
[Embed(source=”assetname”)]
private var AssetClass:Class;
[/as]

Here, “assetname” would be the path to a file, usually a bitmap or a SWF. For example, to embed a bitmap named “picture.jpg” in your SWF, do something like:

[as]
[Embed(source=”picture.jpg”)]
private var Picture:Class;
[/as]

Now Picture represents a class that you can create an instance of, like so:

[as]
var pic:Bitmap = new Picture();
[/as]

Notice that because you imported a bitmap, it ends up as type Bitmap.

That’s pretty cool, but importing assets from SWFs is even more powerful. In fact, you can even import Flash 8 SWFs, though you’ll only get the graphic assets in them.

You can embed SWFs two ways, just like the bitmap example above where you embed the whole thing, or you can target a particular library asset from the SWF to embed. The latter is obviously much more powerful. Here’s the syntax for that:

[as]
[Embed(source=”library.swf”, symbol=”linkageID”)]
private var AssetClass:Class;
[/as]

Here, “library.swf” is the name of the SWF holding your assets, and “linkageID” is, you guessed it, the linkage ID of the particular asset you want to embed in your new SWF. AssetClass is again the name of the class that will be associated with that asset.

To try it create a new Flash 8 file and save it as “library.fla”. Create a few shapes on the stage and convert each one to a movie clip, exporting it for AS. I saved mine as “star”, “square” and “circle”. You don’t need to leave the symbols on the stage. As long as they are in the library and exported, you are fine.
Inside the star movie clip, I made a tween that just spun the star around.

Inside the square movie clip, I put the code:

[as]function onEnterFrame()
{
_rotation += 5;
}
[/as]

Then, publish this movie, so it creates “library.swf”.

Now create a new AS3 class, like the one below:

[as]
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;

public class App extends Sprite
{
[Embed(source=”library.swf”, symbol=”star”)]
private var Star:Class;

[Embed(source=”library.swf”, symbol=”square”)]
private var Square:Class;

[Embed(source=”library.swf”, symbol=”circle”)]
private var Circle:Class;

public function App()
{
init();
}

private function init():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align=StageAlign.TOP_LEFT;

var star:Sprite = new Star();
addChild(star);
star.x = 100;
star.y = 100;

var square:Sprite = new Square();
addChild(square);
square.x = 200;
square.y = 100;

var circle:Sprite = new Circle();
addChild(circle);
circle.x = 300;
circle.y = 100;
}
}
}
[/as]

Save this in the same directory as the library SWF, and compile it with mxmlc. When you do so, you’ll get a warning that the ActionScript in the square symbol is AS2, and will be ignored. (I just put it there to prove a point. If you believe me, you can leave it out.)

When you open the new swf, you’ll have your three symbols sitting on stage. The star will be tweening around, but the square won’t move, as its AS2 code was ignored.

Note that you don’t have to import all the assets from the library. You could have a large library SWF with hundreds of elements, think skins, which you could import whichever ones you needed and leave the rest behind. Only the ones you chose would get compiled into your SWF.

Of course, you can also create a Flash 9 SWF with the new AS3 preview IDE, and import assets from it in the same way. And, since those assets could include AS3 timeline code in them, you could actually have the code come along with them. But if you are coding apps in AS3 and embedding resources from external library SWFs, you are probably not the kind of developer who writes timeline code, and you wouldn’t likely want that coming into your nicely organized code base anyway, so for the most part, you are using the SWF to import visual elements only, so it really doesn’t matter whether it’s Flash 8 or 9.

Another big advantage to using Flash 8 for this purpose, at least if you are using FlashDevelop, is that when you add the library SWF to your project, you can actually expand it and see what exported assets are in it, and double click on them to add the linkage name directly to your code. (FlashDevelop cannot currently decompile a Flash 9 SWF in this way.)

I’ve created some sample files if you want to test this out yourself: Embedding.zip

(It’s created as an Ant-based FlashDevelop project, but you can ignore everything but the Flash files in the src dir if you use something else.)

ps. If anyone knows how to get proper indenting using iG syntax highligher in WordPress 2.0, let me know.

This entry was posted in Flash. Bookmark the permalink.

57 Responses to Embedding Resources with AS3

  1. kp says:

    An important concept that I may not have pointed up enough is that these assets are COMPILED IN to your SWF – at COMPILE TIME. They are NOT loaded in at run time. They are NOT in a runtime shared library. This means:

    1. You don’t need to deploy the library.swf when you deploy your application. They are not linked in any way.

    2. If you change something in the library.swf, you need to recompile your application swf to re-embed the changed assets.

  2. kp says:

    After some more thought, I’m sure that there is a good use case for using a Flash 9 SWF as a library. Perhaps if the class you give a symbol in Flash 9 is an actual class, not an auto-generated one, but I’m not quite sure how or if that comes through. Still playing.

  3. Ben says:

    Hey Keith,

    Great info once again. As far as the indentation thing, you have to not use the rich text editor or whatever they call it when writing your post. I had the same problem when I first installed iG.

  4. kp says:

    Thanks. But I’m still having no luck with indenting. How do I not use the rich text editor? I can click on the html button on the top and paste my code in there, but when I hit update, it formats the whole thing into one long line. Are you using WP 2.0?

  5. Dongwook says:

    I’m flying here to read this article, because I heard that Embed tag is not available anymore in AS3, but I think I was wrong. Anyway thanks for great tip. However, I have one question, somehow, I can’t complie this in Flash 9 preview version, could you tell me why isn’t that? It should work I guess. I did something wrong maybe.

  6. Ben says:

    Yea, its kind of in a weird place. Options -> Writing -> uncheck “Users should use the visual rich editor by default”. I am using 2.0.3

    Good luck!

  7. kp says:

    Thanks Ben. I tried that and it didn’t seem to make a difference, but I’ll give it another shot.

    Dongwook, metadata tags such as embed are not supported by the Flash IDE compiler, because you set everything up (stage size, fps, bg color) in the IDE, and you have a library, so don’t “need” to embed things like that.

  8. kp says:

    Ah, found it! In addition to disabling the RTE in options, you have to disable it in your user preferences too. Yay! Indenting!

  9. matt says:

    Thats great, thanks. I can compile in Flashdevelop and see all the shapes in the swf if i launch the swf with the standalone player, but the swf that opens in the tab is blank, any idea what the problem may be. Sorry if its slightly off topic :/

    cheers

    MaTT

  10. Would embedding swf’s with linkage id’s be the best way to go for embedding components. Or are there specific metatags to handle swc embedding?

  11. Philippe says:

    I’m fairly confident that FlashDevelop’s SWF exploration can show the symbols of Flash 9 IDE’s SWFs.

    Matt, check that you have the Flash 9 ActiveX plugin installed.

  12. Francis Gabon says:

    Hey Keith,

    Thanks for that great tip. I’ve been looking for a way to embed SWF generated by the F9 IDE for a long time!

    As there’s no linkage id in F9 anymore, I tried to attach a class of my own (Anim.as) to a movieclip in the lib and that worked the same way :

    [Embed(source="lib.swf", symbol="Anim")]

    Nevertheless, back to my main app class in Flex Builder, I can’t cast the embedded MovieClip to my Anim class.

    trace("MovieClip: " + (anim is MovieClip)) //returns true
    trace("Anim: " + (anim is Anim)) //returns false

    Moreover, code I wrote on the Anim symbol’s timeline isn’t executed once the main app is launched in FB, although the symbol is visible. It’s pretty annoying as I may need some gotoAndPlay to be executed…

    Any help is welcomed on that 🙂

    Cheers,
    FG

  13. kp says:

    Yeah, i haven’t quit figured out how to force the type of an embedded resource to anything beyond its default Movieclip/sprite/bitmap. Even if you have a named text field in an embedded asset, and try to access that, it says Sprite doesn’t have that property. I imagine there is a way, I just got distracted onto something else last night and didn’t explore it further.

  14. Never mind..

    Swf embedded actionscript 2.0 components can not be used because of AS 3.0 compiler error’s, and Actionscript 3.0 components are simply classes to be instantiated ;).

  15. Sam says:

    So timeline code can exist. But wat about frames? Can assets have frames in their timelines?

  16. yo Keith. thanks for sharing all this great info, much appreciated.
    im trying to import a symbol from my external swf and then cast it as a custom object, but failing miserably!!

    heres where i started, successfully instancing the asset as a sprite

    ——————————————————————

    [Embed (source = “../fla/library.swf”, symbol = “customCursor”)]
    private var cursorSprite:Class;

    var customCursor:Sprite = new cursorSprite();
    addChild(customCursor);

    ——————————————————————-

    but now i want to cast customCursor, so tried:

    ——————————————————————-

    import CustomCursor;

    [Embed (source = “../fla/library.swf”, symbol = “customCursor”)]
    private var cursorSprite:Class;

    var customCursor:CustomCursor = new cursorSprite() as CustomCursor;
    addChild(customCursor);

    ——————————————————————-

    and various variations on the above, all of which failed. any tips would be much appreciated.

    chur
    vinnie

  17. kp says:

    i’ve run into the same thing vinnie. haven’t had the time to investigate it far enough to find the solution though.

  18. kp says:

    sam, yes, as demonstrated in the example, you can have a timeline tween or frame by frame animation in a movie clip, and import that. however, you can’t control its frames. can’t even say stop() or gotoAndPlay().

  19. alco says:

    “however, you can’t control its frames. can’t even say stop() or gotoAndPlay().”

    Presumably, this is because a SWF published in Flash 8 contains AVM1 bytecode, which, according to Adobe documentation, cannot be ‘understood’ by AVM2 bytecode. So when you build an AVM2 SWF (i.e. from AS3 sourcecode) mxmlc strips out incompatible AVM1 bytecode, even something as simple as a ‘stop()’.

  20. thanks keith, thought i was being dense!!

  21. jNj says:

    hey, new to AS2.0 let alone AS3.0 so could be doing alot wrong but the following worked

    [Embed(source=”assets/tagDom.swf”, symbol=”dom”)]
    private var dom:Class;

    var myDom:MovieClip = new dom();
    addChild(myDom);
    myDom.gotoAndStop(4); //changing frame number was working
    myDdom.x = 100;
    myDdom.y = 100;

  22. jNj says:

    sorry,
    typo “myDdom.x = 100;”, “myDdom.y = 100;” myDom etc..

  23. bong says:

    ok thanks a lot for that info ..

    this code :

    public function App()
    {
    init();
    }

    what exactly it do?

  24. sascha/hdrs says:

    Can somebody give me a hint how to use embedded assets properly with a preloader? Before AS3 we used the timeline in Flash and put a preloader on frame1 and all the heavy stuff on frame2 or later. How does this go in AS3 without a Flash9 IDE? I’ve wrote a custom AS3 Preloader class that extends MovieClip and once it finished loading it jumps to frame 2 but how in the first place do I get embedded assets onto frame2 (if thats even possible)?
    I think there must be a way, after all Flex’s Preloader preloads properly (what a sentence!). And that one extends Sprite and Flex’s SystemManager class extends MovieClip, so maybe there are some parallels.

  25. Mark Walters says:

    In case anyone comes stumbling upon this post again like I did, I wanted to offer up the solution to associating a custom class with an embedded symbol.

    Instead of doing something like this:

    [Embed(source="/library.swf", symbol="customButton")]
    private var CustomButton:Class;
    var customButton:SimpleButton = new CustomButton();

    Do this instead:

    [Embed(source="/library.swf", symbol="customButton")]
    public class CustomButton extends SimpleButton

    Add the embed tag above the class declaration that you want the embedded symbol to be associated with instead of above a variable that you want associated with the class.

  26. Dennis van Nooij says:

    all this looks great but did anyone get this to work without embedding the Flex framework ? I get all kind of compile errors when I leave out the framework.swc.. 🙁

  27. Dennis van Nooij says:

    note to self: better read the comments first..:)

    Mark’s solution works great. thanks

  28. kp says:

    yeah, you’ll need the framework swc included, as assets are actually embedded as instances of SpriteAsset, MovieClipAsset, BitmapAsset, etc. which live in the mx package. Those classes are pretty self contained though, so you don’t have to worry that your file size is going to balloon by pulling in a bunch of the framework itself.

  29. Jerry says:

    Maybe a solution: It works with anything, if you cast the Class, like this:


    [Embed(source="stuff/library.swf", symbol="Box")]
    private var Box:Class;

    var boxInstance:Sprite= new Box();
    addChild(boxInstance);
    Box(boxInstance).myLabel.text = "hello, again"; //"myLabel" is a Textfield in the Box

  30. waltsatan says:

    Scalegrid doesn’t seem to work when embedding assets using the factory method.

    [Embed(source="roundedbox.png", scaleGridTop=2,scaleGridBottom=9, scaleGridLeft=2, scaleGridRight=9)]
    private var RoundBox:Class;

    It works as a bitmap, but when I try it as a sprite, it fails:

    var assetClass:Class = getDefinitionByName("RoundBox:) as Class;
    var assetBitmap:Sprite = new assetClass();

    Anyone know a way to get it to work?

  31. Dr S says:

    Thanks for this great tutorial. The only thing is I can’t seem to get this to preview from the Flash CS3 IDE. I get the swf to publish and appear with no compiler errors but I can see none of the symbols on the stage.

    Am I doing something wrong?

    Thanks 🙂

  32. dannym says:

    Does anyone have experience importing a PNG from the Flash IDE that has jpg compression applied? I seem to recall that I was able to make this happen in the past, but now I get a “Error: Error #2136: The SWF file _ contains invalid data.” error. Works perfectly if I sent the PNG compression to loseless in the IDE, but I need to crunch these mofos. Worst part is, I remember doing this in the past. Has something changed? Doesn’t seem to work with Flex 2 or 3 SDK and fcsh.
    Any ideas?

  33. In reference to Dannym:
    “Error: Error #2136: The SWF file _ contains invalid data.” error
    I’m using a .swf as an assets source to embedded images/icons in Flex.
    Flex send me this 2136 error.

    Situation:
    you import a png file into the Flash library, then it is exported as an swf to be used in Flex to get images to embed.
    If by default a jpg compression is applied to it, the 2136 error is sent when you try to use this asset.

    To fix this problem:
    just double click on the imported png image in the library, in the bitmap properties panel sets its compression to lossless (GIF/PNG), and then everything works great.

    Why?:
    I guess Flash or Flex makes a conflict between compressions and source files formats?

    I haven’t tested it in an “only Flash” workflow…
    I hope this will help somebody.

    Best regards.

  34. halaszlo says:

    Hi,
    My code is the following:
    package
    {
    import flash.display.MovieClip;
    public class Main extends MovieClip
    {
    public var mcWall:MovieClip;
    public function Main():void
    {
    [Embed(source = ‘../Wall.swf’)]
    var classWall:Class;
    mcWall = new classWall();
    addChild(mcWall);
    mcWall.stop();
    }
    }
    }
    I am using FlashDevelop and as3 project. The imported swf is a Flash 8 MovieClip.

    My problem is that the general movieclip functions don’t work (e.g. gotoAndStop() or stop().

    Is it caused by that the imported movie is Flash 8 or I am doing something wrong?

    Thanks in advance.

  35. unhitched says:

    Is it possible to embed an flv file into a swf/swc that can be instantiated later? ie not importing to stage in Flash and saving as a MovieClip but using a standalone file that has been h264 encoded. I notice that if I create a Flex Library project and add FLV assets to it, I get a compiled swc conataining these assets – but can’t figure out how to use them in another Flex project. Any ideas would be great!

  36. Doug says:

    You can embed and use an FLV file as follows:

    package
    {

    import flash.display.Sprite;
    import flash.display.MovieClip;

    public class Test extends MovieClip
    {

    [Embed(source=”bin/test.swf”)]
    private var myVideo:Class;

    public function Test ()
    {
    var k:Object = new this.myVideo();
    var v:MovieClip = k as MovieClip;
    addChild(v);
    v.play();
    }

    }

    }

    To generate a SWF from an FLV you need to transcode the file. I recommend using one of the (many) FLV to SWF encoders out there. Typically you can use ffmpeg directly if you already have the flv:

    ffmpeg -i myflv.flv -acodec copy -vcodec copy myswf.swf

    All the methods mentioned previously can then be used to load the swf as normal. Remember external swfs extend MovieClip, not Sprite. 🙂

  37. Andrew says:

    I’m wondering if there’s a way to dynamically set the ‘source’ of the Embed so I can do batch Embeds? That would be fantastic.

    It seems you can’t access variables once you enter the embed tag…

  38. BubbleBoy says:

    I am trying to do this but it doesnt work, I keep getting:

    “App_Picture.as(10): col: 42 Error: The definition of base class BitmapAsset was not found.”

    Any ideas?

  39. BubbleBoy says:

    Seems I found the solution.

    Just create “fake” a BitmapAsset class, a fake SpriteAsset and a fake MovieClipAsset class.

    http://www.ultrashock.com/forums/flex/embed-flex-assets-without-using-flex-123405.html

  40. ComChan says:

    For those who have problem on frame control with embedded Swf, without a debugger you will never understand what the hell is going on inside.

    [Embed(source=”omg.swf”)] public var OMGAnimation:Class;

    var omg_mc:MovieClip;

    function pasteOMG(){
    omg_mc = new OMGAnimation();
    addChild(omg_mc); // Yea i see that
    omg_mc.gotoAndStop(2); // That’s not working, the MC keeps on playing
    }

    So what’s the deal?
    Yup, omg_mc is really a MovieClip object, but only a shell with a Loader object as child.
    And the loader’s content is the real MovieClip object that you can manipulate.

    var omg_mc:MovieClip;

    function pasteOMG():void{
    var omg_object:MovieClip = new OMGAnimation();
    var omg_loader:Loader = omg_object.getChildAt(0) as Loader;
    omg_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);
    }

    function loaderComplete(e:Event):void{
    omg_mc = LoaderInfo(e.target).loader.content as MovieClip;
    addChild(omg_mc);
    omg_mc.gotoAndStop(2); // Now it works
    }

  41. Sumeet says:

    Andrew I am also looking for something like that. If anyone has some soluton then help would be appreciated.

  42. kp says:

    Andrew, Sumeet, the only way to do that would be some kind of precompiler that changed the variable before the flash compiler got to it.

  43. Peter Schum says:

    Hi there,
    I simply want to create something like what is explained in this tutorial but (maybe because of probabily the new version of Flex SDK) there is no way I can see the preload working, just a blank screen.

    Would it be worth trying within Flex Developer? And how?

  44. Charles says:

    I’ve been trying to get this to work for some time.

    I have this:

    [Embed(source=”mplib.swf”,symbol=”menuBgGr3″)]
    var menuBG:Class;

    then later I call this:

    var theScreen:MovieClip = new menuBG();

    and I get this:

    Error #1007: Instantiation attempted on a non-constructor

    Any idea what I’m doing wrong?

  45. Charles says:

    I tried to download the source files but the link appears to be broken.

  46. Terence says:

    Hi, how do I access properties of the Star, Circle? For example, if there is a dynamic text that I would like to control, can I code star.mytext.text = “hello”; I have try on my side..it does not seem to work

  47. Daniel Bunte says:

    hi there,
    you might also be interested in embedding fonts, bitmaps, binaryData, etc. without using the flex framework at all.
    see: http://danielbunte.de/2011/07/24/embed-bitmaps-fonts-binarydata-etc-without-using-the-flex-framework-at-all/

    best regards,
    daniel

  48. Ray says:

    It seems that these code is obsolete now, I copy it and create the library.swf but it doesn’t make sense…

  49. zzlasp says:

    Can you help to use an embeded swf’s property or variale?

Leave a Reply