Browse Source

Prefab 2 (#238)

* New Prefab System

* removed todos

* Fix reference returning null object3d when ref is Prefab

* Passed local2d/3d into prefab, removed trace

* Potential fix for currenPath for references

* Instanciate now don't override local2d/d3 if null

* References now ihnerit customMake

* Prefabs copy currentPath on clone

* Change Prefab.createFromPath to loadPath

* Prefab2 : fix spline + meshspray

* Fix ref loading

* Fixed compilation

* Fix model library game compilation

* Fix crash with ref loading

* Fixed render props creation

* Added dispose to Prefab

* Fix compilation

* Moved local2d/3d back into Object2D/Object3D

* Reworked removeInstance and deleteElements

* Make loadPreb relative + fix some load functions

* Fix dispose + check enabled before make with a customMake

* Fix find reference

* Fix some prefabs

* Fixes for reference selection in editor

* Reference: apply transform to the referenced prefab

* Spray: fix makeChild

* Fix getRoot with reference + fix some prefabs

* Fix shader loading in editor

* Fixed set param value

* Fixed mesh spray instancing

* Prefab.instanciate don't override shared.root if already set (Prefab.make does)

* Fx: don't list disabled shaders

* Object3D.getAbsPos3d : getAbsPos using heaps object when instanciated + add followRefs on getAbsPos

* Fix mesh spray spamming refreshes

* Refacto prefab2 makeChildren

* Cleaned up emitter template particle creation

* Fix Object3D.getAbsPos3D (use root3d)

* Fixed removal of materials, restored ctrl+z on delete

* dispose reference

* Removed locald2d/3d from make/instanciate arguments, reworked SharedContext

* Fixed some bugs with fx init and added a way to force init of prefabs without root2d/3d

* Fix compilation after rebase

* Fixed duplicate command in editor

* Reimplemented auto typed make

* Removed usings in Prefab

* Reworked find and findAll, removed obsolette getAll

* Reworked findParent, removed getParent

* Removed findParents (unused)

* Removed refresh, serializeToDynamic/save/load/copy are now private

* Removed getPrefabsByPath, getSerializableProps is now private, removed obsolete serialization functions and commented code

* Removed get prefab by name, put some function editor only

* Moved getObjects into Object3D, renamed getDefault name to getDefaultEditorName

* Misc cleanup

* Reworked make part 1

* Make refacto part 2

* Removed public from setEditorChildren, cleaned up setEditor

* serializeToDynamic -> serialize, removed save arguments

* Minors cleanups

* Reorganized Prefab order, changed some function visibility

* Post rebase bugfix

* Fix reference in reference crash

* Removed depedency to getDefaultName in getAbsPath

* Fix prefab.make

* Make use now macro magic for the guard, added abstract as parameter to allow passing an object as a shared context

* cl parameter is now optionnal for find* functions

* Removed shoudMakeChild, isSceneReference, parent -> parentPrefab

* Make functions are now grouped together

* Fixed MeshSpray compilation

* fix

* Fixing non editor builds

* remove Object3D.getAbsPos3d

* clone now don't call the prefab constructor, tentative fix caching in ModelLibrary

* Fixed model library, Object2d/3d properly init root2d/3d if null now

* Fix ContextShared.getObjects, get only for self local3d

* Fix new prefab

* Prefab new is now extracted into __newInit()

* Fix init of final vars in prefabs

* children is now init before __newInit()

* Fix capsule light not being added to scene.

* Fix post rebase compilation

---------

Co-authored-by: Tom Spira <[email protected]>
Co-authored-by: Nicolas Cannasse <[email protected]>
Co-authored-by: clementlandrin <Alcotest84!!>
Valden 1 year ago
parent
commit
c714e48089
100 changed files with 4052 additions and 3894 deletions
  1. 1 1
      .vscode/launch.json
  2. 3 0
      hide.hxml
  3. 7 2
      hide/Ide.hx
  4. 8 1
      hide/Renderer.hx
  5. 5 0
      hide/comp/CameraControllerEditor.hx
  6. 5 5
      hide/comp/CurveEditor.hx
  7. 1 1
      hide/comp/PropsEditor.hx
  8. 4 2
      hide/comp/Scene.hx
  9. 273 233
      hide/comp/SceneEditor.hx
  10. 27 3
      hide/comp/cdb/DataFiles.hx
  11. 1 1
      hide/comp/cdb/Editor.hx
  12. 10 19
      hide/prefab/ContextShared.hx
  13. 14 21
      hide/prefab/EditContext.hx
  14. 1 1
      hide/prefab/HideProps.hx
  15. 30 29
      hide/prefab/PolygonEditor.hx
  16. 56 60
      hide/prefab/SplineEditor.hx
  17. 55 56
      hide/prefab/terrain/TerrainEditor.hx
  18. 5 6
      hide/tools/IdeData.hx
  19. 180 62
      hide/view/FXEditor.hx
  20. 20 14
      hide/view/Model.hx
  21. 32 29
      hide/view/Prefab.hx
  22. 18 17
      hide/view/l3d/Gizmo.hx
  23. 4 10
      hide/view/l3d/LightProbeBaker.hx
  24. 2 3
      hide/view/l3d/ProbeBakerProcess.hx
  25. 10 10
      hide/view/shadereditor/ShaderEditor.hx
  26. 34 0
      hrt/prefab/Cache.hx
  27. 0 108
      hrt/prefab/Context.hx
  28. 48 162
      hrt/prefab/ContextShared.hx
  29. 68 46
      hrt/prefab/Curve.hx
  30. 11 19
      hrt/prefab/DynamicShader.hx
  31. 0 81
      hrt/prefab/Library.hx
  32. 55 53
      hrt/prefab/Light.hx
  33. 753 0
      hrt/prefab/Macros.hx
  34. 53 46
      hrt/prefab/Material.hx
  35. 29 38
      hrt/prefab/Model.hx
  36. 56 52
      hrt/prefab/Object2D.hx
  37. 155 103
      hrt/prefab/Object3D.hx
  38. 514 245
      hrt/prefab/Prefab.hx
  39. 87 118
      hrt/prefab/Reference.hx
  40. 16 19
      hrt/prefab/RenderProps.hx
  41. 26 14
      hrt/prefab/Resource.hx
  42. 43 44
      hrt/prefab/Shader.hx
  43. 54 21
      hrt/prefab/Unknown.hx
  44. 31 39
      hrt/prefab/World.hx
  45. 10 15
      hrt/prefab/fx/AnimEvent.hx
  46. 32 45
      hrt/prefab/fx/BaseFX.hx
  47. 4 16
      hrt/prefab/fx/Billboard.hx
  48. 83 91
      hrt/prefab/fx/Emitter.hx
  49. 6 8
      hrt/prefab/fx/Event.hx
  50. 76 71
      hrt/prefab/fx/FX.hx
  51. 63 57
      hrt/prefab/fx/FX2D.hx
  52. 0 216
      hrt/prefab/fx/FXScript.hx
  53. 0 476
      hrt/prefab/fx/FXScriptParser.hx
  54. 11 18
      hrt/prefab/fx/LookAt.hx
  55. 16 20
      hrt/prefab/fx/SubFX.hx
  56. 28 43
      hrt/prefab/fx/Swarm.hx
  57. 0 7
      hrt/prefab/import.hx
  58. 10 14
      hrt/prefab/l2d/Anim2D.hx
  59. 11 16
      hrt/prefab/l2d/Atlas.hx
  60. 11 16
      hrt/prefab/l2d/Bitmap.hx
  61. 20 26
      hrt/prefab/l2d/Blur.hx
  62. 15 19
      hrt/prefab/l2d/Flow.hx
  63. 21 19
      hrt/prefab/l2d/NoiseGenerator.hx
  64. 12 20
      hrt/prefab/l2d/Particle2D.hx
  65. 14 19
      hrt/prefab/l2d/Text.hx
  66. 13 11
      hrt/prefab/l3d/AnimSpeedControl.hx
  67. 10 15
      hrt/prefab/l3d/Box.hx
  68. 34 34
      hrt/prefab/l3d/Camera.hx
  69. 10 12
      hrt/prefab/l3d/Constraint.hx
  70. 42 38
      hrt/prefab/l3d/Decal.hx
  71. 13 20
      hrt/prefab/l3d/Environment.hx
  72. 17 17
      hrt/prefab/l3d/GameController.hx
  73. 29 33
      hrt/prefab/l3d/HeightMap.hx
  74. 35 24
      hrt/prefab/l3d/Instance.hx
  75. 28 33
      hrt/prefab/l3d/Layers2D.hx
  76. 7 9
      hrt/prefab/l3d/Level3D.hx
  77. 53 50
      hrt/prefab/l3d/MeshGenerator.hx
  78. 76 66
      hrt/prefab/l3d/MeshSpray.hx
  79. 87 65
      hrt/prefab/l3d/ModelLibrary.hx
  80. 4 11
      hrt/prefab/l3d/ModelLibraryOptimizer.hx
  81. 12 13
      hrt/prefab/l3d/Particles3D.hx
  82. 38 33
      hrt/prefab/l3d/Polygon.hx
  83. 9 11
      hrt/prefab/l3d/PrefabSpray.hx
  84. 59 69
      hrt/prefab/l3d/Spline.hx
  85. 31 26
      hrt/prefab/l3d/SplineMesh.hx
  86. 14 45
      hrt/prefab/l3d/SplineMover.hx
  87. 40 58
      hrt/prefab/l3d/Spray.hx
  88. 21 29
      hrt/prefab/l3d/Text3D.hx
  89. 9 18
      hrt/prefab/l3d/Trail.hx
  90. 25 28
      hrt/prefab/l3d/Trails.hx
  91. 20 23
      hrt/prefab/pbr/Anisotropy.hx
  92. 16 17
      hrt/prefab/pbr/LightVolume.hx
  93. 16 23
      hrt/prefab/pbr/SpecularColor.hx
  94. 2 1
      hrt/prefab/rfx/AutoExposure.hx
  95. 4 3
      hrt/prefab/rfx/Bloom.hx
  96. 10 5
      hrt/prefab/rfx/Border.hx
  97. 5 5
      hrt/prefab/rfx/CloudShadow.hx
  98. 2 2
      hrt/prefab/rfx/ColorGrading.hx
  99. 9 17
      hrt/prefab/rfx/Configurator.hx
  100. 4 4
      hrt/prefab/rfx/DistanceBlur.hx

+ 1 - 1
.vscode/launch.json

@@ -24,7 +24,7 @@
             "preLaunchTask": "Build"
             "preLaunchTask": "Build"
         },
         },
         {
         {
-            "type": "nwjs",
+            "type": "chrome",
             "request": "attach",
             "request": "attach",
             "name": "Attach to HIDE",
             "name": "Attach to HIDE",
             "port": 9222,
             "port": 9222,

+ 3 - 0
hide.hxml

@@ -1,5 +1,6 @@
 common.hxml
 common.hxml
 -D hide
 -D hide
+-D prefab2
 -js bin/hide.js
 -js bin/hide.js
 -main hide.Ide
 -main hide.Ide
 --macro include("h3d.shader")
 --macro include("h3d.shader")
@@ -9,7 +10,9 @@ common.hxml
 --macro include("hxd.clipper")
 --macro include("hxd.clipper")
 --macro include("hxd.earcut")
 --macro include("hxd.earcut")
 --macro include("hrt.prefab")
 --macro include("hrt.prefab")
+--macro include("hrt.prefab")
 --macro include("hrt.shgraph.nodes")
 --macro include("hrt.shgraph.nodes")
+--macro include("hide.view")
 -dce no
 -dce no
 -debug
 -debug
 #-D shader_debug_dump
 #-D shader_debug_dump

+ 7 - 2
hide/Ide.hx

@@ -786,10 +786,15 @@ class Ide extends hide.tools.IdeData {
 			onSelect(dir == "" ? null : (isAbsolute ? dir : makeRelative(dir)));
 			onSelect(dir == "" ? null : (isAbsolute ? dir : makeRelative(dir)));
 			e.remove();
 			e.remove();
 		}).appendTo(window.window.document.body).click();
 		}).appendTo(window.window.document.body).click();
+
+		// remove comments
+
+
+
 	}
 	}
 
 
 	public function filterPrefabs( callb : hrt.prefab.Prefab -> Bool ) {
 	public function filterPrefabs( callb : hrt.prefab.Prefab -> Bool ) {
-		var exts = Lambda.array({iterator : @:privateAccess hrt.prefab.Library.registeredExtensions.keys });
+		var exts = Lambda.array({iterator : @:privateAccess hrt.prefab.Prefab.extensionRegistry.keys });
 		exts.push("prefab");
 		exts.push("prefab");
 		var todo = [];
 		var todo = [];
 		browseFiles(function(path) {
 		browseFiles(function(path) {
@@ -804,7 +809,7 @@ class Ide extends hide.tools.IdeData {
 			}
 			}
 			filterRec(prefab);
 			filterRec(prefab);
 			if( !changed ) return;
 			if( !changed ) return;
-			todo.push(function() sys.io.File.saveContent(getPath(path), toJSON(prefab.saveData())));
+			@:privateAccess todo.push(function() sys.io.File.saveContent(getPath(path), toJSON(prefab.serialize())));
 		});
 		});
 		for( t in todo )
 		for( t in todo )
 			t();
 			t();

+ 8 - 1
hide/Renderer.hx

@@ -94,7 +94,14 @@ class PbrSetup extends h3d.mat.PbrMaterialSetup {
 	function getEnvMap() {
 	function getEnvMap() {
 		var ide = hide.Ide.inst;
 		var ide = hide.Ide.inst;
 		var scene = hide.comp.Scene.getCurrent();
 		var scene = hide.comp.Scene.getCurrent();
-		var path = ide.getPath(scene.config.get("scene.environment"));
+		var path : String = "";
+		if (scene != null) {
+			path = ide.getPath(scene.config.get("scene.environment"));
+		}
+		else {
+			var scene2 = hide.comp.Scene.getCurrent();
+			path = ide.getPath(scene2.config.get("scene.environment"));
+		}
 		var data = sys.io.File.getBytes(path);
 		var data = sys.io.File.getBytes(path);
 		var pix = hxd.res.Any.fromBytes(path, data).toImage().getPixels();
 		var pix = hxd.res.Any.fromBytes(path, data).toImage().getPixels();
 		var t = h3d.mat.Texture.fromPixels(pix, h3d.mat.Texture.nativeFormat); // sync
 		var t = h3d.mat.Texture.fromPixels(pix, h3d.mat.Texture.nativeFormat); // sync

+ 5 - 0
hide/comp/CameraControllerEditor.hx

@@ -1,5 +1,10 @@
 package hide.comp;
 package hide.comp;
 import hide.view.CameraController;
 import hide.view.CameraController;
+import hide.comp.Popup;
+import hide.comp.Range;
+import hide.comp.ExpRange;
+
+
 
 
 class CameraControllerEditor extends Popup {
 class CameraControllerEditor extends Popup {
 
 

+ 5 - 5
hide/comp/CurveEditor.hx

@@ -472,7 +472,7 @@ class OverviewEditor extends Component implements CurveEditorComponent
 	public function afterChange() {}
 	public function afterChange() {}
 }
 }
 
 
-class CurveEditor extends Component {
+class CurveEditor extends hide.comp.Component {
 
 
 	public static var CURVE_COLORS: Array<Int> = [
 	public static var CURVE_COLORS: Array<Int> = [
 		0xff3352,
 		0xff3352,
@@ -747,7 +747,7 @@ class CurveEditor extends Component {
 				maxLength = c.maxTime;
 				maxLength = c.maxTime;
 		}
 		}
 
 
-		lastValue = [for (c in curves) c.save()];
+		@:privateAccess lastValue = [for (c in curves) c.serialize()];
 		refresh();
 		refresh();
 		return curves;
 		return curves;
 	}
 	}
@@ -1028,14 +1028,14 @@ class CurveEditor extends Component {
 	}
 	}
 
 
 	function beforeChange() {
 	function beforeChange() {
-		lastValue = [for (c in curves) c.save()];
+		@:privateAccess lastValue = [for (c in curves) c.serialize()];
 
 
 		for (c in components)
 		for (c in components)
 			c.beforeChange();
 			c.beforeChange();
 	}
 	}
 
 
 	function afterChange() {
 	function afterChange() {
-		var newVal = [for (c in curves) c.save()];
+		@:privateAccess var newVal = [for (c in curves) c.serialize()];
 		var oldVal = lastValue;
 		var oldVal = lastValue;
 		undo.change(Custom(function(undo) {
 		undo.change(Custom(function(undo) {
 			if(undo) {
 			if(undo) {
@@ -1046,7 +1046,7 @@ class CurveEditor extends Component {
 				for (i in 0...curves.length)
 				for (i in 0...curves.length)
 					curves[i].load(newVal[i]);
 					curves[i].load(newVal[i]);
 			}
 			}
-			lastValue = [for (c in curves) c.save()];
+			@:privateAccess lastValue = [for (c in curves) c.serialize()];
 			selectedElements = [];
 			selectedElements = [];
 			refresh();
 			refresh();
 			onChange(false);
 			onChange(false);

+ 1 - 1
hide/comp/PropsEditor.hx

@@ -92,7 +92,7 @@ class PropsEditor extends Component {
 			else {
 			else {
 				var row = new Element('<div class="flex"/>').appendTo(parent);
 				var row = new Element('<div class="flex"/>').appendTo(parent);
 				for( i in 0...n ) {
 				for( i in 0...n ) {
-					var e = new Element('<input type="number" field="${p.name}.$i">').appendTo(row);
+					var e = new Element('<input type="number" field="${p.name}.$i" step="0.1">').appendTo(row);
 					if(min == null) min = isColor ? 0.0 : -1.0;
 					if(min == null) min = isColor ? 0.0 : -1.0;
 					if(max == null)	max = 1.0;
 					if(max == null)	max = 1.0;
 					e.attr("min", "" + min);
 					e.attr("min", "" + min);

+ 4 - 2
hide/comp/Scene.hx

@@ -1,6 +1,6 @@
 package hide.comp;
 package hide.comp;
 
 
-class Scene extends Component implements h3d.IDrawable {
+class Scene extends hide.comp.Component implements h3d.IDrawable {
 
 
 	static var UID = 0;
 	static var UID = 0;
 
 
@@ -25,6 +25,8 @@ class Scene extends Component implements h3d.IDrawable {
 	public var editor : hide.comp.SceneEditor;
 	public var editor : hide.comp.SceneEditor;
 	var unFocusedTime = 0.;
 	var unFocusedTime = 0.;
 
 
+	public static var cache : h3d.prim.ModelCache = new h3d.prim.ModelCache();
+
 	public function new(config, parent, el) {
 	public function new(config, parent, el) {
 		super(parent,el);
 		super(parent,el);
 		this.config = config;
 		this.config = config;
@@ -529,7 +531,7 @@ class Scene extends Component implements h3d.IDrawable {
 		function pathRec(p : String) {
 		function pathRec(p : String) {
 			try {
 			try {
 				var prefab = hxd.res.Loader.currentInstance.load(p).toPrefab().load();
 				var prefab = hxd.res.Loader.currentInstance.load(p).toPrefab().load();
-				var mats = prefab.getAll(hrt.prefab.Material);
+				var mats = prefab.findAll(hrt.prefab.Material);
 				for ( m in mats )
 				for ( m in mats )
 					materials.push({ path : p, mat : m});
 					materials.push({ path : p, mat : m});
 			} catch ( e : hxd.res.NotFound ) {
 			} catch ( e : hxd.res.NotFound ) {

File diff suppressed because it is too large
+ 273 - 233
hide/comp/SceneEditor.hx


+ 27 - 3
hide/comp/cdb/DataFiles.hx

@@ -60,7 +60,7 @@ class DataFiles {
 	}
 	}
 	#else
 	#else
 	static function loadPrefab(file:String) {
 	static function loadPrefab(file:String) {
-		var l = hrt.prefab.Library.create(file.split(".").pop().toLowerCase());
+		var l = hrt.prefab.Prefab.create(file.split(".").pop().toLowerCase());
 		var path = getPath(file);
 		var path = getPath(file);
 		l.loadData(haxe.Json.parse(sys.io.File.getContent(path)));
 		l.loadData(haxe.Json.parse(sys.io.File.getContent(path)));
 		return l;
 		return l;
@@ -265,6 +265,30 @@ class DataFiles {
 		return obj;
 		return obj;
 	}
 	}
 
 
+	static function getPrefabsByPath(prefab: hrt.prefab.Prefab, path : String ) : Array<hrt.prefab.Prefab> {
+		function rec(prefab: hrt.prefab.Prefab, parts : Array<String>, index : Int, out : Array<hrt.prefab.Prefab> ) {
+			var name = parts[index++];
+			if( name == null ) {
+				out.push(prefab);
+				return;
+			}
+			var r = name.indexOf('*') < 0 ? null : new EReg("^"+name.split("*").join(".*")+"$","");
+			for( c in prefab.children ) {
+				var cname = c.name;
+				if( cname == null ) cname = c.getDefaultEditorName();
+				if( r == null ? c.name == name : r.match(cname) )
+					rec(prefab, parts, index, out);
+			}
+		}
+
+		var out = [];
+		if( path == "" )
+			out.push(prefab);
+		else
+			rec(prefab,path.split("."), 0, out);
+		return out;
+	}
+
 	public static function save( ?onSaveBase, ?force, ?prevSheetNames : Map<String,String> ) {
 	public static function save( ?onSaveBase, ?force, ?prevSheetNames : Map<String,String> ) {
 		var ide = Ide.inst;
 		var ide = Ide.inst;
 		var temp = [];
 		var temp = [];
@@ -303,7 +327,7 @@ class DataFiles {
 							pf = ide.loadPrefab(p.file);
 							pf = ide.loadPrefab(p.file);
 							prefabs.set(p.file, pf);
 							prefabs.set(p.file, pf);
 						}
 						}
-						var all = pf.getPrefabsByPath(p.path);
+						var all = getPrefabsByPath(pf, p.path);
 						var inst : hrt.prefab.Prefab = all[p.index];
 						var inst : hrt.prefab.Prefab = all[p.index];
 						if( inst == null || inst.getCdbType() != prevName )
 						if( inst == null || inst.getCdbType() != prevName )
 							ide.error("Can't save prefab data "+p.path);
 							ide.error("Can't save prefab data "+p.path);
@@ -327,7 +351,7 @@ class DataFiles {
 		for( file => pf in prefabs ) {
 		for( file => pf in prefabs ) {
 			skip++;
 			skip++;
 			var path = ide.getPath(file);
 			var path = ide.getPath(file);
-			var out = ide.toJSON(pf.saveData());
+			@:privateAccess var out = ide.toJSON(pf.serialize());
 			if( force ) {
 			if( force ) {
 				var txt = try sys.io.File.getContent(path) catch( e : Dynamic ) null;
 				var txt = try sys.io.File.getContent(path) catch( e : Dynamic ) null;
 				if( txt == out ) continue;
 				if( txt == out ) continue;

+ 1 - 1
hide/comp/cdb/Editor.hx

@@ -1216,7 +1216,7 @@ class Editor extends Component {
 								continue;
 								continue;
 							}
 							}
 							var ext = f.split(".").pop();
 							var ext = f.split(".").pop();
-							if( @:privateAccess hrt.prefab.Library.registeredExtensions.exists(ext) ) {
+							if( @:privateAccess hrt.prefab.Prefab.extensionRegistry.exists(ext) ) {
 								prefabFileCache.push({path: fpath, data: sys.io.File.getContent(fpath)});
 								prefabFileCache.push({path: fpath, data: sys.io.File.getContent(fpath)});
 							}
 							}
 						}
 						}

+ 10 - 19
hide/prefab/ContextShared.hx

@@ -1,46 +1,37 @@
 package hide.prefab;
 package hide.prefab;
 
 
-class ContextShared extends hrt.prefab.ContextShared {
+class ContextShared extends hrt.prefab.ContextShared.ContextSharedBase {
 	#if editor
 	#if editor
-	public var scene : hide.comp.Scene;
 	public var editor : hide.comp.SceneEditor;
 	public var editor : hide.comp.SceneEditor;
+	public var scene(get, never) : hide.comp.Scene;
+	public var editorDisplay : Bool;
 
 
-	public function new(scene, editor) {
-		super();
-		this.scene = scene;
-		this.editor = editor;
+	public function new(?path : String, ?root2d: h2d.Object = null, ?root3d: h3d.scene.Object = null, isInstance: Bool = true) {
+		super(path, root2d, root3d, isInstance);
 	}
 	}
 
 
-	function getScene() {
-		return scene;
-	}
-
-	override function allocForRef() {
-		return new ContextShared(scene, editor);
+	function get_scene() {
+		return editor.scene;
 	}
 	}
 
 
 	override function onError( e : Dynamic ) {
 	override function onError( e : Dynamic ) {
 		hide.Ide.inst.error(e);
 		hide.Ide.inst.error(e);
 	}
 	}
 
 
-	override function loadPrefab( path : String ) : hrt.prefab.Prefab {
-		return hide.Ide.inst.loadPrefab(path, null, true);
-	}
-
 	override function loadShader( path : String ) {
 	override function loadShader( path : String ) {
 		return hide.Ide.inst.shaderLoader.loadSharedShader(path);
 		return hide.Ide.inst.shaderLoader.loadSharedShader(path);
 	}
 	}
 
 
 	override function loadModel( path : String ) {
 	override function loadModel( path : String ) {
-		return getScene().loadModel(path);
+		return scene.loadModel(path);
 	}
 	}
 
 
 	override function loadAnimation( path : String ) {
 	override function loadAnimation( path : String ) {
-		return getScene().loadAnimation(path);
+		return scene.loadAnimation(path);
 	}
 	}
 
 
 	override function loadTexture( path : String, async : Bool = false ) {
 	override function loadTexture( path : String, async : Bool = false ) {
-		return getScene().loadTexture("",path, async);
+		return scene.loadTexture("",path, async);
 	}
 	}
 
 
 	override function loadBakedFile():Null<haxe.io.Bytes> {
 	override function loadBakedFile():Null<haxe.io.Bytes> {

+ 14 - 21
hide/prefab/EditContext.hx

@@ -1,11 +1,9 @@
 package hide.prefab;
 package hide.prefab;
+
 import hrt.prefab.Prefab;
 import hrt.prefab.Prefab;
-import hrt.prefab.Context;
 
 
 class EditContext {
 class EditContext {
 
 
-	public var rootContext : Context;
-
 	#if editor
 	#if editor
 
 
 	var updates : Array<Float->Void> = [];
 	var updates : Array<Float->Void> = [];
@@ -17,20 +15,15 @@ class EditContext {
 	function get_ide() return hide.Ide.inst;
 	function get_ide() return hide.Ide.inst;
 
 
 	public function onChange(p : Prefab, propName : String) {
 	public function onChange(p : Prefab, propName : String) {
-		var ctx = getContext(p);
-		scene.setCurrent();
-		if(ctx != null) {
-			p.updateInstance(ctx, propName);
-			var parent = p.parent;
-			while( parent != null ) {
-				var pr = parent.getHideProps();
-				if( pr.onChildUpdate != null ) pr.onChildUpdate(p);
+
+		p.updateInstance(propName);
+
+		var parent = p.parent;
+		while( parent != null ) {
+			var pr = parent.getHideProps();
+			if( pr.onChildUpdate != null ) pr.onChildUpdate(p);
 				parent = parent.parent;
 				parent = parent.parent;
-			}
 		}
 		}
-		for( ctx2 in rootContext.shared.getContexts(p) )
-			if( ctx2 != ctx )
-				p.updateInstance(ctx2, propName);
 	}
 	}
 
 
 	public function getCurrentProps( p : Prefab ) : Element {
 	public function getCurrentProps( p : Prefab ) : Element {
@@ -51,7 +44,8 @@ class EditContext {
 	}
 	}
 
 
 	public function makeChanges( p : Prefab, f : Void -> Void ) @:privateAccess {
 	public function makeChanges( p : Prefab, f : Void -> Void ) @:privateAccess {
-		var current = haxe.Json.parse(haxe.Json.stringify(p.save()));
+		var current = p.save();
+
 		properties.undo.change(Custom(function(b) {
 		properties.undo.change(Custom(function(b) {
 			var old = p.save();
 			var old = p.save();
 			p.load(current);
 			p.load(current);
@@ -66,13 +60,12 @@ class EditContext {
 
 
 	#end
 	#end
 
 
-	public function new(ctx) {
-		this.rootContext = ctx;
+	public function new() {
 	}
 	}
 
 
-	public function getContext( p : Prefab ) {
+	/*public function getContext( p : Prefab ) {
 		return rootContext.shared.contexts.get(p);
 		return rootContext.shared.contexts.get(p);
-	}
+	}*/
 
 
 	/**
 	/**
 		Converts screen mouse coordinates into projection into ground.
 		Converts screen mouse coordinates into projection into ground.
@@ -129,7 +122,7 @@ class EditContext {
 			path.pop();
 			path.pop();
 		}
 		}
 
 
-		for( o in rootContext.shared.root3d )
+		for( o in scene.s3d)
 			getRec([], o);
 			getRec([], o);
 
 
 		return out;
 		return out;

+ 1 - 1
hide/prefab/HideProps.hx

@@ -5,7 +5,7 @@ typedef HideProps = {
 	var name : String;
 	var name : String;
 	var ?isGround : Bool;
 	var ?isGround : Bool;
 	var ?fileSource : Array<String>;
 	var ?fileSource : Array<String>;
-	@:optional dynamic function allowChildren( type : String ) : Bool;
+	@:optional dynamic function allowChildren( cl : Class<hrt.prefab.Prefab> ) : Bool;
 	@:optional dynamic function allowParent( p : hrt.prefab.Prefab ) : Bool;
 	@:optional dynamic function allowParent( p : hrt.prefab.Prefab ) : Bool;
 	@:optional dynamic function onChildUpdate( p : hrt.prefab.Prefab ) : Void;
 	@:optional dynamic function onChildUpdate( p : hrt.prefab.Prefab ) : Void;
 	@:optional dynamic function onChildListChanged() : Void;
 	@:optional dynamic function onChildListChanged() : Void;

+ 30 - 29
hide/prefab/PolygonEditor.hx

@@ -1,6 +1,7 @@
 package hide.prefab;
 package hide.prefab;
 import hxd.Key as K;
 import hxd.Key as K;
-import hrt.prefab.Context;
+
+using hrt.prefab.Object3D; // GetLocal3D
 
 
 enum ColorState{
 enum ColorState{
 	None;
 	None;
@@ -49,7 +50,7 @@ class MovablePoint {
 	var localPosText : h2d.ObjectFollower;
 	var localPosText : h2d.ObjectFollower;
 	var worldPosText : h2d.ObjectFollower;
 	var worldPosText : h2d.ObjectFollower;
 
 
-	public function new(point : h2d.col.Point, ctx : Context){
+	public function new(point : h2d.col.Point, ctx : hrt.prefab.l3d.Polygon){
 		this.point = point;
 		this.point = point;
 		mesh = new SphereHandle(h3d.prim.Cube.defaultUnitCube(), null, ctx.local3d);
 		mesh = new SphereHandle(h3d.prim.Cube.defaultUnitCube(), null, ctx.local3d);
 		mesh.name = "_movablePoint";
 		mesh.name = "_movablePoint";
@@ -74,7 +75,7 @@ class MovablePoint {
 		updateText(ctx);
 		updateText(ctx);
 	}
 	}
 
 
-	function createText(ctx : Context){
+	function createText(ctx : hrt.prefab.l3d.Polygon){
 		var o = new h2d.ObjectFollower(mesh, ctx.shared.root2d.getScene());
 		var o = new h2d.ObjectFollower(mesh, ctx.shared.root2d.getScene());
 		var t = new h2d.Text(hxd.res.DefaultFont.get(), o);
 		var t = new h2d.Text(hxd.res.DefaultFont.get(), o);
 		t.textColor = 0xFFFFFF;
 		t.textColor = 0xFFFFFF;
@@ -89,7 +90,7 @@ class MovablePoint {
 		localPosText.remove();
 		localPosText.remove();
 	}
 	}
 
 
-	function worldToScreen(wx: Float, wy: Float, wz: Float, ctx : Context) {
+	function worldToScreen(wx: Float, wy: Float, wz: Float, ctx : hrt.prefab.l3d.Polygon) {
 		var s2d = ctx.shared.root2d.getScene();
 		var s2d = ctx.shared.root2d.getScene();
 		var camera = @:privateAccess ctx.local3d.getScene().camera;
 		var camera = @:privateAccess ctx.local3d.getScene().camera;
 		camera.update();
 		camera.update();
@@ -97,7 +98,7 @@ class MovablePoint {
 		return new h2d.col.Point( pt.x, pt.y);
 		return new h2d.col.Point( pt.x, pt.y);
 	}
 	}
 
 
-	public function updateText(ctx : Context){
+	public function updateText(ctx : hrt.prefab.l3d.Polygon){
 		inline function getText(o) : h2d.Text{
 		inline function getText(o) : h2d.Text{
 			return Std.downcast(o.getChildAt(0), h2d.Text);
 			return Std.downcast(o.getChildAt(0), h2d.Text);
 		}
 		}
@@ -129,7 +130,7 @@ class MovablePoint {
 
 
 class PolygonEditor {
 class PolygonEditor {
 
 
-	public var editContext : EditContext;
+	public var editContext : hide.prefab.EditContext;
 	public var showDebug : Bool;
 	public var showDebug : Bool;
 	public var gridSize(get, set): Float;
 	public var gridSize(get, set): Float;
 	public var showTriangles : Bool = false;
 	public var showTriangles : Bool = false;
@@ -179,7 +180,7 @@ class PolygonEditor {
 	}
 	}
 
 
 	inline function getContext(){
 	inline function getContext(){
-		return editContext.getContext(polygonPrefab);
+		return polygonPrefab;
 	}
 	}
 
 
 	inline function refreshInteractive() {
 	inline function refreshInteractive() {
@@ -197,7 +198,7 @@ class PolygonEditor {
 			drawTriangles(showTriangles);
 			drawTriangles(showTriangles);
 		}
 		}
 		else if(propName == "editMode") {
 		else if(propName == "editMode") {
-			setSelected(getContext(), true);
+			setSelected(true);
 		} else {
 		} else {
 			refreshInteractive();
 			refreshInteractive();
 		}
 		}
@@ -355,24 +356,24 @@ class PolygonEditor {
 		return localPos;
 		return localPos;
 	}
 	}
 
 
-	public function setSelected( ctx : Context, b : Bool ) {
+	public function setSelected(b : Bool ) {
 		if (!polygonPrefab.enabled) return;
 		if (!polygonPrefab.enabled) return;
 		reset();
 		reset();
 		if(!editMode) return;
 		if(!editMode) return;
 		if(b){
 		if(b){
-			var s2d = ctx.shared.root2d.getScene();
+			var s2d = editContext.scene.s2d;
 			interactive = new h2d.Interactive(10000, 10000, s2d);
 			interactive = new h2d.Interactive(10000, 10000, s2d);
 			interactive.propagateEvents = true;
 			interactive.propagateEvents = true;
 			interactive.cancelEvents = false;
 			interactive.cancelEvents = false;
-			lineGraphics = new h3d.scene.Graphics(ctx.local3d);
+			lineGraphics = new h3d.scene.Graphics(polygonPrefab.getLocal3d());
 			lineGraphics.lineStyle(2, 0xFFFFFF);
 			lineGraphics.lineStyle(2, 0xFFFFFF);
 			lineGraphics.material.mainPass.setPassName("overlay");
 			lineGraphics.material.mainPass.setPassName("overlay");
 			lineGraphics.material.mainPass.depth(false, LessEqual);
 			lineGraphics.material.mainPass.depth(false, LessEqual);
-			selectedEdgeGraphic = new h3d.scene.Graphics(ctx.local3d);
+			selectedEdgeGraphic = new h3d.scene.Graphics(polygonPrefab.getLocal3d());
 			selectedEdgeGraphic.lineStyle(3, 0xFFFF00, 0.5);
 			selectedEdgeGraphic.lineStyle(3, 0xFFFF00, 0.5);
 			selectedEdgeGraphic.material.mainPass.setPassName("overlay");
 			selectedEdgeGraphic.material.mainPass.setPassName("overlay");
 			selectedEdgeGraphic.material.mainPass.depth(false, LessEqual);
 			selectedEdgeGraphic.material.mainPass.depth(false, LessEqual);
-			triangleGraphics = new h3d.scene.Graphics(ctx.local3d);
+			triangleGraphics = new h3d.scene.Graphics(polygonPrefab.getLocal3d());
 			triangleGraphics.lineStyle(2, 0xFF0000);
 			triangleGraphics.lineStyle(2, 0xFF0000);
 			triangleGraphics.material.mainPass.setPassName("overlay");
 			triangleGraphics.material.mainPass.setPassName("overlay");
 			triangleGraphics.material.mainPass.depth(false, LessEqual);
 			triangleGraphics.material.mainPass.depth(false, LessEqual);
@@ -385,11 +386,11 @@ class PolygonEditor {
 			};
 			};
 			interactive.onKeyDown =
 			interactive.onKeyDown =
 			function(e) {
 			function(e) {
-				if (ctx.local3d.getScene() == null) return;
+				if (polygonPrefab.getLocal3d().getScene().getScene() == null) return;
 				e.propagate = false;
 				e.propagate = false;
 				if( K.isDown( K.SHIFT ) ){
 				if( K.isDown( K.SHIFT ) ){
 					clearSelectedPoint();
 					clearSelectedPoint();
-					var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
+					var ray = @:privateAccess polygonPrefab.getLocal3d().getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
 					refreshMovablePoints(ray);
 					refreshMovablePoints(ray);
 					if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY);
 					if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY);
 					refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y));
 					refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y));
@@ -397,18 +398,18 @@ class PolygonEditor {
 			}
 			}
 			interactive.onKeyUp =
 			interactive.onKeyUp =
 			function(e) {
 			function(e) {
-				if (ctx.local3d.getScene() == null) return;
+				if (polygonPrefab.getLocal3d().getScene() == null) return;
 				e.propagate = false;
 				e.propagate = false;
-				var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
+				var ray = @:privateAccess polygonPrefab.getLocal3d().getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
 				refreshMovablePoints(ray);
 				refreshMovablePoints(ray);
 				if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY);
 				if(lastPos == null) lastPos = getFinalPos(s2d.mouseX, s2d.mouseY);
 				refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y));
 				refreshSelectedEdge(new h2d.col.Point(lastPos.x, lastPos.y));
 			}
 			}
 			interactive.onPush =
 			interactive.onPush =
 			function(e) {
 			function(e) {
-				if (ctx.local3d.getScene() == null) return;
+				if (polygonPrefab.getLocal3d().getScene() == null) return;
 				var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY);
 				var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY);
-				var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
+				var ray = @:privateAccess polygonPrefab.getLocal3d().getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
 				if( K.isDown( K.MOUSE_LEFT ) ){
 				if( K.isDown( K.MOUSE_LEFT ) ){
 					e.propagate = false;
 					e.propagate = false;
 					// Shift + Left Click : Remove Point
 					// Shift + Left Click : Remove Point
@@ -456,7 +457,7 @@ class PolygonEditor {
 			};
 			};
 			interactive.onRelease =
 			interactive.onRelease =
 			function(e) {
 			function(e) {
-				if (ctx.local3d.getScene() == null) return;
+				if (polygonPrefab.getLocal3d().getScene() == null) return;
 				//lastPos = null;
 				//lastPos = null;
 				lastPointSelected = null;
 				lastPointSelected = null;
 				if( beforeMoveList != null ){
 				if( beforeMoveList != null ){
@@ -468,9 +469,9 @@ class PolygonEditor {
 			};
 			};
 			interactive.onMove =
 			interactive.onMove =
 			function(e) {
 			function(e) {
-				if (ctx.local3d.getScene() == null) return;
+				if (polygonPrefab.getLocal3d().getScene() == null) return;
 
 
-				var ray = @:privateAccess ctx.local3d.getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
+				var ray = @:privateAccess polygonPrefab.getLocal3d().getScene().camera.rayFromScreen(s2d.mouseX, s2d.mouseY);
 				var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY, false);
 				var finalPos = getFinalPos(s2d.mouseX, s2d.mouseY, false);
 				refreshMovablePoints(ray);
 				refreshMovablePoints(ray);
 				refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y));
 				refreshSelectedEdge(new h2d.col.Point(finalPos.x, finalPos.y));
@@ -513,9 +514,9 @@ class PolygonEditor {
 		if (triangleGraphics == null)
 		if (triangleGraphics == null)
 			return;
 			return;
 		triangleGraphics.clear();
 		triangleGraphics.clear();
-		if(b && polygonPrefab.getPrimitive(getContext()) != null){
+		var prim = polygonPrefab.getPrimitive();
+		if(b && prim != null){
 			var i = 0;
 			var i = 0;
-			var prim = polygonPrefab.getPrimitive(getContext());
 			while(i < prim.idx.length){
 			while(i < prim.idx.length){
 				triangleGraphics.moveTo(prim.points[prim.idx[i]].x, prim.points[prim.idx[i]].y, 0);
 				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 + 1]].x, prim.points[prim.idx[i + 1]].y, 0);
@@ -575,7 +576,7 @@ class PolygonEditor {
 			refreshPointList(editContext.getCurrentProps(polygonPrefab));
 			refreshPointList(editContext.getCurrentProps(polygonPrefab));
 	}
 	}
 
 
-	public function addProps( ctx : EditContext ){
+	public function addProps( ctx : hide.prefab.EditContext ){
 		var props = new hide.Element('
 		var props = new hide.Element('
 		<div class="poly-editor">
 		<div class="poly-editor">
 			<div class="group" name="Tool">
 			<div class="group" name="Tool">
@@ -610,7 +611,7 @@ class PolygonEditor {
 			editMode = !editMode;
 			editMode = !editMode;
 			editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled");
 			editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled");
 			editModeButton.toggleClass("editModeEnabled", editMode);
 			editModeButton.toggleClass("editModeEnabled", editMode);
-			setSelected(getContext(), true);
+			setSelected(true);
 			if(!editMode)
 			if(!editMode)
 				refreshInteractive();
 				refreshInteractive();
 		});
 		});
@@ -769,7 +770,7 @@ class PolygonEditor {
 				obj.x += deltaChildSpace.x;
 				obj.x += deltaChildSpace.x;
 				obj.y += deltaChildSpace.y;
 				obj.y += deltaChildSpace.y;
 				obj.z += deltaChildSpace.z;
 				obj.z += deltaChildSpace.z;
-				obj.updateInstance(editContext.getContext(obj));
+				obj.updateInstance();
 			}
 			}
 
 
 			refreshPolygon();
 			refreshPolygon();
@@ -793,7 +794,7 @@ class PolygonEditor {
 						obj.x -= undoDelta.x;
 						obj.x -= undoDelta.x;
 						obj.y -= undoDelta.y;
 						obj.y -= undoDelta.y;
 						obj.z -= undoDelta.z;
 						obj.z -= undoDelta.z;
-						obj.updateInstance(editContext.getContext(obj));
+						obj.updateInstance();
 					}
 					}
 
 
 					polygonPrefab.x = undoPrevPos.x;
 					polygonPrefab.x = undoPrevPos.x;
@@ -813,7 +814,7 @@ class PolygonEditor {
 						obj.x += undoDelta.x;
 						obj.x += undoDelta.x;
 						obj.y += undoDelta.y;
 						obj.y += undoDelta.y;
 						obj.z += undoDelta.z;
 						obj.z += undoDelta.z;
-						obj.updateInstance(editContext.getContext(obj));
+						obj.updateInstance();
 					}
 					}
 
 
 					polygonPrefab.x = undoNextPos.x;
 					polygonPrefab.x = undoNextPos.x;

+ 56 - 60
hide/prefab/SplineEditor.hx

@@ -91,7 +91,7 @@ class SplineEditor {
 		this.undo = undo;
 		this.undo = undo;
 	}
 	}
 
 
-	public function update( ctx : hrt.prefab.Context , ?propName : String ) {
+	public function update(?propName : String ) {
 		if( editMode ) {
 		if( editMode ) {
 			showViewers();
 			showViewers();
 		}
 		}
@@ -110,12 +110,8 @@ class SplineEditor {
 		}
 		}
 	}
 	}
 
 
-	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 )
+	function getClosestSplinePointFromMouse( mouseX : Float, mouseY : Float) : SplinePoint {
+		if(prefab == null || prefab.local3d == null || prefab.local3d.getScene() == null )
 			return null;
 			return null;
 
 
 		var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0);
 		var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0);
@@ -123,7 +119,7 @@ class SplineEditor {
 		var result : SplinePoint = null;
 		var result : SplinePoint = null;
 		for( sp in prefab.points ) {
 		for( sp in prefab.points ) {
 			var screenPos = sp.getPoint().toVector();
 			var screenPos = sp.getPoint().toVector();
-			screenPos.project(ctx.local3d.getScene().camera.m);
+			screenPos.project(prefab.local3d.getScene().camera.m);
 			screenPos.z = 0;
 			screenPos.z = 0;
 			screenPos.scale(0.5);
 			screenPos.scale(0.5);
 			screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
 			screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
@@ -136,16 +132,16 @@ class SplineEditor {
 		return result;
 		return result;
 	}
 	}
 
 
-	function getNewPointPosition( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData {
+	function getNewPointPosition( mouseX : Float, mouseY : Float) : SplinePointData {
 		if( prefab.points.length == 0 ) {
 		if( prefab.points.length == 0 ) {
-			return { pos : ctx.local3d.getAbsPos().getPosition().toPoint(), tangent : ctx.local3d.getAbsPos().right().toPoint() , prev : null, next : null };
+			return { pos : prefab.local3d.getAbsPos().getPosition().toPoint(), tangent : prefab.local3d.getAbsPos().right().toPoint() , prev : null, next : null };
 		}
 		}
 
 
-		var closestPt = getClosestPointFromMouse(mouseX, mouseY, ctx);
+		var closestPt = getClosestPointFromMouse(mouseX, mouseY);
 
 
 		// 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 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) ) {
 		if( !prefab.loop && (closestPt.next == null || closestPt.prev == null) ) {
-			var camera = @:privateAccess ctx.local3d.getScene().camera;
+			var camera = @:privateAccess prefab.local3d.getScene().camera;
 			var ray = camera.rayFromScreen(mouseX, mouseY);
 			var ray = camera.rayFromScreen(mouseX, mouseY);
 			var normal = closestPt.next == null ? closestPt.prev.getAbsPos().up().toPoint() : closestPt.next.getAbsPos().up().toPoint();
 			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 point = closestPt.next == null ? closestPt.prev.getAbsPos().getPosition().toPoint() : closestPt.next.getAbsPos().getPosition().toPoint();
@@ -157,9 +153,9 @@ class SplineEditor {
 			return closestPt;
 			return closestPt;
 	}
 	}
 
 
-	function getClosestPointFromMouse( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData {
+	function getClosestPointFromMouse( mouseX : Float, mouseY : Float) : SplinePointData {
 
 
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null )
+		if(prefab == null || prefab.local3d == null || prefab.local3d.getScene() == null )
 			return null;
 			return null;
 
 
 		var result : SplinePointData = null;
 		var result : SplinePointData = null;
@@ -167,7 +163,7 @@ class SplineEditor {
 		var minDist = -1.0;
 		var minDist = -1.0;
 		for( s in prefab.data.samples ) {
 		for( s in prefab.data.samples ) {
 			var screenPos = s.pos.toVector();
 			var screenPos = s.pos.toVector();
-			screenPos.project(ctx.local3d.getScene().camera.m);
+			screenPos.project(prefab.local3d.getScene().camera.m);
 			screenPos.z = 0;
 			screenPos.z = 0;
 			screenPos.scale(0.5);
 			screenPos.scale(0.5);
 			screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
 			screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
@@ -184,7 +180,7 @@ class SplineEditor {
 			var firstSp = prefab.points[0];
 			var firstSp = prefab.points[0];
 			var firstPt = firstSp.getPoint();
 			var firstPt = firstSp.getPoint();
 			var firstPtScreenPos = firstPt.toVector();
 			var firstPtScreenPos = firstPt.toVector();
-			firstPtScreenPos.project(ctx.local3d.getScene().camera.m);
+			firstPtScreenPos.project(prefab.local3d.getScene().camera.m);
 			firstPtScreenPos.z = 0;
 			firstPtScreenPos.z = 0;
 			firstPtScreenPos.scale(0.5);
 			firstPtScreenPos.scale(0.5);
 			firstPtScreenPos = firstPtScreenPos.add(new h3d.Vector(0.5,0.5));
 			firstPtScreenPos = firstPtScreenPos.add(new h3d.Vector(0.5,0.5));
@@ -193,7 +189,7 @@ class SplineEditor {
 			var lastSp = prefab.points[prefab.points.length - 1];
 			var lastSp = prefab.points[prefab.points.length - 1];
 			var lastPt = lastSp.getPoint();
 			var lastPt = lastSp.getPoint();
 			var lastPtSreenPos = lastPt.toVector();
 			var lastPtSreenPos = lastPt.toVector();
-			lastPtSreenPos.project(ctx.local3d.getScene().camera.m);
+			lastPtSreenPos.project(prefab.local3d.getScene().camera.m);
 			lastPtSreenPos.z = 0;
 			lastPtSreenPos.z = 0;
 			lastPtSreenPos.scale(0.5);
 			lastPtSreenPos.scale(0.5);
 			lastPtSreenPos = lastPtSreenPos.add(new h3d.Vector(0.5,0.5));
 			lastPtSreenPos = lastPtSreenPos.add(new h3d.Vector(0.5,0.5));
@@ -216,9 +212,9 @@ class SplineEditor {
 		return result;
 		return result;
 	}
 	}
 
 
-	function addSplinePoint( spd : SplinePointData, ctx : hrt.prefab.Context ) : SplinePoint {
+	function addSplinePoint( spd : SplinePointData) : SplinePoint {
 
 
-		var invMatrix = ctx.local3d.getInvPos();
+		var invMatrix = prefab.local3d.getInvPos();
 
 
 		var pos = spd.pos.toVector();
 		var pos = spd.pos.toVector();
 		pos.project(invMatrix);
 		pos.project(invMatrix);
@@ -242,7 +238,7 @@ class SplineEditor {
 			scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5;
 			scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5;
 		}
 		}
 
 
-		var sp = new SplinePoint(prefab);
+		var sp = new SplinePoint(prefab, null);
 		sp.x = pos.x;
 		sp.x = pos.x;
 		sp.y = pos.y;
 		sp.y = pos.y;
 		sp.z = pos.z;
 		sp.z = pos.z;
@@ -261,7 +257,7 @@ class SplineEditor {
 		sp.scaleZ = scale;
 		sp.scaleZ = scale;
 		editContext.scene.editor.addElements([sp], false, true, false);
 		editContext.scene.editor.addElements([sp], false, true, false);
 
 
-		prefab.updateInstance(ctx);
+		prefab.updateInstance();
 		showViewers();
 		showViewers();
 		return sp;
 		return sp;
 	}
 	}
@@ -286,7 +282,7 @@ class SplineEditor {
 		gizmos = [];
 		gizmos = [];
 	}
 	}
 
 
-	function createGizmos( ctx : hrt.prefab.Context  ) {
+	function createGizmos() {
 		removeGizmos(); // Security, avoid duplication
 		removeGizmos(); // Security, avoid duplication
 		var sceneEditor = @:privateAccess editContext.scene.editor;
 		var sceneEditor = @:privateAccess editContext.scene.editor;
 		var sceneGizmo = @:privateAccess sceneEditor.gizmo;
 		var sceneGizmo = @:privateAccess sceneEditor.gizmo;
@@ -325,7 +321,7 @@ class SplineEditor {
 
 
 			gizmo.onStartMove = function(mode) {
 			gizmo.onStartMove = function(mode) {
 
 
-				var sceneObj = sceneEditor.getContext(sp).local3d;
+				var sceneObj = prefab.local3d;
 				var obj3d = sp.to(hrt.prefab.Object3D);
 				var obj3d = sp.to(hrt.prefab.Object3D);
 				var pivotPt = sceneObj.getAbsPos().getPosition();
 				var pivotPt = sceneObj.getAbsPos().getPosition();
 				var pivot = new h3d.Matrix();
 				var pivot = new h3d.Matrix();
@@ -376,7 +372,7 @@ class SplineEditor {
 						obj3d.scaleY = quantize(scaleSnap(s.y), scaleQuant);
 						obj3d.scaleY = quantize(scaleSnap(s.y), scaleQuant);
 						obj3d.scaleZ = quantize(scaleSnap(s.z), scaleQuant);
 						obj3d.scaleZ = quantize(scaleSnap(s.z), scaleQuant);
 					}
 					}
-					obj3d.applyTransform(sceneObj);
+					obj3d.applyTransform();
 				}
 				}
 
 
 				gizmo.onFinishMove = function() {
 				gizmo.onFinishMove = function() {
@@ -384,22 +380,22 @@ class SplineEditor {
 					undo.change(Custom(function(undo) {
 					undo.change(Custom(function(undo) {
 						if( undo ) {
 						if( undo ) {
 							obj3d.loadTransform(prevState);
 							obj3d.loadTransform(prevState);
-							obj3d.applyTransform(sceneObj);
-							prefab.updateInstance(ctx);
+							obj3d.applyTransform();
+							prefab.updateInstance();
 							showViewers();
 							showViewers();
 							@:privateAccess editContext.scene.editor.refresh(Partial);
 							@:privateAccess editContext.scene.editor.refresh(Partial);
 							showViewers();
 							showViewers();
-							createGizmos(ctx);
+							createGizmos();
 						}
 						}
 						else {
 						else {
 							obj3d.loadTransform(newState);
 							obj3d.loadTransform(newState);
-							obj3d.applyTransform(sceneObj);
-							prefab.updateInstance(ctx);
+							obj3d.applyTransform();
+							prefab.updateInstance();
 							showViewers();
 							showViewers();
-							createGizmos(ctx);
+							createGizmos();
 						}
 						}
 					}));
 					}));
-					var worldPos = ctx.local3d.localToGlobal(new h3d.col.Point(sp.x, sp.y, sp.z));
+					var worldPos = prefab.local3d.localToGlobal(new h3d.col.Point(sp.x, sp.y, sp.z));
 					gizmo.setPosition(worldPos.x, worldPos.y, worldPos.z);
 					gizmo.setPosition(worldPos.x, worldPos.y, worldPos.z);
 				}
 				}
 			}
 			}
@@ -418,7 +414,7 @@ class SplineEditor {
 		};
 		};
 	}
 	}
 
 
-	public function setSelected( ctx : hrt.prefab.Context , b : Bool ) {
+	public function setSelected(b : Bool ) {
 		reset();
 		reset();
 
 
 		if( !b ) {
 		if( !b ) {
@@ -427,8 +423,8 @@ class SplineEditor {
 		}
 		}
 
 
 		if( editMode ) {
 		if( editMode ) {
-			createGizmos(ctx);
-			var s2d = ctx.shared.root2d.getScene();
+			createGizmos();
+			var s2d = prefab.shared.root2d.getScene();
 			interactive = new h2d.Interactive(10000, 10000, s2d);
 			interactive = new h2d.Interactive(10000, 10000, s2d);
 			interactive.propagateEvents = true;
 			interactive.propagateEvents = true;
 			interactive.onPush =
 			interactive.onPush =
@@ -436,25 +432,25 @@ class SplineEditor {
 					// Add a new point
 					// Add a new point
 					if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.CTRL )  ) {
 					if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.CTRL )  ) {
 						e.propagate = false;
 						e.propagate = false;
-						var pt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx);
-						var sp = addSplinePoint(pt, ctx);
+						var pt = getNewPointPosition(s2d.mouseX, s2d.mouseY);
+						var sp = addSplinePoint(pt);
 						showViewers();
 						showViewers();
-						createGizmos(ctx);
+						createGizmos();
 
 
 						undo.change(Custom(function(undo) {
 						undo.change(Custom(function(undo) {
 							if( undo ) {
 							if( undo ) {
 								editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
 								editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
 								for (sp in prefab.points)
 								for (sp in prefab.points)
-									sp.computeName(editContext.getContext(sp));
+									sp.computeName();
 								@:privateAccess editContext.scene.editor.refresh(Partial);
 								@:privateAccess editContext.scene.editor.refresh(Partial);
-								prefab.updateInstance(ctx);
+								prefab.updateInstance();
 								showViewers();
 								showViewers();
-								createGizmos(ctx);
+								createGizmos();
 							}
 							}
 							else {
 							else {
-								addSplinePoint(pt, ctx);
+								addSplinePoint(pt);
 								showViewers();
 								showViewers();
-								createGizmos(ctx);
+								createGizmos();
 							}
 							}
 						}));
 						}));
 
 
@@ -462,33 +458,33 @@ class SplineEditor {
 					// Delete a point
 					// Delete a point
 					if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.SHIFT )  ) {
 					if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.SHIFT )  ) {
 						e.propagate = false;
 						e.propagate = false;
-						var sp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx);
+						var sp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY);
 						var index = prefab.points.indexOf(sp);
 						var index = prefab.points.indexOf(sp);
 						editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
 						editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
 						for (sp in prefab.points)
 						for (sp in prefab.points)
-							sp.computeName(editContext.getContext(sp));
+							sp.computeName();
 						@:privateAccess editContext.scene.editor.refresh(Partial);
 						@:privateAccess editContext.scene.editor.refresh(Partial);
 
 
-						prefab.updateInstance(ctx);
+						prefab.updateInstance();
 						showViewers();
 						showViewers();
-						createGizmos(ctx);
+						createGizmos();
 
 
 						undo.change(Custom(function(undo) {
 						undo.change(Custom(function(undo) {
 							if( undo ) {
 							if( undo ) {
 								prefab.children.insert(index, sp);
 								prefab.children.insert(index, sp);
 								editContext.scene.editor.addElements([sp], false, true, false);
 								editContext.scene.editor.addElements([sp], false, true, false);
-								prefab.updateInstance(ctx);
+								prefab.updateInstance();
 								showViewers();
 								showViewers();
-								createGizmos(ctx);
+								createGizmos();
 							}
 							}
 							else {
 							else {
 								editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
 								editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
 								for (sp in prefab.points)
 								for (sp in prefab.points)
-									sp.computeName(editContext.getContext(sp));
+									sp.computeName();
 								@:privateAccess editContext.scene.editor.refresh(Partial);
 								@:privateAccess editContext.scene.editor.refresh(Partial);
-								prefab.updateInstance(ctx);
+								prefab.updateInstance();
 								showViewers();
 								showViewers();
-								createGizmos(ctx);
+								createGizmos();
 							}
 							}
 						}));
 						}));
 					}
 					}
@@ -501,7 +497,7 @@ class SplineEditor {
 						return;
 						return;
 
 
 					// Only show the gizmo of the closest splinePoint
 					// Only show the gizmo of the closest splinePoint
-					var closetSp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx);
+					var closetSp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY);
 					var index = prefab.points.indexOf(closetSp);
 					var index = prefab.points.indexOf(closetSp);
 					for( g in gizmos ) {
 					for( g in gizmos ) {
 						g.visible = gizmos.indexOf(g) == index && !K.isDown( K.CTRL ) && !K.isDown( K.SHIFT );
 						g.visible = gizmos.indexOf(g) == index && !K.isDown( K.CTRL ) && !K.isDown( K.SHIFT );
@@ -509,10 +505,10 @@ class SplineEditor {
 
 
 					if( K.isDown( K.CTRL ) ) {
 					if( K.isDown( K.CTRL ) ) {
 						if( newSplinePointViewer == null )
 						if( newSplinePointViewer == null )
-							newSplinePointViewer = new NewSplinePointViewer(ctx.local3d.getScene());
+							newSplinePointViewer = new NewSplinePointViewer(prefab.local3d.getScene());
 						newSplinePointViewer.visible = true;
 						newSplinePointViewer.visible = true;
 
 
-						var npt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx);
+						var npt = getNewPointPosition(s2d.mouseX, s2d.mouseY);
 						newSplinePointViewer.update(npt);
 						newSplinePointViewer.update(npt);
 					}
 					}
 					else {
 					else {
@@ -521,7 +517,7 @@ class SplineEditor {
 					}
 					}
 
 
 					if( K.isDown( K.SHIFT ) ) {
 					if( K.isDown( K.SHIFT ) ) {
-						var index = prefab.points.indexOf(getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx));
+						var index = prefab.points.indexOf(getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY));
 						for( sp in prefab.points ) {
 						for( sp in prefab.points ) {
 							if( index == prefab.points.indexOf(sp) )
 							if( index == prefab.points.indexOf(sp) )
 								sp.setColor(0xFFFF0000);
 								sp.setColor(0xFFFF0000);
@@ -561,7 +557,7 @@ class SplineEditor {
 			prefab.children.reverse();
 			prefab.children.reverse();
 			for (sp in prefab.points) {
 			for (sp in prefab.points) {
 				sp.rotationZ += hxd.Math.degToRad(180);
 				sp.rotationZ += hxd.Math.degToRad(180);
-				sp.computeName(editContext.getContext(sp));
+				sp.computeName();
 			}
 			}
 			@:privateAccess editContext.scene.editor.refresh(Partial);
 			@:privateAccess editContext.scene.editor.refresh(Partial);
 
 
@@ -569,13 +565,13 @@ class SplineEditor {
 				prefab.children.reverse();
 				prefab.children.reverse();
 				for (sp in prefab.points) {
 				for (sp in prefab.points) {
 					sp.rotationZ += hxd.Math.degToRad(180);
 					sp.rotationZ += hxd.Math.degToRad(180);
-					sp.computeName(editContext.getContext(sp));
+					sp.computeName();
 				}
 				}
 				@:privateAccess editContext.scene.editor.refresh(Partial);
 				@:privateAccess editContext.scene.editor.refresh(Partial);
 			}));
 			}));
 			ctx.onChange(prefab, null);
 			ctx.onChange(prefab, null);
 			removeGizmos();
 			removeGizmos();
-			createGizmos(getContext());
+			createGizmos();
 		});
 		});
 
 
 		var editModeButton = props.find(".editModeButton");
 		var editModeButton = props.find(".editModeButton");
@@ -585,8 +581,8 @@ class SplineEditor {
 			prefab.onEdit(editMode);
 			prefab.onEdit(editMode);
 			editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled");
 			editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled");
 			editModeButton.toggleClass("editModeEnabled", editMode);
 			editModeButton.toggleClass("editModeEnabled", editMode);
-			prefab.updateInstance(ctx.getContext(prefab));
-			setSelected(getContext(), true);
+			prefab.updateInstance();
+			setSelected(true);
 			@:privateAccess editContext.scene.editor.showGizmo = !editMode;
 			@:privateAccess editContext.scene.editor.showGizmo = !editMode;
 			ctx.onChange(prefab, null);
 			ctx.onChange(prefab, null);
 		});
 		});

+ 55 - 56
hide/prefab/terrain/TerrainEditor.hx

@@ -3,7 +3,6 @@ using Lambda;
 import hxd.Pixels;
 import hxd.Pixels;
 import hrt.prefab.terrain.Tile;
 import hrt.prefab.terrain.Tile;
 import hxd.Key as K;
 import hxd.Key as K;
-import hrt.prefab.Context;
 
 
 enum RenderMode {
 enum RenderMode {
 	PBR;
 	PBR;
@@ -136,11 +135,11 @@ class TerrainEditor {
 		}
 		}
 	}
 	}
 
 
-	function renderTerrainUV( ctx : Context ) {
+	function renderTerrainUV() {
 		if( customScene == null ) return;
 		if( customScene == null ) return;
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return;
+		if( terrainPrefab == null || terrainPrefab.local3d == null || terrainPrefab.local3d.getScene() == null ) return;
 		var engine = h3d.Engine.getCurrent();
 		var engine = h3d.Engine.getCurrent();
-		var mainScene = @:privateAccess ctx.local3d.getScene();
+		var mainScene = @:privateAccess terrainPrefab.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.width != Std.int(h3d.Engine.getCurrent().width * uvTexRes) || uvTex.height != Std.int(h3d.Engine.getCurrent().height * uvTexRes) ) {
 			if(uvTex != null) {
 			if(uvTex != null) {
@@ -581,23 +580,23 @@ class TerrainEditor {
 		return minDist;
 		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;
+	function screenToWorld( u : Float, v : Float) {
+        if( terrainPrefab == null || terrainPrefab.local3d == null || terrainPrefab.local3d.getScene() == null ) return new h3d.col.Point();
+		var camera = @:privateAccess terrainPrefab.local3d.getScene().camera;
 		var ray = camera.rayFromScreen(u, v);
 		var ray = camera.rayFromScreen(u, v);
 		var dist = projectToGround(ray);
 		var dist = projectToGround(ray);
 		return dist >= 0 ? ray.getPoint(dist) : new h3d.col.Point();
 		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;
+	function worldToScreen( wx: Float, wy: Float, wz: Float) {
+		if( terrainPrefab == null || terrainPrefab.local3d == null || terrainPrefab.local3d.getScene() == null) return new h2d.col.Point();
+		var camera = @:privateAccess terrainPrefab.local3d.getScene().camera;
 		var pt = camera.project(wx, wy, wz, h3d.Engine.getCurrent().width, h3d.Engine.getCurrent().height);
 		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));
 		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);
+	function getBrushPlanePos( mouseX : Float, mouseY : Float) {
+		var worldPos = screenToWorld(mouseX, mouseY);
 		if( currentBrush.brushMode.snapToGrid ) {
 		if( currentBrush.brushMode.snapToGrid ) {
 			var localPos = terrainPrefab.terrain.globalToLocal(worldPos.clone());
 			var localPos = terrainPrefab.terrain.globalToLocal(worldPos.clone());
 			localPos.x = hxd.Math.round(localPos.x / terrainPrefab.terrain.cellSize.x) * terrainPrefab.terrain.cellSize.x;
 			localPos.x = hxd.Math.round(localPos.x / terrainPrefab.terrain.cellSize.x) * terrainPrefab.terrain.cellSize.x;
@@ -608,9 +607,9 @@ class TerrainEditor {
 		return worldPos;
 		return worldPos;
 	}
 	}
 
 
-	function getBrushWorldPosFromTex( worldPos : h3d.col.Point, ctx : Context ) : h3d.col.Point {
+	function getBrushWorldPosFromTex( worldPos : h3d.col.Point) : h3d.col.Point {
 		if(currentBrush.brushMode.snapToGrid) return worldPos;
 		if(currentBrush.brushMode.snapToGrid) return worldPos;
-		var screenPos = worldToScreen(worldPos.x, worldPos.y, worldPos.z, ctx);
+		var screenPos = worldToScreen(worldPos.x, worldPos.y, worldPos.z);
 		var brushWorldPos = worldPos.clone();
 		var brushWorldPos = worldPos.clone();
 		var fetchPos = new h2d.col.Point(hxd.Math.floor(screenPos.x * uvTexRes), hxd.Math.floor(screenPos.y * uvTexRes));
 		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.x = hxd.Math.clamp(fetchPos.x, 0, uvTexPixels.width - 1);
@@ -623,27 +622,27 @@ class TerrainEditor {
 		return brushWorldPos;
 		return brushWorldPos;
 	}
 	}
 
 
-	function drawBrushPreview( worldPos : h3d.col.Point, ctx : Context ) {
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null ) return;
+	function drawBrushPreview( worldPos : h3d.col.Point) {
+		if(terrainPrefab == null || terrainPrefab.local3d == null || terrainPrefab.local3d.getScene() == null) return;
 		brushPreview.reset();
 		brushPreview.reset();
 		if( currentBrush.brushMode.mode == Delete || currentBrush.bitmap == null ) return;
 		if( currentBrush.brushMode.mode == Delete || currentBrush.bitmap == null ) return;
-		var brushWorldPos = uvTexPixels == null ? worldPos : getBrushWorldPosFromTex(worldPos, ctx);
+		var brushWorldPos = uvTexPixels == null ? worldPos : getBrushWorldPosFromTex(worldPos);
 		brushPreview.previewAt(currentBrush, brushWorldPos);
 		brushPreview.previewAt(currentBrush, brushWorldPos);
 	}
 	}
 
 
-	function applyBrush( pos : h3d.col.Point, ctx : Context ) {
+	function applyBrush( pos : h3d.col.Point) {
 		switch ( currentBrush.brushMode.mode ) {
 		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);
+			case Paint: drawSurface(pos);
+			case AddSub: drawHeight(pos);
+			case Smooth: drawHeight(pos);
+			case Set: drawHeight(pos);
+			case Delete: deleteTile(pos);
 			default:
 			default:
 		}
 		}
 		terrainPrefab.modified = true;
 		terrainPrefab.modified = true;
 	}
 	}
 
 
-	function useBrush( from : h3d.col.Point, to : h3d.col.Point, ctx : Context ) {
+	function useBrush( from : h3d.col.Point, to : h3d.col.Point) {
 		var dist = (to.sub(from)).length();
 		var dist = (to.sub(from)).length();
 		if( currentBrush.firstClick ) {
 		if( currentBrush.firstClick ) {
 			if( currentBrush.brushMode.mode == Set ) {
 			if( currentBrush.brushMode.mode == Set ) {
@@ -652,7 +651,7 @@ class TerrainEditor {
 				else
 				else
 					currentBrush.brushMode.setHeightValue = currentBrush.strength;
 					currentBrush.brushMode.setHeightValue = currentBrush.strength;
 			}
 			}
-			applyBrush(from, ctx);
+			applyBrush(from);
 			previewStrokeBuffers();
 			previewStrokeBuffers();
 			return;
 			return;
 		}
 		}
@@ -673,7 +672,7 @@ class TerrainEditor {
 					pos = pos.add(firstStep);
 					pos = pos.add(firstStep);
 				}else
 				}else
 					pos = pos.add(step);
 					pos = pos.add(step);
-				applyBrush(pos, ctx);
+				applyBrush(pos);
 				dist -= currentBrush.step - remainingDist;
 				dist -= currentBrush.step - remainingDist;
 				remainingDist = 0;
 				remainingDist = 0;
 			}
 			}
@@ -683,8 +682,8 @@ class TerrainEditor {
 			remainingDist += dist;
 			remainingDist += dist;
 	}
 	}
 
 
-	public function deleteTile( pos : h3d.col.Point, ctx : Context ) {
-		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx);
+	public function deleteTile( pos : h3d.col.Point) {
+		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos);
 		if( brushWorldPos == null ) return;
 		if( brushWorldPos == null ) return;
 		var tile = terrainPrefab.terrain.getTileAtWorldPos(brushWorldPos.x, brushWorldPos.y);
 		var tile = terrainPrefab.terrain.getTileAtWorldPos(brushWorldPos.x, brushWorldPos.y);
 		if( tile == null ) return;
 		if( tile == null ) return;
@@ -695,18 +694,18 @@ class TerrainEditor {
 			trd.prevWeightMapPixels.push(w.capturePixels());
 			trd.prevWeightMapPixels.push(w.capturePixels());
 		tileTrashBin.push(trd);
 		tileTrashBin.push(trd);
 		terrainPrefab.terrain.removeTile(tile);
 		terrainPrefab.terrain.removeTile(tile);
-		renderTerrainUV(ctx);
+		renderTerrainUV();
 	}
 	}
 
 
-	public function drawSurface( pos : h3d.col.Point, ctx : Context ) {
+	public function drawSurface( pos : h3d.col.Point) {
 		if( currentBrush.index == -1 ) return;
 		if( currentBrush.index == -1 ) return;
-		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx);
+		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos);
 		if( brushWorldPos == null ) return;
 		if( brushWorldPos == null ) return;
 		var c = terrainPrefab.terrain.tiles.length;
 		var c = terrainPrefab.terrain.tiles.length;
 		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
 		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
 		if( c != terrainPrefab.terrain.tiles.length ) {
 		if( c != terrainPrefab.terrain.tiles.length ) {
-			renderTerrainUV(ctx);
-			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
+			renderTerrainUV();
+			brushWorldPos = getBrushWorldPosFromTex(pos);
 		}
 		}
 
 
 		currentBrush.bitmap.color = new h3d.Vector4(1.0);
 		currentBrush.bitmap.color = new h3d.Vector4(1.0);
@@ -735,14 +734,14 @@ class TerrainEditor {
 		}
 		}
 	}
 	}
 
 
-	public function drawHeight( pos : h3d.col.Point, ctx : Context ) {
-		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx);
+	public function drawHeight( pos : h3d.col.Point) {
+		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos);
 		if( brushWorldPos == null ) return;
 		if( brushWorldPos == null ) return;
 		var c = terrainPrefab.terrain.tiles.length;
 		var c = terrainPrefab.terrain.tiles.length;
 		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
 		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
 		if( c != terrainPrefab.terrain.tiles.length ) {
 		if( c != terrainPrefab.terrain.tiles.length ) {
-			renderTerrainUV(ctx);
-			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
+			renderTerrainUV();
+			brushWorldPos = getBrushWorldPosFromTex(pos);
 		}
 		}
 
 
 		var shader : hrt.shader.Brush = currentBrush.bitmap.getShader(hrt.shader.Brush);
 		var shader : hrt.shader.Brush = currentBrush.bitmap.getShader(hrt.shader.Brush);
@@ -778,9 +777,9 @@ class TerrainEditor {
 		}
 		}
 	}
 	}
 
 
-	public function setSelected( ctx : Context, b : Bool ) {
+	public function setSelected(b : Bool ) {
 		if( b ) {
 		if( b ) {
-			var s2d = ctx.shared.root2d.getScene();
+			var s2d = terrainPrefab.shared.root2d.getScene();
 			if( interactive == null )
 			if( interactive == null )
 				interactive.remove();
 				interactive.remove();
 			interactive = new h2d.Interactive(10000, 10000, s2d);
 			interactive = new h2d.Interactive(10000, 10000, s2d);
@@ -789,9 +788,9 @@ class TerrainEditor {
 
 
 			interactive.onWheel = function(e) {
 			interactive.onWheel = function(e) {
 				e.propagate = true;
 				e.propagate = true;
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
-				renderTerrainUV(ctx);
-				drawBrushPreview(worldPos, ctx);
+				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY);
+				renderTerrainUV();
+				drawBrushPreview(worldPos);
 			};
 			};
 
 
 			interactive.onPush = function(e) {
 			interactive.onPush = function(e) {
@@ -799,28 +798,28 @@ class TerrainEditor {
 				currentBrush.brushMode.lockDir = K.isDown(K.ALT);
 				currentBrush.brushMode.lockDir = K.isDown(K.ALT);
 				currentBrush.brushMode.subAction = K.isDown(K.SHIFT);
 				currentBrush.brushMode.subAction = K.isDown(K.SHIFT);
 				currentBrush.brushMode.snapToGrid = K.isDown(K.CTRL);
 				currentBrush.brushMode.snapToGrid = K.isDown(K.CTRL);
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
+				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY);
 				if( K.isDown( K.MOUSE_LEFT) ) {
 				if( K.isDown( K.MOUSE_LEFT) ) {
 					currentBrush.firstClick = true;
 					currentBrush.firstClick = true;
 					lastPos = worldPos.clone();
 					lastPos = worldPos.clone();
 					if( currentBrush.isValid() ) {
 					if( currentBrush.isValid() ) {
-						useBrush( lastPos, worldPos, ctx);
+						useBrush( lastPos, worldPos);
 						previewStrokeBuffers();
 						previewStrokeBuffers();
-						drawBrushPreview(worldPos, ctx);
+						drawBrushPreview(worldPos);
 					}
 					}
 				}
 				}
 			};
 			};
 
 
 			interactive.onRelease = function(e) {
 			interactive.onRelease = function(e) {
 				e.propagate = false;
 				e.propagate = false;
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
+				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY);
 				remainingDist = 0;
 				remainingDist = 0;
 				lastPos = null;
 				lastPos = null;
 				currentBrush.brushMode.lockAxe = NoLock;
 				currentBrush.brushMode.lockAxe = NoLock;
 				currentBrush.firstClick = false;
 				currentBrush.firstClick = false;
 				applyStrokeBuffers();
 				applyStrokeBuffers();
 				resetStrokeBuffers();
 				resetStrokeBuffers();
-				drawBrushPreview(worldPos, ctx);
+				drawBrushPreview(worldPos);
 				checkTrashBin();
 				checkTrashBin();
 			};
 			};
 
 
@@ -838,7 +837,7 @@ class TerrainEditor {
 					var sensibility = 0.5;
 					var sensibility = 0.5;
 					currentBrush.size = hxd.Math.max(0, lastBrushSize + sensibility * dist);
 					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;
 					@:privateAccess Lambda.find(editContext.properties.fields, f->f.fname=="editor.currentBrush.size").range.value = currentBrush.size;
-					drawBrushPreview(getBrushPlanePos(lastMousePos.x, lastMousePos.y, ctx), ctx);
+					drawBrushPreview(getBrushPlanePos(lastMousePos.x, lastMousePos.y));
 					return;
 					return;
 				}
 				}
 				else {
 				else {
@@ -847,7 +846,7 @@ class TerrainEditor {
 				}
 				}
 
 
 				currentBrush.brushMode.snapToGrid = /*K.isDown(K.CTRL)*/ false;
 				currentBrush.brushMode.snapToGrid = /*K.isDown(K.CTRL)*/ false;
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
+				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY);
 				if( K.isDown( K.MOUSE_LEFT) ) {
 				if( K.isDown( K.MOUSE_LEFT) ) {
 					currentBrush.firstClick = false;
 					currentBrush.firstClick = false;
 					e.propagate = false;
 					e.propagate = false;
@@ -868,15 +867,15 @@ class TerrainEditor {
 								worldPos.y += distY;
 								worldPos.y += distY;
 							}
 							}
 						}
 						}
-						useBrush( lastPos, worldPos, ctx);
+						useBrush( lastPos, worldPos);
 						lastPos = worldPos;
 						lastPos = worldPos;
 					}
 					}
 				}
 				}
 				else {
 				else {
-					renderTerrainUV(ctx);
+					renderTerrainUV();
 					e.propagate = true;
 					e.propagate = true;
 				}
 				}
-				drawBrushPreview(worldPos, ctx);
+				drawBrushPreview(worldPos);
 			};
 			};
 		}
 		}
 		else {
 		else {
@@ -991,7 +990,7 @@ class TerrainEditor {
 	}
 	}
 
 
 	function loadTexture( ctx : hide.prefab.EditContext, propsName : String, ?wrap : h3d.mat.Data.Wrap ) {
 	function loadTexture( ctx : hide.prefab.EditContext, propsName : String, ?wrap : h3d.mat.Data.Wrap ) {
-		var texture = ctx.rootContext.shared.loadTexture(propsName);
+		var texture = terrainPrefab.shared.loadTexture(propsName);
 		texture.wrap = wrap == null ? Repeat : wrap;
 		texture.wrap = wrap == null ? Repeat : wrap;
 		return texture;
 		return texture;
 	}
 	}
@@ -1191,9 +1190,9 @@ class TerrainEditor {
 		}
 		}
 		var name = split[0];
 		var name = split[0];
 		var ext = "."+path.split(".").pop();
 		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);
+		var albedo = terrainPrefab.shared.loadTexture(name + textureType[0] + ext);
+		var normal = terrainPrefab.shared.loadTexture(name + textureType[1] + ext);
+		var pbr = terrainPrefab.shared.loadTexture(name + textureType[2] + ext);
 
 
 		if( albedo == null || normal == null || pbr == null ) return;
 		if( albedo == null || normal == null || pbr == null ) return;
 
 

+ 5 - 6
hide/tools/IdeData.hx

@@ -228,23 +228,22 @@ class IdeData {
 	public function loadPrefab<T:hrt.prefab.Prefab>( file : String, ?cl : Class<T>, ?checkExists ) : T {
 	public function loadPrefab<T:hrt.prefab.Prefab>( file : String, ?cl : Class<T>, ?checkExists ) : T {
 		if( file == null )
 		if( file == null )
 			return null;
 			return null;
-		var l = hrt.prefab.Library.create(file.split(".").pop().toLowerCase());
 		try {
 		try {
 			var path = getPath(file);
 			var path = getPath(file);
 			if( checkExists && !sys.FileSystem.exists(path) )
 			if( checkExists && !sys.FileSystem.exists(path) )
 				return null;
 				return null;
-			l.loadData(parseJSON(sys.io.File.getContent(path)));
+			var p = hrt.prefab.Prefab.createFromDynamic(parseJSON(sys.io.File.getContent(path)));
+			if( cl == null )
+				return cast p;
+			return p.get(cl);
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			error("Invalid prefab "+file+" ("+e+")");
 			error("Invalid prefab "+file+" ("+e+")");
 			throw e;
 			throw e;
 		}
 		}
-		if( cl == null )
-			return cast l;
-		return l.get(cl);
 	}
 	}
 
 
 	public function savePrefab( file : String, f : hrt.prefab.Prefab ) {
 	public function savePrefab( file : String, f : hrt.prefab.Prefab ) {
-		var content = f.saveData();
+		@:privateAccess var content = f.serialize();
 		sys.io.File.saveContent(getPath(file), toJSON(content));
 		sys.io.File.saveContent(getPath(file), toJSON(content));
 	}
 	}
 
 

+ 180 - 62
hide/view/FXEditor.hx

@@ -1,4 +1,5 @@
 package hide.view;
 package hide.view;
+import hide.view.FileTree;
 import hrt.prefab.Light;
 import hrt.prefab.Light;
 using Lambda;
 using Lambda;
 
 
@@ -23,8 +24,8 @@ typedef Section = {
 @:access(hide.view.FXEditor)
 @:access(hide.view.FXEditor)
 class FXEditContext extends hide.prefab.EditContext {
 class FXEditContext extends hide.prefab.EditContext {
 	var parent : FXEditor;
 	var parent : FXEditor;
-	public function new(parent, context) {
-		super(context);
+	public function new(parent) {
+		super();
 		this.parent = parent;
 		this.parent = parent;
 	}
 	}
 	override function onChange(p, propName) {
 	override function onChange(p, propName) {
@@ -58,8 +59,7 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 	}
 	}
 
 
 	override function duplicate(thenMove : Bool) {
 	override function duplicate(thenMove : Bool) {
-		if(curEdit == null) return;
-		var elements = curEdit.rootElements;
+		var elements = selectedPrefabs;
 		if(elements == null || elements.length == 0)
 		if(elements == null || elements.length == 0)
 			return;
 			return;
 		if( isDuplicating )
 		if( isDuplicating )
@@ -71,13 +71,16 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 		var undoes = [];
 		var undoes = [];
 		var newElements = [];
 		var newElements = [];
 		for(elt in elements) {
 		for(elt in elements) {
-			var clone = elt.cloneData();
+			var clone = elt.clone(elt.parent, null);
 			var index = elt.parent.children.indexOf(elt) + 1;
 			var index = elt.parent.children.indexOf(elt) + 1;
-			clone.parent = elt.parent;
 			elt.parent.children.remove(clone);
 			elt.parent.children.remove(clone);
 			elt.parent.children.insert(index, clone);
 			elt.parent.children.insert(index, clone);
+
+			clone.shared.current2d = elt.parent.findFirstLocal2d();
+			clone.shared.current3d = elt.parent.findFirstLocal3d();
+			clone.make();
+
 			autoName(clone);
 			autoName(clone);
-			makeInstance(clone);
 			newElements.push(clone);
 			newElements.push(clone);
 
 
 			undoes.push(function(undo) {
 			undoes.push(function(undo) {
@@ -104,10 +107,7 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 			var fullRefresh = false;
 			var fullRefresh = false;
 			if(undo) {
 			if(undo) {
 				for(elt in newElements) {
 				for(elt in newElements) {
-					if(!removeInstance(elt)) {
-						fullRefresh = true;
-						break;
-					}
+					removeInstance(elt);
 				}
 				}
 			}
 			}
 
 
@@ -115,7 +115,7 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 
 
 			if(!undo) {
 			if(!undo) {
 				for(elt in newElements)
 				for(elt in newElements)
-					makeInstance(elt);
+					makePrefab(elt);
 			}
 			}
 
 
 			refresh(fullRefresh ? Full : Partial);
 			refresh(fullRefresh ? Full : Partial);
@@ -123,10 +123,10 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 	}
 	}
 
 
 	override function createDroppedElement(path:String, parent:PrefabElement):hrt.prefab.Object3D {
 	override function createDroppedElement(path:String, parent:PrefabElement):hrt.prefab.Object3D {
-		var type = hrt.prefab.Library.getPrefabType(path);
+		var type = hrt.prefab.Prefab.getPrefabType(path);
 		if(type == "fx") {
 		if(type == "fx") {
 			var relative = ide.makeRelative(path);
 			var relative = ide.makeRelative(path);
-			var ref = new hrt.prefab.fx.SubFX(parent);
+			var ref = new hrt.prefab.fx.SubFX(parent, null);
 			ref.source = relative;
 			ref.source = relative;
 			ref.name = new haxe.io.Path(relative).file;
 			ref.name = new haxe.io.Path(relative).file;
 			return ref;
 			return ref;
@@ -134,10 +134,10 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 		return super.createDroppedElement(path, parent);
 		return super.createDroppedElement(path, parent);
 	}
 	}
 
 
-	override function setElementSelected( p : PrefabElement, ctx : hrt.prefab.Context, b : Bool ) {
-		if( p.getParent(hrt.prefab.fx.Emitter) != null )
+	override function setElementSelected( p : PrefabElement, b : Bool ) {
+		if( p.findParent(hrt.prefab.fx.Emitter) != null )
 			return false;
 			return false;
-		return super.setElementSelected(p, ctx, b);
+		return super.setElementSelected(p, b);
 	}
 	}
 
 
 	override function selectElements( elts, ?mode ) {
 	override function selectElements( elts, ?mode ) {
@@ -258,7 +258,7 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 	}
 	}
 }
 }
 
 
-class FXEditor extends FileView {
+class FXEditor extends hide.view.FileView {
 
 
 	var sceneEditor : FXSceneEditor;
 	var sceneEditor : FXSceneEditor;
 	var data : hrt.prefab.fx.BaseFX;
 	var data : hrt.prefab.fx.BaseFX;
@@ -302,13 +302,13 @@ class FXEditor extends FileView {
 	var statusText : h2d.Text;
 	var statusText : h2d.Text;
 
 
 	var scriptEditor : hide.comp.ScriptEditor;
 	var scriptEditor : hide.comp.ScriptEditor;
-	var fxScriptParser : hrt.prefab.fx.FXScriptParser;
+	//var fxScriptParser : hrt.prefab.fx.FXScriptParser;
 	var cullingPreview : h3d.scene.Sphere;
 	var cullingPreview : h3d.scene.Sphere;
 
 
-	var viewModes : Array<String>;
+    var viewModes : Array<String>;
 
 
 	override function getDefaultContent() {
 	override function getDefaultContent() {
-		return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX().saveData()));
+		@:privateAccess return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX(null, null).serialize()));
 	}
 	}
 
 
 	override function canSave() {
 	override function canSave() {
@@ -318,7 +318,7 @@ class FXEditor extends FileView {
 	override function save() {
 	override function save() {
 		if( !canSave() )
 		if( !canSave() )
 			return;
 			return;
-		var content = ide.toJSON(data.saveData());
+		@:privateAccess var content = ide.toJSON(cast(data, hrt.prefab.Prefab).serialize());
 		var newSign = ide.makeSignature(content);
 		var newSign = ide.makeSignature(content);
 		if(newSign != currentSign)
 		if(newSign != currentSign)
 			haxe.Timer.delay(saveBackup.bind(content), 0);
 			haxe.Timer.delay(saveBackup.bind(content), 0);
@@ -333,17 +333,8 @@ class FXEditor extends FileView {
 		xOffset = -timelineLeftMargin / xScale;
 		xOffset = -timelineLeftMargin / xScale;
 		var content = sys.io.File.getContent(getPath());
 		var content = sys.io.File.getContent(getPath());
 		var json = haxe.Json.parse(content);
 		var json = haxe.Json.parse(content);
-		if (json.type == "fx") {
-			var inf = hrt.prefab.Library.getRegistered().get("fx");
-			data = Std.downcast(Type.createInstance(inf.cl, null), hrt.prefab.fx.FX);
-			if ( data == null )
-				throw "fx prefab override failed";
-		}
-		else {
-			is2D = true;
-			data = new hrt.prefab.fx.FX2D();
-		}
-		data.loadData(json);
+
+		data = cast(PrefabElement.createFromDynamic(json), hrt.prefab.fx.BaseFX);
 		currentSign = ide.makeSignature(content);
 		currentSign = ide.makeSignature(content);
 
 
 		element.html('
 		element.html('
@@ -389,7 +380,7 @@ class FXEditor extends FileView {
 			</div>');
 			</div>');
 		tools = new hide.comp.Toolbar(null,element.find(".tools-buttons"));
 		tools = new hide.comp.Toolbar(null,element.find(".tools-buttons"));
 		var tabs = new hide.comp.Tabs(null,element.find(".tabs"));
 		var tabs = new hide.comp.Tabs(null,element.find(".tabs"));
-		sceneEditor = new FXSceneEditor(this, data);
+		sceneEditor = new FXSceneEditor(this, cast(data, hrt.prefab.Prefab));
 		element.find(".hide-scenetree").first().append(sceneEditor.tree.element);
 		element.find(".hide-scenetree").first().append(sceneEditor.tree.element);
 		element.find(".hide-scroll").first().append(sceneEditor.properties.element);
 		element.find(".hide-scroll").first().append(sceneEditor.properties.element);
 		element.find(".heaps-scene").first().append(sceneEditor.scene.element);
 		element.find(".heaps-scene").first().append(sceneEditor.scene.element);
@@ -443,11 +434,11 @@ class FXEditor extends FileView {
 		});
 		});
 		var fxprops = new hide.comp.PropsEditor(undo,null,element.find(".fx-props"));
 		var fxprops = new hide.comp.PropsEditor(undo,null,element.find(".fx-props"));
 		{
 		{
-			var edit = new FXEditContext(this, sceneEditor.context);
+			var edit = new FXEditContext(this);
 			edit.properties = fxprops;
 			edit.properties = fxprops;
 			edit.scene = sceneEditor.scene;
 			edit.scene = sceneEditor.scene;
 			edit.cleanups = [];
 			edit.cleanups = [];
-			data.edit(edit);
+			cast(data, hrt.prefab.Prefab).edit(edit);
 		}
 		}
 
 
 		if (is2D) {
 		if (is2D) {
@@ -463,7 +454,7 @@ class FXEditor extends FileView {
 			modified = false;
 			modified = false;
 		}
 		}
 		scriptEditor.onSave = onSaveScript;
 		scriptEditor.onSave = onSaveScript;
-		fxScriptParser = new hrt.prefab.fx.FXScriptParser();
+		//fxScriptParser = new hrt.prefab.fx.FXScriptParser();
 		data.scriptCode = scriptEditor.code;
 		data.scriptCode = scriptEditor.code;
 
 
 		keys.register("playPause", function() { pauseButton.toggle(!pauseButton.isDown()); });
 		keys.register("playPause", function() { pauseButton.toggle(!pauseButton.isDown()); });
@@ -488,7 +479,6 @@ class FXEditor extends FileView {
 		if (tools != null)
 		if (tools != null)
 			tools.refreshToggles();
 			tools.refreshToggles();
 	}
 	}
-
 	public function onSceneReady() {
 	public function onSceneReady() {
 		light = sceneEditor.scene.s3d.find(function(o) return Std.downcast(o, h3d.scene.fwd.DirLight));
 		light = sceneEditor.scene.s3d.find(function(o) return Std.downcast(o, h3d.scene.fwd.DirLight));
 		if( light == null ) {
 		if( light == null ) {
@@ -521,6 +511,11 @@ class FXEditor extends FileView {
 
 
 		toolsDefs.push({id: "", title : "", icon : "", type : Separator});
 		toolsDefs.push({id: "", title : "", icon : "", type : Separator});
 
 
+		toolsDefs.push({id: "toggleSnap", title : "Snap Toggle", icon: "magnet", type : Toggle((v) -> {sceneEditor.snapToggle = v; sceneEditor.updateGrid();})});
+		toolsDefs.push({id: "snap-menu", title : "", icon: "", type : Popup((e) -> new hide.comp.SceneEditor.SnapSettingsPopup(null, e, sceneEditor))});
+
+		toolsDefs.push({id: "", title : "", icon : "", type : Separator});
+
 		toolsDefs.push({id: "localTransformsToggle", title : "Local transforms", icon : "compass", type : Toggle((v) -> sceneEditor.localTransform = v)});
 		toolsDefs.push({id: "localTransformsToggle", title : "Local transforms", icon : "compass", type : Toggle((v) -> sceneEditor.localTransform = v)});
 
 
 		toolsDefs.push({id: "", title : "", icon : "", type : Separator});
 		toolsDefs.push({id: "", title : "", icon : "", type : Separator});
@@ -569,6 +564,7 @@ class FXEditor extends FileView {
 			updateGrid();
 			updateGrid();
 		}, scene.engine.backgroundColor);
 		}, scene.engine.backgroundColor);
 
 
+
 		tools.addSeparator();
 		tools.addSeparator();
 
 
 		tools.addPopup(null, "View Modes", (e) -> new hide.comp.SceneEditor.ViewModePopup(null, e, Std.downcast(@:privateAccess scene.s3d.renderer, h3d.scene.pbr.Renderer), sceneEditor), null);
 		tools.addPopup(null, "View Modes", (e) -> new hide.comp.SceneEditor.ViewModePopup(null, e, Std.downcast(@:privateAccess scene.s3d.renderer, h3d.scene.pbr.Renderer), sceneEditor), null);
@@ -577,6 +573,7 @@ class FXEditor extends FileView {
 
 
 		tools.addPopup(null, "Render Props", (e) -> new hide.comp.SceneEditor.RenderPropsPopup(null, e, this, sceneEditor, true), null);
 		tools.addPopup(null, "Render Props", (e) -> new hide.comp.SceneEditor.RenderPropsPopup(null, e, this, sceneEditor, true), null);
 
 
+
 		tools.addSeparator();
 		tools.addSeparator();
 
 
 
 
@@ -585,6 +582,8 @@ class FXEditor extends FileView {
 			scene.speed = v;
 			scene.speed = v;
 		}, scene.speed);
 		}, scene.speed);
 
 
+
+
 		var gizmo = @:privateAccess sceneEditor.gizmo;
 		var gizmo = @:privateAccess sceneEditor.gizmo;
 
 
 		var onSetGizmoMode = function(mode: hide.view.l3d.Gizmo.EditMode) {
 		var onSetGizmoMode = function(mode: hide.view.l3d.Gizmo.EditMode) {
@@ -604,8 +603,128 @@ class FXEditor extends FileView {
 		updateGrid();
 		updateGrid();
 	}
 	}
 
 
+	// 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());
+	//     tools.addButton("arrows", "Gizmo translation Mode", @:privateAccess sceneEditor.gizmo.translationMode, () -> {
+	//         var items = [{
+	//             label : "Snap to Grid",
+	//             click : function() {
+	//                 @:privateAccess sceneEditor.gizmo.snapToGrid = !sceneEditor.gizmo.snapToGrid;
+	//             },
+	//             checked: @:privateAccess sceneEditor.gizmo.snapToGrid
+	//         }];
+	//         var steps : Array<Float> = sceneEditor.view.config.get("sceneeditor.gridSnapSteps");
+	//         for (step in steps) {
+	//             items.push({
+	//                 label : ""+step,
+	//                 click : function() {
+	//                     @:privateAccess sceneEditor.gizmo.moveStep = step;
+	//                 },
+	//                 checked: @:privateAccess sceneEditor.gizmo.moveStep == step
+	//             });
+	//         }
+	//         new hide.comp.ContextMenu(items);
+	//     });
+	//     tools.addButton("undo", "Gizmo rotation Mode", @:privateAccess sceneEditor.gizmo.rotationMode, () -> {
+	//         var steps : Array<Float> = sceneEditor.view.config.get("sceneeditor.rotateStepCoarses");
+	//         var items = [{
+	//             label : "Snap enabled",
+	//             click : function() {
+	//                 @:privateAccess sceneEditor.gizmo.rotateSnap = !sceneEditor.gizmo.rotateSnap;
+	//             },
+	//             checked: @:privateAccess sceneEditor.gizmo.rotateSnap
+	//         }];
+	//         for (step in steps) {
+	//             items.push({
+	//                 label : ""+step+"°",
+	//                 click : function() {
+	//                     @:privateAccess sceneEditor.gizmo.rotateStepCoarse = step;
+	//                 },
+	//                 checked: @:privateAccess sceneEditor.gizmo.rotateStepCoarse == step
+	//             });
+	//         }
+	//         new hide.comp.ContextMenu(items);
+	//     });
+	//     tools.addButton("compress", "Gizmo scaling Mode", @:privateAccess sceneEditor.gizmo.scalingMode);
+
+	//     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.addToggle("cube", "Toggle model axis", null, (v) -> { sceneEditor.showBasis = v; sceneEditor.updateBasis(); });
+
+	//     tools.addToggle("image", "Toggle 3d icons visibility", null, function(v) { hide.Ide.inst.show3DIcons = v; }, true);
+	//     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);
+	//     tools.addToggle("connectdevelop", "Wireframe",(b) -> { sceneEditor.setWireframe(b); });
+	//     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) {
 	function onPrefabChange(p: PrefabElement, ?pname: String) {
-		if(p == data) {
+		if(p == cast(data, hrt.prefab.Prefab)) {
 			if (this.curveEditor != null) {
 			if (this.curveEditor != null) {
 				previewMax = data.duration == 0 ? 5000 : data.duration;
 				previewMax = data.duration == 0 ? 5000 : data.duration;
 				this.curveEditor.refreshTimeline(currentTime);
 				this.curveEditor.refreshTimeline(currentTime);
@@ -630,7 +749,7 @@ class FXEditor extends FileView {
 
 
 				while (toRemove.length > 0) {
 				while (toRemove.length > 0) {
 					var c = toRemove.pop();
 					var c = toRemove.pop();
-					c.removeInstance(sceneEditor.context);
+					//c.removeInstance();
 					c.parent.children.remove(c);
 					c.parent.children.remove(c);
 				}
 				}
 			}
 			}
@@ -642,7 +761,7 @@ class FXEditor extends FileView {
 
 
 						// We're currently supporting blending with only 2 curves
 						// We're currently supporting blending with only 2 curves
 						for (i in 0...2) {
 						for (i in 0...2) {
-							var c = new Curve();
+							var c = new Curve(null, null);
 							c.parent = curve;
 							c.parent = curve;
 							c.name = '${curve.name}.${i}';
 							c.name = '${curve.name}.${i}';
 						}
 						}
@@ -659,7 +778,7 @@ class FXEditor extends FileView {
 
 
 		if(pname == "time" || pname == "loop" || pname == "animation" || pname == "blendMode" || pname == "blendFactor") {
 		if(pname == "time" || pname == "loop" || pname == "animation" || pname == "blendMode" || pname == "blendFactor") {
 			afterPan(false);
 			afterPan(false);
-			data.refreshObjectAnims(sceneEditor.getContext(data));
+			data.refreshObjectAnims();
 		}
 		}
 
 
 		if (pname == "loop") {
 		if (pname == "loop") {
@@ -674,7 +793,7 @@ class FXEditor extends FileView {
 	}
 	}
 
 
 	function onRefreshScene() {
 	function onRefreshScene() {
-		var renderProps = data.find(e -> e.to(hrt.prefab.RenderProps));
+		var renderProps = cast(data, hrt.prefab.Prefab).find(hrt.prefab.RenderProps);
 		if(renderProps != null)
 		if(renderProps != null)
 			renderProps.applyProps(scene.s3d.renderer);
 			renderProps.applyProps(scene.s3d.renderer);
 		updateGrid();
 		updateGrid();
@@ -718,7 +837,6 @@ class FXEditor extends FileView {
 
 
 		var minHeight = 40;
 		var minHeight = 40;
 		var curveEditorHeight = 100;
 		var curveEditorHeight = 100;
-		var ctx = sceneEditor.getContext(data);
 
 
 		for (curve in curves){
 		for (curve in curves){
 			var dispKey = getPath() + "/" + curve.getAbsPath(true);
 			var dispKey = getPath() + "/" + curve.getAbsPath(true);
@@ -746,7 +864,7 @@ class FXEditor extends FileView {
 			}
 			}
 			var shader = curve.parent.to(hrt.prefab.Shader);
 			var shader = curve.parent.to(hrt.prefab.Shader);
 			if(shader != null) {
 			if(shader != null) {
-				var sh = shader.getShaderDefinition(ctx);
+				var sh = shader.getShaderDefinition();
 				if(sh != null) {
 				if(sh != null) {
 					var v = sh.data.vars.find(v -> v.kind == Param && v.name == curve.name);
 					var v = sh.data.vars.find(v -> v.kind == Param && v.name == curve.name);
 					if(v != null && v.qualifiers != null) {
 					if(v != null && v.qualifiers != null) {
@@ -1250,7 +1368,7 @@ class FXEditor extends FileView {
 			var id = prefix != null ? prefix + "." + prop.name : prop.name;
 			var id = prefix != null ? prefix + "." + prop.name : prop.name;
 			if(Curve.getCurve(element, id) != null)
 			if(Curve.getCurve(element, id) != null)
 				continue;
 				continue;
-			var curve = new Curve(element);
+			var curve = new Curve(element,null);
 			curve.name = id;
 			curve.name = id;
 			if(prop.def != null)
 			if(prop.def != null)
 				curve.addKey(0, prop.def, Linear);
 				curve.addKey(0, prop.def, Linear);
@@ -1280,6 +1398,7 @@ class FXEditor extends FileView {
 		var obj2dElt = Std.downcast(elt, hrt.prefab.Object2D);
 		var obj2dElt = Std.downcast(elt, hrt.prefab.Object2D);
 		var shaderElt = Std.downcast(elt, hrt.prefab.Shader);
 		var shaderElt = Std.downcast(elt, hrt.prefab.Shader);
 		var emitterElt = Std.downcast(elt, hrt.prefab.fx.Emitter);
 		var emitterElt = Std.downcast(elt, hrt.prefab.fx.Emitter);
+
 		var particle2dElt = Std.downcast(elt, hrt.prefab.l2d.Particle2D);
 		var particle2dElt = Std.downcast(elt, hrt.prefab.l2d.Particle2D);
 		var menuItems : Array<hide.comp.ContextMenu.ContextMenuItem> = [];
 		var menuItems : Array<hide.comp.ContextMenu.ContextMenuItem> = [];
 		var lightElt = Std.downcast(elt, Light);
 		var lightElt = Std.downcast(elt, Light);
@@ -1364,7 +1483,7 @@ class FXEditor extends FileView {
 		}
 		}
 		if(shaderElt != null) {
 		if(shaderElt != null) {
 			var shader = shaderElt.makeShader();
 			var shader = shaderElt.makeShader();
-			var inEmitter = shaderElt.getParent(hrt.prefab.fx.Emitter) != null;
+			var inEmitter = shaderElt.findParent(hrt.prefab.fx.Emitter) != null;
 			var params = shader == null ? [] : @:privateAccess shader.shader.data.vars.filter(v -> v.kind == Param);
 			var params = shader == null ? [] : @:privateAccess shader.shader.data.vars.filter(v -> v.kind == Param);
 			for(param in params) {
 			for(param in params) {
 				if (param.qualifiers?.contains(Ignore) ?? false)
 				if (param.qualifiers?.contains(Ignore) ?? false)
@@ -1417,6 +1536,7 @@ class FXEditor extends FileView {
 				addParam(param, "Instance ");
 				addParam(param, "Instance ");
 			}
 			}
 		}
 		}
+
 		if (particle2dElt != null) {
 		if (particle2dElt != null) {
 			for(param in hrt.prefab.l2d.Particle2D.emitter2dParams) {
 			for(param in hrt.prefab.l2d.Particle2D.emitter2dParams) {
 				if(!param.animate)
 				if(!param.animate)
@@ -1424,6 +1544,7 @@ class FXEditor extends FileView {
 				addParam(param, "");
 				addParam(param, "");
 			}
 			}
 		}
 		}
+
 		if( lightElt != null ) {
 		if( lightElt != null ) {
 			switch lightElt.kind {
 			switch lightElt.kind {
 				case Point:
 				case Point:
@@ -1492,7 +1613,7 @@ class FXEditor extends FileView {
 			return;
 			return;
 
 
 		if (is2D) {
 		if (is2D) {
-			grid2d = new h2d.Graphics(scene.editor.context.local2d);
+			grid2d = new h2d.Graphics(scene.s2d);
 			grid2d.scale(1);
 			grid2d.scale(1);
 
 
 			grid2d.lineStyle(1.0, 12632256, 1.0);
 			grid2d.lineStyle(1.0, 12632256, 1.0);
@@ -1536,11 +1657,9 @@ class FXEditor extends FileView {
 	}
 	}
 
 
 	function onUpdate2D(dt:Float) {
 	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);
-		}
+
+		var anim = Std.downcast(sceneEditor.root2d, hrt.prefab.fx.FX2D.FX2DAnimation);
+
 		if(!pauseButton.isDown()) {
 		if(!pauseButton.isDown()) {
 			currentTime += scene.speed * dt;
 			currentTime += scene.speed * dt;
 			if(this.curveEditor != null) {
 			if(this.curveEditor != null) {
@@ -1577,7 +1696,6 @@ class FXEditor extends FileView {
 			@:privateAccess grid2d.setPosition(scene.s2d.children[0].x, scene.s2d.children[0].y);
 			@:privateAccess grid2d.setPosition(scene.s2d.children[0].x, scene.s2d.children[0].y);
 		}
 		}
 
 
-
 	}
 	}
 
 
 	var avg_smooth = 0.0;
 	var avg_smooth = 0.0;
@@ -1635,11 +1753,11 @@ class FXEditor extends FileView {
 	}
 	}
 
 
 	function onUpdate3D(dt:Float) {
 	function onUpdate3D(dt:Float) {
-		var ctx = sceneEditor.getContext(data);
-		if(ctx == null || ctx.local3d == null)
+		var local3d = sceneEditor.root3d;
+		if(local3d == null)
 			return;
 			return;
 
 
-		var allFx = ctx.local3d.findAll(o -> Std.downcast(o, hrt.prefab.fx.FX.FXAnimation));
+		var allFx = local3d.findAll(o -> Std.downcast(o, hrt.prefab.fx.FX.FXAnimation));
 
 
 		if(!pauseButton.isDown()) {
 		if(!pauseButton.isDown()) {
 			currentTime += scene.speed * dt;
 			currentTime += scene.speed * dt;
@@ -1662,7 +1780,7 @@ class FXEditor extends FileView {
 
 
 		var emitRateCurrent = 0.0;
 		var emitRateCurrent = 0.0;
 
 
-		var emitters = ctx.local3d.findAll(o -> Std.downcast(o, hrt.prefab.fx.Emitter.EmitterObject));
+		var emitters = local3d.findAll(o -> Std.downcast(o, hrt.prefab.fx.Emitter.EmitterObject));
 		var totalParts = 0;
 		var totalParts = 0;
 		for(e in emitters) {
 		for(e in emitters) {
 			totalParts += @:privateAccess e.numInstances;
 			totalParts += @:privateAccess e.numInstances;
@@ -1676,7 +1794,7 @@ class FXEditor extends FileView {
 			emitterTime += e.tickTime;
 			emitterTime += e.tickTime;
 		}
 		}
 
 
-		var trails = ctx.local3d.findAll(o -> Std.downcast(o, hrt.prefab.l3d.Trails.TrailObj));
+		var trails = local3d.findAll(o -> Std.downcast(o, hrt.prefab.l3d.Trails.TrailObj));
 		var trailCount = 0;
 		var trailCount = 0;
 		var trailTime = 0.0;
 		var trailTime = 0.0;
 		var trailTris = 0.0;
 		var trailTris = 0.0;
@@ -1777,7 +1895,7 @@ class FXEditor extends FileView {
 	}
 	}
 
 
 	static function isInstanceCurve(curve: Curve) {
 	static function isInstanceCurve(curve: Curve) {
-		return curve.getParent(hrt.prefab.fx.Emitter) != null;
+		return curve.findParent(hrt.prefab.fx.Emitter) != null;
 	}
 	}
 
 
 	static var _ = FileTree.registerExtension(FXEditor, ["fx"], { icon : "sitemap", createNew : "FX" });
 	static var _ = FileTree.registerExtension(FXEditor, ["fx"], { icon : "sitemap", createNew : "FX" });
@@ -1798,8 +1916,8 @@ class FXEditor extends FileView {
 class FX2DEditor extends FXEditor {
 class FX2DEditor extends FXEditor {
 
 
 	override function getDefaultContent() {
 	override function getDefaultContent() {
-		return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX2D().saveData()));
+		@:privateAccess return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.fx.FX2D(null, null).save()));
 	}
 	}
 
 
-	static var _2d = FileTree.registerExtension(FX2DEditor, ["fx2d"], { icon : "sitemap", createNew : "FX 2D" });
+	static var _2d = FileTree.registerExtension(FX2DEditor, ["fx2d__"], { icon : "sitemap", createNew : "FX 2D" });
 }
 }

+ 20 - 14
hide/view/Model.hx

@@ -120,7 +120,10 @@ class Model extends FileView {
 		tabs = new hide.comp.Tabs(null,element.find(".tabs"));
 		tabs = new hide.comp.Tabs(null,element.find(".tabs"));
 		eventList = element.find(".event-editor");
 		eventList = element.find(".event-editor");
 
 
-		root = new hrt.prefab.Library();
+		root = new hrt.prefab.Prefab(null, null);
+		var def = new hrt.prefab.Prefab(null, null);
+		new hrt.prefab.RenderProps(def, null).name = "renderer";
+		var l = new hrt.prefab.Light(def, null);
 		sceneEditor = new hide.comp.SceneEditor(this, root);
 		sceneEditor = new hide.comp.SceneEditor(this, root);
 		sceneEditor.editorDisplay = false;
 		sceneEditor.editorDisplay = false;
 		sceneEditor.onRefresh = onRefresh;
 		sceneEditor.onRefresh = onRefresh;
@@ -142,14 +145,17 @@ class Model extends FileView {
 		sceneEditor.view.keys.register("sceneeditor.focus", {name: "Focus Selection", category: "Scene"},
 		sceneEditor.view.keys.register("sceneeditor.focus", {name: "Focus Selection", category: "Scene"},
 			function() {if (lastSelectedObject != null) refreshSelectionHighlight(lastSelectedObject);});
 			function() {if (lastSelectedObject != null) refreshSelectionHighlight(lastSelectedObject);});
 		sceneEditor.tree.element.addClass("small");
 		sceneEditor.tree.element.addClass("small");
-		element.find("input[value=\"Save render props\"]").click(function(_) {
+		var e = element.find("input[value=\"Save render props\"]");
+		function callback(ev : js.jquery.Event) : Void {
 			if( !canSave() )
 			if( !canSave() )
 				return;
 				return;
 			var toSave = root.children[0];
 			var toSave = root.children[0];
 			@:privateAccess toSave.save();
 			@:privateAccess toSave.save();
 
 
 			save();
 			save();
-		});
+		}
+
+		e.on("click", callback);
 	}
 	}
 
 
 	override function onActivate() {
 	override function onActivate() {
@@ -590,10 +596,10 @@ class Model extends FileView {
 		sceneEditor.loadSavedCameraController3D(true);
 		sceneEditor.loadSavedCameraController3D(true);
 
 
 		// Remove current instancied render props
 		// Remove current instancied render props
-		sceneEditor.context.local3d.removeChildren();
+		sceneEditor.root3d.removeChildren();
 
 
 		// Remove current library to create a new one with the actual render prop
 		// Remove current library to create a new one with the actual render prop
-		root = new hrt.prefab.Library();
+		root = new hrt.prefab.Prefab(null, null);
 		for (c in @:privateAccess sceneEditor.sceneData.children)
 		for (c in @:privateAccess sceneEditor.sceneData.children)
 			@:privateAccess sceneEditor.sceneData.children.remove(c);
 			@:privateAccess sceneEditor.sceneData.children.remove(c);
 
 
@@ -606,11 +612,11 @@ class Model extends FileView {
 		// Create default render props if no render props has been created yet
 		// Create default render props if no render props has been created yet
 		var r = root.getOpt(hrt.prefab.RenderProps, true);
 		var r = root.getOpt(hrt.prefab.RenderProps, true);
 		if( r == null) {
 		if( r == null) {
-			var def = new hrt.prefab.Object3D(root);
+			var def = new hrt.prefab.Object3D(root, null);
 			def.name = "Default Ligthing";
 			def.name = "Default Ligthing";
-			var render = new hrt.prefab.RenderProps(def);
+			var render = new hrt.prefab.RenderProps(def, null);
 			render.name = "renderer";
 			render.name = "renderer";
-			var l = new hrt.prefab.Light(def);
+			var l = new hrt.prefab.Light(def, null);
 			l.name = "sunLight";
 			l.name = "sunLight";
 			l.kind = Directional;
 			l.kind = Directional;
 			l.power = 1.5;
 			l.power = 1.5;
@@ -623,23 +629,23 @@ class Model extends FileView {
 			l.shadows.mode = Dynamic;
 			l.shadows.mode = Dynamic;
 			l.shadows.size = 1024;
 			l.shadows.size = 1024;
 
 
-			def.make(sceneEditor.context);
+			def.make(new hrt.prefab.ContextShared());
 
 
 			r = render;
 			r = render;
 			r.applyProps(scene.s3d.renderer);
 			r.applyProps(scene.s3d.renderer);
 		}
 		}
 
 
 		// Apply render props properties on scene
 		// Apply render props properties on scene
-		var refPrefab = new hrt.prefab.Reference();
-		if( @:privateAccess refPrefab.ref != null ) {
-			var renderProps = @:privateAccess refPrefab.ref.getOpt(hrt.prefab.RenderProps);
+		var refPrefab = new hrt.prefab.Reference(null, null);
+		if( @:privateAccess refPrefab.refInstance != null ) {
+			var renderProps = @:privateAccess refPrefab.refInstance.getOpt(hrt.prefab.RenderProps);
 			if( renderProps != null )
 			if( renderProps != null )
 				renderProps.applyProps(scene.s3d.renderer);
 				renderProps.applyProps(scene.s3d.renderer);
 		}
 		}
 
 
-		plight = root.getAll(hrt.prefab.Light)[0];
+		plight = root.find(hrt.prefab.Light);
 		if( plight != null ) {
 		if( plight != null ) {
-			this.light = sceneEditor.context.shared.contexts.get(plight).local3d;
+			this.light = hrt.prefab.Object3D.getLocal3d(plight);
 			lightDirection = this.light.getLocalDirection();
 			lightDirection = this.light.getLocalDirection();
 		}
 		}
 
 

+ 32 - 29
hide/view/Prefab.hx

@@ -1,4 +1,5 @@
 package hide.view;
 package hide.view;
+import hrt.prefab.l3d.Instance;
 import hide.view.CameraController.CamController;
 import hide.view.CameraController.CamController;
 using Lambda;
 using Lambda;
 
 
@@ -7,12 +8,10 @@ import hxd.Key as K;
 
 
 import hrt.prefab.Prefab as PrefabElement;
 import hrt.prefab.Prefab as PrefabElement;
 import hrt.prefab.Object3D;
 import hrt.prefab.Object3D;
-import hrt.prefab.l3d.Instance;
 import hide.comp.cdb.DataFiles;
 import hide.comp.cdb.DataFiles;
 
 
 class FiltersPopup extends hide.comp.Popup {
 class FiltersPopup extends hide.comp.Popup {
 	var editor:Prefab;
 	var editor:Prefab;
-
 	public function new(?parent:Element, ?root:Element, editor:Prefab, filters:Map<String, Bool>, type:String) {
 	public function new(?parent:Element, ?root:Element, editor:Prefab, filters:Map<String, Bool>, type:String) {
 		super(parent, root);
 		super(parent, root);
 		this.editor = editor;
 		this.editor = editor;
@@ -46,7 +45,6 @@ class FiltersPopup extends hide.comp.Popup {
 		}
 		}
 	}
 	}
 }
 }
-
 @:access(hide.view.Prefab)
 @:access(hide.view.Prefab)
 class PrefabSceneEditor extends hide.comp.SceneEditor {
 class PrefabSceneEditor extends hide.comp.SceneEditor {
 	var parent : Prefab;
 	var parent : Prefab;
@@ -106,7 +104,7 @@ class PrefabSceneEditor extends hide.comp.SceneEditor {
 				var idCol = refCols == null ? null : Instance.findIDColumn(refSheet);
 				var idCol = refCols == null ? null : Instance.findIDColumn(refSheet);
 
 
 				function make(name) {
 				function make(name) {
-					var p = new Instance(current == null ? sceneData : current);
+					var p = new Instance(current == null ? sceneData : current, null);
 					p.name = name;
 					p.name = name;
 					p.props = makeCdbProps(p, type);
 					p.props = makeCdbProps(p, type);
 					setup(p);
 					setup(p);
@@ -178,10 +176,11 @@ class PrefabSceneEditor extends hide.comp.SceneEditor {
 	}
 	}
 }
 }
 
 
-class Prefab extends FileView {
+@:keep
+class Prefab extends hide.view.FileView {
 
 
 	public var sceneEditor : PrefabSceneEditor;
 	public var sceneEditor : PrefabSceneEditor;
-	var data : hrt.prefab.Library;
+	var data : hrt.prefab.Prefab;
 
 
 	var tools : hide.comp.Toolbar;
 	var tools : hide.comp.Toolbar;
 
 
@@ -213,7 +212,7 @@ class Prefab extends FileView {
 
 
 
 
 	function createData() {
 	function createData() {
-		data = new hrt.prefab.Library();
+		data = new hrt.prefab.Prefab(null, null);
 	}
 	}
 
 
 	function createEditor() {
 	function createEditor() {
@@ -225,9 +224,10 @@ class Prefab extends FileView {
 
 
 		createData();
 		createData();
 		var content = sys.io.File.getContent(getPath());
 		var content = sys.io.File.getContent(getPath());
-		data.loadData(haxe.Json.parse(content));
+		data = hrt.prefab.Prefab.createFromDynamic(haxe.Json.parse(content));
 		currentSign = ide.makeSignature(content);
 		currentSign = ide.makeSignature(content);
 
 
+
 		element.html('
 		element.html('
 			<div class="flex vertical">
 			<div class="flex vertical">
 				<div id="prefab-toolbar"></div>
 				<div id="prefab-toolbar"></div>
@@ -394,6 +394,7 @@ class Prefab extends FileView {
 		refreshViewModes();
 		refreshViewModes();
 		tools.saveDisplayKey = "Prefab/toolbar";
 		tools.saveDisplayKey = "Prefab/toolbar";
 		statusText = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d);
 		statusText = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d);
+		statusText = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d);
 		statusText.setPosition(5, 5);
 		statusText.setPosition(5, 5);
 		statusText.visible = false;
 		statusText.visible = false;
 
 
@@ -429,6 +430,9 @@ class Prefab extends FileView {
 
 
 		toolsDefs.push({id: "", title : "", icon : "", type : Separator});
 		toolsDefs.push({id: "", title : "", icon : "", type : Separator});
 
 
+		toolsDefs.push({id: "gridToggle", title : "Toggle grid", icon : "th", type : Toggle((v) -> { showGrid = v; updateGrid(); }) });
+		toolsDefs.push({id: "axisToggle", title : "Toggle model axis", icon : "cube", type : Toggle((v) -> { sceneEditor.showBasis = v; sceneEditor.updateBasis(); }) });
+		toolsDefs.push({id: "iconVisibility", title : "Toggle 3d icons visibility", icon : "image", type : Toggle((v) -> { hide.Ide.inst.show3DIcons = v; }), defaultValue: true });
 		toolsDefs.push({id: "gridToggle", title : "Toggle grid", icon : "th", type : Toggle((v) -> { showGrid = v; updateGrid(); }) });
 		toolsDefs.push({id: "gridToggle", title : "Toggle grid", icon : "th", type : Toggle((v) -> { showGrid = v; updateGrid(); }) });
 		toolsDefs.push({id: "axisToggle", title : "Toggle model axis", icon : "cube", type : Toggle((v) -> { sceneEditor.showBasis = v; sceneEditor.updateBasis(); }) });
 		toolsDefs.push({id: "axisToggle", title : "Toggle model axis", icon : "cube", type : Toggle((v) -> { sceneEditor.showBasis = v; sceneEditor.updateBasis(); }) });
 		toolsDefs.push({id: "iconVisibility", title : "Toggle 3d icons visibility", icon : "image", type : Toggle((v) -> { hide.Ide.inst.show3DIcons = v; }), defaultValue: true });
 		toolsDefs.push({id: "iconVisibility", title : "Toggle 3d icons visibility", icon : "image", type : Toggle((v) -> { hide.Ide.inst.show3DIcons = v; }), defaultValue: true });
@@ -472,6 +476,7 @@ class Prefab extends FileView {
 			icon: "connectdevelop",
 			icon: "connectdevelop",
 			type: Toggle((b) -> { sceneEditor.setWireframe(b); }),
 			type: Toggle((b) -> { sceneEditor.setWireframe(b); }),
 		});
 		});
+
 		toolsDefs.push({
 		toolsDefs.push({
 			id: "jointsToggle",
 			id: "jointsToggle",
 			title: "Joints",
 			title: "Joints",
@@ -530,6 +535,7 @@ class Prefab extends FileView {
 		posToolTip = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d);
 		posToolTip = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d);
 		posToolTip.dropShadow = { dx : 1, dy : 1, color : 0, alpha : 0.5 };
 		posToolTip.dropShadow = { dx : 1, dy : 1, color : 0, alpha : 0.5 };
 
 
+
 		var gizmo = @:privateAccess sceneEditor.gizmo;
 		var gizmo = @:privateAccess sceneEditor.gizmo;
 
 
 		var onSetGizmoMode = function(mode: hide.view.l3d.Gizmo.EditMode) {
 		var onSetGizmoMode = function(mode: hide.view.l3d.Gizmo.EditMode) {
@@ -544,6 +550,7 @@ class Prefab extends FileView {
 		updateStats();
 		updateStats();
 		updateGrid();
 		updateGrid();
 		initGraphicsFilters();
 		initGraphicsFilters();
+
 		initSceneFilters();
 		initSceneFilters();
 		sceneEditor.onRefresh = () -> {
 		sceneEditor.onRefresh = () -> {
 			initGraphicsFilters();
 			initGraphicsFilters();
@@ -558,7 +565,6 @@ class Prefab extends FileView {
 			var lines : Array<String> = [
 			var lines : Array<String> = [
 				'Scene objects: ${scene.s3d.getObjectsCount()}',
 				'Scene objects: ${scene.s3d.getObjectsCount()}',
 				'Interactives: ' + sceneEditor.interactives.count(),
 				'Interactives: ' + sceneEditor.interactives.count(),
-				'Contexts: ' + sceneEditor.context.shared.contexts.count(),
 				'Triangles: ${scene.engine.drawTriangles}',
 				'Triangles: ${scene.engine.drawTriangles}',
 				'Buffers: ${memStats.bufferCount}',
 				'Buffers: ${memStats.bufferCount}',
 				'Textures: ${memStats.textureCount}',
 				'Textures: ${memStats.textureCount}',
@@ -572,9 +578,8 @@ class Prefab extends FileView {
 
 
 	function resetCamera( top : Bool ) {
 	function resetCamera( top : Bool ) {
 		var targetPt = new h3d.col.Point(0, 0, 0);
 		var targetPt = new h3d.col.Point(0, 0, 0);
-		var curEdit = sceneEditor.curEdit;
-		if(curEdit != null && curEdit.rootObjects.length > 0) {
-			targetPt = curEdit.rootObjects[0].getAbsPos().getPosition().toPoint();
+		if(sceneEditor.selectedPrefabs.length > 0) {
+			targetPt = sceneEditor.selectedPrefabs[0].findFirstLocal3d().getAbsPos().getPosition().toPoint();
 		}
 		}
 		if(top)
 		if(top)
 			sceneEditor.cameraController.set(200, Math.PI/2, 0.001, targetPt);
 			sceneEditor.cameraController.set(200, Math.PI/2, 0.001, targetPt);
@@ -584,7 +589,7 @@ class Prefab extends FileView {
 	}
 	}
 
 
 	override function getDefaultContent() {
 	override function getDefaultContent() {
-		return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.Library().saveData()));
+		@:privateAccess return haxe.io.Bytes.ofString(ide.toJSON(new hrt.prefab.Prefab(null, null).serialize()));
 	}
 	}
 
 
 	override function canSave() {
 	override function canSave() {
@@ -595,7 +600,7 @@ class Prefab extends FileView {
 		if( !canSave() )
 		if( !canSave() )
 			return;
 			return;
 
 
-		var content = ide.toJSON(data.saveData());
+		@:privateAccess var content = ide.toJSON(data.serialize());
 		var newSign = ide.makeSignature(content);
 		var newSign = ide.makeSignature(content);
 		if(newSign != currentSign)
 		if(newSign != currentSign)
 			haxe.Timer.delay(saveBackup.bind(content), 0);
 			haxe.Timer.delay(saveBackup.bind(content), 0);
@@ -682,12 +687,10 @@ class Prefab extends FileView {
 		saveDisplayState("graphicsFilters/" + typeid, enable);
 		saveDisplayState("graphicsFilters/" + typeid, enable);
 
 
 		var r : h3d.scene.Renderer = scene.s3d.renderer;
 		var r : h3d.scene.Renderer = scene.s3d.renderer;
-		var all = data.getAll(hrt.prefab.Object3D, true);
+		var all = data.findAll(hrt.prefab.Object3D, true);
 		for (obj in all) {
 		for (obj in all) {
 			if (obj.getDisplayFilters().contains(typeid)) {
 			if (obj.getDisplayFilters().contains(typeid)) {
-				var ctx = scene.editor.getContext(obj);
-				if (ctx != null)
-					obj.updateInstance(ctx);
+				obj.updateInstance();
 			}
 			}
 		}
 		}
 
 
@@ -703,7 +706,7 @@ class Prefab extends FileView {
 		saveDisplayState("sceneFilters/" + typeid, visible);
 		saveDisplayState("sceneFilters/" + typeid, visible);
 		var all = [];
 		var all = [];
 		if (typeid != 'light')
 		if (typeid != 'light')
-			all = data.getAll(hrt.prefab.Prefab, true);
+			all = data.findAll(hrt.prefab.Prefab, true);
 		else
 		else
 			all = data.flatten(hrt.prefab.Prefab);
 			all = data.flatten(hrt.prefab.Prefab);
 		for(p in all) {
 		for(p in all) {
@@ -741,7 +744,7 @@ class Prefab extends FileView {
 
 
 	function refreshGraphicsFilters() {
 	function refreshGraphicsFilters() {
 		var filters : Array<String> = ["shadows"];
 		var filters : Array<String> = ["shadows"];
-		var all = data.getAll(hrt.prefab.Object3D, true);
+		var all = data.findAll(hrt.prefab.Object3D, true);
 		for (obj in all) {
 		for (obj in all) {
 			var objFilters = obj.getDisplayFilters();
 			var objFilters = obj.getDisplayFilters();
 			for (f in filters) {
 			for (f in filters) {
@@ -837,7 +840,7 @@ class Prefab extends FileView {
 	}
 	}
 
 
 	function applySceneStyle(p: PrefabElement) {
 	function applySceneStyle(p: PrefabElement) {
-		var prefabView = Std.downcast(p, hrt.prefab.Library); // don't use "to" (Reference)
+		var prefabView = Std.downcast(p, hrt.prefab.Prefab); // don't use "to" (Reference)
 		if( prefabView != null && prefabView.parent == null ) {
 		if( prefabView != null && prefabView.parent == null ) {
 			updateGrid();
 			updateGrid();
 			return;
 			return;
@@ -851,8 +854,8 @@ class Prefab extends FileView {
 				if(cdbType != null && sceneFilters.get(cdbType) == false)
 				if(cdbType != null && sceneFilters.get(cdbType) == false)
 					visible = false;
 					visible = false;
 			}
 			}
-			for(ctx in sceneEditor.getContexts(obj3d)) {
-				ctx.local3d.visible = visible;
+			if (obj3d.local3d != null) {
+				obj3d.local3d.visible = visible;
 			}
 			}
 		}
 		}
 		var color = getDisplayColor(p);
 		var color = getDisplayColor(p);
@@ -860,17 +863,17 @@ class Prefab extends FileView {
 			color = (color & 0xffffff) | 0xa0000000;
 			color = (color & 0xffffff) | 0xa0000000;
 			var box = p.to(hrt.prefab.l3d.Box);
 			var box = p.to(hrt.prefab.l3d.Box);
 			if(box != null) {
 			if(box != null) {
-				var ctx = sceneEditor.getContext(box);
-				box.setColor(ctx, color);
+				box.setColor(color);
 			}
 			}
 			var poly = p.to(hrt.prefab.l3d.Polygon);
 			var poly = p.to(hrt.prefab.l3d.Polygon);
 			if(poly != null) {
 			if(poly != null) {
-				var ctx = sceneEditor.getContext(poly);
-				poly.setColor(ctx, color);
+				poly.setColor(color);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
+
+
 	function getDisplayColor(p: PrefabElement) : Null<Int> {
 	function getDisplayColor(p: PrefabElement) : Null<Int> {
 		var typeId = p.getCdbType();
 		var typeId = p.getCdbType();
 		if(typeId != null) {
 		if(typeId != null) {
@@ -883,7 +886,7 @@ class Prefab extends FileView {
 		return null;
 		return null;
 	}
 	}
 
 
-	static var _ = FileTree.registerExtension(Prefab, ["prefab"], { icon : "sitemap", createNew : "Prefab" });
-	static var _1 = FileTree.registerExtension(Prefab, ["l3d"], { icon : "sitemap" });
+	static var _ = hide.view.FileTree.registerExtension(Prefab, ["prefab"], { icon : "sitemap", createNew : "Prefab" });
+	static var _1 = hide.view.FileTree.registerExtension(Prefab, ["l3d"], { icon : "sitemap" });
 
 
 }
 }

+ 18 - 17
hide/view/l3d/Gizmo.hx

@@ -277,7 +277,7 @@ class Gizmo extends h3d.scene.Object {
 			}
 			}
 
 
 			function moveSnap(m: Float) {
 			function moveSnap(m: Float) {
-                return m;
+				return m;
 				/*if(moveStep <= 0 || !scene.editor.getSnapStatus() || axisScale)
 				/*if(moveStep <= 0 || !scene.editor.getSnapStatus() || axisScale)
 					return m;
 					return m;
 
 
@@ -285,7 +285,7 @@ class Gizmo extends h3d.scene.Object {
 				return hxd.Math.round(m / step) * step;*/
 				return hxd.Math.round(m / step) * step;*/
 			}
 			}
 
 
-            var isMove = (mode == MoveX || mode == MoveY || mode == MoveZ || mode == MoveXY || mode == MoveYZ || mode == MoveZX);
+			var isMove = (mode == MoveX || mode == MoveY || mode == MoveZ || mode == MoveXY || mode == MoveYZ || mode == MoveZX);
 
 
 			if(mode == MoveX || mode == MoveXY || mode == MoveZX) vec.x = scene.editor.snap(delta.dot(startMat.front().toPoint()),scene.editor.snapMoveStep);
 			if(mode == MoveX || mode == MoveXY || mode == MoveZX) vec.x = scene.editor.snap(delta.dot(startMat.front().toPoint()),scene.editor.snapMoveStep);
 			if(mode == MoveY || mode == MoveYZ || mode == MoveXY) vec.y = scene.editor.snap(delta.dot(startMat.right().toPoint()),scene.editor.snapMoveStep);
 			if(mode == MoveY || mode == MoveYZ || mode == MoveXY) vec.y = scene.editor.snap(delta.dot(startMat.right().toPoint()),scene.editor.snapMoveStep);
@@ -308,11 +308,11 @@ class Gizmo extends h3d.scene.Object {
 				x = startPos.x + vec.x;
 				x = startPos.x + vec.x;
 				y = startPos.y + vec.y;
 				y = startPos.y + vec.y;
 				z = startPos.z + vec.z;
 				z = startPos.z + vec.z;
-                if (scene.editor.snapForceOnGrid && isMove) {
-                    x = scene.editor.snap(x, scene.editor.snapMoveStep);
-                    y = scene.editor.snap(y, scene.editor.snapMoveStep);
-                    z = scene.editor.snap(z, scene.editor.snapMoveStep);
-                }
+				if (scene.editor.snapForceOnGrid && isMove) {
+					x = scene.editor.snap(x, scene.editor.snapMoveStep);
+					y = scene.editor.snap(y, scene.editor.snapMoveStep);
+					z = scene.editor.snap(z, scene.editor.snapMoveStep);
+				}
 			}
 			}
 
 
 			if(mode == Scale) {
 			if(mode == Scale) {
@@ -320,16 +320,17 @@ class Gizmo extends h3d.scene.Object {
 				vec.set(scale, scale, scale);
 				vec.set(scale, scale, scale);
 			}
 			}
 
 
-            var doRot = false;
+			var doRot = false;
 			if(mode == RotateX || mode == RotateY || mode == RotateZ) {
 			if(mode == RotateX || mode == RotateY || mode == RotateZ) {
 				doRot = true;
 				doRot = true;
-                var v1 = startDragPt.sub(startPos);
+				var v1 = startDragPt.sub(startPos);
 				v1.normalize();
 				v1.normalize();
 				var v2 = curPt.sub(startPos);
 				var v2 = curPt.sub(startPos);
 				v2.normalize();
 				v2.normalize();
 
 
 				var angle = scene.editor.snap(Math.radToDeg(Math.atan2(v1.cross(v2).dot(norm), v1.dot(v2)) * speedFactor), scene.editor.snapRotateStep);
 				var angle = scene.editor.snap(Math.radToDeg(Math.atan2(v1.cross(v2).dot(norm), v1.dot(v2)) * speedFactor), scene.editor.snapRotateStep);
-                angle = Math.degToRad(angle);
+				angle = Math.degToRad(angle);
+
 				if (mode == RotateX && angle != 0) {
 				if (mode == RotateX && angle != 0) {
 					tx.visible = true;
 					tx.visible = true;
 					tx.text = ""+ Math.round(Math.radToDeg(angle)*100)/100. + "°";
 					tx.text = ""+ Math.round(Math.radToDeg(angle)*100)/100. + "°";
@@ -385,10 +386,10 @@ class Gizmo extends h3d.scene.Object {
 					}
 					}
 					else if (doRot) {
 					else if (doRot) {
 						onMove(null, quat, null);
 						onMove(null, quat, null);
-                    }
-                    else {
+					}
+					else {
 						onMove(vec, null, null);
 						onMove(vec, null, null);
-                    }
+					}
 				}
 				}
 			}
 			}
 
 
@@ -440,9 +441,9 @@ class Gizmo extends h3d.scene.Object {
 		var engine = h3d.Engine.getCurrent();
 		var engine = h3d.Engine.getCurrent();
 		var ratio = 150 / engine.height;
 		var ratio = 150 / engine.height;
 		var scale = ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0);
 		var scale = ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0);
-        if (cam.orthoBounds != null) {
-            scale = ratio *  (cam.orthoBounds.xSize) * 0.5;
-        }
+		if (cam.orthoBounds != null) {
+			scale = ratio *  (cam.orthoBounds.xSize) * 0.5;
+		}
 		gizmo.setScale(scale);
 		gizmo.setScale(scale);
 
 
 		if( !moving ) {
 		if( !moving ) {
@@ -457,7 +458,7 @@ class Gizmo extends h3d.scene.Object {
 			gizmo.getObjectByName("yAxis").setRotation(0, 0, dir.y < 0 ? Math.PI : 0);
 			gizmo.getObjectByName("yAxis").setRotation(0, 0, dir.y < 0 ? Math.PI : 0);
 			gizmo.getObjectByName("zAxis").setRotation(dir.z < 0 ? Math.PI : 0, 0, 0);
 			gizmo.getObjectByName("zAxis").setRotation(dir.z < 0 ? Math.PI : 0, 0, 0);
 
 
-            var zrot = dir.x < 0 ? dir.y < 0 ? Math.PI : Math.PI / 2.0 : dir.y < 0 ? -Math.PI / 2.0 : 0;
+			var zrot = dir.x < 0 ? dir.y < 0 ? Math.PI : Math.PI / 2.0 : dir.y < 0 ? -Math.PI / 2.0 : 0;
 
 
 			gizmo.getObjectByName("xy").setRotation(0, 0, zrot);
 			gizmo.getObjectByName("xy").setRotation(0, 0, zrot);
 			gizmo.getObjectByName("xz").setRotation(0, dir.z < 0 ? Math.PI : 0, dir.x < 0 ? Math.PI : 0);
 			gizmo.getObjectByName("xz").setRotation(0, dir.z < 0 ? Math.PI : 0, dir.x < 0 ? Math.PI : 0);

+ 4 - 10
hide/view/l3d/LightProbeBaker.hx

@@ -7,7 +7,6 @@ class LightProbeBaker {
 	public var useGPU = false;
 	public var useGPU = false;
 	public var environment : h3d.scene.pbr.Environment;
 	public var environment : h3d.scene.pbr.Environment;
 
 
-	var context : hrt.prefab.Context;
 	var offScreenScene : h3d.scene.Scene = null;
 	var offScreenScene : h3d.scene.Scene = null;
 	var prim : h3d.prim.Plane2D;
 	var prim : h3d.prim.Plane2D;
 
 
@@ -38,7 +37,6 @@ class LightProbeBaker {
 		customCamera.screenRatio = 1.0;
 		customCamera.screenRatio = 1.0;
 		customCamera.fovY = 90;
 		customCamera.fovY = 90;
 		customCamera.zFar = 100;
 		customCamera.zFar = 100;
-		context = new hrt.prefab.Context();
 	}
 	}
 
 
 	public function dispose() {
 	public function dispose() {
@@ -58,16 +56,11 @@ class LightProbeBaker {
 		if(offScreenScene != null) offScreenScene.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) {
+	public function initScene( sceneData : hrt.prefab.Prefab, scene : hide.comp.Scene , env : h3d.scene.pbr.Environment) {
 		if(offScreenScene != null) offScreenScene.dispose();
 		if(offScreenScene != null) offScreenScene.dispose();
 		offScreenScene = new h3d.scene.Scene();
 		offScreenScene = new h3d.scene.Scene();
 
 
-		var newShared = new hide.prefab.ContextShared(scene, null);
-		newShared.currentPath = shared.currentPath;
-		@:privateAccess newShared.shaderCache =  @:privateAccess hide.Ide.inst.shaderLoader.shaderCache;
-		context.shared = newShared;
-		context.shared.root3d = offScreenScene;
-		context.local3d = offScreenScene;
+		//@:privateAccess sceneData.shared.shaderCache =  @:privateAccess hide.Ide.inst.shaderLoader.shaderCache;
 
 
 		var whiteList = [ "level3d", "object", "model", "material", "light"];
 		var whiteList = [ "level3d", "object", "model", "material", "light"];
 		function keep( p : hrt.prefab.Prefab ) {
 		function keep( p : hrt.prefab.Prefab ) {
@@ -84,7 +77,8 @@ class LightProbeBaker {
 					filter(c);
 					filter(c);
 		}
 		}
 		filter(sceneData);
 		filter(sceneData);
-		sceneData.make(context);
+		var shared = new hrt.prefab.ContextShared(sceneData.shared.root2d, offScreenScene);
+		sceneData.make(shared);
 
 
 		/*function disableFaceCulling( o : Object ){
 		/*function disableFaceCulling( o : Object ){
 			for( m in o.getMaterials() )
 			for( m in o.getMaterials() )

+ 2 - 3
hide/view/l3d/ProbeBakerProcess.hx

@@ -18,8 +18,8 @@ class ProbeBakerProcess {
 		lightProbeBaker.useGPU = useGPU;
 		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 init( env : h3d.scene.pbr.Environment, sceneData : hrt.prefab.Prefab, scene : hide.comp.Scene) {
+		lightProbeBaker.initScene(sceneData, scene, env);
 	}
 	}
 
 
 	public function update(dt:Float) {
 	public function update(dt:Float) {
@@ -37,4 +37,3 @@ class ProbeBakerProcess {
 	}
 	}
 
 
 }
 }
-

+ 10 - 10
hide/view/shadereditor/ShaderEditor.hx

@@ -93,7 +93,7 @@ class PreviewShaderParticle extends hxsl.Shader {
 
 
 class Preview extends h2d.Bitmap {
 class Preview extends h2d.Bitmap {
 
 
-	public var shaderDef(default, set) : hrt.prefab.ContextShared.ShaderDef;
+	public var shaderDef(default, set) : hrt.prefab.Cache.ShaderDef;
 	public var shader : DynamicShader;
 	public var shader : DynamicShader;
 
 
 	function rebuildShader() {
 	function rebuildShader() {
@@ -106,7 +106,7 @@ class Preview extends h2d.Bitmap {
 		addShader(shader);
 		addShader(shader);
 	}
 	}
 
 
-	function set_shaderDef(v: hrt.prefab.ContextShared.ShaderDef) {
+	function set_shaderDef(v: hrt.prefab.Cache.ShaderDef) {
 		shaderDef = v;
 		shaderDef = v;
 		rebuildShader();
 		rebuildShader();
 		return v;
 		return v;
@@ -137,7 +137,7 @@ class ShaderEditor extends hide.view.Graph {
 
 
 	var previewsScene : hide.comp.Scene;
 	var previewsScene : hide.comp.Scene;
 	var previewParamDirty : Bool = true;
 	var previewParamDirty : Bool = true;
-	var currentShaderPreviewsDef : hrt.prefab.ContextShared.ShaderDef;
+	var currentShaderPreviewsDef : hrt.prefab.Cache.ShaderDef;
 
 
 	// used to preview
 	// used to preview
 	var sceneEditor : SceneEditor;
 	var sceneEditor : SceneEditor;
@@ -156,7 +156,7 @@ class ShaderEditor extends hide.view.Graph {
 	var COMPILE_SHADER_DEBOUNCE : Int = 100;
 	var COMPILE_SHADER_DEBOUNCE : Int = 100;
 	var VIEW_VISIBLE_CHECK_TIMER : Int = 500;
 	var VIEW_VISIBLE_CHECK_TIMER : Int = 500;
 	var currentShader : DynamicShader;
 	var currentShader : DynamicShader;
-	var currentShaderDefMainPreview : hrt.prefab.ContextShared.ShaderDef;
+	var currentShaderDefMainPreview : hrt.prefab.Cache.ShaderDef;
 
 
 
 
 
 
@@ -247,9 +247,9 @@ class ShaderEditor extends hide.view.Graph {
 			setDomain(domain);
 			setDomain(domain);
 		});
 		});
 
 
-		var def = new hrt.prefab.Library();
-		new hrt.prefab.RenderProps(def).name = "renderer";
-		defaultLight = new hrt.prefab.Light(def);
+		var def = new hrt.prefab.Prefab(null, null);
+		new hrt.prefab.RenderProps(def, null).name = "renderer";
+		defaultLight = new hrt.prefab.Light(def, null);
 		defaultLight.name = "sunLight";
 		defaultLight.name = "sunLight";
 		defaultLight.kind = Directional;
 		defaultLight.kind = Directional;
 		defaultLight.power = 1.5;
 		defaultLight.power = 1.5;
@@ -506,8 +506,8 @@ class ShaderEditor extends hide.view.Graph {
 		var relative = ide.makeRelative(path);
 		var relative = ide.makeRelative(path);
 		if( ext == "fbx" )
 		if( ext == "fbx" )
 			obj = sceneEditor.scene.loadModel(path, true);
 			obj = sceneEditor.scene.loadModel(path, true);
-		else if( hrt.prefab.Library.getPrefabType(relative) != null ) {
-			var ref = new hrt.prefab.Reference(root);
+		else if( hrt.prefab.Prefab.getPrefabType(relative) != null ) {
+			var ref = new hrt.prefab.Reference(root, null);
 			ref.source = relative;
 			ref.source = relative;
 			sceneEditor.addElements([ref], false, true, false);
 			sceneEditor.addElements([ref], false, true, false);
 			prefabObj = ref;
 			prefabObj = ref;
@@ -1220,7 +1220,7 @@ class ShaderEditor extends hide.view.Graph {
 	}
 	}
 
 
 	function setParamValue(shader : DynamicShader, variable : hxsl.Ast.TVar, value : Dynamic) {
 	function setParamValue(shader : DynamicShader, variable : hxsl.Ast.TVar, value : Dynamic) {
-		@:privateAccess ShaderGraph.setParamValue(sceneEditor.context.shared, shader, variable, value);
+		@:privateAccess ShaderGraph.setParamValue(shader, variable, value);
 	}
 	}
 
 
 	var boxToPreview : Map<Box, Preview>;
 	var boxToPreview : Map<Box, Preview>;

+ 34 - 0
hrt/prefab/Cache.hx

@@ -0,0 +1,34 @@
+package hrt.prefab;
+
+
+typedef ShaderDef = {
+	var shader : hxsl.SharedShader;
+	var inits : Array<{ variable : hxsl.Ast.TVar, value : Dynamic }>;
+}
+
+typedef ShaderDefCache = Map<String, ShaderDef>;
+
+class Cache {
+	static var inst : Cache;
+
+	// Override this with your own cache objets
+	public static dynamic function init() : Cache {
+		var c = new Cache();
+		c.modelCache = new h3d.prim.ModelCache();
+		c.shaderDefCache = new ShaderDefCache();
+		return c;
+	}
+
+	public function new() {
+
+	}
+
+	public static function get() : Cache {
+		if (inst == null)
+			inst = Cache.init();
+		return inst;
+	}
+
+	public var modelCache : h3d.prim.ModelCache = new h3d.prim.ModelCache();
+	public var shaderDefCache : ShaderDefCache = new ShaderDefCache();
+}

+ 0 - 108
hrt/prefab/Context.hx

@@ -1,108 +0,0 @@
-package hrt.prefab;
-
-@:final class Context {
-
-	public var local2d : h2d.Object;
-	public var local3d : h3d.scene.Object;
-	public var shared : ContextShared;
-	public var cleanup(default, set) : Void -> Void;
-	public var custom : Dynamic;
-
-	/**
-		isSceneReference is set to true when this
-		context is a local reference to another prefab
-		within the same scene.
-	**/
-	public var isSceneReference : Bool;
-
-	public function new() {
-	}
-
-	function set_cleanup( fct : Void -> Void ) {
-		this.cleanup = fct;
-		if( fct != null && shared != null && shared.customCleanup != null )
-			shared.customCleanup(this);
-		return this.cleanup;
-	}
-
-	public function init( ?res : hxd.res.Resource ) {
-		if( shared == null )
-			shared = new ContextShared(res);
-		local2d = shared.root2d;
-		local3d = shared.root3d;
-	}
-
-	public function clone( p : Prefab ) {
-		var c = new Context();
-		c.shared = shared;
-		c.local2d = local2d;
-		c.local3d = local3d;
-		c.custom = custom;
-		c.isSceneReference = isSceneReference;
-		if( p != null ) {
-			if( !isSceneReference )
-				shared.contexts.set(p, c);
-			else @:privateAccess {
-				var arr = shared.sceneReferences.get(p);
-				if( arr == null ) {
-					arr = [];
-					shared.sceneReferences.set(p, arr);
-				}
-				arr.push(c);
-			}
-		}
-		return c;
-	}
-
-	public function loadModel( path : String ) {
-		return shared.loadModel(path);
-	}
-
-	public function loadAnimation( path : String ) {
-		return shared.loadAnimation(path);
-	}
-
-	public function loadTexture( path : String ) {
-		return shared.loadTexture(path);
-	}
-
-	public function loadShader( name : String ) {
-		return shared.loadShader(name);
-	}
-
-	public function locateObject( path : String ) {
-		if( path == null )
-			return null;
-		var parts = path.split(".");
-		var root = shared.root3d;
-		while( parts.length > 0 ) {
-			var v = null;
-			var pname = parts.shift();
-			for( o in root )
-				if( o.name == pname ) {
-					v = o;
-					break;
-				}
-			if( v == null ) {
-				v = root.getObjectByName(pname);
-				//if( v != null && v.parent != root ) v = null; ??
-			}
-			if( v == null ) {
-				var parts2 = path.split(".");
-				for( i in 0...parts.length ) parts2.pop();
-				return null;
-			}
-			root = v;
-		}
-		return root;
-	}
-
-	#if editor
-	public function setCurrent() {
-		var shared = Std.downcast(shared, hide.prefab.ContextShared);
-		if( shared == null ) throw "This context was not created by editor!";
-		shared.scene.setCurrent();
-	}
-	#end
-
-}

+ 48 - 162
hrt/prefab/ContextShared.hx

@@ -1,131 +1,56 @@
 package hrt.prefab;
 package hrt.prefab;
 
 
-typedef ShaderDef = {
-	var shader : hxsl.SharedShader;
-	var inits : Array<{ variable : hxsl.Ast.TVar, value : Dynamic }>;
-}
-
-typedef ShaderDefCache = Map<String, ShaderDef>;
-
+#if editor
+typedef ContextShared = hide.prefab.ContextShared;
+class ContextSharedBase {
+#else
 class ContextShared {
 class ContextShared {
-	public var root2d : h2d.Object;
-	public var root3d : h3d.scene.Object;
-	public var contexts : Map<Prefab,Context>;
+#end
+	public var root2d(default, null) : h2d.Object;
+	public var root3d(default, null) : h3d.scene.Object;
+
 	public var currentPath : String;
 	public var currentPath : String;
-	public var editorDisplay : Bool;
+	public var prefabSource : String = "";
 
 
 	/**
 	/**
 		When make() is called on prefab, it will instead call customMake on
 		When make() is called on prefab, it will instead call customMake on
 		each child with current which can either intercept or call make() recursively.
 		each child with current which can either intercept or call make() recursively.
 	 **/
 	 **/
-	public var customMake : Context -> Prefab -> Void;
+	 public var customMake : Prefab -> Void;
+
+	// When make/instanciate is called, this contains the 3d object that should be used as a parent for the newly created object
+	// Never modify this in the middle of a instanciate without restoring it after
+	public var current3d : h3d.scene.Object = null;
+
+	// When make/instanciate is called, this contains the 2d object that should be used as a parent for the newly created object
+	// Never modify this in the middle of a instanciate without restoring it after
+	public var current2d : h2d.Object = null;
+
+	// Parent prefab if the object if it was created as a reference
+	public var parentPrefab : Prefab = null;
 
 
 	/**
 	/**
-		If is a reference to another prefab file, this is the parent prefab.
-		See refContexts for children.
+		Disable some checks at the prefab instanciation time. Used to initialize prefabs that
+		don't need locals2d/3d like shaders
 	**/
 	**/
-	public var parent : { prefab : Prefab, shared : ContextShared };
+	public var isInstance(default, null) : Bool = false;
 
 
-	var cache : h3d.prim.ModelCache;
-	var shaderCache : ShaderDefCache;
 	var bakedData : Map<String, haxe.io.Bytes>;
 	var bakedData : Map<String, haxe.io.Bytes>;
-	/**
-		References to prefab within the same scene
-	**/
-	var sceneReferences : Map<Prefab,Array<Context>>;
-	/**
-		Contexts of references to other prefabs
-	**/
-	var refsContexts : Map<Prefab, ContextShared>;
 
 
-	public var customCleanup : Context -> Void;
+	public function new( ?path : String, ?root2d: h2d.Object = null, ?root3d: h3d.scene.Object = null, isInstance: Bool = true) {
+		if( path != null ) prefabSource = currentPath = path;
+		this.isInstance = isInstance;
+		this.root2d = root2d;
+		this.root3d = root3d;
 
 
-	public function new( ?res : hxd.res.Resource ) {
-		root2d = new h2d.Object();
-		root3d = new h3d.scene.Object();
-		contexts = new Map();
-		cache = new h3d.prim.ModelCache();
-		shaderCache = new ShaderDefCache();
-		sceneReferences = new Map();
-		refsContexts = new Map();
-		if( res != null ) currentPath = res.entry.path;
+		this.current2d = this.root2d;
+		this.current3d = this.root3d;
 	}
 	}
 
 
 	public function onError( e : Dynamic ) {
 	public function onError( e : Dynamic ) {
 		throw e;
 		throw e;
 	}
 	}
 
 
-	public function elements() {
-		return [for(e in contexts.keys()) e];
-	}
-
-	public function getContexts(p: Prefab) : Array<Context> {
-		var ret : Array<Context> = [];
-		var ctx = contexts.get(p);
-		if(ctx != null)
-			ret.push(ctx);
-		var ctxs = sceneReferences.get(p);
-		if( ctxs != null )
-			for( v in ctxs )
-				ret.push(v);
-		for( ref in refsContexts )
-			for( v in ref.getContexts(p) )
-				ret.push(v);
-		return ret;
-	}
-
-	public function find<T:hrt.prefab.Prefab>( cur : Prefab, cl : Class<T>, ?name, ?references ) : T {
-		var root = cur;
-		while( root.parent != null ) root = root.parent;
-		var p = root.getOpt(cl, name, true);
-		if( p != null )
-			return p;
-		if( references ) {
-			for( p => ref in refsContexts ) {
-				var v = ref.find(p, cl, name, true);
-				if( v != null ) return v;
-			}
-		}
-		return null;
-	}
-
-	public function getRef( prefab : Prefab ) {
-		return refsContexts.get(prefab);
-	}
-
-	public function cloneRef( prefab : Prefab, newPath : String ) {
-		var ctx = contexts.get(prefab);
-		if( ctx == null )
-			throw "Prefab reference has no context created";
-		var sh = refsContexts.get(prefab);
-		if( sh != null ) {
-			sh.root2d = ctx.local2d;
-			sh.root3d = ctx.local3d;
-			return sh;
-		}
-		sh = allocForRef();
-		refsContexts.set(prefab, sh);
-
-		sh.root2d = ctx.local2d;
-		sh.root3d = ctx.local3d;
-		// own contexts
-		// own references
-		sh.currentPath = newPath;
-		sh.editorDisplay = editorDisplay;
-		sh.parent = { shared : this, prefab : prefab };
-		sh.cache = cache;
-		sh.shaderCache = shaderCache;
-		sh.customMake = customMake;
-		sh.customCleanup = customCleanup;
-		// own bakedData
-		// own refsContext
-		return sh;
-	}
-
-	function allocForRef() {
-		return new ContextShared();
-	}
-
 	public function loadDir(p : String, ?dir : String ) : Array<hxd.res.Any> {
 	public function loadDir(p : String, ?dir : String ) : Array<hxd.res.Any> {
 		var datPath = new haxe.io.Path(currentPath);
 		var datPath = new haxe.io.Path(currentPath);
 		datPath.ext = "dat";
 		datPath.ext = "dat";
@@ -150,12 +75,8 @@ class ContextShared {
 		throw "Not implemented";
 		throw "Not implemented";
 	}
 	}
 
 
-	public function loadPrefab( path : String ) : Prefab {
-		return hxd.res.Loader.currentInstance.load(path).toPrefab().load();
-	}
-
-	public function loadShader( path : String ) : ShaderDef {
-		var r = shaderCache.get(path);
+	public function loadShader( path : String ) : Cache.ShaderDef {
+		var r = Cache.get().shaderDefCache.get(path);
 		if(r != null)
 		if(r != null)
 			return r;
 			return r;
 		var cl : Class<hxsl.Shader> = cast Type.resolveClass(path.split("/").join("."));
 		var cl : Class<hxsl.Shader> = cast Type.resolveClass(path.split("/").join("."));
@@ -169,20 +90,20 @@ class ContextShared {
 			shader: shader,
 			shader: shader,
 			inits: []
 			inits: []
 		};
 		};
-		shaderCache.set(path, r);
+		Cache.get().shaderDefCache.set(path, r);
 		return r;
 		return r;
 	}
 	}
 
 
 	public function loadModel( path : String ) {
 	public function loadModel( path : String ) {
-		return cache.loadModel(hxd.res.Loader.currentInstance.load(path).toModel());
+		return Cache.get().modelCache.loadModel(hxd.res.Loader.currentInstance.load(path).toModel());
 	}
 	}
 
 
 	public function loadAnimation( path : String ) {
 	public function loadAnimation( path : String ) {
-		return @:privateAccess cache.loadAnimation(hxd.res.Loader.currentInstance.load(path).toModel());
+		return @:privateAccess Cache.get().modelCache.loadAnimation(hxd.res.Loader.currentInstance.load(path).toModel());
 	}
 	}
 
 
 	public function loadTexture( path : String, async : Bool = false ) {
 	public function loadTexture( path : String, async : Bool = false ) {
-		return cache.loadTexture(null, path, async);
+		return Cache.get().modelCache.loadTexture(null, path, async);
 	}
 	}
 
 
 	public function loadBytes( file : String) : haxe.io.Bytes {
 	public function loadBytes( file : String) : haxe.io.Bytes {
@@ -265,31 +186,8 @@ class ContextShared {
 		}
 		}
 	}
 	}
 
 
-	function getChildrenRoots( base : h3d.scene.Object, p : Prefab, out : Array<h3d.scene.Object> ) {
-		for( c in p.children ) {
-			var ctx = contexts.get(c);
-			if( ctx == null ) continue;
-			if( ctx.local3d == base )
-				getChildrenRoots(base, c, out);
-			else
-				out.push(ctx.local3d);
-		}
-		return out;
-	}
-
-	public function getSelfObject( p : Prefab ) : h3d.scene.Object {
-		var ctx = contexts.get(p);
-		if(ctx == null) return null;
-
-		var parentCtx = p.parent != null ? contexts.get(p.parent) : null;
-		if(parentCtx != null && ctx.local3d == parentCtx.local3d)
-			return null;
-
-		return ctx.local3d;
-	}
-
 	public function getObjects<T:h3d.scene.Object>( p : Prefab, c: Class<T> ) : Array<T> {
 	public function getObjects<T:h3d.scene.Object>( p : Prefab, c: Class<T> ) : Array<T> {
-		var root = getSelfObject(p);
+		var root = p.to(Object3D)?.local3d;
 		if(root == null) return [];
 		if(root == null) return [];
 		var childObjs = getChildrenRoots(root, p, []);
 		var childObjs = getChildrenRoots(root, p, []);
 		var ret = [];
 		var ret = [];
@@ -308,28 +206,16 @@ class ContextShared {
 		return ret;
 		return ret;
 	}
 	}
 
 
-	public function getMaterials( p : Prefab ) {
-		var root = getSelfObject(p);
-		if(root == null) return [];
-		var childObjs = getChildrenRoots(root, p, []);
-		var ret = [];
-		function rec(o : h3d.scene.Object) {
-			if( o.isMesh() ) {
-				var m = o.toMesh();
-				var multi = Std.downcast(m, h3d.scene.MultiMaterial);
-				if( multi != null ) {
-					for( m in multi.materials )
-						if( m != null )
-							ret.push(m);
-				} else if( m.material != null )
-					ret.push(m.material);
-			}
-			for( child in o )
-				if( childObjs.indexOf(child) < 0 )
-					rec(child);
+	function getChildrenRoots( base : h3d.scene.Object, p : Prefab, out : Array<h3d.scene.Object> ) {
+		for( c in p.children ) {
+			var o3d = c.to(Object3D);
+			if (o3d == null)
+				return out;
+			if( o3d.local3d == base )
+				getChildrenRoots(base, c, out);
+			else
+				out.push(o3d.local3d);
 		}
 		}
-		rec(root);
-		return ret;
+		return out;
 	}
 	}
-
 }
 }

+ 68 - 46
hrt/prefab/Curve.hx

@@ -1,9 +1,19 @@
 package hrt.prefab;
 package hrt.prefab;
+
+#if editor
+import hide.prefab.EditContext;
+#end
+
+import hide.prefab.HideProps;
+
+import hrt.prefab.fx.Value;
+
 using Lambda;
 using Lambda;
 
 
+@:build(hrt.prefab.Macros.buildSerializable())
 class CurveHandle {
 class CurveHandle {
-	public var dt: Float;
-	public var dv: Float;
+	@:s public var dv: Float = -1; // Force serialization of 0 values for retrocompat
+	@:s public var dt: Float = -1; // Force serialization of 0 values for retrocompat
 	public function new(t, v) {
 	public function new(t, v) {
 		this.dt = t;
 		this.dt = t;
 		this.dv = v;
 		this.dv = v;
@@ -23,12 +33,13 @@ enum abstract CurveBlendMode(Int) {
 	var RandomBlend = 2;
 	var RandomBlend = 2;
 }
 }
 
 
+@:build(hrt.prefab.Macros.buildSerializable())
 class CurveKey {
 class CurveKey {
-	public var time: Float;
-	public var value: Float;
-	public var mode: CurveKeyMode;
-	public var prevHandle: CurveHandle;
-	public var nextHandle: CurveHandle;
+	@:s public var time: Float = -1; // Force serialization of 0 values for retrocompat
+	@:s public var value: Float = -1; // Force serialization of 0 values for retrocompat
+	@:s public var mode: CurveKeyMode = Aligned;
+	@:s public var prevHandle: CurveHandle;
+	@:s public var nextHandle: CurveHandle;
 	public function new() {}
 	public function new() {}
 }
 }
 
 
@@ -37,8 +48,8 @@ typedef CurveKeys = Array<CurveKey>;
 class Curve extends Prefab {
 class Curve extends Prefab {
 
 
 	@:s public var keyMode : CurveKeyMode = Linear;
 	@:s public var keyMode : CurveKeyMode = Linear;
-	@:c public var keys : CurveKeys = [];
-	@:c public var previewKeys : CurveKeys = [];
+	@:s public var keys : CurveKeys = [];
+	@:s public var previewKeys : CurveKeys = [];
 
 
 	@:s public var blendMode : CurveBlendMode = None;
 	@:s public var blendMode : CurveBlendMode = None;
 	@:s public var blendFactor : Float = 0;
 	@:s public var blendFactor : Float = 0;
@@ -64,49 +75,60 @@ class Curve extends Prefab {
 		return keys[keys.length-1].time;
 		return keys[keys.length-1].time;
 	}
 	}
 
 
-   	public function new(?parent) {
-		super(parent);
-		this.type = "curve";
+	   public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 	}
 	}
 
 
 	public override function load(o:Dynamic) {
 	public override function load(o:Dynamic) {
 		super.load(o);
 		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 ) {
 		if( keys.length == 0 ) {
 			addKey(0.0, 0.0);
 			addKey(0.0, 0.0);
 			addKey(1.0, 1.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;
-	}
+	// public override function copy(o:Prefab) {
+	// 	super.copy(o);
+	// 	var p = Std.downcast(o, Curve);
+
+	// 	keys = p.keys;
+	// 	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(to : Dynamic) {
+	// 	var to = super.save(to);
+	// 	var obj = to;
+	// 	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 to;
+	// }
 
 
 	static inline function bezier(c0: Float, c1:Float, c2:Float, c3: Float, t:Float) {
 	static inline function bezier(c0: Float, c1:Float, c2:Float, c3: Float, t:Float) {
 		var u = 1 - t;
 		var u = 1 - t;
@@ -378,7 +400,7 @@ class Curve extends Prefab {
 		return curves.find(c -> StringTools.endsWith(c.name, suffix));
 		return curves.find(c -> StringTools.endsWith(c.name, suffix));
 	}
 	}
 
 
-	public static function getVectorValue(curves: Array<Curve>, defVal: Float=0.0, scale: Float=1.0, blendFactor: Float = 1.0, randomValue: Float = 0) : hrt.prefab.fx.Value {
+	public static function getVectorValue(curves: Array<Curve>, defVal: Float=0.0, scale: Float=1.0, blendFactor: Float = 1.0, randomValue: Float = 0) : Value {
 		inline function find(s) {
 		inline function find(s) {
 			return findCurve(curves, s);
 			return findCurve(curves, s);
 		}
 		}
@@ -387,7 +409,7 @@ class Curve extends Prefab {
 		var z = find(".z");
 		var z = find(".z");
 		var w = find(".w");
 		var w = find(".w");
 
 
-		inline function curveOrVal(c: Curve, defVal: Float) : hrt.prefab.fx.Value {
+		inline function curveOrVal(c: Curve, defVal: Float) : Value {
 			if (c == null)
 			if (c == null)
 				return VConst(defVal);
 				return VConst(defVal);
 
 
@@ -407,7 +429,7 @@ class Curve extends Prefab {
 			curveOrVal(w, 1.0));
 			curveOrVal(w, 1.0));
 	}
 	}
 
 
-	public static function getColorValue(curves: Array<Curve>) : hrt.prefab.fx.Value {
+	public static function getColorValue(curves: Array<Curve>) : Value {
 		inline function find(s) {
 		inline function find(s) {
 			return findCurve(curves, s);
 			return findCurve(curves, s);
 		}
 		}
@@ -441,5 +463,5 @@ class Curve extends Prefab {
 			a != null ? VCurve(a) : VConst(1.0));
 			a != null ? VCurve(a) : VConst(1.0));
 	}
 	}
 
 
-	static var _ = Library.register("curve", Curve);
+	static var _ = Prefab.register("curve", Curve);
 }
 }

+ 11 - 19
hrt/prefab/DynamicShader.hx

@@ -2,14 +2,13 @@ package hrt.prefab;
 
 
 class DynamicShader extends Shader {
 class DynamicShader extends Shader {
 
 
-	var shaderDef : hrt.prefab.ContextShared.ShaderDef;
+	var shaderDef : hrt.prefab.Cache.ShaderDef;
 	var shaderClass : Class<hxsl.Shader>;
 	var shaderClass : Class<hxsl.Shader>;
 	@:s var isInstance : Bool = false;
 	@:s var isInstance : Bool = false;
 	var isShadergraph : Bool = false;
 	var isShadergraph : Bool = false;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "shader";
+	public function new(parent,  shared: ContextShared) {
+		super(parent, shared);
 	}
 	}
 
 
 	override function setShaderParam(shader:hxsl.Shader, v:hxsl.Ast.TVar, value:Dynamic) {
 	override function setShaderParam(shader:hxsl.Shader, v:hxsl.Ast.TVar, value:Dynamic) {
@@ -20,16 +19,15 @@ class DynamicShader extends Shader {
 		cast(shader,hxsl.DynamicShader).setParamValue(v, value);
 		cast(shader,hxsl.DynamicShader).setParamValue(v, value);
 	}
 	}
 
 
-	override function getShaderDefinition(ctx:Context):hxsl.SharedShader {
-		if( shaderDef == null && ctx != null )
-			loadShaderDef(ctx);
+	override function getShaderDefinition():hxsl.SharedShader {
+		if( shaderDef == null)
+			loadShaderDef();
 		return shaderDef == null ? null : shaderDef.shader;
 		return shaderDef == null ? null : shaderDef.shader;
 	}
 	}
 
 
-	override function makeShader( ?ctx:Context ) {
-		if( getShaderDefinition(ctx) == null )
+	override function makeShader() {
+		if( getShaderDefinition() == null )
 			return null;
 			return null;
-		var shader;
 		if( isInstance && !isShadergraph)
 		if( isInstance && !isShadergraph)
 			shader = Type.createInstance(shaderClass,[]);
 			shader = Type.createInstance(shaderClass,[]);
 		else {
 		else {
@@ -43,12 +41,6 @@ class DynamicShader extends Shader {
 		return shader;
 		return shader;
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		if( source == null )
-			return ctx;
-		return super.makeInstance(ctx);
-	}
-
 	function fixSourcePath() {
 	function fixSourcePath() {
 		#if editor
 		#if editor
 		// shader source is loaded with ../src/path/to/Shader.hx
 		// shader source is loaded with ../src/path/to/Shader.hx
@@ -76,7 +68,7 @@ class DynamicShader extends Shader {
 		return cl;
 		return cl;
 	}
 	}
 
 
-	public function loadShaderDef(ctx: Context) {
+	public function loadShaderDef() {
 		if(shaderDef == null) {
 		if(shaderDef == null) {
 			fixSourcePath();
 			fixSourcePath();
 			if (StringTools.endsWith(source, ".shgraph")) {
 			if (StringTools.endsWith(source, ".shgraph")) {
@@ -97,7 +89,7 @@ class DynamicShader extends Shader {
 			} else {
 			} else {
 				var path = source;
 				var path = source;
 				if(StringTools.endsWith(path, ".hx")) path = path.substr(0, -3);
 				if(StringTools.endsWith(path, ".hx")) path = path.substr(0, -3);
-				shaderDef = ctx.loadShader(path);
+				shaderDef = shared.loadShader(path);
 			}
 			}
 		}
 		}
 		if(shaderDef == null)
 		if(shaderDef == null)
@@ -175,5 +167,5 @@ class DynamicShader extends Shader {
 		return null;
 		return null;
 	}
 	}
 
 
-	static var _ = Library.register("shader", DynamicShader);
+	static var _ = Prefab.register("shader", DynamicShader);
 }
 }

+ 0 - 81
hrt/prefab/Library.hx

@@ -1,81 +0,0 @@
-package hrt.prefab;
-
-class Library extends Prefab {
-
-	public function new() {
-		super(null);
-		type = "prefab";
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		if( ctx.shared.parent != null ) ctx = ctx.clone(this);
-		return super.makeInstance(ctx);
-	}
-
-	/**
-		Returns the prefab within children that matches the given absolute path
-	**/
-	public function getFromPath( path : String ) : Prefab {
-		var parts = path.split(".");
-		var cur : Prefab = this;
-		for( p in parts ) {
-			var found = false;
-			for( c in cur.children )
-				if( c.name == p ) {
-					found = true;
-					cur = c;
-					break;
-				}
-			if( !found ) return null;
-		}
-		return cur;
-	}
-
-	static var registeredElements = new Map<String,{ cl : Class<Prefab> #if editor, inf : hide.prefab.HideProps #end }>();
-	static var registeredExtensions = new Map<String,String>();
-
-	public static function getRegistered() {
-		return registeredElements;
-	}
-
-	public static function isOfType( prefabKind : String, cl : Class<Prefab> ) {
-		var inf = registeredElements.get(prefabKind);
-		if( inf == null ) return false;
-		var c : Class<Dynamic> = inf.cl;
-		while( c != null ) {
-			if( c == cl ) return true;
-			c = Type.getSuperClass(c);
-		}
-		return false;
-	}
-
-	public static function register( type : String, cl : Class<Prefab>, ?extension : String ) {
-		registeredElements.set(type, { cl : cl #if editor, inf : Type.createEmptyInstance(cl).getHideProps() #end });
-		if( extension != null ) registeredExtensions.set(extension, type);
-		return true;
-	}
-
-	public static function create( extension : String ) {
-		var type = getPrefabType(extension);
-		var p : hrt.prefab.Prefab;
-		if( type == null )
-			p = new Library();
-		else
-			p = Type.createInstance(registeredElements.get(type).cl,[]);
-		return p;
-	}
-
-	public static function getPrefabType(path: String) {
-		var extension = path.split(".").pop().toLowerCase();
-		return registeredExtensions.get(extension);
-	}
-
-	#if editor
-	override function getHideProps() : HideProps {
-		return { icon : "sitemap", name : "Prefab", allowParent: _ -> false};
-	}
-	#end
-
-	static var _ = Library.register("prefab", Library, "prefab");
-
-}

+ 55 - 53
hrt/prefab/Light.hx

@@ -82,6 +82,10 @@ class Light extends Object3D {
 	// Debug
 	// Debug
 	@:s public var debugDisplay : Bool = true;
 	@:s public var debugDisplay : Bool = true;
 
 
+	#if editor
+	var icon : hrt.impl.EditorTools.EditorIcon = null;
+	#end
+
 	static function getShadowsDefault() : LightShadows {
 	static function getShadowsDefault() : LightShadows {
 		return {
 		return {
 			mode : None,
 			mode : None,
@@ -95,14 +99,13 @@ class Light extends Object3D {
 		};
 		};
 	}
 	}
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "light";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		range = 10;
 		range = 10;
 		zNear = 0.02;
 		zNear = 0.02;
 	}
 	}
 
 
-	override function save() {
+	override function save() : Dynamic {
 		var obj : Dynamic = super.save();
 		var obj : Dynamic = super.save();
 		if( shadows.mode != None ) {
 		if( shadows.mode != None ) {
 			obj.shadows = Reflect.copy(shadows);
 			obj.shadows = Reflect.copy(shadows);
@@ -117,23 +120,23 @@ class Light extends Object3D {
 		super.load(obj);
 		super.load(obj);
 		if( obj.shadows != null ) {
 		if( obj.shadows != null ) {
 			var sh : Dynamic = Reflect.copy(obj.shadows);
 			var sh : Dynamic = Reflect.copy(obj.shadows);
-			sh.mode = h3d.pass.Shadows.RenderMode.createByName(sh.mode);
 			shadows = sh;
 			shadows = sh;
+			shadows.mode = h3d.pass.Shadows.RenderMode.createByName(sh.mode);
 		} else
 		} else
 			shadows = getShadowsDefault();
 			shadows = getShadowsDefault();
 	}
 	}
 
 
-	override function copy(p:Prefab) {
-		super.copy(p);
-		shadows = copyValue(p.shadows);
+	override function applyTransform() {
+		//super.applyTransform(o); // Disable scaling
+		applyTransformToObject(local3d);
 	}
 	}
 
 
-	override function applyTransform( o : h3d.scene.Object ) {
-		//super.applyTransform(o); // Disable scaling
+	public function applyTransformToObject( o : h3d.scene.Object ) {
 		o.x = x;
 		o.x = x;
 		o.y = y;
 		o.y = y;
 		o.z = z;
 		o.z = z;
 		o.setRotation(hxd.Math.degToRad(rotationX), hxd.Math.degToRad(rotationY), hxd.Math.degToRad(rotationZ));
 		o.setRotation(hxd.Math.degToRad(rotationX), hxd.Math.degToRad(rotationY), hxd.Math.degToRad(rotationZ));
+
 	}
 	}
 
 
 	function initTexture( path : String, ?wrap : h3d.mat.Data.Wrap ) {
 	function initTexture( path : String, ?wrap : h3d.mat.Data.Wrap ) {
@@ -145,37 +148,36 @@ class Light extends Object3D {
 		return null;
 		return null;
 	}
 	}
 
 
-	override function makeInstance( ctx : Context ) : Context {
-		ctx = ctx.clone(this);
+	override function makeObject(parent3d:h3d.scene.Object) : h3d.scene.Object {
+		var object : h3d.scene.Object = null;
 
 
 		var isPbr = Std.isOfType(h3d.mat.MaterialSetup.current, h3d.mat.PbrMaterialSetup);
 		var isPbr = Std.isOfType(h3d.mat.MaterialSetup.current, h3d.mat.PbrMaterialSetup);
 		if( !isPbr ) {
 		if( !isPbr ) {
 			switch( kind ) {
 			switch( kind ) {
-			case Point: ctx.local3d = new h3d.scene.fwd.PointLight(ctx.local3d);
-			case Directional: ctx.local3d = new h3d.scene.fwd.DirLight(ctx.local3d);
+			case Point: object = new h3d.scene.fwd.PointLight(parent3d);
+			case Directional: object = new h3d.scene.fwd.DirLight(parent3d);
 			case Spot:
 			case Spot:
 			case Capsule:
 			case Capsule:
 			}
 			}
 		} else {
 		} else {
 			switch( kind ) {
 			switch( kind ) {
-			case Point: ctx.local3d = new h3d.scene.pbr.PointLight(ctx.local3d);
-			case Directional: ctx.local3d = new h3d.scene.pbr.DirLight(ctx.local3d, cascade);
-			case Spot: ctx.local3d = new h3d.scene.pbr.SpotLight(ctx.local3d);
-			case Capsule: ctx.local3d = new h3d.scene.pbr.CapsuleLight(ctx.local3d);
+			case Point: object = new h3d.scene.pbr.PointLight(parent3d);
+			case Directional: object = new h3d.scene.pbr.DirLight(parent3d, cascade);
+			case Spot: object = new h3d.scene.pbr.SpotLight(parent3d);
+			case Capsule: object = new h3d.scene.pbr.CapsuleLight(parent3d);
 			}
 			}
 		}
 		}
-		ctx.local3d.name = name;
 
 
 		#if editor
 		#if editor
-		ctx.custom = hrt.impl.EditorTools.create3DIcon(ctx.local3d, hide.Ide.inst.getHideResPath("icons/PointLight.png"), 0.5, Light);
+		icon = hrt.impl.EditorTools.create3DIcon(local3d, hide.Ide.inst.getHideResPath("icons/PointLight.png"), 0.5, Light);
 		#end
 		#end
 
 
 		cookieTex = initTexture(cookiePath);
 		cookieTex = initTexture(cookiePath);
-		updateInstance(ctx);
-		return ctx;
+
+		return object;
 	}
 	}
 
 
-	#if editor
+	/*#if editor
 	override function removeInstance(ctx:Context):Bool {
 	override function removeInstance(ctx:Context):Bool {
 		var icon = Std.downcast(ctx.custom, hrt.impl.EditorTools.EditorIcon);
 		var icon = Std.downcast(ctx.custom, hrt.impl.EditorTools.EditorIcon);
 		if (icon != null) {
 		if (icon != null) {
@@ -184,17 +186,18 @@ class Light extends Object3D {
 		}
 		}
 		return super.removeInstance(ctx);
 		return super.removeInstance(ctx);
 	}
 	}
-	#end
+	#end*/
 
 
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 
 
 		var color = color | 0xff000000;
 		var color = color | 0xff000000;
-		var pbrLight = Std.downcast(ctx.local3d, h3d.scene.pbr.Light);
-		var light = Std.downcast(ctx.local3d, h3d.scene.pbr.Light);
-		if( pbrLight != null ) { // PBR
-			pbrLight.isMainLight = isMainLight;
-			pbrLight.occlusionFactor = occlusionFactor;
+		var pbrLight = Std.downcast(local3d, h3d.scene.pbr.Light);
+		var light = Std.downcast(local3d, h3d.scene.pbr.Light);
+
+		if( light != null ) { // PBR
+			light.isMainLight = isMainLight;
+			light.occlusionFactor = occlusionFactor;
 
 
 			switch( kind ) {
 			switch( kind ) {
 			case Directional:
 			case Directional:
@@ -266,10 +269,10 @@ class Light extends Object3D {
 		}
 		}
 
 
 		#if editor
 		#if editor
-		var debugPoint = ctx.local3d.find(c -> if(c.name == "_debugPoint") c else null);
-		var debugDir = ctx.local3d.find(c -> if(c.name == "_debugDir") c else null);
-		var debugSpot = ctx.local3d.find(c -> if(c.name == "_debugSpot") c else null);
-		var debugCapsule = ctx.local3d.find(c -> if(c.name == "_debugCapsule") c else null);
+		var debugPoint = local3d.find(c -> if(c.name == "_debugPoint") c else null);
+		var debugDir = local3d.find(c -> if(c.name == "_debugDir") c else null);
+		var debugSpot = local3d.find(c -> if(c.name == "_debugSpot") c else null);
+		var debugCapsule = local3d.find(c -> if(c.name == "_debugCapsule") c else null);
 		var sel : h3d.scene.Object = null;
 		var sel : h3d.scene.Object = null;
 
 
 		switch(kind){
 		switch(kind){
@@ -283,7 +286,7 @@ class Light extends Object3D {
 				var rangeSphere : h3d.scene.Sphere;
 				var rangeSphere : h3d.scene.Sphere;
 
 
 				if(debugPoint == null) {
 				if(debugPoint == null) {
-					debugPoint = new h3d.scene.Object(ctx.local3d);
+					debugPoint = new h3d.scene.Object(local3d);
 					debugPoint.name = "_debugPoint";
 					debugPoint.name = "_debugPoint";
 
 
 					rangeSphere = new h3d.scene.Sphere(0xffffff, 1, true, debugPoint);
 					rangeSphere = new h3d.scene.Sphere(0xffffff, 1, true, debugPoint);
@@ -315,7 +318,7 @@ class Light extends Object3D {
 				if(debugCapsule != null) debugCapsule.remove();
 				if(debugCapsule != null) debugCapsule.remove();
 
 
 				if(debugDir == null) {
 				if(debugDir == null) {
-					debugDir = new h3d.scene.Object(ctx.local3d);
+					debugDir = new h3d.scene.Object(local3d);
 					debugDir.name = "_debugDir";
 					debugDir.name = "_debugDir";
 
 
 
 
@@ -342,7 +345,7 @@ class Light extends Object3D {
 				if(debugCapsule != null) debugCapsule.remove();
 				if(debugCapsule != null) debugCapsule.remove();
 
 
 				if(debugSpot == null) {
 				if(debugSpot == null) {
-					debugSpot = new h3d.scene.Object(ctx.local3d);
+					debugSpot = new h3d.scene.Object(local3d);
 					debugSpot.name = "_debugSpot";
 					debugSpot.name = "_debugSpot";
 
 
 					var g = new h3d.scene.Graphics(debugSpot);
 					var g = new h3d.scene.Graphics(debugSpot);
@@ -387,7 +390,7 @@ class Light extends Object3D {
 				var rangeCapsule : h3d.scene.Capsule;
 				var rangeCapsule : h3d.scene.Capsule;
 
 
 				if(debugCapsule == null) {
 				if(debugCapsule == null) {
-					debugCapsule = new h3d.scene.Object(ctx.local3d);
+					debugCapsule = new h3d.scene.Object(local3d);
 					debugCapsule.name = "_debugCapsule";
 					debugCapsule.name = "_debugCapsule";
 
 
 					rangeCapsule = new h3d.scene.Capsule(0xffffff, 1, true, debugCapsule);
 					rangeCapsule = new h3d.scene.Capsule(0xffffff, 1, true, debugCapsule);
@@ -417,7 +420,6 @@ class Light extends Object3D {
 		}
 		}
 
 
 
 
-		var icon = Std.downcast(ctx.custom, hrt.impl.EditorTools.EditorIcon);
 		if (icon != null) {
 		if (icon != null) {
 			icon.color = h3d.Vector4.fromColor(color);
 			icon.color = h3d.Vector4.fromColor(color);
 
 
@@ -437,10 +439,10 @@ class Light extends Object3D {
 		var isSelected = false;
 		var isSelected = false;
 		if(sel != null){
 		if(sel != null){
 			isSelected = sel.visible;
 			isSelected = sel.visible;
-			if( debugPoint != null ) debugPoint.visible = (isSelected || ctx.shared.editorDisplay);
-			if( debugDir != null ) debugDir.visible = (isSelected || ctx.shared.editorDisplay);
-			if( debugSpot != null ) debugSpot.visible = (isSelected || ctx.shared.editorDisplay);
-			if( debugCapsule != null ) debugCapsule.visible = (isSelected || ctx.shared.editorDisplay);
+			if( debugPoint != null ) debugPoint.visible = (isSelected || shared.editorDisplay);
+			if( debugDir != null ) debugDir.visible = (isSelected || shared.editorDisplay);
+			if( debugSpot != null ) debugSpot.visible = (isSelected || shared.editorDisplay);
+			if( debugCapsule != null ) debugCapsule.visible = (isSelected || shared.editorDisplay);
 			sel.name = "__selection";
 			sel.name = "__selection";
 		}
 		}
 
 
@@ -452,14 +454,14 @@ class Light extends Object3D {
 
 
 	#if editor
 	#if editor
 
 
-	override function setSelected( ctx : Context, b : Bool ) {
-		var sel = ctx.local3d.getObjectByName("__selection");
+	override function setSelected(b : Bool ) {
+		var sel = local3d.getObjectByName("__selection");
 		if( sel != null ) sel.visible = b;
 		if( sel != null ) sel.visible = b;
-		updateInstance(ctx);
+		updateInstance();
 		return true;
 		return true;
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var group = new hide.Element('
 		var group = new hide.Element('
@@ -527,7 +529,7 @@ class Light extends Object3D {
 				ctx.rebuildProperties();
 				ctx.rebuildProperties();
 			}
 			}
 			else{
 			else{
-				if( pname == "cookiePath") cookieTex = loadTexture(ctx, this.cookiePath, cookieTex, Clamp);
+				if( pname == "cookiePath") cookieTex = loadTextureCustom(this.cookiePath, cookieTex, Clamp);
 				ctx.onChange(this, pname);
 				ctx.onChange(this, pname);
 			}
 			}
 		});
 		});
@@ -655,18 +657,18 @@ class Light extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	function loadTexture( ctx : hide.prefab.EditContext, propsName : String, texture : h3d.mat.Texture, ?wrap : h3d.mat.Data.Wrap){
+	function loadTextureCustom(propsName : String, texture : h3d.mat.Texture, ?wrap : h3d.mat.Data.Wrap){
 		if(texture != null) texture.dispose();
 		if(texture != null) texture.dispose();
 		if(propsName == null) return null;
 		if(propsName == null) return null;
-		texture = ctx.rootContext.loadTexture(propsName);
+		texture = shared.loadTexture(propsName);
 		texture.wrap = wrap == null ? Repeat : wrap;
 		texture.wrap = wrap == null ? Repeat : wrap;
 		return texture;
 		return texture;
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "sun-o", name : "Light" };
 		return { icon : "sun-o", name : "Light" };
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("light", Light);
+	static var _ = Prefab.register("light", Light);
 }
 }

+ 753 - 0
hrt/prefab/Macros.hx

@@ -0,0 +1,753 @@
+package hrt.prefab;
+
+import haxe.macro.Context;
+import haxe.macro.Expr;
+import haxe.macro.Type;
+import haxe.macro.ExprTools;
+
+using Lambda;
+
+
+class Macros {
+
+	public static macro function getSerializableProps() : Expr {
+
+		var serializableProps = [];
+		var clRef = Context.getLocalClass();
+		if (clRef == null)
+			throw 'no class';
+		var cl : ClassType = clRef.get();
+
+		while (cl != null) {
+			var fields = cl.fields.get();
+			for (f in fields) {
+				if (f.meta.has(":s")) {
+					serializableProps.push(f);
+				}
+			}
+			if (cl.superClass != null) {
+				cl = cl.superClass.t.get();
+			} else {
+				break;
+			}
+		}
+
+		var serArrayExprs = [
+			for (f in serializableProps) {
+				var props : Array<ObjectField> = [];
+				props.push({
+					field: "name",
+					expr: macro $v{f.name},
+				});
+
+				var meta : Array<ObjectField> = [];
+
+				if (f.doc != null) {
+					meta.push({
+						field: "doc",
+						expr: macro $v{f.doc},
+					});
+				}
+
+				var ranges = f.meta.extract(":range");
+				if (ranges.length > 0) {
+					var range = ranges[0];
+					if (range.params.length > 0) {
+						meta.push({
+							field: "range_min",
+							expr: range.params[0],
+						});
+					}
+					if (range.params.length > 1 ) {
+						meta.push({
+							field: "range_max",
+							expr: range.params[1],
+						});
+					}
+					if (range.params.length > 2 ) {
+						meta.push({
+							field: "range_step",
+							expr: range.params[2],
+						});
+					}
+				}
+
+				props.push({
+					field: "meta",
+					expr: {
+						expr: EObjectDecl(meta),
+						pos: Context.currentPos(),
+					}
+				});
+
+
+				var hasSetter = false;
+				switch(f.kind) {
+					case FVar(_, AccCall):
+						hasSetter = true;
+					default:
+				};
+
+				props.push({
+					field: "hasSetter",
+					expr: macro $v{hasSetter},
+				});
+
+				var e : Expr = macro @:pos(f.pos) null;
+				if (f.expr() != null) {
+					e = Context.getTypedExpr(f.expr());
+				}
+				var defVal = e.expr.match(EConst(_) | EBinop(_) | EUnop(_)) ? e : macro @:pos(f.pos) null;
+
+				props.push({
+					field: "defaultValue",
+					expr: macro ($defVal:Dynamic),
+				});
+
+				{
+					expr: EObjectDecl(props),
+					pos: Context.currentPos(),
+				}
+			}
+		];
+
+		return macro $a{serArrayExprs};
+	}
+
+	public static macro function Cast(e : Expr, typeToCast : String) : Expr {
+		return macro Std.downcast(${e}, $i{typeToCast});
+	}
+
+	public static function enumOrNullByName<T>(e:Enum<T>, constr:String, ?params:Array<Dynamic>, ?defValue:T):T {
+		var value = try {
+			haxe.EnumTools.createByName(e, constr, params);
+		} catch (_) {
+			null;
+		};
+
+		if (value == null) {
+			if (defValue != null)
+				value = defValue;
+			else {
+				var defaultConstructors = std.Type.allEnums(e);
+				if (defaultConstructors.length > 0) value = defaultConstructors[0];
+			}
+		}
+
+		return value;
+	}
+
+	static function tryCopyInst(cl : Ref<ClassType>, params : Array<Type>, funcName : String, source : Expr) : Null<Expr> {
+		switch(cl.toString()){
+			case "Array" | "String":
+				return null;
+			default:
+				var name = cl.get().pack.copy();
+				name.push(cl.get().name);
+				return macro {
+					if ($e{source} != null) {
+						var tmp = std.Type.createEmptyInstance($p{name});
+						@:privateAccess tmp.$funcName($e{source});
+						tmp;
+					}
+					else {
+						null;
+					}
+				}
+		}
+	}
+
+	static macro public function deepCopyFromDynamic(target: Expr, sourceExpr: Expr, defaultValue: Expr) : Expr {
+		var type = Context.typeof(target);
+
+		function custommFilter(type:Type, source:Expr, sourceType:Type, defaultValue: Expr) : Expr {
+			switch (type) {
+				// Fixup string to enum
+				case TEnum(t, _):
+					var path = t.get().pack.copy();
+					path.push(t.get().name);
+					if (defaultValue == null)
+						defaultValue = macro @:pos(source.pos) null;
+					return macro @:pos(source.pos) {
+						if (Std.isOfType($e{source}, String) || $e{source} == null) {
+							hrt.prefab.Macros.enumOrNullByName($p{path}, $e{source}, null, $e{defaultValue});
+						} else {
+							$e{source};
+						}
+					}
+				case TInst(cl, params):
+					return tryCopyInst(cl, params, "copyFromDynamic", source);
+				default:
+					return null;
+			}
+		}
+
+		var e : Expr = deepCopyRec(type, sourceExpr, Context.typeof(sourceExpr), defaultValue, custommFilter);
+
+		var pos = Context.currentPos();
+
+		return macro @:pos(pos) $e{target} = ${e};
+	};
+
+	static macro public function deepCopyFromOther(target: Expr, sourceExpr: Expr, defaultValue: Expr) : Expr {
+		var type = Context.typeof(target);
+
+		function custommFilter(type:Type, source:Expr, sourceType:Type, defaultValue: Expr) : Expr {
+			switch (type) {
+				case TInst(cl, params):
+					return tryCopyInst(cl, params, "copyFromOther", source);
+				default:
+					return null;
+			}
+		}
+
+		var e : Expr = deepCopyRec(type, sourceExpr, Context.typeof(sourceExpr), defaultValue, custommFilter);
+
+		var pos = Context.currentPos();
+
+		return macro @:pos(pos) $e{target} = ${e};
+	};
+
+	static macro public function deepCopyToDynamic(target: Expr, sourceExpr: Expr, defaultValue: Expr) : Expr {
+		var type = Context.typeof(sourceExpr);
+
+		// Transform enum -> strings for json
+		function custommFilter(type:Type, source:Expr, sourceType:Type, defaultValue: Expr) : Expr {
+			switch (sourceType) {
+				case TEnum(t, _):
+					return macro haxe.EnumTools.EnumValueTools.getName($e{source});
+				case TInst(cl, params):
+					switch(cl.toString()){
+						case "Array" | "String":
+							return null;
+						default:
+							var name = cl.get().pack.copy();
+							name.push(cl.get().name);
+							return macro {
+								if ($e{source} != null) {
+									@:privateAccess $e{source}.copyToDynamic({});
+								}
+								else {
+									null;
+								}
+							}
+					}
+				default:
+					return null;
+			}
+		}
+
+		var e : Expr = deepCopyRec(type, sourceExpr, Context.typeof(sourceExpr), null, custommFilter);
+		var pos = Context.currentPos();
+		return macro @:pos(pos) if ($e{shouldSerializeValule(Context.typeof(sourceExpr), sourceExpr, defaultValue)}) $e{target} = ${e};
+	}
+
+	#if macro
+
+	static function shouldSerializeValule(type: Type, a: Expr, b: Expr) : Expr {
+		switch (type) {
+			case TInst(cl, params):
+				switch(cl.toString()){
+					case "Array":
+						return macro @:pos(a.pos) $a.length > 0;
+					}
+			case TType(subtype, _):
+				return shouldSerializeValule(subtype.get().type, a, b);
+			default:
+		}
+		return macro @:pos(a.pos) ${a} != ${b};
+	}
+
+	static public function getDefValueForType(t : Type) {
+		return switch(t) {
+			case TAbstract(t, c):
+				var n = t.get().name;
+				switch(n) {
+					case "Int"|"Float": macro 0;
+					case "Bool": macro false;
+					default: macro null;
+				}
+			default:
+				macro null;
+		}
+	}
+
+	static public function buildPrefab() {
+		var buildFields = Context.getBuildFields();
+
+		var getSerFunc : Function = {
+			args: [],
+			expr: macro {
+				if (serializablePropsFields == null)
+					serializablePropsFields = hrt.prefab.Macros.getSerializableProps();
+				return serializablePropsFields;
+			},
+		};
+
+		buildFields.push({
+			name: "serializablePropsFields",
+			access: [AStatic],
+			kind: FVar(macro : Array<hrt.prefab.Prefab.PrefabField>, macro null),
+			pos: Context.currentPos(),
+		});
+
+		var serFieldField : Field = {
+			name: "getSerializablePropsStatic",
+			doc: "Returns the list of props that have the @:s meta tag associated to them in this prefab type",
+			access: [AStatic, APublic],
+			kind: FFun(getSerFunc),
+			pos: Context.currentPos(),
+		}
+
+		buildFields.push(serFieldField);
+
+		var typeName = Context.getLocalClass().get().name;
+
+
+		for (f in buildFields) {
+			if (f.name == "make") {
+				f.name = "__makeInternal";
+				f.meta.push({name: ":noCompletion", pos:Context.currentPos()});
+			}
+		}
+
+		var expr = macro {
+			if (shared == sh) sh = null;
+			if (sh != null || !this.shared.isInstance) return cast makeClone(sh);
+			return cast __makeInternal();
+		};
+
+		var make : Function = {
+			args: [
+				{ name : "sh", type : macro : hrt.prefab.Prefab.ContextMake, opt: true}
+			],
+			expr: expr,
+			ret: haxe.macro.TypeTools.toComplexType(Context.getLocalType()),
+		}
+
+		var access = [APublic];
+		if (typeName != "Prefab")
+			access.push(AOverride);
+
+		buildFields.push({
+			name: "make",
+			access : access,
+			pos : Context.currentPos(),
+			kind: FFun(make)
+		});
+
+
+
+		var buildFields2 = buildSerializableInternal(buildFields);
+		for (f in buildFields2) {
+			buildFields.push(f);
+		}
+
+		replaceNew(buildFields);
+
+		return buildFields;
+	}
+
+	static public function replaceNew(fields: Array<Field>) {
+		final newName = "__newInit";
+		var localClass = Context.getLocalClass().get();
+		var isRoot = localClass.superClass == null;
+
+		var newReplaced = false;
+		for (f in fields) {
+			if (f.name == "new") {
+				newReplaced = true;
+				f.name = newName;
+				if (!isRoot) {
+					f.access = f.access ?? [];
+					if (!f.access.contains(AOverride))
+						f.access.push(AOverride);
+				}
+
+				f.meta = f.meta ?? [];
+				if (f.meta.find((m) -> m.name == ":noCompletion") == null) {
+					f.meta.push({name: ":noCompletion", pos:Context.currentPos()});
+				}
+
+				switch (f.kind) {
+					case FFun(func): {
+						function rec(e: Expr){
+							switch (e.expr) {
+								case ECall(subE = {expr: EConst(CIdent("super"))}, _):
+									subE.expr = EField({pos:e.pos, expr: EConst(CIdent("super"))}, newName);
+								case _:
+									ExprTools.iter(e, rec);
+							}
+						};
+						ExprTools.iter(func.expr, rec);
+
+						//trace(ExprTools.toString(func.expr));
+					}
+					default:
+						throw "new is not a function";
+				}
+			}
+		}
+
+		if (newReplaced) {
+			var newExpr = null;
+			var access = [APublic];
+			if (isRoot) {
+				newExpr = macro {
+					this.$newName(parent, contextShared);
+				};
+			}
+			else {
+				access.push(AOverride);
+				newExpr = macro {
+					super(parent, contextShared);
+				};
+			}
+
+			var newDecl : Field = {
+				name: "new",
+				access: access,
+				kind: FFun({args:[
+					{name: "parent", type: {macro: hrt.prefab.Prefab;}},
+					{name: "contextShared", type: {macro: hrt.prefab.ContextShared;}},
+				],expr: newExpr}),
+				pos: Context.currentPos(),
+			}
+
+			fields.push(newDecl);
+		}
+	}
+
+	static public function buildSerializable() {
+		var buildFields = Context.getBuildFields();
+		var ser = buildSerializableInternal(buildFields);
+		for (f in ser) {
+			buildFields.push(f);
+		}
+		return buildFields;
+	}
+	static public function buildSerializableInternal(fields: Array<Field>) {
+		var thisClass = Context.getLocalClass();
+		var isRoot = thisClass.get().superClass == null;
+		var buildFields = fields;
+
+		var serializableFields = [];
+		var copyableFields = [];
+		var cloneInitFields : Array<Field> = [];
+		var pos = Context.currentPos();
+
+
+		for (f in buildFields) {
+			if (f.meta == null)
+				continue;
+
+			var isSerializable = false;
+			var isDeepCopy = false;
+			var isCopyable = false;
+			for (m in f.meta) {
+				switch(m.name) {
+					case ":s":
+						isSerializable = true;
+					case ":c":
+						isCopyable = true;
+					case ":deepCopy":
+						isDeepCopy = true;
+				}
+			}
+
+			if (isSerializable) {
+				serializableFields.push({field: f, deepCopy: isDeepCopy});
+			}
+
+			if (isCopyable || isSerializable) {
+				copyableFields.push({field: f, deepCopy: isDeepCopy});
+			}
+
+			if (!isSerializable && !isDeepCopy && !isCopyable) {
+				cloneInitFields.push(f);
+			}
+		}
+
+		var copyFromDynamic : Array<Expr> = [];
+		var copyFromOther : Array<Expr> = [];
+		var copyToDynamic : Array<Expr> = [];
+
+		var root = thisClass;
+		while(root.get().superClass != null) {
+			root = root.get().superClass.t;
+		}
+
+		var rootPath = root.get().pack.copy();
+		rootPath.push(root.get().name);
+
+		if( !isRoot ) {
+			copyFromDynamic.push(macro @:pos(pos) super.copyFromDynamic(obj));
+			copyFromOther.push(macro @:pos(pos) super.copyFromOther(obj));
+			copyToDynamic.push(macro @:pos(pos) obj = super.copyToDynamic(obj));
+
+			{
+				copyFromOther.push(macro @:pos() var obj = cast obj);
+			}
+		}
+
+		function getDefExpr(f:Field, replaceNull: Bool = true) {
+			return switch(f.kind) {
+				case FProp(_, _, t, e), FVar(t,e):
+					if (e == null) {
+						if (replaceNull) {
+							var typ = haxe.macro.ComplexTypeTools.toType(t);
+							getDefValueForType(typ);
+						}
+						else {
+							macro @:pos(pos) null;
+						}
+					} else {
+						e;
+					}
+				default:
+					throw "Invalid serializable field " + f.kind;
+			}
+		}
+
+		for (f in serializableFields) {
+			var name = f.field.name;
+			var defExpr = getDefExpr(f.field);
+			var defExprNull = getDefExpr(f.field);
+
+			copyFromDynamic.push(macro hrt.prefab.Macros.deepCopyFromDynamic(this.$name, obj.$name, $e{defExpr}));
+			copyToDynamic.push(macro hrt.prefab.Macros.deepCopyToDynamic(obj.$name, this.$name, $e{defExprNull}));
+		}
+
+		for (f in copyableFields) {
+			var name = f.field.name;
+			var defExpr = getDefExpr(f.field);
+			if (f.deepCopy) {
+				copyFromOther.push(macro hrt.prefab.Macros.deepCopyFromOther(this.$name, obj.$name, null));
+			} else {
+				copyFromOther.push(macro this.$name = obj.$name);
+			}
+		}
+
+		var cloneInitExprs = [];
+		if (!isRoot) {
+			cloneInitExprs.push(macro super.postCloneInit());
+			for (f in cloneInitFields) {
+				var name = f.name;
+				var isFinal = false;
+				if (f.access != null) {
+					if (f.access.contains(AStatic)) {
+						continue;
+					}
+
+					if (f.access.contains(AFinal)) {
+						isFinal = true;
+					}
+				}
+
+				switch (f.kind) {
+					case FVar(_, defaultValue): {
+						if (defaultValue != null) {
+							if (isFinal) {
+								// Force final initialisation
+								cloneInitExprs.push(macro (this:Dynamic).$name = ${defaultValue});
+							}
+							else {
+								cloneInitExprs.push(macro this.$name = ${defaultValue});
+							}
+						}
+					}
+					case FProp(_,set, _, defaultValue): {
+						if (defaultValue != null) {
+							switch(set) {
+								case "default", "set", "null":
+									cloneInitExprs.push(macro this.$name = ${defaultValue});
+								case "never":
+								default: throw "Unexpected setter kind " + set;
+							}
+						}
+					}
+					default:
+
+				}
+			}
+		}
+
+
+		function makeFun(name,expr, paramType, returnType) : Field {
+			return {
+				name : name,
+				kind : FFun({
+					ret : returnType,
+					expr : { expr : expr, pos : pos },
+					args : paramType != null ? [{ name : "obj", type : paramType }] : [],
+				}),
+				meta : [{ name : ":noCompletion", pos : pos }],
+				access : isRoot ? [] : [AOverride],
+				pos : pos,
+			};
+		}
+
+		var fields = [];
+		fields.push(makeFun("copyFromDynamic", EBlock(copyFromDynamic), macro : Dynamic, null));
+		var rootType =
+		fields.push(makeFun("copyFromOther", EBlock(copyFromOther), Context.toComplexType(TInst(root, [])), null));
+
+		var expr = macro {
+			if (obj == null)
+				obj = {};
+			$b{copyToDynamic};
+			return obj;
+		};
+		fields.push(makeFun("copyToDynamic", EBlock([expr]), macro : Dynamic, macro : Dynamic));
+
+		fields.push(makeFun("postCloneInit", EBlock(cloneInitExprs), null, null));
+
+
+
+		return fields;
+	}
+
+	static public function getFieldType(type: Type, field: String) : Type {
+		switch(type) {
+			case TDynamic(_):
+				return TDynamic(null);
+			case TAnonymous(a):
+				return a.get().fields.find((f) -> f.name == field).type;
+			case TType(a, _):
+				return getFieldType(a.get().type, field);
+			default:
+				throw "Type does not have fields or is not supported";
+		}
+		return null;
+	}
+
+	static public function canBeNull(type:Type) : Bool {
+		return switch (type) {
+			case TDynamic(_):
+				true;
+			case TInst(_, _):
+				true;
+			case TType(a, _):
+				canBeNull(a.get().type);
+			case TAbstract(t,c):
+				if (t.get().name == "Null")
+					true;
+				else
+					false;
+			case TAnonymous(_):
+				return true;
+			case TEnum(_,_):
+				false;
+			default:
+				throw "Unhandled type " + type;
+		}
+	}
+
+	// Custom allow overrides over the behavior of this function if it returns not null
+	static public function deepCopyRec(type:Type, source: Expr, sourceType: Type, ?defaultValue: Expr, custom:(Type, Expr, Type, Null<Expr>) -> Null<Expr>, parentIsArray: Bool = false) : Expr {
+		if (custom != null) {
+			var cus = custom(type, source, sourceType, defaultValue);
+			if (cus != null)
+				return cus;
+		}
+
+		var nullCheck = if (canBeNull(sourceType) && !parentIsArray) {
+			function(source: Expr, ?defaultValue: Expr) : Expr {
+				var defVal = defaultValue != null ? switch(defaultValue.expr) {
+					case EConst(CIdent("null")): null;
+					default: macro $e{defaultValue};
+				} : null;
+				if (defVal != null)
+					return macro @:pos(source.pos) $e{source} != null ? $e{source} : $e{defaultValue};
+				else
+					return macro @:pos(source.pos) $e{source};
+			}
+		} else {
+			function(source: Expr, ?defaultValue: Expr) : Expr {
+				return macro @:pos(source.pos) $e{source};
+			}
+		}
+
+		switch (type) {
+			case TAnonymous(a):
+				var objFields : Array<ObjectField> = [];
+				for (f in a.get().fields) {
+					var name = f.name;
+					var subField = macro @:pos(source.pos) ${source}.$name;
+					var defVal = defaultValue != null ? switch(defaultValue.expr) {
+						case EConst(CIdent("null")): null;
+						default: subField;
+					} : null;
+					var e : Expr = deepCopyRec(f.type, subField, getFieldType(sourceType, name), defVal, custom);
+					objFields.push({field : f.name, expr : e});
+				}
+				var declExpr : Expr = {expr: EObjectDecl(objFields), pos : source.pos};
+				if (defaultValue == null) {
+					defaultValue = macro null;
+				}
+				return macro @:pos(source.pos) {$e{source} != null ? $e{declExpr} : $e{defaultValue}};
+			case TType(t, _):
+				return deepCopyRec(t.get().type, source, sourceType, defaultValue, custom);
+			case TInst(cl, params):
+				switch(cl.toString()) {
+					case "Array":
+						function getArrayType(type: Type) : Type{
+							//trace(type + "");
+							switch (type) {
+								case TDynamic(_):
+									return TDynamic(null);
+								case TInst(cl, params):
+									if (cl.toString() == "Array")
+										return params[0];
+									else
+										return params[0];
+								case TType(a, _):
+									return getArrayType(a.get().type);
+								case TAbstract(a, c):
+									if (a.get().name == "Null") {
+										return getArrayType(c[0]);
+									}
+									throw 'Tying to unserialize non array ($type) into array variable ---';
+								default:
+									throw 'Tying to unserialize non array ($type) into array variable';
+							}
+						}
+
+						var targetType = getArrayType(sourceType);
+
+						if (defaultValue == null)
+							defaultValue = macro @:pos(source.pos) [];
+						return macro @:pos(source.pos) {
+							if ($e{source} == null) $e{defaultValue}
+							else
+							{
+								var _a : Array<Dynamic> = cast $e{source};
+								[for (_elem in _a) $e{hrt.prefab.Macros.deepCopyRec(params[0], macro @:pos(source.pos) _elem, targetType, null, custom, true)}];
+							}
+						};
+					case "String":
+						return nullCheck(source, defaultValue); // No need to copy haxe string as they are immutable
+					default:
+						throw "Can't unserialize " + cl.toString();
+				}
+			case TEnum(t, _):
+				return nullCheck(source, defaultValue);
+			case TAbstract(t,c):
+				if (t.get().name == "Null") {
+					if (defaultValue == null)
+						defaultValue = macro null;
+					return deepCopyRec(c[0], source, sourceType, defaultValue, custom);
+				}
+				else {
+					var trueType = haxe.macro.TypeTools.followWithAbstracts(t.get().type, false);
+					var def = defaultValue != null ? defaultValue : getDefValueForType(t.get().type);
+					return nullCheck(source, defaultValue);
+				}
+			case TDynamic(_):
+				return nullCheck(source, defaultValue);
+			default:
+				throw "error unhandled type " + type;
+		}
+	}
+	#end
+}

+ 53 - 46
hrt/prefab/Material.hx

@@ -3,6 +3,7 @@ package hrt.prefab;
 import h3d.scene.Mesh;
 import h3d.scene.Mesh;
 import h3d.scene.Object;
 import h3d.scene.Object;
 import h3d.mat.PbrMaterial;
 import h3d.mat.PbrMaterial;
+import hide.prefab.HideProps;
 
 
 class Material extends Prefab {
 class Material extends Prefab {
 
 
@@ -16,19 +17,24 @@ class Material extends Prefab {
 	@:s public var refMatLib : String;
 	@:s public var refMatLib : String;
 	@:s public var overrides : Array<Dynamic> = [];
 	@:s public var overrides : Array<Dynamic> = [];
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "material";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		props = {};
 		props = {};
 	}
 	}
 
 
-	override function load(obj:Dynamic) {
+	override function load(obj:Dynamic) : Void {
 		super.load(obj);
 		super.load(obj);
 		color = obj.color != null ? obj.color : [1,1,1,1];
 		color = obj.color != null ? obj.color : [1,1,1,1];
 	}
 	}
 
 
-	override function save() {
-		var obj : Dynamic = super.save();
+	override function copy(o:Prefab) : Void {
+		super.copy(o);
+		var p = Std.downcast(o, Material);
+		this.color = p.color;
+	}
+
+	override function save() : Dynamic {
+		var obj = super.save();
 		if(color != null && h3d.Vector.fromArray(color).toColor() != 0xffffffff) obj.color = color;
 		if(color != null && h3d.Vector.fromArray(color).toColor() != 0xffffffff) obj.color = color;
 		if(mainPassName == "" || mainPassName == null ) Reflect.deleteField(obj, "mainPassName");
 		if(mainPassName == "" || mainPassName == null ) Reflect.deleteField(obj, "mainPassName");
 		return obj;
 		return obj;
@@ -49,8 +55,8 @@ class Material extends Prefab {
 		return r;
 		return r;
 	}
 	}
 
 
-	public function getMaterials( ctx : Context ) {
-		var mats = ctx.local3d.getMaterials();
+	public function getMaterials() {
+		var mats = findFirstLocal3d().getMaterials();
 		var mat = Lambda.find(mats, m -> m.name == this.name || (m.name != null && m.name == materialName));
 		var mat = Lambda.find(mats, m -> m.name == this.name || (m.name != null && m.name == materialName));
 		return mat == null ? mats : [mat];
 		return mat == null ? mats : [mat];
 	}
 	}
@@ -79,11 +85,12 @@ class Material extends Prefab {
 			mat.mainPass.setPassName(mainPassName);
 			mat.mainPass.setPassName(mainPassName);
 	}
 	}
 
 
-	override function updateInstance( ctx : Context, ?propName ) {
-		if( ctx.local3d == null )
+	override function updateInstance(?propName ) {
+		var local3d = findFirstLocal3d();
+		if( local3d == null )
 			return;
 			return;
 
 
-		var mats = getMaterials(ctx);
+		var mats = getMaterials();
 
 
 		if (this.refMatLib != null && this.refMatLib != "") {
 		if (this.refMatLib != null && this.refMatLib != "") {
 			// We want to save some infos to reapply them after loading datas from the choosen mat
 			// We want to save some infos to reapply them after loading datas from the choosen mat
@@ -95,7 +102,7 @@ class Material extends Prefab {
 			var refMatLibPath = this.refMatLib.substring(0, this.refMatLib.lastIndexOf("/"));
 			var refMatLibPath = this.refMatLib.substring(0, this.refMatLib.lastIndexOf("/"));
 			var refMatName = this.refMatLib.substring(this.refMatLib.lastIndexOf("/") + 1);
 			var refMatName = this.refMatLib.substring(this.refMatLib.lastIndexOf("/") + 1);
 
 
-			var prefabLib = hxd.res.Loader.currentInstance.load(refMatLibPath).toPrefab().load().clone(true);
+			var prefabLib = hxd.res.Loader.currentInstance.load(refMatLibPath).toPrefab().load();
 
 
 			for(c in prefabLib.children) {
 			for(c in prefabLib.children) {
 				if (c.name != refMatName)
 				if (c.name != refMatName)
@@ -120,27 +127,27 @@ class Material extends Prefab {
 		if ( mats == null || mats.length == 0 ) {
 		if ( mats == null || mats.length == 0 ) {
 			var sphere = new h3d.prim.Sphere(1., 64, 48);
 			var sphere = new h3d.prim.Sphere(1., 64, 48);
 			sphere.addUVs();
 			sphere.addUVs();
-			sphere.addNormals();
+            sphere.addNormals();
 			sphere.addTangents();
 			sphere.addTangents();
 			var preview = new h3d.scene.Mesh(sphere);
 			var preview = new h3d.scene.Mesh(sphere);
 			preview.name = "materialPreviewSphere";
 			preview.name = "materialPreviewSphere";
-			ctx.local3d.parent.addChild(preview);
-			ctx.local3d = preview;
-			ctx.local3d.x = ctx.local3d.getScene().getMaterials().length * 5.0;
-			mats = getMaterials(ctx);
+			local3d.parent.addChild(preview);
+			local3d = preview;
+			local3d.x = local3d.getScene().getMaterials().length * 5.0;
+			mats = getMaterials();
 		}
 		}
 		#end
 		#end
+		function loadTextureCb( path : String ) : h3d.mat.Texture {
+			return shared.loadTexture(path, false);
+		}
 		for( m in mats )
 		for( m in mats )
-			update(m, props, ctx.loadTexture);
+			update(m, props, loadTextureCb);
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		if(ctx.local3d == null)
-			return ctx;
-		ctx = ctx.clone(this);
 
 
-		updateInstance(ctx);
-		return ctx;
+
+	override function makeInstance() {
+		updateInstance();
 	}
 	}
 
 
 	function applyOverrides() {
 	function applyOverrides() {
@@ -179,7 +186,7 @@ class Material extends Prefab {
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var isPbr = Std.isOfType(ctx.scene.s3d.renderer, h3d.scene.pbr.Renderer);
 		var isPbr = Std.isOfType(ctx.scene.s3d.renderer, h3d.scene.pbr.Renderer);
@@ -222,39 +229,39 @@ class Material extends Prefab {
 
 
 		function updateLibSelect() {
 		function updateLibSelect() {
 			libSelect.empty();
 			libSelect.empty();
-			new Element('<option value="">None</option>').appendTo(libSelect);
+			new hide.Element('<option value="">None</option>').appendTo(libSelect);
 
 
 			for (idx in 0...matLibs.length) {
 			for (idx in 0...matLibs.length) {
-				new Element('<option value="${matLibs[idx].name}" ${(selectedLib == matLibs[idx].path) ? 'selected' : ''}>${matLibs[idx].name}</option>');
+				new hide.Element('<option value="${matLibs[idx].name}" ${(selectedLib == matLibs[idx].path) ? 'selected' : ''}>${matLibs[idx].name}</option>');
 			}
 			}
 		}
 		}
 
 
 		function updateMatSelect() {
 		function updateMatSelect() {
 			matSelect.empty();
 			matSelect.empty();
-			new Element('<option value="">None</option>').appendTo(matSelect);
+			new hide.Element('<option value="">None</option>').appendTo(matSelect);
 
 
 			materials = ctx.scene.listMaterialFromLibrary(this.getAbsPath(), libSelect.val());
 			materials = ctx.scene.listMaterialFromLibrary(this.getAbsPath(), libSelect.val());
 
 
 			for (idx in 0...materials.length) {
 			for (idx in 0...materials.length) {
-				new Element('<option value="${materials[idx].path + "/" + materials[idx].mat.name}" ${(selectedMat == materials[idx].mat.name) ? 'selected' : ''}>${materials[idx].mat.name}</option>').appendTo(matSelect);
+				new hide.Element('<option value="${materials[idx].path + "/" + materials[idx].mat.name}" ${(selectedMat == materials[idx].mat.name) ? 'selected' : ''}>${materials[idx].mat.name}</option>').appendTo(matSelect);
 			}
 			}
 		}
 		}
 
 
 		function updateMat() {
 		function updateMat() {
-			var previousMat = this.clone();
+			var previousMat = this.serialize();
 			var mat = ctx.scene.findMat(materials, matSelect.val());
 			var mat = ctx.scene.findMat(materials, matSelect.val());
 			if ( mat != null ) {
 			if ( mat != null ) {
 				var previousName = this.name;
 				var previousName = this.name;
 				this.load(Reflect.field(mat, "mat"));
 				this.load(Reflect.field(mat, "mat"));
 				this.name = previousName;
 				this.name = previousName;
 				this.refMatLib = Reflect.field(mat, "path") + "/" + Reflect.field(mat, "mat").name;
 				this.refMatLib = Reflect.field(mat, "path") + "/" + Reflect.field(mat, "mat").name;
-				updateInstance(ctx.scene.editor.getContext(this));
+				updateInstance();
 				ctx.rebuildProperties();
 				ctx.rebuildProperties();
 			} else {
 			} else {
 				this.refMatLib = "";
 				this.refMatLib = "";
 			}
 			}
 
 
-			var newMat = this.clone();
+			var newMat = this.serialize();
 
 
 			ctx.properties.undo.change(Custom(function(undo) {
 			ctx.properties.undo.change(Custom(function(undo) {
 				if( undo ) {
 				if( undo ) {
@@ -267,7 +274,7 @@ class Material extends Prefab {
 				updateLibSelect();
 				updateLibSelect();
 				updateMatSelect();
 				updateMatSelect();
 				ctx.rebuildProperties();
 				ctx.rebuildProperties();
-				updateInstance(ctx.scene.editor.getContext(this));
+				updateInstance();
 			}));
 			}));
 		}
 		}
 
 
@@ -335,7 +342,7 @@ class Material extends Prefab {
 
 
 			ctx.onChange(this, "props");
 			ctx.onChange(this, "props");
 
 
-			var fx = getParent(hrt.prefab.fx.FX);
+			var fx = findParent(hrt.prefab.fx.FX);
 			if(fx != null)
 			if(fx != null)
 				ctx.rebuildPrefab(fx, true);
 				ctx.rebuildPrefab(fx, true);
 		});
 		});
@@ -355,12 +362,12 @@ class Material extends Prefab {
 			</div>');
 			</div>');
 			ctx.properties.add(colorMask, this, function(pname) {
 			ctx.properties.add(colorMask, this, function(pname) {
 				ctx.onChange(this, pname);
 				ctx.onChange(this, pname);
-				var fx = getParent(hrt.prefab.fx.FX);
+				var fx = findParent(hrt.prefab.fx.FX);
 				if(fx != null)
 				if(fx != null)
 					ctx.rebuildPrefab(fx, true);
 					ctx.rebuildPrefab(fx, true);
 			});
 			});
 
 
-			function setBit( e : Element, field : String, className : String, bitIndex : Int ) {
+			function setBit( e : hide.Element, field : String, className : String, bitIndex : Int ) {
 				var mask = e.find(className);
 				var mask = e.find(className);
 				var val : Int = cast Reflect.field(pbrProps, field);
 				var val : Int = cast Reflect.field(pbrProps, field);
 				mask.prop("checked", val & (1<<bitIndex) > 0 ? true : false);
 				mask.prop("checked", val & (1<<bitIndex) > 0 ? true : false);
@@ -378,7 +385,7 @@ class Material extends Prefab {
 						mask.prop("checked", val & (1<<bitIndex) > 0 ? true : false);
 						mask.prop("checked", val & (1<<bitIndex) > 0 ? true : false);
 					}));
 					}));
 
 
-					var fx = getParent(hrt.prefab.fx.FX);
+					var fx = findParent(hrt.prefab.fx.FX);
 					if(fx != null)
 					if(fx != null)
 						ctx.rebuildPrefab(fx, true);
 						ctx.rebuildPrefab(fx, true);
 				});
 				});
@@ -499,7 +506,7 @@ class Material extends Prefab {
 					<dt>Name</dt><dd><select><option value="any">Any</option></select>
 					<dt>Name</dt><dd><select><option value="any">Any</option></select>
 				</dl> ');
 				</dl> ');
 		var select = dropDownMaterials.find("select");
 		var select = dropDownMaterials.find("select");
-		var materialList = ctx.rootContext.local3d.getMaterials();
+		var materialList = findFirstLocal3d().getMaterials();
 		for( m in materialList )
 		for( m in materialList )
 			if( m.name != null && m.name != "" )
 			if( m.name != null && m.name != "" )
 				new hide.Element('<option>').attr("value", m.name).text(m.name).appendTo(select);
 				new hide.Element('<option>').attr("value", m.name).text(m.name).appendTo(select);
@@ -518,7 +525,7 @@ class Material extends Prefab {
 			ctx.rebuildProperties();
 			ctx.rebuildProperties();
 			ctx.scene.editor.refresh();
 			ctx.scene.editor.refresh();
 
 
-			var fx = getParent(hrt.prefab.fx.FX);
+			var fx = findParent(hrt.prefab.fx.FX);
 			if(fx != null)
 			if(fx != null)
 				ctx.rebuildPrefab(fx, true);
 				ctx.rebuildPrefab(fx, true);
 		});
 		});
@@ -541,7 +548,7 @@ class Material extends Prefab {
 			if (this.refMatLib != null && this.refMatLib != "")
 			if (this.refMatLib != null && this.refMatLib != "")
 				addOverrideProperty(ctx, pname, false);
 				addOverrideProperty(ctx, pname, false);
 
 
-			var fx = getParent(hrt.prefab.fx.FX);
+			var fx = findParent(hrt.prefab.fx.FX);
 			if(fx != null)
 			if(fx != null)
 				ctx.rebuildPrefab(fx, true);
 				ctx.rebuildPrefab(fx, true);
 		});
 		});
@@ -549,7 +556,7 @@ class Material extends Prefab {
 		updateHighlightOverrides(ctx);
 		updateHighlightOverrides(ctx);
 	}
 	}
 
 
-	public function addOverrideProperty(ctx : EditContext, pname : String, isMatSetupProp : Bool) {
+	public function addOverrideProperty(ctx : hide.prefab.EditContext, pname : String, isMatSetupProp : Bool) {
 		// Remove previous value of this props name in overrides
 		// Remove previous value of this props name in overrides
 		var idx = 0;
 		var idx = 0;
 		while (idx < overrides.length) {
 		while (idx < overrides.length) {
@@ -573,7 +580,7 @@ class Material extends Prefab {
 		updateHighlightOverrides(ctx);
 		updateHighlightOverrides(ctx);
 	}
 	}
 
 
-	public function updateHighlightOverrides(ctx : EditContext) {
+	public function updateHighlightOverrides(ctx : hide.prefab.EditContext) {
 		ctx.properties.element.find(".override").removeClass("override");
 		ctx.properties.element.find(".override").removeClass("override");
 		ctx.properties.element.find(".remove-override-btn").remove();
 		ctx.properties.element.find(".remove-override-btn").remove();
 
 
@@ -592,11 +599,11 @@ class Material extends Prefab {
 			parentDiv.addClass("override");
 			parentDiv.addClass("override");
 
 
 			var label = parentDiv.children().first();
 			var label = parentDiv.children().first();
-			var removeOverrideBtn = new Element('<i title="Remove override" class="remove-override-btn icon ico ico-remove"></i>').insertBefore(label);
+			var removeOverrideBtn = new hide.Element('<i title="Remove override" class="remove-override-btn icon ico ico-remove"></i>').insertBefore(label);
 			removeOverrideBtn.css({ "cursor":"pointer" });
 			removeOverrideBtn.css({ "cursor":"pointer" });
 			removeOverrideBtn.on("click", function(_){
 			removeOverrideBtn.on("click", function(_){
 				overrides.remove(o);
 				overrides.remove(o);
-				updateInstance(ctx.scene.editor.getContext(this));
+				updateInstance();
 				ctx.rebuildProperties();
 				ctx.rebuildProperties();
 			});
 			});
 		}
 		}
@@ -617,7 +624,7 @@ class Material extends Prefab {
 				var refPath = refMatLib.substr(0,refMatLib.lastIndexOf("/"));
 				var refPath = refMatLib.substr(0,refMatLib.lastIndexOf("/"));
 				refMatLib = f(refPath) + refMatLib.substr(refMatLib.lastIndexOf("/"));
 				refMatLib = f(refPath) + refMatLib.substr(refMatLib.lastIndexOf("/"));
 			},
 			},
-			allowChildren: function(t) return !Library.isOfType(t, Material),
+			allowChildren: function(t) return !Prefab.isOfType(t, Material),
 		};
 		};
 	}
 	}
 	#end
 	#end
@@ -630,5 +637,5 @@ class Material extends Prefab {
 		return false;
 		return false;
 	}
 	}
 
 
-	static var _ = Library.register("material", Material);
+	static var _ = Prefab.register("material", Material);
 }
 }

+ 29 - 38
hrt/prefab/Model.hx

@@ -7,24 +7,23 @@ class Model extends Object3D {
 	@:s var retargetAnim : Bool = false;
 	@:s var retargetAnim : Bool = false;
 	@:s var retargetIgnore : String;
 	@:s var retargetIgnore : String;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "model";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 	}
 	}
 
 
-	override function save() {
+	override function save() : Dynamic {
 		if( retargetIgnore == "" ) retargetIgnore = null;
 		if( retargetIgnore == "" ) retargetIgnore = null;
 		return super.save();
 		return super.save();
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
 		if( source == null)
 		if( source == null)
-			return super.makeInstance(ctx);
-		ctx = ctx.clone(this);
+			return super.makeObject(parent3d);
+
 		#if editor
 		#if editor
 		try {
 		try {
 		#end
 		#end
-			var obj = ctx.loadModel(source);
+			var obj = shared.loadModel(source);
 			if(obj.defaultTransform != null && children.length > 0) {
 			if(obj.defaultTransform != null && children.length > 0) {
 				obj.name = "root";
 				obj.name = "root";
 				var root = new h3d.scene.Object();
 				var root = new h3d.scene.Object();
@@ -39,25 +38,19 @@ class Model extends Object3D {
 			if( retargetAnim ) applyRetarget(obj);
 			if( retargetAnim ) applyRetarget(obj);
 
 
 			obj.name = name;
 			obj.name = name;
-			ctx.local3d.addChild(obj);
-			ctx.local3d = obj;
-			updateInstance(ctx);
-
+			parent3d.addChild(obj);
 
 
 			if( animation != null )
 			if( animation != null )
-				obj.playAnimation(ctx.loadAnimation(animation));
+				obj.playAnimation(shared.loadAnimation(animation));
 
 
-			return ctx;
+			return obj;
 		#if editor
 		#if editor
 		} catch( e : Dynamic ) {
 		} catch( e : Dynamic ) {
 			e.message = "Could not load model " + source + ": " + e.message;
 			e.message = "Could not load model " + source + ": " + e.message;
-			ctx.shared.onError(e);
+			shared.onError(e);
 		}
 		}
 		#end
 		#end
-		ctx.local3d = new h3d.scene.Object(ctx.local3d);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return new h3d.scene.Object(parent3d);
 	}
 	}
 
 
 	function applyRetarget( obj : h3d.scene.Object ) {
 	function applyRetarget( obj : h3d.scene.Object ) {
@@ -91,24 +84,24 @@ class Model extends Object3D {
 
 
 	#if editor
 	#if editor
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 		polys3D = null;
 		polys3D = null;
 		boundingSphere = null;
 		boundingSphere = null;
 	}
 	}
 
 
     var polys3D = null;
     var polys3D = null;
     var boundingSphere = null;
     var boundingSphere = null;
-    override function localRayIntersection( ctx : Context, ray : h3d.col.Ray ) : Float {
+    override function localRayIntersection(ray : h3d.col.Ray ) : Float {
         if( polys3D == null ) {
         if( polys3D == null ) {
             polys3D = [];
             polys3D = [];
-            var bounds = ctx.local3d.getBounds();
-			bounds.transform(ctx.local3d.getAbsPos().getInverse());
+            var bounds = local3d.getBounds();
+			bounds.transform(local3d.getAbsPos().getInverse());
             boundingSphere = bounds.toSphere();
             boundingSphere = bounds.toSphere();
-            for( m in ctx.shared.getObjects(this, h3d.scene.Mesh) ) {
+            for( m in getObjects(h3d.scene.Mesh) ) {
                 var p = cast(m.primitive, h3d.prim.HMDModel);
                 var p = cast(m.primitive, h3d.prim.HMDModel);
                	var col = cast(cast(p.getCollider(), h3d.col.Collider.OptimizedCollider).b, h3d.col.PolygonBuffer);
                	var col = cast(cast(p.getCollider(), h3d.col.Collider.OptimizedCollider).b, h3d.col.PolygonBuffer);
-                polys3D.push({ col : col, mat : m.getRelPos(ctx.local3d).getInverse() });
+                polys3D.push({ col : col, mat : m.getRelPos(local3d).getInverse() });
             }
             }
         }
         }
 
 
@@ -127,14 +120,14 @@ class Model extends Object3D {
         return minD;
         return minD;
     }
     }
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 		var props = ctx.properties.add(new hide.Element('
 		var props = ctx.properties.add(new hide.Element('
 			<div class="group" name="Animation">
 			<div class="group" name="Animation">
 				<dl>
 				<dl>
 					<dt>Model</dt><dd><input type="model" field="source"/></dd>
 					<dt>Model</dt><dd><input type="model" field="source"/></dd>
 					<dt/><dd><input type="button" value="Change All" id="changeAll"/></dd>
 					<dt/><dd><input type="button" value="Change All" id="changeAll"/></dd>
-					<dt>Animation</dt><dd><input id="anim" value="--- Choose ---"></dd>
+					<dt>Animation</dt><dd><select><option value="">-- Choose --</option></select>
 					<dt title="Don\'t save animation changes">Lock</dt><dd><input type="checkbox" field="lockAnimation"></dd>
 					<dt title="Don\'t save animation changes">Lock</dt><dd><input type="checkbox" field="lockAnimation"></dd>
 					<dt>Retarget</dt><dd><input type="checkbox" field="retargetAnim"></dd>
 					<dt>Retarget</dt><dd><input type="checkbox" field="retargetAnim"></dd>
 					<dt>Retarget Ignore</dt><dd><input type="text" field="retargetIgnore"></dd>
 					<dt>Retarget Ignore</dt><dd><input type="text" field="retargetIgnore"></dd>
@@ -162,41 +155,39 @@ class Model extends Object3D {
 		select.onChange = function(newAnim : String) {
 		select.onChange = function(newAnim : String) {
 			var v = newAnim;
 			var v = newAnim;
 			var prev = animation;
 			var prev = animation;
-			var obj = ctx.getContext(this).local3d;
+			var obj = local3d;
 			ctx.scene.setCurrent();
 			ctx.scene.setCurrent();
 			if( v == "" ) {
 			if( v == "" ) {
 				animation = null;
 				animation = null;
 				obj.stopAnimation();
 				obj.stopAnimation();
 			} else {
 			} else {
-				obj.playAnimation(ctx.rootContext.loadAnimation(v)).loop = true;
+				obj.playAnimation(shared.loadAnimation(v)).loop = true;
 				if( lockAnimation ) return;
 				if( lockAnimation ) return;
 				animation = v;
 				animation = v;
 			}
 			}
 			var newValue = animation;
 			var newValue = animation;
 			ctx.properties.undo.change(Custom(function(undo) {
 			ctx.properties.undo.change(Custom(function(undo) {
-				var obj = ctx.getContext(this).local3d;
+				var obj = local3d;
 				animation = undo ? prev : newValue;
 				animation = undo ? prev : newValue;
 				if( animation == null ) {
 				if( animation == null ) {
 					obj.stopAnimation();
 					obj.stopAnimation();
 				} else {
 				} else {
-					obj.playAnimation(ctx.rootContext.loadAnimation(animation)).loop = true;
+					obj.playAnimation(shared.loadAnimation(animation)).loop = true;
 				}
 				}
 				select.value = animation;
 				select.value = animation;
 			}));
 			}));
-		}
+		};
 	}
 	}
 
 
-
-
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return {
 		return {
 			icon : "cube", name : "Model", fileSource : ["fbx","hmd"],
 			icon : "cube", name : "Model", fileSource : ["fbx","hmd"],
-			allowChildren : function(t) return Library.isOfType(t,Object3D) || Library.isOfType(t,Material) || Library.isOfType(t,Shader) || Library.isOfType(t, hrt.prefab.fx.AnimEvent),
+			allowChildren : function(t) return Prefab.isOfType(t,Object3D) || Prefab.isOfType(t,Material) || Prefab.isOfType(t,Shader) || Prefab.isOfType(t, hrt.prefab.fx.AnimEvent),
 			onResourceRenamed : function(f) animation = f(animation),
 			onResourceRenamed : function(f) animation = f(animation),
 		};
 		};
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("model", Model);
+	static var _ = Prefab.register("model", Model);
 
 
 }
 }

+ 56 - 52
hrt/prefab/Object2D.hx

@@ -1,17 +1,55 @@
 package hrt.prefab;
 package hrt.prefab;
 import hxd.Math;
 import hxd.Math;
-using Lambda;
 
 
 class Object2D extends Prefab {
 class Object2D extends Prefab {
 
 
-	@:s public var x : Float = 0.;
-	@:s public var y : Float = 0.;
+	public var local2d : h2d.Object = null;
+
+	@:s @:range(0,400) public var x : Float = 0.;
+	@:s @:range(0,400) public var y : Float = 0.;
 	@:s public var scaleX : Float = 1.;
 	@:s public var scaleX : Float = 1.;
 	@:s public var scaleY : Float = 1.;
 	@:s public var scaleY : Float = 1.;
 	@:s public var rotation : Float = 0.;
 	@:s public var rotation : Float = 0.;
 
 
 	@:s public var visible : Bool = true;
 	@:s public var visible : Bool = true;
-	@:c public var blendMode : h2d.BlendMode = None;
+	@:s public var blendMode : h2d.BlendMode = None;
+
+
+	public static inline function getLocal2d(prefab: Prefab) : h2d.Object {
+		var obj2d = Std.downcast(prefab, Object2D);
+		if (obj2d != null)
+			return obj2d.local2d;
+		return null;
+	}
+
+	function makeObject(parent2d: h2d.Object) : h2d.Object {
+		return new h2d.Object(parent2d);
+	}
+
+	override function makeInstance() {
+		local2d = makeObject(shared.current2d);
+		if (local2d != null)
+			local2d.name = name;
+		updateInstance();
+	}
+
+	override function make(?sh:hrt.prefab.Prefab.ContextMake) : Prefab {
+		if (shared.root2d == null) @:privateAccess shared.root2d = shared.current2d = new h2d.Object();
+
+		makeInstance();
+
+		var old2d = shared.current2d;
+		shared.current2d = local2d ?? shared.current2d;
+
+		for (c in children)
+			makeChild(c);
+
+		shared.current2d = old2d;
+
+		postMakeInstance();
+
+		return this;
+	}
 
 
 	public function loadTransform(t) {
 	public function loadTransform(t) {
 		x = t.x;
 		x = t.x;
@@ -33,34 +71,6 @@ class Object2D extends Prefab {
 		rotation = t.rotation;
 		rotation = t.rotation;
 	}
 	}
 
 
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		if( obj.blendMode != null )
-			blendMode = std.Type.createEnum(h2d.BlendMode, obj.blendMode);
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		ctx.local2d = new h2d.Object(ctx.local2d);
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function save() {
-		var o : Dynamic = super.save();
-		if( blendMode != None ) o.blendMode = blendMode.getName();
-		return o;
-	}
-
-	public function getTransform() {
-		var m = new h2d.col.Matrix();
-		m.initScale(scaleX, scaleY);
-		m.rotate(Math.degToRad(rotation));
-		m.translate(x, y);
-		return m;
-	}
-
 	public function applyTransform( o : h2d.Object ) {
 	public function applyTransform( o : h2d.Object ) {
 		o.x = x;
 		o.x = x;
 		o.y = y;
 		o.y = y;
@@ -69,8 +79,8 @@ class Object2D extends Prefab {
 		o.rotation = Math.degToRad(rotation);
 		o.rotation = Math.degToRad(rotation);
 	}
 	}
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		var o = ctx.local2d;
+	override function updateInstance(?propName : String ) {
+		var o = local2d;
 		o.x = x;
 		o.x = x;
 		o.y = y;
 		o.y = y;
 		if(propName == null || propName.indexOf("scale") == 0) {
 		if(propName == null || propName.indexOf("scale") == 0) {
@@ -86,15 +96,16 @@ class Object2D extends Prefab {
 			if (blendMode != null) o.blendMode = blendMode;
 			if (blendMode != null) o.blendMode = blendMode;
 	}
 	}
 
 
-	override function removeInstance(ctx: Context):Bool {
-		if(ctx.local2d != null)
-			ctx.local2d.remove();
-		return true;
-	}
-
 	#if editor
 	#if editor
+	override function getHideProps() : hide.prefab.HideProps {
+		// Check children
+		return {
+			icon : children == null || children.length > 0 ? "folder-open" : "genderless",
+			name : "Group 2D"
+		};
+	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 		var props = new hide.Element('
 			<div class="group" name="Position">
 			<div class="group" name="Position">
 				<dl>
 				<dl>
@@ -116,19 +127,12 @@ class Object2D extends Prefab {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
-		// Check children
-		return {
-			icon : children == null || children.length > 0 ? "folder-open" : "genderless",
-			name : "Group 2D"
-		};
+	override function getDefaultEditorName() {
+		return type == "object2D" ? "group2D" : super.getDefaultEditorName();
 	}
 	}
-	#end
 
 
-	override function getDefaultName() {
-		return type == "object2D" ? "group2D" : super.getDefaultName();
-	}
+	#end
 
 
-	static var _ = Library.register("object2D", Object2D);
+	static var _ = Prefab.register("object2D", Object2D);
 
 
 }
 }

+ 155 - 103
hrt/prefab/Object3D.hx

@@ -1,55 +1,33 @@
 package hrt.prefab;
 package hrt.prefab;
 import hxd.Math;
 import hxd.Math;
-using Lambda;
 
 
 class Object3D extends Prefab {
 class Object3D extends Prefab {
 
 
-	@:s public var x : Float = 0.;
-	@:s public var y : Float = 0.;
-	@:s public var z : Float = 0.;
-	@:s public var scaleX : Float = 1.;
-	@:s public var scaleY : Float = 1.;
-	@:s public var scaleZ : Float = 1.;
-	@:s public var rotationX : Float = 0.;
-	@:s public var rotationY : Float = 0.;
-	@:s public var rotationZ : Float = 0.;
-	@:s public var visible : Bool = true;
+	public var local3d : h3d.scene.Object = null;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "object";
-	}
+	@:s @:range(0,400) public var x : Float = 0.0;
+	@:s @:range(0,400) public var y : Float = 0.0;
+	@:s @:range(0,400) public var z : Float = 0.0;
 
 
-	public function loadTransform(t) {
-		x = t.x;
-		y = t.y;
-		z = t.z;
-		scaleX = t.scaleX;
-		scaleY = t.scaleY;
-		scaleZ = t.scaleZ;
-		rotationX = t.rotationX;
-		rotationY = t.rotationY;
-		rotationZ = t.rotationZ;
-	}
+	@:s public var scaleX : Float = 1.0;
+	@:s public var scaleY : Float = 1.0;
+	@:s public var scaleZ : Float = 1.0;
 
 
-	public function saveTransform() {
-		return { x : x, y : y, z : z, scaleX : scaleX, scaleY : scaleY, scaleZ : scaleZ, rotationX : rotationX, rotationY : rotationY, rotationZ : rotationZ };
-	}
+	@:s public var rotationX : Float = 0.0;
+	@:s public var rotationY : Float = 0.0;
+	@:s public var rotationZ : Float = 0.0;
 
 
-	public function localRayIntersection( ctx : Context, ray : h3d.col.Ray ) : Float {
-		return -1;
-	}
+	@:s public var visible : Bool = true;
 
 
-	function createObject(ctx:Context) {
-		return new h3d.scene.Object(ctx.local3d);
-	}
+	#if editor
+	public var editorIcon : h2d.ObjectFollower;
+	#end
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		ctx.local3d = createObject(ctx);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+	public static inline function getLocal3d(prefab: Prefab) : h3d.scene.Object {
+		var obj3d = Std.downcast(prefab, Object3D);
+		if (obj3d != null)
+			return obj3d.local3d;
+		return null;
 	}
 	}
 
 
 	public function setTransform(mat : h3d.Matrix) {
 	public function setTransform(mat : h3d.Matrix) {
@@ -66,6 +44,61 @@ class Object3D extends Prefab {
 		rotationZ = Math.radToDeg(rot.z);
 		rotationZ = Math.radToDeg(rot.z);
 	}
 	}
 
 
+	override function make( ?sh:hrt.prefab.Prefab.ContextMake) : Prefab {
+		if (shared.root3d == null) @:privateAccess shared.root3d = shared.current3d = new h3d.scene.Object();
+
+		makeInstance();
+
+		var old3d = shared.current3d;
+		shared.current3d = local3d ?? shared.current3d;
+
+		for (c in children)
+			makeChild(c);
+
+		shared.current3d = old3d;
+
+		postMakeInstance();
+
+		return this;
+	}
+
+	/* Override makeObject instead of this */
+	override function makeInstance() : Void {
+		local3d = makeObject(shared.current3d);
+		if( local3d != null )
+			local3d.name = name;
+		updateInstance();
+	}
+
+	function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+		return new h3d.scene.Object(parent3d);
+	}
+
+	override function updateInstance(?propName : String ) {
+		applyTransform();
+		if (local3d != null) {
+			local3d.name = name;
+			local3d.visible = visible;
+		}
+	}
+
+	public static var _ = Prefab.register("object", Object3D);
+
+	public function saveTransform() {
+		return { x : x, y : y, z : z, scaleX : scaleX, scaleY : scaleY, scaleZ : scaleZ, rotationX : rotationX, rotationY : rotationY, rotationZ : rotationZ };
+	}
+
+	public function applyTransform() {
+		var o = local3d;
+		if (o == null) return;
+		o.x = x;
+		o.y = y;
+		o.z = z;
+		o.scaleX = scaleX;
+		o.scaleY = scaleY;
+		o.scaleZ = scaleZ;
+		o.setRotation(Math.degToRad(rotationX), Math.degToRad(rotationY), Math.degToRad(rotationZ));
+	}
 
 
 	public function getTransform( ?m: h3d.Matrix ) {
 	public function getTransform( ?m: h3d.Matrix ) {
 		if( m == null ) m = new h3d.Matrix();
 		if( m == null ) m = new h3d.Matrix();
@@ -75,11 +108,31 @@ class Object3D extends Prefab {
 		return m;
 		return m;
 	}
 	}
 
 
-	public function getAbsPos() {
+	public function localRayIntersection(ray : h3d.col.Ray ) : Float {
+		return -1;
+	}
+
+	public function loadTransform(t) {
+		x = t.x;
+		y = t.y;
+		z = t.z;
+		scaleX = t.scaleX;
+		scaleY = t.scaleY;
+		scaleZ = t.scaleZ;
+		rotationX = t.rotationX;
+		rotationY = t.rotationY;
+		rotationZ = t.rotationZ;
+	}
+
+	public function getAbsPos( followRefs : Bool = false ) {
 		var p = parent;
 		var p = parent;
 		while( p != null ) {
 		while( p != null ) {
 			var obj = p.to(Object3D);
 			var obj = p.to(Object3D);
 			if( obj == null ) {
 			if( obj == null ) {
+				if( p.parent == null && followRefs ) {
+					p = p.shared.parentPrefab;
+					continue;
+				}
 				p = p.parent;
 				p = p.parent;
 				continue;
 				continue;
 			}
 			}
@@ -91,41 +144,38 @@ class Object3D extends Prefab {
 		return getTransform();
 		return getTransform();
 	}
 	}
 
 
-	public function applyTransform( o : h3d.scene.Object ) {
-		o.x = x;
-		o.y = y;
-		o.z = z;
-		o.scaleX = scaleX;
-		o.scaleY = scaleY;
-		o.scaleZ = scaleZ;
-		o.setRotation(Math.degToRad(rotationX), Math.degToRad(rotationY), Math.degToRad(rotationZ));
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		var o = ctx.local3d;
-		applyTransform(o);
-		o.visible = visible;
-		#if editor
-		addEditorUI(ctx);
-		#end
+	/**
+		Returns the list of all h3d.scene.Object with the given class contained
+		by this prefab and all of it's children
+	**/
+	public function getObjects<T:h3d.scene.Object>(c: Class<T> ) : Array<T> {
+		var root = Object3D.getLocal3d(this);
+		if(root == null) return [];
+		var childObjs = Prefab.getChildrenRoots(root, this, []);
+		var ret = [];
+		function rec(o : h3d.scene.Object) {
+			var m = Std.downcast(o, c);
+			if(m != null) {
+				ret.push(m);
+			}
+			for( child in o )
+				if( childObjs.indexOf(child) < 0 )
+					rec(child);
+		}
+		rec(root);
+		return ret;
 	}
 	}
 
 
-	override function removeInstance(ctx: Context):Bool {
-		if(ctx.local3d != null)
-			ctx.local3d.remove();
-		#if editor
-		if( ctx.local2d != null ) {
-			var f = Std.downcast(ctx.local2d, h2d.ObjectFollower);
-			if( f != null && f.follow == ctx.local3d ) f.remove();
-		}
-		#end
-		return true;
+	public function getDisplayFilters() : Array<String> {
+		return [];
 	}
 	}
 
 
-	#if editor
+#if editor
+	override function setSelected(b:Bool):Bool {
+		if (local3d == null)
+			return true;
 
 
-	override function setSelected(ctx:Context, b:Bool):Bool {
-		var materials = ctx.shared.getMaterials(this);
+		var materials = local3d.getMaterials();
 
 
 		if( !b ) {
 		if( !b ) {
 			for( m in materials ) {
 			for( m in materials ) {
@@ -155,23 +205,25 @@ class Object3D extends Prefab {
 		return true;
 		return true;
 	}
 	}
 
 
-	public function addEditorUI( ctx : Context ) {
-		for( r in ctx.shared.getObjects(this,h3d.scene.Object) )
-			if( r.name != null && StringTools.startsWith(r.name,"$UI.") )
-				r.remove();
+	public function addEditorUI(ctx : hide.prefab.EditContext) {
+		var objs = findAll(Object3D, true);
+		for( obj in objs ) {
+			var local3d : h3d.scene.Object = obj.local3d;
+			if( local3d.name != null && StringTools.startsWith(local3d.name,"$UI.") )
+				local3d.remove();
+		}
 		// add ranges
 		// add ranges
-		var shared = Std.downcast(ctx.shared, hide.prefab.ContextShared);
-		if( shared != null && shared.editorDisplay ) {
+
 			var sheet = getCdbType();
 			var sheet = getCdbType();
 			if( sheet != null ) {
 			if( sheet != null ) {
 				var ide = hide.Ide.inst;
 				var ide = hide.Ide.inst;
-				var ranges = Reflect.field(shared.scene.config.get("sceneeditor.ranges"), sheet);
+			var ranges = Reflect.field(ctx.scene.config.get("sceneeditor.ranges"), sheet);
 				if( ranges != null ) {
 				if( ranges != null ) {
 					for( key in Reflect.fields(ranges) ) {
 					for( key in Reflect.fields(ranges) ) {
 						var color = Std.parseInt(Reflect.field(ranges,key));
 						var color = Std.parseInt(Reflect.field(ranges,key));
 						var value : Dynamic = hide.comp.cdb.DataFiles.resolveCDBValue(sheet,key, props);
 						var value : Dynamic = hide.comp.cdb.DataFiles.resolveCDBValue(sheet,key, props);
 						if( value != null ) {
 						if( value != null ) {
-							var mesh = new h3d.scene.Mesh(hrt.prefab.l3d.Spray.makePrimCircle(128, 0.99), ctx.local3d);
+						var mesh = new h3d.scene.Mesh(hrt.prefab.l3d.Spray.makePrimCircle(128, 0.99), local3d);
 							mesh.name = "$UI.RANGE";
 							mesh.name = "$UI.RANGE";
 							mesh.ignoreCollide = true;
 							mesh.ignoreCollide = true;
 							mesh.ignoreBounds = true;
 							mesh.ignoreBounds = true;
@@ -186,14 +238,14 @@ class Object3D extends Prefab {
 						}
 						}
 					}
 					}
 				}
 				}
-				var huds : Dynamic = shared.scene.config.get("sceneeditor.huds");
+			var huds : Dynamic = ctx.scene.config.get("sceneeditor.huds");
 				var icon = Reflect.field(huds, sheet);
 				var icon = Reflect.field(huds, sheet);
 				if( icon != null ) {
 				if( icon != null ) {
 					var t : Dynamic = hide.comp.cdb.DataFiles.resolveCDBValue(sheet,icon, props);
 					var t : Dynamic = hide.comp.cdb.DataFiles.resolveCDBValue(sheet,icon, props);
 					if( t != null && (t.file != null || Std.isOfType(t,String)) ) {
 					if( t != null && (t.file != null || Std.isOfType(t,String)) ) {
-						var obj = Std.downcast(ctx.local2d, h2d.ObjectFollower);
-						if( obj == null || obj.follow != ctx.local3d ) {
-							ctx.local2d = obj = new h2d.ObjectFollower(ctx.local3d, ctx.local2d);
+					var obj = editorIcon;
+					if( obj == null || obj.follow != local3d ) {
+						editorIcon = obj = new h2d.ObjectFollower(local3d, shared.root2d);
 							obj.horizontalAlign = Middle;
 							obj.horizontalAlign = Middle;
 							obj.followVisibility = true;
 							obj.followVisibility = true;
 						}
 						}
@@ -206,7 +258,7 @@ class Object3D extends Prefab {
 								bmp = new h2d.Bitmap(null, obj);
 								bmp = new h2d.Bitmap(null, obj);
 								bmp.name = "$huds";
 								bmp.name = "$huds";
 							}
 							}
-							bmp.tile = h2d.Tile.fromTexture(ctx.loadTexture(t.file)).sub(
+						bmp.tile = h2d.Tile.fromTexture(shared.loadTexture(t.file)).sub(
 								t.x * t.size,
 								t.x * t.size,
 								t.y * t.size,
 								t.y * t.size,
 								(t.width == null ? 1 : t.width) * t.size,
 								(t.width == null ? 1 : t.width) * t.size,
@@ -220,7 +272,7 @@ class Object3D extends Prefab {
 								int.y = bmp.tile.dy;
 								int.y = bmp.tile.dy;
 
 
 								int.onClick = function(e) {
 								int.onClick = function(e) {
-									var editorContext = Std.downcast(ctx.shared, hide.prefab.ContextShared);
+									var editorContext = Std.downcast(shared, hide.prefab.ContextShared);
 									if (editorContext != null)
 									if (editorContext != null)
 										editorContext.editor.selectElements([ this ]);
 										editorContext.editor.selectElements([ this ]);
 								}
 								}
@@ -247,13 +299,15 @@ class Object3D extends Prefab {
 				}
 				}
 			}
 			}
 		}
 		}
-	}
 
 
-	override function makeInteractive( ctx : Context ) : hxd.SceneEvents.Interactive {
-		var local3d = ctx.local3d;
+	override function makeInteractive() : hxd.SceneEvents.Interactive {
 		if(local3d == null)
 		if(local3d == null)
 			return null;
 			return null;
-		var meshes = ctx.shared.getObjects(this, h3d.scene.Mesh);
+		var meshes = getObjects(h3d.scene.Mesh);
+		var mesh = Std.downcast(local3d, h3d.scene.Mesh);
+		if (mesh != null ) {
+			meshes.push(mesh);
+		}// ctx.shared.getObjects(this, h3d.scene.Mesh);
 		var invRootMat = local3d.getAbsPos().clone();
 		var invRootMat = local3d.getAbsPos().clone();
 		invRootMat.invert();
 		invRootMat.invert();
 		var bounds = new h3d.col.Bounds();
 		var bounds = new h3d.col.Bounds();
@@ -297,6 +351,14 @@ class Object3D extends Prefab {
 				continue;
 				continue;
 			}
 			}
 
 
+			var asIcon = Std.downcast(mesh, hrt.impl.EditorTools.EditorIcon);
+			if (asIcon != null) {
+				hasSkin = true; // hack
+				/*var pos = asIcon.getAbsPos();
+				bounds.addSpherePos(pos.tx, pos.ty, pos.tz, asIcon.billboardScale);*/
+				continue;
+			}
+
 			var lb = mesh.primitive.getBounds().clone();
 			var lb = mesh.primitive.getBounds().clone();
 			lb.transform(localMat);
 			lb.transform(localMat);
 			bounds.add(lb);
 			bounds.add(lb);
@@ -332,7 +394,7 @@ class Object3D extends Prefab {
 		return int;
 		return int;
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 		var props = new hide.Element('
 			<div class="group" name="Position">
 			<div class="group" name="Position">
 				<dl>
 				<dl>
@@ -352,11 +414,7 @@ class Object3D extends Prefab {
 		});
 		});
 	}
 	}
 
 
-	public function getDisplayFilters() : Array<String> {
-		return [];
-	}
-
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		// Check children
 		// Check children
 		var cname = Type.getClassName(Type.getClass(this)).split(".").pop();
 		var cname = Type.getClassName(Type.getClass(this)).split(".").pop();
 		return {
 		return {
@@ -364,12 +422,6 @@ class Object3D extends Prefab {
 			name : cname == "Object3D" ? "Group" : cname,
 			name : cname == "Object3D" ? "Group" : cname,
 		};
 		};
 	}
 	}
-	#end
-
-	override function getDefaultName() {
-		return type == "object" ? "group" : super.getDefaultName();
-	}
-
-	static var _ = Library.register("object", Object3D);
 
 
+#end // if editor
 }
 }

+ 514 - 245
hrt/prefab/Prefab.hx

@@ -1,25 +1,54 @@
 package hrt.prefab;
 package hrt.prefab;
 
 
-/**
-	Prefab is an data-oriented tree container capable of creating instances of Heaps objects.
-**/
-@:keepSub @:build(hrt.impl.Macros.buildPrefab()) @:autoBuild(hrt.impl.Macros.buildPrefab())
+typedef PrefabField = {
+	var name : String;
+	var hasSetter : Bool;
+	var meta : PrefabMeta;
+	var defaultValue : Dynamic;
+}
+
+typedef PrefabMeta = {
+	var ?doc : String;
+	var ?range_min : Float;
+	var ?range_max : Float;
+	var ?range_step : Float;
+}
+
+typedef PrefabInfo = {
+	var prefabClass : Class<Prefab>;
+	var ?extension: String;
+	#if editor
+	var inf : hide.prefab.HideProps;
+	#end
+};
+
+@:access(Prefab)
+abstract ContextMake(ContextShared) from ContextShared to ContextShared {
+
+	@:from static function fromObject3D( parent : h3d.scene.Object ) : ContextMake {
+		return new ContextShared(parent, true);
+	}
+
+	@:from static function fromObject2D( parent : h2d.Object ) : ContextMake {
+		return new ContextShared(parent, true);
+	}
+}
+
+@:allow(hide)
+@:keepSub
+@:autoBuild(hrt.prefab.Macros.buildPrefab())
+@:build(hrt.prefab.Macros.buildPrefab())
 class Prefab {
 class Prefab {
 
 
 	/**
 	/**
-		The type of prefab, allows to identify which class it should be loaded with.
+		The registered type name for this prefab, used to identify a prefab when serializing
 	**/
 	**/
-	@:s public var type(default, null) : String;
+	public var type(get, never) : String;
 
 
 	/**
 	/**
 		The name of the prefab in the tree view
 		The name of the prefab in the tree view
 	**/
 	**/
-	@:s public var name : String;
-
-	/**
-		The parent of the prefab in the tree view
-	**/
-	public var parent(default, set) : Prefab;
+	@:s public var name : String = "";
 
 
 	/**
 	/**
 		The associated source file (an image, a 3D model, etc.) if the prefab type needs it.
 		The associated source file (an image, a 3D model, etc.) if the prefab type needs it.
@@ -27,9 +56,9 @@ class Prefab {
 	@:s public var source : String;
 	@:s public var source : String;
 
 
 	/**
 	/**
-		The list of children prefab in the tree view
+		The parent of the prefab in the tree view
 	**/
 	**/
-	public var children(default, null) : Array<Prefab>;
+	public var children : Array<Prefab> = [];
 
 
 	/**
 	/**
 		Tells if the prefab will create an instance when calling make() or be ignored. Also apply to this prefab children.
 		Tells if the prefab will create an instance when calling make() or be ignored. Also apply to this prefab children.
@@ -60,140 +89,157 @@ class Prefab {
 	/**
 	/**
 		A storage for some extra properties
 		A storage for some extra properties
 	**/
 	**/
-	@:s public var props : Any;
+	@:s public var props : Any = null;
 
 
 	/**
 	/**
-		Creates a new prefab with the given parent.
+		The parent of the prefab in the tree view
 	**/
 	**/
-	public function new(?parent : Prefab) {
-		this.parent = parent;
-		children = [];
+	public var parent(default, set) : Prefab;
+
+	/**
+		Infos shared by all the prefabs in a given prefab hierarchy (but not by references)
+	**/
+	public var shared(default, null) : ContextShared;
+
+	// Public API
+
+	public function new(parent:Prefab, contextShared: ContextShared) {
+		initParentShared(parent, contextShared);
+	}
+
+	function initParentShared(parent:Prefab, contextShared: ContextShared) {
+		if (parent == null) {
+			shared = contextShared;
+			if (shared == null) {
+				shared = new ContextShared(false);
+			}
+		}
+		else
+			this.parent = parent;
+	}
+
+	function get_type() {
+		var thisClass = Type.getClass(this);
+		return getClassTypeName(thisClass);
 	}
 	}
 
 
 	function set_parent(p) {
 	function set_parent(p) {
-		if( parent != null )
+		if( parent != null ) {
 			parent.children.remove(this);
 			parent.children.remove(this);
+		}
 		parent = p;
 		parent = p;
-		if( parent != null )
+		if( parent != null ) {
+			this.shared = parent.shared;
 			parent.children.push(this);
 			parent.children.push(this);
+		}
+		else {
+			setSharedRec(new ContextShared(false));
+		}
 		return p;
 		return p;
 	}
 	}
 
 
-	#if editor
-
 	/**
 	/**
-		Allows to customize how the prefab object is edited within Hide
+		Instanciate this prefab. If `newContextShared` is given or if `this.shared.isInstance` is false,
+		this prefab is cloned and then the clone is instanciated and returned.
+		If `this.shared.isInstance` is true, this prefab is instanciated instead.
 	**/
 	**/
-	public function edit( ctx : hide.prefab.EditContext ) {
-	}
+	public function make( ?sh:ContextMake ) : Prefab {
+		// -- There is generated code here to properly clone the prefab if sh is set. See hrt.prefab.Macros
+		makeInstance();
+		for (c in children)
+			makeChild(c);
+		postMakeInstance();
 
 
-	/**
-		Allows to customize how the prefab object is displayed / handled within Hide
-	**/
-	public function getHideProps() : hide.prefab.HideProps {
-		return { icon : "question-circle", name : "Unknown" };
+		return this;
 	}
 	}
 
 
-	/**
-		Allows to customize how the prefab instance changes when selected/unselected within Hide.
-		Selection of descendants is skipped if false is returned.
-	**/
-	public function setSelected( ctx : Context, b : Bool ) {
-		return true;
+	function makeClone(?sh:ContextShared) : Prefab {
+		if( sh == null ) {
+			sh = new ContextShared(shared.currentPath);
+		}
+		if( !sh.isInstance ) throw "assert";
+		if( sh.currentPath == null ) sh.currentPath = shared.currentPath;
+		#if editor
+		sh.editor = this.shared.editor;
+		#end
+		return this.clone(sh).make(sh);
 	}
 	}
 
 
 	/**
 	/**
-		Allows the prefab to create an interactive so it can be selected in the scene.
+		Create a copy of the data this prefab and all of it's children (unless `withChildren` is `false`), without calling `make()` on them.
+		If `parent` is given, then `sh` will be set to `parent.shared`. If `parent` and `sh` is null, `sh` will be set to a new context shared will be created.
+		The `parent` and `sh` are then given to the clone constructor.
 	**/
 	**/
-	public function makeInteractive( ctx : Context ) : hxd.SceneEvents.Interactive {
-		return null;
-	}
+	public function clone(?parent:Prefab = null, ?sh: ContextShared = null, withChildren : Bool = true) : Prefab {
+		if (parent != null && sh != null && parent.shared != sh)
+			throw "Both parent and sh are set but shared don't match";
 
 
-	#end
+		if (sh == null) {
+			if (parent != null) {
+				sh = parent.shared;
+			} else {
+				sh = new hrt.prefab.ContextShared(this.shared.currentPath, true);
+				#if editor
+				sh.editor = shared.editor;
+				#end
+			}
+		}
 
 
-	/**
-		Iterate over children prefab
-	**/
-	public inline function iterator() : Iterator<Prefab> {
-		return children.iterator();
-	}
+		var thisClass = Type.getClass(this);
 
 
-	/**
-		Override to implement your custom prefab data loading
-	**/
-	function load( obj : Dynamic ) {
-		loadSerializedFields(obj);
-	}
+		// We bypass the normal new function to avoid initializing the
+		// serializable fields, because they will be initialized by the copy function
+		var inst = Type.createEmptyInstance(thisClass);
+		inst.postCloneInit();		// Macro function that init all the non serializable fields of a prefab
+		inst.children = [];
+		inst.__newInit(parent, sh);// Macro function that contains the code of the new function
 
 
-	/**
-		Override to implement your custom prefab data saving
-	**/
-	function save() : {} {
-		var obj = {};
-		saveSerializedFields(obj);
-		return obj;
-	}
+		inst.copy(this);
+		if (withChildren) {
+			for (child in children) {
+				child.clone(inst, sh);
+			}
+		}
 
 
-	/**
-		Override to implement your custom prefab data copying.
-		You should copy the field from `p` to `this`, p being an instance of your class
-	**/
-	function copy( p : Prefab ) {
-		copySerializedFields(p);
+		return inst;
 	}
 	}
 
 
-	function copyValue<T>( v : T ) : T {
-		// copy in-depth - might be optimized by macros when called in copy()
-		return haxe.Unserializer.run(haxe.Serializer.run(v));
-	}
+	// Make related functions
 
 
 	/**
 	/**
-		Creates an instance for this prefab only (and not its children).
-		Use make(ctx) to creates the whole instances tree;
+		Create a child from this prefab. Override to filter which child should
+		be created
 	**/
 	**/
-	public function makeInstance( ctx : Context ) : Context {
-		return ctx;
+	function makeChild(c:Prefab) : Void {
+		if (!c.shouldBeInstanciated()) return;
+		if (shared.customMake == null) {
+			c.make(shared);
+		}
+		else {
+			shared.customMake(c);
+		}
 	}
 	}
 
 
 	/**
 	/**
-		Allows to customize how an instance gets updated when a property name changes.
-		You can also call updateInstance(ctx) in order to force whole instance synchronization against current prefab data.
+		Override this function to create runtime objects from this prefab
 	**/
 	**/
-	public function updateInstance( ctx : Context, ?propName : String ) {
+	function makeInstance() : Void {
 	}
 	}
 
 
 	/**
 	/**
-		Removes the created instance for this prefab only (not is children).
-		If false is returned, the instance could not be removed and the whole context scene needs to be rebuilt
+		Called after makeInstance (and by extension postMakeInstance) has been called on all the children
 	**/
 	**/
-	public function removeInstance( ctx : Context ) : Bool {
-		return false;
+	function postMakeInstance() : Void {
 	}
 	}
 
 
 	/**
 	/**
-		Save the whole prefab data and its children.
+		Allows to customize how an instance gets updated when a property name changes.
+		You can also call updateInstance() in order to force whole instance synchronization against current prefab data.
 	**/
 	**/
-	public function saveData() : {} {
-		var obj : Dynamic = save();
-
-		if( children.length > 0 )
-			obj.children = [for( s in children ) s.saveData()];
-		
-		return obj;
+	function updateInstance(?propName : String) {
 	}
 	}
 
 
-	/**
-		Load the whole prefab data and creates its children.
-	**/
-	public function loadData( v : Dynamic ) {
-		load(v);
-		if( children.length > 0 )
-			children = [];
-		var children : Array<Dynamic> = v.children;
-		if( children != null )
-			for( v in children )
-				loadPrefab(v, this);
-	}
+	// End of make related functions
 
 
 	/**
 	/**
 		Updates in-place the whole prefab data and its children.
 		Updates in-place the whole prefab data and its children.
@@ -249,68 +295,63 @@ class Prefab {
 				prev.reload(v);
 				prev.reload(v);
 				newchild.push(prev);
 				newchild.push(prev);
 			} else {
 			} else {
-				newchild.push(loadPrefab(v,this));
+				newchild.push(createFromDynamic(v,this));
 			}
 			}
 		}
 		}
 		children = newchild;
 		children = newchild;
 	}
 	}
 
 
 	/**
 	/**
-		Creates the correct prefab based on v.type and load its data and children.
-		If one the prefab in the tree is not registered, a hxd.prefab.Unkown is created instead.
+		Cleanup prefab specific ressources, and call dispose on it's children.
 	**/
 	**/
-	public static function loadPrefab( v : Dynamic, ?parent : Prefab ) {
-		var pcl = @:privateAccess Library.registeredElements.get(v.type);
-		var pcl = pcl == null ? null : pcl.cl;
-		if( pcl == null ) pcl = Unknown;
-		var p = Type.createInstance(pcl, [parent]);
-		p.loadData(v);
-		return p;
+	public function dispose() {
+		for (child in children) {
+			child.dispose();
+		}
 	}
 	}
 
 
 	/**
 	/**
-		Creates an instance for this prefab and its children.
+		Find the first h2d.Object in this hierarchy, in either this or it's parents
 	**/
 	**/
-	public function make( ctx : Context ) : Context {
-		if( !enabled )
-			return ctx;
-		if( ctx == null ) {
-			ctx = new Context();
-			ctx.init();
-		}
-		var fromRef = #if editor ctx.shared.parent != null #else true #end;
-		if (fromRef && editorOnly #if editor || inGameOnly #end)
-			return ctx;
-		ctx = makeInstance(ctx);
-		for( c in children )
-			makeChild(ctx, c);
-		return ctx;
+	public function findFirstLocal2d() : h2d.Object {
+		var o2d = findParent(Object2D, (p) -> p.local2d != null, true);
+		return o2d != null ? o2d.local2d : shared.root2d;
 	}
 	}
 
 
-	function makeChild( ctx : Context, p : Prefab ) {
-		if( ctx.shared.customMake == null )
-			p.make(ctx);
-		else if( p.enabled )
-			ctx.shared.customMake(ctx, p);
+	/**
+		Find the first h3d.scene.Object in this hierarchy, in either this or it's parents
+	**/
+	public function findFirstLocal3d() : h3d.scene.Object {
+		var o3d = findParent(Object3D, (p) -> p.local3d != null, true);
+		return o3d != null ? o3d.local3d : shared.root3d;
 	}
 	}
 
 
 	/**
 	/**
-	 	If the prefab `props` represent CDB data, returns the sheet name of it, or null.
-	 **/
-	public function getCdbType() : String {
-		if( props == null )
-			return null;
-		return Reflect.field(props, "$cdbtype");
+		Search the prefab tree for the prefab matching the given prefab class (and name, if specified).
+		Throw an exception if not found. Uses getOpt() to return null instead.
+	**/
+	public function get<T:Prefab>( ?cl : Class<T>, ?name : String ) : T {
+		var v = getOpt(cl, name);
+		if( v == null )
+			throw "Missing prefab " + (name == null ? Type.getClassName(cl) : (cl == null ? name : name+"(" + Type.getClassName(cl) + ")"));
+		return v;
 	}
 	}
 
 
 	/**
 	/**
-		Search the prefab tree for the prefab matching the given name, returns null if not found
+		Simlar to get() but returns null if not found.
 	**/
 	**/
-	public function getPrefabByName( name : String ) {
-		if( this.name == name )
-			return this;
+	public function getOpt<T:Prefab>( ?cl : Class<T>, ?name : String, ?followRefs : Bool ) : Null<T> {
+		if( name == null || this.name == name ) {
+			if (cl != null) {
+				var cval = to(cl);
+				if( cval != null ) return cval;
+			}
+			else {
+				return cast this;
+			}
+		}
 		for( c in children ) {
 		for( c in children ) {
-			var p = c.getPrefabByName(name);
+			var p = c.getOpt(cl, name, followRefs);
 			if( p != null )
 			if( p != null )
 				return p;
 				return p;
 		}
 		}
@@ -318,131 +359,116 @@ class Prefab {
 	}
 	}
 
 
 	/**
 	/**
-		Search the prefab tree for the prefabs matching the given path.
-		Can use wildcards, such as `*`/level`*`/collision
+		Returns the root prefab, i.e. the first prefab that doesn't have any parent.
 	**/
 	**/
-	public function getPrefabsByPath( path : String ) {
-		var out = [];
-		if( path == "" )
-			out.push(this);
-		else
-			getPrefabsByPathRec(path.split("."), 0, out);
-		return out;
-	}
+	public function getRoot( followRefs : Bool = false ) : Prefab {
+		var root = this;
 
 
-	function getPrefabsByPathRec( parts : Array<String>, index : Int, out : Array<Prefab> ) {
-		var name = parts[index++];
-		if( name == null ) {
-			out.push(this);
-			return;
-		}
-		var r = name.indexOf('*') < 0 ? null : new EReg("^"+name.split("*").join(".*")+"$","");
-		for( c in children ) {
-			var cname = c.name;
-			if( cname == null ) cname = c.getDefaultName();
-			if( r == null ? c.name == name : r.match(cname) )
-				c.getPrefabsByPathRec(parts, index, out);
+		while( root.parent != null || (followRefs && root.shared.parentPrefab != null) ) {
+			if( root.parent != null )
+				root = root.parent;
+			else if( followRefs )
+				root = root.shared.parentPrefab;
 		}
 		}
+		return root;
 	}
 	}
 
 
 	/**
 	/**
-		Simlar to get() but returns null if not found.
+		Returns all prefabs in the tree matching the specified class.
 	**/
 	**/
-	public function getOpt<T:Prefab>( cl : Class<T>, ?name : String, ?followRefs : Bool ) : T {
-		if( name == null || this.name == name ) {
-			var cval = to(cl);
-			if( cval != null ) return cval;
-		}
-		for( c in children ) {
-			var p = c.getOpt(cl, name, followRefs);
-			if( p != null )
-				return p;
+	public function flatten<T:Prefab>( ?cl : Class<T>, ?arr: Array<T> ) : Array<T> {
+		if(arr == null)
+			arr = [];
+		if( cl == null )
+			arr.push(cast this);
+		else {
+			var i = to(cl);
+			if(i != null)
+				arr.push(i);
 		}
 		}
-		return null;
+		for(c in children)
+			c.flatten(cl, arr);
+		return arr;
 	}
 	}
 
 
 	/**
 	/**
-		Search the prefab tree for the prefab matching the given prefab class (and name, if specified).
-		Throw an exception if not found. Uses getOpt() to return null instead.
+		Returns all the prefab in the tree
 	**/
 	**/
-	public function get<T:Prefab>( cl : Class<T>, ?name : String ) : T {
-		var v = getOpt(cl, name);
-		if( v == null )
-			throw "Missing prefab " + (name == null ? Type.getClassName(cl) : (cl == null ? name : name+"(" + Type.getClassName(cl) + ")"));
-		return v;
+	public function all(?arr: Array<Prefab>) : Array<Prefab> {
+		return flatten(Prefab, arr != null ? arr : []);
 	}
 	}
 
 
 	/**
 	/**
-		Return all prefabs in the tree matching the given prefab class.
+		Converts the prefab to another prefab class.
+		Returns null if not of this type.
 	**/
 	**/
-	public function getAll<T:Prefab>( cl : Class<T>, ?followRefs : Bool, ?arr: Array<T> ) : Array<T> {
-		return findAll(function(p) return p.to(cl), followRefs, arr);
+	public function to<T:Prefab>( c : Class<T> ) : Null<T> {
+		return Std.downcast(this, c);
 	}
 	}
 
 
 	/**
 	/**
-		Find a single prefab in the tree by calling `f` on each and returning the first not-null value returned, or null if not found.
+		Find a the first prefab in the tree with the given class that matches the optionnal `filter`.
+		Returns null if no matching prefab was found
 	**/
 	**/
-	public function find<T>( f : Prefab -> Null<T>, ?followRefs : Bool ) : Null<T> {
-		var v = f(this);
-		if( v != null )
-			return v;
+	public function find<T:Prefab>(?cl: Class<T>, ?filter : T -> Bool, followRefs : Bool = false ) : Null<T> {
+		var asCl = cl != null ? Std.downcast(this, cl) : cast this;
+		if (asCl != null)
+			if (filter == null || filter(asCl))
+				return asCl;
 		for( p in children ) {
 		for( p in children ) {
-			var v = p.find(f, followRefs);
+			var v = p.find(cl, filter, followRefs);
 			if( v != null ) return v;
 			if( v != null ) return v;
 		}
 		}
 		return null;
 		return null;
 	}
 	}
 
 
 	/**
 	/**
-		Find several prefabs in the tree by calling `f` on each and returning all the not-null values returned.
+		Find all the prefabs of the given class `cl` in the tree, that matches `filter` if it is is defined.
+		The result is stored in the given array `arr` if it's defined, otherwise an array is created. The final array
+		is then returned.
 	**/
 	**/
-	public function findAll<T>( f : Prefab -> Null<T>, ?followRefs : Bool, ?arr : Array<T> ) : Array<T> {
+	public function findAll<T:Prefab>(?cl: Class<T>, ?filter : Prefab -> Bool, followRefs : Bool = false, ?arr : Array<T> ) : Array<T> {
 		if( arr == null ) arr = [];
 		if( arr == null ) arr = [];
-		var v = f(this);
-		if( v != null )
-			arr.push(v);
-		for( o in children )
-			o.findAll(f,followRefs,arr);
-		return arr;
-	}
-
-	/**
-		Returns all prefabs in the tree matching the specified class.
-	**/
-	public function flatten<T:Prefab>( ?cl : Class<T>, ?arr: Array<T> ) : Array<T> {
-		if(arr == null)
-			arr = [];
-		if( cl == null )
-			arr.push(cast this);
-		else {
-			var i = to(cl);
-			if(i != null)
-				arr.push(i);
+		var asCl = cl != null ? Std.downcast(this, cl) : cast this;
+		if (asCl != null) {
+			if (filter == null || filter(asCl))
+				arr.push(asCl);
 		}
 		}
-		for(c in children)
-			c.flatten(cl, arr);
+		if (followRefs) {
+			var ref = to(Reference);
+			if (ref != null && ref.refInstance != null) {
+				ref.refInstance.findAll(cl, filter, followRefs, arr);
+			}
+		}
+		for( o in children )
+			o.findAll(cl, filter,followRefs,arr);
 		return arr;
 		return arr;
 	}
 	}
 
 
 	/**
 	/**
-		Returns the first parent in the tree matching the specified class or null if not found.
+		Find the first prefab in this prefab parent chain that matches the given class `cl`, and optionally the given `filter`.
+		If `includeSelf` is true, then this prefab is checked as well.
 	**/
 	**/
-	public function getParent<T:Prefab>( c : Class<T> ) : Null<T> {
-		var p = parent;
-		while(p != null) {
-			var inst = p.to(c);
-			if(inst != null) return inst;
-			p = p.parent;
+	public function findParent<T:Prefab>(?cl:Class<T> ,?filter : (p:T) -> Bool, includeSelf:Bool = false) : Null<T> {
+		var current = includeSelf ? this : this.parent;
+		while(current != null) {
+			var asCl = cl != null ? Std.downcast(current, cl) : cast current;
+			if (asCl != null) {
+				if (filter == null || filter(asCl))
+					return asCl;
+			}
+			current = current.parent;
 		}
 		}
 		return null;
 		return null;
 	}
 	}
 
 
 	/**
 	/**
-		Converts the prefab to another prefab class.
-		Returns null if not of this type.
+		Iterate over this children prefab
 	**/
 	**/
-	public function to<T:Prefab>( c : Class<T> ) : Null<T> {
-		return Std.downcast(this, c);
+	public inline function iterator() : Iterator<Prefab> {
+		if (children != null)
+			return children.iterator();
+		return [].iterator();
 	}
 	}
 
 
 	/**
 	/**
@@ -451,7 +477,7 @@ class Prefab {
 	public function getAbsPath(unique=false) {
 	public function getAbsPath(unique=false) {
 		if(parent == null)
 		if(parent == null)
 			return "";
 			return "";
-		var path = name != null ? name : getDefaultName();
+		var path = name ?? "";
 		if(unique) {
 		if(unique) {
 			var suffix = 0;
 			var suffix = 0;
 			for(i in 0...parent.children.length) {
 			for(i in 0...parent.children.length) {
@@ -459,7 +485,7 @@ class Prefab {
 				if(c == this)
 				if(c == this)
 					break;
 					break;
 				else {
 				else {
-					var cname = c.name != null ? c.name : c.getDefaultName();
+					var cname = c.name ?? "";
 					if(cname == path)
 					if(cname == path)
 						++suffix;
 						++suffix;
 				}
 				}
@@ -473,9 +499,90 @@ class Prefab {
 	}
 	}
 
 
 	/**
 	/**
-		Returns the default name for this prefab
+		If the prefab `props` represent CDB data, returns the sheet name of it, or null.
+	 **/
+	 public function getCdbType() : String {
+		if( props == null )
+			return null;
+		return Reflect.field(props, "$cdbtype");
+	}
+
+	public final function toString() : String{
+		var str = type;
+		if ( name != "" ) str += '($name)';
+		return str;
+	}
+
+	/**
+		Check if `original` prefab class is or inherits for the class `parent`.
+	**/
+	public static function isOfType( original : Class<Prefab>, parent : Class<Prefab> ) {
+		var c : Class<Dynamic> = original;
+		while( c != null ) {
+			if( c == parent ) return true;
+			c = Type.getSuperClass(c);
+		}
+		return false;
+	}
+
+	// Editor API
+
+	#if editor
+	/**
+		Allows to customize how the prefab object is displayed / handled within Hide
+	**/
+	public function getHideProps() : hide.prefab.HideProps {
+		return { icon : "question-circle", name : "Unknown" };
+	}
+
+	/**
+		Create an interactive object to the scene objects of this prefab
+	**/
+	public function makeInteractive() : hxd.SceneEvents.Interactive {
+		return null;
+	}
+
+	/**
+		Allows to customize how the prefab instance changes when selected/unselected within Hide.
+		Selection of descendants is skipped if false is returned.
+	**/
+	public function setSelected(b : Bool ) : Bool {
+		return true;
+	}
+
+	/**
+		Called when the hide editor wants to edit this Prefab.
+		Used to create the various editor interfaces
+	**/
+	public function edit(editContext : hide.prefab.EditContext) {
+	}
+
+	public function setEditor(sceneEditor: hide.comp.SceneEditor) {
+		if (sceneEditor == null)
+			throw "No editor for setEditor";
+
+		shared.editor = sceneEditor;
+
+		setEditorChildren(sceneEditor);
+	}
+
+	function setEditorChildren(sceneEditor: hide.comp.SceneEditor) {
+		for (c in children) {
+			c.setEditorChildren(sceneEditor);
+		}
+	}
+
+	/**
+		Returns a list of all the serializable fieds of the prefab.
+	**/
+	public final function getSerializableProps() : Array<PrefabField> {
+		return getSerializablePropsForClass(Type.getClass(this));
+	}
+
+	/**
+		Returns the default display name for this prefab
 	**/
 	**/
-	public function getDefaultName() : String {
+	public function getDefaultEditorName() : String {
 		if(source != null) {
 		if(source != null) {
 			var f = new haxe.io.Path(source).file;
 			var f = new haxe.io.Path(source).file;
 			f = f.split(" ")[0].split("-")[0];
 			f = f.split(" ")[0].split("-")[0];
@@ -483,26 +590,188 @@ class Prefab {
 		}
 		}
 		return type.split(".").pop();
 		return type.split(".").pop();
 	}
 	}
+	#end
+
+	// Internal
+
+	function setSharedRec(newShared : ContextShared) {
+		this.shared = newShared;
+		for (c in children)
+			c.setSharedRec(newShared);
+	}
+
+	/**
+		Recursively copy this prefab and it's children into a dynamic object, containing
+		all the serializable properties and the type of the object
+	**/
+	function serialize() : Dynamic {
+		var ser = save();
+		ser.type = type;
+
+		if (children.length > 0) {
+			var serChildren = [];
+			for (child in children) {
+				serChildren.push(child.serialize());
+			}
+			ser.children = serChildren;
+		}
+
+		return ser;
+	}
+
+	function locateObject( path : String ) {
+		if( path == null )
+			return null;
+		var parts = path.split(".");
+		var root = shared.root3d;
+		if (root == null)
+			return null;
+		while( parts.length > 0 ) {
+			var v = null;
+			var pname = parts.shift();
+			for( o in root )
+				if( o.name == pname ) {
+					v = o;
+					break;
+				}
+			if( v == null ) {
+				v = root.getObjectByName(pname);
+				//if( v != null && v.parent != root ) v = null; ??
+			}
+			if( v == null ) {
+				var parts2 = path.split(".");
+				for( i in 0...parts.length ) parts2.pop();
+				return null;
+			}
+			root = v;
+		}
+		return root;
+	}
+
+	function shouldBeInstanciated() : Bool {
+		if (!enabled) return false;
+
+		#if editor
+		if (shared.parentPrefab != null && inGameOnly)
+			return false;
+		#else
+		if (editorOnly)
+			return false;
+		#end
+
+		return true;
+	}
+
+	/**
+		Copy all the properties in data to this prefab object. This is not recursive. Done when loading the json data of the prefab.
+	**/
+	function load(data : Dynamic) : Void {
+		this.copyFromDynamic(data);
+	}
+
+	/**
+		Copy all the properties in Prefab to this prefab object. Done when cloning an existing prefab.
+	**/
+	function copy(data: Prefab) : Void {
+		this.copyFromOther(data);
+	}
+
+	/**
+		Save all the properties to the given dynamic object. This is not recursive. Returns the updated dynamic object.
+	**/
+	function save() : Dynamic {
+		return this.copyToDynamic({});
+	}
+
+	/**
+		Create a new prefab from the given `data`.
+	**/
+	static function createFromDynamic(data:Dynamic, parent:Prefab = null, contextShared:ContextShared = null) : Prefab {
+		var type : String = data.type;
+
+		var cl : Class<Prefab> = Unknown;
+
+		if (type != null) {
+			var classEntry = registry.get(type);
+			if (classEntry != null)
+				cl = classEntry.prefabClass;
+		}
+
+		var prefabInstance = Type.createInstance(cl, [parent, contextShared]);
+
+		prefabInstance.load(data);
+
+		var children = Std.downcast(Reflect.field(data, "children"), Array);
+		if (children != null) {
+			for (child in children) {
+				createFromDynamic(child, prefabInstance);
+			}
+		}
+
+		return prefabInstance;
+	}
 
 
 	/**
 	/**
-		Clone this prefab, and all its children if recursive=true.
+		Return the first h3d.scene.Objects found in each of this prefab children.
+		If a children has no h3d.scene.Objects, it then search in it's children and so on.
 	**/
 	**/
-	public final function clone( ?parent : Prefab, recursive = true ) : Prefab {
-		var obj = Type.createInstance(Type.getClass(this),[parent]);
-		obj.copy(this);
-		if( recursive ) {
-			for( c in children )
-				c.clone(obj);
+	static function getChildrenRoots( base : h3d.scene.Object, p : Prefab, out : Array<h3d.scene.Object> ) {
+		for( c in p.children ) {
+			var local3d = Object3D.getLocal3d(c);
+			if( local3d == base )
+				getChildrenRoots(base, c, out);
+			else
+				out.push(local3d);
 		}
 		}
-		return obj;
+		return out;
+	}
+
+	inline static function getSerializablePropsForClass(cl : Class<Prefab>) {
+		return (cl:Dynamic).getSerializablePropsStatic();
+	}
+
+	static function getClassTypeName(cl : Class<Prefab>) : String {
+		return reverseRegistry.get(Type.getClassName(cl));
+	}
+
+	static function getPrefabInfoByName(name:String) : PrefabInfo {
+		return registry[name];
 	}
 	}
 
 
+	static function getPrefabType(path: String) {
+		var extension = path.split(".").pop().toLowerCase();
+		return extensionRegistry.get(extension);
+	}
+
+	static var registry : Map<String, PrefabInfo> = new Map();
+
+	// Map prefab class name to the serialized name of the prefab
+	static var reverseRegistry : Map<String, String> = new Map();
+	static var extensionRegistry : Map<String, String> = new Map();
+
 	/**
 	/**
-		Similar to clone() but uses full data copying to guarantee a whole copy with no data reference (but is slower).
+		Register the given prefab class with the given typeName in the prefab regsitry.
+		This is necessary for the serialisation system.
+		Call it by placing this in you prefab class :
+		```
+		public static var _ = Prefab.register("myPrefabName", myPrefabClassName);
+		```
 	**/
 	**/
-	public final function cloneData( recursive = true ) {
-		var data = recursive ? saveData() : save();
-		data = haxe.Json.parse(haxe.Json.stringify(data));
-		return loadPrefab(data);
+	static function register(typeName : String, prefabClass: Class<hrt.prefab.Prefab>, ?extension: String) {
+		#if editor
+		var info : hide.prefab.HideProps = cast Type.createEmptyInstance(prefabClass).getHideProps();
+		#end
+
+		reverseRegistry.set(Type.getClassName(prefabClass), typeName);
+		registry.set(typeName, {prefabClass: prefabClass #if editor, inf : info #end, extension: extension});
+		if (extension != null) {
+			extensionRegistry.set(extension, typeName);
+		}
+
+		return true;
 	}
 	}
+
+	// Static initialization trick to register this class with the given name
+	// in the prefab registry. Call this in your own classes
+	static var _ = Prefab.register("prefab", Prefab, "prefab");
 }
 }

+ 87 - 118
hrt/prefab/Reference.hx

@@ -1,162 +1,130 @@
 package hrt.prefab;
 package hrt.prefab;
 
 
 class Reference extends Object3D {
 class Reference extends Object3D {
+	@:s public var editMode : Bool = false;
 
 
-	@:s var editMode : Bool = false;
-	public var ref: Prefab = null;
-	#if editor
-	var editor : hide.comp.SceneEditor;
-	#end
+	public var refInstance : Prefab;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "reference";
-	}
-
-	override function load(v:Dynamic) {
-		super.load(v);
-		// backward compatibility
-		var old : String = v.refpath;
-		if( old != null ) {
-			source = old.charCodeAt(0) == "/".code ? old.substr(1) : "/"+old;
+	public static function copy_overrides(from:Dynamic) : haxe.ds.StringMap<Dynamic> {
+		if (Std.isOfType(from, haxe.ds.StringMap)) {
+			return from != null ? cast(from, haxe.ds.StringMap<Dynamic>).copy() : new haxe.ds.StringMap<Dynamic>();
+		}
+		else {
+			var m = new haxe.ds.StringMap<Dynamic>();
+			for (f in Reflect.fields(from)) {
+				m.set(f, Reflect.getProperty(from ,f));
+			}
+			return m;
 		}
 		}
 	}
 	}
 
 
 	override function save() {
 	override function save() {
 		var obj : Dynamic = super.save();
 		var obj : Dynamic = super.save();
 		#if editor
 		#if editor
-		if( editMode && ref != null ) {
-			if( editor != null ) editor.watchIgnoreChanges(source);
+		if( editMode && refInstance != null ) {
+			var sheditor = Std.downcast(shared, hide.prefab.ContextShared);
+			if( sheditor.editor != null ) sheditor.editor.watchIgnoreChanges(source);
 
 
-			hide.Ide.inst.savePrefab(source, ref);
+			var s = refInstance.serialize();
+			sys.io.File.saveContent(hide.Ide.inst.getPath(source), hide.Ide.inst.toJSON(s));
 		}
 		}
 		#end
 		#end
 		return obj;
 		return obj;
 	}
 	}
 
 
-	public function resolveRef(shared : hrt.prefab.ContextShared) {
-		if(ref != null)
-			return ref;
-		if(source == null)
-			return null;
-		if(shared == null) { // Allow resolving ref in Hide prefore makeInstance
-			#if editor
-			ref = hide.Ide.inst.loadPrefab(source, null, true);
-			#else
-			return null;
-			#end
-		}
-		else
-			ref = shared.loadPrefab(source);
-		return ref;
-	}
-
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		var p = resolveRef(ctx.shared);
-		if(p == null)
-			return;
-		var parentCtx = parent == null ? null : ctx.shared.contexts.get(parent);
-		if(parentCtx == null || parentCtx.local3d != ctx.local3d) {
-			// Only apply reference Object3D properties (pos, scale...) to own local3D
-			// Not all refs will create their own scene object
-			super.updateInstance(ctx, propName);
-		}
-	}
+	#if editor
+	override function setEditorChildren(sceneEditor:hide.comp.SceneEditor) {
+		super.setEditorChildren(sceneEditor);
 
 
-	override function find<T>( f : Prefab -> Null<T>, ?followRefs : Bool ) : T {
-		if( followRefs && ref != null ) {
-			var v = ref.find(f, followRefs);
-			if( v != null ) return v;
+		if (refInstance != null) {
+			refInstance.setEditor(sceneEditor);
 		}
 		}
-		return super.find(f, followRefs);
 	}
 	}
+	#end
 
 
-	override function findAll<T>( f : Prefab -> Null<T>, ?followRefs : Bool, ?arr : Array<T> ) : Array<T> {
-		if( followRefs && ref != null )
-			arr = ref.findAll(f, followRefs, arr);
-		return super.findAll(f, followRefs, arr);
+	function resolveRef() : Prefab {
+		if(source == null)
+			return null;
+		if (refInstance != null)
+			return refInstance;
+		return hxd.res.Loader.currentInstance.load(source).to(hrt.prefab.Resource).load();
 	}
 	}
 
 
-	override function getOpt<T:Prefab>( cl : Class<T>, ?name : String, ?followRefs ) : T {
-		if( followRefs && ref != null ) {
-			var v = ref.getOpt(cl, name, true);
-			if( v != null )
-				return v;
+	override function makeInstance() {
+		if( source == null )
+			return;
+		var p = resolveRef();
+		var refLocal3d : h3d.scene.Object = null;
+
+		if (p.to(Object3D) != null) {
+			refLocal3d = shared.current3d;
+		} else {
+			super.makeInstance();
+			refLocal3d = local3d;
 		}
 		}
-		return super.getOpt(cl, name, followRefs);
-	}
-
-	override function makeInstance(ctx: Context) : Context {
-		var p = resolveRef(ctx.shared);
-		if(p == null)
-			return ctx;
-
-		ctx = super.makeInstance(ctx);
-		var objFollow = new h2d.ObjectFollower(ctx.local3d, ctx.local2d);
-		objFollow.followVisibility = true;
-		ctx.local2d = objFollow;
-		var prevShared = ctx.shared;
-		ctx.shared = ctx.shared.cloneRef(this, source);
-		makeChild(ctx, p);
-		ctx.shared = prevShared;
 
 
+		var sh = new ContextShared(source, findFirstLocal2d(), refLocal3d);
 		#if editor
 		#if editor
-
-		if( editMode ) {
-			editor = cast(ctx.shared, hide.prefab.ContextShared).editor;
-			if( editor != null ) editor.watch(source);
+		sh.editor = this.shared.editor;
+		#end
+		sh.parentPrefab = this;
+		sh.customMake = this.shared.customMake;
+		refInstance = p.clone(null, sh);
+
+		if (refInstance.to(Object3D) != null) {
+			var obj3d = refInstance.to(Object3D);
+			obj3d.loadTransform(this); // apply this transform to the reference prefab
+			obj3d.name = name;
+			obj3d.visible = visible;
+			refInstance.make();
+			local3d = Object3D.getLocal3d(refInstance);
 		}
 		}
-
-		if (ctx.local2d == null) {
-			var path = hide.Ide.inst.appPath + "/res/icons/fileRef.png";
-			var data = sys.io.File.getBytes(path);
-			var tile = hxd.res.Any.fromBytes(path, data).toTile().center();
-			var objFollow = new h2d.ObjectFollower(ctx.local3d, ctx.shared.root2d);
-			objFollow.followVisibility = true;
-			var bmp = new h2d.Bitmap(tile, objFollow);
-			ctx.local2d = objFollow;
+		else {
+			refInstance.make();
 		}
 		}
-		#end
-
-		return ctx;
 	}
 	}
 
 
-	override function removeInstance(ctx:Context):Bool {
-		if(!super.removeInstance(ctx))
-			return false;
-		if(ctx.local2d != null)
-			ctx.local2d.remove();
-		return true;
+	override public function find<T:Prefab>(?cl: Class<T>, ?filter : T -> Bool, followRefs : Bool = false ) : Null<T> {
+		var res = super.find(cl, filter, followRefs);
+		if (res == null && followRefs ) {
+			var p = resolveRef();
+			if( p != null )
+				return p.find(cl, filter, followRefs);
+		}
+		return res;
 	}
 	}
 
 
-	override function to<T:Prefab>( c : Class<T> ) : Null<T> {
-		var base = super.to(c);
-		if(base != null)
-			return base;
-		var p = resolveRef(null);
-		if(p == null) return null;
-		return Std.downcast(p, c);
+	override public function getOpt<T:Prefab>( ?cl : Class<T>, ?name : String, ?followRefs : Bool ) : Null<T> {
+		var res = super.getOpt(cl, name, followRefs);
+		if (res == null && followRefs && refInstance != null) {
+			return refInstance.getOpt(cl, name, followRefs);
+		}
+		return res;
 	}
 	}
 
 
-	override function flatten<T:Prefab>(?cl:Class<T>, ?arr:Array<T>):Array<T> {
+	override public function flatten<T:Prefab>( ?cl : Class<T>, ?arr: Array<T> ) : Array<T> {
 		arr = super.flatten(cl, arr);
 		arr = super.flatten(cl, arr);
-		if (editMode && ref != null) {
-			for (c in ref.children) {
-				c.flatten(cl, arr);
-			}
+		if (editMode && refInstance != null) {
+			arr = refInstance.flatten(cl, arr);
 		}
 		}
 		return arr;
 		return arr;
 	}
 	}
 
 
+	override function dispose() {
+		super.dispose();
+		if( refInstance != null )
+			refInstance.dispose();
+	}
+
 	#if editor
 	#if editor
 
 
-	override function makeInteractive(ctx) {
+	override function makeInteractive() {
 		if( editMode )
 		if( editMode )
 			return null;
 			return null;
-		return super.makeInteractive(ctx);
+		return super.makeInteractive();
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var element = new hide.Element('
 		var element = new hide.Element('
 			<div class="group" name="Reference">
 			<div class="group" name="Reference">
 			<dl>
 			<dl>
@@ -167,7 +135,7 @@ class Reference extends Object3D {
 
 
 		function updateProps() {
 		function updateProps() {
 			var input = element.find("input");
 			var input = element.find("input");
-			var found = resolveRef(ctx.rootContext.shared) != null;
+			var found = resolveRef() != null;
 			input.toggleClass("error", !found);
 			input.toggleClass("error", !found);
 		}
 		}
 		updateProps();
 		updateProps();
@@ -175,7 +143,7 @@ class Reference extends Object3D {
 		var props = ctx.properties.add(element, this, function(pname) {
 		var props = ctx.properties.add(element, this, function(pname) {
 			ctx.onChange(this, pname);
 			ctx.onChange(this, pname);
 			if(pname == "source" || pname == "editMode") {
 			if(pname == "source" || pname == "editMode") {
-				ref = null;
+				refInstance = null;
 				updateProps();
 				updateProps();
 				if(!ctx.properties.isTempChange)
 				if(!ctx.properties.isTempChange)
 					ctx.rebuildPrefab(this);
 					ctx.rebuildPrefab(this);
@@ -185,10 +153,11 @@ class Reference extends Object3D {
 		super.edit(ctx);
 		super.edit(ctx);
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "share", name : "Reference" };
 		return { icon : "share", name : "Reference" };
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("reference", Reference);
+
+	public static var _ = hrt.prefab.Prefab.register("reference", Reference);
 }
 }

+ 16 - 19
hrt/prefab/RenderProps.hx

@@ -4,22 +4,18 @@ class RenderPropsObject extends h3d.scene.Object {
 
 
 }
 }
 
 
-class RenderProps extends Prefab {
+class RenderProps extends Object3D {
 
 
 	@:s var isDefault = false;
 	@:s var isDefault = false;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "renderProps";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		props = {};
 		props = {};
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		ctx.local3d = new RenderPropsObject(ctx.local3d);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+		return new RenderPropsObject(parent3d);
+
 	}
 	}
 
 
 	public function getProps(renderer: h3d.scene.Renderer) {
 	public function getProps(renderer: h3d.scene.Renderer) {
@@ -67,7 +63,8 @@ class RenderProps extends Prefab {
 		renderer.props = props;
 		renderer.props = props;
 		for(fx in renderer.effects)
 		for(fx in renderer.effects)
 			fx.dispose();
 			fx.dispose();
-		renderer.effects = [for( v in getAll(hrt.prefab.rfx.RendererFX,true) ) v];
+
+		renderer.effects = [for( v in findAll(hrt.prefab.rfx.RendererFX,true) ) v];
 		var env = getOpt(hrt.prefab.l3d.Environment);
 		var env = getOpt(hrt.prefab.l3d.Environment);
 		if( env != null )
 		if( env != null )
 			env.applyToRenderer(renderer);
 			env.applyToRenderer(renderer);
@@ -77,7 +74,7 @@ class RenderProps extends Prefab {
 
 
 	#if editor
 	#if editor
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit(ctx) {
 		super.edit(ctx);
 		super.edit(ctx);
 		var renderer = ctx.scene.s3d.renderer;
 		var renderer = ctx.scene.s3d.renderer;
 		var props = getProps(renderer);
 		var props = getProps(renderer);
@@ -93,19 +90,19 @@ class RenderProps extends Prefab {
 			}
 			}
 			applyProps(renderer);
 			applyProps(renderer);
 		});
 		});
-		ctx.properties.add(new Element('<dl><dt>Make Default</dt><dd><input type="checkbox" field="isDefault"/></dd></dl>'), this);
+		ctx.properties.add(new hide.Element('<dl><dt>Make Default</dt><dd><input type="checkbox" field="isDefault"/></dd></dl>'), this);
 		applyProps(renderer);
 		applyProps(renderer);
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
-		return { icon : "sun-o", name : "RenderProps", allowChildren : function(t) {
-			return Library.isOfType(t,hrt.prefab.rfx.RendererFX)
-				|| Library.isOfType(t,Light)
-				|| Library.isOfType(t,hrt.prefab.l3d.Environment);
+	override function getHideProps() : hide.prefab.HideProps {
+		return { icon : "sun-o", name : "RenderProps", allowChildren : function(p) {
+			return Prefab.isOfType(p,hrt.prefab.rfx.RendererFX)
+				|| Prefab.isOfType(p,Light)
+				|| Prefab.isOfType(p,hrt.prefab.l3d.Environment);
 		}};
 		}};
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("renderProps", RenderProps);
+	static var _ = Prefab.register("renderProps", RenderProps);
 }
 }

+ 26 - 14
hrt/prefab/Resource.hx

@@ -1,8 +1,9 @@
 package hrt.prefab;
 package hrt.prefab;
 
 
+@:access(hrt.prefab.Prefab)
 class Resource extends hxd.res.Resource {
 class Resource extends hxd.res.Resource {
 
 
-	var lib : Prefab;
+	var prefab : Prefab;
 	var cacheVersion : Int;
 	var cacheVersion : Int;
 	var isWatched : Bool;
 	var isWatched : Bool;
 
 
@@ -16,10 +17,10 @@ class Resource extends hxd.res.Resource {
 		}
 		}
 		isWatched = true;
 		isWatched = true;
 		super.watch(function() {
 		super.watch(function() {
-			if( lib != null ) {
+			if( prefab != null ) {
 				var data = try loadData() catch( e : Dynamic ) return; // parsing error (conflict ?)
 				var data = try loadData() catch( e : Dynamic ) return; // parsing error (conflict ?)
-				lib.reload(data);
-				onPrefabLoaded(lib);
+				prefab.reload(data);
+				onPrefabLoaded(prefab);
 			}
 			}
 			onChanged();
 			onChanged();
 		});
 		});
@@ -31,22 +32,33 @@ class Resource extends hxd.res.Resource {
 	}
 	}
 
 
 	public function load() : Prefab {
 	public function load() : Prefab {
-		if( lib != null && cacheVersion == CACHE_VERSION)
-			return lib;
+		if( prefab != null && cacheVersion == CACHE_VERSION )
+			return prefab;
 		var data = loadData();
 		var data = loadData();
-		lib = Library.create(entry.extension);
-		lib.loadData(data);
+		prefab = Prefab.createFromDynamic(data, new ContextShared(entry.path, false));
 		cacheVersion = CACHE_VERSION;
 		cacheVersion = CACHE_VERSION;
-		onPrefabLoaded(lib);
-		if( !isWatched )
-			watch(function() {}); // auto lib reload
-		return lib;
+		onPrefabLoaded(prefab);
+		watch(function() {}); // auto lib reload
+		return cast prefab;
 	}
 	}
 
 
-	public static function make( p : Prefab ) {
+	public function load2d(?shared: ContextShared) : Object2D {
+		if( Std.downcast(prefab, Object2D) != null && cacheVersion == CACHE_VERSION )
+			return cast prefab;
+		var data = loadData();
+		prefab = Std.downcast(Prefab.createFromDynamic(data), Object2D);
+		prefab.shared.prefabSource = entry.path;
+		prefab.shared.currentPath = entry.path;
+		cacheVersion = CACHE_VERSION;
+		onPrefabLoaded(prefab);
+		watch(function() {}); // auto lib reload
+		return cast prefab;
+	}
+
+	public static function make( p : Object3D ) {
 		if( p == null ) throw "assert";
 		if( p == null ) throw "assert";
 		var r = new Resource(null);
 		var r = new Resource(null);
-		r.lib = p;
+		r.prefab = p;
 		return r;
 		return r;
 	}
 	}
 
 

+ 43 - 44
hrt/prefab/Shader.hx

@@ -2,31 +2,35 @@ package hrt.prefab;
 
 
 import hrt.impl.Gradient;
 import hrt.impl.Gradient;
 import hrt.impl.TextureType;
 import hrt.impl.TextureType;
+import hide.prefab.HideProps;
 
 
 class Shader extends Prefab {
 class Shader extends Prefab {
 
 
 	@:s var targetMaterial : String;
 	@:s var targetMaterial : String;
 	@:s var recursiveApply = true;
 	@:s var recursiveApply = true;
 
 
-	function new(?parent) {
-		super(parent);
+	public var shader : hxsl.Shader;
+
+	function new(parent, sh: ContextShared) {
+		super(parent, sh);
 		props = {};
 		props = {};
 	}
 	}
 
 
-	public function makeShader( ?ctx : hrt.prefab.Context ) : hxsl.Shader {
+	public function makeShader() : hxsl.Shader {
 		return null;
 		return null;
 	}
 	}
 
 
-	public function getShaderDefinition( ctx : hrt.prefab.Context ) : hxsl.SharedShader {
-		var s = makeShader(ctx);
+	public function getShaderDefinition() : hxsl.SharedShader {
+		var s = shader != null ? shader : makeShader();
+		this.shader = s;
 		return s == null ? null : @:privateAccess s.shader;
 		return s == null ? null : @:privateAccess s.shader;
 	}
 	}
 
 
-	override function updateInstance(ctx: Context, ?propName) {
-		var shaderDef = getShaderDefinition(ctx);
-		if( ctx.custom == null || shaderDef == null )
+	override function updateInstance(?propName) {
+		var shaderDef = getShaderDefinition();
+		if( shader == null || shaderDef == null )
 			return;
 			return;
-		syncShaderVars(ctx.custom, shaderDef);
+		syncShaderVars(shader, shaderDef);
 	}
 	}
 
 
 	function syncShaderVars( shader : hxsl.Shader, shaderDef : hxsl.SharedShader ) {
 	function syncShaderVars( shader : hxsl.Shader, shaderDef : hxsl.SharedShader ) {
@@ -80,21 +84,20 @@ class Shader extends Prefab {
 		material.mainPass.addShader(shader);
 		material.mainPass.addShader(shader);
 	}
 	}
 
 
+	function removeShader( obj : h3d.scene.Object, material : h3d.mat.Material, shader : hxsl.Shader ) {
+		material.mainPass.removeShader(shader);
+	}
+
 	function checkMaterial(mat: h3d.mat.Material) {
 	function checkMaterial(mat: h3d.mat.Material) {
 		return targetMaterial == null || targetMaterial == mat.name;
 		return targetMaterial == null || targetMaterial == mat.name;
 	}
 	}
 
 
-	function iterMaterials(ctx:Context, callb) {
+	function iterMaterials(callb) {
 		var parent = parent;
 		var parent = parent;
-		var shared = ctx.shared;
-		while( parent != null && parent.parent == null && shared.parent != null ) {
-			parent = shared.parent.prefab.parent; // reference parent
-			shared = shared.parent.shared;
-		}
+
 		if( Std.isOfType(parent, Material) ) {
 		if( Std.isOfType(parent, Material) ) {
 			var material : Material = cast parent;
 			var material : Material = cast parent;
-			if (ctx.local3d != null) // Fix non made materials in emitters
-				for( m in material.getMaterials(ctx) )
+			for( m in material.getMaterials() )
 					callb(null, m);
 					callb(null, m);
 		} else {
 		} else {
 			var objs = [];
 			var objs = [];
@@ -114,42 +117,39 @@ class Shader extends Prefab {
 					for( o in shared.getObjects(c, h3d.scene.Object) )
 					for( o in shared.getObjects(c, h3d.scene.Object) )
 						pushUnique(o);
 						pushUnique(o);
 			} else
 			} else
-				objs = shared.getObjects(parent, h3d.scene.Object);
+			{
+				var obj3d = Std.downcast(parent,hrt.prefab.Object3D);
+				if (obj3d != null)
+					objs = obj3d.getObjects(h3d.scene.Object);
+			}
 			for( obj in objs )
 			for( obj in objs )
 				for( m in obj.getMaterials(false) )
 				for( m in obj.getMaterials(false) )
 					callb(obj, m);
 					callb(obj, m);
 		}
 		}
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var shader = makeShader(ctx);
+	override function makeInstance() {
+		var shader = makeShader();
 		if( shader == null )
 		if( shader == null )
-			return ctx;
-		if( ctx.local2d != null ) {
-			var drawable = Std.downcast(ctx.local2d, h2d.Drawable);
+			return;
+		if( shared.current2d != null ) {
+			var drawable = Std.downcast(shared.current2d, h2d.Drawable);
 			if (drawable != null) {
 			if (drawable != null) {
 				drawable.addShader(shader);
 				drawable.addShader(shader);
-				ctx.cleanup = function() {
-					drawable.removeShader(shader);
-				}
 			} else {
 			} else {
-				var flow = Std.downcast(ctx.local2d, h2d.Flow);
+				var flow = Std.downcast(shared.current2d, h2d.Flow);
 				if (flow != null) {
 				if (flow != null) {
 					@:privateAccess if (flow.background != null) {
 					@:privateAccess if (flow.background != null) {
 						flow.background.addShader(shader);
 						flow.background.addShader(shader);
-						ctx.cleanup = function() {
-							flow.background.removeShader(shader);
-						}
 					}
 					}
 				}
 				}
 			}
 			}
 		}
 		}
-		if( ctx.local3d != null )
-			iterMaterials(ctx, function(obj,mat) if(checkMaterial(mat)) applyShader(obj, mat, shader));
-		ctx.custom = shader;
-		updateInstance(ctx);
-		return ctx;
+
+		if( shared.current3d != null )
+			iterMaterials(function(obj,mat) if(checkMaterial(mat)) applyShader(obj, mat, shader));
+		this.shader = shader;
+		updateInstance();
 	}
 	}
 
 
 	#if editor
 	#if editor
@@ -168,13 +168,12 @@ class Shader extends Prefab {
 		return props;
 		return props;
 	}
 	}
 
 
-	override function edit( ectx : EditContext ) {
+	override function edit( ectx : hide.prefab.EditContext ) {
 		super.edit(ectx);
 		super.edit(ectx);
 
 
-		var ctx = ectx.getContext(this);
-		var shaderDef = getShaderDefinition(ctx);
-		if( shaderDef == null || ctx == null ) {
-			var el = new Element("<p>Shader definition is missing</p>");
+		var shaderDef = getShaderDefinition();
+		if( shaderDef == null) {
+			var el = new hide.Element("<p>Shader definition is missing</p>");
 			el.css("color", "#ff5555");
 			el.css("color", "#ff5555");
 			ectx.properties.add(el);
 			ectx.properties.add(el);
 			return;
 			return;
@@ -186,7 +185,7 @@ class Shader extends Prefab {
 			</dl>
 			</dl>
 		</div>');
 		</div>');
 		var materials = [];
 		var materials = [];
-		iterMaterials(ctx, function(_,m) if( m.name != null && materials.indexOf(m.name) < 0 ) materials.push(m.name));
+		iterMaterials(function(_,m) if( m.name != null && materials.indexOf(m.name) < 0 ) materials.push(m.name));
 		if( targetMaterial != null && materials.indexOf(targetMaterial) < 0 )
 		if( targetMaterial != null && materials.indexOf(targetMaterial) < 0 )
 			materials.push(targetMaterial);
 			materials.push(targetMaterial);
 		if( materials.length >= 2 || targetMaterial != null ) {
 		if( materials.length >= 2 || targetMaterial != null ) {
@@ -213,7 +212,7 @@ class Shader extends Prefab {
 			ectx.onChange(this, pname);
 			ectx.onChange(this, pname);
 
 
 			// Notify change to FX in case param is used by curves
 			// Notify change to FX in case param is used by curves
-			var fx = getParent(hrt.prefab.fx.FX);
+			var fx = findParent(hrt.prefab.fx.FX);
 			if(fx != null)
 			if(fx != null)
 				ectx.rebuildPrefab(fx, true);
 				ectx.rebuildPrefab(fx, true);
 		});
 		});
@@ -252,7 +251,7 @@ class Shader extends Prefab {
 		return {
 		return {
 			icon : "cog",
 			icon : "cog",
 			name : name,
 			name : name,
-			fileSource : cl == DynamicShader ? ["hx"] : null,
+			fileSource : cl == hrt.prefab.DynamicShader ? ["hx"] : null,
 			allowParent : function(p) return p.to(Object2D) != null || p.to(Object3D) != null || p.to(Material) != null
 			allowParent : function(p) return p.to(Object2D) != null || p.to(Object3D) != null || p.to(Material) != null
 		};
 		};
 	}
 	}

+ 54 - 21
hrt/prefab/Unknown.hx

@@ -1,36 +1,69 @@
 package hrt.prefab;
 package hrt.prefab;
 
 
+/**
+	Allow openning prefabs with a type not found in the project, keeping the data unchanged.
+**/
 class Unknown extends Prefab {
 class Unknown extends Prefab {
+	public var data : Dynamic = null;
 
 
-	@:c var data : Dynamic;
+	override function load(newData: Dynamic) : Void {
+		data = {};
 
 
-	public function getPrefabType() {
-		return data.type;
-	}
-
-	override function load(v:Dynamic) {
-		this.type = v.type;
-		this.data = Reflect.copy(v);
-		this.props = v.props;
-		Reflect.deleteField(this.data, "children");
-		Reflect.deleteField(this.data, "props");
+		for (f in Reflect.fields(newData)) {
+			if (f == "name") {
+				name = newData.name;
+			}
+			else if (f != "children") {
+				Reflect.setField(data, f, copyValue(Reflect.getProperty(newData, f)));
+			}
+		}
 	}
 	}
 
 
 	override function save() {
 	override function save() {
-		var data : Dynamic = Reflect.copy(data);
-		if( this.props != null ) data.props = props;
-		return data;
+		var to : Dynamic = {};
+		to.name = name;
+		for (f in Reflect.fields(data)) {
+			Reflect.setField(to, f, copyValue(Reflect.getProperty(data, f)));
+		}
+		return to;
 	}
 	}
 
 
-	override function getDefaultName():String {
-		return "unknown";
+	static function copyValue(v:Dynamic) : Dynamic {
+		switch (Type.typeof(v)) {
+			case TClass(c):
+				switch(c) {
+					case cast Array:
+						var v:Array<Dynamic> = v;
+						return v.copy();
+					case cast String:
+						var v:String = v;
+						return v;
+					default:
+						// Fallback hard data copy
+						return haxe.Json.parse(haxe.Json.stringify(v));
+				}
+			default:
+				return v;
+		}
 	}
 	}
 
 
-	#if editor
-	override function edit(ctx:hide.prefab.EditContext) {
-		ctx.properties.add(new hide.Element('<font color="red">Unknown prefab $type</font>'));
+#if editor
+	override function getHideProps() : hide.prefab.HideProps {
+		return {
+			icon : "question-circle-o",
+			name : "Unknown",
+		};
 	}
 	}
-	#end
-
 
 
+	override function edit( ctx : hide.prefab.EditContext ) {
+		var props = new hide.Element('
+			<p>Unknown prefab type : <code>${data.type}</code></p>
+			<p>This prefab might has been saved in a more recent version of hide (in that case try to update), or this type no longer exists.</p>
+			<p>No data will be lost if this prefab is saved, but rendering glitches or strange offsets can occur.</p>
+		');
+		ctx.properties.add(props, this, function(pname) {
+			ctx.onChange(this, pname);
+		});
+	}
+#end
 }
 }

+ 31 - 39
hrt/prefab/World.hx

@@ -1,5 +1,6 @@
 package hrt.prefab;
 package hrt.prefab;
 
 
+using hrt.prefab.Object3D;
 typedef ChunkData = {
 typedef ChunkData = {
 	var id : String;
 	var id : String;
 	var level : Int;
 	var level : Int;
@@ -33,9 +34,8 @@ class World extends Object3D {
 	}
 	}
 	var datDir : String;
 	var datDir : String;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "world";
+	public function new(parent, shared) {
+		super(parent, shared);
 		chunkPrefabs = [];
 		chunkPrefabs = [];
 	}
 	}
 
 
@@ -46,9 +46,7 @@ class World extends Object3D {
 		var content = chunkPrefabs.get(data.id);
 		var content = chunkPrefabs.get(data.id);
 		if ( content == null )
 		if ( content == null )
 			return;
 			return;
-		var ctx = new hrt.prefab.Context();
-		ctx.init();
-		ctx.local2d = null;
+
 		var tmp = new h3d.scene.Object();
 		var tmp = new h3d.scene.Object();
 		tmp.name = "chunk_inverse_transform";
 		tmp.name = "chunk_inverse_transform";
 		chunk.addChild(tmp);
 		chunk.addChild(tmp);
@@ -56,26 +54,26 @@ class World extends Object3D {
 		// create a tmp object to hold chunk inverse transform as prefab positions are stored relative to chunk position.
 		// create a tmp object to hold chunk inverse transform as prefab positions are stored relative to chunk position.
 		tmp.x = -chunkPos.x;
 		tmp.x = -chunkPos.x;
 		tmp.y = -chunkPos.y;
 		tmp.y = -chunkPos.y;
-		ctx.local3d = tmp;
 		for ( p in content.children ) {
 		for ( p in content.children ) {
-			var context = p.make(ctx);
-			if ( context.local3d == tmp )
+			shared.current3d = tmp;
+			var context = p.make(shared);
+			if ( context.getLocal3d() == tmp )
 				continue;
 				continue;
 			#if editor
 			#if editor
 			for ( elt in p.flatten() )
 			for ( elt in p.flatten() )
-				@:privateAccess editor.makeInteractive(elt, ctx.shared);
+				@:privateAccess editor.makeInteractive(elt);
 			if ( editor != null ) {
 			if ( editor != null ) {
 				var curEdit = editor.curEdit;
 				var curEdit = editor.curEdit;
-				var contexts = curEdit.rootContext.shared.contexts;
-				contexts.set(p, context);
-				if ( context != null ) {
+				//var contexts = curEdit.rootContext.shared.contexts;
+				//contexts.set(p, context);
+				/*if ( context != null ) {
 					var pobj = context.shared.root3d;
 					var pobj = context.shared.root3d;
 					var pobj2d = context.shared.root2d;
 					var pobj2d = context.shared.root2d;
 					if ( context.local3d != pobj && context.local3d != null )
 					if ( context.local3d != pobj && context.local3d != null )
 						editor.curEdit.rootObjects.push(context.local3d);
 						editor.curEdit.rootObjects.push(context.local3d);
 					if ( context.local2d != pobj2d && context.local2d != null )
 					if ( context.local2d != pobj2d && context.local2d != null )
 						editor.curEdit.rootObjects2D.push(context.local2d);
 						editor.curEdit.rootObjects2D.push(context.local2d);
-				}
+				}*/
 			}
 			}
 			#end
 			#end
 		}
 		}
@@ -86,7 +84,7 @@ class World extends Object3D {
 			var id = data.id;
 			var id = data.id;
 			var path = datDir + id + "/content.prefab";
 			var path = datDir + id + "/content.prefab";
 			var p = hxd.res.Loader.currentInstance.load(path).toPrefab().load();
 			var p = hxd.res.Loader.currentInstance.load(path).toPrefab().load();
-			var content = new hrt.prefab.Object3D();
+			var content = new hrt.prefab.Object3D(this, shared);
 			chunkPrefabs.set(id, content);
 			chunkPrefabs.set(id, content);
 			var i = p.children.length;
 			var i = p.children.length;
 			while ( i-- > 0 ) {
 			while ( i-- > 0 ) {
@@ -167,19 +165,19 @@ class World extends Object3D {
 		return 0;
 		return 0;
 	}
 	}
 
 
-	override function saveData() : {} {
+	override function serialize() : Dynamic {
 		var tmpChildren = [];
 		var tmpChildren = [];
 
 
 		var chunks = new Map();
 		var chunks = new Map();
 		if ( children.length > 0 ) {
 		if ( children.length > 0 ) {
 			for ( c in children ) {
 			for ( c in children ) {
 				if ( !isStreamable(c) )
 				if ( !isStreamable(c) )
-					tmpChildren.push(c.saveData());
+					tmpChildren.push(c.serialize());
 				else {
 				else {
 					var object3D = Std.downcast(c, hrt.prefab.Object3D);
 					var object3D = Std.downcast(c, hrt.prefab.Object3D);
 					if ( object3D == null )
 					if ( object3D == null )
 						throw "TODO : stream prefab that are not 3D objects";
 						throw "TODO : stream prefab that are not 3D objects";
-					object3D = cast(object3D.clone(), hrt.prefab.Object3D);
+					object3D = cast(object3D.clone(null, null), hrt.prefab.Object3D);
 					var data = getChunkData(getObjectLevel(object3D), object3D.x, object3D.y);
 					var data = getChunkData(getObjectLevel(object3D), object3D.x, object3D.y);
 					// prefab positions are stored relative to the chunk parent.
 					// prefab positions are stored relative to the chunk parent.
 					// it's arbitrary but some work has to be done as the make occurs with the chunk as parent.
 					// it's arbitrary but some work has to be done as the make occurs with the chunk as parent.
@@ -193,7 +191,7 @@ class World extends Object3D {
 						chunk.children = [];
 						chunk.children = [];
 						chunks.set(data.id, chunk);
 						chunks.set(data.id, chunk);
 					}
 					}
-					chunk.children.push(object3D.saveData());
+					chunk.children.push(object3D.serialize());
 					if ( findChunk(data.id) == null ) {
 					if ( findChunk(data.id) == null ) {
 						chunkData.push(data);
 						chunkData.push(data);
 					}
 					}
@@ -240,8 +238,8 @@ class World extends Object3D {
 		return obj;
 		return obj;
 	}
 	}
 
 
-	function initPath(ctx : hrt.prefab.Context) {
-		var path = new haxe.io.Path(ctx.shared.currentPath);
+	function initPath() {
+		var path = new haxe.io.Path(shared.currentPath);
 		datDir = if ( path.dir == null )
 		datDir = if ( path.dir == null )
 			'${path.file}.dat/';
 			'${path.file}.dat/';
 		else
 		else
@@ -252,18 +250,12 @@ class World extends Object3D {
 		return Std.isOfType(p, hrt.prefab.Object3D);
 		return Std.isOfType(p, hrt.prefab.Object3D);
 	}
 	}
 
 
-	function createObjectFromData(ctx : hrt.prefab.Context, data : h3d.scene.HierarchicalWorld.WorldData) : h3d.scene.HierarchicalWorld {
-		return new h3d.scene.HierarchicalWorld(ctx.local3d, data);
+	function createObjectFromData(data : h3d.scene.HierarchicalWorld.WorldData) : h3d.scene.HierarchicalWorld {
+		return new h3d.scene.HierarchicalWorld(local3d, data);
 	}
 	}
 
 
-	override function make(ctx : hrt.prefab.Context) {
-		if( !enabled )
-			return ctx;
-		var fromRef = #if editor ctx.shared.parent != null #else true #end;
-		if (fromRef && editorOnly #if editor || inGameOnly #end)
-			return ctx;
-		ctx = ctx.clone(this);
-		initPath(ctx);
+	override function makeObject(parent3d: h3d.scene.Object) {
+		initPath();
 		loadDataFromFiles();
 		loadDataFromFiles();
 		initBounds();
 		initBounds();
 		var d = { size : size,
 		var d = { size : size,
@@ -274,21 +266,21 @@ class World extends Object3D {
 			maxDepth : depth,
 			maxDepth : depth,
 			onCreate : onCreateChunk,
 			onCreate : onCreateChunk,
 		};
 		};
-		var worldObj = createObjectFromData(ctx, d);
-		ctx.local3d = worldObj;
+		var worldObj = createObjectFromData(d);
+
 		for( c in children ) {
 		for( c in children ) {
 			if ( !isStreamable(c) )
 			if ( !isStreamable(c) )
-				makeChild(ctx, c);
+				makeChild(c);
 		}
 		}
 		// Calling init on root after non streamable objects are made.
 		// Calling init on root after non streamable objects are made.
 		// This way objects such as terrain can be created in custom onCreateChunk.
 		// This way objects such as terrain can be created in custom onCreateChunk.
 		worldObj.init();
 		worldObj.init();
-		updateInstance(ctx);
-		return ctx;
+		updateInstance();
+		return worldObj;
 	}
 	}
 
 
-	override function updateInstance(ctx : hrt.prefab.Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String) {
+		super.updateInstance(propName);
 		h3d.scene.HierarchicalWorld.DEBUG = debug;
 		h3d.scene.HierarchicalWorld.DEBUG = debug;
 	}
 	}
 
 
@@ -324,5 +316,5 @@ class World extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("world", World);
+	static var _ = Prefab.register("world", World);
 }
 }

+ 10 - 15
hrt/prefab/fx/AnimEvent.hx

@@ -8,14 +8,9 @@ class AnimEvent extends hrt.prefab.fx.Event {
 	@:s public var duration : Float = 0.0;
 	@:s public var duration : Float = 0.0;
 	@:s public var offset : 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;
+	override function prepare() : Event.EventInstance {
+		var obj = findFirstLocal3d();
+		var anim = animation != null ? shared.loadAnimation(animation) : null;
 		var lastTime = -1.0;
 		var lastTime = -1.0;
 		var inst = null;
 		var inst = null;
 		if(anim == null) { return null; }
 		if(anim == null) { return null; }
@@ -45,14 +40,14 @@ class AnimEvent extends hrt.prefab.fx.Event {
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 		var props = ctx.properties.add(new hide.Element('
 		var props = ctx.properties.add(new hide.Element('
 			<div class="group" name="Event">
 			<div class="group" name="Event">
 				<dl>
 				<dl>
 					<dt>Time</dt><dd><input type="number" value="0" field="time"/></dd>
 					<dt>Time</dt><dd><input type="number" value="0" field="time"/></dd>
 					<dt>Loop</dt><dd><input type="checkbox" field="loop"/></dd>
 					<dt>Loop</dt><dd><input type="checkbox" field="loop"/></dd>
-					<dt>Animation</dt><dd><input id="anim" value="--- Choose ---"></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>Speed</dt><dd><input type="number" value="0" field="speed"/></dd>
 					<dt>Duration</dt><dd><input type="number" value="0" field="duration"/></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>
 					<dt>Offset</dt><dd><input type="number" value="0" field="offset"/></dd>
@@ -84,19 +79,19 @@ class AnimEvent extends hrt.prefab.fx.Event {
 		}
 		}
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return {
 		return {
 			icon : "play-circle", name : "AnimEvent",
 			icon : "play-circle", name : "AnimEvent",
-			allowParent : (p) -> p.to(Model) != null,
+			allowParent : (p) -> Std.downcast(p,hrt.prefab.Model) != null,
 			allowChildren: function(s) return false
 			allowChildren: function(s) return false
 		};
 		};
 	}
 	}
 
 
-	override function getDisplayInfo(ctx: EditContext) {
+	override function getDisplayInfo(ctx: hide.prefab.EditContext) {
 		var anim = null;
 		var anim = null;
 		if(animation != null) {
 		if(animation != null) {
 			try {
 			try {
-				anim = ctx.rootContext.loadAnimation(animation);
+				anim = shared.loadAnimation(animation);
 			} catch(e : hxd.res.NotFound) { }
 			} catch(e : hxd.res.NotFound) { }
 		}
 		}
 		return {
 		return {
@@ -107,6 +102,6 @@ class AnimEvent extends hrt.prefab.fx.Event {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("animEvent", AnimEvent);
+	static var _ = Prefab.register("animEvent", AnimEvent);
 
 
 }
 }

+ 32 - 45
hrt/prefab/fx/BaseFX.hx

@@ -1,6 +1,9 @@
 package hrt.prefab.fx;
 package hrt.prefab.fx;
 import hrt.prefab.Curve;
 import hrt.prefab.Curve;
 import hrt.prefab.Prefab as PrefabElement;
 import hrt.prefab.Prefab as PrefabElement;
+import hrt.prefab.fx.Value as Value;
+
+import hrt.prefab.fx.Evaluator;
 
 
 typedef ShaderParam = {
 typedef ShaderParam = {
 	idx: Int,
 	idx: Int,
@@ -102,38 +105,25 @@ typedef ObjectAnimation = {
 	?additionalProperies : AdditionalProperies
 	?additionalProperies : AdditionalProperies
 };
 };
 
 
-class BaseFX extends hrt.prefab.Library {
-	public static var useAutoPerInstance = true;
+interface BaseFX {
 
 
 	@:s public var duration : Float;
 	@:s public var duration : Float;
 	@:s public var startDelay : Float;
 	@:s public var startDelay : Float;
 	@:c public var scriptCode : String;
 	@:c public var scriptCode : String;
 	@:c public var cullingRadius : Float;
 	@:c public var cullingRadius : Float;
 	@:c public var blendFactor : Float;
 	@:c public var blendFactor : Float;
-	@:c public var markers : Array<{t: Float}> = [];
-
-	public function new() {
-		super();
-		duration = 5.0;
-		scriptCode = null;
-		cullingRadius = 1000;
-		blendFactor = 1.0;
-	}
+	@:s public var markers : Array<{t: Float}>;
 
 
-	override function save() {
-		var obj : Dynamic = super.save();
-		if( markers != null && markers.length > 0 )
-			obj.markers = markers;
-		return obj;
-	}
+	#if editor
+	public function refreshObjectAnims() : Void;
+	#end
+}
 
 
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		markers = obj.markers == null ? [] : obj.markers;
-	}
+class BaseFXTools {
+	public static var useAutoPerInstance = true;
 
 
-	public static function makeShaderParams(ctx: Context, shaderElt: hrt.prefab.Shader) {
-		var shaderDef = shaderElt.getShaderDefinition(ctx);
+	public static function makeShaderParams(shaderElt: hrt.prefab.Shader) {
+		var shaderDef = shaderElt.getShaderDefinition();
 		if(shaderDef == null)
 		if(shaderDef == null)
 			return null;
 			return null;
 
 
@@ -186,37 +176,35 @@ class BaseFX extends hrt.prefab.Library {
 	}
 	}
 
 
 	static var emptyParams : Array<String> = [];
 	static var emptyParams : Array<String> = [];
-	public static function getShaderAnims(ctx: Context, elt: PrefabElement, anims: Array<ShaderAnimation>, ?batch: h3d.scene.MeshBatch) {
+	public static function getShaderAnims(elt: PrefabElement, anims: Array<ShaderAnimation>, ?batch: h3d.scene.MeshBatch) {
 		// Init all animations recursively except Emitter ones (called in Emitter)
 		// Init all animations recursively except Emitter ones (called in Emitter)
 		if(Std.downcast(elt, hrt.prefab.fx.Emitter) == null) {
 		if(Std.downcast(elt, hrt.prefab.fx.Emitter) == null) {
 			for(c in elt.children) {
 			for(c in elt.children) {
-				getShaderAnims(ctx, c, anims, batch);
+				getShaderAnims(c, anims, batch);
 			}
 			}
 		}
 		}
 
 
 		var shader = elt.to(hrt.prefab.Shader);
 		var shader = elt.to(hrt.prefab.Shader);
-		if(shader == null)
+		if(shader == null || shader.shader == null)
 			return;
 			return;
 
 
-		for(shCtx in ctx.shared.getContexts(elt)) {
-			if(shCtx.custom == null) continue;
-			var params = makeShaderParams(ctx, shader);
-			var shader : hxsl.Shader = shCtx.custom;
+		var params = makeShaderParams(shader);
 
 
-			if(useAutoPerInstance && batch != null)  @:privateAccess {
-				var perInstance = batch.instancedParams;
-				if ( perInstance == null ) {
-					perInstance = new hxsl.Cache.BatchInstanceParams([]);
+		var shader = shader.shader;
+
+		if(useAutoPerInstance && batch != null) @:privateAccess {
+			var perInstance = batch.instancedParams;
+			if ( perInstance == null ) {
+				perInstance = new hxsl.Cache.BatchInstanceParams([]);
 					batch.instancedParams = perInstance;
 					batch.instancedParams = perInstance;
-				}
-				perInstance.forcedPerInstance.push({
-					shader: shader.shader.data.name,
-					params: params == null ? emptyParams : params.map(p -> p.def.name)
-				});
 			}
 			}
+			perInstance.forcedPerInstance.push({
+				shader: shader.shader.data.name,
+				params: params == null ? emptyParams : params.map(p -> p.def.name)
+			});
+		}
 
 
-			if(params == null) continue;
-
+		if(params != null) {
 			var anim = Std.isOfType(shader,hxsl.DynamicShader) ? new ShaderDynAnimation() : new ShaderAnimation();
 			var anim = Std.isOfType(shader,hxsl.DynamicShader) ? new ShaderDynAnimation() : new ShaderAnimation();
 			anim.shader = shader;
 			anim.shader = shader;
 			anim.params = params;
 			anim.params = params;
@@ -224,17 +212,16 @@ class BaseFX extends hrt.prefab.Library {
 		}
 		}
 
 
 		if(batch != null) {
 		if(batch != null) {
-			var shader = Std.downcast(ctx.custom, hxsl.Shader);
 			batch.material.mainPass.addShader(shader);
 			batch.material.mainPass.addShader(shader);
 		}
 		}
 	}
 	}
 
 
-	public function getFXRoot( ctx : Context, elt : PrefabElement ) : PrefabElement {
+	public static function getFXRoot(elt : PrefabElement ) : PrefabElement {
 		if( elt.name == "FXRoot" )
 		if( elt.name == "FXRoot" )
 			return elt;
 			return elt;
 		else {
 		else {
 			for(c in elt.children) {
 			for(c in elt.children) {
-				var elt = getFXRoot(ctx, c);
+				var elt = getFXRoot(c);
 				if(elt != null) return elt;
 				if(elt != null) return elt;
 			}
 			}
 		}
 		}
@@ -242,6 +229,6 @@ class BaseFX extends hrt.prefab.Library {
 	}
 	}
 
 
 	#if editor
 	#if editor
-	public function refreshObjectAnims(ctx: Context) { }
+	public function refreshObjectAnims() { }
 	#end
 	#end
 }
 }

+ 4 - 16
hrt/prefab/fx/Billboard.hx

@@ -34,25 +34,13 @@ class BillboardObject extends h3d.scene.Object {
 
 
 @:allow(hrt.prefab.fx.Billboard.BillboardInstance)
 @:allow(hrt.prefab.fx.Billboard.BillboardInstance)
 class Billboard extends Object3D {
 class Billboard extends Object3D {
-	public function new(?parent) {
-		super(parent);
-		type = "billboard";
-	}
-
-	override function updateInstance(ctx:hrt.prefab.Context, ?propName:String) {
-		super.updateInstance(ctx, propName);
-	}
 
 
-	override function makeInstance(ctx:Context) {
-		ctx = ctx.clone(this);
-		ctx.local3d = new BillboardObject(ctx.local3d);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+	override function makeObject(parent3d: h3d.scene.Object) {
+		return new BillboardObject(parent3d);
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps():HideProps {
+	override function getHideProps():hide.prefab.HideProps {
 		return {
 		return {
 			icon: "cog",
 			icon: "cog",
 			name: "Billboard"
 			name: "Billboard"
@@ -60,5 +48,5 @@ class Billboard extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("billboard", Billboard);
+	static var _ = Prefab.register("billboard", Billboard);
 }
 }

+ 83 - 91
hrt/prefab/fx/Emitter.hx

@@ -4,6 +4,11 @@ import hrt.impl.Gradient;
 import hrt.prefab.l3d.Polygon;
 import hrt.prefab.l3d.Polygon;
 import hrt.prefab.Curve;
 import hrt.prefab.Curve;
 import hrt.prefab.fx.BaseFX.ShaderAnimation;
 import hrt.prefab.fx.BaseFX.ShaderAnimation;
+import hrt.prefab.fx.Value;
+import hrt.prefab.fx.Evaluator;
+
+import hide.prefab.HideProps;
+
 using Lambda;
 using Lambda;
 
 
 enum SimulationSpace {
 enum SimulationSpace {
@@ -412,6 +417,7 @@ class ParticleInstance {
 	}
 	}
 }
 }
 
 
+@:access(hrt.prefab.Prefab)
 @:allow(hrt.prefab.fx.ParticleInstance)
 @:allow(hrt.prefab.fx.ParticleInstance)
 @:allow(hrt.prefab.fx.Emitter)
 @:allow(hrt.prefab.fx.Emitter)
 class EmitterObject extends h3d.scene.Object {
 class EmitterObject extends h3d.scene.Object {
@@ -509,7 +515,6 @@ class EmitterObject extends h3d.scene.Object {
 
 
 	var random: hxd.Rand;
 	var random: hxd.Rand;
 	var randomSeed = 0;
 	var randomSeed = 0;
-	var context : hrt.prefab.Context;
 	var emitCount = 0;
 	var emitCount = 0;
 	var emitTarget = 0.0;
 	var emitTarget = 0.0;
 	var curTime = 0.0;
 	var curTime = 0.0;
@@ -531,15 +536,11 @@ class EmitterObject extends h3d.scene.Object {
 		random = new hxd.Rand(randomSeed);
 		random = new hxd.Rand(randomSeed);
 	}
 	}
 
 
-	function makeShaderInstance(prefab: hrt.prefab.Shader, ctx:Context):Context {
-		ctx = ctx.clone(prefab);
-		var shader = prefab.makeShader(ctx);
+	function makeShaderInstance(prefab: hrt.prefab.Shader) {
+		var shader = prefab.makeShader();
 		if( shader == null )
 		if( shader == null )
-			return ctx;
-		ctx.custom = shader;
-		prefab.updateInstance(ctx);
-		ctx.local3d = null;  // prevent ContextShared.getSelfObject from incorrectly reporting object
-		return ctx;
+			return;
+		prefab.updateInstance();
 	}
 	}
 
 
 	function init(randSlots: Int, prefab: Emitter) {
 	function init(randSlots: Int, prefab: Emitter) {
@@ -557,11 +558,15 @@ class EmitterObject extends h3d.scene.Object {
 			if(baseEmitMat.isIdentityEpsilon(0.01))
 			if(baseEmitMat.isIdentityEpsilon(0.01))
 				baseEmitMat = null;
 				baseEmitMat = null;
 
 
-			var template = particleTemplate.makeInstance(context);
-			var mesh = Std.downcast(template.local3d, h3d.scene.Mesh);
+			var empty3d = new h3d.scene.Object();
+			var clone = particleTemplate.clone(new hrt.prefab.ContextShared(empty3d),false);
+			clone.make();
+			var loc3d = Object3D.getLocal3d(clone);
+
+			var mesh = Std.downcast(loc3d, h3d.scene.Mesh);
 			if( mesh == null ) {
 			if( mesh == null ) {
-				for( i in 0...template.local3d.numChildren ) {
-					mesh = Std.downcast(template.local3d.getChildAt(i), h3d.scene.Mesh);
+				for( i in 0...loc3d.numChildren ) {
+					mesh = Std.downcast(loc3d.getChildAt(i), h3d.scene.Mesh);
 					if( mesh != null ) {
 					if( mesh != null ) {
 						break;
 						break;
 					}
 					}
@@ -571,12 +576,9 @@ class EmitterObject extends h3d.scene.Object {
 			if (mesh != null) {
 			if (mesh != null) {
 				meshPrimitive = Std.downcast(mesh.primitive, h3d.prim.MeshPrimitive);
 				meshPrimitive = Std.downcast(mesh.primitive, h3d.prim.MeshPrimitive);
 				meshMaterial = mesh.material;
 				meshMaterial = mesh.material;
-				mesh.remove();
 			}
 			}
 
 
-			template.shared.contexts.remove(particleTemplate);
-			template.local3d.remove();
-			template.local3d = null;
+			empty3d.remove();
 		}
 		}
 
 
 		if (meshPrimitive == null ) {
 		if (meshPrimitive == null ) {
@@ -594,30 +596,27 @@ class EmitterObject extends h3d.scene.Object {
 			batch.name = "emitter";
 			batch.name = "emitter";
 			batch.calcBounds = false;
 			batch.calcBounds = false;
 
 
-			var batchContext = context.clone(null);
-			batchContext.local3d = batch;
 			// Setup mats.
 			// Setup mats.
 			// Should we do this manually here or make a recursive makeInstance on the template?
 			// Should we do this manually here or make a recursive makeInstance on the template?
-			var materials = emitterPrefab.getAll(hrt.prefab.Material);
+			var materials = emitterPrefab.findAll(hrt.prefab.Material);
 			for(mat in materials) {
 			for(mat in materials) {
 
 
 				// Remove materials that are not directly parented to this emitter
 				// Remove materials that are not directly parented to this emitter
 				var p = mat.parent;
 				var p = mat.parent;
-				while (p != null && Std.downcast(p, Emitter) == null) {
+				while (p != null && Std.downcast(p, Emitter) == null)
 					p = p.parent;
 					p = p.parent;
-				}
 
 
+				// TODO(ces) : Attach materials directly to the batch
 				if (this.emitterPrefab == p) {
 				if (this.emitterPrefab == p) {
 					if(mat.enabled) {
 					if(mat.enabled) {
-						var ctx = mat.makeInstance(batchContext);
-						ctx.local3d = null;
+						@:privateAccess mat.makeInstance();
 					}
 					}
 				}
 				}
 			}
 			}
 
 
 			// Setup shaders
 			// Setup shaders
 			shaderAnims = [];
 			shaderAnims = [];
-			var shaders = emitterPrefab.getAll(hrt.prefab.Shader);
+			var shaders = emitterPrefab.findAll(hrt.prefab.Shader);
 			for( shader in shaders ) {
 			for( shader in shaders ) {
 				// Remove shaders that are not directly parented to this emitter
 				// Remove shaders that are not directly parented to this emitter
 				var p = shader.parent;
 				var p = shader.parent;
@@ -626,13 +625,15 @@ class EmitterObject extends h3d.scene.Object {
 				}
 				}
 				if (this.emitterPrefab == p) {
 				if (this.emitterPrefab == p) {
 					if( !shader.enabled ) continue;
 					if( !shader.enabled ) continue;
-					var shCtx = makeShaderInstance(shader, batchContext);
-					if( shCtx == null ) continue;
-
-					shCtx.local3d = null; // Prevent shader.iterMaterials from adding our objet to the list incorectly
+					// TODO(ces) : Attach materials directly to the batch
 
 
-					hrt.prefab.fx.BaseFX.getShaderAnims(shCtx, shader, shaderAnims, batch);
+					makeShaderInstance(shader);
+					//shCtx.local3d = null; // Prevent shader.iterMaterials from adding our objet to the list incorectly
+					// TODO(ces) : It looks like particles anims are broken
+					hrt.prefab.fx.BaseFX.BaseFXTools.getShaderAnims(shader, shaderAnims, batch);
+				//var shader = Std.downcast(shCtx.custom, hxsl.Shader);
 				}
 				}
+
 			}
 			}
 
 
 			// Animated textures animations
 			// Animated textures animations
@@ -662,6 +663,7 @@ class EmitterObject extends h3d.scene.Object {
 		randomValues = [for(i in 0...(maxCount * randSlots)) 0];
 		randomValues = [for(i in 0...(maxCount * randSlots)) 0];
 		evaluator = new Evaluator(randomValues, randSlots);
 		evaluator = new Evaluator(randomValues, randSlots);
 		reset();
 		reset();
+
 	}
 	}
 
 
 	override function onRemove() {
 	override function onRemove() {
@@ -792,7 +794,6 @@ class EmitterObject extends h3d.scene.Object {
 		return idx;
 		return idx;
 	}
 	}
 
 
-	var tmpCtx : hrt.prefab.Context;
 	static var tmpQuat = new h3d.Quat();
 	static var tmpQuat = new h3d.Quat();
 	static var tmpEmitterQuat = new h3d.Quat();
 	static var tmpEmitterQuat = new h3d.Quat();
 	static var tmpOffset = new h3d.Vector();
 	static var tmpOffset = new h3d.Vector();
@@ -815,13 +816,8 @@ class EmitterObject extends h3d.scene.Object {
 			var scene = relativeScenePosition ? getScene() : null;
 			var scene = relativeScenePosition ? getScene() : null;
 
 
 			if (trailsTemplate != null && trails == null) {
 			if (trailsTemplate != null && trails == null) {
-				if( tmpCtx == null ) {
-					tmpCtx = new hrt.prefab.Context();
-					tmpCtx.shared = context.shared;
-				}
-				tmpCtx.custom = {numTrails: maxCount};
-				tmpCtx.local3d = this;
-				trails = cast trailsTemplate.make(tmpCtx).local3d;
+				trailsTemplate.make();
+				trails = cast trailsTemplate.local3d;
 				trails.autoTrackPosition = false;
 				trails.autoTrackPosition = false;
 			}
 			}
 
 
@@ -940,11 +936,11 @@ class EmitterObject extends h3d.scene.Object {
 			}
 			}
 		}
 		}
 
 
-		context.local3d = this;
 		emitCount += count;
 		emitCount += count;
 	}
 	}
 
 
-	/** Called every time a particle is emitted. `offset` and `orient` can be modified (local space) **/
+	/** Called every time a particle is emitted. `offset` and `orient`
+		 can be modified (local space) **/
 	public dynamic function onEmit(offset: h3d.Vector, orient : h3d.Quat) { }
 	public dynamic function onEmit(offset: h3d.Vector, orient : h3d.Quat) { }
 
 
 	// No-alloc version of h3d.Matrix.getEulerAngles()
 	// No-alloc version of h3d.Matrix.getEulerAngles()
@@ -1217,14 +1213,10 @@ class EmitterObject extends h3d.scene.Object {
 					i = disposeInstance(i);
 					i = disposeInstance(i);
 					// SUB EMITTER
 					// SUB EMITTER
 					if( subEmitterTemplates != null ) {
 					if( subEmitterTemplates != null ) {
-						if( tmpCtx == null ) {
-							tmpCtx = new hrt.prefab.Context();
-							tmpCtx.local3d = this.getScene();
-							tmpCtx.shared = context.shared;
-						}
-						tmpCtx.local3d = this.getScene();
-						for (sub in subEmitterTemplates) {
-							var emitter : EmitterObject = cast sub.makeInstance(tmpCtx).local3d;
+
+						for (subEmitterTemplate in subEmitterTemplates) {
+							var subEmitterInstance : Emitter = @:privateAccess subEmitterTemplate.make(new ContextShared());
+						    var emitter : EmitterObject = cast subEmitterInstance.local3d;
 							var pos = p.absPos.getPosition();
 							var pos = p.absPos.getPosition();
 							emitter.setPosition(pos.x, pos.y, pos.z);
 							emitter.setPosition(pos.x, pos.y, pos.z);
 							emitter.isSubEmitter = true;
 							emitter.isSubEmitter = true;
@@ -1341,8 +1333,8 @@ class EmitterObject extends h3d.scene.Object {
 
 
 class Emitter extends Object3D {
 class Emitter extends Object3D {
 
 
-	public function new(?parent) {
-		super(parent);
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		props = { };
 		props = { };
 		for(param in emitterParams) {
 		for(param in emitterParams) {
 			if(param.def != null)
 			if(param.def != null)
@@ -1430,8 +1422,8 @@ class Emitter extends Object3D {
 	};
 	};
 
 
 	override function save() {
 	override function save() {
-		var obj : Dynamic = super.save();
-		obj.props = Reflect.copy(props);
+		var data = super.save();
+		data.props = Reflect.copy(props);
 		for(param in PARAMS) {
 		for(param in PARAMS) {
 			var f : Dynamic = Reflect.field(props, param.name);
 			var f : Dynamic = Reflect.field(props, param.name);
 			if(f != null && haxe.Json.stringify(f) != haxe.Json.stringify(param.def)) {
 			if(f != null && haxe.Json.stringify(f) != haxe.Json.stringify(param.def)) {
@@ -1441,13 +1433,13 @@ class Emitter extends Object3D {
 						val = Type.enumConstructor(val);
 						val = Type.enumConstructor(val);
 					default:
 					default:
 				}
 				}
-				Reflect.setField(obj.props, param.name, val);
+				Reflect.setField(data.props, param.name, val);
 			}
 			}
 			else {
 			else {
-				Reflect.deleteField(obj.props, param.name);
+				Reflect.deleteField(data.props, param.name);
 			}
 			}
 		}
 		}
-		return obj;
+		return data;
 	}
 	}
 
 
 	override function load( obj : Dynamic ) {
 	override function load( obj : Dynamic ) {
@@ -1467,17 +1459,24 @@ class Emitter extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function make(ctx: Context) {
-		if( ctx == null ) {
-			ctx = new Context();
-			ctx.init();
+	override function copy(obj:Prefab) {
+		super.copy(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);
 		}
 		}
-		ctx = makeInstance(ctx);
-		return ctx;
 	}
 	}
 
 
 
 
-
 	static inline function randProp(name: String) {
 	static inline function randProp(name: String) {
 		return name + "_rand";
 		return name + "_rand";
 	}
 	}
@@ -1509,9 +1508,9 @@ class Emitter extends Object3D {
 			Reflect.setField(props, param.name, param.def);
 			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);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
+		var emitterObj = Std.downcast(local3d, EmitterObject);
 
 
 		var randIdx = 0;
 		var randIdx = 0;
 		var template : Object3D = cast children.find(
 		var template : Object3D = cast children.find(
@@ -1723,7 +1722,7 @@ class Emitter extends Object3D {
 
 
 
 
 		#if !editor  // Keep startTime at 0 in Editor, since global.time is synchronized to timeline
 		#if !editor  // Keep startTime at 0 in Editor, since global.time is synchronized to timeline
-		var scene = ctx.local3d.getScene();
+		var scene = local3d.getScene();
 		if(scene != null)
 		if(scene != null)
 			emitterObj.startTime = @:privateAccess scene.renderer.ctx.time;
 			emitterObj.startTime = @:privateAccess scene.renderer.ctx.time;
 		#end
 		#end
@@ -1736,22 +1735,15 @@ class Emitter extends Object3D {
 		#end
 		#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 makeChild(p:Prefab) {
+	};
 
 
-	override function removeInstance(ctx:Context):Bool {
-		return false;
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+		return new EmitterObject(parent3d);
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		function refresh() {
 		function refresh() {
@@ -1862,7 +1854,7 @@ class Emitter extends Object3D {
 
 
 			for( gn in groupNames ) {
 			for( gn in groupNames ) {
 				var params = params.filter( p -> p.groupName == (gn == "Emitter" ? null : gn) );
 				var params = params.filter( p -> p.groupName == (gn == "Emitter" ? null : gn) );
-				var group = new Element('<div class="group" name="$gn"></div>');
+				var group = new hide.Element('<div class="group" name="$gn"></div>');
 				group.append(hide.comp.PropsEditor.makePropsList(params));
 				group.append(hide.comp.PropsEditor.makePropsList(params));
 				ctx.properties.add(group, this.props, onChange);
 				ctx.properties.add(group, this.props, onChange);
 			}
 			}
@@ -1881,12 +1873,12 @@ class Emitter extends Object3D {
 
 
 			for (groupName => params in groups)
 			for (groupName => params in groups)
 			{
 			{
-				var instGroup = new Element('<div class="group" name="$groupName"></div>');
-				var dl = new Element('<dl>').appendTo(instGroup);
+				var instGroup = new hide.Element('<div class="group" name="$groupName"></div>');
+				var dl = new hide.Element('<dl>').appendTo(instGroup);
 
 
 				for (p in params) {
 				for (p in params) {
-					var dt = new Element('<dt>${p.disp != null ? p.disp : p.name}</dt>').appendTo(dl);
-					var dd = new Element('<dd>').appendTo(dl);
+					var dt = new hide.Element('<dt>${p.disp != null ? p.disp : p.name}</dt>').appendTo(dl);
+					var dd = new hide.Element('<dd>').appendTo(dl);
 
 
 					function addUndo(pname: String) {
 					function addUndo(pname: String) {
 						ctx.properties.undo.change(Field(this.props, pname, Reflect.field(this.props, pname)), function() {
 						ctx.properties.undo.change(Field(this.props, pname, Reflect.field(this.props, pname)), function() {
@@ -1918,15 +1910,15 @@ class Emitter extends Object3D {
 						});
 						});
 					}
 					}
 					else {
 					else {
-						var btn = new Element('<input type="button" value="+"></input>').appendTo(dd);
+						var btn = new hide.Element('<input type="button" value="+"></input>').appendTo(dd);
 						btn.click(function(e) {
 						btn.click(function(e) {
 							addUndo(p.name);
 							addUndo(p.name);
 							resetParam(p);
 							resetParam(p);
 							refresh();
 							refresh();
 						});
 						});
 					}
 					}
-					var dt = new Element('<dt>~</dt>').appendTo(dl);
-					var dd = new Element('<dd>').appendTo(dl);
+					var dt = new hide.Element('<dt>~</dt>').appendTo(dl);
+					var dd = new hide.Element('<dd>').appendTo(dl);
 					var randDef : Dynamic = switch(p.t) {
 					var randDef : Dynamic = switch(p.t) {
 						case PVec(n): [for(i in 0...n) 0.0];
 						case PVec(n): [for(i in 0...n) 0.0];
 						case PFloat(_): 0.0;
 						case PFloat(_): 0.0;
@@ -1957,7 +1949,7 @@ class Emitter extends Object3D {
 						});
 						});
 					}
 					}
 					else {
 					else {
-						var btn = new Element('<input type="button" value="+"></input>').appendTo(dd);
+						var btn = new hide.Element('<input type="button" value="+"></input>').appendTo(dd);
 						btn.click(function(e) {
 						btn.click(function(e) {
 							addUndo(randProp(p.name));
 							addUndo(randProp(p.name));
 							Reflect.setField(this.props, randProp(p.name), randDef);
 							Reflect.setField(this.props, randProp(p.name), randDef);
@@ -1971,8 +1963,8 @@ class Emitter extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function setSelected( ctx : Context, b : Bool ) {
-		var emitterObj = Std.downcast(ctx.local3d, EmitterObject);
+	override function setSelected(b : Bool ) {
+		var emitterObj = Std.downcast(local3d, EmitterObject);
 		if(emitterObj == null)
 		if(emitterObj == null)
 			return false;
 			return false;
 		var debugShape : h3d.scene.Object = emitterObj.find(c -> if(c.name == "_highlight") c else null);
 		var debugShape : h3d.scene.Object = emitterObj.find(c -> if(c.name == "_highlight") c else null);
@@ -2094,11 +2086,11 @@ class Emitter extends Object3D {
 	}
 	}
 
 
 	override function getHideProps() : HideProps {
 	override function getHideProps() : HideProps {
-		return { icon : "asterisk", name : "Emitter", allowParent : function(p) return p.to(FX) != null || p.getParent(FX) != null };
+		return { icon : "asterisk", name : "Emitter", allowParent : function(p) return p.to(FX) != null || p.findParent(FX) != null };
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("emitter", Emitter);
+	static var _ = Prefab.register("emitter", Emitter);
 
 
 }
 }
 
 

+ 6 - 8
hrt/prefab/fx/Event.hx

@@ -9,8 +9,7 @@ typedef EventInstance = {
 interface IEvent {
 interface IEvent {
 	#if editor
 	#if editor
 	function getEventPrefab() : hrt.prefab.Prefab;
 	function getEventPrefab() : hrt.prefab.Prefab;
-	function getHideProps() : hide.prefab.HideProps;
-	function getDisplayInfo(ctx: EditContext) : { label: String, length: Float, ?loop: Bool};
+	function getDisplayInfo(ctx: hide.prefab.EditContext) : { label: String, length: Float, ?loop: Bool };
 	#end
 	#end
 	var time(default, set) : Float;
 	var time(default, set) : Float;
 	var hidden : Bool;
 	var hidden : Bool;
@@ -24,16 +23,15 @@ class Event extends hrt.prefab.Prefab implements IEvent {
 	public var lock:Bool = false;
 	public var lock:Bool = false;
 	public var selected:Bool = false;
 	public var selected:Bool = false;
 
 
-	public function new(?parent) {
-		super(parent);
-		this.type = "event";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 	}
 	}
 
 
 	function set_time(v) {
 	function set_time(v) {
 		return time = v;
 		return time = v;
 	}
 	}
 
 
-	public function prepare(ctx: Context) : EventInstance {
+	public function prepare() : EventInstance {
 		return {
 		return {
 			evt: this
 			evt: this
 		};
 		};
@@ -74,7 +72,7 @@ class Event extends hrt.prefab.Prefab implements IEvent {
 		};
 		};
 	}
 	}
 
 
-	public function getDisplayInfo(ctx) {
+	public function getDisplayInfo(ctx: hide.prefab.EditContext) {
 		return {
 		return {
 			label: name,
 			label: name,
 			length: 1.0,
 			length: 1.0,
@@ -84,5 +82,5 @@ class Event extends hrt.prefab.Prefab implements IEvent {
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("event", Event);
+	static var _ = Prefab.register("event", Event);
 }
 }

+ 76 - 71
hrt/prefab/fx/FX.hx

@@ -48,16 +48,16 @@ class FXAnimation extends h3d.scene.Object {
 		inheritCulled = true;
 		inheritCulled = true;
 	}
 	}
 
 
-	function init(ctx: Context, def: FX, ?root: PrefabElement) {
+	function init(def: FX, ?root: PrefabElement) {
 		if(root == null)
 		if(root == null)
 			root = def;
 			root = def;
-		initObjAnimations(ctx, root);
-		initEmitters(ctx, root);
-		BaseFX.getShaderAnims(ctx, root, shaderAnims);
+		initObjAnimations(root);
+		initEmitters(root);
+		hrt.prefab.fx.BaseFX.BaseFXTools.getShaderAnims(root, shaderAnims);
 		if(shaderAnims.length == 0) shaderAnims = null;
 		if(shaderAnims.length == 0) shaderAnims = null;
-		events = initEvents(root, ctx);
-		var root = def.getFXRoot(ctx, def);
-		initConstraints(ctx, root != null ? root : def);
+		events = initEvents(root);
+		var root = hrt.prefab.fx.BaseFX.BaseFXTools.getFXRoot(def);
+		initConstraints(root != null ? root : def);
 
 
 		trails = findAll((p) -> Std.downcast(p, hrt.prefab.l3d.Trails.TrailObj));
 		trails = findAll((p) -> Std.downcast(p, hrt.prefab.l3d.Trails.TrailObj));
 	}
 	}
@@ -270,11 +270,11 @@ class FXAnimation extends h3d.scene.Object {
 		this.prevTime = localTime;
 		this.prevTime = localTime;
 	}
 	}
 
 
-	function initEvents(elt: PrefabElement, ctx: Context) {
+	function initEvents(elt: PrefabElement) {
 		var childEvents = [for(c in elt.children) if(c.enabled && c.to(Event) != null) c.to(Event)];
 		var childEvents = [for(c in elt.children) if(c.enabled && c.to(Event) != null) c.to(Event)];
 		var ret = null;
 		var ret = null;
 		for(evt in childEvents) {
 		for(evt in childEvents) {
-			var eventObj = evt.prepare(ctx);
+			var eventObj = evt.prepare();
 			if(eventObj == null) continue;
 			if(eventObj == null) continue;
 			if(ret == null) ret = [];
 			if(ret == null) ret = [];
 			ret.push(eventObj);
 			ret.push(eventObj);
@@ -282,12 +282,12 @@ class FXAnimation extends h3d.scene.Object {
 		return ret;
 		return ret;
 	}
 	}
 
 
-	function initObjAnimations(ctx:Context, elt: PrefabElement) {
-		if(!elt.enabled) return;
+	function initObjAnimations(elt: PrefabElement) {
+		if(@:privateAccess !elt.shouldBeInstanciated()) return;
 		if(Std.downcast(elt, hrt.prefab.fx.Emitter) == null) {
 		if(Std.downcast(elt, hrt.prefab.fx.Emitter) == null) {
 			// Don't extract animations for children of Emitters
 			// Don't extract animations for children of Emitters
 			for(c in elt.children) {
 			for(c in elt.children) {
-				initObjAnimations(ctx, c);
+				initObjAnimations(c);
 			}
 			}
 		}
 		}
 
 
@@ -295,11 +295,6 @@ class FXAnimation extends h3d.scene.Object {
 		if(obj3d == null)
 		if(obj3d == null)
 			return;
 			return;
 
 
-		// TODO: Support references?
-		var objCtx = ctx.shared.contexts.get(elt);
-		if(objCtx == null || objCtx.local3d == null)
-			return;
-
 		var anyFound = false;
 		var anyFound = false;
 
 
 		function makeVal(name, def) : Value {
 		function makeVal(name, def) : Value {
@@ -340,19 +335,21 @@ class FXAnimation extends h3d.scene.Object {
 		}
 		}
 
 
 		var ap : AdditionalProperies = null;
 		var ap : AdditionalProperies = null;
-		if( Std.isOfType(objCtx.local3d, h3d.scene.pbr.PointLight)) {
+		var local3d = Object3D.getLocal3d(elt);
+
+		if( Std.isOfType(local3d, h3d.scene.pbr.PointLight)) {
 			ap = PointLight(makeColor("color"), makeVal("power", null), makeVal("size", null), makeVal("range", null) );
 			ap = PointLight(makeColor("color"), makeVal("power", null), makeVal("size", null), makeVal("range", null) );
 		}
 		}
-		else if( Std.isOfType(objCtx.local3d, h3d.scene.pbr.SpotLight)) {
+		else if( Std.isOfType(local3d, h3d.scene.pbr.SpotLight)) {
 			ap = SpotLight(makeColor("color"), makeVal("power", null), makeVal("range", null), makeVal("angle", null), makeVal("fallOff", null) );
 			ap = SpotLight(makeColor("color"), makeVal("power", null), makeVal("range", null), makeVal("angle", null), makeVal("fallOff", null) );
 		}
 		}
-		else if( Std.isOfType(objCtx.local3d, h3d.scene.pbr.DirLight)) {
+		else if( Std.isOfType(local3d, h3d.scene.pbr.DirLight)) {
 			ap = DirLight(makeColor("color"), makeVal("power", null));
 			ap = DirLight(makeColor("color"), makeVal("power", null));
 		}
 		}
 
 
 		var anim : ObjectAnimation = {
 		var anim : ObjectAnimation = {
 			elt: obj3d,
 			elt: obj3d,
-			obj: objCtx.local3d,
+			obj: local3d,
 			events: null,
 			events: null,
 			position: makeVector("position", 0.0),
 			position: makeVector("position", 0.0),
 			scale: makeVector("scale", 1.0, true),
 			scale: makeVector("scale", 1.0, true),
@@ -362,7 +359,7 @@ class FXAnimation extends h3d.scene.Object {
 			additionalProperies: ap,
 			additionalProperies: ap,
 		};
 		};
 
 
-		anim.events = initEvents(elt, objCtx);
+		anim.events = initEvents(elt);
 		if(anim.events != null)
 		if(anim.events != null)
 			anyFound = true;
 			anyFound = true;
 
 
@@ -372,26 +369,26 @@ class FXAnimation extends h3d.scene.Object {
 		}
 		}
 	}
 	}
 
 
-	function initEmitters(ctx: Context, elt: PrefabElement) {
+	function initEmitters(elt: PrefabElement) {
 		if(!elt.enabled) return;
 		if(!elt.enabled) return;
 		var em = Std.downcast(elt, hrt.prefab.fx.Emitter);
 		var em = Std.downcast(elt, hrt.prefab.fx.Emitter);
 		if(em != null)  {
 		if(em != null)  {
-			for(emCtx in ctx.shared.getContexts(elt)) {
-				if(emCtx.local3d == null) continue;
+			var local3d = Object3D.getLocal3d(em);
+			if (local3d != null) {
 				if(emitters == null) emitters = [];
 				if(emitters == null) emitters = [];
-				var emobj : hrt.prefab.fx.Emitter.EmitterObject = cast emCtx.local3d;
+				var emobj : hrt.prefab.fx.Emitter.EmitterObject = cast local3d;
 				emobj.setRandSeed(randSeed);
 				emobj.setRandSeed(randSeed);
 				emitters.push(emobj);
 				emitters.push(emobj);
 			}
 			}
 		}
 		}
 		else {
 		else {
 			for(c in elt.children) {
 			for(c in elt.children) {
-				initEmitters(ctx, c);
+				initEmitters(c);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	function initConstraints( ctx : Context, elt : PrefabElement ){
+	function initConstraints(elt : PrefabElement ){
 		if(!elt.enabled) return;
 		if(!elt.enabled) return;
 		var co = Std.downcast(elt, hrt.prefab.l3d.Constraint);
 		var co = Std.downcast(elt, hrt.prefab.l3d.Constraint);
 		if(co != null) {
 		if(co != null) {
@@ -400,7 +397,7 @@ class FXAnimation extends h3d.scene.Object {
 		}
 		}
 		else
 		else
 			for(c in elt.children)
 			for(c in elt.children)
-				initConstraints(ctx, c);
+				initConstraints(c);
 	}
 	}
 
 
 	public function resolveConstraints( caster : h3d.scene.Object ) {
 	public function resolveConstraints( caster : h3d.scene.Object ) {
@@ -422,35 +419,46 @@ class FXAnimation extends h3d.scene.Object {
 	}
 	}
 }
 }
 
 
-class FX extends BaseFX {
+class FX extends Object3D implements BaseFX {
+
+	@:s public var duration : Float;
+	@:s public var startDelay : Float = 0.0;
+	@:c public var scriptCode : String;
+	@:s public var cullingRadius : Float;
+	@:s public var markers : Array<{t: Float}> = [];
+	@:c public var blendFactor : Float;
 
 
-	public function new() {
-		super();
-		type = "fx";
+
+	/*override function save(data : Dynamic) {
+		super.save(data);
+		data.cullingRadius = cullingRadius;
+		if( scriptCode != "" ) data.scriptCode = scriptCode;
+	}*/
+
+	public function new(parent:Prefab, contextShared: ContextShared) {
+		super(parent, contextShared);
+		duration = 5.0;
 		cullingRadius = 3.0;
 		cullingRadius = 3.0;
 		blendFactor = 1.0;
 		blendFactor = 1.0;
 	}
 	}
 
 
-	override function save() {
-		var obj : Dynamic = super.save();
-		obj.cullingRadius = cullingRadius;
-		obj.blendFactor = blendFactor;
-		if( scriptCode != "" ) obj.scriptCode = scriptCode;
-		return obj;
-	}
-
-	override function load( obj : Dynamic ) {
-		super.load(obj);
-		if(obj.cullingRadius != null)
-			cullingRadius = obj.cullingRadius;
-		if(obj.blendFactor != null)
-			blendFactor = obj.blendFactor;
-		scriptCode = obj.scriptCode;
+	override function make( ?sh:hrt.prefab.Prefab.ContextMake) : Prefab  {
+		var fromRef = shared.parentPrefab != null;
+		var useFXRoot = #if editor fromRef #else true #end;
+		var root = hrt.prefab.fx.BaseFX.BaseFXTools.getFXRoot(this);
+		if(useFXRoot && root != null){
+			var childrenBackup = children;
+			children = [root];
+			var r = super.__makeInternal(sh);
+			children = childrenBackup;
+			return r;
+		}
+		else
+			return super.__makeInternal(sh);
 	}
 	}
 
 
-	override function make( ctx : Context ) : Context {
-		ctx = ctx.clone(this);
-		var fxanim = createInstance(ctx.local3d);
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		var fxanim = createInstance(parent3d);
 		fxanim.duration = duration;
 		fxanim.duration = duration;
 		fxanim.cullingRadius = cullingRadius;
 		fxanim.cullingRadius = cullingRadius;
 		fxanim.blendFactor = blendFactor;
 		fxanim.blendFactor = blendFactor;
@@ -465,8 +473,7 @@ class FX extends BaseFX {
 			p = p.parent;
 			p = p.parent;
 		}
 		}
 
 
-		ctx.local3d = fxanim;
-		var fromRef = ctx.shared.parent != null;
+		var fromRef = shared.parentPrefab != null;
 		#if editor
 		#if editor
 		// only play if we are as a reference
 		// only play if we are as a reference
 		if( fromRef ) fxanim.playSpeed = 1.0;
 		if( fromRef ) fxanim.playSpeed = 1.0;
@@ -474,21 +481,18 @@ class FX extends BaseFX {
 		fxanim.playSpeed = 1.0;
 		fxanim.playSpeed = 1.0;
 		#end
 		#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);
+		return fxanim;
+	}
 
 
-		return ctx;
+	override function postMakeInstance() {
+		var root = hrt.prefab.fx.BaseFX.BaseFXTools.getFXRoot(this);
+		var fxAnim : FXAnimation = cast local3d;
+		fxAnim.init(this, root);
 	}
 	}
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, null);
-		var fxanim = Std.downcast(ctx.local3d, FXAnimation);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(null);
+		var fxanim = Std.downcast(local3d, FXAnimation);
 		fxanim.duration = duration;
 		fxanim.duration = duration;
 		fxanim.cullingRadius = cullingRadius;
 		fxanim.cullingRadius = cullingRadius;
 		fxanim.blendFactor = blendFactor;
 		fxanim.blendFactor = blendFactor;
@@ -507,13 +511,13 @@ class FX extends BaseFX {
 
 
 	#if editor
 	#if editor
 
 
-	override function refreshObjectAnims(ctx: Context) {
-		var fxanim = Std.downcast(ctx.local3d, FXAnimation);
+	public function refreshObjectAnims() : Void {
+		var fxanim = Std.downcast(local3d, FXAnimation);
 		fxanim.objAnims = null;
 		fxanim.objAnims = null;
-		fxanim.initObjAnimations(ctx, this);
+		fxanim.initObjAnimations(this);
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 		var props = new hide.Element('
 			<div class="group" name="FX Scene">
 			<div class="group" name="FX Scene">
 				<dl>
 				<dl>
@@ -527,10 +531,11 @@ class FX extends BaseFX {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "cube", name : "FX", allowParent: _ -> false};
 		return { icon : "cube", name : "FX", allowParent: _ -> false};
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("fx", FX, "fx");
+	// TOCO(ces) : restore extension support
+	static var _ = Prefab.register("fx", FX, "fx");
 }
 }

+ 63 - 57
hrt/prefab/fx/FX2D.hx

@@ -38,36 +38,34 @@ class FX2DAnimation extends h2d.Object {
 		random.init(seed);
 		random.init(seed);
 	}
 	}
 
 
-	function init(ctx: Context, def: FX2D) {
-		initEmitters(ctx, def);
+	function init(def: FX2D) {
+		initEmitters(def);
 		if (def.children.length == 1 && def.children[0].name == "FXRoot")
 		if (def.children.length == 1 && def.children[0].name == "FXRoot")
-			events = initEvents(def.children[0], ctx);
+			events = initEvents(def.children[0]);
 		else
 		else
-			events = initEvents(def, ctx);
+			events = initEvents(def);
 	}
 	}
 
 
-	function initEmitters(ctx: Context, elt: PrefabElement) {
+	function initEmitters(elt: PrefabElement) {
 		var em = Std.downcast(elt, hrt.prefab.l2d.Particle2D);
 		var em = Std.downcast(elt, hrt.prefab.l2d.Particle2D);
 		if(em != null)  {
 		if(em != null)  {
-			for(emCtx in ctx.shared.getContexts(elt)) {
-				if(emCtx.local2d == null) continue;
+			if(em.local2d == null) return;
 				if(emitters == null) emitters = [];
 				if(emitters == null) emitters = [];
-				var emobj : hrt.prefab.l2d.Particle2D.Particles = cast emCtx.local2d;
+			var emobj : hrt.prefab.l2d.Particle2D.Particles = cast em.local2d;
 				emitters.push(emobj);
 				emitters.push(emobj);
 			}
 			}
-		}
 		else {
 		else {
 			for(c in elt.children) {
 			for(c in elt.children) {
-				initEmitters(ctx, c);
+				initEmitters(c);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	function initEvents(elt: PrefabElement, ctx: Context) {
+	function initEvents(elt: PrefabElement) {
 		var childEvents = [for(c in elt.children) if(c.to(Event) != null) c.to(Event)];
 		var childEvents = [for(c in elt.children) if(c.to(Event) != null) c.to(Event)];
 		var ret = null;
 		var ret = null;
 		for(evt in childEvents) {
 		for(evt in childEvents) {
-			var eventObj = evt.prepare(ctx);
+			var eventObj = evt.prepare();
 			if(eventObj == null) continue;
 			if(eventObj == null) continue;
 			if(ret == null) ret = [];
 			if(ret == null) ret = [];
 			ret.push(eventObj);
 			ret.push(eventObj);
@@ -163,19 +161,23 @@ class FX2DAnimation extends h2d.Object {
 	}
 	}
 }
 }
 
 
-class FX2D extends BaseFX {
+class FX2D extends Object2D implements BaseFX {
+
+	@:s public var duration : Float;
+	@:s public var startDelay : Float;
+	@:c public var scriptCode : String;
+	@:c public var cullingRadius : Float;
+	@:c public var markers : Array<{t: Float}> = [];
+	@:c public var blendFactor : Float;
+
 
 
 	@:s var loop : Bool = false;
 	@:s var loop : Bool = false;
 	@:s var startLoop : Float = 0.0;
 	@:s var startLoop : Float = 0.0;
 
 
-	public function new() {
-		super();
-		type = "fx2d";
-	}
 
 
-	function getObjAnimations(ctx:Context, elt: PrefabElement, anims: Array<ObjectAnimation>) {
+	function getObjAnimations(elt: PrefabElement, anims: Array<ObjectAnimation>) {
 		for(c in elt.children) {
 		for(c in elt.children) {
-			getObjAnimations(ctx, c, anims);
+			getObjAnimations(c, anims);
 		}
 		}
 
 
 		var obj2d = elt.to(hrt.prefab.Object2D);
 		var obj2d = elt.to(hrt.prefab.Object2D);
@@ -183,10 +185,6 @@ class FX2D extends BaseFX {
 			return;
 			return;
 
 
 		// TODO: Support references?
 		// TODO: Support references?
-		var objCtx = ctx.shared.contexts.get(elt);
-		if(objCtx == null || objCtx.local2d == null)
-			return;
-
 		var anyFound = false;
 		var anyFound = false;
 
 
 		function makeVal(name, def) : Value {
 		function makeVal(name, def) : Value {
@@ -220,7 +218,7 @@ class FX2D extends BaseFX {
 
 
 		var anim : ObjectAnimation = {
 		var anim : ObjectAnimation = {
 			elt2d: obj2d,
 			elt2d: obj2d,
-			obj2d: objCtx.local2d,
+			obj2d: local2d,
 			events: null,
 			events: null,
 			position: makeVector("position", 0.0),
 			position: makeVector("position", 0.0),
 			scale: makeVector("scale", 1.0, true),
 			scale: makeVector("scale", 1.0, true),
@@ -229,8 +227,8 @@ class FX2D extends BaseFX {
 			visibility: makeVal("visibility", null),
 			visibility: makeVal("visibility", null),
 		};
 		};
 
 
-		for(evt in elt.getAll(Event)) {
-			var eventObj = evt.prepare(objCtx);
+		for(evt in elt.findAll(Event)) {
+			var eventObj = evt.prepare();
 			if(eventObj == null) continue;
 			if(eventObj == null) continue;
 			if(anim.events == null) anim.events = [];
 			if(anim.events == null) anim.events = [];
 			anim.events.push(eventObj);
 			anim.events.push(eventObj);
@@ -244,41 +242,49 @@ class FX2D extends BaseFX {
 			anims.push(anim);
 			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;
-
+	override function make( ?sh:hrt.prefab.Prefab.ContextMake) : Prefab {
 		#if editor
 		#if editor
-		super.make(ctx);
+		return super.__makeInternal(sh);
 		#else
 		#else
-		var root = getFXRoot(ctx, this);
-		if( root != null ) {
-			for( c in root.children )
-				makeChild(ctx, c);
+		var fromRef = shared.parentPrefab != null;
+		var useFXRoot = #if editor fromRef #else true #end;
+		var root = hrt.prefab.fx.BaseFX.BaseFXTools.getFXRoot(this);
+		if( useFXRoot && root != null ) {
+			var childrenBackup = children;
+			children = [root];
+			var r = super.__makeInternal(sh);
+			children = childrenBackup;
+			return r;
 		} else
 		} else
-			super.make(ctx);
+			return super.__makeInternal(sh);
 		#end
 		#end
-		fxanim.init(ctx, this);
+	}
+
+
+	override function postMakeInstance() {
+		var fxanim : FX2DAnimation = cast local2d;
+		fxanim.init(this);
+		getObjAnimations(this, fxanim.objects);
+		hrt.prefab.fx.BaseFX.BaseFXTools.getShaderAnims(this, fxanim.shaderAnims);
+	}
 
 
-		getObjAnimations(ctx, this, fxanim.objects);
-		BaseFX.getShaderAnims(ctx, this, fxanim.shaderAnims);
+	override function makeObject(parent2d: h2d.Object) : h2d.Object {
+		var fxanim = createInstance(parent2d);
+		fxanim.duration = duration;
+		fxanim.loop = loop;
+		fxanim.startLoop = startLoop;
+		fxanim.playSpeed = 1.0;
 
 
-		return ctx;
+		return fxanim;
 	}
 	}
 
 
-	public function getTargetShader2D( ctx : Context, name : String ) {
-		return ctx.local2d;
+	public function getTargetShader2D(name : String ) {
+		return local2d;
 	}
 	}
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, null);
-		var fxanim = Std.downcast(ctx.local2d, FX2DAnimation);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
+		var fxanim = Std.downcast(local2d, FX2DAnimation);
 		fxanim.duration = duration;
 		fxanim.duration = duration;
 		fxanim.loop = loop;
 		fxanim.loop = loop;
 	}
 	}
@@ -290,13 +296,13 @@ class FX2D extends BaseFX {
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function refreshObjectAnims(ctx: Context) {
-		var fxanim = Std.downcast(ctx.local2d, FX2DAnimation);
+	public function refreshObjectAnims() {
+		var fxanim = Std.downcast(local2d, FX2DAnimation);
 		fxanim.objects = [];
 		fxanim.objects = [];
-		getObjAnimations(ctx, this, fxanim.objects);
+		getObjAnimations(this, fxanim.objects);
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 		var props = new hide.Element('
 			<div class="group" name="FX2D Scene">
 			<div class="group" name="FX2D Scene">
 				<dl>
 				<dl>
@@ -310,10 +316,10 @@ class FX2D extends BaseFX {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "cube", name : "FX2D", allowParent: _ -> false};
 		return { icon : "cube", name : "FX2D", allowParent: _ -> false};
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("fx2d", FX2D, "fx2d");
+	static var _ = Prefab.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.isOfType(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
-}

+ 11 - 18
hrt/prefab/fx/LookAt.hx

@@ -92,35 +92,26 @@ class LookAt extends Object3D {
 	@:s var target(default,null) : String;
 	@:s var target(default,null) : String;
 	@:s var lockAxis: Array<Float> = [0,0,0];
 	@: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);
+	override function updateInstance(?propName:String) {
+		super.updateInstance(propName);
 		var targetObj = null;
 		var targetObj = null;
 		if(target != "camera")
 		if(target != "camera")
-			targetObj = ctx.locateObject(target);
+			targetObj = 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;
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		return new LookAtObject(parent3d, this);
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return {
 		return {
 			icon : "cog",
 			icon : "cog",
 			name : "LookAt"
 			name : "LookAt"
 		};
 		};
 	}
 	}
 
 
-	override function edit(ctx:EditContext) {
+	override function edit(ctx:hide.prefab.EditContext) {
 		super.edit(ctx);
 		super.edit(ctx);
 		var group = new hide.Element('
 		var group = new hide.Element('
 		<div class="group" name="LookAt">
 		<div class="group" name="LookAt">
@@ -133,7 +124,9 @@ class LookAt extends Object3D {
 			{ name: "lockAxis", t: PVec(3), def: [1,0,0] }
 			{ name: "lockAxis", t: PVec(3), def: [1,0,0] }
 		]));
 		]));
 
 
-		var props = ctx.properties.add(group ,this, function(_) { trace(this.lockAxis); });
+		var props = ctx.properties.add(group ,this);
+
+
 
 
 		var select = props.find("select");
 		var select = props.find("select");
 		var opt = new hide.Element("<option>").attr("value", "camera").html("Camera");
 		var opt = new hide.Element("<option>").attr("value", "camera").html("Camera");
@@ -148,5 +141,5 @@ class LookAt extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("lookAt", LookAt);
+	static var _ = Prefab.register("lookAt", LookAt);
 }
 }

+ 16 - 20
hrt/prefab/fx/SubFX.hx

@@ -14,24 +14,20 @@ class SubFX extends Reference implements hrt.prefab.fx.Event.IEvent{
 	public var selected:Bool = false;
 	public var selected:Bool = false;
 
 
 
 
-	public function new(?parent) {
-		super(parent);
-		this.type = "subFX";
-	}
-
-	override function makeInstance(ctx:Context):Context {
-		var ctx = super.makeInstance(ctx);
-		var fxanim = ctx.local3d.find(o -> Std.downcast(o, hrt.prefab.fx.FX.FXAnimation));
-		if(fxanim != null) {
-			fxanim.startDelay = time;
-			fxanim.loop = loop;
-			#if editor
-			instance = fxanim;
-			#end
+	override function postMakeInstance() : Void {
+		if (refInstance != null) {
+			var fxanim : hrt.prefab.fx.FX.FXAnimation = refInstance.findFirstLocal3d().find(o -> Std.downcast(o, hrt.prefab.fx.FX.FXAnimation));
+			if(fxanim != null) {
+				fxanim.startDelay = time;
+			    fxanim.loop = loop;
+				#if editor
+				instance = fxanim;
+				#end
+			}
 		}
 		}
-		return ctx;
 	}
 	}
 
 
+
 	function set_time(v) {
 	function set_time(v) {
 		#if editor
 		#if editor
 		if(instance != null)
 		if(instance != null)
@@ -50,7 +46,7 @@ class SubFX extends Reference implements hrt.prefab.fx.Event.IEvent{
 
 
 	#if editor
 	#if editor
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = ctx.properties.add(new hide.Element('
 		var props = ctx.properties.add(new hide.Element('
 			<div class="group" name="Event">
 			<div class="group" name="Event">
 				<dl>
 				<dl>
@@ -66,8 +62,8 @@ class SubFX extends Reference implements hrt.prefab.fx.Event.IEvent{
 
 
 	public function getEventPrefab() { return this; }
 	public function getEventPrefab() { return this; }
 
 
-	public function getDisplayInfo(ctx:EditContext) {
-		var ref = Std.downcast(resolveRef(ctx.rootContext.shared), FX);
+	public function getDisplayInfo(ctx:hide.prefab.EditContext) {
+		var ref = Std.downcast(resolveRef(), FX);
 		return {
 		return {
 			label: ref != null ? new haxe.io.Path(source).file : "null",
 			label: ref != null ? new haxe.io.Path(source).file : "null",
 			length: ref != null ? ref.duration : 1.0,
 			length: ref != null ? ref.duration : 1.0,
@@ -75,13 +71,13 @@ class SubFX extends Reference implements hrt.prefab.fx.Event.IEvent{
 		};
 		};
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return {
 		return {
 			icon : "play-circle", name : "SubFX"
 			icon : "play-circle", name : "SubFX"
 		};
 		};
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("subFX", SubFX);
+	static var _ = Prefab.register("subFX", SubFX);
 
 
 }
 }

+ 28 - 43
hrt/prefab/fx/Swarm.hx

@@ -33,6 +33,7 @@ class SwarmElement {
 	public var prev_vz: Float = 0.0;
 	public var prev_vz: Float = 0.0;
 }
 }
 
 
+@:access(hrt.prefab.Prefab)
 class SwarmObject extends h3d.scene.Object {
 class SwarmObject extends h3d.scene.Object {
 	public var prefab : Swarm = null;
 	public var prefab : Swarm = null;
 	public var elements: Array<SwarmElement> = [];
 	public var elements: Array<SwarmElement> = [];
@@ -41,7 +42,6 @@ class SwarmObject extends h3d.scene.Object {
 	public var targetAngle: Float = 0.0;
 	public var targetAngle: Float = 0.0;
 
 
 	public var batch : h3d.scene.MeshBatch = null;
 	public var batch : h3d.scene.MeshBatch = null;
-	public var context : Context = null;
 
 
 	public var swarmElementTemplate: Object3D = null;
 	public var swarmElementTemplate: Object3D = null;
 
 
@@ -82,11 +82,14 @@ class SwarmObject extends h3d.scene.Object {
 			// if(baseEmitMat.isIdentityEpsilon(0.01))
 			// if(baseEmitMat.isIdentityEpsilon(0.01))
 			// 	baseEmitMat = null;
 			// 	baseEmitMat = null;
 
 
-			var template = swarmElementTemplate.makeInstance(context);
-			var mesh = Std.downcast(template.local3d, h3d.scene.Mesh);
+			var empty3d = new h3d.scene.Object();
+
+			var template = swarmElementTemplate.make(new ContextShared(empty3d));
+			var local3d = Object3D.getLocal3d(template);
+			var mesh = Std.downcast(local3d, h3d.scene.Mesh);
 			if( mesh == null ) {
 			if( mesh == null ) {
-				for( i in 0...template.local3d.numChildren ) {
-					mesh = Std.downcast(template.local3d.getChildAt(i), h3d.scene.Mesh);
+				for( i in 0...local3d.numChildren ) {
+					mesh = Std.downcast(local3d.getChildAt(i), h3d.scene.Mesh);
 					if( mesh != null ) {
 					if( mesh != null ) {
 						break;
 						break;
 					}
 					}
@@ -99,9 +102,7 @@ class SwarmObject extends h3d.scene.Object {
 				mesh.remove();
 				mesh.remove();
 			}
 			}
 
 
-			template.shared.contexts.remove(swarmElementTemplate);
-			template.local3d.remove();
-			template.local3d = null;
+			empty3d.remove();
 		}
 		}
 
 
 		if (meshPrimitive == null) {
 		if (meshPrimitive == null) {
@@ -121,11 +122,9 @@ class SwarmObject extends h3d.scene.Object {
 			batch.name = "emitter";
 			batch.name = "emitter";
 			batch.calcBounds = true;
 			batch.calcBounds = true;
 
 
-			var batchContext = context.clone(null);
-			batchContext.local3d = batch;
 			// Setup mats.
 			// Setup mats.
 			// Should we do this manually here or make a recursive makeInstance on the template?
 			// Should we do this manually here or make a recursive makeInstance on the template?
-			var materials = prefab.getAll(hrt.prefab.Material);
+			var materials = prefab.findAll(hrt.prefab.Material);
 			for(mat in materials) {
 			for(mat in materials) {
 
 
 				// Remove materials that are not directly parented to this Swarm
 				// Remove materials that are not directly parented to this Swarm
@@ -136,15 +135,14 @@ class SwarmObject extends h3d.scene.Object {
 
 
 				if (this.prefab == p) {
 				if (this.prefab == p) {
 					if(mat.enabled) {
 					if(mat.enabled) {
-						var ctx = mat.makeInstance(batchContext);
-						ctx.local3d = null;
+						@:privateAccess mat.makeInstance();
 					}
 					}
 				}
 				}
 			}
 			}
 
 
 			// Setup shaders
 			// Setup shaders
 			shaderAnims = [];
 			shaderAnims = [];
-			var shaders = prefab.getAll(hrt.prefab.Shader);
+			var shaders = prefab.findAll(hrt.prefab.Shader);
 			for( shader in shaders ) {
 			for( shader in shaders ) {
 				// Remove shaders that are not directly parented to this Swarm
 				// Remove shaders that are not directly parented to this Swarm
 				var p = shader.parent;
 				var p = shader.parent;
@@ -153,12 +151,11 @@ class SwarmObject extends h3d.scene.Object {
 				}
 				}
 				if (this.prefab == p) {
 				if (this.prefab == p) {
 					if( !shader.enabled ) continue;
 					if( !shader.enabled ) continue;
-					var shCtx = makeShaderInstance(shader, batchContext);
-					if( shCtx == null ) continue;
+					makeShaderInstance(shader);
 
 
-					shCtx.local3d = null; // Prevent shader.iterMaterials from adding our objet to the list incorectly
+					//shCtx.local3d = null; // Prevent shader.iterMaterials from adding our objet to the list incorectly
 
 
-					hrt.prefab.fx.BaseFX.getShaderAnims(shCtx, shader, shaderAnims, batch);
+					hrt.prefab.fx.BaseFX.BaseFXTools.getShaderAnims(shader, shaderAnims, batch);
 				}
 				}
 			}
 			}
 
 
@@ -169,15 +166,11 @@ class SwarmObject extends h3d.scene.Object {
 
 
 	}
 	}
 
 
-	function makeShaderInstance(prefab: hrt.prefab.Shader, ctx:Context):Context {
-		ctx = ctx.clone(prefab);
-		var shader = prefab.makeShader(ctx);
+	function makeShaderInstance(prefab: hrt.prefab.Shader) {
+		var shader = prefab.makeShader();
 		if( shader == null )
 		if( shader == null )
-			return ctx;
-		ctx.custom = shader;
-		prefab.updateInstance(ctx);
-		ctx.local3d = null;  // prevent ContextShared.getSelfObject from incorrectly reporting object
-		return ctx;
+			return;
+		prefab.updateInstance();
 	}
 	}
 
 
 	static var tmpVector = new h3d.Vector();
 	static var tmpVector = new h3d.Vector();
@@ -480,24 +473,16 @@ class Swarm extends Object3D {
 	@:s public var debugTargets : Bool = false;
 	@:s public var debugTargets : Bool = false;
 
 
 	// Override child creation
 	// Override child creation
-	override function make(ctx: Context) {
-		if( ctx == null ) {
-			ctx = new Context();
-			ctx.init();
-		}
-		ctx = makeInstance(ctx);
-		return ctx;
+	override function makeChild(p:Prefab) {
 	}
 	}
 
 
-	override function createObject(ctx:Context) {
-		var obj = new SwarmObject(ctx.local3d, this);
-		obj.context = ctx;
-		return obj;
+	override function makeObject(parent:h3d.scene.Object) {
+		return new SwarmObject(parent, this);
 	}
 	}
 
 
-	override function updateInstance( ctx: Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
-		var swarm : SwarmObject = cast ctx.local3d;
+	override function updateInstance(?propName : String) {
+		super.updateInstance(propName);
+		var swarm : SwarmObject = cast local3d;
 
 
 		var template : Object3D = cast children.find(
 		var template : Object3D = cast children.find(
 			c -> c.enabled &&
 			c -> c.enabled &&
@@ -511,11 +496,11 @@ class Swarm extends Object3D {
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "random", name : "Swarm" };
 		return { icon : "random", name : "Swarm" };
 	}
 	}
 
 
-	override public function edit(ctx:EditContext) {
+	override public function edit(ctx:hide.prefab.EditContext) {
 		super.edit(ctx);
 		super.edit(ctx);
 		var props = ctx.properties.add(new hide.Element('
 		var props = ctx.properties.add(new hide.Element('
 		<div class="group" name="Swarm Entities">
 		<div class="group" name="Swarm Entities">
@@ -572,5 +557,5 @@ class Swarm extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = hrt.prefab.Library.register("Swarm", Swarm);
+	static var _ = hrt.prefab.Prefab.register("Swarm", Swarm);
 }
 }

+ 0 - 7
hrt/prefab/import.hx

@@ -1,7 +0,0 @@
-package hrt.prefab;
-
-#if editor
-import hide.prefab.EditContext;
-import hide.prefab.HideProps;
-import hide.Element;
-#end

+ 10 - 14
hrt/prefab/l2d/Anim2D.hx

@@ -13,17 +13,17 @@ class Anim2D extends Object2D {
 
 
 	var tex : h3d.mat.Texture;
 	var tex : h3d.mat.Texture;
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 
 
-		var h2dAnim = (cast ctx.local2d : h2d.Anim);
+		var h2dAnim = (cast local2d : h2d.Anim);
 
 
 		if (propName == null || (propName == "src" || propName == "widthFrame" || propName == "heightFrame" || propName == "nbFrames")) {
 		if (propName == null || (propName == "src" || propName == "widthFrame" || propName == "heightFrame" || propName == "nbFrames")) {
 			if (tex != null) {
 			if (tex != null) {
 				tex = null;
 				tex = null;
 			}
 			}
 			if (src != null) {
 			if (src != null) {
-				tex = ctx.loadTexture(src);
+				tex = shared.loadTexture(src);
 				var t = h2d.Tile.fromTexture(tex);
 				var t = h2d.Tile.fromTexture(tex);
 				var tiles = [];
 				var tiles = [];
 				var nbFrameRow = Std.int(t.width / widthFrame);
 				var nbFrameRow = Std.int(t.width / widthFrame);
@@ -46,17 +46,13 @@ class Anim2D extends Object2D {
 		h2dAnim.blendMode = blendMode;
 		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;
+	override function makeObject(parent2d: h2d.Object) : h2d.Object {
+		var h2dAnim = new h2d.Anim([], fpsAnimation, parent2d);
+		return h2dAnim;
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		ctx.properties.add(new hide.Element('<div class="group" name="Frames">
 		ctx.properties.add(new hide.Element('<div class="group" name="Frames">
@@ -73,12 +69,12 @@ class Anim2D extends Object2D {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Anim2D" };
 		return { icon : "square", name : "Anim2D" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("anim2D", Anim2D);
+	static var _ = Prefab.register("anim2D", Anim2D);
 
 
 }
 }

+ 11 - 16
hrt/prefab/l2d/Atlas.hx

@@ -11,10 +11,10 @@ class Atlas extends Object2D {
 
 
 	var atlas : hxd.res.Atlas;
 	var atlas : hxd.res.Atlas;
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 
 
-		var h2dAnim = (cast ctx.local2d : h2d.Anim);
+		var h2dAnim = (cast local2d : h2d.Anim);
 		h2dAnim.smooth = true;
 		h2dAnim.smooth = true;
 
 
 		if (propName == null || propName == "src" || propName == "forcePivotCenter") {
 		if (propName == null || propName == "src" || propName == "forcePivotCenter") {
@@ -46,19 +46,14 @@ class Atlas extends Object2D {
 		#end
 		#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;
+	override function makeObject(parent2d:h2d.Object): h2d.Object {
+		var h2dAnim = new h2d.Anim([], fpsAnimation, parent2d);
+		return h2dAnim;
 	}
 	}
 
 
 	#if editor
 	#if editor
 
 
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
+	override function makeInteractive():h2d.Interactive {
 		if(local2d == null)
 		if(local2d == null)
 			return null;
 			return null;
 		var h2dAnim = cast(local2d, h2d.Anim);
 		var h2dAnim = cast(local2d, h2d.Anim);
@@ -71,7 +66,7 @@ class Atlas extends Object2D {
 		return int;
 		return int;
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
@@ -86,7 +81,7 @@ class Atlas extends Object2D {
 		if (this.src != null && this.src.length > 0) tfile.path = this.src;
 		if (this.src != null && this.src.length > 0) tfile.path = this.src;
 		tfile.onChange = function() {
 		tfile.onChange = function() {
 			this.src = tfile.path;
 			this.src = tfile.path;
-			updateInstance(ctx.getContext(this), "src");
+			updateInstance("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>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>Delay Start</dt><dd><input type="range" min="0" max="5" field="delayStart"/></dd>').appendTo(gr);
@@ -99,12 +94,12 @@ class Atlas extends Object2D {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Atlas" };
 		return { icon : "square", name : "Atlas" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("atlas", Atlas);
+	static var _ = Prefab.register("atlas", Atlas);
 
 
 }
 }

+ 11 - 16
hrt/prefab/l2d/Bitmap.hx

@@ -10,16 +10,16 @@ class Bitmap extends Object2D {
 
 
 	var tex : h3d.mat.Texture;
 	var tex : h3d.mat.Texture;
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		var bmp = (cast ctx.local2d : h2d.Bitmap);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
+		var bmp = (cast local2d : h2d.Bitmap);
 		bmp.visible = visible;
 		bmp.visible = visible;
 		if (propName == null || propName == "src") {
 		if (propName == null || propName == "src") {
 			if (tex != null) {
 			if (tex != null) {
 				tex = null;
 				tex = null;
 			}
 			}
 			if (src != null) {
 			if (src != null) {
-				tex = ctx.loadTexture(src);
+				tex = shared.loadTexture(src);
 				bmp.tile = h2d.Tile.fromTexture(this.tex);
 				bmp.tile = h2d.Tile.fromTexture(this.tex);
 			} else {
 			} else {
 				bmp.tile = h2d.Tile.fromColor(0xFF00FF,32,32,0.5);
 				bmp.tile = h2d.Tile.fromColor(0xFF00FF,32,32,0.5);
@@ -41,14 +41,10 @@ class Bitmap extends Object2D {
 		#end
 		#end
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var bmp = new h2d.Bitmap(null, ctx.local2d);
+	override function makeObject(parent2d:h2d.Object):h2d.Object {
+		var bmp = new h2d.Bitmap(null, parent2d);
 		bmp.smooth = true;
 		bmp.smooth = true;
-		ctx.local2d = bmp;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return bmp;
 	}
 	}
 
 
 	static public function getCenterRatio(dx : Float, dy : Float) {
 	static public function getCenterRatio(dx : Float, dy : Float) {
@@ -57,8 +53,7 @@ class Bitmap extends Object2D {
 
 
 	#if editor
 	#if editor
 
 
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
+	override function makeInteractive():h2d.Interactive {
 		if(local2d == null)
 		if(local2d == null)
 			return null;
 			return null;
 		var bmp = cast(local2d, h2d.Bitmap);
 		var bmp = cast(local2d, h2d.Bitmap);
@@ -70,7 +65,7 @@ class Bitmap extends Object2D {
 		return int;
 		return int;
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		ctx.properties.add(new hide.Element('<div class="group" name="Parameters">
 		ctx.properties.add(new hide.Element('<div class="group" name="Parameters">
@@ -84,12 +79,12 @@ class Bitmap extends Object2D {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Bitmap" };
 		return { icon : "square", name : "Bitmap" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("bitmap", Bitmap);
+	static var _ = Prefab.register("bitmap", Bitmap);
 
 
 }
 }

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

@@ -13,6 +13,8 @@ class Blur extends Prefab {
 
 
 	var pass : h3d.pass.Blur;
 	var pass : h3d.pass.Blur;
 
 
+	var bitmap : h2d.Bitmap;
+
 	public function makeFilter() {
 	public function makeFilter() {
 		var f = new h2d.filter.Blur(radius, gain, quality);
 		var f = new h2d.filter.Blur(radius, gain, quality);
 		f.linear = linear;
 		f.linear = linear;
@@ -32,38 +34,35 @@ class Blur extends Prefab {
 		return 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;
+	override function makeInstance() {
+		bitmap = new h2d.Bitmap(null, shared.current2d);
+		syncBitmap();
+		bitmap.visible = false;
 	}
 	}
 
 
-	function syncBitmap( bmp : h2d.Bitmap, ctx : Context ) {
+	function syncBitmap() {
 		var t;
 		var t;
 		if( image != null )
 		if( image != null )
-			t = h2d.Tile.fromTexture(ctx.loadTexture(image));
+			t = h2d.Tile.fromTexture(shared.loadTexture(image));
 		else {
 		else {
 			t = h2d.Tile.fromTexture(h3d.mat.Texture.genChecker(16));
 			t = h2d.Tile.fromTexture(h3d.mat.Texture.genChecker(16));
 			t.setSize(256, 256);
 			t.setSize(256, 256);
 		}
 		}
 		t.dx = -t.iwidth>>1;
 		t.dx = -t.iwidth>>1;
 		t.dy = -t.iheight>>1;
 		t.dy = -t.iheight>>1;
-		bmp.tile = t;
-		bmp.filter = makeFilter();
-		bmp.smooth = true;
-		bmp.tileWrap = image == null;
-		bmp.setScale(zoom);
+		bitmap.tile = t;
+		bitmap.filter = makeFilter();
+		bitmap.smooth = true;
+		bitmap.tileWrap = image == null;
+		bitmap.setScale(zoom);
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { name : "Blur", icon : "bullseye" };
 		return { name : "Blur", icon : "bullseye" };
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var e : hide.Element = null;
 		var e : hide.Element = null;
 		function sync( bmp : h2d.Bitmap ) {
 		function sync( bmp : h2d.Bitmap ) {
 			var k = @:privateAccess Std.downcast(bmp.filter, h2d.filter.Blur).pass.getKernelSize();
 			var k = @:privateAccess Std.downcast(bmp.filter, h2d.filter.Blur).pass.getKernelSize();
@@ -83,19 +82,14 @@ class Blur extends Prefab {
 				<dt>Display zoom</dt><dd><input type="range" min="1" max="8" step="1" field="zoom"/></dd>
 				<dt>Display zoom</dt><dd><input type="range" min="1" max="8" step="1" field="zoom"/></dd>
 			</dl>
 			</dl>
 		'),this,function(f) {
 		'),this,function(f) {
-			var ctx = ctx.getContext(this);
-			var bmp = cast(ctx.local2d, h2d.Bitmap);
-			syncBitmap(bmp, ctx);
-			sync(bmp);
+			sync(bitmap);
 		});
 		});
-		var lctx = ctx.getContext(this);
-		var bmp = cast(lctx.local2d, h2d.Bitmap);
-		bmp.visible = true;
-		ctx.cleanups.push(function() bmp.visible = false);
-		sync(bmp);
+		bitmap.visible = true;
+		ctx.cleanups.push(function() bitmap.visible = false);
+		sync(bitmap);
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("blur", Blur);
+	static var _ = Prefab.register("blur", Blur);
 
 
 }
 }

+ 15 - 19
hrt/prefab/l2d/Flow.hx

@@ -10,17 +10,13 @@ class Flow extends Object2D {
 	@:s var vAlign : Int = 0;
 	@:s var vAlign : Int = 0;
 	@:s var hAlign : Int = 0;
 	@:s var hAlign : Int = 0;
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		ctx.local2d = new h2d.Flow(ctx.local2d);
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
+	override function makeObject(parent2d: h2d.Object) : h2d.Object {
+		return new h2d.Flow(parent2d);
 	}
 	}
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		var flow = (cast ctx.local2d : h2d.Flow);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
+		var flow = (cast local2d : h2d.Flow);
 		if( height > 0 ) {
 		if( height > 0 ) {
 			flow.minHeight = flow.maxHeight = height;
 			flow.minHeight = flow.maxHeight = height;
 		} else {
 		} else {
@@ -51,7 +47,7 @@ class Flow extends Object2D {
 
 
 	#if editor
 	#if editor
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
@@ -79,19 +75,19 @@ class Flow extends Object2D {
 		leftAlign.on("click", function(e) {
 		leftAlign.on("click", function(e) {
 			hAlign = 0;
 			hAlign = 0;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "hAlign");
+			updateInstance("hAlign");
 		});
 		});
 		middleAlign.on("click", function(e) {
 		middleAlign.on("click", function(e) {
 			hAlign = 1;
 			hAlign = 1;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "hAlign");
+			updateInstance("hAlign");
 		});
 		});
 		rightAlign.on("click", function(e) {
 		rightAlign.on("click", function(e) {
 			hAlign = 2;
 			hAlign = 2;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "hAlign");
+			updateInstance("hAlign");
 		});
 		});
-		
+
 		new hide.Element('<dt>Vertical Align</dt>').appendTo(gr);
 		new hide.Element('<dt>Vertical Align</dt>').appendTo(gr);
 		var vElement = new hide.Element('<dd></dd>').appendTo(gr);
 		var vElement = new hide.Element('<dd></dd>').appendTo(gr);
 		var topAlign = new hide.Element('<input type="button" style="width: 50px" value="Top" /> ').appendTo(vElement);
 		var topAlign = new hide.Element('<input type="button" style="width: 50px" value="Top" /> ').appendTo(vElement);
@@ -113,17 +109,17 @@ class Flow extends Object2D {
 		topAlign.on("click", function(e) {
 		topAlign.on("click", function(e) {
 			vAlign = 0;
 			vAlign = 0;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "vAlign");
+			updateInstance("vAlign");
 		});
 		});
 		middleAlign.on("click", function(e) {
 		middleAlign.on("click", function(e) {
 			vAlign = 1;
 			vAlign = 1;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "vAlign");
+			updateInstance("vAlign");
 		});
 		});
 		rightAlign.on("click", function(e) {
 		rightAlign.on("click", function(e) {
 			vAlign = 2;
 			vAlign = 2;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "vAlign");
+			updateInstance("vAlign");
 		});
 		});
 		updateDisabled();
 		updateDisabled();
 
 
@@ -135,11 +131,11 @@ class Flow extends Object2D {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Flow" };
 		return { icon : "square", name : "Flow" };
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("flow", Flow);
+	static var _ = Prefab.register("flow", Flow);
 
 
 }
 }

+ 21 - 19
hrt/prefab/l2d/NoiseGenerator.hx

@@ -12,7 +12,7 @@ enum abstract RepeatMode(String) {
 	var None;
 	var None;
 }
 }
 
 
-class NoiseGenerator extends Prefab {
+class NoiseGenerator extends Object2D {
 
 
 	@:s public var seed : Int;
 	@:s public var seed : Int;
 
 
@@ -37,8 +37,8 @@ class NoiseGenerator extends Prefab {
 
 
 	var tex : h3d.mat.Texture;
 	var tex : h3d.mat.Texture;
 
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		seed = Std.random(100);
 		seed = Std.random(100);
 	}
 	}
 
 
@@ -112,27 +112,28 @@ class NoiseGenerator extends Prefab {
 		return t.sub(repeat == Both || repeat == X ? tex.width >> 1 : 0, repeat == Both || repeat == Y ? tex.height >> 1 : 0, tex.width, tex.height);
 		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]);
+	override function makeInstance() {
+		tex = new h3d.mat.Texture(size, size, [Target]);
 		updateTexture(tex);
 		updateTexture(tex);
-		ctx = ctx.clone(this);
-		var bmp = new h2d.Bitmap(makeTile(tex), ctx.local2d);
+		var bmp = new h2d.Bitmap(makeTile(tex), shared.current2d);
 		bmp.tileWrap = !tex.flags.has(IsNPOT);
 		bmp.tileWrap = !tex.flags.has(IsNPOT);
 		bmp.visible = false;
 		bmp.visible = false;
 		bmp.x = -size >> 1;
 		bmp.x = -size >> 1;
 		bmp.y = -size >> 1;
 		bmp.y = -size >> 1;
-		ctx.local2d = bmp;
-		ctx.cleanup = function() tex.dispose();
-		return ctx;
+		local2d = bmp;
+	}
+
+	function destroy() {
+		tex.dispose();
 	}
 	}
 
 
 	#if editor
 	#if editor
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "cloud", name : "Noise Generator" };
 		return { icon : "cloud", name : "Noise Generator" };
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var e = ctx.properties.add(new hide.Element('
 		var e = ctx.properties.add(new hide.Element('
 			<dl>
 			<dl>
 				<dt>Mode</dt><dd><select field="mode">
 				<dt>Mode</dt><dd><select field="mode">
@@ -183,7 +184,7 @@ class NoiseGenerator extends Prefab {
 				<dt>&nbsp;</dt><dd><input type="button" value="Download" name="dl"/></dd>
 				<dt>&nbsp;</dt><dd><input type="button" value="Download" name="dl"/></dd>
 			</dl>
 			</dl>
 		'),this,function(pname)  {
 		'),this,function(pname)  {
-			var bmp = cast(ctx.getContext(this).local2d, h2d.Bitmap);
+			var bmp = cast(local2d, h2d.Bitmap);
 			var tex = bmp.tile.getTexture();
 			var tex = bmp.tile.getTexture();
 			if( tex.width != size ) {
 			if( tex.width != size ) {
 				tex.resize(size, size);
 				tex.resize(size, size);
@@ -195,14 +196,15 @@ class NoiseGenerator extends Prefab {
 			updateTexture(tex);
 			updateTexture(tex);
 			ctx.onChange(this, pname);
 			ctx.onChange(this, pname);
 		});
 		});
-		var bmp = cast(ctx.getContext(this).local2d, h2d.Bitmap);
+		var bmp = cast(local2d, h2d.Bitmap);
+		var ide = hide.Ide.inst;
 		e.find("[name=dl]").click(function(_) {
 		e.find("[name=dl]").click(function(_) {
-			ctx.ide.chooseFileSave("noise.png", function(f) {
+			ide.chooseFileSave("noise.png", function(f) {
 				try {
 				try {
-					var data = cast(ctx.getContext(this).local2d, h2d.Bitmap).tile.getTexture().capturePixels().toPNG();
-					sys.io.File.saveBytes(ctx.ide.getPath(f), data);
+					var data = cast(local2d, h2d.Bitmap).tile.getTexture().capturePixels().toPNG();
+					sys.io.File.saveBytes(ide.getPath(f), data);
 				} catch( e : Dynamic ) {
 				} catch( e : Dynamic ) {
-					ctx.ide.error(e);
+					ide.error(e);
 				}
 				}
 			});
 			});
 		});
 		});
@@ -212,7 +214,7 @@ class NoiseGenerator extends Prefab {
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("noise", NoiseGenerator);
+	static var _ = Prefab.register("noise", NoiseGenerator);
 
 
 }
 }
 
 

+ 12 - 20
hrt/prefab/l2d/Particle2D.hx

@@ -118,10 +118,10 @@ class Particle2D extends Object2D {
 	@:s var initialBurstDelay : Float;
 	@:s var initialBurstDelay : Float;
 	@:s var burstDelay : Float;
 	@:s var burstDelay : Float;
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 
 
-		var particles2d = (cast ctx.local2d : Particles);
+		var particles2d = (cast local2d : Particles);
 
 
 		particles2d.visible = visible;
 		particles2d.visible = visible;
 		particles2d.isBurstEmit = this.isBurstEmit;
 		particles2d.isBurstEmit = this.isBurstEmit;
@@ -148,11 +148,8 @@ class Particle2D extends Object2D {
 		}
 		}
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var particle2d = new Particles(ctx.local2d);
-		ctx.local2d = particle2d;
-		ctx.local2d.name = name;
+	override function makeObject(parent2d:h2d.Object):h2d.Object {
+		var particle2d = new Particles(local2d);
 
 
 		var group = new ParticleGroup(particle2d);
 		var group = new ParticleGroup(particle2d);
 		particle2d.addGroup(group);
 		particle2d.addGroup(group);
@@ -162,8 +159,7 @@ class Particle2D extends Object2D {
 			paramsParticleGroup = group.save();
 			paramsParticleGroup = group.save();
 		group.rebuildOnChange = false;
 		group.rebuildOnChange = false;
 
 
-		updateInstance(ctx);
-		return ctx;
+		return particle2d;
 	}
 	}
 
 
 	#if editor
 	#if editor
@@ -176,8 +172,7 @@ class Particle2D extends Object2D {
 		{ name: "gravity", t: PFloat(), disp: "Gravity", 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;
+	override function makeInteractive():h2d.Interactive {
 		if(local2d == null)
 		if(local2d == null)
 			return null;
 			return null;
 		var particles2d = cast(local2d, h2d.Particles);
 		var particles2d = cast(local2d, h2d.Particles);
@@ -188,16 +183,14 @@ class Particle2D extends Object2D {
 		return int;
 		return int;
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var params = new hide.Element(hide.view.Particles2D.getParamsHTMLform());
 		var params = new hide.Element(hide.view.Particles2D.getParamsHTMLform());
 
 
-		var context = ctx.getContext(this);
-		if( context != null ) {
-			var particles2d = (cast context.local2d : Particles);
+		var particles2d = (cast local2d : Particles);
 			var group = @:privateAccess particles2d.groups[0];
 			var group = @:privateAccess particles2d.groups[0];
-			ctx.properties.add(new Element('
+			ctx.properties.add(new hide.Element('
 			<div class="content">
 			<div class="content">
 				<div class="group" name="Emit">
 				<div class="group" name="Emit">
 					<dt>Is burst emit</dt><dd><input type="checkbox" field="isBurstEmit"/></dd>
 					<dt>Is burst emit</dt><dd><input type="checkbox" field="isBurstEmit"/></dd>
@@ -218,14 +211,13 @@ class Particle2D extends Object2D {
 				ctx.onChange(this, pname);
 				ctx.onChange(this, pname);
 			});
 			});
 		}
 		}
-	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Particle2D" };
 		return { icon : "square", name : "Particle2D" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("particle2D", Particle2D);
+	static var _ = Prefab.register("particle2D", Particle2D);
 
 
 }
 }

+ 14 - 19
hrt/prefab/l2d/Text.hx

@@ -41,9 +41,9 @@ class Text extends Object2D {
 			blendMode = Alpha;
 			blendMode = Alpha;
 	}
 	}
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
-		var h2dText = (cast ctx.local2d : h2d.HtmlText);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
+		var h2dText = (cast local2d : h2d.HtmlText);
 		h2dText.visible = visible;
 		h2dText.visible = visible;
 		h2dText.textColor = color;
 		h2dText.textColor = color;
 		h2dText.maxWidth = maxWidth > 0 ? maxWidth : null;
 		h2dText.maxWidth = maxWidth > 0 ? maxWidth : null;
@@ -107,15 +107,11 @@ class Text extends Object2D {
 		#end
 		#end
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var h2dText = new h2d.HtmlText(hxd.res.DefaultFont.get(), ctx.local2d);
+	override function makeObject(parent2d:h2d.Object):h2d.Object {
+		var h2dText = new h2d.HtmlText(hxd.res.DefaultFont.get(), parent2d);
 		h2dText.text = "";
 		h2dText.text = "";
 		h2dText.smooth = true;
 		h2dText.smooth = true;
-		ctx.local2d = h2dText;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return h2dText;
 	}
 	}
 
 
 	public dynamic function loadFont() : h2d.Font {
 	public dynamic function loadFont() : h2d.Font {
@@ -137,8 +133,7 @@ class Text extends Object2D {
 
 
 	#if editor
 	#if editor
 
 
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
+	override function makeInteractive():h2d.Interactive {
 		if(local2d == null)
 		if(local2d == null)
 			return null;
 			return null;
 		var text = cast(local2d, h2d.Text);
 		var text = cast(local2d, h2d.Text);
@@ -149,7 +144,7 @@ class Text extends Object2D {
 		return int;
 		return int;
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
@@ -177,17 +172,17 @@ class Text extends Object2D {
 		leftAlign.on("click", function(e) {
 		leftAlign.on("click", function(e) {
 			align = 0;
 			align = 0;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		});
 		middleAlign.on("click", function(e) {
 		middleAlign.on("click", function(e) {
 			align = 1;
 			align = 1;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		});
 		rightAlign.on("click", function(e) {
 		rightAlign.on("click", function(e) {
 			align = 2;
 			align = 2;
 			updateDisabled();
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		});
 		updateDisabled();
 		updateDisabled();
 
 
@@ -199,7 +194,7 @@ class Text extends Object2D {
 		if (this.pathFont != null && this.pathFont.length > 0) tfile.path = this.pathFont;
 		if (this.pathFont != null && this.pathFont.length > 0) tfile.path = this.pathFont;
 		tfile.onChange = function() {
 		tfile.onChange = function() {
 			this.pathFont = tfile.path;
 			this.pathFont = tfile.path;
-			updateInstance(ctx.getContext(this), "src");
+			updateInstance("src");
 		}
 		}
 
 
 		new hide.Element('<dt>Color</dt><dd><input type="color" field="color" /></dd>').appendTo(gr);
 		new hide.Element('<dt>Color</dt><dd><input type="color" field="color" /></dd>').appendTo(gr);
@@ -246,12 +241,12 @@ class Text extends Object2D {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Text" };
 		return { icon : "square", name : "Text" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("text", Text);
+	static var _ = Prefab.register("text", Text);
 
 
 }
 }

+ 13 - 11
hrt/prefab/l3d/AnimSpeedControl.hx

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

+ 10 - 15
hrt/prefab/l3d/Box.hx

@@ -3,21 +3,19 @@ package hrt.prefab.l3d;
 class Box extends Object3D {
 class Box extends Object3D {
 
 
 
 
-	public function setColor(ctx: Context, color: Int) {
+	public function setColor(color: Int) {
 		#if editor
 		#if editor
-		if(ctx.local3d == null)
+		if(local3d == null)
 			return;
 			return;
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
+		var mesh = Std.downcast(local3d, h3d.scene.Mesh);
 		if(mesh != null) {
 		if(mesh != null) {
 			setDebugColor(color, mesh.material);
 			setDebugColor(color, mesh.material);
 		}
 		}
 		#end
 		#end
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-
-		var mesh = new h3d.scene.Mesh(h3d.prim.Cube.defaultUnitCube(), ctx.local3d);
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+		var mesh = new h3d.scene.Mesh(h3d.prim.Cube.defaultUnitCube(), parent3d);
 
 
 		#if editor
 		#if editor
 		setDebugColor(0x60ffffff, mesh.material);
 		setDebugColor(0x60ffffff, mesh.material);
@@ -28,10 +26,7 @@ class Box extends Object3D {
 		wire.material.shadows = false;
 		wire.material.shadows = false;
 		#end
 		#end
 
 
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return mesh;
 	}
 	}
 
 
 	#if editor
 	#if editor
@@ -45,8 +40,8 @@ class Box extends Object3D {
 			if(alpha != null)
 			if(alpha != null)
 				mat.removePass(alpha);
 				mat.removePass(alpha);
 			mat.mainPass.setPassName("default");
 			mat.mainPass.setPassName("default");
-		 	mat.mainPass.setBlendMode(None);
-		 	mat.mainPass.depthWrite = true;
+			 mat.mainPass.setBlendMode(None);
+			 mat.mainPass.depthWrite = true;
 			mat.mainPass.culling = None;
 			mat.mainPass.culling = None;
 		}
 		}
 		else {
 		else {
@@ -61,10 +56,10 @@ class Box extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Box" };
 		return { icon : "square", name : "Box" };
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("box", Box);
+	static var _ = Prefab.register("box", Box);
 }
 }

+ 34 - 34
hrt/prefab/l3d/Camera.hx

@@ -1,8 +1,8 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 import hrt.prefab.rfx.RendererFX;
 import hrt.prefab.rfx.RendererFX;
 import h3d.scene.Object;
 import h3d.scene.Object;
-import hrt.prefab.Context;
-import hrt.prefab.Library;
+
+// NOTE(ces) : Not Tested
 
 
 class CameraSyncObject extends h3d.scene.Object {
 class CameraSyncObject extends h3d.scene.Object {
 
 
@@ -36,13 +36,12 @@ class Camera extends Object3D {
 	var beforePreviewCam : h3d.Camera; // Used to save scene camera controller's values
 	var beforePreviewCam : h3d.Camera; // Used to save scene camera controller's values
 	#end
 	#end
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "camera";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 	}
 	}
 
 
 	var g : h3d.scene.Graphics;
 	var g : h3d.scene.Graphics;
-	function drawFrustum( ctx : Context ) {
+	function drawFrustum() {
 
 
 		if( !showFrustum ) {
 		if( !showFrustum ) {
 			if( g != null ) {
 			if( g != null ) {
@@ -53,7 +52,7 @@ class Camera extends Object3D {
 		}
 		}
 
 
 		if( g == null ) {
 		if( g == null ) {
-			g = new h3d.scene.Graphics(ctx.local3d);
+			g = new h3d.scene.Graphics(local3d);
 			g.name = "frustumDebug";
 			g.name = "frustumDebug";
 			g.material.mainPass.setPassName("overlay");
 			g.material.mainPass.setPassName("overlay");
 			g.ignoreBounds = true;
 			g.ignoreBounds = true;
@@ -104,22 +103,19 @@ class Camera extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function makeInstance( ctx : hrt.prefab.Context ) {
-		ctx = ctx.clone(this);
-		ctx.local3d = new CameraSyncObject(ctx.local3d);
-		obj = ctx.local3d;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+	override function makeObject(parent3d:Object):Object {
+		var cam = new CameraSyncObject(parent3d);
+		obj = cam;
+		return obj;
 	}
 	}
 
 
-	override function updateInstance( ctx : hrt.prefab.Context, ?p ) {
-		applyRFX(ctx);
-		super.updateInstance(ctx, p);
+	override function updateInstance( ?p ) {
+		applyRFX();
+		super.updateInstance(p);
 		#if editor
 		#if editor
-		drawFrustum(ctx);
+		drawFrustum();
 		#end
 		#end
-		var cso = Std.downcast(ctx.local3d, CameraSyncObject);
+		var cso = Std.downcast(local3d, CameraSyncObject);
 		if( cso != null ) {
 		if( cso != null ) {
 			cso.fovY = fovY;
 			cso.fovY = fovY;
 			cso.zFar = zFar;
 			cso.zFar = zFar;
@@ -172,13 +168,13 @@ class Camera extends Object3D {
 		c.zNear = zNear;
 		c.zNear = zNear;
 	}
 	}
 
 
-	function applyRFX(ctx : hrt.prefab.Context) {
-		if (ctx.local3d.getScene() == null) return;
-		var renderer = ctx.local3d.getScene().renderer;
+	function applyRFX() {
+		if (local3d.getScene() == null) return;
+		var renderer = local3d.getScene().renderer;
 		if (renderer == null) return;
 		if (renderer == null) return;
 		if (preview) {
 		if (preview) {
 
 
-			for ( effect in getAll(hrt.prefab.rfx.RendererFX) ) {
+			for ( effect in findAll(hrt.prefab.rfx.RendererFX) ) {
 				var prevEffect = renderer.getEffect(hrt.prefab.rfx.RendererFX);
 				var prevEffect = renderer.getEffect(hrt.prefab.rfx.RendererFX);
 				if ( prevEffect != null )
 				if ( prevEffect != null )
 					renderer.effects.remove(prevEffect);
 					renderer.effects.remove(prevEffect);
@@ -186,7 +182,7 @@ class Camera extends Object3D {
 			}
 			}
 		}
 		}
 		else {
 		else {
-			for ( effect in getAll(hrt.prefab.rfx.RendererFX) )
+			for ( effect in findAll(hrt.prefab.rfx.RendererFX) )
 				renderer.effects.remove( effect );
 				renderer.effects.remove( effect );
 		}
 		}
 	}
 	}
@@ -209,7 +205,7 @@ class Camera extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function setSelected( ctx : Context, b : Bool ) {
+	override function setSelected(b : Bool ) {
 		setEditModeButton();
 		setEditModeButton();
 		return false;
 		return false;
 	}
 	}
@@ -253,16 +249,17 @@ class Camera extends Object3D {
 			editModeButton.val(preview ? "Preview Mode : Enabled" : "Preview Mode : Disabled");
 			editModeButton.val(preview ? "Preview Mode : Enabled" : "Preview Mode : Disabled");
 			editModeButton.toggleClass("editModeEnabled", preview);
 			editModeButton.toggleClass("editModeEnabled", preview);
 		};
 		};
-		editModeButton.click(function(_) {
+
+		function onclick(e: js.jquery.Event) : Void {
 			preview = !preview;
 			preview = !preview;
 			setEditModeButton();
 			setEditModeButton();
 			var cam = ctx.scene.s3d.camera;
 			var cam = ctx.scene.s3d.camera;
 			var renderer = @:privateAccess ctx.scene.s3d.renderer;
 			var renderer = @:privateAccess ctx.scene.s3d.renderer;
 			if (preview) {
 			if (preview) {
 				beforePreviewCam = ctx.scene.s3d.camera.clone();
 				beforePreviewCam = ctx.scene.s3d.camera.clone();
-				updateInstance(ctx.getContext(this));
+				updateInstance();
 				applyTo(cam);
 				applyTo(cam);
-				for ( effect in getAll(hrt.prefab.rfx.RendererFX) ) {
+				for ( effect in findAll(hrt.prefab.rfx.RendererFX) ) {
 					var prevEffect = @:privateAccess renderer.getEffect(hrt.prefab.rfx.RendererFX);
 					var prevEffect = @:privateAccess renderer.getEffect(hrt.prefab.rfx.RendererFX);
 					if ( prevEffect != null )
 					if ( prevEffect != null )
 						renderer.effects.remove(prevEffect);
 						renderer.effects.remove(prevEffect);
@@ -270,10 +267,12 @@ class Camera extends Object3D {
 				}
 				}
 				ctx.scene.editor.cameraController.lockZPlanes = true;
 				ctx.scene.editor.cameraController.lockZPlanes = true;
 				ctx.scene.editor.cameraController.loadFromCamera();
 				ctx.scene.editor.cameraController.loadFromCamera();
-				renderer.effects.push(new hrt.prefab.rfx.Border(0.02, 0x0000ff, 0.5));
+				var border = new hrt.prefab.rfx.Border(null, null);
+				border.setParams(0.02, 0x0000ff, 0.5);
+				renderer.effects.push(border);
 			}
 			}
 			else {
 			else {
-				for ( effect in getAll(hrt.prefab.rfx.RendererFX) )
+				for ( effect in findAll(hrt.prefab.rfx.RendererFX) )
 					renderer.effects.remove( effect );
 					renderer.effects.remove( effect );
 				for ( effect in renderer.effects ) {
 				for ( effect in renderer.effects ) {
 					if ( Std.isOfType(effect, hrt.prefab.rfx.Border) ) {
 					if ( Std.isOfType(effect, hrt.prefab.rfx.Border) ) {
@@ -290,7 +289,7 @@ class Camera extends Object3D {
 					transform.rotate(angles.x, angles.y, angles.z);
 					transform.rotate(angles.x, angles.y, angles.z);
 					transform.translate(cam.pos.x, cam.pos.y, cam.pos.z);
 					transform.translate(cam.pos.x, cam.pos.y, cam.pos.z);
 
 
-					var parent = getParent(hrt.prefab.Object3D);
+					var parent = findParent(hrt.prefab.Object3D);
 					if ( parent != null ) {
 					if ( parent != null ) {
 						var invPos = new h3d.Matrix();
 						var invPos = new h3d.Matrix();
 						invPos._44 = 0;
 						invPos._44 = 0;
@@ -323,7 +322,8 @@ class Camera extends Object3D {
 					this.rotationZ = floatToStringPrecision(floatToStringPrecision(this.rotationZ));
 					this.rotationZ = floatToStringPrecision(floatToStringPrecision(this.rotationZ));
 				});
 				});
 			}
 			}
-		});
+		};
+		editModeButton.click(onclick);
 
 
 		var deprecationButton = props.find(".upgrade");
 		var deprecationButton = props.find(".upgrade");
 		deprecationButton.click(function(_) {
 		deprecationButton.click(function(_) {
@@ -343,7 +343,7 @@ class Camera extends Object3D {
 				transform.rotate(angles.x, angles.y, angles.z);
 				transform.rotate(angles.x, angles.y, angles.z);
 				transform.translate(cam.pos.x, cam.pos.y, cam.pos.z);
 				transform.translate(cam.pos.x, cam.pos.y, cam.pos.z);
 
 
-				var parent = getParent(hrt.prefab.Object3D);
+				var parent = findParent(hrt.prefab.Object3D);
 				if ( parent != null ) {
 				if ( parent != null ) {
 					var invPos = new h3d.Matrix();
 					var invPos = new h3d.Matrix();
 					invPos._44 = 0;
 					invPos._44 = 0;
@@ -375,6 +375,6 @@ class Camera extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("camera", Camera);
+	static var _ = Prefab.register("camera", Camera);
 
 
 }
 }

+ 10 - 12
hrt/prefab/l3d/Constraint.hx

@@ -16,24 +16,22 @@ class Constraint extends Prefab {
 		return srcObj;
 		return srcObj;
 	}
 	}
 
 
-	override function makeInstance( ctx : Context ) {
-		if(!enabled) return ctx;
-		var srcObj = ctx.locateObject(object);
-		var targetObj = ctx.locateObject(target);
+	override function makeInstance() {
+		var srcObj = locateObject(object);
+		var targetObj = locateObject(target);
 		if( srcObj != null && targetObj != null ){
 		if( srcObj != null && targetObj != null ){
 			srcObj.follow = targetObj;
 			srcObj.follow = targetObj;
 			srcObj.followPositionOnly = positionOnly;
 			srcObj.followPositionOnly = positionOnly;
 		}
 		}
-		return ctx;
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "lock", name : "Constraint" };
 		return { icon : "lock", name : "Constraint" };
 	}
 	}
 
 
-	override function edit(ctx:EditContext) {
-		var curObj = ctx.rootContext.locateObject(object);
+	override function edit(ctx:hide.prefab.EditContext) {
+		var curObj = getRoot().locateObject(object);
 		var props = ctx.properties.add(new hide.Element('
 		var props = ctx.properties.add(new hide.Element('
 			<dl>
 			<dl>
 				<dt title="Object to constraint">Object</dt><dd><select field="object"><option value="">-- Choose --</option></select>
 				<dt title="Object to constraint">Object</dt><dd><select field="object"><option value="">-- Choose --</option></select>
@@ -42,12 +40,12 @@ class Constraint extends Prefab {
 			</dl>
 			</dl>
 		'),this, function(_) {
 		'),this, function(_) {
 			if( curObj != null ) curObj.follow = null;
 			if( curObj != null ) curObj.follow = null;
-			makeInstance(ctx.rootContext);
-			curObj = ctx.rootContext.locateObject(object);
+			apply(shared.root3d);
+			curObj = getRoot().locateObject(object);
 		});
 		});
 
 
 		for( select in [props.find("[field=object]"), props.find("[field=target]")] ) {
 		for( select in [props.find("[field=object]"), props.find("[field=target]")] ) {
-			for( path in ctx.getNamedObjects() ) {
+			for( path in ctx.getNamedObjects(Object3D.getLocal3d(getRoot())) ) {
 				var parts = path.split(".");
 				var parts = path.split(".");
 				var opt = new hide.Element("<option>").attr("value", path).html([for( p in 1...parts.length ) "&nbsp; "].join("") + parts.pop());
 				var opt = new hide.Element("<option>").attr("value", path).html([for( p in 1...parts.length ) "&nbsp; "].join("") + parts.pop());
 				select.append(opt);
 				select.append(opt);
@@ -57,6 +55,6 @@ class Constraint extends Prefab {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("constraint", Constraint);
+	static var _ = Prefab.register("constraint", Constraint);
 
 
 }
 }

+ 42 - 38
hrt/prefab/l3d/Decal.hx

@@ -1,5 +1,7 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 
 
+// NOTE(ces) : Not Tested
+
 enum abstract DecalMode(String) {
 enum abstract DecalMode(String) {
 	var Default;
 	var Default;
 	var BeforeTonemapping;
 	var BeforeTonemapping;
@@ -29,20 +31,25 @@ class Decal extends Object3D {
 	@:s var normalFadeEnd : Float = 1;
 	@:s var normalFadeEnd : Float = 1;
 	@:s var refMatLib : String;
 	@:s var refMatLib : String;
 
 
-	override function save() {
+	override function save() : Dynamic {
 		var obj : Dynamic = super.save();
 		var obj : Dynamic = super.save();
 		if(blendMode != Alpha) obj.blendMode = blendMode.getIndex();
 		if(blendMode != Alpha) obj.blendMode = blendMode.getIndex();
 		return obj;
 		return obj;
 	}
 	}
 
 
+	override function copy( obj : Dynamic ) {
+		super.copy(obj);
+		blendMode = obj.blendMode;
+	}
+
 	override function load( obj : Dynamic ) {
 	override function load( obj : Dynamic ) {
 		super.load(obj);
 		super.load(obj);
-		blendMode = obj.blendMode != null ? h2d.BlendMode.createByIndex(obj.blendMode) : Alpha;
+		if( obj.blendMode != null )
+			blendMode = h2d.BlendMode.createByIndex(obj.blendMode);
 	}
 	}
 
 
-	override function makeInstance(ctx:Context) : Context {
-		ctx = ctx.clone(this);
-		var mesh = new h3d.scene.pbr.Decal(h3d.prim.Cube.defaultUnitCube(), ctx.local3d);
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		var mesh = new h3d.scene.pbr.Decal(h3d.prim.Cube.defaultUnitCube(), parent3d);
 
 
 		switch (renderMode) {
 		switch (renderMode) {
 			case Default, Terrain:
 			case Default, Terrain:
@@ -71,14 +78,11 @@ class Decal extends Object3D {
 		mesh.material.mainPass.depthTest = GreaterEqual;
 		mesh.material.mainPass.depthTest = GreaterEqual;
 		mesh.material.mainPass.culling = Front;
 		mesh.material.mainPass.culling = Front;
 		mesh.material.shadows = false;
 		mesh.material.shadows = false;
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return mesh;
 	}
 	}
 
 
-	public function updateRenderParams(ctx) {
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
+	public function updateRenderParams() {
+		var mesh = Std.downcast(local3d, h3d.scene.Mesh);
 
 
 		if (this.refMatLib != null && this.refMatLib != "") {
 		if (this.refMatLib != null && this.refMatLib != "") {
 			// If a decal reference a material in the material library, we only
 			// If a decal reference a material in the material library, we only
@@ -88,7 +92,7 @@ class Decal extends Object3D {
 			var refMatLibPath = this.refMatLib.substring(0, this.refMatLib.lastIndexOf("/"));
 			var refMatLibPath = this.refMatLib.substring(0, this.refMatLib.lastIndexOf("/"));
 			var refMatName = this.refMatLib.substring(this.refMatLib.lastIndexOf("/") + 1);
 			var refMatName = this.refMatLib.substring(this.refMatLib.lastIndexOf("/") + 1);
 
 
-			var prefabLib = hxd.res.Loader.currentInstance.load(refMatLibPath).toPrefab().load().clone(true);
+			var prefabLib = hxd.res.Loader.currentInstance.load(refMatLibPath).toPrefab().load();
 			var mat : Material = null;
 			var mat : Material = null;
 			for(c in prefabLib.children) {
 			for(c in prefabLib.children) {
 				if (c.name != refMatName)
 				if (c.name != refMatName)
@@ -129,8 +133,8 @@ class Decal extends Object3D {
 			case Default, Terrain:
 			case Default, Terrain:
 				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalPBR);
 				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalPBR);
 				if( shader != null ){
 				if( shader != null ){
-					shader.albedoTexture = albedoMap != null ? ctx.loadTexture(albedoMap) : null;
-					shader.normalTexture = normalMap != null ? ctx.loadTexture(normalMap) : null;
+					shader.albedoTexture = albedoMap != null ? shared.loadTexture(albedoMap) : null;
+					shader.normalTexture = normalMap != null ? shared.loadTexture(normalMap) : null;
 					if(shader.albedoTexture != null) shader.albedoTexture.wrap = Repeat;
 					if(shader.albedoTexture != null) shader.albedoTexture.wrap = Repeat;
 					if(shader.normalTexture != null) shader.normalTexture.wrap = Repeat;
 					if(shader.normalTexture != null) shader.normalTexture.wrap = Repeat;
 					shader.albedoStrength = albedoStrength;
 					shader.albedoStrength = albedoStrength;
@@ -142,7 +146,7 @@ class Decal extends Object3D {
 					shader.CENTERED = centered;
 					shader.CENTERED = centered;
 					commonSetup(shader);
 					commonSetup(shader);
 				}
 				}
-				var pbrTexture = pbrMap != null ? ctx.loadTexture(pbrMap) : null;
+				var pbrTexture = pbrMap != null ? shared.loadTexture(pbrMap) : null;
 				if( pbrTexture != null ) {
 				if( pbrTexture != null ) {
 					var propsTexture = mesh.material.mainPass.getShader(h3d.shader.pbr.PropsTexture);
 					var propsTexture = mesh.material.mainPass.getShader(h3d.shader.pbr.PropsTexture);
 					if( propsTexture == null )
 					if( propsTexture == null )
@@ -167,7 +171,7 @@ class Decal extends Object3D {
 			case BeforeTonemapping, AfterTonemapping:
 			case BeforeTonemapping, AfterTonemapping:
 				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalOverlay);
 				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalOverlay);
 				if( shader != null ){
 				if( shader != null ){
-					shader.colorTexture = albedoMap != null ? ctx.loadTexture(albedoMap) : null;
+					shader.colorTexture = albedoMap != null ? shared.loadTexture(albedoMap) : null;
 					if(shader.colorTexture != null) shader.colorTexture.wrap = Repeat;
 					if(shader.colorTexture != null) shader.colorTexture.wrap = Repeat;
 					shader.CENTERED = centered;
 					shader.CENTERED = centered;
 					shader.GAMMA_CORRECT = renderMode == BeforeTonemapping;
 					shader.GAMMA_CORRECT = renderMode == BeforeTonemapping;
@@ -178,19 +182,19 @@ class Decal extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		super.updateInstance(ctx,propName);
-		updateRenderParams(ctx);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
+		updateRenderParams();
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "paint-brush", name : "Decal" };
 		return { icon : "paint-brush", name : "Decal" };
 	}
 	}
 
 
-	override function setSelected( ctx : Context, b : Bool ) {
+	override function setSelected(b : Bool ) {
 		if( b ) {
 		if( b ) {
-			var obj = ctx.shared.getSelfObject(this);
+			var obj = local3d;
 			if(obj != null) {
 			if(obj != null) {
 				var wire = new h3d.scene.Box(0xFFFFFFFF,obj);
 				var wire = new h3d.scene.Box(0xFFFFFFFF,obj);
 				wire.name = "_highlight";
 				wire.name = "_highlight";
@@ -206,20 +210,20 @@ class Decal extends Object3D {
 				wireCenter.material.mainPass.depthTest = Always;
 				wireCenter.material.mainPass.depthTest = Always;
 			}
 			}
 		} else {
 		} else {
-			clearSelection( ctx );
+			clearSelection();
 		}
 		}
 		return true;
 		return true;
 	}
 	}
 
 
-	function clearSelection( ctx : Context ) {
-		var obj = ctx.shared.getSelfObject(this);
+	function clearSelection() {
+		var obj = local3d;
 		if(obj == null) return;
 		if(obj == null) return;
 		var objs = obj.findAll( o -> if(o.name == "_highlight") o else null );
 		var objs = obj.findAll( o -> if(o.name == "_highlight") o else null );
 		for( o in objs )
 		for( o in objs )
 			o.remove();
 			o.remove();
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var pbrParams = '<dt>Albedo</dt><dd><input type="texturepath" field="albedoMap"/>
 		var pbrParams = '<dt>Albedo</dt><dd><input type="texturepath" field="albedoMap"/>
@@ -281,49 +285,49 @@ class Decal extends Object3D {
 
 
 			function updateMatSelect() {
 			function updateMatSelect() {
 				matSelect.empty();
 				matSelect.empty();
-				new Element('<option value="">None</option>').appendTo(matSelect);
+				new hide.Element('<option value="">None</option>').appendTo(matSelect);
 
 
 				materials = ctx.scene.listMaterialFromLibrary(this.getAbsPath(), libSelect.val());
 				materials = ctx.scene.listMaterialFromLibrary(this.getAbsPath(), libSelect.val());
 
 
 				for (idx in 0...materials.length) {
 				for (idx in 0...materials.length) {
-					new Element('<option value="${materials[idx].path + "/" + materials[idx].mat.name}" ${(selectedMat == materials[idx].mat.name) ? 'selected' : ''}>${materials[idx].mat.name}</option>').appendTo(matSelect);
+					new hide.Element('<option value="${materials[idx].path + "/" + materials[idx].mat.name}" ${(selectedMat == materials[idx].mat.name) ? 'selected' : ''}>${materials[idx].mat.name}</option>').appendTo(matSelect);
 				}
 				}
 			}
 			}
 
 
 			function updateLibSelect() {
 			function updateLibSelect() {
 				libSelect.empty();
 				libSelect.empty();
-				new Element('<option value="">None</option>').appendTo(libSelect);
+				new hide.Element('<option value="">None</option>').appendTo(libSelect);
 
 
 				for (idx in 0...matLibs.length) {
 				for (idx in 0...matLibs.length) {
-					new Element('<option value="${matLibs[idx].name}" ${(selectedLib == matLibs[idx].path) ? 'selected' : ''}>${matLibs[idx].name}</option>');
+					new hide.Element('<option value="${matLibs[idx].name}" ${(selectedLib == matLibs[idx].path) ? 'selected' : ''}>${matLibs[idx].name}</option>');
 				}
 				}
 			}
 			}
 
 
 			function updateMat() {
 			function updateMat() {
-				var previousDecal = this.clone();
+				var previousData = this.serialize();
 				var mat = ctx.scene.findMat(materials, matSelect.val());
 				var mat = ctx.scene.findMat(materials, matSelect.val());
 				if ( mat != null ) {
 				if ( mat != null ) {
 					this.refMatLib = mat.path + "/" + mat.mat.name;
 					this.refMatLib = mat.path + "/" + mat.mat.name;
-					updateInstance(ctx.scene.editor.getContext(this));
+					updateInstance();
 					ctx.rebuildProperties();
 					ctx.rebuildProperties();
 				} else {
 				} else {
 					this.refMatLib = "";
 					this.refMatLib = "";
 				}
 				}
 
 
-				var newDecal = this.clone();
+				var newDecal = this.serialize();
 
 
 				ctx.properties.undo.change(Custom(function(undo) {
 				ctx.properties.undo.change(Custom(function(undo) {
 					if( undo ) {
 					if( undo ) {
-						this.load(previousDecal.saveData());
+						this.load(previousData);
 					}
 					}
 					else {
 					else {
-						this.load(newDecal.saveData());
+						this.load(newDecal);
 					}
 					}
 
 
 					updateLibSelect();
 					updateLibSelect();
 					updateMatSelect();
 					updateMatSelect();
 					ctx.rebuildProperties();
 					ctx.rebuildProperties();
-					updateInstance(ctx.scene.editor.getContext(this));
+					updateInstance();
 				}));
 				}));
 			}
 			}
 
 
@@ -384,7 +388,7 @@ class Decal extends Object3D {
 			</div>
 			</div>
 			'),this, function(pname) {
 			'),this, function(pname) {
 				if( pname == "renderMode" ) {
 				if( pname == "renderMode" ) {
-					clearSelection( ctx.rootContext );
+					clearSelection();
 					ctx.rebuildPrefab(this);
 					ctx.rebuildPrefab(this);
 					ctx.rebuildProperties();
 					ctx.rebuildProperties();
 				}
 				}
@@ -397,6 +401,6 @@ class Decal extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("advancedDecal", Decal);
+	static var _ = Prefab.register("advancedDecal", Decal);
 
 
 }
 }

+ 13 - 20
hrt/prefab/l3d/Environment.hx

@@ -16,11 +16,6 @@ class Environment extends Object3D {
 	@:s var configName : String;
 	@:s var configName : String;
 	var env : h3d.scene.pbr.Environment;
 	var env : h3d.scene.pbr.Environment;
 
 
-	public function new( ?parent ) {
-		super(parent);
-		type = "environment";
-	}
-
 	function loadFromBinary() {
 	function loadFromBinary() {
 		try {
 		try {
 			env.dispose();
 			env.dispose();
@@ -53,27 +48,25 @@ class Environment extends Object3D {
 		#end
 		#end
 	}
 	}
 
 
-	override function makeInstance( ctx : Context ) : Context {
-		super.makeInstance(ctx);
-		updateInstance(ctx);
-		return ctx;
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		return super.makeObject(parent3d);
 	}
 	}
 
 
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 
 
 		if( sourceMapPath == null )
 		if( sourceMapPath == null )
 			return;
 			return;
 
 
 		#if editor
 		#if editor
-		var sourceMap = ctx.loadTexture(sourceMapPath);
+		var sourceMap = shared.loadTexture(sourceMapPath);
 		if( sourceMap == null )
 		if( sourceMap == null )
 			return;
 			return;
 		if( sourceMap.flags.has(Loading) ) {
 		if( sourceMap.flags.has(Loading) ) {
 			haxe.Timer.delay(function() {
 			haxe.Timer.delay(function() {
-				ctx.setCurrent();
+				shared.scene.setCurrent();
 				if( h3d.Engine.getCurrent().driver == null ) return; // was disposed
 				if( h3d.Engine.getCurrent().driver == null ) return; // was disposed
-				updateInstance(ctx,propName);
+				updateInstance(propName);
 			},100);
 			},100);
 			return;
 			return;
 		}
 		}
@@ -106,12 +99,12 @@ class Environment extends Object3D {
 			env.dispose();
 			env.dispose();
 			env.specular = null;
 			env.specular = null;
 			env.diffuse = null;
 			env.diffuse = null;
-			env.source = ctx.loadTexture(sourceMapPath);
+			env.source = shared.loadTexture(sourceMapPath);
 			env.compute();
 			env.compute();
 			saveToBinary();
 			saveToBinary();
 		}
 		}
 
 
-		var scene = ctx.local3d.getScene();
+		var scene = local3d.getScene();
 		// Auto Apply on change
 		// Auto Apply on change
 		if( scene != null )
 		if( scene != null )
 			applyToRenderer(scene.renderer);
 			applyToRenderer(scene.renderer);
@@ -125,11 +118,11 @@ class Environment extends Object3D {
 
 
 	#if editor
 	#if editor
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "sun-o", name : "Environment" };
 		return { icon : "sun-o", name : "Environment" };
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		// super.edit(ctx);
 		// super.edit(ctx);
 
 
 		var props = new hide.Element('
 		var props = new hide.Element('
@@ -162,7 +155,7 @@ class Environment extends Object3D {
 
 
 		var applyButton = props.find(".apply");
 		var applyButton = props.find(".apply");
 		applyButton.click(function(_) {
 		applyButton.click(function(_) {
-			applyToRenderer(ctx.rootContext.local3d.getScene().renderer);
+			applyToRenderer(findFirstLocal3d().getScene().renderer);
 		});
 		});
 
 
 		props.find(".compute").click(function(_) {
 		props.find(".compute").click(function(_) {
@@ -184,5 +177,5 @@ class Environment extends Object3D {
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("environment", Environment);
+	static var _ = Prefab.register("environment", Environment);
 }
 }

+ 17 - 17
hrt/prefab/l3d/GameController.hx

@@ -1,5 +1,7 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 
 
+// NOTE(ces) : Not Tested
+
 class GameController extends Object3D {
 class GameController extends Object3D {
 
 
 	@:s public var moveSpeed : Float = 1.;
 	@:s public var moveSpeed : Float = 1.;
@@ -19,13 +21,14 @@ class GameController extends Object3D {
 
 
 	#if editor
 	#if editor
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = super.makeInstance(ctx);
-		ctx.local3d.ignoreParentTransform = true;
-		return ctx;
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		var local3d = super.makeObject(parent3d);
+		local3d.ignoreParentTransform = true;
+		return local3d;
 	}
 	}
 
 
-	override function edit(ctx:EditContext) {
+
+	override function edit(ctx:hide.prefab.EditContext) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		ctx.properties.add(new hide.Element('
 		ctx.properties.add(new hide.Element('
@@ -58,18 +61,17 @@ class GameController extends Object3D {
 		'),this);
 		'),this);
 
 
 		var active = false;
 		var active = false;
-		var lctx = ctx.getContext(this);
-		var obj = lctx.local3d;
+		var obj = local3d;
 		var camSave = null;
 		var camSave = null;
 		var dummy : h3d.scene.Object = null;
 		var dummy : h3d.scene.Object = null;
-		var cam = ctx.scene.s3d.camera;
+		var cam = local3d.getScene().camera;
 		var camRot : h3d.Vector4 = null;
 		var camRot : h3d.Vector4 = null;
 		var startCamRot : h3d.Vector4 = null;
 		var startCamRot : h3d.Vector4 = null;
 		var zSpeed = 0.;
 		var zSpeed = 0.;
 		var startJumpTime = 1e9;
 		var startJumpTime = 1e9;
 
 
 		function selectRec( p : Prefab, b : Bool ) {
 		function selectRec( p : Prefab, b : Bool ) {
-			if( !p.setSelected(ctx.getContext(p), b) )
+			if( !p.setSelected(b) )
 				return;
 				return;
 			for( c in p.children )
 			for( c in p.children )
 				selectRec(c, b);
 				selectRec(c, b);
@@ -94,21 +96,19 @@ class GameController extends Object3D {
 		var baseZ = obj.z;
 		var baseZ = obj.z;
 
 
 		function playAnim( anim : String ) {
 		function playAnim( anim : String ) {
-			for( o in getAll(Model,true) ) {
+			for( o in findAll(Model,true) ) {
 				if( o.source == null ) continue;
 				if( o.source == null ) continue;
-				var octx = ctx.getContext(o);
-				if( octx == null ) continue;
 
 
-				if( currentAnim.get(octx.local3d) == anim )
+				if( currentAnim.get(local3d) == anim )
 					continue;
 					continue;
 
 
 				var animList = try ctx.scene.listAnims(o.source) catch(e: Dynamic) [];
 				var animList = try ctx.scene.listAnims(o.source) catch(e: Dynamic) [];
 				for( a2 in animList ) {
 				for( a2 in animList ) {
 					if( ctx.scene.animationName(a2).toLowerCase() == anim.toLowerCase() ) {
 					if( ctx.scene.animationName(a2).toLowerCase() == anim.toLowerCase() ) {
-						octx.local3d.playAnimation(octx.loadAnimation(a2));
+						local3d.playAnimation(shared.loadAnimation(a2));
 						if( animSmooth > 0 )
 						if( animSmooth > 0 )
-							octx.local3d.switchToAnimation(new h3d.anim.SmoothTarget(octx.local3d.currentAnimation,animSmooth));
-						currentAnim.set(octx.local3d, anim);
+							local3d.switchToAnimation(new h3d.anim.SmoothTarget(local3d.currentAnimation,animSmooth));
+						currentAnim.set(local3d, anim);
 						break;
 						break;
 					}
 					}
 				}
 				}
@@ -229,6 +229,6 @@ class GameController extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("gamectrl", GameController);
+	static var _ = Prefab.register("gamectrl", GameController);
 
 
 }
 }

+ 29 - 33
hrt/prefab/l3d/HeightMap.hx

@@ -1,5 +1,7 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 
 
+// NOTE(ces) : Not Tested
+
 enum abstract HeightMaPTexturePathKind(String) {
 enum abstract HeightMaPTexturePathKind(String) {
 	var Albedo = "albedo";
 	var Albedo = "albedo";
 	var Height = "height";
 	var Height = "height";
@@ -623,11 +625,10 @@ class HeightMap extends Object3D {
 	@:s var albedoRoughness : Float = 0.;
 	@:s var albedoRoughness : Float = 0.;
 
 
 	// todo : instead of storing the context, we should find a way to have a texture loader
 	// 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.Vector4>;
 	var albedoProps : Array<h3d.Vector4>;
 	var texArrayCache : Map<HeightMaPTexturePathKind, { texture : h3d.mat.TextureArray, indexes : Array<Int> }>;
 	var texArrayCache : Map<HeightMaPTexturePathKind, { texture : h3d.mat.TextureArray, indexes : Array<Int> }>;
 
 
-	override function save():{} {
+	override function save():Dynamic {
 		var o : Dynamic = super.save();
 		var o : Dynamic = super.save();
 		o.textures = [for( t in textures ) {
 		o.textures = [for( t in textures ) {
 			var v : Dynamic = { path : t.path, kind : t.kind };
 			var v : Dynamic = { path : t.path, kind : t.kind };
@@ -645,6 +646,12 @@ class HeightMap extends Object3D {
 		textures = [for( o in (obj.textures:Array<Dynamic>) ) { path : o.path, kind : o.kind, enable : o.enable == null ? true : o.enable, props : o.props }];
 		textures = [for( o in (obj.textures:Array<Dynamic>) ) { path : o.path, kind : o.kind, enable : o.enable == null ? true : o.enable, props : o.props }];
 	}
 	}
 
 
+	override function copy(o:Prefab) {
+		super.copy(o);
+		var p : HeightMap = cast o;
+		this.textures = p.textures;
+	}
+
 	function getAlbedoProps() : Array<h3d.Vector4> {
 	function getAlbedoProps() : Array<h3d.Vector4> {
 		if( albedoProps != null )
 		if( albedoProps != null )
 			return albedoProps;
 			return albedoProps;
@@ -685,7 +692,7 @@ class HeightMap extends Object3D {
 		return h;
 		return h;
 	}
 	}
 
 
-	override function localRayIntersection(ctx:Context, ray:h3d.col.Ray):Float {
+	override function localRayIntersection(ray:h3d.col.Ray):Float {
 		if( ray.lz > 0 )
 		if( ray.lz > 0 )
 			return -1; // only from top
 			return -1; // only from top
 		if( ray.lx == 0 && ray.ly == 0 ) {
 		if( ray.lx == 0 && ray.ly == 0 ) {
@@ -703,7 +710,7 @@ class HeightMap extends Object3D {
 		if( pt.z < minZ )
 		if( pt.z < minZ )
 			return -1;
 			return -1;
 
 
-		var prim = @:privateAccess cast(ctx.local3d, HeightMapMesh).grid;
+		var prim = @:privateAccess cast(local3d, HeightMapMesh).grid;
 		var m = hxd.Math.min(prim.cellWidth, prim.cellHeight) * 0.5;
 		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 curX = -1, curY = -1, curMap = null, offX = 0., offY = 0., cw = 0., ch = 0.;
 		var prevH = pt.z;
 		var prevH = pt.z;
@@ -794,7 +801,7 @@ class HeightMap extends Object3D {
 			#end
 			#end
 			if( b ) {
 			if( b ) {
 				var path = resolveTexturePath(t.path,tx,ty);
 				var path = resolveTexturePath(t.path,tx,ty);
-				tl.push(loadTexture(path));
+				tl.push(shared.loadTexture(path));
 			}
 			}
 		}
 		}
 		return tl;
 		return tl;
@@ -822,7 +829,7 @@ class HeightMap extends Object3D {
 					var path = new haxe.io.Path(t.path);
 					var path = new haxe.io.Path(t.path);
 					path.file = path.file.split("_Albedo").join("");
 					path.file = path.file.split("_Albedo").join("");
 					path.file += "_Normal";
 					path.file += "_Normal";
-					tl.push(loadTexture(path.toString()));
+					tl.push(shared.loadTexture(path.toString()));
 				}
 				}
 			tl;
 			tl;
 		default: throw "assert";
 		default: throw "assert";
@@ -901,21 +908,12 @@ class HeightMap extends Object3D {
 		return arr;
 		return arr;
 	}
 	}
 
 
-	function loadTexture( path : String ) {
-		return storedCtx.shared.loadTexture(path, false);
-	}
-
-	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 makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		var mesh = new HeightMapMesh(this, parent3d);
+		return mesh;
 	}
 	}
 
 
-	override function updateInstance( ctx : Context, ?propName : String ) {
+	override function updateInstance( ?propName : String ) {
 
 
 		#if editor
 		#if editor
 		if( (propName == "albedoTiling" || propName == "albedoColorGamma") && albedoProps != null ) {
 		if( (propName == "albedoTiling" || propName == "albedoColorGamma") && albedoProps != null ) {
@@ -923,20 +921,19 @@ class HeightMap extends Object3D {
 			return;
 			return;
 		}
 		}
 		if (view == null) {
 		if (view == null) {
-			var shared = Std.downcast(ctx.shared, hide.prefab.ContextShared);
-			if (shared != null && shared.editor != null)
-				view = shared.editor.view;
+			if (shared != null)
+				view = shared.scene.editor.view;
 		}
 		}
 		#end
 		#end
 
 
 		albedoProps = null;
 		albedoProps = null;
 		cleanCache();
 		cleanCache();
-		super.updateInstance(ctx, propName);
+		super.updateInstance(propName);
 
 
 		for( t in tilesCache )
 		for( t in tilesCache )
 			t.remove();
 			t.remove();
 		tilesCache = new Map();
 		tilesCache = new Map();
-		var mesh = cast(ctx.local3d,HeightMapMesh);
+		var mesh = cast(local3d,HeightMapMesh);
 		mesh.init();
 		mesh.init();
 	}
 	}
 
 
@@ -946,11 +943,11 @@ class HeightMap extends Object3D {
 
 
 	#if editor
 	#if editor
 
 
-	override function setSelected(ctx:Context, b:Bool):Bool {
+	override function setSelected(b:Bool):Bool {
 		return true;
 		return true;
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "industry", name : "HeightMap", isGround : true };
 		return { icon : "industry", name : "HeightMap", isGround : true };
 	}
 	}
 
 
@@ -963,9 +960,8 @@ class HeightMap extends Object3D {
 		albedoProps = prev;
 		albedoProps = prev;
 	}
 	}
 
 
-	override function edit(ectx:EditContext) {
+	override function edit(ectx:hide.prefab.EditContext) {
 		super.edit(ectx);
 		super.edit(ectx);
-		var ctx = ectx.getContext(this);
 		var hasSplat = false;
 		var hasSplat = false;
 		for( t in textures )
 		for( t in textures )
 			if( t.kind == SplatMap ) {
 			if( t.kind == SplatMap ) {
@@ -1020,7 +1016,7 @@ class HeightMap extends Object3D {
 		');
 		');
 
 
 		var list = props.find("ul#tex");
 		var list = props.find("ul#tex");
-		ectx.properties.add(props,this, (_) -> updateInstance(ctx));
+		ectx.properties.add(props,this, (_) -> updateInstance());
 		for( tex in textures ) {
 		for( tex in textures ) {
 			var prevTex = tex.path;
 			var prevTex = tex.path;
 			var e = new hide.Element('<li style="position:relative">
 			var e = new hide.Element('<li style="position:relative">
@@ -1044,14 +1040,14 @@ class HeightMap extends Object3D {
 				textures.remove(tex);
 				textures.remove(tex);
 				textures.insert(index-1, tex);
 				textures.insert(index-1, tex);
 				ectx.rebuildProperties();
 				ectx.rebuildProperties();
-				updateInstance(ctx);
+				updateInstance();
 			});
 			});
 			e.find(".down").click(function(_) {
 			e.find(".down").click(function(_) {
 				var index = textures.indexOf(tex);
 				var index = textures.indexOf(tex);
 				textures.remove(tex);
 				textures.remove(tex);
 				textures.insert(index+1, tex);
 				textures.insert(index+1, tex);
 				ectx.rebuildProperties();
 				ectx.rebuildProperties();
-				updateInstance(ctx);
+				updateInstance();
 			});
 			});
 			e.appendTo(list);
 			e.appendTo(list);
 			ectx.properties.build(e, tex, (pname) -> {
 			ectx.properties.build(e, tex, (pname) -> {
@@ -1078,7 +1074,7 @@ class HeightMap extends Object3D {
 					textures.remove(tex);
 					textures.remove(tex);
 					ectx.rebuildProperties();
 					ectx.rebuildProperties();
 				}
 				}
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 			});
 			if( tex.props != null ) {
 			if( tex.props != null ) {
 				var e = new hide.Element('<li style="position:relative">
 				var e = new hide.Element('<li style="position:relative">
@@ -1109,7 +1105,7 @@ class HeightMap extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("heightmap", HeightMap);
+	static var _ = Prefab.register("heightmap", HeightMap);
 
 
 }
 }
 
 

+ 35 - 24
hrt/prefab/l3d/Instance.hx

@@ -3,47 +3,56 @@ using Lambda;
 
 
 class Instance extends Object3D {
 class Instance extends Object3D {
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "instance";
+	var instance : Prefab;
+	var model : h3d.scene.Object;
+	var icon : h2d.Object;
+
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		props = {};
 		props = {};
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function makeInstance(ctx:Context):Context {
-		var ctx = super.makeInstance(ctx);
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+
 		var kind = getRefSheet(this);
 		var kind = getRefSheet(this);
 		var unknown = kind == null || kind.idx == null;
 		var unknown = kind == null || kind.idx == null;
 
 
 		var modelPath = unknown ? null : findModelPath(kind.sheet, kind.idx.obj);
 		var modelPath = unknown ? null : findModelPath(kind.sheet, kind.idx.obj);
 		if(modelPath != null) {
 		if(modelPath != null) {
 			try {
 			try {
-				if(hrt.prefab.Library.getPrefabType(modelPath) != null) {
-					var ref = ctx.shared.loadPrefab(modelPath);
+				if(hrt.prefab.Prefab.getPrefabType(modelPath) != null) {
+					var ref = hxd.res.Loader.currentInstance.load(modelPath).to(hrt.prefab.Resource).load();
 					if(ref != null) {
 					if(ref != null) {
-						var prevShared = ctx.shared;
-						ctx.shared = ctx.shared.cloneRef(this, modelPath);
-						ref.make(ctx);
-						ctx.shared = prevShared;
+						var sh = new hrt.prefab.ContextShared(findFirstLocal2d(), parent3d);
+						sh.currentPath = source;
+						sh.parentPrefab = this;
+						sh.customMake = this.shared.customMake;
+						#if editor
+						ref.setEditor(shared.editor);
+						#end
+
+						instance = ref.make(sh);
+						return instance.findFirstLocal3d();
 					}
 					}
 				}
 				}
 				else {
 				else {
-					var obj = ctx.loadModel(modelPath);
-					obj.name = name;
-					ctx.local3d.addChild(obj);
+					model = shared.loadModel(modelPath);
+					model.name = name;
+					return model;
 				}
 				}
 			} catch( e : hxd.res.NotFound ) {
 			} catch( e : hxd.res.NotFound ) {
-				ctx.shared.onError(e);
+				shared.onError(e);
 			}
 			}
 		}
 		}
-		return ctx;
+        return new h3d.scene.Object();
 	}
 	}
 
 
-	override function makeInteractive(ctx:Context):hxd.SceneEvents.Interactive {
-		var int = super.makeInteractive(ctx);
+	override function makeInteractive():hxd.SceneEvents.Interactive {
+		var int = super.makeInteractive();
 		if( int == null ) {
 		if( int == null ) {
 			// no meshes ? do we have an icon instead...
 			// no meshes ? do we have an icon instead...
-			var follow = Std.downcast(ctx.local2d, h2d.ObjectFollower);
+			var follow = Std.downcast(findFirstLocal2d(), h2d.ObjectFollower);
 			if( follow != null ) {
 			if( follow != null ) {
 				var bmp = Std.downcast(follow.getChildAt(0), h2d.Bitmap);
 				var bmp = Std.downcast(follow.getChildAt(0), h2d.Bitmap);
 				if( bmp != null ) {
 				if( bmp != null ) {
@@ -57,7 +66,9 @@ class Instance extends Object3D {
 		return int;
 		return int;
 	}
 	}
 
 
-	override function removeInstance(ctx:Context):Bool {
+	// TODO(ces) restore
+
+	/*override function removeInstance():Bool {
 		if(!super.removeInstance(ctx))
 		if(!super.removeInstance(ctx))
 			return false;
 			return false;
 		if(ctx.local2d != null ) {
 		if(ctx.local2d != null ) {
@@ -71,7 +82,7 @@ class Instance extends Object3D {
 			if( ctx.local2d != (pctx == null ? ctx.shared.root2d : pctx.local2d) ) ctx.local2d.remove();
 			if( ctx.local2d != (pctx == null ? ctx.shared.root2d : pctx.local2d) ) ctx.local2d.remove();
 		}
 		}
 		return true;
 		return true;
-	}
+	}*/
 
 
 	// ---- statics
 	// ---- statics
 
 
@@ -128,7 +139,7 @@ class Instance extends Object3D {
 		function filter(f: String) {
 		function filter(f: String) {
 			if(f != null) {
 			if(f != null) {
 				var lower = f.toLowerCase();
 				var lower = f.toLowerCase();
-				if(StringTools.endsWith(lower, ".fbx") || hrt.prefab.Library.getPrefabType(lower) != null)
+				if(StringTools.endsWith(lower, ".fbx") || hrt.prefab.Prefab.getPrefabType(lower) != null)
 					return f;
 					return f;
 			}
 			}
 			return null;
 			return null;
@@ -155,10 +166,10 @@ class Instance extends Object3D {
 		return path;
 		return path;
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "circle", name : "Instance" };
 		return { icon : "circle", name : "Instance" };
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("instance", Instance);
+	static var _ = Prefab.register("instance", Instance);
 }
 }

+ 28 - 33
hrt/prefab/l3d/Layers2D.hx

@@ -1,5 +1,7 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 
 
+// NOTE(ces) : Not Tested
+
 typedef Layer2DValue = {
 typedef Layer2DValue = {
 	index	: Int,
 	index	: Int,
 	name 	: String,
 	name 	: String,
@@ -92,6 +94,7 @@ class LayerView2DRFXShader extends h3d.shader.ScreenShader {
 	}
 	}
 }
 }
 
 
+@:access(h3d.scene.Renderer)
 class Layer2DRFX extends hrt.prefab.rfx.RendererFX {
 class Layer2DRFX extends hrt.prefab.rfx.RendererFX {
 
 
 	public var pass = new h3d.pass.ScreenFx(new LayerView2DRFXShader());
 	public var pass = new h3d.pass.ScreenFx(new LayerView2DRFXShader());
@@ -155,7 +158,6 @@ class Layers2D extends hrt.prefab.Object3D {
 	@:s public var keepVisible : Bool = false;
 	@:s public var keepVisible : Bool = false;
 
 
 	#if editor
 	#if editor
-	var storedCtx : hrt.prefab.Context;
 
 
 	var currentPixels : hxd.Pixels = null;
 	var currentPixels : hxd.Pixels = null;
 	var currentTexture : h3d.mat.Texture = null;
 	var currentTexture : h3d.mat.Texture = null;
@@ -188,32 +190,29 @@ class Layers2D extends hrt.prefab.Object3D {
 	#end
 	#end
 
 
 	#if editor
 	#if editor
-	override function save() : {} {
-		var o : Dynamic = super.save();
+	override function save() : Dynamic {
+		var obj = super.save();
 
 
 		for ( l in layers ) {
 		for ( l in layers ) {
 			var pixels = layerTextures.get(l.name);
 			var pixels = layerTextures.get(l.name);
 			if ( pixels != null ) {
 			if ( pixels != null ) {
-				var contextShared = storedCtx.shared;
-				var path = new haxe.io.Path(contextShared.currentPath);
+				var path = new haxe.io.Path(shared.currentPath);
 				path.ext = "dat";
 				path.ext = "dat";
 				var fileName = "layer_" + l.name;
 				var fileName = "layer_" + l.name;
-				contextShared.saveTexture(fileName, pixels.toPNG(), path.toString() + "/" + this.name, "png");
+				shared.saveTexture(fileName, pixels.toPNG(), path.toString() + "/" + this.name, "png");
 			}
 			}
 		}
 		}
 
 
-		return o;
+		return obj;
 	}
 	}
 	#end
 	#end
 
 
-	override function makeInstance( ctx : hrt.prefab.Context ) : hrt.prefab.Context {
-		ctx = super.makeInstance(ctx);
-		#if editor
-		storedCtx = ctx;
-		#end
+
+	override function makeInstance(){
+		super.makeInstance();
 
 
 		for ( l in layers ) {
 		for ( l in layers ) {
-			var path = new haxe.io.Path(ctx.shared.currentPath);
+			var path = new haxe.io.Path(shared.currentPath);
 			path.ext = "dat";
 			path.ext = "dat";
 			var datDir = path.toString();
 			var datDir = path.toString();
 			var fileName = "layer_" + l.name + ".png";
 			var fileName = "layer_" + l.name + ".png";
@@ -225,7 +224,6 @@ class Layers2D extends hrt.prefab.Object3D {
 			if ( pixels != null )
 			if ( pixels != null )
 				layerTextures.set(l.name, pixels);
 				layerTextures.set(l.name, pixels);
 		}
 		}
-		return ctx;
 	}
 	}
 
 
 	function loadPixels(path : String) {
 	function loadPixels(path : String) {
@@ -285,7 +283,7 @@ class Layers2D extends hrt.prefab.Object3D {
 			return;
 			return;
 		if ( b ) {
 		if ( b ) {
 			if ( rfx == null ) {
 			if ( rfx == null ) {
-				rfx = new Layer2DRFX();
+				rfx = new Layer2DRFX(null, null);
 				var renderer = Std.downcast(ectx.scene.s3d.renderer, h3d.scene.pbr.Renderer);
 				var renderer = Std.downcast(ectx.scene.s3d.renderer, h3d.scene.pbr.Renderer);
 				renderer.effects.push(rfx);
 				renderer.effects.push(rfx);
 			}
 			}
@@ -296,12 +294,12 @@ class Layers2D extends hrt.prefab.Object3D {
 		}
 		}
 	}
 	}
 
 
-	function updateVisuals( ctx : hrt.prefab.Context ) {
+	function updateVisuals() {
 		if ( rfx != null ) {
 		if ( rfx != null ) {
 			var sh : LayerView2DRFXShader = cast rfx.pass.shader;
 			var sh : LayerView2DRFXShader = cast rfx.pass.shader;
 			if( collideMap == null || collideMap.isDisposed() ) {
 			if( collideMap == null || collideMap.isDisposed() ) {
 				if ( collidePath != null ) {
 				if ( collidePath != null ) {
-					collideMap = ctx.loadTexture(collidePath);
+					collideMap = shared.loadTexture(collidePath);
 					collideMap.filter = Nearest;
 					collideMap.filter = Nearest;
 					collidePixels = loadPixels(collidePath);
 					collidePixels = loadPixels(collidePath);
 				}
 				}
@@ -363,7 +361,7 @@ class Layers2D extends hrt.prefab.Object3D {
 
 
 			if ( currentLayer == revertDataToApply.layer ) {
 			if ( currentLayer == revertDataToApply.layer ) {
 				currentTexture.uploadPixels(currentPixels);
 				currentTexture.uploadPixels(currentPixels);
-				updateVisuals(editorCtx.getContext(this));
+				updateVisuals();
 			}
 			}
 		}));
 		}));
 	}
 	}
@@ -371,8 +369,7 @@ class Layers2D extends hrt.prefab.Object3D {
 	function createInteractiveBrush(ectx : hide.prefab.EditContext) {
 	function createInteractiveBrush(ectx : hide.prefab.EditContext) {
 		if (!enabled) return;
 		if (!enabled) return;
 		editorCtx = ectx;
 		editorCtx = ectx;
-		var ctx = ectx.getContext(this);
-		var s2d = ctx.shared.root2d.getScene();
+		var s2d = shared.root2d.getScene();
 		interactive = new h2d.Interactive(10000, 10000, s2d);
 		interactive = new h2d.Interactive(10000, 10000, s2d);
 		interactive.propagateEvents = true;
 		interactive.propagateEvents = true;
 		interactive.cancelEvents = false;
 		interactive.cancelEvents = false;
@@ -398,7 +395,7 @@ class Layers2D extends hrt.prefab.Object3D {
 				color = 0xff0000;
 				color = 0xff0000;
 			}
 			}
 
 
-			drawCircle(ctx, worldPos.x, worldPos.y, worldPos.z, radius, 5, color);
+			drawCircle(worldPos.x, worldPos.y, worldPos.z, radius, 5, color);
 		}
 		}
 
 
 		interactive.onWheel = function(e) {
 		interactive.onWheel = function(e) {
@@ -573,16 +570,16 @@ class Layers2D extends hrt.prefab.Object3D {
 				paint();
 				paint();
 			}
 			}
 		};
 		};
-		updateVisuals(ctx);
+		updateVisuals();
 
 
 	}
 	}
 
 
-	public function drawCircle(ctx : hrt.prefab.Context, originX : Float, originY : Float, originZ : Float, radius: Float, thickness: Float, color) {
+	public function drawCircle(originX : Float, originY : Float, originZ : Float, radius: Float, thickness: Float, color) {
 		var newColor = h3d.Vector4.fromColor(color);
 		var newColor = h3d.Vector4.fromColor(color);
 		if (gBrushes == null || gBrushes.length == 0 || gBrushes[0].scaleX != radius || gBrushes[0].material.color != newColor) {
 		if (gBrushes == null || gBrushes.length == 0 || gBrushes[0].scaleX != radius || gBrushes[0].material.color != newColor) {
 			clearBrushes();
 			clearBrushes();
 			gBrushes = [];
 			gBrushes = [];
-			var gBrush = new h3d.scene.Mesh(hrt.prefab.l3d.Spray.makePrimCircle(64, 0.95), ctx.local3d);
+			var gBrush = new h3d.scene.Mesh(hrt.prefab.l3d.Spray.makePrimCircle(64, 0.95), local3d);
 			gBrush.scaleX = gBrush.scaleY = radius;
 			gBrush.scaleX = gBrush.scaleY = radius;
 			gBrush.ignoreParentTransform = true;
 			gBrush.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
 			var pass = gBrush.material.mainPass;
@@ -592,7 +589,7 @@ class Layers2D extends hrt.prefab.Object3D {
 			gBrush.material.shadows = false;
 			gBrush.material.shadows = false;
 			gBrush.material.color = newColor;
 			gBrush.material.color = newColor;
 			gBrushes.push(gBrush);
 			gBrushes.push(gBrush);
-			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), ctx.local3d);
+			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), local3d);
 			gBrush.ignoreParentTransform = true;
 			gBrush.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
 			var pass = gBrush.material.mainPass;
 			pass.setPassName("outline");
 			pass.setPassName("outline");
@@ -610,12 +607,12 @@ class Layers2D extends hrt.prefab.Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function setSelected( ctx : hrt.prefab.Context, b : Bool ) {
+	override function setSelected(b : Bool ) {
 		if( !b ) {
 		if( !b ) {
 			removeInteractiveBrush();
 			removeInteractiveBrush();
 		}
 		}
 		setupRfx(editorCtx, keepVisible || b);
 		setupRfx(editorCtx, keepVisible || b);
-		updateVisuals(ctx);
+		updateVisuals();
 		return false;
 		return false;
 	}
 	}
 
 
@@ -642,7 +639,6 @@ class Layers2D extends hrt.prefab.Object3D {
 
 
 	override function edit( ectx : hide.prefab.EditContext ) {
 	override function edit( ectx : hide.prefab.EditContext ) {
 		super.edit(ectx);
 		super.edit(ectx);
-		var ctx = ectx.getContext(this);
 
 
 		sceneEditor = ectx.scene.editor;
 		sceneEditor = ectx.scene.editor;
 
 
@@ -762,7 +758,7 @@ class Layers2D extends hrt.prefab.Object3D {
 					collideMap = null;
 					collideMap = null;
 				}
 				}
 			}
 			}
-			updateVisuals(ctx);
+			updateVisuals();
 		});
 		});
 
 
 		function selectLayer( name : String ) {
 		function selectLayer( name : String ) {
@@ -809,7 +805,7 @@ class Layers2D extends hrt.prefab.Object3D {
 					ectx.properties.build(lValueContent, vLayer, (pname) -> {
 					ectx.properties.build(lValueContent, vLayer, (pname) -> {
 						if (pname == "color") {
 						if (pname == "color") {
 							updateColors();
 							updateColors();
-							updateVisuals(ctx);
+							updateVisuals();
 						}
 						}
 					});
 					});
 
 
@@ -893,7 +889,7 @@ class Layers2D extends hrt.prefab.Object3D {
 		}
 		}
 
 
 		setupRfx(ectx, true);
 		setupRfx(ectx, true);
-		updateVisuals(ctx);
+		updateVisuals();
 
 
 		var actions = new hide.Element('<div class="btn-list" align="center" style="margin-top: 5px;" ></div>').appendTo(list);
 		var actions = new hide.Element('<div class="btn-list" align="center" style="margin-top: 5px;" ></div>').appendTo(list);
 		var addLayer = new hide.Element('<input type="button" value="Create a new layer" />').appendTo(actions);
 		var addLayer = new hide.Element('<input type="button" value="Create a new layer" />').appendTo(actions);
@@ -921,6 +917,5 @@ class Layers2D extends hrt.prefab.Object3D {
 
 
 	#end
 	#end
 
 
-	static var _ = hrt.prefab.Library.register("layers2D", Layers2D);
-
+	static var _ = hrt.prefab.Prefab.register("layers2D", Layers2D);
 }
 }

+ 7 - 9
hrt/prefab/l3d/Level3D.hx

@@ -1,18 +1,16 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 
 
+/**
+	Alias of Object for compatibility with the old prefab system
+**/
 @:deprecated("Use hrt.prefab.Library instead")
 @:deprecated("Use hrt.prefab.Library instead")
-class Level3D extends hrt.prefab.Library {
-
-	public function new() {
-		super();
-		type = "level3d";
-	}
-
+class Level3D extends Object3D
+{
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "sitemap", name : "Level3D", allowParent: _ -> false};
 		return { icon : "sitemap", name : "Level3D", allowParent: _ -> false};
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("level3d", Level3D, "l3d");
+	public static var _ = Prefab.register("level3d", Level3D);
 }
 }

+ 53 - 50
hrt/prefab/l3d/MeshGenerator.hx

@@ -123,8 +123,8 @@ class MeshGenerator extends Object3D {
 	public var maxDepth = 1;
 	public var maxDepth = 1;
 	@:s public var shadows = true;
 	@:s public var shadows = true;
 
 
-	override function save() {
-		var obj : Dynamic = super.save();
+	override function save() : Dynamic {
+		var obj = super.save();
 		obj.root = root.save();
 		obj.root = root.save();
 		return obj;
 		return obj;
 	}
 	}
@@ -135,19 +135,24 @@ class MeshGenerator extends Object3D {
 		root.load(obj.root);
 		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;
+	override function copy( obj : Dynamic ) {
+		super.copy(obj);
+		root = new MeshPart();
+		root.load(obj.root);
+	}
 
 
-		var rootObject = new MeshGeneratorRoot(ctx.local3d);
+	override function makeInstance() : Void {
+		local3d = new h3d.scene.Object(shared.current3d);
+		local3d.name = name;
+
+		var rootObject = new MeshGeneratorRoot(shared.current3d);
 		rootObject.name = "rootObject";
 		rootObject.name = "rootObject";
 
 
 		if( root == null ) {
 		if( root == null ) {
 			root = new MeshPart();
 			root = new MeshPart();
 			root.socket.type = "Root";
 			root.socket.type = "Root";
 		}
 		}
-		updateInstance(ctx);
+		updateInstance();
 
 
 		#if editor
 		#if editor
 		if( customScene == null ) {
 		if( customScene == null ) {
@@ -157,25 +162,23 @@ class MeshGenerator extends Object3D {
 			#end
 			#end
 		}
 		}
 		#end
 		#end
-
-		return ctx;
 	}
 	}
 
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx,propName);
-		resetMesh(ctx);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
+		resetMesh();
 
 
 		#if editor
 		#if editor
-		createEmptyMeshPart(ctx, root);
+		createEmptyMeshPart(root);
 		#end
 		#end
 
 
-		var rootObject = ctx.local3d.getObjectByName("rootObject");
-		createMeshPart(ctx, root, rootObject);
+		var rootObject = local3d.getObjectByName("rootObject");
+		createMeshPart(root, rootObject);
 
 
 		#if editor
 		#if editor
-		var int = ctx.local3d.find(o -> Std.downcast(o, h3d.scene.Interactive));
+		var int = local3d.find(o -> Std.downcast(o, h3d.scene.Interactive));
 		if(int != null) {
 		if(int != null) {
-			var dummy = Std.downcast(makeInteractive(ctx), h3d.scene.Interactive);
+			var dummy = Std.downcast(makeInteractive(), h3d.scene.Interactive);
 			int.preciseShape = dummy.preciseShape;
 			int.preciseShape = dummy.preciseShape;
 			dummy.remove();
 			dummy.remove();
 		}
 		}
@@ -201,16 +204,16 @@ class MeshGenerator extends Object3D {
 		return null;
 		return null;
 	}
 	}
 
 
-	function createMeshPart( ctx : Context, mp : MeshPart, parent : h3d.scene.Object ) {
+	function createMeshPart(mp : MeshPart, parent : h3d.scene.Object ) {
 
 
 		#if editor
 		#if editor
 		if( mp.previewPos ) {
 		if( mp.previewPos ) {
 			if( mp.isRoot() )
 			if( mp.isRoot() )
-				parent.addChild(createPreviewSphere(ctx));
+				parent.addChild(createPreviewSphere());
 			else {
 			else {
 				var socket = getSocket(parent, mp.socket);
 				var socket = getSocket(parent, mp.socket);
 				if( socket != null )
 				if( socket != null )
-					socket.addChild(createPreviewSphere(ctx));
+					socket.addChild(createPreviewSphere());
 			}
 			}
 		}
 		}
 		#end
 		#end
@@ -221,7 +224,7 @@ class MeshGenerator extends Object3D {
 		if( mp.meshPath == null )
 		if( mp.meshPath == null )
 			return;
 			return;
 
 
-		var obj = ctx.loadModel(mp.meshPath);
+		var obj = shared.loadModel(mp.meshPath);
 		for( m in obj.getMaterials() ) {
 		for( m in obj.getMaterials() ) {
 			m.castShadows = shadows;
 			m.castShadows = shadows;
 		}
 		}
@@ -239,11 +242,11 @@ class MeshGenerator extends Object3D {
 		obj.setPosition(mp.offset.x, mp.offset.y, mp.offset.z);
 		obj.setPosition(mp.offset.x, mp.offset.y, mp.offset.z);
 
 
 		for( cmp in mp.childParts )
 		for( cmp in mp.childParts )
-			createMeshPart(ctx, cmp, obj);
+			createMeshPart(cmp, obj);
 	}
 	}
 
 
-	function resetMesh( ctx : Context ) {
-		ctx.local3d.getObjectByName("rootObject").removeChildren();
+	function resetMesh() {
+		local3d.getObjectByName("rootObject").removeChildren();
 	}
 	}
 
 
 	function getSocketMatFromHMD( hmd : hxd.fmt.hmd.Library, s : Socket ) : h3d.Matrix {
 	function getSocketMatFromHMD( hmd : hxd.fmt.hmd.Library, s : Socket ) : h3d.Matrix {
@@ -261,18 +264,18 @@ class MeshGenerator extends Object3D {
 
 
 	#if editor
 	#if editor
 
 
-	function generate( ctx : EditContext, mp : MeshPart, maxDepth : Int, curDepth : Int) {
+	function generate( ctx : hide.prefab.EditContext, mp : MeshPart, maxDepth : Int, curDepth : Int) {
 		if( curDepth >  maxDepth ) return;
 		if( curDepth >  maxDepth ) return;
 		curDepth++;
 		curDepth++;
 		mp.meshPath = getRandomMeshPath(ctx.scene.config, mp.socket);
 		mp.meshPath = getRandomMeshPath(ctx.scene.config, mp.socket);
 		if( root.meshPath == null ) return;
 		if( root.meshPath == null ) return;
-		mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(ctx.rootContext, mp.meshPath)));
+		mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(mp.meshPath)));
 		for( cmp in mp.childParts )
 		for( cmp in mp.childParts )
 			generate(ctx, cmp, maxDepth, curDepth);
 			generate(ctx, cmp, maxDepth, curDepth);
 	}
 	}
 
 
-	function createEmptyMeshPart( ctx : Context, mp : MeshPart ) {
-		var sl = getSocketListFromHMD(getHMD(ctx, mp.meshPath));
+	function createEmptyMeshPart(mp : MeshPart ) {
+		var sl = getSocketListFromHMD(getHMD(mp.meshPath));
 		if( mp.childParts.length < sl.length ) {
 		if( mp.childParts.length < sl.length ) {
 			for( s in sl ) {
 			for( s in sl ) {
 				var b = true;
 				var b = true;
@@ -291,11 +294,11 @@ class MeshGenerator extends Object3D {
 			}
 			}
 		}
 		}
 		for( cmp in mp.childParts )
 		for( cmp in mp.childParts )
-			createEmptyMeshPart(ctx, cmp);
+			createEmptyMeshPart(cmp);
 	}
 	}
 
 
 	var target : h3d.mat.Texture;
 	var target : h3d.mat.Texture;
-	function renderMeshThumbnail( ctx : Context, meshPath : String ) {
+	function renderMeshThumbnail(meshPath : String ) {
 
 
 		if( target == null )
 		if( target == null )
 			target = new h3d.mat.Texture(256, 256, [Target], RGBA);
 			target = new h3d.mat.Texture(256, 256, [Target], RGBA);
@@ -303,7 +306,7 @@ class MeshGenerator extends Object3D {
 		if( meshPath == null )
 		if( meshPath == null )
 			return;
 			return;
 
 
-		var obj = ctx.loadModel(meshPath);
+		var obj = shared.loadModel(meshPath);
 		if( obj == null )
 		if( obj == null )
 			return;
 			return;
 
 
@@ -323,7 +326,7 @@ class MeshGenerator extends Object3D {
 		if(sys.FileSystem.exists(file))
 		if(sys.FileSystem.exists(file))
 			return;
 			return;
 
 
-		var mainScene = @:privateAccess ctx.local3d.getScene();
+		var mainScene = @:privateAccess local3d.getScene();
 		@:privateAccess customScene.children = [];
 		@:privateAccess customScene.children = [];
 		@:privateAccess customScene.children.push(obj);
 		@:privateAccess customScene.children.push(obj);
 
 
@@ -356,10 +359,10 @@ class MeshGenerator extends Object3D {
 		return false;
 		return false;
 	}
 	}
 
 
-	function createPreviewSphere( ctx : Context ) {
+	function createPreviewSphere() {
 		var root = new h3d.scene.Object();
 		var root = new h3d.scene.Object();
 		root.setRotation(0,0, hxd.Math.degToRad(180));
 		root.setRotation(0,0, hxd.Math.degToRad(180));
-		var m : h3d.scene.Mesh = cast ctx.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
+		var m : h3d.scene.Mesh = cast shared.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
 		m.material.shadows = false;
 		m.material.shadows = false;
 		root.addChild(m);
 		root.addChild(m);
 		m.scale(0.5);
 		m.scale(0.5);
@@ -368,7 +371,7 @@ class MeshGenerator extends Object3D {
 		m.material.mainPass.depthTest = GreaterEqual;
 		m.material.mainPass.depthTest = GreaterEqual;
 		m.material.mainPass.depthWrite = false;
 		m.material.mainPass.depthWrite = false;
 		m.material.mainPass.setPassName("overlay");
 		m.material.mainPass.setPassName("overlay");
-		var m : h3d.scene.Mesh = cast ctx.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
+		var m : h3d.scene.Mesh = cast shared.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
 		m.material.shadows = false;
 		m.material.shadows = false;
 		root.addChild(m);
 		root.addChild(m);
 		m.scale(0.5);
 		m.scale(0.5);
@@ -386,15 +389,15 @@ class MeshGenerator extends Object3D {
 			resetPreview(cmp);
 			resetPreview(cmp);
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "paint-brush", name : "MeshGenerator" };
 		return { icon : "paint-brush", name : "MeshGenerator" };
 	}
 	}
 
 
-	override function setSelected( ctx : Context, b : Bool ) {
-		super.setSelected(ctx, b);
+	override function setSelected(b : Bool ) {
+		super.setSelected(b);
 
 
 		if( !b ) {
 		if( !b ) {
-			var previewSpheres = ctx.local3d.findAll(c -> if(c.name == "previewSphere") c else null);
+			var previewSpheres = local3d.findAll(c -> if(c.name == "previewSphere") c else null);
 			for( s in previewSpheres ) {
 			for( s in previewSpheres ) {
 				s.remove();
 				s.remove();
 			}
 			}
@@ -402,9 +405,9 @@ class MeshGenerator extends Object3D {
 		return true;
 		return true;
 	}
 	}
 
 
-	function getHMD( ctx : Context, meshPath : String ) : hxd.fmt.hmd.Library {
+	function getHMD(meshPath : String ) : hxd.fmt.hmd.Library {
 		if( meshPath == null ) return null;
 		if( meshPath == null ) return null;
-		return @:privateAccess ctx.shared.cache.loadLibrary(hxd.res.Loader.currentInstance.load(meshPath).toModel());
+		return @:privateAccess Cache.get().modelCache.loadLibrary(hxd.res.Loader.currentInstance.load(meshPath).toModel());
 	}
 	}
 
 
 	function createMeshParts( sl : Array<Socket> ) : Array<MeshPart> {
 	function createMeshParts( sl : Array<Socket> ) : Array<MeshPart> {
@@ -441,7 +444,7 @@ class MeshGenerator extends Object3D {
 		return childParts[childParts.length - 1].split(".")[0];
 		return childParts[childParts.length - 1].split(".")[0];
 	}
 	}
 
 
-	function getThumbnailPath( ctx : EditContext, meshPath : String ) : String {
+	function getThumbnailPath( ctx : hide.prefab.EditContext, meshPath : String ) : String {
 		return ctx.ide.getPath(".tmp/meshGeneratorData/"+ extractMeshName(meshPath) +"_thumbnail.png");
 		return ctx.ide.getPath(".tmp/meshGeneratorData/"+ extractMeshName(meshPath) +"_thumbnail.png");
 	}
 	}
 
 
@@ -466,7 +469,7 @@ class MeshGenerator extends Object3D {
 		return available[hxd.Math.round(hxd.Math.random() * (available.length - 1))];
 		return available[hxd.Math.round(hxd.Math.random() * (available.length - 1))];
 	}
 	}
 
 
-	function fillSelectMenu( ctx : EditContext, select : hide.Element, socket : Socket ) {
+	function fillSelectMenu( ctx : hide.prefab.EditContext, select : hide.Element, socket : Socket ) {
 		for( f in filter ) {
 		for( f in filter ) {
 			var meshList : Array<Dynamic> = ctx.scene.config.get("meshGenerator." + f);
 			var meshList : Array<Dynamic> = ctx.scene.config.get("meshGenerator." + f);
 			if( meshList == null ) continue;
 			if( meshList == null ) continue;
@@ -489,7 +492,7 @@ class MeshGenerator extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	function createMenu( ctx : EditContext, mp : MeshPart ) {
+	function createMenu( ctx : hide.prefab.EditContext, mp : MeshPart ) {
 
 
 		if( mp.isRoot() ) {
 		if( mp.isRoot() ) {
 			var rootElement = new hide.Element('
 			var rootElement = new hide.Element('
@@ -509,7 +512,7 @@ class MeshGenerator extends Object3D {
 				var previous = mp.clone();
 				var previous = mp.clone();
 				var actual = mp;
 				var actual = mp;
 				mp.meshPath = val == "none" ? null : val;
 				mp.meshPath = val == "none" ? null : val;
-				mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(ctx.rootContext, mp.meshPath)));
+				mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(mp.meshPath)));
 				ctx.properties.undo.change(Custom(function(undo) {
 				ctx.properties.undo.change(Custom(function(undo) {
 					undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
 					undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
 					ctx.onChange(this, null);
 					ctx.onChange(this, null);
@@ -523,7 +526,7 @@ class MeshGenerator extends Object3D {
 			ctx.properties.add(rootElement, mp, function(pname) {});
 			ctx.properties.add(rootElement, mp, function(pname) {});
 		}
 		}
 
 
-		var socketList = getSocketListFromHMD(getHMD(ctx.rootContext, mp.meshPath));
+		var socketList = getSocketListFromHMD(getHMD(mp.meshPath));
 		if( mp.meshPath != null && socketList.length != 0 ) {
 		if( mp.meshPath != null && socketList.length != 0 ) {
 			var s = '<div class="group" name="${extractMeshName(mp.meshPath)}">';
 			var s = '<div class="group" name="${extractMeshName(mp.meshPath)}">';
 			s += '<div align="center"><div class="meshGenerator-thumbnail"></div></div><dl>';
 			s += '<div align="center"><div class="meshGenerator-thumbnail"></div></div><dl>';
@@ -617,7 +620,7 @@ class MeshGenerator extends Object3D {
 						var previous = mp.clone();
 						var previous = mp.clone();
 						var actual = mp;
 						var actual = mp;
 						mp.meshPath = val == "none" ? null : val;
 						mp.meshPath = val == "none" ? null : val;
-						mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(ctx.rootContext, cmp.meshPath)));
+						mp.childParts = createMeshParts(getSocketListFromHMD(getHMD(cmp.meshPath)));
 						ctx.properties.undo.change(Custom(function(undo) {
 						ctx.properties.undo.change(Custom(function(undo) {
 							undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
 							undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
 							ctx.onChange(this, null);
 							ctx.onChange(this, null);
@@ -651,7 +654,7 @@ class MeshGenerator extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		undo = ctx.properties.undo;
 		undo = ctx.properties.undo;
@@ -714,5 +717,5 @@ class MeshGenerator extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("meshGenerator", MeshGenerator);
+	static var _ = Prefab.register("meshGenerator", MeshGenerator);
 }
 }

+ 76 - 66
hrt/prefab/l3d/MeshSpray.hx

@@ -1,6 +1,7 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 
 
 import hrt.prefab.l3d.Spray;
 import hrt.prefab.l3d.Spray;
+
 #if !editor
 #if !editor
 
 
 typedef BatchData = {
 typedef BatchData = {
@@ -38,8 +39,8 @@ class MeshSpray extends Spray {
 		}
 		}
 	}
 	}
 
 
-	override function createObject( ctx : Context ) {
-		var mspray = new MeshSprayObject(ctx.local3d);
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		var mspray = new MeshSprayObject(parent3d);
 		// preallocate batches so their materials can be resolved
 		// preallocate batches so their materials can be resolved
 		var curID = 0, curMap = mspray.batchesMap.get(0);
 		var curID = 0, curMap = mspray.batchesMap.get(0);
 		if( curMap == null ) {
 		if( curMap == null ) {
@@ -73,7 +74,7 @@ class MeshSpray extends Spray {
 				batch.emitCountTip++;
 				batch.emitCountTip++;
 				return;
 				return;
 			}
 			}
-			var obj = ctx.loadModel(source);
+			var obj = shared.loadModel(source);
 			if ( obj.isMesh() ) {
 			if ( obj.isMesh() ) {
 				loadBatchMesh( source, obj.toMesh() );
 				loadBatchMesh( source, obj.toMesh() );
 			} else {
 			} else {
@@ -102,9 +103,9 @@ class MeshSpray extends Spray {
 		return mspray;
 		return mspray;
 	}
 	}
 
 
-	function loadBinary( ctx : Context ) {
+	function loadBinary() {
 		binaryMeshes = [];
 		binaryMeshes = [];
-		var bytes = new haxe.io.BytesInput(ctx.shared.loadPrefabDat("content","dat",name).entry.getBytes());
+		var bytes = new haxe.io.BytesInput(shared.loadPrefabDat("content","dat",name).entry.getBytes());
 		try {
 		try {
 			while( true ) {
 			while( true ) {
 				binaryMeshes.push({
 				binaryMeshes.push({
@@ -127,13 +128,13 @@ class MeshSpray extends Spray {
 		return true;
 		return true;
 	}
 	}
 
 
-	override function make( ctx : Context ) {
+	override function make(?sh:hrt.prefab.Prefab.ContextMake) : hrt.prefab.Prefab {
 		if( !enabled )
 		if( !enabled )
-			return ctx;
+			return this;
 		if( binaryStorage )
 		if( binaryStorage )
-			loadBinary(ctx);
-		ctx = super.make(ctx);
-		var mspray = Std.downcast(ctx.local3d, MeshSprayObject);
+			loadBinary();
+		super.__makeInternal(sh);
+		var mspray = Std.downcast(local3d, MeshSprayObject);
 		var pos = mspray.getAbsPos();
 		var pos = mspray.getAbsPos();
 		var tmp = new h3d.Matrix();
 		var tmp = new h3d.Matrix();
 		var curID = 0, curMap = mspray.batchesMap.get(0);
 		var curID = 0, curMap = mspray.batchesMap.get(0);
@@ -203,16 +204,16 @@ class MeshSpray extends Spray {
 			b.worldPosition = null;
 			b.worldPosition = null;
 		if ( clearBinaryMeshes )
 		if ( clearBinaryMeshes )
 			binaryMeshes = null;
 			binaryMeshes = null;
-		return ctx;
+		return this;
 	}
 	}
 
 
-	override function makeChild( ctx : Context, p : hrt.prefab.Prefab ) {
+	override function makeChild(p : hrt.prefab.Prefab ) {
 		if( p.type == "model" )
 		if( p.type == "model" )
 			return;
 			return;
-		super.makeChild(ctx, p);
+		super.makeChild(p);
 	}
 	}
 
 
-	static var _ = Library.register("meshSpray", MeshSpray);
+	static var _ = Prefab.register("meshSpray", MeshSpray);
 
 
 }
 }
 
 
@@ -334,7 +335,7 @@ class MeshSpray extends Spray {
 		return hide.Ide.inst.resourceDir + "/" + MESH_SPRAY_CONFIG_FILE;
 		return hide.Ide.inst.resourceDir + "/" + MESH_SPRAY_CONFIG_FILE;
 	}
 	}
 
 
-	override function save() {
+	override function save() : Dynamic {
 		clearPreview();
 		clearPreview();
 		if( binaryStorage ) saveToBinary();
 		if( binaryStorage ) saveToBinary();
 		return super.save();
 		return super.save();
@@ -359,8 +360,9 @@ class MeshSpray extends Spray {
 		for( i => m in this.sources )
 		for( i => m in this.sources )
 			meshes.set(m.path, i+1);
 			meshes.set(m.path, i+1);
 		for( c in children.copy() ) {
 		for( c in children.copy() ) {
-			if( c.type != "model" || c.children.length != 0 || !meshes.exists(c.source) ) continue;
+			if( c.type != "model" || c.children.length != 0) continue;
 			var c = c.to(Model);
 			var c = c.to(Model);
+			if (!meshes.exists(c.source)) continue;
 			binaryMeshes.push({ path : c.source, x : c.x, y : c.y, z : c.z, scale : c.scaleX, rotX : c.rotationX, rotY : c.rotationY, rotZ : c.rotationZ });
 			binaryMeshes.push({ path : c.source, x : c.x, y : c.y, z : c.z, scale : c.scaleX, rotX : c.rotationX, rotY : c.rotationY, rotZ : c.rotationZ });
 			children.remove(c);
 			children.remove(c);
 			binaryChanged = true;
 			binaryChanged = true;
@@ -398,7 +400,7 @@ class MeshSpray extends Spray {
 		binaryChanged = false;
 		binaryChanged = false;
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "paint-brush", name : "MeshSpray", hideChildren : p -> return (!editChildren && Std.isOfType(p, Model)) };
 		return { icon : "paint-brush", name : "MeshSpray", hideChildren : p -> return (!editChildren && Std.isOfType(p, Model)) };
 	}
 	}
 
 
@@ -406,7 +408,7 @@ class MeshSpray extends Spray {
 		sys.io.File.saveContent(MESH_SPRAY_CONFIG_PATH, hide.Ide.inst.toJSON(allSetGroups));
 		sys.io.File.saveContent(MESH_SPRAY_CONFIG_PATH, hide.Ide.inst.toJSON(allSetGroups));
 	}
 	}
 
 
-	override function edit( ectx : EditContext ) {
+	override function edit( ectx : hide.prefab.EditContext ) {
 		invParent = getAbsPos().clone();
 		invParent = getAbsPos().clone();
 		invParent.invert();
 		invParent.invert();
 
 
@@ -455,7 +457,7 @@ class MeshSpray extends Spray {
 						removeSourcePath(elt.val());
 						removeSourcePath(elt.val());
 						addSourcePath(newPath);
 						addSourcePath(newPath);
 						for (child in children) {
 						for (child in children) {
-							var model = child.to(hrt.prefab.Object3D);
+							var model = child.to(Model);
 							if (model != null && model.source == elt.val()) {
 							if (model != null && model.source == elt.val()) {
 								model.source = newPath;
 								model.source = newPath;
 							}
 							}
@@ -468,7 +470,7 @@ class MeshSpray extends Spray {
 								removeSourcePath(newPath);
 								removeSourcePath(newPath);
 								addSourcePath(path);
 								addSourcePath(path);
 								for (child in children) {
 								for (child in children) {
-									var model = child.to(hrt.prefab.Object3D);
+									var model = child.to(Model);
 									if (model != null && model.source == elt.val()) {
 									if (model != null && model.source == elt.val()) {
 										model.source = path;
 										model.source = path;
 									}
 									}
@@ -481,7 +483,7 @@ class MeshSpray extends Spray {
 								removeSourcePath(elt.val());
 								removeSourcePath(elt.val());
 								addSourcePath(newPath);
 								addSourcePath(newPath);
 								for (child in children) {
 								for (child in children) {
-									var model = child.to(hrt.prefab.Object3D);
+									var model = child.to(Model);
 									if (model != null && model.source == elt.val()) {
 									if (model != null && model.source == elt.val()) {
 										model.source = newPath;
 										model.source = newPath;
 									}
 									}
@@ -687,16 +689,14 @@ class MeshSpray extends Spray {
 		});
 		});
 
 
 		options.find("#toground").click(function(_) {
 		options.find("#toground").click(function(_) {
-			var ctx = ectx.getContext(this);
-			var mso = cast(ctx.local3d,MeshSprayObject);
+			var mso = cast(local3d,MeshSprayObject);
 			undo.change(Custom(function(undo) {
 			undo.change(Custom(function(undo) {
 			}));
 			}));
 			for( c in this.children ) {
 			for( c in this.children ) {
 				var obj = c.to(Object3D);
 				var obj = c.to(Object3D);
 				if( obj == null ) continue;
 				if( obj == null ) continue;
-				setGroundPos(ectx, obj);
-				var ctx = ectx.getContext(obj);
-				if( ctx != null ) obj.applyTransform(ctx.local3d);
+				setGroundPos(obj);
+				obj.applyTransform();
 				wasEdited = true;
 				wasEdited = true;
 			}
 			}
 			if ( this.binaryMeshes != null ) {
 			if ( this.binaryMeshes != null ) {
@@ -706,7 +706,7 @@ class MeshSpray extends Spray {
 					pos.x = bm.x + pivot.tx;
 					pos.x = bm.x + pivot.tx;
 					pos.y = bm.y + pivot.ty;
 					pos.y = bm.y + pivot.ty;
 					pos.z = bm.z + pivot.tz;
 					pos.z = bm.z + pivot.tz;
-					var ground = setGroundPos(ectx, null, pos);
+					var ground = setGroundPos(null, pos);
 					bm.z += ground.mz;
 					bm.z += ground.mz;
 					bm.rotX = ground.rotX;
 					bm.rotX = ground.rotX;
 					bm.rotY = ground.rotY;
 					bm.rotY = ground.rotY;
@@ -738,7 +738,7 @@ class MeshSpray extends Spray {
 					}
 					}
 				}
 				}
 				sceneEditor.deleteElements(meshes);
 				sceneEditor.deleteElements(meshes);
-				cast(ectx.getContext(this).local3d, MeshSprayObject).redraw();
+				cast(local3d, MeshSprayObject).redraw();
 			}
 			}
 		});
 		});
 
 
@@ -773,7 +773,7 @@ class MeshSpray extends Spray {
 			createInteractiveBrush(ectx);
 			createInteractiveBrush(ectx);
 		super.edit(ectx);
 		super.edit(ectx);
 
 
-		ectx.properties.add(new Element('
+		ectx.properties.add(new hide.Element('
 		<div class="group" name="Extra">
 		<div class="group" name="Extra">
 		<dl>
 		<dl>
 			<dt>Split</dt><dd><input type="range" min="0" max="2048" field="split"/></dd>
 			<dt>Split</dt><dd><input type="range" min="0" max="2048" field="split"/></dd>
@@ -783,12 +783,11 @@ class MeshSpray extends Spray {
 		</div>'), this);
 		</div>'), this);
 	}
 	}
 
 
-	override function createInteractiveBrush(ectx : EditContext) {
+	override function createInteractiveBrush(ectx : hide.prefab.EditContext) {
 		super.createInteractiveBrush(ectx);
 		super.createInteractiveBrush(ectx);
 		if (!enabled) return;
 		if (!enabled) return;
-		var ctx = ectx.getContext(this);
 
 
-		var s2d = ctx.shared.root2d.getScene();
+		var s2d = shared.root2d.getScene();
 
 
 		interactive.onMove = function(e) {
 		interactive.onMove = function(e) {
 			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
 			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
@@ -800,12 +799,12 @@ class MeshSpray extends Spray {
 				return;
 				return;
 			}
 			}
 
 
-			drawCircle(ctx, worldPos.x, worldPos.y, worldPos.z, (shiftPressed) ? currentConfig.deleteRadius : currentConfig.radius, 5, (shiftPressed) ? 9830400 : 38400);
+			drawCircle(worldPos.x, worldPos.y, worldPos.z, (shiftPressed) ? currentConfig.deleteRadius : currentConfig.radius, 5, (shiftPressed) ? 9830400 : 38400);
 
 
 			if (lastSpray < Date.now().getTime() - 100) {
 			if (lastSpray < Date.now().getTime() - 100) {
 				clearPreview();
 				clearPreview();
 				if( !shiftPressed ) {
 				if( !shiftPressed ) {
-					previewItemsAround(ectx, ctx, worldPos);
+					previewItemsAround(ectx, worldPos);
 				}
 				}
 
 
 				if( K.isDown( K.MOUSE_LEFT) ) {
 				if( K.isDown( K.MOUSE_LEFT) ) {
@@ -814,17 +813,17 @@ class MeshSpray extends Spray {
 
 
 					if (sprayEnable) {
 					if (sprayEnable) {
 						if( shiftPressed ) {
 						if( shiftPressed ) {
-							removeItemsAround(ctx, worldPos);
+							removeItemsAround(worldPos);
 						} else {
 						} else {
 							if (currentConfig.density == 1) {
 							if (currentConfig.density == 1) {
 								if(lastItemPos.distance(worldPos) > currentConfig.step) {
 								if(lastItemPos.distance(worldPos) > currentConfig.step) {
 									lastItemPos = worldPos.clone();
 									lastItemPos = worldPos.clone();
-									addItems(ctx);
+									addItems();
 								}
 								}
 							}
 							}
 							else {
 							else {
 								lastItemPos = worldPos.clone();
 								lastItemPos = worldPos.clone();
-								addItems(ctx);
+								addItems();
 							}
 							}
 						}
 						}
 					}
 					}
@@ -870,7 +869,7 @@ class MeshSpray extends Spray {
 			saveConfigMeshBatch();
 			saveConfigMeshBatch();
 	}
 	}
 
 
-	override function removeItemsAround(ctx : Context, point : h3d.col.Point) {
+	override function removeItemsAround(point : h3d.col.Point) {
 		var vecRelat = point.toVector();
 		var vecRelat = point.toVector();
 		vecRelat.transform(invParent);
 		vecRelat.transform(invParent);
 		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
 		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
@@ -906,7 +905,7 @@ class MeshSpray extends Spray {
 					for( c in toDelete ) {
 					for( c in toDelete ) {
 						if( undo ) binaryMeshes.push(c) else binaryMeshes.remove(c);
 						if( undo ) binaryMeshes.push(c) else binaryMeshes.remove(c);
 					}
 					}
-					cast(ctx.local3d,MeshSprayObject).redraw();
+					cast(local3d,MeshSprayObject).redraw();
 				}));
 				}));
 				needRedraw = true;
 				needRedraw = true;
 			}
 			}
@@ -914,36 +913,31 @@ class MeshSpray extends Spray {
 
 
 		if( needRedraw ) {
 		if( needRedraw ) {
 			clearBrushes();
 			clearBrushes();
-			cast(ctx.local3d,MeshSprayObject).redraw();
+			cast(local3d,MeshSprayObject).redraw();
 		}
 		}
 	}
 	}
 
 
-	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 makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		return new MeshSprayObject(this, parent3d);
 	}
 	}
 
 
+
 	function emitCondition(m: h3d.Matrix) {
 	function emitCondition(m: h3d.Matrix) {
 		return true;
 		return true;
 	}
 	}
 
 
-	override function updateInstance(ctx:Context, ?propName) {
-		cast(ctx.local3d, MeshSprayObject).editChildren = editChildren;
-		@:privateAccess cast(ctx.local3d, MeshSprayObject).emitCondition = emitCondition;
+	override function updateInstance(?propName) {
+		cast(local3d, MeshSprayObject).editChildren = editChildren;
+		@:privateAccess cast(local3d, MeshSprayObject).emitCondition = emitCondition;
 		if ( editChildren )
 		if ( editChildren )
 			locked = false;
 			locked = false;
-		super.updateInstance(ctx, propName);
+		super.updateInstance(propName);
 	}
 	}
 
 
-	override function make(ctx:Context):Context {
-		if( !enabled )
-			return ctx;
+	override function makeInstance() {
 		if( binaryStorage ) {
 		if( binaryStorage ) {
 			binaryMeshes = [];
 			binaryMeshes = [];
-			var bytes = new haxe.io.BytesInput(ctx.shared.loadPrefabDat("content","dat",name).entry.getBytes());
+			var bytes = new haxe.io.BytesInput(shared.loadPrefabDat("content","dat",name).entry.getBytes());
 			try {
 			try {
 				while( true ) {
 				while( true ) {
 					binaryMeshes.push({
 					binaryMeshes.push({
@@ -961,25 +955,41 @@ class MeshSpray extends Spray {
 			} catch( e : haxe.io.Eof ) {
 			} catch( e : haxe.io.Eof ) {
 			}
 			}
 		}
 		}
-		shared = ctx.shared;
-		ctx = makeInstance(ctx);
+		super.makeInstance();
+	}
+
+	override function make(?sh:hrt.prefab.Prefab.ContextMake) : Prefab {
+		makeInstance();
+
+		var old3d = shared.current3d;
+		shared.current3d = local3d ?? old3d;
+
 		// add all children then build meshspray
 		// add all children then build meshspray
 		for( c in children )
 		for( c in children )
 			if( c.type == "model" )
 			if( c.type == "model" )
-				makeChild(ctx, c);
-		cast(ctx.local3d, MeshSprayObject).redraw();
+				makeChild(c);
+
+		cast(local3d, MeshSprayObject).redraw();
 		// then add other children (shaders etc.)
 		// then add other children (shaders etc.)
 		for( c in children )
 		for( c in children )
 			if( c.type != "model" )
 			if( c.type != "model" )
-				makeChild(ctx, c);
-		// rebuild to apply per instance shaders
-		cast(ctx.local3d, MeshSprayObject).redraw(true);
-		return ctx;
+				makeChild(c);
+
+		shared.current3d = old3d;
+
+		postMakeInstance();
+
+		return this;
+	}
+
+	override function postMakeInstance() {
+		cast(local3d, MeshSprayObject).redraw(true);
+		super.postMakeInstance();
 	}
 	}
 
 
-	override function applyTransform(o : h3d.scene.Object) {
-		super.applyTransform(o);
-		cast(o, MeshSprayObject).redraw();
+	override function applyTransform() {
+		super.applyTransform();
+		cast(local3d, MeshSprayObject).redraw();
 	}
 	}
 
 
 
 
@@ -1041,7 +1051,7 @@ class MeshSpray extends Spray {
 		return arr;
 		return arr;
 	}
 	}
 
 
-	static var _ = Library.register("meshSpray", MeshSpray);
+	static var _ = Prefab.register("meshSpray", MeshSpray);
 
 
 }
 }
 
 

+ 87 - 65
hrt/prefab/l3d/ModelLibrary.hx

@@ -49,10 +49,10 @@ class ModelLibShader extends hxsl.Shader {
 		@param var mipPower : Float;
 		@param var mipPower : Float;
 		@param var mipNumber : Float;
 		@param var mipNumber : Float;
 
 
-        @input var input2 : {
+		@input var input2 : {
 			var tangent : Vec3;
 			var tangent : Vec3;
 			var uv : Vec2;
 			var uv : Vec2;
-        };
+		};
 
 
 		var calculatedUV : Vec2;
 		var calculatedUV : Vec2;
 		var transformedTangent : Vec4;
 		var transformedTangent : Vec4;
@@ -92,6 +92,14 @@ class ModelLibShader extends hxsl.Shader {
 	}
 	}
 }
 }
 
 
+class ModelLibraryCache {
+	public function new() {};
+	public var wasMade = false;
+	public var hmdPrim : h3d.prim.HMDModel;
+	public var shader : ModelLibShader;
+	public var geomBounds : Array<h3d.col.Bounds>;
+}
+
 class ModelLibrary extends Prefab {
 class ModelLibrary extends Prefab {
 
 
 	@:s var bakedMaterials : haxe.DynamicAccess<MaterialData>;
 	@:s var bakedMaterials : haxe.DynamicAccess<MaterialData>;
@@ -111,19 +119,27 @@ class ModelLibrary extends Prefab {
 	@:s var mipPower : Float;
 	@:s var mipPower : Float;
 	@:s var mipLevels : Int = 1;
 	@:s var mipLevels : Int = 1;
 
 
-	final reg = ~/[0-9]+/g;
+    final reg = ~/[0-9]+/g;
+
+	override public function dispose() {
+		super.dispose();
+		optimizedMeshes = [];
+		batches = [];
+	}
+
+	var cache : ModelLibraryCache;
+	public function new(prefab, shared) {
+		super(prefab, shared);
+		cache = new ModelLibraryCache();
+	}
+
 	#if editor
 	#if editor
 
 
 	@:s var compress : Bool = true;
 	@:s var compress : Bool = true;
 
 
 	var errors = [];
 	var errors = [];
 
 
-	override function makeInstance(ctx) {
-		return ctx.clone(this);
-	}
-
 	override function edit(ectx:hide.prefab.EditContext) {
 	override function edit(ectx:hide.prefab.EditContext) {
-		var ctx = ectx.getContext(this);
 
 
 		ectx.properties.add(new hide.Element('
 		ectx.properties.add(new hide.Element('
 		<div class="group" name="Params">
 		<div class="group" name="Params">
@@ -137,13 +153,13 @@ class ModelLibrary extends Prefab {
 			ectx.onChange(this, pname);
 			ectx.onChange(this, pname);
 		});
 		});
 
 
-		var bt = new Element('<div align="center"><input type="button" value="Build"/></div>');
+		var bt = new hide.Element('<div align="center"><input type="button" value="Build"/></div>');
 		bt.find("input").click(function(e) {
 		bt.find("input").click(function(e) {
 			ectx.makeChanges(this, function() {
 			ectx.makeChanges(this, function() {
 				errors = [];
 				errors = [];
-				rebuildData(ctx.shared, ectx.scene);
+				rebuildData(ectx.scene);
 				if ( compress )
 				if ( compress )
-					compression(ctx.shared, ectx.scene);
+					compression(ectx.scene);
 
 
 				var ide = hide.Ide.inst;
 				var ide = hide.Ide.inst;
 				ide.setProgress();
 				ide.setProgress();
@@ -162,11 +178,11 @@ class ModelLibrary extends Prefab {
 			ectx.onChange(this, pname);
 			ectx.onChange(this, pname);
 		});
 		});
 
 
-		var bt = new Element('<div align="center"><input type="button" value="CompressOnly"/></div>');
+		var bt = new hide.Element('<div align="center"><input type="button" value="CompressOnly"/></div>');
 		bt.find("input").click(function(e) {
 		bt.find("input").click(function(e) {
 			ectx.makeChanges(this, function() {
 			ectx.makeChanges(this, function() {
 				errors = [];
 				errors = [];
-				compression(ctx.shared, ectx.scene);
+				compression(ectx.scene);
 
 
 				var ide = hide.Ide.inst;
 				var ide = hide.Ide.inst;
 				ide.setProgress();
 				ide.setProgress();
@@ -176,7 +192,7 @@ class ModelLibrary extends Prefab {
 		});
 		});
 		ectx.properties.add(bt);
 		ectx.properties.add(bt);
 
 
-		var listMaterials = new Element('
+		var listMaterials = new hide.Element('
 		<div class="group" name="Ignored materials"><ul id="ignoreMatList"></ul></div>');
 		<div class="group" name="Ignored materials"><ul id="ignoreMatList"></ul></div>');
 		ectx.properties.add(listMaterials);
 		ectx.properties.add(listMaterials);
 		for( i in 0...ignoredMaterials.length ) {
 		for( i in 0...ignoredMaterials.length ) {
@@ -190,7 +206,7 @@ class ModelLibrary extends Prefab {
 			});
 			});
 			e.appendTo(listMaterials);
 			e.appendTo(listMaterials);
 			ectx.properties.build(e, ignoredMaterials[i], (pname) -> {
 			ectx.properties.build(e, ignoredMaterials[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 			});
 		}
 		}
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
@@ -200,7 +216,7 @@ class ModelLibrary extends Prefab {
 			ectx.rebuildProperties();
 			ectx.rebuildProperties();
 		});
 		});
 
 
-		var listPrefabs = new Element('
+		var listPrefabs = new hide.Element('
 		<div class="group" name="Ignored prefabs"><ul id="ignorePrefabList"></ul></div>');
 		<div class="group" name="Ignored prefabs"><ul id="ignorePrefabList"></ul></div>');
 		ectx.properties.add(listPrefabs);
 		ectx.properties.add(listPrefabs);
 		for( i in 0...ignoredPrefabs.length ) {
 		for( i in 0...ignoredPrefabs.length ) {
@@ -215,7 +231,7 @@ class ModelLibrary extends Prefab {
 			});
 			});
 			e.appendTo(listPrefabs);
 			e.appendTo(listPrefabs);
 			ectx.properties.build(e, ignoredPrefabs[i], (pname) -> {
 			ectx.properties.build(e, ignoredPrefabs[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 			});
 		}
 		}
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
@@ -225,7 +241,7 @@ class ModelLibrary extends Prefab {
 			ectx.rebuildProperties();
 			ectx.rebuildProperties();
 		});
 		});
 
 
-		var listObjectNames = new Element('
+		var listObjectNames = new hide.Element('
 		<div class="group" name="Ignored object names"><ul id="ignoreObjectNames"></ul></div>');
 		<div class="group" name="Ignored object names"><ul id="ignoreObjectNames"></ul></div>');
 		ectx.properties.add(listObjectNames);
 		ectx.properties.add(listObjectNames);
 		for( i in 0...ignoredObjectNames.length ) {
 		for( i in 0...ignoredObjectNames.length ) {
@@ -239,7 +255,7 @@ class ModelLibrary extends Prefab {
 			});
 			});
 			e.appendTo(listObjectNames);
 			e.appendTo(listObjectNames);
 			ectx.properties.build(e, ignoredObjectNames[i], (pname) -> {
 			ectx.properties.build(e, ignoredObjectNames[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 			});
 		}
 		}
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
@@ -249,7 +265,7 @@ class ModelLibrary extends Prefab {
 			ectx.rebuildProperties();
 			ectx.rebuildProperties();
 		});
 		});
 
 
-		var listpreserveObjectNames = new Element('
+		var listpreserveObjectNames = new hide.Element('
 		<div class="group" name="Preserve object names"><ul id="preserveObjectNames"></ul></div>');
 		<div class="group" name="Preserve object names"><ul id="preserveObjectNames"></ul></div>');
 		ectx.properties.add(listpreserveObjectNames);
 		ectx.properties.add(listpreserveObjectNames);
 		for( i in 0...preserveObjectNames.length ) {
 		for( i in 0...preserveObjectNames.length ) {
@@ -263,7 +279,7 @@ class ModelLibrary extends Prefab {
 			});
 			});
 			e.appendTo(listpreserveObjectNames);
 			e.appendTo(listpreserveObjectNames);
 			ectx.properties.build(e, preserveObjectNames[i], (pname) -> {
 			ectx.properties.build(e, preserveObjectNames[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 			});
 		}
 		}
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
@@ -274,7 +290,7 @@ class ModelLibrary extends Prefab {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Model Library" };
 		return { icon : "square", name : "Model Library" };
 	}
 	}
 
 
@@ -282,7 +298,7 @@ class ModelLibrary extends Prefab {
 		hide.Ide.inst.setProgress(text);
 		hide.Ide.inst.setProgress(text);
 	}
 	}
 
 
-	function rebuildData( shared : ContextShared, scene : hide.comp.Scene ) {
+	function rebuildData(scene : hide.comp.Scene ) {
 
 
 		bakedMaterials = {};
 		bakedMaterials = {};
 		materialConfigs = [];
 		materialConfigs = [];
@@ -449,10 +465,10 @@ class ModelLibrary extends Prefab {
 		modelRoot.position.qz = 0;
 		modelRoot.position.qz = 0;
 		hmd.models.push(modelRoot);
 		hmd.models.push(modelRoot);
 
 
-		for( m in getAll(hrt.prefab.Model, true) ) {
+		for( m in findAll(hrt.prefab.Model, true) ) {
 			if( models.exists(m.source) )
 			if( models.exists(m.source) )
 				continue;
 				continue;
-			if( m.getParent(hrt.prefab.fx.FX) != null )
+			if( m.findParent(hrt.prefab.fx.FX) != null )
 				continue;
 				continue;
 			var ignoreModel = false;
 			var ignoreModel = false;
 			if ( m.animation != null )
 			if ( m.animation != null )
@@ -677,7 +693,7 @@ class ModelLibrary extends Prefab {
 		make(specMaps,"specular");
 		make(specMaps,"specular");
 	}
 	}
 
 
-	function compression( shared : ContextShared, scene : hide.comp.Scene ) {
+	function compression(scene : hide.comp.Scene ) {
 		var convert = new hxd.fs.Convert.CompressIMG("png,tga,jpg,jpeg,dds,envd,envs","dds");
 		var convert = new hxd.fs.Convert.CompressIMG("png,tga,jpg,jpeg,dds,envd,envs","dds");
 		convert.params = {format: "BC3"};
 		convert.params = {format: "BC3"};
 		var path = new haxe.io.Path(Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem).baseDir+shared.currentPath);
 		var path = new haxe.io.Path(Std.downcast(hxd.res.Loader.currentInstance.fs, hxd.fs.LocalFileSystem).baseDir+shared.currentPath);
@@ -711,28 +727,27 @@ class ModelLibrary extends Prefab {
 	#else
 	#else
 
 
 	// var shared : hrt.prefab.ContextShared;
 	// var shared : hrt.prefab.ContextShared;
-	var wasMake = false;
-	var hmdPrim : h3d.prim.HMDModel;
-	var shader : ModelLibShader;
-	var geomBounds : Array<h3d.col.Bounds>;
+
 	public var debug = false;
 	public var debug = false;
 	public var clear = false;
 	public var clear = false;
 
 
-	override function make(ctx:hrt.prefab.Context) {
+	override function make(?sh:hrt.prefab.Prefab.ContextMake) : hrt.prefab.Prefab {
 		// don't load/build children
 		// don't load/build children
-		var shared = ctx.shared;
-		wasMake = true;
-		if ( hmdPrim == null )
-			hmdPrim = Std.downcast(shared.loadModel(shared.getPrefabDatPath("model","hmd",this.name)).toMesh().primitive, h3d.prim.HMDModel);
-		if ( geomBounds == null )
-			geomBounds = [for( g in @:privateAccess hmdPrim.lib.header.geometries ) g.bounds];
-		@:privateAccess hmdPrim.curMaterial = -1;
-		if ( shader == null ) {
-			shader = new ModelLibShader();
-			shader.mipStart = mipStart;
-			shader.mipEnd = mipEnd;
-			shader.mipPower = mipPower;
-			shader.mipNumber = mipLevels;
+		if (cache.wasMade)
+			return this;
+
+		cache.wasMade = true;
+		if ( cache.hmdPrim == null )
+			cache.hmdPrim = Std.downcast(shared.loadModel(shared.getPrefabDatPath("model","hmd",this.name)).toMesh().primitive, h3d.prim.HMDModel);
+		if ( cache.geomBounds == null )
+			cache.geomBounds = [for( g in @:privateAccess cache.hmdPrim.lib.header.geometries ) g.bounds];
+		@:privateAccess cache.hmdPrim.curMaterial = -1;
+		if ( cache.shader == null ) {
+			cache.shader = new ModelLibShader();
+			cache.shader.mipStart = mipStart;
+			cache.shader.mipEnd = mipEnd;
+			cache.shader.mipPower = mipPower;
+			cache.shader.mipNumber = mipLevels;
 			var tex = shared.loadTexture(shared.getPrefabDatPath("texture","dds",this.name));
 			var tex = shared.loadTexture(shared.getPrefabDatPath("texture","dds",this.name));
 			var tnormal = try shared.loadTexture(shared.getPrefabDatPath("normal","dds",this.name)) catch( e : hxd.res.NotFound ) null;
 			var tnormal = try shared.loadTexture(shared.getPrefabDatPath("normal","dds",this.name)) catch( e : hxd.res.NotFound ) null;
 			var tspec = try shared.loadTexture(shared.getPrefabDatPath("specular","dds",this.name)) catch( e : hxd.res.NotFound ) null;
 			var tspec = try shared.loadTexture(shared.getPrefabDatPath("specular","dds",this.name)) catch( e : hxd.res.NotFound ) null;
@@ -740,32 +755,39 @@ class ModelLibrary extends Prefab {
 			tnormal.wrap = Repeat;
 			tnormal.wrap = Repeat;
 			tspec.wrap = Repeat;
 			tspec.wrap = Repeat;
 			if( texturesCount == 1 || !Std.isOfType(tex, h3d.mat.TextureArray) ) {
 			if( texturesCount == 1 || !Std.isOfType(tex, h3d.mat.TextureArray) ) {
-				shader.singleTexture = true;
-				shader.texture = tex;
-				shader.normalMap = tnormal;
-				shader.specular = tspec;
+				cache.shader.singleTexture = true;
+				cache.shader.texture = tex;
+				cache.shader.normalMap = tnormal;
+				cache.shader.specular = tspec;
 			} else {
 			} else {
-				shader.textures = cast(tex,h3d.mat.TextureArray);
-				shader.normalMaps = cast(tnormal,h3d.mat.TextureArray);
-				shader.speculars = cast(tspec,h3d.mat.TextureArray);
+				cache.shader.textures = cast(tex,h3d.mat.TextureArray);
+				cache.shader.normalMaps = cast(tnormal,h3d.mat.TextureArray);
+				cache.shader.speculars = cast(tspec,h3d.mat.TextureArray);
 			}
 			}
-			shader.hasNormal = tnormal != null;
-			shader.hasPbr = tspec != null;
+			cache.shader.hasNormal = tnormal != null;
+			cache.shader.hasPbr = tspec != null;
 		}
 		}
-		return ctx;
+		return this;
 	}
 	}
 
 
-	public function dispose() {
-		optimizedMeshes = [];
-		batches = [];
+	override function clone(?parent:Prefab = null, ?sh: ContextShared = null, withChildren : Bool = true) : Prefab {
+		var clone : ModelLibrary = cast super.clone(parent, sh, withChildren);
+		clone.cache = cache;
+		return clone;
 	}
 	}
 
 
+
+	// public function dispose() {
+	// 	optimizedMeshes = [];
+	// 	batches = [];
+	// }
+
 	var killAlpha = new h3d.shader.KillAlpha(0.5);
 	var killAlpha = new h3d.shader.KillAlpha(0.5);
 	var curSubMeshes : SubMeshes = null;
 	var curSubMeshes : SubMeshes = null;
 	public function optimize( obj : h3d.scene.Object, isStatic = true ) {
 	public function optimize( obj : h3d.scene.Object, isStatic = true ) {
 		if( bakedMaterials == null )
 		if( bakedMaterials == null )
 			throw "Model library was not built or saved";
 			throw "Model library was not built or saved";
-		if( !wasMake )
+		if( !cache.wasMade )
 			throw "Please call make() on modelLibrary first";
 			throw "Please call make() on modelLibrary first";
 
 
 		var meshBatches = [for (i in 0...materialConfigs.length * (preserveObjectNames.length + 1)) null];
 		var meshBatches = [for (i in 0...materialConfigs.length * (preserveObjectNames.length + 1)) null];
@@ -817,14 +839,14 @@ class ModelLibrary extends Prefab {
 	}
 	}
 
 
 	public function createMeshBatch(parent : h3d.scene.Object, isStatic : Bool, ?bounds : h3d.col.Bounds, ?props : h3d.mat.PbrMaterial.PbrProps) {
 	public function createMeshBatch(parent : h3d.scene.Object, isStatic : Bool, ?bounds : h3d.col.Bounds, ?props : h3d.mat.PbrMaterial.PbrProps) {
-		var batch = new h3d.scene.MeshBatch(hmdPrim, h3d.mat.Material.create(), parent);
+		var batch = new h3d.scene.MeshBatch(cache.hmdPrim, h3d.mat.Material.create(), parent);
 		if ( isStatic ) {
 		if ( isStatic ) {
 			batch.material.staticShadows = true;
 			batch.material.staticShadows = true;
 			batch.fixedPosition = true;
 			batch.fixedPosition = true;
 		}
 		}
 		batch.cullingCollider = bounds;
 		batch.cullingCollider = bounds;
 		batch.name = "modelLibrary";
 		batch.name = "modelLibrary";
-		batch.material.mainPass.addShader(shader);
+		batch.material.mainPass.addShader(cache.shader);
 		if ( props != null ) {
 		if ( props != null ) {
 			batch.material.props = props;
 			batch.material.props = props;
 			batch.material.refreshProps();
 			batch.material.refreshProps();
@@ -917,22 +939,22 @@ class ModelLibrary extends Prefab {
 
 
 	public function emit(m : MaterialMesh, batch : h3d.scene.MeshBatch, emitCountTip = -1) {
 	public function emit(m : MaterialMesh, batch : h3d.scene.MeshBatch, emitCountTip = -1) {
 		var bk = m.mat;
 		var bk = m.mat;
-		shader.delta = 1.0 / 4096 / bk.uvSX;
-		shader.uvTransform.set(bk.uvX, bk.uvY, bk.uvSX, bk.uvSY);
-		shader.material = bk.texId;
+		cache.shader.delta = 1.0 / 4096 / bk.uvSX;
+		cache.shader.uvTransform.set(bk.uvX, bk.uvY, bk.uvSX, bk.uvSY);
+		cache.shader.material = bk.texId;
 		if ( batch.primitiveSubPart == null ) {
 		if ( batch.primitiveSubPart == null ) {
 			batch.primitiveSubPart = new h3d.scene.MeshBatch.MeshBatchPart();
 			batch.primitiveSubPart = new h3d.scene.MeshBatch.MeshBatchPart();
 			batch.begin(emitCountTip);
 			batch.begin(emitCountTip);
 		}
 		}
 		batch.primitiveSubPart.indexCount = bk.indexCount;
 		batch.primitiveSubPart.indexCount = bk.indexCount;
 		batch.primitiveSubPart.indexStart = bk.indexStart;
 		batch.primitiveSubPart.indexStart = bk.indexStart;
-		batch.primitiveSubPart.bounds = geomBounds[bk.geomId];
+		batch.primitiveSubPart.bounds = cache.geomBounds[bk.geomId];
 		batch.worldPosition = m.mesh.getAbsPos();
 		batch.worldPosition = m.mesh.getAbsPos();
 		batch.emitInstance();
 		batch.emitInstance();
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("modelLib", ModelLibrary);
+	static var _ = Prefab.register("modelLib", ModelLibrary);
 
 
 }
 }

+ 4 - 11
hrt/prefab/l3d/ModelLibraryOptimizer.hx

@@ -7,32 +7,25 @@ class ModelLibraryOptimizer extends Object3D {
 	public var modelLibrary : ModelLibrary;
 	public var modelLibrary : ModelLibrary;
 	public var clear = false;
 	public var clear = false;
 
 
-	public function postMake( ctx : Context ) {
+	override public function postMakeInstance() : Void {
 		modelLibrary = getOpt(ModelLibrary, null, true);
 		modelLibrary = getOpt(ModelLibrary, null, true);
 		if ( modelLibrary == null )
 		if ( modelLibrary == null )
 			throw "Missing modelLibrary as children";
 			throw "Missing modelLibrary as children";
 		modelLibrary.clear = clear;
 		modelLibrary.clear = clear;
-		for ( c in @:privateAccess ctx.local3d.children.copy() ) {
+		for ( c in @:privateAccess local3d.children.copy() ) {
 			if ( c != null )
 			if ( c != null )
 				modelLibrary.optimize(c);
 				modelLibrary.optimize(c);
 		}
 		}
 	}
 	}
-	override function make( ctx : Context ) : Context {
-		if( !enabled )
-			return ctx;
-		ctx = super.make(ctx);
-		postMake(ctx);
-		return ctx;
-	}
 
 
 	#else
 	#else
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Model Library Optimizer" };
 		return { icon : "square", name : "Model Library Optimizer" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("modelLibOptimizer", ModelLibraryOptimizer);
+	static var _ = Prefab.register("modelLibOptimizer", ModelLibraryOptimizer);
 
 
 }
 }

+ 12 - 13
hrt/prefab/l3d/Particles3D.hx

@@ -1,16 +1,17 @@
 package hrt.prefab.l3d;
 package hrt.prefab.l3d;
 
 
+// NOTE(ces) : Not Tested
+
 class Particles3D extends Object3D {
 class Particles3D extends Object3D {
 
 
 	@:s var data : Any;
 	@:s var data : Any;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "particles3D";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 	}
 	}
 
 
-	override function createObject(ctx:Context) {
-		var parts = new h3d.parts.GpuParticles(ctx.local3d);
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		var parts = new h3d.parts.GpuParticles(parent3d);
 		if( source != null ) {
 		if( source != null ) {
 			var src = null;
 			var src = null;
 			try {
 			try {
@@ -28,16 +29,14 @@ class Particles3D extends Object3D {
 
 
 	#if editor
 	#if editor
 
 
-	override function setSelected(ctx:Context, b:Bool):Bool {
+	override function setSelected(b:Bool):Bool {
 		return true;
 		return true;
 	}
 	}
 
 
-	override function edit(ectx:EditContext) {
+	override function edit(ectx:hide.prefab.EditContext) {
 		super.edit(ectx);
 		super.edit(ectx);
 		if(source == null) {
 		if(source == null) {
-			var ctx = ectx.getContext(this);
-			if( ctx == null ) return;
-			var parts = cast(ctx.local3d,h3d.parts.GpuParticles);
+			var parts = cast(local3d,h3d.parts.GpuParticles);
 
 
 			function undo(f) {
 			function undo(f) {
 				ectx.properties.undo.change(Custom(function(redo) { f(redo); data = parts.save(); }));
 				ectx.properties.undo.change(Custom(function(redo) { f(redo); data = parts.save(); }));
@@ -45,7 +44,7 @@ class Particles3D extends Object3D {
 			}
 			}
 
 
 			function addGroup( g : h3d.parts.GpuParticles.GpuPartGroup ) {
 			function addGroup( g : h3d.parts.GpuParticles.GpuPartGroup ) {
-				var e = new Element('
+				var e = new hide.Element('
 					<div class="section">
 					<div class="section">
 						<h1><span>${g.name}</span> &nbsp;<input type="checkbox" field="enable"/></h1>
 						<h1><span>${g.name}</span> &nbsp;<input type="checkbox" field="enable"/></h1>
 						<div class="content">
 						<div class="content">
@@ -179,7 +178,7 @@ class Particles3D extends Object3D {
 			for( g in parts.getGroups() )
 			for( g in parts.getGroups() )
 				addGroup(g);
 				addGroup(g);
 
 
-			var extra = new Element('
+			var extra = new hide.Element('
 				<div class="section">
 				<div class="section">
 					<h1>Manage</h1>
 					<h1>Manage</h1>
 					<div class="content">
 					<div class="content">
@@ -222,6 +221,6 @@ class Particles3D extends Object3D {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("particles3D", Particles3D);
+	static var _ = Prefab.register("particles3D", Particles3D);
 
 
 }
 }

+ 38 - 33
hrt/prefab/l3d/Polygon.hx

@@ -2,6 +2,13 @@ package hrt.prefab.l3d;
 import hxd.Math;
 import hxd.Math;
 import h2d.col.Point;
 import h2d.col.Point;
 
 
+#if editor
+import hide.prefab.EditContext;
+#end
+
+import hide.prefab.HideProps;
+
+
 
 
 enum Shape {
 enum Shape {
 	Quad(subdivision : Int);
 	Quad(subdivision : Int);
@@ -27,21 +34,16 @@ class Polygon extends Object3D {
 	var prevScale = [1.0, 1.0];
 	var prevScale = [1.0, 1.0];
 	#end
 	#end
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "polygon";
-	}
-
 	override function save() {
 	override function save() {
-		var obj : Dynamic = super.save();
-		obj.kind = shape.getIndex();
+		var data = super.save();
+		data.kind = shape.getIndex();
 		switch(shape){
 		switch(shape){
 		case Quad(_), Disc(_), Sphere(_), Capsule(_):
 		case Quad(_), Disc(_), Sphere(_), Capsule(_):
-			obj.args = shape.getParameters();
+			data.args = shape.getParameters();
 		case Custom:
 		case Custom:
-			obj.points = [for( p in points ) { x : p.x, y : p.y }];
+			data.points = [for( p in points ) { x : p.x, y : p.y }];
 		}
 		}
-		return obj;
+		return data;
 	}
 	}
 
 
 	override function load( obj : Dynamic ) {
 	override function load( obj : Dynamic ) {
@@ -55,12 +57,19 @@ class Polygon extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function updateInstance( ctx : Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
-		var mesh : h3d.scene.Mesh = cast ctx.local3d;
+	override function copy(obj:Prefab) {
+		super.copy(obj);
+		var p : Polygon = cast obj;
+		this.shape = p.shape;
+		this.points = p.points;
+	}
+
+	override function updateInstance(?propName : String) {
+		super.updateInstance(propName);
+		var mesh : h3d.scene.Mesh = cast local3d;
 		mesh.primitive = makePrimitive();
 		mesh.primitive = makePrimitive();
 		#if editor
 		#if editor
-		setColor(ctx, color);
+		setColor(color);
 		if(editor != null)
 		if(editor != null)
 			editor.update(propName);
 			editor.update(propName);
 		#else
 		#else
@@ -98,7 +107,7 @@ class Polygon extends Object3D {
 		return primitive;
 		return primitive;
 	}
 	}
 
 
-	override function localRayIntersection(ctx : hrt.prefab.Context, ray:h3d.col.Ray):Float {
+	override function localRayIntersection(ray:h3d.col.Ray):Float {
 		var prim = makePrimitive();
 		var prim = makePrimitive();
 		var col = prim.getCollider();
 		var col = prim.getCollider();
 		return col.rayIntersection(ray, true);
 		return col.rayIntersection(ray, true);
@@ -234,26 +243,22 @@ class Polygon extends Object3D {
 		return primitive;
 		return primitive;
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
 		var primitive = makePrimitive();
 		var primitive = makePrimitive();
-		var mesh = new h3d.scene.Mesh(primitive, ctx.local3d);
+		var mesh = new h3d.scene.Mesh(primitive, parent3d);
 		mesh.material.props = h3d.mat.MaterialSetup.current.getDefaults("overlay");
 		mesh.material.props = h3d.mat.MaterialSetup.current.getDefaults("overlay");
 		mesh.material.blendMode = Alpha;
 		mesh.material.blendMode = Alpha;
 		mesh.material.mainPass.culling = None;
 		mesh.material.mainPass.culling = None;
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return mesh;
 	}
 	}
 
 
 	#if editor
 	#if editor
-	public function setColor(ctx: Context, color: Int) {
+	public function setColor(color: Int) {
 		if(hrt.prefab.Material.hasOverride(this))
 		if(hrt.prefab.Material.hasOverride(this))
 			return;
 			return;
-		if(ctx.local3d == null)
+		if(local3d == null)
 			return;
 			return;
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
+		var mesh = Std.downcast(local3d, h3d.scene.Mesh);
 		if(mesh != null && hasDebugColor)
 		if(mesh != null && hasDebugColor)
 			hrt.prefab.l3d.Box.setDebugColor(color, mesh.material);
 			hrt.prefab.l3d.Box.setDebugColor(color, mesh.material);
 	}
 	}
@@ -280,8 +285,8 @@ class Polygon extends Object3D {
 		return polyPrim;
 		return polyPrim;
 	}
 	}
 
 
-	public function getPrimitive( ctx : Context ) : h3d.prim.Polygon {
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
+	public function getPrimitive() : h3d.prim.Polygon {
+		var mesh : h3d.scene.Mesh = cast local3d;
 		return Std.downcast(mesh.primitive, h3d.prim.Polygon);
 		return Std.downcast(mesh.primitive, h3d.prim.Polygon);
 	}
 	}
 
 
@@ -293,11 +298,11 @@ class Polygon extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function setSelected( ctx : Context, b : Bool ) {
+	override function setSelected( b : Bool ) {
 		if (!enabled) return true;
 		if (!enabled) return true;
-		super.setSelected(ctx, b);
+		super.setSelected(b);
 		if( editor != null && shape == Custom)
 		if( editor != null && shape == Custom)
-			editor.setSelected(ctx, b);
+			editor.setSelected(b);
 		return true;
 		return true;
 	}
 	}
 
 
@@ -388,7 +393,7 @@ class Polygon extends Object3D {
 					}
 					}
 				}
 				}
 				else if( prevKind == Custom ){
 				else if( prevKind == Custom ){
-					var mesh = Std.downcast(ctx.getContext(this).local3d, h3d.scene.Mesh);
+					var mesh = Std.downcast(local3d, h3d.scene.Mesh);
 					if( mesh.primitive != null ) mesh.primitive.dispose(); // Dispose custom prim
 					if( mesh.primitive != null ) mesh.primitive.dispose(); // Dispose custom prim
 				}
 				}
 
 
@@ -459,7 +464,7 @@ class Polygon extends Object3D {
 				case "Sphere": sphereProps.show();
 				case "Sphere": sphereProps.show();
 				case "Custom":
 				case "Custom":
 					editorProps.show();
 					editorProps.show();
-					setSelected(ctx.getContext(this), true);
+					setSelected(true);
 				default:
 				default:
 			}
 			}
 		}
 		}
@@ -479,5 +484,5 @@ class Polygon extends Object3D {
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("polygon", Polygon);
+	static var _ = Prefab.register("polygon", Polygon);
 }
 }

+ 9 - 11
hrt/prefab/l3d/PrefabSpray.hx

@@ -4,7 +4,7 @@ import hrt.prefab.l3d.Spray;
 
 
 class PrefabSpray extends Spray {
 class PrefabSpray extends Spray {
 
 
-	static var _ = Library.register("prefabSpray", PrefabSpray);
+	static var _ = Prefab.register("prefabSpray", PrefabSpray);
 
 
 }
 }
 
 
@@ -22,16 +22,16 @@ class PrefabSpray extends Spray {
 		return hide.Ide.inst.resourceDir + "/" + PREFAB_SPRAY_CONFIG_FILE;
 		return hide.Ide.inst.resourceDir + "/" + PREFAB_SPRAY_CONFIG_FILE;
 	}
 	}
 
 
-	override function save() {
+	override function save() : Dynamic {
 		clearPreview();
 		clearPreview();
 		return super.save();
 		return super.save();
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "paint-brush", name : "PrefabSpray", hideChildren : p -> return Std.isOfType(p, Object3D) };
 		return { icon : "paint-brush", name : "PrefabSpray", hideChildren : p -> return Std.isOfType(p, Object3D) };
 	}
 	}
 
 
-	override function edit( ectx : EditContext ) {
+	override function edit( ectx : hide.prefab.EditContext ) {
 
 
 		invParent = getAbsPos().clone();
 		invParent = getAbsPos().clone();
 		invParent.invert();
 		invParent.invert();
@@ -308,16 +308,14 @@ class PrefabSpray extends Spray {
 		});
 		});
 
 
 		options.find("#toground").click(function(_) {
 		options.find("#toground").click(function(_) {
-			var ctx = ectx.getContext(this);
-			var mso = cast(ctx.local3d, Spray.SprayObject);
+			var mso = cast(local3d, Spray.SprayObject);
 			undo.change(Custom(function(undo) {
 			undo.change(Custom(function(undo) {
 			}));
 			}));
 			for( c in this.children ) {
 			for( c in this.children ) {
 				var obj = c.to(Object3D);
 				var obj = c.to(Object3D);
 				if( obj == null ) continue;
 				if( obj == null ) continue;
-				setGroundPos(ectx, obj);
-				var ctx = ectx.getContext(obj);
-				if( ctx != null ) obj.applyTransform(ctx.local3d);
+				setGroundPos(obj);
+				obj.applyTransform();
 				wasEdited = true;
 				wasEdited = true;
 			}
 			}
 			mso.redraw();
 			mso.redraw();
@@ -339,7 +337,7 @@ class PrefabSpray extends Spray {
 					prefabs.push(c);
 					prefabs.push(c);
 				}
 				}
 				sceneEditor.deleteElements(prefabs);
 				sceneEditor.deleteElements(prefabs);
-				cast(ectx.getContext(this).local3d, Spray.SprayObject).redraw();
+				cast(local3d, Spray.SprayObject).redraw();
 			}
 			}
 		});
 		});
 
 
@@ -399,7 +397,7 @@ class PrefabSpray extends Spray {
 			currentSources.push(source);
 			currentSources.push(source);
 	}
 	}
 
 
-	static var _ = Library.register("prefabSpray", PrefabSpray);
+	static var _ = Prefab.register("prefabSpray", PrefabSpray);
 
 
 }
 }
 
 

+ 59 - 69
hrt/prefab/l3d/Spline.hx

@@ -70,25 +70,19 @@ class SplinePoint extends Object3D {
 		return parent.to(Spline);
 		return parent.to(Spline);
 	}
 	}
 
 
-	override public function new(?parent) {
-		super(parent);
-		type = "splinePoint";
-	}
-
-	override function makeInstance(ctx:Context):Context {
+	override function makeInstance() : Void {
 		#if editor
 		#if editor
-		ctx = ctx.clone(this);
-		ctx.local3d = createObject(ctx);
-		pointViewer = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), null, ctx.local3d.getScene());
+		local3d = makeObject(shared.current3d);
+		pointViewer = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), null, local3d.getScene());
 		pointViewer.ignoreParentTransform = true;
 		pointViewer.ignoreParentTransform = true;
-		pointViewer.follow = ctx.local3d;
+		pointViewer.follow = local3d;
 		pointViewer.followPositionOnly = true;
 		pointViewer.followPositionOnly = true;
 		pointViewer.name = "pointViewer";
 		pointViewer.name = "pointViewer";
 		pointViewer.material.setDefaultProps("ui");
 		pointViewer.material.setDefaultProps("ui");
 		pointViewer.material.color.set(0,0,1,1);
 		pointViewer.material.color.set(0,0,1,1);
 		pointViewer.material.mainPass.depthTest = Always;
 		pointViewer.material.mainPass.depthTest = Always;
 
 
-		controlPointsViewer = new h3d.scene.Graphics(ctx.local3d);
+		controlPointsViewer = new h3d.scene.Graphics(local3d);
 		controlPointsViewer.name = "controlPointsViewer";
 		controlPointsViewer.name = "controlPointsViewer";
 		controlPointsViewer.lineStyle(4, 0xffffff);
 		controlPointsViewer.lineStyle(4, 0xffffff);
 		controlPointsViewer.material.mainPass.setPassName("ui");
 		controlPointsViewer.material.mainPass.setPassName("ui");
@@ -98,15 +92,15 @@ class SplinePoint extends Object3D {
 		controlPointsViewer.moveTo(1, 0, 0);
 		controlPointsViewer.moveTo(1, 0, 0);
 		controlPointsViewer.lineTo(-1, 0, 0);
 		controlPointsViewer.lineTo(-1, 0, 0);
 
 
-		indexText = new h2d.ObjectFollower(pointViewer, ctx.shared.root2d.getScene());
+		indexText = new h2d.ObjectFollower(pointViewer, shared.current2d.getScene());
 		var t = new h2d.Text(hxd.res.DefaultFont.get(), indexText);
 		var t = new h2d.Text(hxd.res.DefaultFont.get(), indexText);
 		t.textColor = 0xff00ff;
 		t.textColor = 0xff00ff;
 		t.textAlign = Center;
 		t.textAlign = Center;
 		t.dropShadow = { dx : 0.5, dy : 0.5, color : 0x202020, alpha : 1.0 };
 		t.dropShadow = { dx : 0.5, dy : 0.5, color : 0x202020, alpha : 1.0 };
 		t.setScale(2.5);
 		t.setScale(2.5);
-		applyTransform(ctx.local3d);
+		applyTransform();
 		setViewerVisible(false);
 		setViewerVisible(false);
-		obj = new SplinePointObject(ctx.local3d);
+		obj = new SplinePointObject(local3d);
 		obj.onSync = function(rctx) {
 		obj.onSync = function(rctx) {
 			var cam = rctx.camera;
 			var cam = rctx.camera;
 			var gpos = obj.getAbsPos().getPosition();
 			var gpos = obj.getAbsPos().getPosition();
@@ -120,33 +114,33 @@ class SplinePoint extends Object3D {
 			indexText.remove();
 			indexText.remove();
 			pointViewer.remove();
 			pointViewer.remove();
 		}
 		}
-		updateInstance(ctx);
+		updateInstance();
 		#end
 		#end
-		return ctx;
 	}
 	}
 
 
-	override function applyTransform(o : h3d.scene.Object) {
-		super.applyTransform(o);
+	override function applyTransform() {
+		super.applyTransform();
 		#if editor
 		#if editor
 			if (spline.editor != null)
 			if (spline.editor != null)
-				@:privateAccess spline.computeSpline(spline.editor.editContext.getContext(spline));
+				@:privateAccess spline.computeSpline();
 		#end
 		#end
 	}
 	}
 
 
-	override function updateInstance(ctx : Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String) {
+		super.updateInstance(propName);
 		#if editor
 		#if editor
 			if( spline.editor != null ) {
 			if( spline.editor != null ) {
-				spline.editor.setSelected(spline.editor.editContext.getContext(spline), true);
-				spline.editor.update(spline.editor.editContext.getContext(spline));
+				spline.editor.setSelected(true);
+				spline.editor.update();
 			}
 			}
 			for (sp in spline.points) {
 			for (sp in spline.points) {
-				sp.computeName(ctx);
+				sp.computeName();
 			}
 			}
 		#end
 		#end
 	}
 	}
 
 
-	override function removeInstance( ctx : Context) : Bool {
+	// TODO(ces) : Restore
+	/*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
 		haxe.Timer.delay(() -> { // wait for next frame, need the point to be removed from children to recompute spline accurately
 			#if editor
 			#if editor
 				if (spline.editor != null && spline.editor.editContext.getContext(spline) != null)
 				if (spline.editor != null && spline.editor.editContext.getContext(spline) != null)
@@ -154,35 +148,36 @@ class SplinePoint extends Object3D {
 			#end
 			#end
 		}, 0);
 		}, 0);
 		return super.removeInstance(ctx);
 		return super.removeInstance(ctx);
-	}
+	}*/
 
 
 
 
 	#if editor
 	#if editor
 
 
-	public function computeName(ctx) {
+	public function computeName() {
+		if( local3d == null ) return;
 		var index = spline.points.indexOf(this);
 		var index = spline.points.indexOf(this);
 		name = "SplinePoint" + index;
 		name = "SplinePoint" + index;
-		ctx.local3d.name = name;
+		local3d.name = name;
 		if (indexText != null) {
 		if (indexText != null) {
 			var t = Std.downcast(indexText.getChildAt(0), h2d.Text);
 			var t = Std.downcast(indexText.getChildAt(0), h2d.Text);
 			t.text = "" + index;
 			t.text = "" + index;
 		}
 		}
 	}
 	}
 
 
-	override function edit(ctx : EditContext) {
+	override function edit(ctx : hide.prefab.EditContext) {
 		super.edit(ctx);
 		super.edit(ctx);
 		if( spline.editor == null ) {
 		if( spline.editor == null ) {
 			spline.editor = new hide.prefab.SplineEditor(spline, ctx.properties.undo);
 			spline.editor = new hide.prefab.SplineEditor(spline, ctx.properties.undo);
 		}
 		}
 		spline.editor.editContext = ctx;
 		spline.editor.editContext = ctx;
 	}
 	}
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "arrows-v", name : "SplinePoint", allowParent: function(p) return p.to(Spline) != null, allowChildren: function(s) return false};
 		return { icon : "arrows-v", name : "SplinePoint", allowParent: function(p) return p.to(Spline) != null, allowChildren: function(s) return false};
 	}
 	}
 	#end
 	#end
 
 
-	override public function getAbsPos() {
-		var result = obj != null ? obj.getAbsPos() : super.getAbsPos();
+	override public function getAbsPos( followRefs : Bool = false ) {
+		var result = obj != null ? obj.getAbsPos() : super.getAbsPos(followRefs);
 		if (offset != null) result.multiply(result, offset);
 		if (offset != null) result.multiply(result, offset);
 		return result;
 		return result;
 	}
 	}
@@ -224,7 +219,7 @@ class SplinePoint extends Object3D {
 		pointViewer.material.color.setColor(color);
 		pointViewer.material.color.setColor(color);
 	}
 	}
 
 
-	static var _ = hrt.prefab.Library.register("splinePoint", SplinePoint);
+	static var _ = Prefab.register("splinePoint", SplinePoint);
 }
 }
 
 
 class Spline extends Object3D {
 class Spline extends Object3D {
@@ -276,8 +271,8 @@ class Spline extends Object3D {
 	#end
 	#end
 	public var wasEdited = false;
 	public var wasEdited = false;
 
 
-	override function save() {
-		var obj : Dynamic = super.save();
+	override function save() : Dynamic {
+		var obj = super.save();
 
 
 		obj.shape = shape.getIndex();
 		obj.shape = shape.getIndex();
 		return obj;
 		return obj;
@@ -299,6 +294,12 @@ class Spline extends Object3D {
 		shape = obj.shape == null ? Linear : CurveShape.createByIndex(obj.shape);
 		shape = obj.shape == null ? Linear : CurveShape.createByIndex(obj.shape);
 	}
 	}
 
 
+	override function copy(obj : Prefab) {
+		super.copy(obj);
+		var p : Spline = cast obj;
+		this.shape = p.shape;
+	}
+
 	// Generate the splineData from a matrix, can't move the spline after that
 	// Generate the splineData from a matrix, can't move the spline after that
 	public function makeFromMatrix( m : h3d.Matrix ) {
 	public function makeFromMatrix( m : h3d.Matrix ) {
 		var tmp = new h3d.Matrix();
 		var tmp = new h3d.Matrix();
@@ -310,39 +311,29 @@ class Spline extends Object3D {
 		computeSplineData();
 		computeSplineData();
 	}
 	}
 
 
-	override public function make( ctx : Context ) : Context {
-		super.make(ctx);
-		var curCtx = ctx.shared.getContexts(this)[0];
-		updateInstance(curCtx);
-		return curCtx;
-	}
-
-
-	override function makeInstance( ctx : hrt.prefab.Context ) : hrt.prefab.Context {
-		var ctx = ctx.clone(this);
-		ctx.local3d = createObject(ctx);
-		ctx.local3d.name = name;
+	override function makeInstance() : Void {
+		local3d = makeObject(shared.current3d);
+		local3d.name = name;
 
 
 		// Backward compatibility
 		// Backward compatibility
 		for( pd in pointsData ) {
 		for( pd in pointsData ) {
-			var sp = new SplinePoint(this);
+			var sp = new SplinePoint(this, null);
 			sp.setTransform(pd);
 			sp.setTransform(pd);
 		}
 		}
 
 
 		if( points.length == 0 )
 		if( points.length == 0 )
-			new SplinePoint(this);
+			new SplinePoint(this, null);
 
 
-		updateInstance(ctx);
-		return ctx;
+		updateInstance();
 	}
 	}
 
 
-	override function updateInstance( ctx : hrt.prefab.Context , ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 		#if editor
 		#if editor
 		if( editor != null )
 		if( editor != null )
-			editor.update(ctx, propName);
+			editor.update(propName);
 		#end
 		#end
-		computeSpline(ctx);
+		computeSpline();
 	}
 	}
 
 
 	// Return an interpolation of two samples at t, 0 <= t <= 1
 	// Return an interpolation of two samples at t, 0 <= t <= 1
@@ -376,7 +367,7 @@ class Spline extends Object3D {
 					tangent.load(data.samples[s1].tangent);
 					tangent.load(data.samples[s1].tangent);
 			}
 			}
 			else {
 			else {
-				var t = (l - s1);
+				var t = (l - s1) / segmentLength;
 				pos.lerp(data.samples[s1].pos, data.samples[s2].pos, t);
 				pos.lerp(data.samples[s1].pos, data.samples[s2].pos, t);
 				if(tangent != null)
 				if(tangent != null)
 					tangent.lerp(data.samples[s1].tangent, data.samples[s2].tangent, t);
 					tangent.lerp(data.samples[s1].tangent, data.samples[s2].tangent, t);
@@ -607,8 +598,7 @@ class Spline extends Object3D {
 		return p1.sub(p0).scaled(3 * (1 - t) * (1 - t)).add(p2.sub(p1).scaled(6 * (1 - t) * t)).add(p3.sub(p2).scaled(3 * t * t)).normalized();
 		return p1.sub(p0).scaled(3 * (1 - t) * (1 - t)).add(p2.sub(p1).scaled(6 * (1 - t) * t)).add(p3.sub(p2).scaled(3 * t * t)).normalized();
 	}
 	}
 
 
-	function generateSplineGraph( ctx : hrt.prefab.Context ) {
-		if (ctx == null) return;
+	function generateSplineGraph() {
 
 
 		if( !showSpline ) {
 		if( !showSpline ) {
 			if( lineGraphics != null ) {
 			if( lineGraphics != null ) {
@@ -619,7 +609,7 @@ class Spline extends Object3D {
 		}
 		}
 
 
 		if( lineGraphics == null ) {
 		if( lineGraphics == null ) {
-			lineGraphics = new h3d.scene.Graphics(ctx.local3d);
+			lineGraphics = new h3d.scene.Graphics(local3d);
 			lineGraphics.lineStyle(lineThickness, color);
 			lineGraphics.lineStyle(lineThickness, color);
 			lineGraphics.name = "lineGraphics";
 			lineGraphics.name = "lineGraphics";
 			lineGraphics.material.mainPass.setPassName("overlay");
 			lineGraphics.material.mainPass.setPassName("overlay");
@@ -631,16 +621,16 @@ class Spline extends Object3D {
 		lineGraphics.clear();
 		lineGraphics.clear();
 		var b = true;
 		var b = true;
 		for( s in data.samples ) {
 		for( s in data.samples ) {
-			var localPos = ctx.local3d.globalToLocal(s.pos.clone());
+			var localPos = lineGraphics.globalToLocal(s.pos.clone());
 			b ? lineGraphics.moveTo(localPos.x, localPos.y, localPos.z) : lineGraphics.lineTo(localPos.x, localPos.y, localPos.z);
 			b ? lineGraphics.moveTo(localPos.x, localPos.y, localPos.z) : lineGraphics.lineTo(localPos.x, localPos.y, localPos.z);
 			b = false;
 			b = false;
 		}
 		}
 	}
 	}
 
 
-	public function computeSpline(ctx : hrt.prefab.Context) {
+	public function computeSpline() {
 		computeSplineData();
 		computeSplineData();
 		#if editor
 		#if editor
-			generateSplineGraph(ctx);
+			generateSplineGraph();
 		#end
 		#end
 	}
 	}
 
 
@@ -650,16 +640,16 @@ class Spline extends Object3D {
 		if( b ) wasEdited = true;
 		if( b ) wasEdited = true;
 	}
 	}
 
 
-	override function setSelected( ctx : hrt.prefab.Context , b : Bool ) {
-		super.setSelected(ctx, b);
+	override function setSelected(b : Bool ) {
+		super.setSelected(b);
 
 
 		if( editor != null )
 		if( editor != null )
-			editor.setSelected(ctx, b);
+			editor.setSelected(b);
 
 
 		return true;
 		return true;
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		ctx.properties.add( new hide.Element('
 		ctx.properties.add( new hide.Element('
@@ -688,10 +678,10 @@ class Spline extends Object3D {
 		editor.edit(ctx);
 		editor.edit(ctx);
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
-		return { icon : "arrows-v", name : "Spline", allowChildren: function(s) return Library.isOfType(s, SplinePoint) };
+	override function getHideProps() : hide.prefab.HideProps {
+		return { icon : "arrows-v", name : "Spline", allowChildren: function(s) return Prefab.isOfType(s, SplinePoint) };
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = hrt.prefab.Library.register("spline", Spline);
+	static var _ = Prefab.register("spline", Spline);
 }
 }

+ 31 - 26
hrt/prefab/l3d/SplineMesh.hx

@@ -122,8 +122,8 @@ class SplineMesh extends Spline {
 	var meshMaterial : h3d.mat.Material = null;
 	var meshMaterial : h3d.mat.Material = null;
 	@:s var customPass : String;
 	@:s var customPass : String;
 
 
-	override function save() {
-		var obj : Dynamic = super.save();
+	override function save() : Dynamic {
+		var obj = super.save();
 		obj.meshScale = meshScale;
 		obj.meshScale = meshScale;
 		obj.meshRotation = meshRotation;
 		obj.meshRotation = meshRotation;
 		return obj;
 		return obj;
@@ -135,13 +135,21 @@ class SplineMesh extends Spline {
 		meshRotation = obj.meshRotation == null ? new h3d.Vector(0,0,0) : new h3d.Vector(obj.meshRotation.x, obj.meshRotation.y, obj.meshRotation.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 copy( obj : Dynamic ) {
+		super.copy(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( ?sh:hrt.prefab.Prefab.ContextMake) : Prefab {
+		makeInstance();
+		postMakeInstance();
+
+		return this;
 	}
 	}
 
 
-	override function updateInstance( ctx : hrt.prefab.Context , ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 
 
 		var rot = new h3d.Matrix();
 		var rot = new h3d.Matrix();
 		rot.initRotation(hxd.Math.degToRad(meshRotation.x), hxd.Math.degToRad(meshRotation.y), hxd.Math.degToRad(meshRotation.z));
 		rot.initRotation(hxd.Math.degToRad(meshRotation.x), hxd.Math.degToRad(meshRotation.y), hxd.Math.degToRad(meshRotation.z));
@@ -149,31 +157,28 @@ class SplineMesh extends Spline {
 		scale.initScale(meshScale.x, meshScale.y, meshScale.z);
 		scale.initScale(meshScale.x, meshScale.y, meshScale.z);
 		modelMat.multiply(scale, rot);
 		modelMat.multiply(scale, rot);
 
 
-		createMeshPrimitive(ctx);
-		createMeshBatch(ctx);
-		createBatches(ctx);
+		createMeshPrimitive();
+		createMeshBatch();
+		createBatches();
 
 
 		// Remake the material
 		// Remake the material
 		if( meshBatch != null ) {
 		if( meshBatch != null ) {
-			var emptyCtx = new hrt.prefab.Context();
-			emptyCtx.local3d = meshBatch;
-			emptyCtx.shared = ctx.shared;
 			for( c in @:privateAccess children ) {
 			for( c in @:privateAccess children ) {
 				var mat = Std.downcast(c, Material);
 				var mat = Std.downcast(c, Material);
 				if( mat != null && mat.enabled )
 				if( mat != null && mat.enabled )
-					@:privateAccess mat.makeInstance(emptyCtx);
+					@:privateAccess mat.makeInstance();
 				var shader = Std.downcast(c, Shader);
 				var shader = Std.downcast(c, Shader);
 				if( shader != null && shader.enabled )
 				if( shader != null && shader.enabled )
-					shader.makeInstance(emptyCtx);
+					shader.makeInstance();
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	function createMeshPrimitive( ctx : Context ) {
+	function createMeshPrimitive() {
 		meshPrimitive = null;
 		meshPrimitive = null;
 		meshMaterial = null;
 		meshMaterial = null;
 		if( meshPath != null ) {
 		if( meshPath != null ) {
-			var meshTemplate : h3d.scene.Mesh = ctx.loadModel(meshPath).toMesh();
+			var meshTemplate : h3d.scene.Mesh = shared.loadModel(meshPath).toMesh();
 			if( meshTemplate != null ) {
 			if( meshTemplate != null ) {
 				meshPrimitive = cast meshTemplate.primitive;
 				meshPrimitive = cast meshTemplate.primitive;
 				meshMaterial = cast meshTemplate.material.clone();
 				meshMaterial = cast meshTemplate.material.clone();
@@ -181,7 +186,7 @@ class SplineMesh extends Spline {
 		}
 		}
 	}
 	}
 
 
-	function createMeshBatch( ctx : Context ) {
+	function createMeshBatch() {
 
 
 		if( meshBatch != null ) {
 		if( meshBatch != null ) {
 			meshBatch.remove();
 			meshBatch.remove();
@@ -199,18 +204,18 @@ class SplineMesh extends Spline {
 
 
 			if( customPass != null ) {
 			if( customPass != null ) {
 				for( p in customPass.split(",") ) {
 				for( p in customPass.split(",") ) {
-					if( ctx.local3d.getScene().renderer.getPassByName(p) != null )
+					if( local3d.getScene().renderer.getPassByName(p) != null )
 						splineMaterial.allocPass(p);
 						splineMaterial.allocPass(p);
 				}
 				}
 			}
 			}
 
 
-			meshBatch = new SplineMeshBatch(meshPrimitive, splineMaterial, ctx.local3d);
+			meshBatch = new SplineMeshBatch(meshPrimitive, splineMaterial, local3d);
 			meshBatch.ignoreParentTransform = true;
 			meshBatch.ignoreParentTransform = true;
 			meshBatch.splineData = this.data;
 			meshBatch.splineData = this.data;
 		}
 		}
 	}
 	}
 
 
-	function createBatches( ctx : Context ) {
+	function createBatches() {
 
 
 		if( meshBatch == null )
 		if( meshBatch == null )
 			return;
 			return;
@@ -233,7 +238,7 @@ class SplineMesh extends Spline {
 		}
 		}
 	}
 	}
 
 
-	function createMultiMeshes( ctx : Context ) {
+	function createMultiMeshes() {
 
 
 		for( m in meshes )
 		for( m in meshes )
 			m.remove();
 			m.remove();
@@ -258,7 +263,7 @@ class SplineMesh extends Spline {
 			var s = createShader();
 			var s = createShader();
 			m.material.mainPass.addShader(s);
 			m.material.mainPass.addShader(s);
 			s.splinePos = i * step + minOffset;
 			s.splinePos = i * step + minOffset;
-			ctx.local3d.addChild(m);
+			local3d.addChild(m);
 			meshes.push(m);
 			meshes.push(m);
 		}
 		}
 	}
 	}
@@ -284,7 +289,7 @@ class SplineMesh extends Spline {
 
 
 	#if editor
 	#if editor
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var props = new hide.Element('
 		var props = new hide.Element('
@@ -314,11 +319,11 @@ class SplineMesh extends Spline {
 		ctx.properties.add(props, this, function(pname) { ctx.onChange(this, pname); });
 		ctx.properties.add(props, this, function(pname) { ctx.onChange(this, pname); });
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "arrows-v", name : "SplineMesh" };
 		return { icon : "arrows-v", name : "SplineMesh" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = hrt.prefab.Library.register("splineMesh", SplineMesh);
+	static var _ = Prefab.register("splineMesh", SplineMesh);
 }
 }

+ 14 - 45
hrt/prefab/l3d/SplineMover.hx

@@ -3,7 +3,6 @@ import hrt.prefab.l3d.Spline;
 
 
 class SplineMoverObject extends h3d.scene.Object {
 class SplineMoverObject extends h3d.scene.Object {
 	var prefab : SplineMover;
 	var prefab : SplineMover;
-	var ctx : Context;
 
 
 	var state : Spline.MoveAlongSplineState = new Spline.MoveAlongSplineState();
 	var state : Spline.MoveAlongSplineState = new Spline.MoveAlongSplineState();
 	public var movables : Array<h3d.scene.Object> = [];
 	public var movables : Array<h3d.scene.Object> = [];
@@ -13,10 +12,9 @@ class SplineMoverObject extends h3d.scene.Object {
 	#end
 	#end
 
 
 
 
-	override public function new(?parent : h3d.scene.Object, prefab : SplineMover, ctx:Context) {
+	override public function new(?parent : h3d.scene.Object, prefab : SplineMover) {
 		super(parent);
 		super(parent);
 		this.prefab = prefab;
 		this.prefab = prefab;
-		this.ctx = ctx;
 
 
 		#if editor
 		#if editor
 		var prim = new h3d.prim.Sphere();
 		var prim = new h3d.prim.Sphere();
@@ -62,59 +60,30 @@ class SplineMover extends Spline {
 	#if editor
 	#if editor
 	@:s public var showDebug : Bool = true;
 	@:s public var showDebug : Bool = true;
 	#end
 	#end
-	override public function new(?parent) {
-		super(parent);
-	}
 
 
-
-	override function createObject(ctx:Context) {
-		var obj = new SplineMoverObject(ctx.local3d, this, ctx);
-		return obj;
+	override function makeObject(parent:h3d.scene.Object) {
+		return new SplineMoverObject(parent, this);
 	}
 	}
 
 
-	override public function make( ctx : Context ) : Context {
-		if( !enabled )
-			return ctx;
-		if( ctx == null ) {
-			ctx = new Context();
-			ctx.init();
-		}
-		var fromRef = #if editor ctx.shared.parent != null #else true #end;
-		if (fromRef && editorOnly #if editor || inGameOnly #end)
-			return ctx;
-		ctx = makeInstance(ctx);
-		for( c in children ){
-			var newCtx = null;
-			if( ctx.shared.customMake == null )
-				newCtx = c.make(ctx);
-			else if( c.enabled )
-				ctx.shared.customMake(ctx, c);
-
-			if (newCtx!= null && newCtx.local3d != null && Std.downcast(c, SplinePoint) == null) {
-				(cast ctx.local3d:SplineMoverObject).movables.push(newCtx.local3d);
-			}
+	override function makeChild(p:Prefab) {
+		super.makeChild(p);
+		var l3d = Object3D.getLocal3d(p);
+		if (l3d != null && p.to(SplinePoint) == null) {
+			(cast local3d:SplineMoverObject).movables.push(l3d);
 		}
 		}
-
-		// Pre-heat spline
-		(cast ctx.local3d:SplineMoverObject).updatePoint(1.0);
-
-		// Original Spline make
-		var curCtx = ctx.shared.getContexts(this)[0];
-		updateInstance(curCtx);
-		return curCtx;
 	}
 	}
 
 
-	override function updateInstance(ctx:Context, ?propName:String) {
-		super.updateInstance(ctx, propName);
-
+	override function postMakeInstance() {
+		super.postMakeInstance();
+		(cast local3d:SplineMoverObject).updatePoint(1.0);
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "arrows-v", name : "Spline Mover", allowChildren: function(s) return true};
 		return { icon : "arrows-v", name : "Spline Mover", allowChildren: function(s) return true};
 	}
 	}
 
 
-	override function edit(ctx:EditContext) {
+	override function edit(ctx:hide.prefab.EditContext) {
 		ctx.properties.add( new hide.Element('
 		ctx.properties.add( new hide.Element('
 			<p>Important ! Save then reload when you add a child prefab to animate in order to see the animation ! It\'s a known bug.</p>
 			<p>Important ! Save then reload when you add a child prefab to animate in order to see the animation ! It\'s a known bug.</p>
 		'));
 		'));
@@ -130,6 +99,6 @@ class SplineMover extends Spline {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = hrt.prefab.Library.register("splineMover", SplineMover);
+	static var _ = hrt.prefab.Prefab.register("splineMover", SplineMover);
 
 
 }
 }

+ 40 - 58
hrt/prefab/l3d/Spray.hx

@@ -17,18 +17,17 @@ class Spray extends Object3D {
 
 
 	@:s var sources : Array<{ path : String }> = [];
 	@:s var sources : Array<{ path : String }> = [];
 
 
-	override function createObject( ctx : Context ) {
-		var spray = new SprayObject(ctx.local3d);
+	override function makeObject(parent3d: h3d.scene.Object ) : h3d.scene.Object {
+		var spray = new SprayObject(parent3d);
 		return spray;
 		return spray;
 	}
 	}
 
 
-	override function make( ctx : Context ) {
-		if( !enabled )
-			return ctx;
+	override function makeInstance() {
+		super.makeInstance();
 		children.sort(function(c1, c2) {
 		children.sort(function(c1, c2) {
 			return Std.isOfType(c1, Object3D) ? -1 : 1;
 			return Std.isOfType(c1, Object3D) ? -1 : 1;
 		});
 		});
-		return super.make(ctx);
+
 	}
 	}
 }
 }
 
 
@@ -126,8 +125,6 @@ class Spray extends Object3D {
 	var lastItemPos : h3d.col.Point;
 	var lastItemPos : h3d.col.Point;
 	var invParent : h3d.Matrix;
 	var invParent : h3d.Matrix;
 
 
-	var shared : ContextShared;
-
 	function clearPreview() {
 	function clearPreview() {
 		// prevent saving preview
 		// prevent saving preview
 		if( previewItems.length > 0 ) {
 		if( previewItems.length > 0 ) {
@@ -162,7 +159,7 @@ class Spray extends Object3D {
 	}
 	}
 
 
 
 
-	function setGroundPos( ectx : EditContext, obj : Object3D = null, absPos : h3d.col.Point = null ) : { mz : Float, rotX : Float, rotY : Float, rotZ : Float } {
+	function setGroundPos(obj : Object3D = null, absPos : h3d.col.Point = null ) : { mz : Float, rotX : Float, rotY : Float, rotZ : Float } {
 		if (absPos == null && obj == null)
 		if (absPos == null && obj == null)
 			throw "setGroundPos should use either object or absPos";
 			throw "setGroundPos should use either object or absPos";
 		var tx : Float; var ty : Float; var tz : Float;
 		var tx : Float; var ty : Float; var tz : Float;
@@ -176,7 +173,7 @@ class Spray extends Object3D {
 			tz = obj.getAbsPos().tz;
 			tz = obj.getAbsPos().tz;
 		}
 		}
 		var config = currentConfig;
 		var config = currentConfig;
-		var groundZ = ectx.positionToGroundZ(tx, ty);
+		var groundZ = shared.scene.editor.getZ(tx, ty);
 		var mz = config.zOffset + groundZ - tz;
 		var mz = config.zOffset + groundZ - tz;
 		if ( obj != null )
 		if ( obj != null )
 			obj.z += mz;
 			obj.z += mz;
@@ -184,7 +181,7 @@ class Spray extends Object3D {
 		var tilt = config.tiltAmount;
 		var tilt = config.tiltAmount;
 
 
 		inline function getPoint(dx,dy) {
 		inline function getPoint(dx,dy) {
-			var dz = ectx.positionToGroundZ(tx + 0.1 * dx, ty + 0.1 * dy) - groundZ;
+			var dz = shared.scene.editor.getZ(tx + 0.1 * dx, ty + 0.1 * dy) - groundZ;
 			return new h3d.col.Point(dx*0.1, dy*0.1, dz * orient);
 			return new h3d.col.Point(dx*0.1, dy*0.1, dz * orient);
 		}
 		}
 
 
@@ -212,10 +209,9 @@ class Spray extends Object3D {
 	var sprayedItems : Array<hrt.prefab.Prefab> = [];
 	var sprayedItems : Array<hrt.prefab.Prefab> = [];
 	var selectElement : hide.Element;
 	var selectElement : hide.Element;
 
 
-	function createInteractiveBrush(ectx : EditContext) {
+	function createInteractiveBrush(ectx : hide.prefab.EditContext) {
 		if (!enabled) return;
 		if (!enabled) return;
-		var ctx = ectx.getContext(this);
-		var s2d = ctx.shared.root2d.getScene();
+		var s2d = shared.root2d.getScene();
 		interactive = new h2d.Interactive(10000, 10000, s2d);
 		interactive = new h2d.Interactive(10000, 10000, s2d);
 		interactive.propagateEvents = true;
 		interactive.propagateEvents = true;
 		interactive.cancelEvents = false;
 		interactive.cancelEvents = false;
@@ -231,7 +227,7 @@ class Spray extends Object3D {
 					if( !K.isDown( K.SHIFT) ) {
 					if( !K.isDown( K.SHIFT) ) {
 						clearPreview();
 						clearPreview();
 						var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
 						var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-						previewItemsAround(ectx, ctx, worldPos);
+						previewItemsAround(ectx, worldPos);
 					}
 					}
 					lastSpray = Date.now().getTime();
 					lastSpray = Date.now().getTime();
 					lastItemPos = null;
 					lastItemPos = null;
@@ -243,7 +239,7 @@ class Spray extends Object3D {
 				currentConfig.rotation = currentConfig.rotation % 360;
 				currentConfig.rotation = currentConfig.rotation % 360;
 				clearPreview();
 				clearPreview();
 				var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
 				var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-				previewItemsAround(ectx, ctx, worldPos);
+				previewItemsAround(ectx, worldPos);
 			}
 			}
 
 
 			if (e.keyCode == K.D) {
 			if (e.keyCode == K.D) {
@@ -252,7 +248,7 @@ class Spray extends Object3D {
 				currentConfig.rotation = currentConfig.rotation % 360;
 				currentConfig.rotation = currentConfig.rotation % 360;
 				clearPreview();
 				clearPreview();
 				var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
 				var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-				previewItemsAround(ectx, ctx, worldPos);
+				previewItemsAround(ectx, worldPos);
 			}
 			}
 		}
 		}
 
 
@@ -261,10 +257,10 @@ class Spray extends Object3D {
 			sprayEnable = true;
 			sprayEnable = true;
 			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
 			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
 			if( K.isDown( K.SHIFT) )
 			if( K.isDown( K.SHIFT) )
-				removeItemsAround(ctx, worldPos);
+				removeItemsAround(worldPos);
 			else {
 			else {
 				lastItemPos = worldPos.clone();
 				lastItemPos = worldPos.clone();
-				addItems(ctx);
+				addItems();
 			}
 			}
 		};
 		};
 
 
@@ -281,7 +277,7 @@ class Spray extends Object3D {
 					else {
 					else {
 						sceneEditor.addElements(addedModels, false, true, false);
 						sceneEditor.addElements(addedModels, false, true, false);
 					}
 					}
-					cast(ctx.local3d,SprayObject).redraw();
+					cast(local3d,SprayObject).redraw();
 				}));
 				}));
 				sprayedItems = [];
 				sprayedItems = [];
 			}
 			}
@@ -298,12 +294,12 @@ class Spray extends Object3D {
 				return;
 				return;
 			}
 			}
 
 
-			drawCircle(ctx, worldPos.x, worldPos.y, worldPos.z, (shiftPressed) ? currentConfig.deleteRadius : currentConfig.radius, 5, (shiftPressed) ? 9830400 : 38400);
+			drawCircle(worldPos.x, worldPos.y, worldPos.z, (shiftPressed) ? currentConfig.deleteRadius : currentConfig.radius, 5, (shiftPressed) ? 9830400 : 38400);
 
 
 			if (lastSpray < Date.now().getTime() - 100) {
 			if (lastSpray < Date.now().getTime() - 100) {
 				clearPreview();
 				clearPreview();
 				if( !shiftPressed ) {
 				if( !shiftPressed ) {
-					previewItemsAround(ectx, ctx, worldPos);
+					previewItemsAround(ectx, worldPos);
 				}
 				}
 
 
 				if( K.isDown( K.MOUSE_LEFT) ) {
 				if( K.isDown( K.MOUSE_LEFT) ) {
@@ -311,17 +307,17 @@ class Spray extends Object3D {
 
 
 					if (sprayEnable) {
 					if (sprayEnable) {
 						if( shiftPressed ) {
 						if( shiftPressed ) {
-							removeItemsAround(ctx, worldPos);
+							removeItemsAround(worldPos);
 						} else {
 						} else {
 							if (currentConfig.density == 1) {
 							if (currentConfig.density == 1) {
 								if(lastItemPos.distance(worldPos) > currentConfig.step) {
 								if(lastItemPos.distance(worldPos) > currentConfig.step) {
 									lastItemPos = worldPos.clone();
 									lastItemPos = worldPos.clone();
-									addItems(ctx);
+									addItems();
 								}
 								}
 							}
 							}
 							else {
 							else {
 								lastItemPos = worldPos.clone();
 								lastItemPos = worldPos.clone();
-								addItems(ctx);
+								addItems();
 							}
 							}
 						}
 						}
 					}
 					}
@@ -332,11 +328,7 @@ class Spray extends Object3D {
 
 
 	}
 	}
 
 
-	override function removeInstance(ctx : Context):Bool {
-		removeInteractiveBrush();
-		return super.removeInstance(ctx);
-	}
-	override function setSelected( ctx : Context, b : Bool ) {
+	override function setSelected(b : Bool ) {
 		if( !b )
 		if( !b )
 			removeInteractiveBrush();
 			removeInteractiveBrush();
 		return false;
 		return false;
@@ -371,7 +363,7 @@ class Spray extends Object3D {
 	var lastPos : h3d.col.Point;
 	var lastPos : h3d.col.Point;
 	var lastItemId = -1;
 	var lastItemId = -1;
 	var lastSprayedObj : h3d.scene.Object;
 	var lastSprayedObj : h3d.scene.Object;
-	function previewItemsAround(ectx : hide.prefab.EditContext, ctx : Context, point : h3d.col.Point) {
+	function previewItemsAround(ectx : hide.prefab.EditContext, point : h3d.col.Point) {
 		if (currentSources.length == 0) {
 		if (currentSources.length == 0) {
 			return;
 			return;
 		}
 		}
@@ -463,11 +455,11 @@ class Spray extends Object3D {
 				var newPrefab : hrt.prefab.Object3D = null;
 				var newPrefab : hrt.prefab.Object3D = null;
 
 
 				if (itemUsed.isRef) {
 				if (itemUsed.isRef) {
-					var refPrefab = new hrt.prefab.Reference(this);
+					var refPrefab = new hrt.prefab.Reference(this, null);
 					refPrefab.source = itemUsed.path;
 					refPrefab.source = itemUsed.path;
 					newPrefab = refPrefab;
 					newPrefab = refPrefab;
 				} else {
 				} else {
-					var model = new hrt.prefab.Model(this);
+					var model = new hrt.prefab.Model(this, null);
 					model.source = itemUsed.path;
 					model.source = itemUsed.path;
 					newPrefab = model;
 					newPrefab = model;
 				}
 				}
@@ -489,7 +481,7 @@ class Spray extends Object3D {
 				localMat.multiply(localMat, invParent);
 				localMat.multiply(localMat, invParent);
 
 
 				newPrefab.setTransform(localMat);
 				newPrefab.setTransform(localMat);
-				setGroundPos(ectx, newPrefab);
+				setGroundPos(newPrefab);
 
 
 				previewItems.push(newPrefab);
 				previewItems.push(newPrefab);
 				currentPivots.push(new h2d.col.Point(newPrefab.x, newPrefab.y));
 				currentPivots.push(new h2d.col.Point(newPrefab.x, newPrefab.y));
@@ -501,18 +493,18 @@ class Spray extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	function addItems(ctx : Context) {
+	function addItems() {
 		lastItemId = -1;
 		lastItemId = -1;
 		if (previewItems.length > 0) {
 		if (previewItems.length > 0) {
 			wasEdited = true;
 			wasEdited = true;
 			sprayedItems = sprayedItems.concat(previewItems);
 			sprayedItems = sprayedItems.concat(previewItems);
 			previewItems = [];
 			previewItems = [];
 			clearBrushes();
 			clearBrushes();
-			cast(ctx.local3d,SprayObject).redraw();
+			cast(local3d,SprayObject).redraw();
 		}
 		}
 	}
 	}
 
 
-	function removeItemsAround(ctx : Context, point : h3d.col.Point) {
+	function removeItemsAround(point : h3d.col.Point) {
 		var vecRelat = point.toVector();
 		var vecRelat = point.toVector();
 		vecRelat.transform(invParent);
 		vecRelat.transform(invParent);
 		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
 		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
@@ -538,30 +530,30 @@ class Spray extends Object3D {
 
 
 		if( needRedraw ) {
 		if( needRedraw ) {
 			clearBrushes();
 			clearBrushes();
-			cast(ctx.local3d,SprayObject).redraw();
+			cast(local3d,SprayObject).redraw();
 		}
 		}
 	}
 	}
 
 
-	public function drawCircle(ctx : Context, originX : Float, originY : Float, originZ : Float, radius: Float, thickness: Float, color) {
+	public function drawCircle(originX : Float, originY : Float, originZ : Float, radius: Float, thickness: Float, color) {
 		var newColor = h3d.Vector4.fromColor(color);
 		var newColor = h3d.Vector4.fromColor(color);
 		if (gBrushes == null || gBrushes.length == 0 || gBrushes[0].scaleX != radius || gBrushes[0].material.color != newColor) {
 		if (gBrushes == null || gBrushes.length == 0 || gBrushes[0].scaleX != radius || gBrushes[0].material.color != newColor) {
 			clearBrushes();
 			clearBrushes();
 			gBrushes = [];
 			gBrushes = [];
-			var gBrush = new h3d.scene.Mesh(makePrimCircle(32, 0.95), ctx.local3d);
+			var gBrush = new h3d.scene.Mesh(makePrimCircle(32, 0.95), local3d);
 			gBrush.scaleX = gBrush.scaleY = radius;
 			gBrush.scaleX = gBrush.scaleY = radius;
 			gBrush.ignoreParentTransform = true;
 			gBrush.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
 			var pass = gBrush.material.mainPass;
 			pass.setPassName("overlay");
 			pass.setPassName("overlay");
-			pass.depthTest = Always;
+			pass.depthTest = h3d.mat.Data.Compare.Always;
 			pass.depthWrite = false;
 			pass.depthWrite = false;
 			gBrush.material.shadows = false;
 			gBrush.material.shadows = false;
 			gBrush.material.color = newColor;
 			gBrush.material.color = newColor;
 			gBrushes.push(gBrush);
 			gBrushes.push(gBrush);
-			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), ctx.local3d);
+			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), local3d);
 			gBrush.ignoreParentTransform = true;
 			gBrush.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
 			var pass = gBrush.material.mainPass;
 			pass.setPassName("overlay");
 			pass.setPassName("overlay");
-			pass.depthTest = Always;
+			pass.depthTest = h3d.mat.Data.Compare.Always;
 			pass.depthWrite = false;
 			pass.depthWrite = false;
 			gBrush.material.shadows = false;
 			gBrush.material.shadows = false;
 			gBrush.material.color = newColor;
 			gBrush.material.color = newColor;
@@ -575,23 +567,13 @@ class Spray extends Object3D {
 		}
 		}
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		ctx.local3d = new SprayObject(this, ctx.local3d);
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
-	}
-
-	override function make(ctx:Context):Context {
-		if( !enabled )
-			return ctx;
-		return super.make(ctx);
+	override function makeObject(parent3d: h3d.scene.Object ) : h3d.scene.Object {
+		return new SprayObject(this, parent3d);
 	}
 	}
 
 
-	override function applyTransform(o : h3d.scene.Object) {
-		super.applyTransform(o);
-		cast(o, SprayObject).redraw();
+	override function applyTransform() {
+		super.applyTransform();
+		cast(local3d, SprayObject).redraw();
 	}
 	}
 
 
 
 

+ 21 - 29
hrt/prefab/l3d/Text3D.hx

@@ -98,18 +98,15 @@ class Text3D extends Object3D {
 
 
 	@:s public var contentText : String = "Empty string";
 	@:s public var contentText : String = "Empty string";
 
 
-	public function new( ?parent ) {
-		super(parent);
-		type = "text3d";
-	}
+	public var text2d : h2d.Text = null;
 
 
 	#if editor
 	#if editor
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "font", name : "Text3D" };
 		return { icon : "font", name : "Text3D" };
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
@@ -124,7 +121,7 @@ class Text3D extends Object3D {
 		if (this.pathFont != null && this.pathFont.length > 0) tfile.path = this.pathFont;
 		if (this.pathFont != null && this.pathFont.length > 0) tfile.path = this.pathFont;
 		tfile.onChange = function() {
 		tfile.onChange = function() {
 			this.pathFont = tfile.path;
 			this.pathFont = tfile.path;
-			updateInstance(ctx.getContext(this), "pathFont");
+			updateInstance("pathFont");
 		}
 		}
         new hide.Element('<dt>Align</dt>').appendTo(gr);
         new hide.Element('<dt>Align</dt>').appendTo(gr);
 		var element = new hide.Element('<dd></dd>').appendTo(gr);
 		var element = new hide.Element('<dd></dd>').appendTo(gr);
@@ -136,21 +133,21 @@ class Text3D extends Object3D {
 			leftAlign.attr("disabled", "true");
 			leftAlign.attr("disabled", "true");
 			middleAlign.removeAttr("disabled");
 			middleAlign.removeAttr("disabled");
 			rightAlign.removeAttr("disabled");
 			rightAlign.removeAttr("disabled");
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		});
 		middleAlign.on("click", function(e) {
 		middleAlign.on("click", function(e) {
 			align = 1;
 			align = 1;
 			leftAlign.removeAttr("disabled");
 			leftAlign.removeAttr("disabled");
 			middleAlign.attr("disabled", "true");
 			middleAlign.attr("disabled", "true");
 			rightAlign.removeAttr("disabled");
 			rightAlign.removeAttr("disabled");
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		});
 		rightAlign.on("click", function(e) {
 		rightAlign.on("click", function(e) {
 			align = 2;
 			align = 2;
 			leftAlign.removeAttr("disabled");
 			leftAlign.removeAttr("disabled");
 			middleAlign.removeAttr("disabled");
 			middleAlign.removeAttr("disabled");
 			rightAlign.attr("disabled", "true");
 			rightAlign.attr("disabled", "true");
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		});
 
 
 		new hide.Element('<dt>Color</dt><dd><input type="color" field="color" /></dd>').appendTo(gr);
 		new hide.Element('<dt>Color</dt><dd><input type="color" field="color" /></dd>').appendTo(gr);
@@ -173,28 +170,28 @@ class Text3D extends Object3D {
 
 
 	#end
 	#end
 
 
-	override function updateInstance( ctx : Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String) {
+		super.updateInstance(propName);
 		if (pathFont == null || pathFont.length == 0) {
 		if (pathFont == null || pathFont.length == 0) {
 			return;
 			return;
 		}
 		}
 		var text = loadText();
 		var text = loadText();
 		if (text == null || text.length == 0)
 		if (text == null || text.length == 0)
 			return;
 			return;
-		var mesh : h3d.scene.Mesh = cast ctx.local3d;
+		var mesh : h3d.scene.Mesh = cast local3d;
 		var h2dFont = loadFont();
 		var h2dFont = loadFont();
-		var h2dText = (cast ctx.local2d : h2d.Text);
+		var h2dText = null/*(cast local2d : h2d.Text)*/;
 		h2dText.font = h2dFont;
 		h2dText.font = h2dFont;
 		h2dText.letterSpacing = letterSpacing;
 		h2dText.letterSpacing = letterSpacing;
 		h2dText.text = text;
 		h2dText.text = text;
 		h2dText.smooth = true;
 		h2dText.smooth = true;
         h2dText.textAlign = switch (align) {
         h2dText.textAlign = switch (align) {
 			case 1:
 			case 1:
-				Center;
+				h2d.Text.Align.Center;
 			case 2:
 			case 2:
-				Right;
+				h2d.Text.Align.Right;
 			default:
 			default:
-				Left;
+				h2d.Text.Align.Left;
 		}
 		}
 		@:privateAccess h2dText.glyphs.content = (cast mesh.primitive : Text3DPrimitive);
 		@:privateAccess h2dText.glyphs.content = (cast mesh.primitive : Text3DPrimitive);
 		@:privateAccess {
 		@:privateAccess {
@@ -247,19 +244,14 @@ class Text3D extends Object3D {
 		return null;
 		return null;
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var mesh = new h3d.scene.Mesh(new Text3DPrimitive(), ctx.local3d);
+	override function makeObject(parent3d : h3d.scene.Object) : h3d.scene.Object {
+		var mesh = new h3d.scene.Mesh(new Text3DPrimitive(), parent3d);
 		mesh.material.blendMode = Alpha;
 		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;
+		text2d = new h2d.Text(hxd.res.DefaultFont.get(), findFirstLocal2d());
+		@:privateAccess text2d.glyphs.content = new Text3DPrimitive();
+		text2d.name = name;
+		return mesh;
 	}
 	}
 
 
-	static var _ = Library.register("text3d", Text3D);
+	static var _ = Prefab.register("text3d", Text3D);
 }
 }

+ 9 - 18
hrt/prefab/l3d/Trail.hx

@@ -4,37 +4,28 @@ class Trail extends Object3D {
 
 
 	@:s var data : Dynamic;
 	@:s var data : Dynamic;
 
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		data = new h3d.scene.Trail().save();
 		data = new h3d.scene.Trail().save();
 	}
 	}
 
 
-	public function create( ?parent : h3d.scene.Object ) {
-		var tr = new h3d.scene.Trail(parent);
+	override public function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
+		var tr = new h3d.scene.Trail(parent3d);
 		tr.load(data);
 		tr.load(data);
-		applyTransform(tr);
-		tr.name = name;
+		applyTransform();
 		return tr;
 		return tr;
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var tr = create(ctx.local3d);
-		ctx.local3d = tr;
-		return ctx;
-	}
-
 	#if editor
 	#if editor
 
 
-	override function getHideProps():HideProps {
+	override function getHideProps():hide.prefab.HideProps {
 		return { icon : "toggle-on", name : "Trail" };
 		return { icon : "toggle-on", name : "Trail" };
 	}
 	}
 
 
-	override public function edit(ctx:EditContext) {
+	override public function edit(ctx:hide.prefab.EditContext) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
-		var trailContext = ctx.getContext(this);
-		var trail = trailContext == null ? create(null) : Std.downcast(trailContext.local3d, h3d.scene.Trail);
+		var trail = Std.downcast(local3d, h3d.scene.Trail);
 		var props = ctx.properties.add(new hide.Element('
 		var props = ctx.properties.add(new hide.Element('
 		<div class="group" name="Material">
 		<div class="group" name="Material">
 		</div>
 		</div>
@@ -58,6 +49,6 @@ class Trail extends Object3D {
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("trail", Trail);
+	static var _ = Prefab.register("trail", Trail);
 
 
 }
 }

+ 25 - 28
hrt/prefab/l3d/Trails.hx

@@ -82,6 +82,7 @@ class TrailObj extends h3d.scene.Mesh {
 	var bounds : h3d.col.Bounds;
 	var bounds : h3d.col.Bounds;
 	var prefab : Trails;
 	var prefab : Trails;
 
 
+
 	public var timeScale : Float = 1.0;
 	public var timeScale : Float = 1.0;
 
 
 	#if editor
 	#if editor
@@ -775,27 +776,22 @@ class TrailsSubTailObj extends h3d.scene.Object {
 
 
 class TrailsSubTrail extends Object3D {
 class TrailsSubTrail extends Object3D {
 
 
-	function new(?parent) {
-		super(parent);
-		name = "SubTrail";
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+		var obj = new TrailsSubTailObj(parent3d);
+		return obj;
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var obj = new TrailsSubTailObj(ctx.local3d);
-		applyTransform(obj);
-		obj.name = name;
-		ctx.local3d = obj;
-		return ctx;
+	override function updateInstance(?props: String) {
+		applyTransform();
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps():HideProps {
-		return { icon : "toggle-on", name : "Sub Trail" , allowChildren: (name) -> name == "Trails"};
+	override function getHideProps():hide.prefab.HideProps {
+		return { icon : "toggle-on", name : "Sub Trail" , allowChildren: (name) -> name == Trails};
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("SubTrail", TrailsSubTrail);
+	static var _ = Prefab.register("SubTrail", TrailsSubTrail);
 
 
 }
 }
 
 
@@ -809,43 +805,44 @@ class Trails extends Object3D {
 	@:s public var minSpeed : Float = 10.0;
 	@:s public var minSpeed : Float = 10.0;
 	@:s public var maxSpeed : Float = 1000.0;
 	@:s public var maxSpeed : Float = 1000.0;
 
 
-
 	@:s public var uvMode : UVMode = EStretch;
 	@:s public var uvMode : UVMode = EStretch;
 	@:s public var uvStretch: Float = 1.0;
 	@:s public var uvStretch: Float = 1.0;
 	@:s public var uvRepeat : UVRepeat = EMod;
 	@:s public var uvRepeat : UVRepeat = EMod;
 
 
-	function new(?parent) {
-		super(parent);
-		name = "Trails";
+	// TODO(ces) : find better way to do that
+	// Override this before calling make() to change how many trails are instancied
+	public var numTrails : Int = 1;
 
 
+	function new(parent, shared) {
+		super(parent, shared);
+		name = "Trails";
 	}
 	}
 
 
 	public function create( ?parent : h3d.scene.Object, ?numTrails : Int ) {
 	public function create( ?parent : h3d.scene.Object, ?numTrails : Int ) {
 		var tr = new TrailObj(this, parent, numTrails);
 		var tr = new TrailObj(this, parent, numTrails);
-		applyTransform(tr);
+		applyTransform();
 		tr.name = name;
 		tr.name = name;
 		tr.updateShader();
 		tr.updateShader();
 		return tr;
 		return tr;
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var tr = create(ctx.local3d, ctx.custom != null ? ctx.custom.numTrails : 1);
-		ctx.local3d = tr;
-		return ctx;
+
+
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+		return create(parent3d, numTrails);
 	}
 	}
 
 
+
 	#if editor
 	#if editor
 
 
-	override function getHideProps():HideProps {
+	override function getHideProps():hide.prefab.HideProps {
 		return { icon : "toggle-on", name : "Trails" };
 		return { icon : "toggle-on", name : "Trails" };
 	}
 	}
 
 
-	override public function edit(ctx:EditContext) {
+	override public function edit(ctx:hide.prefab.EditContext) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
-		var trailContext = ctx.getContext(this);
-		var trailObj = trailContext == null ? null : Std.downcast(trailContext.local3d, TrailObj);
+		var trailObj : TrailObj= cast local3d;
 		var props = ctx.properties.add(new hide.Element('
 		var props = ctx.properties.add(new hide.Element('
 		<div class="group" name="Trail Properties">
 		<div class="group" name="Trail Properties">
 			<dl>
 			<dl>
@@ -882,5 +879,5 @@ class Trails extends Object3D {
 
 
 	#end
 	#end
 
 
-	static var _ = Library.register("trails", Trails);
+	static var _ = Prefab.register("trails", Trails);
 }
 }

+ 20 - 23
hrt/prefab/pbr/Anisotropy.hx

@@ -23,38 +23,35 @@ class Anisotropy extends Prefab {
 	@:s public var noiseDirectionPath : String = null;
 	@:s public var noiseDirectionPath : String = null;
 	@:s public var rotationOffset : Float = 0.0;
 	@:s public var rotationOffset : Float = 0.0;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "anisotropy";
+	public function new(parent, shared: ContextShared) {
+		super(parent,shared);
 	}
 	}
 
 
-	function getMaterials( ctx : Context ) {
+	function getMaterials() {
 		if( Std.isOfType(parent, Material) ) {
 		if( Std.isOfType(parent, Material) ) {
 			var material : Material = cast parent;
 			var material : Material = cast parent;
-			return material.getMaterials(ctx);
+			return material.getMaterials();
 		}
 		}
 		else {
 		else {
-			return ctx.local3d.getMaterials();
+			return findFirstLocal3d().getMaterials();
 		}
 		}
 	}
 	}
 
 
-	override function makeInstance( ctx : Context ):Context {
-		ctx = ctx.clone(this);
-		refreshShaders(ctx);
-		updateInstance(ctx);
-		return ctx;
+	override function makeInstance():Void {
+		refreshShaders();
+		updateInstance();
 	}
 	}
 
 
-	function refreshShaders( ctx : Context ) {
+	function refreshShaders() {
 		var fv = new FlatValue();
 		var fv = new FlatValue();
 		var as = new AnisotropicForward();
 		var as = new AnisotropicForward();
 		var nt = new NoiseTexture();
 		var nt = new NoiseTexture();
 		var ff = new FrequencyValue();
 		var ff = new FrequencyValue();
 
 
-		var noiseIntensityTexture = noiseIntensityPath != null ? ctx.loadTexture(noiseIntensityPath) : null;
-		var noiseDirectionTexture = noiseDirectionPath != null ? ctx.loadTexture(noiseDirectionPath) : null;
+		var noiseIntensityTexture = noiseIntensityPath != null ? shared.loadTexture(noiseIntensityPath) : null;
+		var noiseDirectionTexture = noiseDirectionPath != null ? shared.loadTexture(noiseDirectionPath) : null;
 
 
-		var mat = getMaterials(ctx);
+		var mat = getMaterials();
 
 
 		for( m in mat ) {
 		for( m in mat ) {
 			m.mainPass.removeShader(m.mainPass.getShader(NoiseTexture));
 			m.mainPass.removeShader(m.mainPass.getShader(NoiseTexture));
@@ -83,8 +80,8 @@ class Anisotropy extends Prefab {
 		}
 		}
 	}
 	}
 
 
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		for( m in getMaterials(ctx) ) {
+	override function updateInstance(?propName : String ) {
+		for( m in getMaterials() ) {
 
 
 			var fv = m.mainPass.getShader(FlatValue);
 			var fv = m.mainPass.getShader(FlatValue);
 			if( fv != null ) {
 			if( fv != null ) {
@@ -104,8 +101,8 @@ class Anisotropy extends Prefab {
 
 
 			var nt = m.mainPass.getShader(NoiseTexture);
 			var nt = m.mainPass.getShader(NoiseTexture);
 			if( nt != null ) {
 			if( nt != null ) {
-				nt.noiseIntensityTexture = noiseIntensityPath != null ? ctx.loadTexture(noiseIntensityPath) : null;
-				nt.noiseDirectionTexture = noiseDirectionPath != null ? ctx.loadTexture(noiseDirectionPath) : null;
+				nt.noiseIntensityTexture = noiseIntensityPath != null ? shared.loadTexture(noiseIntensityPath) : null;
+				nt.noiseDirectionTexture = noiseDirectionPath != null ? shared.loadTexture(noiseDirectionPath) : null;
 				nt.intensityFactor = intensityFactor;
 				nt.intensityFactor = intensityFactor;
 				nt.rotationOffset = hxd.Math.degToRad(rotationOffset);
 				nt.rotationOffset = hxd.Math.degToRad(rotationOffset);
 			}
 			}
@@ -113,13 +110,13 @@ class Anisotropy extends Prefab {
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { 	icon : "cube",
 		return { 	icon : "cube",
 					name : "Anisotropy",
 					name : "Anisotropy",
 					allowParent : function(p) return p.to(Material) != null  };
 					allowParent : function(p) return p.to(Material) != null  };
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var flatParams = 	'<dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
 		var flatParams = 	'<dt>Intensity</dt><dd><input type="range" min="0" max="1" field="intensity"/></dd>
@@ -160,12 +157,12 @@ class Anisotropy extends Prefab {
 		ctx.properties.add(props, this, function(pname) {
 		ctx.properties.add(props, this, function(pname) {
 			if( pname == "mode" || pname == "noiseIntensityPath" || pname == "noiseDirectionPath" ) {
 			if( pname == "mode" || pname == "noiseIntensityPath" || pname == "noiseDirectionPath" ) {
 				ctx.rebuildProperties();
 				ctx.rebuildProperties();
-				refreshShaders(ctx.getContext(this));
+				refreshShaders();
 			}
 			}
 			ctx.onChange(this, pname);
 			ctx.onChange(this, pname);
 		});
 		});
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("anisotropy", Anisotropy);
+	static var _ = Prefab.register("anisotropy", Anisotropy);
 }
 }

+ 16 - 17
hrt/prefab/pbr/LightVolume.hx

@@ -162,47 +162,46 @@ class LightVolumeObject extends h3d.scene.Mesh {
 	}
 	}
 }
 }
 
 
-class LightVolume extends hrt.prefab.Prefab {
+class LightVolume extends Object3D {
 
 
 	@:s var fallOff : Float = 1.0;
 	@:s var fallOff : Float = 1.0;
 	@:s var opacity : Float = 1.0;
 	@:s var opacity : Float = 1.0;
 	@:s var USE_SHADOW_MAP : Bool = false;
 	@:s var USE_SHADOW_MAP : Bool = false;
 
 
-	override function makeInstance(ctx : hrt.prefab.Context ) : hrt.prefab.Context {
-		ctx = ctx.clone(this);
-
-		var pbrLight = Std.downcast(ctx.local3d, h3d.scene.pbr.Light);
+	override function makeInstance() : Void {
+		var pbrLight = Std.downcast(shared.current3d, h3d.scene.pbr.Light);
 		if ( pbrLight == null )
 		if ( pbrLight == null )
-			return ctx;
+			return;
 
 
-		var mesh = new LightVolumeObject(@:privateAccess pbrLight.primitive, ctx.local3d);
-		var pointLight = Std.downcast(ctx.local3d, h3d.scene.pbr.PointLight);
+		var mesh = new LightVolumeObject(@:privateAccess pbrLight.primitive, shared.current3d);
+		var pointLight = Std.downcast(shared.current3d, h3d.scene.pbr.PointLight);
 		if ( pointLight != null ) {
 		if ( pointLight != null ) {
 			var shader = new PointLightVolumeShader();
 			var shader = new PointLightVolumeShader();
 			mesh.shader = shader;
 			mesh.shader = shader;
 			mesh.material.mainPass.addShader(shader);
 			mesh.material.mainPass.addShader(shader);
 		} else {
 		} else {
-			var spotLight = Std.downcast(ctx.local3d, h3d.scene.pbr.SpotLight);
+			var spotLight = Std.downcast(shared.current3d, h3d.scene.pbr.SpotLight);
 			if ( spotLight != null ) {
 			if ( spotLight != null ) {
 				var shader = new SpotLightVolumeShader();
 				var shader = new SpotLightVolumeShader();
 				mesh.shader = shader;
 				mesh.shader = shader;
 				mesh.material.mainPass.addShader(shader);
 				mesh.material.mainPass.addShader(shader);
 			}
 			}
 		}
 		}
-		ctx.local3d = mesh;
+
+		local3d = mesh;
 		mesh.material.shadows = false;
 		mesh.material.shadows = false;
 		mesh.material.mainPass.setBlendMode(Add);
 		mesh.material.mainPass.setBlendMode(Add);
 		mesh.material.mainPass.depthTest = Always;
 		mesh.material.mainPass.depthTest = Always;
 		mesh.material.mainPass.culling = Front;
 		mesh.material.mainPass.culling = Front;
 		mesh.material.mainPass.depthWrite = false;
 		mesh.material.mainPass.depthWrite = false;
 		mesh.material.mainPass.setPassName("lightVolume");
 		mesh.material.mainPass.setPassName("lightVolume");
-		updateInstance(ctx);
-		return ctx;
+		updateInstance();
 	}
 	}
 
 
-	override function updateInstance(ctx : hrt.prefab.Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
-		var lvo = Std.downcast(ctx.local3d, LightVolumeObject);
+
+	override function updateInstance(?propName : String) {
+		super.updateInstance(propName);
+		var lvo = Std.downcast(local3d, LightVolumeObject);
 		lvo.USE_SHADOW_MAP = USE_SHADOW_MAP;
 		lvo.USE_SHADOW_MAP = USE_SHADOW_MAP;
 		lvo.shader.fallOff = fallOff;
 		lvo.shader.fallOff = fallOff;
 		lvo.shader.opacity = opacity;
 		lvo.shader.opacity = opacity;
@@ -224,12 +223,12 @@ class LightVolume extends hrt.prefab.Prefab {
 		});
 		});
 	}
 	}
 
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "sun-o", name : "Light volume" };
 		return { icon : "sun-o", name : "Light volume" };
 	}
 	}
 
 
 	#end
 	#end
 
 
-	static var _ = hrt.prefab.Library.register("lightVolume", LightVolume);
+	static var _ = Prefab.register("lightVolume", LightVolume);
 
 
 }
 }

+ 16 - 23
hrt/prefab/pbr/SpecularColor.hx

@@ -25,30 +25,23 @@ class SpecularColor extends Prefab {
 	@:s public var specularColorCustomValue : Int;
 	@:s public var specularColorCustomValue : Int;
 	@:s public var mode : SpecularColorMode = Albedo;
 	@:s public var mode : SpecularColorMode = Albedo;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "specularColor";
-	}
-
-	function getMaterials( ctx : Context ) {
+	function getMaterials() {
 		if( Std.isOfType(parent, Material) ) {
 		if( Std.isOfType(parent, Material) ) {
 			var material : Material = cast parent;
 			var material : Material = cast parent;
-			return material.getMaterials(ctx);
+			return material.getMaterials();
 		}
 		}
 		else {
 		else {
-			return ctx.local3d.getMaterials();
+			return findFirstLocal3d().getMaterials();
 		}
 		}
 	}
 	}
 
 
-	override function makeInstance( ctx : Context ):Context {
-		ctx = ctx.clone(this);
-		refreshShaders(ctx);
-		updateInstance(ctx);
-		return ctx;
+	override function makeInstance() : Void {
+		refreshShaders();
+		updateInstance();
 	}
 	}
 
 
-	override function updateInstance( ctx : Context, ?propName : String ) {
-		for( m in getMaterials(ctx) ) {
+	override function updateInstance(?propName : String ) {
+		for( m in getMaterials() ) {
 			var sca = m.mainPass.getShader(hrt.shader.SpecularColorAlbedo);
 			var sca = m.mainPass.getShader(hrt.shader.SpecularColorAlbedo);
 			if( sca != null ) {
 			if( sca != null ) {
 				// No params
 				// No params
@@ -59,7 +52,7 @@ class SpecularColor extends Prefab {
 			}
 			}
 			var sct = m.mainPass.getShader(hrt.shader.SpecularColorTexture);
 			var sct = m.mainPass.getShader(hrt.shader.SpecularColorTexture);
 			if( sct != null ) {
 			if( sct != null ) {
-				sct.specularColorTexture = ctx.loadTexture(specularColorPath);
+				sct.specularColorTexture = shared.loadTexture(specularColorPath);
 			}
 			}
 			var sc = m.mainPass.getShader(hrt.shader.SpecularColor);
 			var sc = m.mainPass.getShader(hrt.shader.SpecularColor);
 			if( sc != null ) {
 			if( sc != null ) {
@@ -69,16 +62,16 @@ class SpecularColor extends Prefab {
 		}
 		}
 	}
 	}
 
 
-	function refreshShaders( ctx : Context ) {
+	function refreshShaders() {
 
 
 		var sca = new SpecularColorAlbedo();
 		var sca = new SpecularColorAlbedo();
 		var scf = new SpecularColorFlat();
 		var scf = new SpecularColorFlat();
 		var sct = new SpecularColorTexture();
 		var sct = new SpecularColorTexture();
 		var sc = new hrt.shader.SpecularColor();
 		var sc = new hrt.shader.SpecularColor();
 
 
-		var specularColorTexture = specularColorPath != null ? ctx.loadTexture(specularColorPath) : null;
+		var specularColorTexture = specularColorPath != null ? shared.loadTexture(specularColorPath) : null;
 
 
-		var mat = getMaterials(ctx);
+		var mat = getMaterials();
 		for( m in mat ) {
 		for( m in mat ) {
 			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorAlbedo));
 			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorAlbedo));
 			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorFlat));
 			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorFlat));
@@ -101,13 +94,13 @@ class SpecularColor extends Prefab {
 	}
 	}
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { 	icon : "cube",
 		return { 	icon : "cube",
 					name : "SpecularColor",
 					name : "SpecularColor",
 					allowParent : function(p) return p.to(Material) != null };
 					allowParent : function(p) return p.to(Material) != null };
 	}
 	}
 
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		super.edit(ctx);
 
 
 		var flatParams = 	'<dt>Color</dt><dd><input type="color" field="specularColorCustomValue"/></dd>';
 		var flatParams = 	'<dt>Color</dt><dd><input type="color" field="specularColorCustomValue"/></dd>';
@@ -143,12 +136,12 @@ class SpecularColor extends Prefab {
 		ctx.properties.add(props, this, function(pname) {
 		ctx.properties.add(props, this, function(pname) {
 			if( pname == "mode" || pname == "specularColorPath" ) {
 			if( pname == "mode" || pname == "specularColorPath" ) {
 				ctx.rebuildProperties();
 				ctx.rebuildProperties();
-				refreshShaders(ctx.getContext(this));
+				refreshShaders();
 			}
 			}
 			ctx.onChange(this, pname);
 			ctx.onChange(this, pname);
 		});
 		});
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("specularColor", SpecularColor);
+	static var _ = Prefab.register("specularColor", SpecularColor);
 }
 }

+ 2 - 1
hrt/prefab/rfx/AutoExposure.hx

@@ -1,5 +1,6 @@
 package hrt.prefab.rfx;
 package hrt.prefab.rfx;
 
 
+@:access(h3d.scene.Renderer)
 class AutoExposure extends RendererFX {
 class AutoExposure extends RendererFX {
 
 
 	@:s var lightFront : Float = 0.;
 	@:s var lightFront : Float = 0.;
@@ -60,6 +61,6 @@ class AutoExposure extends RendererFX {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("rfx.autoexp", AutoExposure);
+	static var _ = Prefab.register("rfx.autoexp", AutoExposure);
 
 
 }
 }

+ 4 - 3
hrt/prefab/rfx/Bloom.hx

@@ -11,6 +11,7 @@ class BloomTonemap extends hxsl.Shader {
 	}
 	}
 }
 }
 
 
+@:access(h3d.scene.Renderer)
 class Bloom extends RendererFX {
 class Bloom extends RendererFX {
 
 
 	var bloomPass = new h3d.pass.ScreenFx(new hrt.shader.Bloom());
 	var bloomPass = new h3d.pass.ScreenFx(new hrt.shader.Bloom());
@@ -25,8 +26,8 @@ class Bloom extends RendererFX {
 	@:s public var blurQuality : Float = 1;
 	@:s public var blurQuality : Float = 1;
 	@:s public var blurLinear : Float;
 	@:s public var blurLinear : Float;
 
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		size = 0.5;
 		size = 0.5;
 		blur = 3;
 		blur = 3;
 		threshold = 0.5;
 		threshold = 0.5;
@@ -72,6 +73,6 @@ class Bloom extends RendererFX {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("rfx.bloom", Bloom);
+	static var _ = Prefab.register("rfx.bloom", Bloom);
 
 
 }
 }

+ 10 - 5
hrt/prefab/rfx/Border.hx

@@ -15,15 +15,20 @@ class BorderShader extends h3d.shader.ScreenShader {
 
 
 class Border extends RendererFX {
 class Border extends RendererFX {
 	public var pass : h3d.pass.ScreenFx<BorderShader>;
 	public var pass : h3d.pass.ScreenFx<BorderShader>;
+	public var shader : BorderShader;
 
 
-	public function new(size = 0.1, color: Int = 0, alpha = 1.0) {
-		super();
-		var shader = new BorderShader();
+	public function new(parent: Prefab, shared: ContextShared) {
+		super(parent, shared);
+		shader = new BorderShader();
+		setParams();
+		pass = new h3d.pass.ScreenFx(shader);
+		pass.pass.setBlendMode(Alpha);
+	}
+
+	public function setParams( size = 0.1, color: Int = 0, alpha = 1.0) {
 		shader.size = size;
 		shader.size = size;
 		shader.alpha = alpha;
 		shader.alpha = alpha;
 		shader.color = h3d.Vector.fromColor(color);
 		shader.color = h3d.Vector.fromColor(color);
-		pass = new h3d.pass.ScreenFx(shader);
-		pass.pass.setBlendMode(Alpha);
 	}
 	}
 
 
 	public override function begin( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {
 	public override function begin( r : h3d.scene.Renderer, step : h3d.impl.RendererFX.Step ) {

+ 5 - 5
hrt/prefab/rfx/CloudShadow.hx

@@ -39,6 +39,7 @@ class DirLightWithClouds extends h3d.shader.pbr.Light {
 }
 }
 
 
 @:access(h3d.scene.pbr.DirLight)
 @:access(h3d.scene.pbr.DirLight)
+@:access(h3d.scene.Renderer)
 class CloudShadow extends RendererFX {
 class CloudShadow extends RendererFX {
 
 
 	var dlwc = new DirLightWithClouds();
 	var dlwc = new DirLightWithClouds();
@@ -56,10 +57,9 @@ class CloudShadow extends RendererFX {
 		var amount : Float;
 		var amount : Float;
 	};
 	};
 
 
-	override function makeInstance( ctx : Context ) : Context {
-		ctx = super.makeInstance(ctx);
-		updateInstance(ctx);
-		return ctx;
+	override function makeInstance() : Void {
+		super.makeInstance();
+		updateInstance();
 	}
 	}
 
 
 	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
 	override function end(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
@@ -146,6 +146,6 @@ class CloudShadow extends RendererFX {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("rfx.cloudShadow", CloudShadow);
+	static var _ = Prefab.register("rfx.cloudShadow", CloudShadow);
 
 
 }
 }

+ 2 - 2
hrt/prefab/rfx/ColorGrading.hx

@@ -30,7 +30,7 @@ class ColorGradingTonemap extends hxsl.Shader {
 		}
 		}
 	}
 	}
 }
 }
-
+@:access(h3d.scene.Renderer)
 class ColorGrading extends RendererFX {
 class ColorGrading extends RendererFX {
 
 
 	var tonemap = new ColorGradingTonemap();
 	var tonemap = new ColorGradingTonemap();
@@ -99,6 +99,6 @@ class ColorGrading extends RendererFX {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("rfx.colorGrading", ColorGrading);
+	static var _ = Prefab.register("rfx.colorGrading", ColorGrading);
 
 
 }
 }

+ 9 - 17
hrt/prefab/rfx/Configurator.hx

@@ -111,7 +111,7 @@ class ConfiguratorInterp extends hscript.Interp {
 }
 }
 #end
 #end
 
 
-
+@:access(h3d.scene.Renderer)
 class Configurator extends RendererFX {
 class Configurator extends RendererFX {
 
 
 	@:s public var vars : Array<{ name : String, defValue : Float }> = [];
 	@:s public var vars : Array<{ name : String, defValue : Float }> = [];
@@ -130,9 +130,8 @@ class Configurator extends RendererFX {
 	#end
 	#end
 	var rootPrefab : Prefab;
 	var rootPrefab : Prefab;
 
 
-	public function new(?parent) {
-		super(parent);
-		type = "configurator";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 	}
 	}
 
 
 	public function set( name : String, value : Float ) {
 	public function set( name : String, value : Float ) {
@@ -190,19 +189,12 @@ class Configurator extends RendererFX {
 		#end
 		#end
 	}
 	}
 
 
-	override function makeInstance(ctx:Context):Context {
+	override function makeInstance() : Void {
 		for( v in vars )
 		for( v in vars )
 			values.set(v.name, v.defValue);
 			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;
+		rootPrefab = getRoot(true);
 		resetCache();
 		resetCache();
-		return super.makeInstance(ctx);
+		super.makeInstance();
 	}
 	}
 
 
 	override function begin(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
 	override function begin(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
@@ -263,11 +255,11 @@ class Configurator extends RendererFX {
 	#end
 	#end
 
 
 	#if editor
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { name : "Configurator", icon : "dashboard" };
 		return { name : "Configurator", icon : "dashboard" };
 	}
 	}
 
 
-	override function edit( ectx : EditContext ) {
+	override function edit( ectx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 		var props = new hide.Element('
 		<div>
 		<div>
 			<div class="group" name="Variables">
 			<div class="group" name="Variables">
@@ -327,7 +319,7 @@ class Configurator extends RendererFX {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("rfx.configurator", Configurator);
+	static var _ = Prefab.register("rfx.configurator", Configurator);
 
 
 
 
 }
 }

+ 4 - 4
hrt/prefab/rfx/DistanceBlur.hx

@@ -50,7 +50,7 @@ class DistanceBlurShader extends hrt.shader.PbrShader {
 	}
 	}
 
 
 }
 }
-
+@:access(h3d.scene.Renderer)
 class DistanceBlur extends RendererFX {
 class DistanceBlur extends RendererFX {
 
 
 	var blurPass = new h3d.pass.ScreenFx(new DistanceBlurShader());
 	var blurPass = new h3d.pass.ScreenFx(new DistanceBlurShader());
@@ -70,8 +70,8 @@ class DistanceBlur extends RendererFX {
 	@:s public var blurTextureSize : Float;
 	@:s public var blurTextureSize : Float;
 	@:s public var blurRange : Int;
 	@:s public var blurRange : Int;
 
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		nearEndDistance = 10;
 		nearEndDistance = 10;
 		farStartDistance = 100;
 		farStartDistance = 100;
 		farEndDistance = 500;
 		farEndDistance = 500;
@@ -132,6 +132,6 @@ class DistanceBlur extends RendererFX {
 	}
 	}
 	#end
 	#end
 
 
-	static var _ = Library.register("rfx.distanceBlur", DistanceBlur);
+	static var _ = Prefab.register("rfx.distanceBlur", DistanceBlur);
 
 
 }
 }

Some files were not shown because too many files changed in this diff