We want everyone to be able to use their preferred design/dev environment to ensure a fast way to produce innovative high quality work. That includes using the Flash IDE and still being able to use Flex/Flash Builder as a developer.
So we are in need of a workflow where:
- Everybody can work on the project at the same time.
- It’s easy to switch out artwork as well as organize it into multiple fla files.
- It must be possible to compile the project from the Flash IDE
- As few steps as possible to compile and test the project.
- Developers can use the coding environment of their choice.
- Everybody is using the same code.
SEPARATE CODE AND ARTWORK
This method does not use any document root classes in the Flash IDE, and we generally don’t link library assets directly to existing classes. We are using an Object-Composition like approach instead of inheritance, and pass the artwork (DisplayObject, usually a MovieClip) as a parameter to the constructor of a class. The class itself extends EventDispatcher to dispatch and listen to specific events. The main timeline and all library assets are just artwork that aren’t directly connected to any additional functionality through the linkage properties.
SETTING UP THE BASIC FILES
Create a new Flash file and save it as main.fla. Instead of a document root class, we are going to create our Main class instance on the 1st frame of the main timeline:
import com.bigspaceship.examples.flexflash.Main; new Main(this);
Notice that we pass the Main class a reference to the main timeline itself.
A basic Main.as class example:
package com.bigspaceship.examples.flexflash { import flash.display.MovieClip; import flash.events.EventDispatcher; public class Main extends EventDispatcher{ private var _mc:MovieClip; public function get mc():MovieClip{ return _mc; } public function Main($mc:MovieClip){ _mc = $mc; trace("Hello World"); } } }
Accessing any property or instance on the stage is as easy as writing:
_mc.myInstanceOnStageinstead of
this.myInstanceOnStage
To simultaneously work with Flex/Flash Builder we need to know if we are compiling from the Flash IDE or from Flex/Flash Builder.
Most sites we build follow the MVC pattern in one way or the other. So we are using a Singleton class called Model.as to store data, e.g. the current state of the site. Now we can just easily add a boolean variable named compiledFromFlex to the Model.as which is false by default.
package com.bigspaceship.examples.flexflash{ import flash.events.EventDispatcher; public class Model extends EventDispatcher{ public var compiledFromFlex:Boolean; private static var _instance:Model; public function Model($pvt:PrivateClass){ super(); if( _instance != null ) throw new Error( "Error:Model already initialised." ); if( _instance == null ) _instance = this; } public static function getInstance():Model { if (_instance == null){ _instance = new Model(new PrivateClass()); } return _instance; } } } class PrivateClass{ public function PrivateClass(){ } }
We only want to create a new Main instance on the first frame if we are compiling from the Flash IDE. To ensure that, we just need to change the script on the first frame to:
import com.bigspaceship.examples.flexflash.Main; import com.bigspaceship.examples.flexflash.Model; if(!Model.getInstance().compiledFromFlex){ new Main(this); }
Compile Main.fla and be happy to see the “Hello World” output.
SETTING UP A FLEX/FLASHBUILDER PROJECT
Create a new ActionScript project. Make sure that you set all classpaths and bin folders etc. correctly. (I don’t wanna go in depth about the process of creating a project in Flex/Flash Builder here. I’ll discuss that another time.)
The class that we set as the default application in Flex is basically just a wrapper that loads the main.swf that we compiled in Flash. I always name that class “Flex_Main.as”. Note that Flex_Main is only used to develop and test the project.
package{ import com.bigspaceship.examples.flexflash.Main; import com.bigspaceship.examples.flexflash.Model; import flash.display.Loader; import flash.display.MovieClip; import flash.events.Event; import flash.net.URLRequest; [SWF(width="518", height="400", frameRate="30", backgroundColor="#ffffff")] public class Main_Flex extends MovieClip{ public function Main_Flex(){ var l:Loader = new Loader(); l.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLoadComplete); l.load(new URLRequest('main.swf')); Model.getInstance().compiledFromFlex = true; } private function _onLoadComplete($evt:Event):void{ var main:Main = new Main( $evt.target.content ); addChild(main.mc); } } }
In the Main_Flex.as file we set
Model.getInstance().compiledFromFlex = true;
so that the loaded file doesn’t instantiate Main on the timeline but in the Main_Flex instance instead.
This process has a lot of advantages:
- It insures that we don't have more than one instance of Main.
- It always compiles and runs the latest code. If you change something in the code you don’t have to compile it from Flash first. You can directly compile and run it from within FlexBuilder. That works because the code gets compiled into main.swf as well as into Main_Flex.swf. If you compile/run it from within Flex/Flash Builder, Main gets instantiated within the Main_Flex.swf ApplicationDomain and uses the code that got compiled into Main_Flex.swf and vice versa.
- All the nice features in Flex/Flash Builder work: auto-completion, live code checking, code-refactoring, interactive step-through debugging, profiling.
Let’s say we created a library Item and set it’s linkage name to “MyLibraryItem”. If I would write
new MyLibraryItem()
I would get an "ERROR 1180: Call to a possibly undefined method MyLibraryItem " in Flex/Flash Builder because that class doesn't exist in Flex/Flash Builder at compile time. But we now that it exists once we load the swf file that contains that library item. An easy fix for that is using the function
ApplicationDomain.getDefinition(name:String)
to create the class instead.
For an easier use we created a class called Lib.as:
package com.bigspaceship.utils { import flash.media.Sound; import flash.display.MovieClip; import flash.display.BitmapData; import flash.display.DisplayObject; import flash.utils.getDefinitionByName; public class Lib { public static function createAsset($mc:MovieClip, $classname:String):DisplayObject { var c:Class = Class($mc.loaderInfo.applicationDomain.getDefinition($classname)); return new c(); } public static function createSound($mc:MovieClip, $classname:String):Sound { var c:Class = Class($mc.loaderInfo.applicationDomain.getDefinition($classname)); return new c(); } public static function createBitmapData($mc:MovieClip, $bitmap:String):BitmapData { var c:Class = Class($mc.loaderInfo.applicationDomain.getDefinition($bitmap)); return new c(0,0); } public static function createClassObject($classname:String):* { var c:Class = Class(getDefinitionByName($classname)); return new c(); } } }
So instead of
new MyLibraryItem();
we can use
Lib.createAsset(_mc, “MyLibraryItem”);
IT'S ALL ABOUT CLASSPATHS
Working with Flash components like FLVPlayback can get you in trouble sometimes because the Flex/Flash Builder Project doesn't have a reference to the fl package. To solve that problem you just need to add the Flash-library-swc to your Flex/Flash Builder project.
Same problem can occur with custom components like Omniture's ActionSource component. My quickfix for that is to create a MovieClip in a Flash library, add the component to the MovieClips timeline, export the MovieClip as a swc and add that swc to your Flex/Flash Builder project.
ADVANTAGES
- assets/artwork can easily split up into many fla/swf files that load on demand
- if code changes only Main.fla needs to be recompiled, all code is compiled into main.swf
- main.fla can contain any number of assets and layers.
- switching out artwork is as easy as switching out the swf file that contains the artwork
- no disadvantage to previous workflow
- designers can work in fla files although code is not ready yet
- developers can create all classes although there’s no final artwork
- no need in creating swc files
- that the project also compiles from within the Flash IDE has a lot of advantages. No need for designers or for archived projects to use Flex/Flash Builder or any other software to compile and test the project.


