Ver Fonte

moved prefab based from hide to heaps

ncannasse há 7 anos atrás
pai
commit
921bb565d2
5 ficheiros alterados com 507 adições e 0 exclusões
  1. 93 0
      hxd/prefab/Context.hx
  2. 93 0
      hxd/prefab/ContextShared.hx
  3. 58 0
      hxd/prefab/Library.hx
  4. 241 0
      hxd/prefab/Prefab.hx
  5. 22 0
      hxd/prefab/Unknown.hx

+ 93 - 0
hxd/prefab/Context.hx

@@ -0,0 +1,93 @@
+package hxd.prefab;
+
+@:final class Context {
+
+	public var local2d : h2d.Sprite;
+	public var local3d : h3d.scene.Object;
+	public var shared : ContextShared;
+	public var custom : Dynamic;
+	public var isRef : Bool = false;
+
+	public function new() {
+	}
+
+	public function init() {
+		if( shared == null )
+			shared = new ContextShared();
+		local2d = shared.root2d;
+		local3d = shared.root3d;
+	}
+
+	public function clone( p : Prefab ) {
+		var c = new Context();
+		c.shared = shared;
+		c.local2d = local2d;
+		c.local3d = local3d;
+		c.custom = custom;
+		c.isRef = isRef;
+		if( p != null ) {
+			if(!isRef)
+				shared.contexts.set(p, c);
+			else {
+				if(!shared.references.exists(p))
+					shared.references.set(p, [c])
+				else
+					shared.references[p].push(c);
+			}
+		}
+		return c;
+	}
+
+	public dynamic function onError( e : Dynamic ) {
+		#if editor
+		js.Browser.window.alert(e);
+		#else
+		throw e;
+		#end
+	}
+
+	public function loadModel( path : String ) {
+		return shared.loadModel(path);
+	}
+
+	public function loadAnimation( path : String ) {
+		return shared.loadAnimation(path);
+	}
+
+	public function loadTexture( path : String ) {
+		return shared.loadTexture(path);
+	}
+
+	public function loadShader( name : String ) {
+		return shared.loadShader(name);
+	}
+
+	public function locateObject( path : String ) {
+		if( path == null )
+			return null;
+		var parts = path.split(".");
+		var root = shared.root3d;
+		while( parts.length > 0 ) {
+			var v = null;
+			var pname = parts.shift();
+			for( o in root )
+				if( o.name == pname ) {
+					v = o;
+					break;
+				}
+			if( v == null ) {
+				v = root.getObjectByName(pname);
+				if( v != null && v.parent != root ) v = null;
+			}
+			if( v == null ) {
+				var parts2 = path.split(".");
+				for( i in 0...parts.length ) parts2.pop();
+				onError("Object not found " + parts2.join("."));
+				return null;
+			}
+			root = v;
+		}
+		return root;
+	}
+
+}

+ 93 - 0
hxd/prefab/ContextShared.hx

@@ -0,0 +1,93 @@
+package hxd.prefab;
+
+typedef ShaderDef = {
+	var shader : hxsl.SharedShader;
+	var inits : Array<{ v : hxsl.Ast.TVar, e : hxsl.Ast.TExpr }>;
+}
+
+typedef ShaderDefCache = Map<String, ShaderDef>;
+
+class ContextShared {
+	public var root2d : h2d.Sprite;
+	public var root3d : h3d.scene.Object;
+	public var contexts : Map<Prefab,Context>;
+	public var references : Map<Prefab,Array<Context>>;
+	public var cleanups : Array<Void->Void>;
+	var cache : h3d.prim.ModelCache;
+	var shaderCache : ShaderDefCache;
+
+	#if editor
+	var scene : hide.comp.Scene;
+	public function getScene() {
+		return scene;
+	}
+	#end
+
+	public function new() {
+		root2d = new h2d.Sprite();
+		root3d = new h3d.scene.Object();
+		contexts = new Map();
+		references = new Map();
+		cache = new h3d.prim.ModelCache();
+		cleanups = [];
+		shaderCache = new ShaderDefCache();
+	}
+
+	public function elements() {
+		return [for(e in contexts.keys()) e];
+	}
+
+	public function getContexts(p: Prefab) {
+		var ret : Array<Context> = [];
+		var ctx = contexts.get(p);
+		if(ctx != null)
+			ret.push(ctx);
+		var ctxs = references.get(p);
+		if(ctxs != null)
+			return ret.concat(ctxs);
+		return ret;
+	}
+
+	public function loadShader( path : String ) : ShaderDef {
+		#if editor
+		return hide.Ide.inst.shaderLoader.loadSharedShader(path);
+		#else
+		var r = shaderCache.get(path);
+		if(r != null)
+			return r;
+		var cl = Type.resolveClass(path.split("/").join("."));
+		var shader = new hxsl.SharedShader(Reflect.field(cl, "SRC"));
+		r = {
+			shader: shader,
+			inits: []
+		};
+		shaderCache.set(path, r);
+		return r;
+		#end
+	}
+
+	public function loadModel( path : String ) {
+		#if editor
+		return getScene().loadModel(path);
+		#else
+		return cache.loadModel(hxd.res.Loader.currentInstance.load(path).toModel());
+		#end
+	}
+
+	public function loadAnimation( path : String ) {
+		#if editor
+		return getScene().loadAnimation(path);
+		#else
+		return @:privateAccess cache.loadAnimation(hxd.res.Loader.currentInstance.load(path).toModel());
+		#end
+	}
+
+	public function loadTexture( path : String ) {
+		#if editor
+		return getScene().loadTexture("",path);
+		#else
+		return cache.loadTexture(null, path);
+		#end
+	}
+
+}

