Improve asset library progress events (close #886)

This commit is contained in:
Joshua Granick
2017-01-14 16:21:38 -08:00
parent b280054c33
commit feec323117
6 changed files with 171 additions and 110 deletions

View File

@@ -21,6 +21,8 @@ import flash.events.ProgressEvent;
import flash.Lib;
#end
@:access(lime.utils.AssetLibrary)
#if !lime_debug
@:fileXml('tags="haxe,release"')
@:noDebug
@@ -34,9 +36,10 @@ class Preloader #if flash extends Sprite #end {
public var onComplete = new Event<Void->Void> ();
public var onProgress = new Event<Int->Int->Void> ();
private var bytesLoaded:Int;
private var bytesTotal:Int;
private var bytesTotalCache = new Map<String, Int> ();
private var initLibraryNames:Bool;
private var itemsProgressLoaded:Int;
private var itemsProgressTotal:Int;
private var libraries:Array<AssetLibrary>;
private var libraryNames:Array<String>;
private var loadedLibraries:Int;
@@ -49,6 +52,8 @@ class Preloader #if flash extends Sprite #end {
super ();
#end
bytesLoaded = 0;
bytesTotal = 0;
libraries = new Array<AssetLibrary> ();
libraryNames = new Array<String> ();
@@ -91,12 +96,9 @@ class Preloader #if flash extends Sprite #end {
public function load ():Void {
itemsProgressLoaded = 0;
itemsProgressTotal = 0;
for (library in libraries) {
itemsProgressTotal += library.computeProgressTotal ();
bytesTotal += library.bytesTotal;
}
@@ -104,9 +106,10 @@ class Preloader #if flash extends Sprite #end {
for (library in libraries) {
library.load ().onProgress (function (_, _) {
library.load ().onProgress (function (loaded, total) {
updateItemsProgress ();
bytesLoaded += loaded;
onProgress.dispatch (bytesLoaded, bytesTotal);
}).onComplete (function (_) {
@@ -121,9 +124,11 @@ class Preloader #if flash extends Sprite #end {
}
// TODO: Handle bytes total better
for (name in libraryNames) {
itemsProgressTotal += 1;
bytesTotal += 200;
}
@@ -159,8 +164,7 @@ class Preloader #if flash extends Sprite #end {
private function updateProgress ():Void {
update (itemsProgressLoaded, itemsProgressTotal);
// update (loadedLibraries, libraries.length);
onProgress.dispatch (bytesLoaded, bytesTotal);
if (loadedLibraries == libraries.length && !initLibraryNames) {
@@ -168,9 +172,23 @@ class Preloader #if flash extends Sprite #end {
for (name in libraryNames) {
Assets.loadLibrary (name).onProgress (function (_, _) {
Assets.loadLibrary (name).onProgress (function (loaded, total) {
updateItemsProgress ();
if (total > 0) {
if (!bytesTotalCache.exists (name)) {
bytesTotalCache.set (name, total);
bytesTotal += (total - 200);
}
if (loaded > total) loaded = total;
bytesLoaded += loaded;
onProgress.dispatch (bytesLoaded, bytesTotal);
}
}).onComplete (function (_) {
@@ -195,16 +213,12 @@ class Preloader #if flash extends Sprite #end {
}
private function updateItemsProgress ():Void {
itemsProgressLoaded++;
updateProgress();
}
#if flash
private function current_onEnter (event:flash.events.Event):Void {
// TODO: Merge progress with library load progress
if (!loadedStage && Lib.current.loaderInfo.bytesLoaded == Lib.current.loaderInfo.bytesTotal) {
loadedStage = true;

View File

@@ -23,11 +23,20 @@ class AssetHelper {
if (asset.type != AssetType.TEMPLATE) {
var size = 100;
if (FileSystem.exists (asset.sourcePath)) {
size = FileSystem.stat (asset.sourcePath).size;
}
manifest.assets.push ({
id: asset.id,
path: asset.resourceName,
type: Std.string (asset.type)
type: Std.string (asset.type),
size: size
});

View File

@@ -26,6 +26,11 @@ class AssetLibrary {
public var onChange = new Event<Void->Void> ();
private var assetsLoaded:Int;
private var assetsTotal:Int;
private var bytesLoaded:Int;
private var bytesLoadedCache:Map<String, Int>;
private var bytesTotal:Int;
private var cachedAudioBuffers = new Map<String, AudioBuffer> ();
private var cachedBytes = new Map<String, Bytes> ();
private var cachedFonts = new Map<String, Font> ();
@@ -34,12 +39,8 @@ class AssetLibrary {
private var classTypes = new Map<String, Class<Dynamic>> ();
private var paths = new Map<String, String> ();
private var preload = new Map<String, Bool> ();
private var progressBytesLoadedCache:Map<String, Int>;
private var progressBytesLoaded:Int;
private var progressBytesTotal:Int;
private var progressLoaded:Int;
private var progressTotal:Int;
private var promise:Promise<AssetLibrary>;
private var sizes = new Map<String, Int> ();
private var types = new Map<String, AssetType> ();
#if (js && html5)
@@ -49,7 +50,8 @@ class AssetLibrary {
public function new () {
bytesLoaded = 0;
bytesTotal = 0;
}
@@ -104,22 +106,18 @@ class AssetLibrary {
var library:AssetLibrary = null;
if (manifest.version == 1) {
if (manifest.libraryType == null) {
if (manifest.libraryType == null) {
library = new AssetLibrary ();
} else {
library = Type.createInstance (Type.resolveClass (manifest.libraryType), manifest.libraryArgs);
}
library = new AssetLibrary ();
library.__fromManifest (manifest);
} else {
library = Type.createInstance (Type.resolveClass (manifest.libraryType), manifest.libraryArgs);
}
library.__fromManifest (manifest);
return library;
}
@@ -378,37 +376,16 @@ class AssetLibrary {
}
public function computeProgressTotal ():Int {
var result = 1;
for (id in preload.keys ()) {
switch (types.get (id)) {
case BINARY, FONT, IMAGE, MUSIC, SOUND, TEXT:
result++;
default:
}
}
return result;
}
public function load ():Future<AssetLibrary> {
if (promise == null) {
promise = new Promise<AssetLibrary> ();
progressBytesLoadedCache = new Map ();
bytesLoadedCache = new Map ();
progressLoaded = 0;
progressTotal = 1;
assetsLoaded = 0;
assetsTotal = 1;
for (id in preload.keys ()) {
@@ -416,7 +393,7 @@ class AssetLibrary {
case BINARY:
progressTotal++;
assetsTotal++;
var future = loadBytes (id);
future.onProgress (load_onProgress.bind (id));
@@ -425,7 +402,7 @@ class AssetLibrary {
case FONT:
progressTotal++;
assetsTotal++;
var future = loadFont (id);
future.onProgress (load_onProgress.bind (id));
@@ -434,7 +411,7 @@ class AssetLibrary {
case IMAGE:
progressTotal++;
assetsTotal++;
var future = loadImage (id);
future.onProgress (load_onProgress.bind (id));
@@ -443,7 +420,7 @@ class AssetLibrary {
case MUSIC, SOUND:
progressTotal++;
assetsTotal++;
var future = loadAudioBuffer (id);
future.onProgress (load_onProgress.bind (id));
@@ -452,7 +429,7 @@ class AssetLibrary {
case TEXT:
progressTotal++;
assetsTotal++;
var future = loadText (id);
future.onProgress (load_onProgress.bind (id));
@@ -465,7 +442,7 @@ class AssetLibrary {
}
updateProgressLoaded ();
__assetLoaded (null);
}
@@ -637,13 +614,41 @@ class AssetLibrary {
}
private function updateProgressLoaded ():Void {
private function __assetLoaded (id:String):Void {
progressLoaded++;
promise.progress(progressLoaded, progressTotal);
assetsLoaded++;
if (progressLoaded == progressTotal) {
if (id != null) {
var size = sizes.get (id);
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 {
promise.progress (bytesTotal, bytesTotal);
promise.complete (this);
}
@@ -653,12 +658,22 @@ class AssetLibrary {
private function __fromManifest (manifest:AssetManifest):Void {
if (manifest.version == 1) {
var hasSize = (manifest.version >= 2);
var size;
bytesTotal = 0;
for (asset in manifest.assets) {
for (asset in manifest.assets) {
size = hasSize ? asset.size : 100;
paths.set (asset.id, asset.path);
sizes.set (asset.id, size);
types.set (asset.id, asset.type);
if (preload.exists (asset.id)) {
paths.set (asset.id, asset.path);
types.set (asset.id, asset.type);
bytesTotal += size;
}
@@ -677,7 +692,7 @@ class AssetLibrary {
private function loadAudioBuffer_onComplete (id:String, audioBuffer:AudioBuffer):Void {
cachedAudioBuffers.set (id, audioBuffer);
updateProgressLoaded ();
__assetLoaded (id);
}
@@ -685,7 +700,7 @@ class AssetLibrary {
private function loadBytes_onComplete (id:String, bytes:Bytes):Void {
cachedBytes.set (id, bytes);
updateProgressLoaded ();
__assetLoaded (id);
}
@@ -693,7 +708,7 @@ class AssetLibrary {
private function loadFont_onComplete (id:String, font:Font):Void {
cachedFonts.set (id, font);
updateProgressLoaded ();
__assetLoaded (id);
}
@@ -701,7 +716,7 @@ class AssetLibrary {
private function loadImage_onComplete (id:String, image:Image):Void {
cachedImages.set (id, image);
updateProgressLoaded ();
__assetLoaded (id);
}
@@ -709,7 +724,7 @@ class AssetLibrary {
private function loadText_onComplete (id:String, text:String):Void {
cachedText.set (id, text);
updateProgressLoaded ();
__assetLoaded (id);
}
@@ -723,21 +738,42 @@ class AssetLibrary {
private function load_onProgress (id:String, bytesLoaded:Int, bytesTotal:Int):Void {
if (progressBytesLoadedCache.exists (id)) {
if (bytesLoaded > 0) {
var previous = progressBytesLoadedCache.get (id);
progressBytesLoaded += (bytesLoaded - previous);
progressBytesLoadedCache.set (id, bytesLoaded);
promise.progress (progressBytesLoaded, progressBytesTotal);
} else {
var size = sizes.get (id);
var percent;
if (bytesTotal > 0) {
progressBytesLoadedCache.set (id, bytesLoaded);
progressBytesLoaded += bytesLoaded;
progressBytesTotal += bytesTotal;
// 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) {
bytesLoaded += (bytesLoaded - cache);
}
bytesLoadedCache.set (id, bytesLoaded);
promise.progress (this.bytesLoaded, this.bytesTotal);
} else {
bytesLoadedCache.set (id, bytesLoaded);
this.bytesLoaded += bytesLoaded;
}

View File

@@ -30,7 +30,7 @@ class AssetManifest {
assets = [];
libraryArgs = [];
version = 1;
version = 2;
}
@@ -82,14 +82,10 @@ class AssetManifest {
var manifestData = Json.parse (data);
var manifest = new AssetManifest ();
if (manifestData.version == 1) {
manifest.name = manifestData.name;
manifest.libraryType = manifestData.libraryType;
manifest.libraryArgs = manifestData.libraryArgs;
manifest.assets = Unserializer.run (manifestData.assets);
}
manifest.name = manifestData.name;
manifest.libraryType = manifestData.libraryType;
manifest.libraryArgs = manifestData.libraryArgs;
manifest.assets = Unserializer.run (manifestData.assets);
return manifest;

View File

@@ -486,9 +486,18 @@ class Assets {
if (data != null && data != "") {
var library = AssetLibrary.fromManifest (AssetManifest.parse (data));
libraries.set (name, library);
library.onChange.add (onChange.dispatch);
promise.completeWith (library.load ());
if (library == null) {
promise.error ("[Assets] Cannot open library \"" + name + "\"");
} else {
libraries.set (name, library);
library.onChange.add (onChange.dispatch);
promise.completeWith (library.load ());
}
} else {

View File

@@ -165,16 +165,13 @@ import sys.FileSystem;
private override function __fromManifest (manifest:AssetManifest):Void {
if (manifest.version == 1) {
super.__fromManifest (manifest);
if (rootPath != "") {
for (asset in manifest.assets) {
if (!classTypes.exists (asset.id)) {
paths.set (asset.id, rootPath + asset.path);
types.set (asset.id, cast (asset.type, AssetType));
}
paths.set (asset.id, rootPath + asset.path);
}