ソースを参照

Merge master back into shadergraph development branch

Leonardo Jeanteur 3 年 前
コミット
254af1a3eb

+ 7 - 0
bin/style.css

@@ -1724,6 +1724,13 @@ body.hide-subview .lm_controls {
 .jstree .filtered {
 .jstree .filtered {
   display: none;
   display: none;
 }
 }
+.jstree .editorOnly {
+  color: #02aeda !important;
+}
+.jstree .editorOnly i,
+.jstree .editorOnly a {
+  color: #02aeda;
+}
 .jstree .hidden {
 .jstree .hidden {
   color: #555 !important;
   color: #555 !important;
 }
 }

+ 8 - 0
bin/style.less

@@ -1960,6 +1960,14 @@ body.hide-subview {
 		display: none;
 		display: none;
 	}
 	}
 
 
+	.editorOnly {
+		color: rgb(2, 174, 218) !important;
+
+		i, a {
+			color: rgb(2, 174, 218);
+		}
+	}
+
 	.hidden {
 	.hidden {
 		color: #555 !important;
 		color: #555 !important;
 
 

+ 9 - 5
hide/comp/DetachablePanel.hx

@@ -108,8 +108,10 @@ class DetachablePanel extends hide.comp.Component {
 			currentSide = None;
 			currentSide = None;
 		});
 		});
 		document.mouseup((_) -> {
 		document.mouseup((_) -> {
-			currentSide = None;
-			saveLayout();
+			if( currentSide != None ) {
+				currentSide = None;
+				saveLayout();
+			}
 		});
 		});
 
 
 		layoutControls.appendTo(element);
 		layoutControls.appendTo(element);
@@ -128,8 +130,10 @@ class DetachablePanel extends hide.comp.Component {
 
 
 	public function setDetached(val) {
 	public function setDetached(val) {
 		element.toggleClass("detached", val);
 		element.toggleClass("detached", val);
-		var existingState = getDisplayState("detachedOffsets");
-		if( existingState != null )
-			element.css(existingState);
+		if( val ) {
+			var existingState = getDisplayState("detachedOffsets");
+			if( existingState != null )
+				element.css(existingState);
+		}
 	}
 	}
 }
 }

+ 20 - 0
hide/comp/SceneEditor.hx

@@ -495,6 +495,7 @@ class SceneEditor {
 
 
 			if( current != null ) {
 			if( current != null ) {
 				menuItems.push({ label : "Enable", checked : current.enabled, stayOpen : true, click : function() setEnabled(curEdit.elements, !current.enabled) });
 				menuItems.push({ label : "Enable", checked : current.enabled, stayOpen : true, click : function() setEnabled(curEdit.elements, !current.enabled) });
+				menuItems.push({ label : "Editor only", checked : current.editorOnly, stayOpen : true, click : function() setEditorOnly(curEdit.elements, !current.editorOnly) });
 			}
 			}
 
 
 			if( isObj ) {
 			if( isObj ) {
@@ -1198,6 +1199,7 @@ class SceneEditor {
 			el.toggleClass("disabled", !p.enabled || !obj3d.visible);
 			el.toggleClass("disabled", !p.enabled || !obj3d.visible);
 			el.toggleClass("hidden", isHidden(obj3d));
 			el.toggleClass("hidden", isHidden(obj3d));
 			el.toggleClass("locked", p.locked);
 			el.toggleClass("locked", p.locked);
+			el.toggleClass("editorOnly", p.editorOnly);
 
 
 			var visTog = el.find(".visibility-toggle").first();
 			var visTog = el.find(".visibility-toggle").first();
 			if(visTog.length == 0) {
 			if(visTog.length == 0) {
@@ -1901,6 +1903,24 @@ class SceneEditor {
 		}));
 		}));
 	}
 	}
 
 
