From b44794c697d526f1266e69e9ca8ac345b8e42239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=8D=9A=7ENex?= <87421482+NexIsDumb@users.noreply.github.com> Date: Sat, 6 Apr 2024 03:26:26 +0200 Subject: [PATCH] subLibraries for AssetLibrary similar to proxy, but the wont cover everything (tested and for now doesnt seem to crash phew) Co-Authored-By: Ne_Eo --- source/lime/utils/AssetLibrary.hx | 985 ++++++++++++++++++++++++++++ source/openfl/utils/AssetLibrary.hx | 449 +++++++++++++ 2 files changed, 1434 insertions(+) create mode 100644 source/lime/utils/AssetLibrary.hx create mode 100644 source/openfl/utils/AssetLibrary.hx diff --git a/source/lime/utils/AssetLibrary.hx b/source/lime/utils/AssetLibrary.hx new file mode 100644 index 00000000..010d18e8 --- /dev/null +++ b/source/lime/utils/AssetLibrary.hx @@ -0,0 +1,985 @@ +package lime.utils; + +import haxe.io.Path; +import lime.app.Event; +import lime.app.Future; +import lime.app.Promise; +import lime.media.AudioBuffer; +import lime.graphics.Image; +import lime.net.HTTPRequest; +import lime.text.Font; +import lime.utils.AssetType; +#if flash +import flash.display.BitmapData; +import flash.media.Sound; +#end + +#if !lime_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end +@:access(lime.text.Font) +@:access(lime.utils.Assets) +class AssetLibrary +{ + public var onChange = new EventVoid>(); + + @:noCompletion private var assetsLoaded:Int; + @:noCompletion private var assetsTotal:Int; + @:noCompletion private var bytesLoaded:Int; + @:noCompletion private var bytesLoadedCache:Map; + @:noCompletion private var bytesTotal:Int; + @:noCompletion private var cachedAudioBuffers = new Map(); + @:noCompletion private var cachedBytes = new Map(); + @:noCompletion private var cachedFonts = new Map(); + @:noCompletion private var cachedImages = new Map(); + @:noCompletion private var cachedText = new Map(); + @:noCompletion private var classTypes = new Map>(); + @:noCompletion private var loaded:Bool; + @:noCompletion private var pathGroups = new Map>(); + @:noCompletion private var paths = new Map(); + @:noCompletion private var preload = new Map(); + @:noCompletion private var promise:Promise; + @:noCompletion private var sizes = new Map(); + @:noCompletion private var types = new Map(); + + public function new() + { + bytesLoaded = 0; + bytesTotal = 0; + } + + public function exists(id:String, type:String):Bool + { + var requestedType = type != null ? cast(type, AssetType) : null; + var assetType = types.get(id); + + if (assetType != null) + { + if (assetType == requestedType + || ((requestedType == SOUND || requestedType == MUSIC) && (assetType == MUSIC || assetType == SOUND))) + { + return true; + } + + #if flash + if (requestedType == BINARY && (assetType == BINARY || assetType == TEXT || assetType == IMAGE)) + { + return true; + } + else if (requestedType == TEXT && assetType == BINARY) + { + return true; + } + else if (requestedType == null || paths.exists(id)) + { + return true; + } + #else + if (requestedType == BINARY || requestedType == null || (assetType == BINARY && requestedType == TEXT)) + { + return true; + } + #end + } + + return false; + } + + public function checkSpecificAsset(id:String, type:String):Bool + { + return switch (type) + { + case BINARY: cachedBytes.exists(id) || classTypes.exists(id) || paths.exists(id); + case FONT: cachedFonts.exists(id) || classTypes.exists(id) || paths.exists(id); + case IMAGE: cachedImages.exists(id) || classTypes.exists(id) || paths.exists(id); + case MUSIC, SOUND: cachedAudioBuffers.exists(id) || classTypes.exists(id) || paths.exists(id); + case TEXT: cachedText.exists(id) || cachedBytes.exists(id) || paths.exists(id); + + case TEMPLATE: false; + default: throw "Unknown asset type: " + type; + } + } + + public static function fromBytes(bytes:Bytes, rootPath:String = null):AssetLibrary + { + return fromManifest(AssetManifest.fromBytes(bytes, rootPath)); + } + + public static function fromFile(path:String, rootPath:String = null):AssetLibrary + { + return fromManifest(AssetManifest.fromFile(path, rootPath)); + } + + public static function fromBundle(bundle:AssetBundle):AssetLibrary + { + if (bundle.data.exists("library.json")) + { + var manifest = AssetManifest.fromBytes(bundle.data.get("library.json")); + if (manifest != null) + { + var library:AssetLibrary = null; + + if (manifest.libraryType == null) + { + library = new AssetLibrary(); + } + else + { + var libraryClass = Type.resolveClass(manifest.libraryType); + + if (libraryClass != null) + { + library = Type.createInstance(libraryClass, manifest.libraryArgs); + } + else + { + Log.warn("Could not find library type: " + manifest.libraryType); + return null; + } + } + + library.__fromBundle(bundle, manifest); + return library; + } + } + else + { + var library = new AssetLibrary(); + library.__fromBundle(bundle); + return library; + } + return null; + } + + public static function fromManifest(manifest:AssetManifest):AssetLibrary + { + if (manifest == null) return null; + + var library:AssetLibrary = null; + + if (manifest.libraryType == null) + { + library = new AssetLibrary(); + } + else + { + var libraryClass = Type.resolveClass(manifest.libraryType); + + if (libraryClass != null) + { + library = Type.createInstance(libraryClass, manifest.libraryArgs); + } + else + { + Log.warn("Could not find library type: " + manifest.libraryType); + return null; + } + } + + library.__fromManifest(manifest); + + return library; + } + + public function getAsset(id:String, type:String):Dynamic + { + return switch (type) + { + case BINARY: getBytes(id); + case FONT: getFont(id); + case IMAGE: getImage(id); + case MUSIC, SOUND: getAudioBuffer(id); + case TEXT: getText(id); + + case TEMPLATE: throw "Not sure how to get template: " + id; + default: throw "Unknown asset type: " + type; + } + } + + public function getAudioBuffer(id:String):AudioBuffer + { + if (cachedAudioBuffers.exists(id)) + { + return cachedAudioBuffers.get(id); + } + else if (classTypes.exists(id)) + { + #if flash + var buffer = new AudioBuffer(); + buffer.src = cast(Type.createInstance(classTypes.get(id), []), Sound); + return buffer; + #else + return AudioBuffer.fromBytes(cast(Type.createInstance(classTypes.get(id), []), Bytes)); + #end + } + else + { + return AudioBuffer.fromFile(getPath(id)); + } + } + + public function getBytes(id:String):Bytes + { + if (cachedBytes.exists(id)) + { + return cachedBytes.get(id); + } + else if (cachedText.exists(id)) + { + var bytes = Bytes.ofString(cachedText.get(id)); + cachedBytes.set(id, bytes); + return bytes; + } + else if (classTypes.exists(id)) + { + #if flash + var data = Type.createInstance(classTypes.get(id), []); + + switch (types.get(id)) + { + case TEXT, BINARY: + return Bytes.ofData(cast(Type.createInstance(classTypes.get(id), []), flash.utils.ByteArray)); + + case IMAGE: + var bitmapData = cast(Type.createInstance(classTypes.get(id), []), BitmapData); + return Bytes.ofData(bitmapData.getPixels(bitmapData.rect)); + + default: + return null; + } + #else + return cast(Type.createInstance(classTypes.get(id), []), Bytes); + #end + } + else + { + return Bytes.fromFile(getPath(id)); + } + } + + public function getFont(id:String):Font + { + if (cachedFonts.exists(id)) + { + return cachedFonts.get(id); + } + else if (classTypes.exists(id)) + { + #if flash + var src = Type.createInstance(classTypes.get(id), []); + + var font = new Font(src.fontName); + font.src = src; + return font; + #else + return cast(Type.createInstance(classTypes.get(id), []), Font); + #end + } + else + { + return Font.fromFile(getPath(id)); + } + } + + public function getImage(id:String):Image + { + if (cachedImages.exists(id)) + { + return cachedImages.get(id); + } + else if (classTypes.exists(id)) + { + #if flash + return Image.fromBitmapData(cast(Type.createInstance(classTypes.get(id), []), BitmapData)); + #else + return cast(Type.createInstance(classTypes.get(id), []), Image); + #end + } + else + { + return Image.fromFile(getPath(id)); + } + } + + public function getPath(id:String):String + { + if (paths.exists(id)) + { + return paths.get(id); + } + else if (pathGroups.exists(id)) + { + return pathGroups.get(id)[0]; + } + else + { + return null; + } + } + + public function getText(id:String):String + { + if (cachedText.exists(id)) + { + return cachedText.get(id); + } + else + { + var bytes = getBytes(id); + + if (bytes == null) + { + return null; + } + else + { + return bytes.getString(0, bytes.length); + } + } + } + + public function isLocal(id:String, type:String):Bool + { + #if sys + return true; + #else + if (classTypes.exists(id)) + { + return true; + } + + return switch (cast(type, AssetType)) + { + case null: + cachedBytes.exists(id) || cachedText.exists(id) || cachedImages.exists(id) + || cachedAudioBuffers.exists(id) || cachedFonts.exists(id); + + case IMAGE: + cachedImages.exists(id); + + case MUSIC, SOUND: + cachedAudioBuffers.exists(id); + + case FONT: + cachedFonts.exists(id); + + default: + cachedBytes.exists(id) || cachedText.exists(id); + } + #end + } + + public function list(type:String):Array + { + var requestedType = type != null ? cast(type, AssetType) : null; + var items = []; + + for (id in types.keys()) + { + if (requestedType == null || exists(id, type)) + { + items.push(id); + } + } + + return items; + } + + public function loadAsset(id:String, type:String):Future + { + return switch (type) + { + case BINARY: loadBytes(id); + case FONT: loadFont(id); + case IMAGE: loadImage(id); + case MUSIC, SOUND: loadAudioBuffer(id); + case TEXT: loadText(id); + + case TEMPLATE: throw "Not sure how to load template: " + id; + default: throw "Unknown asset type: " + type; + } + } + + public function load():Future + { + if (loaded) + { + return Future.withValue(this); + } + + if (promise == null) + { + promise = new Promise(); + bytesLoadedCache = new Map(); + + assetsLoaded = 0; + assetsTotal = 1; + + for (id in preload.keys()) + { + if (!preload.get(id)) continue; + + Log.verbose("Preloading asset: " + id + " [" + types.get(id) + "]"); + + switch (types.get(id)) + { + case BINARY: + assetsTotal++; + + var future = loadBytes(id); + future.onProgress(load_onProgress.bind(id)); + future.onError(load_onError.bind(id)); + future.onComplete(loadBytes_onComplete.bind(id)); + + case FONT: + assetsTotal++; + + var future = loadFont(id); + future.onProgress(load_onProgress.bind(id)); + future.onError(load_onError.bind(id)); + future.onComplete(loadFont_onComplete.bind(id)); + + case IMAGE: + assetsTotal++; + + var future = loadImage(id); + future.onProgress(load_onProgress.bind(id)); + future.onError(load_onError.bind(id)); + future.onComplete(loadImage_onComplete.bind(id)); + + case MUSIC, SOUND: + assetsTotal++; + + var future = loadAudioBuffer(id); + future.onProgress(load_onProgress.bind(id)); + future.onError(loadAudioBuffer_onError.bind(id)); + future.onComplete(loadAudioBuffer_onComplete.bind(id)); + + case TEXT: + assetsTotal++; + + var future = loadText(id); + future.onProgress(load_onProgress.bind(id)); + future.onError(load_onError.bind(id)); + future.onComplete(loadText_onComplete.bind(id)); + + default: + } + } + + __assetLoaded(null); + } + + return promise.future; + } + + public function loadAudioBuffer(id:String):Future + { + if (cachedAudioBuffers.exists(id)) + { + return Future.withValue(cachedAudioBuffers.get(id)); + } + else if (classTypes.exists(id)) + { + return Future.withValue(AudioBuffer.fromBytes(cast(Type.createInstance(classTypes.get(id), []), Bytes))); + } + else + { + if (pathGroups.exists(id)) + { + return AudioBuffer.loadFromFiles(pathGroups.get(id)); + } + else + { + return AudioBuffer.loadFromFile(paths.get(id)); + } + } + } + + public function loadBytes(id:String):Future + { + if (cachedBytes.exists(id)) + { + return Future.withValue(cachedBytes.get(id)); + } + else if (classTypes.exists(id)) + { + #if flash + return Future.withValue(Bytes.ofData(Type.createInstance(classTypes.get(id), []))); + #else + return Future.withValue(Type.createInstance(classTypes.get(id), [])); + #end + } + else + { + return Bytes.loadFromFile(getPath(id)); + } + } + + public function loadFont(id:String):Future + { + if (cachedFonts.exists(id)) + { + return Future.withValue(cachedFonts.get(id)); + } + else if (classTypes.exists(id)) + { + var font:Font = Type.createInstance(classTypes.get(id), []); + + #if (js && html5) + return font.__loadFromName(font.name); + #else + return Future.withValue(font); + #end + } + else + { + #if (js && html5) + return Font.loadFromName(getPath(id)); + #else + return Font.loadFromFile(getPath(id)); + #end + } + } + + public static function loadFromBytes(bytes:Bytes, rootPath:String = null):Future + { + return AssetManifest.loadFromBytes(bytes, rootPath).then(function(manifest) + { + return loadFromManifest(manifest); + }); + } + + public static function loadFromFile(path:String, rootPath:String = null):Future + { + return AssetManifest.loadFromFile(path, rootPath).then(function(manifest) + { + return loadFromManifest(manifest); + }); + } + + public static function loadFromManifest(manifest:AssetManifest):Future + { + var library = fromManifest(manifest); + + if (library != null) + { + return library.load(); + } + else + { + return cast Future.withError("Could not load asset manifest"); + } + } + + public function loadImage(id:String):Future + { + if (cachedImages.exists(id)) + { + return Future.withValue(cachedImages.get(id)); + } + else if (classTypes.exists(id)) + { + return Future.withValue(Type.createInstance(classTypes.get(id), [])); + } + else if (cachedBytes.exists(id)) + { + return Image.loadFromBytes(cachedBytes.get(id)).then(function(image) + { + cachedBytes.remove(id); + cachedImages.set(id, image); + return Future.withValue(image); + }); + } + else + { + return Image.loadFromFile(getPath(id)); + } + } + + public function loadText(id:String):Future + { + if (cachedText.exists(id)) + { + return Future.withValue(cachedText.get(id)); + } + else if (cachedBytes.exists(id) || classTypes.exists(id)) + { + var bytes = getBytes(id); + + if (bytes == null) + { + return cast Future.withValue(null); + } + else + { + var text = bytes.getString(0, bytes.length); + cachedText.set(id, text); + return Future.withValue(text); + } + } + else + { + var request = new HTTPRequest(); + return request.load(getPath(id)); + } + } + + public function unload():Void + { + #if haxe4 + cachedBytes.clear(); + cachedFonts.clear(); + cachedImages.clear(); + cachedAudioBuffers.clear(); + cachedText.clear(); + #else + cachedBytes = new Map(); + cachedFonts = new Map(); + cachedImages = new Map(); + cachedText = new Map(); + classTypes = new Map>(); + #end + } + + @:noCompletion private function __assetLoaded(id:String):Void + { + assetsLoaded++; + + if (id != null) + { + Log.verbose("Loaded asset: " + id + " [" + types.get(id) + "] (" + (assetsLoaded - 1) + "/" + (assetsTotal - 1) + ")"); + } + + if (id != null) + { + var size = sizes.exists(id) ? sizes.get(id) : 0; + + if (!bytesLoadedCache.exists(id)) + { + bytesLoaded += size; + } + else + { + var cache = bytesLoadedCache.get(id); + + if (cache < size) + { + bytesLoaded += (size - cache); + } + } + + bytesLoadedCache.set(id, size); + } + + if (assetsLoaded < assetsTotal) + { + promise.progress(bytesLoaded, bytesTotal); + } + else + { + loaded = true; + promise.progress(bytesTotal, bytesTotal); + promise.complete(this); + } + } + + @:noCompletion private function __cacheBreak(path:String):String + { + return Assets.__cacheBreak(path); + } + + @:noCompletion private function __fromBundle(bundle:AssetBundle, manifest:AssetManifest = null):Void + { + if (manifest != null) + { + var id, data, type:AssetType; + for (asset in manifest.assets) + { + id = Reflect.hasField(asset, "id") ? asset.id : asset.path; + data = bundle.data.get(asset.path); + + if (Reflect.hasField(asset, "type")) + { + type = asset.type; + switch (type) + { + #if !web + case IMAGE: + cachedImages.set(id, Image.fromBytes(data)); + case MUSIC, SOUND: + cachedAudioBuffers.set(id, AudioBuffer.fromBytes(data)); + case FONT: + cachedFonts.set(id, Font.fromBytes(data)); + #end + case TEXT: + cachedText.set(id, data != null ? Std.string(data) : null); + default: + cachedBytes.set(id, data); + } + types.set(id, asset.type); + } + else + { + cachedBytes.set(id, data); + types.set(id, BINARY); + } + } + } + else + { + for (path in bundle.paths) + { + cachedBytes.set(path, bundle.data.get(path)); + types.set(path, BINARY); + } + } + } + + @:noCompletion private function __fromManifest(manifest:AssetManifest):Void + { + var hasSize = (manifest.version >= 2); + var size, id, pathGroup:Array, classRef; + + var basePath = manifest.rootPath; + if (basePath == null) basePath = ""; + if (basePath != "") basePath += "/"; + + for (asset in manifest.assets) + { + size = hasSize && Reflect.hasField(asset, "size") ? asset.size : 100; + id = Reflect.hasField(asset, "id") ? asset.id : asset.path; + + if (Reflect.hasField(asset, "path")) + { + paths.set(id, __cacheBreak(__resolvePath(basePath + Reflect.field(asset, "path")))); + } + + if (Reflect.hasField(asset, "pathGroup")) + { + pathGroup = Reflect.field(asset, "pathGroup"); + + for (i in 0...pathGroup.length) + { + pathGroup[i] = __cacheBreak(__resolvePath(basePath + pathGroup[i])); + } + + pathGroups.set(id, pathGroup); + } + + sizes.set(id, size); + types.set(id, asset.type); + + if (Reflect.hasField(asset, "preload")) + { + preload.set(id, Reflect.field(asset, "preload")); + } + + if (Reflect.hasField(asset, "className")) + { + classRef = Type.resolveClass(Reflect.field(asset, "className")); + + #if (js && html5 && modular) + if (classRef == null) + { + classRef = untyped $hx_exports[asset.className]; + } + #end + + classTypes.set(id, classRef); + } + } + + bytesTotal = 0; + + for (asset in manifest.assets) + { + id = Reflect.hasField(asset, "id") ? asset.id : asset.path; + + if (preload.exists(id) && preload.get(id) && sizes.exists(id)) + { + bytesTotal += sizes.get(id); + } + } + } + + @:noCompletion private function __resolvePath(path:String):String + { + path = StringTools.replace(path, "\\", "/"); + + var colonIdx:Int = path.indexOf(":"); + if (StringTools.startsWith(path, "http") && colonIdx > 0) + { + var lastSlashIdx:Int = colonIdx + 3; + var httpSection:String = path.substr(0, lastSlashIdx); + path = httpSection + StringTools.replace(path.substr(lastSlashIdx), "//", "/"); + } + else + { + path = StringTools.replace(path, "//", "/"); + } + + #if android + if (StringTools.startsWith(path, "./")) + { + path = path.substr(2); + } + #end + + if (path.indexOf("./") > -1) + { + var split = path.split("/"); + var newPath = []; + + for (i in 0...split.length) + { + if (split[i] == "..") + { + if (i == 0 || newPath[i - 1] == "..") + { + newPath.push(".."); + } + else + { + newPath.pop(); + } + } + else if (split[i] == ".") + { + if (i == 0) + { + newPath.push("."); + } + } + else + { + newPath.push(split[i]); + } + } + path = newPath.join("/"); + } + + return path; + } + + // Event Handlers + @:noCompletion private function loadAudioBuffer_onComplete(id:String, audioBuffer:AudioBuffer):Void + { + cachedAudioBuffers.set(id, audioBuffer); + + if (pathGroups.exists(id)) + { + var pathGroup = pathGroups.get(id); + + for (otherID in pathGroups.keys()) + { + if (otherID == id) continue; + + for (path in pathGroup) + { + if (pathGroups.get(otherID).indexOf(path) > -1) + { + cachedAudioBuffers.set(otherID, audioBuffer); + break; + } + } + } + } + + __assetLoaded(id); + } + + @:noCompletion private function loadAudioBuffer_onError(id:String, message:Dynamic):Void + { + #if (js && html5) + if (message != null && message != "") + { + Log.warn("Could not load \"" + id + "\": " + Std.string(message)); + } + else + { + Log.warn("Could not load \"" + id + "\""); + } + + loadAudioBuffer_onComplete(id, new AudioBuffer()); + #else + load_onError(id, message); + #end + } + + @:noCompletion private function loadBytes_onComplete(id:String, bytes:Bytes):Void + { + cachedBytes.set(id, bytes); + __assetLoaded(id); + } + + @:noCompletion private function loadFont_onComplete(id:String, font:Font):Void + { + cachedFonts.set(id, font); + __assetLoaded(id); + } + + @:noCompletion private function loadImage_onComplete(id:String, image:Image):Void + { + cachedImages.set(id, image); + __assetLoaded(id); + } + + @:noCompletion private function loadText_onComplete(id:String, text:String):Void + { + cachedText.set(id, text); + __assetLoaded(id); + } + + @:noCompletion private function load_onError(id:String, message:Dynamic):Void + { + if (message != null && message != "") + { + promise.error("Error loading asset \"" + id + "\": " + Std.string(message)); + } + else + { + promise.error("Error loading asset \"" + id + "\""); + } + } + + @:noCompletion private function load_onProgress(id:String, bytesLoaded:Int, bytesTotal:Int):Void + { + if (bytesLoaded > 0) + { + var size = sizes.get(id); + var percent; + + if (bytesTotal > 0) + { + // Use a ratio in case the real bytesTotal is different than our precomputed total + + percent = (bytesLoaded / bytesTotal); + if (percent > 1) percent = 1; + bytesLoaded = Math.floor(percent * size); + } + else if (bytesLoaded > size) + { + bytesLoaded = size; + } + + if (bytesLoadedCache.exists(id)) + { + var cache = bytesLoadedCache.get(id); + + if (bytesLoaded != cache) + { + this.bytesLoaded += (bytesLoaded - cache); + } + } + else + { + this.bytesLoaded += bytesLoaded; + } + + bytesLoadedCache.set(id, bytesLoaded); + promise.progress(this.bytesLoaded, this.bytesTotal); + } + } +} diff --git a/source/openfl/utils/AssetLibrary.hx b/source/openfl/utils/AssetLibrary.hx new file mode 100644 index 00000000..64d924d1 --- /dev/null +++ b/source/openfl/utils/AssetLibrary.hx @@ -0,0 +1,449 @@ +package openfl.utils; + +import openfl.display.MovieClip; +#if lime +import lime.graphics.Image; +import lime.media.AudioBuffer; +import lime.text.Font; +import lime.utils.AssetLibrary as LimeAssetLibrary; +import lime.utils.AssetType; +import lime.utils.AssetManifest; +import lime.utils.Bytes; +#end + +#if !openfl_debug +@:fileXml('tags="haxe,release"') +@:noDebug +#end +class AssetLibrary #if lime extends LimeAssetLibrary #end +{ + #if lime + @:noCompletion private var __proxy:LimeAssetLibrary; + + // Had to edit this file for mainly this, its similar to proxy but doesnt cover everything - Nex + public var subLibraries:Array = []; + + @:noCompletion private function set_subLibraries(value:Array):Array { + if (value == null) value = []; + return subLibraries = value; + } + #end + + public function new() + { + #if lime + super(); + #end + } + + public function bind(className:String, instance:Dynamic = null):Bool + { + return false; + } + + #if lime + public override function exists(id:String, type:String):Bool + { + if (__proxy != null) + { + return __proxy.exists(id, type); + } + else + { + for(lib in subLibraries) if(lib != null && lib.exists(id, type)) return true; + return super.exists(id, type); + } + } + #end + + public static function fromBundle(bundle:AssetBundle):AssetLibrary + { + #if lime + var library = LimeAssetLibrary.fromBundle(bundle); + + if (library != null) + { + if ((library is AssetLibrary)) + { + return cast library; + } + else + { + var _library = new AssetLibrary(); + _library.__proxy = library; + return _library; + } + } + else + { + return null; + } + #else + return null; + #end + } + + public static function fromBytes(bytes:ByteArray, rootPath:String = null):AssetLibrary + { + #if lime + return cast fromManifest(AssetManifest.fromBytes(bytes, rootPath)); + #else + return null; + #end + } + + public static function fromFile(path:String, rootPath:String = null):AssetLibrary + { + #if lime + return cast fromManifest(AssetManifest.fromFile(path, rootPath)); + #else + return null; + #end + } + + public static function fromManifest(manifest:AssetManifest):#if (java && lime) LimeAssetLibrary #else AssetLibrary #end + { + #if lime + var library = LimeAssetLibrary.fromManifest(manifest); + + if (library != null) + { + if ((library is AssetLibrary)) + { + return cast library; + } + else + { + var _library = new AssetLibrary(); + _library.__proxy = library; + return _library; + } + } + else + { + return null; + } + #else + return null; + #end + } + + #if lime + public override function getAsset(id:String, type:String):Dynamic + { + if (__proxy != null) + { + return __proxy.getAsset(id, type); + } + else + { + var val:Dynamic = null; + for(lib in subLibraries) if(lib != null && (val = lib.getAsset(id, type)) != null) return val; + return super.getAsset(id, type); + } + } + #end + + #if lime + public override function getAudioBuffer(id:String):AudioBuffer + { + if (__proxy != null) + { + return __proxy.getAudioBuffer(id); + } + else + { + var val:Dynamic = null; + for(lib in subLibraries) if(lib != null && (val = lib.getAudioBuffer(id)) != null) return val; + return super.getAudioBuffer(id); + } + } + #end + + #if lime + public override function getBytes(id:String):Bytes + { + if (__proxy != null) + { + return __proxy.getBytes(id); + } + else + { + var val:Dynamic = null; + for(lib in subLibraries) if(lib != null && (val = lib.getBytes(id)) != null) return val; + return super.getBytes(id); + } + } + #end + + #if lime + public override function getFont(id:String):Font + { + if (__proxy != null) + { + return __proxy.getFont(id); + } + else + { + var val:Dynamic = null; + for(lib in subLibraries) if(lib != null && (val = lib.getFont(id)) != null) return val; + return super.getFont(id); + } + } + #end + + #if lime + public override function getImage(id:String):Image + { + if (__proxy != null) + { + return __proxy.getImage(id); + } + else + { + var val:Dynamic = null; + for(lib in subLibraries) if(lib != null && (val = lib.getImage(id)) != null) return val; + return super.getImage(id); + } + } + #end + + public function getMovieClip(id:String):MovieClip + { + return null; + } + + #if lime + public override function getPath(id:String):String + { + if (__proxy != null) + { + return __proxy.getPath(id); + } + else + { + var val:Dynamic = null; + for(lib in subLibraries) if(lib != null && (val = lib.getPath(id)) != null) return val; + return super.getPath(id); + } + } + #end + + #if lime + public override function getText(id:String):String + { + if (__proxy != null) + { + return __proxy.getText(id); + } + else + { + var val:Dynamic = null; + for(lib in subLibraries) if(lib != null && (val = lib.getText(id)) != null) return val; + return super.getText(id); + } + } + #end + + #if lime + public override function isLocal(id:String, type:String):Bool + { + if (__proxy != null) + { + return __proxy.isLocal(id, type); + } + else + { + for(lib in subLibraries) if(lib != null && lib.isLocal(id, type)) return true; + return super.isLocal(id, type); + } + } + #end + + #if lime + public override function list(type:String):Array + { + if (__proxy != null) + { + return __proxy.list(type); + } + else + { + var finalArr:Array = []; + for(lib in subLibraries.concat([this])) if(lib != null) for(f in lib.list(type)) if(!finalArr.contains(f)) finalArr.push(f); + return finalArr; + } + } + #end + + #if lime + public override function loadAsset(id:String, type:String):Future + { + if (__proxy != null) + { + return __proxy.loadAsset(id, type); + } + else + { + for(lib in subLibraries) if(lib != null && lib.checkSpecificAsset(id, type)) return lib.loadAsset(id, type); + return super.loadAsset(id, type); + } + } + #end + + #if lime + public override function load():Future + { + if (__proxy != null) + { + return __proxy.load(); + } + else + { + // TODO: Make this work by using multiple Futures + for(lib in subLibraries) if(lib != null) return lib.load(); + return super.load(); + } + } + #end + + #if lime + public override function loadAudioBuffer(id:String):Future + { + if (__proxy != null) + { + return __proxy.loadAudioBuffer(id); + } + else + { + for(lib in subLibraries) if(lib != null && lib.checkSpecificAsset(id, MUSIC)) return lib.loadAudioBuffer(id); + return super.loadAudioBuffer(id); + } + } + #end + + #if lime + public override function loadBytes(id:String):Future + { + if (__proxy != null) + { + return __proxy.loadBytes(id); + } + else + { + for(lib in subLibraries) if(lib != null && lib.checkSpecificAsset(id, BINARY)) return lib.loadBytes(id); + return super.loadBytes(id); + } + } + #end + + #if lime + public override function loadFont(id:String):Future + { + if (__proxy != null) + { + return __proxy.loadFont(id); + } + else + { + for(lib in subLibraries) if(lib != null && lib.checkSpecificAsset(id, FONT)) return lib.loadFont(id); + return super.loadFont(id); + } + } + #end + + public static function loadFromBytes(bytes:ByteArray, rootPath:String = null):#if (java && lime) Future #else Future #end + { + #if lime + return AssetManifest.loadFromBytes(bytes, rootPath).then(function(manifest) + { + return loadFromManifest(manifest); + }); + #else + return cast Future.withValue(null); + #end + } + + public static function loadFromFile(path:String, rootPath:String = null):#if (java && lime) Future #else Future #end + { + #if lime + return AssetManifest.loadFromFile(path, rootPath).then(function(manifest) + { + return loadFromManifest(manifest); + }); + #else + return cast Future.withValue(null); + #end + } + + public static function loadFromManifest(manifest:AssetManifest):#if (java && lime) Future #else Future #end + { + #if lime + var library:AssetLibrary = cast fromManifest(manifest); + + if (library != null) + { + return library.load().then(function(library) + { + return Future.withValue(cast library); + }); + } + else + { + return cast Future.withError("Could not load asset manifest"); + } + #else + return cast Future.withValue(null); + #end + } + + #if lime + public override function loadImage(id:String):Future + { + if (__proxy != null) + { + return __proxy.loadImage(id); + } + else + { + for(lib in subLibraries) if(lib != null && lib.checkSpecificAsset(id, IMAGE)) return lib.loadImage(id); + return super.loadImage(id); + } + } + #end + + public function loadMovieClip(id:String):Future + { + return Future.withValue(getMovieClip(id)); + } + + #if lime + public override function loadText(id:String):Future + { + if (__proxy != null) + { + return __proxy.loadText(id); + } + else + { + for(lib in subLibraries) if(lib != null && lib.checkSpecificAsset(id, TEXT)) return lib.loadText(id); + return super.loadText(id); + } + } + #end + + #if lime + public override function unload():Void + { + if (__proxy != null) + { + return __proxy.unload(); + } + else + { + for(lib in subLibraries) if(lib != null) lib.unload(); + return super.unload(); + } + } + #end +}