import org.swxformat.*; import mx.utils.Delegate; class org.swxformat.LoadManager extends EventfulObject { public static var COMPLETE:String = "complete"; public static var PROGRESS:String = "progress"; private static var instance:LoadManager = null; private static var CLIP_NAME:String = "SWXLoadManagerClip" public static var verbose:Boolean = true; private var isRunning:Boolean = false; private var holder:MovieClip = null; private var queue:Array = null; private var currentExternalAsset = null; private var loadNextExternalAssetDelegate = null; private var nextId = 0; // Private Constructor private function LoadManager() { // If not in verbose mode, do not output status/error messages. if (!LoadManager.verbose) LoadManager.echo = null; echo ("SWX LoadManager INFO: Initialized."); // Create the load queue queue = new Array(); // Counter to generate ids nextId = 0; // Delegate loadNextExternalAssetDelegate = Delegate.create(this, loadNextExternalAsset); // Creating the Load Manager at a depth 1024 below the max // that we can do removeMovieClip on (1048675, which is reserved // by the V2 components). _level0.createEmptyMovieClip(CLIP_NAME, 1047551); holder = _level0[CLIP_NAME]; } // Accessor method public static function getInstance():LoadManager { if (instance == null) { instance = new LoadManager(); } return instance; } // Always call addToQueue() immediately after prepare() if calling // prepare manually. public function prepare(externalAsset:ExternalAsset):Number { // One-based loaderId. var id:Number = nextId; nextId = (nextId + 1) % 1048574; // 1048575 is the highest possible dynamic depth (used below). Hopefully no one will make that many swx calls at one time! :) // If the external asset doesn't already // have a holder, create one for it. (You should // only use this for load SWX files). if (!externalAsset.hasHolder) { var holderName:String = "holder"+id; var holderDepth:Number = id + 1; // Depths start at 1, not 0. holder.createEmptyMovieClip(holderName, holderDepth); var currentHolder:MovieClip = holder[holderName]; externalAsset.holder = currentHolder; } return id; } public function load(externalAsset:ExternalAsset):Number { var id:Number = prepare(externalAsset); addToQueue(externalAsset); return id; } public function addToQueue(externalAsset:ExternalAsset):Void { queue.push(externalAsset); // If the queue is not running, start it. if (!isRunning) start(); } public function getAssetClip(id:Number) { return queue[id].clip; } // Stops the loading of all external assets in the queue. // Thanks to Folkert Hielima for leading me in the right // direction on this one! :) public function cancelAllLoads() { // Stop loading the current external asset. currentExternalAsset.removeEventListener(ExternalAsset.LOAD, loadNextExternalAssetDelegate); currentExternalAsset.removeEventListener(ExternalAsset.TIMEOUT, loadNextExternalAssetDelegate); currentExternalAsset.cancel(); // Cancel all external assets in the queue. var numAssetsInQueue:Number = queue.length; for (var i:Number = 0; i < numAssetsInQueue; i++) { queue[i].cancel(); } // Empty the queue. queue = []; // Not running. isRunning = false; } // // Private methods // // Static methods. // echos the passed string. (Gets nulled out in non-verbose mode.) static private function echo(msg:String) { trace (msg); } // Instance methods. private function start() { isRunning = true; loadNextExternalAsset(); } private function loadNextExternalAsset() { // Clean up handlers on the last external asset if (!currentExternalAsset.isCancelled) { currentExternalAsset.removeEventListener(ExternalAsset.LOADED_BUT_NOT_READY, loadNextExternalAssetDelegate); currentExternalAsset.removeEventListener(ExternalAsset.TIMEOUT, loadNextExternalAssetDelegate); } if (queue.length == 0) { // Queue is complete isRunning = false; dispatchEvent({type:LoadManager.COMPLETE}); return; } // trace ("STARTING TO LOAD " + currentExternalAsset.clip); // Get the next external asset currentExternalAsset = queue.shift(); currentExternalAsset.addEventListener(ExternalAsset.LOADED_BUT_NOT_READY, loadNextExternalAssetDelegate); currentExternalAsset.addEventListener(ExternalAsset.TIMEOUT, loadNextExternalAssetDelegate); currentExternalAsset.load(); dispatchEvent({type:LoadManager.PROGRESS, clip:currentExternalAsset.clip, holder:currentExternalAsset.holder}); } }