+ 58 - 0
hxd/prefab/Library.hx

@@ -0,0 +1,58 @@
+package hxd.prefab;
+
+class Library extends Prefab {
+
+	var inRec = false;
+
+	public function new() {
+		super(null);
+		type = "prefab";
+	}
+
+	// hacks to use directly non-recursive api
+
+	override function load( obj : Dynamic ) {
+		if( inRec )
+			return;
+		var children : Array<Dynamic> = obj.children;
+		if( children != null )
+			for( v in children )
+				Prefab.loadRec(v, this);
+	}
+
+	override function reload(v:Dynamic) {
+		inRec = true;
+		super.reload(v);
+		inRec = false;
+	}
+
+	override function save() {
+		if( inRec )
+			return {};
+		inRec = true;
+		var obj = saveRec();
+		inRec = false;
+		return obj;
+	}
+
+	override function makeInstance(ctx:Context):Context {
+		if( inRec )
+			return ctx;
+		inRec = true;
+		makeInstanceRec(ctx);
+		inRec = false;
+		return ctx;
+	}
+
+	static var registeredElements = new Map<String,Class<Prefab>>();
+
+	public static function getRegistered() {
+		return registeredElements;
+	}
+
+	public static function register( type : String, cl : Class<Prefab> ) {
+		registeredElements.set(type, cl);
+		return true;
+	}
+
+}

+ 241 - 0
hxd/prefab/Prefab.hx

