瀏覽代碼

delete non-core prefabs

Nicolas Cannasse 4 年之前
父節點
當前提交
ba46dbed3d
共有 83 個文件被更改,包括 0 次插入22137 次删除
  1. 0 668
      hide/prefab/PolygonEditor.hx
  2. 0 590
      hide/prefab/SplineEditor.hx
  3. 0 136
      hide/prefab/terrain/Brush.hx
  4. 0 31
      hide/prefab/terrain/ClampWeight.hx
  5. 0 21
      hide/prefab/terrain/CustomRenderer.hx
  6. 0 27
      hide/prefab/terrain/CustomUV.hx
  7. 0 29
      hide/prefab/terrain/GenerateIndex.hx
  8. 0 25
      hide/prefab/terrain/NormalizeWeight.hx
  9. 0 17
      hide/prefab/terrain/SetHeight.hx
  10. 0 27
      hide/prefab/terrain/SmoothHeight.hx
  11. 0 91
      hide/prefab/terrain/StrokeBuffer.hx
  12. 0 40
      hide/prefab/terrain/SwapIndex.hx
  13. 0 1231
      hide/prefab/terrain/TerrainEditor.hx
  14. 0 1782
      hide/view/FXEditor.hx
  15. 0 445
      hide/view/l3d/LightProbeBaker.hx
  16. 0 40
      hide/view/l3d/ProbeBakerProcess.hx
  17. 0 385
      hrt/prefab/Curve.hx
  18. 0 46
      hrt/prefab/ShaderGraph.hx
  19. 0 102
      hrt/prefab/fx/AnimEvent.hx
  20. 0 186
      hrt/prefab/fx/BaseFX.hx
  21. 0 1722
      hrt/prefab/fx/Emitter.hx
  22. 0 113
      hrt/prefab/fx/Evaluator.hx
  23. 0 66
      hrt/prefab/fx/Event.hx
  24. 0 485
      hrt/prefab/fx/FX.hx
  25. 0 300
      hrt/prefab/fx/FX2D.hx
  26. 0 216
      hrt/prefab/fx/FXScript.hx
  27. 0 476
      hrt/prefab/fx/FXScriptParser.hx
  28. 0 155
      hrt/prefab/fx/LookAt.hx
  29. 0 17
      hrt/prefab/fx/Value.hx
  30. 0 84
      hrt/prefab/l2d/Anim2D.hx
  31. 0 110
      hrt/prefab/l2d/Atlas.hx
  32. 0 95
      hrt/prefab/l2d/Bitmap.hx
  33. 0 101
      hrt/prefab/l2d/Blur.hx
  34. 0 365
      hrt/prefab/l2d/NoiseGenerator.hx
  35. 0 172
      hrt/prefab/l2d/Particle2D.hx
  36. 0 254
      hrt/prefab/l2d/Text.hx
  37. 0 37
      hrt/prefab/l3d/AnimSpeedControl.hx
  38. 0 70
      hrt/prefab/l3d/Box.hx
  39. 0 225
      hrt/prefab/l3d/Camera.hx
  40. 0 62
      hrt/prefab/l3d/Constraint.hx
  41. 0 233
      hrt/prefab/l3d/Decal.hx
  42. 0 185
      hrt/prefab/l3d/Environment.hx
  43. 0 118
      hrt/prefab/l3d/GameController.hx
  44. 0 931
      hrt/prefab/l3d/HeightMap.hx
  45. 0 18
      hrt/prefab/l3d/Level3D.hx
  46. 0 718
      hrt/prefab/l3d/MeshGenerator.hx
  47. 0 1076
      hrt/prefab/l3d/MeshSpray.hx
  48. 0 205
      hrt/prefab/l3d/Particles3D.hx
  49. 0 451
      hrt/prefab/l3d/Polygon.hx
  50. 0 575
      hrt/prefab/l3d/Spline.hx
  51. 0 322
      hrt/prefab/l3d/SplineMesh.hx
  52. 0 265
      hrt/prefab/l3d/Text3D.hx
  53. 0 63
      hrt/prefab/l3d/Trail.hx
  54. 0 172
      hrt/prefab/pbr/Anisotropy.hx
  55. 0 154
      hrt/prefab/pbr/SpecularColor.hx
  56. 0 65
      hrt/prefab/rfx/AutoExposure.hx
  57. 0 77
      hrt/prefab/rfx/Bloom.hx
  58. 0 151
      hrt/prefab/rfx/CloudShadow.hx
  59. 0 103
      hrt/prefab/rfx/ColorGrading.hx
  60. 0 274
      hrt/prefab/rfx/Configurator.hx
  61. 0 135
      hrt/prefab/rfx/DistanceBlur.hx
  62. 0 51
      hrt/prefab/rfx/Distortion.hx
  63. 0 231
      hrt/prefab/rfx/FrustumJitter.hx
  64. 0 245
      hrt/prefab/rfx/GenFog.hx
  65. 0 144
      hrt/prefab/rfx/SSR.hx
  66. 0 110
      hrt/prefab/rfx/Sao.hx
  67. 0 265
      hrt/prefab/rfx/ScreenShaderGraph.hx
  68. 0 61
      hrt/prefab/rfx/Sharpen.hx
  69. 0 192
      hrt/prefab/rfx/TemporalBloom.hx
  70. 0 247
      hrt/prefab/rfx/TemporalFiltering.hx
  71. 0 67
      hrt/prefab/rfx/Vignetting.hx
  72. 0 35
      hrt/prefab/terrain/PackWeight.hx
  73. 0 67
      hrt/prefab/terrain/Surface.hx
  74. 0 626
      hrt/prefab/terrain/Terrain.hx
  75. 0 296
      hrt/prefab/terrain/TerrainMesh.hx
  76. 0 148
      hrt/prefab/terrain/TerrainResize.hx
  77. 0 462
      hrt/prefab/terrain/Tile.hx
  78. 0 22
      hrt/prefab/terrain/UnpackWeight.hx
  79. 0 733
      hrt/prefab/vlm/LightProbe.hx
  80. 0 310
      hrt/prefab/vlm/ProbeBaker.hx
  81. 0 17
      hrt/prefab/vlm/SphericalHarmonic.hx
  82. 0 297
      hrt/prefab/vlm/VolumetricLightmap.hx
  83. 0 176
      hrt/prefab/vlm/VolumetricMesh.hx

+ 0 - 668
hide/prefab/PolygonEditor.hx

@@ -1,668 +0,0 @@
-package hide.prefab;
-import hxd.Key as K;
-import hrt.prefab.Context;
-
-enum ColorState{
-	None;
-	Overlapped;
-	OverlappedForDelete;
-	Selected;
-}
-
-class Edge{
-	public var p1 : h2d.col.Point;
-	public var p2 : h2d.col.Point;
-	public function new(p1, p2){
-		this.p1 = p1;
-		this.p2 = p2;
-	}
-}
-
-class SphereHandle extends h3d.scene.Mesh {
-	public function new(prim, mat, parent) {
-		super(prim, mat, parent);
-	}
-
-	var tmp = new h3d.Vector();
-	override function sync(ctx:h3d.scene.RenderContext) {
-		var cam = ctx.camera;
-		var gpos = getAbsPos().getPosition();
-		var distToCam = cam.pos.sub(gpos).length();
-		var engine = h3d.Engine.getCurrent();
-		var ratio = 18 / engine.height;
-		// Ignore parent scale
-		parent.getAbsPos().getScale(tmp);
-		var scale = ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0);
-		scaleX = scale / tmp.x;
-		scaleY = scale / tmp.y;
-		scaleZ = scale / tmp.z;
-		calcAbsPos();
-		super.sync(ctx);
-	}
-}
-
-class MovablePoint {
-
-	public var showDebug : Bool;
-	public var point : h2d.col.Point;
-	var mesh: h3d.scene.Mesh;
-	public var colorState = None;
-	var localPosText : h2d.ObjectFollower;
-	var worldPosText : h2d.ObjectFollower;
-
-	public function new(point : h2d.col.Point, ctx : Context){
-		this.point = point;
-		mesh = new SphereHandle(h3d.prim.Cube.defaultUnitCube(), null, ctx.local3d);
-		mesh.name = "_movablePoint";
-		mesh.material.setDefaultProps("ui");
-		mesh.material.mainPass.depthTest = Always;
-		mesh.scale(0.1);
-		mesh.setPosition(point.x, point.y, 0);
-		localPosText = createText(ctx);
-		worldPosText = createText(ctx);
-		worldPosText.offsetZ = (0.3);
-		localPosText.offsetZ = (0.6);
-		updateText(ctx);
-	}
-
-	function createText(ctx : Context){
-		var o = new h2d.ObjectFollower(mesh,  @:privateAccess ctx.local2d.getScene());
-		var t = new h2d.Text(hxd.res.DefaultFont.get(), o);
-		t.textColor = 0xFFFFFF;
-		t.textAlign = Center;
-		t.dropShadow = { dx : 1.5, dy : 1.5, color : 0x202020, alpha : 1.0 };
-		return o;
-	}
-
-	public function dispose(){
-		mesh.remove();
-		worldPosText.remove();
-		localPosText.remove();
-	}
-
-	function worldToScreen(wx: Float, wy: Float, wz: Float, ctx : Context) {
-		var s2d = @:privateAccess ctx.local2d.getScene();
-		var camera = @:privateAccess ctx.local3d.getScene().camera;
-		camera.update();
-		var pt = camera.project(wx, wy, wz, s2d.width, s2d.height);
-		return new h2d.col.Point( pt.x, pt.y);
-	}
-
-	public function updateText(ctx : Context){
-		inline function getText(o) : h2d.Text{
-			return Std.downcast(o.getChildAt(0), h2d.Text);
-		}
-		getText(localPosText).visible = showDebug;
-		getText(worldPosText).visible = showDebug;
-		var pointWorldPos = new h3d.col.Point(point.x, point.y, 0.);
-		ctx.local3d.localToGlobal(pointWorldPos);
-		getText(localPosText).text = "Local : " + untyped point.x.toFixed(3) + " / " + untyped point.y.toFixed(3);
-		getText(worldPosText).text = "World : " + untyped pointWorldPos.x.toFixed(3) + " / " + untyped pointWorldPos.y.toFixed(3) + " / " + untyped pointWorldPos.z.toFixed(3);
-	}
-
-	public function updateColor(){
-		switch(colorState){
-			case None : mesh.material.color.set(0,0,0);
-			case Overlapped : mesh.material.color.set(1,1,0);
-			case OverlappedForDelete : mesh.material.color.set(1,0,0);
-			case Selected : mesh.material.color.set(0,0,1);
-		}
-	}
-
-	public function interset(ray : h3d.col.Ray) : Bool{
-		return mesh.getCollider().rayIntersection(ray, false) != -1;
-	}
-
-	public function setColorState(s : ColorState){
-		colorState = s;
-	}
-}
-
-class PolygonEditor {
-
-	public var editContext : EditContext;
-	public var showDebug : Bool;
-	public var gridSize = 1;
-	public var showTriangles : Bool = false;
-	public var worldSnap = false;
-
-	var polygonPrefab : hrt.prefab.l3d.Polygon;
-	var undo : hide.ui.UndoHistory;
-	var interactive : h2d.Interactive;
-	var lineGraphics : h3d.scene.Graphics;
-	var triangleGraphics : h3d.scene.Graphics;
-	var movablePoints : Array<MovablePoint> = [];
-	var selectedPoints : Array<h2d.col.Point> = [];
-	var lastPointSelected : h2d.col.Point;
-	var lastPos : h3d.col.Point;
-	var selectedEdge : Edge;
-	var selectedEdgeGraphic : h3d.scene.Graphics;
-	//var lastClickStamp = 0.0;
-	var editMode = false;
-
-	// Temp container for Undo
-	var beforeMoveList : Array<h2d.col.Point> = [];
-	var afterMoveList : Array<h2d.col.Point> = [];
-
-	public function new( polygonPrefab , undo : hide.ui.UndoHistory ){
-		this.polygonPrefab = polygonPrefab;
-		this.undo = undo;
-	}
-
-	public function dispose(){
-		reset();
-	}
-
-	function removeGraphics(g : h3d.scene.Graphics){
-		if(g != null){
-			g.clear();
-			g.remove();
-		}
-	}
-
-	public function reset(){
-		clearMovablePoints();
-		clearSelectedPoint();
-		if(interactive != null) interactive.remove();
-		removeGraphics(lineGraphics);
-		removeGraphics(selectedEdgeGraphic);
-		removeGraphics(triangleGraphics);
-	}
-
-	inline function getContext(){
-		return editContext.getContext(polygonPrefab);
-	}
-
-	inline function refreshInteractive() {
-		editContext.scene.editor.refreshInteractive(polygonPrefab);
-	}
-
-	public function update( ?propName : String) {
-		if(propName == "showDebug"){
-			for(mp in movablePoints){
-				mp.showDebug = showDebug;
-				mp.updateText(getContext());
-			}
-		}
-		else if(propName == "showTriangles") {
-			drawTriangles(showTriangles);
-		}
-		else if(propName == "editMode") {
-			setSelected(getContext(), true);
-		} else {
-			refreshInteractive();
-		}
-	}
-
-	function copyArray(array : Array<h2d.col.Point>){
-		var copy : Array<h2d.col.Point> = [];
-		for(p in array)
-		copy.push(p.clone());
-		return copy;
-	}
-
-	function addUndo( prev : Array<h2d.col.Point>, next : Array<h2d.col.Point>){
-		undo.change(Custom(function(undo) {
-			var prevList = prev;
-			var newList = next;
-			if(undo)
-				polygonPrefab.points = prevList;
-			else
-				polygonPrefab.points = newList;
-			refreshPolygon();
-		}));
-	}
-
-	function refreshPolygon(withProps=false) {
-		if(!polygonPrefab.points.isClockwise())
-			polygonPrefab.points.reverse();  // Ensure poly is always clockwise
-
-		var polyPrim = polygonPrefab.generateCustomPolygon();
-		var mesh : h3d.scene.Mesh = cast getContext().local3d;
-		mesh.primitive = polyPrim;
-		refreshEditorDisplay(withProps);
-	}
-
-	function refreshDebugDisplay(){
-		for(mp in movablePoints)
-			mp.updateText(getContext());
-	}
-
-	function clearSelectedPoint(){
-		selectedPoints.splice(0, selectedPoints.length);
-		lastPointSelected = null;
-	}
-
-	function isAlreadySelected( p : h2d.col.Point ) : Bool {
-		if( p == null) return false;
-		for( point in selectedPoints )
-			if( point == p ) return true;
-		return false;
-	}
-
-	function addSelectedPoint( p : h2d.col.Point ){
-		if( p == null) return;
-		for( point in selectedPoints )
-			if( point == p ) return;
-		selectedPoints.push(p);
-	}
-
-	function removePoint( p : h2d.col.Point) {
-		polygonPrefab.points.remove(p);
-		refreshPolygon();
-	}
-
-	function addPointOnEdge( pos: h2d.col.Point, e : Edge) {
-		if(e == null){
-			polygonPrefab.points.points.push(pos);
-			return;
-		}
-		function findIndex(p) : Int {
-			for(i in 0 ... polygonPrefab.points.length)
-				if( p == polygonPrefab.points[i])
-					return i;
-			return -1;
-		}
-		var i1 = findIndex(e.p1);
-		var i2 = findIndex(e.p2);
-		if( hxd.Math.abs(i1 - i2) > 1 )
-			polygonPrefab.points.points.push(pos);
-		else
-			polygonPrefab.points.points.insert(Std.int(hxd.Math.max(i1,i2)), pos);
-		refreshPolygon();
-	}
-
-	function projectToGround( ray: h3d.col.Ray) {
-		var minDist = -1.;
-		var normal = getContext().local3d.getAbsPos().up();
-		var plane = h3d.col.Plane.fromNormalPoint(normal.toPoint(), new h3d.col.Point(getContext().local3d.getAbsPos().tx, getContext().local3d.getAbsPos().ty, getContext().local3d.getAbsPos().tz));
-		var pt = ray.intersect(plane);
-		if(pt != null) { minDist = pt.sub(ray.getPos()).length();}
-		return minDist;
-	}
-
-	function screenToWorld( u : Float, v : Float ) {
-		var camera = @:privateAccess getContext().local3d.getScene().camera;
-		var ray = camera.rayFromScreen(u, v);
-		var dist = projectToGround(ray);
-		return dist >= 0 ? ray.getPoint(dist) : null;
-	}
-
-	function trySelectPoint( ray: h3d.col.Ray ) : MovablePoint {
-		for(mp in movablePoints)
-			if(mp.interset(ray))
-				return mp;
-		return null;
-	}
-
-	function trySelectEdge( pos : h2d.col.Point ) : Edge {
-		inline function crossProduct( a : h2d.col.Point, b : h2d.col.Point ){
-			return a.x * b.y - a.y * b.x;
-		}
-		inline function dist(s1 : h2d.col.Point, s2 : h2d.col.Point, p : h2d.col.Point){
-			var l = s2.distance(s1);
-			l = l * l;
-			if(l == 0) return p.distance(s1);
-			var t = hxd.Math.max(0, hxd.Math.min(1, p.sub(s1).dot(s2.sub(s1)) / l));
-			var proj = s1.add((s2.sub(s1).multiply(t)));
-			return p.distance(proj);
-		}
-		if(polygonPrefab.points.length < 2) return null;
-		var minDist = dist(polygonPrefab.points[0], polygonPrefab.points[polygonPrefab.points.length - 1], pos);
-		var edge : Edge = new Edge(polygonPrefab.points[0],polygonPrefab.points[polygonPrefab.points.length - 1]);
-		for(i in 1 ... polygonPrefab.points.length){
-			var p1 = polygonPrefab.points[i-1];
-			var p2 = polygonPrefab.points[i];
-			var dist = dist(p1, p2, pos);
-			if(dist < minDist){
-				edge.p1 = p1;
-				edge.p2 = p2;
-				minDist = dist;
-			}
-		}
-		return edge;
-	}
-
-	function getFinalPos( mouseX, mouseY ){
-		var worldPos = screenToWorld(mouseX, mouseY);
-		var localPos = getContext().local3d.globalToLocal(worldPos);
-		if( K.isDown( K.CTRL ) ){ // Snap To Grid with Ctrl
-			var gridPos = new h3d.col.Point();
-			if( worldSnap ){
-				var absPos = getContext().local3d.getAbsPos();
-				worldPos = getContext().local3d.localToGlobal(worldPos);
-				gridPos.x = hxd.Math.round(localPos.x / gridSize) * gridSize;
-				gridPos.y = hxd.Math.round(localPos.y / gridSize) * gridSize;
-				gridPos.z = hxd.Math.round(localPos.z / gridSize) * gridSize;
-				gridPos = getContext().local3d.globalToLocal(gridPos);
-			}
-			else{
-				gridPos.x = hxd.Math.round(worldPos.x / gridSize) * gridSize;
-				gridPos.y = hxd.Math.round(worldPos.y / gridSize) * gridSize;
-				gridPos.z = hxd.Math.round(worldPos.z / gridSize) * gridSize;
-			}
-			localPos = gridPos;
-		}
-		return localPos;
-	}
-
-	public function setSelected( ctx : Context, b : Bool ) {
-		reset();
-		if(!editMode) return;
-		if(b){
-			var s2d = @:privateAccess ctx.local2d.getScene();
-			interactive = new h2d.Interactive(10000, 10000, s2d);
-			interactive.propagateEvents = true;
-			interactive.cancelEvents = false;
-			lineGraphics = new h3d.scene.Graphics(ctx.local3d);
-			lineGraphics.lineStyle(2, 0xFFFFFF);
-			lineGraphics.material.mainPass.setPassName("overlay");
-			lineGraphics.material.mainPass.depth(false, LessEqual);
-			selectedEdgeGraphic = new h3d.scene.Graphics(ctx.local3d);
-			selectedEdgeGraphic.lineStyle(3, 0xFFFF00, 0.5);
-			selectedEdgeGraphic.material.mainPass.setPassName("overlay");
-			selectedEdgeGraphic.material.mainPass.depth(false, LessEqual);
-			triangleGraphics = new h3d.scene.Graphics(ctx.local3d);
-			triangleGraphics.lineStyle(2, 0xFF0000);
-			triangleGraphics.material.mainPass.setPassName("overlay");
-			triangleGraphics.material.mainPass.depth(false, LessEqual);
-
-			refreshEditorDisplay();
-			drawTriangles(showTriangles);
-
-			interactive.onWheel = function(e) {
-				refreshDebugDisplay();
-			};
-			interactive.onKeyDown =
-			function(e) {
-				e.propagate = false;
-				if( K.isDown( K.SHIFT ) ){
-					clearSelectedPoint();
-					var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
-					refreshMovablePoints(ray);
-					if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY);
-					refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y));
-				}
-			}
-			interactive.onKeyUp =
-			function(e) {
-				e.propagate = false;
-				var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
-				refreshMovablePoints(ray);
-				if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY);
-				refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y));
-			}
-			interactive.onPush =
-			function(e) {
-				var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY);
-				var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
-				if( K.isDown( K.MOUSE_LEFT ) ){
-					e.propagate = false;
-					// Shift + Left Click : Remove Point
-					if( K.isDown( K.SHIFT ) ){
-						var mp = trySelectPoint(ray);
-						if(mp != null){
-							var prevList = copyArray(polygonPrefab.points.points);
-							removePoint(mp.point);
-							var newList = copyArray(polygonPrefab.points.points);
-							addUndo(prevList, newList);
-						}
-					}
-					else {
-						// Left Click : Add/Set selected point / Clear selection
-						lastPos = finalPos.clone();
-						var mp = trySelectPoint(ray);
-						if(mp != null){
-							if( K.isDown(K.ALT) && !isAlreadySelected(mp.point))
-									addSelectedPoint(mp.point);
-							lastPointSelected = mp.point;
-							beforeMoveList = copyArray(polygonPrefab.points.points);
-						}
-						// Double Left Click : Create point
-						else{
-							clearSelectedPoint();
-							if(K.isDown(K.CTRL)) {
-							// var curStamp = haxe.Timer.stamp();
-							// var diff = curStamp - lastClickStamp;
-							// if(diff < 0.2){
-								var prevList = copyArray(polygonPrefab.points.points);
-								var pt = new h2d.col.Point(finalPos.x, finalPos.y);
-								addPointOnEdge(pt, selectedEdge);
-								var newList = copyArray(polygonPrefab.points.points);
-								addUndo(prevList, newList);
-								refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y));
-								// Select new point
-								lastPointSelected = pt;
-							}
-							//lastClickStamp = curStamp;
-						}
-						refreshMovablePoints();
-					}
-				}
-			};
-			interactive.onRelease =
-			function(e) {
-				//lastPos = null;
-				lastPointSelected = null;
-				if( beforeMoveList != null ){
-					afterMoveList = copyArray(polygonPrefab.points.points);
-					addUndo(beforeMoveList, afterMoveList);
-					beforeMoveList = null;
-					afterMoveList = null;
-				}
-			};
-			interactive.onMove =
-			function(e) {
-				var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
-				var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY);
-				refreshMovablePoints(ray);
-				refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y));
-				if( K.isDown( K.MOUSE_LEFT )){
-					var move : h2d.col.Point = null;
-					var pos = new h2d.col.Point(finalPos.x, finalPos.y);
-					if(lastPointSelected != null){
-						move = pos.sub(lastPointSelected);
-						lastPointSelected.load(pos);
-						for(p in selectedPoints){
-							if(lastPointSelected == p) continue;
-							p.x += move.x; p.y += move.y;
-						}
-					}
-					refreshMovablePoints();
-					refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y));
-					refreshPolygon(false);
-					lastPos = finalPos.clone();
-				}
-				else
-					refreshDebugDisplay();
-			};
-		}
-		else
-			editMode = false;
-	}
-
-	function refreshSelectedEdge( pos : h2d.col.Point ){
-		selectedEdge = trySelectEdge(pos);
-		selectedEdgeGraphic.clear();
-		if(K.isDown( K.SHIFT ) )
-			return;
-		if(selectedEdge != null){
-			selectedEdgeGraphic.moveTo(selectedEdge.p1.x, selectedEdge.p1.y, 0);
-			selectedEdgeGraphic.lineTo(selectedEdge.p2.x, selectedEdge.p2.y, 0);
-		}
-	}
-
-	function drawTriangles( b : Bool ){
-		triangleGraphics.clear();
-		if(b && polygonPrefab.getPrimitive(getContext()) != null){
-			var i = 0;
-			var prim = polygonPrefab.getPrimitive(getContext());
-			while(i < prim.idx.length){
-				triangleGraphics.moveTo(prim.points[prim.idx[i]].x, prim.points[prim.idx[i]].y, 0);
-				triangleGraphics.lineTo(prim.points[prim.idx[i + 1]].x, prim.points[prim.idx[i + 1]].y, 0);
-				triangleGraphics.lineTo(prim.points[prim.idx[i + 2]].x, prim.points[prim.idx[i + 2]].y, 0);
-				triangleGraphics.lineTo(prim.points[prim.idx[i]].x, prim.points[prim.idx[i]].y, 0);
-				i += 3;
-			}
-		}
-	}
-
-	function clearMovablePoints(){
-		for(mp in movablePoints)
-			mp.dispose();
-		movablePoints.splice(0, movablePoints.length);
-	}
-
-	function createMovablePoints(){
-		for(p in polygonPrefab.points){
-			var mp = new MovablePoint(p, getContext());
-			movablePoints.push(mp);
-		}
-	}
-
-	function refreshMovablePoints( ?ray ){
-		for(mp in movablePoints)
-			mp.setColorState(None);
-		if(ray != null){
-			var mp = trySelectPoint(ray);
-			if( mp != null && mp.colorState != Selected)
-				K.isDown( K.SHIFT ) ? mp.setColorState(OverlappedForDelete) : mp.setColorState(Overlapped);
-		}
-		for(p in selectedPoints)
-			for(mp in movablePoints)
-				if(mp.point == p){
-					mp.setColorState(Selected);
-					break;
-				}
-		for(mp in movablePoints){
-			if( mp.point == lastPointSelected) mp.setColorState(Selected);
-			mp.updateColor();
-			mp.showDebug = showDebug;
-			mp.updateText(getContext());
-		}
-	}
-
-	function refreshEditorDisplay(withProps=true) {
-		lineGraphics.clear();
-		clearMovablePoints();
-		if(polygonPrefab.points == null || polygonPrefab.points.length == 0) return;
-		lineGraphics.moveTo(polygonPrefab.points[polygonPrefab.points.length - 1].x, polygonPrefab.points[polygonPrefab.points.length - 1].y, 0);
-		for(p in polygonPrefab.points)
-			lineGraphics.lineTo(p.x, p.y, 0);
-		createMovablePoints();
-		refreshMovablePoints();
-		if(withProps)
-			refreshPointList(editContext.getCurrentProps(polygonPrefab));
-	}
-
-	public function addProps( ctx : EditContext ){
-		var props = new hide.Element('
-		<div class="poly-editor">
-			<div class="group" name="Tool">
-				<div align="center">
-					<input type="button" value="Edit Mode : Disabled" class="editModeButton" />
-				</div>
-				<div class="description">
-					<i>Ctrl + Left Click</i> : Add point on edge <br>
-					<i>Shift + Left Click</i> : Delete selected point <br>
-					Drag with <i>Left Click</i> : Move selected points <br>
-					Drag with <i>Left Click + Ctrl</i> : Move selected points on grid <br>
-					<i>Alt + Left Click</i> : Add point to selection
-				</div>
-				<dt>Show Debug</dt><dd><input type="checkbox" field="showDebug"/></dd>
-				<dt>Show Triangles</dt><dd><input type="checkbox" field="showTriangles"/></dd>
-				<dt>Grid Size</dt><dd><input type="range" min="0" max="10" field="gridSize"/></dd>
-				<dt>World Snap</dt><dd><input type="checkbox" field="worldSnap"/></dd>
-			</div>
-			<div align="center">
-				<div class="group" name="Points">
-					<div class="point-list"> </div>
-					<input type="button" value="Reset" class="reset" />
-				</div>
-			</div>
-		</div>');
-
-		var editModeButton = props.find(".editModeButton");
-		editModeButton.click(function(_) {
-			editMode = !editMode;
-			editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled");
-			editModeButton.toggleClass("editModeEnabled", editMode);
-			setSelected(getContext(), true);
-			if(!editMode)
-				refreshInteractive();
-		});
-
-		props.find(".reset").click(function(_) {
-			var prevList = copyArray(polygonPrefab.points.points);
-			polygonPrefab.points.points.splice(0, polygonPrefab.points.points.length);
-			var nextList = copyArray(polygonPrefab.points.points);
-			addUndo(prevList, nextList);
-			refreshPolygon();
-		});
-
-		refreshPointList(props);
-
-		ctx.properties.add(props, this, function(pname) {ctx.onChange(polygonPrefab, pname); });
-		return props;
-	}
-
-	function refreshPointList( props : hide.Element){
-		var container = props.find(".point-list");
-		container.empty();
-
-		function createVector(p : h2d.col.Point){
-			var v = new Element('<div class="poly-vector2" >');
-			var deleteButton = new Element('<input type="button" value="-" class="deletePoint" />');
-			var fieldX = new Element('<input class="inputX" type="text" name="xfield" minlength="1" maxlength="4">');
-			var fieldY = new Element('<input type="text" name="yfield" minlength="1" maxlength="4">');
-
-			fieldX.val(p.x);
-			fieldY.val(p.y);
-
-			fieldX.on("input", function(_) {
-				var prevValue = p.x;
-				p.x = Std.parseFloat(fieldX.val());
-				var nextValue = p.x;
-				undo.change(Custom(function(undo) {
-					p.x = undo ? prevValue : nextValue;
-					refreshPolygon();
-				}));
-				refreshPolygon();
-			});
-
-			fieldY.on("input", function(_) {
-				var prevValue = p.y;
-				p.y = Std.parseFloat(fieldY.val());
-				var nextValue = p.y;
-				undo.change(Custom(function(undo) {
-					p.y = undo ? prevValue : nextValue;
-					refreshPolygon();
-				}));
-				refreshPolygon();
-			});
-
-			deleteButton.on("click", function(_) {
-				var prevList = copyArray(polygonPrefab.points.points);
-				polygonPrefab.points.points.remove(p);
-				var nextList = copyArray(polygonPrefab.points.points);
-				addUndo(prevList, nextList);
-				refreshPolygon();
-				refreshPointList(props);
-			});
-
-			v.append('<label>X </label>');
-			v.append(fieldX);
-			v.append('<label> Y </label>');
-			v.append(fieldY);
-			v.append(deleteButton);
-			v.append('</div>');
-			container.append(v);
-		}
-
-		if(polygonPrefab.points != null) {
-			for(p in polygonPrefab.points){
-				createVector(p);
-			}
-		}
-	}
-}

+ 0 - 590
hide/prefab/SplineEditor.hx

@@ -1,590 +0,0 @@
-package hide.prefab;
-import hxd.Key as K;
-import hrt.prefab.l3d.Spline;
-
-#if editor
-
-class NewSplinePointViewer extends h3d.scene.Object {
-
-	var pointViewer : h3d.scene.Mesh;
-	var connectionViewer : h3d.scene.Graphics;
-	var tangentViewer : h3d.scene.Graphics;
-
-	public function new( parent : h3d.scene.Object ) {
-		super(parent);
-		name = "SplinePointViewer";
-		pointViewer = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), null, this);
-		pointViewer.name = "pointViewer";
-		pointViewer.material.setDefaultProps("ui");
-		pointViewer.material.color.set(1,1,0,1);
-		pointViewer.material.mainPass.depthTest = Always;
-
-		connectionViewer = new h3d.scene.Graphics(this);
-		connectionViewer.name = "connectionViewer";
-		connectionViewer.lineStyle(3, 0xFFFF00);
-		connectionViewer.material.mainPass.setPassName("ui");
-		connectionViewer.material.mainPass.depthTest = Always;
-		connectionViewer.clear();
-
-		tangentViewer = new h3d.scene.Graphics(this);
-		tangentViewer.name = "tangentViewerViewer";
-		tangentViewer.lineStyle(3, 0xFFFF00);
-		tangentViewer.material.mainPass.setPassName("ui");
-		tangentViewer.material.mainPass.depthTest = Always;
-		tangentViewer.clear();
-	}
-
-	override function sync( ctx : h3d.scene.RenderContext ) {
-		var cam = ctx.camera;
-		var gpos = getAbsPos().getPosition();
-		var distToCam = cam.pos.sub(gpos).length();
-		var engine = h3d.Engine.getCurrent();
-		var ratio = 18 / engine.height;
-		var correctionFromParents =  1.0 / getAbsPos().getScale().x;
-		pointViewer.setScale(correctionFromParents * ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0));
-		calcAbsPos();
-		super.sync(ctx);
-	}
-
-	public function update( spd : SplinePointData ) {
-
-		pointViewer.setPosition(spd.pos.x, spd.pos.y, spd.pos.z);
-
-		tangentViewer.clear();
-		tangentViewer.visible = spd.tangent != null;
-		if( spd.tangent != null ) {
-			var scale = 1.0;
-			if( spd.prev != null && spd.next != null ) scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5;
-			else if( spd.prev != null ) scale = spd.prev.scaleX;
-			else if( spd.next != null ) scale = spd.next.scaleX;
-			tangentViewer.moveTo(spd.pos.x - spd.tangent.x * scale, spd.pos.y - spd.tangent.y * scale, spd.pos.z - spd.tangent.z * scale);
-			tangentViewer.lineTo(spd.pos.x + spd.tangent.x * scale, spd.pos.y + spd.tangent.y * scale, spd.pos.z + spd.tangent.z * scale);
-		}
-
-		// Only display the connection if we are adding the new point at the end or the beggining fo the spline
-		connectionViewer.clear();
-		connectionViewer.visible = spd.prev == null || spd.next == null;
-		if( connectionViewer.visible ) {
-			var startPos = spd.prev == null ? spd.next.getPoint() : spd.prev.getPoint();
-			connectionViewer.moveTo(startPos.x, startPos.y, startPos.z);
-			connectionViewer.lineTo(spd.pos.x, spd.pos.y, spd.pos.z);
-		}
-	}
-}
-
-@:access(hrt.prefab.l3d.Spline)
-class SplineEditor {
-
-	public var prefab : Spline;
-	public var editContext : EditContext;
-	var editMode = false;
-	var undo : hide.ui.UndoHistory;
-
-	var interactive : h2d.Interactive;
-
-	 // Easy way to keep track of viewers
-	var gizmos : Array<hide.view.l3d.Gizmo> = [];
-	var newSplinePointViewer : NewSplinePointViewer;
-
-	public function new( prefab : Spline, undo : hide.ui.UndoHistory ){
-		this.prefab = prefab;
-		this.undo = undo;
-	}
-
-	public function update( ctx : hrt.prefab.Context , ?propName : String ) {
-		if( editMode ) {
-			showViewers();
-		}
-	}
-
-	function reset() {
-		removeViewers();
-		removeGizmos();
-		if( interactive != null ) {
-			interactive.remove();
-			interactive = null;
-		}
-		if( newSplinePointViewer != null ) {
-			newSplinePointViewer.remove();
-			newSplinePointViewer = null;
-		}
-	}
-
-	inline function getContext() {
-		return editContext.getContext(prefab);
-	}
-
-	function getClosestSplinePointFromMouse( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePoint {
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null )
-			return null;
-
-		var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0);
-		var minDist = -1.0;
-		var result : SplinePoint = null;
-		for( sp in prefab.points ) {
-			var screenPos = sp.getPoint().toVector();
-			screenPos.project(ctx.local3d.getScene().camera.m);
-			screenPos.z = 0;
-			screenPos.scale3(0.5);
-			screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
-			var dist = screenPos.distance(mousePos);
-			if( dist < minDist || minDist == -1 ) {
-				minDist = dist;
-				result = sp;
-			}
-		}
-		return result;
-	}
-
-	function getNewPointPosition( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData {
-		if( prefab.points.length == 0 ) {
-			return { pos : ctx.local3d.getAbsPos().getPosition().toPoint(), tangent : ctx.local3d.getAbsPos().right().toPoint() , prev : null, next : null };
-		}
-
-		var closestPt = getClosestPointFromMouse(mouseX, mouseY, ctx);
-
-		// If we are are adding a new point at the beginning/end, just make a raycast 'cursor -> plane' with the transform of the first/last SplinePoint
-		if( !prefab.loop && (closestPt.next == null || closestPt.prev == null) ) {
-			var camera = @:privateAccess ctx.local3d.getScene().camera;
-			var ray = camera.rayFromScreen(mouseX, mouseY);
-			var normal = closestPt.next == null ? closestPt.prev.getAbsPos().up().toPoint() : closestPt.next.getAbsPos().up().toPoint();
-			var point = closestPt.next == null ? closestPt.prev.getAbsPos().getPosition().toPoint() : closestPt.next.getAbsPos().getPosition().toPoint();
-			var plane = h3d.col.Plane.fromNormalPoint(normal, point);
-			var pt = ray.intersect(plane);
-			return { pos : pt, tangent : closestPt.tangent, prev : closestPt.prev, next : closestPt.next };
-		}
-		else
-			return closestPt;
-	}
-
-	function getClosestPointFromMouse( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData {
-
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null )
-			return null;
-
-		var result : SplinePointData = null;
-		var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0);
-		var minDist = -1.0;
-		for( s in prefab.data.samples ) {
-			var screenPos = s.pos.toVector();
-			screenPos.project(ctx.local3d.getScene().camera.m);
-			screenPos.z = 0;
-			screenPos.scale3(0.5);
-			screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
-			var dist = screenPos.distance(mousePos);
-			if( (dist < minDist || minDist == -1) && dist < 0.1 ) {
-				minDist = dist;
-				result = s;
-			}
-		}
-
-		if( result == null ) {
-			result = { pos : null, tangent : null, prev : null, next : null };
-
-			var firstSp = prefab.points[0];
-			var firstPt = firstSp.getPoint();
-			var firstPtScreenPos = firstPt.toVector();
-			firstPtScreenPos.project(ctx.local3d.getScene().camera.m);
-			firstPtScreenPos.z = 0;
-			firstPtScreenPos.scale3(0.5);
-			firstPtScreenPos = firstPtScreenPos.add(new h3d.Vector(0.5,0.5));
-			var distToFirstPoint = firstPtScreenPos.distance(mousePos);
-
-			var lastSp = prefab.points[prefab.points.length - 1];
-			var lastPt = lastSp.getPoint();
-			var lastPtSreenPos = lastPt.toVector();
-			lastPtSreenPos.project(ctx.local3d.getScene().camera.m);
-			lastPtSreenPos.z = 0;
-			lastPtSreenPos.scale3(0.5);
-			lastPtSreenPos = lastPtSreenPos.add(new h3d.Vector(0.5,0.5));
-			var distTolastPoint = lastPtSreenPos.distance(mousePos);
-
-			if( distTolastPoint < distToFirstPoint ) {
-				result.pos = lastPt;
-				result.tangent = lastSp.getAbsPos().right().toPoint();
-				result.prev = prefab.points[prefab.points.length - 1];
-				result.next = null;
-			}
-			else {
-				result.pos = firstPt;
-				result.tangent = firstSp.getAbsPos().right().toPoint();
-				result.prev = null;
-				result.next = prefab.points[0];
-			}
-		}
-
-		return result;
-	}
-
-	function addSplinePoint( spd : SplinePointData, ctx : hrt.prefab.Context ) : SplinePoint {
-
-		var invMatrix = new h3d.Matrix();
-		invMatrix.identity();
-		var o : hrt.prefab.Object3D = prefab;
-		while(o != null) {
-			invMatrix.multiply(invMatrix, o.getTransform());
-			o = o.parent.to(hrt.prefab.Object3D);
-		}
-		invMatrix.initInverse(invMatrix);
-
-		var pos = spd.pos.toVector();
-		pos.project(invMatrix);
-
-		var index = 0;
-		var scale = 1.0;
-		if( spd.prev == null && spd.next == null ) {
-			scale = 1.0;
-			index = 0;
-		}
-		else if( spd.prev == null ) {
-			index = 0;
-			scale = prefab.points[0].getAbsPos().getScale().x;
-		}
-		else if( spd.next == null ) {
-			index = prefab.points.length;
-			scale = prefab.points[prefab.points.length - 1].getAbsPos().getScale().x;
-		}
-		else {
-			index = prefab.points.indexOf(spd.next);
-			scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5;
-		}
-
-		var sp = new SplinePoint(prefab);
-		sp.x = pos.x;
-		sp.y = pos.y;
-		sp.z = pos.z;
-		prefab.children.remove(sp);
-		prefab.children.insert(index, sp);
-		if( spd.tangent != null ) {
-			var dir = spd.tangent.toVector();
-			dir.transform3x3(invMatrix); // Don't take the translation
-			dir.scale3(-1);
-			sp.rotationX = h3d.Matrix.lookAtX(dir).getFloats()[0];
-			sp.rotationY = h3d.Matrix.lookAtX(dir).getFloats()[1];
-			sp.rotationZ = h3d.Matrix.lookAtX(dir).getFloats()[2];
-		}
-		sp.scaleX = scale;
-		sp.scaleY = scale;
-		sp.scaleZ = scale;
-		editContext.scene.editor.addElements([sp], false, true, false);
-
-		prefab.updateInstance(ctx);
-		showViewers();
-		return sp;
-	}
-
-	function removeViewers() {
-		for( sp in prefab.points ) {
-			sp.setViewerVisible(false);
-		}
-	}
-
-	function showViewers() {
-		for( sp in prefab.points ) {
-			sp.setViewerVisible(true);
-		}
-	}
-
-	function removeGizmos() {
-		for( g in gizmos ) {
-			g.remove();
-			@:privateAccess editContext.scene.editor.updates.remove(g.update);
-		}
-		gizmos = [];
-	}
-
-	function createGizmos( ctx : hrt.prefab.Context  ) {
-		removeGizmos(); // Security, avoid duplication
-		var sceneEditor = @:privateAccess editContext.scene.editor;
-		for( sp in prefab.points ) {
-			var gizmo = new hide.view.l3d.Gizmo(editContext.scene);
-			gizmo.getRotationQuat().identity();
-			gizmo.visible = true;
-			var tmpMat = new h3d.Matrix();
-			tmpMat.load(sp.getAbsPos());
-			var tmpScale = new h3d.Vector();
-			tmpMat.getScale(tmpScale);
-			tmpMat.prependScale(1.0/tmpScale.x, 1.0/tmpScale.y, 1.0/tmpScale.z);
-			gizmo.setTransform(tmpMat);
-			@:privateAccess sceneEditor.updates.push( gizmo.update );
-			gizmos.insert(gizmos.length, gizmo);
-			gizmo.visible = false; // Not visible by default, only show the closest in the onMove of interactive
-
-			var posQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.xyzPrecision");
-			var scaleQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.scalePrecision");
-			var rotQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.rotatePrecision");
-
-			inline function quantize(x: Float, step: Float) {
-				if(step > 0) {
-					x = Math.round(x / step) * step;
-					x = untyped parseFloat(x.toFixed(5)); // Snap to closest nicely displayed float :cold_sweat:
-				}
-				return x;
-			}
-
-			gizmo.onStartMove = function(mode) {
-
-				var sceneObj = sceneEditor.getContext(sp).local3d;
-				var obj3d = sp.to(hrt.prefab.Object3D);
-				var pivotPt = sceneObj.getAbsPos().getPosition();
-				var pivot = new h3d.Matrix();
-				pivot.initTranslation(pivotPt.x, pivotPt.y, pivotPt.z);
-				var invPivot = pivot.clone();
-				invPivot.invert();
-
-				var localMat : h3d.Matrix = sceneEditor.worldMat(sceneObj).clone();
-				localMat.multiply(localMat, invPivot);
-
-				var prevState = obj3d.saveTransform();
-				gizmo.onMove = function(translate: h3d.Vector, rot: h3d.Quat, scale: h3d.Vector) {
-					var transf = new h3d.Matrix();
-					transf.identity();
-
-					if(rot != null) rot.toMatrix(transf);
-					if(translate != null) transf.translate(translate.x, translate.y, translate.z);
-
-					var newMat = localMat.clone();
-					newMat.multiply(newMat, transf);
-					newMat.multiply(newMat, pivot);
-					if(sceneEditor.snapToGround && (mode == MoveXY || mode == MoveX || mode == MoveY || mode == MoveZ || mode == MoveYZ || mode == MoveZX)) {
-						newMat.tz = sceneEditor.getZ(newMat.tx, newMat.ty);
-					}
-
-					var parentInvMat = sceneObj.parent.getAbsPos().clone();
-					parentInvMat.initInverse(parentInvMat);
-					newMat.multiply(newMat, parentInvMat);
-					if(scale != null) newMat.prependScale(scale.x, scale.y, scale.z);
-
-					var rot = newMat.getEulerAngles();
-					obj3d.x = quantize(newMat.tx, posQuant);
-					obj3d.y = quantize(newMat.ty, posQuant);
-					obj3d.z = quantize(newMat.tz, posQuant);
-					obj3d.rotationX = quantize(hxd.Math.radToDeg(rot.x), rotQuant);
-					obj3d.rotationY = quantize(hxd.Math.radToDeg(rot.y), rotQuant);
-					obj3d.rotationZ = quantize(hxd.Math.radToDeg(rot.z), rotQuant);
-					if(scale != null) {
-						inline function scaleSnap(x: Float) {
-							if(K.isDown(K.CTRL)) {
-								var step = K.isDown(K.SHIFT) ? 0.5 : 1.0;
-								x = Math.round(x / step) * step;
-							}
-							return x;
-						}
-						var s = newMat.getScale();
-						obj3d.scaleX = quantize(scaleSnap(s.x), scaleQuant);
-						obj3d.scaleY = quantize(scaleSnap(s.y), scaleQuant);
-						obj3d.scaleZ = quantize(scaleSnap(s.z), scaleQuant);
-					}
-					obj3d.applyTransform(sceneObj);
-				}
-
-				gizmo.onFinishMove = function() {
-					var newState = obj3d.saveTransform();
-					undo.change(Custom(function(undo) {
-						if( undo ) {
-							obj3d.loadTransform(prevState);
-							obj3d.applyTransform(sceneObj);
-							prefab.updateInstance(ctx);
-							showViewers();
-							@:privateAccess editContext.scene.editor.refresh(Partial);
-							showViewers();
-							createGizmos(ctx);
-						}
-						else {
-							obj3d.loadTransform(newState);
-							obj3d.applyTransform(sceneObj);
-							prefab.updateInstance(ctx);
-							showViewers();
-							createGizmos(ctx);
-						}
-					}));
-					var worldPos = ctx.local3d.localToGlobal(new h3d.col.Point(sp.x, sp.y, sp.z));
-					gizmo.setPosition(worldPos.x, worldPos.y, worldPos.z);
-				}
-			}
-		}
-	}
-
-	public function setSelected( ctx : hrt.prefab.Context , b : Bool ) {
-		reset();
-
-		if( !b ) {
-			editMode = false;
-			return;
-		}
-
-		if( editMode ) {
-			createGizmos(ctx);
-			var s2d = @:privateAccess ctx.local2d.getScene();
-			interactive = new h2d.Interactive(10000, 10000, s2d);
-			interactive.propagateEvents = true;
-			interactive.onPush =
-				function(e) {
-					// Add a new point
-					if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.CTRL )  ) {
-						e.propagate = false;
-						var pt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx);
-						var sp = addSplinePoint(pt, ctx);
-						showViewers();
-						createGizmos(ctx);
-
-						undo.change(Custom(function(undo) {
-							if( undo ) {
-								editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
-								for (sp in prefab.points)
-									sp.computeName(editContext.getContext(sp));
-								@:privateAccess editContext.scene.editor.refresh(Partial);
-								prefab.updateInstance(ctx);
-								showViewers();
-								createGizmos(ctx);
-							}
-							else {
-								addSplinePoint(pt, ctx);
-								showViewers();
-								createGizmos(ctx);
-							}
-						}));
-
-					}
-					// Delete a point
-					if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.SHIFT )  ) {
-						e.propagate = false;
-						var sp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx);
-						var index = prefab.points.indexOf(sp);
-						editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
-						for (sp in prefab.points)
-							sp.computeName(editContext.getContext(sp));
-						@:privateAccess editContext.scene.editor.refresh(Partial);
-
-						prefab.updateInstance(ctx);
-						showViewers();
-						createGizmos(ctx);
-
-						undo.change(Custom(function(undo) {
-							if( undo ) {
-								prefab.children.insert(index, sp);
-								editContext.scene.editor.addElements([sp], false, true, false);
-								prefab.updateInstance(ctx);
-								showViewers();
-								createGizmos(ctx);
-							}
-							else {
-								editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
-								for (sp in prefab.points)
-									sp.computeName(editContext.getContext(sp));
-								@:privateAccess editContext.scene.editor.refresh(Partial);
-								prefab.updateInstance(ctx);
-								showViewers();
-								createGizmos(ctx);
-							}
-						}));
-					}
-				};
-
-			interactive.onMove =
-				function(e) {
-
-					if( prefab.points.length == 0 )
-						return;
-
-					// Only show the gizmo of the closest splinePoint
-					var closetSp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx);
-					var index = prefab.points.indexOf(closetSp);
-					for( g in gizmos ) {
-						g.visible = gizmos.indexOf(g) == index && !K.isDown( K.CTRL ) && !K.isDown( K.SHIFT );
-					}
-
-					if( K.isDown( K.CTRL ) ) {
-						if( newSplinePointViewer == null )
-							newSplinePointViewer = new NewSplinePointViewer(ctx.local3d.getScene());
-						newSplinePointViewer.visible = true;
-
-						var npt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx);
-						newSplinePointViewer.update(npt);
-					}
-					else {
-						if( newSplinePointViewer != null )
-							newSplinePointViewer.visible = false;
-					}
-
-					if( K.isDown( K.SHIFT ) ) {
-						var index = prefab.points.indexOf(getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx));
-						for( sp in prefab.points ) {
-							if( index == prefab.points.indexOf(sp) )
-								sp.setColor(0xFFFF0000);
-							else
-								sp.setColor(0xFF0000FF);
-						}
-					}
-
-				};
-		}
-	}
-
-	public function edit( ctx : EditContext ) {
-
-		var props = new hide.Element('
-		<div class="spline-editor">
-			<div class="group" name="Utility">
-				<div align="center">
-					<input type="button" value="Reverse" class="reverse"/>
-				</div>
-			</div>
-			<div class="group" name="Description">
-				<div class="description">
-					<i>Ctrl + Left Click</i> Add a point on the spline <br>
-					<i>Shift + Left Click</i> Delete a point from the spline
-				</div>
-			</div>
-			<div class="group" name="Tool">
-				<div align="center">
-					<input type="button" value="Edit Mode : Disabled" class="editModeButton" />
-				</div>
-			</div>
-		</div>');
-
-		var reverseButton = props.find(".reverse");
-		reverseButton.click(function(_) {
-			prefab.children.reverse();
-			for (sp in prefab.points) {
-				sp.rotationZ += hxd.Math.degToRad(180);
-				sp.computeName(editContext.getContext(sp));
-			}
-			@:privateAccess editContext.scene.editor.refresh(Partial);
-
-			undo.change(Custom(function(undo) {
-				prefab.children.reverse();
-				for (sp in prefab.points) {
-					sp.rotationZ += hxd.Math.degToRad(180);
-					sp.computeName(editContext.getContext(sp));
-				}
-				@:privateAccess editContext.scene.editor.refresh(Partial);
-			}));
-			ctx.onChange(prefab, null);
-			removeGizmos();
-			createGizmos(getContext());
-		});
-
-		var editModeButton = props.find(".editModeButton");
-		editModeButton.toggleClass("editModeEnabled", editMode);
-		editModeButton.click(function(_) {
-			editMode = !editMode;
-			prefab.onEdit(editMode);
-			editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled");
-			editModeButton.toggleClass("editModeEnabled", editMode);
-			prefab.updateInstance(ctx.getContext(prefab));
-			setSelected(getContext(), true);
-			@:privateAccess editContext.scene.editor.showGizmo = !editMode;
-			ctx.onChange(prefab, null);
-		});
-
-		ctx.properties.add(props, this, function(pname) {
-			ctx.onChange(prefab, pname);
-		});
-
-		return props;
-	}
-
-}
-
-#end

+ 0 - 136
hide/prefab/terrain/Brush.hx

@@ -1,136 +0,0 @@
-package hide.prefab.terrain;
-import h3d.shader.pbr.AlphaMultiply;
-import h3d.shader.FixedColor;
-import h3d.mat.Stencil;
-using Lambda;
-import hxd.Key as K;
-
-class Brush {
-	public var name : String;
-	public var size : Float;
-	public var strength : Float;
-	public var step : Float;
-	public var tex : h3d.mat.Texture;
-	public var bitmap : h2d.Bitmap;
-	public var texPath : String;
-	public var index : Int = -1;
-	public var brushMode : BrushMode;
-	public var firstClick = false;
-
-	public function new(){
-		brushMode = new BrushMode();
-	}
-
-	public function isValid() : Bool {
-		return ( brushMode.mode == Delete || (bitmap != null && tex != null && name != null && step > 0.0 && texPath != null) );
-	}
-
-	public function scaleForTex( tileSize : h2d.col.Point, texResolution : h2d.col.IPoint ) {
-		if( tex != null ) {
-			bitmap.scaleX = size / ((tileSize.x / texResolution.x) * tex.width);
-			bitmap.scaleY = size / ((tileSize.y / texResolution.y) * tex.height);
-		}
-	}
-
-	public function drawTo( target : h3d.mat.Texture, pos : h3d.col.Point, tileSize : h2d.col.Point, ?offset = 0 ) {
-		var texSize = new h2d.col.IPoint(target.width + offset, target.height + offset);
-		scaleForTex(tileSize, texSize);
-		bitmap.setPosition(
-						(pos.x * texSize.x - ( size / (tileSize.x / texSize.x) * 0.5 )),
-						(pos.y * texSize.y - ( size / (tileSize.y / texSize.y) * 0.5 )));
-		bitmap.drawTo(target);
-	}
-}
-
-enum Mode {
-	AddSub;
-	Set;
-	Smooth;
-	Paint;
-	Delete;
-	NoMode;
-}
-
-enum LockAxe {
-	LockX;
-	LockY;
-	NoLock;
-}
-
-class BrushMode {
-	public var accumulate = false;
-	public var subAction = false;
-	public var lockDir = false;
-	public var snapToGrid = false;
-	public var mode = NoMode;
-	public var lockAxe = NoLock;
-	public var setHeightValue = 0.0;
-	public function new(){}
-}
-
-class AlphaMult extends hxsl.Shader {
-	static var SRC = {
-		@param var amount : Float;
-		var pixelColor : Vec4;
-		function fragment() {
-			pixelColor.a *= amount;
-		}
-	}
-}
-
-class BrushPreview extends h3d.scene.Mesh {
-
-	var terrain : hrt.prefab.terrain.TerrainMesh;
-	var decalShader : h3d.shader.pbr.VolumeDecal.DecalOverlay;
-	public var opacity : Float = 1.0;
-
-	public function new( terrain : hrt.prefab.terrain.TerrainMesh ) {
-		this.terrain = terrain;
-		var material = h3d.mat.MaterialSetup.current.createMaterial();
-		material.props = material.getDefaultProps();
-		material.mainPass.removeShader(material.mainPass.getShader(h3d.shader.pbr.PropsValues));
-		material.mainPass.setPassName("afterTonemappingDecal");
-		material.mainPass.depthWrite = false;
-		material.mainPass.depthTest = GreaterEqual;
-		material.mainPass.culling = Front;
-		material.mainPass.setBlendMode(Alpha);
-		material.shadows = false;
-		super(h3d.prim.Cube.defaultUnitCube(), material, terrain.getScene());
-		decalShader = new h3d.shader.pbr.VolumeDecal.DecalOverlay();
-		decalShader.fadeStart = 1;
-		decalShader.fadeEnd = 0;
-		decalShader.fadePower = 1;
-		decalShader.emissive = 0;
-		decalShader.CENTERED = true;
-		decalShader.GAMMA_CORRECT = false;
-		material.mainPass.addShader(decalShader);
-		var colorSet = new FixedColor();
-		colorSet.color.set(1,1,1,1);
-		colorSet.USE_ALPHA = false;
-		material.mainPass.addShader(colorSet);
-		var am = new AlphaMult();
-		am.setPriority(-1);
-		am.amount = opacity;
-		material.mainPass.addShader(am);
-
-		// Only draw the preview on terrain
-		material.mainPass.stencil = new h3d.mat.Stencil();
-		material.mainPass.stencil.setFunc(Equal, 0x01, 0x01, 0x01);
-		material.mainPass.stencil.setOp(Keep, Keep, Keep);
-	}
-
-	public function previewAt( brush : Brush, pos : h3d.col.Point ) {
-		setPosition(pos.x, pos.y, pos.z);
-		setScale(brush.size);
-		scaleZ = 1000;
-		decalShader.colorTexture = brush.tex;
-		material.mainPass.getShader(AlphaMult).amount = opacity;
-		visible = true;
-	}
-
-	public function reset() {
-		setPosition(0,0,0);
-		visible = false;
-		decalShader.colorTexture = null;
-	}
-}

+ 0 - 31
hide/prefab/terrain/ClampWeight.hx

@@ -1,31 +0,0 @@
-package hide.prefab.terrain;
-
-class ClampWeight extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var weightTextures : Sampler2DArray;
-		@param var weightCount : Int;
-		@param var baseTexIndex : Int;
-		@param var curTexIndex : Int;
-
-		function fragment() {
-			var count = 0;
-			var smallestWeightIndex = -1;
-			var smallestWeight = 1.0;
-			for(i in 0 ... weightCount){
-				var w = weightTextures.get(vec3(calculatedUV, i)).r;
-				if(w > 0.0){
-					count++;
-					if(i != baseTexIndex && smallestWeight > w){
-						smallestWeight = w;
-						smallestWeightIndex = i;
-					}
-				}
-			}
-			pixelColor = weightTextures.get(vec3(calculatedUV, curTexIndex)).rgba;
-			if(count > 3 && curTexIndex == smallestWeightIndex)
-				pixelColor = vec4(0);
-		}
-	}
-}

+ 0 - 21
hide/prefab/terrain/CustomRenderer.hx

@@ -1,21 +0,0 @@
-package hide.prefab.terrain;
-
-class CustomRenderer extends h3d.scene.Renderer {
-
-	var passName : String;
-
-	public function new(passName) {
-		super();
-		this.passName = passName;
-		defaultPass = new h3d.pass.Default("default");
-		allPasses.push(defaultPass);
-	}
-
-	override function start() {
-
-	}
-
-	override function render() {
-		defaultPass.draw(get(passName));
-	}
-}

+ 0 - 27
hide/prefab/terrain/CustomUV.hx

@@ -1,27 +0,0 @@
-package hide.prefab.terrain;
-
-class CustomUV extends hxsl.Shader {
-
-	static var SRC = {
-
-		@:import h3d.shader.BaseMesh;
-		@param var tileIndex : Float;
-
-		@param var heightMapSize : Vec2;
-		@param var heightMap : Sampler2D;
-		@param var primSize : Vec2;
-
-		var calculatedUV : Vec2;
-		var terrainUV : Vec2;
-
-		function vertex() {
-			calculatedUV = input.position.xy / primSize.xy;
-			transformedPosition += (vec3(0,0, heightMap.get(calculatedUV).r) * global.modelView.mat3());
-			transformedNormal = vec3(0,0,0);
-		}
-
-		function fragment() {
-			pixelColor = vec4(calculatedUV.x, calculatedUV.y, tileIndex , 1);
-		}
-	}
-}

+ 0 - 29
hide/prefab/terrain/GenerateIndex.hx

@@ -1,29 +0,0 @@
-package hide.prefab.terrain;
-
-class GenerateIndex extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var weightTextures : Sampler2DArray;
-		@param var weightCount : Int;
-		@param var mask : Array<Vec4, 4>;
-
-		function fragment() {
-			var indexes = vec4(0,0,0,1);
-			var curMask = 0;
-			for(i in 0 ... weightCount){
-				var w = weightTextures.get(vec3(calculatedUV, i)).r;
-				if( w > 0 && curMask < 3){
-					indexes += mask[curMask] * i / 255.0;
-					curMask++;
-				}
-			}
-			pixelColor = indexes;
-		}
-	}
-
-	public function new(){
-		super();
-		mask = [new h3d.Vector(1,0,0,0), new h3d.Vector(0,1,0,0), new h3d.Vector(0,0,1,0), new h3d.Vector(0,0,0,1)];
-	}
-}

+ 0 - 25
hide/prefab/terrain/NormalizeWeight.hx

@@ -1,25 +0,0 @@
-package hide.prefab.terrain;
-
-class NormalizeWeight extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var weightTextures : Sampler2DArray;
-		@param var weightCount : Int;
-		@param var baseTexIndex : Int;
-		@param var curTexIndex : Int;
-
-		function fragment() {
-			var refValue = weightTextures.get(vec3(calculatedUV, baseTexIndex)).r;
-			var sum = 0.0;
-			for(i in 0 ... weightCount)
-				if(i != baseTexIndex) sum += weightTextures.get(vec3(calculatedUV, i)).r;
-			var targetSum = 1 - refValue;
-			pixelColor = vec4(vec3((weightTextures.get(vec3(calculatedUV, curTexIndex)).rgb / sum) * targetSum), 1.0);
-
-			if(baseTexIndex == curTexIndex){
-				pixelColor = mix(vec4(1), vec4(refValue), ceil(min(1,sum)));
-			}
-		}
-	}
-}

+ 0 - 17
hide/prefab/terrain/SetHeight.hx

@@ -1,17 +0,0 @@
-package hide.prefab.terrain;
-
-class SetHeight extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var prevHeight : Sampler2D;
-		@param var strengthTex : Sampler2D;
-		@param var targetHeight : Float;
-
-		function fragment() {
-			var height = prevHeight.get(calculatedUV).r;
-			var strength = strengthTex.get(calculatedUV).r;
-			pixelColor = vec4(mix(height, targetHeight, clamp(strength,0,1)));
-		}
-	}
-}

+ 0 - 27
hide/prefab/terrain/SmoothHeight.hx

@@ -1,27 +0,0 @@
-package hide.prefab.terrain;
-
-class SmoothHeight extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var prevHeight : Sampler2D;
-		@param var prevHeightResolution : Vec2;
-		@param var strengthTex : Sampler2D;
-		@param var range : Int;
-
-		function fragment() {
-			var height = prevHeight.get(calculatedUV).r;
-			var strength = strengthTex.get(calculatedUV).r;
-			var pixelSize =  1.0 / prevHeightResolution;
-
-			var averageHeight = 0.0;
-			for( i in -range ... range + 1 ){
-				for( j in -range ... range + 1){
-					averageHeight += prevHeight.getLod(calculatedUV + pixelSize * vec2(i,j), 0).r;
-				}
-			}
-			averageHeight /= (range * 2 + 1) * (range * 2 + 1);
-			pixelColor = vec4(mix(height, averageHeight, clamp(strength,0,1)));
-		}
-	}
-}

+ 0 - 91
hide/prefab/terrain/StrokeBuffer.hx

@@ -1,91 +0,0 @@
-package hide.prefab.terrain;
-
-class StrokeBuffer {
-	public var tex : h3d.mat.Texture;
-	public var x : Int;
-	public var y : Int;
-	public var used : Bool;
-	public var prevTex : h3d.mat.Texture;
-	public var tempTex : h3d.mat.Texture;
-	public var format : hxd.PixelFormat;
-
-	public function new(size : h2d.col.IPoint, x, y, format){
-		this.format = format;
-		tex = new h3d.mat.Texture(size.x, size.y, [Target], format);
-		tempTex = new h3d.mat.Texture(size.x, size.y, [Target], format);
-		tex.filter = Linear;
-		tempTex.filter = Linear;
-		this.x = x;
-		this.y = y;
-		used = false;
-	}
-
-	public function dispose(){
-		if(tex != null) tex.dispose();
-		if(tempTex != null) tempTex.dispose();
-	}
-
-	public function refresh(size: h2d.col.IPoint){
-		if(tex != null) tex.dispose();
-		if(tempTex != null) tempTex.dispose();
-		tex = new h3d.mat.Texture(size.x, size.y, [Target], format);
-		tempTex = new h3d.mat.Texture(size.x, size.y, [Target], format);
-		tex.filter = Linear;
-		tempTex.filter = Linear;
-		tex.preventAutoDispose();
-		tempTex.preventAutoDispose();
-	}
-
-	public function reset(){
-		used = false;
-		switch tex.format {
-			case RGB16F, RGB32F:
-				if(tex != null) tex.clearF(0);
-				if(tempTex != null) tempTex.clearF(0);
-			default:
-				if(tex != null) tex.clear(0);
-				if(tempTex != null) tempTex.clear(0);
-		}
-	}
-}
-
-class StrokeBufferArray{
-
-	public var strokeBuffers(default, null) : Array<StrokeBuffer> = [];
-	var texSize = new h2d.col.IPoint(0,0);
-	var format : hxd.PixelFormat;
-
-	public function new(format, texSize : h2d.col.IPoint ) {
-		this.format = format;
-		this.texSize = texSize;
-	}
-
-	public function dispose(){
-		for(strokebuffer in strokeBuffers) strokebuffer.dispose();
-	}
-
-	public function getStrokeBuffer(x, y){
-		for(strokebuffer in strokeBuffers)
-			if((strokebuffer.x == x && strokebuffer.y == y) || strokebuffer.used == false){
-				strokebuffer.x = x;
-				strokebuffer.y = y;
-				return strokebuffer;
-			}
-		var strokeBuffer = new StrokeBuffer(texSize, x, y, format);
-		strokeBuffers.push(strokeBuffer);
-		return strokeBuffer;
-	}
-
-	public function refresh( size : h2d.col.IPoint ){
-		if(texSize == size) return;
-		texSize = size;
-		for(strokeBuffer in strokeBuffers)
-			strokeBuffer.refresh(size);
-	}
-
-	public function reset(){
-		for(strokeBuffer in strokeBuffers){
-			strokeBuffer.reset();
-		}
-	}
-}

+ 0 - 40
hide/prefab/terrain/SwapIndex.hx

@@ -1,40 +0,0 @@
-package hide.prefab.terrain;
-
-class SwapIndex extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@const var USE_ARRAY : Bool;
-		@const var INDEX_COUNT : Int;
-		@param var surfaceIndexMap : Sampler2D;
-		@param var oldIndex : Int;
-		@param var newIndex : Int;
-		@param var oldIndexes : Array<Vec4, INDEX_COUNT>;
-		@param var newIndexes : Array<Vec4, INDEX_COUNT>;
-
-		function fragment() {
-			var indexes = surfaceIndexMap.get(calculatedUV);
-			var i1 = int(indexes.r * 255);
-			var i2 = int(indexes.g * 255);
-			var i3 = int(indexes.b * 255);
-			if(USE_ARRAY){
-				for(i in 0 ... INDEX_COUNT){
-					if(i1 == int(oldIndexes[i].r)) i1 = int(newIndexes[i].r);
-					if(i2 == int(oldIndexes[i].r)) i2 = int(newIndexes[i].r);
-					if(i3 == int(oldIndexes[i].r)) i3 = int(newIndexes[i].r);
-				}
-			}
-			else {
-				if(i1 == oldIndex) i1 = newIndex;
-				if(i2 == oldIndex) i2 = newIndex;
-				if(i3 == oldIndex) i3 = newIndex;
-			}
-			pixelColor = vec4(i1 / 255, i2 / 255, i3 / 255, 1);
-		}
-	}
-
-	public function new(){
-		super();
-		this.USE_ARRAY = false;
-	}
-}

+ 0 - 1231
hide/prefab/terrain/TerrainEditor.hx

@@ -1,1231 +0,0 @@
-package hide.prefab.terrain;
-using Lambda;
-import hxd.Pixels;
-import hrt.prefab.terrain.Tile;
-import hxd.Key as K;
-import hrt.prefab.Context;
-
-enum RenderMode {
-	PBR;
-	ShaderComplexity;
-	Checker;
-}
-
-class TerrainRevertData {
-	public var surfaceIndex : Int;
-	public var surface : hrt.prefab.terrain.Surface;
-	public function new(){
-
-	}
-}
-
-class TileRevertData {
-	public var x : Int;
-	public var y : Int;
-	public var prevHeightMapPixels : hxd.Pixels;
-	public var nextHeightMapPixels : hxd.Pixels;
-	public var prevWeightMapPixels : Array<hxd.Pixels> = [];
-	public var nextWeightMapPixels : Array<hxd.Pixels> = [];
-	public var prevSurfaceIndexMapPixels : hxd.Pixels;
-	public var nextSurfaceIndexMapPixels : hxd.Pixels;
-	public function new(x, y){
-		this.x = x;
-		this.y = y;
-	}
-}
-
-@:access(hrt.prefab.terrain.TerrainMesh)
-@:access(hrt.prefab.terrain.Terrain)
-@:access(hrt.prefab.terrain.Tile)
-class TerrainEditor {
-
-	public var currentBrush = new Brush();
-	public var currentSurface : hrt.prefab.terrain.Surface;
-	public var textureType = ["_Albedo", "_Normal", "_MetallicGlossAO"];
-	public var autoCreateTile = false;
-	public var editContext : hide.prefab.EditContext;
-
-	// Debug
-	var renderMode : RenderMode = PBR;
-	// Edition
-	var brushPreview : hide.prefab.terrain.Brush.BrushPreview;
-	var interactive : h2d.Interactive;
-	var remainingDist = 0.0;
-	var lastPos : h3d.col.Point;
-	var lastMousePos : h2d.col.Point;
-	var lastBrushSize : Float;
-	var heightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray;
-	var weightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray;
-	// Shader for edition
-	var copyPass = new h3d.pass.Copy();
-	var normalizeWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.NormalizeWeight());
-	var clampWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.ClampWeight());
-	var generateIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.GenerateIndex());
-	var swapIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.SwapIndex());
-	var setHeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.SetHeight());
-	var smoothHeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.SmoothHeight());
-	// Revert
-	var terrainPrefab : hrt.prefab.terrain.Terrain;
-	var undo : hide.ui.UndoHistory;
-	var tileTrashBin : Array<TileRevertData> = [];
-	var paintRevertDatas : Array<TileRevertData> = [];
-	// Render UV offscreen
-	var uvTexPixels : hxd.Pixels;
-	var uvTex : h3d.mat.Texture;
-	var uvTexRes = 0.5;
-	var customScene = new h3d.scene.Scene(false, false);
-	var customRenderer = new hide.prefab.terrain.CustomRenderer("terrainUV");
-
-	public function new( terrainPrefab : hrt.prefab.terrain.Terrain, undo : hide.ui.UndoHistory ) {
-		this.terrainPrefab = terrainPrefab;
-		this.undo = undo;
-		renderMode = terrainPrefab.showChecker ? Checker : PBR;
-		autoCreateTile = terrainPrefab.autoCreateTile;
-
-		brushPreview = new hide.prefab.terrain.Brush.BrushPreview(terrainPrefab.terrain);
-
-		heightStrokeBufferArray = new hide.prefab.terrain.StrokeBuffer.StrokeBufferArray(R32F,new h2d.col.IPoint(terrainPrefab.terrain.heightMapResolution.x, terrainPrefab.terrain.heightMapResolution.y));
-		weightStrokeBufferArray = new hide.prefab.terrain.StrokeBuffer.StrokeBufferArray(R8, terrainPrefab.terrain.weightMapResolution);
-		customScene.renderer = customRenderer;
-		#if debug
-		customScene.checkPasses = false;
-		#end
-	}
-
-	public function dispose() {
-		if(uvTex != null) uvTex.dispose();
-		heightStrokeBufferArray.dispose();
-		weightStrokeBufferArray.dispose();
-		brushPreview.remove();
-		if( interactive != null ) interactive.remove();
-	}
-
-	public function update( ?propName : String ) {
-		if( propName == "editor.currentSurface.tilling"
-		|| propName == "editor.currentSurface.offset.x"
-		|| propName == "editor.currentSurface.offset.y"
-		|| propName == "editor.currentSurface.angle"
-		|| propName == "editor.currentSurface.minHeight"
-		|| propName == "editor.currentSurface.maxHeight"
-		|| propName == "editor.currentSurface.parallaxAmount" )
-			terrainPrefab.terrain.updateSurfaceParams();
-
-		autoCreateTile = terrainPrefab.autoCreateTile;
-		brushPreview.opacity = terrainPrefab.brushOpacity;
-
-		if( propName == "editor.renderMode" ) updateRender();
-	}
-
-	public function refresh() {
-		heightStrokeBufferArray.refresh(new h2d.col.IPoint(terrainPrefab.terrain.heightMapResolution.x + 1, terrainPrefab.terrain.heightMapResolution.y + 1));
-		weightStrokeBufferArray.refresh(terrainPrefab.terrain.weightMapResolution);
-	}
-
-	function updateRender() {
-		for( tile in terrainPrefab.terrain.tiles )
-			tile.material.removePass(tile.material.getPass("overlay"));
-		terrainPrefab.terrain.showChecker = false;
-		terrainPrefab.terrain.showComplexity = false;
-		terrainPrefab.showChecker = false;
-		switch( renderMode ) {
-			case PBR :
-			case ShaderComplexity : terrainPrefab.terrain.showComplexity = true;
-			case Checker :
-				terrainPrefab.terrain.showChecker = true;
-				terrainPrefab.showChecker = true;
-		}
-	}
-
-	function renderTerrainUV( ctx : Context ) {
-		if( customScene == null ) return;
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return;
-		var engine = h3d.Engine.getCurrent();
-		var mainScene = @:privateAccess ctx.local3d.getScene();
-
-		if( uvTex == null || uvTex.width != Std.int(h3d.Engine.getCurrent().width * uvTexRes) || uvTex.height != Std.int(h3d.Engine.getCurrent().height * uvTexRes) ) {
-			if(uvTex != null) {
-				uvTex.depthBuffer.dispose();
-				uvTex.dispose();
-			}
-			uvTex = new h3d.mat.Texture( Std.int(h3d.Engine.getCurrent().width * uvTexRes),  Std.int(h3d.Engine.getCurrent().height * uvTexRes), [Target], RGBA32F);
-			uvTex.depthBuffer = new h3d.mat.DepthBuffer(uvTex.width, uvTex.height);
-		}
-
-		var prevParent = terrainPrefab.terrain.parent;
-		@:privateAccess {
-			customScene.children = [terrainPrefab.terrain]; // Prevent OnRemove() call
-			terrainPrefab.terrain.parent = customScene;
-		}
-
-		customScene.camera = mainScene.camera;
-		brushPreview.reset();
-
-		var tiles = terrainPrefab.terrain.tiles;
-		for( i in 0 ... tiles.length ) {
-			var tile = tiles[i];
-			var p = new h3d.mat.Pass("terrainUV");
-			p.addShader(new h3d.shader.BaseMesh());
-			p.depthTest = Less;
-			p.culling = None;
-			p.depthWrite = true;
-			tile.material.addPass(p);
-			var s = new hide.prefab.terrain.CustomUV();
-			s.primSize.set(terrainPrefab.terrain.tileSize.x, terrainPrefab.terrain.tileSize.y);
-			s.heightMapSize.set(terrainPrefab.terrain.heightMapResolution.x, terrainPrefab.terrain.heightMapResolution.y);
-			s.heightMap = tile.heightMap;
-			s.tileIndex = i;
-			p.addShader(s);
-		}
-
-		engine.begin();
-		engine.pushTarget(uvTex);
-		engine.clear(0xffffff,1,0);
-		engine.clearF(new h3d.Vector(-1, -1, -1, -1),1,0);
-		customScene.render(engine);
-		engine.popTarget();
-
-		for( tile in tiles )
-			tile.material.removePass(tile.material.getPass("terrainUV"));
-
-		@:privateAccess {
-			customScene.children = [];
-			terrainPrefab.terrain.parent = prevParent;
-		}
-		customScene.camera = null;
-
-		uvTexPixels = uvTex.capturePixels();
-	}
-
-	function checkTrashBin() {
-		if( tileTrashBin.length > 0 ) {
-			var tileTrashBinTmp = tileTrashBin.copy();
-			tileTrashBin = [];
-			undo.change(Custom(function(undo) {
-				for( t in tileTrashBinTmp ) {
-					if( undo ) {
-						var tile = terrainPrefab.terrain.createTile(t.x, t.y);
-						tile.material.mainPass.stencil = new h3d.mat.Stencil();
-						tile.material.mainPass.stencil.setFunc(Always, 0x01, 0x01, 0x01);
-						tile.material.mainPass.stencil.setOp(Keep, Keep, Replace);
-						tile.refreshHeightMap();
-						tile.refreshNormalMap();
-						tile.refreshIndexMap();
-						tile.refreshSurfaceWeightArray();
-						tile.heightMap.uploadPixels(t.prevHeightMapPixels);
-						tile.surfaceIndexMap.uploadPixels(t.prevSurfaceIndexMapPixels);
-						for( i in 0 ... t.prevWeightMapPixels.length )
-							tile.surfaceWeights[i].uploadPixels(t.prevWeightMapPixels[i]);
-						tile.generateWeightTextureArray();
-					}
-					else
-						terrainPrefab.terrain.removeTileAt(t.x, t.y);
-				}
-			}));
-			tileTrashBin = [];
-		}
-	}
-
-	function blendEdges( modifiedTile : Array<Tile> ) {
-
-		// Adjust the edge for each modified tiles and their neighbors
-		var tiles : Array<Tile> = [];
-		for( t in modifiedTile ) {
-			for( i in -1 ... 2 ) {
-				for( j in - 1 ... 2 ) {
-					var adj = t.terrain.getTile(t.tileX + i, t.tileY + j);
-					if( adj != null && tiles.indexOf(adj) == -1 )
-						tiles.push(adj);
-				}
-			}
-		}
-
-		// Adjust the height to avoid seams
-		for( t in tiles ) {
-			var pixels = t.getHeightMapPixels();
-			if( pixels == null )
-				throw("Try to blend the edges of a null heightmap.");
-			var adjTileX = t.terrain.getTile(t.tileX + 1, t.tileY);
-			var adjHeightMapX = adjTileX != null ? adjTileX.heightMap : null;
-			if( adjHeightMapX != null ) {
-				var adjpixels = adjTileX.getHeightMapPixels();
-				for( i in 0 ... t.heightMap.height ) {
-					pixels.setPixelF(t.heightMap.width - 1, i, adjpixels.getPixelF(0,i) );
-				}
-			}
-
-			var adjTileY = t.terrain.getTile(t.tileX, t.tileY + 1);
-			var adjHeightMapY = adjTileY != null ? adjTileY.heightMap : null;
-			if( adjHeightMapY != null ) {
-				var adjpixels = adjTileY.getHeightMapPixels();
-				for( i in 0 ... t.heightMap.width ) {
-					pixels.setPixelF(i, t.heightMap.height - 1, adjpixels.getPixelF(i,0) );
-				}
-			}
-
-			var adjTileXY = t.terrain.getTile(t.tileX + 1, t.tileY + 1);
-			var adjHeightMapXY = adjTileXY != null ? adjTileXY.heightMap : null;
-			if( adjHeightMapXY != null ) {
-				var adjpixels = adjTileXY.getHeightMapPixels();
-				pixels.setPixelF(t.heightMap.width - 1, t.heightMap.height - 1, adjpixels.getPixelF(0,0));
-			}
-
-			t.heightMapPixels = pixels;
-			t.heightMap.uploadPixels(pixels);
-			t.needNewPixelCapture = false;
-		}
-
-		// Compute the normal for each tile, but there's seam on the edge
-		for( t in tiles )  {
-			t.bakeNormal();
-			t.normalMapPixels = t.normalMap.capturePixels();
-		}
-
-		// Compute the average normal on edge
-		for( t in tiles ) {
-
-			var pixelsAfterBlend = t.normalMapPixels;
-			var left = t.terrain.getTile(t.tileX - 1, t.tileY);
-			var right = t.terrain.getTile(t.tileX + 1, t.tileY);
-			var up = t.terrain.getTile(t.tileX, t.tileY - 1);
-			var down = t.terrain.getTile(t.tileX, t.tileY + 1);
-			var upRight = t.terrain.getTile(t.tileX + 1, t.tileY - 1);
-			var upLeft = t.terrain.getTile(t.tileX - 1, t.tileY - 1);
-			var downRight = t.terrain.getTile(t.tileX + 1, t.tileY + 1);
-			var downLeft = t.terrain.getTile(t.tileX - 1, t.tileY + 1);
-			var width = pixelsAfterBlend.width - 1;
-			var height = pixelsAfterBlend.height - 1;
-
-			// Return the normal of tile t at (x,y) without any blend
-			function getNormalFromHeightMap(t : Tile, x : Int, y : Int ) {
-				var h = t.heightMapPixels.getPixelF(x, y).x;
-				var h1 = y + 1 >= t.heightMapPixels.height ? h : t.heightMapPixels.getPixelF(x, y + 1).x;
-				var h2 = x + 1 >= t.heightMapPixels.width ? h : t.heightMapPixels.getPixelF(x + 1, y).x;
-				var h3 = y - 1 < 0 ? h : t.heightMapPixels.getPixelF(x, y - 1).x;
-				var h4 = x - 1 < 0 ? h : t.heightMapPixels.getPixelF(x - 1, y).x;
-				var v1 = new h3d.Vector(0, 1, h1 - h);
-				var v2 = new h3d.Vector(1, 0, h2 - h);
-				var v3 = new h3d.Vector(0, -1, h3 - h);
-				var v4 = new h3d.Vector(-1, 0, h4 - h);
-				var n = v1.cross(v2).add(v2.cross(v3).add(v3.cross(v4).add(v4.cross(v1))));
-				n.scale3(-1.0);
-				n.normalize();
-				return n;
-			}
-
-			inline function packNormal( n : h3d.Vector ) {
-				n.scale3(0.5);
-				return n.add(new h3d.Vector(0.5, 0.5, 0.5)).toColor();
-			}
-
-			inline function unpackNormal( n : Int ) {
-				var n = h3d.Vector.fromColor(n);
-				n = n.add(new h3d.Vector(-0.5, -0.5, -0.5));
-				n.scale3(2.0);
-				return n;
-			}
-
-			for( i in 1 ... pixelsAfterBlend.width - 1 ) {
-				if( up != null ) {
-					var n = unpackNormal(pixelsAfterBlend.getPixel(i, 0)).add(getNormalFromHeightMap(up, i, height));
-					n.normalize();
-					pixelsAfterBlend.setPixel(i, 0, packNormal(n));
-				}
-				if( down != null ) {
-					var n = unpackNormal(pixelsAfterBlend.getPixel(i, height)).add(getNormalFromHeightMap(down, i, 0));
-					n.normalize();
-					pixelsAfterBlend.setPixel(i, height, packNormal(n));
-				}
-			}
-			for( i in 1 ... pixelsAfterBlend.height - 1 ) {
-				if( left != null ) {
-					var n = unpackNormal(pixelsAfterBlend.getPixel(0, i)).add(getNormalFromHeightMap(left, width, i));
-					n.normalize();
-					pixelsAfterBlend.setPixel(0, i, packNormal(n));
-				}
-				if( right != null ) {
-					var n = unpackNormal(pixelsAfterBlend.getPixel(width, i)).add(getNormalFromHeightMap(right, 0, i));
-					n.normalize();
-					pixelsAfterBlend.setPixel(width, i, packNormal(n));
-				}
-			}
-
-			var n = unpackNormal(pixelsAfterBlend.getPixel(0, 0));
-			if( up != null ) n = n.add(getNormalFromHeightMap(up, 0, height));
-			if( left != null ) n = n.add(getNormalFromHeightMap(left, width, 0));
-			if( upLeft != null ) n = n.add(getNormalFromHeightMap(upLeft, width, height));
-			n.normalize();
-			pixelsAfterBlend.setPixel(0, 0, packNormal(n));
-
-			var n = unpackNormal(pixelsAfterBlend.getPixel(width, 0));
-			if( up != null ) n = n.add(getNormalFromHeightMap(up, width, height));
-			if( right != null ) n = n.add(getNormalFromHeightMap(right, 0, 0));
-			if( upRight != null ) n = n.add(getNormalFromHeightMap(upRight, 0, height));
-			n.normalize();
-			pixelsAfterBlend.setPixel(width, 0, packNormal(n));
-
-			var n = unpackNormal(pixelsAfterBlend.getPixel(0, height));
-			if( down != null ) n = n.add(getNormalFromHeightMap(down, 0, 0));
-			if( left != null ) n = n.add(getNormalFromHeightMap(left, width, height));
-			if( downLeft != null ) n = n.add(getNormalFromHeightMap(downLeft, width, 0));
-			n.normalize();
-			pixelsAfterBlend.setPixel(0, height, packNormal(n));
-
-			var n = unpackNormal(pixelsAfterBlend.getPixel(width, height));
-			if( down != null ) n = n.add(getNormalFromHeightMap(down, width, 0));
-			if( right != null ) n = n.add(getNormalFromHeightMap(right, 0, height));
-			if( downRight != null ) n = n.add(getNormalFromHeightMap(downRight, 0, 0));
-			n.normalize();
-			pixelsAfterBlend.setPixel(width, height, packNormal(n));
-
-			t.normalMap.uploadPixels(pixelsAfterBlend);
-			t.needNormalBake = false;
-		}
-	}
-
-	function resetStrokeBuffers() {
-		heightStrokeBufferArray.reset();
-		weightStrokeBufferArray.reset();
-	}
-
-	function applyStrokeBuffers() {
-
-		var revertDatas = new Array<TileRevertData>();
-
-		for( strokeBuffer in heightStrokeBufferArray.strokeBuffers ) {
-			if( strokeBuffer.used == true ) {
-				var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y);
-				strokeBuffer.tempTex = tile.heightMap;
-				tile.heightMap = strokeBuffer.prevTex;
-				strokeBuffer.prevTex = null;
-				var revert = new TileRevertData(strokeBuffer.x, strokeBuffer.y);
-				revert.prevHeightMapPixels = tile.heightMapPixels;
-
-				switch( currentBrush.brushMode.mode ) {
-					case AddSub :
-						copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.subAction ? Sub : Add);
-					case Set :
-						copyPass.apply(tile.heightMap, strokeBuffer.tempTex);
-						setHeight.shader.prevHeight = strokeBuffer.tempTex;
-						setHeight.shader.targetHeight = currentBrush.brushMode.setHeightValue;
-						setHeight.shader.strengthTex = strokeBuffer.tex;
-						h3d.Engine.getCurrent().pushTarget(tile.heightMap);
-						setHeight.render();
-					case Smooth :
-						copyPass.apply(tile.heightMap, strokeBuffer.tempTex);
-						smoothHeight.shader.prevHeight = strokeBuffer.tempTex;
-						smoothHeight.shader.prevHeightResolution = new h3d.Vector(strokeBuffer.tempTex.width, strokeBuffer.tempTex.height);
-						smoothHeight.shader.range = 4;
-						smoothHeight.shader.strengthTex = strokeBuffer.tex;
-						h3d.Engine.getCurrent().pushTarget(tile.heightMap);
-						smoothHeight.render();
-					default:
-				}
-				revertDatas.push(revert);
-				tile.heightMapPixels = tile.heightMap.capturePixels();
-				revert.nextHeightMapPixels = tile.heightMapPixels;
-				tile.cachedBounds = null;
-			}
-		}
-		var tiles = [ for( sb in heightStrokeBufferArray.strokeBuffers ) { if( sb.used ) terrainPrefab.terrain.getTile(sb.x, sb.y); }];
-		blendEdges(tiles);
-
-		if( revertDatas.length > 0 ) {
-			undo.change(Custom(function(undo) {
-				for( revertData in revertDatas ) {
-					var tile = terrainPrefab.terrain.getTile(revertData.x, revertData.y);
-					if( tile == null ) continue;
-					tile.heightMap.uploadPixels(undo ? revertData.prevHeightMapPixels : revertData.nextHeightMapPixels);
-					tile.heightMapPixels = undo ? revertData.prevHeightMapPixels : revertData.nextHeightMapPixels;
-				}
-				var tiles = [ for( rd in revertDatas ) { terrainPrefab.terrain.getTile(rd.x, rd.y); }];
-				blendEdges(tiles);
-			}));
-		}
-
-		for( strokeBuffer in weightStrokeBufferArray.strokeBuffers ) {
-			if( strokeBuffer.used == true ) {
-				var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y);
-				strokeBuffer.tempTex = tile.surfaceWeights[currentBrush.index];
-				tile.surfaceWeights[currentBrush.index] = strokeBuffer.prevTex;
-				strokeBuffer.prevTex = null;
-
-				copyPass.apply(strokeBuffer.tex, tile.surfaceWeights[currentBrush.index], currentBrush.brushMode.subAction ? Sub : Add);
-				tile.generateWeightTextureArray();
-
-				clampWeight.shader.weightTextures = tile.surfaceWeightArray;
-				clampWeight.shader.weightCount = tile.surfaceWeights.length;
-				clampWeight.shader.baseTexIndex = currentBrush.index;
-				for( i in 0 ... tile.surfaceWeights.length ) {
-					if( i == currentBrush.index ) continue;
-					clampWeight.shader.curTexIndex = i;
-					h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]);
-					clampWeight.render();
-				}
-				tile.generateWeightTextureArray();
-
-				normalizeWeight.shader.weightTextures = tile.surfaceWeightArray;
-				normalizeWeight.shader.weightCount = tile.surfaceWeights.length;
-				normalizeWeight.shader.baseTexIndex = currentBrush.index;
-				for( i in 0 ... tile.surfaceWeights.length ) {
-					normalizeWeight.shader.curTexIndex = i;
-					h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]);
-					normalizeWeight.render();
-				}
-				tile.generateWeightTextureArray();
-
-				var revert : TileRevertData = null;
-				for( r in paintRevertDatas )
-					if( r.x == strokeBuffer.x && r.y == strokeBuffer.y ) {
-						revert = r;
-						break;
-					}
-				if( revert != null )
-					for( w in tile.surfaceWeights )
-						revert.nextWeightMapPixels.push(w.capturePixels());
-
-				generateIndex.shader.weightTextures = tile.surfaceWeightArray;
-				generateIndex.shader.weightCount = tile.surfaceWeights.length;
-				h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap);
-				generateIndex.render();
-			}
-		}
-
-		if( paintRevertDatas.length > 0 ) {
-			var paintRevertdataTmp = paintRevertDatas.copy();
-			paintRevertDatas = [];
-			undo.change(Custom(function(undo) {
-				for( revertData in paintRevertdataTmp ) {
-					var tile = terrainPrefab.terrain.getTile(revertData.x, revertData.y);
-					if (tile == null ) continue;
-					for (i in 0 ... tile.surfaceWeights.length )
-						tile.surfaceWeights[i].uploadPixels(undo ? revertData.prevWeightMapPixels[i] : revertData.nextWeightMapPixels[i]);
-					tile.generateWeightTextureArray();
-					generateIndex.shader.weightTextures = tile.surfaceWeightArray;
-					generateIndex.shader.weightCount = tile.surfaceWeights.length;
-					h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap);
-					generateIndex.render();
-				}
-			}));
-		}
-	}
-
-	function previewStrokeBuffers() {
-		for( strokeBuffer in heightStrokeBufferArray.strokeBuffers ) {
-			if( strokeBuffer.used == true ) {
-				var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y);
-				switch( currentBrush.brushMode.mode ) {
-					case AddSub :
-						copyPass.apply(strokeBuffer.prevTex, tile.heightMap);
-						copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.subAction ? Sub : Add);
-					case Set :
-						setHeight.shader.prevHeight = strokeBuffer.prevTex;
-						setHeight.shader.targetHeight = currentBrush.brushMode.setHeightValue;
-						setHeight.shader.strengthTex = strokeBuffer.tex;
-						h3d.Engine.getCurrent().pushTarget(tile.heightMap);
-						setHeight.render();
-					case Smooth :
-						smoothHeight.shader.prevHeight = strokeBuffer.prevTex;
-						smoothHeight.shader.prevHeightResolution = new h3d.Vector(strokeBuffer.tempTex.width, strokeBuffer.tempTex.height);
-						smoothHeight.shader.range = 4;
-						smoothHeight.shader.strengthTex = strokeBuffer.tex;
-						h3d.Engine.getCurrent().pushTarget(tile.heightMap);
-						smoothHeight.render();
-					default:
-				}
-			}
-		}
-
-		for( strokeBuffer in weightStrokeBufferArray.strokeBuffers ) {
-			if( strokeBuffer.used == true ) {
-				var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y);
-				copyPass.apply(strokeBuffer.prevTex, strokeBuffer.tempTex);
-				copyPass.apply(strokeBuffer.tex, strokeBuffer.tempTex, currentBrush.brushMode.subAction ? Sub : Add);
-				tile.generateWeightTextureArray();
-
-				var engine = h3d.Engine.getCurrent();
-				clampWeight.shader.weightTextures = tile.surfaceWeightArray;
-				clampWeight.shader.weightCount = tile.surfaceWeights.length;
-				clampWeight.shader.baseTexIndex = currentBrush.index;
-				for( i in 0 ... tile.surfaceWeights.length) {
-					if( i == currentBrush.index ) continue;
-					clampWeight.shader.curTexIndex = i;
-					engine.pushTarget(tile.surfaceWeights[i]);
-					clampWeight.render();
-				}
-				tile.generateWeightTextureArray();
-
-				normalizeWeight.shader.weightTextures = tile.surfaceWeightArray;
-				normalizeWeight.shader.weightCount = tile.surfaceWeights.length;
-				normalizeWeight.shader.baseTexIndex = currentBrush.index;
-				for( i in 0 ... tile.surfaceWeights.length ) {
-					normalizeWeight.shader.curTexIndex = i;
-					engine.pushTarget(tile.surfaceWeights[i]);
-					normalizeWeight.render();
-				}
-				tile.generateWeightTextureArray();
-
-				generateIndex.shader.weightTextures = tile.surfaceWeightArray;
-				generateIndex.shader.weightCount = tile.surfaceWeights.length;
-				engine.pushTarget(tile.surfaceIndexMap);
-				generateIndex.render();
-			}
-		}
-	}
-
-	function projectToGround( ray: h3d.col.Ray ) {
-		var minDist = -1.;
-		var normal = terrainPrefab.terrain.getAbsPos().up();
-		var plane = h3d.col.Plane.fromNormalPoint(normal.toPoint(), new h3d.col.Point(terrainPrefab.terrain.getAbsPos().tx, terrainPrefab.terrain.getAbsPos().ty, terrainPrefab.terrain.getAbsPos().tz));
-		var pt = ray.intersect(plane);
-		if(pt != null) { minDist = pt.sub(ray.getPos()).length();}
-		return minDist;
-	}
-
-	function screenToWorld( u : Float, v : Float, ctx : Context ) {
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return new h3d.col.Point();
-		var camera = @:privateAccess ctx.local3d.getScene().camera;
-		var ray = camera.rayFromScreen(u, v);
-		var dist = projectToGround(ray);
-		return dist >= 0 ? ray.getPoint(dist) : new h3d.col.Point();
-	}
-
-	function worldToScreen( wx: Float, wy: Float, wz: Float, ctx : Context ) {
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null || ctx.local2d == null || ctx.local2d.getScene() == null ) return new h2d.col.Point();
-		var camera = @:privateAccess ctx.local3d.getScene().camera;
-		var pt = camera.project(wx, wy, wz, h3d.Engine.getCurrent().width, h3d.Engine.getCurrent().height);
-		return new h2d.col.Point(hxd.Math.abs(pt.x), hxd.Math.abs(pt.y));
-	}
-
-	function getBrushPlanePos( mouseX : Float, mouseY : Float, ctx : Context ) {
-		var worldPos = screenToWorld(mouseX, mouseY, ctx);
-		if( currentBrush.brushMode.snapToGrid ) {
-			var localPos = terrainPrefab.terrain.globalToLocal(worldPos.clone());
-			localPos.x = hxd.Math.round(localPos.x / terrainPrefab.terrain.cellSize.x) * terrainPrefab.terrain.cellSize.x;
-			localPos.y = hxd.Math.round(localPos.y / terrainPrefab.terrain.cellSize.y) * terrainPrefab.terrain.cellSize.y;
-			localPos.z = localPos.z;
-			worldPos = terrainPrefab.terrain.globalToLocal(localPos.clone());
-		}
-		return worldPos;
-	}
-
-	function getBrushWorldPosFromTex( worldPos : h3d.col.Point, ctx : Context ) : h3d.col.Point {
-		if(currentBrush.brushMode.snapToGrid) return worldPos;
-		var screenPos = worldToScreen(worldPos.x, worldPos.y, worldPos.z, ctx);
-		var brushWorldPos = worldPos.clone();
-		var fetchPos = new h2d.col.Point(hxd.Math.floor(screenPos.x * uvTexRes), hxd.Math.floor(screenPos.y * uvTexRes));
-		fetchPos.x = hxd.Math.clamp(fetchPos.x, 0, uvTexPixels.width - 1);
-		fetchPos.y = hxd.Math.clamp(fetchPos.y, 0, uvTexPixels.height - 1);
-		var pixel = uvTexPixels.getPixelF( Std.int(fetchPos.x), Std.int(fetchPos.y));
-		var tiles = terrainPrefab.terrain.tiles;
-		for( i in 0 ... tiles.length )
-			if( hxd.Math.ceil(pixel.z) == i )
-				brushWorldPos = tiles[i].localToGlobal(new h3d.col.Point(pixel.x * terrainPrefab.tileSizeX, pixel.y * terrainPrefab.tileSizeY, 0));
-		return brushWorldPos;
-	}
-
-	function drawBrushPreview( worldPos : h3d.col.Point, ctx : Context ) {
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return;
-		brushPreview.reset();
-		if( currentBrush.brushMode.mode == Delete || currentBrush.bitmap == null ) return;
-		var brushWorldPos = uvTexPixels == null ? worldPos : getBrushWorldPosFromTex(worldPos, ctx);
-		brushPreview.previewAt(currentBrush, brushWorldPos);
-	}
-
-	function applyBrush( pos : h3d.col.Point, ctx : Context ) {
-		switch ( currentBrush.brushMode.mode ) {
-			case Paint: drawSurface(pos, ctx);
-			case AddSub: drawHeight(pos, ctx);
-			case Smooth: drawHeight(pos, ctx);
-			case Set: drawHeight(pos, ctx);
-			case Delete: deleteTile(pos, ctx);
-			default:
-		}
-		terrainPrefab.modified = true;
-	}
-
-	function useBrush( from : h3d.col.Point, to : h3d.col.Point, ctx : Context ) {
-		var dist = (to.sub(from)).length();
-		if( currentBrush.firstClick ) {
-			if( currentBrush.brushMode.mode == Set ) {
-				if( currentBrush.brushMode.subAction )
-					currentBrush.brushMode.setHeightValue = terrainPrefab.terrain.getHeight(from.x, from.y);
-				else
-					currentBrush.brushMode.setHeightValue = currentBrush.strength;
-			}
-			applyBrush(from, ctx);
-			previewStrokeBuffers();
-			return;
-		}
-
-		if( currentBrush == null || currentBrush.step <= 0 ) return;
-
-		var dist = (to.sub(from)).length();
-		if( dist + remainingDist >= currentBrush.step ) {
-			var dir = to.sub(from);
-			dir.normalize();
-			var pos = from.clone();
-			var step = dir.clone();
-			step.scale(currentBrush.step);
-			while( dist + remainingDist >= currentBrush.step ) {
-				if( remainingDist > 0 ) {
-					var firstStep = dir.clone();
-					firstStep.scale(currentBrush.step - remainingDist);
-					pos = pos.add(firstStep);
-				}else
-					pos = pos.add(step);
-				applyBrush(pos, ctx);
-				dist -= currentBrush.step - remainingDist;
-				remainingDist = 0;
-			}
-			remainingDist = dist;
-			previewStrokeBuffers();
-		}else
-			remainingDist += dist;
-	}
-
-	public function deleteTile( pos : h3d.col.Point, ctx : Context ) {
-		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx);
-		if( brushWorldPos == null ) return;
-		var tile = terrainPrefab.terrain.getTileAtWorldPos(brushWorldPos.x, brushWorldPos.y);
-		if( tile == null ) return;
-		var trd = new TileRevertData(tile.tileX, tile.tileY);
-		trd.prevHeightMapPixels = tile.heightMap.capturePixels();
-		trd.prevSurfaceIndexMapPixels = tile.surfaceIndexMap.capturePixels();
-		for( w in tile.surfaceWeights )
-			trd.prevWeightMapPixels.push(w.capturePixels());
-		tileTrashBin.push(trd);
-		terrainPrefab.terrain.removeTile(tile);
-		renderTerrainUV(ctx);
-	}
-
-	public function drawSurface( pos : h3d.col.Point, ctx : Context ) {
-		if( currentBrush.index == -1 ) return;
-		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx);
-		if( brushWorldPos == null ) return;
-		var c = terrainPrefab.terrain.tiles.length;
-		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
-		if( c != terrainPrefab.terrain.tiles.length ) {
-			renderTerrainUV(ctx);
-			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
-		}
-
-		currentBrush.bitmap.color = new h3d.Vector(1.0);
-		var shader : hrt.shader.Brush = currentBrush.bitmap.getShader(hrt.shader.Brush);
-		if( shader == null ) shader = currentBrush.bitmap.addShader(new hrt.shader.Brush());
-		currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max;
-		shader.strength = currentBrush.strength;
-		shader.size.set(currentBrush.size / terrainPrefab.tileSizeX, currentBrush.size / terrainPrefab.tileSizeY);
-
-		for( tile in tiles ) {
-			var strokeBuffer = weightStrokeBufferArray.getStrokeBuffer(tile.tileX, tile.tileY);
-			if( strokeBuffer.used == false ) {
-				var revert = new TileRevertData(strokeBuffer.x, strokeBuffer.y);
-				for( w in tile.surfaceWeights )
-					revert.prevWeightMapPixels.push(w.capturePixels());
-				paintRevertDatas.push(revert);
-				strokeBuffer.prevTex = tile.surfaceWeights[currentBrush.index];
-				tile.surfaceWeights[currentBrush.index] = strokeBuffer.tempTex;
-				strokeBuffer.used = true;
-			}
-			var localPos = tile.globalToLocal(brushWorldPos.clone());
-			localPos.x *= 1.0 / terrainPrefab.tileSizeX;
-			localPos.y *= 1.0 / terrainPrefab.tileSizeY;
-			shader.pos = new h3d.Vector(localPos.x - (currentBrush.size  / terrainPrefab.tileSizeX * 0.5), localPos.y - (currentBrush.size  / terrainPrefab.tileSizeY * 0.5));
-			currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.terrain.tileSize );
-		}
-	}
-
-	public function drawHeight( pos : h3d.col.Point, ctx : Context ) {
-		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx);
-		if( brushWorldPos == null ) return;
-		var c = terrainPrefab.terrain.tiles.length;
-		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
-		if( c != terrainPrefab.terrain.tiles.length ) {
-			renderTerrainUV(ctx);
-			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
-		}
-
-		var shader : hrt.shader.Brush = currentBrush.bitmap.getShader(hrt.shader.Brush);
-		if( shader == null ) shader = currentBrush.bitmap.addShader(new hrt.shader.Brush());
-		currentBrush.bitmap.color = new h3d.Vector(1.0);
-		shader.size.set(currentBrush.size / terrainPrefab.tileSizeX, currentBrush.size / terrainPrefab.tileSizeY);
-
-		switch( currentBrush.brushMode.mode ) {
-			case AddSub :
-				currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max;
-				shader.strength = currentBrush.strength;
-			case Set :
-				currentBrush.bitmap.blendMode = Max;
-				shader.strength = 1;
-			case Smooth :
-				currentBrush.bitmap.blendMode = Max;
-				shader.strength = 1;
-			default:
-		}
-
-		for( tile in tiles ) {
-			var localPos = tile.globalToLocal(brushWorldPos.clone());
-			localPos.x *= 1.0 / terrainPrefab.tileSizeX;
-			localPos.y *= 1.0 / terrainPrefab.tileSizeY;
-			var strokeBuffer = heightStrokeBufferArray.getStrokeBuffer(tile.tileX, tile.tileY);
-			if( strokeBuffer.used == false ) {
-				strokeBuffer.prevTex = tile.heightMap;
-				tile.heightMap = strokeBuffer.tempTex;
-				strokeBuffer.used = true;
-			}
-			shader.pos = new h3d.Vector(localPos.x - (currentBrush.size  / terrainPrefab.tileSizeX * 0.5), localPos.y - (currentBrush.size  / terrainPrefab.tileSizeY * 0.5));
-			currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.terrain.tileSize, -1);
-		}
-	}
-
-	public function setSelected( ctx : Context, b : Bool ) {
-		if( b ) {
-			var s2d = @:privateAccess ctx.local2d.getScene();
-			if( interactive == null )
-				interactive.remove();
-			interactive = new h2d.Interactive(10000, 10000, s2d);
-			interactive.propagateEvents = true;
-			interactive.cancelEvents = false;
-
-			interactive.onWheel = function(e) {
-				e.propagate = true;
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
-				renderTerrainUV(ctx);
-				drawBrushPreview(worldPos, ctx);
-			};
-
-			interactive.onPush = function(e) {
-				e.propagate = false;
-				currentBrush.brushMode.lockDir = K.isDown(K.ALT);
-				currentBrush.brushMode.subAction = K.isDown(K.SHIFT);
-				currentBrush.brushMode.snapToGrid = K.isDown(K.CTRL);
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
-				if( K.isDown( K.MOUSE_LEFT) ) {
-					currentBrush.firstClick = true;
-					lastPos = worldPos.clone();
-					if( currentBrush.isValid() ) {
-						useBrush( lastPos, worldPos, ctx);
-						previewStrokeBuffers();
-						drawBrushPreview(worldPos, ctx);
-					}
-				}
-			};
-
-			interactive.onRelease = function(e) {
-				e.propagate = false;
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
-				remainingDist = 0;
-				lastPos = null;
-				currentBrush.brushMode.lockAxe = NoLock;
-				currentBrush.firstClick = false;
-				applyStrokeBuffers();
-				resetStrokeBuffers();
-				drawBrushPreview(worldPos, ctx);
-				checkTrashBin();
-			};
-
-			interactive.onMove = function(e) {
-
-				// Brush Scale - Drag left/right
-				if( K.isDown(K.MOUSE_RIGHT) && K.isDown(K.CTRL) ) {
-					if( lastMousePos == null ) {
-						lastMousePos = new h2d.col.Point(s2d.mouseX, s2d.mouseY);
-						lastBrushSize = currentBrush.size;
-					}
-					e.propagate = false;
-					var newMousePos = new h2d.col.Point(s2d.mouseX, s2d.mouseY);
-					var dist = newMousePos.x - lastMousePos.x;
-					var sensibility = 0.5;
-					currentBrush.size = hxd.Math.max(0, lastBrushSize + sensibility * dist);
-					@:privateAccess Lambda.find(editContext.properties.fields, f->f.fname=="editor.currentBrush.size").range.value = currentBrush.size;
-					drawBrushPreview(getBrushPlanePos(lastMousePos.x, lastMousePos.y, ctx), ctx);
-					return;
-				}
-				else {
-					lastMousePos = null;
-					lastBrushSize = 0;
-				}
-
-				currentBrush.brushMode.snapToGrid = /*K.isDown(K.CTRL)*/ false;
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
-				if( K.isDown( K.MOUSE_LEFT) ) {
-					currentBrush.firstClick = false;
-					e.propagate = false;
-					if( lastPos == null ) return;
-					if( currentBrush.isValid() ) {
-						if( currentBrush.brushMode.lockDir ){
-							var dir = worldPos.sub(lastPos);
-							if( currentBrush.brushMode.lockAxe == NoLock && dir.length() > 0.4 )
-								currentBrush.brushMode.lockAxe = hxd.Math.abs(dir.x) > hxd.Math.abs(dir.y) ? LockX : LockY;
-							if( currentBrush.brushMode.lockAxe == LockX ) {
-								var distX = worldPos.sub(lastPos).x;
-								worldPos.load(lastPos);
-								worldPos.x += distX;
-							}
-							else if( currentBrush.brushMode.lockAxe == LockY ) {
-								var distY = worldPos.sub(lastPos).y;
-								worldPos.load(lastPos);
-								worldPos.y += distY;
-							}
-						}
-						useBrush( lastPos, worldPos, ctx);
-						lastPos = worldPos;
-					}
-				}
-				else {
-					renderTerrainUV(ctx);
-					e.propagate = true;
-				}
-				drawBrushPreview(worldPos, ctx);
-			};
-		}
-		else {
-			if( interactive != null ) interactive.remove();
-			brushPreview.reset();
-		}
-	}
-
-	function removeSurface( index :Int, onChange : Void -> Void ) {
-		terrainPrefab.modified = true;
-		var terrainRevertData = new TerrainRevertData();
-		var tileRevertDatas = new Array<TileRevertData>();
-		for( tile in terrainPrefab.terrain.tiles )
-			tileRevertDatas.push(new TileRevertData(tile.tileX, tile.tileY));
-
-		var oldIndexes : Array<h3d.Vector> = [];
-		var newIndexes : Array<h3d.Vector> = [];
-		for( i in 0 ... terrainPrefab.terrain.surfaces.length )
-			oldIndexes.push(new h3d.Vector(i));
-		var offset = 0;
-		for( i in 0 ... terrainPrefab.terrain.surfaces.length ) {
-			if( i == index ) {
-				offset = -1;
-				newIndexes.push(new h3d.Vector(0)); // Replace the surface removec by the surface 0
-			}
-			else
-				newIndexes.push(new h3d.Vector(i + offset));
-		}
-
-		swapIndex.shader.USE_ARRAY = true;
-		swapIndex.shader.INDEX_COUNT = oldIndexes.length;
-		swapIndex.shader.oldIndexes = oldIndexes;
-		swapIndex.shader.newIndexes = newIndexes;
-		var newSurfaceIndexMap = new h3d.mat.Texture(terrainPrefab.terrain.weightMapResolution.x, terrainPrefab.terrain.weightMapResolution.y, [Target], RGBA);
-		for( i in 0 ... terrainPrefab.terrain.tiles.length ) {
-			var tile = terrainPrefab.terrain.tiles[i];
-			var revert = tileRevertDatas[i];
-			revert.prevSurfaceIndexMapPixels = tile.surfaceIndexMap.capturePixels();
-			for( w in tile.surfaceWeights ) revert.prevWeightMapPixels.push(w.capturePixels());
-			swapIndex.shader.surfaceIndexMap = tile.surfaceIndexMap;
-			h3d.Engine.getCurrent().pushTarget(newSurfaceIndexMap);
-			swapIndex.render();
-			copyPass.apply(newSurfaceIndexMap, tile.surfaceIndexMap);
-			tile.surfaceWeights.remove(tile.surfaceWeights[index]);
-			tile.generateWeightTextureArray();
-		}
-		terrainRevertData.surfaceIndex = index;
-		terrainRevertData.surface = terrainPrefab.terrain.surfaces[index];
-		terrainPrefab.terrain.surfaces.remove(terrainPrefab.terrain.surfaces[index]);
-		terrainPrefab.terrain.generateSurfaceArray();
-
-		for( i in 0 ... terrainPrefab.terrain.tiles.length ) {
-			var tile = terrainPrefab.terrain.tiles[i];
-			normalizeWeight.shader.weightTextures = tile.surfaceWeightArray;
-			normalizeWeight.shader.weightCount = tile.surfaceWeights.length;
-			normalizeWeight.shader.baseTexIndex = 0;
-			for( i in 0 ... tile.surfaceWeights.length ) {
-				normalizeWeight.shader.curTexIndex = i;
-				h3d.Engine.getCurrent().pushTarget(tile.surfaceWeights[i]);
-				normalizeWeight.render();
-			}
-			tile.generateWeightTextureArray();
-
-			generateIndex.shader.weightTextures = tile.surfaceWeightArray;
-			generateIndex.shader.weightCount = tile.surfaceWeights.length;
-			h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap);
-			generateIndex.render();
-
-			var revert = tileRevertDatas[i];
-			revert.nextSurfaceIndexMapPixels = tile.surfaceIndexMap.capturePixels();
-			for( w in tile.surfaceWeights ) revert.nextWeightMapPixels.push(w.capturePixels());
-		}
-
-		onChange();
-
-		undo.change(Custom(function(undo) {
-			terrainPrefab.modified = true;
-			if( undo )
-				terrainPrefab.terrain.surfaces.insert(terrainRevertData.surfaceIndex, terrainRevertData.surface);
-			else
-				terrainPrefab.terrain.surfaces.remove(terrainRevertData.surface);
-			terrainPrefab.terrain.generateSurfaceArray();
-
-			for( revertData in tileRevertDatas ) {
-				var tile = terrainPrefab.terrain.getTile(revertData.x, revertData.y);
-				if( tile == null ) continue;
-				var oldArray = tile.surfaceWeights;
-				tile.surfaceWeights = new Array<h3d.mat.Texture>();
-				tile.surfaceWeights = [for( i in 0...terrainPrefab.terrain.surfaces.length ) null];
-				for( i in 0 ... tile.surfaceWeights.length ) {
-					tile.surfaceWeights[i] = new h3d.mat.Texture(terrainPrefab.terrain.weightMapResolution.x, terrainPrefab.terrain.weightMapResolution.y, [Target], R8);
-					tile.surfaceWeights[i].wrap = Clamp;
-					tile.surfaceWeights[i].preventAutoDispose();
-				}
-				for( i in 0 ... oldArray.length )
-					if( oldArray[i] != null) oldArray[i].dispose();
-
-				tile.surfaceIndexMap.uploadPixels(undo ? revertData.prevSurfaceIndexMapPixels : revertData.nextSurfaceIndexMapPixels);
-
-				for( i in 0 ... tile.surfaceWeights.length )
-					tile.surfaceWeights[i].uploadPixels(undo ? revertData.prevWeightMapPixels[i] : revertData.nextWeightMapPixels[i]);
-
-				tile.generateWeightTextureArray();
-				generateIndex.shader.weightTextures = tile.surfaceWeightArray;
-				generateIndex.shader.weightCount = tile.surfaceWeights.length;
-				h3d.Engine.getCurrent().pushTarget(tile.surfaceIndexMap);
-				generateIndex.render();
-			}
-			onChange();
-		}));
-
-	}
-
-	function loadTexture( ctx : hide.prefab.EditContext, propsName : String, ?wrap : h3d.mat.Data.Wrap ) {
-		var texture = ctx.rootContext.shared.loadTexture(propsName);
-		texture.wrap = wrap == null ? Repeat : wrap;
-		return texture;
-	}
-
-	inline function setRange( name, value, ctx : EditContext ) {
-		var field = Lambda.find(ctx.properties.fields, f->f.fname==name);
-		if(field != null) @:privateAccess field.range.value = value;
-	}
-
-	function refreshSurfaces( props : hide.Element, ctx : EditContext ) {
-
-		if( currentSurface == null )
-			props.find('div[name="Params"]').hide();
-		else
-			props.find('div[name="Params"]').show();
-
-		var surfacesContainer = props.find(".terrain-surfaces");
-		surfacesContainer.empty();
-		for( i in 0 ... terrainPrefab.terrain.surfaces.length ){
-			var surface = terrainPrefab.terrain.surfaces[i];
-			if(surface == null || surface.albedo == null) continue;
-			var texName = surface.albedo.name.split(".");
-			texName = texName[0].split("/");
-			texName = texName[texName.length - 1].split("_Albedo");
-			var label = texName[0];
-			var img : Element;
-			if( i == currentBrush.index) img = new Element('<div class="surface-preview-selected"></div>');
-			else img = new Element('<div class="surface-preview"></div>');
-			var imgPath = ctx.ide.getPath(surface.albedo.name);
-			img.css("background-image", 'url("file://$imgPath")');
-			var surfaceElem = new Element('<div class=" surface"><span class="tooltiptext">$label</span></div>').prepend(img);
-			surfaceElem.contextmenu(function(e) {
-				e.preventDefault();
-				var cmi :Array< hide.comp.ContextMenu.ContextMenuItem> = [];
-				var delete : hide.comp.ContextMenu.ContextMenuItem = {label : "Delete"};
-				delete.click = function(){
-					removeSurface(i, function(){refreshSurfaces(props, ctx);});
-				};
-				cmi.push(delete);
-				var cm = new hide.comp.ContextMenu(cmi);
-			});
-			surfaceElem.click(function(e){
-				editContext.scene.setCurrent();
-				currentBrush.index = i;
-				currentSurface = terrainPrefab.terrain.getSurface(i);
-				refreshSurfaces(props, ctx);
-			});
-			surfacesContainer.append(surfaceElem);
-		}
-		if( currentSurface != null ) {
-			setRange("editor.currentSurface.tilling", currentSurface.tilling, ctx);
-			setRange("editor.currentSurface.offset.x", currentSurface.offset.x, ctx);
-			setRange("editor.currentSurface.offset.y", currentSurface.offset.y, ctx);
-			setRange("editor.currentSurface.angle", currentSurface.angle, ctx);
-			setRange("editor.currentSurface.minHeight", currentSurface.minHeight, ctx);
-			setRange("editor.currentSurface.maxHeight", currentSurface.maxHeight, ctx);
-		}
-	}
-
-	function refreshBrushMode (props : hide.Element, ctx : EditContext ) {
-		var brushIcons = ["icons/addsub.png", "icons/set.png", "icons/smooth.png", "icons/paint.png", "icons/delete.png"];
-		var brushMode = [Brush.Mode.AddSub, Brush.Mode.Set, Brush.Mode.Smooth, Brush.Mode.Paint, Brush.Mode.Delete];
-		var brushDescription = [
-			'Raiser / Lower Terrain <br>
-			<i>Click to raise, hold down shift to lower</i>',
-			'Paint height <br>
-			<i>Hold down shift to sample target height</i>',
-			'Smooth height <br>
-			<i>Paint to smooth the terrain</i>',
-			'Paint surface <br>
-			<i>Hold down shift to subsract</i>',
-			'Delete tile <br>
-			<i>Paint to delete tiles</i>'];
-		var brushModeContainer = props.find(".terrain-brushModeContainer");
-		brushModeContainer.empty();
-		for( i in 0 ... brushIcons.length ) {
-			var elem = new Element('<div class="terrain-brushMode"></div>');
-			var img = new Element('<div class="terrain-brushModeIcon"></div>');
-			img.css("background-image", 'url("file://${ctx.ide.getPath("${HIDE}/res/" + brushIcons[i])}")');
-			elem.prepend(img);
-			elem.click(function(_) {
-				editContext.scene.setCurrent();
-				var l = props.find(".terrain-brushModeIcon");
-				for( e in l ) {
-					var elem = new Element(e);
-					elem.toggleClass("selected", false);
-				}
-				img.toggleClass("selected", true);
-				currentBrush.brushMode.mode = brushMode[i];
-				var desc = props.find(".terrain-brushModeDescription");
-				desc.empty();
-				desc.append(brushDescription[i]);
-
-			});
-			brushModeContainer.append(elem);
-		}
-	}
-
-	var brushMode =
-	'<div class="group" name="Mode">
-		<div class="terrain-brushModeContainer" align="center"></div>
-		<div class="terrain-brushModeDescription" align="center">
-			<i> Please select a tool </i>
-		</div>
-		<dt>AutoCreate</dt><dd><input type="checkbox" field="autoCreateTile"/></dd>
-		<dt>Accumulate</dt><dd><input type="checkbox" field="editor.currentBrush.brushMode.accumulate"/></dd>
-	</div>';
-
-	var brushParams =
-	'<div class="group" name="Brush">
-		<div class="terrain-brushes"></div>
-		<dt>Size</dt><dd><input type="range" min="0.01" max="50" field="editor.currentBrush.size"/></dd>
-		<dt>Strength</dt><dd><input type="range" min="0" max="1" field="editor.currentBrush.strength"/></dd>
-		<dt>Step</dt><dd><input type="range" min="0.01" max="10" field="editor.currentBrush.step"/></dd>
-		<dt>Opacity</dt><dd><input type="range" min="0" max="1" field="brushOpacity"/></dd>
-	</div>';
-
-	var surfaceParams =
-	'<div class="group">
-		<div class="title">Surface <input type="button" style="font-weight:bold" id="addSurface" value="+"/></div>
-		<div class="terrain-surfaces"></div>
-		<div class="group" name="Params">
-			<dt>Tilling</dt><dd><input type="range" min="0" max="2" field="editor.currentSurface.tilling"/></dd>
-			<dt>Offset X</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.offset.x"/></dd>
-			<dt>Offset Y</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.offset.y"/></dd>
-			<dt>Rotate</dt><dd><input type="range" min="0" max="360" field="editor.currentSurface.angle"/></dd>
-			<dt>Min Height</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.minHeight"/></dd>
-			<dt>Max Height</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.maxHeight"/></dd>
-		</div>
-	</div>';
-
-	public function setupUI( props : hide.Element, ctx : EditContext ) {
-		props.append(brushMode);
-		props.append(brushParams);
-		props.append(surfaceParams);
-		props.find("#addSurface").click(function(_) {
-			ctx.ide.chooseImage(onSurfaceAdd.bind(props,ctx));
-		});
-		refreshBrushMode(props, ctx);
-
-		var brushes : Array<Dynamic> = ctx.scene.config.get("terrain.brushes");
-		var brushesContainer = props.find(".terrain-brushes");
-		function refreshBrushes() {
-			brushesContainer.empty();
-			for( brush in brushes ) {
-				var label = brush.name + "</br>Step : " + brush.step + "</br>Strength : " + brush.strength + "</br>Size : " + brush.size ;
-				var img : Element;
-				if( brush.name == currentBrush.name ) img = new Element('<div class="brush-preview-selected"></div>');
-				else img = new Element('<div class="brush-preview"></div>');
-				img.css("background-image", 'url("file://${ctx.ide.getPath(brush.texture)}")');
-				var brushElem = new Element('<div class="brush"><span class="tooltiptext">$label</span></div>').prepend(img);
-				brushElem.click(function(e){
-					editContext.scene.setCurrent();
-					currentBrush.size = brush.size;
-					currentBrush.strength = brush.strength;
-					currentBrush.step = brush.step;
-					currentBrush.texPath = ctx.ide.getPath(brush.texture);
-					currentBrush.tex = loadTexture(ctx, currentBrush.texPath);
-					currentBrush.name = brush.name;
-					if( currentBrush.tex != null ) {
-						if( currentBrush.bitmap != null ) {
-							currentBrush.bitmap.tile.dispose();
-							currentBrush.bitmap.tile = h2d.Tile.fromTexture(currentBrush.tex);
-						}
-						else
-							currentBrush.bitmap = new h2d.Bitmap(h2d.Tile.fromTexture(currentBrush.tex));
-
-						currentBrush.bitmap.smooth = true;
-						currentBrush.bitmap.color = new h3d.Vector(currentBrush.strength);
-					}
-					refreshBrushes();
-				});
-				brushesContainer.append(brushElem);
-			}
-			if( currentBrush != null ) {
-				setRange("editor.currentBrush.size", currentBrush.size, ctx);
-				setRange("editor.currentBrush.strength", currentBrush.strength, ctx);
-				setRange("editor.currentBrush.step", currentBrush.step, ctx);
-			}
-		}
-		refreshBrushes();
-		refreshSurfaces(props, ctx);
-	}
-
-	function onSurfaceAdd( props : Element, ctx : EditContext, path : String ) {
-		editContext.scene.setCurrent();
-		terrainPrefab.modified = true;
-		var split : Array<String> = [];
-		var curTypeIndex = 0;
-		while( split.length <= 1 && curTypeIndex < textureType.length) {
-			split = path.split(textureType[curTypeIndex]);
-			curTypeIndex++;
-		}
-		if( split.length <= 1 ) {
-			ctx.ide.error("Invalid file name format, should be name_Albedo");
-			return;
-		}
-		var name = split[0];
-		var ext = "."+path.split(".").pop();
-		var albedo = ctx.rootContext.shared.loadTexture(name + textureType[0] + ext);
-		var normal = ctx.rootContext.shared.loadTexture(name + textureType[1] + ext);
-		var pbr = ctx.rootContext.shared.loadTexture(name + textureType[2] + ext);
-
-		if( albedo == null || normal == null || pbr == null ) return;
-
-		function wait() {
-			if( albedo.flags.has(Loading) || normal.flags.has(Loading)|| pbr.flags.has(Loading))
-				haxe.Timer.delay(wait, 1);
-			else{
-				if( terrainPrefab.terrain.getSurfaceFromTex(name + textureType[0] + ext, name + textureType[1] + ext, name + textureType[2] + ext) == null ) {
-					terrainPrefab.terrain.addSurface(albedo, normal, pbr);
-					terrainPrefab.terrain.generateSurfaceArray();
-					refreshSurfaces(props, ctx);
-					var terrainRevertData = new TerrainRevertData();
-					terrainRevertData.surface = terrainPrefab.terrain.getSurface(terrainPrefab.terrain.surfaces.length - 1);
-					terrainRevertData.surfaceIndex = terrainPrefab.terrain.surfaces.length - 1;
-					undo.change(Custom(function(undo) {
-						if( undo ) {
-							terrainPrefab.terrain.surfaces.remove(terrainRevertData.surface);
-							if( currentSurface == terrainRevertData.surface ) currentSurface = null;
-							currentBrush.index = Std.int(hxd.Math.min(terrainPrefab.terrain.surfaces.length - 1, currentBrush.index));
-						}
-						else
-							terrainPrefab.terrain.surfaces.push(terrainRevertData.surface);
-						terrainPrefab.terrain.generateSurfaceArray();
-						refreshSurfaces(props, ctx);
-					}));
-				}
-				albedo.dispose();
-				normal.dispose();
-				pbr.dispose();
-			}
-		}
-		wait();
-	}
-
-}

+ 0 - 1782
hide/view/FXEditor.hx

@@ -1,1782 +0,0 @@
-package hide.view;
-import hrt.prefab.Light;
-using Lambda;
-
-import hide.Element;
-import hrt.prefab.Prefab in PrefabElement;
-import hrt.prefab.Curve;
-import hrt.prefab.fx.Event;
-import hide.view.CameraController.CamController;
-
-typedef PropTrackDef = {
-	name: String,
-	?def: Float
-};
-
-@:access(hide.view.FXEditor)
-class FXEditContext extends hide.prefab.EditContext {
-	var parent : FXEditor;
-	public function new(parent, context) {
-		super(context);
-		this.parent = parent;
-	}
-	override function onChange(p, propName) {
-		super.onChange(p, propName);
-		parent.onPrefabChange(p, propName);
-	}
-}
-
-@:access(hide.view.FXEditor)
-private class FXSceneEditor extends hide.comp.SceneEditor {
-	var parent : hide.view.FXEditor;
-	public function new(view,  data) {
-		super(view, data);
-		parent = cast view;
-	}
-
-	override function onSceneReady() {
-		super.onSceneReady();
-		parent.onSceneReady();
-	}
-
-	override function onPrefabChange(p: PrefabElement, ?pname: String) {
-		super.onPrefabChange(p, pname);
-		parent.onPrefabChange(p, pname);
-	}
-
-	override function update(dt) {
-		super.update(dt);
-		parent.onUpdate(dt);
-	}
-
-	override function duplicate(thenMove : Bool) {
-		if(curEdit == null) return;
-		var elements = curEdit.rootElements;
-		if(elements == null || elements.length == 0)
-			return;
-		if( isDuplicating )
-			return;
-		isDuplicating = true;
-		if( gizmo.moving ) {
-			@:privateAccess gizmo.finishMove();
-		}
-		var undoes = [];
-		var newElements = [];
-		for(elt in elements) {
-			var clone = elt.cloneData();
-			var index = elt.parent.children.indexOf(elt) + 1;
-			clone.parent = elt.parent;
-			elt.parent.children.remove(clone);
-			elt.parent.children.insert(index, clone);
-			autoName(clone);
-			makeInstance(clone);
-			newElements.push(clone);
-
-			undoes.push(function(undo) {
-				if(undo) elt.parent.children.remove(clone);
-				else elt.parent.children.insert(index, clone);
-			});
-		}
-		refresh(Full, function() {
-			selectElements(newElements);
-			tree.setSelection(newElements);
-			if(thenMove && curEdit.rootObjects.length > 0) {
-				gizmo.startMove(MoveXY, true);
-				gizmo.onFinishMove = function() {
-					refreshProps();
-				}
-			}
-			isDuplicating = false;
-		});
-		refreshParents(elements);
-
-		undo.change(Custom(function(undo) {
-			selectElements([], NoHistory);
-
-			var fullRefresh = false;
-			if(undo) {
-				for(elt in newElements) {
-					if(!removeInstance(elt)) {
-						fullRefresh = true;
-						break;
-					}
-				}
-			}
-
-			for(u in undoes) u(undo);
-
-			if(!undo) {
-				for(elt in newElements)
-					makeInstance(elt);
-			}
-
-			refresh(fullRefresh ? Full : Partial);
-		}));
-
-	}
-
-	override function setElementSelected( p : PrefabElement, ctx : hrt.prefab.Context, b : Bool ) {
-		if( p.getParent(hrt.prefab.fx.Emitter) != null )
-			return false;
-		return super.setElementSelected(p, ctx, b);
-	}
-
-	override function selectElements( elts, ?mode ) {
-		super.selectElements(elts, mode);
-		parent.onSelect(elts);
-	}
-
-	override function refresh(?mode, ?callb:Void->Void) {
-		// Always refresh scene
-		refreshScene();
-		refreshTree(callb);
-		parent.onRefreshScene();
-	}
-
-	override function getNewContextMenu(current: PrefabElement, ?onMake: PrefabElement->Void=null, ?groupByType = true ) {
-		if(current != null && current.to(hrt.prefab.Shader) != null) {
-			var ret : Array<hide.comp.ContextMenu.ContextMenuItem> = [];
-			ret.push({
-				label: "Animation",
-				menu: parent.getNewTrackMenu(current)
-			});
-			return ret;
-		}
-		var allTypes = super.getNewContextMenu(current, onMake, false);
-		var recents = getNewRecentContextMenu(current, onMake);
-
-		var menu = [];
-		if (parent.is2D) {
-			for(name in ["Group 2D", "Bitmap", "Anim2D", "Atlas", "Particle2D", "Text", "Shader", "Shader Graph", "Placeholder"]) {
-				var item = allTypes.find(i -> i.label == name);
-				if(item == null) continue;
-				allTypes.remove(item);
-				menu.push(item);
-			}
-			if(current != null) {
-				menu.push({
-					label: "Animation",
-					menu: parent.getNewTrackMenu(current)
-				});
-			}
-		} else {
-			for(name in ["Group", "Polygon", "Model", "Shader", "Emitter"]) {
-				var item = allTypes.find(i -> i.label == name);
-				if(item == null) continue;
-				allTypes.remove(item);
-				menu.push(item);
-			}
-			if(current != null) {
-				menu.push({
-					label: "Animation",
-					menu: parent.getNewTrackMenu(current)
-				});
-			}
-
-			menu.push({
-				label: "Material",
-				menu: [
-					getNewTypeMenuItem("material", current, onMake, "Default"),
-					getNewTypeMenuItem("material", current, function (p) {
-						// TODO: Move material presets to props.json
-						p.props = {
-							PBR: {
-								mode: "BeforeTonemapping",
-								blend: "Alpha",
-								shadows: false,
-								culling: "Back",
-								colorMask: 0xff
-							}
-						}
-						if(onMake != null) onMake(p);
-					}, "Unlit")
-				]
-			});
-			menu.sort(function(l1,l2) return Reflect.compare(l1.label,l2.label));
-		}
-
-		var events = allTypes.filter(i -> StringTools.endsWith(i.label, "Event"));
-		if(events.length > 0) {
-			menu.push({
-				label: "Events",
-				menu: events
-			});
-			for(e in events)
-				allTypes.remove(e);
-		}
-
-		menu.push({label: null, isSeparator: true});
-		menu.push({
-			label: "Other",
-			menu: allTypes
-		});
-		menu.unshift({
-			label : "Recents",
-			menu : recents,
-		});
-		return menu;
-	}
-
-	override function getAvailableTags(p:PrefabElement) {
-		return cast ide.currentConfig.get("fx.tags");
-	}
-}
-
-class FXEditor extends FileView {
-
-	var sceneEditor : FXSceneEditor;
-	var data : hrt.prefab.fx.BaseFX;
-	var is2D : Bool = false;
-	var tabs : hide.comp.Tabs;
-	var fxprops : hide.comp.PropsEditor;
-
-	var tools : hide.comp.Toolbar;
-	var treePanel : hide.comp.ResizablePanel;
-	var animPanel : hide.comp.ResizablePanel;
-	var light : h3d.scene.fwd.DirLight;
-	var lightDirection = new h3d.Vector( 1, 2, -4 );
-
-	var scene(get, null):  hide.comp.Scene;
-	function get_scene() return sceneEditor.scene;
-	var properties(get, null):  hide.comp.PropsEditor;
-	function get_properties() return sceneEditor.properties;
-
-	// autoSync
-	var autoSync : Bool;
-	var currentVersion : Int = 0;
-	var lastSyncChange : Float = 0.;
-	var showGrid = true;
-	var grid : h3d.scene.Graphics;
-	var grid2d : h2d.Graphics;
-
-	var lastPan : h2d.col.Point;
-
-	var timelineLeftMargin = 10;
-	var xScale = 200.;
-	var xOffset = 0.;
-
-	var pauseButton : hide.comp.Toolbar.ToolToggle;
-	var currentTime : Float;
-	var selectMin : Float;
-	var selectMax : Float;
-	var previewMin : Float;
-	var previewMax : Float;
-	var curveEdits : Array<hide.comp.CurveEditor>;
-	var timeLineEl : Element;
-	var afterPanRefreshes : Array<Bool->Void> = [];
-	var statusText : h2d.Text;
-
-	var scriptEditor : hide.comp.ScriptEditor;
-	var fxScriptParser : hrt.prefab.fx.FXScriptParser;
-	var cullingPreview : h3d.scene.Sphere;
-
-	override function getDefaultContent() {
-		return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX().saveData()));
-	}
-
-	override function canSave() {
-		return data != null;
-	}
-
-	override function save() {
-		if( !canSave() )
-			return;
-		var content = ide.toJSON(data.saveData());
-		var newSign = haxe.crypto.Md5.encode(content);
-		if(newSign != currentSign)
-			haxe.Timer.delay(saveBackup.bind(content), 0);
-		currentSign = newSign;
-		sys.io.File.saveContent(getPath(), content);
-		super.save();
-	}
-
-	override function onDisplay() {
-		if( sceneEditor != null ) sceneEditor.dispose();
-		currentTime = 0.;
-		xOffset = -timelineLeftMargin / xScale;
-		var content = sys.io.File.getContent(getPath());
-		var json = haxe.Json.parse(content);
-		if (json.type == "fx")
-			data = new hrt.prefab.fx.FX();
-		else {
-			is2D = true;
-			data = new hrt.prefab.fx.FX2D();
-		}
-		data.loadData(json);
-		currentSign = haxe.crypto.Md5.encode(content);
-
-		element.html('
-			<div class="flex vertical">
-				<div style="flex: 0 0 30px;">
-					<span class="tools-buttons"></span>
-				</div>
-				<div class="scene-partition" style="display: flex; flex-direction: row; flex: 1; overflow: hidden;">
-					<div style="display: flex; flex-direction: column; flex: 1; overflow: hidden;">
-						<div class="flex heaps-scene"></div>
-						<div class="fx-animpanel">
-							<div class="top-bar">
-								<div class="timeline">
-									<div class="timeline-scroll"/>
-								</div>
-							</div>
-							<div class="anim-scroll"></div>
-							<div class="overlay-container">
-								<div class="overlay"></div>
-							</div>
-						</div>
-					</div>
-					<div class="tree-column">
-						<div class="flex vertical">
-							<div class="hide-toolbar" style="zoom: 80%">
-								<div class="button collapse-btn" title="Collapse all">
-									<div class="icon ico ico-reply-all"></div>
-								</div>
-							</div>
-							<div class="hide-scenetree"></div>
-						</div>
-					</div>
-					<div class="tabs">
-						<div class="tab expand" name="Scene" icon="sitemap">
-							<div class="hide-scroll"></div>
-						</div>
-						<div class="tab expand" name="Properties" icon="cog">
-							<div class="fx-props"></div>
-						</div>
-						<div class="tab expand" name="Script" icon="cog">
-							<div class="fx-script"></div>
-							<div class="fx-scriptParams"></div>
-						</div>
-					</div>
-				</div>
-			</div>');
-		tools = new hide.comp.Toolbar(null,element.find(".tools-buttons"));
-		tabs = new hide.comp.Tabs(null,element.find(".tabs"));
-		sceneEditor = new FXSceneEditor(this, data);
-		element.find(".hide-scenetree").first().append(sceneEditor.tree.element);
-		element.find(".hide-scroll").first().append(sceneEditor.properties.element);
-		element.find(".heaps-scene").first().append(sceneEditor.scene.element);
-
-		var treeColumn = element.find(".tree-column").first();
-		treePanel = new hide.comp.ResizablePanel(Horizontal, treeColumn);
-		treePanel.saveDisplayKey = "treeColumn";
-		treePanel.onResize = () -> @:privateAccess if( scene.window != null) scene.window.checkResize();
-
-		var fxPanel = element.find(".fx-animpanel").first();
-		animPanel = new hide.comp.ResizablePanel(Vertical, fxPanel);
-		animPanel.saveDisplayKey = "animPanel";
-		animPanel.onResize = () -> @:privateAccess if( scene.window != null) scene.window.checkResize();
-
-		refreshLayout();
-		element.resize(function(e) {
-			refreshTimeline(false);
-			rebuildAnimPanel();
-		});
-		element.find(".collapse-btn").click(function(e) {
-			sceneEditor.collapseTree();
-		});
-		fxprops = new hide.comp.PropsEditor(undo,null,element.find(".fx-props"));
-		{
-			var edit = new FXEditContext(this, sceneEditor.context);
-			edit.properties = fxprops;
-			edit.scene = sceneEditor.scene;
-			edit.cleanups = [];
-			data.edit(edit);
-		}
-
-		if (is2D) {
-			sceneEditor.camera2D = true;
-		}
-
-		var scriptElem = element.find(".fx-script");
-		scriptEditor = new hide.comp.ScriptEditor(data.scriptCode, null, scriptElem, scriptElem);
-		function onSaveScript() {
-			data.scriptCode = scriptEditor.code;
-			save();
-			skipNextChange = true;
-			modified = false;
-		}
-		scriptEditor.onSave = onSaveScript;
-		fxScriptParser = new hrt.prefab.fx.FXScriptParser();
-		data.scriptCode = scriptEditor.code;
-
-		keys.register("playPause", function() { pauseButton.toggle(!pauseButton.isDown()); });
-
-		currentVersion = undo.currentID;
-		sceneEditor.tree.element.addClass("small");
-
-		var timeline = element.find(".timeline");
-		var sMin = 0.0;
-		var sMax = 0.0;
-		timeline.contextmenu(function(e) {
-			var offset = e.clientX - timeline.offset().left;
-			var marker = data.markers.find(m -> hxd.Math.abs(offset - xt(m.t)) < 4);
-			new hide.comp.ContextMenu([
-			{ label : "Add marker", click : function() {
-				if(data.markers == null)
-					data.markers = [];
-				var prevVal = data.markers.copy();
-				data.markers.push({t : ixt(e.clientX - timeline.offset().left)});
-				undo.change(Field(data, "markers", prevVal), refreshTimeline.bind(false));
-				refreshTimeline(false);
-			} },
-			{ label : "Remove marker", enabled: marker != null, click : function() {
-				var prevVal = data.markers.copy();
-				data.markers.remove(marker);
-				undo.change(Field(data, "markers", prevVal), refreshTimeline.bind(false));
-				refreshTimeline(false);
-			} }
-			]);
-			e.preventDefault();
-			return false;
-		});
-		timeline.mousedown(function(e) {
-			var lastX = e.clientX;
-			var shift = e.shiftKey;
-			var ctrl = e.ctrlKey;
-			var xoffset = timeline.offset().left;
-			var clickTime = ixt(e.clientX - xoffset);
-
-			if(shift) {
-				sMin = hxd.Math.max(0, clickTime);
-			}
-			else if(ctrl) {
-				previewMin = hxd.Math.max(0, clickTime);
-			}
-
-			function updateMouse(e: js.jquery.Event) {
-				var dt = (e.clientX - lastX) / xScale;
-				if(e.which == 2) {
-					xOffset -= dt;
-					xOffset = hxd.Math.max(xOffset, -timelineLeftMargin/xScale);
-				}
-				else if(e.which == 1) {
-					if(shift) {
-						sMax = ixt(e.clientX - xoffset);
-					}
-					else if(ctrl) {
-						previewMax = ixt(e.clientX - xoffset);
-					}
-					else {
-						if(!pauseButton.isDown())
-							pauseButton.toggle(true);
-						currentTime = ixt(e.clientX - xoffset);
-						currentTime = hxd.Math.max(currentTime, 0);
-					}
-				}
-
-				if(hxd.Math.abs(sMax - sMin) < 1e-5) {
-					selectMin = 0;
-					selectMax = 0;
-				}
-				else {
-					selectMax = hxd.Math.max(sMin, sMax);
-					selectMin = hxd.Math.min(sMin, sMax);
-				}
-			}
-
-			if(data.markers != null) {
-				var marker = data.markers.find(m -> hxd.Math.abs(xt(clickTime) - xt(m.t)) < 4);
-				if(marker != null) {
-					var prevVal = marker.t;
-					startDrag(function(e) {
-						updateMouse(e);
-						var x = ixt(e.clientX - xoffset);
-						x = hxd.Math.max(0, x);
-						x = untyped parseFloat(x.toFixed(5));
-						marker.t = x;
-						refreshTimeline(true);
-					}, function(e) {
-						undo.change(Field(marker, "t", prevVal), refreshTimeline.bind(false));
-					});
-					e.preventDefault();
-					e.stopPropagation();
-					return;
-				}
-			}
-
-			element.mousemove(function(e: js.jquery.Event) {
-				updateMouse(e);
-				lastX = e.clientX;
-				refreshTimeline(true);
-				afterPan(true);
-			});
-			element.mouseup(function(e: js.jquery.Event) {
-				updateMouse(e);
-
-				if(previewMax < previewMin + 0.1) {
-					previewMin = 0;
-					previewMax = data.duration == 0 ? 5000 : data.duration;
-				}
-
-				element.off("mousemove");
-				element.off("mouseup");
-				e.preventDefault();
-				e.stopPropagation();
-				refreshTimeline(false);
-				afterPan(false);
-			});
-			e.preventDefault();
-			e.stopPropagation();
-		});
-
-		var wheelTimer : haxe.Timer = null;
-		timeline.on("mousewheel", function(e) {
-			var step = e.originalEvent.wheelDelta > 0 ? 1.0 : -1.0;
-			xScale *= Math.pow(1.125, step);
-			e.preventDefault();
-			e.stopPropagation();
-			refreshTimeline(false);
-			if(wheelTimer != null)
-				wheelTimer.stop();
-			wheelTimer = haxe.Timer.delay(function() {
-				for(ce in curveEdits) {
-					ce.xOffset = xOffset;
-					ce.xScale = xScale;
-					ce.refresh();
-				}
-				afterPan(false);
-			}, 50);
-		});
-
-		selectMin = 0.0;
-		selectMax = 0.0;
-		previewMin = 0.0;
-		previewMax = data.duration == 0 ? 5000 : data.duration;
-		refreshTimeline(false);
-	}
-
-	function refreshLayout() {
-		if (animPanel != null) animPanel.setSize();
-		if (treePanel != null) treePanel.setSize();
-	}
-
-	override function onActivate() {
-		if( sceneEditor != null )
-			refreshLayout();
-	}
-
-
-	public function onSceneReady() {
-		light = sceneEditor.scene.s3d.find(function(o) return Std.downcast(o, h3d.scene.fwd.DirLight));
-		if( light == null ) {
-			light = new h3d.scene.fwd.DirLight(scene.s3d);
-			light.enableSpecular = true;
-		} else
-			light = null;
-
-		var axis = new h3d.scene.Graphics(scene.s3d);
-		axis.z = 0.001;
-		axis.lineStyle(2,0xFF0000); axis.lineTo(1,0,0);
-		axis.lineStyle(1,0x00FF00); axis.moveTo(0,0,0); axis.lineTo(0,1,0);
-		axis.lineStyle(1,0x0000FF); axis.moveTo(0,0,0); axis.lineTo(0,0,1);
-		axis.lineStyle();
-		axis.material.mainPass.setPassName("debuggeom");
-		axis.visible = (!is2D) ? showGrid : false;
-
-		cullingPreview = new h3d.scene.Sphere(0xffffff, data.cullingRadius, true, scene.s3d);
-		cullingPreview.visible = (!is2D) ? showGrid : false;
-
-		tools.saveDisplayKey = "FXScene/tools";
-		tools.addButton("video-camera", "Perspective camera", () -> sceneEditor.resetCamera());
-
-		function renderProps() {
-			properties.clear();
-			var renderer = scene.s3d.renderer;
-			var group = new Element('<div class="group" name="Renderer"></div>');
-			renderer.editProps().appendTo(group);
-			properties.add(group, renderer.props, function(_) {
-				renderer.refreshProps();
-				if( !properties.isTempChange ) renderProps();
-			});
-			var lprops = {
-				power : Math.sqrt(light.color.r),
-				enable: true
-			};
-			var group = new Element('<div class="group" name="Light">
-				<dl>
-				<dt>Power</dt><dd><input type="range" min="0" max="4" field="power"/></dd>
-				</dl>
-			</div>');
-			properties.add(group, lprops, function(_) {
-				var p = lprops.power * lprops.power;
-				light.color.set(p, p, p);
-			});
-		}
-		tools.addButton("gears", "Renderer Properties", renderProps);
-
-		tools.addToggle("th", "Show grid", function(v) {
-			showGrid = v;
-			axis.visible = (is2D) ? false : v;
-			cullingPreview.visible = (is2D) ? false : v;
-			updateGrid();
-		}, showGrid);
-		tools.addColor("Background color", function(v) {
-			scene.engine.backgroundColor = v;
-			updateGrid();
-		}, scene.engine.backgroundColor);
-		tools.addToggle("refresh", "Auto synchronize", function(b) {
-			autoSync = b;
-		});
-		tools.addToggle("compass", "Local transforms", (v) -> sceneEditor.localTransform = v, sceneEditor.localTransform);
-		pauseButton = tools.addToggle("pause", "Pause animation", function(v) {}, false);
-		tools.addRange("Speed", function(v) {
-			scene.speed = v;
-		}, scene.speed);
-
-		statusText = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d);
-		statusText.setPosition(5, 5);
-
-		updateGrid();
-	}
-
-	function onPrefabChange(p: PrefabElement, ?pname: String) {
-		if(p == data) {
-			previewMax = hxd.Math.min(data.duration == 0 ? 5000 : data.duration, previewMax);
-			refreshTimeline(false);
-
-			cullingPreview.radius = data.cullingRadius;
-		}
-
-		if(p.to(Event) != null) {
-			afterPan(false);
-			data.refreshObjectAnims(sceneEditor.getContext(data));
-		}
-	}
-
-	function onRefreshScene() {
-		var renderProps = data.find(e -> e.to(hrt.prefab.RenderProps));
-		if(renderProps != null)
-			renderProps.applyProps(scene.s3d.renderer);
-		updateGrid();
-	}
-
-	override function onDragDrop(items : Array<String>, isDrop : Bool) {
-		return sceneEditor.onDragDrop(items,isDrop);
-	}
-
-	function onSelect(elts : Array<PrefabElement>) {
-		rebuildAnimPanel();
-	}
-
-	inline function xt(x: Float) return Math.round((x - xOffset) * xScale);
-	inline function ixt(px: Float) return px / xScale + xOffset;
-
-	function refreshTimeline(anim: Bool) {
-		var scroll = element.find(".timeline-scroll");
-		scroll.empty();
-		var width = scroll.parent().width();
-		var minX = Math.floor(ixt(0));
-		var maxX = Math.ceil(hxd.Math.min(data.duration == 0 ? 5000 : data.duration, ixt(width)));
-		for(ix in minX...(maxX+1)) {
-			var mark = new Element('<span class="mark"></span>').appendTo(scroll);
-			mark.css({left: xt(ix)});
-			mark.text(ix + ".00");
-		}
-
-		var overlay = element.find(".overlay");
-		overlay.empty();
-		timeLineEl = new Element('<span class="time-marker"></span>').appendTo(overlay);
-		timeLineEl.css({left: xt(currentTime)});
-
-		if(data.markers != null) {
-			for(m in data.markers) {
-				var el = new Element('<span class="marker"></span>').appendTo(overlay);
-				el.css({left: xt(m.t)});
-			}
-		}
-
-		var select = new Element('<span class="selection"></span>').appendTo(overlay);
-		select.css({left: xt(selectMin), width: xt(selectMax) - xt(selectMin)});
-
-		if(!anim && selectMax != selectMin) {
-			var selLeft = new Element('<span class="selection-left"></span>').appendTo(overlay);
-			var selRight = new Element('<span class="selection-right"></span>').appendTo(overlay);
-
-			function updateSelectPos() {
-				select.css({left: xt(selectMin), width: xt(selectMax) - xt(selectMin)});
-				selLeft.css({left: xt(selectMin) - 4});
-				selRight.css({left: xt(selectMax)});
-			}
-			updateSelectPos();
-
-			function refreshViews() {
-				for(ce in curveEdits) {
-					ce.refreshGraph(false);
-					ce.onChange(false);
-				}
-			}
-
-			var curves = null;
-			var allKeys = null;
-
-			function updateSelected() {
-				curves = [];
-				var anyNonEmitter = curveEdits.find(ce -> !isInstanceCurve(ce.curve)) != null;
-				for(ce in curveEdits) {
-					if(anyNonEmitter && isInstanceCurve(ce.curve))
-						continue;  // Filter-out emitter curves unless only emitter curves are selected
-					curves.push(ce.curve);
-				}
-
-				allKeys = [];
-				for(curve in curves) {
-					for(key in curve.keys) {
-						if(key.time >= selectMin && key.time <= selectMax)
-							allKeys.push(key);
-					}
-				}
-			}
-
-			var backup = null;
-			var prevSel = null;
-
-			function beforeChange() {
-				backup = [for(c in curves) haxe.Json.parse(haxe.Json.stringify(c.save()))];
-				prevSel = [selectMin, selectMax];
-			}
-
-			function afterChange() {
-				var newVals = [for(c in curves) haxe.Json.parse(haxe.Json.stringify(c.save()))];
-				var newSel = [selectMin, selectMax];
-				undo.change(Custom(function(undo) {
-					if(undo) {
-						for(i in 0...curves.length)
-							curves[i].load(backup[i]);
-						selectMin = prevSel[0];
-						selectMax = prevSel[1];
-					}
-					else {
-						for(i in 0...curves.length)
-							curves[i].load(newVals[i]);
-						selectMin = newSel[0];
-						selectMax = newSel[1];
-					}
-					updateSelected();
-					updateSelectPos();
-					refreshViews();
-				}));
-				refreshViews();
-			}
-
-			var duplicateMode = false;
-			var previewKeys = [];
-			function setupSelectDrag(element: js.jquery.JQuery, update: Float->Float->Void) {
-				element.mousedown(function(e) {
-					updateSelected();
-
-					if(e.button != 0)
-						return;
-					var offset = scroll.offset();
-					e.preventDefault();
-					e.stopPropagation();
-					var lastTime = ixt(e.clientX);
-					beforeChange();
-					startDrag(function(e) {
-						var time = ixt(e.clientX);
-						update(time, lastTime);
-						for(ce in curveEdits) {
-							ce.refreshGraph(true);
-							ce.onChange(true);
-						}
-						updateSelectPos();
-						lastTime = time;
-					}, function(e) {
-						for (pKey in previewKeys) {
-							var curve = curves.find((curve) -> return curve.previewKeys.contains(pKey));
-							curve.previewKeys.remove(pKey);
-						}
-						previewKeys = [];
-						for(ce in curveEdits) {
-							ce.refreshGraph(true);
-							ce.onChange(true);
-						}
-						afterChange();
-					}, function(e) {
-						if (e.keyCode == hxd.Key.ALT){
-							if (!duplicateMode) {
-								duplicateMode = !duplicateMode;
-								for (key in allKeys) {
-									var curve = curves.find((curve) -> return curve.keys.contains(key));
-									var pKey = curve.addPreviewKey(key.time, key.value);
-									previewKeys.push(pKey);
-								}
-								allKeys = [];
-								for(ce in curveEdits) {
-									ce.refreshGraph(true);
-									ce.onChange(true);
-								}
-							}
-						}
-					}, function(e) {
-						if (e.keyCode == hxd.Key.ALT){
-							if (duplicateMode) {
-								duplicateMode = !duplicateMode;
-								for (pKey in previewKeys) {
-									var curve = curves.find((curve) -> return curve.previewKeys.contains(pKey));
-									curve.previewKeys.remove(pKey);
-									allKeys.push(curve.addKey(pKey.time, pKey.value));
-								}
-								previewKeys = [];
-								for(ce in curveEdits) {
-									ce.refreshGraph(true);
-									ce.onChange(true);
-								}
-							}
-						}
-					});
-				});
-			}
-
-			setupSelectDrag(selRight, function(time, lastTime) {
-				var shift = time - lastTime;
-				if(selectMax > selectMin + 0.1) {
-					var scaleFactor = (selectMax + shift - selectMin) / (selectMax - selectMin);
-
-					if (duplicateMode) {
-						for (key in previewKeys)
-							key.time = (key.time - selectMin) * scaleFactor + selectMin;
-					}
-					else {
-						for(key in allKeys)
-							key.time = (key.time - selectMin) * scaleFactor + selectMin;
-					}
-
-					selectMax += shift;
-				}
-			});
-
-			setupSelectDrag(selLeft, function(time, lastTime) {
-				var shift = time - lastTime;
-				if(selectMax > selectMin + 0.1) {
-					var scaleFactor = (selectMax - (selectMin + shift)) / (selectMax - selectMin);
-
-					if (duplicateMode) {
-						for(key in previewKeys)
-							key.time = selectMax - (selectMax - key.time) * scaleFactor;
-					}
-					else {
-						for(key in allKeys)
-							key.time = selectMax - (selectMax - key.time) * scaleFactor;
-					}
-
-					selectMin += shift;
-				}
-			});
-
-			setupSelectDrag(select, function(time, lastTime) {
-				var shift = time - lastTime;
-
-				if (duplicateMode) {
-					for(key in previewKeys)
-						key.time += shift;
-				}
-				else {
-					for(key in allKeys)
-						key.time += shift;
-				}
-				selectMin += shift;
-				selectMax += shift;
-
-			});
-		}
-
-		//var preview = new Element('<span class="preview"></span>').appendTo(overlay);
-		// preview.css({left: xt(previewMin), width: xt(previewMax) - xt(previewMin)});
-		var prevLeft = new Element('<span class="preview-left"></span>').appendTo(overlay);
-		prevLeft.css({left: 0, width: xt(previewMin)});
-		var prevRight = new Element('<span class="preview-right"></span>').appendTo(overlay);
-		prevRight.css({left: xt(previewMax), width: xt(data.duration == 0 ? 5000 : data.duration) - xt(previewMax)});
-	}
-
-	function afterPan(anim: Bool) {
-		if(!anim) {
-			for(curve in curveEdits) {
-				curve.setPan(xOffset, curve.yOffset);
-			}
-		}
-		for(clb in afterPanRefreshes) {
-			clb(anim);
-		}
-	}
-
-	function addCurvesTrack(trackName: String, curves: Array<Curve>, tracksEl: Element) {
-		var keyTimeTolerance = 0.05;
-		var trackEdits : Array<hide.comp.CurveEditor> = [];
-		var trackEl = new Element('<div class="track">
-			<div class="track-header">
-				<div class="track-prop">
-					<label>${upperCase(trackName)}</label>
-					<div class="track-toggle"><div class="icon ico"></div></div>
-				</div>
-				<div class="dopesheet"></div>
-			</div>
-			<div class="curves"></div>
-		</div>');
-		if(curves.length == 0)
-			return;
-		var parent = curves[0].parent;
-		var isColorTrack = trackName.toLowerCase().indexOf("color") >= 0 && (curves.length == 3 || curves.length == 4);
-		var isColorHSL = isColorTrack && curves.find(c -> StringTools.endsWith(c.name, ".h")) != null;
-
-		var trackToggle = trackEl.find(".track-toggle");
-		tracksEl.append(trackEl);
-		var curvesContainer = trackEl.find(".curves");
-		var trackKey = "trackVisible:" + parent.getAbsPath(true) + "/" + trackName;
-		var expand = getDisplayState(trackKey) == true;
-		function updateExpanded() {
-			var icon = trackToggle.find(".icon");
-			if(expand)
-				icon.removeClass("ico-angle-right").addClass("ico-angle-down");
-			else
-				icon.removeClass("ico-angle-down").addClass("ico-angle-right");
-			curvesContainer.toggleClass("hidden", !expand);
-			for(c in trackEdits)
-				c.refresh();
-		}
-		trackEl.find(".track-prop").click(function(e) {
-			expand = !expand;
-			saveDisplayState(trackKey, expand);
-			updateExpanded();
-		});
-		var dopesheet = trackEl.find(".dopesheet");
-		var evaluator = new hrt.prefab.fx.Evaluator(new hxd.Rand(0));
-
-		function getKeyColor(key) {
-			return evaluator.getVector(Curve.getColorValue(curves), key.time);
-		}
-
-		function dragKey(from: hide.comp.CurveEditor, prevTime: Float, newTime: Float) {
-			for(edit in trackEdits) {
-				if(edit == from) continue;
-				var k = edit.curve.findKey(prevTime, keyTimeTolerance);
-				if(k != null) {
-					newTime = hxd.Math.clamp(newTime, 0.0, edit.curve.maxTime);
-					k.time = newTime;
-					edit.refreshGraph(false, k);
-				}
-			}
-		}
-		function refreshCurves(anim: Bool) {
-			for(c in trackEdits) {
-				c.refreshGraph(anim);
-			}
-		}
-
-		function refreshKey(key: hide.comp.CurveEditor.CurveKey, el: Element) {
-			if(isColorTrack) {
-				var color = getKeyColor(key);
-				var colorStr = "#" + StringTools.hex(color.toColor() & 0xffffff, 6);
-				el.css({background: colorStr});
-			}
-		}
-
-		var refreshDopesheet : Void -> Void;
-
-		function backupCurves() {
-			return [for(c in curves) haxe.Json.parse(haxe.Json.stringify(c.save()))];
-		}
-		var lastBackup = backupCurves();
-
-		function beforeChange() {
-			lastBackup = backupCurves();
-		}
-
-		function afterChange() {
-			var newVal = backupCurves();
-			var oldVal = lastBackup;
-			lastBackup = newVal;
-			undo.change(Custom(function(undo) {
-				if(undo) {
-					for(i in 0...curves.length)
-						curves[i].load(oldVal[i]);
-				}
-				else {
-					for(i in 0...curves.length)
-						curves[i].load(newVal[i]);
-				}
-				lastBackup = backupCurves();
-				refreshCurves(false);
-				refreshDopesheet();
-			}));
-			refreshCurves(false);
-		}
-
-		function addKey(time: Float) {
-			beforeChange();
-			for(curve in curves) {
-				curve.addKey(time);
-			}
-			afterChange();
-			refreshDopesheet();
-		}
-
-
-		function keyContextClick(key: hrt.prefab.Curve.CurveKey, el: Element) {
-			function setCurveVal(suffix: String, value: Float) {
-				var c = curves.find(c -> StringTools.endsWith(c.name, suffix));
-				if(c != null) {
-					var k = c.findKey(key.time, keyTimeTolerance);
-					if(k == null) {
-						k = c.addKey(key.time);
-					}
-					k.value = value;
-				}
-			}
-
-			if(isColorTrack) {
-				var picker = new Element("<div></div>").css({
-					"z-index": 100,
-				}).appendTo(el);
-				var cp = new hide.comp.ColorPicker(false, picker);
-				var prevCol = getKeyColor(key);
-				cp.value = prevCol.toColor();
-				cp.open();
-				cp.onClose = function() {
-					picker.remove();
-				};
-				cp.onChange = function(dragging) {
-					if(dragging)
-						return;
-					var col = h3d.Vector.fromColor(cp.value, 1.0);
-					if(isColorHSL) {
-						col = col.toColorHSL();
-						setCurveVal(".h", col.x);
-						setCurveVal(".s", col.y);
-						setCurveVal(".l", col.z);
-						setCurveVal(".a", prevCol.a);
-					}
-					else {
-						setCurveVal(".r", col.x);
-						setCurveVal(".g", col.y);
-						setCurveVal(".b", col.z);
-						setCurveVal(".a", prevCol.a);
-					}
-					refreshCurves(false);
-					refreshKey(key, el);
-				};
-			}
-		}
-
-		refreshDopesheet = function () {
-			dopesheet.empty();
-			dopesheet.off();
-			dopesheet.mouseup(function(e) {
-				var offset = dopesheet.offset();
-				if(e.ctrlKey) {
-					var x = ixt(e.clientX - offset.left);
-					addKey(x);
-				}
-			});
-			var refKeys = curves[0].keys;
-			for(ik in 0...refKeys.length) {
-				var key = refKeys[ik];
-				var keyEl = new Element('<span class="key">').appendTo(dopesheet);
-				function updatePos() keyEl.css({left: xt(refKeys[ik].time)});
-				updatePos();
-				keyEl.contextmenu(function(e) {
-					keyContextClick(key, keyEl);
-					e.preventDefault();
-					e.stopPropagation();
-				});
-				keyEl.mousedown(function(e) {
-					var offset = dopesheet.offset();
-					e.preventDefault();
-					e.stopPropagation();
-					if(e.button == 2) {
-					}
-					else {
-						var prevVal = key.time;
-						beforeChange();
-						startDrag(function(e) {
-							var x = ixt(e.clientX - offset.left);
-							x = hxd.Math.max(0, x);
-							var next = refKeys[ik + 1];
-							if(next != null)
-								x = hxd.Math.min(x, next.time - 0.01);
-							var prev = refKeys[ik - 1];
-							if(prev != null)
-								x = hxd.Math.max(x, prev.time + 0.01);
-							dragKey(null, key.time, x);
-							updatePos();
-						}, function(e) {
-							afterChange();
-						});
-					}
-				});
-				afterPanRefreshes.push(function(anim) {
-					updatePos();
-				});
-				refreshKey(key, keyEl);
-			}
-		}
-
-		var minHeight = 40;
-		var ctx = sceneEditor.getContext(data);
-		for(curve in curves) {
-			var dispKey = getPath() + "/" + curve.getAbsPath(true);
-			var curveContainer = new Element('<div class="curve"><label class="curve-label">${curve.name}</alpha></div>').appendTo(curvesContainer);
-			var height = getDisplayState(dispKey + "/height");
-			if(height == null)
-				height = 100;
-			if(height < minHeight) height = minHeight;
-			curveContainer.height(height);
-			curve.maxTime = data.duration;
-			var curveEdit = new hide.comp.CurveEditor(this.undo, curveContainer);
-			curveEdit.saveDisplayKey = dispKey;
-			curveEdit.lockViewX = true;
-			if(curves.length > 1)
-				curveEdit.lockKeyX = true;
-			if(["visibility", "s", "l", "a"].indexOf(curve.name.split(".").pop()) >= 0) {
-				curveEdit.minValue = 0;
-				curveEdit.maxValue = 1;
-			}
-			if(curve.name.indexOf("Rotation") >= 0) {
-				curveEdit.minValue = 0;
-				curveEdit.maxValue = 360;
-			}
-			var shader = curve.parent.to(hrt.prefab.Shader);
-			if(shader != null) {
-				var sh = shader.getShaderDefinition(ctx);
-				if(sh != null) {
-					var v = sh.data.vars.find(v -> v.kind == Param && v.name == curve.name);
-					if(v != null && v.qualifiers != null) {
-						for( q in v.qualifiers )
-							switch( q ) {
-							case Range(rmin, rmax):
-								curveEdit.minValue = rmin;
-								curveEdit.maxValue = rmax;
-							default:
-						}
-					}
-				}
-			}
-			curveEdit.xOffset = xOffset;
-			curveEdit.xScale = xScale;
-			if(isInstanceCurve(curve) && curve.parent.to(hrt.prefab.fx.Emitter) == null || curve.name.indexOf("inst") >= 0)
-				curve.maxTime = 1.0;
-			curveEdit.curve = curve;
-			curveEdit.onChange = function(anim) {
-				refreshDopesheet();
-			}
-
-			curveContainer.on("mousewheel", function(e) {
-				var step = e.originalEvent.wheelDelta > 0 ? 1.0 : -1.0;
-				if(e.ctrlKey) {
-					var prevH = curveContainer.height();
-					var newH = hxd.Math.max(minHeight, prevH + Std.int(step * 20.0));
-					curveContainer.height(newH);
-					saveDisplayState(dispKey + "/height", newH);
-					curveEdit.yScale *= newH / prevH;
-					curveEdit.refresh();
-					e.preventDefault();
-					e.stopPropagation();
-				}
-			});
-			trackEdits.push(curveEdit);
-			curveEdits.push(curveEdit);
-		}
-		refreshDopesheet();
-		updateExpanded();
-	}
-
-	function addEventsTrack(events: Array<Event>, tracksEl: Element) {
-		var trackEl = new Element('<div class="track">
-			<div class="track-header">
-				<div class="track-prop">
-					<label>Events</label>
-				</div>
-				<div class="events"></div>
-			</div>
-		</div>');
-		var eventsEl = trackEl.find(".events");
-		var items : Array<{el: Element, event: Event }> = [];
-		function refreshItems() {
-			var yoff = 1;
-			for(item in items) {
-				var info = item.event.getDisplayInfo(sceneEditor.curEdit);
-				item.el.css({left: xt(item.event.time), top: yoff});
-				item.el.width(info.length * xScale);
-				item.el.find("label").text(info.label);
-				yoff += 21;
-			}
-			eventsEl.css("height", yoff + 1);
-		}
-
-		function refreshTrack() {
-			trackEl.remove();
-			trackEl = addEventsTrack(events, tracksEl);
-		}
-
-		for(event in events) {
-			var info = event.getDisplayInfo(sceneEditor.curEdit);
-			var evtEl = new Element('<div class="event">
-				<i class="icon ico ico-play-circle"></i><label></label>
-			</div>').appendTo(eventsEl);
-			items.push({el: evtEl, event: event });
-
-			evtEl.click(function(e) {
-				sceneEditor.showProps(event);
-			});
-
-			evtEl.contextmenu(function(e) {
-				e.preventDefault();
-				e.stopPropagation();
-				new hide.comp.ContextMenu([
-					{
-						label: "Delete", click: function() {
-							events.remove(event);
-							sceneEditor.deleteElements([event], refreshTrack);
-						}
-					}
-				]);
-			});
-
-			evtEl.mousedown(function(e) {
-				var offsetX = e.clientX - xt(event.time);
-				e.preventDefault();
-				e.stopPropagation();
-				if(e.button == 2) {
-				}
-				else {
-					var prevVal = event.time;
-					startDrag(function(e) {
-						var x = ixt(e.clientX - offsetX);
-						x = hxd.Math.max(0, x);
-						x = untyped parseFloat(x.toFixed(5));
-						event.time = x;
-						refreshItems();
-					}, function(e) {
-						undo.change(Field(event, "time", prevVal), refreshItems);
-					});
-				}
-			});
-		}
-		refreshItems();
-		afterPanRefreshes.push(function(anim) refreshItems());
-		tracksEl.append(trackEl);
-		return trackEl;
-	}
-
-	function rebuildAnimPanel() {
-		if(element == null)
-			return;
-		var selection = sceneEditor.getSelection();
-		var scrollPanel = element.find(".anim-scroll");
-		scrollPanel.empty();
-		curveEdits = [];
-		afterPanRefreshes = [];
-
-		var sections : Array<{
-			elt: PrefabElement,
-			curves: Array<Curve>,
-			events: Array<Event>
-		}> = [];
-
-		function getSection(elt: PrefabElement) {
-			var ctxElt = elt.parent;
-			var sect = sections.find(s -> s.elt == ctxElt);
-			if(sect == null) {
-				sect = {elt: ctxElt, curves: [], events: []};
-				sections.push(sect);
-			}
-			return sect;
-		}
-
-		function getTagRec(elt : PrefabElement) {
-			var p = elt;
-			while(p != null) {
-				var tag = sceneEditor.getTag(p);
-				if(tag != null)
-					return tag;
-				p = p.parent;
-			}
-			return null;
-		}
-
-		for(sel in selection) {
-			for(curve in sel.flatten(Curve))
-				getSection(curve).curves.push(curve);
-			for(evt in sel.flatten(Event))
-				getSection(evt).events.push(evt);
-		}
-
-		for(sec in sections) {
-			var objPanel = new Element('<div>
-				<div class="tracks-header">
-					<label class="name">${upperCase(sec.elt.name)}</label> <div class="addtrack ico ico-plus-circle"></div>
-					<label class="abspath">${sec.elt.getAbsPath(true)}</label>
-				</div>
-				<div class="tracks"></div>
-			</div>').appendTo(scrollPanel);
-			var addTrackEl = objPanel.find(".addtrack");
-
-			var parentTag = getTagRec(sec.elt);
-			if(parentTag != null) {
-				objPanel.find(".name").css("background", parentTag.color);
-			}
-
-			addTrackEl.click(function(e) {
-				var menuItems = getNewTrackMenu(sec.elt);
-				new hide.comp.ContextMenu(menuItems);
-			});
-			var tracksEl = objPanel.find(".tracks");
-
-			if(sec.events.length > 0)
-				addEventsTrack(sec.events, tracksEl);
-
-			var groups = Curve.getGroups(sec.curves);
-			for(group in groups) {
-				addCurvesTrack(group.name, group.items, tracksEl);
-			}
-		}
-	}
-
-	function startDrag(onMove: js.jquery.Event->Void, onStop: js.jquery.Event->Void, ?onKeyDown: js.jquery.Event->Void, ?onKeyUp: js.jquery.Event->Void) {
-		var el = new Element(element[0].ownerDocument.body);
-		var startX = null, startY = null;
-		var dragging = false;
-		var threshold = 3;
-		el.keydown(onKeyDown);
-		el.keyup(onKeyUp);
-		el.on("mousemove.fxedit", function(e: js.jquery.Event) {
-			if(startX == null) {
-				startX = e.clientX;
-				startY = e.clientY;
-			}
-			else {
-				if(!dragging) {
-					if(hxd.Math.abs(e.clientX - startX) + hxd.Math.abs(e.clientY - startY) > threshold) {
-						dragging = true;
-					}
-				}
-				if(dragging)
-					onMove(e);
-			}
-		});
-		el.on("mouseup.fxedit", function(e: js.jquery.Event) {
-			el.off("mousemove.fxedit");
-			el.off("mouseup.fxedit");
-			e.preventDefault();
-			e.stopPropagation();
-			onStop(e);
-		});
-	}
-
-	function addTracks(element : PrefabElement, props : Array<PropTrackDef>, ?prefix: String) {
-		var added = [];
-		for(prop in props) {
-			var id = prefix != null ? prefix + "." + prop.name : prop.name;
-			if(Curve.getCurve(element, id) != null)
-				continue;
-			var curve = new Curve(element);
-			curve.name = id;
-			if(prop.def != null)
-				curve.addKey(0, prop.def, Linear);
-			added.push(curve);
-		}
-
-		if(added.length == 0)
-			return added;
-
-		undo.change(Custom(function(undo) {
-			for(c in added) {
-				if(undo)
-					element.children.remove(c);
-				else
-					element.children.push(c);
-			}
-			sceneEditor.refresh();
-		}));
-		sceneEditor.refresh(function() {
-			sceneEditor.selectElements([element]);
-		});
-		return added;
-	}
-
-	public function getNewTrackMenu(elt: PrefabElement) : Array<hide.comp.ContextMenu.ContextMenuItem> {
-		var obj3dElt = Std.downcast(elt, hrt.prefab.Object3D);
-		var obj2dElt = Std.downcast(elt, hrt.prefab.Object2D);
-		var shaderElt = Std.downcast(elt, hrt.prefab.Shader);
-		var emitterElt = Std.downcast(elt, hrt.prefab.fx.Emitter);
-		var particle2dElt = Std.downcast(elt, hrt.prefab.l2d.Particle2D);
-		var menuItems : Array<hide.comp.ContextMenu.ContextMenuItem> = [];
-		var lightElt = Std.downcast(elt, Light);
-
-		inline function hasTrack(pname) {
-			return getTrack(elt, pname) != null;
-		}
-
-		function trackItem(name: String, props: Array<PropTrackDef>, ?prefix: String) : hide.comp.ContextMenu.ContextMenuItem {
-			var hasAllTracks = true;
-			for(p in props) {
-				if(getTrack(elt, prefix + "." + p.name) == null)
-					hasAllTracks = false;
-			}
-			return {
-				label: upperCase(name),
-				click: function() {
-					var added = addTracks(elt, props, prefix);
-				},
-				enabled: !hasAllTracks };
-		}
-
-		function groupedTracks(prefix: String, props: Array<PropTrackDef>) : Array<hide.comp.ContextMenu.ContextMenuItem> {
-			var allLabel = [for(p in props) upperCase(p.name)].join("/");
-			var ret = [];
-			ret.push(trackItem(allLabel, props, prefix));
-			for(p in props) {
-				var label = upperCase(p.name);
-				ret.push(trackItem(label, [p], prefix));
-			}
-			return ret;
-		}
-
-		var hslTracks : Void -> Array<PropTrackDef> = () -> [{name: "h", def: 0.0}, {name: "s", def: 0.0}, {name: "l", def: 1.0}];
-		var alphaTrack : Void -> Array<PropTrackDef> = () -> [{name: "a", def: 1.0}];
-		var xyzwTracks : Int -> Array<PropTrackDef> = (n) -> [{name: "x"}, {name: "y"}, {name: "z"}, {name: "w"}].slice(0, n);
-
-		if (obj2dElt != null) {
-			var scaleTracks = groupedTracks("scale", xyzwTracks(2));
-			scaleTracks.unshift(trackItem("Uniform", [{name: "scale"}]));
-			menuItems.push({
-				label: "Position",
-				menu: groupedTracks("position", xyzwTracks(2)),
-			});
-			menuItems.push({
-				label: "Rotation",
-				menu: [trackItem("X", [{name: "x"}], "rotation")],
-			});
-			menuItems.push({
-				label: "Scale",
-				menu: scaleTracks,
-			});
-			menuItems.push({
-				label: "Color",
-				menu: [
-					trackItem("HSL", hslTracks(), "color"),
-					trackItem("Alpha", alphaTrack(), "color")
-				]
-			});
-			menuItems.push(trackItem("Visibility", [{name: "visibility"}]));
-		}
-		if(obj3dElt != null) {
-			var scaleTracks = groupedTracks("scale", xyzwTracks(3));
-			scaleTracks.unshift(trackItem("Uniform", [{name: "scale"}]));
-			menuItems.push({
-				label: "Position",
-				menu: groupedTracks("position", xyzwTracks(3)),
-			});
-			menuItems.push({
-				label: "Rotation",
-				menu: groupedTracks("rotation", xyzwTracks(3)),
-			});
-			menuItems.push({
-				label: "Scale",
-				menu: scaleTracks,
-			});
-			menuItems.push({
-				label: "Color",
-				menu: [
-					trackItem("HSL", hslTracks(), "color"),
-					trackItem("Alpha", alphaTrack(), "color")
-				]
-			});
-			menuItems.push(trackItem("Visibility", [{name: "visibility"}]));
-		}
-		if(shaderElt != null) {
-			var shader = shaderElt.makeShader();
-			var inEmitter = shaderElt.getParent(hrt.prefab.fx.Emitter) != null;
-			var params = shader == null ? [] : @:privateAccess shader.shader.data.vars.filter(inEmitter ? isPerInstance : v -> v.kind == Param);
-			for(param in params) {
-				var item : hide.comp.ContextMenu.ContextMenuItem = switch(param.type) {
-					case TVec(n, VFloat):
-						var color = param.name.toLowerCase().indexOf("color") >= 0;
-						var label = upperCase(param.name);
-						var menu = null;
-						if(color) {
-							if(n == 3)
-								menu = trackItem(label, hslTracks(), param.name);
-							else if(n == 4)
-								menu = trackItem(label, hslTracks().concat(alphaTrack()), param.name);
-						}
-						if(menu == null)
-							menu = trackItem(label, xyzwTracks(n), param.name);
-						menu;
-					case TFloat:
-						trackItem(upperCase(param.name), [{name: param.name}]);
-					default:
-						null;
-				}
-				if(item != null)
-					menuItems.push(item);
-			}
-		}
-		function addParam(param : hrt.prefab.fx.Emitter.ParamDef, prefix: String) {
-			var label = prefix + (param.disp != null ? param.disp : upperCase(param.name));
-			var item : hide.comp.ContextMenu.ContextMenuItem = switch(param.t) {
-				case PVec(n, _):
-					{
-						label: label,
-						menu: groupedTracks(param.name, xyzwTracks(n)),
-					}
-				default:
-					trackItem(label, [{name: param.name}]);
-			};
-			menuItems.push(item);
-		}
-		if(emitterElt != null) {
-			for(param in hrt.prefab.fx.Emitter.emitterParams) {
-				if(!param.animate)
-					continue;
-				addParam(param, "");
-			}
-			for(param in hrt.prefab.fx.Emitter.instanceParams) {
-				if(!param.animate)
-					continue;
-				addParam(param, "Instance ");
-			}
-		}
-		if (particle2dElt != null) {
-			for(param in hrt.prefab.l2d.Particle2D.emitter2dParams) {
-				if(!param.animate)
-					continue;
-				addParam(param, "");
-			}
-		}
-		if( lightElt != null ) {
-			switch lightElt.kind {
-				case Point:
-					menuItems.push({
-						label: "PointLight",
-						menu: [	trackItem("Color", hslTracks(), "color"),
-								trackItem("Power",[{name: "power"}]),
-								trackItem("Size", [{name: "size"}]),
-								trackItem("Range", [{name: "range"}]),
-								]
-					});
-				case Directional:
-					menuItems.push({
-						label: "DirLight",
-						menu: [	trackItem("Color", hslTracks(), "color"),
-								trackItem("Power",[{name: "power"}]),
-								]
-					});
-				case Spot:
-					menuItems.push({
-						label: "SpotLight",
-						menu: [	trackItem("Color", hslTracks(), "color"),
-								trackItem("Power",[{name: "power"}]),
-								trackItem("Range", [{name: "range"}]),
-								trackItem("Angle", [{name: "angle"}]),
-								trackItem("FallOff", [{name: "fallOff"}]),
-								]
-					});
-			}
-		}
-		return menuItems;
-	}
-
-	function isPerInstance( v : hxsl.Ast.TVar ) {
-		if( v.kind != Param )
-			return false;
-		if( v.qualifiers == null )
-			return false;
-		for( q in v.qualifiers )
-			if( q.match(PerInstance(_)) )
-				return true;
-		return false;
-	}
-
-	function updateGrid() {
-		if(grid != null) {
-			grid.remove();
-			grid = null;
-		}
-		if(grid2d != null) {
-			grid2d.remove();
-			grid2d = null;
-		}
-
-		if(!showGrid)
-			return;
-
-		if (is2D) {
-			grid2d = new h2d.Graphics(scene.editor.context.local2d);
-			grid2d.scale(1);
-
-			grid2d.lineStyle(1.0, 12632256, 1.0);
-			grid2d.moveTo(0, -2000);
-			grid2d.lineTo(0, 2000);
-			grid2d.moveTo(-2000, 0);
-			grid2d.lineTo(2000, 0);
-			grid2d.lineStyle(0);
-
-			return;
-		}
-
-		grid = new h3d.scene.Graphics(scene.s3d);
-		grid.scale(1);
-		grid.material.mainPass.setPassName("debuggeom");
-
-		var col = h3d.Vector.fromColor(scene.engine.backgroundColor);
-		var hsl = col.toColorHSL();
-		if(hsl.z > 0.5) hsl.z -= 0.1;
-		else hsl.z += 0.1;
-		col.makeColor(hsl.x, hsl.y, hsl.z);
-
-		grid.lineStyle(1.0, col.toColor(), 1.0);
-		for(ix in -10...11) {
-			grid.moveTo(ix, -10, 0);
-			grid.lineTo(ix, 10, 0);
-			grid.moveTo(-10, ix, 0);
-			grid.lineTo(10, ix, 0);
-
-		}
-		grid.lineStyle(0);
-	}
-
-	function onUpdate(dt : Float) {
-		if (is2D)
-			onUpdate2D(dt);
-		else
-			onUpdate3D(dt);
-
-		@:privateAccess scene.s3d.renderer.ctx.time = currentTime - scene.s3d.renderer.ctx.elapsedTime;
-	}
-
-	function onUpdate2D(dt:Float) {
-		var anim : hrt.prefab.fx.FX2D.FX2DAnimation = null;
-		var ctx = sceneEditor.getContext(data);
-		if(ctx != null && ctx.local2d != null) {
-			anim = Std.downcast(ctx.local2d, hrt.prefab.fx.FX2D.FX2DAnimation);
-		}
-		if(!pauseButton.isDown()) {
-			currentTime += scene.speed * dt;
-			if(timeLineEl != null)
-				timeLineEl.css({left: xt(currentTime)});
-			if(currentTime >= previewMax) {
-				currentTime = previewMin;
-
-				anim.setRandSeed(Std.random(0xFFFFFF));
-			}
-		}
-
-		if(anim != null) {
-			anim.setTime(currentTime);
-		}
-
-		if(statusText != null) {
-			var lines : Array<String> = [
-				'Time: ${Math.round(currentTime*1000)} ms',
-				'Scene objects: ${scene.s2d.getObjectsCount()}',
-				'Drawcalls: ${h3d.Engine.getCurrent().drawCalls}',
-			];
-			statusText.text = lines.join("\n");
-		}
-
-		if( autoSync && (currentVersion != undo.currentID || lastSyncChange != properties.lastChange) ) {
-			save();
-			lastSyncChange = properties.lastChange;
-			currentVersion = undo.currentID;
-		}
-
-		if (grid2d != null) {
-			@:privateAccess grid2d.setPosition(scene.s2d.children[0].x, scene.s2d.children[0].y);
-		}
-
-
-	}
-
-	function onUpdate3D(dt:Float) {
-		var anim : hrt.prefab.fx.FX.FXAnimation = null;
-		var ctx = sceneEditor.getContext(data);
-		if(ctx != null && ctx.local3d != null) {
-			anim = Std.downcast(ctx.local3d,hrt.prefab.fx.FX.FXAnimation);
-		}
-
-		if(!pauseButton.isDown()) {
-			currentTime += scene.speed * dt;
-			if(timeLineEl != null)
-				timeLineEl.css({left: xt(currentTime)});
-			if(currentTime >= previewMax) {
-				currentTime = previewMin;
-
-				//if(data.scriptCode != null && data.scriptCode.length > 0)
-					//sceneEditor.refreshScene(); // This allow to reset the scene when values are modified causes edition issues, solves
-
-				if( anim.script != null )
-					anim.script.init();
-
-				anim.setRandSeed(Std.random(0xFFFFFF));
-			}
-		}
-
-		if(anim != null) {
-			anim.setTime(currentTime);
-
-			var emitters = anim.findAll(o -> Std.downcast(o, hrt.prefab.fx.Emitter.EmitterObject));
-			var totalParts = 0;
-			for(e in emitters)
-				totalParts += @:privateAccess e.numInstances;
-
-			if(statusText != null) {
-				var lines : Array<String> = [
-					'Time: ${Math.round(currentTime*1000)} ms',
-					'Scene objects: ${scene.s3d.getObjectsCount()}',
-					'Drawcalls: ${h3d.Engine.getCurrent().drawCalls}',
-					'Particles: $totalParts',
-				];
-				statusText.text = lines.join("\n");
-			}
-		}
-
-		var cam = scene.s3d.camera;
-		if( light != null ) {
-			var angle = Math.atan2(cam.target.y - cam.pos.y, cam.target.x - cam.pos.x);
-			light.setDirection(new h3d.Vector(
-				Math.cos(angle) * lightDirection.x - Math.sin(angle) * lightDirection.y,
-				Math.sin(angle) * lightDirection.x + Math.cos(angle) * lightDirection.y,
-				lightDirection.z
-			));
-		}
-		if( autoSync && (currentVersion != undo.currentID || lastSyncChange != properties.lastChange) ) {
-			save();
-			lastSyncChange = properties.lastChange;
-			currentVersion = undo.currentID;
-		}
-
-		if( data.scriptCode != scriptEditor.code || !fxScriptParser.firstParse ){
-			modified = fxScriptParser.firstParse;
-			data.scriptCode = scriptEditor.code;
-			anim.script = fxScriptParser.createFXScript(scriptEditor.code, anim);
-			anim.script.init();
-			fxScriptParser.generateUI(anim.script, this);
-			fxScriptParser.firstParse = true;
-		}
-	}
-
-	static function getTrack(element : PrefabElement, propName : String) {
-		return Curve.getCurve(element, propName, false);
-	}
-
-	static function upperCase(prop: String) {
-		if(prop == null) return "";
-		return prop.charAt(0).toUpperCase() + prop.substr(1);
-	}
-
-	static function isInstanceCurve(curve: Curve) {
-		return curve.getParent(hrt.prefab.fx.Emitter) != null;
-	}
-
-	static var _ = FileTree.registerExtension(FXEditor, ["fx"], { icon : "sitemap", createNew : "FX" });
-}
-
-
-class FX2DEditor extends FXEditor {
-
-	override function getDefaultContent() {
-		return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX2D().saveData()));
-	}
-
-	static var _2d = FileTree.registerExtension(FX2DEditor, ["fx2d"], { icon : "sitemap", createNew : "FX 2D" });
-}

+ 0 - 445
hide/view/l3d/LightProbeBaker.hx

@@ -1,445 +0,0 @@
-package hide.view.l3d;
-
-import h3d.scene.pbr.Renderer;
-
-class LightProbeBaker {
-
-	public var useGPU = false;
-	public var environment : h3d.scene.pbr.Environment;
-
-	var context : hrt.prefab.Context;
-	var offScreenScene : h3d.scene.Scene = null;
-	var prim : h3d.prim.Plane2D;
-
-	var envMap : h3d.mat.Texture;
-	var customCamera : h3d.Camera;
-	var cubeDir = [ h3d.Matrix.L([0,0,-1,0, 0,1,0,0, -1,-1,1,0]),
-					h3d.Matrix.L([0,0,1,0, 0,1,0,0, 1,-1,-1,0]),
-	 				h3d.Matrix.L([-1,0,0,0, 0,0,1,0, 1,-1,-1,0]),
-	 				h3d.Matrix.L([-1,0,0,0, 0,0,-1,0, 1,1,1,0]),
-				 	h3d.Matrix.L([-1,0,0,0, 0,1,0,0, 1,-1,1,0]),
-				 	h3d.Matrix.L([1,0,0,0, 0,1,0,0, -1,-1,-1,0]) ];
-
-	function getSwiz(name,comp) : hxsl.Output { return Swiz(Value(name,3),[comp]); }
-
-	var computeSH : h3d.pass.ScreenFx<hrt.shader.ComputeSH>;
-	var output0 : h3d.mat.Texture;
-	var output1 : h3d.mat.Texture;
-	var output2 : h3d.mat.Texture;
-	var output3 : h3d.mat.Texture;
-	var output4 : h3d.mat.Texture;
-	var output5 : h3d.mat.Texture;
-	var output6 : h3d.mat.Texture;
-	var output7 : h3d.mat.Texture;
-	var textureArray: Array<h3d.mat.Texture>;
-
-	public function new(){
-		customCamera = new h3d.Camera();
-		customCamera.screenRatio = 1.0;
-		customCamera.fovY = 90;
-		customCamera.zFar = 100;
-		context = new hrt.prefab.Context();
-	}
-
-	public function dispose() {
-		if( envMap != null ) {
-			envMap.dispose();
-			envMap = null;
-		}
-		if(output0 != null) output0.dispose();
-		if(output1 != null) output1.dispose();
-		if(output2 != null) output2.dispose();
-		if(output3 != null) output3.dispose();
-		if(output4 != null) output4.dispose();
-		if(output5 != null) output5.dispose();
-		if(output6 != null) output6.dispose();
-		if(output7 != null) output7.dispose();
-		if(prim != null) prim.dispose();
-		if(offScreenScene != null) offScreenScene.dispose();
-	}
-
-	public function initScene( sceneData : hrt.prefab.Prefab, shared : hide.prefab.ContextShared, scene : hide.comp.Scene , env : h3d.scene.pbr.Environment) {
-		if(offScreenScene != null) offScreenScene.dispose();
-		offScreenScene = new h3d.scene.Scene();
-
-		var newShared = new hide.prefab.ContextShared(scene);
-		newShared.currentPath = shared.currentPath;
-		@:privateAccess newShared.shaderCache =  @:privateAccess hide.Ide.inst.shaderLoader.shaderCache;
-		context.shared = newShared;
-		context.shared.root3d = offScreenScene;
-		context.local3d = offScreenScene;
-
-		var whiteList = [ "level3d", "object", "model", "material", "light"];
-		function keep( p : hrt.prefab.Prefab ) {
-			for( f in whiteList )
-				if( f == p.type ) return true;
-			return false;
-		}
-		function filter( p : hrt.prefab.Prefab ) {
-			for( c in p.children ) {
-				if(!keep(c))
-					sceneData.children.remove(c);
-			}
-			for( c in p.children )
-					filter(c);
-		}
-		filter(sceneData);
-		sceneData.make(context);
-
-		/*function disableFaceCulling( o : Object ){
-			for( m in o.getMaterials() )
-				m.mainPass.culling = None;
-			for( i in 0 ... o.numChildren)
-				disableFaceCulling(o.getChildAt(i));
-		}
-		disableFaceCulling(offScreenScene);*/
-
-		var pbrRenderer = Std.downcast(offScreenScene.renderer, h3d.scene.pbr.Renderer) ;
-		pbrRenderer.env = env;
-		pbrRenderer.renderMode = LightProbe;
-		offScreenScene.camera = customCamera;
-
-		setupScene();
-	}
-
-	var passes = [];
-	function setupScene() {
-		var engine = h3d.Engine.getCurrent();
-		var ctx = @:privateAccess offScreenScene.ctx;
-
-		if( customCamera.rightHanded )
-			engine.driver.setRenderFlag(CameraHandness,1);
-
-		ctx.camera = customCamera;
-		ctx.engine = engine;
-		ctx.scene = offScreenScene;
-		ctx.start();
-		offScreenScene.renderer.start();
-		ctx.lightSystem = @:privateAccess offScreenScene.lightSystem;
-
-		@:privateAccess offScreenScene.syncRec(ctx);
-		@:privateAccess offScreenScene.emitRec(ctx);
-
-		// sort by pass id
-		@:privateAccess ctx.passes = haxe.ds.ListSort.sortSingleLinked(@:privateAccess ctx.passes, function(p1, p2) {
-			return @:privateAccess p1.pass.passId - @:privateAccess p2.pass.passId;
-		});
-
-		// group by pass implementation
-		var curPass = @:privateAccess ctx.passes;
-		passes = [];
-		while( curPass != null ) {
-			var passId = @:privateAccess curPass.pass.passId;
-			var p = curPass, prev = null;
-			while( p != null && @:privateAccess p.pass.passId == passId ) {
-				prev = p;
-				p = p.next;
-			}
-			prev.next = null;
-			var po = new h3d.scene.Renderer.PassObjects();
-			po.name = curPass.pass.name;
-			po.passes = new h3d.pass.PassList(curPass);
-			passes.push(po);
-			curPass = p;
-		}
-	}
-
-	function renderScene(){
-		offScreenScene.lightSystem.initLights( @:privateAccess offScreenScene.ctx);
-		offScreenScene.renderer.process(passes);
-	}
-
-	var pixels : hxd.Pixels = null;
-	public function bake( volumetricLightMap : hrt.prefab.vlm.VolumetricMesh, resolution : Int, ?time :Float ) {
-
-		var timer = haxe.Timer.stamp();
-		var timeElapsed = 0.0;
-
-		var index = volumetricLightMap.lastBakedProbeIndex + 1;
-		if(index > volumetricLightMap.getProbeCount() - 1) return time;
-
-		setupEnvMap(resolution);
-		setupShaderOutput(volumetricLightMap.shOrder, volumetricLightMap.getProbeCount() );
-
-		var coefCount = volumetricLightMap.getCoefCount();
-		var sizeX = volumetricLightMap.probeCount.x * coefCount;
-		var sizeY = volumetricLightMap.probeCount.y * volumetricLightMap.probeCount.z;
-		if( volumetricLightMap.lightProbeTexture == null || volumetricLightMap.lightProbeTexture.width != sizeX || volumetricLightMap.lightProbeTexture.height != sizeY ) {
-			if( volumetricLightMap.lightProbeTexture != null ) volumetricLightMap.lightProbeTexture.dispose();
-			volumetricLightMap.lightProbeTexture = new h3d.mat.Texture(sizeX, sizeY, [Dynamic], RGBA32F);
-			volumetricLightMap.lightProbeTexture.filter = Nearest;
-		}
-
-		if( pixels == null || pixels.width != sizeX || pixels.height != sizeY){
-			if( pixels != null ) pixels.dispose();
-			var bytes = haxe.io.Bytes.alloc(volumetricLightMap.getProbeCount() * volumetricLightMap.getCoefCount() * 4 * 4);
-			pixels = new hxd.Pixels(sizeX, sizeY, bytes, RGBA32F, 0);
-		}
-
-		var engine = h3d.Engine.getCurrent();
-		while( ( time != null && timeElapsed < time) || time == null ) {
-			var coords = volumetricLightMap.getProbeCoords(index);
-			// Bake a Probe
-			for( f in 0...6 ) {
-				engine.begin();
-				customCamera.setCubeMap(f, volumetricLightMap.getProbePosition(coords).toVector());
-				customCamera.update();
-				engine.pushTarget(envMap, f);
-				engine.clear(0,1,0);
-				//offScreenScene.render(engine);
-				renderScene();
-				engine.popTarget();
-			}
-			volumetricLightMap.lastBakedProbeIndex = index;
-
-			var pbrRenderer = Std.downcast(offScreenScene.renderer, h3d.scene.pbr.Renderer);
-			if( useGPU ) {
-				drawSHIntoTexture(pbrRenderer, envMap, volumetricLightMap.shOrder, index);
-			}
-			else {
-				var pbrRenderer = Std.downcast(offScreenScene.renderer, h3d.scene.pbr.Renderer);
-				var sh : hrt.prefab.vlm.SphericalHarmonic = convertEnvIntoSH_CPU(envMap, volumetricLightMap.shOrder);
-				for( coef in 0 ... coefCount ) {
-					var u = coords.x + volumetricLightMap.probeCount.x * coef;
-					var v = coords.y + coords.z * volumetricLightMap.probeCount.y;
-					pixels.setPixelF(u, v, new h3d.Vector(sh.coefR[coef], sh.coefG[coef], sh.coefB[coef], 0));
-				}
-			}
-
-			index = volumetricLightMap.lastBakedProbeIndex + 1;
-			if( index > volumetricLightMap.getProbeCount() - 1 ) {
-				if( useGPU ) convertOuputTexturesIntoSH(volumetricLightMap, pixels);
-				volumetricLightMap.lightProbeTexture.uploadPixels(pixels, 0, 0);
-				break;
-			}
-
-			timeElapsed = haxe.Timer.stamp() - timer;
-		}
-
-		return time - timeElapsed;
-	}
-
-	function setupEnvMap( resolution : Int ) {
-		if( envMap == null || resolution != envMap.width ) {
-			if( envMap != null ) envMap.dispose();
-			envMap = new h3d.mat.Texture(resolution, resolution, [Cube, Target], RGBA32F);
-		}
-	}
-
-	function setupShaderOutput( order : Int, probeCount: Int ) {
-
-		if( order > 3 || order <= 0 ){ throw "Not Supported"; return; }
-
-		if( !useGPU )
-			probeCount = 1;
-
-		if( order >= 1 && (output0 == null || output0.width != probeCount)){
-			if(output0 != null) output0.dispose();
-			output0 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-		}
-		if( order >= 2 && (output1 == null || output1.width != probeCount)){
-			if(output1 != null) output1.dispose();
-			if(output2 != null) output2.dispose();
-			if(output3 != null) output3.dispose();
-			output1 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output2 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output3 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-		}
-		if( order >= 3 && (output4 == null || output4.width != probeCount)){
-			if(output4 != null) output4.dispose();
-			if(output5 != null) output5.dispose();
-			if(output6 != null) output6.dispose();
-			if(output7 != null) output7.dispose();
-			output4 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output5 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output6 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output7 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-		}
-
-		switch(order){
-			case 1:
-				textureArray = [output0];
-				computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[
-								Vec4([Value("out.coefL00", 3), Const(0)])]);
-			case 2:
-				textureArray = [output0, output1, output2, output3];
-				computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[
-							Vec4([Value("out.coefL00", 3), Const(0)]),
-							Vec4([Value("out.coefL1n1", 3), Const(0)]),
-							Vec4([Value("out.coefL10", 3), Const(0)]),
-							Vec4([Value("out.coefL11", 3), Const(0)])]);
-
-			case 3:
-				textureArray = [output0, output1, output2, output3, output4, output5, output6, output7];
-				computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[
-							Vec4([Value("out.coefL00", 3), getSwiz("out.coefL22",X) ]),
-							Vec4([Value("out.coefL1n1", 3), getSwiz("out.coefL22",Y) ]),
-							Vec4([Value("out.coefL10", 3), getSwiz("out.coefL22",Z) ]),
-							Vec4([Value("out.coefL11", 3), Const(0)]),
-							Vec4([Value("out.coefL2n2", 3), Const(0)]),
-							Vec4([Value("out.coefL2n1", 3), Const(0)]),
-							Vec4([Value("out.coefL20", 3), Const(0)]),
-							Vec4([Value("out.coefL21", 3), Const(0)])]);
-		}
-	}
-
-	function drawSHIntoTexture(renderer : h3d.scene.Renderer, env : h3d.mat.Texture, order : Int, probeIndex: Int) {
-		if( prim == null ){
-			prim = new h3d.prim.Plane2D();
-		}
-
-		function setPrimPos( index : Int ){
-			var v = new hxd.FloatBuffer();
-			var pixelSize = (1.0 / output0.width);
-			var translation =  pixelSize * index * 2;
-			var posX = -1.0 + translation;
-			v.push( posX ) ; v.push( -1 ); v.push(0); v.push(0);
-			v.push( posX ); v.push( 1 ); v.push(0); v.push(0);
-			v.push( posX + pixelSize * 2 ); v.push( -1 ); v.push(0); v.push(0);
-			v.push( posX + pixelSize * 2 ); v.push( 1 ); v.push(0); v.push(0);
-			prim.buffer = h3d.Buffer.ofFloats(v, 4, [Quads, RawFormat]);
-		}
-		setPrimPos(probeIndex);
-
-		@:privateAccess renderer.ctx.engine = h3d.Engine.getCurrent();
-		@:privateAccess renderer.setTargets(textureArray);
-		computeSH.shader.ORDER = order;
-		computeSH.shader.width = env.width;
-		computeSH.shader.environment = env;
-		computeSH.shader.cubeDir = cubeDir;
-		computeSH.primitive = prim;
-		computeSH.render();
-		@:privateAccess renderer.resetTarget();
-		@:privateAccess renderer.ctx.engine.flushTarget();
-	}
-
-	function convertOuputTexturesIntoSH( volumetricLightMap : hrt.prefab.vlm.VolumetricMesh, pixelsOut : hxd.Pixels ) {
-
-		var order = volumetricLightMap.shOrder;
-		var sh = new hrt.prefab.vlm.SphericalHarmonic(order);
-		var coefCount = order * order;
-		var maxCoef : Int = Std.int(Math.min(8, coefCount));
-
-		for(coef in 0 ... maxCoef){
-			var pixels = textureArray[coef].capturePixels();
-			for( index in 0 ... pixels.width){
-				var coefs : h3d.Vector = pixels.getPixelF(index, 0);
-				var coords = volumetricLightMap.getProbeCoords(index);
-				var u = coords.x + volumetricLightMap.probeCount.x * coef;
-				var v = coords.y + coords.z * volumetricLightMap.probeCount.y;
-				pixelsOut.setPixelF(u, v, new h3d.Vector(coefs.r, coefs.g, coefs.b, 0));
-
-				// Last coefs is inside the alpha channel
-				if( order == 3 ){
-					var u = coords.x + volumetricLightMap.probeCount.x * 8;
-					var v = coords.y + coords.z * volumetricLightMap.probeCount.y;
-					var prev = pixelsOut.getPixelF(u, v);
-					if( coef == 0 ){ prev.r = coefs.a; }
-					if( coef == 1 ){ prev.g = coefs.a; }
-					if( coef == 2 ){ prev.b = coefs.a; }
-					pixelsOut.setPixelF(u, v, prev);
-				}
-			}
-		}
-	}
-
-	function convertEnvIntoSH_CPU( env : h3d.mat.Texture, order : Int ) : hrt.prefab.vlm.SphericalHarmonic {
-		var coefCount = order * order;
-		var sphericalHarmonic = new hrt.prefab.vlm.SphericalHarmonic(order);
-		var face : hxd.Pixels;
-		var weightSum = 0.0;
-		var invWidth = 1.0 / env.width;
-		var shData : Array<Float> = [for ( value in 0...coefCount ) 0];
-
-		for( f in 0...6 ){
-			face = env.capturePixels(f, 0);
-			for (u in 0...face.width) {
-				var fU : Float = (u / face.width ) * 2 - 1;// Texture coordinate U in range [-1 to 1]
-				fU *= fU;
-				var uCoord = 2.0 * u * invWidth + invWidth;
-				for (v in 0...face.width) {
-        			var fV : Float = (v / face.height ) * 2 - 1;// Texture coordinate V in range [-1 to 1]
-					fV *= fV;
-					var vCoord = 2.0 * v * invWidth + invWidth;
-					var dir = getDir(uCoord, vCoord, f);// Get direction from center of cube texture to current texel
-           			var diffSolid = 4.0 / ((1.0 + fU + fV) * Math.sqrt(1.0 + fU + fV));	// Scale factor depending on distance from center of the face
-					weightSum += diffSolid;
-					var color = face.getPixelF(u,v);// Get color from the current face
-					evalSH(order, dir, shData);// Calculate coefficients of spherical harmonics for current direction
-					for(i in 0...coefCount){
-						sphericalHarmonic.coefR[i] += shData[i] * color.r * diffSolid;
-						sphericalHarmonic.coefG[i] += shData[i] * color.g * diffSolid;
-						sphericalHarmonic.coefB[i] += shData[i] * color.b * diffSolid;
-					}
-				}
-			}
-		}
-		// Final scale for coefficients
-		var normProj = (4.0 * Math.PI) / weightSum;
-		for( i in 0...coefCount ){
-			sphericalHarmonic.coefR[i] *= normProj;
-			sphericalHarmonic.coefG[i] *= normProj;
-			sphericalHarmonic.coefB[i] *= normProj;
-		}
-		return sphericalHarmonic;
-	}
-
-	inline function evalSH( order : Int, dir : h3d.Vector, shData : Array<Float> ) {
-		for (l in 0...order) {
-       		for (m in -l...l+1) {
-				shData[getIndex(l, m)] = evalCoef(l, m, dir);
-			}
-		}
-	}
-
-	inline function getIndex( l : Int, m :Int ) : Int {
-		return l * (l + 1) + m;
-	}
-
-	inline function getDir( u : Float, v : Float, face : Int ) : h3d.Vector {
-		var dir = new h3d.Vector();
-		switch( face ) {
-			case 0: dir.x = -1.0; dir.y = -1.0 + v; dir.z = 1.0 - u;
-			case 1: dir.x = 1.0; dir.y = -1.0 + v; dir.z = -1.0 + u;
-			case 2: dir.x = 1.0 - u; dir.y = -1.0; dir.z = -1.0 + v;
-			case 3: dir.x = 1.0 - u; dir.y = 1.0; dir.z = 1.0 - v;
-			case 4: dir.x = 1.0 - u;  dir.y = -1.0 + v; dir.z = 1.0;
-			case 5: dir.x = -1.0 + u; dir.y = -1.0 + v;  dir.z = -1.0;
-			default:
-		}
-		dir.normalizeFast();
-		return dir;
-	}
-
-	inline function evalCoef( l : Int, m : Int, dir : h3d.Vector ) : Float {
-		// Coef from Stupid Spherical Harmonics (SH) Peter-Pike Sloan Microsoft Corporation
-		return switch [l,m] {
-			case[0,0]:	0.282095; // 0.5 * sqrt(1/pi)
-			case[1,-1]:	-0.488603 * dir.y;  // -sqrt(3/(4pi)) * y
-			case[1,0]:	0.488603 * dir.z; // sqrt(3/(4pi)) * z
-			case[1,1]:	-0.488603 * dir.x; // -sqrt(3/(4pi)) * x
-			case[2,-2]:	1.092548 * dir.y * dir.x;// 0.5 * sqrt(15/pi) * y * x
-			case[2,-1]:	-1.092548 * dir.y * dir.z; // -0.5 * sqrt(15/pi) * y * z
-			case[2,0]:	0.315392 * (-dir.x * dir.x - dir.y * dir.y + 2.0 * dir.z * dir.z);// 0.25 * sqrt(5/pi) * (-x^2-y^2+2z^2)
-			case[2,1]:  -1.092548 * dir.x * dir.z; // -0.5 * sqrt(15/pi) * x * z
-			case[2,2]:	0.546274 * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(15/pi) * (x^2 - y^2)
-			case[3,-3]:	-0.590044 * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y);// -0.25 * sqrt(35/(2pi)) * y * (3x^2 - y^2)
-			case[3,-2]: 2.890611 * dir.x * dir.y * dir.z; // 0.5 * sqrt(105/pi) * x * y * z
-			case[3,-1]: -0.457046 * dir.y * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * y * (4z^2-x^2-y^2)
-			case[3,0]:  0.373176 * dir.z * (2.0 * dir.z * dir.z - 3.0 * dir.x * dir.x - 3.0 * dir.y * dir.y);  // 0.25 * sqrt(7/pi) * z * (2z^2 - 3x^2 - 3y^2)
-			case[3,1]:	-0.457046 * dir.x * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * x * (4z^2-x^2-y^2)
-			case[3,2]:  1.445306 * dir.z * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(105/pi) * z * (x^2 - y^2)
-			case[3,3]:	-0.590044 * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y); // -0.25 * sqrt(35/(2pi)) * x * (x^2-3y^2)
-			case[4,-4]: 2.503343 * dir.x * dir.y * (dir.x * dir.x - dir.y * dir.y);// 0.75 * sqrt(35/pi) * x * y * (x^2-y^2)
-			case[4,-3]: -1.770131 * dir.y * dir.z * (3.0 * dir.x * dir.x - dir.y * dir.y); // -0.75 * sqrt(35/(2pi)) * y * z * (3x^2-y^2)
-			case[4,-2]: 0.946175 * dir.x * dir.y * (7.0 * dir.z * dir.z - 1.0);// 0.75 * sqrt(5/pi) * x * y * (7z^2-1)
-			case[4,-1]: -0.669047 * dir.y * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * y * z * (7z^2-3)
-			case[4,0]:  0.105786 * (35.0 * dir.z * dir.z * dir.z * dir.z - 30.0 * dir.z * dir.z + 3.0);// 3/16 * sqrt(1/pi) * (35z^4-30z^2+3)
-			case[4,1]:  -0.669047 * dir.x * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * x * z * (7z^2-3)
-			case[4,2]:  0.473087 * (dir.x * dir.x - dir.y * dir.y) * (7.0 * dir.z * dir.z - 1.0);// 3/8 * sqrt(5/pi) * (x^2 - y^2) * (7z^2 - 1)
-			case[4,3]:  -1.770131 * dir.x * dir.z * (dir.x * dir.x - 3.0 * dir.y * dir.y);// -0.75 * sqrt(35/(2pi)) * x * z * (x^2 - 3y^2)
-			case[4,4]:  0.625836 * (dir.x * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y) - dir.y * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y)); // 3/16*sqrt(35/pi) * (x^2 * (x^2 - 3y^2) - y^2 * (3x^2 - y^2))
-			default: 0;
-		}
-	}
-}

+ 0 - 40
hide/view/l3d/ProbeBakerProcess.hx

@@ -1,40 +0,0 @@
-package hide.view.l3d;
-
-class ProbeBakerProcess {
-
-	public var progress : Float = 0.;
-
-	var lightProbeBaker : hide.view.l3d.LightProbeBaker;
-	var volumetricLightmap : hrt.prefab.vlm.VolumetricLightmap;
-	var bakeTime : Float;
-	var resolution : Int;
-
-	public function new(volumetricLightmap, res, useGPU, bakeTime = 0.016 ){
-		progress = 0;
-		this.bakeTime = bakeTime;
-		this.volumetricLightmap = volumetricLightmap;
-		this.resolution = res;
-		lightProbeBaker = new hide.view.l3d.LightProbeBaker();
-		lightProbeBaker.useGPU = useGPU;
-	}
-
-	public function init( env : h3d.scene.pbr.Environment, sceneData : hrt.prefab.Prefab , shared : hide.prefab.ContextShared, scene : hide.comp.Scene) {
-		lightProbeBaker.initScene(sceneData, shared, scene, env);
-	}
-
-	public function update(dt:Float) {
-		lightProbeBaker.bake(volumetricLightmap.volumetricLightmap, resolution, bakeTime);
-		progress = (volumetricLightmap.volumetricLightmap.lastBakedProbeIndex +1.0) / volumetricLightmap.volumetricLightmap.getProbeCount();
-		if( progress == 1 ) {
-			lightProbeBaker.dispose();
-			lightProbeBaker = null;
-			onEnd();
-		}
-	}
-
-	public dynamic function onEnd() {
-
-	}
-
-}
-

+ 0 - 385
hrt/prefab/Curve.hx

@@ -1,385 +0,0 @@
-package hrt.prefab;
-using Lambda;
-
-class CurveHandle {
-	public var dt: Float;
-	public var dv: Float;
-	public function new(t, v) {
-		this.dt = t;
-		this.dv = v;
-	}
-}
-
-enum abstract CurveKeyMode(Int) {
-	var Aligned = 0;
-	var Free = 1;
-	var Linear = 2;
-	var Constant = 3;
-}
-
-class CurveKey {
-	public var time: Float;
-	public var value: Float;
-	public var mode: CurveKeyMode;
-	public var prevHandle: CurveHandle;
-	public var nextHandle: CurveHandle;
-	public function new() {}
-}
-
-typedef CurveKeys = Array<CurveKey>;
-
-class Curve extends Prefab {
-
-	@:s public var keyMode : CurveKeyMode = Linear;
-	@:c public var keys : CurveKeys = [];
-	@:c public var previewKeys : CurveKeys = [];
-
-	@:s public var loop : Bool = false;
-
-	public var maxTime : Float;
-	public var duration(get, never): Float;
-	function get_duration() {
-		if(keys.length == 0) return 0.0;
-		return keys[keys.length-1].time;
-	}
-
-   	public function new(?parent) {
-		super(parent);
-		this.type = "curve";
-	}
-
-	public override function load(o:Dynamic) {
-		super.load(o);
-		keys = [];
-		if(o.keys != null) {
-			for(k in (o.keys: Array<Dynamic>)) {
-				var nk = new CurveKey();
-				nk.time = k.time;
-				nk.value = k.value;
-				nk.mode = k.mode;
-				if(k.prevHandle != null)
-					nk.prevHandle = new CurveHandle(k.prevHandle.dt, k.prevHandle.dv);
-				if(k.nextHandle != null)
-					nk.nextHandle = new CurveHandle(k.nextHandle.dt, k.nextHandle.dv);
-				keys.push(nk);
-			}
-		}
-		if( keys.length == 0 ) {
-			addKey(0.0, 0.0);
-			addKey(1.0, 1.0);
-		}
-	}
-
-	public override function save() {
-		var obj : Dynamic = super.save();
-		var keysDat = [];
-		for(k in keys) {
-			var o = {
-				time: k.time,
-				value: k.value,
-				mode: k.mode
-			};
-			if(k.prevHandle != null) Reflect.setField(o, "prevHandle", { dv: k.prevHandle.dv, dt: k.prevHandle.dt });
-			if(k.nextHandle != null) Reflect.setField(o, "nextHandle", { dv: k.nextHandle.dv, dt: k.nextHandle.dt });
-			keysDat.push(o);
-		}
-		obj.keys = keysDat;
-		return obj;
-	}
-
-	static inline function bezier(c0: Float, c1:Float, c2:Float, c3: Float, t:Float) {
-		var u = 1 - t;
-		return u * u * u * c0 + c1 * 3 * t * u * u + c2 * 3 * t * t * u + t * t * t * c3;
-	}
-
-	public function findKey(time: Float, tolerance: Float) {
-		var minDist = tolerance;
-		var closest = null;
-		for(k in keys) {
-			var d = hxd.Math.abs(k.time - time);
-			if(d < minDist) {
-				minDist = d;
-				closest = k;
-			}
-		}
-		return closest;
-	}
-
-	public function addKey(time: Float, ?val: Float, ?mode=null) {
-		var index = 0;
-		for(ik in 0...keys.length) {
-			var key = keys[ik];
-			if(time > key.time)
-				index = ik + 1;
-		}
-
-		if(val == null)
-			val = getVal(time);
-
-		var key = new hrt.prefab.Curve.CurveKey();
-		key.time = time;
-		key.value = val;
-		key.mode = mode != null ? mode : (keys[index] != null ? keys[index].mode : keyMode);
-		keys.insert(index, key);
-		return key;
-	}
-
-	public function addPreviewKey(time: Float, val: Float) {
-		var key = new hrt.prefab.Curve.CurveKey();
-		key.time = time;
-		key.value = val;
-		previewKeys.push(key);
-		return key;
-	}
-
-	public function getBounds() {
-		// TODO: Take bezier handles into account
-		var ret = new h2d.col.Bounds();
-		for(k in keys) {
-			ret.addPos(k.time, k.value);
-		}
-		return ret;
-	}
-
-	public function getVal(time: Float) : Float {
-		switch(keys.length) {
-			case 0: return 0;
-			case 1: return keys[0].value;
-			default:
-		}
-
-		if (loop)
-			time = time % keys[keys.length-1].time;
-
-		var idx = -1;
-		for(ik in 0...keys.length) {
-			var key = keys[ik];
-			if(time > key.time)
-				idx = ik;
-		}
-
-		if(idx < 0)
-			return keys[0].value;
-
-		var cur = keys[idx];
-		var next = keys[idx + 1];
-		if(next == null || cur.mode == Constant)
-			return cur.value;
-
-		var minT = 0.;
-		var maxT = 1.;
-		var maxDelta = 1./ 25.;
-
-		inline function sampleTime(t) {
-			return bezier(
-				cur.time,
-				cur.time + (cur.nextHandle != null ? cur.nextHandle.dt : 0.),
-				next.time + (next.prevHandle != null ? next.prevHandle.dt : 0.),
-				next.time, t);
-		}
-
-		inline function sampleVal(t) {
-			return bezier(
-				cur.value,
-				cur.value + (cur.nextHandle != null ? cur.nextHandle.dv : 0.),
-				next.value + (next.prevHandle != null ? next.prevHandle.dv : 0.),
-				next.value, t);
-		}
-
-		while( maxT - minT > maxDelta ) {
-			var t = (maxT + minT) * 0.5;
-			var x = sampleTime(t);
-			if( x > time )
-				maxT = t;
-			else
-				minT = t;
-		}
-
-		var x0 = sampleTime(minT);
-		var x1 = sampleTime(maxT);
-		var dx = x1 - x0;
-		var xfactor = dx == 0 ? 0.5 : (time - x0) / dx;
-
-		var y0 = sampleVal(minT);
-		var y1 = sampleVal(maxT);
-		var y = y0 + (y1 - y0) * xfactor;
-		return y;
-	}
-
-	public function getSum(time: Float) : Float {
-		var duration = keys[keys.length-1].time;
-		if(loop && time > duration) {
-			var cycles = Math.floor(time / duration);
-			return getSum(duration) * cycles + getSum(time - cycles);
-		}
-
-		var sum = 0.0;
-		for(ik in 0...keys.length) {
-			var key = keys[ik];
-			if(time < key.time)
-				break;
-
-			if(ik == 0 && key.time > 0) {
-				// Account for start of curve
-				sum += key.time * key.value;
-			}
-
-			var nkey = keys[ik + 1];
-			if(nkey != null) {
-				if(time > nkey.time) {
-					// Full interval
-					sum += key.value * (nkey.time - key.time);
-					if(key.mode != Constant)
-						sum += 0.5 * (nkey.time - key.time) * (nkey.value - key.value);
-				}
-				else {
-					// Split interval
-					sum += key.value * (time - key.time);
-					if(key.mode != Constant)
-						sum += 0.5 * (time - key.time) * hxd.Math.lerp(key.value, nkey.value, (time - key.time) / (nkey.time - key.time));
-				}
-			}
-			else {
-				sum += key.value * (time - key.time);
-			}
-		}
-		return sum;
-	}
-
-	public function sample(numPts: Int) {
-		var vals = [];
-		var duration = this.duration;
-		for(i in 0...numPts) {
-			var v = getVal(duration * i/(numPts-1));
-			vals.push(v);
-		}
-		return vals;
-	}
-
-	#if editor
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-		ctx.properties.add(new hide.Element('
-		<div class="group" name="Parameters">
-			<dl>
-				<dt>Loop curve</dt><dd><input type="checkbox" field="loop"/></dd>
-			</dl>
-		</div>'), this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-
-		var ce = new hide.comp.CurveEditor(ctx.properties.undo, ctx.properties.element);
-		ce.curve = this;
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "paint-brush", name : "Curve" };
-	}
-	#end
-
-	public static function getCurve(parent : Prefab, name: String, onlyEnabled=true) {
-		for(c in parent.children) {
-			if(onlyEnabled && !c.enabled) continue;
-			if(c.name != name) continue;
-			var curve = c.to(Curve);
-			if(curve == null) continue;
-			return curve;
-		}
-		return null;
-	}
-
-	public static function getCurves(parent: Prefab, prefix: String) {
-		var ret = null;
-		for(c in parent.children) {
-			if(!c.enabled) continue;
-			var idx = c.name.indexOf(".");
-			var curvePrefix = (idx >= 0) ? c.name.substr(0, idx) : c.name;
-			if(curvePrefix != prefix)
-				continue;
-			var curve = c.to(Curve);
-			if(curve == null) continue;
-			if (ret == null) ret = [];
-			ret.push(curve);
-		}
-		return ret;
-	}
-
-	public static function getGroups(curves: Array<Curve>) {
-		var groups : Array<{name: String, items: Array<Curve>}> = [];
-		for(c in curves) {
-			var prefix = c.name.split(".")[0];
-			var g = groups.find(g -> g.name == prefix);
-			if(g == null) {
-				groups.push({
-					name: prefix,
-					items: [c]
-				});
-			}
-			else {
-				g.items.push(c);
-			}
-		}
-		return groups;
-	}
-
-
-	static inline function findCurve(curves: Array<Curve>, suffix: String) {
-		return curves.find(c -> StringTools.endsWith(c.name, suffix));
-	}
-
-	public static function getVectorValue(curves: Array<Curve>, defVal: Float=0.0, scale: Float=1.0) : hrt.prefab.fx.Value {
-		inline function find(s) {
-			return findCurve(curves, s);
-		}
-		var x = find(".x");
-		var y = find(".y");
-		var z = find(".z");
-		var w = find(".w");
-
-		inline function curveOrVal(c: Curve, defVal: Float) : hrt.prefab.fx.Value {
-			return c != null ? (scale != 1.0 ? VCurveScale(c, scale) : VCurve(c)) : VConst(defVal);
-		}
-
-		return VVector(
-			curveOrVal(x, defVal),
-			curveOrVal(y, defVal),
-			curveOrVal(z, defVal),
-			curveOrVal(w, 1.0));
-	}
-
-	public static function getColorValue(curves: Array<Curve>) : hrt.prefab.fx.Value {
-		inline function find(s) {
-			return findCurve(curves, s);
-		}
-
-		var r = find(".r");
-		var g = find(".g");
-		var b = find(".b");
-		var a = find(".a");
-		var h = find(".h");
-		var s = find(".s");
-		var l = find(".l");
-
-		if(h != null || s != null || l != null) {
-			return VHsl(
-				h != null ? VCurve(h) : VConst(0.0),
-				s != null ? VCurve(s) : VConst(1.0),
-				l != null ? VCurve(l) : VConst(1.0),
-				a != null ? VCurve(a) : VConst(1.0));
-		}
-
-		if(a != null && r == null && g == null && b == null)
-			return VCurve(a);
-
-		if(a == null && r == null && g == null && b == null)
-			return VOne; // White by default
-
-		return VVector(
-			r != null ? VCurve(r) : VConst(1.0),
-			g != null ? VCurve(g) : VConst(1.0),
-			b != null ? VCurve(b) : VConst(1.0),
-			a != null ? VCurve(a) : VConst(1.0));
-	}
-
-	static var _ = Library.register("curve", Curve);
-}

+ 0 - 46
hrt/prefab/ShaderGraph.hx

@@ -1,46 +0,0 @@
-package hrt.prefab;
-
-class ShaderGraph extends DynamicShader {
-
-	public function new(?parent) {
-		super(parent);
-		type = "shadergraph";
-	}
-
-	override public function loadShaderDef(ctx: Context) {
-		if(shaderDef == null) {
-			var shaderGraph = new hrt.shgraph.ShaderGraph(source);
-			shaderDef = shaderGraph.compile();
-		}
-		if(shaderDef == null)
-			return;
-
-		#if editor
-		for( v in shaderDef.inits ) {
-			if(!Reflect.hasField(props, v.variable.name)) {
-				Reflect.setField(props, v.variable.name, v.value);
-			}
-		}
-		#end
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { icon : "scribd", name : "Shader Graph", fileSource : ["shgraph"], allowParent : function(p) return p.to(Object2D) != null || p.to(Object3D) != null };
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var btn = new hide.Element("<input type='submit' style='width: 100%; margin-top: 10px;' value='Open Shader Graph' />");
-		btn.on("click", function() {
- 			ctx.ide.openFile(source);
-		});
-		ctx.properties.add(btn,this.props, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-	#end
-
-	static var _ = Library.register("shgraph", ShaderGraph);
-}

+ 0 - 102
hrt/prefab/fx/AnimEvent.hx

@@ -1,102 +0,0 @@
-package hrt.prefab.fx;
-
-class AnimEvent extends hrt.prefab.fx.Event {
-
-	@:s public var animation: String;
-	@:s public var speed : Float = 1.0;
-	@:s public var duration : Float = 0.0;
-	@:s public var offset : Float = 0.0;
-
-	public function new(?parent) {
-		super(parent);
-		this.type = "animEvent";
-	}
-
-	override function prepare(ctx: Context) : Event.EventInstance {
-		var obj = ctx.local3d;
-		var anim = animation != null ? ctx.loadAnimation(animation) : null;
-		var lastTime = -1.0;
-		var inst = null;
-		if(anim == null) { return null; }
-		return {
-			evt: this,
-			setTime: function(localTime) {
-				var duration = duration > 0 ? duration : anim.getDuration();
-				if(localTime > 0 && localTime < duration) {
-					if(inst == null) {
-						inst = obj.playAnimation(anim);
-						inst.pause = true;
-						inst.loop = false;
-					}
-					inst.setFrame(hxd.Math.clamp((localTime + offset) * anim.sampling * anim.speed * speed, 0, anim.frameCount));
-				}
-				else inst = null;
-				lastTime = localTime;
-			}
-		}
-	}
-
-	#if editor
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-		var props = ctx.properties.add(new hide.Element('
-			<div class="group" name="Event">
-				<dl>
-					<dt>Time</dt><dd><input type="number" value="0" field="time"/></dd>
-					<dt>Animation</dt><dd><select><option value="">-- Choose --</option></select></dd>
-					<dt>Speed</dt><dd><input type="number" value="0" field="speed"/></dd>
-					<dt>Duration</dt><dd><input type="number" value="0" field="duration"/></dd>
-					<dt>Offset</dt><dd><input type="number" value="0" field="offset"/></dd>
-				</dl>
-			</div>
-		'),this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-
-		if(parent.source != null) {
-			var select = props.find("select");
-			var anims = try ctx.scene.listAnims(parent.source) catch(e: Dynamic) [];
-			for( a in anims )
-				new hide.Element('<option>').attr("value", ctx.ide.makeRelative(a)).text(ctx.scene.animationName(a)).appendTo(select);
-			if( animation != null )
-				select.val(animation);
-			select.change(function(_) {
-				ctx.scene.setCurrent();
-				var v = select.val();
-				var prev = animation;
-				if( v == "" ) {
-					animation = null;
-				} else {
-					animation = v;
-				}
-				ctx.properties.undo.change(Field(this, "animation", prev));
-				ctx.onChange(this, "animation");
-			});
-		}
-	}
-
-	override function getHideProps() : HideProps {
-		return {
-			icon : "play-circle", name : "AnimEvent",
-			allowParent : (p) -> p.to(Model) != null,
-			allowChildren: function(s) return false
-		};
-	}
-
-	override function getDisplayInfo(ctx: EditContext) {
-		var anim = null;
-		if(animation != null) {
-			try {
-				anim = ctx.rootContext.loadAnimation(animation);
-			} catch(e : hxd.res.NotFound) { }
-		}
-		return {
-			label: anim != null ? ctx.scene.animationName(animation) : "null",
-			length: duration > 0 ? duration : anim != null ? anim.getDuration() : 1.0
-		}
-	}
-	#end
-
-	static var _ = Library.register("animEvent", AnimEvent);
-
-}

+ 0 - 186
hrt/prefab/fx/BaseFX.hx

@@ -1,186 +0,0 @@
-package hrt.prefab.fx;
-import hrt.prefab.Curve;
-import hrt.prefab.Prefab as PrefabElement;
-
-typedef ShaderParam = {
-	def: hxsl.Ast.TVar,
-	value: Value
-};
-
-enum AdditionalProperies {
-	None;
-	PointLight(color : Value, power : Value, size : Value, range : Value );
-	SpotLight(color : Value, power : Value, range : Value, angle : Value, fallOff : Value );
-	DirLight(color : Value, power : Value);
-}
-
-typedef ShaderParams = Array<ShaderParam>;
-
-class ShaderAnimation extends Evaluator {
-	public var params : ShaderParams;
-	public var shader : hxsl.Shader;
-
-	public function setTime(time: Float) {
-		for(param in params) {
-			var v = param.def;
-			var val : Dynamic;
-			switch(v.type) {
-			case TFloat: val = getFloat(param.value, time);
-			case TInt: val = hxd.Math.round(getFloat(param.value, time));
-			case TBool: val = getFloat(param.value, time) >= 0.5;
-			case TVec(_, VFloat): val = getVector(param.value, time);
-			default:
-				continue;
-			}
-			Reflect.setProperty(shader, v.name, val);
-		}
-	}
-}
-
-class ShaderDynAnimation extends ShaderAnimation {
-
-	override function setTime(time: Float) {
-		var shader : hxsl.DynamicShader = cast shader;
-		for(param in params) {
-			var v = param.def;
-			switch(v.type) {
-				case TFloat:
-					var val = getFloat(param.value, time);
-					shader.setParamFloatValue(v, val);
-				case TInt:
-					var val = hxd.Math.round(getFloat(param.value, time));
-					shader.setParamValue(v, val);
-				case TBool:
-					var val = getFloat(param.value, time) >= 0.5;
-					shader.setParamValue(v, val);
-				case TVec(_, VFloat):
-					var val = getVector(param.value, time);
-					shader.setParamValue(v, val);
-				default:
-			}
-		}
-	}
-}
-
-typedef ObjectAnimation = {
-	?elt: hrt.prefab.Object3D,
-	?obj: h3d.scene.Object,
-	?elt2d: hrt.prefab.Object2D,
-	?obj2d: h2d.Object,
-	events: Array<hrt.prefab.fx.Event.EventInstance>,
-	?position: Value,
-	?scale: Value,
-	?rotation: Value,
-	?color: Value,
-	?visibility: Value,
-	?additionalProperies : AdditionalProperies
-};
-
-class BaseFX extends hrt.prefab.Library {
-
-	@:s public var duration : Float;
-	@:c public var scriptCode : String;
-	@:c public var cullingRadius : Float;
-	@:c public var markers : Array<{t: Float}> = [];
-
-	public function new() {
-		super();
-		duration = 5.0;
-		scriptCode = null;
-		cullingRadius = 1000;
-	}
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		if( markers != null && markers.length > 0 )
-			obj.markers = markers;
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		markers = obj.markers == null ? [] : obj.markers;
-	}
-
-	public static function makeShaderParams(ctx: Context, shaderElt: hrt.prefab.Shader) {
-		var shaderDef = shaderElt.getShaderDefinition(ctx);
-		if(shaderDef == null)
-			return null;
-
-		var ret : ShaderParams = [];
-
-		for(v in shaderDef.data.vars) {
-			if(v.kind != Param)
-				continue;
-
-			var prop = Reflect.field(shaderElt.props, v.name);
-			if(prop == null)
-				prop = hrt.prefab.DynamicShader.getDefault(v.type);
-
-			var curves = Curve.getCurves(shaderElt, v.name);
-			if(curves == null || curves.length == 0)
-				continue;
-
-			switch(v.type) {
-				case TVec(_, VFloat) :
-					var isColor = v.name.toLowerCase().indexOf("color") >= 0;
-					var val = isColor ? Curve.getColorValue(curves) : Curve.getVectorValue(curves);
-					ret.push({
-						def: v,
-						value: val
-					});
-
-				default:
-					var base = 1.0;
-					if(Std.is(prop, Float) || Std.is(prop, Int))
-						base = cast prop;
-					var curve = Curve.getCurve(shaderElt, v.name);
-					var val = Value.VConst(base);
-					if(curve != null)
-						val = Value.VCurveScale(curve, base);
-					ret.push({
-						def: v,
-						value: val
-					});
-			}
-		}
-
-		return ret;
-	}
-
-	public static function getShaderAnims(ctx: Context, elt: PrefabElement, anims: Array<ShaderAnimation>) {
-		if(Std.downcast(elt, hrt.prefab.fx.Emitter) == null) {
-			for(c in elt.children) {
-				getShaderAnims(ctx, c, anims);
-			}
-		}
-
-		var shader = elt.to(hrt.prefab.Shader);
-		if(shader == null)
-			return;
-
-		for(shCtx in ctx.shared.getContexts(elt)) {
-			if(shCtx.custom == null) continue;
-			var anim = Std.is(shCtx.custom,hxsl.DynamicShader) ? new ShaderDynAnimation(new hxd.Rand(0)) : new ShaderAnimation(new hxd.Rand(0));
-			anim.shader = shCtx.custom;
-			anim.params = makeShaderParams(ctx, shader);
-			anims.push(anim);
-		}
-	}
-
-	public function getFXRoot( ctx : Context, elt : PrefabElement ) : PrefabElement {
-		if( elt.name == "FXRoot" )
-			return elt;
-		else {
-			for(c in elt.children) {
-				var elt = getFXRoot(ctx, c);
-				if(elt != null) return elt;
-			}
-		}
-		return null;
-	}
-
-	#if editor
-	public function refreshObjectAnims(ctx: Context) { }
-	#end
-}

+ 0 - 1722
hrt/prefab/fx/Emitter.hx

@@ -1,1722 +0,0 @@
-package hrt.prefab.fx;
-import hrt.prefab.l3d.Polygon;
-import hrt.prefab.Curve;
-import hrt.prefab.fx.BaseFX.ShaderAnimation;
-using Lambda;
-
-enum SimulationSpace {
-	Local;
-	World;
-}
-
-enum AlignMode {
-	None;
-	Screen;
-	Axis;
-}
-
-enum EmitShape {
-	Cone;
-	Sphere;
-	Box;
-	Cylinder;
-}
-
-enum Orientation {
-	Forward;
-	Normal;
-	Speed;
-	Random;
-}
-
-enum EmitType {
-	Infinity;
-	Duration;
-	Burst;
-	BurstDuration;
-}
-
-typedef ParamDef = {
-	> hrt.prefab.Props.PropDef,
-	?animate: Bool,
-	?instance: Bool,
-	?groupName: String
-}
-
-typedef InstanceDef = {
-	localSpeed: Value,
-	worldSpeed: Value,
-	startSpeed: Value,
-	startWorldSpeed: Value,
-	orbitSpeed: Value,
-	acceleration: Value,
-	worldAcceleration: Value,
-	localOffset: Value,
-	scale: Value,
-	stretch: Value,
-	rotation: Value
-}
-
-typedef EmitterTrail = {
-	particle : ParticleInstance,
-	trail : h3d.scene.Trail,
-	timeBeforeDeath : Float
-}
-
-typedef ShaderAnims = Array<ShaderAnimation>;
-
-private class ParticleTransform {
-
-	public var parent : h3d.scene.Object;
-	public var absPos = new h3d.Matrix();
-	public var qRot = new h3d.Quat();
-	public var x = 0.0;
-	public var y = 0.0;
-	public var z = 0.0;
-	public var scaleX = 1.0;
-	public var scaleY = 1.0;
-	public var scaleZ = 1.0;
-
-	public function new() {
-
-	}
-
-	public function reset() {
-		x = 0.0;
-		y = 0.0;
-		z = 0.0;
-		scaleX = 1.0;
-		scaleY = 1.0;
-		scaleZ = 1.0;
-	}
-
-	public function setRotation( quat ) {
-		qRot.load(quat);
-	}
-
-	public inline function getPosition() {
-		return new h3d.Vector(x, y, z);
-	}
-
-	public inline function setPosition( x, y, z ) {
-		this.x = x;
-		this.y = y;
-		this.z = z;
-	}
-
-	public inline function transform3x3( m : h3d.Matrix ) {
-		var px = x * m._11 + y * m._21 + z * m._31;
-		var py = x * m._12 + y * m._22 + z * m._32;
-		var pz = x * m._13 + y * m._23 + z * m._33;
-		x = px;
-		y = py;
-		z = pz;
-	}
-
-	public inline function setScale( x, y, z ) {
-		this.scaleX = x;
-		this.scaleY = y;
-		this.scaleZ = z;
-	}
-
-	public inline function getWorldPosition() {
-		var ppos = parent.getAbsPos();
-		return new h3d.Vector(x + ppos.tx, y + ppos.ty, z + ppos.tz);
-	}
-
-	public inline function setWorldPosition(v: h3d.Vector) {
-		var ppos = parent.getAbsPos();
-		x = v.x - ppos.tx;
-		y = v.y - ppos.ty;
-		z = v.z - ppos.tz;
-	}
-
-
-	public function calcAbsPos() {
-		qRot.toMatrix(absPos);
-		absPos._11 *= scaleX;
-		absPos._12 *= scaleX;
-		absPos._13 *= scaleX;
-		absPos._21 *= scaleY;
-		absPos._22 *= scaleY;
-		absPos._23 *= scaleY;
-		absPos._31 *= scaleZ;
-		absPos._32 *= scaleZ;
-		absPos._33 *= scaleZ;
-		absPos._41 = x;
-		absPos._42 = y;
-		absPos._43 = z;
-		if( parent != null )
-			absPos.multiply3x4inline(absPos, parent.getAbsPos());
-	}
-
-	static var tmpMat = new h3d.Matrix();
-	static var tmpVec = new h3d.Vector();
-	public function setTransform( mat : h3d.Matrix ) {
-		var s = mat.getScale(tmpVec);
-		this.x = mat.tx;
-		this.y = mat.ty;
-		this.z = mat.tz;
-		this.scaleX = s.x;
-		this.scaleY = s.y;
-		this.scaleZ = s.z;
-		tmpMat.load(mat);
-		tmpMat.prependScale(1.0 / s.x, 1.0 / s.y, 1.0 / s.z);
-		qRot.initRotateMatrix(tmpMat);
-	}
-}
-
-@:allow(hrt.prefab.fx.EmitterObject)
-private class ParticleInstance  {
-	public var next : ParticleInstance;
-
-	var emitter : EmitterObject;
-	var evaluator : Evaluator;
-
-	var transform = new ParticleTransform();
-	var localTransform = new ParticleTransform();
-	public var absPos = new h3d.Matrix();
-	public var localMat = new h3d.Matrix();
-	public var baseMat : h3d.Matrix;
-
-	public var startTime = 0.0;
-	public var life = 0.0;
-	public var lifeTime = 0.0;
-	public var startFrame : Int;
-	public var speedAccumulation = new h3d.Vector();
-	public var colorMult : h3d.Vector;
-	public var distToCam = 0.0;
-
-	public var orientation = new h3d.Quat();
-
-	public var def : InstanceDef;
-
-	public function new() {
-	}
-
-	public function init(emitter: EmitterObject, def: InstanceDef) {
-		transform.reset();
-		localTransform.reset();
-		life = 0;
-		lifeTime = 0;
-		startFrame = 0;
-		speedAccumulation.set(0,0,0);
-		orientation.identity();
-
-		switch(emitter.simulationSpace){
-			// Particles in Local are spawned next to emitter in the scene tree,
-			// so emitter shape can be transformed (especially scaled) without affecting children
-			case Local : transform.parent = emitter.parent;
-			case World : transform.parent = emitter.getScene();
-		}
-		this.def = def;
-		this.emitter = emitter;
-		this.evaluator = new Evaluator(emitter.random);
-		evaluator.vecPool = this.emitter.vecPool;
-	}
-
-	public function dispose() {
-		transform.parent = localTransform.parent = null;
-		emitter = null;
-	}
-
-	static var tmpRot = new h3d.Vector();
-	static var tmpOffset = new h3d.Vector();
-	static var tmpScale = new h3d.Vector();
-	static var tmpLocalSpeed = new h3d.Vector();
-	static var tmpWorldSpeed = new h3d.Vector();
-	static var tmpSpeedAccumulation = new h3d.Vector();
-	static var tmpGroundNormal = new h3d.Vector(0,0,1);
-	static var tmpSpeed = new h3d.Vector();
-	static var tmpMat = new h3d.Matrix();
-	static var tmpPos = new h3d.Vector();
-	static var tmpPos2 = new h3d.Vector();
-	static var tmpCamRotAxis = new h3d.Vector();
-	static var tmpCamAlign = new h3d.Vector();
-	static var tmpCamVec = new h3d.Vector();
-	static var tmpCamVec2 = new h3d.Vector();
-	static var tmpQuat = new h3d.Quat();
-
-
-	inline function add( v1 : h3d.Vector, v2 : h3d.Vector ) {
-		v1.x += v2.x;
-		v1.y += v2.y;
-		v1.z += v2.z;
-	}
-
-	inline function sub( v1 : h3d.Vector, v2 : h3d.Vector ) {
-		v1.x -= v2.x;
-		v1.y -= v2.y;
-		v1.z -= v2.z;
-	}
-
-	inline function cross( v1 : h3d.Vector, v2 : h3d.Vector ) {
-		v1.x -= v1.y * v2.z - v1.z * v2.y;
-		v1.y -= v1.z * v2.x - v1.x * v2.z;
-		v1.z -= v1.x * v2.y - v1.y * v2.x;
-		v1.w = 1.0;
-	}
-
-	public function update( dt : Float ) {
-		var t = hxd.Math.clamp(life / lifeTime, 0.0, 1.0);
-		tmpSpeed.set(0,0,0);
-
-		if( life == 0 ) {
-			// START LOCAL SPEED
-			evaluator.getVector(def.startSpeed, 0.0, tmpSpeedAccumulation);
-			tmpSpeedAccumulation.transform3x3(orientation.toMatrix(tmpMat));
-			add(speedAccumulation, tmpSpeedAccumulation);
-			// START WORLD SPEED
-			evaluator.getVector(def.startWorldSpeed, 0.0, tmpSpeedAccumulation);
-			tmpSpeedAccumulation.transform3x3(emitter.invTransform);
-			add(speedAccumulation, tmpSpeedAccumulation);
-		}
-
-		// ACCELERATION
-		if(def.acceleration != VZero) {
-			evaluator.getVector(def.acceleration, t, tmpSpeedAccumulation);
-			tmpSpeedAccumulation.scale3(dt);
-			tmpSpeedAccumulation.transform3x3(orientation.toMatrix(tmpMat));
-			add(speedAccumulation, tmpSpeedAccumulation);
-		}
-
-		// WORLD ACCELERATION
-		if(def.worldAcceleration != VZero) {
-			evaluator.getVector(def.worldAcceleration, t, tmpSpeedAccumulation);
-			tmpSpeedAccumulation.scale3(dt);
-			if(emitter.simulationSpace == Local)
-				tmpSpeedAccumulation.transform3x3(emitter.invTransform);
-			add(speedAccumulation, tmpSpeedAccumulation);
-		}
-
-		add(tmpSpeed, speedAccumulation);
-
-		// SPEED
-		if(def.localSpeed != VZero) {
-			evaluator.getVector(def.localSpeed, t, tmpLocalSpeed);
-			tmpLocalSpeed.transform3x3(orientation.toMatrix(tmpMat));
-			add(tmpSpeed, tmpLocalSpeed);
-		}
-		// WORLD SPEED
-		if(def.worldSpeed != VZero) {
-			evaluator.getVector(def.worldSpeed, t, tmpWorldSpeed);
-			if(emitter.simulationSpace == Local)
-				tmpWorldSpeed.transform3x3(emitter.invTransform);
-			add(tmpSpeed, tmpWorldSpeed);
-		}
-
-		if(emitter.simulationSpace == World) {
-			tmpSpeed.x *= emitter.worldScale.x;
-			tmpSpeed.y *= emitter.worldScale.y;
-			tmpSpeed.z *= emitter.worldScale.z;
-		}
-
-		transform.x += tmpSpeed.x * dt;
-		transform.y += tmpSpeed.y * dt;
-		transform.z += tmpSpeed.z * dt;
-
-		if(def.orbitSpeed != VZero) {
-			evaluator.getVector(def.orbitSpeed, t, tmpLocalSpeed);
-			tmpMat.initRotation(tmpLocalSpeed.x * dt, tmpLocalSpeed.y * dt, tmpLocalSpeed.z * dt);
-			// Rotate in emitter space and convert back to world space
-			var pos = transform.getWorldPosition();
-			var prevPos = transform.getPosition();
-			pos.transform3x4(emitter.getInvPos());
-			pos.transform3x3(tmpMat);
-			pos.transform3x4(emitter.getAbsPos());
-			transform.setWorldPosition(pos);
-
-			// Take transform into account into local speed
-			var delta = transform.getPosition().sub(prevPos);
-			delta.scale(1 / dt);
-			add(tmpSpeed, delta);
-		}
-
-		// SPEED ORIENTATION
-		if(emitter.emitOrientation == Speed && tmpSpeed.lengthSq() > 0.01)
-			transform.qRot.initDirection(tmpSpeed);
-
-		// ROTATION
-		var rot = evaluator.getVector(def.rotation, t, tmpRot);
-		rot.scale3(Math.PI / 180.0);
-
-		//OFFSET
-		var offset = evaluator.getVector(def.localOffset, t, tmpOffset);
-
-		//SCALE
-		var scaleVec = evaluator.getVector(def.stretch, t, tmpScale);
-		scaleVec.scale3(evaluator.getFloat(def.scale, t));
-
-		// TRANSFORM
-		localMat.initScale(scaleVec.x, scaleVec.y, scaleVec.z);
-		localMat.rotate(rot.x, rot.y, rot.z);
-		localMat.translate(offset.x, offset.y, offset.z);
-		if( baseMat != null )
-			localMat.multiply(baseMat, localMat);
-		localTransform.setTransform(localMat);
-
-		// ALIGNMENT
-		switch( emitter.alignMode ) {
-			case Screen:
-				transform.qRot.load(emitter.screenQuat);
-				transform.calcAbsPos();
-				localTransform.calcAbsPos();
-				absPos.multiply(localTransform.absPos, transform.absPos);
-
-			case Axis:
-				transform.calcAbsPos();
-
-				var absChildMat = tmpMat;
-				absChildMat.multiply3x4(transform.absPos, localMat);
-				tmpCamAlign.load(emitter.alignAxis);
-				tmpCamAlign.transform3x3(absChildMat);
-				tmpCamAlign.normalizeFast();
-
-				tmpCamRotAxis.load(emitter.alignLockAxis);
-				tmpCamRotAxis.transform3x3(transform.absPos);
-				tmpCamRotAxis.normalizeFast();
-
-				tmpCamVec.load(emitter.getScene().camera.pos);
-				sub(tmpCamVec, transform.absPos.getPosition(tmpPos));
-				tmpCamVec.normalizeFast();
-
-				tmpCamVec2.load(tmpCamVec);
-				tmpCamVec2.scale3(tmpCamVec.dot(tmpCamRotAxis));
-				sub(tmpCamVec, tmpCamVec2);
-				tmpCamVec.normalizeFast();
-
-				var angle = hxd.Math.acos(tmpCamAlign.dot(tmpCamVec));
-				cross(tmpCamAlign, tmpCamVec2);
-				if(tmpCamRotAxis.dot(tmpCamAlign) < 0)
-					angle = -angle;
-
-				tmpQuat.identity();
-				tmpQuat.initRotateAxis(emitter.alignLockAxis.x, emitter.alignLockAxis.y, emitter.alignLockAxis.z, angle);
-				var cq = localTransform.qRot;
-				cq.multiply(cq, tmpQuat);
-				localTransform.setRotation(cq);
-
-				localTransform.calcAbsPos();
-				absPos.multiply(localTransform.absPos, transform.absPos);
-
-			case None:
-				transform.calcAbsPos();
-				localTransform.calcAbsPos();
-				absPos.multiply(localTransform.absPos, transform.absPos);
-		}
-
-		// COLLISION
-		if( emitter.useCollision ) {
-			var worldPos = absPos.getPosition(tmpPos);
-			if( worldPos.z < 0 ) {
-				if( emitter.killOnCollision == 1 || hxd.Math.random() < emitter.killOnCollision ) {
-					life = lifeTime + 1; // No survivor
-				}
-				else {
-					var speedAmount = speedAccumulation.length();
-					speedAccumulation.normalize();
-					var newDir = speedAccumulation.reflect(tmpGroundNormal);
-					newDir.scale3(emitter.elasticity);
-					newDir.scale3(speedAmount);
-					speedAccumulation.set(newDir.x, newDir.y, newDir.z);
-					transform.z = 0;
-					absPos.multiply(localTransform.absPos, transform.absPos);
-				}
-			}
-		}
-
-		life += dt;
-	}
-}
-
-@:allow(hrt.prefab.fx.ParticleInstance)
-@:allow(hrt.prefab.fx.Emitter)
-class EmitterObject extends h3d.scene.Object {
-
-	public static var pool : ParticleInstance;
-	public static var poolSize = 0;
-	public static function clearPool() {
-		pool = null;
-		poolSize = 0;
-	}
-
-	public var instDef : InstanceDef;
-
-	public var batch : h3d.scene.MeshBatch;
-	public var particles : ParticleInstance;
-	public var shaderAnims : ShaderAnims;
-
-	public var isSubEmitter : Bool = false;
-	public var parentEmitter : EmitterObject = null;
-	public var enable : Bool;
-	public var particleVisibility(default, null) : Bool;
-
-	public var startTime = 0.0;
-	public var catchupSpeed = 4; // Use larger ticks when catching-up to save calculations
-	public var maxCatchupWindow = 0.5; // How many seconds max to simulate when catching up
-	public var totalBurstCount : Int = 0; // Keep track of burst count
-
-	// RANDOM
-	public var seedGroup = 0;
-	// OBJECTS
-	public var particleTemplate : hrt.prefab.Object3D;
-	public var subEmitterTemplate : Emitter;
-	public var trailTemplate : hrt.prefab.l3d.Trail;
-	public var subEmitters : Array<EmitterObject> = [];
-	public var trails : Array<EmitterTrail> = [];
-	// LIFE
-	public var lifeTime = 2.0;
-	public var lifeTimeRand = 0.0;
-	public var speedFactor = 1.0;
-	public var warmUpTime = 0.0;
-	// EMIT PARAMS
-	public var emitOrientation : Orientation = Forward;
-	public var simulationSpace : SimulationSpace = Local;
-	public var emitType : EmitType = Infinity;
-	public var burstCount : Int = 1;
-	public var burstParticleCount : Int = 5;
-	public var burstDelay : Float = 1.0;
-	public var emitDuration : Float = 1.0;
-	public var emitRate : Value;
-	public var maxCount = 20;
-	public var enableSort = true;
-	// EMIT SHAPE
-	public var emitShape : EmitShape = Cylinder;
-	public var emitAngle : Float = 0.0;
-	public var emitRad1 : Float = 1.0;
-	public var emitRad2 : Float = 1.0;
-	public var emitSurface : Bool = false;
-	// ANIMATION
-	public var spriteSheet : String;
-	public var frameCount : Int = 0;
-	public var frameDivisionX : Int = 1;
-	public var frameDivisionY : Int = 1;
-	public var animationSpeed : Float = 1;
-	public var animationLoop : Bool = true;
-	// ALIGNMENT
-	public var alignMode : AlignMode;
-	public var alignAxis : h3d.Vector;
-	public var alignLockAxis : h3d.Vector;
-	// COLLISION
-	public var elasticity : Float = 1.0;
-	public var killOnCollision : Float = 0.0;
-	public var useCollision : Bool = false;
-	// RANDOM COLOR
-	public var useRandomColor : Bool = false;
-	public var randomColor1 : h3d.Vector;
-	public var randomColor2 : h3d.Vector;
-
-	public var invTransform = new h3d.Matrix();
-	public var screenQuat = new h3d.Quat();
-	public var worldScale = new h3d.Vector(1,1,1);
-
-	var random: hxd.Rand;
-	var randomSeed = 0;
-	var context : hrt.prefab.Context;
-	var emitCount = 0;
-	var emitTarget = 0.0;
-	var curTime = 0.0;
-	var evaluator : Evaluator;
-	var vecPool = new Evaluator.VecPool();
-	var numInstances = 0;
-	var animatedTextureShader : h3d.shader.AnimatedTexture = null;
-	var colorMultShader : h3d.shader.ColorMult = null;
-
-	public function new(?parent) {
-		super(parent);
-		randomSeed = Std.random(0xFFFFFF);
-		random = new hxd.Rand(randomSeed);
-		evaluator = new Evaluator(random);
-		evaluator.vecPool = vecPool;
-		reset();
-	}
-
-	public function reset() {
-		particleVisibility = true;
-		enable = true;
-		random.init(randomSeed);
-		curTime = 0.0;
-		emitCount = 0;
-		emitTarget = 0;
-		totalBurstCount = 0;
-
-		var p = particles;
-		while(p != null) {
-			var n = p.next;
-			disposeInstance(p);
-			p = n;
-		}
-		particles = null;
-		for( s in subEmitters ) {
-			s.remove();
-		}
-		subEmitters = [];
-		for( t in trails ) {
-			t.trail.remove();
-		}
-		trails = [];
-	}
-
-	override function onRemove() {
-		super.onRemove();
-		reset();
-	}
-
-	public function setParticleVibility( b : Bool ){
-		particleVisibility = b;
-	}
-
-	function allocInstance() {
-		++numInstances;
-		if(pool != null) {
-			var p = pool;
-			pool = p.next;
-			--poolSize;
-			return p;
-		}
-		var p = new ParticleInstance();
-		return p;
-	}
-
-	var tmpPos = new h3d.Vector();
-	var tmpCtx : hrt.prefab.Context;
-	function disposeInstance(p: ParticleInstance) {
-
-		// TRAIL
-		for( t in trails ) {
-			if( t.particle == p ) {
-				t.particle = null;
-				break;
-			}
-		}
-
-		p.next = pool;
-		p.dispose();
-		pool = p;
-		--numInstances;
-		++poolSize;
-		if(numInstances < 0)
-			throw "assert";
-	}
-
-	static var tmpQuat = new h3d.Quat();
-	static var tmpEmitterQuat = new h3d.Quat();
-	static var tmpOffset = new h3d.Vector();
-	static var tmpVec = new h3d.Vector();
-	static var tmpDir = new h3d.Vector();
-	static var tmpScale = new h3d.Vector();
-	static var tmpMat = new h3d.Matrix();
-	static var tmpMat2 = new h3d.Matrix();
-	static var tmpPt = new h3d.col.Point();
-	function doEmit( count : Int ) {
-		if( count == 0 )
-			return;
-
-		if( instDef == null || particleTemplate == null )
-			return;
-
-		var emitterQuat : h3d.Quat = null;
-		var emitterBaseMat : h3d.Matrix = null;
-
-		for( i in 0...count ) {
-			var part = allocInstance();
-			part.init(this, instDef);
-			part.next = particles;
-			particles = part;
-
-			if(emitterBaseMat == null) {
-				emitterBaseMat = particleTemplate.getTransform();
-				part.baseMat = emitterBaseMat;
-			}
-			else
-				part.baseMat = emitterBaseMat.clone();
-
-			part.startTime = startTime + curTime;
-			part.lifeTime = hxd.Math.max(0.01, lifeTime + hxd.Math.srand(lifeTimeRand));
-
-			if(useRandomColor) {
-				var col = new h3d.Vector();
-				col.lerp(randomColor1, randomColor2, random.rand());
-				part.colorMult = col;
-			}
-
-			tmpQuat.identity();
-
-			switch( emitShape ) {
-				case Box:
-					tmpOffset.set(random.srand(0.5), random.srand(0.5), random.srand(0.5));
-					if( emitSurface ) {
-						var max = Math.max(Math.max(Math.abs(tmpOffset.x), Math.abs(tmpOffset.y)), Math.abs(tmpOffset.z));
-						tmpOffset.scale(0.5 / max);
-					}
-					if( emitOrientation == Normal )
-						tmpQuat.initDirection(tmpOffset);
-				case Cylinder:
-					var z = random.rand();
-					var dx = 0.0, dy = 0.0;
-					var shapeAngle = hxd.Math.degToRad(emitAngle) / 2.0;
-					var a = random.srand(shapeAngle);
-					if(emitSurface) {
-						dx = Math.cos(a)*(emitRad2*z + emitRad1*(1.0-z));
-						dy = Math.sin(a)*(emitRad2*z + emitRad1*(1.0-z));
-					}
-					else {
-						dx = Math.cos(a)*(emitRad2*z + emitRad1*(1.0-z))*random.rand();
-						dy = Math.sin(a)*(emitRad2*z + emitRad1*(1.0-z))*random.rand();
-					}
-					tmpOffset.set(dx * 0.5, dy * 0.5, z - 0.5);
-					if( emitOrientation == Normal )
-						tmpQuat.initRotation(0, 0, hxd.Math.atan2(dy, dx));
-				case Sphere:
-					do {
-						tmpOffset.x = random.srand(1.0);
-						tmpOffset.y = random.srand(1.0);
-						tmpOffset.z = random.srand(1.0);
-					}
-					while( tmpOffset.lengthSq() > 1.0 );
-					if( emitSurface )
-						tmpOffset.normalize();
-					tmpOffset.scale3(0.5);
-					if( emitOrientation == Normal )
-						tmpQuat.initDirection(tmpOffset);
-				case Cone:
-					tmpOffset.set(0, 0, 0);
-					var theta = random.rand() * Math.PI * 2;
-					var shapeAngle = hxd.Math.degToRad(emitAngle) / 2.0;
-					var phi = shapeAngle * random.rand();
-					tmpDir.x = Math.cos(phi) * scaleX;
-					tmpDir.y = Math.sin(phi) * Math.sin(theta) * scaleY;
-					tmpDir.z = Math.sin(phi) * Math.cos(theta) * scaleZ;
-					tmpDir.normalizeFast();
-					tmpQuat.initDirection(tmpDir);
-			}
-
-			if( emitOrientation == Random )
-				tmpQuat.initRotation(hxd.Math.srand(Math.PI), hxd.Math.srand(Math.PI), hxd.Math.srand(Math.PI));
-
-			switch( simulationSpace ) {
-				case Local:
-					if(emitterQuat == null) {
-						emitterQuat = tmpEmitterQuat;
-						emitterQuat.load(getRotationQuat());
-						tmpMat.load(getAbsPos());
-						tmpMat2.load(parent.getAbsPos());
-						tmpMat2.invert();
-						tmpMat.multiply(tmpMat, tmpMat2);
-					}
-
-					tmpOffset.transform(tmpMat);
-					part.transform.setPosition(tmpOffset.x, tmpOffset.y, tmpOffset.z);
-					tmpQuat.multiply(emitterQuat, tmpQuat);
-					part.transform.setRotation(tmpQuat);
-					part.orientation.load(tmpQuat);
-				case World:
-					tmpPt.set(tmpOffset.x, tmpOffset.y, tmpOffset.z);
-					localToGlobal(tmpPt);
-					part.transform.setPosition(tmpPt.x, tmpPt.y, tmpPt.z);
-					emitterQuat = tmpEmitterQuat;
-					tmpMat.load(getAbsPos());
-					tmpMat.getScale(tmpScale);
-					tmpMat.prependScale(1.0/tmpScale.x, 1.0/tmpScale.y, 1.0/tmpScale.z);
-					emitterQuat.initRotateMatrix(tmpMat);
-					emitterQuat.normalize();
-					tmpQuat.multiply(tmpQuat, emitterQuat);
-					part.transform.setRotation(tmpQuat);
-					part.orientation.load(tmpQuat);
-					part.transform.setScale(worldScale.x, worldScale.y, worldScale.z);
-			}
-
-			var frameCount = frameCount == 0 ? frameDivisionX * frameDivisionY : frameCount;
-			if(animationLoop)
-				part.startFrame = random.random(frameCount);
-
-			if( trailTemplate != null ) {
-				if( tmpCtx == null ) {
-					tmpCtx = new hrt.prefab.Context();
-					tmpCtx.local3d = this.getScene();
-					tmpCtx.shared = context.shared;
-				}
-				tmpCtx.local3d = this.getScene();
-				var trail : h3d.scene.Trail = cast trailTemplate.make(tmpCtx).local3d;
-				trail.setTransform(part.absPos);
-				trails.push({particle: part, trail: trail, timeBeforeDeath: 0.0});
-			}
-		}
-		context.local3d = this;
-		emitCount += count;
-	}
-
-	function createMeshBatch() {
-
-		if( batch != null )
-			batch.remove();
-
-		if( particleTemplate == null )
-			return;
-
-		var template = particleTemplate.makeInstance(context);
-		var mesh = Std.downcast(template.local3d, h3d.scene.Mesh);
-		if( mesh == null ) {
-			for( i in 0...template.local3d.numChildren ) {
-				mesh = Std.downcast(template.local3d.getChildAt(i), h3d.scene.Mesh);
-				if( mesh != null ) break;
-			}
-		}
-
-		if( mesh != null && mesh.primitive != null ) {
-			var meshPrim = Std.downcast(mesh.primitive, h3d.prim.MeshPrimitive);
-
-			// Setup mats.
-			// Should we do this manually here or make a recursive makeInstance on the template?
-			var materials = particleTemplate.getAll(hrt.prefab.Material);
-			for(mat in materials) {
-				if(mat.enabled)
-					mat.makeInstance(template);
-			}
-
-			// Setup shaders
-			shaderAnims = [];
-			var shaders = particleTemplate.getAll(hrt.prefab.Shader);
-			for( shader in shaders ) {
-				if( !shader.enabled ) continue;
-				var shCtx = shader.makeInstance(template);
-				if( shCtx == null ) continue;
-				hrt.prefab.fx.BaseFX.getShaderAnims(template, shader, shaderAnims);
-			}
-			for(s in shaderAnims) {
-				s.vecPool = vecPool;
-			}
-
-			// Animated textures animations
-			var frameCount = frameCount == 0 ? frameDivisionX * frameDivisionY : frameCount;
-			if( frameCount > 1 && spriteSheet != null ) {
-				var tex = hxd.res.Loader.currentInstance.load(spriteSheet).toTexture();
-				animatedTextureShader = new h3d.shader.AnimatedTexture(tex, frameDivisionX, frameDivisionY, frameCount, frameCount * animationSpeed / lifeTime);
-				animatedTextureShader.startTime = startTime;
-				animatedTextureShader.loop = animationLoop;
-				animatedTextureShader.setPriority(1);
-				mesh.material.mainPass.addShader(animatedTextureShader);
-			}
-
-			if(useRandomColor) {
-				colorMultShader = new h3d.shader.ColorMult();
-				mesh.material.mainPass.addShader(colorMultShader);
-			}
-
-			if( meshPrim != null ) {
-				batch = new h3d.scene.MeshBatch(meshPrim, mesh.material, this);
-				batch.name = "batch";
-			}
-			template.local3d.remove();
-		}
-	}
-
-	static function sortZ( p1 : ParticleInstance, p2 : ParticleInstance ) : Int {
-		return p1.distToCam < p2.distToCam ? 1 : -1;
-	}
-
-	function tick( dt : Float, full=true) {
-
-		// Auto remove of sub emitters
-		if( !enable && particles == null && isSubEmitter ) {
-			parentEmitter.subEmitters.remove(this);
-			remove();
-			return;
-		}
-
-		for( se in subEmitters ) {
-			se.tick(dt);
-		}
-
-		if( emitRate == null || emitRate == VZero )
-			return;
-
-		if( parent != null ) {
-			invTransform.load(parent.getInvPos());
-
-			if(alignMode == Screen) {
-				var cam = getScene().camera;
-				tmpMat.load(cam.mcam);
-				tmpMat.invert();
-
-				if(simulationSpace == Local) {  // Compensate parent rotation
-					tmpMat2.load(parent.getAbsPos());
-					var s = tmpMat2.getScale();
-					tmpMat2.prependScale(1.0 / s.x, 1.0 / s.y, 1.0 / s.z);
-					tmpMat2.invert();
-					tmpMat.multiply(tmpMat, tmpMat2);
-				}
-				screenQuat.initRotateMatrix(tmpMat);
-				tmpQuat.initRotateAxis(1,0,0,Math.PI);  // Flip Y axis so Y is pointing down
-				screenQuat.multiply(screenQuat, tmpQuat);
-			}
-
-			parent.getAbsPos().getScale(worldScale);
-		}
-		vecPool.begin();
-
-		if( enable ) {
-			switch emitType {
-				case Infinity:
-					emitTarget += evaluator.getFloat(emitRate, curTime) * dt;
-					var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, emitTarget - emitCount));
-					doEmit(delta);
-					if( isSubEmitter && (parentEmitter == null || parentEmitter.parent == null) )
-						enable = false;
-				case Duration:
-					emitTarget += evaluator.getFloat(emitRate, hxd.Math.min(curTime, emitDuration)) * dt;
-					var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, emitTarget - emitCount));
-					doEmit(delta);
-					if( isSubEmitter && curTime >= emitDuration )
-						enable = false;
-				case BurstDuration:
-					if( burstDelay > 0 ) {
-						var burstTarget = 1 + hxd.Math.floor(curTime / burstDelay);
-						var lastBurstTime = totalBurstCount * burstDelay;
-						var nextBurstTime = lastBurstTime + burstDelay;
-						var needBurst = nextBurstTime <= emitDuration && totalBurstCount < burstTarget;
-						while( needBurst ) {
-							var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, burstParticleCount));
-							doEmit(delta);
-							totalBurstCount++;
-							lastBurstTime += burstDelay;
-							nextBurstTime = lastBurstTime + burstDelay;
-							needBurst = nextBurstTime <= emitDuration && totalBurstCount < burstTarget;
-						}
-					}
-					if( isSubEmitter && curTime > emitDuration )
-						enable = false;
-				case Burst:
-					if( burstDelay > 0 ) {
-						var burstTarget = hxd.Math.min(burstCount, 1 + hxd.Math.floor(curTime / burstDelay));
-						while( totalBurstCount < burstTarget ) {
-							var delta = hxd.Math.ceil(hxd.Math.min(maxCount - numInstances, burstParticleCount));
-							doEmit(delta);
-							totalBurstCount++;
-						}
-					}
-					if( isSubEmitter && totalBurstCount == burstCount )
-						enable = false;
-
-			}
-		}
-
-		updateParticles(dt);
-
-		if( full && batch != null ) {
-			batch.begin(hxd.Math.nextPOT(maxCount));
-			if( particleVisibility ) {
-				particles = haxe.ds.ListSort.sortSingleLinked(particles, sortZ);
-				var p = particles;
-				var i = 0;
-				while(p != null) {
-					batch.worldPosition = p.absPos;
-					for( anim in shaderAnims ) {
-						var t = hxd.Math.clamp(p.life / p.lifeTime, 0.0, 1.0);
-						anim.setTime(t);
-					}
-					if( animatedTextureShader != null ){
-						animatedTextureShader.startTime = p.startTime;
-						animatedTextureShader.startFrame = p.startFrame;
-					}
-					if(colorMultShader != null)
-						colorMultShader.color = p.colorMult;
-					batch.emitInstance();
-					p = p.next;
-					++i;
-				}
-			}
-		}
-		curTime += dt;
-	}
-
-	function updateParticles(dt: Float) {
-		var p = particles;
-		var prev : ParticleInstance = null;
-		var camPos = getScene().camera.pos;
-		while(p != null) {
-			var next = p.next;
-			if(p.life > p.lifeTime) {
-				if(prev != null)
-					prev.next = next;
-				else
-					particles = next;
-
-				disposeInstance(p);
-
-				// SUB EMITTER
-				if( subEmitterTemplate != null ) {
-					if( tmpCtx == null ) {
-						tmpCtx = new hrt.prefab.Context();
-						tmpCtx.local3d = this.getScene();
-						tmpCtx.shared = context.shared;
-					}
-					tmpCtx.local3d = this.getScene();
-					var emitter : EmitterObject = cast subEmitterTemplate.makeInstance(tmpCtx).local3d;
-					var pos = p.absPos.getPosition(tmpPos);
-					emitter.setPosition(pos.x, pos.y, pos.z);
-					emitter.isSubEmitter = true;
-					emitter.parentEmitter = this;
-					subEmitters.push(emitter);
-				}
-			}
-			else {
-				p.update(dt);
-				if(p.distToCam < 0 || enableSort)
-					p.distToCam = camPos.distanceSq(p.absPos.getPosition());
-				prev = p;
-			}
-			p = next;
-		}
-
-		// TRAIL
-		var i = 0;
-		while( i < trails.length ) {
-			var emitterTrail = trails[i];
-			var trail = emitterTrail.trail;
-			var particle = emitterTrail.particle;
-			if( particle != null ) {
-				trail.setTransform(particle.absPos);
-				i++;
-			}
-			else {
-				emitterTrail.timeBeforeDeath += dt;
-				if( emitterTrail.timeBeforeDeath > trail.duration ) {
-					trail.remove();
-					trails[i] = trails[trails.length - 1];
-					trails.pop();
-				}
-				else
-					i++;
-			}
-		}
-	}
-
-	public function setRandSeed(seed: Int) {
-		randomSeed = seed ^ seedGroup;
-		reset();
-	}
-
-	public function setTime(time: Float) {
-		time = time * speedFactor + warmUpTime;
-		if(time < curTime) {
-			reset();
-		}
-
-		var catchupTime = time - curTime;
-
-		#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));
-
-			// Force sort after long time invisible
-			var p = particles;
-			while(p != null) {
-				p.distToCam = -1;
-				p = p.next;
-			}
-		}
-		#end
-
-		var catchupTickRate = hxd.Timer.wantedFPS * speedFactor / catchupSpeed;
-		var numTicks = hxd.Math.ceil(catchupTickRate * catchupTime);
-		for(i in 0...numTicks) {
-			tick(catchupTime / numTicks, i == (numTicks - 1));
-		}
-	}
-
-	override function getBoundsRec( b : h3d.col.Bounds ) {
-		if( posChanged ) {
-			posChanged = false;
-			calcAbsPos();
-		}
-		return b;
-	}
-}
-
-class Emitter extends Object3D {
-
-	public function new(?parent) {
-		super(parent);
-		props = { };
-		for(param in emitterParams) {
-			if(param.def != null)
-				resetParam(param);
-		}
-	}
-
-	public static var emitterParams : Array<ParamDef> = [
-		// RANDOM
-		{ name: "seedGroup", t: PInt(0, 100), def: 0, groupName : "Random", disp: "Seed"},
-		// LIFE
-		{ name: "lifeTime", t: PFloat(0, 10), def: 1.0, groupName : "Time" },
-		{ name: "lifeTimeRand", t: PFloat(0, 1), def: 0.0, groupName : "Time" },
-		{ name: "speedFactor", disp: "Speed Factor", t: PFloat(0, 1), def: 1.0, groupName : "Time" },
-		{ name: "warmUpTime", disp: "Warm Up", t: PFloat(0, 1), def: 0.0, groupName : "Time" },
-		// EMIT PARAMS
-		{ name: "emitType", t: PEnum(EmitType), def: EmitType.Infinity, disp: "Type", groupName : "Emit Params"  },
-		{ name: "emitDuration", t: PFloat(0, 10.0), disp: "Duration", def : 1.0, groupName : "Emit Params" },
-		{ name: "emitRate", t: PInt(0, 100), def: 5, disp: "Rate", animate: true, groupName : "Emit Params" },
-		{ name: "burstCount", t: PInt(1, 10), disp: "Count", def : 1, groupName : "Emit Params" },
-		{ name: "burstDelay", t: PFloat(0, 1.0), disp: "Delay", def : 1.0, groupName : "Emit Params" },
-		{ name: "burstParticleCount", t: PInt(1, 10), disp: "Particle Count", def : 1, groupName : "Emit Params" },
-		{ name: "simulationSpace", t: PEnum(SimulationSpace), def: SimulationSpace.Local, disp: "Simulation Space", groupName : "Emit Params" },
-		{ name: "emitOrientation", t: PEnum(Orientation), def: Orientation.Forward, disp: "Orientation", groupName : "Emit Params" },
-		{ name: "maxCount", t: PInt(0, 100), def: 20, groupName : "Emit Params" },
-		{ name: "enableSort", t: PBool, def: true, disp: "Enable Sort", groupName : "Emit Params" },
-		// EMIT SHAPE
-		{ name: "emitShape", t: PEnum(EmitShape), def: EmitShape.Sphere, disp: "Shape", 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: "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" },
-		// ALIGNMENT
-		{ name: "alignMode", t: PEnum(AlignMode), def: AlignMode.None, disp: "Mode", groupName : "Alignment" },
-		{ name: "alignAxis", t: PVec(3, -1.0, 1.0), def: [0.,0.,0.], disp: "Axis", groupName : "Alignment" },
-		{ name: "alignLockAxis", t: PVec(3, -1.0, 1.0), def: [0.,0.,0.], disp: "Lock Axis", groupName : "Alignment" },
-		// COLOR
-		{ name: "useRandomColor", t: PBool, def: false, disp: "Random Color", groupName : "Color" },
-		{ name: "randomColor1", t: PVec(4), disp: "Color 1", def : [0,0,0,1], groupName : "Color" },
-		{ name: "randomColor2", t: PVec(4), disp: "Color 2", def : [1,1,1,1], groupName : "Color" },
-		// ANIMATION
-		{ name: "spriteSheet", t: PFile(["jpg","png"]), def: null, groupName : "Animation", disp: "Sheet" },
-		{ name: "frameCount", t: PInt(0), def: 0, groupName : "Animation", disp: "Frames" },
-		{ name: "frameDivisionX", t: PInt(1), def: 1, groupName : "Animation", disp: "Divisions X" },
-		{ name: "frameDivisionY", t: PInt(1), def: 1, groupName : "Animation", disp: "Divisions Y" },
-		{ name: "animationSpeed", t: PFloat(0, 2.0), def: 1.0, groupName : "Animation", disp: "Speed" },
-		{ name: "animationLoop", t: PBool, def: true, groupName : "Animation", disp: "Loop" },
-		// COLLISION
-		{ name: "useCollision", t: PBool, def: false, groupName : "Ground Collision" },
-		{ name: "elasticity", t: PFloat(0, 1.0), disp: "Elasticity", def : 1.0, groupName : "Ground Collision" },
-		{ name: "killOnCollision", t: PFloat(0, 1.0), disp: "Kill On Collision", def : 0.0, groupName : "Ground Collision" },
-	];
-
-	public static var instanceParams : Array<ParamDef> = [
-		{ name: "instSpeed",      			t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "Fixed Speed" },
-		{ name: "instWorldSpeed", 			t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "Fixed World Speed" },
-		{ name: "instStartSpeed",      		t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "Start Speed" },
-		{ name: "instStartWorldSpeed", 		t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "Start World Speed" },
-		{ name: "instOrbitSpeed", 			t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "Orbit Speed" },
-		{ name: "instAcceleration",			t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "Acceleration" },
-		{ name: "instWorldAcceleration",	t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "World Acceleration" },
-		{ name: "instScale",      			t: PFloat(0, 2.0),    def: 1.,         disp: "Scale" },
-		{ name: "instStretch",    			t: PVec(3, 0.0, 2.0), def: [1.,1.,1.], disp: "Stretch" },
-		{ name: "instRotation",   			t: PVec(3, 0, 360),   def: [0.,0.,0.], disp: "Rotation" },
-		{ name: "instOffset",     			t: PVec(3, -10, 10),  def: [0.,0.,0.], disp: "Offset" }
-	];
-
-	public static var PARAMS : Array<ParamDef> = {
-		var a = emitterParams.copy();
-		for(i in instanceParams) {
-			i.instance = true;
-			i.animate = true;
-			a.push(i);
-		}
-		a;
-	};
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		obj.props = Reflect.copy(props);
-		for(param in PARAMS) {
-			var f : Dynamic = Reflect.field(props, param.name);
-			if(f != null && haxe.Json.stringify(f) != haxe.Json.stringify(param.def)) {
-				var val : Dynamic = f;
-				switch(param.t) {
-					case PEnum(en):
-						val = Type.enumConstructor(val);
-					default:
-				}
-				Reflect.setField(obj.props, param.name, val);
-			}
-			else {
-				Reflect.deleteField(obj.props, param.name);
-			}
-		}
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		for(param in emitterParams) {
-			if(Reflect.hasField(obj.props, param.name)) {
-				var val : Dynamic = Reflect.field(obj.props, param.name);
-				switch(param.t) {
-					case PEnum(en):
-						val = Type.createEnum(en, val);
-					default:
-				}
-				Reflect.setField(props, param.name, val);
-			}
-			else if(param.def != null)
-				resetParam(param);
-		}
-	}
-
-	override function make(ctx: Context) {
-		if( ctx == null ) {
-			ctx = new Context();
-			ctx.init();
-		}
-		ctx = makeInstance(ctx);
-		return ctx;
-	}
-
-	function refreshChildren(ctx: Context) {
-		// Don't make all children, which are used to setup particles
-		for( c in children ) {
-			var shader = Std.downcast(c, hrt.prefab.Shader);
-			if( shader != null )
-				makeChildren(ctx, shader);
-		}
-	}
-
-	static inline function randProp(name: String) {
-		return name + "_rand";
-	}
-
-	function getParamVal(name: String, rand: Bool=false) : Dynamic {
-		var param = PARAMS.find(p -> p.name == name);
-		if(param == null)
-			return Reflect.field(props, name);
-		var isVector = switch(param.t) {
-			case PVec(_): true;
-			default: false;
-		}
-		var val : Dynamic = rand ? (isVector ? [0.,0.,0.,0.] : 0.) : param.def;
-		if(rand)
-			name = randProp(name);
-		if(props != null && Reflect.hasField(props, name)) {
-			val = Reflect.field(props, name);
-		}
-		if(isVector)
-			return h3d.Vector.fromArray(val);
-		return val;
-	}
-
-	function resetParam(param: ParamDef) {
-		var a = Std.downcast(param.def, Array);
-		if(a != null)
-			Reflect.setField(props, param.name, a.copy());
-		else
-			Reflect.setField(props, param.name, param.def);
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		var emitterObj = Std.downcast(ctx.local3d, EmitterObject);
-
-		var randIdx = 0;
-		var template : Object3D = cast children.find( c -> c.enabled && (c.name == null || c.name.indexOf("collision") == -1) && c.to(Object3D) != null && c.to(Object3D).visible );
-
-		function makeParam(scope: Prefab, name: String): Value {
-			var getCurve = hrt.prefab.Curve.getCurve.bind(scope);
-
-			function vVal(f: Float) : Value {
-				return switch(f) {
-					case 0.0: VZero;
-					case 1.0: VOne;
-					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 randVal : Value = VZero;
-				if(randCurve != null)
-					randVal = VRandom(randIdx++, VCurveScale(randCurve, randProp != null ? randProp : 1.0));
-				else if(randProp != null && randProp != 0.0)
-					randVal = VRandomScale(randIdx++, randProp);
-
-				var xCurve = getCurve(pname + suffix);
-				if (xCurve != null)
-					if (pname.indexOf("Rotation") >= 0 || pname.indexOf("Offset") >= 0)
-						return vAdd(vAdd(xVal, randVal), VCurve(xCurve));
-					else
-						return vMult(vAdd(xVal, randVal), VCurve(xCurve));
-				else
-					return vAdd(xVal, randVal);
-			}
-
-			var baseProp: Dynamic = Reflect.field(props, name);
-			var randProp: Dynamic = Reflect.field(props, randProp(name));
-			var param = PARAMS.find(p -> p.name == name);
-			switch(param.t) {
-				case PVec(_):
-					inline function makeComp(idx, suffix) {
-						return makeCompVal(
-							baseProp != null ? (baseProp[idx] : Float) : null,
-							param.def != null ? param.def[idx] : 0.0,
-							randProp != null ? (randProp[idx] : Float) : null,
-							param.name, suffix);
-					}
-					var v : Value = VVector(
-						makeComp(0, ".x"),
-						makeComp(1, ".y"),
-						makeComp(2, ".z"));
-					if(v.match(VVector(VZero, VZero, VZero)))
-						v = VZero;
-					else if(v.match(VVector(VOne, VOne, VOne)))
-						v = VOne;
-					return v;
-
-				default:
-					return makeCompVal(baseProp, param.def != null ? param.def : 0.0, randProp, param.name, "");
-			}
-		}
-
-		function makeColor(scope: Prefab, name: String) {
-			var curves = hrt.prefab.Curve.getCurves(scope, name);
-			if(curves == null || curves.length == 0)
-				return null;
-			return hrt.prefab.Curve.getColorValue(curves);
-		}
-
-		if(template != null) {
-			emitterObj.instDef = {
-				localSpeed: makeParam(this, "instSpeed"),
-				worldSpeed: makeParam(this, "instWorldSpeed"),
-				startSpeed: makeParam(this, "instStartSpeed"),
-				startWorldSpeed: makeParam(this, "instStartWorldSpeed"),
-				orbitSpeed: makeParam(this, "instOrbitSpeed"),
-				acceleration: makeParam(this, "instAcceleration"),
-				worldAcceleration: makeParam(this, "instWorldAcceleration"),
-				localOffset: makeParam(this, "instOffset"),
-				scale: makeParam(this, "instScale"),
-				stretch: makeParam(this, "instStretch"),
-				rotation: makeParam(this, "instRotation")
-			};
-
-			emitterObj.particleTemplate = template;
-		}
-
-		// SUB-EMITTER
-		var subEmitterTemplate : Emitter = cast children.find( p -> p.enabled && Std.downcast(p, Emitter) != null && p.to(Object3D).visible);
-		emitterObj.subEmitterTemplate = subEmitterTemplate;
-		// TRAIL
-		var trailTemplate : hrt.prefab.l3d.Trail = cast children.find( p -> p.enabled && Std.is(p, hrt.prefab.l3d.Trail) && p.to(Object3D).visible);
-		emitterObj.trailTemplate = trailTemplate;
-		// RANDOM
-		emitterObj.seedGroup 			= 	getParamVal("seedGroup");
-		// LIFE
-		emitterObj.lifeTime 			= 	getParamVal("lifeTime");
-		emitterObj.lifeTimeRand 		= 	getParamVal("lifeTimeRand");
-		emitterObj.speedFactor 			= 	getParamVal("speedFactor");
-		emitterObj.warmUpTime 			= 	getParamVal("warmUpTime");
-		// EMIT PARAMS
-		emitterObj.emitType 			= 	getParamVal("emitType");
-		emitterObj.burstCount 			= 	getParamVal("burstCount");
-		emitterObj.burstDelay 			= 	getParamVal("burstDelay");
-		emitterObj.burstParticleCount 	= 	getParamVal("burstParticleCount");
-		emitterObj.emitDuration 		= 	getParamVal("emitDuration");
-		emitterObj.simulationSpace 		= 	getParamVal("simulationSpace");
-		emitterObj.emitOrientation 		= 	getParamVal("emitOrientation");
-		emitterObj.maxCount 			= 	getParamVal("maxCount");
-		emitterObj.enableSort 			= 	getParamVal("enableSort");
-		emitterObj.emitRate 			= 	makeParam(this, "emitRate");
-		emitterObj.emitShape 			= 	getParamVal("emitShape");
-		// EMIT SHAPE
-		emitterObj.emitAngle 			= 	getParamVal("emitAngle");
-		emitterObj.emitRad1 			= 	getParamVal("emitRad1");
-		emitterObj.emitRad2 			= 	getParamVal("emitRad2");
-		emitterObj.emitSurface 			= 	getParamVal("emitSurface");
-		// ALIGNMENT
-		emitterObj.alignMode 			= 	getParamVal("alignMode");
-		emitterObj.alignAxis 			= 	getParamVal("alignAxis");
-		emitterObj.alignLockAxis 		= 	getParamVal("alignLockAxis");
-		// ANIMATION
-		emitterObj.spriteSheet 			= 	getParamVal("spriteSheet");
-		emitterObj.frameCount 			= 	getParamVal("frameCount");
-		emitterObj.frameDivisionX 		= 	getParamVal("frameDivisionX");
-		emitterObj.frameDivisionY 		= 	getParamVal("frameDivisionY");
-		emitterObj.animationSpeed 		= 	getParamVal("animationSpeed");
-		emitterObj.animationLoop 		= 	getParamVal("animationLoop");
-		// COLLISION
-		emitterObj.useCollision 		= 	getParamVal("useCollision");
-		emitterObj.killOnCollision 		= 	getParamVal("killOnCollision");
-		emitterObj.elasticity 			= 	getParamVal("elasticity");
-		// RANDOM COLOR
-		emitterObj.useRandomColor 		= 	getParamVal("useRandomColor");
-		emitterObj.randomColor1 		= 	getParamVal("randomColor1");
-		emitterObj.randomColor2 		= 	getParamVal("randomColor2");
-
-
-		#if !editor  // Keep startTime at 0 in Editor, since global.time is synchronized to timeline
-		var scene = ctx.local3d.getScene();
-		if(scene != null)
-			emitterObj.startTime = @:privateAccess scene.renderer.ctx.time;
-		#end
-
-		emitterObj.createMeshBatch();
-		emitterObj.reset();
-		refreshChildren(ctx);
-
-		#if editor
-		if(propName == null || ["emitShape", "emitAngle", "emitRad1", "emitRad2"].indexOf(propName) >= 0)
-			updateEmitShape(emitterObj);
-		#end
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var emitterObj = new EmitterObject(ctx.local3d);
-		emitterObj.context = ctx;
-		ctx.local3d = emitterObj;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function removeInstance(ctx:Context):Bool {
-		return false;
-	}
-
-	#if editor
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		function refresh() {
-			ctx.properties.clear();
-			this.edit(ctx);
-		}
-
-		function onChange(?pname: String) {
-			ctx.onChange(this, pname);
-
-			if(["emitShape",
-				"alignMode",
-				"useCollision",
-				"emitType",
-				"useRandomColor"].indexOf(pname) >= 0)
-				refresh();
-		}
-
-		var params = emitterParams.copy();
-		inline function removeParam(pname: String) {
-			params.remove(params.find(p -> p.name == pname));
-		}
-
-		var emitShape : EmitShape = getParamVal("emitShape");
-		if(!(emitShape == Cone || emitShape == Cylinder))
-			removeParam("emitAngle");
-		if(emitShape != Cylinder) {
-			removeParam("emitRad1");
-			removeParam("emitRad2");
-		}
-
-		var alignMode : AlignMode = getParamVal("alignMode");
-		switch(alignMode) {
-			case None | Screen:
-				removeParam("alignAxis");
-				removeParam("alignLockAxis");
-			default:
-		}
-
-		var useCollision = getParamVal("useCollision");
-		if( !useCollision ) {
-			removeParam("elasticity");
-			removeParam("killOnCollision");
-		}
-
-		if(!getParamVal("useRandomColor")) {
-			removeParam("randomColor1");
-			removeParam("randomColor2");
-		}
-
-		var emitType : EmitType = getParamVal("emitType");
-		switch (emitType) {
-			case Infinity:
-				removeParam("burstCount");
-				removeParam("burstDelay");
-				removeParam("burstParticleCount");
-				removeParam("emitDuration");
-			case BurstDuration:
-				removeParam("emitRate");
-				removeParam("burstCount");
-			case Burst:
-				removeParam("emitDuration");
-				removeParam("emitRate");
-			case Duration:
-				removeParam("burstCount");
-				removeParam("burstDelay");
-				removeParam("burstParticleCount");
-		}
-
-		// Emitter
-		{
-			// Sort by groupName
-			var groupNames : Array<String> = [];
-			for( p in params ) {
-				if( p.groupName == null && groupNames.indexOf("Emitter") == -1 )
-					groupNames.push("Emitter");
-				else if( p.groupName != null && groupNames.indexOf(p.groupName) == -1 )
-					groupNames.push(p.groupName);
-			}
-
-			for( gn in groupNames ) {
-				var params = params.filter( p -> p.groupName == (gn == "Emitter" ? null : gn) );
-				var group = new Element('<div class="group" name="$gn"></div>');
-				group.append(hide.comp.PropsEditor.makePropsList(params));
-				ctx.properties.add(group, this.props, onChange);
-			}
-		}
-
-		// Instances
-		{
-			var instGroup = new Element('<div class="group" name="Particles"></div>');
-			var dl = new Element('<dl>').appendTo(instGroup);
-			for(p in instanceParams) {
-				var dt = new Element('<dt>${p.disp != null ? p.disp : p.name}</dt>').appendTo(dl);
-				var dd = new Element('<dd>').appendTo(dl);
-
-				function addUndo(pname: String) {
-					ctx.properties.undo.change(Field(this.props, pname, Reflect.field(this.props, pname)), function() {
-						if(Reflect.field(this.props, pname) == null)
-							Reflect.deleteField(this.props, pname);
-						refresh();
-					});
-				}
-
-				if(Reflect.hasField(this.props, p.name)) {
-					hide.comp.PropsEditor.makePropEl(p, dd);
-					dt.contextmenu(function(e) {
-						e.preventDefault();
-						new hide.comp.ContextMenu([
-							{ label : "Reset", click : function() {
-								addUndo(p.name);
-								resetParam(p);
-								onChange();
-								refresh();
-							} },
-							{ label : "Remove", click : function() {
-								addUndo(p.name);
-								Reflect.deleteField(this.props, p.name);
-								onChange();
-								refresh();
-							} },
-						]);
-						return false;
-					});
-				}
-				else {
-					var btn = new Element('<input type="button" value="+"></input>').appendTo(dd);
-					btn.click(function(e) {
-						addUndo(p.name);
-						resetParam(p);
-						refresh();
-					});
-				}
-				var dt = new Element('<dt>~</dt>').appendTo(dl);
-				var dd = new Element('<dd>').appendTo(dl);
-				var randDef : Dynamic = switch(p.t) {
-					case PVec(n): [for(i in 0...n) 0.0];
-					case PFloat(_): 0.0;
-					default: 0;
-				};
-				if(Reflect.hasField(this.props, randProp(p.name))) {
-					hide.comp.PropsEditor.makePropEl({
-						name: randProp(p.name),
-						t: p.t,
-						def: randDef}, dd);
-					dt.contextmenu(function(e) {
-						e.preventDefault();
-						new hide.comp.ContextMenu([
-							{ label : "Reset", click : function() {
-								addUndo(randProp(p.name));
-								Reflect.setField(this.props, randProp(p.name), randDef);
-								onChange();
-								refresh();
-							} },
-							{ label : "Remove", click : function() {
-								addUndo(randProp(p.name));
-								Reflect.deleteField(this.props, randProp(p.name));
-								onChange();
-								refresh();
-							} },
-						]);
-						return false;
-					});
-				}
-				else {
-					var btn = new Element('<input type="button" value="+"></input>').appendTo(dd);
-					btn.click(function(e) {
-						addUndo(randProp(p.name));
-						Reflect.setField(this.props, randProp(p.name), randDef);
-						refresh();
-					});
-				}
-			}
-			var props = ctx.properties.add(instGroup, this.props, onChange);
-		}
-	}
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		var emitterObj = Std.downcast(ctx.local3d, EmitterObject);
-		if(emitterObj == null)
-			return false;
-		var debugShape : h3d.scene.Object = emitterObj.find(c -> if(c.name == "_highlight") c else null);
-		if(debugShape != null)
-			debugShape.visible = b;
-
-		if( false && emitterObj.batch != null ) {  // Disabling, selection causes crashes
-			if( b ) {
-				var shader = new h3d.shader.FixedColor(0xffffff);
-				var p = emitterObj.batch.material.allocPass("highlight");
-				p.culling = None;
-				p.depthWrite = false;
-				p.addShader(shader);
-				@:privateAccess p.batchMode = true;
-			}
-			else {
-				emitterObj.batch.material.removePass(emitterObj.batch.material.getPass("highlight"));
-			}
-			emitterObj.batch.shadersChanged = true;
-		}
-		return false;
-	}
-
-	function updateEmitShape(emitterObj: EmitterObject) {
-
-		var debugShape : h3d.scene.Object = emitterObj.find(c -> if(c.name == "_highlight") c else null);
-		if(debugShape == null) {
-			debugShape = new h3d.scene.Object(emitterObj);
-			debugShape.name = "_highlight";
-			debugShape.visible = false;
-		}
-
-		for(i in 0...debugShape.numChildren)
-			debugShape.removeChild(debugShape.getChildAt(i));
-
-		var mesh : h3d.scene.Mesh = null;
-		switch(emitterObj.emitShape) {
-			case Cylinder: {
-				var rad1 = getParamVal("emitRad1") * 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);
-				g.material.mainPass.setPassName("overlay");
-				g.lineStyle(1, 0xffffff);
-				circle(32, function(i, c, s) {
-					if(i == 0)
-						g.moveTo(c * rad1, s * rad1, -0.5);
-					else
-						g.lineTo(c * rad1, s * rad1, -0.5);
-				});
-				circle(32, function(i, c, s) {
-					if(i == 0)
-						g.moveTo(c * rad2, s * rad2, 0.5);
-					else
-						g.lineTo(c * rad2, s * rad2, 0.5);
-				});
-				g.lineStyle(1, 0xffffff);
-				circle(8, function(i, c, s) {
-					g.moveTo(c * rad1, s * rad1, -0.5);
-					g.lineTo(c * rad2, s * rad2, 0.5);
-				});
-				g.ignoreCollide = true;
-				mesh = g;
-			}
-			case Box: {
-				mesh = new h3d.scene.Box(0xffffff, true, debugShape);
-			}
-			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);
-				g.material.mainPass.setPassName("overlay");
-				var angle = hxd.Math.degToRad(getParamVal("emitAngle")) / 2.0;
-				var rad = hxd.Math.sin(angle);
-				var dist = hxd.Math.cos(angle);
-				g.lineStyle(1, 0xffffff);
-				circle(32, function(i, c, s) {
-					if(i == 0)
-						g.moveTo(dist, c * rad, s * rad);
-					else
-						g.lineTo(dist, c * rad, s * rad);
-				});
-				g.lineStyle(1, 0xffffff);
-				circle(4, function(i, c, s) {
-					g.moveTo(0, 0, 0);
-					g.lineTo(dist, c * rad, s * rad);
-				});
-				g.ignoreCollide = true;
-				mesh = g;
-			}
-			case Sphere:
-				mesh = new h3d.scene.Sphere(0xffffff, 0.5, true, debugShape);
-		}
-
-		if(mesh != null) {
-			var mat = mesh.material;
-			mat.mainPass.setPassName("overlay");
-			mat.shadows = false;
-		}
-
-		return debugShape;
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "asterisk", name : "Emitter", allowParent : function(p) return p.to(FX) != null || p.getParent(FX) != null };
-	}
-	#end
-
-	static var _ = Library.register("emitter", Emitter);
-
-}

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

@@ -1,113 +0,0 @@
-package hrt.prefab.fx;
-
-class VecPool {
-	var vecPool : Array<h3d.Vector> = null;
-	var vecPoolSize = 0;
-
-	public function new() { }
-
-	public function begin() {
-		if(vecPool == null)
-			vecPool = [];
-		vecPoolSize = 0;
-	}
-
-	public function get() {
-		var vec = null;
-		if(vecPoolSize < vecPool.length)
-			vec = vecPool[vecPoolSize++];
-		else {
-			vec = new h3d.Vector();
-			vecPool.push(vec);
-		}
-		return vec;
-	}
-}
-
-class Evaluator {
-	var randValues : Array<Float> = [];
-	var random: hxd.Rand;
-	public var vecPool : VecPool;
-
-	public function new(random: hxd.Rand) {
-		this.random = random;
-	}
-
-	public function getFloat(val: Value, time: Float) : Float {
-		if(val == null)
-			return 0.0;
-		switch(val) {
-			case VZero: return 0.0;
-			case VOne: return 1.0;
-			case VConst(v): return v;
-			case VCurve(c): return c.getVal(time);
-			case VCurveScale(c, scale): return c.getVal(time) * scale;
-			case VRandom(idx, scale):
-				var len = randValues.length;
-				while(idx >= len) {
-					randValues.push(random.srand());
-					++len;
-				}
-				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):
-				return getFloat(a, time) * getFloat(b, time);
-			case VAdd(a, b):
-				return getFloat(a, time) + getFloat(b, time);
-			default: 0.0;
-		}
-		return 0.0;
-	}
-
-	public function getSum(val: Value, time: Float) : Float {
-		switch(val) {
-			case VOne: return time;
-			case VConst(v): return v * time;
-			case VCurveScale(c, scale): return c.getSum(time) * scale;
-			case VCurve(c): return c.getSum(time);
-			case VAdd(a, b):
-				return getSum(a, time) + getSum(b, time);
-			case VMult(a, b):
-				throw "Not implemented";
-				return 0.0;
-			default: 0.0;
-		}
-		return 0.0;
-	}
-
-	public function getVector(v: Value, time: Float, ?vec: h3d.Vector) : h3d.Vector {
-		if(vec == null)
-			vec = vecPool != null ? vecPool.get() : new h3d.Vector();
-		switch(v) {
-			case VMult(a, b):
-				var av = getVector(a, time);
-				var bv = getVector(b, time);
-				vec.set(av.x * bv.x, av.y * bv.y, av.z * bv.z, av.w * bv.w);
-			case VVector(x, y, z, null):
-				vec.set(getFloat(x, time), getFloat(y, time), getFloat(z, time), 1.0);
-			case VVector(x, y, z, w):
-				vec.set(getFloat(x, time), getFloat(y, time), getFloat(z, time), getFloat(w, time));
-			case VHsl(h, s, l, a):
-				var hval = getFloat(h, time);
-				var sval = getFloat(s, time);
-				var lval = getFloat(l, time);
-				var aval = getFloat(a, time);
-				vec.makeColor(hval, sval, lval);
-				vec.a = aval;
-			case VZero:
-				vec.set(0,0,0,1);
-			case VOne:
-				vec.set(1,1,1,1);
-			default:
-				var f = getFloat(v, time);
-				vec.set(f, f, f, 1.0);
-		}
-		return vec;
-	}
-}

+ 0 - 66
hrt/prefab/fx/Event.hx

@@ -1,66 +0,0 @@
-package hrt.prefab.fx;
-
-typedef EventInstance = {
-	evt: Event,
-	?play: Void->Void,
-	?setTime: Float->Void
-};
-
-class Event extends hrt.prefab.Prefab {
-	@:s public var time: Float = 0.0;
-
-	public function new(?parent) {
-		super(parent);
-		this.type = "event";
-	}
-
-	public function prepare(ctx: Context) : EventInstance {
-		return {
-			evt: this
-		};
-	}
-
-	public static function updateEvents(evts: Array<EventInstance>, time: Float, prevTime: Float) {
-		if(evts == null) return;
-
-		for(evt in evts) {
-			if(evt.play != null && time > prevTime && evt.evt.time > prevTime && evt.evt.time < time)
-				evt.play();
-
-			if(evt.setTime != null)
-				evt.setTime(time - evt.evt.time);
-		}
-	}
-
-	#if editor
-
-	override function edit( ctx ) {
-		super.edit(ctx);
-		var props = ctx.properties.add(new hide.Element('
-			<div class="group" name="Event">
-				<dl>
-					<dt>Time</dt><dd><input type="number" value="0" field="time"/></dd>
-				</dl>
-			</div>
-		'),this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	override function getHideProps() : hide.prefab.HideProps {
-		return {
-			icon : "bookmark", name : "Event",
-		};
-	}
-
-	public function getDisplayInfo(ctx) {
-		return {
-			label: name,
-			length: 1.0
-		};
-	}
-
-	#end
-
-	static var _ = Library.register("event", Event);
-}

+ 0 - 485
hrt/prefab/fx/FX.hx

@@ -1,485 +0,0 @@
-package hrt.prefab.fx;
-import hrt.prefab.fx.BaseFX.AdditionalProperies;
-import hrt.prefab.Curve;
-import hrt.prefab.Prefab as PrefabElement;
-import hrt.prefab.fx.BaseFX.ObjectAnimation;
-import hrt.prefab.fx.BaseFX.ShaderAnimation;
-
-
-@:allow(hrt.prefab.fx.FX)
-class FXAnimation extends h3d.scene.Object {
-	public static var defaultCullingDistance = 0.0;
-
-	public var onEnd : Void -> Void;
-	public var playSpeed : Float = 0;
-	public var localTime : Float = 0.0;
-	var totalTime : Float = 0.0;
-	public var duration : Float;
-	public var additionLoopDuration : Float = 0.0;
-
-	public var enableCulling = true;
-	public var cullingRadius : Float;
-	public var cullingDistance = defaultCullingDistance;
-
-	public var objAnims: Array<ObjectAnimation>;
-	public var events: Array<hrt.prefab.fx.Event.EventInstance>;
-	public var emitters : Array<hrt.prefab.fx.Emitter.EmitterObject>;
-	public var shaderAnims : Array<ShaderAnimation> = [];
-	public var constraints : Array<hrt.prefab.l3d.Constraint>;
-	public var script : hrt.prefab.fx.FXScript;
-
-	public var vecPool = new Evaluator.VecPool();
-	var evaluator : Evaluator;
-	var random : hxd.Rand;
-	var prevTime = -1.0;
-	var randSeed : Int;
-
-	var startLoop : Float = -1.0;
-	var endLoop : Float;
-	var syncedOnce = false;
-
-	public function new(?parent) {
-		super(parent);
-		randSeed = Std.random(0xFFFFFF);
-		random = new hxd.Rand(randSeed);
-		evaluator = new Evaluator(random);
-		evaluator.vecPool = vecPool;
-		name = "FXAnimation";
-		inheritCulled = true;
-	}
-
-	function init(ctx: Context, def: FX, ?root: PrefabElement) {
-		if(root == null)
-			root = def;
-		initObjAnimations(ctx, root);
-		initEmitters(ctx, root);
-		BaseFX.getShaderAnims(ctx, root, shaderAnims);
-		events = initEvents(root, ctx);
-		if (events != null) {
-			for (e in events) {
-				if (e.evt.name == "startLoop") {
-					startLoop = e.evt.time;
-				} else if (e.evt.name == "endLoop") {
-					endLoop = e.evt.time;
-				}
-			}
-		}
-		var root = def.getFXRoot(ctx, def);
-		initConstraints(ctx, root != null ? root : def);
-		for(s in shaderAnims)
-			s.vecPool = vecPool;
-	}
-
-	override function onRemove() {
-		super.onRemove();
-		if(objAnims != null)
-			for(obj in objAnims)
-				obj.obj.remove();
-		if(emitters != null)
-			for(emitter in emitters)
-				emitter.reset();
-	}
-
-	public function setRandSeed(seed: Int) {
-		randSeed = seed;
-		random.init(seed);
-		if(emitters != null)
-			for(em in emitters)
-				em.setRandSeed(randSeed);
-	}
-
-	static var tmpSphere = new h3d.col.Sphere();
-	override function syncRec(ctx:h3d.scene.RenderContext) {
-		var changed = posChanged;
-		if( changed ) calcAbsPos();
-
-		if(enableCulling && !syncedOnce) {
-			culled = true;
-			var pos = getAbsPos().getPosition();
-			tmpSphere.load(pos.x, pos.y, pos.z, cullingRadius);
-			if(!ctx.camera.frustum.hasSphere(tmpSphere))
-				return;
-
-			if(cullingDistance > 0) {
-				var distSq = ctx.camera.pos.distanceSq(pos);
-				if(distSq > cullingDistance * cullingDistance)
-					return;
-			}
-			culled = false;
-		}
-
-		super.syncRec(ctx);
-		syncedOnce = true;
-	}
-
-	override function sync( ctx : h3d.scene.RenderContext ) {
-		if(emitters != null)
-			for(emitter in emitters)
-				emitter.setParticleVibility(ctx.visibleFlag);
-
-		if (additionLoopDuration > 0 && startLoop >= 0) {
-			if (totalTime > startLoop) {
-				var timeLeft = endLoop + additionLoopDuration - totalTime;
-				if (timeLeft > 0) {
-					this.localTime = startLoop + ((totalTime - startLoop) % (endLoop - startLoop));
-				} else {
-					this.localTime = endLoop - timeLeft;
-				}
-			}
-		}
-
-		if(playSpeed > 0) {
-			var curTime = localTime;
-			if( ctx.visibleFlag || alwaysSync ) setTime(curTime);
-			localTime += ctx.elapsedTime * playSpeed;
-			totalTime += ctx.elapsedTime;
-			if( duration > 0 && curTime < duration && localTime >= duration) {
-				localTime = duration;
-				if( onEnd != null )
-					onEnd();
-			}
-		}
-	}
-
-	static var tempMat = new h3d.Matrix();
-	static var tempTransform = new h3d.Matrix();
-	static var tempVec = new h3d.Vector();
-	public function setTime( time : Float ) {
-		this.localTime = time;
-		vecPool.begin();
-		if(objAnims != null) {
-			for(anim in objAnims) {
-				if(anim.scale != null || anim.rotation != null || anim.position != null) {
-					var m = tempMat;
-					if(anim.scale != null) {
-						var scale = evaluator.getVector(anim.scale, time, tempVec);
-						m.initScale(scale.x, scale.y, scale.z);
-					}
-					else
-						m.identity();
-
-					if(anim.rotation != null) {
-						var rotation = evaluator.getVector(anim.rotation, time, tempVec);
-						rotation.scale3(Math.PI / 180.0);
-						m.rotate(rotation.x, rotation.y, rotation.z);
-					}
-
-					var baseMat = anim.elt.getTransform(tempTransform);
-					var offset = baseMat.getPosition(tempVec);
-					baseMat.tx = baseMat.ty = baseMat.tz = 0.0;  // Ignore
-					m.multiply(baseMat, m);
-					m.translate(offset.x, offset.y, offset.z);
-
-					if(anim.position != null) {
-						var pos = evaluator.getVector(anim.position, time, tempVec);
-						m.translate(pos.x, pos.y, pos.z);
-					}
-
-					anim.obj.setTransform(m);
-				}
-
-				if(anim.visibility != null)
-					anim.obj.visible = anim.elt.visible && evaluator.getFloat(anim.visibility, time) > 0.5;
-
-				if(anim.color != null) {
-					switch(anim.color) {
-						case VCurve(a):
-							for(mat in anim.obj.getMaterials())
-								mat.color.a = evaluator.getFloat(anim.color, time);
-						default:
-							for(mat in anim.obj.getMaterials())
-								mat.color.load(evaluator.getVector(anim.color, time, tempVec));
-					}
-				}
-				Event.updateEvents(anim.events, time, prevTime);
-
-				if( anim.additionalProperies != null ) {
-					switch(anim.additionalProperies) {
-						case None :
-						case PointLight( color, power, size, range ) :
-							var l = Std.downcast(anim.obj, h3d.scene.pbr.PointLight);
-							if( l != null ) {
-								if( color != null ) l.color = evaluator.getVector(color, time, tempVec);
-								if( power != null ) l.power = evaluator.getFloat(power, time);
-								if( size != null ) l.size = evaluator.getFloat(size, time);
-								if( range != null ) l.range = evaluator.getFloat(range, time);
-							}
-						case DirLight(color, power):
-							var l = Std.downcast(anim.obj, h3d.scene.pbr.DirLight);
-							if( l != null ) {
-								if( color != null ) l.color = evaluator.getVector(color, time, tempVec);
-								if( power != null ) l.power = evaluator.getFloat(power, time);
-							}
-						case SpotLight(color, power, range, angle, fallOff):
-							var l = Std.downcast(anim.obj, h3d.scene.pbr.SpotLight);
-							if( l != null ) {
-								if( color != null ) l.color = evaluator.getVector(color, time, tempVec);
-								if( power != null ) l.power = evaluator.getFloat(power, time);
-								if( range != null ) l.range = evaluator.getFloat(range, time);
-								if( angle != null ) l.angle = evaluator.getFloat(angle, time);
-								if( fallOff != null ) l.fallOff = evaluator.getFloat(fallOff, time);
-							}
-					}
-				}
-			}
-		}
-
-		if(shaderAnims != null)
-			for(anim in shaderAnims)
-				anim.setTime(time);
-
-		if(emitters != null) {
-			for(em in emitters) {
-				if (prevTime > localTime) {
-					@:privateAccess em.curTime = time;
-					#if editor
-					em.reset();
-					#end
-				}
-				if(em.visible)
-					em.setTime(time);
-			}
-		}
-
-		Event.updateEvents(events, time, prevTime);
-
-		if(script != null)
-			script.update();
-
-		this.prevTime = localTime;
-	}
-
-	function initEvents(elt: PrefabElement, ctx: Context) {
-		var childEvents = [for(c in elt.children) if(c.to(Event) != null) c.to(Event)];
-		var ret = null;
-		for(evt in childEvents) {
-			var eventObj = evt.prepare(ctx);
-			if(eventObj == null) continue;
-			if(ret == null) ret = [];
-			ret.push(eventObj);
-		}
-		return ret;
-	}
-
-	function initObjAnimations(ctx:Context, elt: PrefabElement) {
-		if(Std.downcast(elt, hrt.prefab.fx.Emitter) == null) {
-			// Don't extract animations for children of Emitters
-			for(c in elt.children) {
-				initObjAnimations(ctx, c);
-			}
-		}
-
-		var obj3d = elt.to(hrt.prefab.Object3D);
-		if(obj3d == null)
-			return;
-
-		// TODO: Support references?
-		var objCtx = ctx.shared.contexts.get(elt);
-		if(objCtx == null || objCtx.local3d == null)
-			return;
-
-		var anyFound = false;
-
-		function makeVal(name, def) : Value {
-			var c = Curve.getCurve(elt, name);
-			if(c != null)
-				anyFound = true;
-			return c != null ? VCurve(c) : def;
-		}
-
-		function makeVector(name: String, defVal: Float, uniform: Bool=true, scale: Float=1.0) : Value {
-			var curves = Curve.getCurves(elt, name);
-			if(curves == null || curves.length == 0)
-				return null;
-
-			anyFound = true;
-
-			if(uniform && curves.length == 1 && curves[0].name == name)
-				return scale != 1.0 ? VCurveScale(curves[0], scale) : VCurve(curves[0]);
-
-			return Curve.getVectorValue(curves, defVal, scale);
-		}
-
-		function makeColor(name: String) {
-			var curves = Curve.getCurves(elt, name);
-			if(curves == null || curves.length == 0)
-				return null;
-
-			anyFound = true;
-			return Curve.getColorValue(curves);
-		}
-
-		var ap : AdditionalProperies = null;
-		if( Std.is(objCtx.local3d, h3d.scene.pbr.PointLight)) {
-			ap = PointLight(makeColor("color"), makeVal("power", null), makeVal("size", null), makeVal("range", null) );
-		}
-		else if( Std.is(objCtx.local3d, h3d.scene.pbr.SpotLight)) {
-			ap = SpotLight(makeColor("color"), makeVal("power", null), makeVal("range", null), makeVal("angle", null), makeVal("fallOff", null) );
-		}
-		else if( Std.is(objCtx.local3d, h3d.scene.pbr.DirLight)) {
-			ap = DirLight(makeColor("color"), makeVal("power", null));
-		}
-
-		var anim : ObjectAnimation = {
-			elt: obj3d,
-			obj: objCtx.local3d,
-			events: null,
-			position: makeVector("position", 0.0),
-			scale: makeVector("scale", 1.0, true),
-			rotation: makeVector("rotation", 0.0, 360.0),
-			color: makeColor("color"),
-			visibility: makeVal("visibility", null),
-			additionalProperies: ap,
-		};
-
-		anim.events = initEvents(elt, objCtx);
-		if(anim.events != null)
-			anyFound = true;
-
-		if(anyFound) {
-			if(objAnims == null) objAnims = [];
-			objAnims.push(anim);
-		}
-	}
-
-	function initEmitters(ctx: Context, elt: PrefabElement) {
-		var em = Std.downcast(elt, hrt.prefab.fx.Emitter);
-		if(em != null)  {
-			for(emCtx in ctx.shared.getContexts(elt)) {
-				if(emCtx.local3d == null) continue;
-				if(emitters == null) emitters = [];
-				var emobj : hrt.prefab.fx.Emitter.EmitterObject = cast emCtx.local3d;
-				emobj.setRandSeed(randSeed);
-				emitters.push(emobj);
-			}
-		}
-		else {
-			for(c in elt.children) {
-				initEmitters(ctx, c);
-			}
-		}
-	}
-
-	function initConstraints( ctx : Context, elt : PrefabElement ){
-		var co = Std.downcast(elt, hrt.prefab.l3d.Constraint);
-		if(co != null) {
-			if(constraints == null) constraints = [];
-			constraints.push(co);
-		}
-		else
-			for(c in elt.children)
-				initConstraints(ctx, c);
-	}
-
-	public function resolveConstraints( caster : h3d.scene.Object ) {
-		for( co in constraints ) {
-			if( !co.enabled )
-		 		continue;
-
-			var objectName = co.object.split(".").pop();
-			var targetName = co.target.split(".").pop();
-
-			var isInFX = co.object.split(".")[1] == "FXRoot";
-			var srcObj = objectName == "FXRoot" ? this : isInFX ? this.getObjectByName(objectName) : caster.getObjectByName(objectName);
-			var targetObj = caster.getObjectByName(targetName);
-			if( srcObj != null && targetObj != null ) {
-				srcObj.follow = targetObj;
-				srcObj.followPositionOnly = co.positionOnly;
-			}
-		}
-	}
-}
-
-class FX extends BaseFX {
-
-	public function new() {
-		super();
-		type = "fx";
-		cullingRadius = 3.0;
-	}
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		obj.cullingRadius = cullingRadius;
-		if( scriptCode != "" ) obj.scriptCode = scriptCode;
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		if(obj.cullingRadius != null)
-			cullingRadius = obj.cullingRadius;
-		scriptCode = obj.scriptCode;
-	}
-
-	override function make( ctx : Context ) : Context {
-		ctx = ctx.clone(this);
-		var fxanim = createInstance(ctx.local3d);
-		fxanim.duration = duration;
-		fxanim.cullingRadius = cullingRadius;
-		ctx.local3d = fxanim;
-		var fromRef = ctx.shared.parent != null;
-		#if editor
-		// only play if we are as a reference
-		if( fromRef ) fxanim.playSpeed = 1.0;
-		#else
-		fxanim.playSpeed = 1.0;
-		#end
-
-		var useFXRoot = #if editor fromRef #else true #end;
-		var root = getFXRoot(ctx, this);
-		if(useFXRoot && root != null){
-			root.make(ctx);
-		}
-		else
-			super.make(ctx);
-		fxanim.init(ctx, this, root);
-
-		if(scriptCode != null && scriptCode != ""){
-			var parser = new FXScriptParser();
-			fxanim.script = parser.createFXScript(scriptCode, fxanim);
-			fxanim.script.init();
-		}
-
-		return ctx;
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, null);
-		var fxanim = Std.downcast(ctx.local3d, FXAnimation);
-		fxanim.duration = duration;
-		fxanim.cullingRadius = cullingRadius;
-	}
-
-	function createInstance(parent: h3d.scene.Object) : FXAnimation {
-		return new FXAnimation(parent);
-	}
-
-	#if editor
-
-	override function refreshObjectAnims(ctx: Context) {
-		var fxanim = Std.downcast(ctx.local3d, FXAnimation);
-		fxanim.objAnims = null;
-		fxanim.initObjAnimations(ctx, this);
-	}
-
-	override function edit( ctx : EditContext ) {
-		var props = new hide.Element('
-			<div class="group" name="FX Scene">
-				<dl>
-					<dt>Duration</dt><dd><input type="number" value="0" field="duration"/></dd>
-					<dt>Culling radius</dt><dd><input type="number" field="cullingRadius"/></dd>
-				</dl>
-			</div>');
-		ctx.properties.add(props, this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "cube", name : "FX", allowParent: _ -> false};
-	}
-	#end
-
-	static var _ = Library.register("fx", FX, "fx");
-}

+ 0 - 300
hrt/prefab/fx/FX2D.hx

@@ -1,300 +0,0 @@
-package hrt.prefab.fx;
-import hrt.prefab.Curve;
-import hrt.prefab.Prefab as PrefabElement;
-import hrt.prefab.fx.BaseFX.ObjectAnimation;
-import hrt.prefab.fx.BaseFX.ShaderAnimation;
-
-@:allow(hrt.prefab.fx.FX2D)
-class FX2DAnimation extends h2d.Object {
-
-	public var prefab : hrt.prefab.Prefab;
-	public var onEnd : Void -> Void;
-
-	public var playSpeed : Float;
-	public var localTime : Float = 0.0;
-	var prevTime = -1.0;
-	public var startLoop : Float = 0.0;
-	public var duration : Float;
-
-	public var loop : Bool;
-	public var objects: Array<ObjectAnimation> = [];
-	public var shaderAnims : Array<ShaderAnimation> = [];
-	public var emitters : Array<hrt.prefab.l2d.Particle2D.Particles>;
-	public var events: Array<hrt.prefab.fx.Event.EventInstance>;
-
-	var evaluator : Evaluator;
-	var random : hxd.Rand;
-
-	public function new(?parent) {
-		super(parent);
-		random = new hxd.Rand(Std.random(0xFFFFFF));
-		evaluator = new Evaluator(random);
-		name = "FX2DAnimation";
-		setTime(0);
-	}
-
-	public function setRandSeed(seed: Int) {
-		random.init(seed);
-	}
-
-	function init(ctx: Context, def: FX2D) {
-		initEmitters(ctx, def);
-		if (def.children.length == 1 && def.children[0].name == "FXRoot")
-			events = initEvents(def.children[0], ctx);
-		else
-			events = initEvents(def, ctx);
-	}
-
-	function initEmitters(ctx: Context, elt: PrefabElement) {
-		var em = Std.downcast(elt, hrt.prefab.l2d.Particle2D);
-		if(em != null)  {
-			for(emCtx in ctx.shared.getContexts(elt)) {
-				if(emCtx.local2d == null) continue;
-				if(emitters == null) emitters = [];
-				var emobj : hrt.prefab.l2d.Particle2D.Particles = cast emCtx.local2d;
-				emitters.push(emobj);
-			}
-		}
-		else {
-			for(c in elt.children) {
-				initEmitters(ctx, c);
-			}
-		}
-	}
-
-	function initEvents(elt: PrefabElement, ctx: Context) {
-		var childEvents = [for(c in elt.children) if(c.to(Event) != null) c.to(Event)];
-		var ret = null;
-		for(evt in childEvents) {
-			var eventObj = evt.prepare(ctx);
-			if(eventObj == null) continue;
-			if(ret == null) ret = [];
-			ret.push(eventObj);
-		}
-		return ret;
-	}
-
-
-	public function setTime( time : Float ) {
-
-		this.localTime = time;
-
-		for(anim in objects) {
-			if(anim.scale != null) {
-				var scale = evaluator.getVector(anim.scale, time);
-				anim.obj2d.scaleX = scale.x;
-				anim.obj2d.scaleY = scale.y;
-			}
-
-			if(anim.rotation != null) {
-				var rotation = evaluator.getVector(anim.rotation, time);
-				anim.obj2d.rotation = rotation.x * (Math.PI / 180.0);
-			}
-
-			if(anim.position != null) {
-				var pos = evaluator.getVector(anim.position, time);
-				anim.obj2d.x = anim.elt2d.x + pos.x;
-				anim.obj2d.y = anim.elt2d.y + pos.y;
-			}
-
-			if(anim.visibility != null)
-				anim.obj2d.visible = anim.elt2d.visible && evaluator.getFloat(anim.visibility, time) > 0.5;
-
-			if(anim.color != null) {
-				switch(anim.color) {
-					case VCurve(a):
-						anim.obj2d.alpha = evaluator.getFloat(anim.color, time);
-					default:
-						var drawable = Std.downcast(anim.obj2d, h2d.Drawable);
-						if (drawable != null)
-							drawable.color = evaluator.getVector(anim.color, time);
-				}
-			}
-
-			var atlas : Dynamic = Std.downcast(anim.elt2d, hrt.prefab.l2d.Atlas);
-			if (atlas == null) {
-				atlas = Std.downcast(anim.elt2d, hrt.prefab.l2d.Anim2D);
-			}
-			if (atlas != null) {
-				@:privateAccess if (!atlas.loop) {
-					var t = time - atlas.delayStart;
-					if (t < 0) {
-						(cast anim.obj2d : h2d.Anim).curFrame = 0;
-					} else {
-						var nbFrames = Math.floor(t*atlas.fpsAnimation);
-						(cast anim.obj2d : h2d.Anim).curFrame = Math.min(nbFrames, (cast anim.obj2d : h2d.Anim).frames.length-1);
-					}
-				}
-			}
-		}
-
-		for(anim in shaderAnims) {
-			anim.setTime(time);
-		}
-		if (emitters != null) {
-			for(em in emitters) {
-				if(em.visible)
-					em.setTime(time);
-			}
-		}
-
-		Event.updateEvents(events, time, prevTime);
-
-		this.prevTime = localTime;
-	}
-}
-
-class FX2D extends BaseFX {
-
-	@:s var loop : Bool = false;
-	@:s var startLoop : Float = 0.0;
-
-	public function new() {
-		super();
-		type = "fx2d";
-	}
-
-	function getObjAnimations(ctx:Context, elt: PrefabElement, anims: Array<ObjectAnimation>) {
-		for(c in elt.children) {
-			getObjAnimations(ctx, c, anims);
-		}
-
-		var obj2d = elt.to(hrt.prefab.Object2D);
-		if(obj2d == null)
-			return;
-
-		// TODO: Support references?
-		var objCtx = ctx.shared.contexts.get(elt);
-		if(objCtx == null || objCtx.local2d == null)
-			return;
-
-		var anyFound = false;
-
-		function makeVal(name, def) : Value {
-			var c = Curve.getCurve(elt, name);
-			if(c != null)
-				anyFound = true;
-			return c != null ? VCurve(c) : def;
-		}
-
-		function makeVector(name: String, defVal: Float, uniform: Bool=true, scale: Float=1.0) : Value {
-			var curves = Curve.getCurves(elt, name);
-			if(curves == null || curves.length == 0)
-				return null;
-
-			anyFound = true;
-
-			if(uniform && curves.length == 1 && curves[0].name == name)
-				return scale != 1.0 ? VCurveScale(curves[0], scale) : VCurve(curves[0]);
-
-			return Curve.getVectorValue(curves, defVal, scale);
-		}
-
-		function makeColor(name: String) {
-			var curves = Curve.getCurves(elt, name);
-			if(curves == null || curves.length == 0)
-				return null;
-
-			anyFound = true;
-			return Curve.getColorValue(curves);
-		}
-
-		var anim : ObjectAnimation = {
-			elt2d: obj2d,
-			obj2d: objCtx.local2d,
-			events: null,
-			position: makeVector("position", 0.0),
-			scale: makeVector("scale", 1.0, true),
-			rotation: makeVector("rotation", 0.0, 360.0),
-			color: makeColor("color"),
-			visibility: makeVal("visibility", null),
-		};
-
-		for(evt in elt.getAll(Event)) {
-			var eventObj = evt.prepare(objCtx);
-			if(eventObj == null) continue;
-			if(anim.events == null) anim.events = [];
-			anim.events.push(eventObj);
-			anyFound = true;
-		}
-
-		if (Std.is(elt, hrt.prefab.l2d.Anim2D) || Std.is(elt, hrt.prefab.l2d.Atlas))
-			anyFound = true;
-
-		if(anyFound)
-			anims.push(anim);
-	}
-
-	override function make( ctx : Context ) : Context {
-		ctx = ctx.clone(this);
-		var fxanim = createInstance(ctx.local2d);
-		fxanim.duration = duration;
-		fxanim.loop = loop;
-		fxanim.startLoop = startLoop;
-		ctx.local2d = fxanim;
-		ctx.local3d = null;
-		fxanim.playSpeed = 1.0;
-
-		#if editor
-		super.make(ctx);
-		#else
-		var root = getFXRoot(ctx, this);
-		if( root != null ) {
-			for( c in root.children )
-				makeChildren(ctx, c);
-		} else
-			super.make(ctx);
-		#end
-		fxanim.init(ctx, this);
-
-		getObjAnimations(ctx, this, fxanim.objects);
-		BaseFX.getShaderAnims(ctx, this, fxanim.shaderAnims);
-
-		return ctx;
-	}
-
-	public function getTargetShader2D( ctx : Context, name : String ) {
-		return ctx.local2d;
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, null);
-		var fxanim = Std.downcast(ctx.local2d, FX2DAnimation);
-		fxanim.duration = duration;
-		fxanim.loop = loop;
-	}
-
-	function createInstance(parent: h2d.Object) : FX2DAnimation {
-		var inst = new FX2DAnimation(parent);
-		inst.prefab = this;
-		return inst;
-	}
-
-	#if editor
-	override function refreshObjectAnims(ctx: Context) {
-		var fxanim = Std.downcast(ctx.local2d, FX2DAnimation);
-		fxanim.objects = [];
-		getObjAnimations(ctx, this, fxanim.objects);
-	}
-
-	override function edit( ctx : EditContext ) {
-		var props = new hide.Element('
-			<div class="group" name="FX2D Scene">
-				<dl>
-					<dt>Duration</dt><dd><input type="number" value="0" field="duration"/></dd>
-					<dt>Loop</dt><dd><input type="checkbox" field="loop"/></dd>
-					<dt>Start loop</dt><dd><input type="range" min="0" max="5" field="startLoop"/></dd>
-				</dl>
-			</div>');
-		ctx.properties.add(props, this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "cube", name : "FX2D", allowParent: _ -> false};
-	}
-	#end
-
-	static var _ = Library.register("fx2d", FX2D, "fx2d");
-}

+ 0 - 216
hrt/prefab/fx/FXScript.hx

@@ -1,216 +0,0 @@
-package hrt.prefab.fx;
-
-import hrt.prefab.fx.FX.FXAnimation;
-
-typedef Argument = { name : String, ?value : FxAst };
-
-enum FxAst {
-	Block( a : Array<FxAst> );
-	Var( get : Void -> Float );
-	Const( v : Float );
-	Set( set : Float -> Void, a : FxAst );
-	Op( a : FxAst, b : FxAst, op : Float -> Float -> Float );
-	Unop( a : FxAst, op : Float -> Float );
-	If( cond : FxAst, eif : FxAst, eelse : FxAst );
-	Function( args : Array<Argument>, a : FxAst, name : String );
-	Call( name : String, args : Array<FxAst> );
-}
-
-enum FXVar {
-	Float( value : Float );
-	Int( value : Int );
-	Bool( value : Bool );
-}
-
-// UI
-enum ParamOption {
-	Range( min : Float, max : Float );
-}
-enum FXParam {
-	Float( name : String, value : Float, options : Array<ParamOption> );
-	Int( name : String, value : Int, options : Array<ParamOption> );
-	Bool( name : String, value : Bool, options : Array<ParamOption> );
-}
-
-class FXScript {
-
-	public var myVars : Map<String, FXVar> = [];
-	public var params : Array<FXParam> = [];
-
-	var fx : FXAnimation;
-	var ast : FxAst;
-	var initAst : FxAst;
-	var updateAst : FxAst;
-
-	public function new( fx : FXAnimation ){
-		this.fx = fx;
-	}
-
-	public function getGetter( p : String ) : Void -> Float {
-		var names = p.split('.');
-		var i = 0;
-		var root : h3d.scene.Object = fx;
-		#if editor
-		var fxRoot = fx.getObjectByName("FXRoot");
-		if( fxRoot != null ) root = fxRoot;
-		#end
-		var curObj : h3d.scene.Object = root.getObjectByName(names[i++]);
-		while(curObj != null && i < p.length) {
-			var next = curObj.getObjectByName(names[i++]);
-			next != null ? curObj = next : break;
-		}
-		if( curObj == null )
-			return () -> 0.0;
-		var field : String = "";
-		for( index in i - 1 ... i )
-			field += names[index];
-
-		return switch( field ) {
-			case "x": function() { return curObj.x; };
-			case "y": function() { return curObj.y; };
-			case "z": function() { return curObj.z; };
-			case "scaleX": function() { return curObj.scaleX; };
-			case "scaleY": function() { return curObj.scaleY; };
-			case "scaleZ": function() { return curObj.scaleZ; };
-			case "visible": function() { return curObj.visible ? 1.0 : 0.0; };
-			case "rotationX": function() {
-				return curObj.getRotationQuat().toEuler().x; }
-			case "rotationY": function() {
-				return curObj.getRotationQuat().toEuler().y; }
-			case "rotationZ": function() {
-				return curObj.getRotationQuat().toEuler().z; }
-			default: return function() {
-				if(Reflect.hasField(curObj, field)) {
-					var p = Reflect.getProperty(curObj, field);
-					return cast(p, Float);
-				}
-				else return 0.0;};
-		}
-	}
-
-	public function getSetter( p : String ) : Float -> Void {
-		var names = p.split('.');
-		var i = 0;
-		var root : h3d.scene.Object = fx;
-		#if editor
-		var fxRoot = fx.getObjectByName("FXRoot");
-		if( fxRoot != null ) root = fxRoot;
-		#end
-		var curObj : h3d.scene.Object = root.getObjectByName(names[i++]);
-		while(curObj != null && i < p.length) {
-			var next = curObj.getObjectByName(names[i++]);
-			next != null ? curObj = next : break;
-		}
-		if( curObj == null )
-			return (v) -> {};
-		var field : String = "";
-		for( index in i - 1 ... i )
-			field += names[index];
-
-		return switch( field ) {
-			case "x": function(v) { curObj.x = v; };
-			case "y": function(v) { curObj.y = v; };
-			case "z": function(v) { curObj.z = v; };
-			case "scaleX": function(v) { curObj.scaleX = v; };
-			case "scaleY": function(v) { curObj.scaleY = v; };
-			case "scaleZ": function(v) { curObj.scaleZ = v; };
-			case "visible": function(v) { curObj.visible = v > 0; };
-			case "rotationX": function(v) {
-				var euler = curObj.getRotationQuat().toEuler();
-				curObj.setRotation(v, euler.y, euler.z); };
-			case "rotationY": function(v) {
-				var euler = curObj.getRotationQuat().toEuler();
-				curObj.setRotation(euler.x, v, euler.z); };
-			case "rotationZ": function(v) {
-				var euler = curObj.getRotationQuat().toEuler();
-				curObj.setRotation(euler.x, euler.y, v); };
-			default: {
-				if(Reflect.hasField(curObj, field)) {
-					var cur = Reflect.field(curObj, field);
-					if(Std.is(cur, Value))
-						(v) -> Reflect.setProperty(curObj, field, Value.VConst(v));
-					else
-						(v) -> Reflect.setProperty(curObj, field, v);
-				}
-				else (v) -> {};
-			};
-		}
-	}
-
-	public function getVar( n : String ) : Float {
-		if( n == "time" )  // TODO: support @global like hxsl
-			return fx.localTime;
-		if( !myVars.exists(n))
-			return 0.0;
-		if( myVars[n] == null )
-			return 0.0;
-		return switch myVars[n] {
-			case Float(value): value;
-			case Int(value): value;
-			case Bool(value): value ? 1.0 : 0.0;
-			default : 0.0;
-		}
-	}
-
-	public function setVar( n : String, v : Float ) : Float {
-		if( !myVars.exists(n) )
-			return 0.0;
-		switch myVars[n]{
-			case Float(value): myVars.set(n, FXVar.Float(v));
-			case Int(value): myVars.set(n, FXVar.Int(Std.int(v)));
-			case Bool(value):  myVars.set(n, FXVar.Bool( v > 0 ));
-		}
-		return switch myVars[n]{
-			case Float(value): value;
-			case Int(value): value;
-			case Bool(value): value ? 1.0 : 0.0;
-		}
-	}
-
-	function call( f : String, args : Array<FxAst>) : Float {
-		switch( f ) {
-			case "rand": return hxd.Math.random();
-			case "mix": return hxd.Math.lerp(eval(args[0]), eval(args[1]), eval(args[2]));
-			case "clamp": return hxd.Math.clamp(eval(args[0]), eval(args[1]), eval(args[2]));
-			default: return 0.0;
-		}
-	}
-
-	function eval(ast : FxAst) : Float {
-		if(ast == null) return 0.0;
-		switch (ast) {
-			case Block(a):
-				for(ast in a)
-					eval(ast);
-				return 0.0;
-			case Call(a, args):
-				return call(a, args);
-			case Function(args, a, name):
-				return 0.0; // TO DO
-			case Var(get):
-				return get();
-			case Const(v):
-				return v;
-			case Set(set, a):
-				var v = eval(a);
-				set(v);
-				return v;
-			case Op(a, b, op):
-				var va = eval(a);
-				var vb = eval(b);
-				return op(va,vb);
-			case Unop(a, op):
-				return op(eval(a));
-			case If(cond, eif, eelse):
-				return eval(cond) != 0 ? eval(eif) : eval(eelse);
-		}
-	}
-
-	public function init() {
-		eval(initAst);
-	}
-
-	public function update() {
-		eval(updateAst);
-	}
-}

+ 0 - 476
hrt/prefab/fx/FXScriptParser.hx

@@ -1,476 +0,0 @@
-package hrt.prefab.fx;
-import hrt.prefab.fx.FXScript;
-
-@:access(hide.view.FXEditor)
-@:access(hrt.prefab.fx.FXScript)
-class FXScriptParser {
-
-	public var firstParse = false;
-
-	public function new(){
-	}
-
-	#if !hscript
-
-	public function createFXScript( s : String, fx : hrt.prefab.fx.FX.FXAnimation ) : FXScript {
-		throw "FX Scripts requires -lib hscript";
-	}
-
-	#else
-
-	inline function getExpr( e : hscript.Expr ) {
-		#if hscriptPos
-		return e.e;
-		#else
-		return e;
-		#end
-	}
-
-	public function createFXScript( s : String, fx : hrt.prefab.fx.FX.FXAnimation ) : FXScript {
-		var parser = new hscript.Parser();
-		parser.allowMetadata = true;
-		parser.allowTypes = true;
-		parser.allowJSON = true;
-		var expr : hscript.Expr = null;
-		var script = new hrt.prefab.fx.FXScript(fx);
-
-		function parse( expr : hscript.Expr ) {
-			if( expr == null ) return;
-			switch(getExpr(expr)){
-				case EMeta(name, args, e):
-					parse(e);
-					switch(name){
-						case "param" :
-							script.params.push(createFXParam(e));
-					}
-
-				case EBlock(e):
-					for(expr in e)
-						parse(expr);
-
-				case EVar(n, t, e):
-					script.myVars.set(n, createFXVar(expr));
-
-				default:
-			}
-		}
-		try {
-			expr = parser.parseString(s, "");
-		} catch( e : hscript.Expr.Error ) { }
-		parse(expr);
-
-		function convert( expr : hscript.Expr ) : FxAst {
-			if( expr == null ) return null;
-
-			function getPath( expr : hscript.Expr ) : String {
-					return switch(getExpr(expr)){
-						case EField(e,f): getPath(e) + "." + f;
-						case EIdent(v): v;
-						default: null;
-					}
-				}
-
-			function getSetField( expr : hscript.Expr ){
-				return script.getSetter(getPath(expr));
-			}
-
-			function getGetField( expr : hscript.Expr ){
-				return script.getGetter(getPath(expr));
-			}
-
-			switch(getExpr(expr)){
-
-				case EBlock(e):
-					return Block( [for(expr in e) convert(expr)] );
-
-				case ECall( e, params ):
-					var name = switch(getExpr(e)) {
-						case EIdent(v): v;
-						default: null;
-					}
-					return Call( name, [for(a in params) convert(a)]);
-
-				case EFunction(args, e, name, ret):
-					switch(name){
-						case "update": script.updateAst = convert(e);
-						case "init": script.initAst = convert(e);
-					}
-					return null;
-
-				case EVar(n, t, e):
-					if(e != null ) return Set(function(v){ script.setVar(n, v); }, convert(e));
-					else return Var( function(){ return script.getVar(n); });
-
-				case EField(e, f):
-					return Var( getGetField(expr) );
-
-				case EIf( cond, e1, e2):
-					return If(convert(cond), convert(e1), convert(e2));
-
-				case EIdent(v):
-					return switch(v) {
-								case "true": Const(1);
-								case "false": Const(0);
-								default: Var( function(){ return script.getVar(v); });
-							}
-
-				case EConst( c ):
-					return switch(c) {
-						case CInt(v): Const(v);
-						case CFloat(f): Const(f);
-						default: null;
-					}
-
-				case EBinop(op, e1, e2):
-					switch(op) {
-						case "%": return Op( convert(e1), convert(e2), function(a,b) { return a % b; });
-						case "*": return Op( convert(e1), convert(e2), function(a,b) { return a * b; });
-						case "/": return Op( convert(e1), convert(e2), function(a,b) { return a / b; });
-						case "+": return Op( convert(e1), convert(e2), function(a,b) { return a + b; });
-						case "-": return Op( convert(e1), convert(e2), function(a,b) { return a - b; });
-						case "=": 	switch(getExpr(e1)){
-											case EIdent(v): return Set(function(val){ script.setVar(v, val); }, convert(e2));
-											case EField(e,f): return Set( getSetField(e1), convert(e2));
-											default: return null;
-										}
-						case "+=":  switch(getExpr(e1)){
-										case EIdent(v): return Set(function(val){ script.setVar(v, val); }, Op( convert(e1), convert(e2), function(a,b) { return a + b; }));
-										case EField(e,f): return Set( getSetField(e1), Op( convert(e1), convert(e2), function(a,b) { return a + b; }));
-										default: return null;
-									}
-
-						case "-=":	switch(getExpr(e1)){
-										case EIdent(v): return Set(function(val){ script.setVar(v, val); }, Op( convert(e1), convert(e2), function(a,b) { return a - b; }));
-										case EField(e,f): return Set( getSetField(e1), Op( convert(e1), convert(e2), function(a,b) { return a - b; }));
-										default: return null;
-									}
-						case "==": return Op( convert(e1), convert(e2), function(a,b) { return a == b ? 1.0 : 0.0; });
-						case "!=": return Op( convert(e1), convert(e2), function(a,b) { return a != b ? 1.0 : 0.0; });
-						case ">": return Op( convert(e1), convert(e2), function(a,b) { return a > b ? 1.0 : 0.0; });
-						case "<": return Op( convert(e1), convert(e2), function(a,b) { return a < b ? 1.0 : 0.0; });
-						case ">=": return Op( convert(e1), convert(e2), function(a,b) { return a >= b ? 1.0 : 0.0; });
-						case "<=": return Op( convert(e1), convert(e2), function(a,b) { return a <= b ? 1.0 : 0.0; });
-						default: return null;
-					}
-
-				case EUnop(op, prefix, e):
-					var expr = e;
-					switch(getExpr(e)){
-						case EIdent(v):
-							return switch(op){
-								case "++": Set( function(val){ script.setVar(v, val); }, Unop(convert(e), function(a){ return prefix ? ++a : a++; }));
-								case "--": Set( function(val){ script.setVar(v, val); }, Unop(convert(e), function(a){ return prefix ? --a : a--; }));
-								case "-": Unop( convert(e), function(a){ return -a;});
-								default: null;
-							}
-						case EField(e,f):
-							return switch(op){
-								case "++": Set( getSetField(expr), Unop(convert(e), function(a){ return prefix ? ++a : a++; }));
-								case "--": Set( getSetField(expr), Unop(convert(e), function(a){ return prefix ? --a : a--; }));
-								case "-": Unop( convert(e), function(a){ return -a;});
-								default : null;
-							}
-						case ECall( e, params ):
-							return switch(op){
-								case "-": Unop( convert(e), function(a){ return -a;});
-								default : null;
-							}
-						default: return null;
-					}
-				case EParent(e):
-					return convert(e);
-				case EObject(fl):
-					for(elem in fl) trace(elem.name);
-					return Block( [for(elem in fl) convert(elem.e)] );
-				default:
-					return null;
-			}
-		}
-		script.ast = convert(expr);
-		return script;
-	}
-
-	function createFXVar( expr : hscript.Expr ) {
-		function parse(expr : hscript.Expr) : FXVar {
-			return switch(getExpr(expr)){
-				case EFunction(args, e, name, ret):
-					return parse(e);
-				case EMeta(name, args, e):
-					return parse(e);
-				case EVar(n, t, e):
-					var r : FXVar = null;
-					if(t != null){
-						switch(t){
-							case CTPath(path, params):
-								switch(path){
-									case ["Int"]: r = FXVar.Int(0);
-									case ["Float"]: r = FXVar.Float(0.0);
-									case ["Bool"]: r = FXVar.Bool(false);
-									default:
-								}
-							default: null;
-						}
-					}
-					if(e != null){
-						switch(getExpr(e)){
-							case EIdent(v):
-								if(r != null){
-									switch(r){
-										case Float(value):
-											switch(v) {
-												case "true": r = FXVar.Float(1.0);
-												case "false": r = FXVar.Float(0.0);
-												default:
-											}
-										case Int(value):
-											switch(v) {
-												case "true": r = FXVar.Int(1);
-												case "false": r = FXVar.Int(0);
-												default:
-											}
-										case Bool(value):
-											switch(v) {
-												case "true": r = FXVar.Bool(true);
-												case "false": r = FXVar.Bool(false);
-												default:
-											}
-									}
-								}else{
-									switch(v) {
-										case "true": r = FXVar.Bool(true);
-										case "false": r = FXVar.Bool(false);
-										default:
-									}
-							}
-							case EConst(c):
-								if(r != null){
-									switch(r){
-										case Float(value):
-											switch(c){
-												case CInt(v): r = FXVar.Float(v);
-												case CFloat(f): r = FXVar.Float(f);
-												default:
-											}
-										case Int(value):
-											switch(c){
-												case CInt(v): r = FXVar.Int(v);
-												case CFloat(f): r = FXVar.Int(Std.int(f));
-												default:
-											}
-										case Bool(value):
-											switch(c){
-												case CInt(v): r = FXVar.Bool(v > 0);
-												case CFloat(f): r = FXVar.Bool(f > 0);
-												default:
-											}
-									}
-								}
-								else{
-									switch(c){
-										case CInt(v): r = FXVar.Int(v);
-										case CFloat(f): r = FXVar.Float(f);
-										default:
-									}
-								}
-							default: null;
-						}
-					}
-					return r;
-
-				default: null;
-			}
-		}
-		return parse(expr);
-	}
-
-	function createFXParam( expr : hscript.Expr ) : FXParam {
-		var options : Array<ParamOption> = [];
-		function parse(expr : hscript.Expr) : FXParam {
-			if( expr == null ) return null;
-			switch(getExpr(expr)){
-				case EFunction(args, e, name, ret):
-					return parse(e);
-				case EMeta(name, args, e):
-					switch(name){
-						case "range":
-						var min = 	switch(getExpr(args[0])){
-										case EConst(c):
-											switch(c){
-												case CInt(v): v;
-												case CFloat(f): f;
-												default: null;
-											}
-										default: null;
-									}
-						var max = 	switch(getExpr(args[1])){
-										case EConst(c):
-											switch(c){
-												case CInt(v): v;
-												case CFloat(f): f;
-												default: null;
-											}
-										default: null;
-									}
-						options.push(Range(min, max));
-						default:
-					}
-					return parse(e);
-
-				case EVar(n, t, e):
-					var r : FXParam = null;
-					if(t != null){
-						switch(t){
-							case CTPath(path, params):
-								switch(path){
-									case ["Int"]: r =  FXParam.Int(n, 0, options);
-									case ["Float"]: r = FXParam.Float(n, 0.0, options);
-									case ["Bool"]: r = FXParam.Bool(n, false, options);
-									default:
-								}
-							default: null;
-						}
-					}
-					if(e != null){
-						switch(getExpr(e)){
-							case EIdent(v):
-								if(r != null){
-									switch(r){
-										case Float(name, value, options):
-											switch(v) {
-												case "true": r = FXParam.Float(n, 1.0, options);
-												case "false": r = FXParam.Float(n, 0.0, options);
-												default:
-											}
-										case Int(name, value, options):
-											switch(v) {
-												case "true": r = FXParam.Int(n, 1, options);
-												case "false": r = FXParam.Int(n, 0, options);
-												default:
-											}
-										case Bool(name, value, options):
-											switch(v) {
-												case "true": r = FXParam.Bool(n, true, options);
-												case "false": r = FXParam.Bool(n, false, options);
-												default:
-											}
-										}
-								}else{
-									switch(v) {
-										case "true": r = FXParam.Bool(n, true, options);
-										case "false": r = FXParam.Bool(n, false, options);
-										default:
-									}
-							}
-							case EConst(c):
-								if(r != null){
-									switch(r){
-										case Float(name, value, options):
-											switch(c){
-												case CInt(v): r = FXParam.Float(n, v, options);
-												case CFloat(f): r = FXParam.Float(n, f, options);
-												default:
-											}
-										case Int(name, value, options):
-											switch(c){
-												case CInt(v): r = FXParam.Int(n, v, options);
-												case CFloat(f): r = FXParam.Int(n, Std.int(f), options);
-												default:
-											}
-										case Bool(name, value, options):
-											switch(c){
-												case CInt(v): r = FXParam.Bool(n, v > 0, options);
-												case CFloat(f): r = FXParam.Bool(n, f > 0, options);
-												default:
-											}
-									}
-								}
-								else{
-									switch(c){
-										case CInt(v): r = FXParam.Int(n, v, options);
-										case CFloat(f): r =  FXParam.Float(n, f, options);
-										default:
-									}
-								}
-							default: null;
-						}
-					}
-					return r;
-
-				default:
-					return null;
-			}
-			return null;
-		}
-		return parse(expr);
-	}
-	#end
-
-	#if editor
-
-	public function generateUI( s : FXScript, editor : hide.view.FXEditor ){
-		var elem = editor.element.find(".fx-scriptParams");
-		elem.empty();
-		if(s == null) return;
-		var root = new Element('<div class="group" name="Params"></div>');
-		for(p in s.params){
-			if(p == null) continue;
-			switch(p){
-				case Float(name, value, options):
-					var sliderMin = 0.0;
-					var sliderMax = 1.0;
-					for(o in options){
-						switch(o){
-							case Range(min, max):
-								sliderMin = min;
-								sliderMax = max;
-							default:
-						}
-					}
-					root.append(createSlider(s, name, sliderMin, sliderMax, 0.1, value));
-				case Int(name, value, options):
-					var sliderMin = 0.0;
-					var sliderMax = 1.0;
-					for(o in options){
-						switch(o){
-							case Range(min, max):
-								sliderMin = min;
-								sliderMax = max;
-							default:
-						}
-					}
-					root.append(createSlider(s, name, sliderMin, sliderMax, 1.0, value));
-				case Bool(name, value, options):
-					root.append(createChekbox(s, name, value));
-			}
-		}
-		elem.append(root);
-	}
-
-	function createSlider( s : FXScript, name : String, min : Float, max : Float, step : Float, defaultVal : Float ) : Element {
-		var root = new Element('<div class="slider"/>');
-		var label = new Element('<label> $name : </label>');
-		var slider = new Element('<input type="range" min="$min" max="$max" step="$step" value="$defaultVal"/>');
-		root.append(label);
-		var range = new hide.comp.Range(root, slider);
-		range.onChange = function(b){
-			s.setVar(name, range.value);
-		}
-		return root;
-	}
-
-	function createChekbox( s : FXScript, name : String, defaultVal : Bool ) : Element {
-		var root = new Element('<div class="checkbox"/>');
-		var label = new Element('<label> $name : </label>');
-		var checkbox = new Element('<input type="checkbox" />');
-		checkbox.prop("checked", defaultVal);
-		checkbox.on("change", function(_) {
-			var checked : Bool = checkbox.prop("checked");
-			s.setVar(name, checked ? 1.0 : 0.0);
-		});
-		root.append(label);
-		root.append(checkbox);
-		return root;
-	}
-
-	#end
-}

+ 0 - 155
hrt/prefab/fx/LookAt.hx

@@ -1,155 +0,0 @@
-package hrt.prefab.fx;
-
-
-@:access(hrt.prefab.fx.LookAt)
-class LookAtObject extends h3d.scene.Object {
-	var target: h3d.scene.Object;
-	var definition: LookAt;
-
-	public function new(parent, def) {
-		super(parent);
-		this.definition = def;
-	}
-
-	static var tmpMat = new h3d.Matrix();
-	static var tmpVec = new h3d.Vector();
-	static var tmpScale = new h3d.Vector();
-	static var deltaVec = new h3d.Vector();
-	static var lookAtPos = new h3d.Vector();
-	static var lockAxis = new h3d.Vector();
-	static var tempQ = new h3d.Quat();
-
-	override function syncRec( ctx ) {
-		posChanged = true;
-		super.syncRec(ctx);
-	}
-
-	override function calcAbsPos() {
-		if(target != null)
-			target.getAbsPos().getPosition(lookAtPos);
-		else {
-			if(getScene() == null || getScene().camera == null) return;
-			lookAtPos.load(getScene().camera.pos);
-			lookAtPos.w = 1;
-		}
-
-		super.calcAbsPos();
-		deltaVec.load(lookAtPos.sub(absPos.getPosition(tmpVec)));
-		if(deltaVec.lengthSq() < 0.001)
-			return;
-
-		if(definition.lockAxis != null)
-			lockAxis.set(definition.lockAxis[0], definition.lockAxis[1], definition.lockAxis[2]);
-		else
-			lockAxis.set();
-
-		if(lockAxis.lengthSq() > 0.001) {
-			tmpMat.load(parent.getAbsPos());
-			tmpMat.invert();
-			lookAtPos.transform(tmpMat);
-			deltaVec.set(lookAtPos.x - x, lookAtPos.y - y, lookAtPos.z - z);
-
-			var invParentQ = tempQ;
-			invParentQ.initRotateMatrix(tmpMat);
-
-			var targetOnPlane = h3d.col.Plane.fromNormalPoint(lockAxis.toPoint(), new h3d.col.Point()).project(deltaVec.toPoint()).toVector();
-			targetOnPlane.normalize();
-			var frontAxis = new h3d.Vector(1, 0, 0);
-			var angle = hxd.Math.acos(frontAxis.dot(targetOnPlane));
-
-			var cross = frontAxis.cross(deltaVec);
-			if(lockAxis.dot(cross) < 0)
-				angle = -angle;
-
-			var q = getRotationQuat();
-			q.initRotateAxis(lockAxis.x, lockAxis.y, lockAxis.z, angle);
-			q.normalize();
-			setRotationQuat(q);
-			super.calcAbsPos();
-		}
-		else
-		{
-			tmpMat.load(absPos);
-			var scale = tmpMat.getScale(tmpScale);
-			qRot.initDirection(deltaVec);
-			qRot.toMatrix(absPos);
-			absPos._11 *= scale.x;
-			absPos._12 *= scale.x;
-			absPos._13 *= scale.x;
-			absPos._21 *= scale.y;
-			absPos._22 *= scale.y;
-			absPos._23 *= scale.y;
-			absPos._31 *= scale.z;
-			absPos._32 *= scale.z;
-			absPos._33 *= scale.z;
-			absPos._41 = tmpMat.tx;
-			absPos._42 = tmpMat.ty;
-			absPos._43 = tmpMat.tz;
-		}
-	}
-}
-
-@:allow(hrt.prefab.fx.LookAt.LookAtInstance)
-class LookAt extends Object3D {
-
-	@:s var target(default,null) : String;
-	@:s var lockAxis: Array<Float> = [0,0,0];
-
-	public function new(?parent) {
-		super(parent);
-		type = "lookAt";
-	}
-
-	override function updateInstance(ctx:hrt.prefab.Context, ?propName:String) {
-		super.updateInstance(ctx, propName);
-		var targetObj = null;
-		if(target != "camera")
-			targetObj = ctx.locateObject(target);
-	}
-
-	override function makeInstance( ctx : Context ) {
-		ctx = ctx.clone(this);
-		ctx.local3d = new LookAtObject(ctx.local3d, this);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return {
-			icon : "cog",
-			name : "LookAt"
-		};
-	}
-
-	override function edit(ctx:EditContext) {
-		super.edit(ctx);
-		var group = new hide.Element('
-		<div class="group" name="LookAt">
-			<dl>
-				<dt>Target</dt><dd><select field="target"><option value="">-- Choose --</option></select></dd>
-			</dl>
-		</div>');
-
-		group.append(hide.comp.PropsEditor.makePropsList([
-			{ name: "lockAxis", t: PVec(3), def: [1,0,0] }
-		]));
-
-		var props = ctx.properties.add(group ,this, function(_) { trace(this.lockAxis); });
-
-		var select = props.find("select");
-		var opt = new hide.Element("<option>").attr("value", "camera").html("Camera");
-		select.append(opt);
-
-		for( path in ctx.getNamedObjects() ) {
-			var parts = path.split(".");
-			var opt = new hide.Element("<option>").attr("value", path).html([for( p in 1...parts.length ) "&nbsp; "].join("") + parts.pop());
-			select.append(opt);
-		}
-		select.val(Reflect.field(this, select.attr("field")));
-	}
-	#end
-
-	static var _ = Library.register("lookAt", LookAt);
-}

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

@@ -1,17 +0,0 @@
-package hrt.prefab.fx;
-
-enum Value {
-	VZero;
-	VOne;
-	VConst(v: Float);
-	VCurve(c: Curve);
-	VCurveScale(c: Curve, scale: Float);
-	VRandom(idx: Int, scale: Value);
-	VRandomScale(idx: Int, scale: Float);
-	VAdd(a: Value, b: Value);
-	VMult(a: Value, b: Value);
-	VVector(x: Value, y: Value, z: Value, ?w: Value);
-	VHsl(h: Value, s: Value, l: Value, a: Value);
-	VBool(v: Value);
-	VInt(v: Value);
-}

+ 0 - 84
hrt/prefab/l2d/Anim2D.hx

@@ -1,84 +0,0 @@
-package hrt.prefab.l2d;
-
-class Anim2D extends Object2D {
-
-	// parameters
-	@:s var src : String;
-	@:s var widthFrame : Int = 10;
-	@:s var heightFrame : Int = 10;
-	@:s var fpsAnimation : Int = 30;
-	@:s var nbFrames : Int = 30;
-	@:s var delayStart : Float = 0;
-	@:s var loop : Bool = false;
-
-	var tex : h3d.mat.Texture;
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-
-		var h2dAnim = (cast ctx.local2d : h2d.Anim);
-
-		if (propName == null || (propName == "src" || propName == "widthFrame" || propName == "heightFrame" || propName == "nbFrames")) {
-			if (tex != null) {
-				tex = null;
-			}
-			if (src != null) {
-				tex = ctx.loadTexture(src);
-				var t = h2d.Tile.fromTexture(tex);
-				var tiles = [];
-				var nbFrameRow = Std.int(t.width / widthFrame);
-				for( y in 0...Std.int(t.height / heightFrame) )
-					for( x in 0...nbFrameRow)
-						if (y * nbFrameRow + x <= nbFrames)
-							tiles.push( t.sub(x * widthFrame, y * heightFrame, widthFrame, heightFrame, -(widthFrame / 2), -(heightFrame / 2)) );
-				h2dAnim.play(tiles);
-			} else {
-				h2dAnim.play([]);
-			}
-		}
-		if (propName == null || propName == "fpsAnimation") {
-			h2dAnim.speed = fpsAnimation;
-		}
-		if (propName == null || propName == "loop") {
-			h2dAnim.loop = loop;
-		}
-		h2dAnim.pause = !loop;
-		h2dAnim.blendMode = blendMode;
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var h2dAnim = new h2d.Anim([], fpsAnimation, ctx.local2d);
-		ctx.local2d = h2dAnim;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	#if editor
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		ctx.properties.add(new hide.Element('<div class="group" name="Frames">
-			<dl>
-				<dt>Background</dt><dd><input type="texturepath" field="src" style="width:165px"/></dd>
-				<dt>Width Frame</dt><dd><input type="range" min="0" max="100" step="1" field="widthFrame"/></dd>
-				<dt>Height Frame</dt><dd><input type="range" min="0" max="100" step="1" field="heightFrame"/></dd>
-				<dt>FPS</dt><dd><input type="range" min="0" max="60" step="1" field="fpsAnimation"/></dd>
-				<dt>nbFrames</dt><dd><input type="range" min="0" max="120" step="1" field="nbFrames"/></dd>
-				<dt>Delay Start</dt><dd><input type="range" min="0" max="10" field="delayStart"/></dd>
-				<dt>Loop</dt><dd><input type="checkbox" field="loop"/></dd>
-			</dl></div>'), this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "square", name : "Anim2D" };
-	}
-
-	#end
-
-	static var _ = Library.register("anim2D", Anim2D);
-
-}

+ 0 - 110
hrt/prefab/l2d/Atlas.hx

@@ -1,110 +0,0 @@
-package hrt.prefab.l2d;
-
-class Atlas extends Object2D {
-
-	// parameters
-	@:s var src : String;
-	@:s var fpsAnimation : Int = 30;
-	@:s var delayStart : Float = 0;
-	@:s var loop : Bool = false;
-	@:s var forcePivotCenter : Bool = false;
-
-	var atlas : hxd.res.Atlas;
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-
-		var h2dAnim = (cast ctx.local2d : h2d.Anim);
-		h2dAnim.smooth = true;
-
-		if (propName == null || propName == "src" || propName == "forcePivotCenter") {
-			if (src != null) {
-				atlas = hxd.res.Loader.currentInstance.load(src).to(hxd.res.Atlas);
-				var tiles = atlas.getAnim();
-				if (forcePivotCenter)
-					for (t in tiles) t.setCenterRatio(0.5, 0.5);
-				h2dAnim.play(tiles);
-			} else {
-				h2dAnim.play([]);
-			}
-		}
-		if (propName == null || propName == "fpsAnimation") {
-			h2dAnim.speed = fpsAnimation;
-		}
-		if (propName == null || propName == "loop") {
-			h2dAnim.loop = loop;
-		}
-		h2dAnim.pause = !loop;
-		h2dAnim.blendMode = blendMode;
-
-		#if editor
-			var int = Std.downcast(h2dAnim.getChildAt(0),h2d.Interactive);
-			if( int != null ) {
-				int.width = h2dAnim.getFrame().width;
-				int.height = h2dAnim.getFrame().height;
-			}
-		#end
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var h2dAnim = new h2d.Anim([], fpsAnimation, ctx.local2d);
-		ctx.local2d = h2dAnim;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	#if editor
-
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
-		if(local2d == null)
-			return null;
-		var h2dAnim = cast(local2d, h2d.Anim);
-		var frame = h2dAnim.getFrame();
-		if( frame == null )
-			return null;
-		var int = new h2d.Interactive(frame.width, frame.height);
-		h2dAnim.addChildAt(int, 0);
-		int.propagateEvents = true;
-		return int;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
-
-		var gr = new hide.Element('<dl></dl>').appendTo(parameters);
-
-		new hide.Element('<dt>Background</dt>').appendTo(gr);
-		var element = new hide.Element('<dd></dd>').appendTo(gr);
-		var fileInput = new hide.Element('<input type="text" field="src" style="width:165px" />').appendTo(element);
-
-		var tfile = new hide.comp.FileSelect(["atlas"], null, fileInput);
-		if (this.src != null && this.src.length > 0) tfile.path = this.src;
-		tfile.onChange = function() {
-			this.src = tfile.path;
-			updateInstance(ctx.getContext(this), "src");
-		}
-		new hide.Element('<dt>FPS</dt><dd><input type="range" min="0" max="60" step="1" field="fpsAnimation"/></dd>').appendTo(gr);
-		new hide.Element('<dt>Delay Start</dt><dd><input type="range" min="0" max="5" field="delayStart"/></dd>').appendTo(gr);
-		new hide.Element('<dt>Loop</dt><dd><input type="checkbox" field="loop"/></dd>').appendTo(gr);
-		new hide.Element('<dt>Force Pivot Center</dt><dd><input type="checkbox" field="forcePivotCenter"/></dd>').appendTo(gr);
-
-
-		ctx.properties.add(parameters, this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "square", name : "Atlas" };
-	}
-
-	#end
-
-	static var _ = Library.register("atlas", Atlas);
-
-}

+ 0 - 95
hrt/prefab/l2d/Bitmap.hx

@@ -1,95 +0,0 @@
-package hrt.prefab.l2d;
-
-class Bitmap extends Object2D {
-
-	// parameters
-	@:s var color : Int = 0xFFFFFF;
-	@:s var src : String;
-	@:s var dx : Float = 0;
-	@:s var dy : Float = 0;
-
-	var tex : h3d.mat.Texture;
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		var bmp = (cast ctx.local2d : h2d.Bitmap);
-		bmp.visible = visible;
-		if (propName == null || propName == "src") {
-			if (tex != null) {
-				tex = null;
-			}
-			if (src != null) {
-				tex = ctx.loadTexture(src);
-				bmp.tile = h2d.Tile.fromTexture(this.tex);
-			} else {
-				bmp.tile = h2d.Tile.fromColor(0xFF00FF,32,32,0.5);
-			}
-		}
-		bmp.color = h3d.Vector.fromColor(color);
-		bmp.color.w = 1;
-		var cRatio = getCenterRatio(dx, dy);
-		bmp.tile.setCenterRatio(cRatio[0], cRatio[1]);
-		bmp.blendMode = blendMode;
-		#if editor
-		var int = Std.downcast(bmp.getChildAt(0),h2d.Interactive);
-		if( int != null ) {
-			int.width = bmp.tile.width;
-			int.height = bmp.tile.height;
-			int.x = bmp.tile.dx;
-			int.y = bmp.tile.dy;
-		}
-		#end
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var bmp = new h2d.Bitmap(null, ctx.local2d);
-		bmp.smooth = true;
-		ctx.local2d = bmp;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	static public function getCenterRatio(dx : Float, dy : Float) {
-		return [0.5 + hxd.Math.clamp(dx, -0.5, 0.5), 0.5 + hxd.Math.clamp(dy, -0.5, 0.5)];
-	}
-
-	#if editor
-
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
-		if(local2d == null)
-			return null;
-		var bmp = cast(local2d, h2d.Bitmap);
-		var int = new h2d.Interactive(bmp.tile.width, bmp.tile.height);
-		bmp.addChildAt(int, 0);
-		int.propagateEvents = true;
-		int.x = bmp.tile.dx;
-		int.y = bmp.tile.dy;
-		return int;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		ctx.properties.add(new hide.Element('<div class="group" name="Parameters">
-			<dl>
-				<dt>Color</dt><dd><input type="color" field="color" /></dd>
-				<dt>Background</dt><dd><input type="texturepath" field="src" style="width:165px"/></dd>
-				<dt>Bg Pivot DX</dt><dd><input type="range" min="-0.5" max="0.5" field="dx"/></dd>
-				<dt>Bg Pivot DY</dt><dd><input type="range" min="-0.5" max="0.5" field="dy"/></dd>
-			</dl></div>'), this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "square", name : "Bitmap" };
-	}
-
-	#end
-
-	static var _ = Library.register("bitmap", Bitmap);
-
-}

+ 0 - 101
hrt/prefab/l2d/Blur.hx

@@ -1,101 +0,0 @@
-package hrt.prefab.l2d;
-
-class Blur extends Prefab {
-
-	@: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
-	@:s public var image : String;
-	@:s public var zoom : Int = 1;
-
-	var pass : h3d.pass.Blur;
-
-	public function makeFilter() {
-		var f = new h2d.filter.Blur(radius, gain, quality);
-		f.linear = linear;
-		return f;
-	}
-
-	public function apply( t : h3d.mat.Texture, ctx : h3d.impl.RenderContext ) {
-		if( radius == 0 )
-			return t;
-		if( pass == null )
-			pass = new h3d.pass.Blur();
-		pass.quality = quality;
-		pass.radius = radius;
-		pass.gain = gain;
-		pass.linear = linear;
-		pass.apply(ctx, t);
-		return t;
-	}
-
-	override function makeInstance( ctx : Context ) {
-		ctx = ctx.clone(this);
-		var bmp = new h2d.Bitmap(null, ctx.local2d);
-		syncBitmap(bmp, ctx);
-		bmp.visible = false;
-		ctx.local2d = bmp;
-		return ctx;
-	}
-
-	function syncBitmap( bmp : h2d.Bitmap, ctx : Context ) {
-		var t;
-		if( image != null )
-			t = h2d.Tile.fromTexture(ctx.loadTexture(image));
-		else {
-			t = h2d.Tile.fromTexture(h3d.mat.Texture.genChecker(16));
-			t.setSize(256, 256);
-		}
-		t.dx = -t.iwidth>>1;
-		t.dy = -t.iheight>>1;
-		bmp.tile = t;
-		bmp.filter = makeFilter();
-		bmp.smooth = true;
-		bmp.tileWrap = image == null;
-		bmp.setScale(zoom);
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { name : "Blur", icon : "bullseye" };
-	}
-
-	override function edit( ctx : EditContext ) {
-		var e : hide.Element = null;
-		function sync( bmp : h2d.Bitmap ) {
-			var k = @:privateAccess Std.downcast(bmp.filter, h2d.filter.Blur).pass.getKernelSize();
-			e.find("[name=fetches]").text( (k + k) +"x" );
-		}
-		e = ctx.properties.add(new hide.Element('
-			<dl>
-				<dt>Radius</dt><dd><input type="range" min="0" max="30" field="radius"/></dd>
-				<dt>Gain</dt><dd><input type="range" min="0.5" max="1.5" field="gain"/></dd>
-				<dt>Linear</dt><dd><input type="range" min="0" max="1" field="linear"/></dd>
-				<dt>Quality</dt><dd><input type="range" min="0" max="1" field="quality"/></dd>
-			</dl>
-			<br/>
-			<dl>
-				<dt>Fetches</dt><dd name="fetches"></dd>
-				<dt>Test Texture</dt><dd><input type="texturepath" field="image"/></dd>
-				<dt>Display zoom</dt><dd><input type="range" min="1" max="8" step="1" field="zoom"/></dd>
-			</dl>
-		'),this,function(f) {
-			var ctx = ctx.getContext(this);
-			var bmp = cast(ctx.local2d, h2d.Bitmap);
-			syncBitmap(bmp, ctx);
-			sync(bmp);
-		});
-		var lctx = ctx.getContext(this);
-		var bmp = cast(lctx.local2d, h2d.Bitmap);
-		bmp.visible = true;
-		ctx.cleanups.push(function() bmp.visible = false);
-		sync(bmp);
-	}
-	#end
-
-	static var _ = Library.register("blur", Blur);
-
-}

+ 0 - 365
hrt/prefab/l2d/NoiseGenerator.hx

@@ -1,365 +0,0 @@
-package hrt.prefab.l2d;
-
-enum abstract NoiseMode(String) {
-	var Perlin;
-	var Ridged;
-}
-
-enum abstract RepeatMode(String) {
-	var Both;
-	var X;
-	var Y;
-	var None;
-}
-
-class NoiseGenerator extends Prefab {
-
-	@:s public var seed : Int;
-
-	@: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;
-
-	function new(?parent) {
-		super(parent);
-		seed = Std.random(100);
-	}
-
-	public function updateTexture( t : h3d.mat.Texture ) {
-		var e = h3d.Engine.getCurrent();
-		e.pushTarget(t);
-		@:privateAccess e.flushTarget();
-		var pass = new h3d.pass.ScreenFx(new NoiseShader());
-		pass.shader.seed = seed;
-		pass.shader.channels = normals ? 0 : channels;
-		pass.shader.octaves = octaves;
-		var scale = size * scale * scale / 16;
-		pass.shader.scale = Math.round(scale*0.5) * 2;
-		pass.shader.persist = persist;
-		pass.shader.lacunarity = lacunarity;
-
-		pass.shader.mode = switch( mode ) {
-		case Perlin: 0;
-		case Ridged :
-			pass.shader.gain = gain;
-			pass.shader.offset = offset;
-			1;
-		}
-
-		pass.shader.contrast = contrast;
-		pass.shader.brightness = brightness;
-		pass.shader.normals = normals;
-		pass.shader.inverse = inverse ? 1 : 0;
-		pass.shader.repeat = switch repeat {
-			case Both: 0;
-			case X: 1;
-			case Y: 2;
-			case None: 3;
-		}
-
-		pass.shader.turbulence = turbulence * 16 / size;
-		pass.shader.turbulenceScale = turbulenceScale;
-
-		pass.render();
-		pass.dispose();
-		e.popTarget();
-	}
-
-	public function toTexture() {
-		if( tex != null )
-			return tex;
-		tex = new h3d.mat.Texture(size, size, [Target]);
-		if( !tex.flags.has(IsNPOT) ) tex.wrap = Repeat;
-		updateTexture(tex);
-		var e = h3d.Engine.getCurrent();
-		tex.realloc = function() haxe.Timer.delay(function() {
-			e.setCurrent();
-			updateTexture(tex);
-		}, 0);
-		return tex;
-	}
-
-	override function reload(p:Dynamic) {
-		if( tex != null ) {
-			tex.dispose();
-			tex = null;
-		}
-		super.reload(p);
-	}
-
-	function makeTile( tex : h3d.mat.Texture ) {
-		var t = h2d.Tile.fromTexture(tex);
-		if( tex.flags.has(IsNPOT) )
-			return t;
-		// make wrapping artefacts apparent, if any
-		return t.sub(repeat == Both || repeat == X ? tex.width >> 1 : 0, repeat == Both || repeat == Y ? tex.height >> 1 : 0, tex.width, tex.height);
-	}
-
-	override function makeInstance( ctx : Context ) {
-		var tex = new h3d.mat.Texture(size, size, [Target]);
-		updateTexture(tex);
-		ctx = ctx.clone(this);
-		var bmp = new h2d.Bitmap(makeTile(tex), ctx.local2d);
-		bmp.tileWrap = !tex.flags.has(IsNPOT);
-		bmp.visible = false;
-		bmp.x = -size >> 1;
-		bmp.y = -size >> 1;
-		ctx.local2d = bmp;
-		ctx.cleanup = function() tex.dispose();
-		return ctx;
-	}
-
-	#if editor
-
-	override function getHideProps() : HideProps {
-		return { icon : "cloud", name : "Noise Generator" };
-	}
-
-	override function edit( ctx : EditContext ) {
-		var e = ctx.properties.add(new hide.Element('
-			<dl>
-				<dt>Mode</dt><dd><select field="mode">
-					<option value="Perlin">Perlin</option>
-					<option value="Ridged">Ridged</option>
-				</select>
-				</dd>
-				<dt>Size</dt><dd><input type="range" min="16" max="2048" step="16" field="size"/></dd>
-				<dt>Scale</dt><dd><input type="range" min="0" max="2" field="scale"/></dd>
-				<dt>Channels</dt><dd><input type="range" min="1" max="4" step="1" field="channels"/></dd>
-				<dt>NormalMap</dt><dd><input type="checkbox" field="normals"/></dd>
-				<dt>Repeat</dt><dd>
-					<select field="repeat">
-						<option value="Both">Both</option>
-						<option value="X">X</option>
-						<option value="Y">Y</option>
-						<option value="None">None</option>
-					</select>
-				</dd>
-			</dl>
-			<br/>
-			<dl>
-				<dt>Octaves</dt><dd><input type="range" min="1" max="8" step="1" field="octaves"/></dd>
-				<dt>Persistence</dt><dd><input type="range" min="0.01" max="1" field="persist"/></dd>
-				<dt>Lacunarity</dt><dd><input type="range" min="1" max="5" field="lacunarity"/></dd>
-			</dl>
-			<br/>
-			${mode == Ridged ? '
-				<dl>
-					<dt>Offset</dt><dd><input type="range" min="-1" max="1" field="offset"/></dd>
-					<dt>Gain</dt><dd><input type="range" min="0.01" max="5" field="gain"/></dd>
-				</dl>
-				<br/>
-			' : ''}
-			<dl>
-				<dt>Turbulence</dt><dd><input type="range" min="0" max="1" field="turbulence"/></dd>
-				<dt>Scale</dt><dd><input type="range" min="0" max="10" field="turbulenceScale"/></dd>
-			</dl>
-			<br/>
-			<dl>
-				<dt>Contrast</dt><dd><input type="range" min="-1" max="1" field="contrast"/></dd>
-				<dt>Brightness</dt><dd><input type="range" min="-1" max="1" field="brightness"/></dd>
-				<dt>Inverse</dt><dd><input type="checkbox" field="inverse"/></dd>
-			</dl>
-			<br/>
-			<dl>
-				<dt>Seed</dt><dd><input type="range" step="1" min="0" max="100" field="seed"/></dd>
-				<dt>&nbsp;</dt><dd><input type="button" value="Download" name="dl"/></dd>
-			</dl>
-		'),this,function(pname)  {
-			var bmp = cast(ctx.getContext(this).local2d, h2d.Bitmap);
-			var tex = bmp.tile.getTexture();
-			if( tex.width != size ) {
-				tex.resize(size, size);
-				bmp.tile = makeTile(tex);
-				bmp.tileWrap = !tex.flags.has(IsNPOT);
-				bmp.x = -size >> 1;
-				bmp.y = -size >> 1;
-			}
-			updateTexture(tex);
-			ctx.onChange(this, pname);
-		});
-		var bmp = cast(ctx.getContext(this).local2d, h2d.Bitmap);
-		e.find("[name=dl]").click(function(_) {
-			ctx.ide.chooseFileSave("noise.png", function(f) {
-				try {
-					var data = cast(ctx.getContext(this).local2d, h2d.Bitmap).tile.getTexture().capturePixels().toPNG();
-					sys.io.File.saveBytes(ctx.ide.getPath(f), data);
-				} catch( e : Dynamic ) {
-					ctx.ide.error(e);
-				}
-			});
-		});
-		bmp.visible = true;
-		ctx.cleanups.push(function() bmp.visible = false);
-	}
-
-	#end
-
-	static var _ = Library.register("noise", NoiseGenerator);
-
-}
-
-class NoiseShader extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@:import h3d.shader.NoiseLib;
-
-		@const(5) var channels : Int = 1;
-		@const(64) var octaves : Int = 1;
-		@const(4) var mode : Int;
-		@const var normals : Bool;
-		@const(4) var repeat : Int;
-
-		@param var seed : Int;
-		@param var scale : Float = 8;
-		@param var persist : Float = 0.5;
-		@param var lacunarity : Float = 2.0;
-
-		@param var gain : Float;
-		@param var offset : Float;
-		@param var inverse : Float;
-
-		@param var contrast : Float;
-		@param var brightness : Float;
-		@param var turbulence : Float;
-		@param var turbulenceScale : Float;
-
-		function makeRepeat( scale : Float ) : Vec2 {
-			var s = int(scale * 0.5) * 2.;
-			return if( repeat == 0 ) vec2(s) else if( repeat == 1 ) vec2(s,scale) else if( repeat == 2 ) vec2(scale,s) else vec2(scale);
-		}
-
-		function makePeriod( scale : Vec2 ) : Vec2 {
-			// TODO : the period is unbound for no-repeat but psrnoise
-			// still exhibits rounding behaviors with low scales
-			if( repeat == 0 )
-				return scale;
-			if( repeat == 1 )
-				return vec2(scale.x, 1e9);
-			if( repeat == 2 )
-				return vec2(1e9, scale.y);
-			return vec2(1e9);
-		}
-
-		function perturb( uv : Vec2, scale : Float, seed : Int ) : Vec2 {
-			if( turbulence > 0. ) {
-				var turbScaleRepeat = makeRepeat(scale * turbulenceScale);
-				noiseSeed = channels * octaves + 1 + seed;
-				uv.x += psnoise(calculatedUV * turbScaleRepeat, makePeriod(turbScaleRepeat)) * turbulence;
-				noiseSeed = channels * octaves + 1025 + seed;
-				uv.y += psnoise(calculatedUV * turbScaleRepeat, makePeriod(turbScaleRepeat)) * turbulence;
-			}
-			return uv;
-		}
-
-		function noise( seed : Int, scale : Float ) : Float {
-			var scaleRepeat = makeRepeat(scale);
-			var uv = perturb(calculatedUV,scale,seed);
-			noiseSeed = seed;
-			return psnoise(uv * scaleRepeat, makePeriod(scaleRepeat));
-		}
-
-		function noiseNormal( seed : Int, scale : Float ) : Vec3 {
-			var scaleRepeat = makeRepeat(scale);
-			var uv = perturb(calculatedUV, scale,seed);
-			noiseSeed = seed;
-			return psrdnoise(uv * scaleRepeat, makePeriod(scaleRepeat), 0.).yzx;
-		}
-
-		function calc( channel : Int ) : Float {
-			var v = 0.;
-			var seed = seed + channel * octaves;
-			var scale = scale;
-			switch( mode ) {
-			case 0: // perlin
-				var k = 1.;
-				for( i in 0...octaves ) {
-					v += noise(seed + i, scale) * k;
-					k *= persist;
-					scale *= lacunarity;
-				}
-			case 1: // ridged
-				var k = 1.;
-				var s = lacunarity;
-				var weight = 1.;
-				var tot = 0.;
-				for( i in 0...octaves ) {
-					var g = noise(seed + i, scale) * k;
-					g = offset - abs(g);
-					g *= g;
-					g *= weight;
-					v += g * s;
-					tot += k;
-					weight = g * gain;
-					if( weight < 0 ) weight = 0 else if( weight > 1 ) weight = 1;
-					k *= persist;
-					scale *= lacunarity;
-				}
-				v /= tot;
-			}
-			v = (v * (1 + contrast) + 1) * 0.5 + brightness;
-			if( inverse > 0 ) v = 1 - v;
-			return v;
-		}
-
-		function calcNormal() : Vec3 {
-			var v = vec3(0.);
-			var scale = scale;
-			switch( mode ) {
-			case 0:
-				var k = 1.;
-				for( i in 0...octaves ) {
-					v += noiseNormal(seed + i, scale) * k;
-					k *= persist;
-					scale *= lacunarity;
-				}
-			default:
-				// TODO
-				v.z = 1.;
-			}
-			v.z = (v.z + 1) * 0.5 + 10;
-			v = v.normalize();
-			v.xy *= pow(2., 1. + contrast * 4.);
-			return v.normalize();
-		}
-
-		function fragment() {
-			var out = vec4(0, 0, 0, 1);
-
-			if( normals ) {
-				out = packNormal(calcNormal());
-			} else {
-				if( channels >= 1 ) {
-					out.r = calc(0);
-					if( channels == 1 ) out.gb = out.rr;
-				}
-				if( channels >= 2 )
-					out.g = calc(1);
-				if( channels >= 3 )
-					out.b = calc(2);
-				if( channels >= 4 )
-					out.a = calc(3);
-			}
-			output.color = out;
-		}
-	}
-
-}

+ 0 - 172
hrt/prefab/l2d/Particle2D.hx

@@ -1,172 +0,0 @@
-package hrt.prefab.l2d;
-
-import hrt.prefab.fx.Evaluator;
-import hrt.prefab.fx.Value;
-import h2d.Particles.ParticleGroup;
-
-class Particles extends h2d.Particles {
-
-	var evaluator : Evaluator;
-
-	var lastTime = -1.0;
-	var curTime = 0.0;
-
-	var random: hxd.Rand;
-	var randomSeed = 0;
-
-	public var catchupSpeed = 4; // Use larger ticks when catching-up to save calculations
-	public var maxCatchupWindow = 0.5; // How many seconds max to simulate when catching up
-
-	// param FX
-	public var enable : Value;
-	public var speed : Value;
-	public var speedIncr : Value;
-	public var gravity : Value;
-
-	public function new( ?parent ) {
-		super(parent);
-		randomSeed = Std.random(0xFFFFFF);
-		random = new hxd.Rand(randomSeed);
-		evaluator = new Evaluator(random);
-	}
-
-	function tick( dt : Float, full=true) {
-		var group = this.groups[0];
-
-		var enableValue = evaluator.getFloat(enable, curTime) >= 0.5;
-		if (group.enable != enableValue) // prevent batch.clear() when false
-			group.enable = enableValue;
-
-		group.speed = evaluator.getFloat(speed, curTime);
-		group.speedIncr = evaluator.getFloat(speedIncr, curTime);
-		group.gravity = evaluator.getFloat(gravity, curTime);
-
-		lastTime = curTime;
-		curTime += dt;
-	}
-
-	public function reset() {
-		random.init(randomSeed);
-		curTime = 0.0;
-		lastTime = 0.0;
-	}
-
-	public function setTime(time: Float) {
-		if(time < lastTime || lastTime < 0) {
-			reset();
-		}
-
-		var catchupTime = time - curTime;
-		#if !editor
-		if(catchupTime > maxCatchupWindow) {
-			curTime = time - maxCatchupWindow;
-			catchupTime = maxCatchupWindow;
-		}
-		#end
-		var catchupTickRate = hxd.Timer.wantedFPS / catchupSpeed;
-		var numTicks = hxd.Math.ceil(catchupTickRate * catchupTime);
-		for(i in 0...numTicks) {
-			tick(catchupTime / numTicks, i == (numTicks - 1));
-		}
-	}
-
-	override function getBounds( ?relativeTo : h2d.Object, ?out : h2d.col.Bounds ) : h2d.col.Bounds {
-		if( out == null ) out = new h2d.col.Bounds() else out.empty();
-		out = super.getBounds(relativeTo, out);
-		out.xMin -= 25*scaleX;
-		out.xMax += 25*scaleX;
-		out.yMin -= 25*scaleY;
-		out.yMax += 25*scaleY;
-		return out;
-	}
-
-}
-
-class Particle2D extends Object2D {
-
-	@:s var paramsParticleGroup : Dynamic;
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-
-		var particles2d = (cast ctx.local2d : Particles);
-
-		particles2d.visible = visible;
-
-		function makeVal(name, def ) : Value {
-			var c = Curve.getCurve(this, name);
-			return c != null ? VCurve(c) : def;
-		}
-
-		if (paramsParticleGroup != null) {
-			particles2d.enable = makeVal("enable", VConst((paramsParticleGroup.enable) ? 1 : 0));
-			particles2d.speed = makeVal("speed", VConst(paramsParticleGroup.speed));
-			particles2d.speedIncr = makeVal("speedIncr", VConst(paramsParticleGroup.speedIncr));
-			particles2d.gravity = makeVal("gravity", VConst(paramsParticleGroup.gravity));
-		}
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var particle2d = new Particles(ctx.local2d);
-		ctx.local2d = particle2d;
-		ctx.local2d.name = name;
-
-		var group = new ParticleGroup(particle2d);
-		particle2d.addGroup(group);
-		if (paramsParticleGroup != null)
-			group.load(1, paramsParticleGroup);
-		else
-			paramsParticleGroup = group.save();
-		group.rebuildOnChange = false;
-
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	#if editor
-
-	public static var emitter2dParams : Array<hrt.prefab.fx.Emitter.ParamDef> = [
-		// EMIT PARAMS
-		{ name: "enable", t: PBool, disp: "Enable", def : 1.0, animate: true, groupName : "Emit Params" },
-		{ name: "speed", t: PFloat(), disp: "Initial Speed", def : 1.0, animate: true, groupName : "Emit Params" },
-		{ name: "speedIncr", t: PFloat(), disp: "Acceleration", def : 1.0, animate: true, groupName : "Emit Params" },
-		{ name: "gravity", t: PFloat(), disp: "Gravity", def : 1.0, animate: true, groupName : "Emit Params" }
-	];
-
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
-		if(local2d == null)
-			return null;
-		var particles2d = cast(local2d, h2d.Particles);
-		var int = new h2d.Interactive(50, 50);
-		particles2d.addChildAt(int, 0);
-		int.propagateEvents = true;
-		int.x = int.y = -25;
-		return int;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var params = new hide.Element(hide.view.Particles2D.getParamsHTMLform());
-
-		var particles2d = (cast ctx.getContext(this).local2d : Particles);
-		var group = @:privateAccess particles2d.groups[0];
-		ctx.properties.add(params, group, function (pname) {
-			// if fx2d is running, tick() changes group params and modifies group.save()
-			// if a param has a curve and we changed this param on the right panel,
-			// the saved value will be the value of the curve at this point.
-			Reflect.setField(paramsParticleGroup, pname, Reflect.field(group.save(), pname));
-		});
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "square", name : "Particle2D" };
-	}
-
-	#end
-
-	static var _ = Library.register("particle2D", Particle2D);
-
-}

+ 0 - 254
hrt/prefab/l2d/Text.hx

@@ -1,254 +0,0 @@
-package hrt.prefab.l2d;
-
-class Text extends Object2D {
-
-	// parameters
-	@:s var color : Int = 0xFFFFFF;
-	@:s var size : Int = 12;
-	@:s var cutoff : Float = 0.5;
-	@:s var smoothing : Float = 1 / 32;
-	@:s var align : Int = 0;
-
-	@:s var pathFont : String;
-
-	// TextShadow
-	@:s var enableTextShadow : Bool = false;
-	@:s var tsDx: Float = 0;
-	@:s var tsDy: Float = 0;
-	@:s var tsColor: Int;
-	@:s var tsAlpha: Float = 1;
-
-	// DropShadow
-	@:s var enableDropShadow : Bool = false;
-	@:s var dsDistance: Float = 0;
-	@:s var dsAngle: Float = 0;
-	@:s var dsColor: Int;
-	@:s var dsAlpha: Float = 1;
-	@:s var dsRadius: Float = 0;
-	@:s var dsGain: Float = 1;
-	@:s var dsQuality: Float = 1;
-	@:s var dsSmoothColor: Bool = true;
-
-	#if editor
-	@:s var text : String = "";
-	#end
-
-	override public function load(v:Dynamic) {
-		super.load(v);
-		if( v.blendMode == null )
-			blendMode = Alpha;
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		var h2dText = (cast ctx.local2d : h2d.HtmlText);
-		h2dText.visible = visible;
-		h2dText.color = h3d.Vector.fromColor(color);
-		h2dText.color.w = 1;
-
-		if (enableTextShadow) {
-			h2dText.dropShadow = {
-				dx: tsDx,
-				dy: tsDy,
-				color: tsColor,
-				alpha: tsAlpha
-			};
-		} else {
-			h2dText.dropShadow = null;
-		}
-
-		if (enableDropShadow) {
-			h2dText.filter = new h2d.filter.DropShadow(
-				dsDistance,
-				dsAngle,
-				dsColor,
-				dsAlpha,
-				dsRadius,
-				dsGain,
-				dsQuality,
-				dsSmoothColor
-			);
-		} else
-			h2dText.filter = null;
-
-		h2dText.textAlign = switch (align) {
-			case 1:
-				Center;
-			case 2:
-				Right;
-			default:
-				Left;
-		}
-		var font = loadFont();
-		if (font != null)
-			h2dText.font = font;
-		#if editor
-			if (propName == null || propName == "text") {
-				h2dText.text = text;
-			}
-			var int = Std.downcast(h2dText.getChildAt(0),h2d.Interactive);
-			if( int != null ) {
-				@:privateAccess {
-					h2dText.rebuild();
-					int.width = h2dText.calcWidth;
-					int.height = h2dText.calcHeight;
-					switch (h2dText.textAlign) {
-						case Center:
-							int.x = -int.width/2;
-						case Right:
-							int.x = -int.width;
-						default:
-							int.x = 0;
-					}
-				}
-			}
-		#end
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var h2dText = new h2d.HtmlText(hxd.res.DefaultFont.get(), ctx.local2d);
-		h2dText.text = "";
-		h2dText.smooth = true;
-		ctx.local2d = h2dText;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	public dynamic function loadFont() : h2d.Font {
-		var f = defaultLoadFont(pathFont, size, cutoff, smoothing);
-		if (f == null) {
-			if (pathFont != null && pathFont.length > 0) {
-				var font = hxd.res.Loader.currentInstance.load(pathFont).to(hxd.res.BitmapFont);
-				return font.toSdfFont(size, MultiChannel, cutoff, smoothing);
-			} else {
-				return null;
-			}
-		}
-		else return f;
-	}
-
-	public static dynamic function defaultLoadFont( pathFont : String, size : Int, cutoff : Float, smoothing : Float ) : h2d.Font {
-		return null;
-	}
-
-	#if editor
-
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
-		if(local2d == null)
-			return null;
-		var text = cast(local2d, h2d.Text);
-		@:privateAccess { text.rebuild(); text.updateSize(); }
-		@:privateAccess var int = new h2d.Interactive(text.calcWidth, text.calcHeight);
-		text.addChildAt(int, 0);
-		int.propagateEvents = true;
-		return int;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
-
-		var gr = new hide.Element('<dl></dl>').appendTo(parameters);
-
-		new hide.Element('<dt>Align</dt>').appendTo(gr);
-		var element = new hide.Element('<dd></dd>').appendTo(gr);
-		var leftAlign = new hide.Element('<input type="button" style="width: 50px" value="Left" /> ').appendTo(element);
-		var middleAlign = new hide.Element('<input type="button" style="width: 50px" value="Center" /> ').appendTo(element);
-		var rightAlign = new hide.Element('<input type="button" style="width: 50px" value="Right" /> ').appendTo(element);
-		inline function updateDisabled() {
-			leftAlign.removeAttr("disabled");
-			middleAlign.removeAttr("disabled");
-			rightAlign.removeAttr("disabled");
-			switch (align) {
-				case 1:
-					middleAlign.attr("disabled", "true");
-				case 2:
-					rightAlign.attr("disabled", "true");
-				default:
-					leftAlign.attr("disabled", "true");
-			}
-		}
-		leftAlign.on("click", function(e) {
-			align = 0;
-			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
-		});
-		middleAlign.on("click", function(e) {
-			align = 1;
-			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
-		});
-		rightAlign.on("click", function(e) {
-			align = 2;
-			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
-		});
-		updateDisabled();
-
-		new hide.Element('<dt>Font</dt>').appendTo(gr);
-		var element = new hide.Element('<dd></dd>').appendTo(gr);
-		var fileInput = new hide.Element('<input type="text" field="pathFont" style="width:165px" />').appendTo(element);
-
-		var tfile = new hide.comp.FileSelect(["fnt"], null, fileInput);
-		if (this.pathFont != null && this.pathFont.length > 0) tfile.path = this.pathFont;
-		tfile.onChange = function() {
-			this.pathFont = tfile.path;
-			updateInstance(ctx.getContext(this), "src");
-		}
-
-		new hide.Element('<dt>Color</dt><dd><input type="color" field="color" /></dd>').appendTo(gr);
-		new hide.Element('<dt>Size</dt><dd><input type="range" min="1" max="50" step="1" field="size" /></dd>').appendTo(gr);
-		new hide.Element('<dt>Cutoff</dt><dd><input type="range" min="0" max="1" field="cutoff" /></dd>').appendTo(gr);
-		new hide.Element('<dt>Smoothing</dt><dd><input type="range" min="0" max="1" field="smoothing" /></dd>').appendTo(gr);
-
-		ctx.properties.add(parameters, this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-
-		ctx.properties.add(new hide.Element('<div class="group" name="Text Shadow (double render)">
-			<dl>
-				<dt>Enable</dt><dd><input type="checkbox" field="enableTextShadow" /></dd><br />
-				<dt>DX</dt><dd><input type="range" min="-50" max="50" step="1" field="tsDx" /></dd>
-				<dt>DY</dt><dd><input type="range" min="-50" max="50" step="1" field="tsDy" /></dd>
-				<dt>Color</dt><dd><input type="color" field="tsColor" /></dd>
-				<dt>Alpha</dt><dd><input type="range" min="0" max="1" step="0.01" field="tsAlpha" /></dd>
-			</dl></div>'), this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-
-		ctx.properties.add(new hide.Element('<div class="group" name="Drop Shadow">
-			<dl>
-				<dt>Enable</dt><dd><input type="checkbox" field="enableDropShadow" /></dd><br />
-				<dt>Distance</dt><dd><input type="range" min="-50" max="50" step="1" field="dsDistance" /></dd>
-				<dt>Angle</dt><dd><input type="range" min="-1.571" max="1.571" step="0.0524" field="dsAngle" /></dd>
-				<dt>Color</dt><dd><input type="color" field="dsColor" /></dd>
-				<dt>Alpha</dt><dd><input type="range" min="0" max="1" step="0.01" field="dsAlpha" /></dd>
-				<dt>Radius</dt><dd><input type="range" min="0" max="50" step="1" field="dsRadius" /></dd>
-				<dt>Gain</dt><dd><input type="range" min="0.1" max="50" step="0.1" field="dsGain" /></dd>
-				<dt>Quality</dt><dd><input type="range" min="0" max="1" step="0.01" field="dsQuality" /></dd>
-				<dt>Smooth Color</dt><dd><input type="checkbox" field="dsSmoothColor" /></dd>
-			</dl></div>'), this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-
-		ctx.properties.add(new hide.Element('<div class="group" name="Responsive">
-			<dl>
-				<dt>Text</dt><dd><input type="text" field="text" /></dd>
-			</dl></div>'), this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "square", name : "Text" };
-	}
-
-	#end
-
-	static var _ = Library.register("text", Text);
-
-}

+ 0 - 37
hrt/prefab/l3d/AnimSpeedControl.hx

@@ -1,37 +0,0 @@
-package hrt.prefab.l3d;
-
-class AnimSpeedControl extends hrt.prefab.Prefab {
-
-	@:s var speed : Float = 1.;
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function updateInstance(ctx:Context,?propName) {
-		if( ctx.local3d != null && ctx.local3d.currentAnimation != null )
-			ctx.local3d.currentAnimation.speed = speed;
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return {
-			name : "AnimSpeedCtrl",
-			icon : "cog",
-			allowParent : (p) -> Std.is(p,Object3D),
-		};
-	}
-	override function edit(ctx:EditContext) {
-		ctx.properties.add(new Element('<dl>
-			<dt>Speed</dt><dd><input type="range" field="speed"/></dd>
-		</dl>'), this, function(p) {
-			ctx.onChange(this, p);
-		});
-	}
-	#end
-
-	static var _ = Library.register("animSpeedCtrl", AnimSpeedControl);
-
-}

+ 0 - 70
hrt/prefab/l3d/Box.hx

@@ -1,70 +0,0 @@
-package hrt.prefab.l3d;
-
-class Box extends Object3D {
-
-
-	public function setColor(ctx: Context, color: Int) {
-		#if editor
-		if(ctx.local3d == null)
-			return;
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
-		if(mesh != null) {
-			setDebugColor(color, mesh.material);
-		}
-		#end
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-
-		var mesh = new h3d.scene.Mesh(h3d.prim.Cube.defaultUnitCube(), ctx.local3d);
-
-		#if editor
-		setDebugColor(0x60ffffff, mesh.material);
-
-		var wire = new h3d.scene.Box(mesh);
-		wire.color = 0;
-		wire.ignoreCollide = true;
-		wire.material.shadows = false;
-		#end
-
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	#if editor
-	static public function setDebugColor(color : Int, mat : h3d.mat.Material) {
-		mat.color.setColor(color);
-		var opaque = (color >>> 24) == 0xff;
-		mat.shadows = false;
-
-		if(opaque) {
-			var alpha = mat.getPass("debuggeom_alpha");
-			if(alpha != null)
-				mat.removePass(alpha);
-			mat.mainPass.setPassName("default");
-		 	mat.mainPass.setBlendMode(None);
-		 	mat.mainPass.depthWrite = true;
-			mat.mainPass.culling = None;
-		}
-		else {
-			mat.mainPass.setPassName("debuggeom");
-			mat.mainPass.setBlendMode(Alpha);
-			mat.mainPass.depthWrite = true;
-			mat.mainPass.culling = Front;
-			var alpha = mat.allocPass("debuggeom_alpha");
-			alpha.setBlendMode(Alpha);
-			alpha.culling = Back;
-			alpha.depthWrite = false;
-		}
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "square", name : "Box" };
-	}
-	#end
-
-	static var _ = Library.register("box", Box);
-}

+ 0 - 225
hrt/prefab/l3d/Camera.hx

@@ -1,225 +0,0 @@
-package hrt.prefab.l3d;
-import h3d.scene.Object;
-import hrt.prefab.Context;
-import hrt.prefab.Library;
-
-class CameraSyncObject extends h3d.scene.Object {
-
-	public var enable : Bool;
-	public var dir : h3d.Vector;
-	public var pos : h3d.Vector;
-	public var fovY : Float;
-	public var zFar : Float;
-	public var zNear : Float;
-
-	override function sync( ctx ) {
-		if( enable ) {
-			var c = getScene().camera;
-			if( c != null ) {
-				c.pos.load(pos);
-				c.target.load(pos.add(dir));
-				c.fovY = fovY;
-				c.zFar = zFar;
-				c.zNear = zNear;
-			}
-		}
-	}
-}
-
-class Camera extends Object3D {
-
-	@:s var fovY : Float = 45;
-	@:s var zFar : Float = 200;
-	@:s var zNear : Float = 0.02;
-	@:s var showFrustum = false;
-	var preview = false;
-
-	public function new(?parent) {
-		super(parent);
-		type = "camera";
-	}
-
-	var g : h3d.scene.Graphics;
-	function drawFrustum( ctx : Context ) {
-
-		if( !showFrustum ) {
-			if( g != null ) {
-				g.remove();
-				g = null;
-			}
-			return;
-		}
-
-		if( g == null ) {
-			g = new h3d.scene.Graphics(ctx.local3d);
-			g.name = "frustumDebug";
-			g.material.mainPass.setPassName("overlay");
-		}
-
-		var c = new h3d.Camera();
-		c.pos.set(0,0,0);
-		c.target.set(1,0,0);
-		c.fovY = fovY;
-		c.zFar = zFar;
-		c.zNear = zNear;
-		c.update();
-
-		var nearPlaneCorner = [c.unproject(-1, 1, 0), c.unproject(1, 1, 0), c.unproject(1, -1, 0), c.unproject(-1, -1, 0)];
-		var farPlaneCorner = [c.unproject(-1, 1, 1), c.unproject(1, 1, 1), c.unproject(1, -1, 1), c.unproject(-1, -1, 1)];
-
-		g.clear();
-		g.lineStyle(1, 0xffffff);
-
-		// Near Plane
-		var last = nearPlaneCorner[nearPlaneCorner.length - 1];
-		g.moveTo(last.x,last.y,last.z);
-		for( fc in nearPlaneCorner ) {
-			g.lineTo(fc.x, fc.y, fc.z);
-		}
-
-		// Far Plane
-		var last = farPlaneCorner[farPlaneCorner.length - 1];
-		g.moveTo(last.x,last.y,last.z);
-		for( fc in farPlaneCorner ) {
-			g.lineTo(fc.x, fc.y, fc.z);
-		}
-
-		// Connections
-		for( i in 0 ... 4 ) {
-			var np = nearPlaneCorner[i];
-			var fp = farPlaneCorner[i];
-			g.moveTo(np.x, np.y, np.z);
-			g.lineTo(fp.x, fp.y, fp.z);
-		}
-
-		// Connections to camera pos
-		g.lineStyle(1, 0xff0000);
-		for( i in 0 ... 4 ) {
-			var np = nearPlaneCorner[i];
-			g.moveTo(np.x, np.y, np.z);
-			g.lineTo(0, 0, 0);
-		}
-	}
-
-	override function makeInstance( ctx : hrt.prefab.Context ) {
-		ctx = ctx.clone(this);
-		ctx.local3d = new CameraSyncObject(ctx.local3d);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function updateInstance( ctx : hrt.prefab.Context, ?p ) {
-		super.updateInstance(ctx, p);
-		drawFrustum(ctx);
-		var cso = Std.downcast(ctx.local3d, CameraSyncObject);
-		if( cso != null ) {
-			cso.pos = getTransform().getPosition();
-			cso.dir = getTransform().front();
-			cso.fovY = fovY;
-			cso.zFar = zFar;
-			cso.zNear = zNear;
-			cso.enable = preview;
-		}
-	}
-
-	public function applyTo(c: h3d.Camera) {
-		var front = getTransform().front();
-		var ray = h3d.col.Ray.fromValues(x, y, z, front.x, front.y, front.z);
-		c.pos.set(x, y, z);
-		c.target = c.pos.add(front);
-
-		// this does not change camera rotation but allows for better navigation in editor
-		var plane = h3d.col.Plane.Z();
-		var pt = ray.intersect(plane);
-		if( pt != null && pt.sub(c.pos.toPoint()).length() > 1 )
-			c.target = pt.toVector();
-
-		c.fovY = fovY;
-		c.zFar = zFar;
-		c.zNear = zNear;
-	}
-
-	#if editor
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		if( !b ) {
-			preview = false;
-			updateInstance(ctx);
-		}
-		return false;
-	}
-
-	override function edit( ctx : hide.prefab.EditContext ) {
-		super.edit(ctx);
-
-		var props : hide.Element = ctx.properties.add(new hide.Element('
-			<div class="group" name="Camera">
-				<dl>
-					<dt>Fov Y</dt><dd><input type="range" min="0" max="180" field="fovY"/></dd>
-					<dt>Z Far</dt><dd><input type="range" min="0" max="1000" field="zFar"/></dd>
-					<dt>Z Near</dt><dd><input type="range" min="0" max="10" field="zNear"/></dd>
-					<dt></dt><dd><input class="copy" type="button" value="Copy Current"/></dd>
-					<dt></dt><dd><input class="apply" type="button" value="Apply" /></dd>
-					<dt></dt><dd><input class="reset" type="button" value="Reset" /></dd>
-				</dl>
-			</div>
-			<div class="group" name="Debug">
-				<dl>
-					<dt>Show Frustum</dt><dd><input type="checkbox" field="showFrustum"/></dd>
-					<div align="center">
-						<input type="button" value="Preview Mode : Disabled" class="editModeButton" />
-					</div>
-				</dl>
-			</div>
-		'),this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-
-		var editModeButton = props.find(".editModeButton");
-		editModeButton.click(function(_) {
-			preview = !preview;
-			editModeButton.val(preview ? "Preview Mode : Enabled" : "Preview Mode : Disabled");
-			editModeButton.toggleClass("editModeEnabled", preview);
-			updateInstance(ctx.getContext(this));
-		});
-
-		props.find(".copy").click(function(e) {
-			var cam = ctx.scene.s3d.camera;
-			ctx.makeChanges(this, function() {
-				var q = new h3d.Quat();
-				q.initDirection(cam.target.sub(cam.pos));
-				var angles = q.toEuler();
-				this.rotationX = hxd.Math.fmt(angles.x * 180 / Math.PI);
-				this.rotationY = hxd.Math.fmt(angles.y * 180 / Math.PI);
-				this.rotationZ = hxd.Math.fmt(angles.z * 180 / Math.PI);
-				this.scaleX = this.scaleY = this.scaleZ = 1;
-				this.x = hxd.Math.fmt(cam.pos.x);
-				this.y = hxd.Math.fmt(cam.pos.y);
-				this.z = hxd.Math.fmt(cam.pos.z);
-				this.zFar = cam.zFar;
-				this.zNear = cam.zNear;
-				this.fovY = cam.fovY;
-			});
-		});
-
-
-		props.find(".apply").click(function(e) {
-			applyTo(ctx.scene.s3d.camera);
-			ctx.scene.editor.cameraController.lockZPlanes = true;
-			ctx.scene.editor.cameraController.loadFromCamera();
-		});
-
-		props.find(".reset").click(function(e) {
-			ctx.scene.editor.resetCamera();
-		});
-	}
-
-	override function getHideProps() : hide.prefab.HideProps {
-		return { icon : "video-camera", name : "Camera" };
-	}
-	#end
-
-	static var _ = Library.register("camera", Camera);
-
-}

+ 0 - 62
hrt/prefab/l3d/Constraint.hx

@@ -1,62 +0,0 @@
-package hrt.prefab.l3d;
-
-class Constraint extends Prefab {
-
-	@: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 ) {
-		var srcObj = root.getObjectByName(object.split(".").pop());
-		var targetObj = root.getObjectByName(target.split(".").pop());
-		if( srcObj != null && targetObj != null ){
-			srcObj.follow = targetObj;
-			srcObj.followPositionOnly = positionOnly;
-		}
-		return srcObj;
-	}
-
-	override function makeInstance( ctx : Context ) {
-		if(!enabled) return ctx;
-		var srcObj = ctx.locateObject(object);
-		var targetObj = ctx.locateObject(target);
-		if( srcObj != null && targetObj != null ){
-			srcObj.follow = targetObj;
-			srcObj.followPositionOnly = positionOnly;
-		}
-		return ctx;
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { icon : "lock", name : "Constraint" };
-	}
-
-	override function edit(ctx:EditContext) {
-		var curObj = ctx.rootContext.locateObject(object);
-		var props = ctx.properties.add(new hide.Element('
-			<dl>
-				<dt>Source</dt><dd><select field="object"><option value="">-- Choose --</option></select>
-				<dt>Target</dt><dd><select field="target"><option value="">-- Choose --</option></select>
-				<dt>Position Only</dt><dd><input type="checkbox" field="positionOnly"/></dd>
-			</dl>
-		'),this, function(_) {
-			if( curObj != null ) curObj.follow = null;
-			makeInstance(ctx.rootContext);
-			curObj = ctx.rootContext.locateObject(object);
-		});
-
-		for( select in [props.find("[field=object]"), props.find("[field=target]")] ) {
-			for( path in ctx.getNamedObjects() ) {
-				var parts = path.split(".");
-				var opt = new hide.Element("<option>").attr("value", path).html([for( p in 1...parts.length ) "&nbsp; "].join("") + parts.pop());
-				select.append(opt);
-			}
-			select.val(Reflect.field(this, select.attr("field")));
-		}
-	}
-	#end
-
-	static var _ = Library.register("constraint", Constraint);
-
-}

+ 0 - 233
hrt/prefab/l3d/Decal.hx

@@ -1,233 +0,0 @@
-package hrt.prefab.l3d;
-
-enum abstract DecalMode(String) {
-	var Default;
-	var BeforeTonemapping;
-	var AfterTonemapping;
-	var Terrain;
-}
-
-class Decal extends Object3D {
-
-	@:s var albedoMap : String;
-	@:s var normalMap : String;
-	@:s var pbrMap : String;
-	@:s var albedoStrength : Float = 1.0;
-	@:s var normalStrength: Float = 1.0;
-	@:s var pbrStrength: Float = 1.0;
-	@:s var fadePower : Float = 1.0;
-	@:s var fadeStart : Float = 0;
-	@:s var fadeEnd : Float = 1.0;
-	@:s var emissive : Float = 0.0;
-	@:s var renderMode : DecalMode = Default;
-	@:s var centered : Bool = true;
-	@:s var autoAlpha : Bool = true;
-	@:c var blendMode : h2d.BlendMode = Alpha;
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		if(blendMode != Alpha) obj.blendMode = blendMode.getIndex();
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		blendMode = obj.blendMode != null ? h2d.BlendMode.createByIndex(obj.blendMode) : Alpha;
-	}
-
-	override function makeInstance(ctx:Context) : Context {
-		ctx = ctx.clone(this);
-		var mesh = new h3d.scene.pbr.Decal(h3d.prim.Cube.defaultUnitCube(), ctx.local3d);
-
-		switch (renderMode) {
-			case Default, Terrain:
-				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalPBR);
-				if( shader == null ) {
-					shader = new h3d.shader.pbr.VolumeDecal.DecalPBR();
-					mesh.material.mainPass.addShader(shader);
-				}
-				mesh.material.mainPass.setPassName(renderMode == Default ? "decal" : "terrainDecal");
-			case BeforeTonemapping:
-				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalOverlay);
-				if( shader == null ) {
-					shader = new h3d.shader.pbr.VolumeDecal.DecalOverlay();
-					mesh.material.mainPass.addShader(shader);
-				}
-				mesh.material.mainPass.setPassName("beforeTonemappingDecal");
-			case AfterTonemapping:
-				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalOverlay);
-				if( shader == null ) {
-					shader = new h3d.shader.pbr.VolumeDecal.DecalOverlay();
-					mesh.material.mainPass.addShader(shader);
-				}
-				mesh.material.mainPass.setPassName("afterTonemappingDecal");
-		}
-
-		mesh.material.mainPass.depthWrite = false;
-		mesh.material.mainPass.depthTest = GreaterEqual;
-		mesh.material.mainPass.culling = Front;
-		mesh.material.shadows = false;
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	public function updateRenderParams(ctx) {
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
-		mesh.material.mainPass.setBlendMode(blendMode);
-		switch (renderMode) {
-			case Default, Terrain:
-				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalPBR);
-				if( shader != null ){
-					shader.albedoTexture = albedoMap != null ? ctx.loadTexture(albedoMap) : null;
-					shader.normalTexture = normalMap != null ? ctx.loadTexture(normalMap) : null;
-					if(shader.albedoTexture != null) shader.albedoTexture.wrap = Repeat;
-					if(shader.normalTexture != null) shader.normalTexture.wrap = Repeat;
-					shader.albedoStrength = albedoStrength;
-					shader.normalStrength = normalStrength;
-					shader.pbrStrength = pbrStrength;
-					shader.USE_ALBEDO = albedoStrength != 0&& shader.albedoTexture != null;
-					shader.USE_NORMAL = normalStrength != 0 && shader.normalTexture != null;
-					shader.CENTERED = centered;
-					shader.fadePower = fadePower;
-					shader.fadeStart = fadeStart;
-					shader.fadeEnd = fadeEnd;
-				}
-				var pbrTexture = pbrMap != null ? ctx.loadTexture(pbrMap) : null;
-				if( pbrTexture != null ) {
-					var propsTexture = mesh.material.mainPass.getShader(h3d.shader.pbr.PropsTexture);
-					if( propsTexture == null ) 
-						propsTexture = mesh.material.mainPass.addShader(new h3d.shader.pbr.PropsTexture());
-					propsTexture.texture = pbrTexture;
-					propsTexture.texture.wrap = Repeat;
-				}
-				else {
-					mesh.material.mainPass.removeShader(mesh.material.mainPass.getShader( h3d.shader.pbr.PropsTexture));
-				}
-			case BeforeTonemapping, AfterTonemapping:
-				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalOverlay);
-				if( shader != null ){
-					shader.colorTexture = albedoMap != null ? ctx.loadTexture(albedoMap) : null;
-					if(shader.colorTexture != null) shader.colorTexture.wrap = Repeat;
-					shader.CENTERED = centered;
-					shader.GAMMA_CORRECT = renderMode == BeforeTonemapping;
-					shader.AUTO_ALPHA = autoAlpha;
-					shader.fadePower = fadePower;
-					shader.fadeStart = fadeStart;
-					shader.fadeEnd = fadeEnd;
-					shader.emissive = emissive;
-				}
-		}
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		super.updateInstance(ctx,propName);
-		updateRenderParams(ctx);
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { icon : "paint-brush", name : "Decal" };
-	}
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		if( b ) {
-			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 {
-			clearSelection( ctx );
-		}
-		return true;
-	}
-
-	function clearSelection( ctx : Context ) {
-		var obj = ctx.shared.getSelfObject(this);
-		if(obj == null) return;
-		var objs = obj.findAll( o -> if(o.name == "_highlight") o else null );
-		for( o in objs )
-			o.remove();
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var pbrParams = '<dt>Albedo</dt><dd><input type="texturepath" field="albedoMap"/>
-					<br/><input type="range" min="0" max="1" field="albedoStrength"/></dd>
-
-					<dt>Normal</dt><dd><input type="texturepath" field="normalMap"/>
-					<br/><input type="range" min="0" max="1" field="normalStrength"/></dd>
-
-					<dt>PBR</dt><dd><input type="texturepath" field="pbrMap"/>
-					<br/><input type="range" min="0" max="1" field="pbrStrength"/></dd>';
-
-		var overlayParams = '<dt>Color</dt><dd><input type="texturepath" field="albedoMap"/></dd>
-						<dt>Emissive</dt><dd> <input type="range" min="0" max="10" field="emissive"/></dd>
-						<dt>AutoAlpha</dt><dd><input type="checkbox" field="autoAlpha"/></dd>';
-
-		var params = switch (renderMode) {
-			case Default, Terrain: pbrParams;
-			case BeforeTonemapping: overlayParams;
-			case AfterTonemapping: overlayParams;
-		}
-
-		function refreshProps() {
-			var props = ctx.properties.add(new hide.Element('
-			<div class="decal">
-				<div class="group" name="Decal">
-					<dl>
-						<dt>Centered</dt><dd><input type="checkbox" field="centered"/></dd>'
-						+ params +
-						'<dt>Render Mode</dt>
-						<dd><select field="renderMode">
-							<option value="Default">Default</option>
-							<option value="BeforeTonemapping">Before Tonemapping</option>
-							<option value="AfterTonemapping">After Tonemapping</option>
-							<option value="Terrain">Terrain</option>
-						</select></dd>
-
-						<dt>Blend Mode</dt>
-						<dd><select field="blendMode">
-							<option value="Alpha">Alpha</option>
-							<option value="Add">Add</option>
-							<option value="Multiply">Multiply</option>
-						</select></dd>
-					</dl>
-				</div>
-				<div class="group" name="Fade">
-					<dt>FadePower</dt><dd> <input type="range" min="0" max="3" field="fadePower"/></dd>
-					<dt>Start</dt><dd> <input type="range" min="0" max="1" field="fadeStart"/></dd>
-					<dt>End</dt><dd> <input type="range" min="0" max="1" field="fadeEnd"/></dd>
-				</div>
-			</div>
-			'),this, function(pname) {
-				if( pname == "renderMode" ) {
-					clearSelection( ctx.rootContext );
-					ctx.rebuildPrefab(this);
-					ctx.rebuildProperties();
-				}
-				else
-					ctx.onChange(this, pname);
-			});
-		}
-
-		refreshProps();
-	}
-	#end
-
-	static var _ = Library.register("advancedDecal", Decal);
-
-}

+ 0 - 185
hrt/prefab/l3d/Environment.hx

@@ -1,185 +0,0 @@
-package hrt.prefab.l3d;
-
-
-@:access(h3d.scene.pbr.Environment)
-class Environment extends Object3D {
-
-	@:s public var power : Float = 1.0;
-	@:s public var hdrMax : Float = 10.0;
-	@:s public var rotation : Float = 0.0;
-	@:s public var sampleBits : Int = 12;
-	@:s public var diffSize : Int = 64;
-	@:s public var specSize : Int = 512;
-	@:s public var ignoredSpecLevels : Int = 1;
-
-	@:s var sourceMapPath : String;
-	@:s var configName : String;
-	var env : h3d.scene.pbr.Environment;
-
-	public function new( ?parent ) {
-		super(parent);
-		type = "environment";
-	}
-
-	function loadFromBinary() {
-		try {
-			env.dispose();
-			env.diffuse = hxd.res.Loader.currentInstance.load(getBinaryPath(true)).toImage().toTexture();
-			env.specular = hxd.res.Loader.currentInstance.load(getBinaryPath(false)).toImage().toTexture();
-			env.specular.mipMap = Linear;
-			env.specLevels = env.getMipLevels() - ignoredSpecLevels;
-			return true;
-		} catch( e : hxd.res.NotFound ) {
-			return false;
-		}
-	}
-
-	function getBinaryPath( diffuse : Bool ) {
-		var path = new haxe.io.Path(sourceMapPath);
-		if( configName != null )
-			path.file += "-" + configName;
-		path.ext = diffuse ? "envd" : "envs";
-		return path.toString();
-	}
-
-	function saveToBinary() {
-		#if (hl || hxnodejs)
-		var fs = cast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem);
-		if( fs == null ) return;
-		var diffuse = hxd.Pixels.toDDSLayers([for( i in 0...6 ) env.diffuse.capturePixels(i)],true);
-		sys.io.File.saveBytes(fs.baseDir + getBinaryPath(true), diffuse);
-		var specular = hxd.Pixels.toDDSLayers([for( i in 0...6 ) for( mip in 0...env.getMipLevels() ) env.specular.capturePixels(i,mip)],true);
-		sys.io.File.saveBytes(fs.baseDir + getBinaryPath(false), specular);
-		#end
-	}
-
-	override function makeInstance( ctx : Context ) : Context {
-		super.makeInstance(ctx);
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-
-		var sourceMap = sourceMapPath != null ? ctx.loadTexture(sourceMapPath) : null;
-		if( sourceMap == null )
-			return;
-
-		#if editor
-		if( sourceMap.flags.has(Loading) ) {
-			haxe.Timer.delay(function() {
-				ctx.setCurrent();
-				if( h3d.Engine.getCurrent().driver == null ) return; // was disposed
-				updateInstance(ctx,propName);
-			},100);
-			return;
-		}
-		#end
-
-		var needLoad = false;
-		if( env == null )
-			env = new h3d.scene.pbr.Environment(null);
-
-		if( configName != null ) {
-			configName = StringTools.trim(configName);
-			if( configName == "" ) configName = null;
-		}
-
-		if( env.source != sourceMap ) {
-			env.source = sourceMap;
-			needLoad = true;
-		}
-
-		env.specSize = specSize;
-		env.diffSize = diffSize;
-		env.sampleBits = sampleBits;
-		env.ignoredSpecLevels = ignoredSpecLevels;
-		env.hdrMax = hdrMax;
-
-		env.rotation = hxd.Math.degToRad(rotation);
-		env.power = power;
-
-		if( propName == "force" || (needLoad && !loadFromBinary()) ) {
-			env.dispose();
-			env.specular = null;
-			env.diffuse = null;
-			env.compute();
-			saveToBinary();
-		}
-
-		var scene = ctx.local3d.getScene();
-		// Auto Apply on change
-		if( scene != null )
-			applyToRenderer(scene.renderer);
-	}
-
-	public function applyToRenderer( r : h3d.scene.Renderer) {
-		var r = Std.downcast(r, h3d.scene.pbr.Renderer);
-		if( r != null )
-			r.env = env;
-	}
-
-	#if editor
-
-	override function getHideProps() : HideProps {
-		return { icon : "sun-o", name : "Environment" };
-	}
-
-	override function edit( ctx : EditContext ) {
-		// super.edit(ctx);
-
-		var props = new hide.Element('
-			<div class="group" name="Environment">
-				<div align="center" >
-					<input type="button" value="Set Current" class="apply" />
-				</div>
-				<dl>
-					<dt>SkyBox</dt><dd><input type="texturepath" field="sourceMapPath"/></dd>
-					<dt>Rotation</dt><dd><input type="range" min="0" max="360" field="rotation"/></dd>
-					<dt>Power</dt><dd><input type="range" min="0" max="2" field="power"/></dd>
-				</dl>
-			</div>
-			<div class="group closed" name="Generation">
-				<dl>
-					<dt>Diffuse</dt><dd><input type="range" min="1" max="512" step="1" field="diffSize"/></dd>
-					<dt>Specular</dt><dd><input type="range" min="1" max="2048" step="1" field="specSize"/></dd>
-					<dt>Sample Count</dt><dd><input type="range" min="1" max="12" step="1" field="sampleBits"/></dd>
-					<dt>Ignored Spec Levels</dt><dd><input type="range" min="0" max="3" step="1" field="ignoredSpecLevels"/></dd>
-					<dt>HDR Max</dt><dd><input type="range" min="0" max="100" field="hdrMax"/></dd>
-					<dt>Config Name</dt><dd><input type="text" field="configName"/></dd>
-					<dt>&nbsp;</dt><dd><input type="button" class="compute" value="Compute"/></dd>
-					<dt>View</dt><dd>
-						<input type="button" style="width:90px" class="showDif" value="Diffuse"/>
-						<input type="button" style="width:90px" class="showSpec" value="Specular"/>
-					</dd>
-				</dl>
-			</div>
-		');
-
-		var applyButton = props.find(".apply");
-		applyButton.click(function(_) {
-			applyToRenderer(ctx.rootContext.local3d.getScene().renderer);
-		});
-
-		props.find(".compute").click(function(_) {
-			ctx.onChange(this,"force");
-		});
-
-		props.find(".showDif").click(function(_) {
-			ctx.ide.openFile(getBinaryPath(true));
-		});
-
-		props.find(".showSpec").click(function(_) {
-			ctx.ide.openFile(getBinaryPath(false));
-		});
-
-		ctx.properties.add(props, this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	#end
-
-	static var _ = Library.register("environment", Environment);
-}

+ 0 - 118
hrt/prefab/l3d/GameController.hx

@@ -1,118 +0,0 @@
-package hrt.prefab.l3d;
-
-class GameController extends Object3D {
-
-	@:s public var moveSpeed : Float = 1.;
-	@:s public var followGround : Bool = true;
-	@:s public var cameraFollowGround : Bool = true;
-	@:s public var startFullScreen : Bool = true;
-
-	#if editor
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = super.makeInstance(ctx);
-		ctx.local3d.ignoreParentTransform = true;
-		return ctx;
-	}
-
-	override function edit(ctx:EditContext) {
-		super.edit(ctx);
-
-		ctx.properties.add(new hide.Element('
-			<div class="group" name="Control">
-				<dl>
-					<dt>Move Speed</dt><dd><input type="range" min="0" max="10" field="moveSpeed"/></dd>
-					<dt>Follow Ground</dt><dd><input type="checkbox" field="followGround"/></dd>
-					<dt>Camera Follow Ground</dt><dd><input type="checkbox" field="cameraFollowGround"/></dd>
-					<dt>Start Full Screen</dt><dd><input type="checkbox" field="startFullScreen"/></dd>
-				</dl>
-			</div>
-		'),this);
-
-		var active = false;
-		var lctx = ctx.getContext(this);
-		var obj = lctx.local3d;
-		var camSave = null;
-		var dummy : h3d.scene.Object = null;
-		var cam = ctx.scene.s3d.camera;
-
-		function selectRec( p : Prefab, b : Bool ) {
-			if( !p.setSelected(ctx.getContext(p), b) )
-				return;
-			for( c in p.children )
-				selectRec(c, b);
-		}
-
-		function restore() {
-			// restore position
-			obj.setTransform(getTransform());
-			// restore camera
-			cam.pos.load(camSave.pos);
-			cam.target.load(camSave.target);
-			cam.zFar = camSave.zFar;
-			cam.fovY = camSave.fovY;
-			ctx.scene.editor.cameraController.loadFromCamera();
-			@:privateAccess ctx.scene.editor.showGizmo = true;
-			if( dummy != null ) dummy.remove();
-			if( startFullScreen ) ctx.scene.editor.setFullScreen(false);
-			selectRec(this, true);
-		}
-
-		function onUpdate( dt : Float ) {
-			var pad = ctx.ide.gamePad;
-			var force = false;
-			if( pad.isPressed(pad.config.start) ) {
-				active = !active;
-				if( !active ) {
-					restore();
-				} else {
-					@:privateAccess ctx.scene.editor.showGizmo = false;
-					camSave = { pos : cam.pos.clone(), target : cam.target.clone(), fovY : cam.fovY, zFar : cam.zFar };
-					var camView = @:privateAccess ctx.scene.editor.sceneData.get(Camera);
-					if( camView != null )
-						camView.applyTo(cam);
-					if( obj.numChildren == 0 )
-						dummy = new h3d.scene.Box(obj);
-					if( startFullScreen )
-						ctx.scene.editor.setFullScreen(true);
-					force = true;
-					selectRec(this, false);
-				}
-			}
-			if( !active )
-				return;
-
-			if( !force && pad.xAxis == 0 && pad.yAxis == 0 )
-				return;
-
-			if( pad.isDown(pad.config.A) ) dt *= 10;
-
-
-			var delta = cam.pos.sub(cam.target);
-			var ax = cam.getViewDirection(1,0,0);
-			ax.z = 0;
-			ax.normalize();
-			obj.x += (pad.xAxis * ax.x - pad.yAxis * ax.y) * dt * moveSpeed;
-			obj.y += (pad.xAxis * ax.y + pad.yAxis * ax.x) * dt * moveSpeed;
-			obj.setRotation(0, 0, Math.atan2(pad.yAxis, pad.xAxis));
-
-			var gz = ctx.scene.editor.getZ(obj.x, obj.y);
-			if( followGround )
-				obj.z = gz;
-			cam.target.set(obj.x, obj.y, cameraFollowGround ? gz : 0);
-			cam.pos = cam.target.add(delta);
-			cam.update();
-			ctx.scene.editor.cameraController.loadFromCamera();
-		}
-
-		ctx.scene.addListener(onUpdate);
-		ctx.cleanups.push(() -> {
-			if( active ) restore();
-			ctx.scene.removeListener(onUpdate);
-		});
-	}
-	#end
-
-	static var _ = Library.register("gamectrl", GameController);
-
-}

+ 0 - 931
hrt/prefab/l3d/HeightMap.hx

@@ -1,931 +0,0 @@
-package hrt.prefab.l3d;
-
-enum abstract HeightMapTextureKind(String) {
-	var Albedo = "albedo";
-	var Height = "height";
-	var Normal = "normal";
-	var SplatMap = "splatmap";
-}
-
-class HeightMapShader extends hxsl.Shader {
-	static var SRC = {
-		@:import h3d.shader.BaseMesh;
-
-		@const var hasHeight : Bool;
-		@const var hasNormal : Bool;
-
-		@param var heightMap : Sampler2D;
-		@param var heightMapFrag : Sampler2D;
-		@param var normalMap : Sampler2D;
-		@param var heightScale : Float;
-		@param var heightOffset : Vec2;
-		@param var normalScale : Float;
-		@param var cellSize : Vec2;
-		@const var heightFlipX : Bool;
-		@const var heightFlipY : Bool;
-
-		@const var SplatCount : Int;
-		@const var AlbedoCount : Int;
-		@const(8) var SplatMode : Int;
-		@const var albedoIsArray : Bool;
-		@param var albedoTiling : Float;
-		@param var albedos : Array<Sampler2D,AlbedoCount>;
-		@param var albedoArray : Sampler2DArray;
-		@param var albedoIndexes : Array<Vec4,AlbedoCount>;
-		@param var splats : Array<Sampler2D,SplatCount>;
-
-		@input var input2 : { uv : Vec2 };
-
-		@const var hasAlbedoProps : Bool;
-		@param var albedoProps : Array<Vec4,AlbedoCount>;
-		@param var albedoGamma : Float;
-
-		@const var hasAlbedoNormals : Bool;
-		@param var albedoNormals : Sampler2DArray;
-		@param var albedoNormalsStrength : Float;
-		@param var albedoRoughness : Float;
-
-		var calculatedUV : Vec2;
-		var heightUV : Vec2;
-		var roughness : Float;
-
-		function getPoint( dx : Float, dy : Float ) : Vec3 {
-			var v = vec2(dx,dy);
-			return vec3( cellSize * v , heightMapFrag.get(heightUV + heightOffset * v).r * heightScale - relativePosition.z);
-		}
-
-		function vertex() {
-			calculatedUV = input2.uv;
-			heightUV = calculatedUV;
-			if( heightFlipX ) heightUV.x = 1 - heightUV.x;
-			if( heightFlipY ) heightUV.y = 1 - heightUV.y;
-			if( hasHeight ) {
-				var z = heightMap.get(heightUV).x * heightScale;
-				relativePosition.z = z;
-			}
-		}
-
-		function setNormal(n:Vec3) {
-			transformedNormal = (n.normalize() * global.modelView.mat3()).normalize();
-		}
-
-		function getAlbedo( index : Int, uv : Vec2 ) : Vec4 {
-			var color = albedoIsArray ? albedoArray.get(vec3(uv,albedoIndexes[index].r)) : albedos[index].get(uv);
-			if( albedoGamma != 1 )
-				color = color.pow(albedoGamma.xxxx);
-			return color;
-		}
-
-		function splat( index : Int, amount : Float ) : Vec4 {
-			if( (!albedoIsArray || index >= AlbedoCount) || amount <= 0 )
-				return vec4(0.);
-			else if( hasAlbedoProps ) {
-				var p = albedoProps[index];
-				return getAlbedo(index, calculatedUV * p.w) * vec4(p.rgb,1) * amount;
-			} else
-				return getAlbedo(index, calculatedUV * albedoTiling) * amount;
-		}
-
-		function __init__fragment() {
-			if( hasNormal ) {
-				var n = unpackNormal(normalMap.get(calculatedUV));
-				n = n.normalize();
-				n.xy *= normalScale;
-				setNormal(n);
-			} else {
-				var px0 = getPoint(-1,0);
-				var py0 = getPoint(0, -1);
-				var px1 = getPoint(1, 0);
-				var py1 = getPoint(0, 1);
-				var n = px1.cross(py1) + py1.cross(px0) + px0.cross(py0) + py0.cross(px1);
-				n.xy *= normalScale;
-				setNormal(n);
-			}
-			if( SplatCount > 0 ) {
-				var color = vec4(0.);
-				@unroll for( i in 0...SplatCount ) {
-					var s = splats[i].getLod(calculatedUV,0);
-					switch( SplatMode ) {
-					case 0:
-						color += splat(i*4, s.r);
-						color += splat(i*4+1, s.g);
-						color += splat(i*4+2, s.b);
-						color += splat(i*4+3, s.a);
-					case 1:
-						color += splat(i*3, s.r);
-						color += splat(i*3+1, s.g);
-						color += splat(i*3+2, s.b);
-					case 2:
-						var i1 = int(s.r*256);
-						var i2 = int(s.g*256);
-						color += splat(i1,s.b);
-						color += splat(i2,s.a);
-						if( hasAlbedoNormals ) {
-							var uv1 = calculatedUV * albedoProps[i1].w;
-							var uv2 = calculatedUV * albedoProps[i2].w;
-							var normal1 = albedoNormals.get(vec3(uv1,albedoIndexes[i1].r));
-							var normal2 = albedoNormals.get(vec3(uv2,albedoIndexes[i2].r));
-							var med = mix(normal1,normal2,s.a);
-							var nf = unpackNormal(med);
-							nf.xy *= albedoNormalsStrength;
-							nf = nf.normalize();
-
-							var n = transformedNormal;
-							var tanX = vec3(1,0,0);
-							var tanY = transformedNormal.cross(tanX);
-							transformedNormal = (nf.x * tanX + nf.y * tanY + nf.z * n).normalize();
-
-							roughness *= 1 - med.a * med.a * albedoRoughness;
-						}
-					}
-				}
-				color.a = 1;
-				pixelColor = color;
-			} else {
-				pixelColor = getAlbedo(0, calculatedUV);
-			}
-		}
-
-	};
-}
-
-class HeightMapTile {
-
-	public var tx(default,null) : Int;
-	public var ty(default,null) : Int;
-	public var bounds(default, null) : h3d.col.Bounds;
-	public var root(default,null) : h3d.scene.Mesh;
-
-	var hmap : HeightMap;
-	var height : hxd.Pixels;
-
-	public function new(hmap, tx, ty) {
-		this.hmap = hmap;
-		this.tx = tx;
-		this.ty = ty;
-		bounds = h3d.col.Bounds.fromValues(tx * hmap.size, ty * hmap.size, hmap.minZ, hmap.size, hmap.size, hmap.maxZ - hmap.minZ);
-	}
-
-	public function remove() {
-		if( root != null ) {
-			root.remove();
-			root = null;
-		}
-	}
-
-	public function isEmpty() {
-		if( tx == 0 && ty == 0 && hmap.sizeX == 0 && hmap.sizeY == 0 && !hmap.autoSize )
-			return false;
-		getHeight();
-		return height.width == 1;
-	}
-
-	public function getHeight() {
-		if( height == null ) {
-			for( t in hmap.textures )
-				if( t.kind == Height && t.enable && t.path != null ) {
-					var path = resolveTexturePath(t.path);
-					if( path == t.path && (tx != 0 || ty != 0) ) continue;
-					height = try hxd.res.Loader.currentInstance.load(path).toImage().getPixels() catch( e : hxd.res.NotFound )
-					#if editor try hxd.res.Any.fromBytes(path, sys.io.File.getBytes(hide.Ide.inst.getPath(path))).toImage().getPixels() catch( e : Dynamic ) #end
-					null;
-					break;
-				}
-			if( height == null ) height = hxd.Pixels.alloc(1, 1, R32F);
-			height.convert(R32F);
-		}
-		return height;
-	}
-
-	@:access(hrt.prefab.l3d.HeightMapMesh)
-	public function create(mesh:HeightMapMesh) {
-		if( root != null ) throw "assert";
-		root = new h3d.scene.Mesh(mesh.grid);
-		root.material.mainPass.setPassName("terrain");
-		root.material.shadows = false;
-		root.x = hmap.size * tx;
-		root.y = hmap.size * ty;
-
-		var shadows = new h3d.scene.Mesh(mesh.shadowGrid, root);
-		shadows.material.shadows = false;
-		shadows.material.mainPass.setPassName("shadow");
-		@:bypassAccessor shadows.material.castShadows = true; // trigger DirShadowMap
-
-		inline function getTextures(k) return hmap.getTextures(k,tx,ty);
-		var htex = getTextures(Height)[0];
-		var splat = getTextures(SplatMap);
-		var normal = getTextures(Normal)[0];
-
-		var shader = root.material.mainPass.addShader(new HeightMapShader());
-		shadows.material.mainPass.addShader(shader);
-		shader.hasHeight = htex != null;
-		shader.heightMap = shader.heightMapFrag = htex;
-		shader.hasNormal = normal != null;
-		shader.normalMap = normal;
-		shader.heightScale = hmap.getHScale();
-		shader.normalScale = hmap.heightScale * hmap.normalScale;
-		var qsize = Math.pow(2,4 - hmap.quality);
-		shader.cellSize.set(mesh.grid.cellWidth / qsize,mesh.grid.cellHeight / qsize);
-		shader.heightFlipX = hmap.heightFlipX;
-		shader.heightFlipY = hmap.heightFlipY;
-		if( htex != null ) shader.heightOffset.set( (hmap.heightFlipX ? -1 : 1) / htex.width, (hmap.heightFlipY ? -1 : 1) / htex.height);
-
-		shader.SplatCount = splat.length;
-		shader.albedoIsArray = false;
-		shader.SplatMode = switch( hmap.splatMode ) {
-		case Weights3: 0;
-		case Weights4: 1;
-		case I1I2W1W2: shader.albedoIsArray = true; 2;
-		}
-
-		shader.albedoTiling = hmap.albedoTiling;
-		shader.albedoGamma = hmap.albedoGamma;
-		shader.splats = splat;
-		for( t in splat ) t.filter = hmap.splatNearest ? Nearest : Linear;
-
-		if( shader.albedoIsArray ) {
-			var arr = hmap.getTextureArray(Albedo);
-			shader.albedoArray = arr.texture;
-			shader.albedoIndexes = [for( i in arr.indexes ) new h3d.Vector(i)];
-			shader.AlbedoCount = arr.indexes.length;
-			if( hmap.albedoNormals > 0 ) {
-				shader.hasAlbedoNormals = true;
-				shader.albedoNormals = hmap.getTextureArray(Normal).texture;
-				shader.albedoNormalsStrength = hmap.albedoNormals;
-				shader.albedoRoughness = hmap.albedoRoughness;
-			}
-		} else {
-			var albedo = getTextures(Albedo);
-			if( albedo.length == 0 )
-				albedo = [h3d.mat.Texture.fromColor(0x808080)];
-			shader.AlbedoCount = albedo.length;
-			shader.albedos = albedo;
-		}
-
-		shader.albedoProps = hmap.getAlbedoProps();
-		shader.hasAlbedoProps = shader.albedoProps.length > 0;
-	}
-
-	inline function resolveTexturePath( path : String ) {
-		return hmap.resolveTexturePath(path, tx, ty);
-	}
-
-}
-
-class HeightMapMesh extends h3d.scene.Object {
-
-	var hmap : HeightMap;
-	var grid : HeightGrid;
-	var shadowGrid : HeightGrid;
-
-	public function new(hmap, ?parent) {
-		super(parent);
-		this.hmap = hmap;
-	}
-
-	override function onRemove() {
-		super.onRemove();
-		hmap.cleanCache();
-	}
-
-	override function sync(ctx:h3d.scene.RenderContext) {
-		super.sync(ctx);
-
-		if( hmap.sizeX == 0 && hmap.sizeY == 0 && !hmap.autoSize ) {
-			checkTile(ctx,0,0);
-			return;
-		}
-
-		var r = h3d.col.Ray.fromPoints(ctx.camera.unproject(0,0,0).toPoint(), ctx.camera.unproject(0,0,1).toPoint());
-		var pt0 = r.intersect(h3d.col.Plane.Z(0));
-		var x0 = Math.round(pt0.x / hmap.size);
-		var y0 = Math.round(pt0.y / hmap.size);
-
-		// spiral for-loop
-		var dx = 0, dy = 0, d = 1, m = 1, out = 0;
-		while( true ) {
-			var xyOut = true;
-			while( m > 2 * dx * d ) {
-				if( checkTile(ctx,dx+x0,dy+y0) ) xyOut = false;
-				dx += d;
-			}
-			while( m > 2 * dy * d ) {
-				if( checkTile(ctx,dx+x0,dy+y0) ) xyOut = false;
-				dy += d;
-			}
-			if( xyOut ) {
-				out++;
-				if( out == 2 ) break;
-			} else
-				out = 0;
-			d = -d;
-			m++;
-		}
-	}
-
-	public dynamic function onTileReady( t : HeightMapTile ) {
-	}
-
-	public dynamic function isAssetFiltered( obj : h3d.scene.World.WorldModel, pos : h3d.Matrix ) {
-		return false;
-	}
-
-	function checkTile( ctx : h3d.scene.RenderContext, x : Int, y : Int ) {
-		var t = hmap.getTile(x,y);
-		if( !ctx.camera.frustum.hasBounds(t.bounds) || t.isEmpty() ) {
-			if( t.root != null ) t.root.visible = false;
-			return x >= 0 && y >= 0 && x < hmap.sizeX && y < hmap.sizeY;
-		}
-		if( t.root != null )
-			t.root.visible = true;
-		else
-			initTile(t);
-		return true;
-	}
-
-	public function initTile( t : HeightMapTile ) {
-		if( t.root != null ) return;
-		t.create(this);
-		addChild(t.root);
-		onTileReady(t);
-	}
-
-	public function init() {
-		var htex = hmap.getTextures(Height, 0, 0)[0];
-		var size = hmap.size;
-		var width = htex == null ? Std.int(size) : Math.ceil(htex.width * hmap.heightPrecision);
-		var height = htex == null ? Std.int(size) : Math.ceil(htex.height * hmap.heightPrecision);
-		var swidth = width >> (4 - hmap.shadowQuality);
-		var sheight = width >> (4 - hmap.shadowQuality);
-		width >>= (4 - hmap.quality);
-		height >>= (4 - hmap.quality);
-		if( width < 4 ) width = 4;
-		if( height < 4 ) height = 4;
-		var cw = size/width, ch = size/height;
-		if( grid == null || grid.width != width || grid.height != height || grid.cellWidth != cw || grid.cellHeight != ch ) {
-			grid = new HeightGrid(width,height,cw,ch);
-			grid.zMin = hmap.minZ;
-			grid.zMax = hmap.maxZ;
-			grid.addUVs();
-			grid.addNormals();
-		}
-		var cw = size/swidth, ch = size/sheight;
-		if( shadowGrid == null || shadowGrid.width != swidth || shadowGrid.height != sheight || shadowGrid.cellWidth != cw || shadowGrid.cellHeight != ch ) {
-			if( swidth == width )
-				shadowGrid = grid;
-			else {
-				shadowGrid = new HeightGrid(swidth,sheight,cw,ch);
-				shadowGrid.zMin = hmap.minZ;
-				shadowGrid.zMax = hmap.maxZ;
-				shadowGrid.addUVs();
-			}
-		}
-	}
-
-}
-
-enum abstract SplatMode(String) {
-	var Weights3;
-	var Weights4;
-	var I1I2W1W2;
-}
-
-@:allow(hrt.prefab.l3d)
-class HeightMap extends Object3D {
-
-	var tilesCache : Map<Int,HeightMapTile> = new Map();
-	var emptyTile : HeightMapTile;
-	@:c var textures : Array<{ path : String, kind : HeightMapTextureKind, enable : Bool, ?props : { color : Int, scale : Float } }> = [];
-	@:s var size = 128.;
-	@:s var heightScale = 0.2;
-	@:s var heightFlipX = false;
-	@:s var heightFlipY = false;
-	@:s var normalScale = 1.;
-	@:s var heightPrecision = 1.;
-	@:s var minZ = -10;
-	@:s var maxZ = 30;
-	@:s public var quality = 4;
-	@:s public var shadowQuality = 4;
-	@:s var sizeX = 0;
-	@:s var sizeY = 0;
-	@:s var autoSize = false;
-	@:s var albedoTiling = 1.;
-	@:s var albedoGamma = 1.;
-	@:s var albedoColorGamma = 1.;
-	@:s var splatNearest = false;
-	@:s var splatMode : SplatMode = Weights4;
-	@:s var albedoNormals : Float = 0.;
-	@:s var albedoRoughness : Float = 0.;
-
-	// todo : instead of storing the context, we should find a way to have a texture loader
-	var storedCtx : hrt.prefab.Context;
-	var albedoProps : Array<h3d.Vector>;
-	var texArrayCache : Map<HeightMapTextureKind, { texture : h3d.mat.TextureArray, indexes : Array<Int> }>;
-
-	override function save():{} {
-		var o : Dynamic = super.save();
-		o.textures = [for( t in textures ) {
-			var v : Dynamic = { path : t.path, kind : t.kind };
-			if( !t.enable ) v.enable = false;
-			if( t.props != null ) v.props = t.props;
-			v;
-		}];
-		return o;
-	}
-
-	override function load(obj:Dynamic) {
-		super.load(obj);
-		textures = [for( o in (obj.textures:Array<Dynamic>) ) { path : o.path, kind : o.kind, enable : o.enable == null ? true : o.enable, props : o.props }];
-	}
-
-	function getAlbedoProps() {
-		if( albedoProps != null )
-			return albedoProps;
-		var hasProps = false;
-		for( t in textures )
-			if( t.kind == Albedo && t.props != null )
-				hasProps = true;
-		if( !hasProps ) {
-			albedoProps = [];
-			return albedoProps;
-		}
-		albedoProps = [for( t in textures ) if( t.kind == Albedo ) t.props == null ? new h3d.Vector(1,1,1,albedoTiling) : {
-			var v = h3d.Vector.fromColor(t.props.color);
-			v.r = Math.pow(v.r,albedoColorGamma);
-			v.g = Math.pow(v.g,albedoColorGamma);
-			v.b = Math.pow(v.b,albedoColorGamma);
-			v.a = t.props.scale * albedoTiling;
-			v;
-		}];
-		return albedoProps;
-	}
-
-	public function getZ( x : Float, y : Float ) : Null<Float> {
-		var rx = x / size;
-		var ry = y / size;
-		var tx = Math.floor(rx);
-		var ty = Math.floor(ry);
-		var curMap = getTile(tx, ty).getHeight();
-		if( curMap == null )
-			return null;
-		var w = curMap.width;
-		var ix = Std.int( (rx - tx) * w );
-		var iy = Std.int( (ry - ty) * w );
-		var h = curMap.bytes.getFloat((ix+iy*w) << 2);
-		h *= getHScale();
-		return h;
-	}
-
-	override function localRayIntersection(ctx:Context, ray:h3d.col.Ray):Float {
-		if( ray.lz > 0 )
-			return -1; // only from top
-		if( ray.lx == 0 && ray.ly == 0 ) {
-			var z = getZ(ray.px, ray.py);
-			if( z == null || z > ray.pz ) return -1;
-			return ray.pz - z;
-		}
-		var dist = 0.;
-		if( ray.pz > maxZ ) {
-			if( ray.lz == 0 )
-				return -1;
-			dist = (maxZ - ray.pz) / ray.lz;
-		}
-		var pt = ray.getPoint(dist);
-		if( pt.z < minZ )
-			return -1;
-
-		var prim = @:privateAccess cast(ctx.local3d, HeightMapMesh).grid;
-		var m = hxd.Math.min(prim.cellWidth, prim.cellHeight) * 0.5;
-		var curX = -1, curY = -1, curMap = null, offX = 0., offY = 0., cw = 0., ch = 0.;
-		var prevH = pt.z;
-		var hscale = getHScale();
-
-		while( true ) {
-			pt.x += ray.lx * m;
-			pt.y += ray.ly * m;
-			pt.z += ray.lz * m;
-			if( pt.z < minZ )
-				return -1;
-			var px = Math.floor(pt.x / size);
-			var py = Math.floor(pt.y / size);
-			if( px != curX || py != curY ) {
-				curX = px;
-				curY = py;
-				offX = -px * size;
-				offY = -py * size;
-				var t = getTile(px, py);
-				curMap = t.getHeight();
-				if( t.isEmpty() )
-					curMap = null;
-				else {
-					cw = curMap.width / size;
-					ch = curMap.height / size;
-				}
-			}
-			if( curMap == null )
-				continue;
-			var ix = Std.int((pt.x + offX)*cw);
-			var iy = Std.int((pt.y + offY)*ch);
-			var h = curMap.bytes.getFloat( (ix + iy * curMap.width) << 2 );
-			h *= hscale;
-			if( pt.z < h ) {
-				// todo : fix interpolation using getZ dichotomy
-				var k = 1 - (prevH - (pt.z - ray.lz * m)) / (ray.lz * m - (h - prevH));
-				pt.x -= k * ray.lx * m;
-				pt.y -= k * ray.ly * m;
-				pt.z -= k * ray.lz * m;
-				return pt.sub(ray.getPos()).length();
-			}
-			prevH = h;
-		}
-		return -1;
-	}
-
-	function getTile( x : Int, y : Int ) {
-		if( (sizeX > 0 && sizeY > 0 && (x < 0 || y < 0 || x >= sizeX || y >= sizeY)) || (sizeX == 0 && sizeY == 0 && (x != 0 || y != 0) && !autoSize) ) {
-			if( emptyTile == null )
-				emptyTile = new HeightMapTile(this, -1, -1);
-			return emptyTile;
-		}
-		var id = x + y * 65535;
-		var t = tilesCache[id];
-		if( t != null )
-			return t;
-		t = new HeightMapTile(this, x, y);
-		tilesCache[id] = t;
-		return t;
-	}
-
-	function resolveTexturePath( path : String, tx : Int, ty : Int ) {
-		if( tx != 0 || ty != 0 ) {
-			var parts = path.split("0");
-			switch( parts.length ) {
-			case 2:
-				path = tx + parts[0] + ty + parts[1];
-			case 3:
-				path = parts[0] + tx + parts[1] + ty + parts[2];
-			default:
-				// pattern not recognized - should contain 2 zeroes
-			}
-		}
-		return path;
-	}
-
-	function getTextures( k : HeightMapTextureKind, tx : Int, ty : Int ) {
-		var tl = [];
-		for( t in textures )
-			if( t.kind == k && t.path != null && t.enable ) {
-				var path = resolveTexturePath(t.path,tx,ty);
-				tl.push(loadTexture(path));
-			}
-		return tl;
-	}
-
-	function cleanCache() {
-		if( texArrayCache == null ) return;
-		for( k in texArrayCache )
-			k.texture.dispose();
-		texArrayCache = null;
-	}
-
-	function getTextureArray( k : HeightMapTextureKind ) {
-		if( texArrayCache == null ) texArrayCache = new Map();
-		var arr = texArrayCache.get(k);
-		if( arr != null && !arr.texture.isDisposed() )
-			return arr;
-		var tl = switch( k ) {
-		case Albedo: getTextures(k, 0, 0);
-		case Normal:
-			var tl = [];
-			for( t in textures )
-				if( t.kind == Albedo && t.path != null && t.enable ) {
-					var path = new haxe.io.Path(t.path);
-					path.file = path.file.split("_Albedo").join("");
-					path.file += "_Normal";
-					tl.push(loadTexture(path.toString()));
-				}
-			tl;
-		default: throw "assert";
-		}
-		if( tl.length == 0 ) tl = [h3d.mat.Texture.fromColor(k == Normal ? 0x8080FF : 0xFF00FF)];
-		var indexes = [];
-		var layers = [];
-		for( t in tl ) {
-			var idx = layers.indexOf(t);
-			if( idx < 0 ) {
-				idx = layers.length;
-				layers.push(t);
-			}
-			indexes.push(idx);
-		}
-		var tex = new h3d.mat.TextureArray(layers[0].width, layers[0].height, layers.length, [Target], switch( layers[0].format ) {
-		case S3TC(_): RGBA;
-		case fmt: fmt;
-		});
-		tex.realloc = function() {
-			for( i => t in layers )
-				h3d.pass.Copy.run(t, tex, null, null, i);
-		};
-		tex.realloc();
-		tex.wrap = Repeat;
-		arr = { texture : tex, indexes : indexes };
-		texArrayCache.set(k, arr);
-		return arr;
-	}
-
-	function loadTexture( path : String ) {
-		return storedCtx.loadTexture(path);
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var mesh = new HeightMapMesh(this, ctx.local3d);
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		storedCtx = ctx;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String ) {
-
-		#if editor
-		if( (propName == "albedoTiling" || propName == "albedoColorGamma") && albedoProps != null ) {
-			updateAlbedoProps();
-			return;
-		}
-		#end
-
-		albedoProps = null;
-		cleanCache();
-		super.updateInstance(ctx, propName);
-
-		for( t in tilesCache )
-			t.remove();
-		tilesCache = new Map();
-		var mesh = cast(ctx.local3d,HeightMapMesh);
-		mesh.init();
-	}
-
-	function getHScale() {
-		return heightScale * size * 0.1;
-	}
-
-	#if editor
-
-	override function getHideProps() : HideProps {
-		return { icon : "industry", name : "HeightMap", isGround : true };
-	}
-
-	function updateAlbedoProps() {
-		var prev = albedoProps;
-		while( prev.length > 0 ) prev.pop();
-		albedoProps = null;
-		for( x in getAlbedoProps() )
-			prev.push(x);
-		albedoProps = prev;
-	}
-
-	override function edit(ectx:EditContext) {
-		super.edit(ectx);
-		var ctx = ectx.getContext(this);
-		var hasSplat = false;
-		for( t in textures )
-			if( t.kind == SplatMap ) {
-				hasSplat = true;
-				break;
-			}
-		var props = new hide.Element('
-		<div>
-			<div class="group" name="View">
-			<dl>
-				<dt>Size</dt><dd><input type="range" min="0" max="1000" value="128" field="size"/></dd>
-				<dt>Height Scale</dt><dd><input type="range" min="0" max="1" field="heightScale"/></dd>
-				<dt>Height Precision</dt><dd><input type="range" min="0.1" max="1" field="heightPrecision"/></dd>
-				<dt>Height Flip</dt><dd>
-					<label><input type="checkbox"field="heightFlipX"/> X</label>
-					<label><input type="checkbox"field="heightFlipY"/> Y</label>
-				</dd>
-				<dt>Normal Scale</dt><dd><input type="range" min="0" max="2" field="normalScale"/></dd>
-				<dt>MinZ</dt><dd><input type="range" min="-1000" max="0" field="minZ"/></dd>
-				<dt>MaxZ</dt><dd><input type="range" min="0" max="1000" field="maxZ"/></dd>
-				<dt>Quality</dt><dd><input type="range" min="0" max="4" field="quality" step="1"/></dd>
-				<dt>Shadows Quality</dt><dd><input type="range" min="0" max="4" field="shadowQuality" step="1"/></dd>
-			'+(hasSplat ? '
-				<dt>Albedo Tiling</dt><dd><input type="range" field="albedoTiling"/>
-				<dt>Splat Mode</dt><dd>
-					<select style="width:120px" field="splatMode">
-						<option value="Weights4">Weights4
-						<option value="Weights3">Weights3
-						<option value="I1I2W1W2">I1I2W1W2
-					</select>
-					<label><input type="checkbox" field="splatNearest"/> Nearest</label>
-				</dd>
-				<dt>Albedo Normals</dt><dd><input type="range" min="0" max="1" field="albedoNormals"/></label>
-				<dt>Albedo Roughness</dt><dd><input type="range" min="0" max="1" field="albedoRoughness"/></label>
-			': '')+'
-				<dt>Gamma</dt><dd><input type="range" min="0" max="4" field="albedoGamma"/></dd>
-				<dt>Gamma Color</dt><dd><input type="range" min="0" max="4" field="albedoColorGamma"/></dd>
-				<dt>Fixed Size</dt><dd><input type="number" style="width:50px" field="sizeX"/><input type="number" style="width:50px" field="sizeY"/> <label><input type="checkBox" field="autoSize"> Auto</label></dd>
-			</dl>
-			</div>
-			<div class="group" name="Textures">
-				<ul id="tex"></ul>
-			</div>
-		</div>
-		');
-
-		var list = props.find("ul#tex");
-		ectx.properties.add(props,this, (_) -> updateInstance(ctx));
-		for( tex in textures ) {
-			var prevTex = tex.path;
-			var e = new hide.Element('<li style="position:relative">
-				<input type="checkbox" field="enable"/>
-				<input type="texturepath" style="width:160px" field="path"/>
-				<select field="kind" style="width:70px">
-					<option value="albedo">Albedo
-					<option value="height">Height
-					<option value="normal">Normal
-					<option value="splatmap">SplatMap
-					<option value="albedoProps">Albedo + Props
-					<option value="delete">-- Delete --
-				</select>
-				<a href="#" class="up">🡅</a>
-				<a href="#" class="down">🡇</a>
-			</li>
-			');
-			e.find(".up").click(function(_) {
-				var index = textures.indexOf(tex);
-				if( index <= 0 ) return;
-				textures.remove(tex);
-				textures.insert(index-1, tex);
-				ectx.rebuildProperties();
-				updateInstance(ctx);
-			});
-			e.find(".down").click(function(_) {
-				var index = textures.indexOf(tex);
-				textures.remove(tex);
-				textures.insert(index+1, tex);
-				ectx.rebuildProperties();
-				updateInstance(ctx);
-			});
-			e.appendTo(list);
-			ectx.properties.build(e, tex, (pname) -> {
-				if( pname == "kind" ) {
-					if( ""+tex.kind == "albedoProps" ) {
-						tex.kind = Albedo;
-						if( tex.props == null ) {
-							tex.props = {
-								color : 0xFFFFFF,
-								scale : 1,
-							};
-							ectx.rebuildProperties();
-						}
-					} else if( tex.props != null ) {
-						tex.props = null;
-						ectx.rebuildProperties();
-					}
-				}
-				if( tex.path != prevTex ) {
-					tex.enable = true; // enable on change texture !
-					prevTex = tex.path;
-				}
-				if( ""+tex.kind == "delete" ) {
-					textures.remove(tex);
-					ectx.rebuildProperties();
-				}
-				updateInstance(ctx, pname);
-			});
-			if( tex.props != null ) {
-				var e = new hide.Element('<li style="position:relative">
-					Scale <input type="range" min="0" max="10" field="scale"/>
-					<input type="color" field="color"/>
- 				</li>');
-				e.appendTo(list);
-				ectx.properties.build(e, tex.props, (pname) -> updateAlbedoProps());
-			}
-		}
-		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
-		add.appendTo(list);
-		add.find("a").click(function(_) {
-			textures.push({ path : null, kind : Albedo, enable: true });
-			ectx.rebuildProperties();
-		});
-	}
-	#end
-
-	static var _ = Library.register("heightmap", HeightMap);
-
-}
-
-
-class HeightGrid extends h3d.prim.MeshPrimitive {
-
-	/**
-		The number of cells in width
-	**/
-	public var width (default, null) : Int;
-
-	/**
-		The number of cells in height
-	**/
-	public var height (default, null)  : Int;
-
-	/**
-		The width of a cell
-	**/
-	public var cellWidth (default, null) : Float;
-
-	/**
-		The height of a cell
-	**/
-	public var cellHeight (default, null)  : Float;
-
-	/**
-	 *  Minimal Z value, used for reporting bounds.
-	 **/
-	public var zMin = 0.;
-
-	/**
-	 *  Maximal Z value, used for reporting bounds.
-	 **/
-	public var zMax = 0.;
-
-	var hasNormals : Bool;
-	var hasUVs : Bool;
-
-	public function new( width : Int, height : Int, cellWidth = 1., cellHeight = 1. ) {
-		this.width = width;
-		this.height = height;
-		this.cellWidth = cellWidth;
-		this.cellHeight = cellHeight;
-	}
-
-	public function addNormals() {
-		hasNormals = true;
-	}
-
-	public function addUVs() {
-		hasUVs = true;
-	}
-
-	override function getBounds():h3d.col.Bounds {
-		return h3d.col.Bounds.fromValues(0,0,zMin,width*cellWidth,height*cellHeight,zMax-zMin);
-	}
-
-	override function alloc(engine:h3d.Engine) {
-		dispose();
-		var size = 3;
-		var names = ["position"];
-		var positions = [0];
-		if( hasNormals ) {
-			names.push("normal");
-			positions.push(size);
-			size += 3;
-		}
-		if( hasUVs ) {
-			names.push("uv");
-			positions.push(size);
-			size += 2;
-		}
-
-		var buf = new hxd.FloatBuffer((width + 1) * (height +  1) * size);
-		var p = 0;
-		for( y in 0...height + 1 )
-			for( x in 0...width + 1 ) {
-				buf[p++] = x * cellWidth;
-				buf[p++] = y * cellHeight;
-				buf[p++] = 0;
-				if( hasNormals ) {
-					buf[p++] = 0;
-					buf[p++] = 0;
-					buf[p++] = 1;
-				}
-				if( hasUVs ) {
-					buf[p++] = x / width;
-					buf[p++] = y / height;
-				}
-			}
-		var flags : Array<h3d.Buffer.BufferFlag> = [LargeBuffer];
-		buffer = h3d.Buffer.ofFloats(buf, size, flags);
-
-		for( i in 0...names.length )
-			addBuffer(names[i], buffer, positions[i]);
-
-		indexes = new h3d.Indexes(width * height * 6, true);
-		var b = haxe.io.Bytes.alloc(indexes.count * 4);
-		var p = 0;
-		for( y in 0...height )
-			for( x in 0...width ) {
-				var s = x + y * (width + 1);
-				b.setInt32(p++ << 2, s);
-				b.setInt32(p++ << 2, s + 1);
-				b.setInt32(p++ << 2, s + width + 1);
-				b.setInt32(p++ << 2, s + 1);
-				b.setInt32(p++ << 2, s + width + 2);
-				b.setInt32(p++ << 2, s + width + 1);
-			}
-		indexes.uploadBytes(b,0,indexes.count);
-	}
-
-}

+ 0 - 18
hrt/prefab/l3d/Level3D.hx

@@ -1,18 +0,0 @@
-package hrt.prefab.l3d;
-
-@:deprecated("Use hrt.prefab.Library instead")
-class Level3D extends hrt.prefab.Library {
-
-	public function new() {
-		super();
-		type = "level3d";
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { icon : "sitemap", name : "Level3D", allowParent: _ -> false};
-	}
-	#end
-
-	static var _ = Library.register("level3d", Level3D, "l3d");
-}

+ 0 - 718
hrt/prefab/l3d/MeshGenerator.hx

@@ -1,718 +0,0 @@
-package hrt.prefab.l3d;
-
-class Socket {
-
-	public var type : String;
-	public var name : String;
-
-	public function new( ?type, ?name ) {
-		this.type = type;
-		this.name = name;
-	}
-
-}
-
-class MeshPart {
-
-	public var socket : Socket;
-	public var meshPath : String;
-	public var offset : h3d.Vector;
-	public var enable : Bool = false;
-	public var childParts : Array<MeshPart> = [];
-
-	#if editor
-	public var previewPos = false;
-	#end
-
-	public function new() {
-		socket = new Socket();
-		offset = new h3d.Vector(0);
-	}
-
-	public function clone() : MeshPart {
-		var clone = new MeshPart();
-		clone.socket.name = socket.name;
-		clone.socket.type = socket.type;
-		clone.offset = offset;
-		clone.enable = enable;
-		clone.meshPath = meshPath;
-		clone.childParts = childParts.copy();
-		clone.childParts.reverse();
-		return clone;
-	}
-
-	public function loadFrom( mp : MeshPart ) {
-		socket.name = mp.socket.name;
-		socket.type = mp.socket.type;
-		offset = mp.offset;
-		meshPath = mp.meshPath;
-		enable = mp.enable;
-		childParts = mp.childParts.copy();
-	}
-
-	public function save() {
-		var o : Dynamic = {};
-
-		if( offset.length() != 0 ) o.offset = { x : offset.x, y : offset.y, z : offset.z };
-		o.socket = { type : socket.type, name : socket.name };
-		o.meshPath = meshPath;
-		o.enable = enable;
-
-		if( childParts.length > 0 ) {
-			var sp : Array<Dynamic> = [];
-			for( mp in childParts )
-				if( mp.meshPath != null )
-					sp.push(mp.save());
-			o.childParts = sp;
-		}
-
-		return o;
-	}
-
-	public function load( o : Dynamic ) {
-		enable = o.enable == null ? true : o.enable;
-		if( o.socket != null ) {
-			socket.type = o.socket.type;
-			socket.name = o.socket.name;
-		}
-		if( o.offset != null )
-			offset.set(o.offset.x, o.offset.y, o.offset.z, 0.0);
-		meshPath = o.meshPath == "none" ? null : o.meshPath;
-		var ps : Array<Dynamic> = o.childParts;
-		if( ps != null ) {
-			for( p in ps ) {
-				var mp = new MeshPart();
-				mp.load(p);
-				childParts.push(mp);
-			}
-		}
-	}
-
-	public function isRoot() : Bool {
-		return socket.type == "Root";
-	}
-
-	public function getSocketFullName() : String {
-		return socket.type + (socket.name == null ? "" : " " + socket.name);
-	}
-}
-
-class MeshGeneratorRoot extends h3d.scene.Object {
-
-	public function new( ?parent : h3d.scene.Object ) {
-		super(parent);
-	}
-
-	override function syncRec( ctx ) {
-		if( posChanged )
-			super.syncRec(ctx);
-	}
-}
-
-class MeshGenerator extends Object3D {
-
-	@:c public var root : MeshPart;
-
-	#if editor
-	static var filterInit = false;
-	static var filter : Array<String> = [];
-	static var customScene : h3d.scene.Scene;
-	var undo : hide.ui.UndoHistory;
-	#end
-
-	public var maxDepth = 1;
-	@:s public var shadows = true;
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		obj.root = root.save();
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		root = new MeshPart();
-		root.load(obj.root);
-	}
-
-	override function makeInstance( ctx : Context ) : Context {
-		ctx = ctx.clone(this);
-		ctx.local3d = new h3d.scene.Object(ctx.local3d);
-		ctx.local3d.name = name;
-
-		var rootObject = new MeshGeneratorRoot(ctx.local3d);
-		rootObject.name = "rootObject";
-
-		if( root == null ) {
-			root = new MeshPart();
-			root.socket.type = "Root";
-		}
-		updateInstance(ctx);
-
-		#if editor
-		if( customScene == null ) {
-			customScene = new h3d.scene.Scene(true, false);
-			#if debug
-			customScene.checkPasses = false;
-			#end
-		}
-		#end
-
-		return ctx;
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx,propName);
-		resetMesh(ctx);
-
-		#if editor
-		createEmptyMeshPart(ctx, root);
-		#end
-
-		var rootObject = ctx.local3d.getObjectByName("rootObject");
-		createMeshPart(ctx, root, rootObject);
-
-		#if editor
-		var int = ctx.local3d.find(o -> Std.downcast(o, h3d.scene.Interactive));
-		if(int != null) {
-			var dummy = Std.downcast(makeInteractive(ctx), h3d.scene.Interactive);
-			int.preciseShape = dummy.preciseShape;
-			dummy.remove();
-		}
-		#end
-	}
-
-	public function getSocket( obj : h3d.scene.Object, s : Socket ) : h3d.scene.Object {
-		for( c in @:privateAccess obj.children ) {
-			if( c.name == null ) continue;
-			var nameInfos = c.name.split("_");
-			if( nameInfos.length < 1 ) continue;
-			if( nameInfos[0] == "Socket" ) {
-				if( nameInfos.length < 2 ) continue;
-				if( nameInfos[1] == s.type ) {
-					if( s.name == null ) return c;
-					else {
-						if( nameInfos.length < 3 ) continue;
-						if( nameInfos[2] == s.name ) return c;
-					}
-				}
-			}
-		}
-		return null;
-	}
-
-	function createMeshPart( ctx : Context, mp : MeshPart, parent : h3d.scene.Object ) {
-
-		#if editor
-		if( mp.previewPos ) {
-			if( mp.isRoot() )
-				parent.addChild(createPreviewSphere(ctx));
-			else {
-				var socket = getSocket(parent, mp.socket);
-				if( socket != null )
-					socket.addChild(createPreviewSphere(ctx));
-			}
-		}
-		#end
-
-		if( !mp.isRoot() && !mp.enable )
-			return;
-
-		if( mp.meshPath == null )
-			return;
-
-		var obj = ctx.loadModel(mp.meshPath);
-		for( m in obj.getMaterials() ) {
-			m.castShadows = shadows;
-		}
-
-		if( mp.isRoot() ) {
-			parent.addChild(obj);
-		}
-		else {
-			var socket = getSocket(parent, mp.socket);
-			if( socket != null ) {
-				socket.addChild(obj);
-			}
-		}
-
-		obj.setPosition(mp.offset.x, mp.offset.y, mp.offset.z);
-
-		for( cmp in mp.childParts )
-			createMeshPart(ctx, cmp, obj);
-	}
-
-	function resetMesh( ctx : Context ) {
-		ctx.local3d.getObjectByName("rootObject").removeChildren();
-	}
-
-	function getSocketMatFromHMD( hmd : hxd.fmt.hmd.Library, s : Socket ) : h3d.Matrix {
-		if( hmd == null ) return null;
-		for( m in @:privateAccess hmd.header.models ) {
-			if( m.name == null ) continue;
-			var nameInfos = m.name.split("_");
-			if( nameInfos.length < 2 ) continue;
-			if( nameInfos[0] == "Socket" && nameInfos[1] == s.type && ((s.name == null && nameInfos.length < 3) || (nameInfos.length >= 3 && s.name == nameInfos[2])) ) {
-				return m.position.toMatrix();
-			}
-		}
-		return null;
-	}
-
-	#if editor
-
-	function generate( ctx : EditContext, mp : MeshPart, maxDepth : Int, curDepth : Int) {
-		if( curDepth >  maxDepth ) return;
-		curDepth++;
-		mp.meshPath = getRandomMeshPath(ctx.scene.config, mp.socket);
-		if( root.meshPath == null ) return;
-		mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(ctx.rootContext, mp.meshPath)));
-		for( cmp in mp.childParts )
-			generate(ctx, cmp, maxDepth, curDepth);
-	}
-
-	function createEmptyMeshPart( ctx : Context, mp : MeshPart ) {
-		var sl = getSocketListFromHMD(getHMD(ctx, mp.meshPath));
-		if( mp.childParts.length < sl.length ) {
-			for( s in sl ) {
-				var b = true;
-				for( cmp in mp.childParts ){
-					if ( cmp.socket.name == s.name && cmp.socket.type == s.type ){
-						b = false;
-						break;
-					}
-				}
-				if( b ) {
-					var cmp = new MeshPart();
-					cmp.socket.name = s.name;
-					cmp.socket.type = s.type;
-					mp.childParts.push(cmp);
-				}
-			}
-		}
-		for( cmp in mp.childParts )
-			createEmptyMeshPart(ctx, cmp);
-	}
-
-	var target : h3d.mat.Texture;
-	function renderMeshThumbnail( ctx : Context, meshPath : String ) {
-
-		if( target == null )
-			target = new h3d.mat.Texture(256, 256, [Target], RGBA);
-
-		if( meshPath == null )
-			return;
-
-		var obj = ctx.loadModel(meshPath);
-		if( obj == null )
-			return;
-
-		for( m in obj.getMaterials() ) {
-			m.mainPass.culling = None;
-		}
-
-		if(!sys.FileSystem.isDirectory(hide.Ide.inst.getPath(".tmp/meshGeneratorData")))
-			sys.FileSystem.createDirectory(hide.Ide.inst.getPath(".tmp/meshGeneratorData"));
-
-		var path = new haxe.io.Path("");
-		path.dir = ".tmp/meshGeneratorData/";
-		path.file =  extractMeshName(meshPath) + "_thumbnail";
-		path.ext = "png";
-		var file = hide.Ide.inst.getPath(path.toString());
-
-		if(sys.FileSystem.exists(file))
-			return;
-
-		var mainScene = @:privateAccess ctx.local3d.getScene();
-		@:privateAccess customScene.children = [];
-		@:privateAccess customScene.children.push(obj);
-
-		var cam = new h3d.Camera(45, 1.0, 1.0);
-		obj.rotate(0, 0, hxd.Math.degToRad(45));
-		var b = obj.getBounds();
-		var s = b.toSphere();
-		cam.pos.set(0, s.r * 1.8, s.r * 1.25);
-		cam.target.set((b.xMax + b.xMin) * 0.5, (b.yMax + b.yMin) * 0.5, (b.zMax + b.zMin) * 0.5);
-
-		customScene.camera = cam;
-		var engine = h3d.Engine.getCurrent();
-		engine.begin();
-		engine.pushTarget(target);
-		engine.clear(0,1,0);
-		customScene.render(engine);
-		engine.popTarget();
-		customScene.camera = null;
-
-		var pixels = target.capturePixels();
-		var bytes = pixels.toPNG();
-
-		sys.io.File.saveBytes(file, bytes);
-	}
-
-	function hasFilter( s : String ) {
-		for( f in filter )
-			if ( s == f )
-				return true;
-		return false;
-	}
-
-	function createPreviewSphere( ctx : Context ) {
-		var root = new h3d.scene.Object();
-		root.setRotation(0,0, hxd.Math.degToRad(180));
-		var m : h3d.scene.Mesh = cast ctx.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
-		m.material.shadows = false;
-		root.addChild(m);
-		m.scale(0.5);
-		m.name = "previewSphere";
-		m.material.color.set(0.05,0,0.05,1);
-		m.material.mainPass.depthTest = GreaterEqual;
-		m.material.mainPass.depthWrite = false;
-		m.material.mainPass.setPassName("overlay");
-		var m : h3d.scene.Mesh = cast ctx.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
-		m.material.shadows = false;
-		root.addChild(m);
-		m.scale(0.5);
-		m.name = "previewSphere";
-		m.material.color.set(1,0,0,1);
-		m.material.mainPass.depthTest = LessEqual;
-		m.material.mainPass.depthWrite = false;
-		m.material.mainPass.setPassName("overlay");
-		return root;
-	}
-
-	function resetPreview( mp : MeshPart ) {
-		mp.previewPos = false;
-		for( cmp in mp.childParts )
-			resetPreview(cmp);
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "paint-brush", name : "MeshGenerator" };
-	}
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		super.setSelected(ctx, b);
-
-		if( !b ) {
-			var previewSpheres = ctx.local3d.findAll(c -> if(c.name == "previewSphere") c else null);
-			for( s in previewSpheres ) {
-				s.remove();
-			}
-		}
-		return true;
-	}
-
-	function getHMD( ctx : Context, meshPath : String ) : hxd.fmt.hmd.Library {
-		if( meshPath == null ) return null;
-		return @:privateAccess ctx.shared.cache.loadLibrary(hxd.res.Loader.currentInstance.load(meshPath).toModel());
-	}
-
-	function createMeshParts( sl : Array<Socket> ) : Array<MeshPart> {
-		var r : Array<MeshPart> = [];
-		for( s in sl ){
-			var mp = new MeshPart();
-			mp.socket.name = s.name;
-			mp.socket.type = s.type;
-			r.push(mp);
-		}
-		return r;
-	}
-
-	function getSocketListFromHMD( hmd : hxd.fmt.hmd.Library ) : Array<Socket> {
-		if( hmd == null ) return [];
-		var r : Array<Socket> = [];
-		for( m in @:privateAccess hmd.header.models ) {
-			if( m.name == null ) continue;
-			var nameInfos = m.name.split("_");
-			if( nameInfos.length < 2 ) continue;
-			if( nameInfos[0] == "Socket" ) {
-				var s = new Socket();
-				s.type = nameInfos[1];
-				if( nameInfos.length >= 3 ) s.name = nameInfos[2];
-				r.push(s);
-			}
-		}
-		return r;
-	}
-
-	function extractMeshName( path : String ) : String {
-		if( path == null ) return "None";
-		var childParts = path.split("/");
-		return childParts[childParts.length - 1].split(".")[0];
-	}
-
-	function getThumbnailPath( ctx : EditContext, meshPath : String ) : String {
-		return ctx.ide.getPath(".tmp/meshGeneratorData/"+ extractMeshName(meshPath) +"_thumbnail.png");
-	}
-
-	function getRandomMeshPath( config : hide.Config, socket : Socket ) : String {
-		var available : Array<String> = [];
-		for( f in filter ) {
-			var meshList : Array<Dynamic> = config.get("meshGenerator." + f);
-			if( meshList == null ) continue;
-			for( m in meshList ) {
-				var sockets : Array<String> = m.socket;
-				if( sockets == null || sockets.length == 0 ) continue;
-				for( s in sockets ) {
-					if( s == socket.type ) {
-						available.push(m.path);
-						break;
-					}
-				}
-			}
-		}
-		if( available.length == 0 )
-			return null;
-		return available[hxd.Math.round(hxd.Math.random() * (available.length - 1))];
-	}
-
-	function fillSelectMenu( ctx : EditContext, select : hide.Element, socket : Socket ) {
-		for( f in filter ) {
-			var meshList : Array<Dynamic> = ctx.scene.config.get("meshGenerator." + f);
-			if( meshList == null ) continue;
-			for( m in meshList ) {
-				var sockets : Array<String> = m.socket;
-				var available = false;
-				if( sockets == null || sockets.length == 0 )
-					available = true;
-				else {
-					for( s in sockets ) {
-						if( s == socket.type ) {
-							available = true;
-							break;
-						}
-					}
-				}
-				if( available )
-					new hide.Element('<option>').attr("value", m.path).text(extractMeshName(m.path)).appendTo(select);
-			}
-		}
-	}
-
-	function createMenu( ctx : EditContext, mp : MeshPart ) {
-
-		if( mp.isRoot() ) {
-			var rootElement = new hide.Element('
-				<div class="group" name="Root">
-					<dl>
-						<dt>Mesh</dt><dd><select><option value="none">None</option></select>
-					</dl>
-				</div>
-			');
-			var select = rootElement.find("select");
-			fillSelectMenu(ctx, select, mp.socket);
-			if( mp.meshPath != null && select.find('option[value="${mp.meshPath}"]').length == 0 )
-				new hide.Element('<option>').attr("value", mp.meshPath).text(extractMeshName(mp.meshPath)).appendTo(select);
-
-			select.change(function(_) {
-				var val = select.val();
-				var previous = mp.clone();
-				var actual = mp;
-				mp.meshPath = val == "none" ? null : val;
-				mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(ctx.rootContext, mp.meshPath)));
-				ctx.properties.undo.change(Custom(function(undo) {
-					undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
-					ctx.onChange(this, null);
-					ctx.rebuildProperties();
-				}));
-				ctx.onChange(this, null);
-				ctx.rebuildProperties();
-			});
-			select.val(mp.meshPath);
-
-			ctx.properties.add(rootElement, mp, function(pname) {});
-		}
-
-		var socketList = getSocketListFromHMD(getHMD(ctx.rootContext, mp.meshPath));
-		if( mp.meshPath != null && socketList.length != 0 ) {
-			var s = '<div class="group" name="${extractMeshName(mp.meshPath)}">';
-			s += '<div align="center"><div class="meshGenerator-thumbnail"></div></div><dl>';
-			for( cmp in mp.childParts ) {
-				var index = mp.childParts.indexOf(cmp);
-				if( cmp.enable ) {
-					s += '<dt><b>${cmp.getSocketFullName()}</b></dt><dd><input type="checkbox" class="enable$index"></dd>';
-					s += '<dt>Mesh</dt><dd><select class="$index"><option value="none">None</option></select>';
-					s += '<dt>Offset</dt>
-									<dd>
-										<div class="flex">
-											<input type="number" style="max-width:50px" class="x$index" min="-100" max="100" step="0.1">
-											<input type="number" style="max-width:50px" class="y$index" min="-100" max="100" step="0.1">
-											<input type="number" style="max-width:50px" class="z$index" min="-100" max="100" step="0.1">
-										</div>
-									</dd>';
-				}
-				else
-					s += '<dt>${cmp.getSocketFullName()}</dt><dd><input type="checkbox" class="enable$index"></dd>';
-			}
-			s += '</dl></div>';
-			var rootElement = new hide.Element(s);
-			for( cmp in mp.childParts ) {
-				var index = mp.childParts.indexOf(cmp);
-
-				var enable = rootElement.find('.enable$index');
-				enable.prop("checked", cmp.enable);
-				enable.change(function(_) {
-					cmp.enable = enable.prop("checked");
-					ctx.onChange(this, null);
-					ctx.rebuildProperties();
-
-					ctx.properties.undo.change(Custom(function(undo) {
-						cmp.enable = !cmp.enable;
-						ctx.onChange(this, null);
-						ctx.rebuildProperties();
-					}));
-				});
-
-
-				if( cmp.enable ) {
-					// Offset
-					var x = rootElement.find('.x$index');
-					x.val(cmp.offset.x);
-					x.change(function(_) {
-						var prev : Float = cmp.offset.x;
-						var newv : Float = Std.parseFloat(x.val());
-						cmp.offset.x = newv;
-						ctx.onChange(this, null);
-						ctx.properties.undo.change(Custom(function(undo) {
-							cmp.offset.x = undo ? prev : newv;
-							ctx.onChange(this, null);
-							ctx.rebuildProperties();
-						}));
-					});
-					var y = rootElement.find('.y$index');
-					y.val(cmp.offset.y);
-					y.change(function(_) {
-						var prev : Float = cmp.offset.y;
-						var newv : Float = Std.parseFloat(y.val());
-						cmp.offset.y = newv;
-						ctx.onChange(this, null);
-						ctx.properties.undo.change(Custom(function(undo) {
-							cmp.offset.y = undo ? prev : newv;
-							ctx.onChange(this, null);
-							ctx.rebuildProperties();
-						}));
-					});
-					var z = rootElement.find('.z$index');
-					z.val(cmp.offset.z);
-					z.change(function(_) {
-						var prev : Float = cmp.offset.z;
-						var newv : Float = Std.parseFloat(z.val());
-						cmp.offset.z = newv;
-						ctx.onChange(this, null);
-						ctx.properties.undo.change(Custom(function(undo) {
-							cmp.offset.z = undo ? prev : newv;
-							ctx.onChange(this, null);
-							ctx.rebuildProperties();
-						}));
-					});
-
-					// MeshPath
-					var select = rootElement.find('.$index');
-					fillSelectMenu(ctx, select, cmp.socket);
-					if( cmp.meshPath != null && select.find('option[value="${cmp.meshPath}"]').length == 0 )
-						new hide.Element('<option>').attr("value", cmp.meshPath).text(extractMeshName(cmp.meshPath)).appendTo(select);
-					select.change(function(_) {
-						var mp = mp.childParts[index];
-						var val = select.val();
-						var previous = mp.clone();
-						var actual = mp;
-						mp.meshPath = val == "none" ? null : val;
-						mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(ctx.rootContext, cmp.meshPath)));
-						ctx.properties.undo.change(Custom(function(undo) {
-							undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
-							ctx.onChange(this, null);
-							ctx.rebuildProperties();
-						}));
-						ctx.onChange(this, null);
-						ctx.rebuildProperties();
-					});
-					select.val(cmp.meshPath);
-				}
-
-				enable.on("mouseover", function(_) {
-					resetPreview(root);
-					cmp.previewPos = true;
-					ctx.onChange(this, null);
-				});
-				enable.on("mouseleave", function(_) {
-					resetPreview(root);
-					ctx.onChange(this, null);
-				});
-			}
-
-			//renderMeshThumbnail(ctx.rootContext, mp.meshPath);
-			//rootElement.find('.meshGenerator-thumbnail').css("background-image", 'url("file://${getThumbnailPath(ctx, mp.meshPath)}")');
-
-			ctx.properties.add(rootElement, mp, function(pname) {});
-
-			for( cmp in mp.childParts ) {
-				createMenu(ctx, cmp);
-			}
-		}
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		undo = ctx.properties.undo;
-
-		var families : Array<Dynamic> = ctx.scene.config.get("meshGenerator.families");
-
-		if( !filterInit ) {
-			for( f in families )
-				filter.push(f);
-			filterInit = true;
-		}
-
-		var editMenu : String = "";
-
-		// Render Params
-		editMenu += '<div class="group" name="Material"><dl>
-						<dt>Shadows</dt><dd><input type="checkbox" field="shadows"></dd>
-					</div>';
-
-		// Procedural Generation
-		editMenu += '<div class="group" name="Procedural Generation"><dl>
-						<dt>Max Depth</dt><dd><input type="range" min="0" max="10" step="1" field="maxDepth"/></dd>
-						<div align="center">
-							<input type="button" value="Generate" class="generate" />
-						</div>
-					</div>';
-
-		editMenu += '<div class="group" name="Filter"><dl>';
-		for( f in families )
-			editMenu += '<dt>${f}</dt><dd><input type="checkbox" class="${families.indexOf(f)}"/></dd>';
-		editMenu += '</dl></div>';
-		var props = new hide.Element(editMenu);
-		for( f in families ) {
-			var checkBox = props.find('.${families.indexOf(f)}');
-			checkBox.prop("checked", hasFilter(f));
-			checkBox.change(function(_) {
-				var checked : Bool = checkBox.prop("checked");
-				checked ? filter.push(f) : filter.remove(f);
-				ctx.rebuildProperties();
-			});
-		}
-
-		var generateButton = props.find('.generate');
-		generateButton.click(function(_) {
-			var previous = root.clone();
-			var actual = root;
-			generate(ctx, root, maxDepth, 0);
-			ctx.properties.undo.change(Custom(function(undo) {
-				undo ? root.loadFrom(previous) : root.loadFrom(actual);
-				ctx.onChange(this, null);
-				ctx.rebuildProperties();
-			}));
-			ctx.onChange(this, null);
-			ctx.rebuildProperties();
-		});
-
-		ctx.properties.add(props, this, function(pname) { ctx.onChange(this, null); });
-
-		createMenu(ctx, root);
-	}
-	#end
-
-	static var _ = Library.register("meshGenerator", MeshGenerator);
-}

+ 0 - 1076
hrt/prefab/l3d/MeshSpray.hx

@@ -1,1076 +0,0 @@
-package hrt.prefab.l3d;
-
-#if !editor
-
-class MeshSprayObject extends h3d.scene.Object {
-	public var batches : Array<h3d.scene.MeshBatch> = [];
-	public var batchesMap : Map<Int,Map<String,{ batch : h3d.scene.MeshBatch, pivot : h3d.Matrix }>> = [];
-	override function getMaterials( ?arr : Array<h3d.mat.Material>, recursive=true ) {
-		if( !recursive ) {
-			// batches materials are considered local materials
-			if( arr == null ) arr = [];
-			for( b in batches )
-				arr = b.getMaterials(arr, false);
-		}
-		return super.getMaterials(arr,recursive);
-	}
-}
-
-class MeshSpray extends Object3D {
-
-	@:s var split : Int;
-
-	inline function getSplitID( c : Prefab ) {
-		var c = c.to(Object3D);
-		return (Math.floor(c.x/split) * 39119 + Math.floor(c.y/split)) % 0x7FFFFFFF;
-	}
-
-	override function createObject( ctx : Context ) {
-		var mspray = new MeshSprayObject(ctx.local3d);
-		// preallocate batches so their materials can be resolved
-		var curID = 0, curMap = mspray.batchesMap.get(0);
-		if( curMap == null ) {
-			curMap = new Map();
-			mspray.batchesMap.set(0, curMap);
-		}
-		for( c in children ) {
-			if( !c.enabled || c.type != "model" ) continue;
-			if( split > 0 ) {
-				var sid = getSplitID(c);
-				if( sid != curID ) {
-					curID = sid;
-					curMap = mspray.batchesMap.get(sid);
-					if( curMap == null ) {
-						curMap = new Map();
-						mspray.batchesMap.set(sid, curMap);
-					}
-				}
-			}
-			var batch = curMap.get(c.source);
-			if( batch == null ) {
-				var obj = ctx.loadModel(c.source).toMesh();
-				var batch = new h3d.scene.MeshBatch(cast(obj.primitive,h3d.prim.MeshPrimitive), obj.material, mspray);
-				batch.cullingCollider = @:privateAccess batch.instanced.bounds;
-				var multi = Std.downcast(obj, h3d.scene.MultiMaterial);
-				if( multi != null ) batch.materials = multi.materials;
-				curMap.set(c.source, { batch : batch, pivot : obj.defaultTransform.isIdentity() ? null : obj.defaultTransform });
-				mspray.batches.push(batch);
-			}
-		}
-		return mspray;
-	}
-
-	override function make( ctx : Context ) {
-		if( !enabled )
-			return ctx;
-		ctx = super.make(ctx);
-		var mspray = Std.downcast(ctx.local3d, MeshSprayObject);
-		var pos = mspray.getAbsPos();
-		var tmp = new h3d.Matrix();
-		for( b in mspray.batches ) {
-			b.begin();
-			b.worldPosition = tmp;
-		}
-		var curID = 0, curMap = mspray.batchesMap.get(0);
-		for( c in children ) {
-			if( !c.enabled || c.type != "model" )
-				continue;
-			if( split > 0 ) {
-				var sid = getSplitID(c);
-				if( sid != curID ) {
-					curMap = mspray.batchesMap.get(sid);
-					curID = sid;
-				}
-			}
-			var inf = curMap.get(c.source);
-			tmp.multiply3x4(c.to(Object3D).getTransform(), pos);
-			if( inf.pivot != null ) tmp.multiply3x4(inf.pivot, tmp);
-			inf.batch.emitInstance();
-		}
-		for( b in mspray.batches )
-			b.worldPosition = null;
-		return ctx;
-	}
-
-	override function makeChildren( ctx : Context, p : hrt.prefab.Prefab ) {
-		if( p.type == "model" )
-			return;
-		super.makeChildren(ctx, p);
-	}
-
-	static var _ = Library.register("meshSpray", MeshSpray);
-
-}
-
-#else
-
-import h3d.Vector;
-import hxd.Key as K;
-
-typedef Mesh = {
-	var path: String;
-	var isRef: Bool;
-}
-
-typedef Set = {
-	var name: String;
-	var meshes: Array<Mesh>;
-	var config: MeshSprayConfig;
-}
-
-typedef SetGroup = {
-	var name: String;
-	var sets: Array<Set>;
-}
-
-typedef MeshSprayConfig = {
-	var density : Int;
-	var densityOffset : Int;
-	var radius : Float;
-	var deleteRadius : Float;
-	var scale : Float;
-	var scaleOffset : Float;
-	var rotation : Float;
-	var rotationOffset : Float;
-	var zOffset: Float;
-	var dontRepeatMesh : Bool;
-	var enableBrush : Bool;
-	var orientTerrain : Float;
-	var tiltAmount : Float;
-}
-
-
-@:access(hrt.prefab.l3d.MeshSpray)
-class MeshSprayObject extends h3d.scene.Object {
-
-	var childCount : Int = -1;
-	var batches : Array<h3d.scene.MeshBatch> = [];
-	var blookup : Map<h3d.prim.Primitive, h3d.scene.MeshBatch> = new Map();
-	var mp : MeshSpray;
-	var currentChk : Float = 0;
-
-	public function new(mp,?parent) {
-		this.mp = mp;
-		super(parent);
-	}
-
-	override function getMaterials( ?arr : Array<h3d.mat.Material>, recursive=true ) {
-		if( !recursive ) {
-			// batches materials are considered local materials
-			if( arr == null ) arr = [];
-			for( b in batches )
-				arr = b.getMaterials(arr, false);
-		}
-		return super.getMaterials(arr,recursive);
-	}
-
-	override function emitRec(ctx:h3d.scene.RenderContext) {
-		for( b in batches ) {
-			var p = b.material.getPass("highlight");
-			if( p != null ) b.material.removePass(p);
-		}
-
-		var count = children.length;
-		count -= batches.length;
-		count -= mp.previewModels.length;
-		if( mp.gBrushes != null ) count -= mp.gBrushes.length;
-		var redraw = false;
-		if( childCount != count ) {
-			childCount = count;
-			redraw = true;
-		}
-
-		var chk = 0.;
-		for( c in children ) {
-			if( c.alwaysSync ) continue;
-			chk += c.x - c.y + c.z * 1.5456 + c.scaleX + c.scaleY + c.scaleZ + c.qRot.x + c.qRot.y + c.qRot.z;
-		}
-		if( chk != currentChk ) {
-			currentChk = chk;
-			redraw = true;
-		}
-
-		if( redraw ) this.redraw();
-		super.emitRec(ctx);
-	}
-
-	public function redraw(updateShaders=false) {
-		for( b in batches ) {
-			if( updateShaders ) b.shadersChanged = true;
-			b.begin();
-		}
-		for( c in children ) {
-			c.culled = false;
-			if( c.alwaysSync ) continue;
-			var m = Std.downcast(c, h3d.scene.Mesh);
-			if( m == null ) continue;
-			var prim = Std.downcast(m.primitive, h3d.prim.MeshPrimitive);
-			if( prim == null ) continue;
-
-			var batch = blookup.get(m.primitive);
-			if( batch == null ) {
-				batch = new h3d.scene.MeshBatch(prim, m.material, this);
-				var multi = Std.downcast(m, h3d.scene.MultiMaterial);
-				if( multi != null ) batch.materials = multi.materials;
-				batch.alwaysSync = true;
-				batch.begin();
-				batches.push(batch);
-				blookup.set(m.primitive, batch);
-			}
-			batch.worldPosition = c.absPos;
-			batch.emitInstance();
-			c.culled = true;
-		}
-		for( b in batches )
-			b.worldPosition = null;
-	}
-
-}
-
-class MeshSpray extends Object3D {
-
-	@:s var meshes : Array<Mesh> = []; // specific set for this mesh spray
-	@:s var defaultConfig: MeshSprayConfig;
-	@:s var currentPresetName : String = null;
-	@:s var currentSetName : String = null;
-	@:s var split : Int = 0;
-
-	var sceneEditor : hide.comp.SceneEditor;
-
-	var undo(get, null):hide.ui.UndoHistory;
-	function get_undo() { return sceneEditor.view.undo; }
-
-	var lastIndexMesh = -1;
-	var allSetGroups : Array<SetGroup>;
-	var setGroup : SetGroup;
-	var currentSet : Set;
-
-	var currentMeshes(get, null) : Array<Mesh>;
-	function get_currentMeshes() {
-		if (currentSet != null)
-			return currentSet.meshes;
-		else
-			return meshes;
-	}
-
-	var currentConfig(get, null) : MeshSprayConfig;
-	function get_currentConfig() {
-		var config = (currentSet != null) ? currentSet.config : defaultConfig;
-		if (config == null) config = getDefaultConfig();
-		return config;
-	}
-
-	var sprayEnable : Bool = false;
-	var interactive : h2d.Interactive;
-	var gBrushes : Array<h3d.scene.Mesh>;
-
-	var timerCicle : haxe.Timer;
-
-	var lastSpray : Float = 0;
-	var invParent : h3d.Matrix;
-
-	var MESH_SPRAY_CONFIG_FILE = "meshSprayProps.json";
-	var MESH_SPRAY_CONFIG_PATH(get, null) : String;
-	function get_MESH_SPRAY_CONFIG_PATH() {
-		return hide.Ide.inst.resourceDir + "/" + MESH_SPRAY_CONFIG_FILE;
-	}
-
-	override function save() {
-		// prevent saving preview
-		if( previewModels.length > 0 )
-			sceneEditor.deleteElements(previewModels, () -> { }, false);
-		return super.save();
-	}
-
-	function getDefaultConfig() : MeshSprayConfig {
-		return {
-			density: 1,
-			densityOffset: 0,
-			radius: 0.1,
-			deleteRadius: 5,
-			scale: 1,
-			scaleOffset: 0.1,
-			rotation: 184,
-			rotationOffset: 0,
-			zOffset: 0,
-			dontRepeatMesh: true,
-			enableBrush: true,
-			orientTerrain : 0,
-			tiltAmount : 0,
-		};
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "paint-brush", name : "MeshSpray", hideChildren : p -> return Std.is(p, Model) };
-	}
-
-	function extractMeshName( path : String ) : String {
-		if( path == null ) return "None";
-		var childParts = path.split("/");
-		return childParts[childParts.length - 1].split(".")[0];
-	}
-
-	function saveConfigMeshBatch() {
-		sys.io.File.saveContent(MESH_SPRAY_CONFIG_PATH, hide.Ide.inst.toJSON(allSetGroups));
-	}
-
-	function setGroundPos( ectx : EditContext, obj : Object3D ) {
-		var pos = obj.getAbsPos();
-		var config = currentConfig;
-		var tz = ectx.positionToGroundZ(pos.tx, pos.ty);
-		var mz = config.zOffset + tz - pos.tz;
-		obj.z += mz;
-		var orient = config.orientTerrain;
-		var tilt = config.tiltAmount;
-
-		var r = config.radius * 0.2;
-		inline function getPoint(dx,dy) {
-			var dz = ectx.positionToGroundZ(pos.tx + r * dx, pos.ty + r * dy) - tz;
-			return new h3d.col.Point(r * dx, r * dy, dz * orient);
-		}
-
-		var px0 = getPoint(-1,0);
-		var py0 = getPoint(0, -1);
-		var px1 = getPoint(1, 0);
-		var py1 = getPoint(0, 1);
-		var n = px1.cross(py1).add(py1.cross(px0)).add(px0.cross(py0)).add(py0.cross(px1)).normalized();
-		var q = new h3d.Quat();
-		q.initNormal(n);
-		var m = q.toMatrix();
-		m.prependRotation(Math.random()*tilt*Math.PI/8,0,  (config.rotation + (Std.random(2) == 0 ? -1 : 1) * Math.round(Math.random() * config.rotationOffset)) * Math.PI / 180);
-		var a = m.getEulerAngles();
-		obj.rotationX = hxd.Math.fmt(a.x * 180 / Math.PI);
-		obj.rotationY = hxd.Math.fmt(a.y * 180 / Math.PI);
-		obj.rotationZ = hxd.Math.fmt(a.z * 180 / Math.PI);
-	}
-
-	var wasEdited = false;
-	var previewModels : Array<hrt.prefab.Prefab> = [];
-	var sprayedModels : Array<hrt.prefab.Prefab> = [];
-	override function edit( ectx : EditContext ) {
-
-		invParent = getAbsPos().clone();
-		invParent.invert();
-
-		if (defaultConfig == null) defaultConfig = getDefaultConfig();
-		if (sceneEditor == null) {
-			allSetGroups = if( sys.FileSystem.exists(MESH_SPRAY_CONFIG_PATH) )
-				try hide.Ide.inst.parseJSON(sys.io.File.getContent(MESH_SPRAY_CONFIG_PATH)) catch( e : Dynamic ) throw e+" (in "+MESH_SPRAY_CONFIG_PATH+")";
-			else
-				[];
-		}
-		sceneEditor = ectx.scene.editor;
-
-		var props = new hide.Element('<div class="group" name="Meshes"></div>');
-
-		var preset = new hide.Element('<div class="btn-list" align="center" ></div>').appendTo(props);
-
-		var presetChoice = new hide.Element('<div align="center" ></div>').appendTo(preset);
-
-		var selectPresetElt = new hide.Element('<select style="width: 150px" ></select>').appendTo(presetChoice);
-
-		function updateSelectPreset() {
-			selectPresetElt.empty();
-			var allSetGroupsName = [null];
-			for (g in allSetGroups) allSetGroupsName.push(g.name);
-			for (presetValue in allSetGroupsName) {
-				var selected = (currentPresetName == presetValue);
-				var presetName = (presetValue == null) ? "No preset" : presetValue;
-				selectPresetElt.append(new hide.Element('<option ${(selected) ? 'selected=selected' : ''} value="${presetValue}"" >${presetName}</option>'));
-			}
-			selectPresetElt.append(new hide.Element('<option value="#add">-- Add preset --</option>'));
-		}
-		updateSelectPreset();
-
-		var editPresetName = new hide.Element('<button>Edit</button>').appendTo(presetChoice);
-		var deletePreset = new hide.Element('<button>Del.</button>').appendTo(presetChoice);
-
-		var setsList = new hide.Element('<div align="center" ></div>').appendTo(preset);
-
-		var selectElement = new hide.Element('<select multiple size="6" style="width: 300px" ></select>').appendTo(props);
-
-		function onChangeSet() {
-			selectElement.empty();
-			for (m in currentMeshes.copy()) {
-				var path : String = null;
-				if (Std.is(m, String)) { // retro-compatibility
-					path = cast m;
-					currentMeshes.remove(m);
-					addMeshPath(path);
-				} else {
-					path = m.path;
-				}
-				selectElement.append(new hide.Element('<option value="${path}">${extractMeshName(path)}</option>'));
-			}
-			updateConfig();
-		}
-
-		var selectedSetElt : hide.Element = null;
-		function setSet(set: Set, setElt : hide.Element) {
-			currentSetName = (set != null) ? set.name : null;
-			currentSet = set;
-			if (selectedSetElt != null)
-				selectedSetElt.css("border-color", "#444444");
-			selectedSetElt = setElt;
-			if (selectedSetElt != null)
-				selectedSetElt.css("border-color", "green");
-			onChangeSet();
-		}
-
-		function onChangePreset(init : Bool = false) {
-			if (currentPresetName != null) {
-				var tmp = allSetGroups.filter(g -> g.name == currentPresetName);
-				if (tmp.length > 0)
-					setGroup = tmp[0];
-				else
-					return;
-			} else {
-				setGroup = null;
-				setSet(null, null);
-			}
-			setsList.empty();
-			if (setGroup != null) {
-				if (!init)
-					currentSetName = setGroup.sets[0].name;
-				for (s in setGroup.sets) {
-					var setElt = new hide.Element('<div style="margin: 5px; padding: 10px; border: solid 1px #444444; display: inline-block;" ></div>').appendTo(setsList);
-					var inputSetElt = new hide.Element('<input type="text" style="width: 75px; border: none; padding: 0; text-align: center;" value="${s.name}" />').appendTo(setElt);
-					setElt.on("click", function(e) {
-						setSet(s, setElt);
-					});
-					inputSetElt.on("change", function(e) {
-						var value : String = inputSetElt.val();
-						if (value != null && value.length > 0) {
-							s.name = value;
-							saveConfigMeshBatch();
-						} else {
-							inputSetElt.val(s.name);
-						}
-					});
-					if (s.name == currentSetName) setSet(s, setElt);
-				}
-				var addSet = new hide.Element('<div style="margin: 5px; padding: 10px; border: solid 1px #444444; display: inline-block;" >Add set</div>').appendTo(setsList);
-				addSet.on("click", function(e) {
-					var name = hide.Ide.inst.ask("Name set:");
-					if (name == null || name.length == 0) return;
-					setGroup.sets.push({
-						name: name,
-						meshes: [],
-						config: getDefaultConfig()
-					});
-					currentSetName = name;
-					onChangePreset();
-				});
-			}
-		}
-		selectPresetElt.on("change", function() {
-			var value = selectPresetElt.val();
-			if (value == "null") value = null;
-			if (value == "#add") {
-				var name = hide.Ide.inst.ask("Name preset:");
-				var groups = allSetGroups.filter(g -> g.name == name);
-				if (name == null || name.length == 0 || groups.length > 0)
-					return;
-				allSetGroups.push({
-					name: name,
-					sets: [{
-						name: "SetName",
-						meshes: [],
-						config: getDefaultConfig()
-					}]
-				});
-				currentPresetName = name;
-				currentSetName = "SetName";
-				saveConfigMeshBatch();
-				updateSelectPreset();
-				onChangePreset();
-				return;
-			}
-			currentPresetName = value;
-			onChangePreset();
-		});
-
-		editPresetName.on("click", function() {
-			if (currentPresetName == null) return;
-			var preset = allSetGroups.filter(s -> s.name == currentPresetName);
-			if (preset.length == 0) return;
-			var name = hide.Ide.inst.ask("New name preset:");
-			if (name == null || name.length == 0) return;
-			preset[0].name = name;
-			currentPresetName = name;
-			saveConfigMeshBatch();
-			updateSelectPreset();
-			onChangePreset();
-		});
-
-		deletePreset.on("click", function() {
-			if (currentPresetName == null) return;
-			var preset = allSetGroups.filter(s -> s.name == currentPresetName);
-			if (preset.length == 0) return;
-			if(hide.Ide.inst.confirm("Are-you sure ?")) {
-				allSetGroups.remove(preset[0]);
-				currentPresetName = null;
-				currentSetName = null;
-				saveConfigMeshBatch();
-				updateSelectPreset();
-				onChangePreset();
-			}
-		});
-
-		onChangePreset(true);
-
-		var options = new hide.Element('
-		<div>
-			<div class="btn-list" align="center">
-				<input type="button" value="Select all" id="select"/>
-				<input type="button" value="Add" id="add"/>
-				<input type="button" value="Remove" id="remove"/>
-				<input type="button" value="Remove all meshes" id="clean"/>
-				<input type="button" value="Set to Ground" id="toground"/>
-			</div>
-			<p align="center">
-				<label><input type="checkbox" id="repeatMesh" style="margin-right: 5px;"/> Don\'t repeat same mesh in a row</label>
-			</p>
-			<p>
-				<b><i>
-				Hold down SHIFT to remove meshes
-				<br/>Push R to randomize preview
-			</p>
-			<p align="center">
-				<label><input type="checkbox" id="enableBrush" style="margin-right: 5px;"/> Enable Brush</label>
-			</p>
-
-		</div>
-		').appendTo(props);
-
-		var repeat = options.find("#repeatMesh");
-		repeat.on("change", function() {
-			currentConfig.dontRepeatMesh = repeat.is(":checked");
-		}).prop("checked", currentConfig.dontRepeatMesh);
-
-		var enableBrush = options.find("#enableBrush");
-		enableBrush.on("change", function() {
-			currentConfig.enableBrush = enableBrush.is(":checked");
-			sceneEditor.setLock([this], currentConfig.enableBrush, false);
-			removeInteractiveBrush();
-			if (currentConfig.enableBrush)
-				createInteractiveBrush(ectx);
-			else {
-				interactive.cancelEvents = true;
-			}
-			
-		}).prop("checked", currentConfig.enableBrush);
-		
-
-		options.find("#select").click(function(_) {
-			var options = selectElement.children().elements();
-			for (opt in options) {
-				opt.prop("selected", true);
-			}
-		});
-		options.find("#add").click(function(_) {
-			hide.Ide.inst.chooseFiles(["fbx", "l3d"], function(paths) {
-				for( path in paths ) {
-					addMeshPath(path);
-					selectElement.append(new hide.Element('<option value="$path">${extractMeshName(path)}</option>'));
-				}
-			});
-		});
-
-		options.find("#toground").click(function(_) {
-			for( c in children ) {
-				var obj = c.to(Object3D);
-				if( obj == null ) continue;
-				setGroundPos(ectx, obj);
-				var ctx = ectx.getContext(obj);
-				if( ctx != null ) obj.applyTransform(ctx.local3d);
-			}
-		});
-
-		options.find("#remove").click(function(_) {
-			var options = selectElement.children().elements();
-			for (opt in options) {
-				if (opt.prop("selected")) {
-					removeMeshPath(opt.val());
-					opt.remove();
-				}
-			}
-		});
-		options.find("#clean").click(function(_) {
-			if (hide.Ide.inst.confirm("Are you sure to remove all meshes for this MeshSpray ?")) {
-				var meshes = [];
-				for( c in children ) {
-					if( Std.is(c, Model) ) {
-						meshes.push(c);
-					}
-				}
-				sceneEditor.deleteElements(meshes);
-			}
-		});
-
-
-		ectx.properties.add(props, this, function(pname) {});
-
-		var optionsGroup = new hide.Element('<div class="group" id="groupConfig" name="Options"><dl></dl></div>');
-		optionsGroup.append(hide.comp.PropsEditor.makePropsList([
-				{ name: "density", t: PInt(1, 25), def: currentConfig.density },
-				{ name: "densityOffset", t: PInt(0, 10), def: currentConfig.densityOffset },
-				{ name: "radius", t: PFloat(0, 50), def: currentConfig.radius },
-				{ name: "deleteRadius", t: PFloat(0, 50), def: currentConfig.deleteRadius },
-				{ name: "scale", t: PFloat(0, 10), def: currentConfig.scale },
-				{ name: "scaleOffset", t: PFloat(0, 1), def: currentConfig.scaleOffset },
-				{ name: "rotation", t: PFloat(0, 180), def: currentConfig.rotation },
-				{ name: "rotationOffset", t: PFloat(0, 30), def: currentConfig.rotationOffset },
-				{ name: "zOffset", t: PFloat(0, 10), def: currentConfig.zOffset },
-				{ name: "orientTerrain", t: PFloat(0, 1), def: currentConfig.orientTerrain },
-				{ name: "tiltAmount", t: PFloat(0, 1), def: currentConfig.tiltAmount },
-			]));
-		ectx.properties.add(optionsGroup, this, function(pname) {
-			var value = sceneEditor.properties.element.find("input[field="+ pname + "]").val();
-			Reflect.setField(currentConfig, pname, Std.parseFloat(value));
-			saveConfigMeshBatch();
-		});
-
-		sceneEditor.setLock([this], currentConfig.enableBrush, false);
-		removeInteractiveBrush();
-		if (currentConfig.enableBrush)
-			createInteractiveBrush(ectx);
-		super.edit(ectx);
-
-		ectx.properties.add(new Element('
-		<div class="group" name="Extra">
-		<dl>
-			<dt>Split</dt><dd><input type="range" min="0" max="2048" field="split"/></dd>
-		</dl>
-		</div>'), this);
-	}
-
-	function createInteractiveBrush(ectx : EditContext) {
-		var ctx = ectx.getContext(this);
-		var s2d = @:privateAccess ctx.local2d.getScene();
-		interactive = new h2d.Interactive(10000, 10000, s2d);
-		interactive.propagateEvents = true;
-		interactive.cancelEvents = false;
-
-		interactive.onWheel = function(e) {
-
-		};
-
-		interactive.onKeyUp = function(e) {
-			if (e.keyCode == hxd.Key.R) {
-				lastMeshId = -1;
-				if (lastSpray < Date.now().getTime() - 100) {
-					if( !K.isDown( K.SHIFT) ) {
-						if (previewModels.length > 0) {
-							sceneEditor.deleteElements(previewModels, () -> { }, false);
-							previewModels = [];
-						}
-						var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-						previewMeshesAround(ectx, ctx, worldPos);
-					}
-					lastSpray = Date.now().getTime();
-				}
-			}
-		}
-
-		interactive.onPush = function(e) {
-			e.propagate = false;
-			sprayEnable = true;
-			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-			if( K.isDown( K.SHIFT) )
-				removeMeshesAround(ctx, worldPos);
-			else {
-				addMeshes(ctx);
-			}
-		};
-
-		interactive.onRelease = function(e) {
-			e.propagate = false;
-			sprayEnable = false;
-			var addedModels = sprayedModels.copy();
-			if (sprayedModels.length > 0) {
-				undo.change(Custom(function(undo) {
-					if(undo) {
-						sceneEditor.deleteElements(addedModels, () -> removeInteractiveBrush(), true, false);
-					}
-					else {
-						sceneEditor.addElements(addedModels, false, true, false);
-					}
-				}));
-				sprayedModels = [];
-			}
-
-			if (previewModels.length > 0) {
-				sceneEditor.deleteElements(previewModels, () -> { }, false);
-				previewModels = [];
-			}
-		};
-
-		interactive.onMove = function(e) {
-			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-
-			var shiftPressed = K.isDown( K.SHIFT);
-
-			drawCircle(ctx, worldPos.x, worldPos.y, worldPos.z, (shiftPressed) ? currentConfig.deleteRadius : currentConfig.radius, 5, (shiftPressed) ? 9830400 : 38400);
-
-			if (lastSpray < Date.now().getTime() - 100) {
-				if (previewModels.length > 0) {
-					sceneEditor.deleteElements(previewModels, () -> { }, false, false);
-					previewModels = [];
-				}
-				if( !shiftPressed ) {
-					previewMeshesAround(ectx, ctx, worldPos);
-				}
-
-				if( K.isDown( K.MOUSE_LEFT) ) {
-					e.propagate = false;
-
-					if (sprayEnable) {
-						if( shiftPressed ) {
-							removeMeshesAround(ctx, worldPos);
-						} else {
-							if (currentConfig.density == 1) sprayEnable = false;
-							else addMeshes(ctx);
-						}
-					}
-				}
-				lastSpray = Date.now().getTime();
-			}
-		};
-
-	}
-
-	function updateConfig() {
-		var CONFIG = currentConfig;
-		var defaultConfig = getDefaultConfig();
-		var fields = Reflect.fields(defaultConfig);
-		for (fieldName in fields) {
-			var fieldValue = Reflect.field(CONFIG, fieldName);
-			if (fieldValue == null) {
-				fieldValue = Reflect.field(defaultConfig, fieldName);
-				Reflect.setField(CONFIG, fieldName, fieldValue);
-			}
-			var input = sceneEditor.properties.element.find("input[field="+ fieldName + "]");
-			input.val(fieldValue);
-			input.change();
-		}
-
-		sceneEditor.properties.element.find("#repeatMesh").prop("checked", CONFIG.dontRepeatMesh);
-	}
-
-	override function removeInstance(ctx : Context):Bool {
-		removeInteractiveBrush();
-		return super.removeInstance(ctx);
-	}
-	override function setSelected( ctx : Context, b : Bool ) {
-		if( !b ) {
-			removeInteractiveBrush();
-			if( gBrushes != null ) {
-				for (g in gBrushes) g.remove();
-				gBrushes = null;
-			}
-		}
-		return false;
-	}
-
-	function removeInteractiveBrush() {
-		if( interactive != null ) interactive.remove();
-		if (previewModels != null && previewModels.length > 0) {
-			sceneEditor.deleteElements(previewModels, () -> { }, false, false);
-			previewModels = [];
-		}
-		if (wasEdited)
-			sceneEditor.refresh(Partial, () -> { });
-		wasEdited = false;
-		if( gBrushes != null ) {
-			for (g in gBrushes) g.remove();
-			gBrushes = null;
-		}
-	}
-
-	function addMeshPath(path : String) {
-		var mesh = { path: path, isRef: path.toLowerCase().indexOf(".fbx") == -1 };
-		if (currentMeshes.filter(m -> m.path == path).length == 0)
-			currentMeshes.push(mesh);
-		if (currentSet != null)
-			saveConfigMeshBatch();
-	}
-
-	function removeMeshPath(path : String) {
-		var mesh = currentMeshes.filter(m -> m.path == path);
-		if (mesh.length > 0)
-			currentMeshes.remove(mesh[0]);
-		if (currentSet != null)
-			saveConfigMeshBatch();
-	}
-
-	var localMat = new h3d.Matrix();
-	var lastPos : h3d.col.Point;
-	var lastMeshId = -1;
-	function previewMeshesAround(ectx : hide.prefab.EditContext, ctx : Context, point : h3d.col.Point) {
-		if (currentMeshes.length == 0) {
-			return;
-		}
-		var nbMeshesInZone = 0;
-		var vecRelat = point.toVector();
-		vecRelat.transform3x4(invParent);
-		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
-
-		final CONFIG = currentConfig;
-
-		var computedDensity = CONFIG.density + Std.random(CONFIG.densityOffset+1);
-
-		var minDistanceBetweenMeshesSq = (CONFIG.radius * CONFIG.radius / computedDensity);
-
-		var currentPivots : Array<h2d.col.Point> = [];
-		inline function distance(x1 : Float, y1 : Float, x2 : Float, y2 : Float) return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
-		var fakeRadius = CONFIG.radius * CONFIG.radius + minDistanceBetweenMeshesSq;
-		for (child in children) {
-			var model = child.to(hrt.prefab.Object3D);
-			if( model == null ) continue;
-			if (distance(point2d.x, point2d.y, model.x, model.y) < fakeRadius) {
-				if (previewModels.indexOf(model) != -1) continue;
-				nbMeshesInZone++;
-				currentPivots.push(new h2d.col.Point(model.x, model.y));
-			}
-		}
-		var nbMeshesToPlace = computedDensity - nbMeshesInZone;
-		if (computedDensity == 1)
-		if (previewModels.length > 0) {
-			sceneEditor.deleteElements(previewModels, () -> { }, false);
-			previewModels = [];
-		}
-		lastPos = point;
-		if (nbMeshesToPlace > 0) {
-			while (nbMeshesToPlace-- > 0) {
-				var nbTry = 5;
-				var position : h3d.col.Point;
-				do {
-					var randomRadius = CONFIG.radius*Math.sqrt(Math.random());
-					var angle = Math.random() * 2*Math.PI;
-
-					position = new h3d.col.Point(point.x + randomRadius*Math.cos(angle), point.y + randomRadius*Math.sin(angle), 0);
-					var vecRelat = position.toVector();
-					vecRelat.transform3x4(invParent);
-
-					var isNextTo = false;
-					for (cPivot in currentPivots) {
-						if (distance(vecRelat.x, vecRelat.y, cPivot.x, cPivot.y) <= minDistanceBetweenMeshesSq) {
-							isNextTo = true;
-							break;
-						}
-					}
-					if (!isNextTo) {
-						break;
-					}
-				} while (nbTry-- > 0);
-
-				var meshId = 0;
-				if(currentMeshes.length > 1) {
-					do
-						meshId = Std.random(currentMeshes.length)
-					while(CONFIG.dontRepeatMesh && meshId == lastMeshId);
-				}
-				lastIndexMesh = meshId;
-				if (computedDensity == 1)
-					lastMeshId = meshId;
-				else
-					lastMeshId = -1;
-
-				var meshUsed = currentMeshes[meshId];
-
-				var newPrefab : hrt.prefab.Object3D = null;
-
-				if (meshUsed.isRef) {
-					var refPrefab = new hrt.prefab.Reference(this);
-					refPrefab.source = meshUsed.path;
-					newPrefab = refPrefab;
-				} else {
-					var model = new hrt.prefab.Model(this);
-					model.source = meshUsed.path;
-					newPrefab = model;
-				}
-
-				newPrefab.name = extractMeshName(meshUsed.path);
-
-				localMat.identity();
-
-				var randScaleOffset = Math.random() * CONFIG.scaleOffset;
-				if (Std.random(2) == 0) {
-					randScaleOffset *= -1;
-				}
-				var currentScale = hxd.Math.fmt(CONFIG.scale + randScaleOffset);
-
-				localMat.scale(currentScale, currentScale, currentScale);
-
-				position.z = ectx.positionToGroundZ(position.x, position.y) + CONFIG.zOffset;
-				localMat.setPosition(new Vector(hxd.Math.fmt(position.x), hxd.Math.fmt(position.y), position.z));
-				localMat.multiply(localMat, invParent);
-
-				newPrefab.setTransform(localMat);
-				setGroundPos(ectx, newPrefab);
-
-				previewModels.push(newPrefab);
-				currentPivots.push(new h2d.col.Point(newPrefab.x, newPrefab.y));
-			}
-
-			if (previewModels.length > 0) {
-				sceneEditor.addElements(previewModels, false, false, false);
-			}
-		}
-	}
-
-	function addMeshes(ctx : Context) {
-		lastMeshId = -1;
-		if (previewModels.length > 0) {
-			wasEdited = true;
-			sprayedModels = sprayedModels.concat(previewModels);
-			previewModels = [];
-		}
-	}
-
-	function removeMeshesAround(ctx : Context, point : h3d.col.Point) {
-		var vecRelat = point.toVector();
-		vecRelat.transform3x4(invParent);
-		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
-
-		var childToRemove = [];
-		inline function distance(x1 : Float, y1 : Float, x2 : Float, y2 : Float) return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
-		var fakeRadius = currentConfig.deleteRadius * currentConfig.deleteRadius;
-		for (child in children) {
-			var model = child.to(hrt.prefab.Object3D);
-			if (model != null) {
-				if (distance(point2d.x, point2d.y, model.x, model.y) < fakeRadius) {
-					childToRemove.push(child);
-				}
-			}
-		}
-		if (childToRemove.length > 0) {
-			wasEdited = true;
-			sceneEditor.deleteElements(childToRemove, () -> { }, false);
-		}
-	}
-
-	public function drawCircle(ctx : Context, originX : Float, originY : Float, originZ : Float, radius: Float, thickness: Float, color) {
-		var newColor = h3d.Vector.fromColor(color);
-		if (gBrushes == null || gBrushes.length == 0 || gBrushes[0].scaleX != radius || gBrushes[0].material.color != newColor) {
-			if (gBrushes != null) {
-				for (g in gBrushes) g.remove();
-			}
-			gBrushes = [];
-			var gBrush = new h3d.scene.Mesh(makePrimCircle(32, 0.95), ctx.local3d);
-			gBrush.scaleX = gBrush.scaleY = radius;
-			gBrush.ignoreParentTransform = true;
-			gBrush.material.mainPass.setPassName("overlay");
-			gBrush.material.shadows = false;
-			gBrush.material.color = newColor;
-			gBrushes.push(gBrush);
-			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), ctx.local3d);
-			gBrush.ignoreParentTransform = true;
-			gBrush.material.mainPass.setPassName("overlay");
-			gBrush.material.shadows = false;
-			gBrush.material.color = newColor;
-			gBrushes.push(gBrush);
-		}
-		for (g in gBrushes) g.visible = true;
-		for (g in gBrushes) {
-			g.x = originX;
-			g.y = originY;
-			g.z = originZ + 0.025;
-		}
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		ctx.local3d = new MeshSprayObject(this, ctx.local3d);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function make(ctx:Context):Context {
-		if( !enabled )
-			return ctx;
-		ctx = makeInstance(ctx);
-		// add all children then build meshspray
-		for( c in children )
-			if( c.type == "model" )
-				makeChildren(ctx, c);
-		cast(ctx.local3d, MeshSprayObject).redraw();
-		// then add other children (shaders etc.)
-		for( c in children )
-			if( c.type != "model" )
-				makeChildren(ctx, c);
-		// rebuild to apply per instance shaders
-		cast(ctx.local3d, MeshSprayObject).redraw(true);
-		return ctx;
-	}
-
-	override function applyTransform(o : h3d.scene.Object) {
-		super.applyTransform(o);
-		cast(o, MeshSprayObject).redraw();
-	}
-
-
-	function makePrimCircle(segments: Int, inner : Float = 0, rings : Int = 0) {
-		var points = [];
-		var uvs = [];
-		var indices = [];
-		++segments;
-		var anglerad = hxd.Math.degToRad(360);
-		for(i in 0...segments) {
-			var t = i / (segments - 1);
-			var a = hxd.Math.lerp(-anglerad/2, anglerad/2, t);
-			var ct = hxd.Math.cos(a);
-			var st = hxd.Math.sin(a);
-			for(r in 0...(rings + 2)) {
-				var v = r / (rings + 1);
-				var r = hxd.Math.lerp(inner, 1.0, v);
-				points.push(new h2d.col.Point(ct * r, st * r));
-				uvs.push(new h2d.col.Point(t, v));
-			}
-		}
-		for(i in 0...segments-1) {
-			for(r in 0...(rings + 1)) {
-				var idx = r + i * (rings + 2);
-				var nxt = r + (i + 1) * (rings + 2);
-				indices.push(idx);
-				indices.push(idx + 1);
-				indices.push(nxt);
-				indices.push(nxt);
-				indices.push(idx + 1);
-				indices.push(nxt + 1);
-			}
-		}
-
-		var verts = [for(p in points) new h3d.col.Point(p.x, p.y, 0.)];
-		var idx = new hxd.IndexBuffer();
-		for(i in indices)
-			idx.push(i);
-		var primitive = new h3d.prim.Polygon(verts, idx);
-		primitive.normals = [for(p in points) new h3d.col.Point(0, 0, 1.)];
-		primitive.tangents = [for(p in points) new h3d.col.Point(0., 1., 0.)];
-		primitive.uvs = [for(uv in uvs) new h3d.prim.UV(uv.x, uv.y)];
-		primitive.colors = [for(p in points) new h3d.col.Point(1,1,1)];
-		primitive.incref();
-		return primitive;
-	}
-
-	override function flatten<T:Prefab>( ?cl : Class<T>, ?arr: Array<T> ) : Array<T> {
-		if(arr == null)
-			arr = [];
-		if( cl == null )
-			arr.push(cast this);
-		else {
-			var i = to(cl);
-			if(i != null)
-				arr.push(i);
-		}
-		return arr;
-	}
-
-	static var _ = Library.register("meshSpray", MeshSpray);
-
-}
-
-#end

+ 0 - 205
hrt/prefab/l3d/Particles3D.hx

@@ -1,205 +0,0 @@
-package hrt.prefab.l3d;
-
-class Particules3D extends Object3D {
-
-	@:s var data : Any;
-
-	public function new(?parent) {
-		super(parent);
-		type = "particules3D";
-	}
-
-	override function createObject(ctx:Context) {
-		var parts = new h3d.parts.GpuParticles(ctx.local3d);
-		if( data != null )
-			parts.load(data);
-		else if( !parts.getGroups().hasNext() )
-			parts.addGroup().isRelative = true;
-		return parts;
-	}
-
-	#if editor
-
-	override function setSelected(ctx:Context, b:Bool):Bool {
-		return true;
-	}
-
-	override function edit(ectx:EditContext) {
-		super.edit(ectx);
-		var ctx = ectx.getContext(this);
-		if( ctx == null ) return;
-		var parts = cast(ctx.local3d,h3d.parts.GpuParticles);
-
-		function undo(f) {
-			ectx.properties.undo.change(Custom(function(redo) { f(redo); data = parts.save(); }));
-			data = parts.save();
-		}
-
-		function addGroup( g : h3d.parts.GpuParticles.GpuPartGroup ) {
-			var e = new Element('
-				<div class="section">
-					<h1><span>${g.name}</span> &nbsp;<input type="checkbox" field="enable"/></h1>
-					<div class="content">
-
-						<div class="group" name="Display">
-							<dl>
-								<dt>Name</dt><dd><input field="name" onchange="$(this).closest(\'.section\').find(\'>h1 span\').text($(this).val())"/></dd>
-								<dt>Texture</dt><dd><input type="texture" field="texture"/></dd>
-								<dt>Color Gradient</dt><dd><input type="texture" field="colorGradient"/></dd>
-								<dt>Sort</dt><dd><select field="sortMode"></select></dd>
-								<dt>3D&nbsp;Transform</dt><dd><input type="checkbox" field="transform3D"/></dd>
-								<dt>Relative position</dt><dd><input type="checkbox" field="isRelative"/></dd>
-								<dt>Attach to cam</dt><dd><input type="checkbox" field="attachToCam"/></dd>
-								<dt>Distance to cam</dt><dd><input type="range" min="0" max="10" field="distanceToCam"/></dd>
-							</dl>
-						</div>
-
-						<div class="group material" name="Material">
-						</div>
-
-						<div class="group" name="Emit">
-							<dl>
-								<dt>Mode</dt><dd><select field="emitMode"/></dd>
-								<dt>Count</dt><dd><input type="range" field="nparts" min="0" max="1000" step="1"/></dd>
-								<dt>Distance</dt><dd><input type="range" field="emitDist" min="0" max="10"/></dd>
-								<dt>Angle</dt><dd><input type="range" field="emitAngle" min="${-Math.PI/2}" max="${Math.PI}"/></dd>
-								<dt>Sync</dt><dd><input type="range" field="emitSync" min="0" max="1"/></dd>
-								<dt>Delay</dt><dd><input type="range" field="emitDelay" min="0" max="10"/></dd>
-								<dt>Loop</dt><dd><input type="checkbox" field="emitLoop"/></dd>
-								<dt>Border</dt><dd><input type="checkbox" field="emitOnBorder"/></dd>
-							</dl>
-						</div>
-
-						<div class="group" name="Life">
-							<dl>
-								<dt>Initial</dt><dd><input type="range" field="life" min="0" max="10"/></dd>
-								<dt>Randomness</dt><dd><input type="range" field="lifeRand" min="0" max="1"/></dd>
-								<dt>Fade In</dt><dd><input type="range" field="fadeIn" min="0" max="1"/></dd>
-								<dt>Fade Out</dt><dd><input type="range" field="fadeOut" min="0" max="1"/></dd>
-								<dt>Fade Power</dt><dd><input type="range" field="fadePower" min="0" max="3"/></dd>
-							</dl>
-						</div>
-
-						<div class="group" name="Speed">
-							<dl>
-								<dt>Initial</dt><dd><input type="range" field="speed" min="0" max="10"/></dd>
-								<dt>Randomness</dt><dd><input type="range" field="speedRand" min="0" max="1"/></dd>
-								<dt>Acceleration</dt><dd><input type="range" field="speedIncr" min="-1" max="1"/></dd>
-								<dt>Gravity</dt><dd><input type="range" field="gravity" min="-5" max="5"/></dd>
-							</dl>
-						</div>
-
-						<div class="group" name="Size">
-							<dl>
-								<dt>Initial</dt><dd><input type="range" field="size" min="0.01" max="2"/></dd>
-								<dt>Randomness</dt><dd><input type="range" field="sizeRand" min="0" max="1"/></dd>
-								<dt>Growth</dt><dd><input type="range" field="sizeIncr" min="-1" max="1"/></dd>
-							</dl>
-						</div>
-
-						<div class="group" name="Rotation">
-							<dl>
-								<dt>Initial</dt><dd><input type="range" field="rotInit" min="0" max="1"/></dd>
-								<dt>Speed</dt><dd><input type="range" field="rotSpeed" min="0" max="5"/></dd>
-								<dt>Randomness</dt><dd><input type="range" field="rotSpeedRand" min="0" max="1"/></dd>
-							</dl>
-						</div>
-
-						<div class="group" name="Animation">
-							<dl>
-								<dt>Animation Repeat</dt><dd><input type="range" field="animationRepeat" min="0" max="10"/></dd>
-								<dt>Frame Division</dt><dd>
-									X <input type="number" style="width:30px" field="frameDivisionX" min="1" max="16"/>
-									Y <input type="number" style="width:30px" field="frameDivisionY" min="1" max="16"/>
-									# <input type="number" style="width:30px" field="frameCount" min="0" max="32"/>
-								</dd>
-							</dl>
-						</div>
-
-					</div>
-				</div>
-			');
-
-			e.find("h1").contextmenu(function(ev) {
-				var groups = @:privateAccess parts.groups;
-				var index = groups.indexOf(g);
-				function moveIndex(d:Int,history=true) {
-					var index = groups.indexOf(g);
-					parts.removeGroup(g);
-					parts.addGroup(g, index + d);
-					if( history ) undo(function(undo) moveIndex(undo ? -d : d,false));
-					ectx.rebuildProperties();
-				}
-				new hide.comp.ContextMenu([
-					{ label : "Enable", checked : g.enable, click : function() { g.enable = !g.enable; e.find("[field=enable]").prop("checked", g.enable); } },
-					{ label : "Copy", click : function() ectx.ide.setClipboard(g.save()) },
-					{ label : "Paste", enabled : ectx.ide.getClipboard() != null, click : function() {
-						var prev = g.save();
-						var next = ectx.ide.getClipboard();
-						g.load(@:privateAccess h3d.parts.GpuParticles.VERSION, next);
-						undo(function(undo) {
-							g.load(@:privateAccess h3d.parts.GpuParticles.VERSION, undo ? prev : next);
-							ectx.rebuildProperties();
-						});
-						ectx.rebuildProperties();
-					} },
-					{ label : "MoveUp", enabled : index > 0, click : function() moveIndex(-1) },
-					{ label : "MoveDown", enabled : index < groups.length - 1, click : function() moveIndex(1) },
-					{ label : "Delete", click : function() {
-						parts.removeGroup(g);
-						e.remove();
-						undo(function(undo) {
-							if( undo )
-								parts.addGroup(g, index);
-							else
-								parts.removeGroup(g);
-							ectx.rebuildProperties();
-						});
-					}},
-				]);
-				ev.preventDefault();
-			});
-			e.find("[field=emitLoop]").change(function(_) parts.currentTime = 0);
-			e = ectx.properties.add(e, g, function(_) {
-				data = parts.save();
-			});
-			ectx.properties.addMaterial( parts.materials[Lambda.indexOf({ iterator : parts.getGroups }, g)], e.find(".material > .content") );
-			return e;
-		}
-
-		for( g in parts.getGroups() )
-			addGroup(g);
-
-		var extra = new Element('
-			<div class="section">
-				<h1>Manage</h1>
-				<div class="content">
-					<dl>
-					<dt></dt><dd><input type="button" class="new" value="New Group"/></dd>
-					</dl>
-				</div>
-			</div>
-		');
-
-		extra.find(".new").click(function(_) {
-			var g = parts.addGroup();
-			g.name = "Group#" + Lambda.count({ iterator : parts.getGroups });
-			g.isRelative = true;
-			addGroup(g);
-			ectx.rebuildProperties();
-			undo(function(undo) {
-				if( undo )
-					parts.removeGroup(g);
-				else
-					parts.addGroup(g);
-				ectx.rebuildProperties();
-			});
-		}, null);
-		ectx.properties.add(extra);
-
-	}
-	#end
-
-	static var _ = Library.register("particules3D", Particules3D);
-
-}

+ 0 - 451
hrt/prefab/l3d/Polygon.hx

@@ -1,451 +0,0 @@
-package hrt.prefab.l3d;
-import hxd.Math;
-import h2d.col.Point;
-
-
-enum Shape {
-	Quad(subdivision : Int);
-	Disc(segments: Int, angle: Float, inner: Float, rings:Int);
-	Custom;
-}
-
-typedef PrimCache = Map<Shape, h3d.prim.Polygon>;
-
-class Polygon extends Object3D {
-
-	@:c public var shape(default, null) : Shape = Quad(0);
-	@:c public var points : h2d.col.Polygon;
-	@:s public var color : Int = 0xFFFFFFFF;
-	#if editor
-	public var editor : hide.prefab.PolygonEditor;
-	public var cachedPrim : h3d.prim.Polygon;
-	public var hasDebugColor : Bool = true;
-	var prevScale = [1.0, 1.0];
-	#end
-
-	public function new(?parent) {
-		super(parent);
-		type = "polygon";
-	}
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		obj.kind = shape.getIndex();
-		switch(shape){
-		case Quad(subdivision):
-			obj.args = shape.getParameters();
-		case Disc(segments, angle, inner, rings):
-			obj.args = shape.getParameters();
-		case Custom:
-			obj.points = [for( p in points ) { x : p.x, y : p.y }];
-		}
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		switch(obj.kind){
-			case 0, 1: shape = Type.createEnumIndex(Shape, obj.kind, obj.args == null ? [0] : obj.args);
-			case 2:
-				shape = Custom;
-				var list : Array<Dynamic> = obj.points;
-				points = [for(pt in list) new h2d.col.Point(pt.x, pt.y)];
-		}
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
-		var mesh : h3d.scene.Mesh = cast ctx.local3d;
-		mesh.primitive = makePrimitive();
-		#if editor
-		setColor(ctx, color);
-		if(editor != null)
-			editor.update(propName);
-		#else
-		mesh.material.color.setColor(color);
-		#end
-	}
-
-	function getPrimCache() {
-		var engine = h3d.Engine.getCurrent();
-		var cache : PrimCache = @:privateAccess engine.resCache.get(Polygon);
-		if(cache == null) {
-			cache = new PrimCache();
-			@:privateAccess engine.resCache.set(Polygon, cache);
-		}
-		return cache;
-	}
-
-	public function makePrimitive() {
-
-		if(shape == Custom) {
-			#if editor
-			if(cachedPrim != null) return cachedPrim;
-			#end
-			return generateCustomPolygon();
-		}
-
-		var cache = getPrimCache();
-		var primitive : h3d.prim.Polygon = cache.get(shape);
-		if(primitive != null)
-			return primitive;
-
-		primitive = createPrimitive(shape);
-		primitive.incref();
-		cache.set(shape, primitive);
-		return primitive;
-	}
-
-	override function localRayIntersection(ctx : hrt.prefab.Context, ray:h3d.col.Ray):Float {
-		var prim = makePrimitive();
-		var col = prim.getCollider();
-		return col.rayIntersection(ray, true);
-	}
-
-	public function getPolygonBounds() : h2d.col.Polygon {
-		return switch( shape ) {
-		case Quad(subdivision):
-			[
-				new Point(-0.5, -0.5),
-				new Point(0.5, -0.5),
-				new Point(0.5,  0.5),
-				new Point(-0.5,  0.5)
-			];
-		case Disc(segments, angle, _):
-			if(angle >= 360)
-				angle = 360;
-			++segments;
-			var anglerad = hxd.Math.degToRad(angle);
-			[for(i in 0...segments) {
-				var t = i / (segments - 1);
-				var a = hxd.Math.lerp(-anglerad/2, anglerad/2, t);
-				var ct = hxd.Math.cos(a);
-				var st = hxd.Math.sin(a);
-				new Point(ct, st);
-			}];
-		case Custom:
-			[for( p in points ) p.clone()];
-		};
-	}
-
-	public static function createPrimitive( shape : Shape ) {
-		var uvs : Array<Point> = null;
-		var points : Array<Point> = null;
-		var indices : Array<Int> = null;
-
-		switch(shape) {
-			case Quad(subdivision):
-
-				var size = subdivision + 1;
-				var cellCount = size;
-				cellCount *= cellCount;
-
-				points = [];
-				for( y in 0 ... size + 1 ) {
-					for( x in 0 ... size + 1 ) {
-						points.push(new Point(Math.lerp(-0.5, 0.5, x / size), Math.lerp(-0.5, 0.5, y / size)));
-					}
-				}
-
-				indices = [];
-				for( y in 0 ... size ) {
-					for( x in 0 ... size ) {
-						var i = x + y * (size + 1);
-						if( i % 2 == 0 ) {
-							indices.push(i);
-							indices.push(i + 1);
-							indices.push(i + size + 2);
-							indices.push(i);
-							indices.push(i + size + 2);
-							indices.push(i + size + 1);
-						}
-						else {
-							indices.push(i + size + 1);
-							indices.push(i);
-							indices.push(i + 1);
-							indices.push(i + 1);
-							indices.push(i + size + 2);
-							indices.push(i + size + 1);
-						}
-					}
-				}
-
-				uvs = [for(v in points) new Point(v.x + 0.5, v.y + 0.5)];
-
-			case Disc(segments, angle, inner, rings):
-				points = [];
-				uvs = [];
-				indices = [];
-				if(angle >= 360)
-					angle = 360;
-				++segments;
-				var anglerad = hxd.Math.degToRad(angle);
-				for(i in 0...segments) {
-					var t = i / (segments - 1);
-					var a = hxd.Math.lerp(-anglerad/2, anglerad/2, t);
-					var ct = hxd.Math.cos(a);
-					var st = hxd.Math.sin(a);
-					for(r in 0...(rings + 2)) {
-						var v = r / (rings + 1);
-						var r = hxd.Math.lerp(inner, 1.0, v);
-						points.push(new Point(ct * r, st * r));
-						uvs.push(new Point(t, v));
-					}
-				}
-				for(i in 0...segments-1) {
-					for(r in 0...(rings + 1)) {
-						var idx = r + i * (rings + 2);
-						var nxt = r + (i + 1) * (rings + 2);
-						indices.push(idx);
-						indices.push(idx + 1);
-						indices.push(nxt);
-						indices.push(nxt);
-						indices.push(idx + 1);
-						indices.push(nxt + 1);
-					}
-				}
-			default:
-		}
-
-		var verts = [for(p in points) new h3d.col.Point(p.x, p.y, 0.)];
-		var idx = new hxd.IndexBuffer();
-		for(i in indices)
-			idx.push(i);
-		var primitive = new h3d.prim.Polygon(verts, idx);
-		primitive.normals = [for(p in points) new h3d.col.Point(0, 0, 1.)];
-		primitive.tangents = [for(p in points) new h3d.col.Point(0., 1., 0.)];
-		primitive.uvs = [for(uv in uvs) new h3d.prim.UV(uv.x, uv.y)];
-		primitive.colors = [for(p in points) new h3d.col.Point(1,1,1)];
-		return primitive;
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var primitive = makePrimitive();
-		var mesh = new h3d.scene.Mesh(primitive, ctx.local3d);
-		mesh.material.props = h3d.mat.MaterialSetup.current.getDefaults("overlay");
-		mesh.material.blendMode = Alpha;
-		mesh.material.mainPass.culling = None;
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	#if editor
-	public function setColor(ctx: Context, color: Int) {
-		if(hrt.prefab.Material.hasOverride(this))
-			return;
-		if(ctx.local3d == null)
-			return;
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
-		if(mesh != null && hasDebugColor)
-			hrt.prefab.l3d.Box.setDebugColor(color, mesh.material);
-	}
-	#end
-
-	public function generateCustomPolygon(){
-		var polyPrim : h3d.prim.Polygon = null;
-		if( points != null ){
-			var indexes = points.fastTriangulate();
-			var idx : hxd.IndexBuffer = new hxd.IndexBuffer();
-			for( i in indexes ) #if js if( i != null ) #end idx.push(i);
-			var pts = [for( p in points ) new h3d.col.Point(p.x, p.y, 0)];
-			polyPrim = new h3d.prim.Polygon(pts, idx);
-			polyPrim.addNormals();
-			polyPrim.addUVs();
-			polyPrim.addTangents() ;
-			polyPrim.alloc(h3d.Engine.getCurrent());
-		}
-		#if editor
-		clearCustomPolygonCache();
-		cachedPrim = polyPrim;
-		cachedPrim.incref();
-		#end
-		return polyPrim;
-	}
-
-	public function getPrimitive( ctx : Context ) : h3d.prim.Polygon {
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
-		return Std.downcast(mesh.primitive, h3d.prim.Polygon);
-	}
-
-	#if editor
-	function clearCustomPolygonCache() {
-		if(cachedPrim != null) {
-			cachedPrim.decref();
-			cachedPrim = null;
-		}
-	}
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		super.setSelected(ctx, b);
-		if( editor != null && shape == Custom)
-			editor.setSelected(ctx, b);
-		return true;
-	}
-
-	function createEditor( ctx : EditContext ){
-		if( editor == null )
-			editor = new hide.prefab.PolygonEditor(this, ctx.properties.undo);
-		editor.editContext = ctx;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-		createEditor(ctx);
-
-		var prevKind : Shape = this.shape;
-		var viewModel = {
-			kind: shape.getName(),
-			subdivision: 0,
-			segments: 24,
-			rings: 4,
-			innerRadius: 0.0,
-			angle: 360.0
-		};
-
-		switch(shape) {
-			case Quad(subdivision):
-				viewModel.subdivision = subdivision;
-			case Disc(seg, angle, inner, rings):
-				viewModel.segments = seg;
-				viewModel.angle = angle;
-				viewModel.innerRadius = inner;
-			case Custom:
-			default:
-		}
-
-		var group = new hide.Element('
-		<div class="group" name="Shape">
-			<dl>
-				<dt>Kind</dt><dd>
-					<select field="kind">
-						<option value="Quad">Quad</option>
-						<option value="Disc">Disc</option>
-						<option value="Custom">Custom</option>
-					</select>
-				</dd>
-			</dl>
-		</div>
-		');
-
-		var quadProps = new hide.Element('
-			<dt>Subdivision</dt><dd><input field="subdivision" type="range" min="0" max="100" step="1" /></dd>');
-
-		var discProps = new hide.Element('
-			<dt>Segments</dt><dd><input field="segments" type="range" min="0" max="100" step="1" /></dd>
-			<dt>Rings</dt><dd><input field="rings" type="range" min="0" max="100" step="1" /></dd>
-			<dt>Inner radius</dt><dd><input field="innerRadius" type="range" min="0" max="1" /></dd>
-			<dt>Angle</dt><dd><input field="angle" type="range" min="0" max="360" /></dd>');
-
-		group.append(quadProps);
-		group.append(discProps);
-
-		var updateProps = null;
-
-		ctx.properties.add(group, viewModel, function(pname) {
-			var pIsKind = pname == "kind";
-			if( pIsKind ) {
-				editor.reset();
-
-				if( prevKind != Custom ){
-					var cache = getPrimCache();
-					var prim = cache.get(shape);
-					if(prim != null){
-						prim.dispose();
-						cache.remove(shape);
-					}
-				}
-				else if( prevKind == Custom ){
-					var mesh = Std.downcast(ctx.getContext(this).local3d, h3d.scene.Mesh);
-					if( mesh.primitive != null ) mesh.primitive.dispose(); // Dispose custom prim
-				}
-
-				prevKind = this.shape;
-			}
-
-			switch( viewModel.kind ) {
-				case "Quad":
-					shape = Quad(viewModel.subdivision);
-					if(pIsKind && prevKind == Custom) {
-						scaleX = prevScale[0];
-						scaleY = prevScale[1];
-					}
-				case "Disc":
-					shape = Disc(viewModel.segments, viewModel.angle, viewModel.innerRadius, viewModel.rings);
-					if(pIsKind && prevKind == Custom) {
-						scaleX = prevScale[0];
-						scaleY = prevScale[1];
-					}
-				case "Custom":
-					shape = Custom;
-					if(pIsKind) {
-						if(prevKind.match(Quad(_))) {
-							prevScale = [scaleX, scaleY];
-							function apply() {
-								points = [
-									new Point(-scaleX/2, -scaleY/2),
-									new Point(-scaleX/2, scaleY/2),
-									new Point(scaleX/2, scaleY/2),
-									new Point(scaleX/2, -scaleY/2)
-								];
-								scaleX = 1.0; scaleY = 1.0;
-							}
-							ctx.properties.undo.change(Custom(function(undo) {
-								if(undo) {
-									scaleX = prevScale[0];
-									scaleY = prevScale[1];
-									points = null;
-								}
-								else apply();
-								ctx.onChange(this, null);
-							}));
-							clearCustomPolygonCache();
-							apply();
-							ctx.onChange(this, null);
-						}
-						else
-							points = [];
-					}
-				default: shape = Quad(0);
-			}
-
-			updateProps();
-			ctx.onChange(this, pname);
-		});
-
-
-		var editorProps = editor.addProps(ctx);
-
-		updateProps = function() {
-			quadProps.hide();
-			discProps.hide();
-			editorProps.hide();
-			switch(viewModel.kind){
-				case "Quad": quadProps.show();
-				case "Disc": discProps.show();
-				case "Custom":
-					editorProps.show();
-					setSelected(ctx.getContext(this), true);
-				default:
-			}
-		}
-
-		ctx.properties.add( new hide.Element('
-			<div class="group" name="Params">
-				<dl><dt>Color</dt><dd><input type="color" alpha="true" field="color"/></dd> </dl>
-			</div>'), this, function(pname) { ctx.onChange(this, pname); });
-
-		updateProps();
-
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "square", name : "Polygon" };
-	}
-
-	#end
-
-	static var _ = Library.register("polygon", Polygon);
-}

+ 0 - 575
hrt/prefab/l3d/Spline.hx

@@ -1,575 +0,0 @@
-package hrt.prefab.l3d;
-
-import hxd.Math;
-
-enum CurveShape {
-	Linear;
-	Quadratic;
-	Cubic;
-}
-
-typedef SplinePointData = {
-	pos : h3d.col.Point,
-	tangent : h3d.col.Point,
-	prev : SplinePoint,
-	next : SplinePoint,
-	?t : Float
-}
-
-class SplineData {
-	public var length : Float;
-	public var step : Int;
-	public var samples : Array<SplinePointData> = [];
-	public function new() {}
-}
-
-class SplinePointObject extends h3d.scene.Object {
-	override function sync(ctx : h3d.scene.RenderContext)
-	{
-		onSync(ctx);
-		super.sync(ctx);
-	}
-
-	override function onRemove() {
-		super.onRemove();
-		onRemoveDynamic();
-	}
-	public dynamic function onRemoveDynamic() {}
-	public dynamic function onSync(rctx: h3d.scene.RenderContext) {}
-}
-
-class SplinePoint extends Object3D {
-
-	var pointViewer : h3d.scene.Mesh;
-	var controlPointsViewer : h3d.scene.Graphics;
-	var indexText : h2d.ObjectFollower;
-	var spline(get, default) : Spline;
-	var obj : SplinePointObject;
-	function get_spline() {
-		return parent.to(Spline);
-	}
-
-	override public function new(?parent) {
-		super(parent);
-		type = "splinePoint";
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		#if editor
-		ctx = ctx.clone(this);
-		ctx.local3d = createObject(ctx);
-		pointViewer = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), null, ctx.local3d.getScene());
-		pointViewer.ignoreParentTransform = true;
-		pointViewer.follow = ctx.local3d;
-		pointViewer.followPositionOnly = true;
-		pointViewer.setScale(0.2);
-		pointViewer.name = "pointViewer";
-		pointViewer.material.setDefaultProps("ui");
-		pointViewer.material.color.set(0,0,1,1);
-		pointViewer.material.mainPass.depthTest = Always;
-
-		controlPointsViewer = new h3d.scene.Graphics(ctx.local3d);
-		controlPointsViewer.name = "controlPointsViewer";
-		controlPointsViewer.lineStyle(4, 0xffffff);
-		controlPointsViewer.material.mainPass.setPassName("ui");
-		controlPointsViewer.material.mainPass.depthTest = Always;
-		controlPointsViewer.ignoreParentTransform = false;
-		controlPointsViewer.clear();
-		controlPointsViewer.moveTo(1, 0, 0);
-		controlPointsViewer.lineTo(-1, 0, 0);
-
-		indexText = new h2d.ObjectFollower(pointViewer,  @:privateAccess ctx.local2d.getScene());
-		var t = new h2d.Text(hxd.res.DefaultFont.get(), indexText);
-		t.textColor = 0xff00ff;
-		t.textAlign = Center;
-		t.dropShadow = { dx : 0.5, dy : 0.5, color : 0x202020, alpha : 1.0 };
-		t.setScale(2.5);
-		applyTransform(ctx.local3d);
-		setViewerVisible(false);
-		obj = new SplinePointObject(ctx.local3d);
-		obj.onSync = function(rctx) {
-			var cam = rctx.camera;
-			var gpos = obj.getAbsPos().getPosition();
-			var distToCam = cam.pos.sub(gpos).length();
-			var engine = h3d.Engine.getCurrent();
-			var ratio = 18 / engine.height;
-			pointViewer.setScale(ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0));
-			@:privateAccess obj.calcAbsPos();
-		}
-		obj.onRemoveDynamic = function() {
-			indexText.remove();
-			pointViewer.remove();
-		}
-		updateInstance(ctx);
-		#end
-		return ctx;
-	}
-
-	override function applyTransform(o : h3d.scene.Object) {
-		super.applyTransform(o);
-		#if editor
-			if (spline.editor != null)
-				@:privateAccess spline.computeSpline(spline.editor.editContext.getContext(spline));
-		#end
-	}
-
-	override function updateInstance(ctx : Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
-		#if editor
-			if( spline.editor != null ) {
-				spline.editor.setSelected(spline.editor.editContext.getContext(spline), true);
-				spline.editor.update(spline.editor.editContext.getContext(spline));
-			}
-			for (sp in spline.points) {
-				sp.computeName(ctx);
-			}
-		#end
-	}
-
-	override function removeInstance( ctx : Context) : Bool {
-		haxe.Timer.delay(() -> { // wait for next frame, need the point to be removed from children to recompute spline accurately
-			#if editor
-				if (spline.editor != null && spline.editor.editContext.getContext(spline) != null)
-					@:privateAccess spline.computeSpline(spline.editor.editContext.getContext(spline));
-			#end
-		}, 0);
-		return super.removeInstance(ctx);
-	}
-
-
-	#if editor
-
-	public function computeName(ctx) {
-		var index = spline.points.indexOf(this);
-		name = "SplinePoint" + index;
-		ctx.local3d.name = name;
-		if (indexText != null) {
-			var t = Std.downcast(indexText.getChildAt(0), h2d.Text);
-			t.text = "" + index;
-		}
-	}
-
-	override function edit(ctx : EditContext) {
-		super.edit(ctx);
-		if( spline.editor == null ) {
-			spline.editor = new hide.prefab.SplineEditor(spline, ctx.properties.undo);
-		}
-		spline.editor.editContext = ctx;
-	}
-	override function getHideProps() : HideProps {
-		return { icon : "arrows-v", name : "SplinePoint", allowParent: function(p) return p.to(Spline) != null, allowChildren: function(s) return false};
-	}
-	#end
-
-	inline public function getPoint() : h3d.col.Point {
-		return getAbsPos().getPosition().toPoint();
-	}
-
-	public function getTangent() : h3d.col.Point {
-		var tangent = getAbsPos().front().toPoint();
-		tangent.scale(-1);
-		return tangent;
-	}
-
-	public function getFirstControlPoint() : h3d.col.Point {
-		var absPos = getAbsPos();
-		var right = absPos.front();
-		right.scale3(scaleX*scaleY);
-		var pos = new h3d.col.Point(absPos.tx, absPos.ty, absPos.tz);
-		pos = pos.add(right.toPoint());
-		return pos;
-	}
-
-	public function getSecondControlPoint() : h3d.col.Point {
-		var absPos = getAbsPos();
-		var left = absPos.front();
-		left.scale3(-scaleX*scaleZ);
-		var pos = new h3d.col.Point(absPos.tx, absPos.ty, absPos.tz);
-		pos = pos.add(left.toPoint());
-		return pos;
-	}
-	public function setViewerVisible(visible : Bool) {
-		pointViewer.visible = visible;
-		indexText.visible = visible;
-		controlPointsViewer.visible = visible;
-	}
-	public function setColor( color : Int ) {
-		controlPointsViewer.setColor(color);
-		pointViewer.material.color.setColor(color);
-	}
-
-	static var _ = hrt.prefab.Library.register("splinePoint", SplinePoint);
-}
-
-class Spline extends Object3D {
-	public var points(get, null) : Array<SplinePoint>;
-	function get_points() {
-		var pts : Array<SplinePoint> = [];
-		for (c in children) {
-			var sp = c.to(SplinePoint);
-			if (sp != null) pts.push(sp);
-		}
-		return pts;
-	}
-
-	@:c public var shape : CurveShape = Linear;
-
-	var data : SplineData;
-	@:s var step : Int = 1;
-
-	// Save/Load the curve as an array of local transform
-	@:c public var pointsData : Array<h3d.Matrix> = [];
-
-	// Graphic
-	@:s public var showSpline : Bool = true;
-	public var lineGraphics : h3d.scene.Graphics;
-	@:s public var lineThickness : Int = 4;
-	@:s public var color : Int = 0xFFFFFFFF;
-	@:s public var loop : Bool = false;
-
-	#if editor
-	public var editor : hide.prefab.SplineEditor;
-	#end
-	public var wasEdited = false;
-
-	override function save() {
-		var obj : Dynamic = super.save();
-
-		obj.shape = shape.getIndex();
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-
-		// Backward compatibility
-		pointsData = [];
-		if( obj.points != null ) {
-			var points : Array<Dynamic> = obj.points;
-			for( p in points ) {
-				var m = new h3d.Matrix();
-				m.loadValues(p);
-				pointsData.push(m);
-			}
-		}
-		shape = obj.shape == null ? Linear : CurveShape.createByIndex(obj.shape);
-	}
-
-	// Generate the splineData from a matrix, can't move the spline after that
-	public function makeFromMatrix( m : h3d.Matrix ) {
-		var tmp = new h3d.Matrix();
-		points = [];
-		for( pd in pointsData ) {
-			var sp = new SplinePoint(this);
-			tmp.load(pd);
-			tmp.multiply(tmp, m);
-			sp.setTransform(tmp);
-			sp.getAbsPos();
-		}
-		computeSplineData();
-	}
-
-
-	override function makeInstance( ctx : hrt.prefab.Context ) : hrt.prefab.Context {
-		var ctx = ctx.clone(this);
-		ctx.local3d = createObject(ctx);
-		ctx.local3d.name = name;
-
-		// Backward compatibility
-		for( pd in pointsData ) {
-			var sp = new SplinePoint(this);
-			sp.setTransform(pd);
-			sp.getAbsPos();
-		}
-
-		if( points.length == 0 )
-			new SplinePoint(this);
-
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function updateInstance( ctx : hrt.prefab.Context , ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		#if editor
-		if( editor != null )
-			editor.update(ctx, propName);
-		#end
-		computeSpline(ctx);
-	}
-
-	// Return an interpolation of two samples at t, 0 <= t <= 1
-	public function getPointAt( t : Float, ?pos: h3d.col.Point, ?tangent: h3d.col.Point ) : h3d.col.Point {
-		if( data == null )
-			computeSplineData();
-
-		// The last point is not at the same distance, be aware of that case
-		t = hxd.Math.clamp(t);
-		var l = t * (data.samples.length - 1);
-		var s1 : Int = hxd.Math.floor(l);
-		var s2 : Int = hxd.Math.ceil(l);
-		s1 = hxd.Math.iclamp(s1, 0, data.samples.length - 1);
-		s2 = hxd.Math.iclamp(s2, 0, data.samples.length - 1);
-
-		if(pos == null)
-			pos = new h3d.col.Point();
-
-		// End/Beginning of the curve, just return the point
-		if( s1 == s2 ) {
-			pos.load(data.samples[s1].pos);
-			if(tangent != null)
-				tangent.load(data.samples[s1].tangent);
-		}
-		// Linear interpolation between the two samples
-		else {
-			var segmentLength = data.samples[s1].pos.distance(data.samples[s2].pos);
-			if (segmentLength == 0) {
-				pos.load(data.samples[s1].pos);
-				if(tangent != null)
-					tangent.load(data.samples[s1].tangent);
-			}
-			else {
-				var t = (l - s1) / segmentLength;
-				pos.lerp(data.samples[s1].pos, data.samples[s2].pos, t);
-				if(tangent != null)
-					tangent.lerp(data.samples[s1].tangent, data.samples[s2].tangent, t);
-			}
-
-		}
-		return pos;
-	}
-
-	// Return the euclidean distance between the two points
-	inline function getMaxLengthBetween( p1 : SplinePoint, p2 : SplinePoint) : Float {
-		switch shape {
-			case Linear: return p1.getPoint().distance(p2.getPoint());
-			case Quadratic: return p1.getPoint().distance(p1.getSecondControlPoint()) + p1.getFirstControlPoint().distance(p2.getPoint());
-			case Cubic: return p1.getPoint().distance(p1.getSecondControlPoint()) + p1.getFirstControlPoint().distance(p2.getFirstControlPoint()) + p2.getFirstControlPoint().distance(p2.getPoint());
-		}
-	}
-
-	// Return the sum of the euclidean distances between each control points
-	inline function getMinLengthBetween( p1 : SplinePoint, p2 : SplinePoint) : Float {
-		return p1.getPoint().distance(p2.getPoint());
-	}
-
-	// Return the sum of the euclidean distances between each samples
-	public function getLength() {
-		if( data == null )
-			computeSplineData();
-		return data.length;
-	}
-
-	// Sample the spline with the step
-	function computeSplineData() {
-
-		var sd = new SplineData();
-		data = sd;
-
-		if( step <= 0 )
-			return;
-
-		if( points == null || points.length <= 1 )
-			return;
-
-		// Sample the spline
-		var samples : Array<SplinePointData> = [{ pos : points[0].getPoint(), tangent : points[0].getTangent(), prev : points[0], next : points[1] }];
-		var maxI = loop ? points.length : points.length - 1;
-		var curP = points[0];
-		var nextP = points[1];
-		for (i in 1...maxI + 1) {
-			var t = 0.;
-			while (t <= 1.) {
-				var p = getPointBetween(t, curP, nextP);
-				if (p.distance(samples[samples.length - 1].pos) >= 1./step)
-					samples.insert(samples.length, { pos : p, tangent : getTangentBetween(t, curP, nextP), prev : curP, next : nextP });
-				t += 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 });
-			curP = points[i];
-			nextP = points[(i + 1) % points.length];
-
-		}
-		sd.samples = samples;
-
-		// Compute the average length of the spline
-		var lengthSum = 0.0;
-		for( i in 0 ... samples.length - 1 ) {
-			lengthSum += samples[i].pos.distance(samples[i+1].pos);
-		}
-		var l = 0.0;
-		for( i in 0 ... samples.length - 1 ) {
-			samples[i].t = l/lengthSum;
-			l += samples[i].pos.distance(samples[i+1].pos);
-		}
-		samples[samples.length - 1].t = 1;
-		sd.length = lengthSum;
-	}
-
-	// Return the closest spline point on the spline from p
-	function getClosestSplinePoint( p : h3d.col.Point ) : SplinePoint {
-		var minDist = -1.0;
-		var curPt : SplinePoint = null;
-		for( sp in points ) {
-			var dist = p.distance(sp.getPoint());
-			if( dist < minDist || minDist == -1 ) {
-				minDist = dist;
-				curPt = sp;
-			}
-		}
-		return curPt;
-	}
-
-	// Return the closest point on the spline from p
-	function getClosestPoint( p : h3d.col.Point ) : SplinePointData {
-
-		if( data == null )
-			computeSplineData();
-
-		var minDist = -1.0;
-		var result : SplinePointData = null;
-		for( s in data.samples ) {
-			var dist = s.pos.distance(p);
-			if( dist < minDist || minDist == -1 ) {
-				minDist = dist;
-				result = s;
-			}
-		}
-		return result;
-	}
-
-	// Return the point on the curve between p1 and p2 at t, 0 <= t <= 1
-	inline function getPointBetween( t : Float, p1 : SplinePoint, p2 : SplinePoint ) : h3d.col.Point {
-		return switch (shape) {
-			case Linear: getLinearBezierPoint( t, p1.getPoint(), p2.getPoint() );
-			case Quadratic: getQuadraticBezierPoint( t, p1.getPoint(), p1.getSecondControlPoint(), p2.getPoint() );
-			case Cubic: getCubicBezierPoint( t, p1.getPoint(), p1.getSecondControlPoint(), p2.getFirstControlPoint(), p2.getPoint() );
-		}
-	}
-
-	// Return the tangent on the curve between p1 and p2 at t, 0 <= t <= 1
-	inline function getTangentBetween( t : Float, p1 : SplinePoint, p2 : SplinePoint ) : h3d.col.Point {
-		return switch (shape) {
-			case Linear: getLinearBezierTangent( t, p1.getPoint(), p2.getPoint() );
-			case Quadratic: getQuadraticBezierTangent( t, p1.getPoint(), p1.getSecondControlPoint(), p2.getPoint() );
-			case Cubic: getCubicBezierTangent( t, p1.getPoint(), p1.getSecondControlPoint(), p2.getFirstControlPoint(), p2.getPoint() );
-		}
-	}
-
-	// Linear Interpolation
-	// p(t) = p0 + (p1 - p0) * t
-	inline function getLinearBezierPoint( t : Float, p0 : h3d.col.Point, p1 : h3d.col.Point ) : h3d.col.Point {
-		return p0.add((p1.sub(p0).multiply(t)));
-	}
-	// p'(t) = (p1 - p0)
-	inline function getLinearBezierTangent( t : Float, p0 : h3d.col.Point, p1 : h3d.col.Point ) : h3d.col.Point {
-		return p1.sub(p0).normalized();
-	}
-
-	// Quadratic Interpolation
-	// p(t) = p0 * (1 - t)² + p1 * t * 2 * (1 - t) + p2 * t²
-	inline function getQuadraticBezierPoint( t : Float, p0 : h3d.col.Point, p1 : h3d.col.Point, p2 : h3d.col.Point) : h3d.col.Point {
-		return p0.multiply((1 - t) * (1 - t)).add(p1.multiply(t * 2 * (1 - t))).add(p2.multiply(t * t));
-	}
-	// p'(t) = 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1)
-	inline function getQuadraticBezierTangent( t : Float, p0 : h3d.col.Point, p1 : h3d.col.Point, p2 : h3d.col.Point) : h3d.col.Point {
-		return p1.sub(p0).multiply(2 * (1 - t)).add(p2.sub(p1).multiply(2 * t)).normalized();
-	}
-
-	// Cubic Interpolation
-	// p(t) = p0 * (1 - t)³ + p1 * t * 3 * (1 - t)² + p2 * t² * 3 * (1 - t) + p3 * t³
-	inline function getCubicBezierPoint( t : Float, p0 : h3d.col.Point, p1 : h3d.col.Point, p2 : h3d.col.Point, p3 : h3d.col.Point) : h3d.col.Point {
-		return p0.multiply((1 - t) * (1 - t) * (1 - t)).add(p1.multiply(t * 3 * (1 - t) * (1 - t))).add(p2.multiply(t * t * 3 * (1 - t))).add(p3.multiply(t * t * t));
-	}
-	// p'(t) = 3 * (1 - t)² * (p1 - p0) + 6 * (1 - t) * t * (p2 - p1) + 3 * t² * (p3 - p2)
-	inline function getCubicBezierTangent( t : Float, p0 : h3d.col.Point, p1 : h3d.col.Point, p2 : h3d.col.Point, p3 : h3d.col.Point) : h3d.col.Point {
-		return p1.sub(p0).multiply(3 * (1 - t) * (1 - t)).add(p2.sub(p1).multiply(6 * (1 - t) * t)).add(p3.sub(p2).multiply(3 * t * t)).normalized();
-	}
-
-	function generateSplineGraph( ctx : hrt.prefab.Context ) {
-
-		if( !showSpline ) {
-			if( lineGraphics != null ) {
-				lineGraphics.remove();
-				lineGraphics = null;
-			}
-			return;
-		}
-
-		if( lineGraphics == null ) {
-			lineGraphics = new h3d.scene.Graphics(ctx.local3d);
-			lineGraphics.lineStyle(lineThickness, color);
-			lineGraphics.material.mainPass.setPassName("overlay");
-			lineGraphics.material.mainPass.depth(false, LessEqual);
-			lineGraphics.ignoreParentTransform = false;
-		}
-
-		lineGraphics.lineStyle(lineThickness, color);
-		lineGraphics.clear();
-		var b = true;
-		for( s in data.samples ) {
-			var localPos = ctx.local3d.globalToLocal(s.pos.clone());
-			b ? lineGraphics.moveTo(localPos.x, localPos.y, localPos.z) : lineGraphics.lineTo(localPos.x, localPos.y, localPos.z);
-			b = false;
-		}
-	}
-
-	public function computeSpline(ctx : hrt.prefab.Context) {
-		computeSplineData();
-		#if editor
-			generateSplineGraph(ctx);
-		#end
-	}
-
-	#if editor
-
-	public function onEdit( b : Bool ) {
-		if( b ) wasEdited = true;
-	}
-
-	override function setSelected( ctx : hrt.prefab.Context , b : Bool ) {
-		super.setSelected(ctx, b);
-
-		if( editor != null )
-			editor.setSelected(ctx, b);
-
-		return true;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		ctx.properties.add( new hide.Element('
-			<div class="group" name="Spline">
-				<dl>
-					<dt>Color</dt><dd><input type="color" alpha="true" field="color"/></dd>
-					<dt>Thickness</dt><dd><input type="range" min="1" max="10" field="lineThickness"/></dd>
-					<dt>Step</dt><dd><input type="range" min="1" max="10" step="1" field="step"/></dd>
-					<dt>Loop</dt><dd><input type="checkbox" field="loop"/></dd>
-					<dt>Show Spline</dt><dd><input type="checkbox" field="showSpline"/></dd>
-					<dt>Type</dt>
-						<dd>
-							<select field="shape" >
-								<option value="Linear">Linear</option>
-								<option value="Cubic">Curve</option>
-							</select>
-						</dd>
-				</dl>
-			</div>'), this, function(pname) { ctx.onChange(this, pname); });
-
-		if( editor == null ) {
-			editor = new hide.prefab.SplineEditor(this, ctx.properties.undo);
-		}
-
-		editor.editContext = ctx;
-		editor.edit(ctx);
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "arrows-v", name : "Spline", allowChildren: function(s) return Library.isOfType(s, SplinePoint) };
-	}
-	#end
-
-	static var _ = hrt.prefab.Library.register("spline", Spline);
-}

+ 0 - 322
hrt/prefab/l3d/SplineMesh.hx

@@ -1,322 +0,0 @@
-package hrt.prefab.l3d;
-
-import h3d.scene.MeshBatch;
-import h3d.scene.Mesh;
-import hrt.prefab.l3d.Spline.SplinePoint;
-
-class SplineMeshShader extends hxsl.Shader {
-
-	static var SRC = {
-		@:import h3d.shader.BaseMesh;
-
-		// Spline Infos
-		@const(4096) var POINT_COUNT : Int;
-		@const var SPLINE_UV_X : Bool;
-		@const var SPLINE_UV_Y : Bool;
-		@param var stepSize : Float;
-		@param var points : Buffer<Vec4, POINT_COUNT>;
-
-		// Instance Infos
-		@param var modelMat : Mat4;
-		@param var splinePos : Float;
-
-		var calculatedUV : Vec2;
-
-		function vertex() {
-
-			var modelPos = relativePosition * modelMat.mat3x4();
-			var pos = splinePos + modelPos.y;
-			pos = clamp(pos, 0.0, POINT_COUNT * stepSize);
-			var offsetY = pos - splinePos;
-
-			// Linear Interpolation between two samples
-			var s1 = clamp(floor(pos / stepSize), 0.0, POINT_COUNT - 1.0).int();
-			var s2 = clamp(ceil(pos / stepSize), 0.0, POINT_COUNT - 1.0).int();
-			var t = saturate((pos - (s1 * stepSize)) / stepSize);
-			var point = mix(points[s1 * 2], points[s2 * 2], t).xyz;
-			var tangent = mix(points[s1 * 2 + 1], points[s2 * 2 + 1], t).xyz;
-
-			// Construct the new transform
-			var worldUp = vec3(0,0,1);
-			var front = -tangent;
-			var right = -front.cross(worldUp).normalize();
-			var up = front.cross(right).normalize();
-
-			var rotation = mat4(	vec4(right.x, front.x, up.x, 0),
-									vec4(right.y, front.y, up.y, 0),
-									vec4(right.z, front.z, up.z, 0),
-									vec4(0,0,0,1));
-
-			var translation = mat4(	vec4(1,0,0, point.x ),
-									vec4(0,1,0, point.y ),
-									vec4(0,0,1, point.z ),
-									vec4(0,0,0,1));
-
-			var transform = rotation * translation;
-			var localPos = (modelPos - vec3(0, offsetY, 0));
-			transformedPosition = localPos * transform.mat3x4();
-			transformedNormal = transformedNormal * modelMat.mat3x4() * rotation.mat3x4();
-
-			if( SPLINE_UV_X )
-				calculatedUV.x = pos;
-			if( SPLINE_UV_Y )
-				calculatedUV.y = pos;
-		}
-	}
-}
-
-enum SplineMeshMode {
-	MultiMesh;
-	Instanced;
-	BigGeometry;
-}
-
-// Need to dipose the GPU buffer manually
-class SplineMeshBatch extends h3d.scene.MeshBatch {
-
-	public var splineData : Spline.SplineData;
-
-	override function onRemove() {
-		super.onRemove();
-		var splinemeshShader = material.mainPass.getShader(SplineMeshShader);
-		if( splinemeshShader != null ) {
-			splinemeshShader.points.dispose();
-		}
-	}
-
-	override function sync(ctx) {
-		super.sync(ctx);
-		var s = material.mainPass.getShader(SplineMeshShader);
-		if( s != null && s.points == null || s.points.isDisposed() ) {
-			var bufferData = new hxd.FloatBuffer(s.POINT_COUNT * 4 * 2);
-			for( i in 0 ... splineData.samples.length ) {
-				var index = i * 2 * 4;
-				var s = splineData.samples[i];
-				bufferData[index] = s.pos.x; bufferData[index + 1] = s.pos.y; bufferData[index + 2] = s.pos.z; bufferData[index + 3] = 0.0;
-				bufferData[index + 4] = s.tangent.x; bufferData[index + 5] = s.tangent.y; bufferData[index + 6] = s.tangent.z; bufferData[index + 7] = 0.0;
-			}
-			s.points = new h3d.Buffer(s.POINT_COUNT * 2, 4, [UniformBuffer,Dynamic]);
-			s.points.uploadVector(bufferData, 0, s.points.vertices, 0);
-		}
-	}
-
-}
-
-class SplineMesh extends Spline {
-
-	@:s var meshPath : String;
-	var meshes : Array<h3d.scene.Mesh> = [];
-
-	@:s var splineUVx : Bool = false;
-	@:s var splineUVy : Bool = false;
-
-	@:s var spacing: Float = 0.0;
-	@:c var meshScale = new h3d.Vector(1,1,1);
-	@:c var meshRotation = new h3d.Vector(0,0,0);
-	var modelMat = new h3d.Matrix();
-
-	var meshBatch : SplineMeshBatch = null;
-	var meshPrimitive : h3d.prim.MeshPrimitive = null;
-	var meshMaterial : h3d.mat.Material = null;
-	@:s var customPass : String;
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		obj.meshScale = meshScale;
-		obj.meshRotation = meshRotation;
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		meshScale = obj.meshScale == null ? new h3d.Vector(1,1,1) : new h3d.Vector(obj.meshScale.x, obj.meshScale.y, obj.meshScale.z);
-		meshRotation = obj.meshRotation == null ? new h3d.Vector(0,0,0) : new h3d.Vector(obj.meshRotation.x, obj.meshRotation.y, obj.meshRotation.z);
-	}
-
-	override function make(ctx: Context) {
-		// Don't make children, which are used to setup the material
-		return makeInstance(ctx);
-	}
-
-	override function updateInstance( ctx : hrt.prefab.Context , ?propName : String ) {
-		super.updateInstance(ctx, propName);
-
-		var rot = new h3d.Matrix();
-		rot.initRotation(hxd.Math.degToRad(meshRotation.x), hxd.Math.degToRad(meshRotation.y), hxd.Math.degToRad(meshRotation.z));
-		var scale = new h3d.Matrix();
-		scale.initScale(meshScale.x, meshScale.y, meshScale.z);
-		modelMat.multiply(scale, rot);
-
-		createMeshPrimitive(ctx);
-		createMeshBatch(ctx);
-		createBatches(ctx);
-
-		// Remake the material
-		if( meshBatch != null ) {
-			var emptyCtx = new hrt.prefab.Context();
-			emptyCtx.local3d = meshBatch;
-			emptyCtx.shared = ctx.shared;
-			for( c in @:privateAccess children ) {
-				var mat = Std.downcast(c, Material);
-				if( mat != null && mat.enabled )
-					@:privateAccess mat.makeInstance(emptyCtx);
-				var shader = Std.downcast(c, Shader);
-				if( shader != null && shader.enabled )
-					shader.makeInstance(emptyCtx);
-			}
-		}
-	}
-
-	function createMeshPrimitive( ctx : Context ) {
-		meshPrimitive = null;
-		meshMaterial = null;
-		if( meshPath != null ) {
-			var meshTemplate : h3d.scene.Mesh = ctx.loadModel(meshPath).toMesh();
-			if( meshTemplate != null ) {
-				meshPrimitive = cast meshTemplate.primitive;
-				meshMaterial = cast meshTemplate.material.clone();
-			}
-		}
-	}
-
-	function createMeshBatch( ctx : Context ) {
-
-		if( meshBatch != null ) {
-			meshBatch.remove();
-			meshBatch = null;
-		}
-
-		if( meshPrimitive == null || (meshBatch != null && meshBatch.primitive == meshPrimitive) )
-			return;
-
-		if( meshBatch == null ) {
-			var splineMaterial : h3d.mat.Material = meshMaterial;
-			var splineMeshShader = createShader();
-			splineMaterial.mainPass.addShader(splineMeshShader);
-			splineMaterial.castShadows = false;
-
-			if( customPass != null ) {
-				for( p in customPass.split(",") ) {
-					if( ctx.local3d.getScene().renderer.getPassByName(p) != null )
-						splineMaterial.allocPass(p);
-				}
-			}
-
-			meshBatch = new SplineMeshBatch(meshPrimitive, splineMaterial, ctx.local3d);
-			meshBatch.ignoreParentTransform = true;
-			meshBatch.splineData = this.data;
-		}
-	}
-
-	function createBatches( ctx : Context ) {
-
-		if( meshBatch == null )
-			return;
-
-		var localBounds = meshPrimitive.getBounds().clone();
-		localBounds.transform(modelMat);
-		var minOffset = hxd.Math.abs(localBounds.yMin);
-		var step = (hxd.Math.abs(localBounds.yMax) + hxd.Math.abs(localBounds.yMin)) + spacing;
-		var stepCount = hxd.Math.ceil((getLength() - minOffset) / step);
-
-		if( stepCount > 4096 )
-			return;
-
-		meshBatch.begin(stepCount);
-		var splinemeshShader = meshBatch.material.mainPass.getShader(SplineMeshShader);
-		for( i in 0 ... stepCount ) {
-			if( splinemeshShader != null )
-				splinemeshShader.splinePos = i * step + minOffset;
-			meshBatch.emitInstance();
-		}
-	}
-
-	function createMultiMeshes( ctx : Context ) {
-
-		for( m in meshes )
-			m.remove();
-
-		meshes = [];
-
-		if( meshPrimitive == null )
-			return;
-
-		var localBounds = meshPrimitive.getBounds().clone();
-		localBounds.transform(modelMat);
-		var minOffset = hxd.Math.abs(localBounds.yMin);
-		var step = (hxd.Math.abs(localBounds.yMax) + hxd.Math.abs(localBounds.yMin)) + spacing;
-
-		var length = getLength();
-		var stepCount = hxd.Math.ceil((length - minOffset) / step);
-		for( i in 0 ... stepCount ) {
-			var m = new h3d.scene.Mesh(meshPrimitive, cast meshMaterial.clone());
-			m.material.castShadows = false;
-			m.ignoreParentTransform = true;
-			m.material.mainPass.culling = None;
-			var s = createShader();
-			m.material.mainPass.addShader(s);
-			s.splinePos = i * step + minOffset;
-			ctx.local3d.addChild(m);
-			meshes.push(m);
-		}
-	}
-
-	function createShader() {
-		var s = new SplineMeshShader();
-		s.POINT_COUNT = data.samples.length;
-		s.stepSize = step;
-		s.modelMat = modelMat;
-		var bufferData = new hxd.FloatBuffer(s.POINT_COUNT * 4 * 2);
-		for( i in 0 ... data.samples.length ) {
-			var index = i * 2 * 4;
-			var s = data.samples[i];
-			bufferData[index] = s.pos.x; bufferData[index + 1] = s.pos.y; bufferData[index + 2] = s.pos.z; bufferData[index + 3] = 0.0;
-			bufferData[index + 4] = s.tangent.x; bufferData[index + 5] = s.tangent.y; bufferData[index + 6] = s.tangent.z; bufferData[index + 7] = 0.0;
-		}
-		s.points = new h3d.Buffer(s.POINT_COUNT * 2, 4, [UniformBuffer,Dynamic]);
-		s.points.uploadVector(bufferData, 0, s.points.vertices, 0);
-		s.SPLINE_UV_X = splineUVx;
-		s.SPLINE_UV_Y = splineUVy;
-		return s;
-	}
-
-	#if editor
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var props = new hide.Element('
-			<div class="group" name="Material">
-				<dl>
-					<dt>Use spline UV on X</dt><dd><input type="checkbox" field="splineUVx"/></dd>
-					<dt>Use spline UV on Y</dt><dd><input type="checkbox" field="splineUVy"/></dd>
-					<dt>Custom Pass</dt><dd><input type="text" field="customPass"/></dd>
-					<div align="center"><input type="button" value="Refresh" class="refresh"/></div>
-				</dl>
-			</div>
-			<div class="group" name="Mesh">
-				<dl>
-					<dt>Mesh</dt><dd><input type="model" field="meshPath"/></dd>
-					<dt>Spacing</dt><dd><input type="range" min="0" max="10" field="spacing"/></dd>
-					<dt>Scale X</dt><dd><input type="range" min="0" max="5" value="1" field="meshScale.x"/></dd>
-					<dt>Scale Y</dt><dd><input type="range" min="0" max="5" value="1" field="meshScale.y"/></dd>
-					<dt>Scale Z</dt><dd><input type="range" min="0" max="5" value="1" field="meshScale.z"/></dd>
-					<dt>Rotation X</dt><dd><input type="range" min="-180" max="180" value="0" field="meshRotation.x" /></dd>
-					<dt>Rotation Y</dt><dd><input type="range" min="-180" max="180" value="0" field="meshRotation.y" /></dd>
-					<dt>Rotation Z</dt><dd><input type="range" min="-180" max="180" value="0" field="meshRotation.z" /></dd>
-				</dl>
-			</div>
-			');
-
-		props.find(".refresh").click(function(_) { ctx.onChange(this, null); });
-		ctx.properties.add(props, this, function(pname) { ctx.onChange(this, pname); });
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "arrows-v", name : "SplineMesh" };
-	}
-
-	#end
-
-	static var _ = hrt.prefab.Library.register("splineMesh", SplineMesh);
-}

+ 0 - 265
hrt/prefab/l3d/Text3D.hx

@@ -1,265 +0,0 @@
-package hrt.prefab.l3d;
-
-import h2d.col.Point;
-
-class Text3DPrimitive extends h2d.TileGroup.TileLayerContent {
-
-	override public function add( x : Float, y : Float, r : Float, g : Float, b : Float, a : Float, t : h2d.Tile ) {
-		@:privateAccess {
-			var sx = x + t.dx;
-			var sy = y + t.dy;
-			tmp.push(sx);
-			tmp.push(sy);
-			tmp.push(1);
-			tmp.push(0);
-			tmp.push(0);
-			tmp.push(1);
-			tmp.push(t.u);
-			tmp.push(t.v);
-			tmp.push(sx + t.width);
-			tmp.push(sy);
-			tmp.push(1);
-			tmp.push(0);
-			tmp.push(0);
-			tmp.push(1);
-			tmp.push(t.u2);
-			tmp.push(t.v);
-			tmp.push(sx);
-			tmp.push(sy + t.height);
-			tmp.push(1);
-			tmp.push(0);
-			tmp.push(0);
-			tmp.push(1);
-			tmp.push(t.u);
-			tmp.push(t.v2);
-			tmp.push(sx + t.width);
-			tmp.push(sy + t.height);
-			tmp.push(1);
-			tmp.push(0);
-			tmp.push(0);
-			tmp.push(1);
-			tmp.push(t.u2);
-			tmp.push(t.v2);
-
-			var x = x + t.dx, y = y + t.dy;
-			if( x < xMin ) xMin = x;
-			if( y < yMin ) yMin = y;
-			x += t.width;
-			y += t.height;
-			if( x > xMax ) xMax = x;
-			if( y > yMax ) yMax = y;
-		}
-	}
-
-	override public function render( engine : h3d.Engine ) {
-		if( tmp == null || tmp.length == 0) return;
-		super.render(engine);
-	}
-
-	override function getBounds() {
-		return h3d.col.Bounds.fromValues(xMin, yMin, 0, xMax, yMax, 0.1);
-	}
-
-	override public function getCollider() : h3d.col.Collider {
-		return getBounds();
-	}
-
-}
-
-class SignedDistanceField3D extends hxsl.Shader {
-
-	static var SRC = {
-
-		@param var alphaCutoff : Float = 0.5;
-		@param var smoothing : Float = 0.04166666666666666666666666666667; // 1/24
-		var pixelColor : Vec4;
-		@param var color : Vec4;
-
-		function median(r : Float, g : Float, b : Float) : Float {
-			return max(min(r, g), min(max(r, g), b));
-		}
-
-		function fragment() {
-			pixelColor = vec4(color.r, color.g, color.b, smoothstep(alphaCutoff - smoothing, alphaCutoff + smoothing, median(pixelColor.r, pixelColor.g, pixelColor.b)));
-		}
-	}
-
-}
-
-class Text3D extends Object3D {
-
-	@:s var color : Int = 0xFFFFFF;
-	@:s var size : Int = 12;
-	@:s var cutoff : Float = 0.5;
-	@:s var smoothing : Float = 1 / 32;
-	@:s var letterSpacing : Float = 0;
-	@:s var align : Int = 0;
-	@:s var pathFont : String;
-
-	@:s public var contentText : String = "Empty string";
-
-	public function new( ?parent ) {
-		super(parent);
-		type = "text3d";
-	}
-
-	#if editor
-
-	override function getHideProps() : HideProps {
-		return { icon : "font", name : "Text3D" };
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
-
-		var gr = new hide.Element('<dl></dl>').appendTo(parameters);
-
-		new hide.Element('<dt>Font</dt>').appendTo(gr);
-		var element = new hide.Element('<dd></dd>').appendTo(gr);
-		var fileInput = new hide.Element('<input type="text" field="pathFont" style="width:165px" />').appendTo(element);
-
-		var tfile = new hide.comp.FileSelect(["fnt"], null, fileInput);
-		if (this.pathFont != null && this.pathFont.length > 0) tfile.path = this.pathFont;
-		tfile.onChange = function() {
-			this.pathFont = tfile.path;
-			updateInstance(ctx.getContext(this), "pathFont");
-		}
-        new hide.Element('<dt>Align</dt>').appendTo(gr);
-		var element = new hide.Element('<dd></dd>').appendTo(gr);
-		var leftAlign = new hide.Element('<input type="button" style="width: 50px" value="Left" /> ').appendTo(element);
-		var middleAlign = new hide.Element('<input type="button" style="width: 50px" value="Center" /> ').appendTo(element);
-		var rightAlign = new hide.Element('<input type="button" style="width: 50px" value="Right" /> ').appendTo(element);
-		leftAlign.on("click", function(e) {
-			align = 0;
-			leftAlign.attr("disabled", "true");
-			middleAlign.removeAttr("disabled");
-			rightAlign.removeAttr("disabled");
-			updateInstance(ctx.getContext(this), "align");
-		});
-		middleAlign.on("click", function(e) {
-			align = 1;
-			leftAlign.removeAttr("disabled");
-			middleAlign.attr("disabled", "true");
-			rightAlign.removeAttr("disabled");
-			updateInstance(ctx.getContext(this), "align");
-		});
-		rightAlign.on("click", function(e) {
-			align = 2;
-			leftAlign.removeAttr("disabled");
-			middleAlign.removeAttr("disabled");
-			rightAlign.attr("disabled", "true");
-			updateInstance(ctx.getContext(this), "align");
-		});
-
-		new hide.Element('<dt>Color</dt><dd><input type="color" field="color" /></dd>').appendTo(gr);
-		new hide.Element('<dt>Size</dt><dd><input type="range" min="1" max="50" step="1" field="size" /></dd>').appendTo(gr);
-		new hide.Element('<dt>Cutoff</dt><dd><input type="range" min="0" max="1" field="cutoff" /></dd>').appendTo(gr);
-		new hide.Element('<dt>Smoothing</dt><dd><input type="range" min="0" max="1" field="smoothing" /></dd>').appendTo(gr);
-		new hide.Element('<dt>Letter Spacing</dt><dd><input type="range" min="-5" max="5" field="letterSpacing" /></dd>').appendTo(gr);
-
-		ctx.properties.add(parameters, this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-
-		ctx.properties.add(new hide.Element('<div class="group" name="Responsive">
-			<dl>
-				<dt>Text</dt><dd><input type="text" field="contentText" /></dd>
-			</dl></div>'), this, function(pname) {
-			ctx.onChange(this, pname);
-		});
-	}
-
-	#end
-
-	override function updateInstance( ctx : Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
-		if (pathFont == null || pathFont.length == 0) {
-			return;
-		}
-		var text = loadText();
-		if (text == null || text.length == 0)
-			return;
-		var mesh : h3d.scene.Mesh = cast ctx.local3d;
-		var h2dFont = loadFont();
-		var h2dText = (cast ctx.local2d : h2d.Text);
-		h2dText.font = h2dFont;
-		h2dText.letterSpacing = letterSpacing;
-		h2dText.text = text;
-		h2dText.smooth = true;
-        h2dText.textAlign = switch (align) {
-			case 1:
-				Center;
-			case 2:
-				Right;
-			default:
-				Left;
-		}
-		@:privateAccess h2dText.glyphs.content = (cast mesh.primitive : Text3DPrimitive);
-		@:privateAccess {
-			h2dText.initGlyphs(text);
-			h2dText.glyphs.setDefaultColor(color, 1);
-			mesh.primitive = h2dText.glyphs.content;
-			mesh.material.texture = h2dFont.tile.getTexture();
-			mesh.material.shadows = false;
-			mesh.material.mainPass.setPassName("overlay");
-			mesh.material.mainPass.depth(false, LessEqual);
-
-			var shader = mesh.material.mainPass.getShader(SignedDistanceField3D);
-			if (shader != null) {
-				mesh.material.mainPass.removeShader(shader);
-			}
-			shader = new SignedDistanceField3D();
-			shader.alphaCutoff = cutoff;
-			shader.smoothing = smoothing;
-			shader.color = h3d.Vector.fromColor(color);
-			mesh.material.mainPass.addShader(shader);
-		}
-	}
-
-	public dynamic function loadFont() : h2d.Font {
-		var f = defaultLoadFont(pathFont, size, cutoff, smoothing);
-		if (f == null) {
-			if (pathFont != null && pathFont.length > 0) {
-				var font = hxd.res.Loader.currentInstance.load(pathFont).to(hxd.res.BitmapFont);
-				return font.toSdfFont(size, MultiChannel, cutoff, smoothing);
-			} else {
-				return null;
-			}
-		}
-		else return f;
-	}
-
-	public static dynamic function defaultLoadFont( pathFont : String, size : Int, cutoff : Float, smoothing : Float ) : h2d.Font {
-		return null;
-	}
-
-	public dynamic function loadText() : String {
-		var str = defaultLoadText(contentText);
-		if (str == null) {
-			return contentText;
-		}
-		else return str;
-	}
-
-	public static dynamic function defaultLoadText(id: String) : String {
-		return null;
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var mesh = new h3d.scene.Mesh(new Text3DPrimitive(), ctx.local3d);
-		mesh.material.blendMode = Alpha;
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		var h2dText = new h2d.Text(hxd.res.DefaultFont.get(), ctx.local2d);
-		@:privateAccess h2dText.glyphs.content = new Text3DPrimitive();
-		ctx.local2d = h2dText;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	static var _ = Library.register("text3d", Text3D);
-}

+ 0 - 63
hrt/prefab/l3d/Trail.hx

@@ -1,63 +0,0 @@
-package hrt.prefab.l3d;
-
-class Trail extends Object3D {
-
-	@:s var data : Dynamic;
-
-	function new(?parent) {
-		super(parent);
-		data = new h3d.scene.Trail().save();
-	}
-
-	public function create( ?parent : h3d.scene.Object ) {
-		var tr = new h3d.scene.Trail(parent);
-		tr.load(data);
-		applyTransform(tr);
-		tr.name = name;
-		return tr;
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var tr = create(ctx.local3d);
-		ctx.local3d = tr;
-		return ctx;
-	}
-
-	#if editor
-
-	override function getHideProps():HideProps {
-		return { icon : "toggle-on", name : "Trail" };
-	}
-
-	override public function edit(ctx:EditContext) {
-		super.edit(ctx);
-
-		var trailContext = ctx.getContext(this);
-		var trail = trailContext == null ? create(null) : Std.downcast(trailContext.local3d, h3d.scene.Trail);
-		var props = ctx.properties.add(new hide.Element('
-		<div class="group" name="Material">
-		</div>
-		<div class="group" name="Trail Properties">
-			<dl>
-				<dt>Angle</dt><dd><input type="range" field="angle" scale="${180/Math.PI}" min="0" max="${Math.PI*2}"/></dd>
-				<dt>Duration</dt><dd><input type="range" field="duration" min="0" max="1"/></dd>
-				<dt>Size Start</dt><dd><input type="range" field="sizeStart" min="0" max="10"/></dd>
-				<dt>Size End</dt><dd><input type="range" field="sizeEnd" min="0" max="10"/></dd>
-				<dt>Movement Min.</dt><dd><input type="range" field="movementMin" min="0" max="1"/></dd>
-				<dt>Movement Max.</dt><dd><input type="range" field="movementMax" min="0" max="1"/></dd>
-				<dt>Smoothness</dt><dd><input type="range" field="smoothness" min="0" max="1"/></dd>
-				<dt>Texture</dt><dd><input type="texture" field="texture"/></dd>
-			</dl>
-		</div>
-		'),trail, function(_) {
-			data = trail.save();
-		});
-		ctx.properties.addMaterial( trail.material, props.find("[name=Material] > .content"), function(_) data = trail.save());
-	}
-
-	#end
-
-	static var _ = Library.register("trail", Trail);
-
-}

+ 0 - 172
hrt/prefab/pbr/Anisotropy.hx

@@ -1,172 +0,0 @@
-package hrt.prefab.pbr;
-
-import h3d.pass.Default;
-import hrt.shader.AnisotropicForward;
-
-enum abstract AnisotropyMode(String) {
-	var Flat;
-	var Texture;
-	var Frequency;
-}
-
-class Anisotropy extends Prefab {
-
-	@:s public var mode : AnisotropyMode = Flat;
-
-	@:s public var intensity : Float = 0.0;
-	@:s public var direction : Float = 0.0;
-
-	@:s public var noiseFrequency : Float = 0.0;
-	@:s public var noiseIntensity : Float = 1.0;
-
-	@:s public var intensityFactor = 1.0;
-	@:s public var noiseIntensityPath : String = null;
-	@:s public var noiseDirectionPath : String = null;
-	@:s public var rotationOffset : Float = 0.0;
-
-	public function new(?parent) {
-		super(parent);
-		type = "anisotropy";
-	}
-
-	function getMaterials( ctx : Context ) {
-		if( Std.is(parent, Material) ) {
-			var material : Material = cast parent;
-			return material.getMaterials(ctx);
-		}
-		else {
-			return ctx.local3d.getMaterials();
-		}
-	}
-
-	override function makeInstance( ctx : Context ):Context {
-		ctx = ctx.clone(this);
-		refreshShaders(ctx);
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	function refreshShaders( ctx : Context ) {
-		var fv = new FlatValue();
-		var as = new AnisotropicForward();
-		var nt = new NoiseTexture();
-		var ff = new FrequencyValue();
-
-		var noiseIntensityTexture = noiseIntensityPath != null ? ctx.loadTexture(noiseIntensityPath) : null;
-		var noiseDirectionTexture = noiseDirectionPath != null ? ctx.loadTexture(noiseDirectionPath) : null;
-
-		var mat = getMaterials(ctx);
-
-		for( m in mat ) {
-			m.mainPass.removeShader(m.mainPass.getShader(NoiseTexture));
-			m.mainPass.removeShader(m.mainPass.getShader(FlatValue));
-			m.mainPass.removeShader(m.mainPass.getShader(FrequencyValue));
-			m.mainPass.removeShader(m.mainPass.getShader(AnisotropicForward));
-		}
-
-		for( m in mat ) {
-
-			if( m.mainPass.name != "forward" )
-				continue;
-
-			if( mode == Texture && noiseIntensityTexture != null && noiseDirectionTexture != null ) {
-				m.mainPass.addShader(nt);
-			}
-			else {
-				switch mode {
-					case Texture,Flat: m.mainPass.addShader(fv);
-					case Frequency:	m.mainPass.addShader(ff);
-					default:
-				}
-			}
-
-			m.mainPass.addShader(as);
-		}
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		for( m in getMaterials(ctx) ) {
-
-			var fv = m.mainPass.getShader(FlatValue);
-			if( fv != null ) {
-				fv.intensity = intensity;
-				var angle = hxd.Math.degToRad(direction);
-				fv.dirVector.set(hxd.Math.cos(angle), hxd.Math.sin(angle), 0);
-			}
-
-			var ff = m.mainPass.getShader(FrequencyValue);
-			if( ff != null ) {
-				ff.intensity = intensity;
-				ff.noiseFrequency = noiseFrequency;
-				ff.noiseIntensity = noiseIntensity;
-				var angle = hxd.Math.degToRad(direction);
-				ff.dirVector.set(hxd.Math.cos(angle), hxd.Math.sin(angle), 0);
-			}
-
-			var nt = m.mainPass.getShader(NoiseTexture);
-			if( nt != null ) {
-				nt.noiseIntensityTexture = noiseIntensityPath != null ? ctx.loadTexture(noiseIntensityPath) : null;
-				nt.noiseDirectionTexture = noiseDirectionPath != null ? ctx.loadTexture(noiseDirectionPath) : null;
-				nt.intensityFactor = intensityFactor;
-				nt.rotationOffset = hxd.Math.degToRad(rotationOffset);
-			}
-		}
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { 	icon : "cube",
-					name : "Anisotropy",
-					allowParent : function(p) return p.to(Material) != null  };
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var flatParams = 	'<dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
-							<dt>Direction</dt><dd><input type="range" min="0" max="360" field="direction"/></dd>';
-
-		var textureParams = '<dt>Factor</dt><dd><input type="range" min="0" max="1" field="intensityFactor"/></dd>
-							<dt>Rotation Offset</dt><dd><input type="range" min="0" max="360" field="rotationOffset"/></dd>
-							<dt>Intensity</dt><dd><input type="texturepath" field="noiseIntensityPath"/>
-							<dt>Direction</dt><dd><input type="texturepath" field="noiseDirectionPath"/>';
-
-		var frequencyParams =	'<dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
-								<dt>Noise Intensity</dt><dd><input type="range" min="0" max="1" field="noiseIntensity"/></dd>
-								<dt>Noise Frequency</dt><dd><input type="range" min="0" max="100" field="noiseFrequency"/></dd>
-								<dt>Direction</dt><dd><input type="range" min="0" max="360" field="direction"/></dd>';
-
-		var params = switch mode {
-			case Flat: flatParams;
-			case Texture: textureParams;
-			case Frequency: frequencyParams;
-		};
-
-		var props = new hide.Element('
-			<div class="group" name="Anisotropy">
-				<dl>
-					<dt>Mode</dt>
-						<dd>
-							<select field="mode">
-								<option value="Flat">Flat</option>
-								<option value="Texture">Texture</option>
-								<option value="Frequency">Frequency</option>
-							</select>
-						</dd>
-					' + params + '
-				</dl>
-			</div>
-		');
-
-		ctx.properties.add(props, this, function(pname) {
-			if( pname == "mode" || pname == "noiseIntensityPath" || pname == "noiseDirectionPath" ) {
-				ctx.rebuildProperties();
-				refreshShaders(ctx.getContext(this));
-			}
-			ctx.onChange(this, pname);
-		});
-	}
-	#end
-
-	static var _ = Library.register("anisotropy", Anisotropy);
-}

+ 0 - 154
hrt/prefab/pbr/SpecularColor.hx

@@ -1,154 +0,0 @@
-package hrt.prefab.pbr;
-
-import hrt.shader.SpecularColor;
-import hrt.shader.SpecularColor.SpecularColorAlbedo;
-import hrt.shader.SpecularColor.SpecularColorFlat;
-import hrt.shader.SpecularColor.SpecularColorTexture;
-
-enum abstract SpecularColorMode(String) {
-	var Albedo;
-	var Flat;
-	var Texture;
-}
-
-class SpecularColor extends Prefab {
-
-	// Amount of dielectric specular reflection. Specifies facing (along normal) reflectivity in the most common 0 - 8% range.
-	@:s public var specular : Float = 0.5;
-
-	// Tints the facing specular reflection using the base color, while glancing reflection remains white.
-	// Normal dielectrics have colorless reflection, so this parameter is not technically physically correct
-	// and is provided for faking the appearance of materials with complex surface structure.
-	@:s public var specularTint : Float = 0.0;
-
-	@:s public var specularColorPath : String;
-	@:s public var specularColorCustomValue : Int;
-	@:s public var mode : SpecularColorMode = Albedo;
-
-	public function new(?parent) {
-		super(parent);
-		type = "specularColor";
-	}
-
-	function getMaterials( ctx : Context ) {
-		if( Std.is(parent, Material) ) {
-			var material : Material = cast parent;
-			return material.getMaterials(ctx);
-		}
-		else {
-			return ctx.local3d.getMaterials();
-		}
-	}
-
-	override function makeInstance( ctx : Context ):Context {
-		ctx = ctx.clone(this);
-		refreshShaders(ctx);
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		for( m in getMaterials(ctx) ) {
-			var sca = m.mainPass.getShader(hrt.shader.SpecularColorAlbedo);
-			if( sca != null ) {
-				// No params
-			}
-			var scf = m.mainPass.getShader(hrt.shader.SpecularColorFlat);
-			if( scf != null ) {
-				scf.specularColorValue = h3d.Vector.fromColor(specularColorCustomValue);
-			}
-			var sct = m.mainPass.getShader(hrt.shader.SpecularColorTexture);
-			if( sct != null ) {
-				sct.specularColorTexture = ctx.loadTexture(specularColorPath);
-			}
-			var sc = m.mainPass.getShader(hrt.shader.SpecularColor);
-			if( sc != null ) {
-				sc.specular = specular;
-				sc.specularTint = specularTint;
-			}
-		}
-	}
-
-	function refreshShaders( ctx : Context ) {
-
-		var sca = new SpecularColorAlbedo();
-		var scf = new SpecularColorFlat();
-		var sct = new SpecularColorTexture();
-		var sc = new hrt.shader.SpecularColor();
-
-		var specularColorTexture = specularColorPath != null ? ctx.loadTexture(specularColorPath) : null;
-
-		var mat = getMaterials(ctx);
-		for( m in mat ) {
-			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorAlbedo));
-			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorFlat));
-			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorTexture));
-			m.mainPass.removeShader(m.mainPass.getShader(hrt.shader.SpecularColor));
-		}
-		for( m in mat ) {
-
-			if( m.mainPass.name != "forward" )
-				continue;
-
-			switch mode {
-				case Albedo: m.mainPass.addShader(sca);
-				case Flat: m.mainPass.addShader(scf);
-				case Texture: specularColorTexture == null ? m.mainPass.addShader(scf) : m.mainPass.addShader(sct);
-			}
-
-			m.mainPass.addShader(sc);
-		}
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { 	icon : "cube",
-					name : "SpecularColor",
-					allowParent : function(p) return p.to(Material) != null };
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var flatParams = 	'<dt>Color</dt><dd><input type="color" field="specularColorCustomValue"/></dd>';
-
-		var textureParams = '<dt>Color</dt><dd><input type="texturepath" field="specularColorPath"/>';
-
-		var albedoParams =	'';
-
-		var params = switch mode {
-			case Albedo: albedoParams;
-			case Texture: textureParams;
-			case Flat: flatParams;
-		};
-
-		var props = new hide.Element('
-			<div class="group" name="Specular Color">
-				<dl>
-					<dt>Reflection Amount</dt><dd><input type="range" min="0" max="1" field="specular"/>
-					<dt>Tint Amount</dt><dd><input type="range" min="0" max="1" field="specularTint"/></dd>
-					<dt>Color Mode</dt>
-						<dd>
-							<select field="mode">
-								<option value="Albedo">Albedo</option>
-								<option value="Flat">Flat</option>
-								<option value="Texture">Texture</option>
-							</select>
-						</dd>
-					' + params + '
-				</dl>
-			</div>
-		');
-
-		ctx.properties.add(props, this, function(pname) {
-			if( pname == "mode" || pname == "specularColorPath" ) {
-				ctx.rebuildProperties();
-				refreshShaders(ctx.getContext(this));
-			}
-			ctx.onChange(this, pname);
-		});
-	}
-	#end
-
-	static var _ = Library.register("specularColor", SpecularColor);
-}

+ 0 - 65
hrt/prefab/rfx/AutoExposure.hx

@@ -1,65 +0,0 @@
-package hrt.prefab.rfx;
-
-class AutoExposure extends RendererFX {
-
-	@:s var lightFront : Float = 0.;
-	@:s var lightBack : Float = 0.;
-	@:s var lightPower : Float = 1.;
-	@:s var transitionSpeed : Float = 1.;
-	@:s var useLightZ : Bool = true;
-
-	override function begin( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) {
-		if( step != BeforeTonemapping )
-			return;
-		var exp = 0.;
-		var l = @:privateAccess r.ctx.lights;
-		var mainLight = null;
-		while( l != null ) {
-			var pbrLight = Std.downcast(l, h3d.scene.pbr.DirLight);
-			if( pbrLight != null && pbrLight.isMainLight ) {
-				mainLight = pbrLight;
-				break;
-			}
-			l = l.next;
-		}
-		if( mainLight != null ) {
-			var lightDir = mainLight.getAbsPos().front();
-			var camDir = r.ctx.camera.target.sub(r.ctx.camera.pos);
-			if( !useLightZ ) {
-				lightDir.z = 0;
-				camDir.z = 0;
-			}
-			lightDir.normalize();
-			camDir.normalize();
-			var dir = (lightDir.dot(camDir) + 1) * 0.5;
-			exp += hxd.Math.lerp(lightFront, lightBack, Math.pow(dir, lightPower * lightPower));
-		}
-		var render = cast(r,h3d.scene.pbr.Renderer);
-		var f = 1 - Math.pow(1 - transitionSpeed * transitionSpeed, r.ctx.elapsedTime * 60);
-		render.exposure = hxd.Math.lerp(render.exposure, exp, f);
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		var pr = ctx.properties.add(new hide.Element('
-			<dl>
-			<dt>Light Front</dt><dd><input type="range" min="-2" max="2" field="lightFront"/></dd>
-			<dt>Light Back</dt><dd><input type="range" min="-2" max="2" field="lightBack"/></dd>
-			<dt>Light Power</dt><dd><input type="range" min="0" max="3" field="lightPower"/></dd>
-			<dt>Use Light-Z</dt><dd><input type="checkbox" field="useLightZ"/></dd>
-			<dt>Transition Speed</dt><dd><input type="range" min="0" max="1" field="transitionSpeed"/></dd>
-			</dl>
-			<dl>
-				<dt>Current</dt><dd id="value"></dd>
-			</dl>
-		'),this);
-		ctx.addUpdate(function(_) {
-			var render = cast(ctx.scene.s3d.renderer, h3d.scene.pbr.Renderer);
-			pr.find("#value").text(""+hxd.Math.fmt(render.exposure));
-		});
-	}
-	#end
-
-	static var _ = Library.register("rfx.autoexp", AutoExposure);
-
-}

+ 0 - 77
hrt/prefab/rfx/Bloom.hx

@@ -1,77 +0,0 @@
-package hrt.prefab.rfx;
-
-class BloomTonemap extends hxsl.Shader {
-	static var SRC = {
-		@param var bloomTexture : Sampler2D;
-		var calculatedUV : Vec2;
-		var hdrColor : Vec4;
-		function fragment() {
-			hdrColor += bloomTexture.get(calculatedUV);
-		}
-	}
-}
-
-class Bloom extends RendererFX {
-
-	var bloomPass = new h3d.pass.ScreenFx(new hrt.shader.Bloom());
-	var bloomBlur = new h3d.pass.Blur();
-	var tonemap = new BloomTonemap();
-
-	@:s public var size : Float;
-	@:s public var threshold : Float;
-	@:s public var intensity : Float = 1;
-	@:s public var blur : Float;
-	@:s public var saturation : Float;
-	@:s public var blurQuality : Float = 1;
-	@:s public var blurLinear : Float;
-
-	function new(?parent) {
-		super(parent);
-		size = 0.5;
-		blur = 3;
-		threshold = 0.5;
-	}
-
-	override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) {
-		if( step == BeforeTonemapping ) {
-			r.mark("Bloom");
-			var bloom = r.allocTarget("bloom", false, size, RGBA16F);
-			var ctx = r.ctx;
-			ctx.engine.pushTarget(bloom);
-			bloomPass.shader.texture = ctx.getGlobal("hdrMap");
-			bloomPass.shader.threshold = threshold;
-			bloomPass.shader.intensity = intensity;
-			bloomPass.shader.colorMatrix.identity();
-			bloomPass.shader.colorMatrix.colorSaturate(saturation);
-			bloomPass.render();
-			ctx.engine.popTarget();
-
-			bloomBlur.radius = blur;
-			bloomBlur.quality = blurQuality;
-			bloomBlur.linear = blurLinear;
-			bloomBlur.apply(ctx, bloom);
-
-			tonemap.bloomTexture = bloom;
-			r.addShader(tonemap);
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-			<dl>
-			<dt>Intensity</dt><dd><input type="range" min="0" max="2" field="intensity"/></dd>
-			<dt>Threshold</dt><dd><input type="range" min="0" max="1" field="threshold"/></dd>
-			<dt>Size</dt><dd><input type="range" min="0" max="1" field="size"/></dd>
-			<dt>Blur</dt><dd><input type="range" min="0" max="20" field="blur"/></dd>
-			<dt>Saturation</dt><dd><input type="range" min="-1" max="1" field="saturation"/></dd>
-			<dt>Blur Quality</dt><dd><input type="range" min="0" max="1" field="blurQuality"/></dd>
-			<dt>Blur Linear</dt><dd><input type="range" min="0" max="1" field="blurLinear"/></dd>
-			</dl>
-		'),this);
-	}
-	#end
-
-	static var _ = Library.register("rfx.bloom", Bloom);
-
-}

+ 0 - 151
hrt/prefab/rfx/CloudShadow.hx

@@ -1,151 +0,0 @@
-package hrt.prefab.rfx;
-
-import hxd.res.Loader;
-
-class DirLightWithClouds extends h3d.shader.pbr.Light {
-
-	static var SRC = {
-
-		@param var clouds : Sampler2D;
-		@param var scale : Float;
-		@param var speed : Vec2;
-		@param var opacity : Float;
-		@param var rotation : Mat3;
-
-		@const var hasDistort : Bool;
-		@param var distort : Sampler2D;
-		@param var distortSpeed : Vec2;
-		@param var distortScale : Float;
-		@param var distortAmount : Float;
-
-		@param var time : Float;
-		@param var cameraPosition : Vec3;
-
-		@param var lightDir : Vec3;
-
-		function fragment() {
-			pbrLightDirection = lightDir;
-			pbrLightColor = lightColor;
-			pbrOcclusionFactor = occlusionFactor;
-
-			var pos = transformedPosition.xy * scale;
-			var uv = pos + time * speed;
-			if( hasDistort )
-				uv += (distort.get(pos * distortScale + time * distortSpeed).xy - 0.5) * distortAmount;
-			var cloudIntensity = clouds.get(uv).r * opacity;
-			pbrLightColor *= 1.0 - cloudIntensity.saturate();
-		}
-	};
-}
-
-@:access(h3d.scene.pbr.DirLight)
-class CloudShadow extends RendererFX {
-
-	var dlwc = new DirLightWithClouds();
-
-	@:s public var opacity : Float = 1;
-	@:s public var scale : Float = 1;
-	@:s public var speed : Float;
-	@:s public var angle : Float;
-	@:s public var texturePath : String;
-	@:s public var distort : {
-		var path : String;
-		var scale : Float;
-		var speed : Float;
-		var angle : Float;
-		var amount : Float;
-	};
-
-	override function makeInstance( ctx : Context ) : Context {
-		ctx = super.makeInstance(ctx);
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		if( step == Shadows ) {
-			var ctx = r.ctx;
-
-			var mainLight : h3d.scene.pbr.DirLight = null;
-			var l = @:privateAccess ctx.lights;
-			while( l != null ) {
-				var pbrLight = Std.downcast(l, h3d.scene.pbr.DirLight);
-				if( pbrLight != null && pbrLight.isMainLight ) {
-					mainLight = pbrLight;
-					break;
-				}
-				l = l.next;
-			}
-
-			if( mainLight != null ) {
-				mainLight.shader = dlwc;
-				dlwc.lightDir = mainLight.pbr.lightDir;
-				dlwc.lightColor.load(mainLight._color);
-				dlwc.lightColor.scale3(mainLight.power * mainLight.power);
-				dlwc.occlusionFactor = mainLight.occlusionFactor;
-				var angle = angle * Math.PI / 180;
-				var speed = speed / scale;
-				dlwc.speed.set(Math.cos(angle) * speed, Math.sin(angle) * speed);
-				dlwc.scale = 1.0 / scale;
-				dlwc.opacity = opacity;
-				dlwc.time = ctx.time;
-				if( texturePath != null )
-					dlwc.clouds = Loader.currentInstance.load(texturePath).toTexture();
-				if( dlwc.clouds != null )
-					dlwc.clouds.wrap = Repeat;
-				var dist = distort;
-				dlwc.hasDistort = dist != null;
-				if( dist != null ) {
-					var angle = dist.angle * Math.PI / 180;
-					dlwc.distort = Loader.currentInstance.load(dist.path).toTexture();
-					if( dlwc.distort != null ) dlwc.distort.wrap = Repeat;
-					dlwc.distortAmount = dist.amount * 0.01;
-					dlwc.distortSpeed.set(Math.cos(angle) * dist.speed * 0.1, Math.sin(angle) * dist.speed * 0.1);
-					dlwc.distortScale = dist.scale;
-				}
-			}
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-			<div class="group" name="Cloud">
-				<dt>Opacity</dt><dd><input type="range" min="0" max="1" field="opacity"/></dd>
-				<dt>Scale</dt><dd><input type="range" min="0" max="50" field="scale"/></dd>
-				<dt>Speed</dt><dd><input type="range" min="-1" max="1" field="speed"/></dd>
-				<dt>Angle</dt><dd><input type="range" min="-180" max="180" field="angle"/></dd>
-				<dt>Texture</dt><dd><input type="texturepath" field="texturePath"/></dd>
-			</div>
-		'),this);
-		var dist = distort;
-		if( dist == null )
-			dist = {
-				path : null,
-				scale : 1,
-				speed : 0,
-				angle : 0,
-				amount : 1,
-			};
-		ctx.properties.add(new hide.Element('
-			<div class="group" name="Distort">
-				<dt>Texture</dt><dd><input type="texturepath" field="path"/></dd>
-				<dt>Amount</dt><dd><input type="range" min="0" max="1" field="amount"/></dd>
-				<dt>Scale</dt><dd><input type="range" min="0.1" max="2" field="scale"/></dd>
-				<dt>Speed</dt><dd><input type="range" min="-1" max="1" field="speed"/></dd>
-				<dt>Angle</dt><dd><input type="range" min="-180" max="180" field="angle"/></dd>
-			</div>
-		'),dist, function(name) {
-			if( name == "path" ) {
-				if( dist.path == null )
-					distort = js.Lib.undefined;
-				else
-					distort = dist;
-			}
-		});
-	}
-	#end
-
-	static var _ = Library.register("rfx.cloudShadow", CloudShadow);
-
-}

+ 0 - 103
hrt/prefab/rfx/ColorGrading.hx

@@ -1,103 +0,0 @@
-package hrt.prefab.rfx;
-
-import hxd.Pixels;
-
-class ColorGradingTonemap extends hxsl.Shader {
-	static var SRC = {
-
-		@param var size : Int;
-		@param var intensity : Float;
-		@param var lut : Sampler2D;
-		var hdrColor : Vec4;
-		var pixelColor : Vec4;
-
-		function fragment() {
-			var uv = pixelColor.rgb;
-			var innerWidth = size - 1.0;
-			var sliceSize = 1.0 / size;
-			var slicePixelSize = sliceSize / size;
-			var sliceInnerSize = slicePixelSize * innerWidth;
-			var blueSlice0 = min(floor(uv.b * innerWidth), innerWidth);
-			var blueSlice1 = min(blueSlice0 + 1.0, innerWidth);
-			var xOffset = slicePixelSize * 0.5 + uv.r * sliceInnerSize;
-			var yOffset = sliceSize * 0.5 + uv.g * (1.0 - sliceSize);
-			var s0 = vec2(xOffset + (blueSlice0 * sliceSize), yOffset);
-			var s1 = vec2(xOffset + (blueSlice1 * sliceSize), yOffset);
-			var slice0Color = texture(lut, s0).rgb;
-			var slice1Color = texture(lut, s1).rgb;
-			var bOffset = mod(uv.b * innerWidth, 1.0);
-			pixelColor.rgb = mix(pixelColor.rgb, mix(slice0Color, slice1Color, bOffset), intensity);
-		}
-	}
-}
-
-class ColorGrading extends RendererFX {
-
-	var tonemap = new ColorGradingTonemap();
-	public var customLut : h3d.mat.Texture;
-
-	@:s var size : Int = 16;
-	@:s var texturePath : String;
-	@:s public var intensity : Float = 1;
-
-	public function getLutTexture() {
-		if( texturePath == null ) return null;
-		return hxd.res.Loader.currentInstance.load(texturePath).toTexture();
-	}
-
-	override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) {
-		if( step == BeforeTonemapping ) {
-			r.mark("ColorGrading");
-			tonemap.intensity = intensity;
-			tonemap.size = size;
-			tonemap.lut = customLut != null ? customLut : getLutTexture();
-			if( tonemap.lut != null && intensity > 0 )
-				r.addShader(tonemap);
-		}
-	}
-
-	#if editor
-
-	override function edit( ctx : hide.prefab.EditContext ) {
-
-		var e = new hide.Element('
-			<div class="group" name="Color Grading">
-				<dl>
-					<dt>LUT</dt><dd><input type="texturepath" field="texturePath"/></dd>
-					<dt>Size</dt><dd><input type="range" min="1" max="256" step="1" field="size"/></dd>
-					<dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
-				</dl>
-			</div>
-			<div class="group" name="Debug">
-				<div align="center" >
-					<input type="button" value="Create default" class="createDefault" />
-				</div>
-			</div>
-		');
-
-		var but = e.find(".createDefault");
-		but.click(function(_) {
-			function saveTexture( name : String ) {
-				var step = hxd.Math.ceil(255/(size - 1));
-				var p = hxd.Pixels.alloc(size * size, size, RGBA);
-				for( r in 0 ... size ) {
-					for( g in 0 ... size ) {
-						for( b in 0 ... size ) {
-							p.setPixel(r + b * size, g, 255 << 24 | ((r*step) << 16) | ((g*step) << 8 ) | (b*step));
-						}
-					}
-				}
-				var path = ctx.ide.getPath(name);
-				sys.io.File.saveBytes(path, p.toPNG());
-				p.dispose();
-			}
-			ctx.ide.chooseFileSave("defaultLUT.png", saveTexture);
-		});
-
-		ctx.properties.add(e, this);
-	}
-	#end
-
-	static var _ = Library.register("rfx.colorGrading", ColorGrading);
-
-}

+ 0 - 274
hrt/prefab/rfx/Configurator.hx

@@ -1,274 +0,0 @@
-package hrt.prefab.rfx;
-
-import h3d.scene.Renderer;
-
-#if hscript
-
-private typedef ChangedVar = { obj : Dynamic, field : String, value : Dynamic, set : Bool };
-
-class ConfiguratorInterp extends hscript.Interp {
-	public var allowChanges : Bool = false;
-	var prevVars : Map<String,Array<ChangedVar>> = [];
-	var allVars : Array<ChangedVar> = [];
-	public function new() {
-		super();
-	}
-
-	override function set( o : Dynamic, f : String, v : Dynamic ) : Dynamic {
-		var prev = prevVars.get(f);
-		if( prev == null ) {
-			prev = [];
-			prevVars.set(f, prev);
-		}
-		var found = null;
-		for( v in prev ) {
-			if( v.obj == o ) {
-				found = v;
-				break;
-			}
-		}
-		if( found == null ) {
-			#if editor
-			if( !Reflect.hasField(o,f) ) {
-				var c = Type.getClass(o);
-				while( c != null ) {
-					if( Type.getInstanceFields(c).indexOf(f) >= 0 )
-						break;
-					c = Type.getSuperClass(c);
-				}
-				if( c == null ) {
-					var cl = Type.getClass(o);
-					throw (cl == null ? ""+o : Type.getClassName(cl)) + " has no field "+f;
-				}
-			}
-			#end
-			found = { obj : o, field : f, value : null, set : false };
-			if ( !allowChanges )
-				allVars.push(found);
-			prev.push(found);
-			if( allVars.length > 200 ) throw "Vars are leaking";
-		}
-		if( !found.set ) {
-			found.set = true;
-			found.value = Reflect.getProperty(o, f);
-		}
-		Reflect.setProperty(o, f, v);
-		return v;
-	}
-
-	public function restoreVars() {
-		for( v in allVars ) {
-			if( v.set ) {
-				Reflect.setProperty(v.obj, v.field, v.value);
-				v.set = false;
-			}
-		}
-	}
-
-}
-#end
-
-
-class Configurator extends RendererFX {
-
-	@:s public var vars : Array<{ name : String, defValue : Float }> = [];
-	@:s var script : String = "";
-	var values : Map<String, Float> = new Map();
-
-	var prefabCache : Map<String, { r : Prefab }> = new Map();
-	var particlesCache : Map<String, { v : h3d.scene.Object }> = new Map();
-
-	#if hscript
-	var interp : ConfiguratorInterp;
-	var parsedExpr : hscript.Expr;
-	#end
-	#if editor
-	var errorTarget : hide.Element;
-	#end
-	var rootPrefab : Prefab;
-
-	public function new(?parent) {
-		super(parent);
-		type = "configurator";
-	}
-
-	public function set( name : String, value : Float ) {
-		values.set(name,value);
-	}
-
-	function smoothValue( v : Float, easing : Float ) : Float {
-		var bpow = Math.pow(v, 1 + easing);
-		return bpow / (bpow + Math.pow(1 - v, easing + 1));
-	}
-
-	function getParts( r : Renderer, id : String) {
-		var p = particlesCache.get(id);
-		if (p != null)
-			return p.v;
-		var obj = r.ctx.scene.getObjectByName(id);
-		if ( obj == null)
-			throw "Missing object #"+id;
-		#if !editor
-		particlesCache.set(id, { v : obj });
-		#end
-		return obj;
-	}
-
-	function getPrefab( opt : Bool, id : String ) {
-		var p = prefabCache.get(id);
-		if( p != null )
-			return p.r;
-		var p = rootPrefab.getOpt(hrt.prefab.Prefab,id,true);
-		if( p == null ) {
-			if( opt ) return null;
-			throw "Missing prefab #"+id;
-		}
-		#if !editor
-		prefabCache.set(id, { r : p });
-		#end
-		return p;
-	}
-
-	#if hscript
-	function allowChanges( v : Bool ) {
-		interp.allowChanges = v;
-	}
-	#end
-
-	function resetCache() {
-		prefabCache = [];
-		particlesCache = [];
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		for( v in vars )
-			values.set(v.name, v.defValue);
-		rootPrefab = this;
-		var shared = ctx.shared;
-		while( shared.parent != null ) {
-			rootPrefab = shared.parent.prefab;
-			shared = shared.parent.shared;
-		}
-		while( rootPrefab.parent != null )
-			rootPrefab = rootPrefab.parent;
-		resetCache();
-		#if hscript
-		interp = null;
-		#end
-		return super.makeInstance(ctx);
-	}
-
-	override function begin(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		#if !hscript
-		throw "Requires -lib hscript";
-		#else
-		if( step == MainDraw ) {
-			var errorMessage = null;
-			if( parsedExpr == null ) {
-				var parser = new hscript.Parser();
-				parsedExpr = try parser.parseString(script) catch( e : hscript.Expr.Error ) { errorMessage = hscript.Printer.errorToString(e); null; };
-			}
-			if( interp == null ) {
-				interp = new ConfiguratorInterp();
-				interp.variables.set("get", getPrefab.bind(false));
-				interp.variables.set("getParts", getParts.bind(r));
-				interp.variables.set("getOpt", getPrefab.bind(true));
-				interp.variables.set("smooth", smoothValue);
-				interp.variables.set("allowChanges", allowChanges);
-			}
-			for( k => v in values )
-				interp.variables.set(k, v);
-			if( errorMessage == null )
-				try {
-					interp.execute(parsedExpr);
-				} catch( e : Dynamic ) {
-					errorMessage = Std.string(e);
-				}
-			if( errorMessage != null ) {
-				#if editor
-				if( errorTarget != null ) errorTarget.text(errorMessage);
-				#end
-			} else {
-				#if editor
-				if( errorTarget != null ) errorTarget.html("&nbsp;");
-				#end
-			}
-		}
-		#end
-	}
-
-	#if hscript
-	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		if( step == Overlay )
-		 	interp.restoreVars();
-	}
-	#end
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { name : "Configurator", icon : "dashboard" };
-	}
-
-	override function edit( ectx : EditContext ) {
-		var props = new hide.Element('
-		<div>
-			<div class="group" name="Variables">
-				<dl id="vars">
-				</dl>
-				<dl>
-					<dt></dt>
-					<dd><input type="button" value="Add" id="addvar"/></dd>
-				</dl>
-			</div>
-			<div class="group" name="Script">
-			<div>
-				<div class="error">&nbsp;</div>
-				<div id="script" style="height:200px"></div>
-			</div>
-			</div>
-		</div>
-		');
-		errorTarget = props.find(".error");
-		var evars = props.find("#vars");
-		props.find("#addvar").click(function(_) {
-			var name = ectx.ide.ask("Variable name");
-			if( name == null ) return;
-			ectx.makeChanges(this, function() vars.push({ name : name, defValue: 0 }));
-			values.set(name, 0);
-			ectx.rebuildProperties();
-		});
-		ectx.properties.add(props);
-		for( v in vars ) {
-			var ref = { v : values.get(v.name) };
-			var def = new hide.Element('<div><dt>${v.name}</dt><dd><input type="range" min="0" max="1" field="v"/></dd></div>').appendTo(evars);
-			ectx.properties.build(def, ref, function(_) {
-				values.set(v.name, ref.v);
-			});
-			def.find("dt").contextmenu(function(e) {
-				new hide.comp.ContextMenu([
-					{ label : "Set Default", click : () -> v.defValue = ref.v },
-					{ label : "Remove", click : () -> {
-						vars.remove(v);
-						values.remove(v.name);
-						interp.variables.remove(v.name);
-						ectx.rebuildProperties();
-					}},
-				]);
-				return false;
-			});
-		}
-
-		var selt = props.find("#script");
-		var editor = new hide.comp.ScriptEditor(this.script, selt, selt);
-		editor.onSave = function() {
-			script = editor.code;
-			parsedExpr = null;
-			interp = null;
-		};
-	}
-	#end
-
-	static var _ = Library.register("rfx.configurator", Configurator);
-
-
-}

+ 0 - 135
hrt/prefab/rfx/DistanceBlur.hx

@@ -1,135 +0,0 @@
-package hrt.prefab.rfx;
-
-class DistanceBlurShader extends hrt.shader.PbrShader {
-
-	static var SRC = {
-
-		@param var nearStartDistance : Float;
-		@param var nearEndDistance : Float;
-		@param var nearStartIntensity : Float;
-		@param var nearEndIntensity : Float;
-
-		@param var farStartDistance : Float;
-		@param var farEndDistance : Float;
-		@param var farStartIntensity : Float;
-		@param var farEndIntensity : Float;
-
-		@param var blurredTexture : Sampler2D;
-
-		@const var DEBUG : Bool = false;
-
-		var currentPosition : Vec3;
-		var blurAmount : Float;
-
-		function __init__fragment() {{
-			currentPosition = getPosition();
-			var distance = (currentPosition - camera.position).length();
-			blurAmount = 0;
-			if( distance < nearEndDistance ) {
-				var nearIntensityFactor = clamp((distance - nearStartDistance) / (nearEndDistance - nearStartDistance), 0, 1);
-				blurAmount = mix(nearStartIntensity, nearEndIntensity, nearIntensityFactor);
-			}
-			else if( distance > farStartDistance ) {
-				var farIntensityFactor = clamp((distance - farStartDistance) / (farEndDistance - farStartDistance), 0, 1);
-				blurAmount = mix(farStartIntensity, farEndIntensity, farIntensityFactor);
-			}
-		}}
-
-		function fragment() {
-			if( blurAmount <= 0.004 ) discard;
-			pixelColor = DEBUG ? vec4(blurAmount.xxx, 1.0) : vec4(blurredTexture.get(calculatedUV).rgb, blurAmount);
-		}
-
-	};
-
-	public function new() {
-		super();
-	}
-
-}
-
-class DistanceBlur extends RendererFX {
-
-	var blurPass = new h3d.pass.ScreenFx(new DistanceBlurShader());
-	var lbrBlur = new h3d.pass.Blur();
-
-	@:s public var nearStartDistance : Float;
-	@:s public var nearEndDistance : Float;
-	@:s public var nearStartIntensity : Float = 1;
-	@:s public var nearEndIntensity : Float;
-
-	@:s public var farStartDistance : Float;
-	@:s public var farEndDistance : Float;
-	@:s public var farStartIntensity : Float;
-	@:s public var farEndIntensity : Float = 1;
-
-	@:s public var showDebug : Bool;
-	@:s public var blurTextureSize : Float;
-	@:s public var blurRange : Int;
-
-	function new(?parent) {
-		super(parent);
-		nearEndDistance = 10;
-		farStartDistance = 100;
-		farEndDistance = 500;
-		blurTextureSize = 0.5;
-		blurRange = 6;
-		blurPass.pass.setBlendMode(Alpha);
-	}
-
-	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		if( !checkEnabled() ) return;
-		if( step == AfterTonemapping ) {
-			var ctx = r.ctx;
-			blurPass.shader.nearStartDistance = nearStartDistance;
-			blurPass.shader.nearEndDistance = nearEndDistance;
-			blurPass.shader.nearStartIntensity = nearStartIntensity;
-			blurPass.shader.nearEndIntensity = nearEndIntensity;
-			blurPass.shader.farStartDistance = farStartDistance;
-			blurPass.shader.farEndDistance = farEndDistance;
-			blurPass.shader.farStartIntensity = farStartIntensity;
-			blurPass.shader.farEndIntensity = farEndIntensity;
-			blurPass.shader.DEBUG = #if editor showDebug #else false #end;
-
-			var ldr : h3d.mat.Texture = ctx.getGlobal("ldrMap");
-			var lbrBlurred = r.allocTarget("ldrBlurred", false, blurTextureSize, RGBA);
-			r.copy(ldr, lbrBlurred);
-			lbrBlur.radius = blurRange;
-			lbrBlur.apply(ctx, lbrBlurred);
-
-			blurPass.shader.blurredTexture = lbrBlurred;
-			blurPass.setGlobals(ctx);
-			blurPass.render();
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-				<div class="group" name="Near Blur">
-					<dt>Start Distance</dt><dd><input type="range" min="0" max="1000" field="nearStartDistance"/></dd>
-					<dt>End Distance</dt><dd><input type="range" min="0" max="1000" field="nearEndDistance"/></dd>
-					<dt>Start Opacity</dt><dd><input type="range" min="0" max="1" field="nearStartIntensity"/></dd>
-					<dt>End Opacity</dt><dd><input type="range" min="0" max="1" field="nearEndIntensity"/></dd>
-				</div>
-				<div class="group" name="Far Blur">
-					<dt>Start Distance</dt><dd><input type="range" min="0" max="1000" field="farStartDistance"/></dd>
-					<dt>End Distance</dt><dd><input type="range" min="0" max="1000" field="farEndDistance"/></dd>
-					<dt>Start Opacity</dt><dd><input type="range" min="0" max="1" field="farStartIntensity"/></dd>
-					<dt>End Opacity</dt><dd><input type="range" min="0" max="1" field="farEndIntensity"/></dd>
-				</div>
-				<div class="group" name="Blur">
-					<dt>Texture Size</dt><dd><input type="range" min="0" max="1" field="blurTextureSize"/></dd>
-					<dt>Range</dt><dd><input type="range" min="0" max="20" step="2" field="blurRange"/></dd>
-				</div>
-				<div class="group" name="Debug">
-					<dt>Show Debug</dt><dd><input type="checkbox" field="showDebug"/></dd>
-				</div>
-		'),this);
-		super.edit(ctx);
-	}
-	#end
-
-	static var _ = Library.register("rfx.distanceBlur", DistanceBlur);
-
-}

+ 0 - 51
hrt/prefab/rfx/Distortion.hx

@@ -1,51 +0,0 @@
-package hrt.prefab.rfx;
-
-class DistortionTonemap extends hxsl.Shader {
-	static var SRC = {
-
-		var calculatedUV : Vec2;
-		@param var distortionMap : Sampler2D;
-		@param var amount : Float;
-
-		function fragment() {
-			var distortionVal = distortionMap.get(calculatedUV).rg * amount;
-			calculatedUV += distortionVal;
-		}
-	}
-}
-
-class Distortion extends RendererFX {
-
-	var tonemap = new DistortionTonemap();
-	@:s public var amount : Float = 1;
-
-	override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) {
-		if( step == BeforeTonemapping ) {
-			r.mark("Distortion");
-			var distortionMap = r.allocTarget("distortion", true, 1.0, RG16F);
-			r.ctx.setGlobal("distortion", distortionMap);
-			r.setTarget(distortionMap);
-			r.clear(0);
-			r.draw("distortion");
-
-			tonemap.amount = amount;
-			tonemap.distortionMap = distortionMap;
-			r.addShader(tonemap);
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-			<div class="group" name="Distortion">
-				<dl>
-					<dt>Amount</dt><dd><input type="range" min="0" max="1" field="amount"/></dd>
-				</dl>
-			</div>
-		'),this);
-	}
-	#end
-
-	static var _ = Library.register("rfx.distortion", Distortion);
-
-}

+ 0 - 231
hrt/prefab/rfx/FrustumJitter.hx

@@ -1,231 +0,0 @@
-package hrt.prefab.rfx;
-
-enum abstract Pattern(String) {
-	var Still;
-	var Uniform2;
-	var Uniform4;
-	var Uniform4_Helix;
-	var Uniform4_DoubleHelix;
-	var SkewButterfly;
-	var Rotated4;
-	var Rotated4_Helix;
-	var Rotated4_Helix2;
-	var Poisson10;
-	var Pentagram;
-	var Halton_2_3_x8;
-	var Halton_2_3_x16;
-	var Halton_2_3_x32;
-	var Halton_2_3_x256;
-	var MotionPerp2;
-	var MotionVPerp2;
-}
-
-class FrustumJitter {
-
-	public var points_Still : Array<Float> = [
-		0.0, 0.0,
-	];
-
-   	public var points_Uniform2 : Array<Float> = [
-		-0.2, -0.2,//ll
-		0.2,  0.2,//ur
-	];
-
-	public var points_Uniform4 : Array<Float> = [
-		-0.2, -0.2,//ll
-		0.2, -0.2,//lr
-		0.2,  0.2,//ur
-		-0.2,  0.2,//ul
-	];
-
-	public var points_Uniform4_Helix : Array<Float> = [
-		-0.2, -0.2,//ll  3  1
-		0.2,  0.2,//ur   \/|
-		0.2, -0.2,//lr   /\|
-		-0.2,  0.2,//ul  0  2
-	];
-
-	public var points_Uniform4_DoubleHelix : Array<Float> = [
-		-0.2, -0.2,//ll  3  1
-		0.2,  0.2,//ur   \/|
-		0.2, -0.2,//lr   /\|
-		-0.2,  0.2,//ul  0  2
-		-0.2, -0.2,//ll  6--7
-		0.2, -0.2,//lr   \
-		-0.2,  0.2,//ul    \
-		0.2,  0.2,//ur  4--5
-	];
-
-	public var points_SkewButterfly : Array<Float> = [
-		-0.250, -0.250,
-		0.250,  0.250,
-		0.12, -0.12,
-		-0.12,  0.12,
-	];
-
-	public var points_Rotated4 : Array<Float> = [
-		-0.12, -0.37,//ll
-		0.37, -0.12,//lr
-		0.12,  0.37,//ur
-		-0.37,  0.12,//ul
-	];
-
-	public var points_Rotated4_Helix : Array<Float> = [
-		-0.12, -0.37,//ll  3  1
-		0.12,  0.37,//ur   \/|
-		0.37, -0.12,//lr   /\|
-		-0.37,  0.12,//ul  0  2
-	];
-
-	public var points_Rotated4_Helix2 : Array<Float> = [
-		-0.12, -0.37,//ll  2--1
-		0.12,  0.37,//ur   \/
-		-0.37,  0.12,//ul   /\
-		0.37, -0.12,//lr  0  3
-	];
-
-	public var points_Poisson10 : Array<Float> = [
-		-0.16795960*0.2,  0.65544910*0.2,
-		-0.69096030*0.2,  0.59015970*0.2,
-		0.49843820*0.2,  0.83099720*0.2,
-		0.17230150*0.2, -0.03882703*0.2,
-		-0.60772670*0.2, -0.06013587*0.2,
-		0.65606390*0.2,  0.24007600*0.2,
-		0.80348370*0.2, -0.48096900*0.2,
-		0.33436540*0.2, -0.73007030*0.2,
-		-0.47839520*0.2, -0.56005300*0.2,
-		-0.12388120*0.2, -0.96633990*0.2,
-	];
-
-	public var points_Pentagram : Array<Float> = [
-		0.000000,  0.525731,// head
-		-0.309017, -0.42532,// lleg
-		0.500000,  0.162460,// rarm
-		-0.500000,  0.162460,// larm
-		0.309017, -0.42532,// rleg
-	];
-
-	public var points_Halton_2_3_x8 : Array<Float> = [];
-	public var points_Halton_2_3_x16 : Array<Float> = [];
-	public var points_Halton_2_3_x32 : Array<Float> = [];
-	public var points_Halton_2_3_x256 : Array<Float> = [];
-	public var points_MotionPerp2 : Array<Float> = [
-		0.00, -0.2,
-		0.00,  0.2,
-	];
-
-	public var points_MotionVPerp2 : Array<Float> = [
-		-0.20, -0.0,
-		0.20,  0.0,
-	];
-
-
-
-    private inline function getSeq( pattern : Pattern ) : Array<Float> {
-       return switch (pattern) {
-			case Still: points_Still;
-			case Uniform2 : points_Uniform2;
-			case Uniform4 : points_Uniform4;
-			case Uniform4_Helix : points_Uniform4_Helix;
-			case Uniform4_DoubleHelix : points_Uniform4_DoubleHelix;
-			case SkewButterfly : points_SkewButterfly;
-			case Rotated4 : points_Rotated4;
-			case Rotated4_Helix : points_Rotated4_Helix;
-			case Rotated4_Helix2 : points_Rotated4_Helix2;
-			case Poisson10 : points_Poisson10;
-			case Pentagram : points_Pentagram;
-			case Halton_2_3_x8 : points_Halton_2_3_x8;
-			case Halton_2_3_x16 : points_Halton_2_3_x16;
-			case Halton_2_3_x32 : points_Halton_2_3_x32;
-			case Halton_2_3_x256 : points_Halton_2_3_x256;
-			case MotionPerp2 : points_MotionPerp2;
-			case MotionVPerp2 : points_MotionVPerp2;
-			default : null;
-		}
-    }
-
-	public var patternScale = 1.0;
-	public var activeIndex = 0;
-	public var curSample = new h2d.col.Point(0,0);
-	public var prevSample = new h2d.col.Point(0,0);
-	public var curPattern : Pattern = Still;
-
-	public function new() {
-		points_Halton_2_3_x8.resize(8);
-		initializeHalton_2_3(points_Halton_2_3_x8);
-		points_Halton_2_3_x16.resize(16);
-		initializeHalton_2_3(points_Halton_2_3_x16);
-		points_Halton_2_3_x32.resize(32);
-		initializeHalton_2_3(points_Halton_2_3_x32);
-		points_Halton_2_3_x256.resize(256);
-		initializeHalton_2_3(points_Halton_2_3_x256);
-	}
-
-	public function update() {
-
-		var seq = getSeq(curPattern);
-		if( seq == null )
-			return;
-
-		activeIndex += 1;
-		activeIndex %= seq.length;
-
-		var newSample = sample(seq, activeIndex);
-		prevSample.load(curSample);
-		curSample.load(newSample);
-	}
-
-	private function sample( pattern : Array<Float>, index : Int ) : h2d.col.Point
-    {
-        var n = Std.int(pattern.length / 2.0);
-        var i = index % n;
-
-        var x = patternScale * pattern[2 * i + 0];
-		var y = patternScale * pattern[2 * i + 1];
-
-		return new h2d.col.Point(x, y);
-
-        /*if (pattern != Pattern.MotionPerp2)
-            return new Vector2(x, y);
-        else
-            return new Vector2(x, y).Rotate(Vector2.right.SignedAngle(focalMotionDir));*/
-    }
-
-	private function transformPattern( seq : Array<Float>, theta : Float, scale : Float) {
-        var cs = hxd.Math.cos(theta);
-		var sn = hxd.Math.sin(theta);
-		var i = 0;
-		var j = 1;
-		while( i != seq.length ) {
-			var x = scale * seq[i];
-            var y = scale * seq[j];
-            seq[i] = x * cs - y * sn;
-            seq[j] = x * sn + y * cs;
-			i += 2;
-			j += 2;
-		}
-    }
-
-	// http://en.wikipedia.org/wiki/Halton_sequence
-	private function haltonSeq(prime : Int, index : Int = 1/* NOT! zero-based */) : Float {
-		var r = 0.0;
-		var f = 1.0;
-		var i = index;
-		while( i > 0 ) {
-			f /= prime;
-			r += f * (i % prime);
-			i = hxd.Math.floor(i / prime);
-		}
-		return r;
-	}
-
-	private function initializeHalton_2_3( seq : Array<Float> ) {
-		var sampleCount = Std.int(seq.length / 2.0);
-		for( i in 0 ... sampleCount ) {
-			var u = haltonSeq(2, i + 1) - 0.5;
-			var v = haltonSeq(3, i + 1) - 0.5;
-			seq[2 * i + 0] = u;
-			seq[2 * i + 1] = v;
-		}
-	}
-}

+ 0 - 245
hrt/prefab/rfx/GenFog.hx

@@ -1,245 +0,0 @@
-package hrt.prefab.rfx;
-
-class GenFogShader extends hrt.shader.PbrShader {
-
-	static var SRC = {
-
-		@param var startDistance : Float;
-		@param var distanceScale : Float;
-		@param var distanceOpacity : Float;
-		@param var cameraDistance : Float;
-
-		@param var startHeight : Float;
-		@param var heightScale : Float;
-		@param var heightOpacity : Float;
-
-		@param var startColor : Vec4;
-		@param var endColor : Vec4;
-
-		@const var usePosition : Bool;
-		@param var position : Vec3;
-
-		@const var useNoise : Bool;
-		@param var noiseTex : Sampler2D;
-		@param var noiseScale : Float;
-		@param var noiseSpeed : Float;
-		@param var noiseAmount : Vec3;
-
-		@param var lightDirection : Vec3;
-		@param var lightColor : Vec3;
-
-		function fragment() {
-			var origin = getPosition();
-			var amount = 0.;
-
-			if( useNoise ) {
-				var noise = noiseTex.get( origin.xy * noiseScale + vec2(global.time * noiseSpeed, noiseScale * origin.z) * vec2(1,-1) );
-				origin += (noise.rgb - 0.5) * noiseAmount;
-			}
-
-			if( distanceOpacity != 0 ) {
-				var distance = (origin - (usePosition ? position : camera.position)).length() - cameraDistance;
-				amount += clamp((distance - startDistance) * distanceScale, 0, 1) * distanceOpacity;
-			}
-
-			if( heightOpacity != 0 ) {
-				var height = origin.z;
-				if( usePosition ) height -= position.z;
-				amount += clamp((height - startHeight) * heightScale, 0, 1) * heightOpacity;
-			}
-
-			var fogColor = mix(startColor, endColor, clamp(amount,0,1));
-			fogColor.rgb += (camera.position - origin).normalize().dot(lightDirection).max(0) * lightColor;
-			pixelColor = fogColor;
-		}
-
-	};
-
-	public function new() {
-		super();
-	}
-
-}
-
-typedef GenFogNoise = {
-	var texture : String;
-	var speed : Float;
-	var scale : Float;
-	var amount : Float;
-	var distAmount : Float;
-}
-
-enum abstract GenFogRenderMode(String) {
-	var BeforeTonemapping;
-	var AfterTonemapping;
-}
-
-class GenFog extends RendererFX {
-
-	var fogPass = new h3d.pass.ScreenFx(new GenFogShader());
-
-	@:s public var startDistance : Float;
-	@:s public var endDistance : Float;
-	@:s public var distanceOpacity : Float;
-	@:s public var distanceFixed : Bool;
-
-	@:s public var startHeight : Float;
-	@:s public var endHeight : Float;
-	@:s public var heightOpacity : Float;
-
-	@:s public var startOpacity : Float;
-	@:s public var endOpacity : Float;
-
-	@:s public var startColor : Int;
-	@:s public var endColor : Int;
-	@:s public var renderMode : GenFogRenderMode;
-
-	@:s public var noise : GenFogNoise;
-
-	@:s public var posX : Float;
-	@:s public var posY : Float;
-	@:s public var posZ : Float;
-	@:s public var usePosition : Bool;
-
-	@:s public var lightColor = 0xFFFFFF;
-	@:s public var lightColorAmount : Float;
-
-	public function new(?parent) {
-		super(parent);
-		renderMode = AfterTonemapping;
-		endDistance = 100;
-		startHeight = 100;
-		endOpacity = 1;
-		startColor = 0xffffff;
-	    endColor = 0xffffff;
-		fogPass.pass.setBlendMode(Alpha);
-	}
-
-	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		if( !checkEnabled() ) return;
-		if( (step == AfterTonemapping && renderMode == AfterTonemapping) || (step == BeforeTonemapping && renderMode == BeforeTonemapping) ) {
-			r.mark("DistanceFog");
-			var ctx = r.ctx;
-
-			fogPass.shader.startDistance = startDistance;
-			fogPass.shader.distanceScale = 1 / (endDistance - startDistance);
-			fogPass.shader.distanceOpacity = distanceOpacity;
-			fogPass.shader.cameraDistance = distanceFixed ? r.ctx.camera.pos.sub(r.ctx.camera.target).length() : 0;
-
-			fogPass.shader.startHeight = startHeight;
-			fogPass.shader.heightScale = 1 / (endHeight - startHeight);
-			fogPass.shader.heightOpacity = heightOpacity;
-
-			fogPass.shader.startColor.setColor(startColor);
-			fogPass.shader.endColor.setColor(endColor);
-			fogPass.shader.startColor.a = startOpacity;
-			fogPass.shader.endColor.a = endOpacity;
-
-			fogPass.shader.position.set(posX, posY, posZ);
-			fogPass.shader.usePosition = usePosition;
-
-			fogPass.shader.useNoise = noise != null && noise.texture != null;
-			if( noise != null && noise.texture != null ) {
-				fogPass.shader.noiseTex = hxd.res.Loader.currentInstance.load(noise.texture).toTexture();
-				fogPass.shader.noiseTex.wrap = Repeat;
-				fogPass.shader.noiseScale = 1 / noise.scale;
-				fogPass.shader.noiseSpeed = noise.speed / noise.scale;
-				fogPass.shader.noiseAmount.set(noise.amount * noise.distAmount, noise.amount * noise.distAmount, noise.amount);
-			}
-
-			var ls = r.getLightSystem().shadowLight;
-			if( ls == null )
-				fogPass.shader.lightDirection.set(0,0,0);
-			else
-				fogPass.shader.lightDirection.load(@:privateAccess ls.getShadowDirection());
-			fogPass.shader.lightColor.setColor(lightColor);
-			fogPass.shader.lightColor.scale3(lightColorAmount);
-
-
-			fogPass.setGlobals(ctx);
-			fogPass.render();
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-			<dl>
-				<div class="group" name="Distance">
-					<dt>Start Distance</dt><dd><input type="range" min="0" max="100" field="startDistance"/></dd>
-					<dt>End Distance</dt><dd><input type="range" min="0" max="100" field="endDistance"/></dd>
-					<dt>Distance Opacity</dt><dd><input type="range" min="0" max="2" field="distanceOpacity"/></dd>
-					<dt>Camera Independant</dt><dd><input type="checkbox" field="distanceFixed"/></dd>
-				</div>
-				<div class="group" name="Height">
-					<dt>Start Height</dt><dd><input type="range" min="0" max="100" field="startHeight"/></dd>
-					<dt>End Height</dt><dd><input type="range" min="0" max="100" field="endHeight"/></dd>
-					<dt>Height Opacity</dt><dd><input type="range" min="0" max="2" field="heightOpacity"/></dd>
-				</div>
-				<div class="group" name="Center">
-					<dt>X</dt><dd><input type="range" min="-100" max="100" field="posX"/></dd>
-					<dt>Y</dt><dd><input type="range" min="-100" max="100" field="posY"/></dd>
-					<dt>Z</dt><dd><input type="range" min="-100" max="100" field="posZ"/></dd>
-					<dt>Use Center Point</dt><dd><input type="checkbox" field="usePosition"/></dd>
-				</div>
-				<div class="group" name="Color">
-					<dt>Start Color</dt><dd><input type="color" field="startColor"/></dd>
-					<dt>End Color</dt><dd><input type="color" field="endColor"/></dd>
-					<dt>Start Opacity</dt><dd><input type="range" min="0" max="1" field="startOpacity"/></dd>
-					<dt>End Opacity</dt><dd><input type="range" min="0" max="1" field="endOpacity"/></dd>
-				</div>
-				<div class="group" name="Light">
-					<dt>Light Color</dt><dd><input type="color" field="lightColor"/></dd>
-					<dt>Amount</dt><dd><input type="range" min="0" max="1" field="lightColorAmount"/></dd>
-				</div>
-				<div class="group" name="Rendering">
-					<dt>Render Mode</dt>
-						<dd><select field="renderMode">
-							<option value="BeforeTonemapping">Before Tonemapping</option>
-							<option value="AfterTonemapping">After Tonemapping</option>
-						</select></dd>
-				</div>
-
-			</dl>
-		'),this);
-		if( noise == null ) {
-			var e = ctx.properties.add(new hide.Element('
-			<div class="group" name="Noise">
-			<dl><dt></dt><dd><a class="button" href="#">Add</a></dd></dl>
-			</div>
-			'));
-			e.find("a.button").click(function(_) {
-				noise = {
-					texture : null,
-					amount : 1,
-					scale : 1,
-					speed : 1,
-					distAmount : 0.5,
-				};
-				ctx.rebuildProperties();
-			});
-		} else {
-			var e = ctx.properties.add(new hide.Element('
-			<div class="group" name="Noise">
-			<dl>
-				<dt>Texture</dt><dd><input type="texturepath" field="texture"/></dd>
-				<dt>Amount</dt><dd><input type="range" min="0" max="10" field="amount"/></dd>
-				<dt>Scale</dt><dd><input type="range" min="0" max="10" field="scale"/></dd>
-				<dt>Speed</dt><dd><input type="range" min="0" max="10" field="speed"/></dd>
-				<dt>Dist.Amount</dt><dd><input type="range" min="0" max="10" field="distAmount"/></dd>
-				<dt></dt><dd><a class="button" href="#">Remove</a></dd>
-			</dl>
-			</div>
-			'),noise);
-			e.find("a.button").click(function(_) {
-				noise = null;
-				ctx.rebuildProperties();
-			});
-		}
-		super.edit(ctx);
-	}
-	#end
-
-	static var _ = Library.register("rfx.genFog", GenFog);
-
-}

+ 0 - 144
hrt/prefab/rfx/SSR.hx

@@ -1,144 +0,0 @@
-package hrt.prefab.rfx;
-
-class SSRShader extends hxsl.Shader {
-
-	static var SRC = {
-
-		@global var camera : {
-			var inverseViewProj : Mat4;
-			var position : Vec3;
-			var viewProj : Mat4;
-			var zNear : Float;
-			var zFar : Float;
-		};
-
-		@global var depthMap:Channel;
-
-		@param var ldrMap:Sampler2D;
-
-		@param var maxRayDistance : Float;
-		@param var stepsFirstPass : Int;
-		@param var stepsSecondPass : Int;
-
-		var projectedPosition:Vec4;
-		var pixelColor:Vec4;
-		var transformedNormal : Vec3;
-		var transformedPosition : Vec3;
-
-		function reflectedRay(ray : Vec3, normal : Vec3) : Vec3 {
-			return ray - 2.0 * dot(ray, normal) * normal;
-		}
-
-		function fragment() {
-
-			var startRay = screenToUv(projectedPosition.xy / projectedPosition.w);
-
-			var camDir = (transformedPosition - camera.position).normalize();
-			var reflectedRay = camDir - 2.0 * dot(camDir, transformedNormal) * transformedNormal;
-			var endRayWS = transformedPosition + reflectedRay * maxRayDistance;
-			var endRayProjected = vec4(endRayWS, 1.0) * camera.viewProj;
-			var endRay = screenToUv(endRayProjected.xy / endRayProjected.w);
-
-			var delta = endRay - startRay;
-			var curPos = startRay + delta / stepsFirstPass;
-			var curPosWS = transformedPosition + reflectedRay * maxRayDistance / stepsFirstPass;
-			var hitFirstPass = false;
-			@unroll for (i in 0 ... stepsFirstPass) {
-
-				var projPos = vec4(curPosWS, 1.0) * camera.viewProj;
-				var distToCam = projPos.z / projPos.w;
-				if (distToCam > depthMap.get(curPos) && curPos.x <= 1.0 && curPos.x >= 0.0 && curPos.y <= 1.0 && curPos.y >= 0.0) {
-					hitFirstPass = true;
-				}
-				if (hitFirstPass == false) {
-					curPos += delta / stepsFirstPass;
-					curPosWS += reflectedRay * maxRayDistance / stepsFirstPass;
-				}
-			}
-
-			delta = delta / stepsFirstPass;
-			endRay = curPos - delta;
-			curPos -= delta / stepsSecondPass;
-			curPosWS -= reflectedRay * maxRayDistance / stepsFirstPass / stepsSecondPass;
-			var hitSecondPass = false;
-			@unroll for (i in 0 ... stepsSecondPass) {
-				var projPos = vec4(curPosWS, 1.0) * camera.viewProj;
-				var distToCam = projPos.z / projPos.w;
-				if (distToCam < depthMap.get(curPos) && curPos.x <= 1.0 && curPos.x >= 0.0 && curPos.y <= 1.0 && curPos.y >= 0.0) {
-					hitSecondPass = true;
-				}
-				if (hitSecondPass == false) {
-					curPos -= delta / stepsSecondPass;
-					curPosWS -= reflectedRay * maxRayDistance / stepsFirstPass / stepsSecondPass;
-				}
-			}
-
-			var fragmentColor = vec3(0.0, 0.0, 0.0);
-			var alpha = 0.0;
-			if (hitFirstPass && hitSecondPass) {
-				fragmentColor = ldrMap.get(curPos).rgb;
-				alpha = 1.0 - (curPosWS - transformedPosition).length() / maxRayDistance;
-			}
-
-			pixelColor.rgba *= vec4(fragmentColor, alpha);
-		}
-	}
-}
-
-class SSR extends RendererFX {
-
-	public var ssrShader : SSRShader;
-
-	@:s public var maxRayDistance : Float = 1.;
-	@:s public var steps : Int = 10;
-	@:s public var stepsFirstPass : Int = 10;
-	@:s public var stepsSecondPass : Int = 10;
-
-	function new(?parent) {
-		super(parent);
-
-		ssrShader = new SSRShader();
-	}
-
-	override function end( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {
-		if( step == Lighting ) {
-			r.mark("SSR");
-
-			var ldrCopy = r.allocTarget("ldrMapCopy", false, 0.5);
-			var ldr = r.ctx.getGlobal("ldrMap");
-			h3d.pass.Copy.run(ldr, ldrCopy);
-
-			ssrShader.ldrMap = ldrCopy;
-			ssrShader.maxRayDistance = maxRayDistance;
-			ssrShader.stepsFirstPass = stepsFirstPass;
-			ssrShader.stepsSecondPass = stepsSecondPass;
-
-			var ssrPasses : h3d.pass.PassList = r.get("ssr");
-			@:privateAccess var it = ssrPasses.current;
-			@:privateAcces while (it != null) {
-				if (@:privateAccess it.pass.getShaderByName("hrt.prefab.rfx.SSRShader") == null)
-					@:privateAccess it.pass.addShader(ssrShader);
-				it = it.next;
-			}
-
-			r.draw("ssr");
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-		<div class="group" name="SSR">
-			<dl>
-				<dt>Max ray distance</dt><dd><input type="range" min="0" max="10" field="maxRayDistance"/></dd>
-				<dt>Steps first pass</dt><dd><input type="range" min="0" max="10" step="1" field="stepsFirstPass"/></dd>
-				<dt>Steps second pass</dt><dd><input type="range" min="0" max="10" step="1" field="stepsSecondPass"/></dd>
-			</dl>
-		</div>
-		'),this);
-	}
-	#end
-
-	static var _ = Library.register("rfx.ssr", SSR);
-
-}

+ 0 - 110
hrt/prefab/rfx/Sao.hx

@@ -1,110 +0,0 @@
-package hrt.prefab.rfx;
-
-class Sao extends RendererFX {
-
-	@:s public var size : Float = 1;
-	@:s public var blur : Float;
-	@:s public var blurQuality : Float = 1;
-	@:s public var noiseScale : Float = 1;
-	@:s public var samples : Int;
-	@:s public var radius : Float;
-	@:s public var intensity : Float = 1;
-	@:s public var bias : Float;
-	@:s public var microIntensity : Float = 1;
-	@:s public var useWorldUV : Bool;
-	@:s public var noiseTexturePath: String;
-
-	var sao : h3d.pass.ScalableAO;
-	var saoBlur = new h3d.pass.Blur();
-	var saoCopy = new h3d.pass.Copy();
-
-	function new(?parent) {
-		super(parent);
-		blur = 5;
-		samples = 30;
-		radius = 1;
-		bias = 0.1;
-	}
-
-	function loadNoiseTexture(path : String, ?wrap : h3d.mat.Data.Wrap){
-		if( path != null ) {
-			var texture = hxd.res.Loader.currentInstance.load(path).toTexture();
-			if( texture == null ) return null;
-			if( wrap != null ) texture.wrap = wrap;
-			// Need mipmap for later
-			return texture;
-		}
-		return null;
-	}
-
-	override function begin( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {
-		if( step == Lighting ) {
-			r.mark("SSAO");
-			if( sao == null ) sao = new h3d.pass.ScalableAO();
-			var ctx = r.ctx;
-			var saoTex = r.allocTarget("sao",false, size);
-			var normal : hxsl.ChannelTexture = ctx.getGlobal("normalMap");
-			var depth : hxsl.ChannelTexture = ctx.getGlobal("depthMap");
-			var occlu : hxsl.ChannelTexture = ctx.getGlobal("occlusionMap");
-			ctx.engine.pushTarget(saoTex);
-			sao.shader.numSamples = samples;
-			sao.shader.sampleRadius	= radius;
-			sao.shader.intensity = intensity - 1;
-			sao.shader.bias = bias * bias;
-			sao.shader.depthTextureChannel = depth.channel;
-			sao.shader.normalTextureChannel = normal.channel;
-			sao.shader.useWorldUV = useWorldUV;
-			sao.shader.microOcclusion = occlu.texture;
-			sao.shader.microOcclusionChannel = occlu.channel;
-			sao.shader.microOcclusionIntensity = microIntensity;
-			sao.shader.noiseScale.set(noiseScale, noiseScale);
-			if( noiseTexturePath != null )
-				sao.shader.noiseTexture = loadNoiseTexture(noiseTexturePath, Repeat);
-			else
-				sao.shader.noiseTexture = h3d.mat.Texture.genNoise(128);
-			sao.apply(depth.texture,normal.texture,ctx.camera);
-			ctx.engine.popTarget();
-
-			saoBlur.radius = blur;
-			saoBlur.quality = blurQuality;
-			saoBlur.apply(ctx, saoTex);
-
-			saoCopy.pass.setColorChannel(occlu.channel);
-			saoCopy.apply(saoTex, occlu.texture);
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-		<div class="group" name="SSAO">
-			<dl>
-				<dt>Intensity</dt><dd><input type="range" min="0" max="10" field="intensity"/></dd>
-				<dt>Radius</dt><dd><input type="range" min="0" max="10" field="radius"/></dd>
-				<dt>Bias</dt><dd><input type="range" min="0" max="0.5" field="bias"/></dd>
-				<dt>Texture Size</dt><dd><input type="range" min="0" max="1" field="size"/></dd>
-				<dt>Samples</dt><dd><input type="range" min="3" max="255" field="samples" step="1"/></dd>
-				<dt>Micro Intensity</dt><dd><input type="range" min="0" max="1" field="microIntensity"/></dd>
-			</dl>
-		</div>
-		<div class="group" name="Noise">
-			<dl>
-				<dt>Scale</dt><dd><input type="range" min="0" max="1" field="noiseScale"/></dd>
-				<dt>Use World UV</dt><dd><input type="checkbox" field="useWorldUV"/></dd>
-				<dt>Texture</dt><dd><input type="texturepath" field="noiseTexturePath"/></dd>
-			</dl>
-		</div>
-		<div class="group" name="Blur">
-			<dl>
-				<dt>Size</dt><dd><input type="range" min="0" max="10" field="blur"/></dd>
-				<dt>Quality</dt><dd><input type="range" min="0" max="1" field="blurQuality"/></dd>
-			</dl>
-			</dl>
-		</div>
-		'),this);
-	}
-	#end
-
-	static var _ = Library.register("rfx.sao", Sao);
-
-}

+ 0 - 265
hrt/prefab/rfx/ScreenShaderGraph.hx

@@ -1,265 +0,0 @@
-package hrt.prefab.rfx;
-
-import hrt.prefab.rfx.RendererFX;
-import hrt.prefab.Library;
-import hxd.Math;
-
-private class GraphShader extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-		@param var source : Sampler2D;
-
-		function fragment() {
-			pixelColor = source.get(calculatedUV);
-		}
-	}
-}
-class ScreenShaderGraph extends RendererFX {
-
-	var shaderPass = new h3d.pass.ScreenFx(new GraphShader());
-	var shaderGraph : hrt.shgraph.ShaderGraph;
-	var shaderDef : hrt.prefab.ContextShared.ShaderDef;
-	var shader : hxsl.DynamicShader;
-
-	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		if( !checkEnabled() ) return;
-		if( step == AfterTonemapping ) {
-			r.mark("ScreenShaderGraph");
-			if (shader != null) {
-				var ctx = r.ctx;
-				var target = r.allocTarget("ppTarget", false);
-				shaderPass.shader.source = ctx.getGlobal("ldrMap");
-
-				ctx.engine.pushTarget(target);
-				shaderPass.render();
-				ctx.engine.popTarget();
-
-				ctx.setGlobal("ldrMap", target);
-				r.setTarget(target);
-			}
-		}
-		if( step == BeforeTonemapping ) {
-			r.mark("ScreenShaderGraph");
-			if (shader != null) {
-				var ctx = r.ctx;
-				var target = r.allocTarget("ppTarget", false);
-				shaderPass.shader.source = ctx.getGlobal("hdrMap");
-
-				ctx.engine.pushTarget(target);
-				shaderPass.render();
-				ctx.engine.popTarget();
-
-				ctx.setGlobal("hdrMap", target);
-				r.setTarget(target);
-			}
-		}
-	}
-
-	override function load( obj : Dynamic ) {
-		loadSerializedFields(obj);
-	}
-
-	public function loadShaderDef() {
-		shaderDef = shaderGraph.compile();
-		if(shaderDef == null)
-			return;
-
-		#if editor
-		for( v in shaderDef.inits ) {
-			if (props == null)
-				props = {};
-			if(!Reflect.hasField(props, v.variable.name)) {
-				Reflect.setField(props, v.variable.name, v.value);
-			}
-		}
-		#end
-	}
-
-	function getShaderDefinition():hxsl.SharedShader {
-		if( shaderDef == null )
-			loadShaderDef();
-		return shaderDef == null ? null : shaderDef.shader;
-	}
-
-	function setShaderParam(shader:hxsl.Shader, v:hxsl.Ast.TVar, value:Dynamic) {
-		cast(shader,hxsl.DynamicShader).setParamValue(v, value);
-	}
-
-	function syncShaderVars() {
-		for(v in shaderDef.shader.data.vars) {
-			if(v.kind != Param)
-				continue;
-			var val : Dynamic = Reflect.field(props, v.name);
-			switch(v.type) {
-			case TVec(_, VFloat):
-				if(val != null) {
-					if( Std.is(val,Int) ) {
-						var v = new h3d.Vector();
-						v.setColor(val);
-						val = v;
-					} else
-						val = h3d.Vector.fromArray(val);
-				} else
-					val = new h3d.Vector();
-			case TSampler2D:
-				if( val != null )
-					val = hxd.res.Loader.currentInstance.load(val).toTexture();
-				else {
-					var childNoise = getOpt(hrt.prefab.l2d.NoiseGenerator, v.name);
-					if(childNoise != null)
-						val = childNoise.toTexture();
-				}
-			default:
-			}
-			if(val == null)
-				continue;
-			setShaderParam(shader,v,val);
-		}
-	}
-
-	function makeShader() {
-		if( getShaderDefinition() == null )
-			return null;
-		var dshader = new hxsl.DynamicShader(shaderDef.shader);
-		for( v in shaderDef.inits ) {
-			#if !hscript
-			throw "hscript required";
-			#else
-			dshader.hscriptSet(v.variable.name, v.value);
-			#end
-		}
-		shader = dshader;
-		syncShaderVars();
-		shaderPass.addShader(shader);
-		return shader;
-	}
-
-	override function makeInstance(ctx: Context) : Context {
-		ctx = super.makeInstance(ctx);
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		var p = resolveRef(ctx.shared);
-		if(p == null)
-			return;
-		if (shader == null)
-			shader = makeShader();
-		else
-			syncShaderVars();
-	}
-
-	public function resolveRef(shared : hrt.prefab.ContextShared) {
-		if(shaderGraph != null)
-			return shaderGraph;
-		if(source == null)
-			return null;
-
-		#if editor
-		shaderGraph = new hrt.shgraph.ShaderGraph(source);
-		#else
-		return null;
-		#end
-		return shaderGraph;
-	}
-
-	function makeShaderParam( v : hxsl.Ast.TVar ) : hrt.prefab.Props.PropType {
-		var min : Null<Float> = null, max : Null<Float> = null;
-		if( v.qualifiers != null )
-			for( q in v.qualifiers )
-				switch( q ) {
-				case Range(rmin, rmax): min = rmin; max = rmax;
-				default:
-				}
-		return switch( v.type ) {
-		case TInt:
-			PInt(min == null ? null : Std.int(min), max == null ? null : Std.int(max));
-		case TFloat:
-			PFloat(min != null ? min : 0.0, max != null ? max : 1.0);
-		case TBool:
-			PBool;
-		case TSampler2D:
-			PTexture;
-		case TVec(n, VFloat):
-			PVec(n);
-		default:
-			PUnsupported(hxsl.Ast.Tools.toString(v.type));
-		}
-	}
-
-	#if editor
-	override function edit( ectx : hide.prefab.EditContext ) {
-		var element = new hide.Element('
-			<div class="group" name="Reference">
-			<dl>
-				<dt>Reference</dt><dd><input type="fileselect" extensions="shgraph" field="source"/></dd>
-			</dl>
-			</div>');
-
-		function updateProps() {
-			var input = element.find("input");
-			updateInstance(ectx.rootContext);
-			var found = shaderGraph != null;
-			input.toggleClass("error", !found);
-		}
-		updateProps();
-
-		ectx.properties.add(element, this, function(pname) {
-			ectx.onChange(this, pname);
-			if(pname == "source") {
-				shaderGraph = null;
-				shaderPass.removeShader(shader);
-				shader = null;
-				if (shaderDef != null) {
-					for(v in shaderDef.inits) {
-						if (Reflect.hasField(props, v.variable.name))
-							Reflect.deleteField(props, v.variable.name);
-					}
-					shaderDef = null;
-				}
-
-				updateProps();
-				ectx.properties.clear();
-				edit(ectx);
-			}
-		});
-
-
-		super.edit(ectx);
-		if (shaderGraph == null)
-			return;
-		getShaderDefinition();
-
-		var group = new hide.Element('<div class="group" name="Shader"></div>');
-		var props = [];
-		for(v in shaderDef.shader.data.vars) {
-			if( v.kind != Param )
-				continue;
-			if( v.qualifiers != null && v.qualifiers.contains(Ignore) )
-				continue;
-			var prop = makeShaderParam(v);
-			if( prop == null ) continue;
-			props.push({name: v.name, t: prop, def: Reflect.field(this.props, v.name)});
-		}
-		group.append(hide.comp.PropsEditor.makePropsList(props));
-		ectx.properties.add(group, this.props, function(pname) {
-			ectx.onChange(this, pname);
-			updateInstance(ectx.rootContext, pname);
-
-		});
-
-		var btn = new hide.Element("<input type='submit' style='width: 100%; margin-top: 10px;' value='Open Shader Graph' />");
-		btn.on("click", function() {
- 			ectx.ide.openFile(source);
-		});
-
-		ectx.properties.add(btn, this, function(pname) {
-			ectx.onChange(this, pname);
-		});
-	}
-	#end
-
-	static var _ = Library.register("rfx.ScreenShaderGraph", ScreenShaderGraph);
-
-}

+ 0 - 61
hrt/prefab/rfx/Sharpen.hx

@@ -1,61 +0,0 @@
-package hrt.prefab.rfx;
-
-class SharpenShader extends h3d.shader.ScreenShader {
-	static var SRC = {
-
-		@param var source : Sampler2D;
-		@param var intensity : Float;
-		@param var resolution : Vec2;
-
-		function fragment() {
-
-			var offset = 1.0 / resolution;
-			var center = texture(source, calculatedUV);
-			var sum = vec4(0);
-			sum += texture(source, calculatedUV + vec2(0, offset.y));
-			sum += texture(source, calculatedUV + vec2(-offset.x, 0));
-			sum += texture(source, calculatedUV + vec2(offset.x, 0));
-			sum += texture(source, calculatedUV + vec2(0, -offset.y) );
-
-			// Return edge detection
-			pixelColor = (1.0 + 4.0 * intensity) * center - intensity * sum;
-		}
-	}
-}
-
-class Sharpen extends RendererFX {
-
-	var sharpenPass = new h3d.pass.ScreenFx(new SharpenShader());
-	@:s public var intensity : Float;
-
-	override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) {
-		if( step == AfterTonemapping ) {
-			r.mark("Sharpen");
-			var sharpen = r.allocTarget("sharpen", true, 1.0, RGBA);
-			var ctx = r.ctx;
-			ctx.engine.pushTarget(sharpen);
-			sharpenPass.shader.source = ctx.getGlobal("ldrMap");
-			sharpenPass.shader.intensity = intensity;
-			sharpenPass.shader.resolution.set(ctx.engine.width, ctx.engine.height);
-			sharpenPass.render();
-			ctx.engine.popTarget();
-			ctx.setGlobal("ldrMap", sharpen);
-			r.setTarget(sharpen);
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-			<div class="group" name="Sharpen">
-				<dl>
-					<dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
-				</dl>
-			</div>
-		'),this);
-	}
-	#end
-
-	static var _ = Library.register("rfx.sharpen", Sharpen);
-
-}

+ 0 - 192
hrt/prefab/rfx/TemporalBloom.hx

@@ -1,192 +0,0 @@
-package hrt.prefab.rfx;
-
-import hxsl.Eval;
-import h3d.pass.Copy;
-
-class DualFilterDown extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var source : Sampler2D;
-		@param var halfPixel : Vec2;
-
-		function fragment() {
-			var sum = vec3(0,0,0);
-			sum += texture(source, calculatedUV).rgb * 4.0;
-			sum += texture(source, calculatedUV + halfPixel.xy).rgb;
-			sum += texture(source, calculatedUV - halfPixel.xy).rgb;
-			sum += texture(source, calculatedUV + vec2(halfPixel.x, -halfPixel.y)).rgb;
-			sum += texture(source, calculatedUV - vec2(halfPixel.x, -halfPixel.y)).rgb;
-			pixelColor.rgb = sum / 8.0;
-		}
-	};
-}
-
-class DualFilterUp extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var source : Sampler2D;
-		@param var halfPixel : Vec2;
-
-		function fragment() {
-			var sum = vec3(0,0,0);
-			sum += texture(source, calculatedUV + vec2(-halfPixel.x * 2.0, 0.0)).rgb;
-			sum += texture(source, calculatedUV + vec2(-halfPixel.x, halfPixel.y)).rgb * 2.0;
-			sum += texture(source, calculatedUV + vec2(0.0, halfPixel.y * 2.0)).rgb;
-			sum += texture(source, calculatedUV + vec2(halfPixel.x, halfPixel.y)).rgb * 2.0;
-			sum += texture(source, calculatedUV + vec2(halfPixel.x * 2.0, 0.0)).rgb;
-			sum += texture(source, calculatedUV + vec2(halfPixel.x, -halfPixel.y)).rgb * 2.0;
-			sum += texture(source, calculatedUV + vec2(0.0, -halfPixel.y * 2.0)).rgb;
-			sum += texture(source, calculatedUV + vec2(-halfPixel.x, -halfPixel.y)).rgb * 2.0;
-			pixelColor.rgb = sum / 12.0;
-		}
-	};
-}
-
-class Threshold extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var hdr : Sampler2D;
-		@param var threshold : Float;
-        @param var intensity : Float;
-		@param var maxIntensity : Float;
-
-		@const var USE_TEMPORAL_FILTER : Bool;
-		@const var PREVENT_GHOSTING : Bool;
-		@param var cur : Sampler2D;
-		@param var prev : Sampler2D;
-		@param var prevCamMat : Mat4;
-		@param var cameraInverseViewProj : Mat4;
-		@param var strength : Float;
-
-		function fragment() {
-			var curVal = max(hdr.get(calculatedUV).rgb - threshold, 0.0) * intensity;
-			pixelColor.rgb = min(curVal, maxIntensity);
-
-			if( USE_TEMPORAL_FILTER ) {
-				var pixelPos = vec4(uvToScreen(calculatedUV), 1, 1) * cameraInverseViewProj;
-				pixelPos.xyz /= pixelPos.w;
-				var prevPos = vec4(pixelPos.xyz, 1.0) * prevCamMat;
-				prevPos.xyz /= prevPos.w;
-				var prevUV = screenToUv(prevPos.xy);
-				var blendStrengh = strength * ceil(1 - max(abs(prevPos.x), abs(prevPos.y)));
-				var prevVal = prev.get(prevUV).rgb;
-				pixelColor.rgb = mix(curVal, prevVal, blendStrengh);
-			}
-		}
-	};
-}
-
-class TemporalBloom extends RendererFX {
-
-	@:s public var size : Float;
-	@:s public var downScaleCount : Int;
-	@:s public var threshold : Float;
-    @:s public var intensity : Float = 1;
-	@:s public var maxValue : Float;
-	@:s public var useTemporalFilter : Bool = true;
-	@:s public var temporalStrength : Float;
-
-	var thresholdPass = new h3d.pass.ScreenFx(new Threshold());
-	var downScale = new h3d.pass.ScreenFx(new DualFilterDown());
-	var upScale = new h3d.pass.ScreenFx(new DualFilterUp());
-
-	var prevResult : h3d.mat.Texture;
-	var prevCamMat : h3d.Matrix;
-
-	var tonemap = new Bloom.BloomTonemap();
-
-	function new(?parent) {
-		super(parent);
-		size = 0.5;
-		downScaleCount = 5;
-		threshold = 0.5;
-		maxValue = 100.0;
-		prevCamMat = new h3d.Matrix();
-		prevCamMat.identity();
-	}
-
-	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		if( step == BeforeTonemapping ) {
-			r.mark("TBloom");
-			var ctx = r.ctx;
-
-			var source = r.allocTarget("source", false, size, RGBA16F);
-			ctx.engine.pushTarget(source);
-			thresholdPass.shader.hdr = ctx.getGlobal("hdrMap");
-			thresholdPass.shader.threshold = threshold;
-            thresholdPass.shader.intensity = intensity;
-			thresholdPass.shader.maxIntensity = maxValue;
-			if( useTemporalFilter ) {
-				thresholdPass.shader.USE_TEMPORAL_FILTER = true;
-				prevResult = r.allocTarget("pr", false, size, RGBA16F);
-				thresholdPass.shader.prev = prevResult;
-				thresholdPass.shader.prevCamMat.load(prevCamMat);
-				thresholdPass.shader.cameraInverseViewProj.load(ctx.camera.getInverseViewProj());
-				thresholdPass.shader.strength = temporalStrength;
-				thresholdPass.render();
-				ctx.engine.popTarget();
-				Copy.run(source, prevResult);
-				prevCamMat.load(ctx.camera.m);
-			}
-			else {
-				thresholdPass.shader.USE_TEMPORAL_FILTER = false;
-				thresholdPass.render();
-				ctx.engine.popTarget();
-			}
-
-			var curSize = size;
-			var curTarget : h3d.mat.Texture = source;
-			for( i in 0 ... downScaleCount ) {
-				curSize *= 0.5;
-				var prevTarget = curTarget;
-				curTarget = r.allocTarget("dso_"+i, false, curSize, RGBA16F);
-				ctx.engine.pushTarget(curTarget);
-				downScale.shader.source = prevTarget;
-				downScale.shader.halfPixel.set(1.0 / prevTarget.width, 1.0 / prevTarget.height);
-				downScale.render();
-				ctx.engine.popTarget();
-			}
-			for( i in 0 ... downScaleCount ) {
-				curSize *= 2.0;
-				var prevTarget = curTarget;
-				curTarget = r.allocTarget("uso_"+i, false, curSize, RGBA16F);
-				ctx.engine.pushTarget(curTarget);
-				upScale.shader.source = prevTarget;
-				upScale.shader.halfPixel.set(1.0 / prevTarget.width, 1.0 / prevTarget.height);
-				upScale.render();
-				ctx.engine.popTarget();
-			}
-
-			tonemap.bloomTexture = curTarget;
-			r.addShader(tonemap);
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-		<div class="group" name="Bloom">
-			<dl>
-				<dt>Threshold</dt><dd><input type="range" min="0" max="1" field="threshold"/></dd>
-				<dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
-				<dt>Max</dt><dd><input type="range" min="0" max="100" field="maxValue"/></dd>
-				<dt>Texture Size</dt><dd><input type="range" min="0" max="1" field="size"/></dd>
-				<dt>DownScale/UpScale Count</dt><dd><input type="range" min="1" max="5" field="downScaleCount" step="1"/></dd>
-			</dl>
-		</div>
-		<div class="group" name="Temporal Filtering">
-			<dl>
-			<dt>Enable</dt><dd><input type="checkbox" field="useTemporalFilter"/></dd>
-			<dt>Strength</dt><dd><input type="range" min="0" max="1" field="temporalStrength"/></dd>
-			</dl>
-		</div>
-		'),this);
-	}
-	#end
-
-	static var _ = Library.register("rfx.temporalbloom", TemporalBloom);
-
-}

+ 0 - 247
hrt/prefab/rfx/TemporalFiltering.hx

@@ -1,247 +0,0 @@
-package hrt.prefab.rfx;
-
-class TemporalFilteringShader extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@const var VARIANCE_CLIPPING : Bool;
-		@const var YCOCG : Bool;
-		@const var UNJITTER : Bool;
-
-		@param var prevFrame : Sampler2D;
-		@param var curFrame : Sampler2D;
-		@param var resolution : Vec2;
-		@param var amount : Float;
-		@param var jitterUV : Vec2;
-		@param var prevJitterUV : Vec2;
-
-		@param var prevCamMat : Mat4;
-		@param var cameraInverseViewProj : Mat4;
-
-		@const var PACKED_DEPTH : Bool;
-		@param var depthChannel : Channel;
-		@param var depthTexture : Sampler2D;
-
-		function rgb2ycocg( rgb : Vec3 ) : Vec3 {
-			if( YCOCG ) {
-				var co = rgb.r - rgb.b;
-				var t = rgb.b + co / 2.0;
-				var cg = rgb.g - t;
-				var y = t + cg / 2.0;
-				return vec3(y, co, cg);
-			}
-			else
-				return rgb;
-		}
-
-		function ycocg2rgb( ycocg : Vec3 ) : Vec3 {
-			if( YCOCG ) {
-				var t = ycocg.r - ycocg.b / 2.0;
-				var g = ycocg.b + t;
-				var b = t - ycocg.g / 2.0;
-				var r = ycocg.g + b;
-				return vec3(r, g, b);
-			}
-			else
-				return ycocg;
-		}
-
-		function clipToAABB( cOld : Vec3, cNew : Vec3, centre : Vec3, halfSize : Vec3 ) : Vec3 {
-			var a = abs(cOld - centre);
-			if( a.r <= halfSize.r && a.g <= halfSize.g && a.b <= halfSize.b ) {
-				return cOld;
-			}
-			else {
-				var dir = (cNew - cOld);
-				var near = centre - sign(dir) * halfSize;
-				var tAll = (near - cOld) / dir;
-				var t = 1.0;
-				if( tAll.x >= 0.0 && tAll.x < t ) t = tAll.x;
-				if( tAll.y >= 0.0 && tAll.y < t ) t = tAll.y;
-				if( tAll.z >= 0.0 && tAll.z < t ) t = tAll.z;
-
-				if( t >= 1.0 ) {
-					return cOld;
-				}
-				else
-					return cOld + dir * t;
-			}
-		}
-
-		var isSky : Bool;
-
-		function getPixelPosition( uv : Vec2 ) : Vec3 {
-			var d = PACKED_DEPTH ? unpack(depthTexture.get(uv)) : depthChannel.get(uv).r;
-			var tmp = vec4(uvToScreen(uv), d, 1) * cameraInverseViewProj;
-			tmp.xyz /= tmp.w;
-			isSky = d <= 0;
-			return tmp.xyz;
-		}
-
-		function fragment() {
-			var unJitteredUV = calculatedUV;
-			if( UNJITTER )
-				unJitteredUV -= jitterUV * 0.5;
-
-			var curPos = getPixelPosition(calculatedUV);
-			var prevPos = vec4(curPos, 1.0) * prevCamMat;
-			prevPos.xyz /= prevPos.w;
-
-			var curColor = curFrame.get(unJitteredUV).rgb;
-			var prevUV = screenToUv(prevPos.xy);
-			var prevColor = prevFrame.get(prevUV).rgb;
-
-			// Neighborhood clipping [MALAN 2012][KARIS 2014]
-			if( VARIANCE_CLIPPING ) {
-				var offsets : Array<Vec2, 4> = [ vec2(-1.0,0.0), vec2(1.0,0.0), vec2(0.0,-1.0), vec2(0.0, 1.0) ];
-				var m1 = rgb2ycocg(curColor);
-				var m2 = m1 * m1;
-				for( i in 0 ... 4 ) {
-					var c = rgb2ycocg(curFrame.getLod(unJitteredUV + (offsets[i] / resolution), 0).rgb);
-					m1 += c;
-					m2 += c * c;
-				}
-				m1 /= 5.0;
-				m2 = sqrt(m2 / 5.0 - m1 * m1);
-				prevColor = max(vec3(0.0), ycocg2rgb(clipToAABB(rgb2ycocg(prevColor), rgb2ycocg(curColor), m1, m2)));
-			}
-			pixelColor.rgb = isSky ? curColor : mix(curColor, prevColor, amount);
-			pixelColor.a = 1.0;
-		}
-	}
-}
-
-class TemporalFiltering extends hrt.prefab.rfx.RendererFX {
-
-	@:s public var amount : Float;
-	@:s public var varianceClipping : Bool = true;
-	@:s public var ycocg : Bool = true;
-	@:s public var unjitter : Bool = true;
-	@:s public var jitterPattern : FrustumJitter.Pattern = Still;
-	@:s public var jitterScale : Float = 1;
-	@:s public var renderMode : String = "AfterTonemapping";
-
-	public var frustumJitter = new FrustumJitter();
-	public var pass = new h3d.pass.ScreenFx(new TemporalFilteringShader());
-	public var jitterMat = new h3d.Matrix();
-	var curMatNoJitter = new h3d.Matrix();
-
-	var tmp = new h3d.Matrix();
-	public function getMatrixJittered( camera : h3d.Camera ) : h3d.Matrix {
-		tmp.identity();
-		tmp.multiply(camera.mproj, jitterMat);
-		tmp.multiply(camera.mcam, tmp);
-		return tmp;
-	}
-
-	override function begin( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) {
-		if( step == MainDraw ) {
-			var ctx = r.ctx;
-			var s = pass.shader;
-
-			frustumJitter.curPattern = jitterPattern;
-			frustumJitter.patternScale = jitterScale;
-			frustumJitter.update();
-
-			// Translation Matrix for Jittering
-			jitterMat.identity();
-			jitterMat.translate(frustumJitter.curSample.x / ctx.engine.width, frustumJitter.curSample.y / ctx.engine.height);
-
-			s.prevJitterUV.set(-frustumJitter.prevSample.x / ctx.engine.width, frustumJitter.prevSample.y / ctx.engine.height);
-			s.jitterUV.set(-frustumJitter.curSample.x / ctx.engine.width, frustumJitter.curSample.y / ctx.engine.height);
-
-			curMatNoJitter.load(ctx.camera.m);
-			ctx.camera.m.load(getMatrixJittered(ctx.camera));
-			@:privateAccess ctx.camera.needInv = true;
-			s.cameraInverseViewProj.initInverse(curMatNoJitter);
-		}
-	}
-
-	override function end( r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step ) {
-		var ctx = r.ctx;
-		if( ( step == AfterTonemapping && renderMode == "AfterTonemapping") || (step == BeforeTonemapping && renderMode == "BeforeTonemapping" ) ) {
-			r.mark("TemporalFiltering");
-			var output : h3d.mat.Texture = ctx.engine.getCurrentTarget();
-			var depthMap : Dynamic = ctx.getGlobal("depthMap");
-			var prevFrame = r.allocTarget("prevFrame", false, 1.0, output.format);
-			var curFrame = r.allocTarget("curFrame", false, 1.0, output.format);
-			h3d.pass.Copy.run(output, curFrame);
-
-			var s = pass.shader;
-			s.curFrame = curFrame;
-			s.prevFrame = prevFrame;
-			s.amount = amount;
-
-			s.PACKED_DEPTH = depthMap.packed != null && depthMap.packed == true;
-			if( s.PACKED_DEPTH ) {
-				s.depthTexture = depthMap.texture;
-			}
-			else {
-				s.depthChannel = depthMap.texture;
-				s.depthChannelChannel = depthMap.channel == null ? hxsl.Channel.R : depthMap.channel;
-			}
-
-			s.resolution.set(output.width, output.height);
-			s.VARIANCE_CLIPPING = varianceClipping;
-			s.YCOCG = ycocg;
-			s.UNJITTER = unjitter;
-
-			r.setTarget(output);
-			pass.render();
-
-			h3d.pass.Copy.run(output, prevFrame);
-			s.prevCamMat.load(curMatNoJitter);
-
-			// Remove Jitter for effects post TAA
-			r.ctx.camera.update();
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-			<dl>
-				<dt>Amount</dt><dd><input type="range" min="0" max="1" field="amount"/></dd>
-				<dt>Variance Clipping</dt><dd><input type="checkbox" field="varianceClipping"/></dd>
-				<dt>Ycocg</dt><dd><input type="checkbox" field="ycocg"/></dd>
-				<dt>Unjitter</dt><dd><input type="checkbox" field="unjitter"/></dd>
-				<div class="group" name="Jitter">
-					<dt>Pattern</dt>
-						<dd>
-							<select field="jitterPattern">
-								<option value="Still">Still</option>
-								<option value="Uniform2">Uniform2</option>
-								<option value="Uniform4">Uniform4</option>
-								<option value="Uniform4_Helix">Uniform4 Helix</option>
-								<option value="Uniform4_DoubleHelix">Uniform4 DoubleHelix</option>
-								<option value="SkewButterfly">SkewButterfly</option>
-								<option value="Rotated4">Rotated4</option>
-								<option value="Rotated4_Helix">Rotated4 Helix</option>
-								<option value="Rotated4_Helix2">Rotated4 Helix2</option>
-								<option value="Poisson10">Poisson10</option>
-								<option value="Pentagram">Pentagram</option>
-								<option value="Halton_2_3_x8">Halton_2_3_x8</option>
-								<option value="Halton_2_3_x16">Halton_2_3_x16</option>
-								<option value="Halton_2_3_x32">Halton_2_3_x32</option>
-								<option value="Halton_2_3_x256">Halton_2_3_x256</option>
-								<option value="MotionPerp2">MotionPerp2</option>
-								<option value="MotionVPerp2">MotionVPerp2</option>
-							</select>
-						</dd>
-					<dt>Scale</dt><dd><input type="range" min="0" max="2" field="jitterScale"/></dd>
-				</div>
-				<div class="group" name="Rendering">
-					<dt>Render Mode</dt>
-						<dd><select field="renderMode">
-							<option value="BeforeTonemapping">Before Tonemapping</option>
-							<option value="AfterTonemapping">After Tonemapping</option>
-						</select></dd>
-				</div>
-			</dl>
-		'),this);
-	}
-	#end
-
-	static var _ = hrt.prefab.Library.register("rfx.temporalFiltering", TemporalFiltering);
-
-}

+ 0 - 67
hrt/prefab/rfx/Vignetting.hx

@@ -1,67 +0,0 @@
-package hrt.prefab.rfx;
-
-import hrt.prefab.rfx.RendererFX;
-import hrt.prefab.Library;
-import hxd.Math;
-
-class VignettingShader extends h3d.shader.ScreenShader {
-	static var SRC = {
-
-		@param var color : Vec4;
-		@param var radius : Float;
-		@param var softness : Float;
-
-		function fragment() {
-			var pos = uvToScreen(calculatedUV);
-			var dist = length(pos);
-			var intensity = 1 - smoothstep(radius, radius-softness, dist);
-			var alpha = color.a * intensity;
-			pixelColor = vec4(color.rgb, alpha);
-		}
-	}
-}
-
-class Vignetting extends RendererFX {
-
-	var vignettingPass = new h3d.pass.ScreenFx(new VignettingShader());
-
-	@:s public var color : Int = 0xFFFFFF;
-	@:s public var alpha : Float = 1;
-	@:s public var radius : Float = 1;
-	@:s public var softness : Float;
-
-	function sync( r : h3d.scene.Renderer ) {
-		var ctx = r.ctx;
-		vignettingPass.shader.color.setColor(color);
-		vignettingPass.shader.color.a = alpha;
-		vignettingPass.shader.radius = radius;
-		vignettingPass.shader.softness = softness;
-		vignettingPass.pass.setBlendMode(Alpha);
-	}
-
-	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
-		if( !checkEnabled() ) return;
-		if( step == AfterTonemapping ) {
-			r.mark("Vignetting");
-			sync(r);
-			vignettingPass.render();
-		}
-	}
-
-	#if editor
-	override function edit( ctx : hide.prefab.EditContext ) {
-		ctx.properties.add(new hide.Element('
-			<dl>
-				<dt>Color</dt><dd><input type="color" field="color"/></dd>
-				<dt>Alpha</dt><dd><input type="range" min="0" max="1" field="alpha"/></dd>
-				<dt>Radius</dt><dd><input type="range" min="0" max="1" field="radius"/></dd>
-				<dt>Softness</dt><dd><input type="range" min="0" max="1" field="softness"/></dd>
-			</dl>
-		'),this);
-		super.edit(ctx);
-	}
-	#end
-
-	static var _ = Library.register("rfx.Vignetting", Vignetting);
-
-}

+ 0 - 35
hrt/prefab/terrain/PackWeight.hx

@@ -1,35 +0,0 @@
-package hrt.prefab.terrain;
-
-class PackWeight extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var indexMap : Sampler2D;
-		@param var weightTextures : Sampler2DArray;
-		@param var weightCount : Int;
-		@param var mask : Array<Vec4, 4>;
-
-		function fragment() {
-			pixelColor = vec4(0,0,0,1);
-			var curMaskIndex = 0;
-			for(i in 0 ... weightCount){
-				var w = weightTextures.get(vec3(calculatedUV, i)).r;
-				if( w > 0 && curMaskIndex < 3){
-					pixelColor += mask[curMaskIndex] * w;
-					curMaskIndex++;
-				}
-			}
-
-			/*var texIndex = indexMap.get(calculatedUV).rgb;
-			var i1 : Int = int(texIndex.r * 255);
-			var i2 : Int = int(texIndex.g * 255);
-			var i3 : Int = int(texIndex.b * 255);
-			pixelColor = vec4(weightTextures.get(vec3(calculatedUV, i1)).r, weightTextures.get(vec3(calculatedUV, i2)).r, weightTextures.get(vec3(calculatedUV, i3)).r, 0);*/
-		}
-	}
-
-	public function new(){
-		super();
-		mask = [new h3d.Vector(1,0,0,0), new h3d.Vector(0,1,0,0), new h3d.Vector(0,0,1,0), new h3d.Vector(0,0,0,1)];
-	}
-}

+ 0 - 67
hrt/prefab/terrain/Surface.hx

@@ -1,67 +0,0 @@
-package hrt.prefab.terrain;
-
-class Surface {
-	public var albedo : h3d.mat.Texture;
-	public var normal : h3d.mat.Texture;
-	public var pbr : h3d.mat.Texture;
-	public var tilling = 1.0;
-	public var offset : h3d.Vector;
-	public var angle = 0.0;
-	public var minHeight = 0.0;
-	public var maxHeight = 1.0;
-
-	public function new( ?albedo : h3d.mat.Texture, ?normal : h3d.mat.Texture, ?pbr : h3d.mat.Texture ) {
-		this.albedo = albedo;
-		this.normal = normal;
-		this.pbr = pbr;
-		this.offset = new h3d.Vector(0);
-	}
-
-	public function clone() : Surface {
-		var o = new Surface(albedo, normal, pbr);
-		o.tilling = tilling;
-		o.offset.load(offset);
-		o.angle = angle;
-		o.minHeight = minHeight;
-		o.maxHeight = maxHeight;
-		return o;
-	}
-
-	public function dispose() {
-	}
-}
-
-class SurfaceArray {
-	public var albedo : h3d.mat.TextureArray;
-	public var normal : h3d.mat.TextureArray;
-	public var pbr : h3d.mat.TextureArray;
-	public var surfaceCount : Int;
-	public var params : Array<h3d.Vector> = [];
-	public var secondParams : Array<h3d.Vector> = [];
-
-	public function new( count, res ) {
-		surfaceCount = count;
-		if( count > 0 && res > 0 ) {
-			albedo = new h3d.mat.TextureArray(res, res, count, [Target], RGBA);
-			normal = new h3d.mat.TextureArray(res, res, count, [Target], RGBA);
-			pbr = new h3d.mat.TextureArray(res, res, count, [Target], RGBA);
-			albedo.wrap = Repeat;
-			albedo.preventAutoDispose();
-			normal.wrap = Repeat;
-			normal.preventAutoDispose();
-			pbr.wrap = Repeat;
-			pbr.preventAutoDispose();
-		}
-	}
-
-	public function clone() : SurfaceArray {
-		var o = new SurfaceArray(albedo.layerCount, albedo.width);
-		return o;
-	}
-
-	public function dispose() {
-		if( albedo != null ) albedo.dispose();
-		if( normal != null ) normal.dispose();
-		if( pbr != null ) pbr.dispose();
-	}
-}

+ 0 - 626
hrt/prefab/terrain/Terrain.hx

@@ -1,626 +0,0 @@
-package hrt.prefab.terrain;
-using Lambda;
-
-typedef SurfaceProps = {
-	albedo : String,
-	normal : String,
-	pbr : String,
-	tilling : Float,
-	angle : Float,
-	offsetX : Float,
-	offsetY : Float,
-	minHeight : Float,
-	maxHeight : Float,
-};
-
-@:access(hrt.prefab.terrain.TerrainMesh)
-@:access(hrt.prefab.terrain.Tile)
-class Terrain extends Object3D {
-
-	public var terrain : TerrainMesh;
-
-	// Tile Param
-	@:s public var tileSizeX : Float = 64.0;
-	@:s public var tileSizeY : Float = 64.0;
-	@:s public var vertexPerMeter : Float = 1.0;
-	// Texture Param
-	@:s public var weightMapPixelPerMeter : Float = 1.0;
-	// Parallax Param
-	@:s public var parallaxAmount = 0.0;
-	@:s public var parallaxMinStep : Int = 1;
-	@:s public var parallaxMaxStep : Int = 16;
-	// Blend Param
-	@:s public var heightBlendStrength : Float = 0.0;
-	@:s public var blendSharpness : Float = 0.0;
-	// Shadows Param
-	@:s public var castShadows = false;
-	// Data for binary save/load
-	@:c var surfaceCount = 0;
-	@:c var surfaceSize = 0;
-	// Utility
-	@:c var tmpSurfacesProps : Array<SurfaceProps> = [];
-	var unpackWeight = new h3d.pass.ScreenFx(new UnpackWeight());
-	var modified = false;
-
-	#if editor
-	var packWeight = new h3d.pass.ScreenFx(new PackWeight());
-	var editor : hide.prefab.terrain.TerrainEditor;
-	@:s public var showChecker = false;
-	@:s public var autoCreateTile = false;
-	@:s public var brushOpacity : Float = 1.0;
-	var myContext : Context;
-	#end
-
-	public function new( ?parent ) {
-		super(parent);
-		type = "terrain";
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		if( obj.surfaces != null ) tmpSurfacesProps = obj.surfaces;
-		surfaceCount = obj.surfaceCount == null ? 0 : obj.surfaceCount;
-		surfaceSize = obj.surfaceSize == null ? 0 : obj.surfaceSize;
-	}
-
-	override function save() {
-		var obj : Dynamic = super.save();
-		if( terrain != null && terrain.surfaces != null ) {
-
-			obj.surfaceCount = terrain.surfaces.length == 0 ? 0 : terrain.surfaceArray.surfaceCount;
-			obj.surfaceSize = terrain.surfaces.length == 0 ? 0 : terrain.surfaceArray.albedo.width;
-
-			var surfacesProps : Array<SurfaceProps> = [];
-			for(surface in terrain.surfaces){
-				var surfaceProps : SurfaceProps =
-				{
-					albedo : surface.albedo.name,
-					normal : surface.normal.name,
-					pbr : surface.pbr.name,
-					tilling : surface.tilling,
-					angle : surface.angle,
-					offsetX : surface.offset.x,
-					offsetY : surface.offset.y,
-					minHeight : surface.minHeight,
-					maxHeight : surface.maxHeight,
-				};
-				surfacesProps.push(surfaceProps);
-			}
-			obj.surfaces = surfacesProps;
-		}
-		else {
-			// When cloning
-			obj.surfaces = tmpSurfacesProps;
-			obj.surfaceCount = tmpSurfacesProps.length;
-		}
-
-		#if editor
-		if( terrain != null ) obj.showChecker = terrain.showChecker;
-		if( modified ) {
-			modified = false;
-			saveTextures(myContext);
-		}
-		#end
-
-		return obj;
-	}
-
-	override function localRayIntersection(ctx:Context, ray:h3d.col.Ray):Float {
-		if( ray.lz > 0 )
-			return -1; // only from top
-		if( ray.lx == 0 && ray.ly == 0 ) {
-			var z = terrain.getLocalHeight(ray.px, ray.py);
-			if( z == null || z > ray.pz ) return -1;
-			return ray.pz - z;
-		}
-
-		var b = new h3d.col.Bounds();
-		for( t in terrain.tiles ) {
-			var cb = t.getCachedBounds();
-			if( cb != null )
-				b.add(cb);
-			else {
-				b.addPos(t.x, t.y, -10000);
-				b.addPos(t.x + terrain.cellSize.x * terrain.cellCount.x, t.y + terrain.cellSize.y * terrain.cellCount.y, 10000);
-			}
-		}
-
-		var dist = b.rayIntersection(ray, false);
-		if( dist < 0 )
-			return -1;
-		var pt = ray.getPoint(dist);
-		var m = this.vertexPerMeter;
-		var prevH = pt.z;
-		while( true ) {
-			pt.x += ray.lx * m;
-			pt.y += ray.ly * m;
-			pt.z += ray.lz * m;
-			if( !b.contains(pt) )
-				break;
-			var h = terrain.getLocalHeight(pt.x, pt.y);
-			if( pt.z < h ) {
-				var k = 1 - (prevH - (pt.z - ray.lz * m)) / (ray.lz * m - (h - prevH));
-				pt.x -= k * ray.lx * m;
-				pt.y -= k * ray.ly * m;
-				pt.z -= k * ray.lz * m;
-				return pt.sub(ray.getPos()).length();
-			}
-			prevH = h;
-		}
-		return -1;
-	}
-
-	function loadTiles( ctx : Context ) {
-
-		var resDir = ctx.shared.loadDir(name);
-		if( resDir == null )
-			return;
-
-		var prevWatch = @:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH;
-		@:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH = false;
-
-		// Avoid texture alloc for unpacking
-		var tmpPackedWeightTexture = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target]);
-		var bakeHeightAndNormalInGeometry = false;
-
-		var heightData = [];
-		var weightData = [];
-		var normalData = [];
-		var indexData = [];
-		for( res in resDir ) {
-			var fileInfos = res.name.split(".");
-			var ext = fileInfos[1];
-			var file = fileInfos[0];
-			var coords = file.split("_");
-			var x = Std.parseInt(coords[0]);
-			var y = Std.parseInt(coords[1]);
-			if( x == null || y == null ) continue;
-			var type = coords[2];
-			var data = { res : res, x : x, y : y, ext : ext };
-			switch( type ) {
-				case "n": normalData.push(data);
-				case "h": heightData.push(data);
-				case "w": weightData.push(data);
-				case "i": indexData.push(data);
-			}
-
-			var tile = terrain.createTile(x, y, false);
-			tile.material.shadows = castShadows;
-			tile.material.mainPass.stencil = new h3d.mat.Stencil();
-			tile.material.mainPass.stencil.setFunc(Always, 0x01, 0x01, 0x01);
-			tile.material.mainPass.stencil.setOp(Keep, Keep, Replace);
-		}
-
-		// NORMAL
-		for( nd in normalData ) {
-			var t = terrain.getTile(nd.x, nd.y);
-			var bytes = nd.res.entry.getBytes();
-			var pixels = new hxd.Pixels(terrain.heightMapResolution.x, terrain.heightMapResolution.y, bytes, RGBA);
-			t.normalMapPixels = pixels;
-			if( !bakeHeightAndNormalInGeometry ) {
-				t.refreshNormalMap();
-				t.normalMap.uploadPixels(pixels);
-				t.needNormalBake = false;
-			}
-		}
-
-		// INDEX
-		for( id in indexData ) {
-			var t = terrain.getTile(id.x, id.y);
-			if( t.surfaceIndexMap == null )
-				@:privateAccess t.refreshIndexMap();
-			if( id.ext == "png" ) { // Retro-compatibility
-				var indexAsPNG = id.res.toTexture();
-				h3d.pass.Copy.run(indexAsPNG, t.surfaceIndexMap);
-				t.indexMapPixels = t.surfaceIndexMap.capturePixels();
-				indexAsPNG.dispose();
-			}
-			else {
-				var pixels : hxd.Pixels = new hxd.Pixels(terrain.weightMapResolution.x, terrain.weightMapResolution.y, id.res.entry.getBytes(), RGBA);
-				t.indexMapPixels = pixels;
-				t.surfaceIndexMap.uploadPixels(pixels);
-			}
-		}
-
-		// WEIGHT
-		for( wd in weightData ) {
-			var t = terrain.getTile(wd.x, wd.y);
-			var pixels : hxd.Pixels = new hxd.Pixels(terrain.weightMapResolution.x, terrain.weightMapResolution.y, wd.res.entry.getBytes(), RGBA);
-			tmpPackedWeightTexture.uploadPixels(pixels);
-			t.packedWeightMapPixel = pixels;
-
-			// Notice that we need the surfaceIndexMap loaded before doing the unpacking
-			var engine = h3d.Engine.getCurrent();
-			#if editor
-			// Unpack weight from RGBA texture into a array of texture of R8, and create the TextureArray
-			if( t.surfaceWeights.length == 0 )
-				@:privateAccess t.refreshSurfaceWeightArray();
-			for( i in 0 ... t.surfaceWeights.length ) {
-				engine.pushTarget(t.surfaceWeights[i]);
-				unpackWeight.shader.indexMap = t.surfaceIndexMap;
-				unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture;
-				unpackWeight.shader.index = i;
-				unpackWeight.render();
-				engine.popTarget();
-			}
-			t.generateWeightTextureArray();
-			#else
-			// Unpack weight from RGBA texture directly into the TextureArray of R8
-			t.generateWeightTextureArray();
-			for( i in 0 ... terrain.surfaceArray.surfaceCount ) {
-				engine.pushTarget(t.surfaceWeightArray, i);
-				unpackWeight.shader.indexMap = t.surfaceIndexMap;
-				unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture;
-				unpackWeight.shader.index = i;
-				unpackWeight.render();
-				engine.popTarget();
-			}
-			#end
-		}
-
-		// HEIGHT
-		for( hd in heightData ) {
-			var t = terrain.getTile(hd.x, hd.y);
-			var bytes = hd.res.entry.getBytes();
-			var pixels = new hxd.Pixels(terrain.heightMapResolution.x, terrain.heightMapResolution.y, bytes, R32F);
-			t.heightMapPixels = pixels;
-
-			if( !bakeHeightAndNormalInGeometry ) {
-				// Need heightmap texture for editing
-				t.refreshHeightMap();
-				t.heightMap.uploadPixels(pixels);
-				t.needNewPixelCapture = false;
-			}
-		}
-
-		// BAKE HEIGHT & NORMAL
-		if( bakeHeightAndNormalInGeometry ) {
-			for( t in terrain.tiles ) {
-				t.createBigPrim();
-			}
-		}
-
-		#if editor
-		for( t in terrain.tiles ) {
-			if( t == null ) {
-				"Missing tile" + terrain.tiles.indexOf(t);
-				continue;
-			}
-			if( t.heightMap == null ) trace("Missing heightmap for tile" + terrain.tiles.indexOf(t));
-			if( t.normalMap == null ) trace("Missing normalmap for tile" + terrain.tiles.indexOf(t));
-			if( t.surfaceIndexMap == null ) trace("Missing surfaceIndexMap for tile" + terrain.tiles.indexOf(t));
-			if( t.surfaceWeightArray == null ) trace("Missing surfaceWeightArray for tile" + terrain.tiles.indexOf(t));
-		}
-		#end
-
-		tmpPackedWeightTexture.dispose();
-		@:privateAccess hxd.res.Image.ENABLE_AUTO_WATCH = prevWatch;
-	}
-
-	function loadSurfaces( ctx : Context, onEnd : Void -> Void ) {
-		for( surfaceProps in tmpSurfacesProps ) {
-			var surface = terrain.addEmptySurface();
-		}
-		for( i in 0 ... tmpSurfacesProps.length ) {
-			var surfaceProps = tmpSurfacesProps[i];
-			var surface = terrain.getSurface(i);
-			var albedo = ctx.shared.loadTexture(surfaceProps.albedo);
-			var normal = ctx.shared.loadTexture(surfaceProps.normal);
-			var pbr = ctx.shared.loadTexture(surfaceProps.pbr);
-			function wait() {
-				if( albedo.isDisposed() || albedo.flags.has(Loading) || normal.flags.has(Loading) || pbr.flags.has(Loading) )
-					return;
-
-				albedo.preventAutoDispose();
-				normal.preventAutoDispose();
-				pbr.preventAutoDispose();
-				surface.albedo = albedo;
-				surface.normal = normal;
-				surface.pbr = pbr;
-				surface.offset.x = surfaceProps.offsetX;
-				surface.offset.y = surfaceProps.offsetY;
-				surface.angle = surfaceProps.angle;
-				surface.tilling = surfaceProps.tilling;
-				surface.minHeight = surfaceProps.minHeight;
-				if( onEnd != null )
-					onEnd();
-			}
-			albedo.waitLoad(wait);
-			normal.waitLoad(wait);
-			pbr.waitLoad(wait);
-		}
-	}
-
-	public function initTerrain( ctx : Context ) {
-
-		terrain.createBigPrimitive();
-
-		// Fix terrain being reloaded after a scene modification
-		if( terrain.surfaceArray != null )
-			return;
-
-		#if editor
-		var shared : hide.prefab.ContextShared = cast myContext.shared;
-		@:privateAccess shared.scene.setCurrent();
-		#end
-
-		var initDone = false;
-		function waitAll() {
-
-			if( initDone )
-				return;
-
-			for( surface in terrain.surfaces ) {
-				if( surface == null || surface.albedo == null || surface.normal == null || surface.pbr == null )
-					return;
-			}
-			terrain.generateSurfaceArray();
-
-			loadTiles(ctx);
-
-			initDone = true;
-		}
-		loadSurfaces(ctx, waitAll);
-	}
-
-	#if editor
-
-	public function saveTextures( ctx : Context )  {
-		if( !readyToSave(ctx) ) {
-			throw "Failed to save terrain";
-			return;
-		}
-		var shared : hide.prefab.ContextShared = cast myContext.shared;
-		@:privateAccess shared.scene.setCurrent();
-		clearSavedTextures(ctx);
-		saveWeightTextures(ctx);
-		saveHeightTextures(ctx);
-		saveNormalTextures(ctx);
-		return;
-	}
-
-	function readyToSave( ctx : Context ) : Bool {
-		var error = "Failed to save terrain : ";
-		if( terrain == null ){
-			trace(error + "terrain is null");
-			return false;
-		}
-		if( terrain.surfaceArray == null ) {
-			trace(error + "surfaceArray is null");
-			return false;
-		}
-		if( terrain.surfaceArray.albedo == null || terrain.surfaceArray.albedo.isDisposed() ){
-			trace(error + "surfaceArray.albedo is null");
-			return false;
-		}
-		if( terrain.surfaceArray.normal == null || terrain.surfaceArray.normal.isDisposed() ){
-			trace(error + "surfaceArray.normal is null");
-			return false;
-		}
-		if( terrain.surfaceArray.pbr == null || terrain.surfaceArray.pbr.isDisposed() ){
-			trace(error + "surfaceArray.pbr is null");
-			return false;
-		}
-
-		for( tile in terrain.tiles ) {
-			if( tile == null ) {
-				trace(error + "tile is null");
-				return false;
-			}
-			for( s in tile.surfaceWeights ) {
-				if( s == null || s.isDisposed() ) {
-					trace(error + "surfaceWeights "+ tile.surfaceWeights.indexOf(s) +" is null or disposed ");
-					return false;
-				}
-			}
-			if( tile.heightMap == null || tile.heightMap.isDisposed() ) {
-					trace(error + "heightMap is null or disposed ");
-					return false;
-			}
-			if( tile.surfaceIndexMap == null || tile.surfaceIndexMap.isDisposed() ) {
-					trace(error + "surfaceIndexMap is null or disposed ");
-					return false;
-			}
-			if( tile.surfaceWeightArray == null || tile.surfaceWeightArray.isDisposed() ) {
-					trace(error + "surfaceWeightArray is null or disposed ");
-					return false;
-			}
-		}
-		return true;
-	}
-
-	function clearSavedTextures( ctx : Context ) {
-		var datPath = new haxe.io.Path(ctx.shared.currentPath);
-		datPath.ext = "dat";
-		var fullPath = hide.Ide.inst.getPath(datPath.toString() + "/" + name);
-		if( sys.FileSystem.isDirectory(fullPath) ) {
-			var files = sys.FileSystem.readDirectory(fullPath);
-			for( f in files )
-				sys.FileSystem.deleteFile(fullPath + "/" + f);
-		}
-	}
-
-	public function saveHeightTextures( ctx : Context ) {
-		for( tile in terrain.tiles ) {
-			var pixels = tile.heightMap.capturePixels();
-			var fileName = tile.tileX + "_" + tile.tileY + "_" + "h";
-			ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes);
-		}
-	}
-
-	public function saveNormalTextures( ctx : Context ) {
-		for( tile in terrain.tiles ) {
-			var pixels : hxd.Pixels = tile.normalMap.capturePixels();
-			var fileName = tile.tileX + "_" + tile.tileY + "_" + "n";
-			ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes);
-		}
-	}
-
-	public function saveWeightTextures( ctx : Context ) {
-		var packedWeightsTex = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], RGBA);
-		for( tile in terrain.tiles ) {
-			h3d.Engine.getCurrent().pushTarget(packedWeightsTex);
-			packWeight.shader.indexMap = tile.surfaceIndexMap;
-			packWeight.shader.weightTextures = tile.surfaceWeightArray;
-			packWeight.shader.weightCount = tile.surfaceWeights.length;
-			packWeight.render();
-
-			var pixels = packedWeightsTex.capturePixels();
-			var fileName = tile.tileX + "_" + tile.tileY + "_" + "w";
-			ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes);
-
-			var pixels = tile.surfaceIndexMap.capturePixels();
-			var fileName = tile.tileX + "_" + tile.tileY + "_" + "i";
-			ctx.shared.savePrefabDat(fileName, "bin", name, pixels.bytes);
-		}
-	}
-
-	#end
-
-	function createTerrain( ctx : Context ) {
-		return new TerrainMesh(ctx.local3d);
-	}
-
-	override function makeInstance( ctx : Context ) : Context {
-		ctx = ctx.clone(this);
-		#if editor
-		myContext = ctx;
-		#end
-
-		terrain = createTerrain(ctx);
-		terrain.tileSize = new h2d.col.Point(tileSizeX, tileSizeY);
-		terrain.cellCount = new h2d.col.IPoint(Math.ceil(tileSizeX * vertexPerMeter), Math.ceil(tileSizeY * vertexPerMeter) );
-		terrain.cellSize = new h2d.col.Point(tileSizeX / terrain.cellCount.x, tileSizeY / terrain.cellCount.y );
-		terrain.heightMapResolution = new h2d.col.IPoint(terrain.cellCount.x + 1, terrain.cellCount.y + 1);
-		terrain.weightMapResolution = new h2d.col.IPoint(Math.round(tileSizeX * weightMapPixelPerMeter), Math.round(tileSizeY * weightMapPixelPerMeter));
-		terrain.parallaxAmount = parallaxAmount;
-		terrain.parallaxMinStep = parallaxMinStep;
-		terrain.parallaxMaxStep = parallaxMaxStep;
-		terrain.heightBlendStrength = heightBlendStrength;
-		terrain.blendSharpness = blendSharpness;
-		terrain.name = "terrain";
-
-		ctx.local3d = terrain;
-		ctx.local3d.name = name;
-
-		updateInstance(ctx);
-		initTerrain(ctx);
-		return ctx;
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, null);
-
-		#if editor
-		terrain.parallaxAmount = parallaxAmount;
-		terrain.parallaxMinStep = parallaxMinStep;
-		terrain.parallaxMaxStep = parallaxMaxStep;
-		terrain.heightBlendStrength = heightBlendStrength;
-		terrain.blendSharpness = blendSharpness;
-		terrain.showChecker = showChecker;
-
-		if( propName == "castShadows" ) {
-			if( terrain != null ) {
-				for( t in terrain.tiles )
-					t.material.castShadows = castShadows;
-			}
-		}
-
-		if( editor != null )
-			editor.update(propName);
-		#end
-	}
-
-	#if editor
-	override function makeInteractive( ctx : Context ) : h3d.scene.Interactive {
-		return null;
-	}
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		if( editor != null ) editor.setSelected(ctx, b);
-		return true;
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "industry", name : "Terrain", isGround : true };
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-		var props = new hide.Element('<div></div>');
-		if( editor == null ) editor = new hide.prefab.terrain.TerrainEditor(this, ctx.properties.undo);
-		editor.editContext = ctx;
-		editor.setupUI(props, ctx);
-
-		props.append('
-			<div class="group" name="Rendering"><dl>
-				<dt>Cast Shadows</dt><dd><input type="checkbox" field="castShadows"/></dd>
-				<dt>Height Blend</dt><dd><input type="range" min="0" max="1" field="heightBlendStrength"/></dd>
-				<dt>Sharpness</dt><dd><input type="range" min="0" max="1" field="blendSharpness"/></dd>
-			</dl></div>
-			<div class="group" name="Parallax"><dl>
-				<dt>Amount</dt><dd><input type="range" min="0" max="1" field="parallaxAmount"/></dd>
-				<dt>Min Step</dt><dd><input type="range" min="1" max="64" value="0" step="1" field="parallaxMinStep"/></dd>
-				<dt>Max Step</dt><dd><input type="range" min="1" max="64" value="0" step="1" field="parallaxMaxStep"/></dd>
-			</dl></div>
-		');
-
-		ctx.properties.add(props, this, function(pname) {
-			modified = true;
-			ctx.onChange(this, pname);
-		});
-
-		var obj = {
-			tileSize : tileSizeX,
-			vertexes : vertexPerMeter,
-			pixels : weightMapPixelPerMeter,
-		};
-		var options = new hide.Element('
-		<div class="group" name="Quality"><dl>
-			<dt>Tile Size (Units 3D)</dt><dd><input type="range" min="1" max="100" step="1" field="tileSize"/></dd>
-			<dt>Vertexes and HeightMap<br/>(per Unit)</dt><dd><input type="range" min="0.1" max="2" field="vertexes"/></dd>
-			<dt>Painting Weight Pixels<br/>(per Unit)</dt><dd><input type="range" min="0.1" max="2" field="pixels"/></dd>
-			<div align="center"><input type="button" value="Apply" class="apply"/></div>
-		</dl></div>
-		');
-		ctx.properties.add(options,obj);
-
-		options.find('.apply').click(function(_) {
-			tileSizeY = tileSizeX = obj.tileSize;
-			TerrainResize.resize(this, new h2d.col.Point(tileSizeX, tileSizeY) );
-			weightMapPixelPerMeter = obj.pixels;
-			vertexPerMeter = obj.vertexes;
-			terrain.weightMapResolution = new h2d.col.IPoint(Math.round(tileSizeX * weightMapPixelPerMeter), Math.round(tileSizeY * weightMapPixelPerMeter));
-			terrain.weightMapResolution.x = Std.int(hxd.Math.max(1, terrain.weightMapResolution.x));
-			terrain.weightMapResolution.y = Std.int(hxd.Math.max(1, terrain.weightMapResolution.y));
-			terrain.tileSize = new h2d.col.Point(tileSizeX, tileSizeY);
-			terrain.cellCount = new h2d.col.IPoint(Math.ceil(tileSizeX * vertexPerMeter), Math.ceil(tileSizeY * vertexPerMeter) );
-			terrain.cellCount.x = Std.int(hxd.Math.max(1, terrain.cellCount.x));
-			terrain.cellCount.y = Std.int(hxd.Math.max(1, terrain.cellCount.y));
-			terrain.cellSize = new h2d.col.Point(tileSizeX / terrain.cellCount.x, tileSizeY / terrain.cellCount.y );
-			terrain.heightMapResolution = new h2d.col.IPoint(terrain.cellCount.x + 1, terrain.cellCount.y + 1);
-			terrain.refreshAllGrids();
-			terrain.refreshAllTex();
-			if( editor != null ) {
-				editor.refresh();
-				@:privateAccess editor.blendEdges(terrain.tiles);
-			}
-			modified = true;
-		});
-
-		ctx.properties.add(new hide.Element('
-			<div class="group" name="Debug"><dl>
-				<dt>Show Grid</dt><dd><input type="checkbox" field="terrain.showGrid"/></dd>
-				<dt>Mode</dt>
-				<dd><select field="editor.renderMode">
-						<option value="PBR">PBR</option>
-						<option value="ShaderComplexity">Shader Complexity</option>
-						<option value="Checker">Checker</option>
-					</select></dd>
-			</dl></div>
-		'), this);
-	}
-	#end
-
-	static var _ = Library.register("terrain", Terrain);
-}

+ 0 - 296
hrt/prefab/terrain/TerrainMesh.hx

@@ -1,296 +0,0 @@
-package hrt.prefab.terrain;
-
-import h3d.mat.Texture;
-
-@:access(hrt.prefab.terrain.Tile)
-class TerrainMesh extends h3d.scene.Object {
-
-	var primitive : h3d.prim.BigPrimitive;
-
-	// Resolution Vertexes/Pixels
-	public var tileSize : h2d.col.Point;
-	public var cellSize : h2d.col.Point;
-	public var cellCount : h2d.col.IPoint;
-
-	public var heightMapResolution : h2d.col.IPoint;
-	public var weightMapResolution : h2d.col.IPoint;
-	public var useBigPrim = false;
-
-	// Shader Params
-	#if editor
-	public var showGrid : Bool;
-	public var showChecker : Bool;
-	public var showComplexity : Bool;
-	#end
-	public var enableParallax : Bool = true;
-	public var parallaxAmount : Float;
-	public var parallaxMinStep : Int;
-	public var parallaxMaxStep : Int;
-	public var heightBlendStrength : Float;
-	public var blendSharpness : Float;
-
-	// Data
-	var tiles : Array<Tile> = [];
-	var surfaces : Array<Surface> = [];
-	var surfaceArray : Surface.SurfaceArray;
-
-	public function new(?parent){
-		super(parent);
-	}
-
-	override function onRemove() {
-		super.onRemove();
-		if( surfaceArray != null )
-			surfaceArray.dispose();
-	}
-
-	public function getLocalHeight( x : Float, y : Float, fast = false) : Null<Float> {
-		var xi = hxd.Math.floor(x/tileSize.x);
-		var yi = hxd.Math.floor(y/tileSize.y);
-		var t = getTile(xi, yi);
-		if( t != null ) {
-			return t.getHeight((x - xi * tileSize.x) / tileSize.x, (y - yi * tileSize.y) / tileSize.y, fast);
-		}
-		return null;
-	}
-
-	public function getHeight( x : Float, y : Float, fast = false) : Null<Float> {
-		var t = getTileAtWorldPos(x, y);
-		if( t != null ) {
-			tmpPt.set(x, y);
-			var pos = t.globalToLocal(tmpPt);
-			return t.getHeight(pos.x / tileSize.x, pos.y / tileSize.y, fast);
-		}
-		return null;
-	}
-
-	public function getSurface( i : Int ) : Surface {
-		if(i < surfaces.length)
-				return surfaces[i];
-		return null;
-	}
-
-	public function getSurfaceFromTex( albedo, ?normal, ?pbr ) : Surface {
-		for( s in surfaces ) {
-			var valid = false;
-			valid = s.albedo.name == albedo;
-			valid = valid && !( normal != null && s.normal.name != normal );
-			valid = valid && !( pbr != null && s.pbr.name != pbr );
-			if( valid ) return s;
-		}
-		return null;
-	}
-
-	public function addSurface( albedo, normal, pbr ) : Surface {
-		surfaces.push(new Surface(albedo, normal, pbr));
-		return surfaces[surfaces.length - 1];
-	}
-
-	public function addEmptySurface() : Surface {
-		surfaces.push( new Surface() );
-		return surfaces[surfaces.length - 1];
-	}
-
-	public function generateSurfaceArray() {
-		if( surfaces.length == 0 ) return;
-		var surfaceSize = 1;
-		for( i in 0 ... surfaces.length )
-			if( surfaces[i].albedo != null ) surfaceSize = hxd.Math.ceil(hxd.Math.max(surfaces[i].albedo.width, surfaceSize));
-
-		if(surfaceArray != null) surfaceArray.dispose();
-		surfaceArray = new Surface.SurfaceArray(surfaces.length, surfaceSize);
-		for( i in 0 ... surfaces.length ) {
-			if( surfaces[i].albedo != null ) h3d.pass.Copy.run(surfaces[i].albedo, surfaceArray.albedo, null, null, i);
-			if( surfaces[i].normal != null ) h3d.pass.Copy.run(surfaces[i].normal, surfaceArray.normal, null, null, i);
-			if( surfaces[i].pbr != null ) h3d.pass.Copy.run(surfaces[i].pbr, surfaceArray.pbr, null, null, i);
-		}
-
-		// OnContextLost support
-		surfaceArray.albedo.realloc = function() {
-			for( i in 0 ... surfaceArray.surfaceCount )
-				h3d.pass.Copy.run(surfaces[i].albedo, surfaceArray.albedo, null, null, i);
-		}
-		surfaceArray.normal.realloc = function() {
-			for( i in 0 ... surfaceArray.surfaceCount )
-				h3d.pass.Copy.run(surfaces[i].normal, surfaceArray.normal, null, null, i);
-		}
-		surfaceArray.pbr.realloc = function() {
-			for( i in 0 ... surfaceArray.surfaceCount )
-				h3d.pass.Copy.run(surfaces[i].pbr, surfaceArray.pbr, null, null, i);
-		}
-
-		updateSurfaceParams();
-		refreshAllTex();
-	}
-
-	public function updateSurfaceParams() {
-		for( i in 0 ... surfaces.length ) {
-			surfaceArray.params[i] = new h3d.Vector(surfaces[i].tilling, surfaces[i].offset.x, surfaces[i].offset.y, hxd.Math.degToRad(surfaces[i].angle));
-			surfaceArray.secondParams[i] = new h3d.Vector(surfaces[i].minHeight, surfaces[i].maxHeight, 0, 0);
-		}
-	}
-
-	function createBigPrimitive() {
-
-		if( primitive != null )
-			primitive.dispose();
-
-		primitive = new h3d.prim.BigPrimitive(3, true);
-
-		inline function addVertice(x : Float, y : Float, i : Int) {
-			primitive.addPoint(x, y, 0);
-		}
-
-		primitive.begin(0,0);
-		for( y in 0 ... cellCount.y + 1 ) {
-			for( x in 0 ... cellCount.x + 1 ) {
-				addVertice(x * cellSize.x, y * cellSize.y, x + y * (cellCount.x + 1));
-			}
-		}
-
-		for( y in 0 ... cellCount.y ) {
-			for( x in 0 ... cellCount.x ) {
-				var i = x + y * (cellCount.x + 1);
-				if( i % 2 == 0 ) {
-					primitive.addIndex(i);
-					primitive.addIndex(i + 1);
-					primitive.addIndex(i + cellCount.x + 2);
-					primitive.addIndex(i);
-					primitive.addIndex(i + cellCount.x + 2);
-					primitive.addIndex(i + cellCount.x + 1);
-				}
-				else {
-					primitive.addIndex(i + cellCount.x + 1);
-					primitive.addIndex(i);
-					primitive.addIndex(i + 1);
-					primitive.addIndex(i + 1);
-					primitive.addIndex(i + cellCount.x + 2);
-					primitive.addIndex(i + cellCount.x + 1);
-				}
-			}
-		}
-		primitive.flush();
-	}
-
-	public function refreshAllGrids() {
-		createBigPrimitive();
-	}
-
-	public function refreshAllTex() {
-		for( tile in tiles )
-			tile.refreshTex();
-	}
-
-	public function refreshAll() {
-		refreshAllGrids();
-		refreshAllTex();
-	}
-
-	public function createTile(x : Int, y : Int, ?createTexture = true) : Tile {
-		var tile = getTile(x,y);
-		if(tile == null){
-			tile = new Tile(x, y, this);
-			if( createTexture ) tile.refreshTex();
-			tiles.push(tile);
-		}
-		return tile;
-	}
-
-	public function addTile( tile : Tile, ?replace = false ) {
-		for( t in tiles ) {
-			if( tile == t ) return;
-			if( tile.tileX == t.tileX && tile.tileY == t.tileY ) {
-				if( replace ) {
-					removeTile(t);
-					break;
-				}else
-					return;
-			}
-		}
-		tile.parent = this;
-		tiles.push(tile);
-		addChild(tile);
-	}
-
-	public function removeTileAt( x : Int, y : Int ) : Bool {
-		var t = getTile(x,y);
-		if( t == null ) {
-			removeTile(t);
-			return true;
-		}
-		return false;
-	}
-
-	public function removeTile( t : Tile ) : Bool {
-		if( t == null ) return false;
-		var r = tiles.remove(t);
-		if( r ) t.remove();
-		return r;
-	}
-
-	public function getTileIndex( t : Tile ) : Int {
-		for( i in 0 ... tiles.length )
-			if( t == tiles[i] ) return i;
-		return -1;
-	}
-
-	public function getTile( x : Int, y : Int ) : Tile {
-		var result : Tile = null;
-		for( tile in tiles )
-			if( tile.tileX == x && tile.tileY == y ) result = tile;
-		return result;
-	}
-
-	public function getTileAtWorldPos( x : Float, y : Float ) : Tile {
-		var pos = toLocalPos(x, y);
-		var result : Tile = null;
-		var tileX = Math.floor(pos.x / tileSize.x);
-		var tileY = Math.floor(pos.y / tileSize.y);
-		for( tile in tiles )
-			if( tile.tileX == tileX && tile.tileY == tileY ) result = tile;
-		return result;
-	}
-
-	public function createTileAtWorldPos( x : Float, y : Float ) : Tile {
-		var pos = toLocalPos(x, y);
-		var tileX = Math.floor(pos.x / tileSize.x);
-		var tileY = Math.floor(pos.y / tileSize.y);
-		var result = getTile(tileX, tileY);
-		return result == null ? createTile(tileX, tileY) : result;
-	}
-
-	public function getTiles( x : Float, y : Float, range : Float, ?create = false ) : Array<Tile> {
-		var pos = toLocalPos(x, y);
-		if( create != null && create ) {
-			var maxTileX = Math.floor((pos.x + range)/ tileSize.x);
-			var minTileX = Math.floor((pos.x - range)/ tileSize.x);
-			var maxTileY = Math.floor((pos.y + range)/ tileSize.y);
-			var minTileY = Math.floor((pos.y - range)/ tileSize.y);
-			for( x in minTileX ... maxTileX + 1) {
-				for( y in minTileY...maxTileY + 1) {
-					var t = createTile(x, y);
-					#if editor
-					t.material.mainPass.stencil = new h3d.mat.Stencil();
-					t.material.mainPass.stencil.setFunc(Always, 0x01, 0x01, 0x01);
-					t.material.mainPass.stencil.setOp(Keep, Keep, Replace);
-					#end
-				}
-			}
-		}
-		var result : Array<Tile> = [];
-		for( tile in tiles)
-			if( Math.abs(pos.x - (tile.tileX * tileSize.x + tileSize.x * 0.5)) <= range + (tileSize.x * 0.5)
-			&& Math.abs(pos.y - (tile.tileY * tileSize.y + tileSize.y * 0.5)) <= range + (tileSize.y * 0.5) )
-				result.push(tile);
-		return result;
-	}
-
-	static var tmpPt = new h3d.col.Point();
-	inline function toLocalPos( x : Float, y : Float ) {
-		tmpPt.set(x, y);
-		globalToLocal(tmpPt);
-		return tmpPt;
-	}
-}
-
-

+ 0 - 148
hrt/prefab/terrain/TerrainResize.hx

@@ -1,148 +0,0 @@
-package hrt.prefab.terrain;
-import h3d.pass.ScreenFx;
-using Lambda;
-
-class TerrainCopy extends h3d.shader.ScreenShader {
-	static var SRC = {
-
-		@param var from : Vec2;
-		@param var to : Vec2;
-		@param var source : Sampler2D;
-
-		function vertex() {
-			output.position = vec4(uvToScreen(mix(from, to, screenToUv(input.position))), 0, 1);
-			output.position.y *= flipY;
-		}
-
-		function fragment() {
-			pixelColor = source.get(calculatedUV);
-		}
-	}
-}
-
-@:access(hrt.prefab.terrain.TerrainMesh)
-@:access(hrt.prefab.terrain.Tile)
-class TerrainResize {
-
-	public function new( ) {
-
-	}
-
-	static inline function getTileBounds( xi, yi, s : h2d.col.Point ) : h2d.col.Bounds {
-		var b = new h2d.col.Bounds();
-		b.xMin = xi * s.x; 
-		b.yMin = yi * s.y;
-		b.xMax = (xi + 1) * s.x;
-		b.yMax = (yi + 1) * s.y;
-		return b;
-	}
-
-	static public function resize( prefab : Terrain, tileSize : h2d.col.Point ) {
-
-		if( prefab.terrain.tileSize.x == tileSize.x && prefab.terrain.tileSize.y == tileSize.y )
-			return;
-
-		var engine = h3d.Engine.getCurrent();
-		var terrainCopy = new ScreenFx(new TerrainCopy());
-
-		var prevTiles = prefab.terrain.tiles;
-		var prevSize = prefab.terrain.tileSize;
-		var curSize = tileSize;
-
-		// Recreate tiles to fit with the new size
-		var terrainMinMax = new h3d.Vector();
-		terrainMinMax.set(hxd.Math.POSITIVE_INFINITY, hxd.Math.POSITIVE_INFINITY, hxd.Math.NEGATIVE_INFINITY);
-		for( t in prefab.terrain.tiles ) {
-			terrainMinMax.x = hxd.Math.min(terrainMinMax.x, t.tileX * prevSize.x);
-			terrainMinMax.y = hxd.Math.min(terrainMinMax.y, t.tileY * prevSize.y);
-			terrainMinMax.z = hxd.Math.max(terrainMinMax.z, (t.tileX + 1) * prevSize.x);
-			terrainMinMax.w = hxd.Math.max(terrainMinMax.w, (t.tileY + 1) * prevSize.y);
-		}
-		var terrainBounds : Array<h2d.col.Bounds> = [];
-		var bias = 0.1;
-		for( t in prefab.terrain.tiles ) {
-			var b = new h2d.col.Bounds();
-			b.xMin = t.tileX * prevSize.x + bias;
-			b.yMin = t.tileY * prevSize.y + bias;
-			b.xMax = (t.tileX + 1) * prevSize.x - bias;
-			b.yMax = (t.tileY + 1) * prevSize.y - bias;
-			terrainBounds.push(b);
-		}
-		prefab.terrain.tiles = [];
-		prefab.terrain.tileSize = tileSize;
-		var x = terrainMinMax.x;
-		var y = terrainMinMax.y;
-		var tmpBounds = new h2d.col.Bounds();
-		while( x < terrainMinMax.z ) {
-			while( y < terrainMinMax.w ) {
-
-				tmpBounds.xMin = x;
-				tmpBounds.yMin = y;
-				tmpBounds.xMax = x + curSize.x;
-				tmpBounds.yMax = y + curSize.y;
-				var intersectTerrain = false;
-				for( b in terrainBounds ) {
-					if( b.intersects(tmpBounds) ) {
-						intersectTerrain = true;
-						break;
-					}
-				}
-				if( intersectTerrain )
-					prefab.terrain.createTile(Std.int(x / curSize.x), Std.int(y / curSize.y));
-
-				y += curSize.y;
-			}
-			y = terrainMinMax.y;
-			x += curSize.x;
-		}	
-
-		// Copy Textures
-		for( curTile in prefab.terrain.tiles ) {
-			var curTileBounds = getTileBounds(curTile.tileX, curTile.tileY, curSize);
-			for( prevTile in prevTiles ) {
-
-				var prevTileBounds = getTileBounds(prevTile.tileX, prevTile.tileY, prevSize);
-				if( !prevTileBounds.intersects(curTileBounds) ) 
-					continue;
-				
-				terrainCopy.shader.from.set((prevTileBounds.x - curTileBounds.x) / curTileBounds.width, (prevTileBounds.y - curTileBounds.y) / curTileBounds.height);
-				terrainCopy.shader.to.set(terrainCopy.shader.from.x + prevTileBounds.width / curTileBounds.width, terrainCopy.shader.from.y + prevTileBounds.height / curTileBounds.height );
-
-				// Copy HeightMap
-				engine.pushTarget(curTile.heightMap);
-				terrainCopy.shader.source = prevTile.heightMap;
-				terrainCopy.render();
-				engine.popTarget();
-
-				// Copy NormalMap
-				engine.pushTarget(curTile.normalMap);
-				terrainCopy.shader.source = prevTile.normalMap;
-				terrainCopy.render();
-				engine.popTarget();
-
-				// Copy Index Map
-				engine.pushTarget(curTile.surfaceIndexMap);
-				terrainCopy.shader.source = prevTile.surfaceIndexMap;
-				terrainCopy.render();
-				engine.popTarget();
-
-				// Copy Weight Map
-				for( i in 0 ... curTile.surfaceWeightArray.layerCount ) {
-					engine.pushTarget(curTile.surfaceWeights[i]);
-					terrainCopy.shader.source = prevTile.surfaceWeights[i];
-					terrainCopy.render();
-					engine.popTarget();
-					engine.pushTarget(curTile.surfaceWeightArray, i);
-					terrainCopy.render();
-					engine.popTarget();
-				}
-			}
-		}
-
-		// Dispose old tiles
-		for( t in prevTiles ) {
-			t.remove();
-		}
-	}
-
-}

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

@@ -1,462 +0,0 @@
-package hrt.prefab.terrain;
-
-class NormalBake extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var heightMap : Sampler2D;
-		@param var heightMapSize : Vec2;
-
-		function fragment() {
-			var pixelSize = 1.0 / heightMapSize;
-			var h = heightMap.get(calculatedUV).r;
-			var h1 = heightMap.get(calculatedUV + vec2(0, pixelSize.y)).r;
-			var h2 = heightMap.get(calculatedUV + vec2(pixelSize.x, 0)).r;
-			var h3 = heightMap.get(calculatedUV + vec2(0, -pixelSize.y)).r;
-			var h4 = heightMap.get(calculatedUV + vec2(-pixelSize.x, 0)).r;
-			var v1 = vec3( 0, 1, h1 - h);
-			var v2 = vec3( 1, 0, h2 - h);
-			var v3 = vec3( 0, -1, h3 - h);
-			var v4 = vec3( -1, 0, h4 - h);
-			var n = (cross(v1, v2) + cross(v2, v3) + cross(v3, v4) + cross(v4, v1)) / -4;
-			n = n.normalize();
-			pixelColor.rgb = n * 0.5 + 0.5;
-		}
-	};
-}
-
-enum Direction {
-	Up; Down; Left; Right; UpLeft; UpRight; DownLeft; DownRight;
-}
-
-@:access(hrt.prefab.terrain.TerrainMesh)
-class Tile extends h3d.scene.Mesh {
-
-	var shader : hrt.shader.Terrain;
-	var terrain : TerrainMesh;
-
-	// INDEXES
-	public var tileX (default, null) : Int;
-	public var tileY (default, null) : Int;
-
-	// TEXTURE & PIXEL
-	public var heightMap : h3d.mat.Texture;
-	var heightMapPixels : hxd.Pixels;
-
-	public var normalMap(default, null) : h3d.mat.Texture;
-	var normalMapPixels : hxd.Pixels.Pixels;
-	var needNormalBake = true;
-
-	public var surfaceIndexMap : h3d.mat.Texture;
-	public var surfaceWeights : Array<h3d.mat.Texture> = [];
-	public var surfaceWeightArray (default, null) : h3d.mat.TextureArray;
-	public var needNewPixelCapture = false;
-
-	// PRIMITIVE
-	var bigPrim : h3d.prim.BigPrimitive;
-	public var insideFrustrum(default, null) = false;
-
-	// Set by prefab loader for CPU access ingame
-	public var packedWeightMapPixel : hxd.Pixels;
-	public var indexMapPixels : hxd.Pixels;
-	public var normalTangentBytes : haxe.io.Bytes;
-
-	public function new( x : Int, y : Int, parent : TerrainMesh) {
-		super(null, null, parent);
-		terrain = parent;
-		tileX = x;
-		tileY = y;
-		shader = new hrt.shader.Terrain();
-		material.mainPass.addShader(shader);
-		material.mainPass.culling = Back;
-		material.staticShadows = true;
-		material.mainPass.setPassName("terrain");
-		material.mainPass.stencil = new h3d.mat.Stencil();
-		material.mainPass.stencil.setFunc(Always, 0x01, 0xFF, 0xFF);
-		material.mainPass.stencil.setOp(Keep, Keep, Replace);
-		this.x = x * terrain.tileSize.x;
-		this.y = y * terrain.tileSize.y;
-		name = "tile_" + x + "_" + y;
-	}
-
-	override function onRemove() {
-		super.onRemove();
-
-		inline function disposeTex( t : h3d.mat.Texture ) { if( t != null ) { t.dispose();  t = null; } }
-		inline function disposePixels( p : hxd.Pixels ) { if( p != null ) { p.dispose(); p = null; } }
-
-		disposeTex(heightMap);
-		disposeTex(normalMap);
-		disposeTex(surfaceIndexMap);
-		disposeTex(surfaceWeightArray);
-		for( i in 0 ... surfaceWeights.length )
-			disposeTex(surfaceWeights[i]);
-
-		disposePixels(packedWeightMapPixel);
-		disposePixels(indexMapPixels);
-		disposePixels(heightMapPixels);
-
-		normalTangentBytes = null;
-		if( bigPrim != null ) bigPrim.dispose();
-	}
-
-	public inline function getHeightMapPixels() {
-		if( (needNewPixelCapture || heightMapPixels == null) && heightMap != null )
-			heightMapPixels = heightMap.capturePixels();
-		needNewPixelCapture = false;
-		return heightMapPixels;
-	}
-
-	public inline function getNormalMapPixels() {
-		if( normalMapPixels == null && normalMap != null )
-			normalMapPixels = normalMap.capturePixels();
-		return normalMapPixels;
-	}
-
-	function bakeNormal() {
-		if( heightMap == null )
-			throw "Can't bake the normalMap of the tile if the heightMap is null.";
-		var s = new NormalBake();
-		s.heightMap = heightMap;
-		s.heightMapSize.set(heightMap.width, heightMap.height);
-		h3d.pass.ScreenFx.run(s, normalMap);
-		needNormalBake = false;
-		if( normalMapPixels != null ) {
-			normalMapPixels.dispose();
-			normalMapPixels = null;
-		}
-	}
-
-	public function createBigPrim() {
-
-		if( normalMapPixels == null || heightMapPixels == null )
-			return;
-
-		if( bigPrim != null )
-			bigPrim.dispose();
-
-		bigPrim = new h3d.prim.BigPrimitive(6, true);
-
-		var cellCount = terrain.cellCount;
-		var cellSize = terrain.cellSize;
-		inline function addVertice(x : Int, y : Int) {
-			// Pos
-			bigPrim.addPoint(x * cellSize.x, y * cellSize.y, getHeight((x * cellSize.x) / terrain.tileSize.x, (y * cellSize.y) / terrain.tileSize.y, true)); // Use addPoint() instead of addVertexValue() for the bounds
-			// Normal
-			var n = h3d.Vector.fromColor(normalMapPixels.getPixel(x, y));
-			n = n.add(new h3d.Vector(-0.5, -0.5, -0.5));
-			n.scale3(2.0);
-			bigPrim.addVertexValue(n.x);
-			bigPrim.addVertexValue(n.y);
-			bigPrim.addVertexValue(n.z);
-		}
-
-		bigPrim.begin(0,0);
-		for( y in 0 ... cellCount.y + 1 ) {
-			for( x in 0 ... cellCount.x + 1 ) {
-				addVertice(x, y);
-			}
-		}
-
-		for( y in 0 ... cellCount.y ) {
-			for( x in 0 ... cellCount.x ) {
-				var i = x + y * (cellCount.x + 1);
-				bigPrim.addIndex(i);
-				bigPrim.addIndex(i + 1);
-				bigPrim.addIndex(i + cellCount.x + 2);
-				bigPrim.addIndex(i);
-				bigPrim.addIndex(i + cellCount.x + 2);
-				bigPrim.addIndex(i + cellCount.x + 1);
-			}
-		}
-		bigPrim.flush();
-	}
-
-	function refreshNormalMap() {
-		if( normalMap == null || normalMap.width != terrain.heightMapResolution.x || normalMap.height != terrain.heightMapResolution.y ) {
-			var oldNormalMap = normalMap;
-			normalMap = new h3d.mat.Texture(terrain.heightMapResolution.x, terrain.heightMapResolution.y, [Target], RGBA);
-			normalMap.setName("terrainNormalMap");
-			normalMap.wrap = Clamp;
-			normalMap.filter = Linear;
-			normalMap.preventAutoDispose();
-			normalMap.realloc = function() {
-				if( normalMapPixels != null )
-					normalMap.uploadPixels(normalMapPixels);
-				else
-					needNormalBake = true;
-			}
-			if( oldNormalMap != null )
-				oldNormalMap.dispose();
-
-			if( normalMapPixels != null && (normalMapPixels.width != normalMap.width || normalMapPixels.height != normalMap.height) ) {
-				normalMapPixels.dispose();
-				normalMapPixels = null;
-			}
-		}
-	}
-
-	function refreshHeightMap() {
-		if( heightMap == null || heightMap.width != terrain.heightMapResolution.x || heightMap.height != terrain.heightMapResolution.y ) {
-			var oldHeightMap = heightMap;
-			heightMap = new h3d.mat.Texture(terrain.heightMapResolution.x, terrain.heightMapResolution.y, [Target], R32F);
-			heightMap.setName("terrainHeightMap");
-			heightMap.wrap = Clamp;
-			heightMap.filter = Linear;
-			heightMap.preventAutoDispose();
-			needNewPixelCapture = true;
-
-			heightMap.realloc = function() {
-				if( heightMapPixels != null )
-					heightMap.uploadPixels(heightMapPixels);
-			}
-
-			if( oldHeightMap != null ) {
-				h3d.pass.Copy.run(oldHeightMap, heightMap);
-				oldHeightMap.dispose();
-			}
-
-			if( heightMapPixels != null && (heightMapPixels.width != heightMap.width || heightMapPixels.height != heightMap.height) ) {
-				heightMapPixels.dispose();
-				heightMapPixels = null;
-			}
-		}
-	}
-
-	function refreshIndexMap() {
-		if( surfaceIndexMap == null || surfaceIndexMap.width != terrain.weightMapResolution.x || surfaceIndexMap.height != terrain.weightMapResolution.y ) {
-			var oldSurfaceIndexMap = surfaceIndexMap;
-			surfaceIndexMap = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], RGBA);
-			surfaceIndexMap.setName("terrainSurfaceIndexMap");
-			surfaceIndexMap.filter = Nearest;
-			surfaceIndexMap.preventAutoDispose();
-
-			surfaceIndexMap.realloc = function() {
-				if( indexMapPixels != null )
-					surfaceIndexMap.uploadPixels(indexMapPixels);
-			}
-
-			if( oldSurfaceIndexMap != null ) {
-				h3d.pass.Copy.run(oldSurfaceIndexMap, surfaceIndexMap);
-				oldSurfaceIndexMap.dispose();
-			}
-		}
-	}
-
-	function refreshSurfaceWeightArray() {
-		if( terrain.surfaceArray.surfaceCount > 0 && (surfaceWeights.length != terrain.surfaceArray.surfaceCount || surfaceWeights[0].width != terrain.weightMapResolution.x || surfaceWeights[0].height != terrain.weightMapResolution.y) ) {
-				var oldArray = surfaceWeights;
-				surfaceWeights = new Array<h3d.mat.Texture>();
-				surfaceWeights = [for( i in 0...terrain.surfaceArray.surfaceCount ) null];
-				for( i in 0 ... surfaceWeights.length ) {
-					surfaceWeights[i] = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], R8);
-					surfaceWeights[i].setName("terrainSurfaceWeight"+i);
-					surfaceWeights[i].wrap = Clamp;
-					surfaceWeights[i].preventAutoDispose();
-					if( i < oldArray.length && oldArray[i] != null )
-						h3d.pass.Copy.run(oldArray[i], surfaceWeights[i]);
-				}
-				for( t in oldArray )
-					if( t != null)
-						t.dispose();
-		}
-	}
-
-	function disposeSurfaceWeightArray() {
-		if( surfaceWeights != null ) {
-			for( t in surfaceWeights )
-				if( t != null ) t.dispose();
-		}
-	}
-
-	public function refreshTex() {
-		refreshHeightMap();
-		refreshNormalMap();
-		refreshIndexMap();
-		refreshSurfaceWeightArray();
-		generateWeightTextureArray();
-	}
-
-	public function generateWeightTextureArray() {
-		if( surfaceWeightArray == null || surfaceWeightArray.width != terrain.weightMapResolution.x || surfaceWeightArray.height != terrain.weightMapResolution.y || surfaceWeightArray.layerCount != terrain.surfaceArray.surfaceCount  ) {
-			if( surfaceWeightArray != null ) surfaceWeightArray.dispose();
-			surfaceWeightArray = new h3d.mat.TextureArray(terrain.weightMapResolution.x, terrain.weightMapResolution.y, terrain.surfaceArray.surfaceCount, [Target], R8);
-			surfaceWeightArray.setName("terrainSurfaceWeightArray");
-			surfaceWeightArray.wrap = Clamp;
-			surfaceWeightArray.preventAutoDispose();
-
-			// OnContextLost support : Restore the textureArray with the pixels from the packedWeight texture
-			surfaceWeightArray.realloc = function() {
-				var engine = h3d.Engine.getCurrent();
-				var unpackWeight = new h3d.pass.ScreenFx(new UnpackWeight());
-				var tmpPackedWeightTexture = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target]);
-				tmpPackedWeightTexture.uploadPixels(packedWeightMapPixel);
-				for( i in 0 ... surfaceWeightArray.layerCount ) {
-					engine.pushTarget(surfaceWeightArray, i);
-					unpackWeight.shader.indexMap = surfaceIndexMap;
-					unpackWeight.shader.packedWeightTexture = tmpPackedWeightTexture;
-					unpackWeight.shader.index = i;
-					unpackWeight.render();
-					engine.popTarget();
-				}
-			}
-		}
-		for( i in 0 ... surfaceWeights.length )
-			if( surfaceWeights[i] != null ) h3d.pass.Copy.run(surfaceWeights[i], surfaceWeightArray, None, null, i);
-	}
-
-	public function getHeight( u : Float, v : Float, ?fast = false ) : Float {
-		var pixels = heightMapPixels;
-		if( pixels == null ) return 0.0;
-		if( !fast ) {
-			inline function getPix(u, v) {
-				return pixels.getPixelF(Std.int(hxd.Math.clamp(u, 0, pixels.width - 1)), Std.int(hxd.Math.clamp(v, 0, pixels.height - 1))).r;
-			}
-			var px = u * (pixels.width - 1) ;
-            var py = v * (pixels.height - 1) ;
-			var pxi = hxd.Math.floor(px);
-            var pyi = hxd.Math.floor(py);
-			var c00 = getPix(pxi, pyi);
-			var c10 = getPix(pxi + 1, pyi);
-			var c01 = getPix(pxi, pyi + 1);
-			var c11 = getPix(pxi + 1, pyi + 1);
-			var wx = px - pxi;
-			var wy = py - pyi;
-			var a = c00 * (1 - wx) + c10 * wx;
-			var b = c01 * (1 - wx) + c11 * wx;
-			return a * (1 - wy) + b * wy;
-
-		}
-		else{
-			var x = hxd.Math.floor(u * (pixels.width - 1));
-			var y = hxd.Math.floor(v * (pixels.height - 1));
-			return pixels.getPixelF(x, y).r;
-		}
-	}
-
-	var cachedBounds : h3d.col.Bounds;
-	function computeBounds() {
-
-		if( bigPrim == null && heightMapPixels == null )
-			return;
-
-		if( cachedBounds == null ) {
-			if( heightMap != null ) {
-				cachedBounds = new h3d.col.Bounds();
-				cachedBounds.xMax = terrain.tileSize.x;
-				cachedBounds.xMin = 0.0;
-				cachedBounds.yMax = terrain.tileSize.y;
-				cachedBounds.yMin = 0.0;
-				for( u in 0 ... heightMap.width ) {
-					for( v in 0 ... heightMap.height ) {
-						var h = getHeight(u / heightMap.width, v / heightMap.height, true);
-						if( cachedBounds.zMin > h ) cachedBounds.zMin = h;
-						if( cachedBounds.zMax < h ) cachedBounds.zMax = h;
-					}
-				}
-			}
-			else if( bigPrim != null ) {
-				cachedBounds = bigPrim.getBounds();
-			}
-		}
-		if( cachedBounds != null )
-			cachedBounds.transform(getAbsPos());
-	}
-
-	inline public function getCachedBounds() : h3d.col.Bounds {
-		if( cachedBounds == null )
-			computeBounds();
-		return cachedBounds;
-	}
-
-	public dynamic function beforeEmit() : Bool { return true; };
-	override function emit( ctx:h3d.scene.RenderContext ) {
-		if( !isReadyForDraw() )
-			return;
-		insideFrustrum = getCachedBounds() != null ? ctx.camera.frustum.hasBounds(getCachedBounds()) : false;
-		insideFrustrum = true;
-		var b = beforeEmit();
-		if( b && insideFrustrum )
-			super.emit(ctx);
-	}
-
-	override function sync(ctx:h3d.scene.RenderContext) {
-
-		primitive = bigPrim == null ? terrain.primitive : bigPrim;
-
-		// DEBUG
-		shader.SHOW_GRID = #if editor terrain.showGrid #else false #end;
-		shader.CHECKER = #if editor terrain.showChecker #else false #end;
-		shader.COMPLEXITY = #if editor terrain.showComplexity #else false #end;
-
-		// TILE INFO
-		shader.VERTEX_DISPLACEMENT = bigPrim == null;
-		shader.primSize.set(terrain.tileSize.x, terrain.tileSize.y);
-		shader.cellSize.set(terrain.cellSize.x, terrain.cellSize.y);
-		shader.tileIndex.set(tileX, tileY);
-
-		// SURFACE
-		if( terrain.surfaceArray != null ) {
-			shader.SURFACE_COUNT = terrain.surfaceArray.surfaceCount;
-			shader.albedoTextures = terrain.surfaceArray.albedo;
-			shader.normalTextures = terrain.surfaceArray.normal;
-			shader.pbrTextures = terrain.surfaceArray.pbr;
-			shader.surfaceParams = terrain.surfaceArray.params;
-			shader.secondSurfaceParams = terrain.surfaceArray.secondParams;
-		}
-
-		// BLEND PARAM
-		shader.PARALLAX = terrain.enableParallax && terrain.parallaxAmount != 0;
-		shader.parallaxAmount = terrain.parallaxAmount;
-		shader.minStep = terrain.parallaxMinStep;
-		shader.maxStep = terrain.parallaxMaxStep;
-		shader.heightBlendStrength = terrain.heightBlendStrength;
-		shader.blendSharpness = terrain.blendSharpness;
-
-		// TILE TEXTURE
-		shader.weightTextures = surfaceWeightArray;
-		shader.heightMap = heightMap;
-		shader.normalMap = normalMap;
-		shader.surfaceIndexMap = surfaceIndexMap;
-
-
-		if( bigPrim == null && needNormalBake && isReadyForDraw() )
-			bakeNormal();
-
-		// OnContextLost support : re-create the bigPrim
-		var needRealloc = false;
-		if( bigPrim != null ) {
-			for( b in @:privateAccess bigPrim.buffers ) {
-				if( b.isDisposed() ) {
-					needRealloc = true;
-					break;
-				}
-			}
-			if( needRealloc ) {
-				createBigPrim();
-				cachedBounds = null;
-			}
-		}
-	}
-
-	function isReadyForDraw() {
-
-		if( primitive == null )
-			return false;
-
-		if( bigPrim == null && (heightMap == null || heightMap.isDisposed()) )
-			return false;
-
-		if( !shader.CHECKER && (shader.weightTextures == null || shader.weightTextures.isDisposed()) )
-			return false;
-
-		if( !shader.CHECKER && !shader.COMPLEXITY ) {
-			if( shader.albedoTextures == null || shader.albedoTextures.isDisposed() ) return false;
-			if( shader.normalTextures == null || shader.normalTextures.isDisposed() ) return false;
-			if( shader.pbrTextures == null || shader.pbrTextures.isDisposed() ) return false;
-			if( shader.surfaceIndexMap == null || shader.surfaceIndexMap.isDisposed() ) return false;
-		}
-
-		return true;
-	}
-}

+ 0 - 22
hrt/prefab/terrain/UnpackWeight.hx

@@ -1,22 +0,0 @@
-package hrt.prefab.terrain;
-
-class UnpackWeight extends h3d.shader.ScreenShader {
-
-	static var SRC = {
-
-		@param var indexMap : Sampler2D;
-		@param var packedWeightTexture : Sampler2D;
-		@param var index : Int;
-
-		function fragment() {
-			pixelColor = vec4(0,0,0,1);
-			var texIndex = indexMap.get(calculatedUV).rgb;
-			var i1 : Int = int(texIndex.r * 255);
-			var i2 : Int = int(texIndex.g * 255);
-			var i3 : Int = int(texIndex.b * 255);
-			if(i1 == index) pixelColor = vec4(vec3(packedWeightTexture.get(calculatedUV).r), 1.0);
-			else if(i2 == index) pixelColor = vec4(vec3(packedWeightTexture.get(calculatedUV).g), 1.0);
-			else if(i3 == index) pixelColor = vec4(vec3(packedWeightTexture.get(calculatedUV).b), 1.0);
-		}
-	}
-}

+ 0 - 733
hrt/prefab/vlm/LightProbe.hx

@@ -1,733 +0,0 @@
-package hrt.prefab.vlm;
-
-import hrt.prefab.l3d.Level3D;
-import h3d.scene.pbr.Environment;
-
-enum abstract ProbeMode(String) {
-	var Texture;
-	var Capture;
-}
-
-enum abstract ProbeFadeMode(String) {
-	var Linear;
-	var Smoothstep;
-	var Pow2;
-}
-
-class DebugView extends hxsl.Shader {
-
-	static var SRC = {
-
-		var pixelColor : Vec4;
-		@param var source : SamplerCube;
-		@param var irrRotation : Vec2;
-		@param var power : Float;
-		var transformedNormal : Vec3;
-
-		function fragment() {
-			var n = vec3(transformedNormal.x * irrRotation.x - transformedNormal.y * irrRotation.y, transformedNormal.x * irrRotation.y + transformedNormal.y * irrRotation.x, transformedNormal.z);
-			var color = source.getLod(n, 0).rgb * power;
-			pixelColor = vec4(color, 1);
-		}
-
-	}
-}
-
-class BoundsFade extends hxsl.Shader {
-
-	static var SRC = {
-
-		@const var SMOOTHSTEP : Bool;
-		@const var POWER2 : Bool;
-
-		@param var scale : Vec3;
-		@param var fadeDist : Float;
-
-		var pixelRelativePosition : Vec3;
-		var pixelColor : Vec4;
-
-		function fragment() {
-			var normalizedPos = abs(pixelRelativePosition) * 2.0;
-			var maxDist = min(min(scale.x - normalizedPos.x * scale.x, scale.y - normalizedPos.y * scale.y), scale.z - normalizedPos.z * scale.z);
-			var fadeAmount = saturate(maxDist / fadeDist);
-			if( SMOOTHSTEP )
-				fadeAmount = smoothstep(0.0, 1.0, fadeAmount);
-			else if( POWER2 )
-				fadeAmount = fadeAmount * fadeAmount;
-			pixelColor.a *= fadeAmount;
-		}
-	};
-
-}
-
-class BoundsClipping extends hxsl.Shader {
-
-	static var SRC = {
-
-		@global var global : {
-			@perObject var modelViewInverse : Mat4;
-		};
-
-		var transformedPosition : Vec3;
-		var pixelRelativePosition : Vec3;
-
-		function fragment() {
-			pixelRelativePosition = (transformedPosition * global.modelViewInverse.mat3x4()).xyz;
-			if( abs(pixelRelativePosition.x) > 0.5 || abs(pixelRelativePosition.y) > 0.5 || abs(pixelRelativePosition.z) > 0.5 )
-				discard;
-		}
-	};
-
-}
-
-class LightProbeObject extends h3d.scene.Mesh {
-
-	public var env : Environment;
-	public var indirectShader : h3d.shader.pbr.Lighting.Indirect;
-	public var boundClippingShader : BoundsClipping;
-	public var boundFadeShader : BoundsFade;
-	public var fadeDist : Float;
-	public var fadeMode : ProbeFadeMode;
-	public var priority : Int;
-
-	public function new(?parent) {
-		var probeMaterial = h3d.mat.MaterialSetup.current.createMaterial();
-		super(h3d.prim.Cube.defaultUnitCube(), probeMaterial, parent);
-		material.castShadows = false;
-		material.mainPass.setPassName("lightProbe");
-		boundClippingShader = new BoundsClipping();
-		material.mainPass.addShader(boundClippingShader);
-		indirectShader = new h3d.shader.pbr.Lighting.Indirect();
-		indirectShader.drawIndirectDiffuse = true;
-		indirectShader.drawIndirectSpecular = true;
-		indirectShader.showSky = false;
-		indirectShader.gammaCorrect = false;
-		material.mainPass.addShader(indirectShader);
-		material.mainPass.setBlendMode(Alpha);
-		material.mainPass.depthTest = GreaterEqual;
-		material.mainPass.culling = Front;
-		material.mainPass.depthWrite = false;
-
-		boundFadeShader = new BoundsFade();
-		material.mainPass.addShader(boundFadeShader);
-	}
-
-	public function clear() {
-		if( env.env != null )
-			env.env.clear(0);
-		if( env.diffuse != null )
-			env.diffuse.clear(0);
-		if( env.specular != null ) {
-			env.specular.dispose();
-		 	env.specular.alloc();
-		}
-	}
-
-	override function emit( ctx : h3d.scene.RenderContext ) {
-
-		if( env == null || env.diffuse == null || env.specular == null )
-			return;
-
-		indirectShader.cameraPosition = ctx.camera.pos;
-		indirectShader.irrLut = env.lut;
-		indirectShader.irrDiffuse = env.diffuse;
-		indirectShader.irrSpecular = env.specular;
-		indirectShader.irrSpecularLevels = env.specLevels;
-		indirectShader.irrPower = env.power * env.power;
-		indirectShader.irrRotation.set(Math.cos(env.rotation), Math.sin(env.rotation));
-
-		super.emit(ctx);
-	}
-
-	override function sync( ctx : h3d.scene.RenderContext ) {
-		super.sync(ctx);
-
-		var r : h3d.scene.pbr.Renderer = cast ctx.scene.renderer;
-		if( r != null ) {
-			if( material.mainPass.getShader(h3d.shader.pbr.PropsImport) == null )
-				@:privateAccess material.mainPass.addShader(r.pbrProps);
-			var props : h3d.scene.pbr.Renderer.RenderProps = r.props;
-			indirectShader.emissivePower = props.emissive;
-		}
-
-		getAbsPos().getScale(boundFadeShader.scale);
-		getAbsPos()._44 = priority;
-		boundFadeShader.fadeDist = fadeDist;
-		switch fadeMode {
-			case Linear:
-				boundFadeShader.POWER2 = false;
-				boundFadeShader.SMOOTHSTEP = false;
-			case Smoothstep:
-				boundFadeShader.POWER2 = false;
-				boundFadeShader.SMOOTHSTEP = true;
-			case Pow2:
-				boundFadeShader.POWER2 = true;
-				boundFadeShader.SMOOTHSTEP = false;
-		}
-	}
-
-}
-
-@:access(h3d.scene.pbr.Environment)
-class LightProbe extends Object3D {
-
-	// Probe
-	@:s public var mode : ProbeMode = Texture;
-	@:s public var priority : Int = 0;
-
-	// Fade
-	@:s public var fadeDist : Float = 0.0;
-	@:s public var fadeMode : ProbeFadeMode = Linear;
-
-	// Texture Mode
-	@:s public var texturePath : String = null;
-	@:s public var hdrMax : Float = 10.0;
-	@:s public var rotation : Float = 0.0;
-
-	// Capture Mode
-	@:s public var bounce : Int = 1;
-
-	// Shared
-	@:s public var power : Float = 1.0;
-	@:s public var sampleBits : Int = 12;
-	@:s public var diffSize : Int = 16;
-	@:s public var specSize : Int = 64;
-	@:s public var ignoredSpecLevels : Int = 2;
-
-	// Debug
-	@:s public var debugDisplay : Bool = true;
-	@:s public var sphereRadius : Float = 0.5;
-
-	public function new( ?parent : Prefab ) {
-		super(parent);
-		type = "lightProbe";
-
-		// Duplicate Name Fix - Prevent baked data conflict
-		var root : Prefab = this;
-		while( root.parent != null ) {
-			root = root.parent;
-		}
-		var probeList : Array<LightProbe> = cast root.findAll( p -> Std.is(p, LightProbe) ? p : null );
-		var curIndex = 0;
-		var needCheck = true;
-		while( needCheck ) {
-			needCheck = false;
-			for( p in probeList ) {
-				if( p.name != null && p.name.indexOf("_" + curIndex) != -1 ) {
-					curIndex++;
-					needCheck = true;
-					continue;
-				}
-			}
-		}
-		name = "lightProbe_" + curIndex;
-	}
-
-	override function makeInstance( ctx : Context ) : Context {
-		ctx = ctx.clone(this);
-		var lpo = new LightProbeObject(ctx.local3d);
-		lpo.material.castShadows = false;
-		lpo.material.mainPass.setPassName("lightProbe");
-		lpo.ignoreCollide = true;
-		ctx.local3d = lpo;
-		ctx.local3d.name = name;
-
-		#if editor
-		var wire = new h3d.scene.Box(lpo);
-		wire.thickness = 2.0;
-		wire.material.mainPass.setPassName("overlay");
-		wire.name = "wire_select";
-		wire.color = 0xFFFFFF;
-		wire.ignoreCollide = true;
-		wire.material.shadows = false;
-		wire.visible = false;
-		wire.material.mainPass.depthTest = Always;
-
-		var previewSphereDiffuse = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), lpo);
-		previewSphereDiffuse.name = "preview_sphere_diffuse";
-		previewSphereDiffuse.material.mainPass.setPassName("overlay");
-		previewSphereDiffuse.material.mainPass.addShader(new DebugView());
-		previewSphereDiffuse.material.castShadows = false;
-
-		var previewSphereSpecular = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), lpo);
-		previewSphereSpecular.name = "preview_sphere_specular";
-		previewSphereSpecular.material.mainPass.setPassName("overlay");
-		previewSphereSpecular.material.mainPass.addShader(new DebugView());
-		previewSphereSpecular.material.castShadows = false;
-		#end
-
-		updateInstance(ctx, texturePath == null ? null : "texturePath");
-		return ctx;
-	}
-
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		var lpo : LightProbeObject = cast ctx.local3d;
-		lpo.fadeDist = fadeDist;
-		lpo.fadeMode = fadeMode;
-		lpo.priority = priority;
-
-		// Full Reset
-		if( propName == "mode" ) {
-			if( lpo.env != null ) {
-				lpo.env.dispose();
-				lpo.env = null;
-			}
-		}
-
-		switch mode {
-			case Texture:
-				var needCompute = false;
-				if( propName == "texturePath" || propName == "mode" ) {
-					var t = texturePath == null ? null : ctx.loadTexture(texturePath);
-					if( t != null ) {
-						lpo.env = new Environment(t);
-						needCompute = true;
-					}
-				}
-				if( lpo.env != null ) {
-					lpo.env.power = power;
-					lpo.env.hdrMax = hdrMax;
-					lpo.env.rotation = hxd.Math.degToRad(rotation);
-					lpo.env.sampleBits = sampleBits;
-					lpo.env.ignoredSpecLevels = ignoredSpecLevels;
-					if( lpo.env.specSize != specSize ) {
-						if( lpo.env.specular != null ) lpo.env.specular.dispose();
-						lpo.env.specular = null;
-						needCompute = true;
-					}
-					lpo.env.specSize = specSize;
-					if( lpo.env.diffSize != diffSize ) {
-						if( lpo.env.diffuse != null ) lpo.env.diffuse.dispose();
-						lpo.env.diffuse = null;
-						needCompute = true;
-					}
-					lpo.env.diffSize = diffSize;
-
-					if( propName == "hdrMax" || propName == "sampleBits" )
-						needCompute = true;
-
-					if( needCompute ) {
-						if( lpo.env.source.flags.has(Loading) )
-							lpo.env.source.waitLoad(lpo.env.compute);
-						else
-							lpo.env.compute();
-					}
-				}
-
-			case Capture:
-
-				var needCompute = false;
-
-				if( lpo.env == null )
-					lpo.env = new Environment(null);
-
-				lpo.env.power = power;
-				lpo.env.sampleBits = sampleBits;
-				lpo.env.ignoredSpecLevels = ignoredSpecLevels;
-
-				if( propName == "sampleBits" || propName == "ignoredSpecLevels" )
-					needCompute = true;
-
-				if( loadBinary(lpo.env, ctx) )
-					needCompute = false; // No Env available with binary load, everything else is already baked
-
-				if( needCompute )
-					lpo.env.compute();
-		}
-
-		updatePreviewSphere(lpo);
-	}
-
-	function updatePreviewSphere( o : h3d.scene.Object ) {
-		#if editor
-		var lpo : LightProbeObject = cast o;
-		var previewSphereDiffuse : h3d.scene.Mesh = Std.downcast(lpo.find( o -> o.name == "preview_sphere_diffuse" ? o : null), h3d.scene.Mesh);
-		var previewSphereSpecular : h3d.scene.Mesh = Std.downcast(lpo.find( o -> o.name == "preview_sphere_specular" ? o : null), h3d.scene.Mesh);
-		var parentScale = lpo.getAbsPos().getScale();
-
-		// Don't use scale from parent for preview phere
-		function updateScale( m : h3d.scene.Mesh ) {
-			m.scaleX = sphereRadius / parentScale.x;
-			m.scaleY = sphereRadius / parentScale.y;
-			m.scaleZ = sphereRadius / parentScale.z;
-		}
-
-		if( previewSphereDiffuse != null ) {
-			previewSphereDiffuse.visible = debugDisplay;
-			previewSphereDiffuse.x = (sphereRadius + (sphereRadius * 0.5)) / parentScale.x;
-			var s = previewSphereDiffuse.material.mainPass.getShader(DebugView);
-			if( lpo.env != null ) {
-				if( lpo.env.source != null && lpo.env.source.flags.has(Loading) )
-					lpo.env.source.waitLoad( () ->  s.source = lpo.env.diffuse );
-				else
-					s.source = lpo.env.diffuse;
-				s.irrRotation.set(Math.cos(lpo.env.rotation), Math.sin(lpo.env.rotation));
-				s.power = lpo.env.power * lpo.env.power;
-			}
-
-			updateScale(previewSphereDiffuse);
-		}
-		if( previewSphereSpecular != null ) {
-			previewSphereSpecular.visible = debugDisplay;
-			previewSphereSpecular.x = -(sphereRadius + (sphereRadius * 0.5)) / parentScale.x;
-			var s = previewSphereSpecular.material.mainPass.getShader(DebugView);
-			if( lpo.env != null ) {
-				if( lpo.env.source != null && lpo.env.source.flags.has(Loading) )
-					lpo.env.source.waitLoad( () -> s.source = lpo.env.specular );
-				else
-					s.source = lpo.env.specular;
-				s.irrRotation.set(Math.cos(lpo.env.rotation), Math.sin(lpo.env.rotation));
-				s.power = lpo.env.power * lpo.env.power;
-			}
-
-			updateScale(previewSphereSpecular);
-		}
-		#end
-	}
-
-	override function applyTransform( o : h3d.scene.Object ) {
-		super.applyTransform(o);
-		updatePreviewSphere(o);
-	}
-
-	function saveBinary( env : Environment, ctx : Context ) {
-
-		var diffuse = hxd.Pixels.toDDSLayers([for( i in 0...6 ) env.diffuse.capturePixels(i)], true);
-		var specular = hxd.Pixels.toDDSLayers([for( i in 0...6 ) for( mip in 0...env.getMipLevels() ) env.specular.capturePixels(i,mip)],true);
-
-		var totalBytes = 4 + 4; //ignoredSpecLevels + sampleBits
-		var data = haxe.io.Bytes.alloc(totalBytes);
-		var curPos = 0;
-		data.setInt32(curPos, env.sampleBits); 			curPos += 4;
-		data.setInt32(curPos, env.ignoredSpecLevels); 	curPos += 4;
-
-		ctx.shared.savePrefabDat("envd", "dds", name, diffuse);
-		ctx.shared.savePrefabDat("envs", "dds", name, specular);
-		ctx.shared.savePrefabDat("data", "bake", name, data);
-	}
-
-	function loadBinary( env : Environment, ctx : Context ) {
-
-		var diffuse = ctx.shared.loadPrefabDat("envd", "dds", name);
-		var specular = ctx.shared.loadPrefabDat("envs", "dds", name);
-		var data = ctx.shared.loadPrefabDat("data", "bake", name);
-
-		if( data == null || specular == null || diffuse == null )
-			return false;
-
-		env.diffuse = diffuse.toImage().toTexture();
-		env.diffSize = env.diffuse.width;
-		env.specular = specular.toImage().toTexture();
-		env.specular.mipMap = Linear;
-		env.specSize = env.specular.width;
-		env.specLevels = @:privateAccess env.getMipLevels() - env.ignoredSpecLevels;
-
-		var curPos = 0;
-		var bytes = data.entry.getBytes();
-		env.sampleBits = bytes.getInt32(curPos); 		curPos += 4;
-		env.ignoredSpecLevels = bytes.getInt32(curPos); curPos += 4;
-
-		return true;
-	}
-
-	#if editor
-
-	function exportData( env : Environment ) : haxe.io.Bytes {
-
-		var diffusePixels : Array<hxd.Pixels> = [ for( i in 0 ... 6) env.diffuse.capturePixels(i) ];
-		var mipLevels = env.getMipLevels();
-		var specularPixels : Array<hxd.Pixels> =
-		 [
-			for( i in 0 ... 6 ) {
-				for( m in 0 ... mipLevels ) {
-					env.specular.capturePixels(i, m);
-				}
-			}
-		];
-
-		var totalBytes = 0;
-		totalBytes += 4 + 4 + 4 + 4; // diffSize + specSize + ignoredSpecLevels + sampleBits
-		for( p in diffusePixels )
-			totalBytes += p.bytes.length;
-		for( p in specularPixels )
-			totalBytes += p.bytes.length;
-
-		var bytes = haxe.io.Bytes.alloc(totalBytes);
-
-		var curPos = 0;
-		bytes.setInt32(curPos, env.sampleBits); 		curPos += 4;
-		bytes.setInt32(curPos, env.diffSize); 			curPos += 4;
-		bytes.setInt32(curPos, env.specSize); 			curPos += 4;
-		bytes.setInt32(curPos, env.ignoredSpecLevels); 	curPos += 4;
-
-		for( p in diffusePixels ) {
-			bytes.blit(curPos, p.bytes, 0, p.bytes.length);
-			curPos += p.bytes.length;
-		}
-
-		for( p in specularPixels ) {
-			bytes.blit(curPos, p.bytes, 0, p.bytes.length);
-			curPos += p.bytes.length;
-		}
-
-		return bytes;
-	}
-
-	function importData( env : Environment, bytes : haxe.io.Bytes ) {
-
-		var curPos = 0;
-		env.sampleBits = bytes.getInt32(curPos); 		curPos += 4;
-		env.diffSize = bytes.getInt32(curPos); 			curPos += 4;
-		env.specSize = bytes.getInt32(curPos); 			curPos += 4;
-		env.ignoredSpecLevels = bytes.getInt32(curPos); curPos += 4;
-		env.createTextures();
-
-		var diffSize = hxd.Pixels.calcStride(env.diffuse.width, env.diffuse.format) * env.diffuse.height;
-		for( i in 0 ... 6 ) {
-			var diffByte = bytes.sub(curPos, diffSize);
-			curPos += diffByte.length;
-			var diffPixels = new hxd.Pixels(env.diffuse.width, env.diffuse.height, diffByte, env.diffuse.format);
-			env.diffuse.uploadPixels(diffPixels, 0, i);
-		}
-
-		var mipLevels = env.getMipLevels();
-		env.specLevels = mipLevels - ignoredSpecLevels;
-		for( i in 0 ... 6 ) {
-			for( m in 0 ... mipLevels ) {
-				var mipMapSize = hxd.Pixels.calcStride(env.specular.width >> m, env.specular.format) * env.specular.height >> m;
-				var specByte = bytes.sub(curPos, mipMapSize);
-				curPos += specByte.length;
-				var specPixels = new hxd.Pixels(env.specular.width >> m, env.specular.height >> m, specByte, env.specular.format);
-				env.specular.uploadPixels(specPixels, m, i);
-			}
-		}
-	}
-
-	override function getHideProps() : HideProps {
-		return { icon : "map-o", name : "LightProbe" };
-	}
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		var w = ctx.local3d.find( o -> o.name == "wire_select" ? o : null);
-		if( w != null )
-			w.visible = b;
-		return true;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-
-		var captureModeParams =
-		'<div class="group" name="Environment" >
-			<dt>Power</dt><dd><input type="range" min="0" max="10" field="power"/></dd>
-			<dt>Bounce</dt><dd><input type="range" min="1" max="3" step="1" field="bounce"/></dd>
-			<br>
-			<div align="center">
-				<input type="button" value="Bake" class="bake" />
-			</div>
-			<div align="center">
-				<input type="button" value="Clear" class="clear" />
-			</div>
-			<br>
-			<div align="center">
-				<input type="button" value="Export" class="export" />
-			</div>
-			<div align="center">
-				<input type="button" value="Import" class="import" />
-			</div>
-			<br>
-		</div>
-		<div class="group" name="Resolution">
-			<dl>
-				<dt>Diffuse</dt><dd><input type="range" min="1" max="512" step="1" field="diffSize"/></dd>
-				<dt>Specular</dt><dd><input type="range" min="1" max="2048" step="1" field="specSize"/></dd>
-				<dt>Sample Count</dt><dd><input type="range" min="1" max="12" step="1" field="sampleBits"/></dd>
-				<dt>Ignored Spec Levels</dt><dd><input type="range" min="0" max="3" step="1" field="ignoredSpecLevels"/></dd>
-			</dl>
-		</div>';
-
-		var textureModeParams =
-		'<div class="group" name="Environment">
-			<dl>
-				<dt>Texture</dt><dd><input type="texturepath" field="texturePath"/></dd>
-				<dt>Rotation</dt><dd><input type="range" min="0" max="360" field="rotation"/></dd>
-				<dt>Power</dt><dd><input type="range" min="0" max="10" field="power"/></dd>
-			</dl>
-		</div>
-		<div class="group" name="Resolution">
-			<dl>
-				<dt>Diffuse</dt><dd><input type="range" min="1" max="512" step="1" field="diffSize"/></dd>
-				<dt>Specular</dt><dd><input type="range" min="1" max="2048" step="1" field="specSize"/></dd>
-				<dt>Sample Count</dt><dd><input type="range" min="1" max="12" step="1" field="sampleBits"/></dd>
-				<dt>Ignored Spec Levels</dt><dd><input type="range" min="0" max="3" step="1" field="ignoredSpecLevels"/></dd>
-			</dl>
-		</div>
-		<div class="group" name="HDR">
-			<dl>
-				<dt>Threshold</dt><dd><input type="range" min="0" max="1" step="0.1" field="threshold"/></dd>
-				<dt>Scale</dt><dd><input type="range" min="0" max="10" field="scale"/></dd>
-			</dl>
-		</div>';
-
-		var props = new hide.Element('
-			<div class="group" name="Probe">
-				<dl>
-					<dt>Mode</dt>
-					<dd>
-						<select field="mode">
-							<option value="Texture">Texture</option>
-							<option value="Capture">Capture</option>
-						</select>
-					</dd>
-					<dt>Priority</dt><dd><input type="range" min="0" max="10" step="1" field="priority"/></dd>
-				</dl>
-			</div>
-			' + (mode == Texture ? textureModeParams : captureModeParams) + '
-			<div class="group" name="Fade">
-				<dl>
-					<dt>Mode</dt>
-						<dd>
-							<select field="fadeMode">
-								<option value="Linear">Linear</option>
-								<option value="Smoothstep">SmoothStep</option>
-								<option value="Pow2">Power</option>
-							</select>
-						</dd>
-					<dt>Distance</dt><dd><input type="range" min="0" max="10" field="fadeDist"/></dd>
-				</dl>
-			</div>
-			<div class="group" name="Debug">
-				<dl>
-					<dt>Debug Display</dt><dd><input type="checkbox" field="debugDisplay"/></dd>
-					<dt>Sphere Radius</dt><dd><input type="range" min="0.1" max="4" field="sphereRadius"/></dd>
-				</dl>
-			</div>
-		');
-		ctx.properties.add(props, this, function(pname) {
-			ctx.onChange(this, pname);
-			if( pname == "mode" )
-				ctx.rebuildProperties();
-		});
-
-		var clearButton = props.find(".clear");
-		if( clearButton != null ) {
-			clearButton.click(function(_) {
-				var lpo : LightProbeObject = cast ctx.getContext(this).local3d;
-				lpo.env.createTextures();
-				lpo.clear();
-				ctx.properties.undo.change(Custom(function(undo) {
-					// TO DO
-				}));
-			});
-		}
-
-		var exportButton = props.find(".export");
-		if( exportButton != null ) {
-			exportButton.click(function(_) {
-
-				var lpo : LightProbeObject = cast ctx.getContext(this).local3d;
-				if( lpo.env == null || lpo.env.specular == null || lpo.env.diffuse == null ) {
-					hide.Ide.inst.message("Capture is empty.");
-					return;
-				}
-
-				var data = exportData(lpo.env);
-				function saveData( name : String ) {
-					var path = ctx.ide.getPath(name)+"/"+this.name+"_export.bake";
-					sys.io.File.saveBytes(path, data);
-				}
-				ctx.ide.chooseDirectory(saveData);
-
-			});
-		}
-
-		var importButton = props.find(".import");
-		if( importButton != null ) {
-			importButton.click(function(_) {
-
-				var lpo : LightProbeObject = cast ctx.getContext(this).local3d;
-
-				function loadData( name : String ) {
-
-					if( name == "null" )
-						return;
-
-					var b = hxd.res.Loader.currentInstance.load(name).entry.getBytes();
-
-					if( lpo.env != null )
-						lpo.env.dispose();
-
-					lpo.env = new Environment(null);
-					importData(lpo.env, b);
-
-					// Upate the prefab
-					sampleBits = lpo.env.sampleBits;
-					diffSize = lpo.env.diffSize;
-					specSize = lpo.env.specSize;
-					ignoredSpecLevels = lpo.env.ignoredSpecLevels;
-
-					// Save the import
-					ctx.rootContext.shared.savePrefabDat("probe", "bake", this.name, b);
-
-					ctx.onChange(this, null);
-					ctx.rebuildProperties();
-				}
-
-				ctx.ide.chooseFile(["bake"], loadData);
-
-				ctx.properties.undo.change(Custom(function(undo) {
-					// TO DO
-				}));
-
-			});
-		}
-
-		var bakeButton = props.find(".bake");
-		if( bakeButton != null ) {
-			bakeButton.click(function(_) {
-
-				var lpo : LightProbeObject = cast ctx.getContext(this).local3d;
-				var captureSize = specSize;
-
-				// Start with a black texture, need to override the default env
-				lpo.env.createTextures();
-				lpo.clear();
-
-				if( lpo.env.env == null || lpo.env.env.width != captureSize ) {
-					if( lpo.env.env != null )
-						lpo.env.env.dispose();
-					lpo.env.env = new h3d.mat.Texture(captureSize, captureSize, [Cube, Target], RGBA32F);
-				}
-
-				var probeBaker = new ProbeBaker();
-				if( bounce > 1 ) {
-					var tmpTexture = new h3d.mat.Texture(captureSize, captureSize, [Cube, Target], RGBA32F);
-					var curCapture : h3d.mat.Texture = tmpTexture;
-					for( b in 0 ... bounce ) {
-						probeBaker.captureEnvironment(lpo.getAbsPos().getPosition(), captureSize, ctx.scene.s3d, curCapture);
-						var tmp = lpo.env.env;
-						lpo.env.env = curCapture;
-						lpo.env.compute();
-						curCapture = tmp;
-					}
-					curCapture.dispose();
-				}
-				else {
-					probeBaker.captureEnvironment(lpo.getAbsPos().getPosition(), captureSize, ctx.scene.s3d, lpo.env.env);
-					lpo.env.compute();
-				}
-
-				probeBaker.dispose();
-
-				saveBinary(lpo.env, ctx.rootContext);
-
-				ctx.onChange(this, null);
-			});
-		}
-	}
-
-	#end
-
-	static var _ = Library.register("lightProbe", LightProbe);
-}

+ 0 - 310
hrt/prefab/vlm/ProbeBaker.hx

@@ -1,310 +0,0 @@
-package hrt.prefab.vlm;
-
-import hrt.prefab.vlm.LightProbe.LightProbeObject;
-
-class ProbeBaker {
-
-	public var useGPU = false;
-
-	// Tmp cube texture for rendring environment
-	var envMap : h3d.mat.Texture;
-
-	// Params for CubeMap rendering
-	var customCamera : h3d.Camera;
-	var cubeDir = [ h3d.Matrix.L([0,0,-1,0, 0,1,0,0, -1,-1,1,0]),
-					h3d.Matrix.L([0,0,1,0, 0,1,0,0, 1,-1,-1,0]),
-	 				h3d.Matrix.L([-1,0,0,0, 0,0,1,0, 1,-1,-1,0]),
-	 				h3d.Matrix.L([-1,0,0,0, 0,0,-1,0, 1,1,1,0]),
-				 	h3d.Matrix.L([-1,0,0,0, 0,1,0,0, 1,-1,1,0]),
-				 	h3d.Matrix.L([1,0,0,0, 0,1,0,0, -1,-1,-1,0]) ];
-
-	// Output for SH computation on GPU
-	var computeSH : h3d.pass.ScreenFx<hrt.shader.ComputeSH>;
-	var output0 : h3d.mat.Texture;
-	var output1 : h3d.mat.Texture;
-	var output2 : h3d.mat.Texture;
-	var output3 : h3d.mat.Texture;
-	var output4 : h3d.mat.Texture;
-	var output5 : h3d.mat.Texture;
-	var output6 : h3d.mat.Texture;
-	var output7 : h3d.mat.Texture;
-	var textureArray: Array<h3d.mat.Texture>;
-
-	// Tmp Buffer
-	var pixels : hxd.Pixels = null;
-	var prim : h3d.prim.Plane2D;
-
-	public function new(){
-		customCamera = new h3d.Camera();
-		customCamera.screenRatio = 1.0;
-		customCamera.fovY = 90;
-		customCamera.zNear = 0.01;
-		customCamera.zFar = 4000;
-	}
-
-	public function dispose() {
-		if( envMap != null ) {
-			envMap.dispose();
-			envMap = null;
-		}
-		if(output0 != null) output0.dispose();
-		if(output1 != null) output1.dispose();
-		if(output2 != null) output2.dispose();
-		if(output3 != null) output3.dispose();
-		if(output4 != null) output4.dispose();
-		if(output5 != null) output5.dispose();
-		if(output6 != null) output6.dispose();
-		if(output7 != null) output7.dispose();
-		if(prim != null) prim.dispose();
-	}
-
-	public function captureEnvironment( position : h3d.Vector, resolution : Int, scene : h3d.scene.Scene, output : h3d.mat.Texture ) {
-		var pbrRenderer = Std.downcast(scene.renderer, h3d.scene.pbr.Renderer);
-
-		var prevCam = scene.camera;
-		var prevRenderMode = pbrRenderer.renderMode;
-		pbrRenderer.renderMode = LightProbe;
-		scene.camera = customCamera;
-
-		// Bake a Probe
-		var engine = h3d.Engine.getCurrent();
-		for( f in 0 ... 6 ) {
-			engine.begin();
-			customCamera.setCubeMap(f, position);
-			customCamera.update();
-			scene.camera = customCamera;
-			engine.pushTarget(output, f);
-			engine.clear(0,1,0);
-			scene.render(engine);
-			engine.popTarget();
-		}
-
-		scene.camera = prevCam;
-		pbrRenderer.renderMode = prevRenderMode;
-	}
-
-	function setupEnvMap( resolution : Int ) {
-		if( envMap == null || resolution != envMap.width || resolution != envMap.height ) {
-			if( envMap != null ) envMap.dispose();
-			envMap = new h3d.mat.Texture(resolution, resolution, [Cube, Target], RGBA32F);
-		}
-	}
-
-	function setupShaderOutput( order : Int, probeCount: Int ) {
-
-		if( order > 3 || order <= 0 ){ throw "Not Supported"; return; }
-
-		if( !useGPU )
-			probeCount = 1;
-
-		if( order >= 1 && (output0 == null || output0.width != probeCount)){
-			if(output0 != null) output0.dispose();
-			output0 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-		}
-		if( order >= 2 && (output1 == null || output1.width != probeCount)){
-			if(output1 != null) output1.dispose();
-			if(output2 != null) output2.dispose();
-			if(output3 != null) output3.dispose();
-			output1 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output2 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output3 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-		}
-		if( order >= 3 && (output4 == null || output4.width != probeCount)){
-			if(output4 != null) output4.dispose();
-			if(output5 != null) output5.dispose();
-			if(output6 != null) output6.dispose();
-			if(output7 != null) output7.dispose();
-			output4 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output5 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output6 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-			output7 = new h3d.mat.Texture(probeCount, 1, [Target], RGBA32F);
-		}
-
-		switch(order){
-			case 1:
-				textureArray = [output0];
-				computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[
-								Vec4([Value("out.coefL00", 3), Const(0)])]);
-			case 2:
-				textureArray = [output0, output1, output2, output3];
-				computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[
-							Vec4([Value("out.coefL00", 3), Const(0)]),
-							Vec4([Value("out.coefL1n1", 3), Const(0)]),
-							Vec4([Value("out.coefL10", 3), Const(0)]),
-							Vec4([Value("out.coefL11", 3), Const(0)])]);
-
-			case 3:
-				function getSwiz(name,comp) : hxsl.Output { return Swiz(Value(name,3),[comp]); }
-				textureArray = [output0, output1, output2, output3, output4, output5, output6, output7];
-				computeSH = new h3d.pass.ScreenFx(new hrt.shader.ComputeSH(),[
-							Vec4([Value("out.coefL00", 3), getSwiz("out.coefL22",X) ]),
-							Vec4([Value("out.coefL1n1", 3), getSwiz("out.coefL22",Y) ]),
-							Vec4([Value("out.coefL10", 3), getSwiz("out.coefL22",Z) ]),
-							Vec4([Value("out.coefL11", 3), Const(0)]),
-							Vec4([Value("out.coefL2n2", 3), Const(0)]),
-							Vec4([Value("out.coefL2n1", 3), Const(0)]),
-							Vec4([Value("out.coefL20", 3), Const(0)]),
-							Vec4([Value("out.coefL21", 3), Const(0)])]);
-		}
-	}
-
-	function drawSHIntoTexture(renderer : h3d.scene.Renderer, env : h3d.mat.Texture, order : Int, probeIndex: Int) {
-		if( prim == null ){
-			prim = new h3d.prim.Plane2D();
-		}
-
-		function setPrimPos( index : Int ){
-			var v = new hxd.FloatBuffer();
-			var pixelSize = (1.0 / output0.width);
-			var translation =  pixelSize * index * 2;
-			var posX = -1.0 + translation;
-			v.push( posX ) ; v.push( -1 ); v.push(0); v.push(0);
-			v.push( posX ); v.push( 1 ); v.push(0); v.push(0);
-			v.push( posX + pixelSize * 2 ); v.push( -1 ); v.push(0); v.push(0);
-			v.push( posX + pixelSize * 2 ); v.push( 1 ); v.push(0); v.push(0);
-			prim.buffer = h3d.Buffer.ofFloats(v, 4, [Quads, RawFormat]);
-		}
-		setPrimPos(probeIndex);
-
-		@:privateAccess renderer.ctx.engine = h3d.Engine.getCurrent();
-		@:privateAccess renderer.setTargets(textureArray);
-		computeSH.shader.ORDER = order;
-		computeSH.shader.width = env.width;
-		computeSH.shader.environment = env;
-		computeSH.shader.cubeDir = cubeDir;
-		computeSH.primitive = prim;
-		computeSH.render();
-		@:privateAccess renderer.resetTarget();
-		@:privateAccess renderer.ctx.engine.flushTarget();
-	}
-
-	function convertOuputTexturesIntoSH( volumetricLightMap : hrt.prefab.vlm.VolumetricMesh, pixelsOut : hxd.Pixels ) {
-
-		var order = volumetricLightMap.shOrder;
-		var sh = new hrt.prefab.vlm.SphericalHarmonic(order);
-		var coefCount = order * order;
-		var maxCoef : Int = Std.int(Math.min(8, coefCount));
-
-		for(coef in 0 ... maxCoef){
-			var pixels = textureArray[coef].capturePixels();
-			for( index in 0 ... pixels.width){
-				var coefs : h3d.Vector = pixels.getPixelF(index, 0);
-				var coords = volumetricLightMap.getProbeCoords(index);
-				var u = coords.x + volumetricLightMap.probeCount.x * coef;
-				var v = coords.y + coords.z * volumetricLightMap.probeCount.y;
-				pixelsOut.setPixelF(u, v, new h3d.Vector(coefs.r, coefs.g, coefs.b, 0));
-
-				// Last coefs is inside the alpha channel
-				if( order == 3 ){
-					var u = coords.x + volumetricLightMap.probeCount.x * 8;
-					var v = coords.y + coords.z * volumetricLightMap.probeCount.y;
-					var prev = pixelsOut.getPixelF(u, v);
-					if( coef == 0 ){ prev.r = coefs.a; }
-					if( coef == 1 ){ prev.g = coefs.a; }
-					if( coef == 2 ){ prev.b = coefs.a; }
-					pixelsOut.setPixelF(u, v, prev);
-				}
-			}
-		}
-	}
-
-	function convertEnvIntoSH_CPU( env : h3d.mat.Texture, order : Int ) : hrt.prefab.vlm.SphericalHarmonic {
-		var coefCount = order * order;
-		var sphericalHarmonic = new hrt.prefab.vlm.SphericalHarmonic(order);
-		var face : hxd.Pixels;
-		var weightSum = 0.0;
-		var invWidth = 1.0 / env.width;
-		var shData : Array<Float> = [for ( value in 0...coefCount ) 0];
-
-		for( f in 0...6 ) {
-			face = env.capturePixels(f, 0);
-			for (u in 0...face.width) {
-				var fU : Float = (u / face.width ) * 2 - 1;// Texture coordinate U in range [-1 to 1]
-				fU *= fU;
-				var uCoord = 2.0 * u * invWidth + invWidth;
-				for (v in 0...face.width) {
-        			var fV : Float = (v / face.height ) * 2 - 1;// Texture coordinate V in range [-1 to 1]
-					fV *= fV;
-					var vCoord = 2.0 * v * invWidth + invWidth;
-					var dir = getDir(uCoord, vCoord, f);// Get direction from center of cube texture to current texel
-           			var diffSolid = 4.0 / ((1.0 + fU + fV) * Math.sqrt(1.0 + fU + fV));	// Scale factor depending on distance from center of the face
-					weightSum += diffSolid;
-					var color = face.getPixelF(u,v);// Get color from the current face
-					evalSH(order, dir, shData);// Calculate coefficients of spherical harmonics for current direction
-					for(i in 0...coefCount){
-						sphericalHarmonic.coefR[i] += shData[i] * color.r * diffSolid;
-						sphericalHarmonic.coefG[i] += shData[i] * color.g * diffSolid;
-						sphericalHarmonic.coefB[i] += shData[i] * color.b * diffSolid;
-					}
-				}
-			}
-		}
-		// Final scale for coefficients
-		var normProj = (4.0 * Math.PI) / weightSum;
-		for( i in 0...coefCount ){
-			sphericalHarmonic.coefR[i] *= normProj;
-			sphericalHarmonic.coefG[i] *= normProj;
-			sphericalHarmonic.coefB[i] *= normProj;
-		}
-		return sphericalHarmonic;
-	}
-
-	inline function evalSH( order : Int, dir : h3d.Vector, shData : Array<Float> ) {
-		for (l in 0...order) {
-       		for (m in -l...l+1) {
-				shData[getIndex(l, m)] = evalCoef(l, m, dir);
-			}
-		}
-	}
-
-	inline function getIndex( l : Int, m :Int ) : Int {
-		return l * (l + 1) + m;
-	}
-
-	inline function getDir( u : Float, v : Float, face : Int ) : h3d.Vector {
-		var dir = new h3d.Vector();
-		switch( face ) {
-			case 0: dir.x = -1.0; dir.y = -1.0 + v; dir.z = 1.0 - u;
-			case 1: dir.x = 1.0; dir.y = -1.0 + v; dir.z = -1.0 + u;
-			case 2: dir.x = 1.0 - u; dir.y = -1.0; dir.z = -1.0 + v;
-			case 3: dir.x = 1.0 - u; dir.y = 1.0; dir.z = 1.0 - v;
-			case 4: dir.x = 1.0 - u;  dir.y = -1.0 + v; dir.z = 1.0;
-			case 5: dir.x = -1.0 + u; dir.y = -1.0 + v;  dir.z = -1.0;
-			default:
-		}
-		dir.normalizeFast();
-		return dir;
-	}
-
-	inline function evalCoef( l : Int, m : Int, dir : h3d.Vector ) : Float {
-		// Coef from Stupid Spherical Harmonics (SH) Peter-Pike Sloan Microsoft Corporation
-		return switch [l,m] {
-			case[0,0]:	0.282095; // 0.5 * sqrt(1/pi)
-			case[1,-1]:	-0.488603 * dir.y;  // -sqrt(3/(4pi)) * y
-			case[1,0]:	0.488603 * dir.z; // sqrt(3/(4pi)) * z
-			case[1,1]:	-0.488603 * dir.x; // -sqrt(3/(4pi)) * x
-			case[2,-2]:	1.092548 * dir.y * dir.x;// 0.5 * sqrt(15/pi) * y * x
-			case[2,-1]:	-1.092548 * dir.y * dir.z; // -0.5 * sqrt(15/pi) * y * z
-			case[2,0]:	0.315392 * (-dir.x * dir.x - dir.y * dir.y + 2.0 * dir.z * dir.z);// 0.25 * sqrt(5/pi) * (-x^2-y^2+2z^2)
-			case[2,1]:  -1.092548 * dir.x * dir.z; // -0.5 * sqrt(15/pi) * x * z
-			case[2,2]:	0.546274 * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(15/pi) * (x^2 - y^2)
-			case[3,-3]:	-0.590044 * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y);// -0.25 * sqrt(35/(2pi)) * y * (3x^2 - y^2)
-			case[3,-2]: 2.890611 * dir.x * dir.y * dir.z; // 0.5 * sqrt(105/pi) * x * y * z
-			case[3,-1]: -0.457046 * dir.y * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * y * (4z^2-x^2-y^2)
-			case[3,0]:  0.373176 * dir.z * (2.0 * dir.z * dir.z - 3.0 * dir.x * dir.x - 3.0 * dir.y * dir.y);  // 0.25 * sqrt(7/pi) * z * (2z^2 - 3x^2 - 3y^2)
-			case[3,1]:	-0.457046 * dir.x * (4.0 * dir.z * dir.z - dir.x * dir.x - dir.y * dir.y); // -0.25 * sqrt(21/(2pi)) * x * (4z^2-x^2-y^2)
-			case[3,2]:  1.445306 * dir.z * (dir.x * dir.x - dir.y * dir.y); // 0.25 * sqrt(105/pi) * z * (x^2 - y^2)
-			case[3,3]:	-0.590044 * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y); // -0.25 * sqrt(35/(2pi)) * x * (x^2-3y^2)
-			case[4,-4]: 2.503343 * dir.x * dir.y * (dir.x * dir.x - dir.y * dir.y);// 0.75 * sqrt(35/pi) * x * y * (x^2-y^2)
-			case[4,-3]: -1.770131 * dir.y * dir.z * (3.0 * dir.x * dir.x - dir.y * dir.y); // -0.75 * sqrt(35/(2pi)) * y * z * (3x^2-y^2)
-			case[4,-2]: 0.946175 * dir.x * dir.y * (7.0 * dir.z * dir.z - 1.0);// 0.75 * sqrt(5/pi) * x * y * (7z^2-1)
-			case[4,-1]: -0.669047 * dir.y * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * y * z * (7z^2-3)
-			case[4,0]:  0.105786 * (35.0 * dir.z * dir.z * dir.z * dir.z - 30.0 * dir.z * dir.z + 3.0);// 3/16 * sqrt(1/pi) * (35z^4-30z^2+3)
-			case[4,1]:  -0.669047 * dir.x * dir.z * (7.0 * dir.z * dir.z - 3.0);// -0.75 * sqrt(5/(2pi)) * x * z * (7z^2-3)
-			case[4,2]:  0.473087 * (dir.x * dir.x - dir.y * dir.y) * (7.0 * dir.z * dir.z - 1.0);// 3/8 * sqrt(5/pi) * (x^2 - y^2) * (7z^2 - 1)
-			case[4,3]:  -1.770131 * dir.x * dir.z * (dir.x * dir.x - 3.0 * dir.y * dir.y);// -0.75 * sqrt(35/(2pi)) * x * z * (x^2 - 3y^2)
-			case[4,4]:  0.625836 * (dir.x * dir.x * (dir.x * dir.x - 3.0 * dir.y * dir.y) - dir.y * dir.y * (3.0 * dir.x * dir.x - dir.y * dir.y)); // 3/16*sqrt(35/pi) * (x^2 * (x^2 - 3y^2) - y^2 * (3x^2 - y^2))
-			default: 0;
-		}
-	}
-}

+ 0 - 17
hrt/prefab/vlm/SphericalHarmonic.hx

@@ -1,17 +0,0 @@
-package hrt.prefab.vlm;
-
-class SphericalHarmonic {
-
-	public var coefR : Array<Float> = [];
-	public var coefG : Array<Float> = [];
-	public var coefB : Array<Float> = [];
-	public var order : Int;
-
-	public function new(order:Int) {
-		this.order = order;
-		var coefCount = order * order;
-		coefR = [for (value in 0...coefCount) 0];
-		coefG = [for (value in 0...coefCount) 0];
-		coefB = [for (value in 0...coefCount) 0];
-	}
-}

+ 0 - 297
hrt/prefab/vlm/VolumetricLightmap.hx

@@ -1,297 +0,0 @@
-package hrt.prefab.vlm;
-
-class VolumetricLightmap extends Object3D {
-
-	@:s var voxelsize_x : Float = 1.0;
-	@:s var voxelsize_y : Float = 1.0;
-	@:s var voxelsize_z : Float = 1.0;
-	@:s var strength :  Float = 1.0;
-	@:s var order : Int = 1;
-
-	public var volumetricLightmap : VolumetricMesh;
-	@:s var useWorldAlignedProbe = false;
-	@:s var displaySH = false;
-	@:s var resolution : Int = 16;
-	var useGPU = true;
-
-	#if editor
-	@:c var displaySH_field = false;
-	var maxOrderBaked = 0;
-	var baker : hide.view.l3d.ProbeBakerProcess;
-	#end
-
-	public function new(?parent) {
-		super(parent);
-		type = "volumetricLightmap";
-	}
-
-	#if editor
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		displaySH_field = displaySH;
-	}
-	#end
-
-	function initProbes(){
-		createDebugPreview();
-	}
-
-	function resetLightmap(){
-		if(volumetricLightmap.lightProbeTexture != null) volumetricLightmap.lightProbeTexture.dispose();
-		volumetricLightmap.lightProbeTexture = null;
-		volumetricLightmap.updateProbeCount();
-		createDebugPreview();
-	}
-
-	function updateVolumetricLightmap(){
-		#if editor
-
-		if(volumetricLightmap == null) return;
-
-		if(volumetricLightmap.voxelSize.x != voxelsize_x || volumetricLightmap.voxelSize.y != voxelsize_y ||volumetricLightmap.voxelSize.z != voxelsize_z){
-			volumetricLightmap.voxelSize = new h3d.Vector(voxelsize_x,voxelsize_y,voxelsize_z);
-			resetLightmap();
-		}
-
-		if(volumetricLightmap.shOrder != order){
-			if(maxOrderBaked >= order){
-				volumetricLightmap.shOrder = order;
-				createDebugPreview();
-			}
-			else{
-				volumetricLightmap.shOrder = order;
-				resetLightmap();
-			}
-		}
-
-		if(volumetricLightmap.useAlignedProb != useWorldAlignedProbe){
-			volumetricLightmap.useAlignedProb = useWorldAlignedProbe;
-			resetLightmap();
-		}
-
-		if(volumetricLightmap.strength != strength){
-			volumetricLightmap.strength = strength;
-		}
-
-		if(displaySH != displaySH_field){
-			displaySH = displaySH_field;
-			if(!displaySH) clearDebugPreview();
-			else createDebugPreview();
-		}
-		#end
-	}
-
-	function clearDebugPreview(){
-		var previewSpheres = volumetricLightmap.findAll(c -> if(c.name == "_previewSphere") c else null);
-		if (previewSpheres != null) {
-			while(previewSpheres.length > 0){
-				previewSpheres[previewSpheres.length- 1].remove();
-				previewSpheres.pop();
-			}
-		}
-	}
-
-	public function createDebugPreview(){
-
-		if(!displaySH) return;
-
-		clearDebugPreview();
-
-		if(volumetricLightmap == null) return;
-
-		var pixels : hxd.Pixels = null;
-		if(volumetricLightmap.lightProbeTexture != null)
-			pixels = volumetricLightmap.lightProbeTexture.capturePixels();
-
-		for( i in 0...volumetricLightmap.getProbeCount()){
-			var previewSphere = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), volumetricLightmap );
-			previewSphere.name = "_previewSphere";
-			previewSphere.material.setDefaultProps("ui");
-			var size = 0.1;
-			previewSphere.scaleX = size/volumetricLightmap.parent.scaleX;
-			previewSphere.scaleY = size/volumetricLightmap.parent.scaleY;
-			previewSphere.scaleZ = size/volumetricLightmap.parent.scaleZ;
-			var probePos = volumetricLightmap.getProbePosition(volumetricLightmap.getProbeCoords(i));
-			volumetricLightmap.globalToLocal(probePos);
-			previewSphere.setPosition(probePos.x, probePos.y, probePos.z);
-			var shader = new hrt.shader.DisplaySH();
-			shader.order = volumetricLightmap.shOrder;
-			shader.strength = volumetricLightmap.strength;
-			var coefCount = volumetricLightmap.getCoefCount();
-			shader.SIZE = coefCount;
-
-			var sh = volumetricLightmap.getProbeSH(volumetricLightmap.getProbeCoords(i), pixels);
-			shader.shCoefsRed = sh.coefR.slice(0, coefCount);
-			shader.shCoefsGreen = sh.coefG.slice(0, coefCount);
-			shader.shCoefsBlue = sh.coefB.slice(0, coefCount);
-
-			previewSphere.material.mainPass.culling = Back;
-			previewSphere.material.shadows = false;
-			previewSphere.material.mainPass.addShader(shader);
-		}
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-
-		if(propName ==  "strength" && displaySH){
-			var previewSpheres = volumetricLightmap.findAll(c -> if(c.name == "_previewSphere") c else null);
-			for(ps in previewSpheres){
-				var mesh = Std.downcast(ps, h3d.scene.Mesh);
-				var shader = mesh.material.mainPass.getShader(hrt.shader.DisplaySH);
-				if(shader != null) shader.strength = volumetricLightmap.strength;
-			}
-		}
-		if( propName != "visible" && propName != "strength" && propName != "order" && propName != "displaySH_field" && propName != "useGPU" &&  propName != "resolution")
-			resetLightmap();
-	}
-
-	override function makeInstance(ctx:Context):Context {
-
-		ctx = ctx.clone(this);
-		var obj = new h3d.scene.Object(ctx.local3d);
-		volumetricLightmap = new hrt.prefab.vlm.VolumetricMesh(obj);
-		volumetricLightmap.ignoreCollide = true;
-		volumetricLightmap.setPosition(-0.5, -0.5, 0);
-		ctx.local3d = obj;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-
-		volumetricLightmap.voxelSize = new h3d.Vector(voxelsize_x,voxelsize_y,voxelsize_z);
-		volumetricLightmap.shOrder = order;
-		volumetricLightmap.useAlignedProb = false;
-		volumetricLightmap.strength = strength;
-
-		var res = ctx.shared.loadPrefabDat("sh", "bake", name);
-		if(res != null) volumetricLightmap.load(res.entry.getBytes());
-
-		#if editor
-		initProbes();
-		#end
-		return ctx;
-	}
-
-	#if editor
-
-	override function getHideProps() : HideProps {
-		return { icon : "map-o", name : "VolumetricLightmap" };
-	}
-
-	override function setSelected( ctx : Context, b : Bool ) {
-		if( b ) {
-			var obj = ctx.shared.contexts.get(this).local3d;
-			var wire = new h3d.scene.Box(volumetricLightmap.lightProbeTexture == null ? 0xFFFF0000 : 0xFFFFFFFF,h3d.col.Bounds.fromValues(-0.5,-0.5,0,1,1,1),obj);
-			wire.name = "_highlight";
-			wire.material.setDefaultProps("ui");
-			wire.ignoreCollide = true;
-			wire.material.shadows = false;
-		} else {
-			for( o in ctx.shared.getObjects(this,h3d.scene.Box) )
-				if( o.name == "_highlight" ) {
-					o.remove();
-					return false;
-				}
-		}
-		return true;
-	}
-
-	override function edit( ctx : EditContext ) {
-		super.edit(ctx);
-		var props = new hide.Element('
-			<div class="group" name="Light Params">
-				<dl>
-				<dt>Strength</dt><dd><input type="range" min="0" max="2" value="0" field="strength"/></dd>
-				<dt>Display SH</dt><dd><input type="checkbox" field="displaySH_field"/></dd>
-				</dl>
-			</div>
-			<div class="group" name="Bake">
-				<dt>SH Order</dt><dd><input type="range" min="1" max="3" value="0" step="1" field="order"/></dd>
-				<dt>Resolution</dt><dd><input type="range" min="1" max="1024" value="0" step="1" field="resolution"/></dd>
-				<dt>Use GPU</dt><dd><input type="checkbox" field="useGPU"/></dd>
-				<dt></dt><dd><input type="button" value="Bake" class="bake"/></dd>
-				<div class="progress">
-					<dt>Baking Process</dt><dd><progress class="bakeProgress" max="1"></progress></dd>
-				</div>
-			</dl></div>
-			<div class="group" name="Voxel Size">
-				<dl>
-					<dt>X</dt><dd><input type="range" min="1" max="10" value="0" field="voxelsize_x"/></dd>
-					<dt>Y</dt><dd><input type="range" min="1" max="10" value="0" field="voxelsize_y"/></dd>
-					<dt>Z</dt><dd><input type="range" min="1" max="10" value="0" field="voxelsize_z"/></dd>
-				</dl>
-			</div>
-		');
-		ctx.properties.add(props, this, function(pname) {
-			updateVolumetricLightmap();
-			ctx.onChange(this, pname);
-		});
-
-		function bakeUpdate(dt:Float){
-			if(baker == null || baker.progress == 1){
-				ctx.removeUpdate(bakeUpdate);
-				baker = null;
-				ctx.rebuildProperties();
-			}
-			else{
-				baker.update(dt);
-				if( baker == null ) return;
-				var props = ctx.getCurrentProps(this);
-				props.find(".bakeProgress").val(baker.progress);
-			}
-		}
-
-		function cancel() {
-			ctx.removeUpdate(bakeUpdate);
-			baker = null;
-			ctx.rebuildProperties();
-		}
-
-		function startedBake() {
-			//var props = ctx.getCurrentProps(this);
-			props.find(".progress").show();
-			props.find(".bake").attr("value","Cancel").off("click").click(function(_) cancel());
-			bakeUpdate(0);
-		}
-
-		props.find(".progress").hide();
-		props.find(".bake").click(function(_) {
-			startBake(ctx, cancel);
-			startedBake();
-			ctx.addUpdate(bakeUpdate);
-		});
-
-		if( baker != null ){
-			startedBake();
-			ctx.addUpdate(bakeUpdate);
-		}
-
-	}
-
-	public function startBake(ctx : EditContext, ?onEnd){
-		maxOrderBaked = order;
-		volumetricLightmap.lastBakedProbeIndex = -1;
-		var s3d = @:privateAccess ctx.rootContext.local3d.getScene();
-		baker = new hide.view.l3d.ProbeBakerProcess(this, resolution, useGPU, 0.032);
-
-		var pbrRenderer = Std.downcast(s3d.renderer, h3d.scene.pbr.Renderer);
-		if(pbrRenderer != null) {
-			if( pbrRenderer.env == null || pbrRenderer.env.env == null || pbrRenderer.env.env.isDisposed() )
-					trace("Environment missing");
-		} else
-			trace("Invalid renderer");
-
-		var sceneData = @:privateAccess ctx.scene.editor.sceneData;
-		baker.init(pbrRenderer.env, sceneData.cloneData(), cast ctx.rootContext.shared, ctx.scene);
-
-		baker.onEnd = function() {
-			if( onEnd != null ) onEnd();
-			var bytes = volumetricLightmap.save();
-			ctx.rootContext.shared.savePrefabDat("sh", "bake", name, bytes);
-			createDebugPreview();
-		}
-	}
-
-	#end
-
-	static var _ = Library.register("volumetricLightmap", VolumetricLightmap);
-}

+ 0 - 176
hrt/prefab/vlm/VolumetricMesh.hx

@@ -1,176 +0,0 @@
-package hrt.prefab.vlm;
-
-class VolumetricMesh extends h3d.scene.Mesh {
-
-	public var lightProbeTexture : h3d.mat.Texture;
-	public var shOrder : Int = 1;
-	public var voxelSize (default, set) : h3d.Vector;
-	public var probeCount : h3d.col.IPoint;
-	public var useAlignedProb : Bool = false;
-	public var strength : Float = 1.;
-
-	public var lastBakedProbeIndex = -1;
-
-	var prim : h3d.prim.Cube;
-
-	var shader : hrt.shader.VolumetricLightmap;
-
-	function set_voxelSize(newSize) :h3d.Vector {
-		voxelSize = newSize;
-		updateProbeCount();
-		return voxelSize;
-	}
-
-	public function new(?parent) {
-		var prim = new h3d.prim.Cube(1,1,1,false);
-		prim.addNormals();
-		super(prim, null, parent);
-		shader = new hrt.shader.VolumetricLightmap();
-		material.mainPass.removeShader(material.mainPass.getShader(h3d.shader.pbr.PropsValues));
-		material.mainPass.addShader(shader);
-		material.mainPass.setPassName("volumetricLightmap");
-		material.mainPass.blend(One, One);
-		material.mainPass.culling = Front;
-		material.mainPass.depth(false, Greater);
-		material.mainPass.enableLights = false;
-		material.castShadows = false;
-		material.shadows = false;
-		material.mainPass.stencil = new h3d.mat.Stencil();
-		material.mainPass.stencil.setFunc(NotEqual, 0x80, 0x80, 0x80);
-		material.mainPass.stencil.setOp(Keep, Keep, Replace);
-		probeCount = new h3d.col.IPoint();
-		voxelSize = new h3d.Vector(1,1,1);
-	}
-
-	public override function clone( ?o : h3d.scene.Object ) : h3d.scene.Object {
-		var vm = o == null ? new VolumetricMesh(null) : cast o;
-		vm.shOrder = shOrder;
-		vm.strength = strength;
-		vm.useAlignedProb = useAlignedProb;
-		vm.lightProbeTexture = lightProbeTexture != null ? lightProbeTexture.clone() : null;
-		vm.probeCount.load(probeCount);
-		vm.voxelSize.load(voxelSize);
-		return vm;
-	}
-
-	public function getProbeSH(coords : h3d.col.IPoint, ?pixels : hxd.Pixels ) : SphericalHarmonic {
-
-		if(lightProbeTexture == null)
-			return new SphericalHarmonic(shOrder);
-
-		if(pixels == null)
-			pixels = lightProbeTexture.capturePixels();
-
-		var sh = new SphericalHarmonic(shOrder);
-
-		var coefCount = getCoefCount();
-		for(c in 0...coefCount){
-			var u = coords.x + probeCount.x * c;
-			var v = coords.y + coords.z * probeCount.y;
-			var color = pixels.getPixelF(u, v);
-			sh.coefR[c] = color.r;
-			sh.coefG[c] = color.g;
-			sh.coefB[c] = color.b;
-		}
-
-		return sh;
-	}
-
-	public inline function getCoefCount() : Int{
-		return shOrder * shOrder;
-	}
-
-	public function getProbePosition(coords : h3d.col.IPoint){
-		var probePos = new h3d.col.Point( coords.x/(probeCount.x - 1),  coords.y/(probeCount.y - 1), coords.z/(probeCount.z - 1));
-		localToGlobal(probePos);
-		return probePos;
-	}
-
-	public function getProbeCoords(i : Int) : h3d.col.IPoint {
-		var coords = new h3d.col.IPoint();
-		coords.z = Std.int(i / (probeCount.x * probeCount.y));
-		coords.y = Std.int((i - coords.z * probeCount.y * probeCount.x) / (probeCount.x));
-		coords.x = Std.int((i - coords.z * probeCount.y * probeCount.x - coords.y * probeCount.x));
-		return coords;
-	}
-
-	public function getProbeCount() {
-		return probeCount.x * probeCount.y * probeCount.z;
-	}
-
-	override function onRemove() {
-		super.onRemove();
-		if( lightProbeTexture != null ) {
-			lightProbeTexture.dispose();
-			lightProbeTexture = null;
-		}
-	}
-
-	public function updateProbeCount(){
-		syncPos();
-		var scale = absPos.getScale();
-		probeCount.set(Std.int(Math.max(1,Math.floor(scale.x/voxelSize.x)) + 1),
-						Std.int(Math.max(1,Math.floor(scale.y/voxelSize.y)) + 1),
-						Std.int(Math.max(1,Math.floor(scale.z/voxelSize.z)) + 1));
-	}
-
-	public function load( bytes : haxe.io.Bytes ) {
-		if( bytes.length == 0 )
-			return false;
-		bytes = try haxe.zip.Uncompress.run(bytes) catch( e : Dynamic ) throw e;
-		var count = getProbeCount();
-		if( bytes.length != count * getCoefCount() * 4 * 4 )
-			return false;
-		lastBakedProbeIndex = count;
-		if( lightProbeTexture != null ) lightProbeTexture.dispose();
-		lightProbeTexture = new h3d.mat.Texture(probeCount.x * getCoefCount(), probeCount.y * probeCount.z, [Dynamic], RGBA32F);
-		lightProbeTexture.filter = Nearest;
-		lightProbeTexture.uploadPixels(new hxd.Pixels(lightProbeTexture.width, lightProbeTexture.height, bytes, RGBA32F));
-		return true;
-	}
-
-	public function save() : haxe.io.Bytes {
-		var data;
-		if( lightProbeTexture == null )
-			data = haxe.io.Bytes.alloc(0);
-		else
-			data = lightProbeTexture.capturePixels().bytes;
-		return haxe.zip.Compress.run(data,9);
-	}
-
-	override function emit(ctx:h3d.scene.RenderContext){
-		if( lightProbeTexture != null ) super.emit(ctx);
-	}
-
-	override function sync(ctx:h3d.scene.RenderContext) {
-		if( lightProbeTexture == null )
-			return;
-		var scale = absPos.getScale();
-		shader.ORDER = shOrder;
-		shader.lightmapInvPos.load(getInvPos());
-		shader.lightmapSize.load(new h3d.Vector(probeCount.x, probeCount.y, probeCount.z));
-		shader.voxelSize.load(new h3d.Vector(scale.x/(probeCount.x - 1), scale.y/(probeCount.y - 1), scale.z/(probeCount.z - 1)));
-		shader.lightProbeTexture = lightProbeTexture;
-		shader.cameraInverseViewProj.load(ctx.camera.getInverseViewProj());
-		shader.cameraPos.load(ctx.camera.pos);
-		shader.strength = strength;
-	}
-
-	public function getWorldAlignment(lightmaps : Array<VolumetricMesh>) : h3d.Vector {
-		var scale = absPos.getScale();
-		var result =  new h3d.Vector(scale.x/(probeCount.x - 1), scale.y/(probeCount.y - 1), scale.z/(probeCount.z - 1));
-		for(i in 0...lightmaps.length){
-			var lsc = lightmaps[i].absPos.getScale();
-			result.x = Math.max(result.x, lsc.x / (lightmaps[i].probeCount.x - 1.0));
-			result.y = Math.max(result.y, lsc.y / (lightmaps[i].probeCount.y - 1.0));
-			result.z = Math.max(result.z, lsc.z / (lightmaps[i].probeCount.z - 1.0));
-		}
-		return result;
-	}
-
-	public function isInsideVolume(worldPos: h3d.col.Point) : Bool {
-		var localPos = worldPos.clone();
-		globalToLocal(localPos);
-		return (localPos.x >= 0 && localPos.y >= 0 && localPos.z >= 0 && localPos.x <= 1 && localPos.y <= 1 && localPos.z <= 1);
-	}
-}