Browse Source

added prefab serialization macro, make sure super.load/save are called

Nicolas Cannasse 4 years ago
parent
commit
a5e299182a

+ 83 - 0
hrt/impl/Macros.hx

@@ -0,0 +1,83 @@
+package hrt.impl;
+import haxe.macro.Context;
+import haxe.macro.Expr;
+
+class Macros {
+
+	#if macro
+	public static function buildPrefab() {
+		var fields = Context.getBuildFields();
+		var toSerialize = [];
+		for( f in fields ) {
+			if( f.meta == null ) continue;
+			for( m in f.meta )
+				if( m.name == ":s" )
+					toSerialize.push(f);
+		}
+		if( toSerialize.length == 0 )
+			return null;
+		var ser = [], unser = [];
+		var pos = Context.currentPos();
+		for( f in toSerialize ) {
+			switch( f.kind ) {
+			case FProp(_, _, t, e), FVar(t,e):
+				var name = f.name;
+				var serCond = null;
+				if( e == null ) {
+					var setDef = true;
+					var c : Constant = switch( t ) {
+					case null: Context.error("Invalid var decl", f.pos);
+					case TPath({ pack : [], name : "Int"|"Float" }): CInt("0");
+					case TPath({ pack : [], name : "Bool" }): CIdent("false");
+					default: setDef = false; CIdent("null");
+					}
+					e = { expr : EConst(c), pos : f.pos };
+					if( setDef ) {
+						f.kind = switch( f.kind ) {
+						case FVar(t,_): FVar(t,e);
+						case FProp(get,set,t,_): FProp(get,set,t,e);
+						default: throw "assert";
+						}
+					}
+				} else {
+					var echeck = e;
+					if( e.expr.match(EArrayDecl([])) )
+						serCond = macro @:pos(f.pos) this.$name.length != 0;
+				}
+
+				if( serCond == null ) {
+					var defVal = e.expr.match(EConst(_)) ? e : macro null;
+					serCond = macro @:pos(pos) this.$name != $defVal;
+				}
+
+				ser.push(macro @:pos(pos) if( $serCond ) obj.$name = this.$name);
+				unser.push(macro @:pos(pos) this.$name = obj.$name == null ? $e : obj.$name);
+			default:
+				Context.error("Invalid serialization field", f.pos);
+			}
+		}
+		var isRoot = Context.getLocalClass().toString() == "hrt.prefab.Prefab";
+		if( !isRoot ) {
+			ser.unshift(macro @:pos(pos) super.saveSerializedFields(obj));
+			unser.unshift(macro @:pos(pos) super.loadSerializedFields(obj));
+		}
+		function makeFun(name,block) : Field {
+			return {
+				name : name,
+				kind : FFun({
+					ret : null,
+					expr : { expr : EBlock(block), pos : pos },
+					args : [{ name : "obj", type : macro : Dynamic }],
+				}),
+				meta : [{ name : ":noCompletion", pos : pos }],
+				access : isRoot ? [] : [AOverride],
+				pos : pos,
+			};
+		}
+		fields.push(makeFun("saveSerializedFields",ser));
+		fields.push(makeFun("loadSerializedFields",unser));
+		return fields;
+	}
+	#end
+
+}

+ 8 - 18
hrt/prefab/Curve.hx