@@ -0,0 +1,241 @@
+package hxd.prefab;
+
+@:keepSub
+class Prefab {
+
+	public var type(default, null) : String;
+	public var name(default, set) : String;
+	public var parent(default, set) : Prefab;
+	public var source(default, set) : String;
+	public var children(default, null) : Array<Prefab>;
+	public var enabled : Bool = true;
+	public var props : {};
+
+	public function new(?parent) {
+		this.parent = parent;
+		children = [];
+	}
+
+	function set_name(n) {
+		return name = n;
+	}
+
+	function set_source(f) {
+		return source = f;
+	}
+
+	function set_parent(p) {
+		if( parent != null )
+			parent.children.remove(this);
+		parent = p;
+		if( parent != null )
+			parent.children.push(this);
+		return p;
+	}
+
+	#if editor
+	public function edit( ctx : hide.prefab.EditContext ) {
+	}
+
+	public function getHideProps() : hide.prefab.HideProps {
+		return { icon : "question-circle", name : "Unknown" };
+	}
+	#end
+
+	public inline function iterator() : Iterator<Prefab> {
+		return children.iterator();
+	}
+
+	public function load( v : Dynamic ) {
+		throw "Not implemented";
+	}
+
+	public function save() : {} {
+		throw "Not implemented";
+		return null;
+	}
+
+	public function makeInstance( ctx : Context ) : Context {
+		return ctx;
+	}
+
+	public function updateInstance( ctx : Context, ?propName : String ) {
+	}
+
+	public function saveRec() : {} {
+		var obj : Dynamic = save();
+		obj.type = type;
+		if( !enabled )
+			obj.enabled = false;
+		if( name != null )
+			obj.name = name;
+		if( source != null )
+			obj.source = source;
+		if( children.length > 0 )
+			obj.children = [for( s in children ) s.saveRec()];
+		if( props != null )
+			obj.props = props;
+		return obj;
+	}
+
+	public function reload( p : Dynamic ) {
+		load(p);
+		var childData : Array<Dynamic> = p.children;
+		if( childData == null ) {
+			if( this.children.length > 0 ) this.children = [];
+			return;
+		}
+		var curChild = new Map();
+		for( c in children )
+			curChild.set(c.name, c);
+		var newchild = [];
+		for( v in childData ) {
+			var name : String = v.name;
+			var prev = curChild.get(name);
+			if( prev != null && prev.type == v.type ) {
+				curChild.remove(name);
+				prev.reload(v);
+				newchild.push(prev);
+			} else {
+				newchild.push(loadRec(v,this));
+			}
+		}
+		children = newchild;
+	}
+
+	public static function loadRec( v : Dynamic, ?parent : Prefab ) {
+		var pcl = @:privateAccess Library.registeredElements.get(v.type);
+		if( pcl == null ) pcl = hxd.prefab.Unknown;
+		var p = Type.createInstance(pcl, [parent]);
+		p.type = v.type;
+		p.name = v.name;
+		if(v.enabled != null)
+			p.enabled = v.enabled;
+		if(v.props != null)
+			p.props = Reflect.copy(v.props);  // TODO: Recursive?
+		if( v.source != null )
+			p.source = v.source;
+		p.load(v);
+		var children : Array<Dynamic> = v.children;
+		if( children != null )
+			for( v in children )
+				loadRec(v, p);
+		return p;
+	}
+
+	public function makeInstanceRec( ctx : Context ) {
+		if(!enabled)
+			return;
+		if( ctx == null ) {
+			ctx = new Context();
+			ctx.init();
+		}
+		ctx = makeInstance(ctx);
+		for( c in children )
+			c.makeInstanceRec(ctx);
+	}
+
+	#if castle
+	public function getCdbModel( ?p : Prefab ) : cdb.Sheet {
+		if( p == null )
+			p = this;
+		if( parent != null )
+			return parent.getCdbModel(p);
+		return null;
+	}
+	#end
+
+	public function getPrefabByName( name : String ) {
+		if( this.name == name )
+			return this;
+		for( c in children ) {
+			var p = c.getPrefabByName(name);
+			if( p != null )
+				return p;
+		}
+		return null;
+	}
+
+	public function getOpt<T:Prefab>( cl : Class<T>, ?name : String ) : T {
+		var parts = name == null ? null : name.split(".");
+		for( c in children ) {
+			if( (name == null || c.name == name) && Std.is(c, cl) )
+				return cast c;
+			if( parts != null && parts.length > 1 && c.name == parts[0] ) {
+				parts.shift();
+				return c.getOpt(cl, parts.join("."));
+			}
+			var p = c.getOpt(cl, name);
+			if( p != null )
+				return p;
+		}
+		return null;
+	}
+
+	public function get<T:Prefab>( cl : Class<T>, ?name : String ) : T {
+		var v = getOpt(cl, name);
+		if( v == null )
+			throw "Missing prefab " + (name == null ? Type.getClassName(cl) : (cl == null ? name : name+"(" + Type.getClassName(cl) + ")"));
+		return v;
+	}
+
+	public function getAll<T:Prefab>( cl : Class<T>, ?arr: Array<T> ) : Array<T> {
+		if(arr == null)
+			arr = [];
+		for(c in children) {
+			var i = Std.instance(c, cl);
+			if(i != null)
+				arr.push(i);
+			c.getAll(cl, arr);
+		}
+		return arr;
+	}
+
+	public function flatten<T:Prefab>( ?cl : Class<T>, ?arr: Array<T> ) : Array<T> {
+		if(arr == null)
+			arr = [];
+		if( cl == null )
+			arr.push(cast this);
+		else {
+			var i = Std.instance(this, cl);
+			if(i != null)
+				arr.push(i);
+		}
+		for(c in children)
+			c.flatten(cl, arr);
+		return arr;
+	}
+
+	public function getParent<T:Prefab>( c : Class<T> ) : Null<T> {
+		var p = parent;
+		while(p != null) {
+			var inst = Std.instance(p, c);
+			if(inst != null) return inst;
+			p = p.parent;
+		}
+		return null;
+	}
+
+	public function to<T:Prefab>( c : Class<T> ) : Null<T> {
+		return Std.instance(this, c);
+	}
+
+	public function getAbsPath() {
+		var p = this;
+		var path = [];
+		while(p.parent != null) {
+			path.unshift(p.name);
+			p = p.parent;
+		}
+		return path.join('.');
+	}
+
+	public function getDefaultName() : String {
+		if(source != null) {
+			var f = new haxe.io.Path(source).file;
+			f = f.split(" ")[0].split("-")[0];
+			return f;
+		}
+		return type;
+	}
+}

+ 22 - 0
hxd/prefab/Unknown.hx

@@ -0,0 +1,22 @@
+package hxd.prefab;
+
+class Unknown extends Prefab {
+
+	var data : Dynamic;
+
+	override function load(v:Dynamic) {
+		this.data = v;
+	}
+
+	override function save() {
+		return data;
+	}
+
+	#if editor
+	override function edit(ctx:hide.prefab.EditContext) {
+		ctx.properties.add(new hide.Element('<font color="red">Unknown prefab $type</font>'));
+	}
+	#end
+
+
+}