The communication methods discussed so far have all involved C++. In a large application where the UI is spilt into multiple SWF files, a great deal of C++ code would need to be written to enable the different components of the interface to communicate with each other.
For example, a massively multiplayer online game (MMOG) might have an inventory HUD, an avatar HUD, and a trading room. Items such as swords and money could move from the player’s inventory to the trading room give it to another player. When the player wears an item of clothing it would move from the inventory HUD to the avatar HUD.
These three interfaces must be broken into separate SWF files and loaded separately in order to conserve memory. However, the writing C++ code to maintain communication between the three GFx::Movie objects for these three interfaces will quickly become cumbersome.
There is a better way. ActionScript supports the loadMovie and unloadMovie methods, which enable multiple SWF files to be swapped into and out a single GFx::Movie. As long as the SWF movies are in the same GFx::Movie, they share the same variable space, eliminating the need for C++ code to initialize each movie every time it is loaded.
As an example, we will create a container.swf (container does not exist in any of the tutorial versions) file with ActionScript functions to load and unload movies into a shared variable space. The container file contains no art assets and is nothing more than several ActionScripts to manage movie loading and unloading. The first step is to create a MovieClipLoader object:
var mclLoader:MovieClipLoader = new MovieClipLoader(); For more information on this and other ActionScript functions used here see the Flash documentation. function loadMovie(url:String):void { var loader = new Loader(); loader.load( new URLRequest(url)); addChild(loader); }
Using loadMovie to load a movie into a specific named clip enables more structured organization of a complex interface. Movies can be arranged in a tree structure and variables can be addressed accordingly (e.g., _root.inventoryWindow.widget1.counter).
Many Flash movie clips reference variables based on _root. If a movie is loaded into a specific level, _root refers to the base of that level. For example, for a movie loaded into level 6, _root.counter and _level6.counter refer to the same variable The same movie loaded with loadMovie into _root.myMovie will not work normally, since _root.counter refers to the counter variable at the base of the tree. Movies organized into a tree structure should set this:_lockroot = true. Lockroot is an ActionScript property that causes all references to _root to point to the root of the submovie, not the root of the level. For more on ActionScript variables, levels, and movie clips see the Adobe Flash documentation.
Regardless of how submovies are organized, movie clips running inside the same GFx::Movie can access each other’s variables and operate off of shared state, greatly simplifying creation of complex interfaces.
Container.fla also contains corresponding functions to unload unneeded movie clips to reduce memory consumption (e.g., once a user closes a window, the content can be freed).
When loadMovie returns, the movie has not necessarily finished loading. The loadClip function only initiates the loading of the movie, which then continues in the background.If your application must know when the movie has completed loading (e.g., to programmatically initialize state), Loader listener functions can be used. Container.fla has placeholder implementations of these functions that can be extended to either process the events in ActionScript or make an ExternalInterface call to enable the C++ application to take action:
function loadMovie(url:String):void { var loader = new Loader(); loader.load( new URLRequest( url ) ); loader.contentLoaderInfo.addEventListener( Event.OPEN, handleLoadOpen, false, 0, true ); loader.contentLoaderInfo.addEventListener( Event.INIT, handleLoadInit, false, 0, true ); loader.contentLoaderInfo.addEventListener( Event.PROGRESS, handleLoadProgress, false, 0, true ); loader.contentLoaderInfo.addEventListener( Event.COMPLETE, handleLoadComplete, false, 0, true ); addChild(loader); } function handleLoadOpen( e:Event ):void { trace("Event.OPEN - Load Started!"); } function handleLoadInit( e:Event ):void { trace("Event.INIT - Loaded Content Ready!"); } function handleLoadProgress( e:Event ):void { trace("Event.PROGRESS - Load Progress!"); } function handleLoadComplete( e:Event ):void { trace("Event.COMPLETE - Load Complete!"); }