forked from ZaaLabs/PushButtonEngine
/
BulkLoaderResourceProvider.as
325 lines (280 loc) · 14.1 KB
/
BulkLoaderResourceProvider.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/*******************************************************************************
* PushButton Engine
* Copyright (C) 2009 PushButton Labs, LLC
* For more information see http://www.pushbuttonengine.com
*
* This file is licensed under the terms of the MIT license, which is included
* in the License.html file at the root directory of this SDK.
******************************************************************************/
package com.pblabs.engine.resource.provider
{
import br.com.stimuli.loading.BulkLoader;
import br.com.stimuli.loading.BulkProgressEvent;
import br.com.stimuli.loading.loadingtypes.LoadingItem;
import com.pblabs.engine.resource.MP3Resource;
import com.pblabs.engine.resource.Resource;
import flash.display.Bitmap;
import flash.events.ErrorEvent;
import flash.events.Event;
/**
* The BulkLoaderResourceProvider provides the ResourceManager with resources
* that are loaded using this provider's BulkLoader instance
*/
public class BulkLoaderResourceProvider extends ResourceProviderBase
{
// -------------------------------------------------------------------
// public getter/setter property functions
// -------------------------------------------------------------------
/**
* Current loading phase
*/
public function get phase():int
{
return _phase;
}
// -------------------------------------------------------------------
// public functions
// -------------------------------------------------------------------
/**
* Constructor
*/
public function BulkLoaderResourceProvider(name:String, numConnections:int = 12, registerAsProvider:Boolean=true)
{
super(registerAsProvider);
// create this provider's bulk loader object
loader = new BulkLoader(name, numConnections);
}
/**
* This method will request a resource from this ResourceProvider
*/
public override function getResource(uri:String, type:Class, forceReload:Boolean = false):Resource
{
var resourceIdentifier:String = uri.toLowerCase() + type;
// if resource is known return it.
if (resources[resourceIdentifier]!=null && !forceReload)
{
return resources[resourceIdentifier];
}
if (loader.get(resourceIdentifier)!=null)
loader.remove(resourceIdentifier);
// the resource has to be loaded so add to BulkLoader
// Special case so that MP3Resource gets a sound like it wants.
loader.add(uri, { id : resourceIdentifier, type: type == MP3Resource ? "sound" : "binary" } );
if (!loader.isRunning) loader.start();
// let BulkLoader give a notification when this resource has been
// load so we can initialize it.
loader.get(resourceIdentifier).addEventListener(Event.COMPLETE,resourceLoaded)
loader.get(resourceIdentifier).addEventListener(BulkLoader.ERROR,resourceError)
//If force reload, delete old resource first:
if (resources[resourceIdentifier] && forceReload)
{
resources[resourceIdentifier] = null;
delete resources[resourceIdentifier];
}
if (resources[resourceIdentifier]==null)
{
// create resource and provide it to the ResourceManager
var resource:Resource = new type();
resource.filename = uri;
resources[resourceIdentifier] = resource;
}
else
resource = resources[resourceIdentifier];
return resource;
}
public override function unloadResource(uri:String, type:Class, force : Boolean = false):void
{
// no bulk loaded resources will be automaticly unloaded
// because we preloaded the resources and want to keep them available
}
/**
* Use the function load(onLoaded:Function = null, onProgress:Function = null, onProvideResources:Function = null):void to load resources with the bulk loader
*
* The function onLoaded(phase:int):void will be called when all items of a specific
* loading phase are loaded by the BulkLoader
*
* The function onProgress(phase:int, progress:int):void will be called when current loading phase is progressing
* progress (0-100)
*
* The function onProvideResources(phase:int):Array will be called for each loading
* phase, starting with value of 1. The function should return an array with resource objects (Object)
* each object should have the following attributes
*
* id:String unique id of item to load
* url:String url of item to load
* type:Class PBE resource type class
*
* if the onProvideResources function is omitted the overidden function provideResources
* will be called on the derived subclass
*
* @param onLoaded Function that will called when a phase of loading is completed
* @param onProgress Function that will be called to notify loading progression
* @param onProvideResources Function that will provide Array with resource objects that have to be loaded
*/
public function load(onLoaded:Function = null, onProgress:Function = null, onProvideResources:Function = null):void
{
// set event/functions
this.onLoaded = onLoaded;
this.onProgress = onProgress;
// if no onProvideResources is provided the overidden provideResources
// of the derived class will be called to retrieve the resources
this.onProvideResources = onProvideResources;
// starting phase = 1
_phase = 1;
// attach processed and progress events to BulkLoader
if (!loader.hasEventListener(BulkProgressEvent.COMPLETE))
loader.addEventListener(BulkProgressEvent.COMPLETE, resourcesLoaded)
if (!loader.hasEventListener(BulkProgressEvent.PROGRESS))
loader.addEventListener(BulkProgressEvent.PROGRESS, resourcesProgress)
// load resources from first phase
loadResources();
}
// -------------------------------------------------------------------
// private and protected functions
// -------------------------------------------------------------------
private function resourceLoaded(event:Event):void
{
// if resource of current LoadingItem exists, initialize it.
if (resources[(event.currentTarget as LoadingItem).id]!=null)
{
// get content from bulkLoader and release memory
var content:* = loader.getContent( (event.currentTarget as LoadingItem).id , true);
// initalize resource with the content from bulkloader
if (content is Bitmap)
{
// initialize the ImageResource with a copy of the 'raw' BitmapData
(resources[(event.currentTarget as LoadingItem).id] as Resource).initialize((content as Bitmap).bitmapData);
// set variable of this Bitmap to null so it will be picked up by GC
content = null;
}
else
(resources[(event.currentTarget as LoadingItem).id] as Resource).initialize(content);
}
}
private function resourceError(event:ErrorEvent):void
{
// if resource of current LoadingItem exists, notify that is has failed
if (resources[(event.currentTarget as LoadingItem).id]!=null)
{
(resources[(event.currentTarget as LoadingItem).id] as Resource).fail(event.text);
}
}
/**
* override this method to provide resources to be loaded in each phase
* the function should return an array with resource objects (Object)
*
* each object should have the following attributes
*
* id:String unique id of item to load
* url:String url of item to load
* type:Class PBE resource type class
*
* @return Array with resource objects
*/
protected function provideResources():Array
{
return new Array();
}
/**
* This method is called if all resources of a specific phase have been
* loaded.
*/
private function resourcesLoaded(event:BulkProgressEvent):void
{
// Create the Resource Objects and store them so the ResourceManager
// can have access to them
saveResources();
// call the onloaded event/function if one was provided
if (onLoaded!=null) onLoaded(phase);
// increment current loading phase
_phase++;
// load resources from next phase
loadResources();
}
/**
* This method is called while the loading of resources of a specific
* phase is progressing
*/
private function resourcesProgress(event:BulkProgressEvent):void
{
// call the onProgress event/function if one was provided
if (onProgress!=null) onProgress(phase,Math.round(event.percentLoaded*100));
}
/**
* This method will request the array with bulkResource Objects of the current
* phase and will start BulkLoader so the resources will be loaded
*/
private function loadResources():void
{
// get array with bulk resources of the current phase
if (onProvideResources!=null)
bulkResources = onProvideResources(phase);
else
bulkResources = provideResources();
// add the provided resources to BulkLoader
if (bulkResources && bulkResources.length>0)
{
for (var r:int=0; r<bulkResources.length; r++)
{
var resourceIdentifier:String = bulkResources[r].url.toLowerCase() + bulkResources[r].type;
if (bulkResources[r].id!=null) resourceIdentifier = bulkResources[r].id;
if (bulkResources[r].url != "" && bulkResources[r].url != null &&
bulkResources[r].type )
{
// this object is a valid bulk loader object so add it to BulkLoader
loader.add(bulkResources[r].url, { id : resourceIdentifier } );
}
}
// start the BulkLoader loading process
if (!loader.isRunning)
loader.start();
}
}
/**
* This method will create the PBE Resource objects of the loaded resources
* and will save them so that they can be retrieved by the ResourceManager
*/
private function saveResources():void
{
// register loaded resources with PBE as embedded resources
for (var r:int=0; r<bulkResources.length; r++)
{
if (bulkResources[r].url != "" && bulkResources[r].url != null &&
bulkResources[r].type != null )
{
var resourceIdentifier:String = bulkResources[r].url.toLowerCase() + bulkResources[r].type;
// valid resource so try to get Content from BulkLoader
if (loader.getContent( resourceIdentifier )!=null)
{
// create a new resource of type
var resource:Resource = new bulkResources[r].type();
// get content from bulkLoader and release memory
var content:* = loader.getContent( resourceIdentifier , true);
resource.filename = bulkResources[r].url;
// initalize resource with the content from bulkloader
if (content is Bitmap)
{
// initialize the ImageResource with a copy of the 'raw' BitmapData
resource.initialize((content as Bitmap).bitmapData);
// set variable of this Bitmap to null so it will be picked up by GC
content = null;
}
else
resource.initialize(content);
// set lookup for later resource retrieval
resources[resourceIdentifier] = resource
}
}
}
}
// -------------------------------------------------------------------
// private / protected variables
// -------------------------------------------------------------------
protected var loader:BulkLoader = null;
private var _phase:int = 1;
private var bulkResources:Array = new Array();
private var onLoaded:Function = null;
private var onProgress:Function = null;
private var onProvideResources:Function = null;
}
}