Browse Source

removed MaterialProps, added MaterialSetup and MaterialScript

Nicolas Cannasse 8 years ago
parent
commit
f6b133b19f

+ 0 - 8
h3d/mat/BaseMaterial.hx

@@ -8,19 +8,11 @@ class BaseMaterial implements h3d.impl.Serializable {
 	@:s public var name : String;
 	public var mainPass(get, never) : Pass;
 
-	public var props(default,set) : MaterialProps;
-
 	public function new(?shader:hxsl.Shader) {
 		if( shader != null )
 			addPass(new Pass("default",null)).addShader(shader);
 	}
 
-	function set_props(p) {
-		this.props = p;
-		if( p != null ) p.apply(this);
-		return p;
-	}
-
 	public function addPass<T:Pass>( p : T ) : T {
 		var prev = null, cur = passes;
 		while( cur != null ) {

+ 0 - 77
h3d/mat/DefaultMaterialProps.hx

@@ -1,77 +0,0 @@
-package h3d.mat;
-
-enum MaterialKind {
-	Opaque;
-	Alpha;
-	AlphaKill;
-	Add;
-	SoftAdd;
-}
-
-@:structInit
-class DefaultMaterialProps {
-
-	public var kind(default,null) : MaterialKind;
-	public var cull(default, null) : Bool;
-
-	public function new( ?kind : MaterialKind, ?cull : Bool ) {
-		this.kind = kind == null ? Opaque : kind;
-		this.cull = cull == null ? true : cull;
-	}
-
-	public function apply( m : BaseMaterial ) {
-		var mainPass = m.mainPass;
-		switch( kind ) {
-		case Opaque, AlphaKill:
-			mainPass.setBlendMode(None);
-			mainPass.depthWrite = true;
-			mainPass.setPassName("default");
-		case Alpha:
-			mainPass.setBlendMode(Alpha);
-			mainPass.depthWrite = true;
-			mainPass.setPassName("alpha");
-		case Add:
-			mainPass.setBlendMode(Add);
-			mainPass.depthWrite = false;
-			mainPass.setPassName("additive");
-		case SoftAdd:
-			mainPass.setBlendMode(SoftAdd);
-			mainPass.depthWrite = false;
-			mainPass.setPassName("additive");
-		}
-		var tshader = mainPass.getShader(h3d.shader.Texture);
-		if( tshader != null ) {
-			tshader.killAlpha = kind == AlphaKill;
-			tshader.killAlphaThreshold = 0.5;
-		}
-		mainPass.culling = cull ? Back : None;
-	}
-
-	public function inspect( onChange : Void -> Void ) : Array<hxd.inspect.Property> {
-		return [
-			PEnum("kind", MaterialKind, function() return kind, function(v) { kind = v; onChange(); }),
-			PBool("cull", function() return cull, function(v) { cull = v; onChange(); }),
-		];
-	}
-
-	public function getData() : Dynamic {
-		return { kind : kind.getName(), cull : cull };
-	}
-
-	public function loadData( o : Dynamic ) {
-		kind = MaterialKind.createByName(o.kind);
-		cull = o.cull;
-	}
-
-	public static function particlesDefault() : MaterialProps {
-	#if (haxe_ver < 3.3)
-		var m = new DefaultMaterialProps();
-		m.kind = Alpha;
-		m.cull = false;
-		return m;
-	#else
-		return { kind : Alpha, cull : false }
-	#end
-	}
-
-}

+ 19 - 0
h3d/mat/Material.hx

@@ -4,6 +4,8 @@ class Material extends BaseMaterial {
 
 	var mshader : h3d.shader.BaseMesh;
 
+	public var props(default,set) : Any;
+
 	public var shadows(get, set) : Bool;
 	public var castShadows(default, set) : Bool;
 	public var receiveShadows(default, set) : Bool;
@@ -166,13 +168,30 @@ class Material extends BaseMaterial {
 		return t;
 	}
 
+	function set_props(p) {
+		this.props = p;
+		refreshProps();
+		return p;
+	}
+
+	public function refreshProps() {
+		if( props != null ) MaterialSetup.current.applyProps(this);
+	}
+
 	#if hxbit
+
+	static function tempDisable( m : Material ) {
+	}
+
 	function customSerialize( ctx : hxbit.Serializer ) {
+		ctx.addDynamic(props);
 	}
+
 	function customUnserialize( ctx : hxbit.Serializer ) {
 		var last = mainPass.shaders;
 		while( last.next != null ) last = last.next;
 		mshader = cast last.s;
+		props = ctx.getDynamic();
 	}
 	#end
 

+ 0 - 22
h3d/mat/MaterialProps.hx

@@ -1,22 +0,0 @@
-package h3d.mat;
-
-#if !macro
-
-typedef MaterialProps = haxe.macro.MacroType<[h3d.mat.MaterialProps.Macros.getDefinition()]>;
-
-#else
-
-class Macros {
-	public static function getDefinition() {
-		// using getType() will create haxe assert
-		try {
-			if( haxe.macro.Context.resolvePath("MaterialProps.hx").indexOf("h3d.mat") < 0 )
-				return macro : std.MaterialProps;
-		} catch( e : Dynamic ) {
-		}
-		return macro : DefaultMaterialProps;
-	}
-}
-
-#end
-

+ 52 - 0
h3d/mat/MaterialScript.hx

@@ -0,0 +1,52 @@
+package h3d.mat;
+
+class MaterialScript extends MaterialSetup {
+
+	var fileName : String;
+	var variables : Map<String,Dynamic>;
+
+	public function new() {
+		super("Script");
+	}
+
+	public dynamic function onError( msg : String ) {
+		throw msg;
+	}
+
+	function getVar( name : String ) {
+		var v = variables.get(name);
+		if( v == null ) onError(fileName + " does not define " + name);
+		return v;
+	}
+
+	#if hscript
+	override function getDefaults(?type:String):Any {
+		return try getVar("getDefaults")(type) catch( e : hscript.Expr.Error ) { onError(Std.string(e)); {}; }
+	}
+
+	#if js
+	override function editMaterial( props : Any ) {
+		return try getVar("editMaterial")(props) catch( e : hscript.Expr.Error) { onError(Std.string(e)); new js.jquery.JQuery(); }
+	}
+	#end
+	#end
+
+	public function load( script : String, ?fileName : String ) {
+		#if !hscript
+		onError("-lib hscript is required to load script");
+		#else
+		if( fileName == null ) fileName = "Renderer.hx";
+		this.fileName = fileName;
+		var parser = new hscript.Parser();
+		var expr = try parser.parseString(script, fileName) catch( e : hscript.Expr.Error ) { onError(Std.string(e)); return; }
+		var interp = new hscript.Interp();
+		#if js
+		interp.variables.set("Element", js.jquery.JQuery);
+		#end
+		try interp.execute(expr) catch( e : hscript.Expr.Error ) { onError(Std.string(e)); return; }
+		variables = interp.variables;
+		#end
+		name = getVar("name");
+	}
+
+}

+ 116 - 0
h3d/mat/MaterialSetup.hx

@@ -0,0 +1,116 @@
+package h3d.mat;
+
+@:enum private abstract DefaultKind(String) {
+	var Opaque = "Opaque";
+	var Alpha = "Alpha";
+	var AlphaKill = "AlphaKill";
+	var Add = "Add";
+	var SoftAdd = "SoftAdd";
+}
+
+private typedef DefaultProps = {
+	var kind : DefaultKind;
+	var shadows : Bool;
+	var culled : Bool;
+	var lighted : Bool;
+}
+
+class MaterialSetup {
+
+	public var name(default,null) : String;
+
+	public function new(name) {
+		this.name = name;
+	}
+
+	public function createRenderer() {
+		return new h3d.scene.Renderer();
+	}
+
+	public function createLightSystem() {
+		return new h3d.pass.LightSystem();
+	}
+
+	public function initModelMaterial( model : hxd.res.Model, material : Material ) {
+		material.mainPass.enableLights = true;
+		material.shadows = true;
+	}
+
+	public function getDefaults( ?type : String ) : Any {
+		var props : DefaultProps;
+		switch( type ) {
+		case "particles3D":
+			props = {
+				kind : Opaque,
+				shadows : false,
+				culled : false,
+				lighted : true,
+			};
+		default:
+			props = {
+				kind : Opaque,
+				shadows : true,
+				culled : true,
+				lighted : true,
+			};
+		}
+		return props;
+	}
+
+	#if js
+	public function editMaterial( props : Any ) {
+		return new js.jquery.JQuery('
+			<dl>
+				<dt>Kind</dt>
+				<dd>
+					<select field="kind">
+						<option value="Opaque">Opaque</option>
+						<option value="Alpha">Alpha</option>
+						<option value="AlphaKill">AlphaKill</option>
+						<option value="Add">Add</option>
+						<option value="SoftAdd">SoftAdd</option>
+					</select>
+				</dd>
+				<dt>Shadows</dt><dd><input type="checkbox" field="shadows"/></dd>
+				<dt>Culled</dt><dd><input type="checkbox" field="culled"/></dd>
+				<dt>Lighted</dt><dd><input type="checkbox" field="lighted"/></dd>
+			</dl>
+		');
+	}
+	#end
+
+	public function applyProps( m : Material ) {
+		var props : DefaultProps = m.props;
+		var mainPass = m.mainPass;
+		switch( props.kind ) {
+		case Opaque, AlphaKill:
+			mainPass.setBlendMode(None);
+			mainPass.depthWrite = true;
+			mainPass.setPassName("default");
+		case Alpha:
+			mainPass.setBlendMode(Alpha);
+			mainPass.depthWrite = true;
+			mainPass.setPassName("alpha");
+		case Add:
+			mainPass.setBlendMode(Add);
+			mainPass.depthWrite = false;
+			mainPass.setPassName("additive");
+		case SoftAdd:
+			mainPass.setBlendMode(SoftAdd);
+			mainPass.depthWrite = false;
+			mainPass.setPassName("additive");
+		}
+		var tshader = m.textureShader;
+		if( tshader != null ) {
+			tshader.killAlpha = props.kind == AlphaKill;
+			tshader.killAlphaThreshold = 0.5;
+		}
+		mainPass.culling = props.culled ? Back : None;
+		mainPass.enableLights = props.lighted;
+		m.shadows = props.shadows;
+		if( m.shadows ) m.getPass("shadow").culling = mainPass.culling;
+	}
+
+	public static var current = new MaterialSetup("Default");
+
+}

+ 40 - 19
h3d/parts/GpuParticles.hx

@@ -90,7 +90,7 @@ class GpuPartGroup {
 		if( FIELDS != null )
 			return FIELDS;
 		FIELDS = Type.getInstanceFields(GpuPartGroup);
-		for( f in ["parent", "material", "sortMode", "emitMode", "needRebuild", "pshader", "partIndex", "particles", "texture", "colorGradient", "amount", "currentParts", "ebounds", "maxTime"] )
+		for( f in ["parent", "sortMode", "emitMode", "needRebuild", "pshader", "partIndex", "particles", "texture", "colorGradient", "amount", "currentParts", "ebounds", "maxTime"] )
 			FIELDS.remove(f);
 		for( f in FIELDS.copy() )
 			if( Reflect.isFunction(Reflect.field(inst, f)) )
@@ -112,7 +112,7 @@ class GpuPartGroup {
 
 	public var name : String;
 	public var enable = true;
-	public var material : h3d.mat.MaterialProps = h3d.mat.MaterialProps.particlesDefault();
+	public var material : {};
 	public var sortMode(default, set) : GpuSortMode = None;
 
 	public var nparts(default, set) : Int 		= 100;
@@ -200,9 +200,18 @@ class GpuPartGroup {
 		pshader.maxTime = maxTime < 0 ? 1e10 : maxTime;
 	}
 
+	public function getMaterialProps() {
+		var name = h3d.mat.MaterialSetup.current.name;
+		var p = Reflect.field(material, name);
+		if( p == null ) {
+			p = h3d.mat.MaterialSetup.current.getDefaults("particles3D");
+			Reflect.setField(material, name, p);
+		}
+		return p;
+	}
+
 	public function save() : Dynamic {
 		var o = {
-			material : material.getData(),
 			sortMode : sortMode.getIndex(),
 			emitMode : emitMode.getIndex(),
 			texture : texture == null ? null : texture.name,
@@ -222,13 +231,23 @@ class GpuPartGroup {
 	public function load( version : Int, o : Dynamic ) {
 		for( f in getFields(this) )
 			Reflect.setField(this, f, Reflect.field(o, f));
-		if( o.material != null ) material.loadData(o.material);
 		sortMode = GpuSortMode.createByIndex(o.sortMode);
 		emitMode = GpuEmitMode.createByIndex(o.emitMode);
 		texture = loadTexture(o.texture);
 		colorGradient = loadTexture(o.colorGradient);
 		if( Math.isNaN(emitStartDist) ) emitStartDist = 0;
-		if( version == 1 ) fadeOut = 1 - fadeOut;
+		if( version == 1 ) {
+			fadeOut = 1 - fadeOut;
+			material = {};
+		}
+		if( parent != null ) {
+			var index = @:privateAccess parent.groups.indexOf(this);
+			if( index >= 0 ) {
+				var mat = parent.materials[index];
+				mat.name = name;
+				mat.props = getMaterialProps();
+			}
+		}
 	}
 
 	public function updateBounds( bounds : h3d.col.Bounds ) {
@@ -468,14 +487,19 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 	public function addGroup( ?g : GpuPartGroup, ?material : h3d.mat.Material, ?index ) {
 		if( g == null )
 			g = new GpuPartGroup(this);
+		if( g.name == null )
+			g.name = "Group#" + (groups.length + 1);
 		if( material == null ) {
 			material = new h3d.mat.Material();
 			material.mainPass.culling = None;
 			material.mainPass.depthWrite = false;
 			material.blendMode = Alpha;
 			if( this.material == null ) this.material = material;
+			if( g.material != null ) {
+				material.props = g.getMaterialProps();
+				material.name = g.name;
+			}
 		}
-		if( g.name == null ) g.name = "Group#" + (groups.length + 1);
 		material.mainPass.addShader(g.pshader);
 		if( index == null )
 			index = groups.length;
@@ -584,7 +608,6 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 		rnd.init(seed);
 	}
 
-
 	static var PUVS = [new h3d.prim.UV(0, 0), new h3d.prim.UV(1, 0), new h3d.prim.UV(0, 1), new h3d.prim.UV(1, 1)];
 
 	function cleanParts( g : GpuPartGroup, pneeded : Int, checkMove = false ) {
@@ -765,13 +788,8 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 		for( i in 0...materials.length ) {
 			var m = materials[i];
 			var g = groups[i];
-			if( m != null && g.enable && g.currentParts > 0 ) {
-				if( m.props != g.material ) {
-					m.name = g.name;
-					m.props = g.material;
-				}
+			if( m != null && g.enable && g.currentParts > 0 )
 				ctx.emit(m, this, i);
-			}
 		}
 	}
 
@@ -798,13 +816,16 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 					primitive = null;
 					break;
 				}
+		var camera = ctx.camera;
+		if( camera == null )
+			camera = new h3d.Camera();
 		if( primitive == null || primitive.buffer.isDisposed() )
-			rebuildAll(ctx.camera);
+			rebuildAll(camera);
 
 		uploadedCount = 0;
 		var hasPart = false;
 		for( g in groups ) {
-			syncGroup(g, ctx.camera, prev, ctx.visibleFlag);
+			syncGroup(g, camera, prev, ctx.visibleFlag);
 			if( g.currentParts == 0 )
 				continue;
 			// sync shader params
@@ -816,7 +837,7 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 				g.pshader.volumeSize.set(volumeBounds.xSize, volumeBounds.ySize, volumeBounds.zSize);
 			}
 			if( g.pshader.transform3D ) {
-				var r = ctx.camera.target.sub(ctx.camera.pos);
+				var r = ctx.camera.target.sub(camera.pos);
 				r.z = 0;
 				r.normalize();
 				var q = new h3d.Quat();
@@ -824,9 +845,9 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 				q.saveToMatrix(g.pshader.cameraRotation);
 			}
 			if( g.emitMode == CameraBounds ) {
-				g.pshader.transform.loadFrom(ctx.camera.getInverseView());
-				g.pshader.offset.set( -ctx.camera.pos.x * g.emitDist, -ctx.camera.pos.y * g.emitDist, -ctx.camera.pos.z * g.emitDist );
-				g.pshader.offset.transform3x3( ctx.camera.mcam );
+				g.pshader.transform.loadFrom(camera.getInverseView());
+				g.pshader.offset.set( -camera.pos.x * g.emitDist, -camera.pos.y * g.emitDist, -camera.pos.z * g.emitDist );
+				g.pshader.offset.transform3x3( camera.mcam );
 				g.pshader.offset.x %= volumeBounds.xSize;
 				g.pshader.offset.y %= volumeBounds.ySize;
 				g.pshader.offset.z %= volumeBounds.zSize;

+ 1 - 9
h3d/prim/ModelCache.hx

@@ -33,7 +33,7 @@ class ModelCache {
 	public function loadModel( res : hxd.res.Model ) : h3d.scene.Object {
 		var obj = loadLibrary(res).makeObject(loadTexture.bind(res));
 		for( m in obj.getMaterials() )
-			initMaterial(res, Std.instance(m, h3d.mat.Material));
+			h3d.mat.MaterialSetup.current.initModelMaterial(res, Std.instance(m, h3d.mat.Material));
 		return obj;
 	}
 
@@ -73,14 +73,6 @@ class ModelCache {
 		return t;
 	}
 
-	/**
-		This can be overriden by subclasses in order to customize material setup depending on your game semantics
-	**/
-	public function initMaterial( model : hxd.res.Model, material : h3d.mat.Material ) {
-		material.mainPass.enableLights = true;
-		material.shadows = true;
-	}
-
 	public function loadAnimation( anim : hxd.res.Model, ?name : String ) : h3d.anim.Animation {
 		var path = anim.entry.path;
 		if( name != null ) path += ":" + name;

+ 2 - 2
h3d/scene/Scene.hx

@@ -25,8 +25,8 @@ class Scene extends Object implements h3d.IDrawable implements hxd.SceneEvents.I
 		if( engine != null )
 			camera.screenRatio = engine.width / engine.height;
 		ctx = new RenderContext();
-		renderer = new Renderer();
-		lightSystem = new h3d.pass.LightSystem();
+		renderer = h3d.mat.MaterialSetup.current.createRenderer();
+		lightSystem = h3d.mat.MaterialSetup.current.createLightSystem();
 	}
 
 	@:noCompletion public function setEvents(events) {

+ 0 - 67
hxd/inspect/ScenePanel.hx

@@ -122,73 +122,6 @@ private class CustomSceneProps extends SceneProps {
 		return code;
 	}
 
-	override function getPartsProps( parts : h3d.parts.GpuParticles ) {
-		var props = super.getPartsProps(parts);
-		props.push(PCustom("", function() {
-
-			var comp = panel.j.query("<div>");
-			comp.addClass("buttonGroup");
-
-			var b = comp.query("<button>");
-			b.appendTo(comp);
-			b.html('<i class="fa fa-plus"/> Add');
-			b.click(function(_) {
-				parts.addGroup();
-				inspect.refreshProps();
-			});
-
-			var b = comp.query("<button>");
-			b.appendTo(comp);
-			b.html('<i class="fa fa-folder-open-o"/> Load');
-			b.click(function(_) {
-				inspect.loadFile("json", function(path, bytes) {
-					resPath.set(parts, path);
-					var data = haxe.Json.parse(bytes.toString());
-					for( g in Lambda.array({ iterator : parts.getGroups }) )
-						parts.removeGroup(g);
-					parts.load(data);
-					inspect.refreshProps();
-				},resPath.get(parts));
-			});
-
-			var b = comp.query("<button>");
-			b.appendTo(comp);
-			b.html('<i class="fa fa-save"/> Save');
-			b.click(function(_) {
-				var data = haxe.Json.stringify(parts.save(), null, "\t");
-				var path = resPath.get(parts);
-				if( path == null ) path = @:privateAccess (parts.resourcePath == null ? "particles.json" : parts.resourcePath);
-				inspect.saveFile(path, "json", haxe.io.Bytes.ofString(data), function(path) resPath.set(parts,path));
-			});
-
-			return comp;
-		}));
-		return props;
-	}
-
-	override function getPartsGroupProps( parts : h3d.parts.GpuParticles, g : h3d.parts.GpuParticles.GpuPartGroup ) {
-		var p = super.getPartsGroupProps(parts, g);
-		p = PPopup(p, ["Move Up", "Move Down", "Remove"], function(j, i) {
-			var groups = Lambda.array({ iterator : parts.getGroups });
-			var index = groups.indexOf(g);
-			if( index < 0 ) return;
-			switch( i ) {
-			case 0:
-				if( index == 0 ) return;
-				parts.removeGroup(g);
-				parts.addGroup(g, null, index - 1);
-			case 1:
-				if( index == groups.length - 1 ) return;
-				parts.removeGroup(g);
-				parts.addGroup(g, null, index + 1);
-			case 2:
-				parts.removeGroup(g);
-			}
-			inspect.refreshProps();
-		});
-		return p;
-	}
-
 	function getWorldInfos( world : h3d.scene.World, o : h3d.scene.Object ) {
 		var emap = new Map();
 		var extraMap = new Map();

+ 7 - 114
hxd/inspect/SceneProps.hx

@@ -240,7 +240,7 @@ class SceneProps {
 				props.push(p);
 			}
 		} else {
-			props = props.concat(mat.props.inspect(function() mat.props.apply(mat)));
+			//props = props.concat(mat.props.inspect(function() mat.props.apply(mat)));
 		}
 		return PGroup("Material",props);
 	}
@@ -267,47 +267,12 @@ class SceneProps {
 		props.push(PBool("visible", function() return o.visible, function(v) o.visible = v));
 
 		if( o.isMesh() ) {
-			var gp = Std.instance(o, h3d.parts.GpuParticles);
-			if( gp != null ) {
-				props.push(PFloats("volumePos", function() {
-					var b = gp.volumeBounds;
-					if( b == null ) return [0, 0, 0];
-					var p = b.getCenter();
-					return [p.x, p.y, p.z];
-				}, function(v) {
-					var b = gp.volumeBounds;
-					if( b != null ) {
-						var c = b.getCenter();
-						b.offset(v[0] - c.x, v[1] - c.y, v[2] - c.z);
-						gp.volumeBounds = null;
-						gp.volumeBounds = b;
-					}
-				}));
-				props.push(PFloats("volumeSize", function() {
-					var b = gp.volumeBounds;
-					if( b == null ) return [0, 0, 0];
-					return [b.xSize, b.ySize, b.zSize];
-				}, function(v) {
-					var b = gp.volumeBounds;
-					if( b != null ) {
-						var c = b.getCenter();
-						b.xMin = c.x - v[0] * 0.5; b.xSize = v[0];
-						b.yMin = c.y - v[1] * 0.5; b.ySize = v[1];
-						b.zMin = c.z - v[2] * 0.5; b.zSize = v[2];
-						gp.volumeBounds = null;
-						gp.volumeBounds = b;
-					}
-				}));
-				props = props.concat(getPartsProps(gp));
-			} else {
-				var multi = Std.instance(o, h3d.scene.MultiMaterial);
-				if( multi != null && multi.materials.length > 1 ) {
-					for( m in multi.materials )
-						props.push(getMaterialProps(m));
-				} else
-					props.push(getMaterialProps(o.toMesh().material));
-			}
-
+			var multi = Std.instance(o, h3d.scene.MultiMaterial);
+			if( multi != null && multi.materials.length > 1 ) {
+				for( m in multi.materials )
+					props.push(getMaterialProps(m));
+			} else
+				props.push(getMaterialProps(o.toMesh().material));
 		} else {
 			var c = Std.instance(o, h3d.scene.CustomObject);
 			if( c != null )
@@ -319,78 +284,6 @@ class SceneProps {
 		return props;
 	}
 
-	function getPartsProps( parts : h3d.parts.GpuParticles ) {
-		var props = [];
-		props.push(PInt("seed", function() return parts.seed, function(v) parts.seed = v));
-		for( g in parts.getGroups() )
-			props.push(getPartsGroupProps(parts, g));
-		return props;
-	}
-
-	function getPartsGroupProps( parts : h3d.parts.GpuParticles, o : h3d.parts.GpuParticles.GpuPartGroup ) {
-		var props = [];
-		props.push(PGroup("Emitter", [
-			PString("name", function() return o.name, function(v) { o.name = v; refresh(); }),
-			PEnum("mode", h3d.parts.GpuParticles.GpuEmitMode, function() return o.emitMode, function(v) o.emitMode = v),
-			PBool("enable", function() return o.enable, function(v) o.enable = v),
-			PRange("count", 0, 1000, function() return o.nparts, function(v) o.nparts = Std.int(v), 1),
-			PRange("startDistance", 0, 10, function() return o.emitStartDist, function(v) o.emitStartDist = v),
-			PRange("distance", 0, 10, function() return o.emitDist, function(v) o.emitDist = v),
-			PRange("angle", -90, 180, function() return Math.round(o.emitAngle*180/Math.PI), function(v) o.emitAngle = v*Math.PI/180, 1),
-			PBool("loop", function() return o.emitLoop, function(v) { o.emitLoop = v; parts.currentTime = 0; }),
-			PRange("sync", 0, 1, function() return o.emitSync, function(v) o.emitSync = v),
-			PRange("delay", 0, 10, function() return o.emitDelay, function(v) o.emitDelay = v),
-			PBool("transform3D", function() return o.transform3D, function(v) o.transform3D = v),
-		]));
-
-		props.push(PGroup("Life", [
-			PRange("initial", 0, 10, function() return o.life, function(v) o.life = v),
-			PRange("randomNess", 0, 1, function() return o.lifeRand, function(v) o.lifeRand = v),
-			PRange("fadeIn", 0, 1, function() return o.fadeIn, function(v) o.fadeIn = v),
-			PRange("fadeOut", 0, 1, function() return o.fadeOut, function(v) o.fadeOut = v),
-			PRange("fadePower", 0, 3, function() return o.fadePower, function(v) o.fadePower = v),
-		]));
-
-		props.push(PGroup("Speed", [
-			PRange("initial", 0, 10, function() return o.speed, function(v) o.speed = v),
-			PRange("randomNess", 0, 1, function() return o.speedRand, function(v) o.speedRand = v),
-			PRange("acceleration", -1, 1, function() return o.speedIncr, function(v) o.speedIncr = v),
-			PRange("gravity", -5, 5, function() return o.gravity, function(v) o.gravity = v),
-		]));
-
-		props.push(PGroup("Size", [
-			PRange("initial", 0.01, 2, function() return o.size, function(v) o.size = v),
-			PRange("randomNess", 0, 1, function() return o.sizeRand, function(v) o.sizeRand = v),
-			PRange("grow", -1, 1, function() return o.sizeIncr, function(v) o.sizeIncr = v),
-		]));
-
-		props.push(PGroup("Rotation", [
-			PRange("init", 0, 1, function() return o.rotInit, function(v) o.rotInit = v),
-			PRange("speed", 0, 5, function() return o.rotSpeed, function(v) o.rotSpeed = v),
-			PRange("randomNess", 0, 1, function() return o.rotSpeedRand, function(v) o.rotSpeedRand = v),
-		]));
-
-		var mat : h3d.mat.MaterialProps = {};
-		mat.loadData(o.material.getData());
-		var matProps = mat.inspect(function() {
-			var mat2 : h3d.mat.MaterialProps = {};
-			mat2.loadData(mat.getData());
-			o.material = mat2;
-		});
-
-		props.push(PGroup("Animation", matProps.concat([
-			PTexture("diffuseTexture", function() return o.texture, function(v) o.texture = v),
-			PEnum("sort", h3d.parts.GpuParticles.GpuSortMode, function() return o.sortMode, function(v) o.sortMode = v),
-			PRange("animationRepeat", 0, 10, function() return o.animationRepeat, function(v) o.animationRepeat = v),
-			PRange("frameDivisionX", 1, 16, function() return o.frameDivisionX, function(v) o.frameDivisionX = Std.int(v), 1),
-			PRange("frameDivisionY", 1, 16, function() return o.frameDivisionY, function(v) o.frameDivisionY = Std.int(v), 1),
-			PRange("frameCount", 0, 32, function() return o.frameCount, function(v) o.frameCount = Std.int(v), 1),
-			PTexture("colorGradient", function() return o.colorGradient, function(v) o.colorGradient = v),
-		])));
-
-		return PGroup(o.name, props);
-	}
-
 	function getDynamicProps( v : Dynamic ) : Array<Property> {
 		if( Std.is(v,h3d.pass.ScreenFx) || Std.is(v,Group) ) {
 			var props = [];