├── examples ├── .gitignore ├── assets │ ├── sound.mp3 │ ├── image1.jpg │ ├── xmldoc.xml.gz │ ├── subfolder │ │ └── image2.png │ ├── xmldoc.xml │ ├── asset-list.xml │ └── binarytest.js ├── AssetLists.as ├── NestedQueues.as ├── Basic.as ├── GZippedAssets.as └── Parameters.as ├── .gitignore ├── src └── com │ └── deadreckoned │ └── assetmanager │ ├── IQueueable.as │ ├── formats │ ├── VariablesHandler.as │ ├── ShaderHandler.as │ ├── BinaryHandler.as │ ├── ImageHandler.as │ ├── XMLHandler.as │ ├── JSONHandler.as │ ├── IFormatHandler.as │ ├── GenericHandler.as │ ├── SoundHandler.as │ ├── SWFHandler.as │ └── GZipHandler.as │ ├── events │ ├── AssetProgressEvent.as │ └── AssetEvent.as │ ├── AssetManager.as │ ├── Asset.as │ └── AssetQueue.as └── README.md /examples/.gitignore: -------------------------------------------------------------------------------- 1 | Test.as 2 | *.swf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | assetmanager.as3proj 2 | assetmanager.docproj 3 | /lib 4 | /bin 5 | /obj 6 | /doc 7 | /zip -------------------------------------------------------------------------------- /examples/assets/sound.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevewoolcock/AssetManager/HEAD/examples/assets/sound.mp3 -------------------------------------------------------------------------------- /examples/assets/image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevewoolcock/AssetManager/HEAD/examples/assets/image1.jpg -------------------------------------------------------------------------------- /examples/assets/xmldoc.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevewoolcock/AssetManager/HEAD/examples/assets/xmldoc.xml.gz -------------------------------------------------------------------------------- /examples/assets/subfolder/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stevewoolcock/AssetManager/HEAD/examples/assets/subfolder/image2.png -------------------------------------------------------------------------------- /examples/assets/xmldoc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/assets/asset-list.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image1.jpg 5 | sound.mp3 6 | xmldoc.xml 7 | swffile.swf 8 | binarytest.js 9 | this-asset-doesnt-exist.foo 10 | subfolder/image2.png 11 | -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/IQueueable.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.IQueueable 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * @author Stephen Woolcock 7 | */ 8 | 9 | package com.deadreckoned.assetmanager 10 | { 11 | 12 | internal interface IQueueable 13 | { 14 | /** 15 | * The priority of the object. 16 | */ 17 | function get priority():int; 18 | 19 | /** 20 | * The id of the object. 21 | */ 22 | function get id():String; 23 | } 24 | } -------------------------------------------------------------------------------- /examples/AssetLists.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Loading assets from an XML formatted list. 3 | */ 4 | package 5 | { 6 | import com.deadreckoned.assetmanager.AssetManager; 7 | import com.deadreckoned.assetmanager.events.AssetEvent; 8 | import flash.display.Sprite; 9 | 10 | public class AssetLists extends Sprite 11 | { 12 | private var _assetManager:AssetManager; 13 | 14 | public function AssetLists():void 15 | { 16 | // Setup asset manager 17 | _assetManager = AssetManager.getInstance(); 18 | _assetManager.addEventListener(AssetEvent.QUEUE_COMPLETE, onQueueComplete, false, 0, true); 19 | 20 | // Set the default path for all assets. Root-relative URLs (/) or URLs beginning 21 | // with protocols (http://, c:/, etc) will not use the default path. 22 | _assetManager.path = "assets/"; 23 | 24 | // Load assets from an asset list XML 25 | _assetManager.loadFromXML("asset-list.xml"); 26 | } 27 | 28 | /** 29 | * Executed when all assets in the queue have completed loading. 30 | * @param e The AssetEvent object 31 | */ 32 | private function onQueueComplete(e:AssetEvent):void 33 | { 34 | trace("---------------------------"); 35 | trace("Master asset queue complete"); 36 | trace("---------------------------"); 37 | 38 | trace("image1.jpg:", _assetManager.get("image1.jpg").asset); 39 | trace("subfolder/image2.png:", _assetManager.get("subfolder/image2.png").asset); 40 | trace("sound.mp3:", _assetManager.get("sound.mp3").asset); 41 | trace("swffile.swf:", _assetManager.get("swffile.swf").asset); 42 | trace("xmldoc.xml:", _assetManager.get("xmldoc.xml").asset); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /examples/NestedQueues.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Usage example showing nested queues. 3 | */ 4 | package 5 | { 6 | import com.deadreckoned.assetmanager.AssetManager; 7 | import com.deadreckoned.assetmanager.AssetQueue; 8 | import com.deadreckoned.assetmanager.events.AssetEvent; 9 | import flash.display.Sprite; 10 | 11 | public class NestedQueues extends Sprite 12 | { 13 | private var _assetManager:AssetManager; 14 | 15 | public function NestedQueues():void 16 | { 17 | _assetManager = AssetManager.getInstance(); 18 | _assetManager.addEventListener(AssetEvent.QUEUE_START, onQueueStarted, false, 0, true); 19 | _assetManager.addEventListener(AssetEvent.QUEUE_COMPLETE, onQueueComplete, false, 0, true); 20 | 21 | // Add a regular asset 22 | _assetManager.add("assets/image1.jpg"); 23 | 24 | // Create a secondary queue and add assets 25 | var secondaryQueue:AssetQueue = AssetManager.getInstance().createQueue("secondary"); 26 | secondaryQueue.addEventListener(AssetEvent.QUEUE_START, onQueueStarted, false, 0, true); 27 | secondaryQueue.addEventListener(AssetEvent.QUEUE_COMPLETE, onQueueComplete, false, 0, true); 28 | secondaryQueue.add("assets/subfolder/image2.png"); 29 | secondaryQueue.add("assets/swffile.swf"); 30 | secondaryQueue.add("assets/sound.mp3"); 31 | 32 | // Add secondary queue to master queue 33 | _assetManager.add(secondaryQueue); 34 | 35 | // Add some more assets to the master queue 36 | _assetManager.add("assets/binarytest.js"); 37 | _assetManager.add("assets/xmldoc.xml"); 38 | 39 | // Prioritize the secondary queue 40 | //_assetManager.prioritize(secondaryQueue); 41 | } 42 | 43 | private function onQueueStarted(e:AssetEvent):void 44 | { 45 | trace("Queue started:", e.target); 46 | } 47 | 48 | private function onQueueComplete(e:AssetEvent):void 49 | { 50 | trace("Queue complete:", e.target); 51 | 52 | if (e.target == _assetManager) 53 | { 54 | // Access assets loaded by the secondary queue via AssetManager 55 | trace("assets/swffile.swf:", _assetManager.get("assets/swffile.swf")); 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /examples/Basic.as: -------------------------------------------------------------------------------- 1 | /** 2 | * Basic AssetManager usage. 3 | */ 4 | package 5 | { 6 | import com.deadreckoned.assetmanager.AssetManager; 7 | import com.deadreckoned.assetmanager.events.AssetEvent; 8 | import flash.display.Sprite; 9 | 10 | public class Basic extends Sprite 11 | { 12 | private var _assetManager:AssetManager; 13 | 14 | public function Basic():void 15 | { 16 | // Turn verbose mode on/off 17 | //AssetManager.verbose = false; 18 | 19 | // Setup asset manager 20 | _assetManager = AssetManager.getInstance(); 21 | _assetManager.addEventListener(AssetEvent.QUEUE_START, onQueueStart, false, 0, true); 22 | _assetManager.addEventListener(AssetEvent.QUEUE_COMPLETE, onQueueComplete, false, 0, true); 23 | 24 | // Add assets to load 25 | _assetManager.add("assets/image1.jpg"); 26 | _assetManager.add("assets/subfolder/image2.png"); 27 | _assetManager.add("assets/sound.mp3"); 28 | _assetManager.add("assets/thisassetwillfailtoload.fail"); 29 | _assetManager.add("assets/swffile.swf"); 30 | _assetManager.add("assets/xmldoc.xml"); 31 | } 32 | 33 | /** 34 | * Executed when the asset queue begins loading. 35 | * @param e The AssetEvent object 36 | */ 37 | private function onQueueStart(e:AssetEvent):void 38 | { 39 | trace("--------------------------"); 40 | trace("Master asset queue started"); 41 | trace("--------------------------"); 42 | } 43 | 44 | /** 45 | * Executed when all assets in the queue have completed loading. 46 | * @param e The AssetEvent object 47 | */ 48 | private function onQueueComplete(e:AssetEvent):void 49 | { 50 | trace("---------------------------"); 51 | trace("Master asset queue complete"); 52 | trace("---------------------------"); 53 | 54 | // Test loaded assets 55 | trace("assets/image1.jpg:", _assetManager.get("assets/image1.jpg").asset); 56 | trace("assets/subfolder/image2.png:", _assetManager.get("assets/subfolder/image2.png").asset); 57 | trace("assets/sound.mp3:", _assetManager.get("assets/sound.mp3").asset); 58 | trace("assets/swffile.swf:", _assetManager.get("assets/swffile.swf").asset); 59 | trace("assets/xmldoc.xml:", _assetManager.get("assets/xmldoc.xml").asset); 60 | 61 | // Remove the swffile.swf asset 62 | _assetManager.purge("assets/swffile.swf"); 63 | trace("Removed: assets/swffile.swf:", _assetManager.get("assets/swffile.swf")); // Output: null 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /examples/GZippedAssets.as: -------------------------------------------------------------------------------- 1 | /** 2 | * GZip AssetManager usage. 3 | */ 4 | package 5 | { 6 | import com.deadreckoned.assetmanager.AssetManager; 7 | import com.deadreckoned.assetmanager.events.AssetEvent; 8 | import com.deadreckoned.assetmanager.formats.GZipHandler; 9 | import com.deadreckoned.assetmanager.formats.XMLHandler; 10 | import flash.display.Sprite; 11 | 12 | public class GZippedAssets extends Sprite 13 | { 14 | private var _assetManager:AssetManager; 15 | 16 | public function GZippedAssets():void 17 | { 18 | // Turn verbose mode on/off 19 | //AssetManager.verbose = false; 20 | 21 | // NOTE: To load and decompress gzip assets, Paul Robertson's Actionscript GZIP encoding library is required, 22 | // which can be found here: http://probertson.com/projects/gzipencoder/ 23 | // Download the SWC and add it to the project 24 | 25 | // Register the GZip handler with the asset manager 26 | AssetManager.registerFormat(GZipHandler, [ "gz" ], "gz"); 27 | 28 | // Register the XML handler with the GZip handler 29 | GZipHandler.addHandler(XMLHandler, "xml"); 30 | 31 | // Setup asset manager 32 | _assetManager = AssetManager.getInstance(); 33 | _assetManager.addEventListener(AssetEvent.QUEUE_COMPLETE, onQueueComplete, false, 0, true); 34 | 35 | // There are two ways to load gzipped assets: 36 | // The second method is generally more useful, as it can allow you to work with uncompressed files 37 | // during development, and compressed files in the live environment, while maintining the same URI formats 38 | _assetManager.add("assets/xmldoc.xml.gz"); // Load gzip file directly 39 | _assetManager.add("assets/xmldoc.xml", { type: GZipHandler.TYPE } ); // Specify gzip as the asset type 40 | } 41 | 42 | /** 43 | * Executed when all assets in the queue have completed loading. 44 | * @param e The AssetEvent object 45 | */ 46 | private function onQueueComplete(e:AssetEvent):void 47 | { 48 | trace("---------------------------"); 49 | trace("Master asset queue complete"); 50 | trace("---------------------------"); 51 | 52 | // Test loaded assets are of XML type 53 | trace("assets/xmldoc.xml.gz:", (_assetManager.get("assets/xmldoc.xml.gz").asset is XML)); 54 | trace(_assetManager.get("assets/xmldoc.xml.gz").asset); 55 | 56 | trace("assets/xmldoc.xml:", (_assetManager.get("assets/xmldoc.xml").asset is XML)); 57 | trace(_assetManager.get("assets/xmldoc.xml").asset); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/VariablesHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.VariablesHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.net.URLVariables; 35 | 36 | /** 37 | * The VariablesHandler handles the loading of variables in name/value pair format. It extends the GenericHandler class and loads 38 | * files in text format, assuming them to be of name/value pair format (ie. name1=value1&name2=value2) The data loaded 39 | * by VariablesHandler is returned as a URLVariables. 40 | */ 41 | public class VariablesHandler extends GenericHandler 42 | { 43 | private var _data:URLVariables; 44 | 45 | /** 46 | * Creates a new instance of the VariablesHandler class. 47 | */ 48 | public function VariablesHandler():void 49 | { 50 | // 51 | } 52 | 53 | /** 54 | * @inheritDoc 55 | */ 56 | public override function dispose():void 57 | { 58 | _data = null; 59 | super.dispose(); 60 | } 61 | 62 | /** 63 | * @inheritDoc 64 | */ 65 | public override function getContent():* 66 | { 67 | if (!loaded) return null; 68 | if (_data == null) _data = new URLVariables(String(_loader.data)); 69 | return _data; 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/ShaderHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.ShaderHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.display.Shader; 35 | import flash.net.URLLoaderDataFormat; 36 | 37 | /** 38 | * The ShaderHandler class handles the loading of Adobe Pixel Blender shader files. It extends the GenericHandler class and loads files in Adobe 39 | * Pixel Blender shader files (.pbj). The data loaded by ShaderHandler is returned as a Shader object. 40 | */ 41 | public class ShaderHandler extends GenericHandler 42 | { 43 | private var _shader:Shader; 44 | 45 | /** 46 | * @inheritDoc 47 | */ 48 | public override function get id ():String { return "pbj"; } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public override function get extensions ():Array { return [ "pbj" ]; } 54 | 55 | /** 56 | * Creates a new instance of the ShaderHandler class. 57 | */ 58 | public function ShaderHandler():void 59 | { 60 | _loader.dataFormat = URLLoaderDataFormat.BINARY; 61 | } 62 | 63 | /** 64 | * @inheritDoc 65 | */ 66 | public override function dispose():void 67 | { 68 | _shader = null; 69 | super.dispose(); 70 | } 71 | 72 | /** 73 | * @inheritDoc 74 | */ 75 | public override function getContent():* 76 | { 77 | if (!loaded) return null; 78 | if (_shader == null) _shader = new Shader(_loader.data); 79 | return _shader; 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/BinaryHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.BinaryHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.events.Event; 35 | import flash.events.EventDispatcher; 36 | import flash.events.IOErrorEvent; 37 | import flash.events.ProgressEvent; 38 | import flash.net.URLLoader; 39 | import flash.net.URLLoaderDataFormat; 40 | import flash.net.URLRequest; 41 | import flash.utils.ByteArray; 42 | 43 | /** 44 | * The BinaryHandler class handles the loading of binary files. It extends the GenericHandler class and loads files in binary 45 | * format. The data loaded by BinaryHandler is returned as a ByteArray. 46 | */ 47 | public class BinaryHandler extends GenericHandler 48 | { 49 | private var _data:ByteArray; 50 | 51 | /** 52 | * @inheritDoc 53 | */ 54 | public override function get id():String { return "bin"; } 55 | 56 | /** 57 | * Creates a new instance of the BinaryHandler class. 58 | */ 59 | public function BinaryHandler():void 60 | { 61 | _loader.dataFormat = URLLoaderDataFormat.BINARY; 62 | } 63 | 64 | /** 65 | * @inheritDoc 66 | */ 67 | public override function dispose():void 68 | { 69 | _data = null; 70 | super.dispose(); 71 | } 72 | 73 | /** 74 | * @inheritDoc 75 | */ 76 | public override function getContent():* 77 | { 78 | if (!loaded) return null; 79 | if (_data == null) _data = ByteArray(_loader.data); 80 | return _data; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/ImageHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.ImageHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.display.Bitmap; 35 | import flash.display.BitmapData; 36 | 37 | /** 38 | * The ImageHandler class handles the loading of image files. It supports the loading and retrieving of images in JPEG, PNG or GIF formats. 39 | * The data loaded by ImageHandler is returned as a BitmapData. 40 | */ 41 | public class ImageHandler extends SWFHandler 42 | { 43 | private var _bitmapData:BitmapData; 44 | 45 | /** 46 | * @inheritDoc 47 | */ 48 | public override function get id():String { return "img"; } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public override function get extensions():Array { return [ "jpg", "jpe", "jpeg", "gif", "png" ]; } 54 | 55 | /** 56 | * Creates a new instance of the ImageHandler class 57 | */ 58 | public function ImageHandler():void 59 | { 60 | // 61 | } 62 | 63 | /** 64 | * @inheritDoc 65 | */ 66 | public override function dispose():void 67 | { 68 | super.dispose(); 69 | if (_bitmapData != null) 70 | { 71 | _bitmapData.dispose(); 72 | _bitmapData = null; 73 | } 74 | } 75 | 76 | /** 77 | * @inheritDoc 78 | */ 79 | public override function getContent():* 80 | { 81 | if (!loaded) return null; 82 | if (_bitmapData == null) _bitmapData = Bitmap(_loader.content).bitmapData; 83 | return _bitmapData; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/XMLHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.XMLHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.events.Event; 35 | import flash.utils.ByteArray; 36 | 37 | /** 38 | * The XMLHandler handles the loading of XML files. It extends the GenericHandler class. The data loaded by XMLHandler is 39 | * returned as an XML object. 40 | */ 41 | public class XMLHandler extends GenericHandler 42 | { 43 | private var _data:XML; 44 | 45 | /** 46 | * @inheritDoc 47 | */ 48 | public override function get id():String { return "xml"; } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public override function get extensions():Array { return [ "xml", "htm", "html" ]; } 54 | 55 | /** 56 | * Creates a new instance of the XMLHandler class 57 | */ 58 | public function XMLHandler () 59 | { 60 | super(); 61 | } 62 | 63 | /** 64 | * @inheritDoc 65 | */ 66 | public override function dispose():void 67 | { 68 | _data = null; 69 | super.dispose(); 70 | } 71 | 72 | /** 73 | * @inheritDoc 74 | */ 75 | public override function getContent():* 76 | { 77 | if (!loaded) return null; 78 | if (_data == null) _data = new XML(_loader.data); 79 | return _data; 80 | } 81 | 82 | /** 83 | * @inheritDoc 84 | */ 85 | public override function loadBytes(bytes:ByteArray, context:* = null):void 86 | { 87 | _loaded = true; 88 | _data = XML(bytes.readUTFBytes(bytes.length)); 89 | dispatchEvent(new Event(Event.COMPLETE)); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/JSONHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.JSONHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.events.Event; 35 | import flash.utils.ByteArray; 36 | 37 | /** 38 | * The JSONHandler handles the loading of JSON files. It extends the GenericHandler class. The data loaded by JSONHandler is 39 | * returned as a dynamic object, parsed using the native JSON parser. 40 | */ 41 | public class JSONHandler extends GenericHandler 42 | { 43 | private var _data:Object; 44 | 45 | /** 46 | * @inheritDoc 47 | */ 48 | public override function get id():String { return "json"; } 49 | 50 | /** 51 | * @inheritDoc 52 | */ 53 | public override function get extensions():Array { return [ "json", "jsn" ]; } 54 | 55 | /** 56 | * Creates a new instance of the XMLHandler class 57 | */ 58 | public function JSONHandler() 59 | { 60 | super(); 61 | } 62 | 63 | /** 64 | * @inheritDoc 65 | */ 66 | public override function dispose():void 67 | { 68 | _data = null; 69 | super.dispose(); 70 | } 71 | 72 | /** 73 | * @inheritDoc 74 | */ 75 | public override function getContent():* 76 | { 77 | if (!loaded) return null; 78 | if (_data == null) _data = JSON.parse(String(_loader.data)); 79 | return _data; 80 | } 81 | 82 | 83 | /** 84 | * @inheritDoc 85 | */ 86 | public override function loadBytes(bytes:ByteArray, context:* = null):void 87 | { 88 | _loaded = true; 89 | _data = JSON.parse(bytes.readUTFBytes(bytes.length)); 90 | dispatchEvent(new Event(Event.COMPLETE)); 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/IFormatHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.IFormatHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.utils.ByteArray; 35 | 36 | /** 37 | * The IFormatHandler interface must be implemented by all registered file formats for the AssetManager. All format handlers should 38 | * also either extends flash.events.EventDispatcher or implement the flash.events.IEventDispatcher interface. 39 | */ 40 | public interface IFormatHandler 41 | { 42 | /** 43 | * A clean up routine that disposes all external references to prepare the class for garbage collection. 44 | */ 45 | function dispose():void; 46 | 47 | /** 48 | * An Array of extensions the IFormatHandler supports. 49 | */ 50 | function get extensions():Array; 51 | 52 | /** 53 | * Retrieves the contents of the loaded asset. 54 | * @return The contents of the loaded asset 55 | */ 56 | function getContent():*; 57 | 58 | /** 59 | * Retrieves the raw contents of the loaded asset. 60 | * @return The raw contents of the loaded asset 61 | */ 62 | function getRawContent():*; 63 | 64 | /** 65 | * The id of the IFormatHandler. 66 | */ 67 | function get id():String; 68 | 69 | /** 70 | * Begins loading a asset from a specific URL. 71 | * @param uri The URL of the asset to load 72 | * @param context An optional load context object 73 | */ 74 | function load(uri:String, context:* = null):void; 75 | 76 | /** 77 | * Begins loading an asset from a byte array. 78 | * @param bytes The byte array to load the asset data from 79 | * @param context An optional load context object 80 | */ 81 | function loadBytes(bytes:ByteArray, context:* = null):void; 82 | 83 | /** 84 | * Pauses the loading of the asset. 85 | */ 86 | function pauseLoad():void; 87 | } 88 | } -------------------------------------------------------------------------------- /examples/Parameters.as: -------------------------------------------------------------------------------- 1 | /** 2 | * AssetManager usage, using custom parameters for loading individual assets. 3 | */ 4 | package 5 | { 6 | import com.deadreckoned.assetmanager.AssetManager; 7 | import com.deadreckoned.assetmanager.events.AssetEvent; 8 | import flash.display.Sprite; 9 | import flash.utils.getQualifiedClassName; 10 | 11 | public class Parameters extends Sprite 12 | { 13 | private var _assetManager:AssetManager; 14 | 15 | public function Parameters():void 16 | { 17 | // Setup asset manager 18 | _assetManager = AssetManager.getInstance(); 19 | _assetManager.addEventListener(AssetEvent.QUEUE_COMPLETE, onQueueComplete, false, 0, true); 20 | 21 | // Set the default path for all assets. Root-relative URLs (/) or URLs beginning 22 | // with protocols (http://, c:/, etc) will not use the default path. 23 | _assetManager.path = "assets/"; 24 | 25 | 26 | // Load image1.jpg as a binary file, rather than BitmapData 27 | _assetManager.add("image1.jpg", { type: AssetManager.TYPE_BINARY } ); 28 | 29 | 30 | // Load swffile.swf, with a high priority. This will force the file to be loaded first, before all other assets in the queue. 31 | // The default priority is 0, and priorities can be a positive or negative integer (just like events) 32 | _assetManager.add("swffile.swf", { priority: 5 } ); 33 | 34 | 35 | // Load subfolder/image2.png with an onComplete callback 36 | _assetManager.add("subfolder/image2.png", { onComplete: function():void 37 | { 38 | trace(" subfolder/image2.png complete"); 39 | } }); 40 | 41 | 42 | // Load sound.mp3 with an onStart callback, with arguments 43 | _assetManager.add("sound.mp3", { onStartParams: [ "foobar", int.MAX_VALUE ], onStart: function(param1:String, param2:int):void 44 | { 45 | trace("> sound.mp3 started, arguments=" + arguments); 46 | } }); 47 | 48 | 49 | // Load a non-existing asset with an onError callback 50 | _assetManager.add("thisassetwillfailtoload.fail", { onError: function():void 51 | { 52 | trace(" thisassetwillfailtoload.fail failed to load"); 53 | } } ); 54 | 55 | 56 | // Load xmldoc.xml, but use a custom id for access 57 | _assetManager.add("xmldoc.xml", { id: "myXMLDoc" } ); 58 | 59 | 60 | // Overwrite subfolder/image2.png. This will cause the initial addition of subfolder/image2.png to be disposed, so the 61 | _assetManager.add("binarytest.js", { onStart: function():void { trace("This callback will not be executed"); } } ); 62 | _assetManager.add("binarytest.js", { overwrite: true } ); 63 | } 64 | 65 | /** 66 | * Executed when all assets in the queue have completed loading. 67 | * @param e The AssetEvent object 68 | */ 69 | private function onQueueComplete(e:AssetEvent):void 70 | { 71 | trace("---------------------------"); 72 | trace("Master asset queue complete"); 73 | trace("---------------------------"); 74 | 75 | trace("image1.jpg:", getQualifiedClassName(_assetManager.get("image1.jpg").asset)); 76 | trace("subfolder/image2.png:", _assetManager.get("subfolder/image2.png").asset); 77 | trace("sound.mp3:", _assetManager.get("sound.mp3").asset); 78 | trace("swffile.swf:", _assetManager.get("swffile.swf").asset); 79 | trace("myXMLDoc:", _assetManager.get("myXMLDoc").asset); 80 | trace("binarytest.js:", getQualifiedClassName(_assetManager.get("binarytest.js").asset)); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AssetManager 2 | 3 | ####A lightweight ActionScript 3.0 asset management solution 4 | 5 | 6 | ## Description 7 | 8 | AssetManager is a simple, yet flexible, solution to asset management for AS3 projects. 9 | 10 | It provides a clean, simple and well documented API to allow you to focus on building 11 | your projects quickly without having to worry about how to load, store and retrieve assets. 12 | 13 | AssetManager contains a simple plugin architecture for file formated to keep the footprint low. 14 | A default import of AssetManager with no custom plugins activated weighs in at around 8.3kb. 15 | 16 | 17 | ## Features 18 | 19 | * Clean and simple API 20 | * Global and local loading queues 21 | * Nestable queues 22 | * Simple purging system for managing garbage collection and keeping memory usage in check 23 | * Priority system for controlling loading priority of individual assets and nested queues 24 | * Ability to store any valid ActionScript object, so all assets, internal or external, can be managed through AssetManager 25 | * Support for XML formatted asset lists 26 | * Plugin architecture for handling different data and file formats. Included format handlers are: 27 | * Binary 28 | * Images (PNG, GIF and JPEG) 29 | * Sound (MP3) 30 | * SWF 31 | * XML 32 | * GZIP (requires [Paul Robertson's Actionscript GZIP encoding library](http://probertson.com/projects/gzipencoder/ "Actionscript GZIP encoding library")) 33 | * Name/value pairs 34 | * Adobe Pixel Blender Shaders 35 | * Easily extendable with plugin architecture to support any format 36 | * Suitable for use in both small projects and large enterprise level projects 37 | 38 | ## Future Additions 39 | 40 | * Support for loading and decompressing of ZIP archives 41 | 42 | ## Quick API Examples 43 | 44 | Load an external asset and listen for completion: 45 | 46 | var assetManager:AssetManager = AssetManager.getInstance(); 47 | assetManager.addEventListener(AssetEvent.QUEUE_COMPLETE, onQueueComplete, false, 0, true); 48 | assetManager.add("assets/image1.jpg"); 49 | assetManager.add("assets/sound.mp3"); 50 | 51 | Retrieving a loaded asset: 52 | 53 | var bmd:BitmapData = AssetManager.getInstance().get("assets/image1.jpg").asset; 54 | 55 | Load an asset with a custom high priority: 56 | 57 | AssetManager.getInstance().add("myChildSWF.swf", { priority: 5 } ); 58 | 59 | Load a single asset and execute a callback upon completion: 60 | 61 | AssetManager.getInstance().add("image.png", { 62 | onComplete: function():void 63 | { 64 | trace("Asset complete:", AssetManager.getInstance().get("image.png")); 65 | } 66 | }); 67 | 68 | Remove a loading, or previously loaded asset: 69 | 70 | AssetManager.getInstance().purge("image.png"); 71 | 72 | Remove all loaded and currently loading assets: 73 | 74 | AssetManager.getInstance().purge(); 75 | 76 | See the [example](https://github.com/stevewoolcock/AssetManager/tree/master/examples "AssetManager examples") projects for more examples and advanced features. 77 | 78 | 79 | ## Documentation 80 | 81 | [API documentation](http://docs.deadreckoned.com/assetmanager "AssetManager API documentation") 82 | 83 | [Examples](https://github.com/stevewoolcock/AssetManager/tree/master/examples "AssetManager examples") 84 | 85 | 86 | ## Contribute 87 | 88 | AssetManager is MIT-licensed. Please let me know of any issues and problems you encounter. Feel free 89 | to submit suggestions or pull-requests with new features or fixes. 90 | 91 | [Issue tracker](https://github.com/stevewoolcock/AssetManager/issues "AssetManager Issue Tracker") -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/events/AssetProgressEvent.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.events.AssetProgressEvent 3 | * 4 | * Copyright (c) 2012 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.events 33 | { 34 | import com.deadreckoned.assetmanager.Asset; 35 | import flash.events.Event; 36 | import flash.events.ProgressEvent; 37 | 38 | /** 39 | * AssetProgressEvent instances are dispatched by AssetManager instances, and relate to the load progress state of files 40 | * being loaded by a AssetManager instance. 41 | */ 42 | public class AssetProgressEvent extends ProgressEvent 43 | { 44 | /** 45 | * The AssetProgressEvent.PROGRESS constant defines the value of the type property of the event object 46 | * for a AssetComplete event. 47 | * 48 | *

The properties of the event object have the following values:

49 | * 50 | * 51 | * 52 | * 53 | * 54 | * 55 | * 56 | * 57 | * 58 | *
PropertyValue
bubblestrue
bytesLoadedThe number of items or bytes loaded at the time the listener processes the event.
bytesTotalThe total number of items or bytes that ultimately will be loaded if the loading process succeeds.
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe object reporting progress.
fileIdThe id of the file that the event relates to.
59 | * 60 | * @eventType AssetProgress 61 | */ 62 | static public const PROGRESS:String = "AssetProgress"; 63 | 64 | private var _asset:Asset; 65 | 66 | /** 67 | * The asset the event relates to. 68 | */ 69 | public function get asset():Asset { return _asset; } 70 | 71 | /** 72 | * Creates a new instance of the AssetProgressEvent class 73 | * @param type The type of event to create 74 | * @param bubbles Specifies if bubbling is enabled for this event 75 | * @param cancelable Specifies if this event can be canceled 76 | */ 77 | public function AssetProgressEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, bytesLoaded:uint = 0, bytesTotal:uint = 0, asset:Asset = null):void 78 | { 79 | super(type, bubbles, cancelable, bytesLoaded, bytesTotal); 80 | _asset = asset; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/GenericHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.GenericHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.events.Event; 35 | import flash.events.EventDispatcher; 36 | import flash.events.IOErrorEvent; 37 | import flash.events.ProgressEvent; 38 | import flash.net.URLLoader; 39 | import flash.net.URLRequest; 40 | import flash.utils.ByteArray; 41 | 42 | /** 43 | * The GenericHandler class handles the loading of generic files using a URLLoader. GenericHandler can be used for loading 44 | * text-based formats, such a Text or XML files, or can be extended to expand on the features of URLLoader. 45 | */ 46 | public class GenericHandler extends EventDispatcher implements IFormatHandler 47 | { 48 | protected var _loaded:Boolean; 49 | protected var _loader:URLLoader; 50 | 51 | /** 52 | * @inheritDoc 53 | */ 54 | public function get id ():String { return null; } 55 | 56 | /** 57 | * @inheritDoc 58 | */ 59 | public function get extensions():Array { return null; } 60 | 61 | /** 62 | * Indicates if the file has been loaded. 63 | */ 64 | public function get loaded():Boolean { return _loaded; } 65 | 66 | /** 67 | * Creates a new instance of the GenericHandler class. 68 | */ 69 | public function GenericHandler():void 70 | { 71 | _loader = new URLLoader(); 72 | _loader.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true); 73 | _loader.addEventListener(ProgressEvent.PROGRESS, onLoadProgress, false, 0, true); 74 | _loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadIOError, false, 0, true); 75 | } 76 | 77 | /** 78 | * @inheritDoc 79 | */ 80 | public function dispose():void 81 | { 82 | try { _loader.close(); } catch (e:Error) { } 83 | _loader = null; 84 | _loaded = false; 85 | } 86 | 87 | /** 88 | * @inheritDoc 89 | */ 90 | public function getContent():* 91 | { 92 | if (!_loaded) return null; 93 | return _loader.data; 94 | } 95 | 96 | /** 97 | * @inheritDoc 98 | */ 99 | public function getRawContent():* 100 | { 101 | if (!_loaded) return null; 102 | return _loader.data; 103 | } 104 | 105 | /** 106 | * @inheritDoc 107 | */ 108 | public function load(uri:String, context:* = null):void 109 | { 110 | _loaded = false; 111 | _loader.load(new URLRequest(uri)); 112 | } 113 | 114 | /** 115 | * @inheritDoc 116 | */ 117 | public function loadBytes(bytes:ByteArray, context:* = null):void 118 | { 119 | _loaded = true; 120 | _loader.data = bytes; 121 | dispatchEvent(new Event(Event.COMPLETE)); 122 | } 123 | 124 | /** 125 | * @inheritDoc 126 | */ 127 | public function pauseLoad():void 128 | { 129 | try { _loader.close(); } catch (e:Error) { } 130 | } 131 | 132 | 133 | // EVENT HANDLERS 134 | // ------------------------------------------------------------------------------------------ 135 | /** 136 | * Executed when the file has completed loading. 137 | * @param e The Event object 138 | */ 139 | private function onLoadComplete(e:Event):void 140 | { 141 | _loaded = true; 142 | if (hasEventListener(e.type)) 143 | dispatchEvent(e.clone()); 144 | } 145 | 146 | /** 147 | * Executed when the file could not be loaded. 148 | * @param e The IOErrorEvent object 149 | */ 150 | private function onLoadIOError(e:IOErrorEvent):void 151 | { 152 | if (hasEventListener(e.type)) 153 | dispatchEvent(e.clone()); 154 | } 155 | 156 | /** 157 | * Executed when the file's load progress changes. 158 | * @param e The ProgressEvent object 159 | */ 160 | private function onLoadProgress(e:ProgressEvent):void 161 | { 162 | if (hasEventListener(e.type)) 163 | dispatchEvent(e.clone()); 164 | } 165 | } 166 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/SoundHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.SoundHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.1.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.events.Event; 35 | import flash.events.EventDispatcher; 36 | import flash.events.IOErrorEvent; 37 | import flash.events.ProgressEvent; 38 | import flash.media.Sound; 39 | import flash.media.SoundLoaderContext; 40 | import flash.net.URLRequest; 41 | import flash.utils.ByteArray; 42 | 43 | /** 44 | * The SoundHandler class handles the loading of sound files. The data loaded by SoundHandler is returned as a 45 | * Sound object. 46 | */ 47 | public class SoundHandler extends EventDispatcher implements IFormatHandler 48 | { 49 | private var _loaded:Boolean; 50 | private var _sound:Sound; 51 | 52 | /** 53 | * @inheritDoc 54 | */ 55 | public function get id ():String { return "snd"; } 56 | 57 | /** 58 | * @inheritDoc 59 | */ 60 | public function get extensions ():Array { return [ "mp3" ]; } 61 | 62 | /** 63 | * Indicates if the file has been loaded. 64 | */ 65 | public function get loaded ():Boolean { return _loaded; } 66 | 67 | /** 68 | * Creates a new instance of the SoundHandler class 69 | */ 70 | public function SoundHandler():void 71 | { 72 | _sound = new Sound(); 73 | _sound.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true); 74 | _sound.addEventListener(ProgressEvent.PROGRESS, onLoadProgress, false, 0, true); 75 | _sound.addEventListener(IOErrorEvent.IO_ERROR, onLoadIOError, false, 0, true); 76 | } 77 | 78 | /** 79 | * @inheritDoc 80 | */ 81 | public function dispose():void 82 | { 83 | try { _sound.close(); } catch (e:Error) { } 84 | _sound = null; 85 | _loaded = false; 86 | } 87 | 88 | /** 89 | * @inheritDoc 90 | */ 91 | public function getContent():* 92 | { 93 | if (!_loaded) return null; 94 | return _sound; 95 | } 96 | 97 | /** 98 | * @inheritDoc 99 | */ 100 | public function getRawContent():* 101 | { 102 | if (!_loaded) return null; 103 | return _sound; 104 | } 105 | 106 | /** 107 | * @inheritDoc 108 | */ 109 | public function load(uri:String, context:* = null):void 110 | { 111 | _loaded = false; 112 | _sound.load(new URLRequest(uri), SoundLoaderContext(context)); 113 | } 114 | 115 | /** 116 | * @inheritDoc 117 | */ 118 | public function loadBytes(bytes:ByteArray, context:* = null):void 119 | { 120 | if (!("loadCompressedDataFromByteArray" in _sound)) 121 | throw new Error("loadBytes is not support for SoundHandler when compiling to < Flash Player 11"); 122 | 123 | _sound["loadCompressedDataFromByteArray"](bytes, bytes.length); 124 | _loaded = true; 125 | dispatchEvent(new Event(Event.COMPLETE)); 126 | } 127 | 128 | /** 129 | * @inheritDoc 130 | */ 131 | public function pauseLoad():void 132 | { 133 | try { _sound.close(); } catch (e:Error) { } 134 | } 135 | 136 | 137 | // EVENT HANDLERS 138 | // ------------------------------------------------------------------------------------------ 139 | /** 140 | * Executed when the file has completed loading. 141 | * @param e The Event object 142 | */ 143 | private function onLoadComplete(e:Event):void 144 | { 145 | _loaded = true; 146 | if (hasEventListener(e.type)) 147 | dispatchEvent(e.clone()); 148 | } 149 | 150 | /** 151 | * Executed when the file could not be loaded. 152 | * @param e The IOErrorEvent object 153 | */ 154 | private function onLoadIOError(e:IOErrorEvent):void 155 | { 156 | if (hasEventListener(e.type)) 157 | dispatchEvent(e.clone()); 158 | } 159 | 160 | /** 161 | * Executed when the file's load progress changes. 162 | * @param e The ProgressEvent object 163 | */ 164 | private function onLoadProgress(e:ProgressEvent):void 165 | { 166 | if (hasEventListener(e.type)) 167 | dispatchEvent(e.clone()); 168 | } 169 | } 170 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/SWFHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.SWFHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager.formats 33 | { 34 | import flash.display.Loader; 35 | import flash.events.Event; 36 | import flash.events.EventDispatcher; 37 | import flash.events.IOErrorEvent; 38 | import flash.events.ProgressEvent; 39 | import flash.net.URLRequest; 40 | import flash.system.Capabilities; 41 | import flash.system.LoaderContext; 42 | import flash.utils.ByteArray; 43 | 44 | /** 45 | * The SWFHandler handles the loading of Flash SWF files. The data loaded by SWFHandler is returned as a DisplayObject. 46 | */ 47 | public class SWFHandler extends EventDispatcher implements IFormatHandler 48 | { 49 | private var _loaded:Boolean; 50 | protected var _loader:Loader; 51 | 52 | /** 53 | * @inheritDoc 54 | */ 55 | public function get id():String { return "swf"; } 56 | 57 | /** 58 | * @inheritDoc 59 | */ 60 | public function get extensions():Array { return [ "swf" ]; } 61 | 62 | /** 63 | * Indicates if the file has been loaded. 64 | */ 65 | public function get loaded():Boolean { return _loaded; } 66 | 67 | /** 68 | * Creates a new instance of the SWFHandler class. 69 | */ 70 | public function SWFHandler():void 71 | { 72 | _loader = new Loader(); 73 | _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true); 74 | _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoadProgress, false, 0, true); 75 | _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onLoadIOError, false, 0, true); 76 | } 77 | 78 | /** 79 | * @inheritDoc 80 | */ 81 | public function dispose():void 82 | { 83 | _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoadComplete); 84 | _loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onLoadProgress); 85 | _loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onLoadIOError); 86 | 87 | try { _loader.close(); } catch (e:Error) { } 88 | try { _loader.unloadAndStop(true); } catch (e:Error) { } 89 | 90 | _loader = null; 91 | _loaded = false; 92 | } 93 | 94 | /** 95 | * @inheritDoc 96 | */ 97 | public function getContent():* 98 | { 99 | if (!_loaded) return null; 100 | return _loader.content; 101 | } 102 | 103 | /** 104 | * @inheritDoc 105 | */ 106 | public function getRawContent():* 107 | { 108 | if (!_loaded) return null; 109 | return _loader.content; 110 | } 111 | 112 | /** 113 | * @inheritDoc 114 | */ 115 | public function load(uri:String, context:* = null):void 116 | { 117 | _loaded = false; 118 | _loader.load(new URLRequest(uri), context as LoaderContext); 119 | } 120 | 121 | /** 122 | * @inheritDoc 123 | */ 124 | public function loadBytes(bytes:ByteArray, context:* = null):void 125 | { 126 | _loaded = false; 127 | _loader.loadBytes(bytes, context as LoaderContext); 128 | } 129 | 130 | /** 131 | * @inheritDoc 132 | */ 133 | public function pauseLoad():void 134 | { 135 | try { _loader.close(); } catch (e:Error) { } 136 | } 137 | 138 | 139 | // EVENT HANDLERS 140 | // ------------------------------------------------------------------------------------------ 141 | /** 142 | * Executed when the file has completed loading. 143 | * @param e The Event object 144 | */ 145 | private function onLoadComplete(e:Event):void 146 | { 147 | _loaded = true; 148 | if (hasEventListener(e.type)) 149 | dispatchEvent(e.clone()); 150 | } 151 | 152 | /** 153 | * Executed when the file could not be loaded. 154 | * @param e The IOErrorEvent object 155 | */ 156 | private function onLoadIOError(e:IOErrorEvent):void 157 | { 158 | if (hasEventListener(e.type)) 159 | dispatchEvent(e.clone()); 160 | } 161 | 162 | /** 163 | * Executed when the file's load progress changes. 164 | * @param e The ProgressEvent object 165 | */ 166 | private function onLoadProgress(e:ProgressEvent):void 167 | { 168 | if (hasEventListener(e.type)) 169 | dispatchEvent(e.clone()); 170 | } 171 | } 172 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/formats/GZipHandler.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.formats.GZipHandler 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * GZipHandler utilises and required Paul Robertson's Actionscript GZIP encoding library. 7 | * The latest version can be downloaded here: 8 | * http://probertson.com/projects/gzipencoder/ 9 | * Download the SWC and add it to your project 10 | * 11 | * Permission is hereby granted, free of charge, to any person 12 | * obtaining a copy of this software and associated documentation 13 | * files (the "Software"), to deal in the Software without 14 | * restriction, including without limitation the rights to use, 15 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the 17 | * Software is furnished to do so, subject to the following 18 | * conditions: 19 | * 20 | * The above copyright notice and this permission notice shall be 21 | * included in all copies or substantial portions of the Software. 22 | * 23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 25 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 27 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30 | * OTHER DEALINGS IN THE SOFTWARE. 31 | * 32 | * @author Stephen Woolcock 33 | * @version 1.0.0 34 | * @link blog.deadreckoned.com 35 | */ 36 | 37 | package com.deadreckoned.assetmanager.formats 38 | { 39 | import com.probertson.utils.GZIPBytesEncoder; 40 | import flash.events.Event; 41 | import flash.events.EventDispatcher; 42 | import flash.events.IOErrorEvent; 43 | import flash.events.ProgressEvent; 44 | import flash.net.URLLoader; 45 | import flash.net.URLLoaderDataFormat; 46 | import flash.net.URLRequest; 47 | import flash.utils.ByteArray; 48 | import flash.utils.Dictionary; 49 | 50 | public class GZipHandler extends EventDispatcher implements IFormatHandler 51 | { 52 | static private var _gzip:GZIPBytesEncoder = new GZIPBytesEncoder(); 53 | static private var _handlerClassByExtension:Dictionary = new Dictionary(true); 54 | 55 | static public const TYPE:String = "gz"; 56 | 57 | /** 58 | * Determines wether or not the '.gz' extension is automatically appended to a URI when loading an asset, if required. 59 | */ 60 | static public var autoAppendGZExtension:Boolean = true; 61 | 62 | private var _context:*; 63 | private var _loaded:Boolean; 64 | private var _data:*; 65 | private var _uri:String; 66 | protected var _loader:URLLoader; 67 | 68 | /** 69 | * @inheritDoc 70 | */ 71 | public function get id ():String { return "gz"; } 72 | 73 | /** 74 | * @inheritDoc 75 | */ 76 | public function get extensions():Array { return [ "gz" ]; } 77 | 78 | /** 79 | * Indicates if the file has been loaded. 80 | */ 81 | public function get loaded():Boolean { return _loaded; } 82 | 83 | /** 84 | * Creates a new instance of the GZipHandler class. 85 | * GZipHandler utilises and required Paul Robertson's Actionscript GZIP encoding library. 86 | * The latest version can be downloaded here: 87 | * http://probertson.com/projects/gzipencoder/ 88 | * Download the SWC and add it to your project 89 | */ 90 | public function GZipHandler():void 91 | { 92 | _loader = new URLLoader(); 93 | _loader.dataFormat = URLLoaderDataFormat.BINARY; 94 | _loader.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true); 95 | _loader.addEventListener(ProgressEvent.PROGRESS, onLoadProgress, false, 0, true); 96 | _loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadIOError, false, 0, true); 97 | } 98 | 99 | /** 100 | * Adds a decompression handler type. 101 | * @param handlerClass The handler class 102 | * @param extension The extension to use the handler on 103 | */ 104 | static public function addHandler(handlerClass:Class, extension:String):void 105 | { 106 | _handlerClassByExtension[extension] = handlerClass; 107 | } 108 | 109 | /** 110 | * @inheritDoc 111 | */ 112 | public function dispose():void 113 | { 114 | try { _loader.close(); } catch (e:Error) { } 115 | _loader = null; 116 | _loaded = false; 117 | } 118 | 119 | /** 120 | * @inheritDoc 121 | */ 122 | public function getContent():* 123 | { 124 | if (!_loaded) return null; 125 | return _data; 126 | } 127 | 128 | /** 129 | * @inheritDoc 130 | */ 131 | public function getRawContent():* 132 | { 133 | if (!_loaded) return null; 134 | return _loader.data; 135 | } 136 | 137 | /** 138 | * @inheritDoc 139 | */ 140 | public function load(uri:String, context:* = null):void 141 | { 142 | try { _loader.close(); } catch (e:Error) { } 143 | 144 | _uri = uri; 145 | _context = context; 146 | _loaded = false; 147 | 148 | // Add Gzip extension if required 149 | if (autoAppendGZExtension) 150 | { 151 | if (uri.indexOf(".gz") == -1) 152 | uri += ".gz"; 153 | } 154 | 155 | _loader.load(new URLRequest(uri)); 156 | } 157 | 158 | /** 159 | * @inheritDoc 160 | */ 161 | public function loadBytes(bytes:ByteArray, context:* = null):void 162 | { 163 | _loader.data = bytes; 164 | onLoadComplete(null); 165 | } 166 | 167 | /** 168 | * @inheritDoc 169 | */ 170 | public function pauseLoad():void 171 | { 172 | try { _loader.close(); } catch (e:Error) { } 173 | } 174 | 175 | 176 | // EVENT HANDLERS 177 | // ------------------------------------------------------------------------------------------ 178 | /** 179 | * Executed when the file has completed loading. 180 | * @param e The Event object 181 | */ 182 | private function onLoadComplete(e:Event):void 183 | { 184 | _loaded = true; 185 | 186 | // Decompress data 187 | var unzipped:ByteArray = _gzip.uncompressToByteArray(_loader.data); 188 | 189 | // Attempt to determine the file type from the extension 190 | var uri:String = _uri.replace("." + extensions[0], ""); // Remove gz extension 191 | var ext:String = uri.substring(uri.lastIndexOf(".") + 1); // Extract extension 192 | 193 | // Get handler for extension 194 | var handlerClass:Class = _handlerClassByExtension[ext]; 195 | if (handlerClass == null) 196 | throw new ArgumentError("No format handler with the type '" + ext + "' has been registered. Use AssetManager.registerFormat() to register new or custom formats."); 197 | 198 | var handler:IFormatHandler = new handlerClass(); 199 | handler.loadBytes(unzipped, _context); 200 | _data = handler.getContent(); 201 | 202 | if (hasEventListener(e.type)) 203 | dispatchEvent(e.clone()); 204 | } 205 | 206 | /** 207 | * Executed when the file could not be loaded. 208 | * @param e The IOErrorEvent object 209 | */ 210 | private function onLoadIOError(e:IOErrorEvent):void 211 | { 212 | if (hasEventListener(e.type)) 213 | dispatchEvent(e.clone()); 214 | } 215 | 216 | /** 217 | * Executed when the file's load progress changes. 218 | * @param e The ProgressEvent object 219 | */ 220 | private function onLoadProgress(e:ProgressEvent):void 221 | { 222 | if (hasEventListener(e.type)) 223 | dispatchEvent(e.clone()); 224 | } 225 | } 226 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/AssetManager.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.AssetManager 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager 33 | { 34 | import com.deadreckoned.assetmanager.formats.*; 35 | import com.deadreckoned.assetmanager.formats.IFormatHandler; 36 | import flash.utils.Dictionary; 37 | 38 | 39 | /** 40 | * [Singleton] The AssetManager class is a Singleton object that handles bulk loading of assets. The singleton AssetManager instance inherits from AssetQueue. 41 | */ 42 | public final class AssetManager extends AssetQueue 43 | { 44 | static private const GLOBAL_ID:String = "$_global"; 45 | 46 | static private var _instance:AssetManager; 47 | static private var _nextId:int = 0; 48 | 49 | /** 50 | * @private 51 | */ 52 | static internal var _formats:Dictionary = new Dictionary(); 53 | 54 | /** 55 | * @private 56 | */ 57 | static internal var _formatExtensions:Dictionary = new Dictionary(); 58 | 59 | /** 60 | * Determines if a verbose description of AssetQueue operations are displayed in the output window. 61 | */ 62 | static public var verbose:Boolean = true; 63 | 64 | /** 65 | * The binary asset type id. 66 | */ 67 | static public const TYPE_BINARY:String = "bin"; 68 | 69 | /** 70 | * The image asset type id. 71 | */ 72 | static public const TYPE_IMAGE:String = "img"; 73 | 74 | /** 75 | * The sound asset type id. 76 | */ 77 | static public const TYPE_SOUND:String = "snd"; 78 | 79 | /** 80 | * The SWF asset type id. 81 | */ 82 | static public const TYPE_SWF:String = "swf"; 83 | 84 | /** 85 | * The text asset type id. 86 | */ 87 | static public const TYPE_TEXT:String = "txt"; 88 | 89 | /** 90 | * The XML asset type id. 91 | */ 92 | static public const TYPE_XML:String = "xml"; 93 | 94 | // Static constructor 95 | { 96 | // Default supported file types 97 | registerFormat(BinaryHandler); 98 | registerFormat(GenericHandler); 99 | registerFormat(GenericHandler, [ "txt" ], TYPE_TEXT); 100 | registerFormat(ImageHandler); 101 | registerFormat(SoundHandler); 102 | registerFormat(SWFHandler); 103 | registerFormat(XMLHandler); 104 | } 105 | 106 | /** 107 | * [Singleton] AssetManager is a Singleton and cannot be directly instantiated. Use AssetManager.getInstance() to retrieve the singleton instance of the AssetManager class. 108 | */ 109 | public function AssetManager(enforcer:AssetManagerSingletonEnforcer):void 110 | { 111 | super("$global"); 112 | 113 | if (enforcer == null) 114 | throw new Error("AssetManager is a Singleton and cannot be directly instantiated. Use AssetManager.getInstance()."); 115 | } 116 | 117 | 118 | // STATIC PUBLIC FUNCTIONS 119 | // ------------------------------------------------------------------------------------------ 120 | /** 121 | * Retrieves a singleton instance of AssetManager class. 122 | * @return The singleton instance of the AssetManager class 123 | */ 124 | static public function getInstance():AssetManager 125 | { 126 | return _instance || (_instance = new AssetManager(new AssetManagerSingletonEnforcer())); 127 | } 128 | 129 | /** 130 | * Registers a new file format handler. 131 | * @param handler The handler Class of the format 132 | * @param extensions [Optional] An Array of file extensions that should be handled by this format handler 133 | * @param id [Optional] The id to associate the handler with 134 | */ 135 | static public function registerFormat(HandlerClass:Class, extensions:Array = null, id:String = null):void 136 | { 137 | var instance:IFormatHandler = new HandlerClass(); 138 | 139 | // If values aren't supplied, use the defaults from the handler 140 | id = id ? id : instance.id; 141 | extensions = extensions ? extensions : instance.extensions; 142 | 143 | _formats[id] = HandlerClass; 144 | 145 | if (extensions != null) 146 | { 147 | for (var i:int = 0, len:int = extensions.length; i < len; i++) 148 | { 149 | _formatExtensions[extensions[i]] = id; 150 | } 151 | } 152 | 153 | instance.dispose(); 154 | } 155 | 156 | /** 157 | * Prints the list of registered file formats to the output window. 158 | */ 159 | static public function listRegisteredFormats():void 160 | { 161 | var output:String = "AssetManager registered file formats: "; 162 | for (var i:String in _formats) 163 | { 164 | output += "\r " + i + " (handler: " + _formats[i] + ")"; 165 | } 166 | trace(output); 167 | } 168 | 169 | 170 | // PUBLIC FUNCTIONS 171 | // ------------------------------------------------------------------------------------------ 172 | /** 173 | * Creates a new AssetQueue, with the same settings as the global queue. 174 | * @param id An option id for the queue 175 | * @return The new AssetQueue, with the same settings as the global queue 176 | */ 177 | public function createQueue(id:String = null):AssetQueue 178 | { 179 | id ||= "_queue" + (_nextId++); 180 | 181 | var queue:AssetQueue = new AssetQueue(id); 182 | queue.path = this.path; 183 | queue.queryString = this.queryString; 184 | queue.urlFunction = this.urlFunction; 185 | queue.loadSequentially = this.loadSequentially; 186 | return queue; 187 | } 188 | 189 | /** 190 | * @inheritDoc 191 | */ 192 | public override function toString():String 193 | { 194 | return "(AssetManager assetsTotal=" + assetsTotal + ", assetsLoading=" + assetsLoading + ", assetsLoaded=" + assetsLoaded + ")"; 195 | } 196 | 197 | 198 | // PRIVATE FUNCTIONS 199 | // ------------------------------------------------------------------------------------------ 200 | /** 201 | * @private 202 | */ 203 | internal function addAsset(asset:Asset):void 204 | { 205 | _assetsById[asset.id] = asset; 206 | if (_loaded.indexOf(asset) == -1) 207 | _loaded.push(asset); 208 | } 209 | 210 | /** 211 | * @private 212 | */ 213 | internal function removeAsset(asset:Asset):void 214 | { 215 | if (_assetsById[asset.id] === asset) 216 | { 217 | _loaded.splice(_loaded.indexOf(asset), 1); 218 | _assetsById[asset.id] = null; 219 | delete _assetsById[asset.id]; 220 | } 221 | } 222 | } 223 | } 224 | 225 | /** 226 | *An internal class used to enforce the AssetManager class as a Singleton. 227 | */ 228 | class AssetManagerSingletonEnforcer { } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/Asset.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.Asset 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager 33 | { 34 | import com.deadreckoned.assetmanager.formats.IFormatHandler; 35 | import flash.events.Event; 36 | import flash.events.IEventDispatcher; 37 | import flash.events.IOErrorEvent; 38 | 39 | /** 40 | * The Asset class contains data relating to a stored or loaded asset within an AssetQueue. 41 | */ 42 | public class Asset implements IQueueable 43 | { 44 | /** 45 | * @private 46 | */ 47 | internal var _asset:*; 48 | 49 | /** 50 | * @private 51 | */ 52 | internal var _bytesLoaded:int; 53 | 54 | /** 55 | * @private 56 | */ 57 | internal var _bytesTotal:int; 58 | 59 | /** 60 | * @private 61 | */ 62 | internal var _context:*; 63 | 64 | /** 65 | * @private 66 | */ 67 | internal var _data:*; 68 | 69 | /** 70 | * @private 71 | */ 72 | internal var _id:String; 73 | 74 | /** 75 | * @private 76 | */ 77 | internal var _loading:Boolean; 78 | 79 | /** 80 | * @private 81 | */ 82 | internal var _priority:int; 83 | 84 | /** 85 | * @private 86 | */ 87 | internal var _type:String; 88 | 89 | /** 90 | * @private 91 | */ 92 | internal var _uri:String; 93 | 94 | // Handlers 95 | /** 96 | * @private 97 | */ 98 | internal var _handler:IFormatHandler; 99 | 100 | /** 101 | * @private 102 | */ 103 | internal var onComplete:Function; 104 | 105 | /** 106 | * @private 107 | */ 108 | internal var onCompleteParams:Array; 109 | 110 | /** 111 | * @private 112 | */ 113 | internal var onError:Function; 114 | 115 | /** 116 | * @private 117 | */ 118 | internal var onErrorParams:Array; 119 | 120 | /** 121 | * @private 122 | */ 123 | internal var onProgress:Function; 124 | 125 | /** 126 | * @private 127 | */ 128 | internal var onProgressParams:Array; 129 | 130 | /** 131 | * @private 132 | */ 133 | internal var onStart:Function; 134 | 135 | /** 136 | * @private 137 | */ 138 | internal var onStartParams:Array; 139 | 140 | /** 141 | * The asset data. This is only available after the asset has completed loading. This value will be null if the asset has not completed loading. 142 | */ 143 | public function get asset():* { return _asset; } 144 | 145 | /** 146 | * The raw asset data. This is only available after the asset has completed loading. This value will be null if the asset has not completed loading. 147 | */ 148 | public function get rawData():* { return (_handler != null) ? _handler.getRawContent() : null; } 149 | 150 | /** 151 | * The current number of bytes loaded. 152 | */ 153 | public function get bytesLoaded():int { return _bytesLoaded; } 154 | 155 | /** 156 | * The total size of the asset, in bytes. 157 | */ 158 | public function get bytesTotal():int { return _bytesTotal; } 159 | 160 | /** 161 | * The context to use when loading the asset. The type of context depends on the asset being loaded (LoaderContext or SoundLoaderContext for sound files). 162 | */ 163 | public function get context():* { return _context; } 164 | public function set context(value:*):void 165 | { 166 | _context = value; 167 | } 168 | 169 | /** 170 | * Custom data associated with the asset. 171 | */ 172 | public function get data():* { return _data; } 173 | public function set data(value:*):void 174 | { 175 | data = value; 176 | } 177 | 178 | /** 179 | * The id of the asset. 180 | */ 181 | public function get id():String { return _id; } 182 | 183 | /** 184 | * Determines if the asset is currently loading. 185 | */ 186 | public function get loading():Boolean { return _loading; } 187 | 188 | /** 189 | * The type of the asset. 190 | */ 191 | public function get type():String { return _type; } 192 | 193 | /** 194 | * The URI of the asset. 195 | */ 196 | public function get uri():String { return _uri; } 197 | 198 | /** 199 | * The extension of the asset's URI. 200 | */ 201 | public function get extension():String { return !_uri ? "" : _uri.substr(_uri.lastIndexOf(".") + 1); } 202 | 203 | /** 204 | * @inheritDoc 205 | */ 206 | public function get priority():int { return _priority; } 207 | 208 | /** 209 | * Creates a new instance of the Asset class. 210 | * @param handler The format handler instance to use 211 | */ 212 | public function Asset(handler:IFormatHandler = null):void 213 | { 214 | _handler = handler; 215 | 216 | if (_handler != null) 217 | { 218 | var dispatcher:IEventDispatcher = _handler as IEventDispatcher; 219 | dispatcher.addEventListener(Event.COMPLETE, onLoadCompleted, false, 0, true); 220 | dispatcher.addEventListener(IOErrorEvent.IO_ERROR, onLoadFailed, false, 0, true); 221 | } 222 | } 223 | 224 | /** 225 | * @private 226 | */ 227 | internal function dispose():void 228 | { 229 | clean(); 230 | disposeHandler(); 231 | 232 | _asset = null; 233 | _context = null; 234 | _data = null; 235 | _uri = _id = _type = null; 236 | _priority = _bytesLoaded = _bytesTotal = 0; 237 | } 238 | 239 | /** 240 | * Generates a String representation of the object. 241 | * @return A String representation of the object. 242 | */ 243 | public function toString():String 244 | { 245 | return "(Asset id=" + id + ", priority=" + _priority + ", type=" + type + ", uri=" + uri + ")"; 246 | } 247 | 248 | /** 249 | * An internal method for cleaning up the asset's external references once loading has completed. 250 | * @private 251 | */ 252 | internal function clean():void 253 | { 254 | // Remove callbacks 255 | onComplete = onError = onProgress = onStart = null; 256 | onCompleteParams = onErrorParams = onProgressParams = onStartParams = null; 257 | } 258 | 259 | /** 260 | * Disposes of the asset's handler. 261 | */ 262 | private function disposeHandler():void 263 | { 264 | if (_handler != null) 265 | { 266 | var dispatcher:IEventDispatcher = _handler as IEventDispatcher; 267 | dispatcher.removeEventListener(Event.COMPLETE, onLoadCompleted); 268 | dispatcher.removeEventListener(IOErrorEvent.IO_ERROR, onLoadFailed); 269 | _handler.dispose(); 270 | } 271 | 272 | _handler = null; 273 | } 274 | 275 | /** 276 | * Executed when the asset has completed loading. 277 | * @param e The Event object 278 | */ 279 | private function onLoadCompleted(e:Event):void 280 | { 281 | _asset = _handler.getContent(); 282 | } 283 | 284 | /** 285 | * Executed when the asset fails to load. 286 | * @param e The IOErrorEvent object 287 | */ 288 | private function onLoadFailed(e:IOErrorEvent):void 289 | { 290 | _asset = null; 291 | } 292 | } 293 | } -------------------------------------------------------------------------------- /examples/assets/binarytest.js: -------------------------------------------------------------------------------- 1 | /* SWFObject v2.2 2 | is released under the MIT License 3 | */ 4 | var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;abtype property of the event object 44 | * for a AssetComplete event. 45 | * 46 | *

The properties of the event object have the following values:

47 | * 48 | * 49 | * 50 | * 51 | * 52 | * 53 | * 54 | * 55 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading the file.
fileIdThe id of the file that has completed loading.
dataAny custom data that was specified when the file was added to the queue.
56 | * 57 | * @eventType AssetComplete 58 | */ 59 | static public const ASSET_ADDED:String = "AssetAdded"; 60 | 61 | /** 62 | * The AssetEvent.ASSET_COMPLETE constant defines the value of the type property of the event object 63 | * for a AssetComplete event. 64 | * 65 | *

The properties of the event object have the following values:

66 | * 67 | * 68 | * 69 | * 70 | * 71 | * 72 | * 73 | * 74 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading the file.
fileIdThe id of the file that has completed loading.
dataAny custom data that was specified when the file was added to the queue.
75 | * 76 | * @eventType AssetComplete 77 | */ 78 | static public const ASSET_COMPLETE:String = "AssetComplete"; 79 | 80 | /** 81 | * The AssetEvent.ASSET_START constant defines the value of the type property of the event object 82 | * for a AssetStart event. 83 | * 84 | *

The properties of the event object have the following values:

85 | * 86 | * 87 | * 88 | * 89 | * 90 | * 91 | * 92 | * 93 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading the file.
fileIdThe id of the file that has completed loading.
dataAny custom data that was specified when the file was added to the queue.
94 | * 95 | * @eventType AssetStart 96 | */ 97 | static public const ASSET_START:String = "AssetStart"; 98 | 99 | /** 100 | * The AssetEvent.ASSET_FAIL constant defines the value of the type property of the event object 101 | * for a AssetFail event. 102 | * 103 | *

The properties of the event object have the following values:

104 | * 105 | * 106 | * 107 | * 108 | * 109 | * 110 | * 111 | * 112 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading the file.
fileIdThe id of the file that has completed loading.
dataAny custom data that was specified when the file was added to the queue.
113 | * 114 | * @eventType AssetFail 115 | */ 116 | static public const ASSET_FAIL:String = "AssetFail"; 117 | 118 | /** 119 | * The AssetEvent.ASSET_PURGED constant defines the value of the type property of the event object 120 | * for a AssetPurged event. 121 | * 122 | *

The properties of the event object have the following values:

123 | * 124 | * 125 | * 126 | * 127 | * 128 | * 129 | * 130 | * 131 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading the file.
fileIdThe id of the file that has completed loading.
dataAny custom data that was specified when the file was added to the queue.
132 | * 133 | * @eventType AssetPurged 134 | */ 135 | static public const ASSET_PURGED:String = "AssetPurged"; 136 | 137 | /** 138 | * The AssetEvent.LIST_COMPLETE constant defines the value of the type property of the event object 139 | * for a AssetListComplete event. 140 | * 141 | *

The properties of the event object have the following values:

142 | * 143 | * 144 | * 145 | * 146 | * 147 | * 148 | * 149 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading the XML file list.
dataThe XML file list containing the file definitions that will be added to the queue.
150 | * 151 | * @eventType AssetListComplete 152 | */ 153 | static public const LIST_COMPLETE:String = "AssetListComplete"; 154 | 155 | /** 156 | * The AssetEvent.LIST_ADDED constant defines the value of the type property of the event object 157 | * for a AssetListAdded event. 158 | * 159 | *

The properties of the event object have the following values:

160 | * 161 | * 162 | * 163 | * 164 | * 165 | * 166 | * 167 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has added the XML file list to the queue.
dataThe XML file list containing the file definitions that were added to the queue.
168 | * 169 | * @eventType AssetListAdded 170 | */ 171 | static public const LIST_ADDED:String = "AssetListAdded"; 172 | 173 | /** 174 | * The AssetEvent.QUEUE_COMPLETE constant defines the value of the type property of the event object 175 | * for a AssetQueueComplete event. 176 | * 177 | *

The properties of the event object have the following values:

178 | * 179 | * 180 | * 181 | * 182 | * 183 | * 184 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading its queue.
185 | * 186 | * @eventType AssetQueueComplete 187 | */ 188 | static public const QUEUE_COMPLETE:String = "AssetQueueComplete"; 189 | 190 | /** 191 | * The AssetEvent.QUEUE_START constant defines the value of the type property of the event object 192 | * for a AssetQueueStart event. 193 | * 194 | *

The properties of the event object have the following values:

195 | * 196 | * 197 | * 198 | * 199 | * 200 | * 201 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading its queue.
202 | * 203 | * @eventType AssetQueueStart 204 | */ 205 | static public const QUEUE_START:String = "AssetQueueStart"; 206 | 207 | /** 208 | * The AssetEvent.QUEUE_STOP constant defines the value of the type property of the event object 209 | * for a AssetQueueStop event. 210 | * 211 | *

The properties of the event object have the following values:

212 | * 213 | * 214 | * 215 | * 216 | * 217 | * 218 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading its queue.
219 | * 220 | * @eventType AssetQueueStop 221 | */ 222 | static public const QUEUE_STOP:String = "AssetQueueStop"; 223 | 224 | /** 225 | * The AssetEvent.QUEUE_PURGED constant defines the value of the type property of the event object 226 | * for a AssetQueuePurged event. 227 | * 228 | *

The properties of the event object have the following values:

229 | * 230 | * 231 | * 232 | * 233 | * 234 | * 235 | *
PropertyValue
bubblestrue
cancelablefalse; there is no default behavior to cancel.
currentTargetThe object that is actively processing the AssetEvent object with an event listener.
targetThe AssetManager instance that has completed loading its queue.
236 | * 237 | * @eventType AssetQueuePurged 238 | */ 239 | static public const QUEUE_PURGED:String = "AssetQueuePurged"; 240 | 241 | private var _asset:Asset; 242 | private var _data:Object; 243 | 244 | /** 245 | * The asset the event relates to. 246 | */ 247 | public function get asset ():Asset { return _asset; } 248 | 249 | /** 250 | * An object passed to the event via the dispatching object. This is usually custom data that was specified for the file the event relates to. 251 | */ 252 | public function get data ():Object { return _data; } 253 | 254 | /** 255 | * Creates a new instance of the AssetEvent class 256 | * @param type The type of event to create 257 | * @param bubbles Specifies if bubbling is enabled for this event 258 | * @param cancelable Specifies if this event can be canceled 259 | */ 260 | public function AssetEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, asset:Asset = null, data:Object = null):void 261 | { 262 | super(type, bubbles, cancelable); 263 | _asset = asset; 264 | _data = data; 265 | } 266 | 267 | /** 268 | * @inheritDoc 269 | */ 270 | override public function clone():Event 271 | { 272 | return new AssetEvent(type, bubbles, cancelable, _asset, _data); 273 | } 274 | } 275 | } -------------------------------------------------------------------------------- /src/com/deadreckoned/assetmanager/AssetQueue.as: -------------------------------------------------------------------------------- 1 | /** 2 | * com.deadreckoned.assetmanager.AssetQueue 3 | * 4 | * Copyright (c) 2013 Stephen Woolcock 5 | * 6 | * Permission is hereby granted, free of charge, to any person 7 | * obtaining a copy of this software and associated documentation 8 | * files (the "Software"), to deal in the Software without 9 | * restriction, including without limitation the rights to use, 10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the 12 | * Software is furnished to do so, subject to the following 13 | * conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be 16 | * included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | * OTHER DEALINGS IN THE SOFTWARE. 26 | * 27 | * @author Stephen Woolcock 28 | * @version 1.0.0 29 | * @link blog.deadreckoned.com 30 | */ 31 | 32 | package com.deadreckoned.assetmanager 33 | { 34 | import com.deadreckoned.assetmanager.events.AssetEvent; 35 | import com.deadreckoned.assetmanager.events.AssetProgressEvent; 36 | import com.deadreckoned.assetmanager.formats.*; 37 | import com.deadreckoned.assetmanager.formats.IFormatHandler; 38 | import flash.display.BitmapData; 39 | import flash.events.Event; 40 | import flash.events.EventDispatcher; 41 | import flash.events.IEventDispatcher; 42 | import flash.events.IOErrorEvent; 43 | import flash.events.ProgressEvent; 44 | import flash.media.Sound; 45 | import flash.media.SoundLoaderContext; 46 | import flash.net.URLLoader; 47 | import flash.net.URLRequest; 48 | import flash.system.ApplicationDomain; 49 | import flash.system.LoaderContext; 50 | import flash.utils.ByteArray; 51 | import flash.utils.Dictionary; 52 | 53 | /** 54 | * Dispatched when an asset has completed loading 55 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.ASSET_COMPLETE 56 | */ 57 | [Event(name = "AssetComplete", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 58 | 59 | /** 60 | * Dispatched when an asset has started loading 61 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.ASSET_START 62 | */ 63 | [Event(name = "AssetStart", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 64 | 65 | /** 66 | * Dispatched when an asset has failed to load 67 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.ASSET_FAIL 68 | */ 69 | [Event(name = "AssetFail", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 70 | 71 | /** 72 | * Dispatched when an asset has been purged via a call to purge(assetId) 73 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.ASSET_PURGE 74 | */ 75 | [Event(name = "AssetPurge", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 76 | 77 | /** 78 | * Dispatched when an XML asset list has completed loading, but before the assets have been added to the queue (when using loadFromXML()) 79 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.LIST_COMPLETE 80 | */ 81 | [Event(name = "AssetListComplete", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 82 | 83 | /** 84 | * Dispatched when assets from an XML asset list have been added to the queue 85 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.LIST_ADDED 86 | */ 87 | [Event(name = "AssetListAdded", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 88 | 89 | /** 90 | * Dispatched when all assets in the queue have completed loading 91 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.QUEUE_COMPLETE 92 | */ 93 | [Event(name = "AssetQueueComplete", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 94 | 95 | /** 96 | * Dispatched when all assets in the queue begins loading 97 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.QUEUE_START 98 | */ 99 | [Event(name = "AssetQueueStart", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 100 | 101 | /** 102 | * Dispatched when the queue has stopped loading via a call to pause() 103 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.QUEUE_STOP 104 | */ 105 | [Event(name = "AssetQueueStop", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 106 | 107 | /** 108 | * Dispatched when the queue has been completed purged via a parameterless call to purge() 109 | * @eventType com.deadreckoned.assetmanager.events.AssetEvent.QUEUE_PURGED 110 | */ 111 | [Event(name = "AssetQueuePurged", type = "com.deadreckoned.assetmanager.events.AssetEvent")] 112 | 113 | /** 114 | * Dispatched when a the load progress of an asset changes 115 | * @eventType com.deadreckoned.assetmanager.events.AssetProgressEvent.PROGRESS 116 | */ 117 | [Event(name = "AssetProgress", type = "com.deadreckoned.assetmanager.events.AssetProgressEvent")] 118 | 119 | /** 120 | * The AssetQueue handles the loading and storage of individual Asset objects. 121 | */ 122 | public class AssetQueue extends EventDispatcher implements IQueueable 123 | { 124 | private var _path:String = ""; 125 | private var _id:String; 126 | private var _loading:Boolean = true; 127 | private var _loadingId:String; 128 | private var _loadingXML:Boolean; 129 | private var _loadSequentially:Boolean = false; 130 | private var _queue:Vector.; 131 | 132 | /** 133 | * @private 134 | */ 135 | protected var _assetsById:Dictionary; 136 | 137 | /** 138 | * @private 139 | */ 140 | protected var _loaded:Vector.; 141 | 142 | /** 143 | * @private 144 | */ 145 | internal var _priority:int; 146 | 147 | /** 148 | * A query string to append to the URLs of assets when loading. 149 | * @example Avoid the browser cache by appending a random query to each asset at load time: var queue:AssetQueue = AssetManager.getInstance().createQueue(); 150 | queue.queryString = "noCache=" + Math.random(); 151 | queue.add("images/myImage.jpg"); 152 | 153 | // Asset be loaded as: 154 | // images/myImage.jpg?noCache=[random number: 0 < n < 1] 155 | */ 156 | public var queryString:String; 157 | 158 | /** 159 | * A function to process URLs before loading. This function is executed on each URL before loading and returns a new URL. The function must take an 160 | * input string (the processed asset URL, including the path and queryString), and must return a new string representing the 161 | * URL of an asset. This feature can be used to supply new absolute URLs for assets, while maintaining relative URLs on the assets themselves (for example, 162 | * on a CDN, where the full base path of an asset may not be known until run time, or is retrieved from another permanent URL). 163 | * @example Route an asset's URL through a custom function before loading: var processURL:Function = function(url:String):String 164 | { 165 | return "http://cdnnode.provider.com/" + url; 166 | }; 167 | 168 | var queue:AssetQueue = AssetManager.getInstance().createQueue(); 169 | queue.urlFunction = processURL; 170 | queue.add("images/myImage.jpg"); 171 | 172 | // Asset will be loaded from: 173 | // http://cdnnode.provider.com/images/myImage.jpg 174 | 175 | // Asset is referenced within the queue (after loading) via get(): 176 | // queue.get("images/myImage.jpg"); 177 | */ 178 | public var urlFunction:Function = defaultURLFunction; 179 | 180 | /** 181 | * The id of the file currently loading. If loadSequentially is false, this value will always be null. 182 | */ 183 | public function get currentLoadingId():String { return _loadSequentially ? _loadingId : null; } 184 | 185 | /** 186 | * The base path to load assets from. For example, if path was set to "myApp/data/", all assets added to the 187 | * queue (and XML file lists loaded using loadFromXML()) would have "myApp/data/" prepended to their URLs, making 188 | * the final URL "myApp/data/myXMLAsset.xml". This is not applied for URIs with root access (URIs beginning with '/'), or for URIs containing 189 | * a protocol or drive access token (for example, http://, c:/, etc). 190 | */ 191 | public function get path():String { return _path; } 192 | public function set path(value:String):void 193 | { 194 | _path = value; 195 | 196 | // If a forward slash is not supplied, add one 197 | if (_path != null && _path.length > 0 && _path.substr(_path.length - 1) != "/") 198 | _path += "/"; 199 | } 200 | 201 | /** 202 | * The id of the AssetQueue instance. 203 | */ 204 | public function get id():String { return _id; } 205 | 206 | /** 207 | * The total number of assets in the AssetQueue. This is the sum of both assetsLoading and assetsLoaded. 208 | */ 209 | public function get assetsTotal():uint { return assetsLoading + _loaded.length; } 210 | 211 | /** 212 | * The number of assets that have completed loading, or have been added using addAsset. 213 | */ 214 | public function get assetsLoaded():uint { return _loaded.length; } 215 | 216 | /** 217 | * The number of assets still to be loaded, not including unloaded assets in child queues. 218 | */ 219 | public function get assetsLoading():uint 220 | { 221 | var c:int = 0; 222 | for each (var a:IQueueable in _queue) 223 | { 224 | if (!(a is AssetQueue)) 225 | c++; 226 | } 227 | return c; 228 | } 229 | 230 | /** 231 | * The number of assets still to be loaded, including the number of unloaded assets in child queues. 232 | */ 233 | public function get assetsLoadingTotal():uint 234 | { 235 | var c:int = 0; 236 | for each (var a:IQueueable in _queue) 237 | { 238 | var assetQueue:AssetQueue = a as AssetQueue 239 | if (assetQueue != null) 240 | c += assetQueue.assetsLoadingTotal; 241 | else c++; 242 | } 243 | return c; 244 | } 245 | 246 | /** 247 | * Determines if the AssetQueue instance is currently set to load assets in the queue. This value will be set to true when 248 | * load() or loadFromXML() methods are called, and set to false when pause() is called. 249 | */ 250 | public function get loading():Boolean { return _loading; } 251 | 252 | /** 253 | * Determines if assets within the queue are loaded sequentially (one after the other) or all at once (using the browser's on queue, if running inside a browser). 254 | * This value is true by default. 255 | */ 256 | public function get loadSequentially():Boolean { return _loadSequentially; } 257 | public function set loadSequentially(value:Boolean):void 258 | { 259 | _loadSequentially = value; 260 | 261 | for each (var object:IQueueable in _queue) 262 | { 263 | !_loadSequentially ? loadObject(object) : pauseObject(object); 264 | } 265 | 266 | if (_loadSequentially) 267 | load(); 268 | } 269 | 270 | /** 271 | * The priority of the AssetQueue when nested as a child queue within the AssetManager, or another AssetQueue. This value can be set when adding this AssetQueue to another, 272 | * using the add() method, or by using the prioritize() method. 273 | */ 274 | public function get priority():int { return _priority; } 275 | 276 | /** 277 | * Creates a new AssetQueue instance. An optional id can be supplied to reference the queue. 278 | * @param id An optional id for the queue 279 | */ 280 | public function AssetQueue(id:String = null):void 281 | { 282 | _id = id; 283 | _queue = new Vector.(); 284 | _loaded = new Vector.(); 285 | _assetsById = new Dictionary(true); 286 | } 287 | 288 | /** 289 | * Adds an asset to the queue. A valid asset can be a URL, which will be loaded, an AssetQueue to add as a child queue, or any other valid ActionScript object. 290 | * The second argument can be an object containing information about the file. If adding an ActionScript object, the args parameter can be a single string, which will be used 291 | * as the unique identifier for the asset. When an asset is added to ANY queue, it is also added to the AssetManager default queue, so it can be accessed from anywhere within 292 | * your application, so beware of duplicate ids. 293 | *

If an asset has already been loaded, unless the overwrite property is supplied, the asset will not be loaded. However, asset and queue related events will still execute 294 | * as expected.

295 | *

AssetQueue objects, when added to another AssetQueue, are added as child queues. When they are reached in the queue while loading, they will begin loading their assets. 296 | * When a child AssetQueue has completed loading, it is removed from the parent queue, and the parent queue will continue loading any remaining child assets. With this system, it makes it 297 | * easy to prioritize and manage your individual AssetQueue instances.

298 | * 299 | * @param obj Either a URL to load an asset from, an AssetQueue object to add as a child queue or any other valid ActionScript object you want to store in the queue. 300 | * @param args Arguments to supply when loading and storing the asset. See method description for a full list of supported arguments. 301 | *

The available properties for the args object when loading an asset from a URL are:

302 | * 303 | * 304 | * 305 | * 306 | * 307 | * 308 | * 309 | * 310 | * 311 | * 312 | * 313 | * 314 | * 315 | * 316 | * 317 | * 318 | *
PropertyTypeDescription
idStringA unique identifier for the asset. If this value is null, the value of the uri parameter is used as the identifier.
typeStringDetermines the type of the asset. If no type is supplied, AssetQueue will try to derive the type from the file extension of the URI. If no type can be discerned, the binary type is used.
priorityint0. The priority of the asset. Higher prorities will be added to the front of the queue.
contextLoaderContext or SoundLoaderContextA context object to use when loading the file (LoaderContext or SoundLoaderContext, if loading a Sound).
dataObjectAny custom data you want to store along with the file. This can be any valid ActionScript object.
ovewriteBooleanfalse. Determines if this asset should overwrite another asset with the same id.
onStartFunctionA callback to execute when the asset begins loading.
onStartParamsArrayAn array of parameters to send to the onStart callback.
onCompleteFunctionA callback to execute when the asset has completed loading.
onCompleteParamsArrayAn array of parameters to send to the onComplete callback.
onProgressFunctionA callback to execute when the asset's load progress changes.
onProgressParamsArrayAn array of parameters to send to the onProgress callback.
onErrorFunctionA callback to execute when the asset fails to load.
onErrorParamsArrayAn array of parameters to send to the onError callback.
319 | * 320 | *

The available properties for the args object when adding a child AssetQueue are:

321 | * 322 | * 323 | * 324 | *
PropertyTypeDescription
priorityintApplicable only when adding an AssetQueue, sets the priority of the queue.
325 | * 326 | *

The available properties for the args object when adding an ActionScript object are:

327 | * 328 | * 329 | * 330 | * 331 | * 332 | *
PropertyTypeDescription
idStringRequired. A unique identifier for the asset.
typeStringThe type of asset. AssetQueue will try to determine the type of the asset by its ActionScript type, if no type value is supplied. This value should be one of the registered file formats, although it can technically be anything you wish.
dataObjectAny custom data you want to store along with the asset. This can be any valid ActionScript object.
333 | *

Note: When adding an ActionScript object, the args paratmer can simply be the unique identifier, if the other parameters are not required.

334 | * 335 | * @return The new Asset object, or the AssetQueue, that was added to the queue 336 | * @throws ArgumentError No format handler exists for the type supplied. 337 | * @throws ArgumentError Manually added assets must supply an id or uri property. 338 | * @example Load an asset from a URL: AssetManager.getInstance().add("images/myImage.jpg"); 339 | * @example Load an asset from a URL, with callbacks and custom data: AssetManager.getInstance().add("images/myImage.jpg", { 340 | onComplete: myCompleteHandler, 341 | onStart: myStartHandler, 342 | onStartParams: [ "param1", 0.5 ], 343 | data: { foo: "bar" } 344 | } ); 345 | * @example Add a custom object: AssetManager.getInstance().add( { foo: "bar", number: 100 }, "myCustomAsset"); 346 | * @example Add a child AssetQueue: var childQueue:AssetQueue = new AssetQueue(); 347 | childQueue.add("images/myImage.jpg"); 348 | AssetManager.getInstance().add(childQueue); 349 | */ 350 | public function add(obj:*, args:Object = null):IQueueable 351 | { 352 | var asset:Asset; 353 | 354 | // Loading a list of assets 355 | // ----------------------------- 356 | if (obj is Vector.) 357 | { 358 | var list:Vector. = Vector.(obj); 359 | for (var i:int = 0, len:int = list.length; i < len; ++i) 360 | { 361 | add(list[i]); 362 | } 363 | return null; 364 | } 365 | 366 | args ||= {}; 367 | 368 | // Loading an external asset 369 | // ----------------------------- 370 | if (obj is String) 371 | { 372 | var uri:String = obj as String; 373 | 374 | // Default values 375 | if (args.id == null) 376 | args.id = uri; 377 | 378 | var existingAsset:Asset = _assetsById[args.id] || AssetManager.getInstance().get(args.id); 379 | if (existingAsset != null) 380 | { 381 | // An asset with this id already exists 382 | if (args.overwrite === true) 383 | { 384 | // Flagged for overwrite, so dispose of previous asset 385 | disposeAsset(_assetsById[args.id]); 386 | } 387 | else 388 | { 389 | if (AssetManager.verbose) 390 | trace("AssetManager: Warning: " + uri + " already exists and is not flagged for overwrite."); 391 | 392 | // Not flagged for overwrite. If the queue is loading and is currently empty, we should dispatch start and complete events 393 | if (_loading && _queue.length == 0) 394 | { 395 | // Queue has started 396 | if (willTrigger(AssetEvent.QUEUE_START)) 397 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_START)); 398 | } 399 | 400 | if (isLoaded(args.id)) 401 | { 402 | // The asset has already loaded, dispatch start and complete events 403 | if (willTrigger(AssetEvent.ASSET_START)) 404 | dispatchEvent(new AssetEvent(AssetEvent.ASSET_START, false, false, existingAsset)); 405 | 406 | if (args.onStart != null) 407 | args.onStart.apply(null, args.onStartParams || [ existingAsset ]); 408 | 409 | if (willTrigger(AssetEvent.ASSET_COMPLETE)) 410 | dispatchEvent(new AssetEvent(AssetEvent.ASSET_COMPLETE, false, false, existingAsset)); 411 | 412 | if (args.onComplete != null) 413 | args.onComplete.apply(null, args.onCompleteParams || [ existingAsset ]); 414 | } 415 | 416 | if (_loading && _queue.length == 0) 417 | { 418 | // Queue is complete 419 | if (willTrigger(AssetEvent.QUEUE_COMPLETE)) 420 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_COMPLETE)); 421 | } 422 | 423 | 424 | // Return previous asset 425 | return existingAsset; 426 | // EXIT 427 | } 428 | } 429 | 430 | // New asset 431 | if (args.type == null) args.type = getTypeFromURL(uri); 432 | if (args.priority == null) args.priority = 0; 433 | 434 | // Get format handler class 435 | var handlerClass:Class = AssetManager._formats[args.type]; 436 | if (handlerClass == null) 437 | throw new ArgumentError("No format handler with the type '" + args.type + "' has been registered. Use AssetManager.registerFormat() to register new or custom formats."); 438 | 439 | asset = new Asset(new handlerClass()); 440 | asset._uri = uri; 441 | 442 | // Apply properties to the asset 443 | asset._id = args.id; 444 | asset._context = args.context; 445 | asset._data = args.data; 446 | asset._type = args.type; 447 | asset._priority = args.priority; 448 | 449 | // Set callbacks 450 | asset.onStart = args.onStart; 451 | asset.onStartParams = args.onStartParams || [ asset ]; 452 | asset.onProgress = args.onProgress; 453 | asset.onProgressParams = args.onProgressParams || [ asset ]; 454 | asset.onComplete = args.onComplete; 455 | asset.onCompleteParams = args.onCompleteParams || [ asset ]; 456 | asset.onError = args.onError; 457 | asset.onErrorParams = args.onErrorParams || [ asset ]; 458 | 459 | // Add asset 460 | _assetsById[asset._id] = asset; 461 | if (AssetManager.getInstance() != this) 462 | AssetManager.getInstance().addAsset(asset); 463 | addObjectToQueue(asset, args.priority, _loading && _queue.length > 1); 464 | 465 | if (_loading) 466 | { 467 | // Begin loading the queue 468 | if (_queue.length == 1) 469 | { 470 | if (willTrigger(AssetEvent.QUEUE_START)) 471 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_START)); 472 | 473 | load(); 474 | } 475 | else if (!_loadSequentially) 476 | { 477 | loadObject(asset); 478 | } 479 | } 480 | 481 | return asset; 482 | // EXIT 483 | } 484 | 485 | 486 | // Adding a child queue 487 | // ----------------------------- 488 | var assetQueue:AssetQueue = obj as AssetQueue; 489 | if (assetQueue != null) 490 | { 491 | // Default priority is NaN, to force the child queue to be added to the end of this queue 492 | if (!args.hasOwnProperty("priority")) 493 | args.priority = NaN; 494 | 495 | addChildQueueEventListeners(assetQueue); 496 | addObjectToQueue(assetQueue, args.priority); 497 | 498 | return assetQueue; 499 | // EXIT 500 | } 501 | 502 | 503 | // Adding an ActionScript object 504 | // ----------------------------- 505 | var argsIsId:Boolean = args is String; 506 | if (!argsIsId && (args.id == null && args.uri == null)) 507 | throw new ArgumentError("Manually added assets must have an 'id' or 'uri' supplied."); 508 | 509 | // Create asset container 510 | asset = new Asset(); 511 | asset._asset = obj; 512 | 513 | // Set properties 514 | asset._id = argsIsId ? String(args) : (args.id || args.uri); 515 | if (args.hasOwnProperty("data")) 516 | asset._data = args.data; 517 | 518 | // Set type 519 | if (args.hasOwnProperty("type")) 520 | { 521 | asset._type = args.type; 522 | } 523 | else 524 | { 525 | // Attempt to detect type 526 | if (obj is String) asset._type = AssetManager.TYPE_TEXT; 527 | else if (obj is XML) asset._type = AssetManager.TYPE_XML; 528 | else if (obj is Sound) asset._type = AssetManager.TYPE_SOUND; 529 | else if (obj is BitmapData) asset._type = AssetManager.TYPE_IMAGE; 530 | else if (obj is ByteArray) asset._type = AssetManager.TYPE_BINARY; 531 | } 532 | 533 | _loaded.push(asset); 534 | _assetsById[asset._id] = asset; 535 | if (AssetManager.getInstance() != this) 536 | AssetManager.getInstance().addAsset(asset); 537 | return asset; 538 | } 539 | 540 | /** 541 | * Adds assets to the queue from an XML asset list. Each asset node within the XML document should be formatted as follows:
542 | * 543 | *

<asset [id="uniqueId"] [type="typeId"] [nocache="1"]>uriToAsset</asset>

544 | *

NOTE: attributes in brackets are optional, see below for full list of supported attributes

545 | * 546 | * Once the asset has loaded, you can use get(uriToAsset).data to retrieve the XML node for the asset. 547 | * This is useful if you are supplying custom attributes for an asset on an application-specific level. 548 | * 549 | *

Supported attributes for an asset node are as follows:

550 | * 551 | * 552 | * 553 | * 554 | * 555 | * 562 | * 563 | * 564 | * 565 | *
PropertyDescription
idA unique identifier for the asset. If this value is null, the value of the uri parameter is used as the identifier.
typeDetermined the type of the asset. If no type is supplied, AssetQueue will try to derive the type from the file extension of the URI. If no type can be discerned, the binary type is used
priority0. The priority of the asset. Higher prorities will be added to the front of the queue.
contextDetermins the ApplicationDomain to use when loading this asset. Leave this value out to use no LoaderContext. 556 | * In the case of sounds, a SoundLoaderContext is always used if thecontext is supplied, although the value of the attribute does not matter. 557 | *

Valid values are:

558 | *

new — A new ApplicationDomain.

559 | *

parent — The ApplicationDomain of the SWF loading the asset.

560 | *

this — The parent ApplicationDomain of the the SWF loading the asset.

561 | *
checkPolicyFileDetermines the value checkPolicyFile flag on the LoaderContext or SoundLoaderContext used to load the asset. Defaults to false.
bufferTime1000. For sounds using a context, this is the buffer time setting in milliseconds.
nocache0. A value of 0 or 1, indicating if a random number should be assigned as part of the query string for the URI when loading, to avoid caching on some servers.
566 | * 567 | * @param xml The XML document containing a list of assets to load 568 | * @example Add a list of assets to the AssetQueue, using XML formatting. Here, the first asset is loaded using its URI as the id. The second element specifies 569 | * a unique id to use for the asset. The third asset specifies that the image asset should be loaded as binary data, rather than as a BitmapData instance: var assetList:XML = <assets> 570 | <asset>images/myImage.jpg</asset> 571 | <asset id="mySound">sounds/mySound.mp3</asset> 572 | <asset type="bin">images/myImage.jpg</asset> 573 | </assets>; 574 | 575 | // Load asset list 576 | AssetManager.getInstance().addFromXML(assetList); 577 | 578 | */ 579 | public function addFromXML(xml:XML):void 580 | { 581 | var loading:Boolean = _loading; 582 | var assetList:XMLList = xml.asset; 583 | 584 | // We set loading to false so that the assets added from the list do not begin loading until the LIST_ADDED event has been fired 585 | _loading = false; 586 | 587 | for (var i:int = 0, len:int = assetList.length(); i < len; i++) 588 | { 589 | var node:XML = assetList[i]; 590 | var uri:String = node.toString(); 591 | 592 | // Create parameters 593 | var args:Object = {}; 594 | args.data = node; 595 | args.priority = node.hasOwnProperty("@priority") ? int(node.@priority.toString()) : 0; 596 | args.id = node.hasOwnProperty("@id") ? node.@id.toString() : null; 597 | args.type = node.hasOwnProperty("@type") ? node.@type.toString() : getTypeFromURL(uri); 598 | 599 | // Check for LoaderContext settings 600 | if (node.hasOwnProperty("@context")) 601 | { 602 | var checkPolicyFile:Boolean = node.hasOwnProperty("@checkPolicyFile") ? Boolean(int(node.@checkPolicyFile.toString())) : false; 603 | if (args.type == AssetManager.TYPE_SOUND) 604 | { 605 | var bufferTime:int = node.hasOwnProperty("@bufferTime") ? int(node.@bufferTime.toString()) : 1000; 606 | args.context = new SoundLoaderContext(bufferTime, checkPolicyFile); 607 | } 608 | else 609 | { 610 | var domain:ApplicationDomain; 611 | switch (node.@context.toString()) 612 | { 613 | case "new": 614 | domain = new ApplicationDomain(); 615 | break; 616 | 617 | case "this": 618 | domain = ApplicationDomain.currentDomain; 619 | break; 620 | 621 | case "parent": 622 | domain = ApplicationDomain.currentDomain.parentDomain; 623 | break; 624 | } 625 | 626 | args.context = new LoaderContext(checkPolicyFile, domain); 627 | } 628 | } 629 | 630 | // Check for cache settings 631 | if (node.hasOwnProperty("@nocache") && (node.@nocache.toString() == "1" || node.@nocache.toString() == "true")) 632 | uri += (uri.indexOf("?") > -1 ? "&" :" ?") + "nocache=" + Math.random(); 633 | 634 | add(uri, args); 635 | } 636 | 637 | if (willTrigger(AssetEvent.LIST_ADDED)) 638 | dispatchEvent(new AssetEvent(AssetEvent.LIST_ADDED, false, false, null, xml)); 639 | 640 | if (loading) load(); 641 | } 642 | 643 | /** 644 | * Loads an asset list from an external location and adds each asset node to the queue. See addFromXML for full documentation on the asset list XML format. 645 | * @param url The URL to the XML document containing the queue 646 | * @see AssetQueue#addFromXML() 647 | */ 648 | public function loadFromXML(url:String):void 649 | { 650 | if (_loading) pauseSilently(); 651 | 652 | _loadingXML = true; 653 | _loading = true; 654 | 655 | var xmlLoader:URLLoader = new URLLoader(); 656 | xmlLoader.addEventListener(Event.COMPLETE, onXMLComplete, false, 0, true); 657 | xmlLoader.addEventListener(IOErrorEvent.IO_ERROR, onXMLError, false, 0, true); 658 | xmlLoader.load(new URLRequest(processURL(url))); 659 | } 660 | 661 | /** 662 | * Returns a Boolean value indicating if the asset with the specified id exists within the queue (loaded or unloaded). 663 | * @param id The id of the asset. 664 | * @return A Boolean value indicating if an asset with the supplied is exists within the queue. 665 | */ 666 | public function contains(id:String):Boolean 667 | { 668 | return (_assetsById[id] != null); 669 | } 670 | 671 | /** 672 | * Retrieves an asset from the queue. 673 | * @param id The id of the asset 674 | * @return The assets with the id supplied 675 | */ 676 | public function get(id:String):Asset 677 | { 678 | return (_assetsById[id] as Asset); 679 | } 680 | 681 | /** 682 | * Retrieves a child AssetQueue from the queue. This method will only return child AssetQueue objects which have not completed loading. 683 | * @param id The id of the AssetQueue 684 | * @return The AssetQueue with the id supplied 685 | */ 686 | public function getQueue(id:String):AssetQueue 687 | { 688 | for (var i:int = 0, len:int = _queue.length; i < len; i++) 689 | { 690 | var assetQueue:AssetQueue = _queue[i] as AssetQueue; 691 | if (assetQueue != null && assetQueue.id == id) 692 | return assetQueue; 693 | } 694 | return null; 695 | } 696 | 697 | /** 698 | * Retrieves the list of all asset ids in the queue (loaded or unloaded). 699 | * @return An Array containing the list of assets ids currently loaded 700 | */ 701 | public function getIds():Array 702 | { 703 | var output:Array = []; 704 | var all:Vector. = _loaded.concat(_queue); 705 | for (var i:int = 0, len:int = all.length; i < len; i++) 706 | { 707 | output.push(Asset(all[i]).id); 708 | } 709 | 710 | return output; 711 | } 712 | 713 | /** 714 | * Retrieves the list of asset ids that have been loaded. 715 | * @return An Array containing the list of assets ids currently loaded 716 | */ 717 | public function getLoadedIds():Array 718 | { 719 | var output:Array = []; 720 | for (var i:int = 0, len:int = _loaded.length; i < len; i++) 721 | { 722 | output.push(Asset(_loaded[i]).id); 723 | } 724 | 725 | return output; 726 | } 727 | 728 | /** 729 | * Retrieves the list of asset ids that are currently in the queue. 730 | * @return An Array containing the list of assets ids currently in the queue 731 | */ 732 | public function getUnloadedIds():Array 733 | { 734 | var output:Array = []; 735 | for (var i:int = 0, len:int = _queue.length; i < len; i++) 736 | { 737 | output.push(Asset(_queue[i]).id); 738 | } 739 | 740 | return output; 741 | } 742 | 743 | /** 744 | * Returns the object at the head of the loading queue (the first asset in the queue). This could be an Asset, or an AssetQueue object. 745 | * @return The object at the head of the queue. 746 | */ 747 | public function getHeadObject():IQueueable 748 | { 749 | return ((_queue.length > 0) ? _queue[0] : null); 750 | } 751 | 752 | /** 753 | * Returns the object at the tail of the loading queue (the last object in the queue). This could be an Asset, or an AssetQueue object. 754 | * @return The object at the head of the queue. 755 | */ 756 | public function getTailObject():IQueueable 757 | { 758 | return ((_queue.length > 0) ? _queue[_queue.length - 1] : null); 759 | } 760 | 761 | /** 762 | * Returns a Boolean value indicating if an asset with a specific id has completed loading. 763 | * @param id The id of the asset to search for. 764 | * @return A Boolean value indicating if the asset with the id supplied has completed loading. 765 | */ 766 | public function isLoaded(id:String):Boolean 767 | { 768 | var asset:Asset; 769 | for (var i:int = 0, len:int = _queue.length; i < len; i++) 770 | { 771 | asset = _queue[i] as Asset; 772 | if (asset != null && asset.id == id) 773 | return false; 774 | } 775 | 776 | return true; 777 | } 778 | 779 | /** 780 | * Begins loading the asset at the head of the queue. This will flag the queue as 'loading', so any assets added AFTER the load() method is called will 781 | * begin loading immediately. By default, the AssetManager default queue will call load() automatically, so calling it is not necessary when using the 782 | * AssetManager.getInstance() queue. 783 | *

To begin loading another queue manually, you can call the load() method at any time. If an AssetQueue is added as a child to another AssetQueue, when 784 | * the queue is reached during the loading process, load() will automatically be called.

785 | *

In most general use cases, you should not have to call load(), unless you have called pause() beforehand.

786 | */ 787 | public function load():void 788 | { 789 | if (_loadingXML) 790 | return; 791 | 792 | // Dispatch a QUEUE_START event if we're not already loading 793 | if (!_loading) 794 | { 795 | _loading = true; 796 | if (_queue.length > 0 && willTrigger(AssetEvent.QUEUE_START)) 797 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_START)); 798 | } 799 | 800 | if (_queue.length == 0) 801 | { 802 | // There are no assets in the queue, so dispatch a QUEUE_COMPLETE event 803 | if (willTrigger(AssetEvent.QUEUE_COMPLETE)) 804 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_COMPLETE)); 805 | return; 806 | } 807 | 808 | if (_loadSequentially) 809 | { 810 | // Load the asset at the head of the queue 811 | if (_queue.length > 0) loadObject(_queue[0]); 812 | } 813 | else 814 | { 815 | // Load all assets 816 | for each (var asset:Asset in _queue) 817 | { 818 | loadObject(asset); 819 | } 820 | } 821 | } 822 | 823 | /** 824 | * Pauses the loading of assets in the queue. Use load() to resume loading. 825 | */ 826 | public function pause():void 827 | { 828 | _loading = false; 829 | pauseSilently(); // Pause all assets in the queue 830 | 831 | if (willTrigger(AssetEvent.QUEUE_STOP)) 832 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_STOP)); 833 | } 834 | 835 | /** 836 | * Prioritizes an asset within the queue. If priority is not set, the asset will be moved to the front of the queue, by setting its priority 837 | * to priority of the first item in the queue, + 1. If a custom priority is set, the asset is moved to the correct position in the queue. 838 | * @param idOrObject Either a String, representing the id of the asset to prioritize, or an IQueueable instance (eg. Asset or AssetQueue instance) 839 | * @param priority The priority to set the asset to. Leave this value as NaN to move the asset to the front of the queue. 840 | * @throws ArgumentError The object supplied must be either a String or IQueueable instance. 841 | */ 842 | public function prioritize(idOrObject:*, priority:Number = Number.NaN):void 843 | { 844 | var obj:IQueueable; 845 | if (idOrObject is IQueueable) 846 | { 847 | obj = IQueueable(idOrObject); 848 | if (_queue.indexOf(obj) == -1) return; 849 | } 850 | else if (idOrObject is String) 851 | { 852 | obj = getObjectInQueue(idOrObject); 853 | } 854 | else 855 | { 856 | throw new ArgumentError("idOrObject must be either a String or IQueueable instance."); 857 | } 858 | 859 | // If the priority isn't changing, exit here 860 | if (obj == null || obj.priority == priority) return; 861 | 862 | var queueLen:int = _queue.length; 863 | var highestPriority:int = queueLen > 0 ? _queue[0].priority : 0; 864 | 865 | // A NaN value is used to force the object to the front of the queue. 866 | // The priority becomes the highest + 1 867 | if (isNaN(priority)) 868 | { 869 | if (_queue.indexOf(obj) == 0) return; // Already at the front of the queue, don't change priority, just exit 870 | priority = highestPriority + 1; 871 | } 872 | 873 | addObjectToQueue(obj, priority); 874 | } 875 | 876 | /** 877 | * Releases data from the queue to prepare the contents for garbage collection. If a specific id is supplied, the asset with 878 | * the supplied id is disposed of. If no id is supplied, all assets in the queue are purged. The AssetQueue instance 879 | * is still useable after this method is called, unlike when calling dispose(). 880 | * @param id The id of an asset to purge. If no id is supplied, all assets in the queue are purged. 881 | */ 882 | public function purge(id:String = null):void 883 | { 884 | var asset:Asset; 885 | 886 | if (id != null) 887 | { 888 | // Purge single asset 889 | asset = _assetsById[id]; 890 | if (asset != null) 891 | disposeAsset(asset); 892 | 893 | return; 894 | } 895 | 896 | pauseSilently(); 897 | 898 | // Purge all assets 899 | var allAssets:Vector. = _loaded.concat(_queue); 900 | for (var i:int = 0, len:int = allAssets.length; i < len; i++) 901 | { 902 | asset = allAssets[i]; 903 | 904 | if (this != AssetManager.getInstance()) 905 | AssetManager.getInstance().removeAsset(asset); 906 | 907 | disposeAsset(asset, false, false); 908 | } 909 | 910 | _queue.length = 0; 911 | _loaded.length = 0; 912 | _assetsById = new Dictionary(true); 913 | 914 | if (willTrigger(AssetEvent.QUEUE_PURGED)) 915 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_PURGED, false, false, null, this)); 916 | } 917 | 918 | /** 919 | * Releases all data that has not already been loaded. Assets that have already been loaded will remain stored within the loader. 920 | */ 921 | public function purgeUnloaded():void 922 | { 923 | for (var i:int = _queue.length - 1; i >= 0; i--) 924 | { 925 | removeAssetFromQueue(_queue[i].id); 926 | } 927 | } 928 | 929 | /** 930 | * Removes a child AssetQueue from this AssetQueue. 931 | * @param queue The AssetQueue to remove 932 | * @return The AssetQueue that was removed 933 | */ 934 | public function removeQueue(queue:AssetQueue):AssetQueue 935 | { 936 | var index:int = _queue.indexOf(queue); 937 | if (index > -1) _queue.splice(index, 1); 938 | 939 | // Clean up 940 | removeChildQueueEventListeners(queue); 941 | return null; 942 | } 943 | 944 | /** 945 | * Returns the string representation of the specified object. 946 | * @return A string representation of the object. 947 | */ 948 | public override function toString():String 949 | { 950 | return "(AssetQueue " + id + ", assetsTotal=" + assetsTotal + ", assetsLoading=" + assetsLoading + ", assetsLoaded=" + assetsLoaded + ")"; 951 | } 952 | 953 | /** 954 | * Adds an object to the queue at a specific priority 955 | * @param obj The object to add to the queue 956 | */ 957 | private function addObjectToQueue(obj:IQueueable, priority:Number = NaN, loadWhenAdded:Boolean = true):void 958 | { 959 | var queueLen:int = _queue.length; 960 | 961 | if (queueLen == 0 || isNaN(priority)) 962 | { 963 | // The queue is empty, or no priority was supplied, so all we have to do is push the object into the queue 964 | _queue.push(obj); 965 | } 966 | else 967 | { 968 | // The queue is already populated, so we need to find the position in which to add it 969 | var highestPriority:int = queueLen > 0 ? _queue[0].priority : 0; 970 | var lowestPriority:int = queueLen > 0 ? _queue[queueLen - 1].priority : 0; 971 | var head:IQueueable = _queue[0]; 972 | var currentIndex:int = _queue.indexOf(obj); 973 | var newIndex:int = 0; 974 | 975 | // Force priority to be an integer 976 | priority = int(priority); 977 | 978 | // Set the object's priority proprty value 979 | if (obj is Asset) Asset(obj)._priority = priority; 980 | else if (obj is AssetQueue) AssetQueue(obj)._priority = priority; 981 | 982 | // Remove the object from the queue, if it exists 983 | if (currentIndex > -1) 984 | _queue.splice(currentIndex, 1); 985 | 986 | if (priority > highestPriority) 987 | { 988 | // This is the highest priority object, add it to the front 989 | _queue.unshift(obj); 990 | } 991 | else if (priority <= lowestPriority) 992 | { 993 | // This is the lowest priority object, add it to the back 994 | _queue.push(obj); 995 | } 996 | else 997 | { 998 | // Find the index to add the object at 999 | var objInQueue:IQueueable = _queue[0]; 1000 | while (objInQueue.priority >= priority) 1001 | { 1002 | newIndex++; 1003 | if (newIndex == _queue.length) break; // Reached the end of the queue 1004 | objInQueue = _queue[newIndex]; 1005 | } 1006 | 1007 | // Index hasn't changed, exit 1008 | if (newIndex == currentIndex) return; 1009 | 1010 | // Add the object to the queue at the new index 1011 | _queue.splice(newIndex, 0, obj); 1012 | } 1013 | } 1014 | 1015 | // If loading sequentially, and the head object has changed, stop loading all assets, and call 1016 | // load() again to begin loading the new head asset 1017 | if (loadWhenAdded && _loadSequentially && head != _queue[0]) 1018 | { 1019 | pauseSilently(); 1020 | if (_loading) load(); 1021 | } 1022 | } 1023 | 1024 | /** 1025 | * Completely removes an asset from the AssetManager and prepares it for garbage collection. 1026 | * @param asset The Asset to dispose. 1027 | * @param removeFromLists Determines if the asset is removed from asset lists. 1028 | * @param dispatchPurgeEvent Determines if the ASSET_PURGE event is dispatched 1029 | */ 1030 | private function disposeAsset(asset:Asset, removeFromLists:Boolean = true, dispatchPurgeEvent:Boolean = true):void 1031 | { 1032 | if (asset == null) 1033 | return; 1034 | 1035 | // Remove event listeners 1036 | var loaderAsDispatcher:IEventDispatcher = asset._handler as IEventDispatcher; 1037 | if (loaderAsDispatcher != null) 1038 | { 1039 | loaderAsDispatcher.removeEventListener(Event.COMPLETE, onAssetLoadComplete); 1040 | loaderAsDispatcher.removeEventListener(IOErrorEvent.IO_ERROR, onAssetIOError); 1041 | loaderAsDispatcher.removeEventListener(ProgressEvent.PROGRESS, onAssetProgress); 1042 | } 1043 | 1044 | if (removeFromLists) 1045 | { 1046 | // Remove from global manager 1047 | if (this != AssetManager.getInstance()) 1048 | AssetManager.getInstance().removeAsset(asset); 1049 | 1050 | // Remove from assetsById dictionary 1051 | _assetsById[asset.id] = null; 1052 | delete _assetsById[asset.id]; 1053 | 1054 | // Remove from asset list 1055 | var i:int = _loaded.indexOf(asset); 1056 | if (i > -1) _loaded.splice(i, 1); 1057 | 1058 | // Remove from queue 1059 | i = _queue.indexOf(asset); 1060 | if (i > -1) _queue.splice(i, 1); 1061 | } 1062 | 1063 | if (dispatchPurgeEvent && willTrigger(AssetEvent.ASSET_PURGED)) 1064 | dispatchEvent(new AssetEvent(AssetEvent.ASSET_PURGED, false, false, asset)); 1065 | 1066 | asset.dispose(); 1067 | } 1068 | 1069 | /** 1070 | * Retrieves the asset in the queue with the id supplied. 1071 | * @param id The id of the asset 1072 | * @return The Asset with the id supplied 1073 | */ 1074 | private function getObjectInQueue(id:String):IQueueable 1075 | { 1076 | var object:IQueueable; 1077 | for (var i:int = 0, len:int = _queue.length; i < len; i ++) 1078 | { 1079 | object = _queue[i]; 1080 | if (object.id == id) return object; 1081 | } 1082 | 1083 | return null; 1084 | } 1085 | 1086 | /** 1087 | * Retrieves the asset in the queue with the handler supplied. 1088 | * @param handler The handler of the asset. 1089 | * @return The Asset with the handler supplied. 1090 | */ 1091 | private function getAssetInQueueByHandler(handler:IFormatHandler):Asset 1092 | { 1093 | for each (var obj:IQueueable in _queue) 1094 | { 1095 | var asset:Asset = obj as Asset; 1096 | if (asset != null && asset._handler === handler) return asset; 1097 | } 1098 | 1099 | return null; 1100 | } 1101 | 1102 | /** 1103 | * Retrieves a format handler for an asset based on the asset's extension in the URL. If no handler could be found 1104 | * for the asset's extension, the binary handler will be used. 1105 | * @param uri The URL of the asset 1106 | * @return The id of the format handler to use for the URL 1107 | */ 1108 | private function getTypeFromURL(url:String):String 1109 | { 1110 | var ext:String = url.substr(url.lastIndexOf(".") + 1); 1111 | var handlerId:String = AssetManager._formatExtensions[ext]; 1112 | return handlerId ? handlerId:"bin"; 1113 | } 1114 | 1115 | /** 1116 | * Begins a load operation for an asset. 1117 | * @param asset The Asset to begin loading 1118 | */ 1119 | private function loadObject(obj:IQueueable):void 1120 | { 1121 | var asset:Asset = obj as Asset; 1122 | if (asset != null) 1123 | { 1124 | if (asset._loading) return; 1125 | 1126 | // Add listeners to the loader 1127 | var loaderAsDispatcher:IEventDispatcher = IEventDispatcher(asset._handler); 1128 | loaderAsDispatcher.addEventListener(Event.COMPLETE, onAssetLoadComplete, false, 0, true); 1129 | loaderAsDispatcher.addEventListener(IOErrorEvent.IO_ERROR, onAssetIOError, false, 0, true); 1130 | loaderAsDispatcher.addEventListener(ProgressEvent.PROGRESS, onAssetProgress, false, 0, true); 1131 | 1132 | _loadingId = asset.id; 1133 | asset._bytesLoaded = asset._bytesTotal = 0; 1134 | asset._loading = true; 1135 | 1136 | if (willTrigger(AssetEvent.ASSET_START)) 1137 | dispatchEvent(new AssetEvent(AssetEvent.ASSET_START, false, false, asset)); 1138 | 1139 | // Execute callbacks 1140 | if (asset.onStart != null) asset.onStart.apply(null, asset.onStartParams); 1141 | 1142 | // Begin loading the asset 1143 | asset._handler.load(processURL(asset.uri), asset.context); 1144 | return; 1145 | } 1146 | 1147 | var assetQueue:AssetQueue = obj as AssetQueue; 1148 | if (assetQueue != null) 1149 | { 1150 | assetQueue.load(); 1151 | return; 1152 | } 1153 | } 1154 | 1155 | /** 1156 | * Pauses an asset's load operation and removes any event listeners attached. 1157 | * @param asset The Asset to pause 1158 | */ 1159 | private function pauseObject(object:IQueueable):void 1160 | { 1161 | var asset:Asset = object as Asset; 1162 | if (asset != null) 1163 | { 1164 | var loaderAsDispatcher:IEventDispatcher = IEventDispatcher(asset._handler); 1165 | loaderAsDispatcher.removeEventListener(Event.COMPLETE, onAssetLoadComplete); 1166 | loaderAsDispatcher.removeEventListener(IOErrorEvent.IO_ERROR, onAssetIOError); 1167 | loaderAsDispatcher.removeEventListener(ProgressEvent.PROGRESS, onAssetProgress); 1168 | 1169 | _loadingId = null; 1170 | asset._handler.pauseLoad(); 1171 | asset._loading = false; 1172 | return; 1173 | } 1174 | 1175 | var queue:AssetQueue = object as AssetQueue; 1176 | if (queue != null) 1177 | { 1178 | queue.pauseSilently(); 1179 | return; 1180 | } 1181 | } 1182 | 1183 | /** 1184 | * Pauses the queue silently, without modifying the loading property. 1185 | */ 1186 | private function pauseSilently():void 1187 | { 1188 | for each (var object:IQueueable in _queue) 1189 | { 1190 | pauseObject(object); 1191 | } 1192 | } 1193 | 1194 | /** 1195 | * Processes a URL and returns the full URL containing the base path. 1196 | * @param uri The uri to process 1197 | * @return A String continaing the fully processed URL 1198 | */ 1199 | private function processURL(uri:String):String 1200 | { 1201 | // Add the query string 1202 | var query:String = ""; 1203 | if (queryString) 1204 | { 1205 | if (queryString.substr(0, 1) == "?") query = queryString.substr(1); 1206 | else query = queryString; 1207 | 1208 | query = (uri.indexOf("?") > -1 ? "&":"?") + query; 1209 | } 1210 | 1211 | // Protocol supplied, or accessing the root, so just return the URI with the query 1212 | if (uri.indexOf(":/") > -1 || uri.indexOf(":\\") > -1 || uri.substr(0, 1) == "/") 1213 | return uri + query; 1214 | 1215 | // Get base URL 1216 | var base:String = (_path != null) ? _path : AssetManager.getInstance().path; 1217 | if (base == null) 1218 | base = ""; 1219 | 1220 | return urlFunction(base + uri + query); 1221 | } 1222 | 1223 | /** 1224 | * 1225 | * @param uri 1226 | * @return 1227 | */ 1228 | private function defaultURLFunction(uri:String):String 1229 | { 1230 | return uri; 1231 | } 1232 | 1233 | /** 1234 | * Removes an asset from the queue. 1235 | * @param id The id of the asset to remove from the queue 1236 | */ 1237 | private function removeAssetFromQueue(id:String):void 1238 | { 1239 | var asset:IQueueable; 1240 | for (var i:int = 0, len:int = _queue.length; i < len; i++) 1241 | { 1242 | asset = _queue[i]; 1243 | if (asset.id == id) 1244 | { 1245 | disposeAsset(asset as Asset); 1246 | break; 1247 | } 1248 | } 1249 | 1250 | if (_loadingId == id) _loadingId = null; 1251 | if (i == 0 && _loading) 1252 | load(); // If the asset was currently being loaded, begin loading the next item in the queue 1253 | } 1254 | 1255 | /** 1256 | * Adds the required event listeners to a child AssetQueue. 1257 | * @param assetQueue The AssetQueue to add listeners to 1258 | */ 1259 | private function addChildQueueEventListeners(assetQueue:AssetQueue):void 1260 | { 1261 | assetQueue.addEventListener(AssetEvent.ASSET_COMPLETE, onChildQueueEvent, false, 0, true); 1262 | assetQueue.addEventListener(AssetEvent.ASSET_FAIL, onChildQueueEvent, false, 0, true); 1263 | assetQueue.addEventListener(AssetEvent.ASSET_START, onChildQueueEvent, false, 0, true); 1264 | assetQueue.addEventListener(AssetEvent.ASSET_PURGED, onChildQueueEvent, false, 0, true); 1265 | assetQueue.addEventListener(AssetEvent.QUEUE_PURGED, onChildQueueEvent, false, 0, true); 1266 | assetQueue.addEventListener(AssetEvent.QUEUE_COMPLETE, onChildQueueComplete, false, 0, true); 1267 | } 1268 | 1269 | /** 1270 | * Removes required event listeners from a child AssetQueue. 1271 | * @param assetQueue The AssetQueue to remove listeners from 1272 | */ 1273 | private function removeChildQueueEventListeners(assetQueue:AssetQueue):void 1274 | { 1275 | assetQueue.removeEventListener(AssetEvent.ASSET_COMPLETE, onChildQueueEvent); 1276 | assetQueue.removeEventListener(AssetEvent.ASSET_FAIL, onChildQueueEvent); 1277 | assetQueue.removeEventListener(AssetEvent.ASSET_START, onChildQueueEvent); 1278 | assetQueue.removeEventListener(AssetEvent.ASSET_PURGED, onChildQueueEvent); 1279 | assetQueue.removeEventListener(AssetEvent.QUEUE_PURGED, onChildQueueEvent); 1280 | assetQueue.removeEventListener(AssetEvent.QUEUE_COMPLETE, onChildQueueComplete); 1281 | } 1282 | 1283 | /** 1284 | * Executed when a child AssetQueue has dispatched an asset-related event. 1285 | * @param e The AssetEvent object 1286 | */ 1287 | private function onChildQueueEvent(e:AssetEvent):void 1288 | { 1289 | var newEvent:AssetEvent = e.clone() as AssetEvent; 1290 | if (willTrigger(e.type)) 1291 | dispatchEvent(newEvent); 1292 | } 1293 | 1294 | /** 1295 | * Executed when a child AssetQueue has completed loading all its assets. 1296 | * @param e The AssetEvent object 1297 | */ 1298 | private function onChildQueueComplete(e:AssetEvent):void 1299 | { 1300 | var assetQueue:AssetQueue = e.currentTarget as AssetQueue; 1301 | var index:int = _queue.indexOf(assetQueue); 1302 | 1303 | // Remove child queue 1304 | _queue.splice(index, 1); 1305 | 1306 | // Remove listeners 1307 | removeChildQueueEventListeners(assetQueue); 1308 | 1309 | // If this queue is empty, it's complete, otherwise continue loading the next asset 1310 | if (_queue.length == 0) 1311 | { 1312 | if (willTrigger(AssetEvent.QUEUE_COMPLETE)) 1313 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_COMPLETE)); 1314 | } 1315 | else if (_loading && _loadSequentially) 1316 | { 1317 | loadObject(_queue[0]); 1318 | } 1319 | } 1320 | 1321 | /** 1322 | * Executed when an asset has completed loading. 1323 | * @param e The Event object 1324 | */ 1325 | private function onAssetLoadComplete(e:Event):void 1326 | { 1327 | // Find the asset that was loaded within the queue 1328 | var asset:Asset, index:int = -1; 1329 | for (var i:int = 0, len:int = _queue.length; i < len; i++) 1330 | { 1331 | var a:Asset = _queue[i] as Asset; 1332 | if (a != null && a._handler == e.target) 1333 | { 1334 | asset = a; 1335 | index = i; 1336 | break; 1337 | } 1338 | } 1339 | 1340 | if (index == -1) 1341 | return; 1342 | 1343 | _queue.splice(index, 1); // Remove the asset from the queue 1344 | 1345 | // Remove event listeners 1346 | var loaderAsDispatcher:IEventDispatcher = asset._handler as IEventDispatcher; 1347 | if (loaderAsDispatcher != null) 1348 | { 1349 | loaderAsDispatcher.removeEventListener(Event.COMPLETE, onAssetLoadComplete); 1350 | loaderAsDispatcher.removeEventListener(IOErrorEvent.IO_ERROR, onAssetIOError); 1351 | loaderAsDispatcher.removeEventListener(ProgressEvent.PROGRESS, onAssetProgress); 1352 | } 1353 | 1354 | _loaded.push(asset); 1355 | _loadingId = null; 1356 | 1357 | if (AssetManager.verbose) 1358 | trace("AssetManager: Complete: " + asset.uri); 1359 | 1360 | if (willTrigger(AssetEvent.ASSET_COMPLETE)) 1361 | dispatchEvent(new AssetEvent(AssetEvent.ASSET_COMPLETE, false, false, asset)); 1362 | 1363 | // Execute callbacks 1364 | if (asset.onComplete != null) 1365 | asset.onComplete.apply(null, asset.onCompleteParams); 1366 | 1367 | asset.clean(); 1368 | 1369 | // If the queue is empty, it's complete, otherwise continue loading the next asset 1370 | if (_queue.length == 0) 1371 | { 1372 | if (willTrigger(AssetEvent.QUEUE_COMPLETE)) 1373 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_COMPLETE)); 1374 | } 1375 | else if (_loading && _loadSequentially) 1376 | { 1377 | loadObject(_queue[0]); 1378 | } 1379 | } 1380 | 1381 | /** 1382 | * Executed when an asset could not be loaded. 1383 | * @param e The IOErrorEvent object 1384 | */ 1385 | private function onAssetIOError(e:IOErrorEvent):void 1386 | { 1387 | var asset:Asset = getAssetInQueueByHandler(IFormatHandler(e.target)); 1388 | var wasLoading:Boolean = _loading; 1389 | 1390 | if (AssetManager.verbose) 1391 | trace("AssetManager: Error: Asset '" + asset.id + "' could not be found: " + asset.uri); 1392 | 1393 | // Store the asset data 1394 | var onError:Function = asset.onError, onErrorParams:Array = asset.onErrorParams; 1395 | var assetId:String = asset.id; 1396 | var assetData:* = asset.data; 1397 | 1398 | if (willTrigger(AssetEvent.ASSET_FAIL)) 1399 | dispatchEvent(new AssetEvent(AssetEvent.ASSET_FAIL, false, false, asset)); 1400 | 1401 | // Execute callbacks 1402 | if (onError != null) onError.apply(null, onErrorParams); 1403 | 1404 | _loading = false; 1405 | disposeAsset(asset); 1406 | 1407 | // Continue loading the queue 1408 | _loading = wasLoading; 1409 | if (_queue.length == 0) 1410 | { 1411 | if (willTrigger(AssetEvent.QUEUE_COMPLETE)) 1412 | dispatchEvent(new AssetEvent(AssetEvent.QUEUE_COMPLETE)); 1413 | } 1414 | else if (_loading && _loadSequentially) 1415 | { 1416 | loadObject(_queue[0]); 1417 | } 1418 | } 1419 | 1420 | /** 1421 | * Executed when an asset's load progress changes. 1422 | * @param e The ProgressEvent object 1423 | */ 1424 | private function onAssetProgress(e:ProgressEvent):void 1425 | { 1426 | var asset:Asset = getAssetInQueueByHandler(IFormatHandler(e.target)); 1427 | if (asset == null) return; 1428 | 1429 | // Update asset progress 1430 | asset._bytesLoaded = e.bytesLoaded; 1431 | asset._bytesTotal = e.bytesTotal; 1432 | 1433 | // Don't dispatch any events if the total bytes is 0 1434 | if (asset.bytesTotal == 0) return; 1435 | 1436 | if (willTrigger(AssetProgressEvent.PROGRESS)) 1437 | dispatchEvent(new AssetProgressEvent(AssetProgressEvent.PROGRESS, false, false, e.bytesLoaded, e.bytesTotal, asset)); 1438 | 1439 | // Execute callbacks 1440 | if (asset.onProgress != null) asset.onProgress.apply(null, asset.onProgressParams); 1441 | } 1442 | 1443 | /** 1444 | * Executed when an XML cue has completed loading. 1445 | * @param e The Event object 1446 | */ 1447 | private function onXMLComplete(e:Event):void 1448 | { 1449 | var xml:XML = XML(e.target.data); 1450 | _loadingXML = false; 1451 | 1452 | if (willTrigger(AssetEvent.LIST_COMPLETE)) 1453 | dispatchEvent(new AssetEvent(AssetEvent.LIST_COMPLETE, false, false, null, xml)); 1454 | 1455 | addFromXML(xml); 1456 | if (_loading) load(); 1457 | } 1458 | 1459 | /** 1460 | * Executed when an XML queue could not be loaded. 1461 | * @param e The IOErrorEvent object 1462 | */ 1463 | private function onXMLError(e:IOErrorEvent):void 1464 | { 1465 | _loadingXML = false; 1466 | 1467 | if (AssetManager.verbose) 1468 | trace("AssetManager: Error: XML queue file could not be found."); 1469 | 1470 | if (willTrigger(e.type)) 1471 | dispatchEvent(e.clone()); 1472 | } 1473 | } 1474 | } 1475 | --------------------------------------------------------------------------------