Browse Source

allow to load PAK file at runtime with hxd.fmt.pak.Loader (in hxd.App.loadAssets)

ncannasse 9 years ago
parent
commit
c04f41ccc9
7 changed files with 183 additions and 33 deletions
  1. 14 6
      hxd/App.hx
  2. 2 1
      hxd/Res.hx
  3. 18 19
      hxd/fmt/pak/Build.hx
  4. 28 4
      hxd/fmt/pak/FileSystem.hx
  5. 72 0
      hxd/fmt/pak/Loader.hx
  6. 35 0
      hxd/net/BinaryLoader.hx
  7. 14 3
      hxd/res/FileTree.hx

+ 14 - 6
hxd/App.hx

@@ -24,19 +24,27 @@ class App {
 	}
 
 	function setup() {
+		var initDone = false;
 		engine.onResized = function() {
 			if( s2d == null ) return; // if disposed
 			s2d.checkResize();
-			onResize();
+			if( initDone ) onResize();
 		};
 		s3d = new h3d.scene.Scene();
 		s2d = new h2d.Scene();
 		s3d.addPass(s2d);
-		init();
-		hxd.Timer.skip();
-		mainLoop();
-		hxd.System.setLoop(mainLoop);
-		hxd.Key.initialize();
+		loadAssets(function() {
+			initDone = true;
+			init();
+			hxd.Timer.skip();
+			mainLoop();
+			hxd.System.setLoop(mainLoop);
+			hxd.Key.initialize();
+		});
+	}
+
+	function loadAssets( onLoaded ) {
+		onLoaded();
 	}
 
 	function init() {

+ 2 - 1
hxd/Res.hx

@@ -26,7 +26,8 @@ class Res {
 		if( dir == null ) dir = "res";
 		return macro {
 			var dir = $v{dir};
-			var pak = new hxd.fmt.pak.FileSystem(dir+".pak");
+			var pak = new hxd.fmt.pak.FileSystem();
+			pak.loadPak(dir + ".pak");
 			var i = 1;
 			while( true ) {
 				if( !hxd.File.exists(dir + i + ".pak") ) break;

+ 18 - 19
hxd/fmt/pak/Build.hx

@@ -100,31 +100,30 @@ class Build {
 		return out;
 	}
 
-	public static function make( dir = "res" ) {
+	public static function make( dir = "res", out = "res", ?pakDiff ) {
 		var pak = new Data();
 		var outBytes = { bytes : [], size : 0 };
 		pak.version = 0;
 		pak.root = buildRec(dir,"",outBytes);
-		var out = "res";
 
-		#if pakDiff
-		var id = 0;
-		while( true ) {
-			var name = out + (id == 0 ? "" : "" + id) + ".pak";
-			if( !sys.FileSystem.exists(name) ) break;
-			var oldPak = new Reader(sys.io.File.read(name)).readHeader();
-			filter(pak.root, oldPak.root);
-			id++;
-		}
-		if( id > 0 ) {
-			out += id;
-			if( pak.root.content.length == 0 ) {
-				Sys.println("No changes in resources");
-				return;
+		if( pakDiff ) {
+			var id = 0;
+			while( true ) {
+				var name = out + (id == 0 ? "" : "" + id) + ".pak";
+				if( !sys.FileSystem.exists(name) ) break;
+				var oldPak = new Reader(sys.io.File.read(name)).readHeader();
+				filter(pak.root, oldPak.root);
+				id++;
+			}
+			if( id > 0 ) {
+				out += id;
+				if( pak.root.content.length == 0 ) {
+					Sys.println("No changes in resources");
+					return;
+				}
 			}
+			outBytes.bytes = rebuild(pak, outBytes.bytes);
 		}
-		outBytes.bytes = rebuild(pak, outBytes.bytes);
-		#end
 
 		var f = sys.io.File.write(out + ".pak");
 		new Writer(f).write(pak, null, outBytes.bytes);
@@ -133,7 +132,7 @@ class Build {
 
 	static function main() {
 		try sys.FileSystem.deleteFile("hxd.fmt.pak.Build.n") catch( e : Dynamic ) {};
-		make(haxe.macro.Compiler.getDefine("resourcesPath"));
+		make(haxe.macro.Compiler.getDefine("resourcesPath"),null #if pakDiff, true #end);
 	}
 
 }

+ 28 - 4
hxd/fmt/pak/FileSystem.hx

@@ -2,9 +2,27 @@ package hxd.fmt.pak;
 import hxd.fs.FileEntry;
 #if air3
 import hxd.impl.Air3File;
-#else
+#elseif sys
 import sys.io.File;
 import sys.io.FileInput;
+#else
+enum FileSeek {
+	SeekBegin;
+	SeekEnd;
+	SeedCurrent;
+}
+class FileInput extends haxe.io.BytesInput {
+	public function seek( pos : Int, seekMode : FileSeek ) {
+		switch( seekMode ) {
+		case SeekBegin:
+			this.position = pos;
+		case SeekEnd:
+			this.position = this.length - pos;
+		case SeedCurrent:
+			this.position += pos;
+		}
+	}
+}
 #end
 
 @:allow(hxd.fmt.pak.FileSystem)
@@ -138,7 +156,7 @@ class FileSystem implements hxd.fs.FileSystem {
 	var dict : Map<String,PakEntry>;
 	var files : Array<FileInput>;
 
-	public function new( pakFile : String ) {
+	public function new() {
 		dict = new Map();
 		var f = new Data.File();
 		f.name = "<root>";
@@ -146,11 +164,17 @@ class FileSystem implements hxd.fs.FileSystem {
 		f.content = [];
 		files = [];
 		root = new PakEntry(null, f, null);
-		loadPak(pakFile);
 	}
 
 	public function loadPak( file : String ) {
-		var s = File.read(file);
+		#if (air3 || sys)
+		addPak(File.read(file));
+		#else
+		throw "TODO";
+		#end
+	}
+
+	public function addPak( s : FileInput ) {
 		var pak = new Reader(s).readHeader();
 		if( pak.root.isDirectory ) {
 			for( f in pak.root.content )

+ 72 - 0
hxd/fmt/pak/Loader.hx

@@ -0,0 +1,72 @@
+package hxd.fmt.pak;
+
+class Loader extends h2d.Sprite {
+
+	var onDone : Void -> Void;
+	var cur : hxd.net.BinaryLoader;
+	var resCount : Int;
+	var fs : FileSystem;
+	var s2d : h2d.Scene;
+	var bg : h2d.Graphics;
+
+	public function new(s2d:h2d.Scene, onDone) {
+		super(s2d);
+		this.s2d = s2d;
+		this.bg = new h2d.Graphics(this);
+		this.onDone = onDone;
+		if( hxd.res.Loader.currentInstance == null )
+			hxd.res.Loader.currentInstance = new hxd.res.Loader(new FileSystem());
+		fs = Std.instance(hxd.res.Loader.currentInstance.fs, FileSystem);
+		if( fs == null )
+			throw "Can only use loader with PAK file system";
+		hxd.System.setLoop(render);
+	}
+
+	function render() {
+		s2d.checkEvents();
+		h3d.Engine.getCurrent().render(s2d);
+	}
+
+	function updateBG( progress : Float ) {
+		bg.clear();
+		bg.beginFill(0x404040);
+		bg.drawRect(0, 0, 100, 10);
+		bg.beginFill(0x40C040);
+		bg.drawRect(1, 1, Std.int(progress * 98), 10);
+	}
+
+	override function sync(ctx:h2d.RenderContext)  {
+		super.sync(ctx);
+		if( cur == null ) {
+
+			bg.x = (s2d.width - 100) >> 1;
+			bg.y = (s2d.height - 10) >> 1;
+			updateBG(0);
+
+			cur = new hxd.net.BinaryLoader("res" + (resCount == 0 ? "" : "" + resCount) + ".pak");
+			cur.onLoaded = function(bytes) {
+				try {
+					fs.addPak(new FileSystem.FileInput(bytes));
+					resCount++;
+					cur = null;
+				} catch( e : Dynamic ) {
+					cur.onError(e);
+				}
+			};
+			cur.onProgress = function(cur, max) {
+				updateBG(cur / max);
+			};
+			cur.onError = function(e) {
+				if( resCount == 0 )
+					trace(e);
+				else {
+					remove();
+					onDone();
+				}
+			};
+			cur.load();
+		}
+	}
+
+
+}

+ 35 - 0
hxd/net/BinaryLoader.hx

@@ -0,0 +1,35 @@
+package hxd.net;
+
+class BinaryLoader {
+
+	public var url(default, null) : String;
+	#if flash
+	var loader : flash.net.URLLoader;
+	#end
+
+	public function new( url : String ) {
+		this.url = url;
+	}
+
+	public dynamic function onLoaded( bytes : haxe.io.Bytes ) {
+	}
+
+	public dynamic function onProgress( cur : Int, max : Int ) {
+	}
+
+	public dynamic function onError( msg : String ) {
+		throw msg;
+	}
+
+	public function load() {
+		#if flash
+		loader = new flash.net.URLLoader();
+		loader.dataFormat = flash.net.URLLoaderDataFormat.BINARY;
+		loader.addEventListener(flash.events.IOErrorEvent.IO_ERROR, function(e:flash.events.IOErrorEvent) onError(e.text));
+		loader.addEventListener(flash.events.Event.COMPLETE, function(_) onLoaded(haxe.io.Bytes.ofData(loader.data)));
+		loader.addEventListener(flash.events.ProgressEvent.PROGRESS, function(e:flash.events.ProgressEvent) onProgress(Std.int(e.bytesLoaded), Std.int(e.bytesTotal)));
+		loader.load(new flash.net.URLRequest(url));
+		#end
+	}
+
+}

+ 14 - 3
hxd/res/FileTree.hx

@@ -209,9 +209,21 @@ class FileTree {
 			fields.push({
 				name : "loader",
 				access : [APublic, AStatic],
-				kind : FProp("default","set",loaderType),
+				kind : FProp("get","set",loaderType),
 				pos : pos,
 			});
+			fields.push( {
+				name : "get_loader",
+				access : [AStatic],
+				kind : FFun( {
+					args : [],
+					ret : loaderType,
+					expr : macro {
+						return hxd.res.Loader.currentInstance;
+					}
+				}),
+				pos : pos
+			});
 			fields.push( {
 				name : "set_loader",
 				access : [AStatic],
@@ -219,8 +231,7 @@ class FileTree {
 					args : [ { name : "l", type : loaderType } ],
 					ret : loaderType,
 					expr : macro {
-						hxd.res.Loader.currentInstance = l;
-						return loader = l;
+						return hxd.res.Loader.currentInstance = l;
 					}
 				}),
 				pos : pos