From: Martijn de V. <mdv...@us...> - 2006-02-13 13:38:57
|
Update of /cvsroot/asapframework/asapframework/playground/classdemos/LoaderTest/scripts/org/asapframework/util/loader In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27130/loader Added Files: FileData.as Loader.as LoaderEvent.as LoaderWorker.as LoaderWorkerEvent.as Log Message: new Loader class test files --- NEW FILE: LoaderWorker.as --- /* Copyright 2005 by the authors of asapframework Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // framework classes import org.asapframework.events.Dispatcher; import org.asapframework.util.debug.Console; import org.asapframework.util.FrameDelay; import org.asapframework.util.framepulse.FramePulse; import org.asapframework.util.framepulse.FramePulseEvent; import org.asapframework.util.loader.FileData; import org.asapframework.util.loader.LoaderWorkerEvent; /** * Used internally by {@link Loader}. * @author Arthur Clemens * @author Martijn de Visser, added check for already loaded movies. These are now unloaded first. * @author Martijn de Visser, implemented MovieClipLoader instead of MovieClip.loadMovie - major refactoring of code. */ class org.asapframework.util.loader.LoaderWorker extends Dispatcher { private var mLoadingState:Boolean = false; private var mLoadingData:FileData; private var mStartTime:Number; private var mTimeOutTime:Number; private var mFPulse:FramePulse; private var mLoader:MovieClipLoader; private static var TIMEOUT:Number = 10000; /**< Initial timeout when waiting for data from server (10 seconds). */ /** * Constructor */ function LoaderWorker () { super(); // initialise framepulse events mFPulse = FramePulse.getInstance(); // setup MovieClipLoader mLoader = new MovieClipLoader(); mLoader.addListener(this); } /** * Starts loading content * @param data: a {@link FileData} object */ public function load (inData:FileData) : Void { delete mLoadingData; mLoadingData = inData; // was a movie already loaded in target? var progress:Object = mLoader.getProgress(inData.location); var b:Number = progress.bytesLoaded; if (b > 4) { unloadContent(true); } else { startLoading(); } } /** * Stops loading the asset * @sends LoaderWorkerEvent#ON_DONE */ public function stopLoading () : Void { // unload clip mLoader.unloadClip(mLoadingData.location); // reset resetState(); // dispatch onWorkerLoadDone event dispatchEvent(new LoaderWorkerEvent(LoaderWorkerEvent.ON_DONE, this, mLoadingData.name, mLoadingData.location)); } /** * The loading state of the worker, true: the worker is currently loading; false: the worker has not yet started loading, or has finished or has encountered an error. */ public function get loading () : Boolean { return mLoadingState; } /** * The {@link FileData} object. */ public function get loadingData () : FileData { return mLoadingData; } /*---------------------- * EVENTS ----------------------*/ /** * Invoked when a file loaded with MovieClipLoader.loadClip() has failed to load. * @sends LoaderWorkerEvent#ON_ERROR */ public function onLoadError ( target_mc:MovieClip, errorCode:String, httpStatus:Number ) : Void { // debug message Console.WARN("LoaderWorker - '" + httpStatus + "' error while loading file: " + mLoadingData.url); // reset resetState(); // dispatch onWorkerLoadError event dispatchEvent(new LoaderWorkerEvent(LoaderWorkerEvent.ON_ERROR, this, mLoadingData.name, mLoadingData.location, httpStatus)); } /** * Invoked every time the loading content is written to the hard disk during the loading process (that is, between MovieClipLoader.onLoadStart and MovieClipLoader.onLoadComplete). * @sends LoaderWorkerEvent#ON_PROGRESS */ public function onLoadProgress ( target_mc:MovieClip, loadedBytes:Number, totalBytes:Number ) : Void { // update data mLoadingData.bytesLoaded = loadedBytes; mLoadingData.bytesTotal = totalBytes; // dispatch onWorkerLoadProgress event dispatchEvent(new LoaderWorkerEvent(LoaderWorkerEvent.ON_PROGRESS, this, mLoadingData.name, mLoadingData.location)); } /** * Invoked when the actions on the first frame of the loaded clip have been executed. * * @sends LoaderWorkerEvent#ON_DONE */ public function onLoadInit ( target_mc:MovieClip ) : Void { // reset resetState(); // set visibility mLoadingData.location._visible = mLoadingData.visible; // dispatch onWorkerLoadDone event dispatchEvent(new LoaderWorkerEvent(LoaderWorkerEvent.ON_DONE, this, mLoadingData.name, mLoadingData.location)); } /** * Invoked when a call to MovieClipLoader.loadClip() has begun to download a file. * @sends Nothing, not yet implemented. */ public function onLoadStart ( target_mc:MovieClip ) : Void { // unused } /** * Invoked when a file that was loaded with MovieClipLoader.loadClip() is completely downloaded. * @sends Nothing, not implemented. */ public function onLoadComplete ( target_mc:MovieClip, httpStatus:Number ) : Void { // unused } /*---------------------- * PRIVATE ----------------------*/ /** * Resets the state of this worker */ private function resetState () : Void { // set flag mLoadingState = false; // reset loaded bytes mLoadingData.bytesTotal = mLoadingData.bytesLoaded = 0; } /** * Starts the actual loading process */ private function startLoading () : Void { mLoader.loadClip(mLoadingData.url, mLoadingData.location); mLoadingState = true; } /** * Unloads the current movie if a movie was already loaded in mc * @param start, set to true to start loading new content after 1 frame dealy */ private function unloadContent ( inStart:Boolean ) : Void { mLoader.unloadClip(mLoadingData.location); if (inStart) var d:FrameDelay = new FrameDelay(this,startLoading,null,1); } /** * @return Package and class name */ public function toString () : String { return "org.asapframework.util.loader.LoaderWorker"; } } --- NEW FILE: LoaderEvent.as --- /* Copyright 2005 by the authors of asapframework Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import org.asapframework.util.loader.Loader; import org.asapframework.events.Event; /** Event object that is dispatched by {@link Loader}. @version 3 July 2005 */ class org.asapframework.util.loader.LoaderEvent extends Event { public static var ON_ALL_LOADED:String = "onAllLoadFinished"; public static var ON_START:String = "onLoadStart"; public static var ON_PROGRESS:String = "onLoadProgress"; public static var ON_DONE:String = "onLoadDone"; public static var ON_ERROR:String = "onLoadError"; public var name:String; public var targetClip:Object; public var total:Number; public var loaded:Number; function LoaderEvent (inType:String, inSource:Loader, inName:String, inTargetClip:Object, inTotal:Number, inLoaded:Number) { super(inType, inSource); name = inName; targetClip = inTargetClip; total = inTotal; loaded = inLoaded; } } --- NEW FILE: Loader.as --- /* Copyright 2005 by the authors of asapframework Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // framework classes import org.asapframework.util.loader.*; import org.asapframework.util.debug.Console; import org.asapframework.events.Dispatcher; /**----------------------------------------------------------------------------- Does the loading of a movie or jpeg into a clip. Multiple/subsequent movies that are added are queued. Loader can deal with multiple loading threads simultaneously (but the real life efficiency is dependent on the capability of the browser). @author Arthur Clemens, Martijn de Visser (rewritten for EventDispatcher usage and added check for already loaded data) @version 8 Feb 2006 @see LoaderWorker @example Example to load multiple images: <code> var loader:Loader = new Loader(); </code> Listen for feedback during loading: <code> loader.addEventListener(LoaderEvent.ON_PROGRESS, this); loader.addEventListener(LoaderEvent.ON_DONE, this); </code> Load the assets. We will make them invisible first, and turn them visible once they are loaded: <code> loader.load( movieholder1_mc, "seaside.jpg", "Seaside", false ); loader.load( movieholder2_mc, "tree.jpg", "Woods", false ); </code> To keep track of loading progress, implement the listener method - we will update a progress bar with the incoming data: <code> private function onLoadProgress (e:LoaderEvent) : Void { progressbar._xscale = 100 / e.total * e.loaded; } </code> And the method that is called when each asset has finished loading: <code> private function onLoadDone (e:LoaderEvent) : Void { trace(e.name + " is loaded"); e.target._visible = true; // or use {@link ActionQueue ActionQueue} to fade in the clip } </code> We could also have implemented {@link LoaderEvent#ON_ALL_LOADED} to find out when everything is done. ------------------------------------------------------------------------------*/ class org.asapframework.util.loader.Loader extends Dispatcher { private var mWorkerCount:Number = 4; /**< The number of LoaderWorker objects that will be doing loading work simultaneously. */ private var mFileQueue:Array; /**< Array of {@link FileData} objects */ private var mWorkers:Array; /**< Array of {@link LoaderWorker} objects */ private var mLoadingState:Boolean; /**< State of the Loader (loading or not loading) */ /**----------------------------------------------------------------------------- @param inThreadCount (optional) The number of threads the Loader should be using. Default (when left empty) is 4. This means that (theoretically) 4 files will be loaded at once. The actual number that Flash uses is dependent on the browser. When the number of threads is 1, the next file will only be loaded when the first is done loading. ------------------------------------------------------------------------------*/ public function Loader (inThreadCount:Number) { super(); mLoadingState = false; if (inThreadCount > 0) { mWorkerCount = inThreadCount; } mFileQueue = new Array(); mWorkers = new Array(); for (var i:Number = 0; i<mWorkerCount; ++i) { var worker:LoaderWorker = new LoaderWorker(); worker.addEventListener(LoaderWorkerEvent.ON_PROGRESS, this); worker.addEventListener(LoaderWorkerEvent.ON_ERROR, this); worker.addEventListener(LoaderWorkerEvent.ON_DONE, this); mWorkers.push(worker); } } /**----------------------------------------------------------------------------- Adds a file to the load queue. The file will be ordered to load as soon as one of the loader workers is idle. Supported file types are: swf, jpg @param loc : Movieclip in where the file should be loaded @param url : File's url or disk location @param name : (optional) Unique identifying name for the loading request @param isVisible : (optional) The visible state of the movieclip once the file is loaded; if not specified, visible = true is assumed @return Error state; false if an error occurred, true if successfully added to the queue ------------------------------------------------------------------------------*/ public function load (inLoc:MovieClip, inUrl:String, inName:String, inIsVisible:Boolean) : Boolean { // Error checking // check if location is valid if (inLoc == undefined) { Console.DEBUG("Loader load; location is not valid"); return false; } // Check if url is valid if (inUrl.length == 0) { Console.DEBUG("Loader load; url is not valid"); return false; } // check for formal validity of url var urlComponents:Array = inUrl.split("."); if (urlComponents.length <= 1) { Console.ERROR("Loader load; filename is wrong: '" + inUrl + "'"); return false; } var extension:String = urlComponents.pop().toLowerCase(); if (extension == "gif") { Console.ERROR("Loader load; file has illegal extension: '" + extension + "'"); return false; } // to do: make list of allowed extensions if ((extension != "swf") && (extension != "jpg") && (extension != "jpeg")) { Console.ERROR("Loader load; file has illegal extension: '" + extension + "'"); return false; } var isVisible:Boolean = (inIsVisible != undefined) ? inIsVisible : true; var fileData:FileData = new FileData(inLoc, inUrl, inName, isVisible); mFileQueue.push(fileData); getNextInQueue(); return true; } /**----------------------------------------------------------------------------- Stops the loading of one file. @param name : Name of the loading request as passed with Loader.load(). ------------------------------------------------------------------------------*/ public function stopLoading (inName:String) : Void { var i:Number, len:Number = mWorkers.length; for (i=0; i<len; ++i) { var w:LoaderWorker = LoaderWorker(mWorkers[i]); if (w.loading == true) { if (w.loadingData.name == inName) { w.stopLoading(); } } } } /**----------------------------------------------------------------------------- Stops the loading of all files, clears the loading queue and frees the loader workers. ------------------------------------------------------------------------------*/ public function stopAllLoading () : Void { var i:Number, len:Number = mWorkers.length; for (i=0; i<len; ++i) { var w:LoaderWorker = LoaderWorker(mWorkers[i]); if (w.loading == true) { w.stopLoading(); } } delete mFileQueue; mFileQueue = new Array(); } /**----------------------------------------------------------------------------- The Loader's loading state. @return True when one of the workers is still loading, false when all workers have finished. ------------------------------------------------------------------------------*/ public function isLoading () : Boolean { return mLoadingState; } /**----------------------------------------------------------------------------- Calculates the total number of bytes loading and loaded of all workers. @return A value object {total:Number, loaded:Number}. ------------------------------------------------------------------------------*/ public function getTotalAndLoaded () : Object { var totalAndLoaded:Object = {total:0, loaded:0}; var i:Number, len:Number = mWorkers.length; for (i=0; i<len; ++i) { var w:LoaderWorker = LoaderWorker(mWorkers[i]); if (w.loading) { var data:FileData = w.loadingData; var dataTotal:Number = data.bytesTotal; if (dataTotal != undefined) totalAndLoaded.total += dataTotal; var dataLoaded:Number = data.bytesLoaded; if (dataLoaded != undefined) totalAndLoaded.loaded += dataLoaded; } } return totalAndLoaded; } /**----------------------------------------------------------------------------- * ------------------------------------------------------------------------------*/ public function toString () : String { return "; org.asapframework.util.loader.Loader"; } /**----------------------------------------------------------------------------- @sends LoaderEvent#ON_ALL_LOADED When no more assets are in the queue @sends LoaderEvent#ON_START When a new LoaderWorker starts loading ------------------------------------------------------------------------------*/ private function getNextInQueue () : Void { if (mFileQueue.length == 0) { assertIsLoading(); if (!mLoadingState) { dispatchEvent(new LoaderEvent(LoaderEvent.ON_ALL_LOADED, this)); } return; } // Not done yet, so get next free Worker var i:Number, len:Number = mWorkers.length; for (i=0; i<len; ++i) { var w:LoaderWorker = LoaderWorker(mWorkers[i]); if (w.loading == false) { // else get the first item var fileData:FileData = FileData(mFileQueue.shift()); w.load(fileData); mLoadingState = true; dispatchEvent(new LoaderEvent(LoaderEvent.ON_START, this, fileData.name, 0, 0)); break; } } } /**----------------------------------------------------------------------------- Updates the loading state; sets mLoadingState to true if one of the workers is loading; to false if all loader workers are free. ------------------------------------------------------------------------------*/ private function assertIsLoading () : Void { var isStillLoading:Boolean = false; var i:Number, len:Number = mWorkers.length; for (i=0; i<len; ++i) { var w:LoaderWorker = LoaderWorker(mWorkers[i]); if (w.loading == true) { isStillLoading = true; } } mLoadingState = isStillLoading; } /**----------------------------------------------------------------------------- Monitors the loading progress of one LoaderWorker object. This event is passed on to listeners of the Loader. @param e: event object with properties: .name, .type, .target @sends LoaderEvent#ON_PROGRESS When some data has been received ------------------------------------------------------------------------------*/ private function onWorkerLoadProgress (e:LoaderWorkerEvent) : Void { // calculate the total amount of data of all workers, // then send this information out var totalAndLoaded:Object = getTotalAndLoaded(); dispatchEvent(new LoaderEvent(LoaderEvent.ON_PROGRESS, this, e.name, e.targetClip, totalAndLoaded.total, totalAndLoaded.loaded)); } /**----------------------------------------------------------------------------- Received when a LoaderWorker object is finished or stopped loading. This event is passed on to listeners of the Loader. @param e: event object with properties: .name, .type, .target @sends LoaderEvent#ON_DONE When one asset has finished loading @implementationNote Calls {@link #getTotalAndLoaded}. ------------------------------------------------------------------------------*/ private function onWorkerLoadDone (e:LoaderWorkerEvent) : Void { var totalAndLoaded:Object = getTotalAndLoaded(); dispatchEvent(new LoaderEvent(LoaderEvent.ON_DONE, this, e.name, e.targetClip, totalAndLoaded.total, totalAndLoaded.loaded)); // check if there is still a worker occupied var isStillLoading:Boolean = false; var i:Number, len:Number = mWorkers.length; for (i=0; i<len; ++i) { var w:LoaderWorker = LoaderWorker(mWorkers[i]); if (w.loading) { isStillLoading = true; } } getNextInQueue(); } /**----------------------------------------------------------------------------- Received when a LoaderWorker object encounters an error during loading. This event is passed on to listeners of the Loader. @param e: event object with properties: .name, .target @sends LoaderEvent#ON_ERROR When an error happened during loading ------------------------------------------------------------------------------*/ private function onWorkerLoadError (e:LoaderWorkerEvent) : Void { // dispatch onLoadError event dispatchEvent(new LoaderEvent(LoaderEvent.ON_ERROR, this, e.name, e.targetClip)); } } --- NEW FILE: LoaderWorkerEvent.as --- /* Copyright 2005 by the authors of asapframework Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import org.asapframework.util.loader.LoaderWorker; import org.asapframework.events.Event; /** * Event object that is dispatched by {@link LoaderWorker} to {@link Loader}. */ class org.asapframework.util.loader.LoaderWorkerEvent extends Event { public static var ON_DONE:String = "onWorkerLoadDone"; public static var ON_ERROR:String = "onWorkerLoadError"; public static var ON_PROGRESS:String = "onWorkerLoadProgress"; public var name:String; public var targetClip:MovieClip; public var httpStatus:Number; function LoaderWorkerEvent (inType:String, inSource:LoaderWorker, inName:String, inTargetClip:MovieClip, inHttpStatus:Number ) { super(inType, inSource); name = inName; targetClip = inTargetClip; httpStatus = inHttpStatus; } } --- NEW FILE: FileData.as --- /* Copyright 2005 by the authors of asapframework Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ class org.asapframework.util.loader.FileData { private var mLocation:MovieClip; private var mUrl:String; private var mName:String; private var mVisible:Boolean; private var mBytesTotal:Number; private var mBytesLoaded:Number; /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function FileData (inLoc:MovieClip, inUrl:String, inName:String, inIsVisible:Boolean) { mLocation = inLoc; mUrl = inUrl; mName = inName; mVisible = inIsVisible; } /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function set location (inLocation:MovieClip) : Void { mLocation = inLocation; } public function get location () : MovieClip { return mLocation; } /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function set url(inUrl:String) : Void { mUrl = inUrl; } public function get url() : String { return mUrl; } /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function set name(inName:String) : Void { mName = inName; } public function get name() : String { return mName; } /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function set visible(inIsVisible:Boolean) : Void { mVisible = inIsVisible; } public function get visible() : Boolean { return mVisible; } /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function set bytesTotal(inTotal:Number) : Void { mBytesTotal = inTotal; } public function get bytesTotal() : Number { return mBytesTotal; } /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function set bytesLoaded(inLoaded:Number) : Void { mBytesLoaded = inLoaded; } public function get bytesLoaded() : Number { return mBytesLoaded; } /**----------------------------------------------------------------------------- ------------------------------------------------------------------------------*/ public function toString () : String { return mLocation + " " + mUrl + " " + mName + " " + mBytesTotal + " " + mBytesLoaded; } } |