Improve Assets, use Futures and Events

This commit is contained in:
Joshua Granick
2015-09-04 09:35:00 -07:00
parent 0e7b5fa056
commit 9b266891dd
3 changed files with 253 additions and 306 deletions

View File

@@ -1,4 +1,7 @@
package lime;
import lime.app.Event;
import lime.app.Promise;
import lime.app.Future;
#if !macro
@@ -33,6 +36,7 @@ class Assets {
public static var cache = new AssetCache ();
public static var libraries (default, null) = new Map <String, AssetLibrary> ();
public static var onChange = new Event<Void->Void> ();
private static var initialized = false;
@@ -330,75 +334,6 @@ class Assets {
}
/**
* Gets an instance of an embedded streaming sound
* @usage var sound = Assets.getMusic("sound.ogg");
* @param id The ID or asset path for the music track
* @return A new Sound object
*/
/*public static function getMusic (id:String, useCache:Bool = true):Dynamic {
initialize ();
#if (tools && !display)
if (useCache && cache.enabled && cache.sound.exists (id)) {
var sound = cache.sound.get (id);
if (isValidSound (sound)) {
return sound;
}
}
var libraryName = id.substring (0, id.indexOf (":"));
var symbolName = id.substr (id.indexOf (":") + 1);
var library = getLibrary (libraryName);
if (library != null) {
if (library.exists (symbolName, cast AssetType.MUSIC)) {
if (library.isLocal (symbolName, cast AssetType.MUSIC)) {
var sound = library.getMusic (symbolName);
if (useCache && cache.enabled) {
cache.sound.set (id, sound);
}
return sound;
} else {
trace ("[Assets] Sound asset \"" + id + "\" exists, but only asynchronously");
}
} else {
trace ("[Assets] There is no Sound asset with an ID of \"" + id + "\"");
}
} else {
trace ("[Assets] There is no asset library named \"" + libraryName + "\"");
}
#end
return null;
}*/
/**
* Gets the file path (if available) for an asset
* @usage var path = Assets.getPath("image.jpg");
@@ -617,10 +552,12 @@ class Assets {
}
public static function loadAudioBuffer (id:String, handler:AudioBuffer -> Void, useCache:Bool = true):Void {
public static function loadAudioBuffer (id:String, useCache:Bool = true):Future<AudioBuffer> {
initialize ();
var promise = new Promise<AudioBuffer> ();
#if (tools && !display)
if (useCache && cache.enabled && cache.audio.exists (id)) {
@@ -629,8 +566,8 @@ class Assets {
if (isValidAudio (audio)) {
handler (audio);
return;
promise.complete (audio);
return promise.future;
}
@@ -644,46 +581,41 @@ class Assets {
if (library.exists (symbolName, cast AssetType.SOUND)) {
var future = library.loadAudioBuffer (symbolName);
if (useCache && cache.enabled) {
library.loadAudioBuffer (symbolName, function (audio:Dynamic):Void {
cache.audio.set (id, audio);
handler (audio);
});
} else {
library.loadAudioBuffer (symbolName, handler);
future.onComplete (function (audio) cache.audio.set (id, audio));
}
return;
promise.completeWith (future);
} else {
trace ("[Assets] There is no audio asset with an ID of \"" + id + "\"");
promise.error ("[Assets] There is no audio asset with an ID of \"" + id + "\"");
}
} else {
trace ("[Assets] There is no asset library named \"" + libraryName + "\"");
promise.error ("[Assets] There is no asset library named \"" + libraryName + "\"");
}
#end
handler (null);
return promise.future;
}
public static function loadBytes (id:String, handler:ByteArray -> Void):Void {
public static function loadBytes (id:String):Future<ByteArray> {
initialize ();
var promise = new Promise<ByteArray> ();
#if (tools && !display)
var libraryName = id.substring (0, id.indexOf (":"));
@@ -694,32 +626,70 @@ class Assets {
if (library.exists (symbolName, cast AssetType.BINARY)) {
library.loadBytes (symbolName, handler);
return;
promise.completeWith (library.loadBytes (symbolName));
} else {
trace ("[Assets] There is no String or ByteArray asset with an ID of \"" + id + "\"");
promise.error ("[Assets] There is no String or ByteArray asset with an ID of \"" + id + "\"");
}
} else {
trace ("[Assets] There is no asset library named \"" + libraryName + "\"");
promise.error ("[Assets] There is no asset library named \"" + libraryName + "\"");
}
#end
handler (null);
return promise.future;
}
public static function loadImage (id:String, handler:Image -> Void, useCache:Bool = true):Void {
public static function loadFont (id:String):Future<Font> {
initialize ();
var promise = new Promise<Font> ();
#if (tools && !display)
var libraryName = id.substring (0, id.indexOf (":"));
var symbolName = id.substr (id.indexOf (":") + 1);
var library = getLibrary (libraryName);
if (library != null) {
if (library.exists (symbolName, cast AssetType.FONT)) {
promise.completeWith (library.loadFont (symbolName));
} else {
promise.error ("[Assets] There is no Font asset with an ID of \"" + id + "\"");
}
} else {
promise.error ("[Assets] There is no asset library named \"" + libraryName + "\"");
}
#end
return promise.future;
}
public static function loadImage (id:String, useCache:Bool = true):Future<Image> {
initialize ();
var promise = new Promise<Image> ();
#if (tools && !display)
if (useCache && cache.enabled && cache.image.exists (id)) {
@@ -728,8 +698,8 @@ class Assets {
if (isValidImage (image)) {
handler (image);
return;
promise.complete (image);
return promise.future;
}
@@ -743,45 +713,40 @@ class Assets {
if (library.exists (symbolName, cast AssetType.IMAGE)) {
var future = library.loadImage (symbolName);
if (useCache && cache.enabled) {
library.loadImage (symbolName, function (image:Image):Void {
cache.image.set (id, image);
handler (image);
});
} else {
library.loadImage (symbolName, handler);
future.onComplete (function (image) cache.image.set (id, image));
}
return;
promise.completeWith (future);
} else {
trace ("[Assets] There is no Image asset with an ID of \"" + id + "\"");
promise.error ("[Assets] There is no Image asset with an ID of \"" + id + "\"");
}
} else {
trace ("[Assets] There is no asset library named \"" + libraryName + "\"");
promise.error ("[Assets] There is no asset library named \"" + libraryName + "\"");
}
#end
handler (null);
return promise.future;
}
public static function loadLibrary (name:String, handler:AssetLibrary -> Void):Void {
public static function loadLibrary (name:String):Future<AssetLibrary> {
initialize();
initialize ();
var promise = new Promise<AssetLibrary> ();
#if (tools && !display)
@@ -792,89 +757,27 @@ class Assets {
var info = Json.parse (data);
var library = Type.createInstance (Type.resolveClass (info.type), info.args);
libraries.set (name, library);
library.eventCallback = library_onEvent;
library.load (handler);
return;
library.onChange.add (onChange.dispatch);
promise.completeWith (library.load ());
} else {
trace ("[Assets] There is no asset library named \"" + name + "\"");
promise.error ("[Assets] There is no asset library named \"" + name + "\"");
}
#end
handler (null);
return promise.future;
}
/*public static function loadMusic (id:String, handler:Dynamic -> Void, useCache:Bool = true):Void {
public static function loadText (id:String):Future<String> {
initialize ();
#if (tools && !display)
if (useCache && cache.enabled && cache.sound.exists (id)) {
var sound = cache.sound.get (id);
if (isValidSound (sound)) {
handler (sound);
return;
}
}
var libraryName = id.substring (0, id.indexOf (":"));
var symbolName = id.substr (id.indexOf (":") + 1);
var library = getLibrary (libraryName);
if (library != null) {
if (library.exists (symbolName, cast AssetType.MUSIC)) {
if (useCache && cache.enabled) {
library.loadMusic (symbolName, function (sound:Dynamic):Void {
cache.sound.set (id, sound);
handler (sound);
});
} else {
library.loadMusic (symbolName, handler);
}
return;
} else {
trace ("[Assets] There is no Sound asset with an ID of \"" + id + "\"");
}
} else {
trace ("[Assets] There is no asset library named \"" + libraryName + "\"");
}
#end
handler (null);
}*/
public static function loadText (id:String, handler:String -> Void):Void {
initialize ();
var promise = new Promise<String> ();
#if (tools && !display)
@@ -886,24 +789,23 @@ class Assets {
if (library.exists (symbolName, cast AssetType.TEXT)) {
library.loadText (symbolName, handler);
return;
promise.completeWith (library.loadText (symbolName));
} else {
trace ("[Assets] There is no String asset with an ID of \"" + id + "\"");
promise.error ("[Assets] There is no String asset with an ID of \"" + id + "\"");
}
} else {
trace ("[Assets] There is no asset library named \"" + libraryName + "\"");
promise.error ("[Assets] There is no asset library named \"" + libraryName + "\"");
}
#end
handler (null);
return promise.future;
}
@@ -912,13 +814,21 @@ class Assets {
if (libraries.exists (name)) {
unloadLibrary (name);
if (libraries.get (name) == library) {
return;
} else {
unloadLibrary (name);
}
}
if (library != null) {
library.eventCallback = library_onEvent;
library.onChange.add (library_onChange);
}
@@ -938,8 +848,8 @@ class Assets {
if (library != null) {
cache.clear (name + ":");
library.onChange.remove (library_onChange);
library.unload ();
library.eventCallback = null;
}
@@ -957,14 +867,10 @@ class Assets {
private static function library_onEvent (library:AssetLibrary, type:String):Void {
private static function library_onChange ():Void {
if (type == "change") {
cache.clear ();
//dispatchEvent (new Event (Event.CHANGE));
}
cache.clear ();
onChange.dispatch ();
}
@@ -975,7 +881,7 @@ class Assets {
class AssetLibrary {
public var eventCallback:Dynamic;
public var onChange = new Event<Void->Void> ();
public function new () {
@@ -1020,13 +926,6 @@ class AssetLibrary {
}
//public function getMusic (id:String):Dynamic /*Sound*/ {
// return getSound (id);
//}
public function getPath (id:String):String {
return null;
@@ -1073,73 +972,60 @@ class AssetLibrary {
}
private function load (handler:AssetLibrary -> Void):Void {
private function load ():Future<AssetLibrary> {
handler (this);
return new Future<AssetLibrary> (function () return this);
}
public function loadAudioBuffer (id:String, handler:AudioBuffer -> Void):Void {
public function loadAudioBuffer (id:String):Future<AudioBuffer> {
handler (getAudioBuffer (id));
return new Future<AudioBuffer> (function () return getAudioBuffer (id));
}
public function loadBytes (id:String, handler:ByteArray -> Void):Void {
public function loadBytes (id:String):Future<ByteArray> {
handler (getBytes (id));
return new Future<ByteArray> (function () return getBytes (id));
}
public function loadFont (id:String, handler:Font -> Void):Void {
public function loadFont (id:String):Future<Font> {
handler (getFont (id));
return new Future<Font> (function () return getFont (id));
}
public function loadImage (id:String, handler:Image -> Void):Void {
public function loadImage (id:String):Future<Image> {
handler (getImage (id));
return new Future<Image> (function () return getImage (id));
}
//public function loadMusic (id:String, handler:Dynamic /*Sound*/ -> Void):Void {
public function loadText (id:String):Future<String> {
// handler (getMusic (id));
return loadBytes (id).then (function (bytes) {
//}
return new Future<String> (function () {
if (bytes == null) {
public function loadText (id:String, handler:String -> Void):Void {
return null;
#if (tools && !display)
} else {
var callback = function (bytes:ByteArray):Void {
return bytes.readUTFBytes (bytes.length);
if (bytes == null) {
}
handler (null);
});
} else {
handler (bytes.readUTFBytes (bytes.length));
}
}
loadBytes (id, callback);
#else
handler (null);
#end
});
}

View File

@@ -8,7 +8,7 @@ class Future<T> {
public var isCompleted (get, null):Bool;
public var value:T;
public var value (default, null):T;
private var __completed:Bool;
private var __completeListeners:Array<T->Void>;

View File

@@ -3,7 +3,9 @@ package;
import haxe.Timer;
import haxe.Unserializer;
import lime.app.Future;
import lime.app.Preloader;
import lime.app.Promise;
import lime.audio.AudioSource;
import lime.audio.openal.AL;
import lime.audio.AudioBuffer;
@@ -26,6 +28,8 @@ import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.media.Sound;
import flash.net.URLLoader;
import flash.net.URLRequest;
@@ -112,11 +116,7 @@ class DefaultAssetLibrary extends AssetLibrary {
lastModified = modified;
loadManifest ();
if (eventCallback != null) {
eventCallback (this, "change");
}
onChange.dispatch ();
}
@@ -492,7 +492,9 @@ class DefaultAssetLibrary extends AssetLibrary {
}
public override function loadAudioBuffer (id:String, handler:AudioBuffer -> Void):Void {
public override function loadAudioBuffer (id:String):Future<AudioBuffer> {
var promise = new Promise<AudioBuffer> ();
#if (flash)
@@ -503,28 +505,45 @@ class DefaultAssetLibrary extends AssetLibrary {
var audioBuffer:AudioBuffer = new AudioBuffer();
audioBuffer.src = event.currentTarget;
handler (audioBuffer);
promise.complete (audioBuffer);
});
soundLoader.addEventListener (ProgressEvent.PROGRESS, function (event) {
if (event.bytesTotal == 0) {
promise.progress (0);
} else {
promise.progress (event.bytesLoaded / event.bytesTotal);
}
});
soundLoader.addEventListener (IOErrorEvent.IO_ERROR, promise.error);
soundLoader.load (new URLRequest (path.get (id)));
} else {
handler (getAudioBuffer (id));
promise.complete (getAudioBuffer (id));
}
#else
handler (getAudioBuffer (id));
promise.complete (getAudioBuffer (id));
#end
return promise.future;
}
public override function loadBytes (id:String, handler:ByteArray -> Void):Void {
public override function loadBytes (id:String):Future<ByteArray> {
var promise = new Promise<ByteArray> ();
#if flash
@@ -537,14 +556,28 @@ class DefaultAssetLibrary extends AssetLibrary {
bytes.writeUTFBytes (event.currentTarget.data);
bytes.position = 0;
handler (bytes);
promise.complete (bytes);
});
loader.addEventListener (ProgressEvent.PROGRESS, function (event) {
if (event.bytesTotal == 0) {
promise.progress (0);
} else {
promise.progress (event.bytesLoaded / event.bytesTotal);
}
});
loader.addEventListener (IOErrorEvent.IO_ERROR, promise.error);
loader.load (new URLRequest (path.get (id)));
} else {
handler (getBytes (id));
promise.complete (getBytes (id));
}
@@ -556,15 +589,32 @@ class DefaultAssetLibrary extends AssetLibrary {
loader.dataFormat = BINARY;
loader.onComplete.add (function (_):Void {
handler (loader.data);
promise.complete (loader.data);
});
loader.onProgress.add (function (_, loaded, total) {
if (total == 0) {
promise.progress (0);
} else {
promise.progress (loaded / total);
}
});
loader.onIOError.add (function (_, e) {
promise.error (e);
});
loader.load (new URLRequest (path.get (id)));
} else {
handler (getBytes (id));
promise.complete (getBytes (id));
}
@@ -576,14 +626,18 @@ class DefaultAssetLibrary extends AssetLibrary {
}
threadPool.queue (id, { handler: handler, getMethod: getBytes });
threadPool.queue (id, { promise: promise, getMethod: getBytes });
#end
return promise.future;
}
public override function loadImage (id:String, handler:Image -> Void):Void {
public override function loadImage (id:String):Future<Image> {
var promise = new Promise<Image> ();
#if flash
@@ -593,14 +647,28 @@ class DefaultAssetLibrary extends AssetLibrary {
loader.contentLoaderInfo.addEventListener (Event.COMPLETE, function (event:Event) {
var bitmapData = cast (event.currentTarget.content, Bitmap).bitmapData;
handler (Image.fromBitmapData (bitmapData));
promise.complete (Image.fromBitmapData (bitmapData));
});
loader.contentLoaderInfo.addEventListener (ProgressEvent.PROGRESS, function (event) {
if (event.bytesTotal == 0) {
promise.progress (0);
} else {
promise.progress (event.bytesLoaded / event.bytesTotal);
}
});
loader.contentLoaderInfo.addEventListener (IOErrorEvent.IO_ERROR, promise.error);
loader.load (new URLRequest (path.get (id)));
} else {
handler (getImage (id));
promise.complete (getImage (id));
}
@@ -611,14 +679,15 @@ class DefaultAssetLibrary extends AssetLibrary {
var image = new js.html.Image ();
image.onload = function (_):Void {
handler (Image.fromImageElement (image));
promise.complete (Image.fromImageElement (image));
}
image.onerror = promise.error;
image.src = path.get (id);
} else {
handler (getImage (id));
promise.complete (getImage (id));
}
@@ -630,10 +699,12 @@ class DefaultAssetLibrary extends AssetLibrary {
}
threadPool.queue (id, { handler: handler, getMethod: getImage });
threadPool.queue (id, { promise: promise, getMethod: getImage });
#end
return promise.future;
}
@@ -703,36 +774,9 @@ class DefaultAssetLibrary extends AssetLibrary {
#end
/*public override function loadMusic (id:String, handler:Dynamic -> Void):Void {
public override function loadText (id:String):Future<String> {
#if (flash || html5)
//if (path.exists (id)) {
// var loader = new Loader ();
// loader.contentLoaderInfo.addEventListener (Event.COMPLETE, function (event) {
// handler (cast (event.currentTarget.content, Bitmap).bitmapData);
// });
// loader.load (new URLRequest (path.get (id)));
//} else {
handler (getMusic (id));
//}
#else
handler (getMusic (id));
#end
}*/
public override function loadText (id:String, handler:String -> Void):Void {
var promise = new Promise<String> ();
#if html5
@@ -741,38 +785,55 @@ class DefaultAssetLibrary extends AssetLibrary {
var loader = new URLLoader ();
loader.onComplete.add (function (_):Void {
handler (loader.data);
promise.complete (loader.data);
});
loader.onProgress.add (function (_, loaded, total) {
if (total == 0) {
promise.progress (0);
} else {
promise.progress (loaded / total);
}
});
loader.onIOError.add (function (_, msg) promise.error (msg));
loader.load (new URLRequest (path.get (id)));
} else {
handler (getText (id));
promise.complete (getText (id));
}
#else
var callback = function (bytes:ByteArray):Void {
promise.completeWith (loadBytes (id).then (function (bytes) {
if (bytes == null) {
return new Future<String> (function () {
handler (null);
if (bytes == null) {
} else {
return null;
handler (bytes.readUTFBytes (bytes.length));
} else {
}
return bytes.readUTFBytes (bytes.length);
}
}
loadBytes (id, callback);
});
}));
#end
return promise.future;
}