+	public function setEditorOnly(elements : Array<PrefabElement>, enable: Bool) {
+		var old = [for(e in elements) e.editorOnly];
+		function apply(on) {
+			for(i in 0...elements.length) {
+				elements[i].editorOnly = on ? enable : old[i];
+				onPrefabChange(elements[i]);
+			}
+			refreshScene();
+		}
+		apply(true);
+		undo.change(Custom(function(undo) {
+			if(undo)
+				apply(false);
+			else
+				apply(true);
+		}));
+	}
+
 	public function isHidden(e: PrefabElement) {
 	public function isHidden(e: PrefabElement) {
 		if(e == null)
 		if(e == null)
 			return false;
 			return false;

+ 6 - 4
hide/comp/cdb/Editor.hx

@@ -275,7 +275,7 @@ class Editor extends Component {
 		var realSheet = cursor.table.getRealSheet();
 		var realSheet = cursor.table.getRealSheet();
 		var allLines = cursor.table.lines;
 		var allLines = cursor.table.lines;
 
 
-		var inserted = false;
+		var fullRefresh = false;
 		var toRefresh : Array<Cell> = [];
 		var toRefresh : Array<Cell> = [];
 
 
 		var isProps = (cursor.table.displayMode != Table);
 		var isProps = (cursor.table.displayMode != Table);
@@ -415,7 +415,7 @@ class Editor extends Component {
 				if( posY == sheet.lines.length ) {
 				if( posY == sheet.lines.length ) {
 					if( !cursor.table.canInsert() ) break;
 					if( !cursor.table.canInsert() ) break;
 					sheet.newLine();
 					sheet.newLine();
-					inserted = true;
+					fullRefresh = true;
 				}
 				}
 				var obj2 = sheet.lines[posY];
 				var obj2 = sheet.lines[posY];
 				for( cid in 0...clipboard.schema.length ) {
 				for( cid in 0...clipboard.schema.length ) {
@@ -427,7 +427,9 @@ class Editor extends Component {
 						continue;
 						continue;
 
 
 					setValue(obj1, obj2, c1, c2);
 					setValue(obj1, obj2, c1, c2);
-					if( !inserted )
+					if( c2.type == TList || c2.type == TProperties )
+						fullRefresh = true;
+					if( !fullRefresh )
 						toRefresh.push(allLines[posY].cells[cid + posX]);
 						toRefresh.push(allLines[posY].cells[cid + posX]);
 				}
 				}
 				posY++;
 				posY++;
@@ -436,7 +438,7 @@ class Editor extends Component {
 		formulas.evaluateAll(realSheet);
 		formulas.evaluateAll(realSheet);
 		endChanges();
 		endChanges();
 		realSheet.sync();
 		realSheet.sync();
-		if( inserted )
+		if( fullRefresh )
 			refreshAll();
 			refreshAll();
 		else {
 		else {
 			for( c in toRefresh ) {
 			for( c in toRefresh ) {

+ 3 - 3
hide/view/FXEditor.hx

@@ -505,7 +505,7 @@ class FXEditor extends FileView {
 
 
 				if(previewMax < previewMin + 0.1) {
 				if(previewMax < previewMin + 0.1) {
 					previewMin = 0;
 					previewMin = 0;
-					previewMax = data.duration == 0 ? 1 : data.duration;
+					previewMax = data.duration == 0 ? 5000 : data.duration;
 				}
 				}
 
 
 				element.off("mousemove");
 				element.off("mousemove");
@@ -1148,7 +1148,7 @@ class FXEditor extends FileView {
 			}
 			}
 			curveEdit.xOffset = xOffset;
 			curveEdit.xOffset = xOffset;
 			curveEdit.xScale = xScale;
 			curveEdit.xScale = xScale;
-			if(isInstanceCurve(curve))
+			if(isInstanceCurve(curve) && curve.parent.to(hrt.prefab.fx.Emitter) == null || curve.name.indexOf("inst") >= 0)
 				curve.maxTime = 1.0;
 				curve.maxTime = 1.0;
 			curveEdit.curve = curve;
 			curveEdit.curve = curve;
 			curveEdit.onChange = function(anim) {
 			curveEdit.onChange = function(anim) {
@@ -1689,7 +1689,7 @@ class FXEditor extends FileView {
 		if(ctx != null && ctx.local3d != null) {
 		if(ctx != null && ctx.local3d != null) {
 			anim = Std.downcast(ctx.local3d,hrt.prefab.fx.FX.FXAnimation);
 			anim = Std.downcast(ctx.local3d,hrt.prefab.fx.FX.FXAnimation);
 		}
 		}
-	
+
 		if(!pauseButton.isDown()) {
 		if(!pauseButton.isDown()) {
 			currentTime += scene.speed * dt;
 			currentTime += scene.speed * dt;
 			if(timeLineEl != null)
 			if(timeLineEl != null)

+ 1 - 1
hide/view/FileTree.hx

@@ -355,7 +355,7 @@ class FileTree extends FileView {
 
 
 	function onCloneFile( path : String ) {
 	function onCloneFile( path : String ) {
 		var sourcePath = getFilePath(path);
 		var sourcePath = getFilePath(path);
-		var nameNewFile = ide.ask("New filename:");
+		var nameNewFile = ide.ask("New filename:", new haxe.io.Path(sourcePath).file);
 		if (nameNewFile == null || nameNewFile.length == 0) {
 		if (nameNewFile == null || nameNewFile.length == 0) {
 			return false;
 			return false;
 		}
 		}

+ 1 - 67
hide/view/Prefab.hx

@@ -342,7 +342,6 @@ class Prefab extends FileView {
 		toolsDefs.push({id: "snapToGroundToggle", title : "Snap to ground", icon : "anchor", type : Toggle((v) -> sceneEditor.snapToGround = v)});
 		toolsDefs.push({id: "snapToGroundToggle", title : "Snap to ground", icon : "anchor", type : Toggle((v) -> sceneEditor.snapToGround = v)});
 		toolsDefs.push({id: "localTransformsToggle", title : "Local transforms", icon : "compass", type : Toggle((v) -> sceneEditor.localTransform = v)});
 		toolsDefs.push({id: "localTransformsToggle", title : "Local transforms", icon : "compass", type : Toggle((v) -> sceneEditor.localTransform = v)});
 		toolsDefs.push({id: "gridToggle", title : "Toggle grid", icon : "th", type : Toggle((v) -> { showGrid = v; updateGrid(); }) });
 		toolsDefs.push({id: "gridToggle", title : "Toggle grid", icon : "th", type : Toggle((v) -> { showGrid = v; updateGrid(); }) });
-		toolsDefs.push({id: "bakeLights", title : "Bake lights", icon : "lightbulb-o", type : Button(() -> bakeLights()) });
 		var texContent : Element = null;
 		var texContent : Element = null;
 		toolsDefs.push({id: "sceneInformationToggle", title : "Scene information", icon : "info-circle", type : Toggle((b) -> statusText.visible = b), rightClick: () -> {
 		toolsDefs.push({id: "sceneInformationToggle", title : "Scene information", icon : "info-circle", type : Toggle((b) -> statusText.visible = b), rightClick: () -> {
 			if( texContent != null ) {
 			if( texContent != null ) {
@@ -435,71 +434,6 @@ class Prefab extends FileView {
 		haxe.Timer.delay(function() sceneEditor.event.wait(0.5, updateStats), 0);
 		haxe.Timer.delay(function() sceneEditor.event.wait(0.5, updateStats), 0);
 	}
 	}
 
 
-	function bakeLights() {
-		var curSel = sceneEditor.curEdit.elements;
-		sceneEditor.selectElements([]);
-		var passes = [];
-		for( m in scene.s3d.getMaterials() ) {
-			var s = m.getPass("shadow");
-			if( s != null && !s.isStatic ) passes.push(s);
-		}
-		for( p in passes )
-			p.isStatic = true;
-
-		function isDynamic(elt: hrt.prefab.Prefab) {
-			var p = elt;
-			while(p != null) {
-				if(p.name == "dynamic")
-					return true;
-				p = p.parent;
-			}
-			return false;
-		}
-
-		for(elt in data.flatten()) {
-			if(Std.is(elt, Instance) || isDynamic(elt)) {
-				var mats = sceneEditor.context.shared.getMaterials(elt);
-				for(mat in mats) {
-					var p = mat.getPass("shadow");
-					if(p != null)
-						p.isStatic = false;
-				}
-			}
-		}
-
-		scene.s3d.computeStatic();
-		for( p in passes )
-			p.isStatic = false;
-		var lights = data.getAll(hrt.prefab.Light);
-		for( l in lights ) {
-			if(!l.visible)
-				continue;
-			l.saveBaked(sceneEditor.context);
-		}
-		sceneEditor.selectElements(curSel);
-	}
-
-	function bakeVolumetricLightmaps(){
-		var volumetricLightmaps = data.getAll(hrt.prefab.vlm.VolumetricLightmap);
-		var total = 0;
-		for( v in volumetricLightmaps )
-			total += v.volumetricLightmap.getProbeCount();
-		if( total == 0 )
-			return;
-		if( !ide.confirm("Bake "+total+" probes?") )
-			return;
-		function bakeNext() {
-			var v = volumetricLightmaps.shift();
-			if( v == null ) {
-				ide.message("Done");
-				return;
-			}
-			v.startBake(sceneEditor.curEdit, bakeNext);
-			sceneEditor.selectElements([v]);
-		}
-		bakeNext();
-	}
-
 	function resetCamera( top : Bool ) {
 	function resetCamera( top : Bool ) {
 		var targetPt = new h3d.col.Point(0, 0, 0);
 		var targetPt = new h3d.col.Point(0, 0, 0);
 		var curEdit = sceneEditor.curEdit;
 		var curEdit = sceneEditor.curEdit;
@@ -662,7 +596,7 @@ class Prefab extends FileView {
 						case "Scene":
 						case "Scene":
 							applySceneFilter(typeid, on);
 							applySceneFilter(typeid, on);
 					}
 					}
-					
+
 				content.find(function(item) return item.label == typeid).checked = on;
 				content.find(function(item) return item.label == typeid).checked = on;
 			}});
 			}});
 		}
 		}

+ 1 - 1
hide/view/Script.hx

@@ -29,7 +29,7 @@ class Script extends FileView {
 						if( text != "" ) {
 						if( text != "" ) {
 							var n = text.split(" ").length;
 							var n = text.split(" ").length;
 							count += n;
 							count += n;
-							category.count += n;
+							if( category != null ) category.count += n;
 						}
 						}
 					case Document:
 					case Document:
 						for( x in x )
 						for( x in x )

+ 0 - 1
hrt/prefab/Context.hx

@@ -83,7 +83,6 @@ package hrt.prefab;
 			if( v == null ) {
 			if( v == null ) {
 				var parts2 = path.split(".");
 				var parts2 = path.split(".");
 				for( i in 0...parts.length ) parts2.pop();
 				for( i in 0...parts.length ) parts2.pop();
-				shared.onError("Object not found " + parts2.join("."));
 				return null;
 				return null;
 			}
 			}
 			root = v;
 			root = v;

+ 2 - 26
hrt/prefab/Light.hx

@@ -147,24 +147,9 @@ class Light extends Object3D {
 
 
 		cookieTex = initTexture(cookiePath);
 		cookieTex = initTexture(cookiePath);
 		updateInstance(ctx);
 		updateInstance(ctx);
-
-		if( ctx.shared.parent == null )
-			loadBaked(ctx);
 		return ctx;
 		return ctx;
 	}
 	}
 
 
-	function loadBaked( ctx : Context ) {
-		var light = Std.downcast(ctx.local3d, h3d.scene.pbr.Light);
-		if( light == null ) return;
-		if( light.shadows.mode == Static || light.shadows.mode == Mixed ){
-			var res = ctx.shared.loadPrefabDat("shadowMap", "bake", name);
-			if( res != null ) light.shadows.loadStaticData(res.entry.getBytes());
-			#if !editor
-			if( res == null ) light.shadows.mode = None; // Prevent crash if shadows are not baked
-			#end
-		}
-	}
-
 	override function updateInstance( ctx : Context, ?propName : String ) {
 	override function updateInstance( ctx : Context, ?propName : String ) {
 		super.updateInstance(ctx, propName);
 		super.updateInstance(ctx, propName);
 
 
@@ -361,23 +346,14 @@ class Light extends Object3D {
 			sel.name = "__selection";
 			sel.name = "__selection";
 		}
 		}
 
 
-		// no "Mixed" in editor (prevent double shadowing)
-		if( light != null && light.shadows.mode == Mixed ) light.shadows.mode = Static;
-
-		// when selected, force Dynamic mode (realtime preview)
-		//if( isSelected && shadows.mode != None ) light.shadows.mode = Dynamic;
+		// no "Mixed" in editor
+		if( light != null && light.shadows.mode == Mixed ) light.shadows.mode = Dynamic;
 
 
 		#end
 		#end
 	}
 	}
 
 
 	#if editor
 	#if editor
 
 
-	public function saveBaked( ctx : Context ) {
-		var light = cast(ctx.shared.contexts.get(this).local3d,h3d.scene.pbr.Light);
-		var bytes = light.shadows.saveStaticData();
-		ctx.shared.savePrefabDat("shadowMap", "bake", name, bytes);
-	}
-
 	override function setSelected( ctx : Context, b : Bool ) {
 	override function setSelected( ctx : Context, b : Bool ) {
 		var sel = ctx.local3d.getObjectByName("__selection");
 		var sel = ctx.local3d.getObjectByName("__selection");
 		if( sel != null ) sel.visible = b;
 		if( sel != null ) sel.visible = b;

+ 1 - 1
hrt/prefab/Model.hx

@@ -181,7 +181,7 @@ class Model extends Object3D {
 	override function getHideProps() : HideProps {
 	override function getHideProps() : HideProps {
 		return {
 		return {
 			icon : "cube", name : "Model", fileSource : ["fbx","hmd"],
 			icon : "cube", name : "Model", fileSource : ["fbx","hmd"],
-			allowChildren : function(t) return Library.isOfType(t,Object3D) || Library.isOfType(t,Material) || Library.isOfType(t,Shader),
+			allowChildren : function(t) return Library.isOfType(t,Object3D) || Library.isOfType(t,Material) || Library.isOfType(t,Shader) || Library.isOfType(t, hrt.prefab.fx.AnimEvent),
 			onResourceRenamed : function(f) animation = f(animation),
 			onResourceRenamed : function(f) animation = f(animation),
 		};
 		};
 	}
 	}

+ 8 - 0
hrt/prefab/Prefab.hx

@@ -36,6 +36,11 @@ class Prefab {
 	**/
 	**/
 	@:s public var enabled : Bool = true;
 	@:s public var enabled : Bool = true;
 
 
+	/**
+		Tells if the prefab will create an instance when used in an other prefab or in game. Also apply to this prefab children.
+	**/
+	@:s public var editorOnly : Bool = false;
+
 	/**
 	/**
 		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.
 	**/
 	**/
@@ -260,6 +265,9 @@ class Prefab {
 			ctx = new Context();
 			ctx = new Context();
 			ctx.init();
 			ctx.init();
 		}
 		}
+		var fromRef = #if editor ctx.shared.parent != null #else true #end;
+		if (fromRef && editorOnly)
+			return ctx;
 		ctx = makeInstance(ctx);
 		ctx = makeInstance(ctx);
 		for( c in children )
 		for( c in children )
 			makeChildren(ctx, c);
 			makeChildren(ctx, c);

+ 90 - 58
hrt/prefab/fx/Emitter.hx

@@ -510,7 +510,7 @@ class EmitterObject extends h3d.scene.Object {
 	var randomSeed = 0;
 	var randomSeed = 0;
 	var context : hrt.prefab.Context;
 	var context : hrt.prefab.Context;
 	var emitCount = 0;
 	var emitCount = 0;
-	var lastTime = -1.0;
+	var emitTarget = 0.0;
 	var curTime = 0.0;
 	var curTime = 0.0;
 	var evaluator : Evaluator;
 	var evaluator : Evaluator;
 	var vecPool = new Evaluator.VecPool();
 	var vecPool = new Evaluator.VecPool();
@@ -532,8 +532,8 @@ class EmitterObject extends h3d.scene.Object {
 		enable = true;
 		enable = true;
 		random.init(randomSeed);
 		random.init(randomSeed);
 		curTime = 0.0;
 		curTime = 0.0;
-		lastTime = 0.0;
 		emitCount = 0;
 		emitCount = 0;
+		emitTarget = 0;
 		totalBurstCount = 0;
 		totalBurstCount = 0;
 
 
 		var p = particles;
 		var p = particles;
@@ -611,7 +611,6 @@ class EmitterObject extends h3d.scene.Object {
 		if( instDef == null || particleTemplate == null )
 		if( instDef == null || particleTemplate == null )
 			return;
 			return;
 
 
-		var shapeAngle = hxd.Math.degToRad(emitAngle) / 2.0;
 		var emitterQuat : h3d.Quat = null;
 		var emitterQuat : h3d.Quat = null;
 		var emitterBaseMat : h3d.Matrix = null;
 		var emitterBaseMat : h3d.Matrix = null;
 
 
@@ -649,26 +648,21 @@ class EmitterObject extends h3d.scene.Object {
 					if( emitOrientation == Normal )
 					if( emitOrientation == Normal )
 						tmpQuat.initDirection(tmpOffset);
 						tmpQuat.initDirection(tmpOffset);
 				case Cylinder:
 				case Cylinder:
+					var z = random.rand();
 					var dx = 0.0, dy = 0.0;
 					var dx = 0.0, dy = 0.0;
+					var shapeAngle = hxd.Math.degToRad(emitAngle) / 2.0;
+					var a = random.srand(shapeAngle);
 					if(emitSurface) {
 					if(emitSurface) {
-						var a = random.srand(Math.PI);
-						dx = Math.cos(a);
-						dy = Math.sin(a);
+						dx = Math.cos(a)*(emitRad2*z + emitRad1*(1.0-z));
+						dy = Math.sin(a)*(emitRad2*z + emitRad1*(1.0-z));
 					}
 					}
 					else {
 					else {
-						do {
-							dx = random.srand(1.0);
-							dy = random.srand(1.0);
-						}
-						while(dx * dx + dy * dy > 1.0);
+						dx = Math.cos(a)*(emitRad2*z + emitRad1*(1.0-z))*random.rand();
+						dy = Math.sin(a)*(emitRad2*z + emitRad1*(1.0-z))*random.rand();
 					}
 					}
-					var z = random.rand();
 					tmpOffset.set(dx * 0.5, dy * 0.5, z - 0.5);
 					tmpOffset.set(dx * 0.5, dy * 0.5, z - 0.5);
 					if( emitOrientation == Normal )
 					if( emitOrientation == Normal )
 						tmpQuat.initRotation(0, 0, hxd.Math.atan2(dy, dx));
 						tmpQuat.initRotation(0, 0, hxd.Math.atan2(dy, dx));
-
-					tmpOffset.x *= hxd.Math.lerp(emitRad1, emitRad2, x);
-					tmpOffset.y *= hxd.Math.lerp(emitRad1, emitRad2, x);
 				case Sphere:
 				case Sphere:
 					do {
 					do {
 						tmpOffset.x = random.srand(1.0);
 						tmpOffset.x = random.srand(1.0);
@@ -684,6 +678,7 @@ class EmitterObject extends h3d.scene.Object {
 				case Cone:
 				case Cone:
 					tmpOffset.set(0, 0, 0);
 					tmpOffset.set(0, 0, 0);
 					var theta = random.rand() * Math.PI * 2;
 					var theta = random.rand() * Math.PI * 2;
+					var shapeAngle = hxd.Math.degToRad(emitAngle) / 2.0;
 					var phi = shapeAngle * random.rand();
 					var phi = shapeAngle * random.rand();
 					tmpDir.x = Math.cos(phi) * scaleX;
 					tmpDir.x = Math.cos(phi) * scaleX;
 					tmpDir.y = Math.sin(phi) * Math.sin(theta) * scaleY;
 					tmpDir.y = Math.sin(phi) * Math.sin(theta) * scaleY;
@@ -859,13 +854,13 @@ class EmitterObject extends h3d.scene.Object {
 		if( enable ) {
 		if( enable ) {
 			switch emitType {
 			switch emitType {
 				case Infinity:
 				case Infinity:
-					var emitTarget = evaluator.getSum(emitRate, curTime);
+					emitTarget += evaluator.getFloat(emitRate, curTime) * dt;
 					var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, emitTarget - emitCount));
 					var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, emitTarget - emitCount));
 					doEmit(delta);
 					doEmit(delta);
 					if( isSubEmitter && (parentEmitter == null || parentEmitter.parent == null) )
 					if( isSubEmitter && (parentEmitter == null || parentEmitter.parent == null) )
 						enable = false;
 						enable = false;
 				case Duration:
 				case Duration:
-					var emitTarget = evaluator.getSum(emitRate, hxd.Math.min(curTime, emitDuration));
+					emitTarget += evaluator.getFloat(emitRate, hxd.Math.min(curTime, emitDuration)) * dt;
 					var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, emitTarget - emitCount));
 					var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, emitTarget - emitCount));
 					doEmit(delta);
 					doEmit(delta);
 					if( isSubEmitter && curTime >= emitDuration )
 					if( isSubEmitter && curTime >= emitDuration )
@@ -928,7 +923,6 @@ class EmitterObject extends h3d.scene.Object {
 				}
 				}
 			}
 			}
 		}
 		}
-		lastTime = curTime;
 		curTime += dt;
 		curTime += dt;
 	}
 	}
 
 
@@ -1001,17 +995,19 @@ class EmitterObject extends h3d.scene.Object {
 
 
 	public function setTime(time: Float) {
 	public function setTime(time: Float) {
 		time = time * speedFactor + warmUpTime;
 		time = time * speedFactor + warmUpTime;
-		if(time < lastTime || lastTime < 0) {
+		if(time < curTime) {
 			reset();
 			reset();
 		}
 		}
 
 
 		var catchupTime = time - curTime;
 		var catchupTime = time - curTime;
 
 
-		#if !editor
-		if(catchupTime > maxCatchupWindow) {
-			curTime = time - maxCatchupWindow;
+		#if !editor  // Limit catchup time to avoid spikes when showing long running FX
+		var longCatchup = catchupTime > maxCatchupWindow;
+		if(longCatchup) {
+			var firstWarmup = curTime <= 0.0 && warmUpTime > 0;
+			catchupTime = firstWarmup ? warmUpTime : maxCatchupWindow;
+			curTime = time - catchupTime;
 			emitCount = hxd.Math.ceil(evaluator.getSum(emitRate, curTime));
 			emitCount = hxd.Math.ceil(evaluator.getSum(emitRate, curTime));
-			catchupTime = maxCatchupWindow;
 
 
 			// Force sort after long time invisible
 			// Force sort after long time invisible
 			var p = particles;
 			var p = particles;
@@ -1070,7 +1066,7 @@ class Emitter extends Object3D {
 		{ name: "enableSort", t: PBool, def: true, disp: "Enable Sort", groupName : "Emit Params" },
 		{ name: "enableSort", t: PBool, def: true, disp: "Enable Sort", groupName : "Emit Params" },
 		// EMIT SHAPE
 		// EMIT SHAPE
 		{ name: "emitShape", t: PEnum(EmitShape), def: EmitShape.Sphere, disp: "Shape", groupName : "Emit Shape" },
 		{ name: "emitShape", t: PEnum(EmitShape), def: EmitShape.Sphere, disp: "Shape", groupName : "Emit Shape" },
-		{ name: "emitAngle", t: PFloat(0, 360.0), disp: "Angle", groupName : "Emit Shape" },
+		{ name: "emitAngle", t: PFloat(0, 360.0), def: 360.0, disp: "Angle", groupName : "Emit Shape" },
 		{ name: "emitRad1", t: PFloat(0, 1.0), def: 1.0, disp: "Radius 1", groupName : "Emit Shape" },
 		{ name: "emitRad1", t: PFloat(0, 1.0), def: 1.0, disp: "Radius 1", groupName : "Emit Shape" },
 		{ name: "emitRad2", t: PFloat(0, 1.0), def: 1.0, disp: "Radius 2", groupName : "Emit Shape" },
 		{ name: "emitRad2", t: PFloat(0, 1.0), def: 1.0, disp: "Radius 2", groupName : "Emit Shape" },
 		{ name: "emitSurface", t: PBool, def: false, disp: "Surface", groupName : "Emit Shape" },
 		{ name: "emitSurface", t: PBool, def: false, disp: "Surface", groupName : "Emit Shape" },
@@ -1172,9 +1168,6 @@ class Emitter extends Object3D {
 			var shader = Std.downcast(c, hrt.prefab.Shader);
 			var shader = Std.downcast(c, hrt.prefab.Shader);
 			if( shader != null )
 			if( shader != null )
 				makeChildren(ctx, shader);
 				makeChildren(ctx, shader);
-			var lit = Std.downcast(c, hrt.prefab.pbr.ParticleLit);
-			if( lit != null )
-				makeChildren(ctx, lit);
 		}
 		}
 	}
 	}
 
 
@@ -1218,38 +1211,64 @@ class Emitter extends Object3D {
 
 
 		function makeParam(scope: Prefab, name: String): Value {
 		function makeParam(scope: Prefab, name: String): Value {
 			var getCurve = hrt.prefab.Curve.getCurve.bind(scope);
 			var getCurve = hrt.prefab.Curve.getCurve.bind(scope);
-			function makeCompVal(baseProp: Null<Float>, defVal: Float, randProp: Null<Float>, pname: String, suffix: String) : Value {
-				var xVal : Value = VZero;
-				var rv = baseProp != null ? baseProp : defVal;
-				xVal = switch(rv) {
+
+			function vVal(f: Float) : Value {
+				return switch(f) {
 					case 0.0: VZero;
 					case 0.0: VZero;
 					case 1.0: VOne;
 					case 1.0: VOne;
-					default: VConst(rv);
+					default: VConst(f);
+				}
+			}
+
+			function vMult(a: Value, b: Value) : Value {
+				if(a == VZero || b == VZero) return VZero;
+				if(a == VOne) return b;
+				if(b == VOne) return a;
+				switch a {
+					case VConst(va):
+						switch b {
+							case VConst(vb): return VConst(va * vb);
+							case VCurve(cb): return VCurveScale(cb, va);
+							default:
+						}
+					case VCurve(ca):
+						switch b {
+							case VConst(vb): return VCurveScale(ca, vb);
+							default:
+						}
+					default:
+				}
+				return VMult(a, b);
+			}
+
+			function vAdd(a: Value, b: Value) : Value {
+				if(a == VZero) return b;
+				if(b == VZero) return a;
+				switch a {
+					case VConst(va):
+						switch b {
+							case VConst(vb): return VConst(va + vb);
+							default:
+						}
+					default:
 				}
 				}
+				return VAdd(a, b);
+			}
 
 
+			function makeCompVal(baseProp: Null<Float>, defVal: Float, randProp: Null<Float>, pname: String, suffix: String) : Value {
+				var xVal = vVal(baseProp != null ? baseProp : defVal);
 				var randCurve = getCurve(pname + suffix + ".rand");
 				var randCurve = getCurve(pname + suffix + ".rand");
 				var randVal : Value = VZero;
 				var randVal : Value = VZero;
 				if(randCurve != null)
 				if(randCurve != null)
 					randVal = VRandom(randIdx++, VCurveScale(randCurve, randProp != null ? randProp : 1.0));
 					randVal = VRandom(randIdx++, VCurveScale(randCurve, randProp != null ? randProp : 1.0));
-				else if(randProp != null)
-					randVal = VRandom(randIdx++, VConst(randProp));
+				else if(randProp != null && randProp != 0.0)
+					randVal = VRandomScale(randIdx++, randProp);
 
 
 				var xCurve = getCurve(pname + suffix);
 				var xCurve = getCurve(pname + suffix);
-				if (xCurve != null) {
-					if(randVal == VZero)
-						return VMult(xVal, VCurve(xCurve));
-					if(xVal == VZero)
-						return VMult(randVal, VCurve(xCurve));
-					xVal = VAdd(xVal, randVal);
-					return VMult(xVal, VCurve(xCurve));
-				}
-				else {
-					if(randVal == VZero)
-						return xVal;
-					if(xVal == VZero)
-						return randVal;
-					return VAdd(xVal, randVal);
-				}
+				if (xCurve != null)
+					return vMult(vAdd(xVal, randVal), VCurve(xCurve))
+				else
+					return vAdd(xVal, randVal);
 			}
 			}
 
 
 			var baseProp: Dynamic = Reflect.field(props, name);
 			var baseProp: Dynamic = Reflect.field(props, name);
@@ -1362,6 +1381,7 @@ class Emitter extends Object3D {
 		#end
 		#end
 
 
 		emitterObj.createMeshBatch();
 		emitterObj.createMeshBatch();
+		emitterObj.reset();
 		refreshChildren(ctx);
 		refreshChildren(ctx);
 
 
 		#if editor
 		#if editor
@@ -1410,7 +1430,7 @@ class Emitter extends Object3D {
 		}
 		}
 
 
 		var emitShape : EmitShape = getParamVal("emitShape");
 		var emitShape : EmitShape = getParamVal("emitShape");
-		if(emitShape != Cone)
+		if(!(emitShape == Cone || emitShape == Cylinder))
 			removeParam("emitAngle");
 			removeParam("emitAngle");
 		if(emitShape != Cylinder) {
 		if(emitShape != Cylinder) {
 			removeParam("emitRad1");
 			removeParam("emitRad1");
@@ -1600,19 +1620,22 @@ class Emitter extends Object3D {
 		for(i in 0...debugShape.numChildren)
 		for(i in 0...debugShape.numChildren)
 			debugShape.removeChild(debugShape.getChildAt(i));
 			debugShape.removeChild(debugShape.getChildAt(i));
 
 
-		inline function circle(npts, f) {
-			for(i in 0...(npts+1)) {
-				var c = hxd.Math.cos((i / npts) * hxd.Math.PI * 2.0);
-				var s = hxd.Math.sin((i / npts) * hxd.Math.PI * 2.0);
-				f(i, c, s);
-			}
-		}
-
 		var mesh : h3d.scene.Mesh = null;
 		var mesh : h3d.scene.Mesh = null;
 		switch(emitterObj.emitShape) {
 		switch(emitterObj.emitShape) {
 			case Cylinder: {
 			case Cylinder: {
 				var rad1 = getParamVal("emitRad1") * 0.5;
 				var rad1 = getParamVal("emitRad1") * 0.5;
 				var rad2 = getParamVal("emitRad2") * 0.5;
 				var rad2 = getParamVal("emitRad2") * 0.5;
+				var angle = hxd.Math.degToRad(getParamVal("emitAngle"));
+
+				inline function circle(npts, f) {
+					for(i in 0...(npts+1)) {
+						var t = Math.PI + (i / npts) * angle + (Math.PI*2 - angle) * 0.5;
+						var c = hxd.Math.cos(t);
+						var s = hxd.Math.sin(t);
+						f(i, c, s);
+					}
+				}
+
 				var g = new h3d.scene.Graphics(debugShape);
 				var g = new h3d.scene.Graphics(debugShape);
 				g.material.mainPass.setPassName("overlay");
 				g.material.mainPass.setPassName("overlay");
 				g.lineStyle(1, 0xffffff);
 				g.lineStyle(1, 0xffffff);
@@ -1640,6 +1663,15 @@ class Emitter extends Object3D {
 				mesh = new h3d.scene.Box(0xffffff, true, debugShape);
 				mesh = new h3d.scene.Box(0xffffff, true, debugShape);
 			}
 			}
 			case Cone: {
 			case Cone: {
+				inline function circle(npts, f) {
+					for(i in 0...(npts+1)) {
+						var t = (i / npts) * hxd.Math.PI * 2.0;
+						var c = hxd.Math.cos(t);
+						var s = hxd.Math.sin(t);
+						f(i, c, s);
+					}
+				}
+
 				var g = new h3d.scene.Graphics(debugShape);
 				var g = new h3d.scene.Graphics(debugShape);
 				g.material.mainPass.setPassName("overlay");
 				g.material.mainPass.setPassName("overlay");
 				var angle = hxd.Math.degToRad(getParamVal("emitAngle")) / 2.0;
 				var angle = hxd.Math.degToRad(getParamVal("emitAngle")) / 2.0;

+ 11 - 0
hrt/prefab/fx/Evaluator.hx

@@ -49,6 +49,13 @@ class Evaluator {
 					++len;
 					++len;
 				}
 				}
 				return randValues[idx] * getFloat(scale, time);
 				return randValues[idx] * getFloat(scale, time);
+			case VRandomScale(idx, scale):
+				var len = randValues.length;
+				while(idx >= len) {
+					randValues.push(random.srand());
+					++len;
+				}
+				return randValues[idx] * scale;
 			case VMult(a, b):
 			case VMult(a, b):
 				return getFloat(a, time) * getFloat(b, time);
 				return getFloat(a, time) * getFloat(b, time);
 			case VAdd(a, b):
 			case VAdd(a, b):
@@ -63,8 +70,12 @@ class Evaluator {
 			case VOne: return time;
 			case VOne: return time;
 			case VConst(v): return v * time;
 			case VConst(v): return v * time;
 			case VCurveScale(c, scale): return c.getSum(time) * scale;
 			case VCurveScale(c, scale): return c.getSum(time) * scale;
+			case VCurve(c): return c.getSum(time);
 			case VAdd(a, b):
 			case VAdd(a, b):
 				return getSum(a, time) + getSum(b, time);
 				return getSum(a, time) + getSum(b, time);
+			case VMult(a, b):
+				throw "Not implemented";
+				return 0.0;
 			default: 0.0;
 			default: 0.0;
 		}
 		}
 		return 0.0;
 		return 0.0;

+ 2 - 6
hrt/prefab/fx/FX.hx

@@ -202,7 +202,7 @@ class FXAnimation extends h3d.scene.Object {
 		if(emitters != null) {
 		if(emitters != null) {
 			for(em in emitters) {
 			for(em in emitters) {
 				if (prevTime > localTime) {
 				if (prevTime > localTime) {
-					@:privateAccess em.curTime = em.lastTime = time;
+					@:privateAccess em.curTime = time;
 					#if editor
 					#if editor
 					em.reset();
 					em.reset();
 					#end
 					#end
@@ -400,11 +400,7 @@ class FX extends BaseFX {
 		var useFXRoot = #if editor fromRef #else true #end;
 		var useFXRoot = #if editor fromRef #else true #end;
 		var root = getFXRoot(ctx, this);
 		var root = getFXRoot(ctx, this);
 		if(useFXRoot && root != null){
 		if(useFXRoot && root != null){
-			for( c in root.children ) {
-				var co = Std.downcast(c , hrt.prefab.l3d.Constraint);
-				if( co == null )
-					makeChildren(ctx,c);
-			}
+			root.make(ctx);
 		}
 		}
 		else
 		else
 			super.make(ctx);
 			super.make(ctx);

+ 1 - 0
hrt/prefab/fx/Value.hx

@@ -7,6 +7,7 @@ enum Value {
 	VCurve(c: Curve);
 	VCurve(c: Curve);
 	VCurveScale(c: Curve, scale: Float);
 	VCurveScale(c: Curve, scale: Float);
 	VRandom(idx: Int, scale: Value);
 	VRandom(idx: Int, scale: Value);
+	VRandomScale(idx: Int, scale: Float);
 	VAdd(a: Value, b: Value);
 	VAdd(a: Value, b: Value);
 	VMult(a: Value, b: Value);
 	VMult(a: Value, b: Value);
 	VVector(x: Value, y: Value, z: Value, ?w: Value);
 	VVector(x: Value, y: Value, z: Value, ?w: Value);

+ 17 - 15
hrt/prefab/l3d/Decal.hx

@@ -133,19 +133,21 @@ class Decal extends Object3D {
 
 
 	override function setSelected( ctx : Context, b : Bool ) {
 	override function setSelected( ctx : Context, b : Bool ) {
 		if( b ) {
 		if( b ) {
-			var obj = ctx.shared.contexts.get(this).local3d;
-			var wire = new h3d.scene.Box(0xFFFFFFFF,obj);
-			wire.name = "_highlight";
-			wire.material.setDefaultProps("ui");
-			wire.ignoreCollide = true;
-			wire.material.shadows = false;
-			var wireCenter = new h3d.scene.Box(0xFFFF00, obj);
-			wireCenter.scaleZ = 0;
-			wireCenter.name = "_highlight";
-			wireCenter.material.setDefaultProps("ui");
-			wireCenter.ignoreCollide = true;
-			wireCenter.material.shadows = false;
-			wireCenter.material.mainPass.depthTest = Always;
+			var obj = ctx.shared.getSelfObject(this);
+			if(obj != null) {
+				var wire = new h3d.scene.Box(0xFFFFFFFF,obj);
+				wire.name = "_highlight";
+				wire.material.setDefaultProps("ui");
+				wire.ignoreCollide = true;
+				wire.material.shadows = false;
+				var wireCenter = new h3d.scene.Box(0xFFFF00, obj);
+				wireCenter.scaleZ = 0;
+				wireCenter.name = "_highlight";
+				wireCenter.material.setDefaultProps("ui");
+				wireCenter.ignoreCollide = true;
+				wireCenter.material.shadows = false;
+				wireCenter.material.mainPass.depthTest = Always;
+			}
 		} else {
 		} else {
 			clearSelection( ctx );
 			clearSelection( ctx );
 		}
 		}
@@ -153,8 +155,8 @@ class Decal extends Object3D {
 	}
 	}
 
 
 	function clearSelection( ctx : Context ) {
 	function clearSelection( ctx : Context ) {
-
-		var obj = ctx.shared.contexts.get(this).local3d;
+		var obj = ctx.shared.getSelfObject(this);
+		if(obj == null) return;
 		var objs = obj.findAll( o -> if(o.name == "_highlight") o else null );
 		var objs = obj.findAll( o -> if(o.name == "_highlight") o else null );
 		for( o in objs )
 		for( o in objs )
 			o.remove();
 			o.remove();

+ 2 - 1
hrt/prefab/l3d/Spline.hx

@@ -380,7 +380,7 @@ class Spline extends Object3D {
 				t += 1./step;
 				t += 1./step;
 			}
 			}
 			if (nextP.getPoint().distance(samples[samples.length - 1].pos) >= 1./step)
 			if (nextP.getPoint().distance(samples[samples.length - 1].pos) >= 1./step)
-				samples.insert(samples.length, { pos : nextP.getPoint(), tangent : nextP.getTangent(), prev : curP, next : nextP, t : 1.0 });
+				samples.insert(samples.length, { pos : nextP.getPoint(), tangent : nextP.getTangent(), prev : curP, next : nextP });
 			curP = points[i];
 			curP = points[i];
 			nextP = points[(i + 1) % points.length];
 			nextP = points[(i + 1) % points.length];
 
 
@@ -397,6 +397,7 @@ class Spline extends Object3D {
 			samples[i].t = l/lengthSum;
 			samples[i].t = l/lengthSum;
 			l += samples[i].pos.distance(samples[i+1].pos);
 			l += samples[i].pos.distance(samples[i+1].pos);
 		}
 		}
+		samples[samples.length - 1].t = 1;
 		sd.length = lengthSum;
 		sd.length = lengthSum;
 	}
 	}
 
 

+ 0 - 167
hrt/prefab/pbr/ParticleLit.hx

@@ -1,167 +0,0 @@
-package hrt.prefab.pbr;
-
-import hrt.shader.CurvedNormal;
-import hrt.prefab.fx.Emitter;
-import hrt.shader.ParticleForward;
-
-class BackLightingFlat extends hxsl.Shader {
-	static var SRC = {
-
-		@param var backLightingValue : Float;
-		var backLightingIntensity : Float;
-
-		function vertex() {
-			backLightingIntensity = backLightingValue;
-		}
-	};
-}
-
-class BackLightingMask extends hxsl.Shader {
-	static var SRC = {
-
-		@const var VERTEX : Bool;
-		@param var backLightingTexture : Sampler2D;
-		@param var backLightingValue : Float;
-		var backLightingIntensity : Float;
-		var calculatedUV : Vec2;
-
-		function vertex() {
-			if( VERTEX ) {
-				backLightingIntensity = backLightingTexture.get(calculatedUV).r * backLightingValue;
-			}
-		}
-
-		function fragment() {
-			if( !VERTEX ) {
-				backLightingIntensity = backLightingTexture.get(calculatedUV).r * backLightingValue;
-			}
-		}
-	};
-}
-
-class ParticleLit extends Prefab {
-
-	@:s public var directLightingIntensity : Float = 1.0;
-	@:s public var indirectLightingIntensity : Float = 1.0;
-	@:s public var vertexShader : Bool = true;
-	@:s public var backLightingIntensity : Float = 0.0;
-	@:s public var backLightingMask : String = null;
-	@:s public var curvature : Float = 0.0;
-
-	@:s public var normalFlipY : Bool;
-	@:s public var normalFlipX : Bool;
-	@:s public var normalMap : String = null;
-	@:s public var normalIntensity : Float = 1.0;
-
-	public function new(?parent) {
-		super(parent);
-		type = "particleLit";
-	}
-
-	override function makeInstance( ctx : Context ):Context {
-		ctx = ctx.clone(this);
-		refreshShaders(ctx);
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	function refreshShaders( ctx : Context ) {
-
-		var pf = new ParticleForward();
-		var cn = new CurvedNormal();
-		var bl = backLightingMask != null && ctx.loadTexture(backLightingMask) != null ? new BackLightingMask() : new BackLightingFlat();
-		var o = ctx.local3d;
-
-		for( m in o.getMaterials() ) {
-
-			m.mainPass.removeShader(m.mainPass.getShader(ParticleForward));
-			m.mainPass.removeShader(m.mainPass.getShader(CurvedNormal));
-			m.mainPass.removeShader(m.mainPass.getShader(BackLightingMask));
-			m.mainPass.removeShader(m.mainPass.getShader(BackLightingFlat));
-
-			if( m.mainPass.name != "forward" )
-				continue;
-
-			m.mainPass.addShader(bl);
-			m.mainPass.addShader(pf);
-			m.mainPass.addShader(cn);
-		}
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		for( m in ctx.local3d.getMaterials() ) {
-			var pf = m.mainPass.getShader(ParticleForward);
-			if( pf != null ) {
-				pf.VERTEX = vertexShader;
-				pf.indirectLightingIntensity = indirectLightingIntensity;
-				pf.directLightingIntensity = directLightingIntensity;
-				pf.normalMap = normalMap == null ? null : ctx.loadTexture(normalMap);
-				pf.normalIntensity = normalIntensity;
-				pf.NORMAL = pf.normalMap != null;
-				pf.NORMAL_FLIP_Y = normalFlipY;
-				pf.NORMAL_FLIP_X = normalFlipX;
-				pf.hl2_basis0.set(-1.0 / hxd.Math.sqrt(6.0), -1.0 / hxd.Math.sqrt(3.0), 1.0 / hxd.Math.sqrt(3.0));
-				pf.hl2_basis1.set(-1.0 / hxd.Math.sqrt(6.0), 1.0 / hxd.Math.sqrt(2.0), 1.0 / hxd.Math.sqrt(3.0));
-				pf.hl2_basis2.set(hxd.Math.sqrt(2.0/3.0), 0.0, 1.0 / hxd.Math.sqrt(3.0));
-			}
-			var cn = m.mainPass.getShader(CurvedNormal);
-			if( cn != null ) {
-				cn.VERTEX = vertexShader;
-				cn.curvature = curvature;
-			}
-			var bl = m.mainPass.getShader(BackLightingFlat);
-			if( bl != null ) {
-				bl.backLightingValue = backLightingIntensity;
-			}
-			var blm = m.mainPass.getShader(BackLightingMask);
-			if( blm != null ) {
-				blm.VERTEX = vertexShader;
-				blm.backLightingValue = backLightingIntensity;
-				blm.backLightingTexture = ctx.loadTexture(backLightingMask);
-			}
-		}
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { 	icon : "cube",
-					name : "ParticleLit",
-					allowParent : function(p) return Std.is(p, Emitter)  };
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var props = new hide.Element('
-			<div class="group" name="Particle Lit">
-				<dl>
-					<dt>Vertex Shader</dt><dd><input type="checkbox" field="vertexShader"/></dd>
-					<dt>Curvature</dt><dd><input type="range" min="0.0" max="1.0" field="curvature"/></dd>
-					<dt>Direct Intensity</dt><dd><input type="range" min="0.0" max="1.0" field="directLightingIntensity"/></dd>
-					<dt>Indirect Intensity</dt><dd><input type="range" min="0.0" max="1.0" field="indirectLightingIntensity"/></dd>
-				</dl>
-			</div>
-			<div class="group" name="Back Lighting">
-				<dl>
-					<dt>Intensity</dt><dd><input type="range" min="0.0" max="1.0" field="backLightingIntensity"/></dd>
-					<dt>Mask</dt><dd><input type="texturepath" field="backLightingMask"/>
-				</dl>
-			</div>
-			<div class="group" name="Normal Mapping">
-				<dl>
-					<dt>Texture</dt><dd><input type="texturepath" field="normalMap"/>
-					<dt>Intensity</dt><dd><input type="range" min="0.0" max="1.0" field="normalIntensity"/></dd>
-					<dt>Flip Y</dt><dd><input type="checkbox" field="normalFlipY"/></dd>
-					<dt>Flip X</dt><dd><input type="checkbox" field="normalFlipX"/></dd>
-				</dl>
-			</div>
-		');
-
-		ctx.properties.add(props, this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-	#end
-
-	static var _ = Library.register("particleLit", ParticleLit);
-}

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

@@ -14,11 +14,7 @@ class RendererFX extends Prefab implements h3d.impl.RendererFX {
 	}
 	}
 
 
 	inline function checkEnabled() {
 	inline function checkEnabled() {
-		#if editor
-		return enableInEditor;
-		#else
-		return true;
-		#end
+		return enabled #if editor && enableInEditor #end;
 	}
 	}
 
 
 	#if editor
 	#if editor

+ 6 - 5
hrt/prefab/rfx/SSR.hx

@@ -14,7 +14,7 @@ class SSRShader extends hxsl.Shader {
 
 
 		@global var depthMap:Channel;
 		@global var depthMap:Channel;
 
 
-		@param var hdrMap:Sampler2D;
+		@param var ldrMap:Sampler2D;
 
 
 		@param var maxRayDistance : Float;
 		@param var maxRayDistance : Float;
 		@param var stepsFirstPass : Int;
 		@param var stepsFirstPass : Int;
@@ -76,7 +76,7 @@ class SSRShader extends hxsl.Shader {
 			var fragmentColor = vec3(0.0, 0.0, 0.0);
 			var fragmentColor = vec3(0.0, 0.0, 0.0);
 			var alpha = 0.0;
 			var alpha = 0.0;
 			if (hitFirstPass && hitSecondPass) {
 			if (hitFirstPass && hitSecondPass) {
-				fragmentColor = hdrMap.get(curPos).rgb;
+				fragmentColor = ldrMap.get(curPos).rgb;
 				alpha = 1.0 - (curPosWS - transformedPosition).length() / maxRayDistance;
 				alpha = 1.0 - (curPosWS - transformedPosition).length() / maxRayDistance;
 			}
 			}
 
 
@@ -104,10 +104,11 @@ class SSR extends RendererFX {
 		if( step == Lighting ) {
 		if( step == Lighting ) {
 			r.mark("SSR");
 			r.mark("SSR");
 
 
-			var hdrCopy = r.allocTarget("hdrMapCopy", false, 0.5);
-			h3d.pass.Copy.run(r.ctx.getGlobal("hdrMap"), hdrCopy);
+			var ldrCopy = r.allocTarget("ldrMapCopy", false, 0.5);
+			var ldr = r.ctx.getGlobal("ldrMap");
+			h3d.pass.Copy.run(ldr, ldrCopy);
 
 
-			ssrShader.hdrMap = hdrCopy;
+			ssrShader.ldrMap = ldrCopy;
 			ssrShader.maxRayDistance = maxRayDistance;
 			ssrShader.maxRayDistance = maxRayDistance;
 			ssrShader.stepsFirstPass = stepsFirstPass;
 			ssrShader.stepsFirstPass = stepsFirstPass;
 			ssrShader.stepsSecondPass = stepsSecondPass;
 			ssrShader.stepsSecondPass = stepsSecondPass;

+ 1 - 0
hrt/prefab/terrain/Tile.hx

@@ -69,6 +69,7 @@ class Tile extends h3d.scene.Mesh {
 		shader = new hrt.shader.Terrain();
 		shader = new hrt.shader.Terrain();
 		material.mainPass.addShader(shader);
 		material.mainPass.addShader(shader);
 		material.mainPass.culling = Back;
 		material.mainPass.culling = Back;
+		material.staticShadows = true;
 		material.mainPass.setPassName("terrain");
 		material.mainPass.setPassName("terrain");
 		material.mainPass.stencil = new h3d.mat.Stencil();
 		material.mainPass.stencil = new h3d.mat.Stencil();
 		material.mainPass.stencil.setFunc(Always, 0x01, 0xFF, 0xFF);
 		material.mainPass.stencil.setFunc(Always, 0x01, 0xFF, 0xFF);