@@ -30,12 +30,12 @@ typedef CurveKeys = Array<CurveKey>;
 
 
 class Curve extends Prefab {
 class Curve extends Prefab {
 
 
-	public var clampMin : Float = 0.;
-	public var clampMax : Float = 0.;
-	public var keyMode : CurveKeyMode = Linear;
+	@:s public var clampMin : Float = 0.;
+	@:s public var clampMax : Float = 0.;
+	@:s public var keyMode : CurveKeyMode = Linear;
 	public var keys : CurveKeys = [];
 	public var keys : CurveKeys = [];
 
 
-	public var loop : Bool = false;
+	@:s public var loop : Bool = false;
 
 
 	public var duration(get, never): Float;
 	public var duration(get, never): Float;
 	function get_duration() {
 	function get_duration() {
@@ -49,6 +49,7 @@ class Curve extends Prefab {
 	}
 	}
 
 
 	public override function load(o:Dynamic) {
 	public override function load(o:Dynamic) {
+		super.load(o);
 		keys = [];
 		keys = [];
 		if(o.keys != null) {
 		if(o.keys != null) {
 			for(k in (o.keys: Array<Dynamic>)) {
 			for(k in (o.keys: Array<Dynamic>)) {
@@ -63,13 +64,6 @@ class Curve extends Prefab {
 				keys.push(nk);
 				keys.push(nk);
 			}
 			}
 		}
 		}
-		clampMin = o.clampMin;
-		clampMax = o.clampMax;
-		if(o.loop != null)
-			loop = o.loop;
-		if(o.keyMode != null)
-			keyMode = o.keyMode;
-
 		if( keys.length == 0 ) {
 		if( keys.length == 0 ) {
 			addKey(0.0, 0.0);
 			addKey(0.0, 0.0);
 			addKey(1.0, 1.0);
 			addKey(1.0, 1.0);
@@ -77,6 +71,7 @@ class Curve extends Prefab {
 	}
 	}
 
 
 	public override function save() {
 	public override function save() {
+		var obj : Dynamic = super.save();
 		var keysDat = [];
 		var keysDat = [];
 		for(k in keys) {
 		for(k in keys) {
 			var o = {
 			var o = {
@@ -88,13 +83,8 @@ class Curve extends Prefab {
 			if(k.nextHandle != null) Reflect.setField(o, "nextHandle", { dv: k.nextHandle.dv, dt: k.nextHandle.dt });
 			if(k.nextHandle != null) Reflect.setField(o, "nextHandle", { dv: k.nextHandle.dv, dt: k.nextHandle.dt });
 			keysDat.push(o);
 			keysDat.push(o);
 		}
 		}
-		return {
-			clampMin: clampMin,
-			clampMax: clampMax,
-			keyMode: keyMode,
-			keys: keysDat,
-			loop: loop
-		};
+		obj.keys = keysDat;
+		return obj;
 	}
 	}
 
 
 	static inline function bezier(c0: Float, c1:Float, c2:Float, c3: Float, t:Float) {
 	static inline function bezier(c0: Float, c1:Float, c2:Float, c3: Float, t:Float) {

+ 0 - 7
hrt/prefab/Library.hx

@@ -7,13 +7,6 @@ class Library extends Prefab {
 		type = "prefab";
 		type = "prefab";
 	}
 	}
 
 
-	override function load( obj : Dynamic ) {
-	}
-
-	override function save() {
-		return {};
-	}
-
 	override function makeInstance(ctx:Context):Context {
 	override function makeInstance(ctx:Context):Context {
 		if( ctx.shared.parent != null ) ctx = ctx.clone(this);
 		if( ctx.shared.parent != null ) ctx = ctx.clone(this);
 		return super.makeInstance(ctx);
 		return super.makeInstance(ctx);

+ 19 - 41
hrt/prefab/Material.hx

@@ -6,12 +6,12 @@ import h3d.mat.PbrMaterial;
 
 
 class Material extends Prefab {
 class Material extends Prefab {
 
 
-	public var wrapRepeat = false;
-	public var diffuseMap : String;
-	public var normalMap : String;
-	public var specularMap : String;
+	@:s public var wrapRepeat = false;
+	@:s public var diffuseMap : String;
+	@:s public var normalMap : String;
+	@:s public var specularMap : String;
+	@:s public var materialName : String;
 	public var color : Array<Float> = [1,1,1,1];
 	public var color : Array<Float> = [1,1,1,1];
-	public var materialName : String;
 
 
 	public function new(?parent) {
 	public function new(?parent) {
 		super(parent);
 		super(parent);
@@ -19,36 +19,15 @@ class Material extends Prefab {
 		props = {};
 		props = {};
 	}
 	}
 
 
-	override function load(o:Dynamic) {
-		if(o.wrapRepeat) wrapRepeat = o.wrapRepeat;
-		if(o.diffuseMap != null) diffuseMap = o.diffuseMap;
-		if(o.normalMap != null) normalMap = o.normalMap;
-		if(o.specularMap != null) specularMap = o.specularMap;
-		if(o.color != null) color = o.color;
-		if(o.materialName != null) materialName = o.materialName;
-
-		// Backward compat
-		if(o.props != null && Reflect.hasField(o.props, "PBR")) {
-			var pbrProps = Reflect.field(o.props, "PBR");
-			for(pname in ["diffuseMap", "normalMap", "specularMap"]) {
-				var p : String = Reflect.field(pbrProps, pname);
-				if(p != null) {
-					Reflect.setField(this, pname, p);
-				}
-				Reflect.deleteField(pbrProps, pname);
-			}
-		}
+	override function load(obj:Dynamic) {
+		super.load(obj);
+		color = obj.color != null ? obj.color : [1,1,1,1];
 	}
 	}
 
 
 	override function save() {
 	override function save() {
-		var o : Dynamic = {};
-		if(wrapRepeat) o.wrapRepeat = true;
-		if(diffuseMap != null) o.diffuseMap = diffuseMap;
-		if(normalMap != null) o.normalMap = normalMap;
-		if(specularMap != null) o.specularMap = specularMap;
-		if(color != null && h3d.Vector.fromArray(color).toColor() != 0xffffffff) o.color = color;
-		if(materialName != null && materialName != "none" ) o.materialName = materialName;
-		return o;
+		var obj : Dynamic = super.save();
+		if(color != null && h3d.Vector.fromArray(color).toColor() != 0xffffffff) obj.color = color;
+		return obj;
 	}
 	}
 
 
 	function renderProps() {
 	function renderProps() {
@@ -69,7 +48,7 @@ class Material extends Prefab {
 	}
 	}
 
 
 	override function updateInstance( ctx : Context, ?propName ) {
 	override function updateInstance( ctx : Context, ?propName ) {
-		if( ctx.local3d == null) 
+		if( ctx.local3d == null )
 			return;
 			return;
 
 
 		function update(mat : h3d.mat.Material, props) {
 		function update(mat : h3d.mat.Material, props) {
@@ -154,7 +133,7 @@ class Material extends Prefab {
 					}));
 					}));
 				});
 				});
 			}
 			}
-		
+
 			setBit(colorMask, "colorMask", ".colorMaskR", 0);
 			setBit(colorMask, "colorMask", ".colorMaskR", 0);
 			setBit(colorMask, "colorMask", ".colorMaskG", 1);
 			setBit(colorMask, "colorMask", ".colorMaskG", 1);
 			setBit(colorMask, "colorMask", ".colorMaskB", 2);
 			setBit(colorMask, "colorMask", ".colorMaskB", 2);
@@ -222,7 +201,7 @@ class Material extends Prefab {
 						<input type="checkbox" class="read3"/>
 						<input type="checkbox" class="read3"/>
 						<input type="checkbox" class="read2"/>
 						<input type="checkbox" class="read2"/>
 						<input type="checkbox" class="read1"/>
 						<input type="checkbox" class="read1"/>
-						<input type="checkbox" class="read0"/>	
+						<input type="checkbox" class="read0"/>
 					</dd>
 					</dd>
 				<dt>Write Mask</dt>
 				<dt>Write Mask</dt>
 					<dd>
 					<dd>
@@ -244,15 +223,15 @@ class Material extends Prefab {
 						<input type="checkbox" class="value3"/>
 						<input type="checkbox" class="value3"/>
 						<input type="checkbox" class="value2"/>
 						<input type="checkbox" class="value2"/>
 						<input type="checkbox" class="value1"/>
 						<input type="checkbox" class="value1"/>
-						<input type="checkbox" class="value0"/>						
+						<input type="checkbox" class="value0"/>
 					</dd>';
 					</dd>';
 			var stencil = new hide.Element('
 			var stencil = new hide.Element('
 			<div class="group" name="Stencil">
 			<div class="group" name="Stencil">
-				<dt>Enable</dt><dd><input type="checkbox" field="enableStencil"/></dd>' 
-				+ (pbrProps.enableStencil ? stencilParams : "") +'		
+				<dt>Enable</dt><dd><input type="checkbox" field="enableStencil"/></dd>'
+				+ (pbrProps.enableStencil ? stencilParams : "") +'
 			</div>');
 			</div>');
 
 
-			ctx.properties.add(stencil, pbrProps, function(pname) { 
+			ctx.properties.add(stencil, pbrProps, function(pname) {
 				ctx.onChange(this, "props");
 				ctx.onChange(this, "props");
 				if( pname == "enableStencil" )
 				if( pname == "enableStencil" )
 					ctx.rebuildProperties();
 					ctx.rebuildProperties();
@@ -262,7 +241,7 @@ class Material extends Prefab {
 				setBit(stencil, "stencilWriteMask", ".write"+i, i);
 				setBit(stencil, "stencilWriteMask", ".write"+i, i);
 				setBit(stencil, "stencilReadMask", ".read"+i, i);
 				setBit(stencil, "stencilReadMask", ".read"+i, i);
 				setBit(stencil, "stencilValue", ".value"+i, i);
 				setBit(stencil, "stencilValue", ".value"+i, i);
-			}	
+			}
 		}
 		}
 
 
 		var dropDownMaterials = new hide.Element('
 		var dropDownMaterials = new hide.Element('
@@ -276,7 +255,6 @@ class Material extends Prefab {
 				new hide.Element('<option>').attr("value", m.name).text(m.name).appendTo(select);
 				new hide.Element('<option>').attr("value", m.name).text(m.name).appendTo(select);
 
 
 		select.change(function(_) {
 		select.change(function(_) {
-			trace(select.val());
 			var previous = materialName;
 			var previous = materialName;
 			materialName = select.val();
 			materialName = select.val();
 			var actual = materialName;
 			var actual = materialName;

+ 10 - 25
hrt/prefab/Object2D.hx

@@ -4,13 +4,13 @@ using Lambda;
 
 
 class Object2D extends Prefab {
 class Object2D extends Prefab {
 
 
-	public var x : Float = 0.;
-	public var y : Float = 0.;
-	public var scaleX : Float = 1.;
-	public var scaleY : Float = 1.;
-	public var rotation : Float = 0.;
+	@:s public var x : Float = 0.;
+	@:s public var y : Float = 0.;
+	@:s public var scaleX : Float = 1.;
+	@:s public var scaleY : Float = 1.;
+	@:s public var rotation : Float = 0.;
 
 
-	public var visible : Bool = true;
+	@:s public var visible : Bool = true;
 	public var blendMode : h2d.BlendMode = None;
 	public var blendMode : h2d.BlendMode = None;
 
 
 	public function loadTransform(t) {
 	public function loadTransform(t) {
@@ -34,17 +34,8 @@ class Object2D extends Prefab {
 	}
 	}
 
 
 	override function load( obj : Dynamic ) {
 	override function load( obj : Dynamic ) {
-		x = obj.x == null ? 0. : obj.x;
-		y = obj.y == null ? 0. : obj.y;
-
-		scaleX = obj.scaleX == null ? 1. : obj.scaleX;
-		scaleY = obj.scaleY == null ? 1. : obj.scaleY;
-
-		rotation = obj.rotation == null ? 0. : obj.rotation;
-
-		visible = obj.visible == null ? true : obj.visible;
-
-		if (obj.blendMode != null)
+		super.load(obj);
+		if( obj.blendMode != null )
 			blendMode = std.Type.createEnum(h2d.BlendMode, obj.blendMode);
 			blendMode = std.Type.createEnum(h2d.BlendMode, obj.blendMode);
 	}
 	}
 
 
@@ -57,14 +48,8 @@ class Object2D extends Prefab {
 	}
 	}
 
 
 	override function save() {
 	override function save() {
-		var o : Dynamic = {};
-		if( x != 0 ) o.x = x;
-		if( y != 0 ) o.y = y;
-		if( scaleX != 1 ) o.scaleX = scaleX;
-		if( scaleY != 1 ) o.scaleY = scaleY;
-		if( rotation != 0 ) o.rotation = rotation;
-		if( !visible ) o.visible = visible;
-		if ( blendMode != None) o.blendMode = blendMode.getName();
+		var o : Dynamic = super.save();
+		if( blendMode != None ) o.blendMode = blendMode.getName();
 		return o;
 		return o;
 	}
 	}
 
 

+ 10 - 42
hrt/prefab/Object3D.hx

@@ -4,16 +4,16 @@ using Lambda;
 
 
 class Object3D extends Prefab {
 class Object3D extends Prefab {
 
 
-	public var x : Float = 0.;
-	public var y : Float = 0.;
-	public var z : Float = 0.;
-	public var scaleX : Float = 1.;
-	public var scaleY : Float = 1.;
-	public var scaleZ : Float = 1.;
-	public var rotationX : Float = 0.;
-	public var rotationY : Float = 0.;
-	public var rotationZ : Float = 0.;
-	public var visible : Bool = true;
+	@:s public var x : Float = 0.;
+	@:s public var y : Float = 0.;
+	@:s public var z : Float = 0.;
+	@:s public var scaleX : Float = 1.;
+	@:s public var scaleY : Float = 1.;
+	@:s public var scaleZ : Float = 1.;
+	@:s public var rotationX : Float = 0.;
+	@:s public var rotationY : Float = 0.;
+	@:s public var rotationZ : Float = 0.;
+	@:s public var visible : Bool = true;
 
 
 	public function new(?parent) {
 	public function new(?parent) {
 		super(parent);
 		super(parent);
@@ -40,23 +40,6 @@ class Object3D extends Prefab {
 		return -1;
 		return -1;
 	}
 	}
 
 
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		x = obj.x == null ? 0. : obj.x;
-		y = obj.y == null ? 0. : obj.y;
-		z = obj.z == null ? 0. : obj.z;
-
-		scaleX = obj.scaleX == null ? 1. : obj.scaleX;
-		scaleY = obj.scaleY == null ? 1. : obj.scaleY;
-		scaleZ = obj.scaleZ == null ? 1. : obj.scaleZ;
-
-		rotationX = obj.rotationX == null ? 0. : obj.rotationX;
-		rotationY = obj.rotationY == null ? 0. : obj.rotationY;
-		rotationZ = obj.rotationZ == null ? 0. : obj.rotationZ;
-
-		visible = obj.visible == null ? true : obj.visible;
-	}
-
 	function createObject(ctx:Context) {
 	function createObject(ctx:Context) {
 		return new h3d.scene.Object(ctx.local3d);
 		return new h3d.scene.Object(ctx.local3d);
 	}
 	}
@@ -69,21 +52,6 @@ class Object3D extends Prefab {
 		return ctx;
 		return ctx;
 	}
 	}
 
 
-	override function save() {
-		var o : Dynamic = super.save();
-		if( x != 0 ) o.x = x;
-		if( y != 0 ) o.y = y;
-		if( z != 0 ) o.z = z;
-		if( scaleX != 1 ) o.scaleX = scaleX;
-		if( scaleY != 1 ) o.scaleY = scaleY;
-		if( scaleZ != 1 ) o.scaleZ = scaleZ;
-		if( rotationX != 0 ) o.rotationX = rotationX;
-		if( rotationY != 0 ) o.rotationY = rotationY;
-		if( rotationZ != 0 ) o.rotationZ = rotationZ;
-		if( !visible ) o.visible = visible;
-		return o;
-	}
-
 	public function setTransform(mat : h3d.Matrix) {
 	public function setTransform(mat : h3d.Matrix) {
 		var rot = mat.getEulerAngles();
 		var rot = mat.getEulerAngles();
 		x = mat.tx;
 		x = mat.tx;

+ 26 - 50
hrt/prefab/Prefab.hx

@@ -3,18 +3,18 @@ package hrt.prefab;
 /**
 /**
 	Prefab is an data-oriented tree container capable of creating instances of Heaps objects.
 	Prefab is an data-oriented tree container capable of creating instances of Heaps objects.
 **/
 **/
-@:keepSub
+@:keepSub @:build(hrt.impl.Macros.buildPrefab()) @:autoBuild(hrt.impl.Macros.buildPrefab())
 class Prefab {
 class Prefab {
 
 
 	/**
 	/**
 		The type of prefab, allows to identify which class it should be loaded with.
 		The type of prefab, allows to identify which class it should be loaded with.
 	**/
 	**/
-	public var type(default, null) : String;
+	@:s public var type(default, null) : String;
 
 
 	/**
 	/**
 		The name of the prefab in the tree view
 		The name of the prefab in the tree view
 	**/
 	**/
-	public var name(default, set) : String;
+	@:s public var name : String;
 
 
 	/**
 	/**
 		The parent of the prefab in the tree view
 		The parent of the prefab in the tree view
@@ -24,7 +24,7 @@ class Prefab {
 	/**
 	/**
 		The associated source file (an image, a 3D model, etc.) if the prefab type needs it.
 		The associated source file (an image, a 3D model, etc.) if the prefab type needs it.
 	**/
 	**/
-	public var source(default, set) : String;
+	@:s public var source : String;
 
 
 	/**
 	/**
 		The list of children prefab in the tree view
 		The list of children prefab in the tree view
@@ -34,17 +34,17 @@ class Prefab {
 	/**
 	/**
 		Tells if the prefab will create an instance when calling make() or be ignored. Also apply to this prefab children.
 		Tells if the prefab will create an instance when calling make() or be ignored. Also apply to this prefab children.
 	**/
 	**/
-	public var enabled : Bool = true;
+	@:s public var enabled : Bool = true;
 
 
 	/**
 	/**
 		Prevent the prefab from being selected in Hide. Also apply to this prefab children.
 		Prevent the prefab from being selected in Hide. Also apply to this prefab children.
 	**/
 	**/
-	public var locked : Bool;
+	@:s public var locked : Bool = false;
 
 
 	/**
 	/**
 		A storage for some extra properties
 		A storage for some extra properties
 	**/
 	**/
-	public var props : Any;
+	@:s public var props : Any;
 
 
 	/**
 	/**
 		Creates a new prefab with the given parent.
 		Creates a new prefab with the given parent.
@@ -54,14 +54,6 @@ class Prefab {
 		children = [];
 		children = [];
 	}
 	}
 
 
-	function set_name(n) {
-		return name = n;
-	}
-
-	function set_source(f) {
-		return source = f;
-	}
-
 	function set_parent(p) {
 	function set_parent(p) {
 		if( parent != null )
 		if( parent != null )
 			parent.children.remove(this);
 			parent.children.remove(this);
@@ -114,14 +106,16 @@ class Prefab {
 		Override to implement your custom prefab data loading
 		Override to implement your custom prefab data loading
 	**/
 	**/
 	function load( v : Dynamic ) {
 	function load( v : Dynamic ) {
-
+		loadSerializedFields(v);
 	}
 	}
 
 
 	/**
 	/**
 		Override to implement your custom prefab data saving
 		Override to implement your custom prefab data saving
 	**/
 	**/
 	function save() : {} {
 	function save() : {} {
-		return {};
+		var o = {};
+		saveSerializedFields(o);
+		return o;
 	}
 	}
 
 
 	/**
 	/**
@@ -152,19 +146,8 @@ class Prefab {
 	**/
 	**/
 	@:final public function saveData() : {} {
 	@:final public function saveData() : {} {
 		var obj : Dynamic = save();
 		var obj : Dynamic = save();
-		obj.type = type;
-		if( !enabled )
-			obj.enabled = false;
-		if( locked )
-			obj.locked = true;
-		if( name != null )
-			obj.name = name;
-		if( source != null )
-			obj.source = source;
 		if( children.length > 0 )
 		if( children.length > 0 )
 			obj.children = [for( s in children ) s.saveData()];
 			obj.children = [for( s in children ) s.saveData()];
-		if( props != null && obj.props == null )
-			obj.props = props;
 		return obj;
 		return obj;
 	}
 	}
 
 
@@ -172,12 +155,6 @@ class Prefab {
 		Load the whole prefab data and creates its children.
 		Load the whole prefab data and creates its children.
 	**/
 	**/
 	@:final public function loadData( v : Dynamic ) {
 	@:final public function loadData( v : Dynamic ) {
-		type = v.type;
-		name = v.name;
-		enabled = v.enabled == null ? true : v.enabled;
-		locked = v.locked == null ? false : v.locked;
-		props = v.props;
-		source = v.source;
 		load(v);
 		load(v);
 		if( children.length > 0 )
 		if( children.length > 0 )
 			children = [];
 			children = [];
@@ -191,26 +168,25 @@ class Prefab {
 		Updates in-place the whole prefab data and its children.
 		Updates in-place the whole prefab data and its children.
 	**/
 	**/
 	public function reload( p : Dynamic ) {
 	public function reload( p : Dynamic ) {
-		name = p.name;
-		enabled = p.enabled == null ? true : p.enabled;
-		locked = p.locked == null ? false : p.locked;
-		if( p.props == null || props == null )
-			props = p.props;
-		else {
-			var old = Reflect.fields(props);
-			for( k in Reflect.fields(p.props) ) {
-				if( haxe.Json.stringify(Reflect.field(props,k)) == haxe.Json.stringify(Reflect.field(p.props,k)) ) {
+		var prevProps = props;
+		load(p);
+
+		if( props != null && prevProps != null ) {
+			// update prev props object instead of rebinding it : allow to propagate cdb changes
+			var old = Reflect.fields(prevProps);
+			for( k in Reflect.fields(props) ) {
+				if( haxe.Json.stringify(Reflect.field(props,k)) == haxe.Json.stringify(Reflect.field(prevProps,k)) ) {
 					old.remove(k);
 					old.remove(k);
 					continue;
 					continue;
 				}
 				}
-				Reflect.setField(props, k, Reflect.field(p.props,k));
+				Reflect.setField(prevProps, k, Reflect.field(props,k));
 				old.remove(k);
 				old.remove(k);
 			}
 			}
 			for( k in old )
 			for( k in old )
-				Reflect.deleteField(props, k);
+				Reflect.deleteField(prevProps, k);
+			props = prevProps;
 		}
 		}
-		source = p.source;
-		load(p);
+
 		var childData : Array<Dynamic> = p.children;
 		var childData : Array<Dynamic> = p.children;
 		if( childData == null ) {
 		if( childData == null ) {
 			if( this.children.length > 0 ) this.children = [];
 			if( this.children.length > 0 ) this.children = [];
@@ -463,10 +439,10 @@ class Prefab {
 	}
 	}
 
 
 	/**
 	/**
-		Clone this prefab and all its children
+		Clone this prefab, and all its children if recursive=true
 	**/
 	**/
-	public function clone() : Prefab {
-		var obj = saveData();
+	public function clone( recursive = true ) : Prefab {
+		var obj = recursive ? saveData() : save();
 		return loadPrefab(haxe.Json.parse(haxe.Json.stringify(obj)));
 		return loadPrefab(haxe.Json.parse(haxe.Json.stringify(obj)));
 	}
 	}
 }
 }

+ 1 - 9
hrt/prefab/RenderProps.hx

@@ -6,7 +6,7 @@ class RenderPropsObject extends h3d.scene.Object {
 
 
 class RenderProps extends Prefab {
 class RenderProps extends Prefab {
 
 
-	var isDefault = false;
+	@:s var isDefault = false;
 
 
 	public function new(?parent) {
 	public function new(?parent) {
 		super(parent);
 		super(parent);
@@ -14,14 +14,6 @@ class RenderProps extends Prefab {
 		props = {};
 		props = {};
 	}
 	}
 
 
-	override function load(o:Dynamic) {
-		isDefault = o.isDefault;
-	}
-
-	override function save() {
-		return { isDefault : isDefault };
-	}
-
 	override function makeInstance(ctx:Context):Context {
 	override function makeInstance(ctx:Context):Context {
 		ctx = ctx.clone(this);
 		ctx = ctx.clone(this);
 		ctx.local3d = new RenderPropsObject(ctx.local3d);
 		ctx.local3d = new RenderPropsObject(ctx.local3d);

+ 1 - 6
hrt/prefab/Shader.hx

@@ -10,14 +10,9 @@ class Shader extends Prefab {
 		props = {};
 		props = {};
 	}
 	}
 
 
-	override function load(o:Dynamic) {
-
-	}
-
 	override function save() {
 	override function save() {
 		fixSourcePath();
 		fixSourcePath();
-		return {
-		};
+		return super.save();
 	}
 	}
 
 
 	override function updateInstance(ctx: Context, ?propName) {
 	override function updateInstance(ctx: Context, ?propName) {

+ 1 - 11
hrt/prefab/fx/Event.hx

@@ -7,23 +7,13 @@ typedef EventInstance = {
 };
 };
 
 
 class Event extends hrt.prefab.Prefab {
 class Event extends hrt.prefab.Prefab {
-	public var time: Float = 0.0;
+	@:s public var time: Float = 0.0;
 
 
 	public function new(?parent) {
 	public function new(?parent) {
 		super(parent);
 		super(parent);
 		this.type = "event";
 		this.type = "event";
 	}
 	}
 
 
-	override function save() : {} {
-		return {
-			time: time
-		};
-	}
-
-	override function load(obj: Dynamic) {
-		this.time = obj.time;
-	}
-
 	public function prepare(ctx: Context) : EventInstance {
 	public function prepare(ctx: Context) : EventInstance {
 		return {
 		return {
 			evt: this
 			evt: this

+ 6 - 26
hrt/prefab/l2d/Blur.hx

@@ -2,37 +2,17 @@ package hrt.prefab.l2d;
 
 
 class Blur extends Prefab {
 class Blur extends Prefab {
 
 
-	public var radius : Float = 1.;
-	public var quality : Float = 1;
-	public var gain : Float = 1.;
-	public var linear : Float = 0.;
+	@:s public var radius : Float = 1.;
+	@:s public var quality : Float = 1;
+	@:s public var gain : Float = 1.;
+	@:s public var linear : Float = 0.;
 
 
 	// mostly testing
 	// mostly testing
-	public var image : String;
-	public var zoom : Int = 1;
+	@:s public var image : String;
+	@:s public var zoom : Int = 1;
 
 
 	var pass : h3d.pass.Blur;
 	var pass : h3d.pass.Blur;
 
 
-	override function load(o:Dynamic) {
-		radius = o.radius;
-		quality = o.quality;
-		gain = o.gain;
-		linear = o.linear;
-		image = o.image;
-		zoom = o.zoom;
-	}
-
-	override function save() {
-		return {
-			radius:radius,
-			quality:quality,
-			gain:gain,
-			linear:linear,
-			image : image,
-			zoom : zoom,
-		};
-	}
-
 	public function makeFilter() {
 	public function makeFilter() {
 		var f = new h2d.filter.Blur(radius, gain, quality);
 		var f = new h2d.filter.Blur(radius, gain, quality);
 		f.linear = linear;
 		f.linear = linear;

+ 20 - 75
hrt/prefab/l2d/NoiseGenerator.hx

@@ -14,84 +14,29 @@ enum abstract RepeatMode(String) {
 
 
 class NoiseGenerator extends Prefab {
 class NoiseGenerator extends Prefab {
 
 
-	public var seed : Int = Std.random(100);
-
-	public var mode : NoiseMode = Perlin;
-
-	public var scale : Float = 1.;
-	public var channels : Int = 1;
-	public var normals : Bool = false;
-	public var contrast : Float = 0.;
-	public var brightness : Float = 0.;
-	public var repeat : RepeatMode = Both;
-
-	public var size : Int = 512;
-	public var octaves : Int = 1;
-	public var persist : Float = 0.5;
-	public var lacunarity : Float = 2.;
-	public var gain : Float = 2.0;
-	public var offset : Float = 0.5;
-	public var turbulence : Float = 0.;
-	public var turbulenceScale : Float = 1.;
-	public var inverse : Bool;
+	@:s public var seed : Int = Std.random(100);
+
+	@:s public var mode : NoiseMode = Perlin;
+
+	@:s public var scale : Float = 1.;
+	@:s public var channels : Int = 1;
+	@:s public var normals : Bool = false;
+	@:s public var contrast : Float = 0.;
+	@:s public var brightness : Float = 0.;
+	@:s public var repeat : RepeatMode = Both;
+
+	@:s public var size : Int = 512;
+	@:s public var octaves : Int = 1;
+	@:s public var persist : Float = 0.5;
+	@:s public var lacunarity : Float = 2.;
+	@:s public var gain : Float = 2.0;
+	@:s public var offset : Float = 0.5;
+	@:s public var turbulence : Float = 0.;
+	@:s public var turbulenceScale : Float = 1.;
+	@:s public var inverse : Bool;
 
 
 	var tex : h3d.mat.Texture;
 	var tex : h3d.mat.Texture;
 
 
-	override public function load(v:Dynamic) {
-		this.mode = v.mode;
-		this.seed = v.seed;
-		this.size = v.size;
-		this.scale = v.scale;
-		if( v.channels != null ) this.channels = v.channels else this.channels = 1;
-		this.octaves = v.octaves;
-		this.persist = v.persist;
-		this.lacunarity = v.lacunarity;
-		if( v.gain != null ) this.gain = v.gain;
-		if( v.offset != null ) this.offset = v.offset;
-		if( v.contrast != null ) this.contrast = v.contrast else this.contrast = 0;
-		if( v.brightness != null ) this.brightness = v.brightness else this.brightness = 0;
-		if( v.normals != null ) this.normals = v.normals else this.normals = false;
-		if( v.turbulence != null ) this.turbulence = v.turbulence else this.turbulence = 0;
-		if( v.turbulenceScale != null ) this.turbulenceScale = v.turbulenceScale;
-		if( v.inverse != null ) this.inverse = v.inverse else this.inverse = false;
-		if( v.repeat != null ) this.repeat = v.repeat else this.repeat = Both;
-	}
-
-	override function save() {
-		var o : Dynamic = {
-			seed : seed,
-			size : size,
-			scale : scale,
-			octaves : octaves,
-			persist : persist,
-			lacunarity : lacunarity,
-		};
-		if( channels != 1 )
-			o.channels = channels;
-		o.mode = mode;
-		switch( mode ) {
-		case Perlin:
-		case Ridged:
-			o.gain = gain;
-			o.offset = offset;
-		}
-		if( contrast != 0 )
-			o.contrast = contrast;
-		if( brightness != 0 )
-			o.brightness = brightness;
-		if( normals )
-			o.normals = normals;
-		if( turbulence != 0 ) {
-			o.turbulence = turbulence;
-			o.turbulenceScale = turbulenceScale;
-		}
-		if( repeat != Both )
-			o.repeat = repeat;
-		if( inverse )
-			o.inverse = inverse;
-		return o;
-	}
-
 	public function updateTexture( t : h3d.mat.Texture ) {
 	public function updateTexture( t : h3d.mat.Texture ) {
 		var e = h3d.Engine.getCurrent();
 		var e = h3d.Engine.getCurrent();
 		e.pushTarget(t);
 		e.pushTarget(t);

+ 3 - 13
hrt/prefab/l3d/Constraint.hx

@@ -2,19 +2,9 @@ package hrt.prefab.l3d;
 
 
 class Constraint extends Prefab {
 class Constraint extends Prefab {
 
 
-	public var object(default,null) : String;
-	public var target(default,null) : String;
-	public var positionOnly(default,null) : Bool;
-
-	override public function load(v:Dynamic) {
-		object = v.object;
-		target = v.target;
-		positionOnly = v.positionOnly;
-	}
-
-	override function save() {
-		return { object : object, target : target, positionOnly : positionOnly };
-	}
+	@:s public var object(default,null) : String;
+	@:s public var target(default,null) : String;
+	@:s public var positionOnly(default,null) : Bool;
 
 
 	public function apply( root : h3d.scene.Object ) {
 	public function apply( root : h3d.scene.Object ) {
 		var srcObj = root.getObjectByName(object.split(".").pop());
 		var srcObj = root.getObjectByName(object.split(".").pop());

+ 1 - 11
hrt/prefab/rfx/RendererFX.hx

@@ -2,7 +2,7 @@ package hrt.prefab.rfx;
 
 
 class RendererFX extends Prefab implements h3d.impl.RendererFX {
 class RendererFX extends Prefab implements h3d.impl.RendererFX {
 
 
-	var enableInEditor = true;
+	@:s var enableInEditor = true;
 
 
 	public function begin( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {
 	public function begin( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {
 	}
 	}
@@ -10,16 +10,6 @@ class RendererFX extends Prefab implements h3d.impl.RendererFX {
 	public function end( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {
 	public function end( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {
 	}
 	}
 
 
-	override function save() {
-		var obj : Dynamic = {};
-		if( !enableInEditor ) obj.enableInEditor = false;
-		return obj;
-	}
-
-	override function load(v:Dynamic) {
-		enableInEditor = v.enableInEditor != false;
-	}
-
 	public function dispose() {
 	public function dispose() {
 	}
 	}