eca8547dba5714f270d839a8e0f3c904c469306f
[potlatch2.git] / net / systemeD / halcyon / ImageBank.as
1 package net.systemeD.halcyon {
2     import flash.events.*;
3         import flash.display.*;
4         import flash.net.*;
5         import flash.utils.ByteArray;
6         import nochump.util.zip.*;
7
8         /*
9                 ImageBank stores and retrieves bitmap images.
10                 All images are internally stored as Loader.
11
12                 See blog.yoz.sk/2009/10/bitmap-bitmapdata-bytearray/ for a really useful conversion guide!
13         */
14
15     public class ImageBank extends EventDispatcher{
16                 private var images:Object={};
17                 private var imagesRequested:uint=0;
18                 private var imagesReceived:uint=0;
19                 
20                 public static const IMAGES_LOADED:String="imagesLoaded";
21                 public static const ZIP_LOADED:String="zipLoaded";
22                 
23                 private static const GLOBAL_INSTANCE:ImageBank = new ImageBank();
24                 public static function getInstance():ImageBank { return GLOBAL_INSTANCE; }
25
26                 public function hasImage(name:String):Boolean {
27                         if (images[name]) return true;
28                         return false;
29                 }
30
31                 /* ==========================================================================================
32                    Populate with images 
33                    ========================================================================================== */
34
35                 public function loadImage(filename:String):void {
36                         if (images[filename]) return;
37                         imagesRequested++;
38
39                         var loader:Loader=new Loader();
40                         images[filename]=loader;
41                         var request:URLRequest=new URLRequest(filename);
42                         loader.contentLoaderInfo.addEventListener(Event.COMPLETE,                                               loadedImage);
43                         loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS,                  httpStatusHandler);
44                         loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,    securityErrorHandler);
45                         loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,                                ioErrorHandler);
46                         loader.load(request);
47                 }
48
49                 private function loadedImage(event:Event):void {
50                         imageReceived();
51                 }
52                 private function httpStatusHandler(event:HTTPStatusEvent):void { }
53                 private function securityErrorHandler(event:SecurityErrorEvent):void { 
54                         trace("securityErrorEvent: "+event.target.url);
55                         imageReceived();
56                 }
57                 private function ioErrorHandler(event:IOErrorEvent):void { 
58                         trace("ioErrorEvent: "+event.target.url); 
59                         imageReceived();
60                 }
61                 private function imageReceived():void {
62                         imagesReceived++;
63                         if (imagesReceived==imagesRequested) { dispatchEvent(new Event(IMAGES_LOADED)); }
64                 }
65
66                 /* ==========================================================================================
67                    Load from .zip file
68                    ========================================================================================== */
69                 
70                 public function loadFromZip(filename:String, prefix:String=""):void {
71                         var loader:URLLoader = new URLLoader();
72                         loader.dataFormat="binary";
73                         loader.addEventListener(Event.COMPLETE, function(e:Event):void { zipReady(e,prefix); } );
74                         loader.load(new URLRequest(filename));
75                 }
76                 private function zipReady(event:Event, prefix:String):void {
77                         var zip:ZipFile = new ZipFile(event.target.data);
78                         for (var i:uint=0; i<zip.entries.length; i++) {
79                                 var fileref:ZipEntry = zip.entries[i];
80                                 var data:ByteArray = zip.getInput(fileref);
81                                 var loader:Loader=new Loader();
82                                 images[prefix+fileref.name]=loader;
83                                 loader.loadBytes(data);
84                         }
85                         dispatchEvent(new Event(ZIP_LOADED));
86                 }
87
88
89                 /* ==========================================================================================
90                    Get images 
91                    getAsDisplayObject(filename)
92                    getAsBitmapData(filename)
93                    getAsByteArray(filename)
94                    ========================================================================================== */
95
96                 public function getAsDisplayObject(name:String):DisplayObject {
97                         /* If the image hasn't loaded yet, then add an EventListener for when it does. */
98                         if (getWidth(name)==0) {
99                                 var loader:Loader = new Loader();
100                                 images[name].contentLoaderInfo.addEventListener(Event.COMPLETE,
101                                         function(e:Event):void { loaderReady(e, loader) });
102                                 return loader;
103                         }
104                         /* Otherwise, create a new Bitmap, because just returning the raw Loader
105                            (i.e. images[name]) would only allow it to be added to one parent. (The other 
106                            way to do this would be by copying the bytes as loaderReady does.). */
107                         return new Bitmap(getAsBitmapData(name));
108                 }
109                 
110                 public function getOriginalDisplayObject(name:String):DisplayObject {
111                         /* But if we're going to clone it later, this'll work fine. */
112                         return images[name];
113                 }
114
115                 private function loaderReady(event:Event, loader:Loader):void {
116                         /* The file has loaded, so we can copy the data from there into our new Loader */
117                         var info:LoaderInfo = event.target as LoaderInfo;
118                         loader.loadBytes(info.bytes);
119                 }
120
121                 public function getAsBitmapData(name:String):BitmapData {
122                         var bitmapData:BitmapData=new BitmapData(getWidth(name), getHeight(name), true, 0xFFFFFF);
123                         bitmapData.draw(images[name]);
124                         return bitmapData;
125                 }
126                 
127                 public function getAsByteArray(name:String):ByteArray {
128                         return images[name].contentLoaderInfo.bytes;
129                 }
130
131                 /* ==========================================================================================
132                    Get file information
133                    ========================================================================================== */
134
135                 public function getWidth(name:String):int { 
136                         try { return images[name].contentLoaderInfo.width; }
137                         catch (error:Error) { } return 0;
138                 }
139
140                 public function getHeight(name:String):int { 
141                         try { return images[name].contentLoaderInfo.height; }
142                         catch (error:Error) { } return 0;
143                 }
144
145         }
146 }