PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/DiegoRay/actionscripts/org/asapframework/util/loader/Loader.as

https://github.com/joemaffia/flash-junk
ActionScript | 324 lines | 160 code | 34 blank | 130 comment | 34 complexity | 32a2e2de59525f0117cf15f4455150b8 MD5 | raw file
  1. /*
  2. Copyright 2005-2006 by the authors of asapframework, http://asapframework.org
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // ASAP classes
  14. import org.asapframework.events.Dispatcher;
  15. import org.asapframework.util.debug.Log;
  16. import org.asapframework.util.loader.FileData;
  17. import org.asapframework.util.loader.LoaderEvent;
  18. import org.asapframework.util.loader.LoaderWorker;
  19. import org.asapframework.util.loader.LoaderWorkerEvent;
  20. import org.asapframework.util.FrameDelay;
  21. /**
  22. Loads SWF movies or JPEG images 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).
  23. @author Arthur Clemens, Martijn de Visser (rewritten for EventDispatcher usage and added check for already loaded data)
  24. @see LoaderWorker
  25. @example
  26. Example to load multiple images:
  27. <code>
  28. var loader:Loader = new Loader();
  29. </code>
  30. Listen for feedback during loading:
  31. <code>
  32. loader.addEventListener(LoaderEvent.ON_PROGRESS, this);
  33. loader.addEventListener(LoaderEvent.ON_DONE, this);
  34. </code>
  35. Load the assets. We will make them invisible first, and turn them visible once they are loaded:
  36. <code>
  37. loader.load( movieholder1_mc, "seaside.jpg", "Seaside", false );
  38. loader.load( movieholder2_mc, "tree.jpg", "Woods", false );
  39. </code>
  40. To keep track of loading progress, implement the listener method - we will update a progress bar with the incoming data:
  41. <code>
  42. private function onLoadProgress (e:LoaderEvent) : Void {
  43. progressbar._xscale = 100 / e.total * e.loaded;
  44. }
  45. </code>
  46. And the method that is called when each asset has finished loading:
  47. <code>
  48. private function onLoadDone (e:LoaderEvent) : Void {
  49. trace(e.name + " is loaded");
  50. e.targetClip._visible = true; // or use {@link ActionQueue ActionQueue} to fade in the clip
  51. }
  52. </code>
  53. We could also have implemented {@link LoaderEvent#ON_ALL_LOADED} to find out when everything is done.
  54. */
  55. class org.asapframework.util.loader.Loader extends Dispatcher {
  56. private var STATE_NONE:Number = 0;
  57. private var STATE_LOADING:Number = 1;
  58. private var STATE_PAUSED:Number = 2;
  59. private var mWorkerCount:Number = 4; /**< The number of LoaderWorker objects that will be doing loading work simultaneously. */
  60. private var mFileQueue:Array; /**< Array of {@link FileData} objects. */
  61. private var mCurrentLoadList:Array; /**< Array of {@link FileData} objects that are currently being loaded. */
  62. private var mWorkers:Array; /**< Array of {@link LoaderWorker} objects. */
  63. private var mLoadingState:Number; /**< Loading state of the Loader. */
  64. /**
  65. @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.
  66. */
  67. public function Loader (inThreadCount:Number) {
  68. super();
  69. mLoadingState = STATE_NONE;
  70. if (inThreadCount > 0) {
  71. mWorkerCount = inThreadCount;
  72. }
  73. mFileQueue = new Array();
  74. mCurrentLoadList = new Array();
  75. mWorkers = new Array();
  76. for (var i:Number = 0; i<mWorkerCount; ++i) {
  77. var worker:LoaderWorker = new LoaderWorker(i);
  78. worker.addEventListener(LoaderWorkerEvent.ON_PROGRESS, this);
  79. worker.addEventListener(LoaderWorkerEvent.ON_ERROR, this);
  80. worker.addEventListener(LoaderWorkerEvent.ON_DONE, this);
  81. mWorkers.push(worker);
  82. }
  83. }
  84. /**
  85. 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
  86. @param loc : Movieclip in where the file should be loaded
  87. @param url : File's url or disk location
  88. @param name : (optional) Unique identifying name for the loading request
  89. @param isVisible : (optional) The visible state of the movieclip once the file is loaded; if not specified, visible = true is assumed
  90. @return Error state; false if an error occurred, true if successfully added to the queue
  91. */
  92. public function load (inLoc:MovieClip, inUrl:String, inName:String, inIsVisible:Boolean) : Boolean {
  93. // Error checking
  94. // check if location is valid
  95. if (inLoc == undefined) {
  96. Log.error("load; location is not valid", toString());
  97. return false;
  98. }
  99. // Check if url is valid
  100. if (inUrl.length == 0) {
  101. Log.error("load; url is not valid", toString());
  102. return false;
  103. }
  104. // check for formal validity of url
  105. var urlComponents:Array = inUrl.split(".");
  106. if (urlComponents.length <= 1) {
  107. Log.error("load; filename is wrong: '" + inUrl + "'", toString());
  108. return false;
  109. }
  110. var isVisible:Boolean = (inIsVisible != undefined) ? inIsVisible : true;
  111. var fileData:FileData = new FileData(inLoc, inUrl, inName, isVisible);
  112. mFileQueue.push(fileData);
  113. // start loading the file one frame later
  114. var fd:FrameDelay = new FrameDelay(this, getNextInQueue);
  115. // return start loading succesful
  116. return true;
  117. }
  118. /**
  119. */
  120. public function getFileCount () : Number {
  121. return mFileQueue.length;
  122. }
  123. /**
  124. Stops the loading of one file.
  125. @param name : Name of the loading request as passed with {@link #load}
  126. */
  127. public function stopLoading (inName:String) : Void {
  128. stopLoadingWorkers(inName);
  129. }
  130. /**
  131. Stops the loading of all files, clears the loading queue and frees the loader workers.
  132. */
  133. public function stopAllLoading () : Void {
  134. stopLoadingWorkers();
  135. delete mFileQueue;
  136. mFileQueue = new Array();
  137. }
  138. /**
  139. Stops the loading of all files until resumeAllLoading is called.
  140. */
  141. public function pauseAllLoading () : Void {
  142. stopLoadingWorkers();
  143. mLoadingState = STATE_PAUSED;
  144. }
  145. /**
  146. Stops the loading of all files until resumeAllLoading is called.
  147. */
  148. public function resumeAllLoading () : Void {
  149. getNextInQueue();
  150. }
  151. /**
  152. The Loader's loading state.
  153. @return True when one of the workers is still loading, false when all workers have finished.
  154. */
  155. public function isLoading () : Boolean {
  156. return mLoadingState == STATE_LOADING;
  157. }
  158. /**
  159. Calculates the total number of bytes loading and loaded of all workers.
  160. @return A value object {total:Number, loaded:Number}.
  161. */
  162. public function getTotalAndLoaded () : Object {
  163. var totalAndLoaded:Object = {total:0, loaded:0};
  164. var i:Number, len:Number = mWorkers.length;
  165. for (i=0; i<len; ++i) {
  166. var worker:LoaderWorker = LoaderWorker(mWorkers[i]);
  167. if (worker.loading) {
  168. var data:FileData = worker.loadingData;
  169. var dataTotal:Number = data.bytesTotal;
  170. if (dataTotal != undefined) totalAndLoaded.total += dataTotal;
  171. var dataLoaded:Number = data.bytesLoaded;
  172. if (dataLoaded != undefined) totalAndLoaded.loaded += dataLoaded;
  173. }
  174. }
  175. return totalAndLoaded;
  176. }
  177. /**
  178. *
  179. */
  180. public function toString () : String {
  181. return "; org.asapframework.util.loader.Loader";
  182. }
  183. /**
  184. @sends LoaderEvent#ON_ALL_LOADED When no more assets are in the queue
  185. @sends LoaderEvent#ON_START When a new LoaderWorker starts loading
  186. */
  187. private function getNextInQueue () : Void {
  188. updateLoadingState();
  189. if (mFileQueue.length == 0) {
  190. if (!isLoading()) {
  191. dispatchEvent(new LoaderEvent(LoaderEvent.ON_ALL_LOADED, this));
  192. }
  193. return;
  194. }
  195. // Not done yet, so get next free Worker
  196. var i:Number, len:Number = mWorkers.length;
  197. for (i=0; i<len; ++i) {
  198. var worker:LoaderWorker = LoaderWorker(mWorkers[i]);
  199. if (!worker.loading) {
  200. // get the first item
  201. var fileData:FileData = FileData(mFileQueue.shift());
  202. mCurrentLoadList.push(fileData);
  203. worker.load(fileData);
  204. mLoadingState = STATE_LOADING;
  205. dispatchEvent(new LoaderEvent(LoaderEvent.ON_START, this, fileData.name, 0, 0));
  206. break;
  207. }
  208. }
  209. }
  210. /**
  211. Updates the loading state; sets mLoadingState to true if one of the workers is loading; to false if all loader workers are free.
  212. */
  213. private function updateLoadingState () : Void {
  214. if (mLoadingState == STATE_PAUSED) {
  215. return;
  216. }
  217. if (mCurrentLoadList.length > 0) {
  218. mLoadingState = STATE_LOADING;
  219. } else {
  220. mLoadingState = STATE_NONE;
  221. }
  222. }
  223. /**
  224. Monitors the loading progress of one LoaderWorker object. This event is passed on to listeners of the Loader.
  225. @param e: event object with properties: .name, .type, .target
  226. @sends LoaderEvent#ON_PROGRESS When some data has been received
  227. */
  228. private function onWorkerLoadProgress (e:LoaderWorkerEvent) : Void {
  229. // calculate the total amount of data of all workers,
  230. // then send this information out
  231. var totalAndLoaded:Object = getTotalAndLoaded();
  232. dispatchEvent(new LoaderEvent(LoaderEvent.ON_PROGRESS, this, e.name, e.targetClip, totalAndLoaded.total, totalAndLoaded.loaded));
  233. }
  234. /**
  235. Received when a LoaderWorker object is finished or stopped loading. This event is passed on to listeners of the Loader.
  236. @param e: event object with properties: .name, .type, .target
  237. @sends LoaderEvent#ON_DONE When one asset has finished loading
  238. @implementationNote Calls {@link #getTotalAndLoaded}.
  239. */
  240. private function onWorkerLoadDone (e:LoaderWorkerEvent) : Void {
  241. var totalAndLoaded:Object = getTotalAndLoaded();
  242. dispatchEvent(new LoaderEvent(LoaderEvent.ON_DONE, this, e.name, e.targetClip, totalAndLoaded.total, totalAndLoaded.loaded));
  243. removeFromCurrentlyLoading(e.target.loadingData);
  244. getNextInQueue();
  245. }
  246. /**
  247. Received when a LoaderWorker object encounters an error during loading. This event is passed on to listeners of the Loader.
  248. @param e: event object with properties: .name, .target
  249. @sends LoaderEvent#ON_ERROR When an error happened during loading
  250. */
  251. private function onWorkerLoadError (e:LoaderWorkerEvent) : Void {
  252. // dispatch onLoadError event
  253. dispatchEvent(new LoaderEvent(LoaderEvent.ON_ERROR, this, e.name, e.targetClip));
  254. }
  255. /**
  256. Stops all workers loading.
  257. @param name : (optional) name of the loading request as passed with {@link #load}; if name is passed only the worker with that loading request name will be stopped; otherwise all workers will be stopped
  258. */
  259. private function stopLoadingWorkers (inName:String) : Void {
  260. var i:Number, len:Number = mWorkers.length;
  261. for (i=0; i<len; ++i) {
  262. var worker:LoaderWorker = LoaderWorker(mWorkers[i]);
  263. if (worker.loading) {
  264. if (inName != undefined) {
  265. if (worker.loadingData.name == inName) {
  266. worker.stopLoading();
  267. }
  268. } else {
  269. worker.stopLoading();
  270. }
  271. }
  272. }
  273. }
  274. /**
  275. Removes a FileData object from mCurrentLoadList.
  276. @param inFileData: object to remove
  277. */
  278. private function removeFromCurrentlyLoading (inFileData:FileData) : Void {
  279. var i:Number, ilen:Number = mCurrentLoadList.length;
  280. for (i=0; i<ilen; ++i) {
  281. if (mCurrentLoadList[i] == inFileData) {
  282. mCurrentLoadList.splice(i,1);
  283. }
  284. }
  285. }
  286. }