// you’re reading...

ActionScript 3.0

Runtime Libraries in Flex ActionScript Projects

Runtime library

This is something I’ve begun using recently, and I thought I would post about it to see if I can help anyone else who’s been thinking about this. I’ve seen some other articles on this, but they’ve had some shortcomings that I think I have improved on. Of course, there’s room for tons of improvement on my class as well, so feel free to extend this to your little collective hearts’ content. The source is downloadable at the bottom of the page, or you can continue to the second page of this article to view it all without downloading. Anyway: onward!

The Need

Okay, so: as a Flex developer who does a lot of ActionScript-only projects, I often run into situations in which I need to import some artwork. This artwork may be in any number of formats, and they all require different solutions. However, for a project that I’m working on now (which I would expound upon if it wasn’t [apparently] top-secret), I needed to import hundreds of little images in a vector format. Furthermore, the client hinted that it would be nice, if not mandatory, to be able to swap out images later without sending it back to me for a recompile. So, I had to do a bit of thinking.

However, it turns out that the solution is really not that hard. When working with Flash, there is really only one vector format worth worrying about, and that is SWF. And furthermore, it turns out that there is a kinda slick way to import all the assets contained in a SWF into a Flex ActionScript project. In the following class, I’ve just smoothed the process a little bit.

The Theory

1- Create a MovieClip in Flash CS3 and check Export for ActionScript in its linkage properties. Remember the class name that you give it, because you’re going to need that to pull this asset back out of its mother SWF.

2- Publish your SWF. Make a note of where it’s going so you can load it in Flex.

3- In Flex, set up a Loader with the typical listeners (see my source below for details) and load the SWF.

4- Once the Loader has successfully loaded the SWF, the part you are interested in is the Loader’s contentLoaderInfo property (which is an instance of the LoaderInfo class, if you’d like to check the Flash help files for more information). This property now contains the data from your Flash CS3 SWF. Interestingly enough, a LoaderInfo class contains an instance of the ApplicationDomain class, which in turns contains all class definitions that are contained in that SWF. Since you checked Export for ActionScript on your MovieClip, that means there is a definition for it in the ApplicationDomain of this LoaderInfo. You just need to pull it out and instantiate it.

5- You have to do a little dancing around with types to get your MovieClip back out, since you will be pulling it out as an instance of Class, not as an instance of MovieClip. However, with a couple lines of code, it’s easy enough to actually create an instance of your original Flash CS3-authored MovieClip.

The Code

Here are the vital parts of the code, as seen below in the source download link at the bottom of the page. These are contained in a wrapper class that I wrote that surrounds Loader.contentLoaderInfo.

This is the handler that is called when the Loader successfully loads the SWF. Notice that we save the LoaderInfo (called “contentLoaderInfo”) for later use. This is the package of all the assets we have just imported.

private static function handleLoadComplete( event:Event ): void
{
	loaderInfo = loader.contentLoaderInfo;
	dispatchEvent( new Event( Event.COMPLETE ) );
}

And here is where the real magic happens, and it must be called after the above handler. Notice how we get a real live Sprite instance from the definition in our LoaderInfo instance. Plus, it looks just like the asset you created in Flash at the beginning of this article.

public static function getAsset( id:String ): Sprite
{
	var Asset:Class = loaderInfo.applicationDomain.getDefinition( id ) as Class;			
	return Sprite( new Asset() );
}

Summary

This is as basic as it gets. My source below extends this enough for me to use it in the aforementioned project (as well as adding some basic error handling), but this could be extended for all types of applications. For instance, my class only returns instances of Sprites because that is what I am interested in. However, you could also return the class itself (un-instantiated), or anything that you might find in LoaderInfo.applicationDomain. The possibilities are… well, not limitless. But more than you might think.

Source

The zip contains a RuntimeLibrary class (shown below), an example using it, and some sample assets in a SWF (with the matching FLA so you can see that they are nothing special- just Exported for ActionScript). As you can see, I’m doing some basic error handling, but you may want to do something a little more robust; or, you may want the error. Feel free to change whatever you want- that’s the beauty of open-source!

DOWNLOAD SOURCE

/**
 * A utility to load a SWF at runtime.
 * This makes all definitions in the loaded SWF available.
 * You can use this to load graphics elements created in Flash CS3 into Flex ActionScript projects
 * 
 * @author	Zack Jordan
 * 			{ P I X E L W E L D E R S }
 * 			pixelwelders.com/blog
 */
package com.pixelwelders.graphics
{
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.Sprite;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
 
	public class RuntimeLibrary extends EventDispatcher
	{
 
		private var request				: URLRequest;
		private var loader				: Loader;
		private var loaderInfo			: LoaderInfo;
 
		/**
		 * Constructor- creates a new RuntimeLibrary
		 * 
		 * @param			nothing
		 * @return			The newly-created RuntimeLibrary 
		 */
		public function RuntimeLibrary()
		{
			request = new URLRequest();
			loader = new Loader();
			loader.contentLoaderInfo.addEventListener( Event.INIT, handleLoadComplete );
			loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, handleIOError );
		}
 
		// === A P I ===
		/**
		 * Loads a swf into this RuntimeLibrary
		 * 
		 * @param	url		the URL of the SWF to load
		 * @return			nothing
		 */
		public function load( url:String ): void
		{
			request.url = url;
			loader.load( request );
		}
 
		/**
		 * Creates and returns an instance of the specified class from the loaded SWF
		 * If the specified class does not exist, dispatches an ErrorEvent and returns an empty Sprite
		 * 
		 * @param	id		Name of the class in the loaded SWF
		 * @return			An instance of the specified class, or an empty Sprite if the class is not found
		 */
		public function getAsset( id:String ): Sprite
		{
			try
			{
				var Asset:Class = loaderInfo.applicationDomain.getDefinition( id ) as Class;
			} catch ( error:ReferenceError )
			{
				trace( "Asset not found." );
				dispatchEvent( new ErrorEvent( ErrorEvent.ERROR ) );
			}
 
			return Asset ? Sprite( new Asset() ) : new Sprite();
		}
 
		// === E V E N T   H A N D L E R S ===
		private function handleLoadComplete( event:Event ): void
		{
			loaderInfo = loader.contentLoaderInfo;
			dispatchEvent( new Event( Event.COMPLETE ) );
		}
 
		private function handleIOError( event:IOErrorEvent ): void
		{
			trace( "load error: " + event.text );
		}
 
	}
}

Discussion

2 comments for “Runtime Libraries in Flex ActionScript Projects”

  1. […] the interest of helping a few people out. This code is a review of sorts, since I already posted a similar utility back in June. However, since then I have been expanding my code library and I thought I’d […]

    Posted by { P I X E L W E L D E R S } | Flash/Flex Integration: SWFLibrary v1.5 | August 19, 2008, 9:28 pm
  2. Great! Thanks much. Finally I found a working example :]

    Posted by Vaclav Vancura | September 27, 2008, 9:14 am

Post a comment

Twitterpated