AS3 / Flex: Dynamic Loading of Bitmaps From a SWC
Say you have a Flex project with a reference to a SWC that you are working with in Flash. This is a common scenario as Flash is the best place to visually organize graphic elements into a single spot for inclusion into a final build of your Flash or AIR project.
You also have a bunch of images in the SWC that you’d like to instantiate without creating wrapper MovieClips for them. A simple strategy would be the following:
- Link all your images to their own class names in Flash using the “Linkage” menu option and publish the SWC.
- Attach the SWC to your Flex project
- Instantiate the classes when you want to using the getDefinitionByName utility function.
Sounds straight forward and simple, right? Unfortunately it’s not the case. Adobe has a couple “Features” baked in that cause a lot of headaches when trying to access these classes dynamically.
SWC Classes (including Bitmap assets) Do Not Get Embedded Automatically Into Your Project
The first problem is that Adobe will not compile any of your library objects that are exported for Actionscript unless you specifically name them inside your Actionscript. This creates unnecessary clutter in your code and wastes resources during runtime because you have to instantiate objects that you very well may never even need to use, simply so Flash can find the class it wants. There are some really weird solutions on the web trying to solve this problem, but the most simplest one is the addition of the “-include-libraries” directive in your compiler options:
-include-libraries “/absolute/path/to/my/assets/assets.swc”
This will force the compiler to include every single linked object, without the need of creating dummy instances (and other such nonsense).
We aren’t out of the woods yet, though.
BitmapData Objects Require 2 Parameters in it’s Constructor … Parameters You Don’t Know The Values For!
Once you have a reference to your bitmap asset’s class, trying to instantiate it will look theoretically impossible. It requires a width and height to be instantiated, but you don’t know these dimensions. The whole point of dynamically loading a class is to take care of all this at runtime, not prior to compiling, so the class is more or less asking you for information that it itself knows but you don’t. Kind of screwy but there’s an easy fix:
var MyCustomBitmapClass:Class = getDefinitionByName("MyCustomBitmapClassNameFromSWC") as Class;
var myUsableBitmap:Bitmap = new Bitmap(new MyCustomBitmapClass(0,0));
Even though we’re passing 0s, the BitmapData class knows to ignore them and instead use its actual image data dimensions. I’m not sure if this is a documented caveat with Adobe, but it works and I’m not complaining.