浏览代码

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 年之前
父节点
当前提交
c714e48089
共有 100 个文件被更改,包括 4052 次插入3894 次删除
  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"
         },
         {
-            "type": "nwjs",
+            "type": "chrome",
             "request": "attach",
             "name": "Attach to HIDE",
             "port": 9222,

+ 3 - 0
hide.hxml

@@ -1,5 +1,6 @@
 common.hxml
 -D hide
+-D prefab2
 -js bin/hide.js
 -main hide.Ide
 --macro include("h3d.shader")
@@ -9,7 +10,9 @@ common.hxml
 --macro include("hxd.clipper")
 --macro include("hxd.earcut")
 --macro include("hrt.prefab")
+--macro include("hrt.prefab")
 --macro include("hrt.shgraph.nodes")
+--macro include("hide.view")
 -dce no
 -debug
 #-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)));
 			e.remove();
 		}).appendTo(window.window.document.body).click();
+
+		// remove comments
+
+
+
 	}
 
 	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");
 		var todo = [];
 		browseFiles(function(path) {
@@ -804,7 +809,7 @@ class Ide extends hide.tools.IdeData {
 			}
 			filterRec(prefab);
 			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 )
 			t();

+ 8 - 1
hide/Renderer.hx

@@ -94,7 +94,14 @@ class PbrSetup extends h3d.mat.PbrMaterialSetup {
 	function getEnvMap() {
 		var ide = hide.Ide.inst;
 		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 pix = hxd.res.Any.fromBytes(path, data).toImage().getPixels();
 		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;
 import hide.view.CameraController;
+import hide.comp.Popup;
+import hide.comp.Range;
+import hide.comp.ExpRange;
+
+
 
 class CameraControllerEditor extends Popup {
 

+ 5 - 5
hide/comp/CurveEditor.hx

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

+ 1 - 1
hide/comp/PropsEditor.hx

@@ -92,7 +92,7 @@ class PropsEditor extends Component {
 			else {
 				var row = new Element('<div class="flex"/>').appendTo(parent);
 				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(max == null)	max = 1.0;
 					e.attr("min", "" + min);

+ 4 - 2
hide/comp/Scene.hx

@@ -1,6 +1,6 @@
 package hide.comp;
 
-class Scene extends Component implements h3d.IDrawable {
+class Scene extends hide.comp.Component implements h3d.IDrawable {
 
 	static var UID = 0;
 
@@ -25,6 +25,8 @@ class Scene extends Component implements h3d.IDrawable {
 	public var editor : hide.comp.SceneEditor;
 	var unFocusedTime = 0.;
 
+	public static var cache : h3d.prim.ModelCache = new h3d.prim.ModelCache();
+
 	public function new(config, parent, el) {
 		super(parent,el);
 		this.config = config;
@@ -529,7 +531,7 @@ class Scene extends Component implements h3d.IDrawable {
 		function pathRec(p : String) {
 			try {
 				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 )
 					materials.push({ path : p, mat : m});
 			} catch ( e : hxd.res.NotFound ) {

文件差异内容过多而无法显示
+ 273 - 233
hide/comp/SceneEditor.hx


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

@@ -60,7 +60,7 @@ class DataFiles {
 	}
 	#else
 	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);
 		l.loadData(haxe.Json.parse(sys.io.File.getContent(path)));
 		return l;
@@ -265,6 +265,30 @@ class DataFiles {
 		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> ) {
 		var ide = Ide.inst;
 		var temp = [];
@@ -303,7 +327,7 @@ class DataFiles {
 							pf = ide.loadPrefab(p.file);
 							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];
 						if( inst == null || inst.getCdbType() != prevName )
 							ide.error("Can't save prefab data "+p.path);
@@ -327,7 +351,7 @@ class DataFiles {
 		for( file => pf in prefabs ) {
 			skip++;
 			var path = ide.getPath(file);
-			var out = ide.toJSON(pf.saveData());
+			@:privateAccess var out = ide.toJSON(pf.serialize());
 			if( force ) {
 				var txt = try sys.io.File.getContent(path) catch( e : Dynamic ) null;
 				if( txt == out ) continue;

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

@@ -1216,7 +1216,7 @@ class Editor extends Component {
 								continue;
 							}
 							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)});
 							}
 						}

+ 10 - 19
hide/prefab/ContextShared.hx

@@ -1,46 +1,37 @@
 package hide.prefab;
 
-class ContextShared extends hrt.prefab.ContextShared {
+class ContextShared extends hrt.prefab.ContextShared.ContextSharedBase {
 	#if editor
-	public var scene : hide.comp.Scene;
 	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 ) {
 		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 ) {
 		return hide.Ide.inst.shaderLoader.loadSharedShader(path);
 	}
 
 	override function loadModel( path : String ) {
-		return getScene().loadModel(path);
+		return scene.loadModel(path);
 	}
 
 	override function loadAnimation( path : String ) {
-		return getScene().loadAnimation(path);
+		return scene.loadAnimation(path);
 	}
 
 	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> {

+ 14 - 21
hide/prefab/EditContext.hx

@@ -1,11 +1,9 @@
 package hide.prefab;
+
 import hrt.prefab.Prefab;
-import hrt.prefab.Context;
 
 class EditContext {
 
-	public var rootContext : Context;
-
 	#if editor
 
 	var updates : Array<Float->Void> = [];
@@ -17,20 +15,15 @@ class EditContext {
 	function get_ide() return hide.Ide.inst;
 
 	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;
-			}
 		}
-		for( ctx2 in rootContext.shared.getContexts(p) )
-			if( ctx2 != ctx )
-				p.updateInstance(ctx2, propName);
 	}
 
 	public function getCurrentProps( p : Prefab ) : Element {
@@ -51,7 +44,8 @@ class EditContext {
 	}
 
 	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) {
 			var old = p.save();
 			p.load(current);
@@ -66,13 +60,12 @@ class EditContext {
 
 	#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);
-	}
+	}*/
 
 	/**
 		Converts screen mouse coordinates into projection into ground.
@@ -129,7 +122,7 @@ class EditContext {
 			path.pop();
 		}
 
-		for( o in rootContext.shared.root3d )
+		for( o in scene.s3d)
 			getRec([], o);
 
 		return out;

+ 1 - 1
hide/prefab/HideProps.hx

@@ -5,7 +5,7 @@ typedef HideProps = {
 	var name : String;
 	var ?isGround : Bool;
 	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 onChildUpdate( p : hrt.prefab.Prefab ) : Void;
 	@:optional dynamic function onChildListChanged() : Void;

+ 30 - 29
hide/prefab/PolygonEditor.hx

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

+ 56 - 60
hide/prefab/SplineEditor.hx

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

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

@@ -3,7 +3,6 @@ using Lambda;
 import hxd.Pixels;
 import hrt.prefab.terrain.Tile;
 import hxd.Key as K;
-import hrt.prefab.Context;
 
 enum RenderMode {
 	PBR;
@@ -136,11 +135,11 @@ class TerrainEditor {
 		}
 	}
 
-	function renderTerrainUV( ctx : Context ) {
+	function renderTerrainUV() {
 		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 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) {
@@ -581,23 +580,23 @@ class TerrainEditor {
 		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 dist = projectToGround(ray);
 		return dist >= 0 ? ray.getPoint(dist) : new h3d.col.Point();
 	}
 
-	function worldToScreen( wx: Float, wy: Float, wz: Float, ctx : Context ) {
-		if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null || ctx.local2d == null || ctx.local2d.getScene() == null ) return new h2d.col.Point();
-		var camera = @:privateAccess ctx.local3d.getScene().camera;
+	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);
 		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 ) {
 			var localPos = terrainPrefab.terrain.globalToLocal(worldPos.clone());
 			localPos.x = hxd.Math.round(localPos.x / terrainPrefab.terrain.cellSize.x) * terrainPrefab.terrain.cellSize.x;
@@ -608,9 +607,9 @@ class TerrainEditor {
 		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;
-		var screenPos = worldToScreen(worldPos.x, worldPos.y, worldPos.z, ctx);
+		var screenPos = worldToScreen(worldPos.x, worldPos.y, worldPos.z);
 		var brushWorldPos = worldPos.clone();
 		var fetchPos = new h2d.col.Point(hxd.Math.floor(screenPos.x * uvTexRes), hxd.Math.floor(screenPos.y * uvTexRes));
 		fetchPos.x = hxd.Math.clamp(fetchPos.x, 0, uvTexPixels.width - 1);
@@ -623,27 +622,27 @@ class TerrainEditor {
 		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();
 		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);
 	}
 
-	function applyBrush( pos : h3d.col.Point, ctx : Context ) {
+	function applyBrush( pos : h3d.col.Point) {
 		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:
 		}
 		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();
 		if( currentBrush.firstClick ) {
 			if( currentBrush.brushMode.mode == Set ) {
@@ -652,7 +651,7 @@ class TerrainEditor {
 				else
 					currentBrush.brushMode.setHeightValue = currentBrush.strength;
 			}
-			applyBrush(from, ctx);
+			applyBrush(from);
 			previewStrokeBuffers();
 			return;
 		}
@@ -673,7 +672,7 @@ class TerrainEditor {
 					pos = pos.add(firstStep);
 				}else
 					pos = pos.add(step);
-				applyBrush(pos, ctx);
+				applyBrush(pos);
 				dist -= currentBrush.step - remainingDist;
 				remainingDist = 0;
 			}
@@ -683,8 +682,8 @@ class TerrainEditor {
 			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;
 		var tile = terrainPrefab.terrain.getTileAtWorldPos(brushWorldPos.x, brushWorldPos.y);
 		if( tile == null ) return;
@@ -695,18 +694,18 @@ class TerrainEditor {
 			trd.prevWeightMapPixels.push(w.capturePixels());
 		tileTrashBin.push(trd);
 		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;
-		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos, ctx);
+		var brushWorldPos = uvTexPixels == null ? pos : getBrushWorldPosFromTex(pos);
 		if( brushWorldPos == null ) return;
 		var c = terrainPrefab.terrain.tiles.length;
 		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
 		if( c != terrainPrefab.terrain.tiles.length ) {
-			renderTerrainUV(ctx);
-			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
+			renderTerrainUV();
+			brushWorldPos = getBrushWorldPosFromTex(pos);
 		}
 
 		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;
 		var c = terrainPrefab.terrain.tiles.length;
 		var tiles = terrainPrefab.terrain.getTiles(brushWorldPos.x, brushWorldPos.y, currentBrush.size / 2.0, autoCreateTile);
 		if( c != terrainPrefab.terrain.tiles.length ) {
-			renderTerrainUV(ctx);
-			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
+			renderTerrainUV();
+			brushWorldPos = getBrushWorldPosFromTex(pos);
 		}
 
 		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 ) {
-			var s2d = ctx.shared.root2d.getScene();
+			var s2d = terrainPrefab.shared.root2d.getScene();
 			if( interactive == null )
 				interactive.remove();
 			interactive = new h2d.Interactive(10000, 10000, s2d);
@@ -789,9 +788,9 @@ class TerrainEditor {
 
 			interactive.onWheel = function(e) {
 				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) {
@@ -799,28 +798,28 @@ class TerrainEditor {
 				currentBrush.brushMode.lockDir = K.isDown(K.ALT);
 				currentBrush.brushMode.subAction = K.isDown(K.SHIFT);
 				currentBrush.brushMode.snapToGrid = K.isDown(K.CTRL);
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
+				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY);
 				if( K.isDown( K.MOUSE_LEFT) ) {
 					currentBrush.firstClick = true;
 					lastPos = worldPos.clone();
 					if( currentBrush.isValid() ) {
-						useBrush( lastPos, worldPos, ctx);
+						useBrush( lastPos, worldPos);
 						previewStrokeBuffers();
-						drawBrushPreview(worldPos, ctx);
+						drawBrushPreview(worldPos);
 					}
 				}
 			};
 
 			interactive.onRelease = function(e) {
 				e.propagate = false;
-				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY, ctx);
+				var worldPos = getBrushPlanePos(s2d.mouseX, s2d.mouseY);
 				remainingDist = 0;
 				lastPos = null;
 				currentBrush.brushMode.lockAxe = NoLock;
 				currentBrush.firstClick = false;
 				applyStrokeBuffers();
 				resetStrokeBuffers();
-				drawBrushPreview(worldPos, ctx);
+				drawBrushPreview(worldPos);
 				checkTrashBin();
 			};
 
@@ -838,7 +837,7 @@ class TerrainEditor {
 					var sensibility = 0.5;
 					currentBrush.size = hxd.Math.max(0, lastBrushSize + sensibility * dist);
 					@:privateAccess Lambda.find(editContext.properties.fields, f->f.fname=="editor.currentBrush.size").range.value = currentBrush.size;
-					drawBrushPreview(getBrushPlanePos(lastMousePos.x, lastMousePos.y, ctx), ctx);
+					drawBrushPreview(getBrushPlanePos(lastMousePos.x, lastMousePos.y));
 					return;
 				}
 				else {
@@ -847,7 +846,7 @@ class TerrainEditor {
 				}
 
 				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) ) {
 					currentBrush.firstClick = false;
 					e.propagate = false;
@@ -868,15 +867,15 @@ class TerrainEditor {
 								worldPos.y += distY;
 							}
 						}
-						useBrush( lastPos, worldPos, ctx);
+						useBrush( lastPos, worldPos);
 						lastPos = worldPos;
 					}
 				}
 				else {
-					renderTerrainUV(ctx);
+					renderTerrainUV();
 					e.propagate = true;
 				}
-				drawBrushPreview(worldPos, ctx);
+				drawBrushPreview(worldPos);
 			};
 		}
 		else {
@@ -991,7 +990,7 @@ class TerrainEditor {
 	}
 
 	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;
 		return texture;
 	}
@@ -1191,9 +1190,9 @@ class TerrainEditor {
 		}
 		var name = split[0];
 		var ext = "."+path.split(".").pop();
-		var albedo = ctx.rootContext.shared.loadTexture(name + textureType[0] + ext);
-		var normal = ctx.rootContext.shared.loadTexture(name + textureType[1] + ext);
-		var pbr = ctx.rootContext.shared.loadTexture(name + textureType[2] + ext);
+		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;
 

+ 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 {
 		if( file == null )
 			return null;
-		var l = hrt.prefab.Library.create(file.split(".").pop().toLowerCase());
 		try {
 			var path = getPath(file);
 			if( checkExists && !sys.FileSystem.exists(path) )
 				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 ) {
 			error("Invalid prefab "+file+" ("+e+")");
 			throw e;
 		}
-		if( cl == null )
-			return cast l;
-		return l.get(cl);
 	}
 
 	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));
 	}
 

+ 180 - 62
hide/view/FXEditor.hx

@@ -1,4 +1,5 @@
 package hide.view;
+import hide.view.FileTree;
 import hrt.prefab.Light;
 using Lambda;
 
@@ -23,8 +24,8 @@ typedef Section = {
 @:access(hide.view.FXEditor)
 class FXEditContext extends hide.prefab.EditContext {
 	var parent : FXEditor;
-	public function new(parent, context) {
-		super(context);
+	public function new(parent) {
+		super();
 		this.parent = parent;
 	}
 	override function onChange(p, propName) {
@@ -58,8 +59,7 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 	}
 
 	override function duplicate(thenMove : Bool) {
-		if(curEdit == null) return;
-		var elements = curEdit.rootElements;
+		var elements = selectedPrefabs;
 		if(elements == null || elements.length == 0)
 			return;
 		if( isDuplicating )
@@ -71,13 +71,16 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 		var undoes = [];
 		var newElements = [];
 		for(elt in elements) {
-			var clone = elt.cloneData();
+			var clone = elt.clone(elt.parent, null);
 			var index = elt.parent.children.indexOf(elt) + 1;
-			clone.parent = elt.parent;
 			elt.parent.children.remove(clone);
 			elt.parent.children.insert(index, clone);
+
+			clone.shared.current2d = elt.parent.findFirstLocal2d();
+			clone.shared.current3d = elt.parent.findFirstLocal3d();
+			clone.make();
+
 			autoName(clone);
-			makeInstance(clone);
 			newElements.push(clone);
 
 			undoes.push(function(undo) {
@@ -104,10 +107,7 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 			var fullRefresh = false;
 			if(undo) {
 				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) {
 				for(elt in newElements)
-					makeInstance(elt);
+					makePrefab(elt);
 			}
 
 			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 {
-		var type = hrt.prefab.Library.getPrefabType(path);
+		var type = hrt.prefab.Prefab.getPrefabType(path);
 		if(type == "fx") {
 			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.name = new haxe.io.Path(relative).file;
 			return ref;
@@ -134,10 +134,10 @@ private class FXSceneEditor extends hide.comp.SceneEditor {
 		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 super.setElementSelected(p, ctx, b);
+		return super.setElementSelected(p, b);
 	}
 
 	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 data : hrt.prefab.fx.BaseFX;
@@ -302,13 +302,13 @@ class FXEditor extends FileView {
 	var statusText : h2d.Text;
 
 	var scriptEditor : hide.comp.ScriptEditor;
-	var fxScriptParser : hrt.prefab.fx.FXScriptParser;
+	//var fxScriptParser : hrt.prefab.fx.FXScriptParser;
 	var cullingPreview : h3d.scene.Sphere;
 
-	var viewModes : Array<String>;
+    var viewModes : Array<String>;
 
 	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() {
@@ -318,7 +318,7 @@ class FXEditor extends FileView {
 	override function save() {
 		if( !canSave() )
 			return;
-		var content = ide.toJSON(data.saveData());
+		@:privateAccess var content = ide.toJSON(cast(data, hrt.prefab.Prefab).serialize());
 		var newSign = ide.makeSignature(content);
 		if(newSign != currentSign)
 			haxe.Timer.delay(saveBackup.bind(content), 0);
@@ -333,17 +333,8 @@ class FXEditor extends FileView {
 		xOffset = -timelineLeftMargin / xScale;
 		var content = sys.io.File.getContent(getPath());
 		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);
 
 		element.html('
@@ -389,7 +380,7 @@ class FXEditor extends FileView {
 			</div>');
 		tools = new hide.comp.Toolbar(null,element.find(".tools-buttons"));
 		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-scroll").first().append(sceneEditor.properties.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 edit = new FXEditContext(this, sceneEditor.context);
+			var edit = new FXEditContext(this);
 			edit.properties = fxprops;
 			edit.scene = sceneEditor.scene;
 			edit.cleanups = [];
-			data.edit(edit);
+			cast(data, hrt.prefab.Prefab).edit(edit);
 		}
 
 		if (is2D) {
@@ -463,7 +454,7 @@ class FXEditor extends FileView {
 			modified = false;
 		}
 		scriptEditor.onSave = onSaveScript;
-		fxScriptParser = new hrt.prefab.fx.FXScriptParser();
+		//fxScriptParser = new hrt.prefab.fx.FXScriptParser();
 		data.scriptCode = scriptEditor.code;
 
 		keys.register("playPause", function() { pauseButton.toggle(!pauseButton.isDown()); });
@@ -488,7 +479,6 @@ class FXEditor extends FileView {
 		if (tools != null)
 			tools.refreshToggles();
 	}
-
 	public function onSceneReady() {
 		light = sceneEditor.scene.s3d.find(function(o) return Std.downcast(o, h3d.scene.fwd.DirLight));
 		if( light == null ) {
@@ -521,6 +511,11 @@ class FXEditor extends FileView {
 
 		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: "", title : "", icon : "", type : Separator});
@@ -569,6 +564,7 @@ class FXEditor extends FileView {
 			updateGrid();
 		}, scene.engine.backgroundColor);
 
+
 		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);
@@ -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.addSeparator();
 
 
@@ -585,6 +582,8 @@ class FXEditor extends FileView {
 			scene.speed = v;
 		}, scene.speed);
 
+
+
 		var gizmo = @:privateAccess sceneEditor.gizmo;
 
 		var onSetGizmoMode = function(mode: hide.view.l3d.Gizmo.EditMode) {
@@ -604,8 +603,128 @@ class FXEditor extends FileView {
 		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) {
-		if(p == data) {
+		if(p == cast(data, hrt.prefab.Prefab)) {
 			if (this.curveEditor != null) {
 				previewMax = data.duration == 0 ? 5000 : data.duration;
 				this.curveEditor.refreshTimeline(currentTime);
@@ -630,7 +749,7 @@ class FXEditor extends FileView {
 
 				while (toRemove.length > 0) {
 					var c = toRemove.pop();
-					c.removeInstance(sceneEditor.context);
+					//c.removeInstance();
 					c.parent.children.remove(c);
 				}
 			}
@@ -642,7 +761,7 @@ class FXEditor extends FileView {
 
 						// We're currently supporting blending with only 2 curves
 						for (i in 0...2) {
-							var c = new Curve();
+							var c = new Curve(null, null);
 							c.parent = curve;
 							c.name = '${curve.name}.${i}';
 						}
@@ -659,7 +778,7 @@ class FXEditor extends FileView {
 
 		if(pname == "time" || pname == "loop" || pname == "animation" || pname == "blendMode" || pname == "blendFactor") {
 			afterPan(false);
-			data.refreshObjectAnims(sceneEditor.getContext(data));
+			data.refreshObjectAnims();
 		}
 
 		if (pname == "loop") {
@@ -674,7 +793,7 @@ class FXEditor extends FileView {
 	}
 
 	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)
 			renderProps.applyProps(scene.s3d.renderer);
 		updateGrid();
@@ -718,7 +837,6 @@ class FXEditor extends FileView {
 
 		var minHeight = 40;
 		var curveEditorHeight = 100;
-		var ctx = sceneEditor.getContext(data);
 
 		for (curve in curves){
 			var dispKey = getPath() + "/" + curve.getAbsPath(true);
@@ -746,7 +864,7 @@ class FXEditor extends FileView {
 			}
 			var shader = curve.parent.to(hrt.prefab.Shader);
 			if(shader != null) {
-				var sh = shader.getShaderDefinition(ctx);
+				var sh = shader.getShaderDefinition();
 				if(sh != null) {
 					var v = sh.data.vars.find(v -> v.kind == Param && v.name == curve.name);
 					if(v != null && v.qualifiers != null) {
@@ -1250,7 +1368,7 @@ class FXEditor extends FileView {
 			var id = prefix != null ? prefix + "." + prop.name : prop.name;
 			if(Curve.getCurve(element, id) != null)
 				continue;
-			var curve = new Curve(element);
+			var curve = new Curve(element,null);
 			curve.name = id;
 			if(prop.def != null)
 				curve.addKey(0, prop.def, Linear);
@@ -1280,6 +1398,7 @@ class FXEditor extends FileView {
 		var obj2dElt = Std.downcast(elt, hrt.prefab.Object2D);
 		var shaderElt = Std.downcast(elt, hrt.prefab.Shader);
 		var emitterElt = Std.downcast(elt, hrt.prefab.fx.Emitter);
+
 		var particle2dElt = Std.downcast(elt, hrt.prefab.l2d.Particle2D);
 		var menuItems : Array<hide.comp.ContextMenu.ContextMenuItem> = [];
 		var lightElt = Std.downcast(elt, Light);
@@ -1364,7 +1483,7 @@ class FXEditor extends FileView {
 		}
 		if(shaderElt != null) {
 			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);
 			for(param in params) {
 				if (param.qualifiers?.contains(Ignore) ?? false)
@@ -1417,6 +1536,7 @@ class FXEditor extends FileView {
 				addParam(param, "Instance ");
 			}
 		}
+
 		if (particle2dElt != null) {
 			for(param in hrt.prefab.l2d.Particle2D.emitter2dParams) {
 				if(!param.animate)
@@ -1424,6 +1544,7 @@ class FXEditor extends FileView {
 				addParam(param, "");
 			}
 		}
+
 		if( lightElt != null ) {
 			switch lightElt.kind {
 				case Point:
@@ -1492,7 +1613,7 @@ class FXEditor extends FileView {
 			return;
 
 		if (is2D) {
-			grid2d = new h2d.Graphics(scene.editor.context.local2d);
+			grid2d = new h2d.Graphics(scene.s2d);
 			grid2d.scale(1);
 
 			grid2d.lineStyle(1.0, 12632256, 1.0);
@@ -1536,11 +1657,9 @@ class FXEditor extends FileView {
 	}
 
 	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()) {
 			currentTime += scene.speed * dt;
 			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);
 		}
 
-
 	}
 
 	var avg_smooth = 0.0;
@@ -1635,11 +1753,11 @@ class FXEditor extends FileView {
 	}
 
 	function onUpdate3D(dt:Float) {
-		var ctx = sceneEditor.getContext(data);
-		if(ctx == null || ctx.local3d == null)
+		var local3d = sceneEditor.root3d;
+		if(local3d == null)
 			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()) {
 			currentTime += scene.speed * dt;
@@ -1662,7 +1780,7 @@ class FXEditor extends FileView {
 
 		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;
 		for(e in emitters) {
 			totalParts += @:privateAccess e.numInstances;
@@ -1676,7 +1794,7 @@ class FXEditor extends FileView {
 			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 trailTime = 0.0;
 		var trailTris = 0.0;
@@ -1777,7 +1895,7 @@ class FXEditor extends FileView {
 	}
 
 	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" });
@@ -1798,8 +1916,8 @@ class FXEditor extends FileView {
 class FX2DEditor extends FXEditor {
 
 	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"));
 		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.editorDisplay = false;
 		sceneEditor.onRefresh = onRefresh;
@@ -142,14 +145,17 @@ class Model extends FileView {
 		sceneEditor.view.keys.register("sceneeditor.focus", {name: "Focus Selection", category: "Scene"},
 			function() {if (lastSelectedObject != null) refreshSelectionHighlight(lastSelectedObject);});
 		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() )
 				return;
 			var toSave = root.children[0];
 			@:privateAccess toSave.save();
 
 			save();
-		});
+		}
+
+		e.on("click", callback);
 	}
 
 	override function onActivate() {
@@ -590,10 +596,10 @@ class Model extends FileView {
 		sceneEditor.loadSavedCameraController3D(true);
 
 		// 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
-		root = new hrt.prefab.Library();
+		root = new hrt.prefab.Prefab(null, null);
 		for (c in @:privateAccess sceneEditor.sceneData.children)
 			@: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
 		var r = root.getOpt(hrt.prefab.RenderProps, true);
 		if( r == null) {
-			var def = new hrt.prefab.Object3D(root);
+			var def = new hrt.prefab.Object3D(root, null);
 			def.name = "Default Ligthing";
-			var render = new hrt.prefab.RenderProps(def);
+			var render = new hrt.prefab.RenderProps(def, null);
 			render.name = "renderer";
-			var l = new hrt.prefab.Light(def);
+			var l = new hrt.prefab.Light(def, null);
 			l.name = "sunLight";
 			l.kind = Directional;
 			l.power = 1.5;
@@ -623,23 +629,23 @@ class Model extends FileView {
 			l.shadows.mode = Dynamic;
 			l.shadows.size = 1024;
 
-			def.make(sceneEditor.context);
+			def.make(new hrt.prefab.ContextShared());
 
 			r = render;
 			r.applyProps(scene.s3d.renderer);
 		}
 
 		// 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 )
 				renderProps.applyProps(scene.s3d.renderer);
 		}
 
-		plight = root.getAll(hrt.prefab.Light)[0];
+		plight = root.find(hrt.prefab.Light);
 		if( plight != null ) {
-			this.light = sceneEditor.context.shared.contexts.get(plight).local3d;
+			this.light = hrt.prefab.Object3D.getLocal3d(plight);
 			lightDirection = this.light.getLocalDirection();
 		}
 

+ 32 - 29
hide/view/Prefab.hx

@@ -1,4 +1,5 @@
 package hide.view;
+import hrt.prefab.l3d.Instance;
 import hide.view.CameraController.CamController;
 using Lambda;
 
@@ -7,12 +8,10 @@ import hxd.Key as K;
 
 import hrt.prefab.Prefab as PrefabElement;
 import hrt.prefab.Object3D;
-import hrt.prefab.l3d.Instance;
 import hide.comp.cdb.DataFiles;
 
 class FiltersPopup extends hide.comp.Popup {
 	var editor:Prefab;
-
 	public function new(?parent:Element, ?root:Element, editor:Prefab, filters:Map<String, Bool>, type:String) {
 		super(parent, root);
 		this.editor = editor;
@@ -46,7 +45,6 @@ class FiltersPopup extends hide.comp.Popup {
 		}
 	}
 }
-
 @:access(hide.view.Prefab)
 class PrefabSceneEditor extends hide.comp.SceneEditor {
 	var parent : Prefab;
@@ -106,7 +104,7 @@ class PrefabSceneEditor extends hide.comp.SceneEditor {
 				var idCol = refCols == null ? null : Instance.findIDColumn(refSheet);
 
 				function make(name) {
-					var p = new Instance(current == null ? sceneData : current);
+					var p = new Instance(current == null ? sceneData : current, null);
 					p.name = name;
 					p.props = makeCdbProps(p, type);
 					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;
-	var data : hrt.prefab.Library;
+	var data : hrt.prefab.Prefab;
 
 	var tools : hide.comp.Toolbar;
 
@@ -213,7 +212,7 @@ class Prefab extends FileView {
 
 
 	function createData() {
-		data = new hrt.prefab.Library();
+		data = new hrt.prefab.Prefab(null, null);
 	}
 
 	function createEditor() {
@@ -225,9 +224,10 @@ class Prefab extends FileView {
 
 		createData();
 		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);
 
+
 		element.html('
 			<div class="flex vertical">
 				<div id="prefab-toolbar"></div>
@@ -394,6 +394,7 @@ class Prefab extends FileView {
 		refreshViewModes();
 		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.setPosition(5, 5);
 		statusText.visible = false;
 
@@ -429,6 +430,9 @@ class Prefab extends FileView {
 
 		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: "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 });
@@ -472,6 +476,7 @@ class Prefab extends FileView {
 			icon: "connectdevelop",
 			type: Toggle((b) -> { sceneEditor.setWireframe(b); }),
 		});
+
 		toolsDefs.push({
 			id: "jointsToggle",
 			title: "Joints",
@@ -530,6 +535,7 @@ class Prefab extends FileView {
 		posToolTip = new h2d.Text(hxd.res.DefaultFont.get(), scene.s2d);
 		posToolTip.dropShadow = { dx : 1, dy : 1, color : 0, alpha : 0.5 };
 
+
 		var gizmo = @:privateAccess sceneEditor.gizmo;
 
 		var onSetGizmoMode = function(mode: hide.view.l3d.Gizmo.EditMode) {
@@ -544,6 +550,7 @@ class Prefab extends FileView {
 		updateStats();
 		updateGrid();
 		initGraphicsFilters();
+
 		initSceneFilters();
 		sceneEditor.onRefresh = () -> {
 			initGraphicsFilters();
@@ -558,7 +565,6 @@ class Prefab extends FileView {
 			var lines : Array<String> = [
 				'Scene objects: ${scene.s3d.getObjectsCount()}',
 				'Interactives: ' + sceneEditor.interactives.count(),
-				'Contexts: ' + sceneEditor.context.shared.contexts.count(),
 				'Triangles: ${scene.engine.drawTriangles}',
 				'Buffers: ${memStats.bufferCount}',
 				'Textures: ${memStats.textureCount}',
@@ -572,9 +578,8 @@ class Prefab extends FileView {
 
 	function resetCamera( top : Bool ) {
 		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)
 			sceneEditor.cameraController.set(200, Math.PI/2, 0.001, targetPt);
@@ -584,7 +589,7 @@ class Prefab extends FileView {
 	}
 
 	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() {
@@ -595,7 +600,7 @@ class Prefab extends FileView {
 		if( !canSave() )
 			return;
 
-		var content = ide.toJSON(data.saveData());
+		@:privateAccess var content = ide.toJSON(data.serialize());
 		var newSign = ide.makeSignature(content);
 		if(newSign != currentSign)
 			haxe.Timer.delay(saveBackup.bind(content), 0);
@@ -682,12 +687,10 @@ class Prefab extends FileView {
 		saveDisplayState("graphicsFilters/" + typeid, enable);
 
 		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) {
 			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);
 		var all = [];
 		if (typeid != 'light')
-			all = data.getAll(hrt.prefab.Prefab, true);
+			all = data.findAll(hrt.prefab.Prefab, true);
 		else
 			all = data.flatten(hrt.prefab.Prefab);
 		for(p in all) {
@@ -741,7 +744,7 @@ class Prefab extends FileView {
 
 	function refreshGraphicsFilters() {
 		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) {
 			var objFilters = obj.getDisplayFilters();
 			for (f in filters) {
@@ -837,7 +840,7 @@ class Prefab extends FileView {
 	}
 
 	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 ) {
 			updateGrid();
 			return;
@@ -851,8 +854,8 @@ class Prefab extends FileView {
 				if(cdbType != null && sceneFilters.get(cdbType) == 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);
@@ -860,17 +863,17 @@ class Prefab extends FileView {
 			color = (color & 0xffffff) | 0xa0000000;
 			var box = p.to(hrt.prefab.l3d.Box);
 			if(box != null) {
-				var ctx = sceneEditor.getContext(box);
-				box.setColor(ctx, color);
+				box.setColor(color);
 			}
 			var poly = p.to(hrt.prefab.l3d.Polygon);
 			if(poly != null) {
-				var ctx = sceneEditor.getContext(poly);
-				poly.setColor(ctx, color);
+				poly.setColor(color);
 			}
 		}
 	}
 
+
+
 	function getDisplayColor(p: PrefabElement) : Null<Int> {
 		var typeId = p.getCdbType();
 		if(typeId != null) {
@@ -883,7 +886,7 @@ class Prefab extends FileView {
 		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) {
-                return m;
+				return m;
 				/*if(moveStep <= 0 || !scene.editor.getSnapStatus() || axisScale)
 					return m;
 
@@ -285,7 +285,7 @@ class Gizmo extends h3d.scene.Object {
 				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 == 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;
 				y = startPos.y + vec.y;
 				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) {
@@ -320,16 +320,17 @@ class Gizmo extends h3d.scene.Object {
 				vec.set(scale, scale, scale);
 			}
 
-            var doRot = false;
+			var doRot = false;
 			if(mode == RotateX || mode == RotateY || mode == RotateZ) {
 				doRot = true;
-                var v1 = startDragPt.sub(startPos);
+				var v1 = startDragPt.sub(startPos);
 				v1.normalize();
 				var v2 = curPt.sub(startPos);
 				v2.normalize();
 
 				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) {
 					tx.visible = true;
 					tx.text = ""+ Math.round(Math.radToDeg(angle)*100)/100. + "°";
@@ -385,10 +386,10 @@ class Gizmo extends h3d.scene.Object {
 					}
 					else if (doRot) {
 						onMove(null, quat, null);
-                    }
-                    else {
+					}
+					else {
 						onMove(vec, null, null);
-                    }
+					}
 				}
 			}
 
@@ -440,9 +441,9 @@ class Gizmo extends h3d.scene.Object {
 		var engine = h3d.Engine.getCurrent();
 		var ratio = 150 / engine.height;
 		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);
 
 		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("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("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 environment : h3d.scene.pbr.Environment;
 
-	var context : hrt.prefab.Context;
 	var offScreenScene : h3d.scene.Scene = null;
 	var prim : h3d.prim.Plane2D;
 
@@ -38,7 +37,6 @@ class LightProbeBaker {
 		customCamera.screenRatio = 1.0;
 		customCamera.fovY = 90;
 		customCamera.zFar = 100;
-		context = new hrt.prefab.Context();
 	}
 
 	public function dispose() {
@@ -58,16 +56,11 @@ class LightProbeBaker {
 		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();
 		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"];
 		function keep( p : hrt.prefab.Prefab ) {
@@ -84,7 +77,8 @@ class LightProbeBaker {
 					filter(c);
 		}
 		filter(sceneData);
-		sceneData.make(context);
+		var shared = new hrt.prefab.ContextShared(sceneData.shared.root2d, offScreenScene);
+		sceneData.make(shared);
 
 		/*function disableFaceCulling( o : Object ){
 			for( m in o.getMaterials() )

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

@@ -18,8 +18,8 @@ class ProbeBakerProcess {
 		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) {
@@ -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 {
 
-	public var shaderDef(default, set) : hrt.prefab.ContextShared.ShaderDef;
+	public var shaderDef(default, set) : hrt.prefab.Cache.ShaderDef;
 	public var shader : DynamicShader;
 
 	function rebuildShader() {
@@ -106,7 +106,7 @@ class Preview extends h2d.Bitmap {
 		addShader(shader);
 	}
 
-	function set_shaderDef(v: hrt.prefab.ContextShared.ShaderDef) {
+	function set_shaderDef(v: hrt.prefab.Cache.ShaderDef) {
 		shaderDef = v;
 		rebuildShader();
 		return v;
@@ -137,7 +137,7 @@ class ShaderEditor extends hide.view.Graph {
 
 	var previewsScene : hide.comp.Scene;
 	var previewParamDirty : Bool = true;
-	var currentShaderPreviewsDef : hrt.prefab.ContextShared.ShaderDef;
+	var currentShaderPreviewsDef : hrt.prefab.Cache.ShaderDef;
 
 	// used to preview
 	var sceneEditor : SceneEditor;
@@ -156,7 +156,7 @@ class ShaderEditor extends hide.view.Graph {
 	var COMPILE_SHADER_DEBOUNCE : Int = 100;
 	var VIEW_VISIBLE_CHECK_TIMER : Int = 500;
 	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);
 		});
 
-		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.kind = Directional;
 		defaultLight.power = 1.5;
@@ -506,8 +506,8 @@ class ShaderEditor extends hide.view.Graph {
 		var relative = ide.makeRelative(path);
 		if( ext == "fbx" )
 			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;
 			sceneEditor.addElements([ref], false, true, false);
 			prefabObj = ref;
@@ -1220,7 +1220,7 @@ class ShaderEditor extends hide.view.Graph {
 	}
 
 	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>;

+ 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;
 
-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 {
-	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 editorDisplay : Bool;
+	public var prefabSource : String = "";
 
 	/**
 		When make() is called on prefab, it will instead call customMake on
 		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>;
-	/**
-		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 ) {
 		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> {
 		var datPath = new haxe.io.Path(currentPath);
 		datPath.ext = "dat";
@@ -150,12 +75,8 @@ class ContextShared {
 		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)
 			return r;
 		var cl : Class<hxsl.Shader> = cast Type.resolveClass(path.split("/").join("."));
@@ -169,20 +90,20 @@ class ContextShared {
 			shader: shader,
 			inits: []
 		};
-		shaderCache.set(path, r);
+		Cache.get().shaderDefCache.set(path, r);
 		return r;
 	}
 
 	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 ) {
-		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 ) {
-		return cache.loadTexture(null, path, async);
+		return Cache.get().modelCache.loadTexture(null, path, async);
 	}
 
 	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> {
-		var root = getSelfObject(p);
+		var root = p.to(Object3D)?.local3d;
 		if(root == null) return [];
 		var childObjs = getChildrenRoots(root, p, []);
 		var ret = [];
@@ -308,28 +206,16 @@ class ContextShared {
 		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;
+
+#if editor
+import hide.prefab.EditContext;
+#end
+
+import hide.prefab.HideProps;
+
+import hrt.prefab.fx.Value;
+
 using Lambda;
 
+@:build(hrt.prefab.Macros.buildSerializable())
 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) {
 		this.dt = t;
 		this.dv = v;
@@ -23,12 +33,13 @@ enum abstract CurveBlendMode(Int) {
 	var RandomBlend = 2;
 }
 
+@:build(hrt.prefab.Macros.buildSerializable())
 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() {}
 }
 
@@ -37,8 +48,8 @@ typedef CurveKeys = Array<CurveKey>;
 class Curve extends Prefab {
 
 	@:s public var keyMode : CurveKeyMode = Linear;
-	@:c public var keys : CurveKeys = [];
-	@:c public var previewKeys : CurveKeys = [];
+	@:s public var keys : CurveKeys = [];
+	@:s public var previewKeys : CurveKeys = [];
 
 	@:s public var blendMode : CurveBlendMode = None;
 	@:s public var blendFactor : Float = 0;
@@ -64,49 +75,60 @@ class Curve extends Prefab {
 		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) {
 		super.load(o);
-		keys = [];
-		if(o.keys != null) {
-			for(k in (o.keys: Array<Dynamic>)) {
-				var nk = new CurveKey();
-				nk.time = k.time;
-				nk.value = k.value;
-				nk.mode = k.mode;
-				if(k.prevHandle != null)
-					nk.prevHandle = new CurveHandle(k.prevHandle.dt, k.prevHandle.dv);
-				if(k.nextHandle != null)
-					nk.nextHandle = new CurveHandle(k.nextHandle.dt, k.nextHandle.dv);
-				keys.push(nk);
-			}
-		}
 		if( keys.length == 0 ) {
 			addKey(0.0, 0.0);
 			addKey(1.0, 1.0);
 		}
 	}
 
-	public override function save() {
-		var obj : Dynamic = super.save();
-		var keysDat = [];
-		for(k in keys) {
-			var o = {
-				time: k.time,
-				value: k.value,
-				mode: k.mode
-			};
-			if(k.prevHandle != null) Reflect.setField(o, "prevHandle", { dv: k.prevHandle.dv, dt: k.prevHandle.dt });
-			if(k.nextHandle != null) Reflect.setField(o, "nextHandle", { dv: k.nextHandle.dv, dt: k.nextHandle.dt });
-			keysDat.push(o);
-		}
-		obj.keys = keysDat;
-		return obj;
-	}
+	// 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) {
 		var u = 1 - t;
@@ -378,7 +400,7 @@ class Curve extends Prefab {
 		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) {
 			return findCurve(curves, s);
 		}
@@ -387,7 +409,7 @@ class Curve extends Prefab {
 		var z = find(".z");
 		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)
 				return VConst(defVal);
 
@@ -407,7 +429,7 @@ class Curve extends Prefab {
 			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) {
 			return findCurve(curves, s);
 		}
@@ -441,5 +463,5 @@ class Curve extends Prefab {
 			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 {
 
-	var shaderDef : hrt.prefab.ContextShared.ShaderDef;
+	var shaderDef : hrt.prefab.Cache.ShaderDef;
 	var shaderClass : Class<hxsl.Shader>;
 	@:s var isInstance : 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) {
@@ -20,16 +19,15 @@ class DynamicShader extends Shader {
 		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;
 	}
 
-	override function makeShader( ?ctx:Context ) {
-		if( getShaderDefinition(ctx) == null )
+	override function makeShader() {
+		if( getShaderDefinition() == null )
 			return null;
-		var shader;
 		if( isInstance && !isShadergraph)
 			shader = Type.createInstance(shaderClass,[]);
 		else {
@@ -43,12 +41,6 @@ class DynamicShader extends Shader {
 		return shader;
 	}
 
-	override function makeInstance(ctx:Context):Context {
-		if( source == null )
-			return ctx;
-		return super.makeInstance(ctx);
-	}
-
 	function fixSourcePath() {
 		#if editor
 		// shader source is loaded with ../src/path/to/Shader.hx
@@ -76,7 +68,7 @@ class DynamicShader extends Shader {
 		return cl;
 	}
 
-	public function loadShaderDef(ctx: Context) {
+	public function loadShaderDef() {
 		if(shaderDef == null) {
 			fixSourcePath();
 			if (StringTools.endsWith(source, ".shgraph")) {
@@ -97,7 +89,7 @@ class DynamicShader extends Shader {
 			} else {
 				var path = source;
 				if(StringTools.endsWith(path, ".hx")) path = path.substr(0, -3);
-				shaderDef = ctx.loadShader(path);
+				shaderDef = shared.loadShader(path);
 			}
 		}
 		if(shaderDef == null)
@@ -175,5 +167,5 @@ class DynamicShader extends Shader {
 		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
 	@:s public var debugDisplay : Bool = true;
 
+	#if editor
+	var icon : hrt.impl.EditorTools.EditorIcon = null;
+	#end
+
 	static function getShadowsDefault() : LightShadows {
 		return {
 			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;
 		zNear = 0.02;
 	}
 
-	override function save() {
+	override function save() : Dynamic {
 		var obj : Dynamic = super.save();
 		if( shadows.mode != None ) {
 			obj.shadows = Reflect.copy(shadows);
@@ -117,23 +120,23 @@ class Light extends Object3D {
 		super.load(obj);
 		if( obj.shadows != null ) {
 			var sh : Dynamic = Reflect.copy(obj.shadows);
-			sh.mode = h3d.pass.Shadows.RenderMode.createByName(sh.mode);
 			shadows = sh;
+			shadows.mode = h3d.pass.Shadows.RenderMode.createByName(sh.mode);
 		} else
 			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.y = y;
 		o.z = z;
 		o.setRotation(hxd.Math.degToRad(rotationX), hxd.Math.degToRad(rotationY), hxd.Math.degToRad(rotationZ));
+
 	}
 
 	function initTexture( path : String, ?wrap : h3d.mat.Data.Wrap ) {
@@ -145,37 +148,36 @@ class Light extends Object3D {
 		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);
 		if( !isPbr ) {
 			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 Capsule:
 			}
 		} else {
 			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
-		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
 
 		cookieTex = initTexture(cookiePath);
-		updateInstance(ctx);
-		return ctx;
+
+		return object;
 	}
 
-	#if editor
+	/*#if editor
 	override function removeInstance(ctx:Context):Bool {
 		var icon = Std.downcast(ctx.custom, hrt.impl.EditorTools.EditorIcon);
 		if (icon != null) {
@@ -184,17 +186,18 @@ class Light extends Object3D {
 		}
 		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 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 ) {
 			case Directional:
@@ -266,10 +269,10 @@ class Light extends Object3D {
 		}
 
 		#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;
 
 		switch(kind){
@@ -283,7 +286,7 @@ class Light extends Object3D {
 				var rangeSphere : h3d.scene.Sphere;
 
 				if(debugPoint == null) {
-					debugPoint = new h3d.scene.Object(ctx.local3d);
+					debugPoint = new h3d.scene.Object(local3d);
 					debugPoint.name = "_debugPoint";
 
 					rangeSphere = new h3d.scene.Sphere(0xffffff, 1, true, debugPoint);
@@ -315,7 +318,7 @@ class Light extends Object3D {
 				if(debugCapsule != null) debugCapsule.remove();
 
 				if(debugDir == null) {
-					debugDir = new h3d.scene.Object(ctx.local3d);
+					debugDir = new h3d.scene.Object(local3d);
 					debugDir.name = "_debugDir";
 
 
@@ -342,7 +345,7 @@ class Light extends Object3D {
 				if(debugCapsule != null) debugCapsule.remove();
 
 				if(debugSpot == null) {
-					debugSpot = new h3d.scene.Object(ctx.local3d);
+					debugSpot = new h3d.scene.Object(local3d);
 					debugSpot.name = "_debugSpot";
 
 					var g = new h3d.scene.Graphics(debugSpot);
@@ -387,7 +390,7 @@ class Light extends Object3D {
 				var rangeCapsule : h3d.scene.Capsule;
 
 				if(debugCapsule == null) {
-					debugCapsule = new h3d.scene.Object(ctx.local3d);
+					debugCapsule = new h3d.scene.Object(local3d);
 					debugCapsule.name = "_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) {
 			icon.color = h3d.Vector4.fromColor(color);
 
@@ -437,10 +439,10 @@ class Light extends Object3D {
 		var isSelected = false;
 		if(sel != null){
 			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";
 		}
 
@@ -452,14 +454,14 @@ class Light extends Object3D {
 
 	#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;
-		updateInstance(ctx);
+		updateInstance();
 		return true;
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		var group = new hide.Element('
@@ -527,7 +529,7 @@ class Light extends Object3D {
 				ctx.rebuildProperties();
 			}
 			else{
-				if( pname == "cookiePath") cookieTex = loadTexture(ctx, this.cookiePath, cookieTex, Clamp);
+				if( pname == "cookiePath") cookieTex = loadTextureCustom(this.cookiePath, cookieTex, Clamp);
 				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(propsName == null) return null;
-		texture = ctx.rootContext.loadTexture(propsName);
+		texture = shared.loadTexture(propsName);
 		texture.wrap = wrap == null ? Repeat : wrap;
 		return texture;
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "sun-o", name : "Light" };
 	}
 	#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.Object;
 import h3d.mat.PbrMaterial;
+import hide.prefab.HideProps;
 
 class Material extends Prefab {
 
@@ -16,19 +17,24 @@ class Material extends Prefab {
 	@:s public var refMatLib : String;
 	@:s public var overrides : Array<Dynamic> = [];
 
-	public function new(?parent) {
-		super(parent);
-		type = "material";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		props = {};
 	}
 
-	override function load(obj:Dynamic) {
+	override function load(obj:Dynamic) : Void {
 		super.load(obj);
 		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(mainPassName == "" || mainPassName == null ) Reflect.deleteField(obj, "mainPassName");
 		return obj;
@@ -49,8 +55,8 @@ class Material extends Prefab {
 		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));
 		return mat == null ? mats : [mat];
 	}
@@ -79,11 +85,12 @@ class Material extends Prefab {
 			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;
 
-		var mats = getMaterials(ctx);
+		var mats = getMaterials();
 
 		if (this.refMatLib != null && this.refMatLib != "") {
 			// 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 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) {
 				if (c.name != refMatName)
@@ -120,27 +127,27 @@ class Material extends Prefab {
 		if ( mats == null || mats.length == 0 ) {
 			var sphere = new h3d.prim.Sphere(1., 64, 48);
 			sphere.addUVs();
-			sphere.addNormals();
+            sphere.addNormals();
 			sphere.addTangents();
 			var preview = new h3d.scene.Mesh(sphere);
 			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
+		function loadTextureCb( path : String ) : h3d.mat.Texture {
+			return shared.loadTexture(path, false);
+		}
 		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() {
@@ -179,7 +186,7 @@ class Material extends Prefab {
 	}
 
 	#if editor
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		var isPbr = Std.isOfType(ctx.scene.s3d.renderer, h3d.scene.pbr.Renderer);
@@ -222,39 +229,39 @@ class Material extends Prefab {
 
 		function updateLibSelect() {
 			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) {
-				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() {
 			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());
 
 			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() {
-			var previousMat = this.clone();
+			var previousMat = this.serialize();
 			var mat = ctx.scene.findMat(materials, matSelect.val());
 			if ( mat != null ) {
 				var previousName = this.name;
 				this.load(Reflect.field(mat, "mat"));
 				this.name = previousName;
 				this.refMatLib = Reflect.field(mat, "path") + "/" + Reflect.field(mat, "mat").name;
-				updateInstance(ctx.scene.editor.getContext(this));
+				updateInstance();
 				ctx.rebuildProperties();
 			} else {
 				this.refMatLib = "";
 			}
 
-			var newMat = this.clone();
+			var newMat = this.serialize();
 
 			ctx.properties.undo.change(Custom(function(undo) {
 				if( undo ) {
@@ -267,7 +274,7 @@ class Material extends Prefab {
 				updateLibSelect();
 				updateMatSelect();
 				ctx.rebuildProperties();
-				updateInstance(ctx.scene.editor.getContext(this));
+				updateInstance();
 			}));
 		}
 
@@ -335,7 +342,7 @@ class Material extends Prefab {
 
 			ctx.onChange(this, "props");
 
-			var fx = getParent(hrt.prefab.fx.FX);
+			var fx = findParent(hrt.prefab.fx.FX);
 			if(fx != null)
 				ctx.rebuildPrefab(fx, true);
 		});
@@ -355,12 +362,12 @@ class Material extends Prefab {
 			</div>');
 			ctx.properties.add(colorMask, this, function(pname) {
 				ctx.onChange(this, pname);
-				var fx = getParent(hrt.prefab.fx.FX);
+				var fx = findParent(hrt.prefab.fx.FX);
 				if(fx != null)
 					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 val : Int = cast Reflect.field(pbrProps, field);
 				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);
 					}));
 
-					var fx = getParent(hrt.prefab.fx.FX);
+					var fx = findParent(hrt.prefab.fx.FX);
 					if(fx != null)
 						ctx.rebuildPrefab(fx, true);
 				});
@@ -499,7 +506,7 @@ class Material extends Prefab {
 					<dt>Name</dt><dd><select><option value="any">Any</option></select>
 				</dl> ');
 		var select = dropDownMaterials.find("select");
-		var materialList = ctx.rootContext.local3d.getMaterials();
+		var materialList = findFirstLocal3d().getMaterials();
 		for( m in materialList )
 			if( m.name != null && m.name != "" )
 				new hide.Element('<option>').attr("value", m.name).text(m.name).appendTo(select);
@@ -518,7 +525,7 @@ class Material extends Prefab {
 			ctx.rebuildProperties();
 			ctx.scene.editor.refresh();
 
-			var fx = getParent(hrt.prefab.fx.FX);
+			var fx = findParent(hrt.prefab.fx.FX);
 			if(fx != null)
 				ctx.rebuildPrefab(fx, true);
 		});
@@ -541,7 +548,7 @@ class Material extends Prefab {
 			if (this.refMatLib != null && this.refMatLib != "")
 				addOverrideProperty(ctx, pname, false);
 
-			var fx = getParent(hrt.prefab.fx.FX);
+			var fx = findParent(hrt.prefab.fx.FX);
 			if(fx != null)
 				ctx.rebuildPrefab(fx, true);
 		});
@@ -549,7 +556,7 @@ class Material extends Prefab {
 		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
 		var idx = 0;
 		while (idx < overrides.length) {
@@ -573,7 +580,7 @@ class Material extends Prefab {
 		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(".remove-override-btn").remove();
 
@@ -592,11 +599,11 @@ class Material extends Prefab {
 			parentDiv.addClass("override");
 
 			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.on("click", function(_){
 				overrides.remove(o);
-				updateInstance(ctx.scene.editor.getContext(this));
+				updateInstance();
 				ctx.rebuildProperties();
 			});
 		}
@@ -617,7 +624,7 @@ class Material extends Prefab {
 				var refPath = refMatLib.substr(0,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
@@ -630,5 +637,5 @@ class Material extends Prefab {
 		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 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;
 		return super.save();
 	}
 
-	override function makeInstance(ctx:Context):Context {
+	override function makeObject(parent3d:h3d.scene.Object):h3d.scene.Object {
 		if( source == null)
-			return super.makeInstance(ctx);
-		ctx = ctx.clone(this);
+			return super.makeObject(parent3d);
+
 		#if editor
 		try {
 		#end
-			var obj = ctx.loadModel(source);
+			var obj = shared.loadModel(source);
 			if(obj.defaultTransform != null && children.length > 0) {
 				obj.name = "root";
 				var root = new h3d.scene.Object();
@@ -39,25 +38,19 @@ class Model extends Object3D {
 			if( retargetAnim ) applyRetarget(obj);
 
 			obj.name = name;
-			ctx.local3d.addChild(obj);
-			ctx.local3d = obj;
-			updateInstance(ctx);
-
+			parent3d.addChild(obj);
 
 			if( animation != null )
-				obj.playAnimation(ctx.loadAnimation(animation));
+				obj.playAnimation(shared.loadAnimation(animation));
 
-			return ctx;
+			return obj;
 		#if editor
 		} catch( e : Dynamic ) {
 			e.message = "Could not load model " + source + ": " + e.message;
-			ctx.shared.onError(e);
+			shared.onError(e);
 		}
 		#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 ) {
@@ -91,24 +84,24 @@ class Model extends Object3D {
 
 	#if editor
 
-	override function updateInstance( ctx: Context, ?propName : String ) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String ) {
+		super.updateInstance(propName);
 		polys3D = null;
 		boundingSphere = null;
 	}
 
     var polys3D = 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 ) {
             polys3D = [];
-            var bounds = ctx.local3d.getBounds();
-			bounds.transform(ctx.local3d.getAbsPos().getInverse());
+            var bounds = local3d.getBounds();
+			bounds.transform(local3d.getAbsPos().getInverse());
             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 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;
     }
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		var props = ctx.properties.add(new hide.Element('
 			<div class="group" name="Animation">
 				<dl>
 					<dt>Model</dt><dd><input type="model" field="source"/></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>Retarget</dt><dd><input type="checkbox" field="retargetAnim"></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) {
 			var v = newAnim;
 			var prev = animation;
-			var obj = ctx.getContext(this).local3d;
+			var obj = local3d;
 			ctx.scene.setCurrent();
 			if( v == "" ) {
 				animation = null;
 				obj.stopAnimation();
 			} else {
-				obj.playAnimation(ctx.rootContext.loadAnimation(v)).loop = true;
+				obj.playAnimation(shared.loadAnimation(v)).loop = true;
 				if( lockAnimation ) return;
 				animation = v;
 			}
 			var newValue = animation;
 			ctx.properties.undo.change(Custom(function(undo) {
-				var obj = ctx.getContext(this).local3d;
+				var obj = local3d;
 				animation = undo ? prev : newValue;
 				if( animation == null ) {
 					obj.stopAnimation();
 				} else {
-					obj.playAnimation(ctx.rootContext.loadAnimation(animation)).loop = true;
+					obj.playAnimation(shared.loadAnimation(animation)).loop = true;
 				}
 				select.value = animation;
 			}));
-		}
+		};
 	}
 
-
-
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return {
 			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),
 		};
 	}
 	#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;
 import hxd.Math;
-using Lambda;
 
 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 scaleY : Float = 1.;
 	@:s public var rotation : Float = 0.;
 
 	@: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) {
 		x = t.x;
@@ -33,34 +71,6 @@ class Object2D extends Prefab {
 		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 ) {
 		o.x = x;
 		o.y = y;
@@ -69,8 +79,8 @@ class Object2D extends Prefab {
 		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.y = y;
 		if(propName == null || propName.indexOf("scale") == 0) {
@@ -86,15 +96,16 @@ class Object2D extends Prefab {
 			if (blendMode != null) o.blendMode = blendMode;
 	}
 
-	override function removeInstance(ctx: Context):Bool {
-		if(ctx.local2d != null)
-			ctx.local2d.remove();
-		return true;
-	}
-
 	#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('
 			<div class="group" name="Position">
 				<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;
 import hxd.Math;
-using Lambda;
 
 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) {
@@ -66,6 +44,61 @@ class Object3D extends Prefab {
 		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 ) {
 		if( m == null ) m = new h3d.Matrix();
@@ -75,11 +108,31 @@ class Object3D extends Prefab {
 		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;
 		while( p != null ) {
 			var obj = p.to(Object3D);
 			if( obj == null ) {
+				if( p.parent == null && followRefs ) {
+					p = p.shared.parentPrefab;
+					continue;
+				}
 				p = p.parent;
 				continue;
 			}
@@ -91,41 +144,38 @@ class Object3D extends Prefab {
 		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 ) {
 			for( m in materials ) {
@@ -155,23 +205,25 @@ class Object3D extends Prefab {
 		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
-		var shared = Std.downcast(ctx.shared, hide.prefab.ContextShared);
-		if( shared != null && shared.editorDisplay ) {
+
 			var sheet = getCdbType();
 			if( sheet != null ) {
 				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 ) {
 					for( key in Reflect.fields(ranges) ) {
 						var color = Std.parseInt(Reflect.field(ranges,key));
 						var value : Dynamic = hide.comp.cdb.DataFiles.resolveCDBValue(sheet,key, props);
 						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.ignoreCollide = 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);
 				if( icon != null ) {
 					var t : Dynamic = hide.comp.cdb.DataFiles.resolveCDBValue(sheet,icon, props);
 					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.followVisibility = true;
 						}
@@ -206,7 +258,7 @@ class Object3D extends Prefab {
 								bmp = new h2d.Bitmap(null, obj);
 								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.y * t.size,
 								(t.width == null ? 1 : t.width) * t.size,
@@ -220,7 +272,7 @@ class Object3D extends Prefab {
 								int.y = bmp.tile.dy;
 
 								int.onClick = function(e) {
-									var editorContext = Std.downcast(ctx.shared, hide.prefab.ContextShared);
+									var editorContext = Std.downcast(shared, hide.prefab.ContextShared);
 									if (editorContext != null)
 										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)
 			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();
 		invRootMat.invert();
 		var bounds = new h3d.col.Bounds();
@@ -297,6 +351,14 @@ class Object3D extends Prefab {
 				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();
 			lb.transform(localMat);
 			bounds.add(lb);
@@ -332,7 +394,7 @@ class Object3D extends Prefab {
 		return int;
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 			<div class="group" name="Position">
 				<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
 		var cname = Type.getClassName(Type.getClass(this)).split(".").pop();
 		return {
@@ -364,12 +422,6 @@ class Object3D extends Prefab {
 			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;
 
-/**
-	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 {
 
 	/**
-		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
 	**/
-	@: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.
@@ -27,9 +56,9 @@ class Prefab {
 	@: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.
@@ -60,140 +89,157 @@ class Prefab {
 	/**
 		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) {
-		if( parent != null )
+		if( parent != null ) {
 			parent.children.remove(this);
+		}
 		parent = p;
-		if( parent != null )
+		if( parent != null ) {
+			this.shared = parent.shared;
 			parent.children.push(this);
+		}
+		else {
+			setSharedRec(new ContextShared(false));
+		}
 		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.
@@ -249,68 +295,63 @@ class Prefab {
 				prev.reload(v);
 				newchild.push(prev);
 			} else {
-				newchild.push(loadPrefab(v,this));
+				newchild.push(createFromDynamic(v,this));
 			}
 		}
 		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 ) {
-			var p = c.getPrefabByName(name);
+			var p = c.getOpt(cl, name, followRefs);
 			if( p != null )
 				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 ) {
-			var v = p.find(f, followRefs);
+			var v = p.find(cl, filter, followRefs);
 			if( v != null ) return v;
 		}
 		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 = [];
-		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;
 	}
 
 	/**
-		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;
 	}
 
 	/**
-		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) {
 		if(parent == null)
 			return "";
-		var path = name != null ? name : getDefaultName();
+		var path = name ?? "";
 		if(unique) {
 			var suffix = 0;
 			for(i in 0...parent.children.length) {
@@ -459,7 +485,7 @@ class Prefab {
 				if(c == this)
 					break;
 				else {
-					var cname = c.name != null ? c.name : c.getDefaultName();
+					var cname = c.name ?? "";
 					if(cname == path)
 						++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) {
 			var f = new haxe.io.Path(source).file;
 			f = f.split(" ")[0].split("-")[0];
@@ -483,26 +590,188 @@ class Prefab {
 		}
 		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;
 
 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() {
 		var obj : Dynamic = super.save();
 		#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
 		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( 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);
-		if (editMode && ref != null) {
-			for (c in ref.children) {
-				c.flatten(cl, arr);
-			}
+		if (editMode && refInstance != null) {
+			arr = refInstance.flatten(cl, arr);
 		}
 		return arr;
 	}
 
+	override function dispose() {
+		super.dispose();
+		if( refInstance != null )
+			refInstance.dispose();
+	}
+
 	#if editor
 
-	override function makeInteractive(ctx) {
+	override function makeInteractive() {
 		if( editMode )
 			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('
 			<div class="group" name="Reference">
 			<dl>
@@ -167,7 +135,7 @@ class Reference extends Object3D {
 
 		function updateProps() {
 			var input = element.find("input");
-			var found = resolveRef(ctx.rootContext.shared) != null;
+			var found = resolveRef() != null;
 			input.toggleClass("error", !found);
 		}
 		updateProps();
@@ -175,7 +143,7 @@ class Reference extends Object3D {
 		var props = ctx.properties.add(element, this, function(pname) {
 			ctx.onChange(this, pname);
 			if(pname == "source" || pname == "editMode") {
-				ref = null;
+				refInstance = null;
 				updateProps();
 				if(!ctx.properties.isTempChange)
 					ctx.rebuildPrefab(this);
@@ -185,10 +153,11 @@ class Reference extends Object3D {
 		super.edit(ctx);
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "share", name : "Reference" };
 	}
 	#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;
 
-	public function new(?parent) {
-		super(parent);
-		type = "renderProps";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		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) {
@@ -67,7 +63,8 @@ class RenderProps extends Prefab {
 		renderer.props = props;
 		for(fx in renderer.effects)
 			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);
 		if( env != null )
 			env.applyToRenderer(renderer);
@@ -77,7 +74,7 @@ class RenderProps extends Prefab {
 
 	#if editor
 
-	override function edit( ctx : EditContext ) {
+	override function edit(ctx) {
 		super.edit(ctx);
 		var renderer = ctx.scene.s3d.renderer;
 		var props = getProps(renderer);
@@ -93,19 +90,19 @@ class RenderProps extends Prefab {
 			}
 			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);
 	}
 
-	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
 
-	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;
 
+@:access(hrt.prefab.Prefab)
 class Resource extends hxd.res.Resource {
 
-	var lib : Prefab;
+	var prefab : Prefab;
 	var cacheVersion : Int;
 	var isWatched : Bool;
 
@@ -16,10 +17,10 @@ class Resource extends hxd.res.Resource {
 		}
 		isWatched = true;
 		super.watch(function() {
-			if( lib != null ) {
+			if( prefab != null ) {
 				var data = try loadData() catch( e : Dynamic ) return; // parsing error (conflict ?)
-				lib.reload(data);
-				onPrefabLoaded(lib);
+				prefab.reload(data);
+				onPrefabLoaded(prefab);
 			}
 			onChanged();
 		});
@@ -31,22 +32,33 @@ class Resource extends hxd.res.Resource {
 	}
 
 	public function load() : Prefab {
-		if( lib != null && cacheVersion == CACHE_VERSION)
-			return lib;
+		if( prefab != null && cacheVersion == CACHE_VERSION )
+			return prefab;
 		var data = loadData();
-		lib = Library.create(entry.extension);
-		lib.loadData(data);
+		prefab = Prefab.createFromDynamic(data, new ContextShared(entry.path, false));
 		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";
 		var r = new Resource(null);
-		r.lib = p;
+		r.prefab = p;
 		return r;
 	}
 

+ 43 - 44
hrt/prefab/Shader.hx

@@ -2,31 +2,35 @@ package hrt.prefab;
 
 import hrt.impl.Gradient;
 import hrt.impl.TextureType;
+import hide.prefab.HideProps;
 
 class Shader extends Prefab {
 
 	@:s var targetMaterial : String;
 	@:s var recursiveApply = true;
 
-	function new(?parent) {
-		super(parent);
+	public var shader : hxsl.Shader;
+
+	function new(parent, sh: ContextShared) {
+		super(parent, sh);
 		props = {};
 	}
 
-	public function makeShader( ?ctx : hrt.prefab.Context ) : hxsl.Shader {
+	public function makeShader() : hxsl.Shader {
 		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;
 	}
 
-	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;
-		syncShaderVars(ctx.custom, shaderDef);
+		syncShaderVars(shader, shaderDef);
 	}
 
 	function syncShaderVars( shader : hxsl.Shader, shaderDef : hxsl.SharedShader ) {
@@ -80,21 +84,20 @@ class Shader extends Prefab {
 		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) {
 		return targetMaterial == null || targetMaterial == mat.name;
 	}
 
-	function iterMaterials(ctx:Context, callb) {
+	function iterMaterials(callb) {
 		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) ) {
 			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);
 		} else {
 			var objs = [];
@@ -114,42 +117,39 @@ class Shader extends Prefab {
 					for( o in shared.getObjects(c, h3d.scene.Object) )
 						pushUnique(o);
 			} 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( m in obj.getMaterials(false) )
 					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 )
-			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) {
 				drawable.addShader(shader);
-				ctx.cleanup = function() {
-					drawable.removeShader(shader);
-				}
 			} else {
-				var flow = Std.downcast(ctx.local2d, h2d.Flow);
+				var flow = Std.downcast(shared.current2d, h2d.Flow);
 				if (flow != null) {
 					@:privateAccess if (flow.background != null) {
 						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
@@ -168,13 +168,12 @@ class Shader extends Prefab {
 		return props;
 	}
 
-	override function edit( ectx : EditContext ) {
+	override function edit( ectx : hide.prefab.EditContext ) {
 		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");
 			ectx.properties.add(el);
 			return;
@@ -186,7 +185,7 @@ class Shader extends Prefab {
 			</dl>
 		</div>');
 		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 )
 			materials.push(targetMaterial);
 		if( materials.length >= 2 || targetMaterial != null ) {
@@ -213,7 +212,7 @@ class Shader extends Prefab {
 			ectx.onChange(this, pname);
 
 			// 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)
 				ectx.rebuildPrefab(fx, true);
 		});
@@ -252,7 +251,7 @@ class Shader extends Prefab {
 		return {
 			icon : "cog",
 			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
 		};
 	}

+ 54 - 21
hrt/prefab/Unknown.hx

@@ -1,36 +1,69 @@
 package hrt.prefab;
 
+/**
+	Allow openning prefabs with a type not found in the project, keeping the data unchanged.
+**/
 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() {
-		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;
 
+using hrt.prefab.Object3D;
 typedef ChunkData = {
 	var id : String;
 	var level : Int;
@@ -33,9 +34,8 @@ class World extends Object3D {
 	}
 	var datDir : String;
 
-	public function new(?parent) {
-		super(parent);
-		type = "world";
+	public function new(parent, shared) {
+		super(parent, shared);
 		chunkPrefabs = [];
 	}
 
@@ -46,9 +46,7 @@ class World extends Object3D {
 		var content = chunkPrefabs.get(data.id);
 		if ( content == null )
 			return;
-		var ctx = new hrt.prefab.Context();
-		ctx.init();
-		ctx.local2d = null;
+
 		var tmp = new h3d.scene.Object();
 		tmp.name = "chunk_inverse_transform";
 		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.
 		tmp.x = -chunkPos.x;
 		tmp.y = -chunkPos.y;
-		ctx.local3d = tmp;
 		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;
 			#if editor
 			for ( elt in p.flatten() )
-				@:privateAccess editor.makeInteractive(elt, ctx.shared);
+				@:privateAccess editor.makeInteractive(elt);
 			if ( editor != null ) {
 				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 pobj2d = context.shared.root2d;
 					if ( context.local3d != pobj && context.local3d != null )
 						editor.curEdit.rootObjects.push(context.local3d);
 					if ( context.local2d != pobj2d && context.local2d != null )
 						editor.curEdit.rootObjects2D.push(context.local2d);
-				}
+				}*/
 			}
 			#end
 		}
@@ -86,7 +84,7 @@ class World extends Object3D {
 			var id = data.id;
 			var path = datDir + id + "/content.prefab";
 			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);
 			var i = p.children.length;
 			while ( i-- > 0 ) {
@@ -167,19 +165,19 @@ class World extends Object3D {
 		return 0;
 	}
 
-	override function saveData() : {} {
+	override function serialize() : Dynamic {
 		var tmpChildren = [];
 
 		var chunks = new Map();
 		if ( children.length > 0 ) {
 			for ( c in children ) {
 				if ( !isStreamable(c) )
-					tmpChildren.push(c.saveData());
+					tmpChildren.push(c.serialize());
 				else {
 					var object3D = Std.downcast(c, hrt.prefab.Object3D);
 					if ( object3D == null )
 						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);
 					// 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.
@@ -193,7 +191,7 @@ class World extends Object3D {
 						chunk.children = [];
 						chunks.set(data.id, chunk);
 					}
-					chunk.children.push(object3D.saveData());
+					chunk.children.push(object3D.serialize());
 					if ( findChunk(data.id) == null ) {
 						chunkData.push(data);
 					}
@@ -240,8 +238,8 @@ class World extends Object3D {
 		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 )
 			'${path.file}.dat/';
 		else
@@ -252,18 +250,12 @@ class World extends 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();
 		initBounds();
 		var d = { size : size,
@@ -274,21 +266,21 @@ class World extends Object3D {
 			maxDepth : depth,
 			onCreate : onCreateChunk,
 		};
-		var worldObj = createObjectFromData(ctx, d);
-		ctx.local3d = worldObj;
+		var worldObj = createObjectFromData(d);
+
 		for( c in children ) {
 			if ( !isStreamable(c) )
-				makeChild(ctx, c);
+				makeChild(c);
 		}
 		// Calling init on root after non streamable objects are made.
 		// This way objects such as terrain can be created in custom onCreateChunk.
 		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;
 	}
 
@@ -324,5 +316,5 @@ class World extends Object3D {
 	}
 	#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 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 inst = null;
 		if(anim == null) { return null; }
@@ -45,14 +40,14 @@ class AnimEvent extends hrt.prefab.fx.Event {
 	}
 
 	#if editor
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 		var props = ctx.properties.add(new hide.Element('
 			<div class="group" name="Event">
 				<dl>
 					<dt>Time</dt><dd><input type="number" value="0" field="time"/></dd>
 					<dt>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>Duration</dt><dd><input type="number" value="0" field="duration"/></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 {
 			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
 		};
 	}
 
-	override function getDisplayInfo(ctx: EditContext) {
+	override function getDisplayInfo(ctx: hide.prefab.EditContext) {
 		var anim = null;
 		if(animation != null) {
 			try {
-				anim = ctx.rootContext.loadAnimation(animation);
+				anim = shared.loadAnimation(animation);
 			} catch(e : hxd.res.NotFound) { }
 		}
 		return {
@@ -107,6 +102,6 @@ class AnimEvent extends hrt.prefab.fx.Event {
 	}
 	#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;
 import hrt.prefab.Curve;
 import hrt.prefab.Prefab as PrefabElement;
+import hrt.prefab.fx.Value as Value;
+
+import hrt.prefab.fx.Evaluator;
 
 typedef ShaderParam = {
 	idx: Int,
@@ -102,38 +105,25 @@ typedef ObjectAnimation = {
 	?additionalProperies : AdditionalProperies
 };
 
-class BaseFX extends hrt.prefab.Library {
-	public static var useAutoPerInstance = true;
+interface BaseFX {
 
 	@:s public var duration : Float;
 	@:s public var startDelay : Float;
 	@:c public var scriptCode : String;
 	@:c public var cullingRadius : 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)
 			return null;
 
@@ -186,37 +176,35 @@ class BaseFX extends hrt.prefab.Library {
 	}
 
 	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)
 		if(Std.downcast(elt, hrt.prefab.fx.Emitter) == null) {
 			for(c in elt.children) {
-				getShaderAnims(ctx, c, anims, batch);
+				getShaderAnims(c, anims, batch);
 			}
 		}
 
 		var shader = elt.to(hrt.prefab.Shader);
-		if(shader == null)
+		if(shader == null || shader.shader == null)
 			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;
-				}
-				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();
 			anim.shader = shader;
 			anim.params = params;
@@ -224,17 +212,16 @@ class BaseFX extends hrt.prefab.Library {
 		}
 
 		if(batch != null) {
-			var shader = Std.downcast(ctx.custom, hxsl.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" )
 			return elt;
 		else {
 			for(c in elt.children) {
-				var elt = getFXRoot(ctx, c);
+				var elt = getFXRoot(c);
 				if(elt != null) return elt;
 			}
 		}
@@ -242,6 +229,6 @@ class BaseFX extends hrt.prefab.Library {
 	}
 
 	#if editor
-	public function refreshObjectAnims(ctx: Context) { }
+	public function refreshObjectAnims() { }
 	#end
 }

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

@@ -34,25 +34,13 @@ class BillboardObject extends h3d.scene.Object {
 
 @:allow(hrt.prefab.fx.Billboard.BillboardInstance)
 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
-	override function getHideProps():HideProps {
+	override function getHideProps():hide.prefab.HideProps {
 		return {
 			icon: "cog",
 			name: "Billboard"
@@ -60,5 +48,5 @@ class Billboard extends Object3D {
 	}
 	#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.Curve;
 import hrt.prefab.fx.BaseFX.ShaderAnimation;
+import hrt.prefab.fx.Value;
+import hrt.prefab.fx.Evaluator;
+
+import hide.prefab.HideProps;
+
 using Lambda;
 
 enum SimulationSpace {
@@ -412,6 +417,7 @@ class ParticleInstance {
 	}
 }
 
+@:access(hrt.prefab.Prefab)
 @:allow(hrt.prefab.fx.ParticleInstance)
 @:allow(hrt.prefab.fx.Emitter)
 class EmitterObject extends h3d.scene.Object {
@@ -509,7 +515,6 @@ class EmitterObject extends h3d.scene.Object {
 
 	var random: hxd.Rand;
 	var randomSeed = 0;
-	var context : hrt.prefab.Context;
 	var emitCount = 0;
 	var emitTarget = 0.0;
 	var curTime = 0.0;
@@ -531,15 +536,11 @@ class EmitterObject extends h3d.scene.Object {
 		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 )
-			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) {
@@ -557,11 +558,15 @@ class EmitterObject extends h3d.scene.Object {
 			if(baseEmitMat.isIdentityEpsilon(0.01))
 				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 ) {
-				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 ) {
 						break;
 					}
@@ -571,12 +576,9 @@ class EmitterObject extends h3d.scene.Object {
 			if (mesh != null) {
 				meshPrimitive = Std.downcast(mesh.primitive, h3d.prim.MeshPrimitive);
 				meshMaterial = mesh.material;
-				mesh.remove();
 			}
 
-			template.shared.contexts.remove(particleTemplate);
-			template.local3d.remove();
-			template.local3d = null;
+			empty3d.remove();
 		}
 
 		if (meshPrimitive == null ) {
@@ -594,30 +596,27 @@ class EmitterObject extends h3d.scene.Object {
 			batch.name = "emitter";
 			batch.calcBounds = false;
 
-			var batchContext = context.clone(null);
-			batchContext.local3d = batch;
 			// Setup mats.
 			// 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) {
 
 				// Remove materials that are not directly parented to this emitter
 				var p = mat.parent;
-				while (p != null && Std.downcast(p, Emitter) == null) {
+				while (p != null && Std.downcast(p, Emitter) == null)
 					p = p.parent;
-				}
 
+				// TODO(ces) : Attach materials directly to the batch
 				if (this.emitterPrefab == p) {
 					if(mat.enabled) {
-						var ctx = mat.makeInstance(batchContext);
-						ctx.local3d = null;
+						@:privateAccess mat.makeInstance();
 					}
 				}
 			}
 
 			// Setup shaders
 			shaderAnims = [];
-			var shaders = emitterPrefab.getAll(hrt.prefab.Shader);
+			var shaders = emitterPrefab.findAll(hrt.prefab.Shader);
 			for( shader in shaders ) {
 				// Remove shaders that are not directly parented to this emitter
 				var p = shader.parent;
@@ -626,13 +625,15 @@ class EmitterObject extends h3d.scene.Object {
 				}
 				if (this.emitterPrefab == p) {
 					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
@@ -662,6 +663,7 @@ class EmitterObject extends h3d.scene.Object {
 		randomValues = [for(i in 0...(maxCount * randSlots)) 0];
 		evaluator = new Evaluator(randomValues, randSlots);
 		reset();
+
 	}
 
 	override function onRemove() {
@@ -792,7 +794,6 @@ class EmitterObject extends h3d.scene.Object {
 		return idx;
 	}
 
-	var tmpCtx : hrt.prefab.Context;
 	static var tmpQuat = new h3d.Quat();
 	static var tmpEmitterQuat = new h3d.Quat();
 	static var tmpOffset = new h3d.Vector();
@@ -815,13 +816,8 @@ class EmitterObject extends h3d.scene.Object {
 			var scene = relativeScenePosition ? getScene() : 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;
 			}
 
@@ -940,11 +936,11 @@ class EmitterObject extends h3d.scene.Object {
 			}
 		}
 
-		context.local3d = this;
 		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) { }
 
 	// No-alloc version of h3d.Matrix.getEulerAngles()
@@ -1217,14 +1213,10 @@ class EmitterObject extends h3d.scene.Object {
 					i = disposeInstance(i);
 					// SUB EMITTER
 					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();
 							emitter.setPosition(pos.x, pos.y, pos.z);
 							emitter.isSubEmitter = true;
@@ -1341,8 +1333,8 @@ class EmitterObject extends h3d.scene.Object {
 
 class Emitter extends Object3D {
 
-	public function new(?parent) {
-		super(parent);
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		props = { };
 		for(param in emitterParams) {
 			if(param.def != null)
@@ -1430,8 +1422,8 @@ class Emitter extends Object3D {
 	};
 
 	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) {
 			var f : Dynamic = Reflect.field(props, param.name);
 			if(f != null && haxe.Json.stringify(f) != haxe.Json.stringify(param.def)) {
@@ -1441,13 +1433,13 @@ class Emitter extends Object3D {
 						val = Type.enumConstructor(val);
 					default:
 				}
-				Reflect.setField(obj.props, param.name, val);
+				Reflect.setField(data.props, param.name, val);
 			}
 			else {
-				Reflect.deleteField(obj.props, param.name);
+				Reflect.deleteField(data.props, param.name);
 			}
 		}
-		return obj;
+		return data;
 	}
 
 	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) {
 		return name + "_rand";
 	}
@@ -1509,9 +1508,9 @@ class Emitter extends Object3D {
 			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 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
-		var scene = ctx.local3d.getScene();
+		var scene = local3d.getScene();
 		if(scene != null)
 			emitterObj.startTime = @:privateAccess scene.renderer.ctx.time;
 		#end
@@ -1736,22 +1735,15 @@ class Emitter extends Object3D {
 		#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
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		function refresh() {
@@ -1862,7 +1854,7 @@ class Emitter extends Object3D {
 
 			for( gn in groupNames ) {
 				var params = params.filter( p -> p.groupName == (gn == "Emitter" ? null : gn) );
-				var group = new Element('<div class="group" name="$gn"></div>');
+				var group = new hide.Element('<div class="group" name="$gn"></div>');
 				group.append(hide.comp.PropsEditor.makePropsList(params));
 				ctx.properties.add(group, this.props, onChange);
 			}
@@ -1881,12 +1873,12 @@ class Emitter extends Object3D {
 
 			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) {
-					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) {
 						ctx.properties.undo.change(Field(this.props, pname, Reflect.field(this.props, pname)), function() {
@@ -1918,15 +1910,15 @@ class Emitter extends Object3D {
 						});
 					}
 					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) {
 							addUndo(p.name);
 							resetParam(p);
 							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) {
 						case PVec(n): [for(i in 0...n) 0.0];
 						case PFloat(_): 0.0;
@@ -1957,7 +1949,7 @@ class Emitter extends Object3D {
 						});
 					}
 					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) {
 							addUndo(randProp(p.name));
 							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)
 			return false;
 		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 {
-		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
 
-	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 {
 	#if editor
 	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
 	var time(default, set) : Float;
 	var hidden : Bool;
@@ -24,16 +23,15 @@ class Event extends hrt.prefab.Prefab implements IEvent {
 	public var lock: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) {
 		return time = v;
 	}
 
-	public function prepare(ctx: Context) : EventInstance {
+	public function prepare() : EventInstance {
 		return {
 			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 {
 			label: name,
 			length: 1.0,
@@ -84,5 +82,5 @@ class Event extends hrt.prefab.Prefab implements IEvent {
 
 	#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;
 	}
 
-	function init(ctx: Context, def: FX, ?root: PrefabElement) {
+	function init(def: FX, ?root: PrefabElement) {
 		if(root == null)
 			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;
-		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));
 	}
@@ -270,11 +270,11 @@ class FXAnimation extends h3d.scene.Object {
 		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 ret = null;
 		for(evt in childEvents) {
-			var eventObj = evt.prepare(ctx);
+			var eventObj = evt.prepare();
 			if(eventObj == null) continue;
 			if(ret == null) ret = [];
 			ret.push(eventObj);
@@ -282,12 +282,12 @@ class FXAnimation extends h3d.scene.Object {
 		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) {
 			// Don't extract animations for children of Emitters
 			for(c in elt.children) {
-				initObjAnimations(ctx, c);
+				initObjAnimations(c);
 			}
 		}
 
@@ -295,11 +295,6 @@ class FXAnimation extends h3d.scene.Object {
 		if(obj3d == null)
 			return;
 
-		// TODO: Support references?
-		var objCtx = ctx.shared.contexts.get(elt);
-		if(objCtx == null || objCtx.local3d == null)
-			return;
-
 		var anyFound = false;
 
 		function makeVal(name, def) : Value {
@@ -340,19 +335,21 @@ class FXAnimation extends h3d.scene.Object {
 		}
 
 		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) );
 		}
-		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) );
 		}
-		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));
 		}
 
 		var anim : ObjectAnimation = {
 			elt: obj3d,
-			obj: objCtx.local3d,
+			obj: local3d,
 			events: null,
 			position: makeVector("position", 0.0),
 			scale: makeVector("scale", 1.0, true),
@@ -362,7 +359,7 @@ class FXAnimation extends h3d.scene.Object {
 			additionalProperies: ap,
 		};
 
-		anim.events = initEvents(elt, objCtx);
+		anim.events = initEvents(elt);
 		if(anim.events != null)
 			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;
 		var em = Std.downcast(elt, hrt.prefab.fx.Emitter);
 		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 = [];
-				var emobj : hrt.prefab.fx.Emitter.EmitterObject = cast emCtx.local3d;
+				var emobj : hrt.prefab.fx.Emitter.EmitterObject = cast local3d;
 				emobj.setRandSeed(randSeed);
 				emitters.push(emobj);
 			}
 		}
 		else {
 			for(c in elt.children) {
-				initEmitters(ctx, c);
+				initEmitters(c);
 			}
 		}
 	}
 
-	function initConstraints( ctx : Context, elt : PrefabElement ){
+	function initConstraints(elt : PrefabElement ){
 		if(!elt.enabled) return;
 		var co = Std.downcast(elt, hrt.prefab.l3d.Constraint);
 		if(co != null) {
@@ -400,7 +397,7 @@ class FXAnimation extends h3d.scene.Object {
 		}
 		else
 			for(c in elt.children)
-				initConstraints(ctx, c);
+				initConstraints(c);
 	}
 
 	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;
 		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.cullingRadius = cullingRadius;
 		fxanim.blendFactor = blendFactor;
@@ -465,8 +473,7 @@ class FX extends BaseFX {
 			p = p.parent;
 		}
 
-		ctx.local3d = fxanim;
-		var fromRef = ctx.shared.parent != null;
+		var fromRef = shared.parentPrefab != null;
 		#if editor
 		// only play if we are as a reference
 		if( fromRef ) fxanim.playSpeed = 1.0;
@@ -474,21 +481,18 @@ class FX extends BaseFX {
 		fxanim.playSpeed = 1.0;
 		#end
 
-		var useFXRoot = #if editor fromRef #else true #end;
-		var root = getFXRoot(ctx, this);
-		if(useFXRoot && root != null){
-			root.make(ctx);
-		}
-		else
-			super.make(ctx);
-		fxanim.init(ctx, this, root);
+		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.cullingRadius = cullingRadius;
 		fxanim.blendFactor = blendFactor;
@@ -507,13 +511,13 @@ class FX extends BaseFX {
 
 	#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.initObjAnimations(ctx, this);
+		fxanim.initObjAnimations(this);
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 			<div class="group" name="FX Scene">
 				<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};
 	}
 	#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);
 	}
 
-	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")
-			events = initEvents(def.children[0], ctx);
+			events = initEvents(def.children[0]);
 		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);
 		if(em != null)  {
-			for(emCtx in ctx.shared.getContexts(elt)) {
-				if(emCtx.local2d == null) continue;
+			if(em.local2d == null) return;
 				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);
 			}
-		}
 		else {
 			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 ret = null;
 		for(evt in childEvents) {
-			var eventObj = evt.prepare(ctx);
+			var eventObj = evt.prepare();
 			if(eventObj == null) continue;
 			if(ret == null) ret = [];
 			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 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) {
-			getObjAnimations(ctx, c, anims);
+			getObjAnimations(c, anims);
 		}
 
 		var obj2d = elt.to(hrt.prefab.Object2D);
@@ -183,10 +185,6 @@ class FX2D extends BaseFX {
 			return;
 
 		// TODO: Support references?
-		var objCtx = ctx.shared.contexts.get(elt);
-		if(objCtx == null || objCtx.local2d == null)
-			return;
-
 		var anyFound = false;
 
 		function makeVal(name, def) : Value {
@@ -220,7 +218,7 @@ class FX2D extends BaseFX {
 
 		var anim : ObjectAnimation = {
 			elt2d: obj2d,
-			obj2d: objCtx.local2d,
+			obj2d: local2d,
 			events: null,
 			position: makeVector("position", 0.0),
 			scale: makeVector("scale", 1.0, true),
@@ -229,8 +227,8 @@ class FX2D extends BaseFX {
 			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(anim.events == null) anim.events = [];
 			anim.events.push(eventObj);
@@ -244,41 +242,49 @@ class FX2D extends BaseFX {
 			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
-		super.make(ctx);
+		return super.__makeInternal(sh);
 		#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
-			super.make(ctx);
+			return super.__makeInternal(sh);
 		#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.loop = loop;
 	}
@@ -290,13 +296,13 @@ class FX2D extends BaseFX {
 	}
 
 	#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 = [];
-		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('
 			<div class="group" name="FX2D Scene">
 				<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};
 	}
 	#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 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;
 		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
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return {
 			icon : "cog",
 			name : "LookAt"
 		};
 	}
 
-	override function edit(ctx:EditContext) {
+	override function edit(ctx:hide.prefab.EditContext) {
 		super.edit(ctx);
 		var group = new hide.Element('
 		<div class="group" name="LookAt">
@@ -133,7 +124,9 @@ class LookAt extends Object3D {
 			{ 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 opt = new hide.Element("<option>").attr("value", "camera").html("Camera");
@@ -148,5 +141,5 @@ class LookAt extends Object3D {
 	}
 	#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 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) {
 		#if editor
 		if(instance != null)
@@ -50,7 +46,7 @@ class SubFX extends Reference implements hrt.prefab.fx.Event.IEvent{
 
 	#if editor
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var props = ctx.properties.add(new hide.Element('
 			<div class="group" name="Event">
 				<dl>
@@ -66,8 +62,8 @@ class SubFX extends Reference implements hrt.prefab.fx.Event.IEvent{
 
 	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 {
 			label: ref != null ? new haxe.io.Path(source).file : "null",
 			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 {
 			icon : "play-circle", name : "SubFX"
 		};
 	}
 	#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;
 }
 
+@:access(hrt.prefab.Prefab)
 class SwarmObject extends h3d.scene.Object {
 	public var prefab : Swarm = null;
 	public var elements: Array<SwarmElement> = [];
@@ -41,7 +42,6 @@ class SwarmObject extends h3d.scene.Object {
 	public var targetAngle: Float = 0.0;
 
 	public var batch : h3d.scene.MeshBatch = null;
-	public var context : Context = null;
 
 	public var swarmElementTemplate: Object3D = null;
 
@@ -82,11 +82,14 @@ class SwarmObject extends h3d.scene.Object {
 			// if(baseEmitMat.isIdentityEpsilon(0.01))
 			// 	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 ) {
-				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 ) {
 						break;
 					}
@@ -99,9 +102,7 @@ class SwarmObject extends h3d.scene.Object {
 				mesh.remove();
 			}
 
-			template.shared.contexts.remove(swarmElementTemplate);
-			template.local3d.remove();
-			template.local3d = null;
+			empty3d.remove();
 		}
 
 		if (meshPrimitive == null) {
@@ -121,11 +122,9 @@ class SwarmObject extends h3d.scene.Object {
 			batch.name = "emitter";
 			batch.calcBounds = true;
 
-			var batchContext = context.clone(null);
-			batchContext.local3d = batch;
 			// Setup mats.
 			// 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) {
 
 				// 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(mat.enabled) {
-						var ctx = mat.makeInstance(batchContext);
-						ctx.local3d = null;
+						@:privateAccess mat.makeInstance();
 					}
 				}
 			}
 
 			// Setup shaders
 			shaderAnims = [];
-			var shaders = prefab.getAll(hrt.prefab.Shader);
+			var shaders = prefab.findAll(hrt.prefab.Shader);
 			for( shader in shaders ) {
 				// Remove shaders that are not directly parented to this Swarm
 				var p = shader.parent;
@@ -153,12 +151,11 @@ class SwarmObject extends h3d.scene.Object {
 				}
 				if (this.prefab == p) {
 					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 )
-			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();
@@ -480,24 +473,16 @@ class Swarm extends Object3D {
 	@:s public var debugTargets : Bool = false;
 
 	// 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(
 			c -> c.enabled &&
@@ -511,11 +496,11 @@ class Swarm extends Object3D {
 	}
 
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "random", name : "Swarm" };
 	}
 
-	override public function edit(ctx:EditContext) {
+	override public function edit(ctx:hide.prefab.EditContext) {
 		super.edit(ctx);
 		var props = ctx.properties.add(new hide.Element('
 		<div class="group" name="Swarm Entities">
@@ -572,5 +557,5 @@ class Swarm extends Object3D {
 	}
 	#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;
 
-	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 (tex != null) {
 				tex = null;
 			}
 			if (src != null) {
-				tex = ctx.loadTexture(src);
+				tex = shared.loadTexture(src);
 				var t = h2d.Tile.fromTexture(tex);
 				var tiles = [];
 				var nbFrameRow = Std.int(t.width / widthFrame);
@@ -46,17 +46,13 @@ class Anim2D extends Object2D {
 		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
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		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" };
 	}
 
 	#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;
 
-	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;
 
 		if (propName == null || propName == "src" || propName == "forcePivotCenter") {
@@ -46,19 +46,14 @@ class Atlas extends Object2D {
 		#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
 
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
+	override function makeInteractive():h2d.Interactive {
 		if(local2d == null)
 			return null;
 		var h2dAnim = cast(local2d, h2d.Anim);
@@ -71,7 +66,7 @@ class Atlas extends Object2D {
 		return int;
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		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;
 		tfile.onChange = function() {
 			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>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" };
 	}
 
 	#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;
 
-	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;
 		if (propName == null || propName == "src") {
 			if (tex != null) {
 				tex = null;
 			}
 			if (src != null) {
-				tex = ctx.loadTexture(src);
+				tex = shared.loadTexture(src);
 				bmp.tile = h2d.Tile.fromTexture(this.tex);
 			} else {
 				bmp.tile = h2d.Tile.fromColor(0xFF00FF,32,32,0.5);
@@ -41,14 +41,10 @@ class Bitmap extends Object2D {
 		#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;
-		ctx.local2d = bmp;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return bmp;
 	}
 
 	static public function getCenterRatio(dx : Float, dy : Float) {
@@ -57,8 +53,7 @@ class Bitmap extends Object2D {
 
 	#if editor
 
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
+	override function makeInteractive():h2d.Interactive {
 		if(local2d == null)
 			return null;
 		var bmp = cast(local2d, h2d.Bitmap);
@@ -70,7 +65,7 @@ class Bitmap extends Object2D {
 		return int;
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		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" };
 	}
 
 	#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 bitmap : h2d.Bitmap;
+
 	public function makeFilter() {
 		var f = new h2d.filter.Blur(radius, gain, quality);
 		f.linear = linear;
@@ -32,38 +34,35 @@ class Blur extends Prefab {
 		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;
 		if( image != null )
-			t = h2d.Tile.fromTexture(ctx.loadTexture(image));
+			t = h2d.Tile.fromTexture(shared.loadTexture(image));
 		else {
 			t = h2d.Tile.fromTexture(h3d.mat.Texture.genChecker(16));
 			t.setSize(256, 256);
 		}
 		t.dx = -t.iwidth>>1;
 		t.dy = -t.iheight>>1;
-		bmp.tile = t;
-		bmp.filter = makeFilter();
-		bmp.smooth = true;
-		bmp.tileWrap = image == null;
-		bmp.setScale(zoom);
+		bitmap.tile = t;
+		bitmap.filter = makeFilter();
+		bitmap.smooth = true;
+		bitmap.tileWrap = image == null;
+		bitmap.setScale(zoom);
 	}
 
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { name : "Blur", icon : "bullseye" };
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		var e : hide.Element = null;
 		function sync( bmp : h2d.Bitmap ) {
 			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>
 			</dl>
 		'),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
 
-	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 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 ) {
 			flow.minHeight = flow.maxHeight = height;
 		} else {
@@ -51,7 +47,7 @@ class Flow extends Object2D {
 
 	#if editor
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
@@ -79,19 +75,19 @@ class Flow extends Object2D {
 		leftAlign.on("click", function(e) {
 			hAlign = 0;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "hAlign");
+			updateInstance("hAlign");
 		});
 		middleAlign.on("click", function(e) {
 			hAlign = 1;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "hAlign");
+			updateInstance("hAlign");
 		});
 		rightAlign.on("click", function(e) {
 			hAlign = 2;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "hAlign");
+			updateInstance("hAlign");
 		});
-		
+
 		new hide.Element('<dt>Vertical Align</dt>').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);
@@ -113,17 +109,17 @@ class Flow extends Object2D {
 		topAlign.on("click", function(e) {
 			vAlign = 0;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "vAlign");
+			updateInstance("vAlign");
 		});
 		middleAlign.on("click", function(e) {
 			vAlign = 1;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "vAlign");
+			updateInstance("vAlign");
 		});
 		rightAlign.on("click", function(e) {
 			vAlign = 2;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "vAlign");
+			updateInstance("vAlign");
 		});
 		updateDisabled();
 
@@ -135,11 +131,11 @@ class Flow extends Object2D {
 		});
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Flow" };
 	}
 	#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;
 }
 
-class NoiseGenerator extends Prefab {
+class NoiseGenerator extends Object2D {
 
 	@:s public var seed : Int;
 
@@ -37,8 +37,8 @@ class NoiseGenerator extends Prefab {
 
 	var tex : h3d.mat.Texture;
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		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);
 	}
 
-	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);
-		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.visible = false;
 		bmp.x = -size >> 1;
 		bmp.y = -size >> 1;
-		ctx.local2d = bmp;
-		ctx.cleanup = function() tex.dispose();
-		return ctx;
+		local2d = bmp;
+	}
+
+	function destroy() {
+		tex.dispose();
 	}
 
 	#if editor
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		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('
 			<dl>
 				<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>
 			</dl>
 		'),this,function(pname)  {
-			var bmp = cast(ctx.getContext(this).local2d, h2d.Bitmap);
+			var bmp = cast(local2d, h2d.Bitmap);
 			var tex = bmp.tile.getTexture();
 			if( tex.width != size ) {
 				tex.resize(size, size);
@@ -195,14 +196,15 @@ class NoiseGenerator extends Prefab {
 			updateTexture(tex);
 			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(_) {
-			ctx.ide.chooseFileSave("noise.png", function(f) {
+			ide.chooseFileSave("noise.png", function(f) {
 				try {
-					var data = cast(ctx.getContext(this).local2d, h2d.Bitmap).tile.getTexture().capturePixels().toPNG();
-					sys.io.File.saveBytes(ctx.ide.getPath(f), data);
+					var data = cast(local2d, h2d.Bitmap).tile.getTexture().capturePixels().toPNG();
+					sys.io.File.saveBytes(ide.getPath(f), data);
 				} catch( e : Dynamic ) {
-					ctx.ide.error(e);
+					ide.error(e);
 				}
 			});
 		});
@@ -212,7 +214,7 @@ class NoiseGenerator extends Prefab {
 
 	#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 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.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);
 		particle2d.addGroup(group);
@@ -162,8 +159,7 @@ class Particle2D extends Object2D {
 			paramsParticleGroup = group.save();
 		group.rebuildOnChange = false;
 
-		updateInstance(ctx);
-		return ctx;
+		return particle2d;
 	}
 
 	#if editor
@@ -176,8 +172,7 @@ class Particle2D extends Object2D {
 		{ 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)
 			return null;
 		var particles2d = cast(local2d, h2d.Particles);
@@ -188,16 +183,14 @@ class Particle2D extends Object2D {
 		return int;
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		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];
-			ctx.properties.add(new Element('
+			ctx.properties.add(new hide.Element('
 			<div class="content">
 				<div class="group" name="Emit">
 					<dt>Is burst emit</dt><dd><input type="checkbox" field="isBurstEmit"/></dd>
@@ -218,14 +211,13 @@ class Particle2D extends Object2D {
 				ctx.onChange(this, pname);
 			});
 		}
-	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Particle2D" };
 	}
 
 	#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;
 	}
 
-	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.textColor = color;
 		h2dText.maxWidth = maxWidth > 0 ? maxWidth : null;
@@ -107,15 +107,11 @@ class Text extends Object2D {
 		#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.smooth = true;
-		ctx.local2d = h2dText;
-		ctx.local2d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return h2dText;
 	}
 
 	public dynamic function loadFont() : h2d.Font {
@@ -137,8 +133,7 @@ class Text extends Object2D {
 
 	#if editor
 
-	override function makeInteractive(ctx:Context):h2d.Interactive {
-		var local2d = ctx.local2d;
+	override function makeInteractive():h2d.Interactive {
 		if(local2d == null)
 			return null;
 		var text = cast(local2d, h2d.Text);
@@ -149,7 +144,7 @@ class Text extends Object2D {
 		return int;
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		var parameters = new hide.Element('<div class="group" name="Parameters"></div>');
@@ -177,17 +172,17 @@ class Text extends Object2D {
 		leftAlign.on("click", function(e) {
 			align = 0;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		middleAlign.on("click", function(e) {
 			align = 1;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		rightAlign.on("click", function(e) {
 			align = 2;
 			updateDisabled();
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		updateDisabled();
 
@@ -199,7 +194,7 @@ class Text extends Object2D {
 		if (this.pathFont != null && this.pathFont.length > 0) tfile.path = this.pathFont;
 		tfile.onChange = function() {
 			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);
@@ -246,12 +241,12 @@ class Text extends Object2D {
 		});
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Text" };
 	}
 
 	#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;
 
+// NOTE(ces) : Not Tested
+
 class AnimSpeedControl extends hrt.prefab.Prefab {
 
 	@: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
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return {
 			name : "AnimSpeedCtrl",
 			icon : "cog",
 			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>
 		</dl>'), this, function(p) {
 			ctx.onChange(this, p);
@@ -32,6 +34,6 @@ class AnimSpeedControl extends hrt.prefab.Prefab {
 	}
 	#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 {
 
 
-	public function setColor(ctx: Context, color: Int) {
+	public function setColor(color: Int) {
 		#if editor
-		if(ctx.local3d == null)
+		if(local3d == null)
 			return;
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
+		var mesh = Std.downcast(local3d, h3d.scene.Mesh);
 		if(mesh != null) {
 			setDebugColor(color, mesh.material);
 		}
 		#end
 	}
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-
-		var mesh = new h3d.scene.Mesh(h3d.prim.Cube.defaultUnitCube(), ctx.local3d);
+	override function makeObject(parent3d: h3d.scene.Object) : h3d.scene.Object {
+		var mesh = new h3d.scene.Mesh(h3d.prim.Cube.defaultUnitCube(), parent3d);
 
 		#if editor
 		setDebugColor(0x60ffffff, mesh.material);
@@ -28,10 +26,7 @@ class Box extends Object3D {
 		wire.material.shadows = false;
 		#end
 
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return mesh;
 	}
 
 	#if editor
@@ -45,8 +40,8 @@ class Box extends Object3D {
 			if(alpha != null)
 				mat.removePass(alpha);
 			mat.mainPass.setPassName("default");
-		 	mat.mainPass.setBlendMode(None);
-		 	mat.mainPass.depthWrite = true;
+			 mat.mainPass.setBlendMode(None);
+			 mat.mainPass.depthWrite = true;
 			mat.mainPass.culling = None;
 		}
 		else {
@@ -61,10 +56,10 @@ class Box extends Object3D {
 		}
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Box" };
 	}
 	#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;
 import hrt.prefab.rfx.RendererFX;
 import h3d.scene.Object;
-import hrt.prefab.Context;
-import hrt.prefab.Library;
+
+// NOTE(ces) : Not Tested
 
 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
 	#end
 
-	public function new(?parent) {
-		super(parent);
-		type = "camera";
+	public function new(parent, shared: ContextShared) {
+		super(parent, shared);
 	}
 
 	var g : h3d.scene.Graphics;
-	function drawFrustum( ctx : Context ) {
+	function drawFrustum() {
 
 		if( !showFrustum ) {
 			if( g != null ) {
@@ -53,7 +52,7 @@ class Camera extends Object3D {
 		}
 
 		if( g == null ) {
-			g = new h3d.scene.Graphics(ctx.local3d);
+			g = new h3d.scene.Graphics(local3d);
 			g.name = "frustumDebug";
 			g.material.mainPass.setPassName("overlay");
 			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
-		drawFrustum(ctx);
+		drawFrustum();
 		#end
-		var cso = Std.downcast(ctx.local3d, CameraSyncObject);
+		var cso = Std.downcast(local3d, CameraSyncObject);
 		if( cso != null ) {
 			cso.fovY = fovY;
 			cso.zFar = zFar;
@@ -172,13 +168,13 @@ class Camera extends Object3D {
 		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 (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);
 				if ( prevEffect != null )
 					renderer.effects.remove(prevEffect);
@@ -186,7 +182,7 @@ class Camera extends Object3D {
 			}
 		}
 		else {
-			for ( effect in getAll(hrt.prefab.rfx.RendererFX) )
+			for ( effect in findAll(hrt.prefab.rfx.RendererFX) )
 				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();
 		return false;
 	}
@@ -253,16 +249,17 @@ class Camera extends Object3D {
 			editModeButton.val(preview ? "Preview Mode : Enabled" : "Preview Mode : Disabled");
 			editModeButton.toggleClass("editModeEnabled", preview);
 		};
-		editModeButton.click(function(_) {
+
+		function onclick(e: js.jquery.Event) : Void {
 			preview = !preview;
 			setEditModeButton();
 			var cam = ctx.scene.s3d.camera;
 			var renderer = @:privateAccess ctx.scene.s3d.renderer;
 			if (preview) {
 				beforePreviewCam = ctx.scene.s3d.camera.clone();
-				updateInstance(ctx.getContext(this));
+				updateInstance();
 				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);
 					if ( prevEffect != null )
 						renderer.effects.remove(prevEffect);
@@ -270,10 +267,12 @@ class Camera extends Object3D {
 				}
 				ctx.scene.editor.cameraController.lockZPlanes = true;
 				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 {
-				for ( effect in getAll(hrt.prefab.rfx.RendererFX) )
+				for ( effect in findAll(hrt.prefab.rfx.RendererFX) )
 					renderer.effects.remove( effect );
 				for ( effect in renderer.effects ) {
 					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.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 ) {
 						var invPos = new h3d.Matrix();
 						invPos._44 = 0;
@@ -323,7 +322,8 @@ class Camera extends Object3D {
 					this.rotationZ = floatToStringPrecision(floatToStringPrecision(this.rotationZ));
 				});
 			}
-		});
+		};
+		editModeButton.click(onclick);
 
 		var deprecationButton = props.find(".upgrade");
 		deprecationButton.click(function(_) {
@@ -343,7 +343,7 @@ class Camera extends Object3D {
 				transform.rotate(angles.x, angles.y, angles.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 ) {
 					var invPos = new h3d.Matrix();
 					invPos._44 = 0;
@@ -375,6 +375,6 @@ class Camera extends Object3D {
 	}
 	#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;
 	}
 
-	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 ){
 			srcObj.follow = targetObj;
 			srcObj.followPositionOnly = positionOnly;
 		}
-		return ctx;
 	}
 
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		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('
 			<dl>
 				<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>
 		'),this, function(_) {
 			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( path in ctx.getNamedObjects() ) {
+			for( path in ctx.getNamedObjects(Object3D.getLocal3d(getRoot())) ) {
 				var parts = path.split(".");
 				var opt = new hide.Element("<option>").attr("value", path).html([for( p in 1...parts.length ) "&nbsp; "].join("") + parts.pop());
 				select.append(opt);
@@ -57,6 +55,6 @@ class Constraint extends Prefab {
 	}
 	#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;
 
+// NOTE(ces) : Not Tested
+
 enum abstract DecalMode(String) {
 	var Default;
 	var BeforeTonemapping;
@@ -29,20 +31,25 @@ class Decal extends Object3D {
 	@:s var normalFadeEnd : Float = 1;
 	@:s var refMatLib : String;
 
-	override function save() {
+	override function save() : Dynamic {
 		var obj : Dynamic = super.save();
 		if(blendMode != Alpha) obj.blendMode = blendMode.getIndex();
 		return obj;
 	}
 
+	override function copy( obj : Dynamic ) {
+		super.copy(obj);
+		blendMode = obj.blendMode;
+	}
+
 	override function load( obj : Dynamic ) {
 		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) {
 			case Default, Terrain:
@@ -71,14 +78,11 @@ class Decal extends Object3D {
 		mesh.material.mainPass.depthTest = GreaterEqual;
 		mesh.material.mainPass.culling = Front;
 		mesh.material.shadows = false;
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		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 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 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;
 			for(c in prefabLib.children) {
 				if (c.name != refMatName)
@@ -129,8 +133,8 @@ class Decal extends Object3D {
 			case Default, Terrain:
 				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalPBR);
 				if( shader != null ){
-					shader.albedoTexture = albedoMap != null ? ctx.loadTexture(albedoMap) : null;
-					shader.normalTexture = normalMap != null ? ctx.loadTexture(normalMap) : null;
+					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.normalTexture != null) shader.normalTexture.wrap = Repeat;
 					shader.albedoStrength = albedoStrength;
@@ -142,7 +146,7 @@ class Decal extends Object3D {
 					shader.CENTERED = centered;
 					commonSetup(shader);
 				}
-				var pbrTexture = pbrMap != null ? ctx.loadTexture(pbrMap) : null;
+				var pbrTexture = pbrMap != null ? shared.loadTexture(pbrMap) : null;
 				if( pbrTexture != null ) {
 					var propsTexture = mesh.material.mainPass.getShader(h3d.shader.pbr.PropsTexture);
 					if( propsTexture == null )
@@ -167,7 +171,7 @@ class Decal extends Object3D {
 			case BeforeTonemapping, AfterTonemapping:
 				var shader = mesh.material.mainPass.getShader(h3d.shader.pbr.VolumeDecal.DecalOverlay);
 				if( shader != null ){
-					shader.colorTexture = albedoMap != null ? ctx.loadTexture(albedoMap) : null;
+					shader.colorTexture = albedoMap != null ? shared.loadTexture(albedoMap) : null;
 					if(shader.colorTexture != null) shader.colorTexture.wrap = Repeat;
 					shader.CENTERED = centered;
 					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
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "paint-brush", name : "Decal" };
 	}
 
-	override function setSelected( ctx : Context, b : Bool ) {
+	override function setSelected(b : Bool ) {
 		if( b ) {
-			var obj = ctx.shared.getSelfObject(this);
+			var obj = local3d;
 			if(obj != null) {
 				var wire = new h3d.scene.Box(0xFFFFFFFF,obj);
 				wire.name = "_highlight";
@@ -206,20 +210,20 @@ class Decal extends Object3D {
 				wireCenter.material.mainPass.depthTest = Always;
 			}
 		} else {
-			clearSelection( ctx );
+			clearSelection();
 		}
 		return true;
 	}
 
-	function clearSelection( ctx : Context ) {
-		var obj = ctx.shared.getSelfObject(this);
+	function clearSelection() {
+		var obj = local3d;
 		if(obj == null) return;
 		var objs = obj.findAll( o -> if(o.name == "_highlight") o else null );
 		for( o in objs )
 			o.remove();
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		var pbrParams = '<dt>Albedo</dt><dd><input type="texturepath" field="albedoMap"/>
@@ -281,49 +285,49 @@ class Decal extends Object3D {
 
 			function updateMatSelect() {
 				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());
 
 				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() {
 				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) {
-					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() {
-				var previousDecal = this.clone();
+				var previousData = this.serialize();
 				var mat = ctx.scene.findMat(materials, matSelect.val());
 				if ( mat != null ) {
 					this.refMatLib = mat.path + "/" + mat.mat.name;
-					updateInstance(ctx.scene.editor.getContext(this));
+					updateInstance();
 					ctx.rebuildProperties();
 				} else {
 					this.refMatLib = "";
 				}
 
-				var newDecal = this.clone();
+				var newDecal = this.serialize();
 
 				ctx.properties.undo.change(Custom(function(undo) {
 					if( undo ) {
-						this.load(previousDecal.saveData());
+						this.load(previousData);
 					}
 					else {
-						this.load(newDecal.saveData());
+						this.load(newDecal);
 					}
 
 					updateLibSelect();
 					updateMatSelect();
 					ctx.rebuildProperties();
-					updateInstance(ctx.scene.editor.getContext(this));
+					updateInstance();
 				}));
 			}
 
@@ -384,7 +388,7 @@ class Decal extends Object3D {
 			</div>
 			'),this, function(pname) {
 				if( pname == "renderMode" ) {
-					clearSelection( ctx.rootContext );
+					clearSelection();
 					ctx.rebuildPrefab(this);
 					ctx.rebuildProperties();
 				}
@@ -397,6 +401,6 @@ class Decal extends Object3D {
 	}
 	#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;
 	var env : h3d.scene.pbr.Environment;
 
-	public function new( ?parent ) {
-		super(parent);
-		type = "environment";
-	}
-
 	function loadFromBinary() {
 		try {
 			env.dispose();
@@ -53,27 +48,25 @@ class Environment extends Object3D {
 		#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 )
 			return;
 
 		#if editor
-		var sourceMap = ctx.loadTexture(sourceMapPath);
+		var sourceMap = shared.loadTexture(sourceMapPath);
 		if( sourceMap == null )
 			return;
 		if( sourceMap.flags.has(Loading) ) {
 			haxe.Timer.delay(function() {
-				ctx.setCurrent();
+				shared.scene.setCurrent();
 				if( h3d.Engine.getCurrent().driver == null ) return; // was disposed
-				updateInstance(ctx,propName);
+				updateInstance(propName);
 			},100);
 			return;
 		}
@@ -106,12 +99,12 @@ class Environment extends Object3D {
 			env.dispose();
 			env.specular = null;
 			env.diffuse = null;
-			env.source = ctx.loadTexture(sourceMapPath);
+			env.source = shared.loadTexture(sourceMapPath);
 			env.compute();
 			saveToBinary();
 		}
 
-		var scene = ctx.local3d.getScene();
+		var scene = local3d.getScene();
 		// Auto Apply on change
 		if( scene != null )
 			applyToRenderer(scene.renderer);
@@ -125,11 +118,11 @@ class Environment extends Object3D {
 
 	#if editor
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "sun-o", name : "Environment" };
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		// super.edit(ctx);
 
 		var props = new hide.Element('
@@ -162,7 +155,7 @@ class Environment extends Object3D {
 
 		var applyButton = props.find(".apply");
 		applyButton.click(function(_) {
-			applyToRenderer(ctx.rootContext.local3d.getScene().renderer);
+			applyToRenderer(findFirstLocal3d().getScene().renderer);
 		});
 
 		props.find(".compute").click(function(_) {
@@ -184,5 +177,5 @@ class Environment extends Object3D {
 
 	#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;
 
+// NOTE(ces) : Not Tested
+
 class GameController extends Object3D {
 
 	@:s public var moveSpeed : Float = 1.;
@@ -19,13 +21,14 @@ class GameController extends Object3D {
 
 	#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);
 
 		ctx.properties.add(new hide.Element('
@@ -58,18 +61,17 @@ class GameController extends Object3D {
 		'),this);
 
 		var active = false;
-		var lctx = ctx.getContext(this);
-		var obj = lctx.local3d;
+		var obj = local3d;
 		var camSave = null;
 		var dummy : h3d.scene.Object = null;
-		var cam = ctx.scene.s3d.camera;
+		var cam = local3d.getScene().camera;
 		var camRot : h3d.Vector4 = null;
 		var startCamRot : h3d.Vector4 = null;
 		var zSpeed = 0.;
 		var startJumpTime = 1e9;
 
 		function selectRec( p : Prefab, b : Bool ) {
-			if( !p.setSelected(ctx.getContext(p), b) )
+			if( !p.setSelected(b) )
 				return;
 			for( c in p.children )
 				selectRec(c, b);
@@ -94,21 +96,19 @@ class GameController extends Object3D {
 		var baseZ = obj.z;
 
 		function playAnim( anim : String ) {
-			for( o in getAll(Model,true) ) {
+			for( o in findAll(Model,true) ) {
 				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;
 
 				var animList = try ctx.scene.listAnims(o.source) catch(e: Dynamic) [];
 				for( a2 in animList ) {
 					if( ctx.scene.animationName(a2).toLowerCase() == anim.toLowerCase() ) {
-						octx.local3d.playAnimation(octx.loadAnimation(a2));
+						local3d.playAnimation(shared.loadAnimation(a2));
 						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;
 					}
 				}
@@ -229,6 +229,6 @@ class GameController extends Object3D {
 	}
 	#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;
 
+// NOTE(ces) : Not Tested
+
 enum abstract HeightMaPTexturePathKind(String) {
 	var Albedo = "albedo";
 	var Height = "height";
@@ -623,11 +625,10 @@ class HeightMap extends Object3D {
 	@:s var albedoRoughness : Float = 0.;
 
 	// todo : instead of storing the context, we should find a way to have a texture loader
-	var storedCtx : hrt.prefab.Context;
 	var albedoProps : Array<h3d.Vector4>;
 	var texArrayCache : Map<HeightMaPTexturePathKind, { texture : h3d.mat.TextureArray, indexes : Array<Int> }>;
 
-	override function save():{} {
+	override function save():Dynamic {
 		var o : Dynamic = super.save();
 		o.textures = [for( t in textures ) {
 			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 }];
 	}
 
+	override function copy(o:Prefab) {
+		super.copy(o);
+		var p : HeightMap = cast o;
+		this.textures = p.textures;
+	}
+
 	function getAlbedoProps() : Array<h3d.Vector4> {
 		if( albedoProps != null )
 			return albedoProps;
@@ -685,7 +692,7 @@ class HeightMap extends Object3D {
 		return h;
 	}
 
-	override function localRayIntersection(ctx:Context, ray:h3d.col.Ray):Float {
+	override function localRayIntersection(ray:h3d.col.Ray):Float {
 		if( ray.lz > 0 )
 			return -1; // only from top
 		if( ray.lx == 0 && ray.ly == 0 ) {
@@ -703,7 +710,7 @@ class HeightMap extends Object3D {
 		if( pt.z < minZ )
 			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 curX = -1, curY = -1, curMap = null, offX = 0., offY = 0., cw = 0., ch = 0.;
 		var prevH = pt.z;
@@ -794,7 +801,7 @@ class HeightMap extends Object3D {
 			#end
 			if( b ) {
 				var path = resolveTexturePath(t.path,tx,ty);
-				tl.push(loadTexture(path));
+				tl.push(shared.loadTexture(path));
 			}
 		}
 		return tl;
@@ -822,7 +829,7 @@ class HeightMap extends Object3D {
 					var path = new haxe.io.Path(t.path);
 					path.file = path.file.split("_Albedo").join("");
 					path.file += "_Normal";
-					tl.push(loadTexture(path.toString()));
+					tl.push(shared.loadTexture(path.toString()));
 				}
 			tl;
 		default: throw "assert";
@@ -901,21 +908,12 @@ class HeightMap extends Object3D {
 		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( (propName == "albedoTiling" || propName == "albedoColorGamma") && albedoProps != null ) {
@@ -923,20 +921,19 @@ class HeightMap extends Object3D {
 			return;
 		}
 		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
 
 		albedoProps = null;
 		cleanCache();
-		super.updateInstance(ctx, propName);
+		super.updateInstance(propName);
 
 		for( t in tilesCache )
 			t.remove();
 		tilesCache = new Map();
-		var mesh = cast(ctx.local3d,HeightMapMesh);
+		var mesh = cast(local3d,HeightMapMesh);
 		mesh.init();
 	}
 
@@ -946,11 +943,11 @@ class HeightMap extends Object3D {
 
 	#if editor
 
-	override function setSelected(ctx:Context, b:Bool):Bool {
+	override function setSelected(b:Bool):Bool {
 		return true;
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "industry", name : "HeightMap", isGround : true };
 	}
 
@@ -963,9 +960,8 @@ class HeightMap extends Object3D {
 		albedoProps = prev;
 	}
 
-	override function edit(ectx:EditContext) {
+	override function edit(ectx:hide.prefab.EditContext) {
 		super.edit(ectx);
-		var ctx = ectx.getContext(this);
 		var hasSplat = false;
 		for( t in textures )
 			if( t.kind == SplatMap ) {
@@ -1020,7 +1016,7 @@ class HeightMap extends Object3D {
 		');
 
 		var list = props.find("ul#tex");
-		ectx.properties.add(props,this, (_) -> updateInstance(ctx));
+		ectx.properties.add(props,this, (_) -> updateInstance());
 		for( tex in textures ) {
 			var prevTex = tex.path;
 			var e = new hide.Element('<li style="position:relative">
@@ -1044,14 +1040,14 @@ class HeightMap extends Object3D {
 				textures.remove(tex);
 				textures.insert(index-1, tex);
 				ectx.rebuildProperties();
-				updateInstance(ctx);
+				updateInstance();
 			});
 			e.find(".down").click(function(_) {
 				var index = textures.indexOf(tex);
 				textures.remove(tex);
 				textures.insert(index+1, tex);
 				ectx.rebuildProperties();
-				updateInstance(ctx);
+				updateInstance();
 			});
 			e.appendTo(list);
 			ectx.properties.build(e, tex, (pname) -> {
@@ -1078,7 +1074,7 @@ class HeightMap extends Object3D {
 					textures.remove(tex);
 					ectx.rebuildProperties();
 				}
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 			if( tex.props != null ) {
 				var e = new hide.Element('<li style="position:relative">
@@ -1109,7 +1105,7 @@ class HeightMap extends Object3D {
 	}
 	#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 {
 
-	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 = {};
 	}
 
 	#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 unknown = kind == null || kind.idx == null;
 
 		var modelPath = unknown ? null : findModelPath(kind.sheet, kind.idx.obj);
 		if(modelPath != null) {
 			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) {
-						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 {
-					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 ) {
-				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 ) {
 			// 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 ) {
 				var bmp = Std.downcast(follow.getChildAt(0), h2d.Bitmap);
 				if( bmp != null ) {
@@ -57,7 +66,9 @@ class Instance extends Object3D {
 		return int;
 	}
 
-	override function removeInstance(ctx:Context):Bool {
+	// TODO(ces) restore
+
+	/*override function removeInstance():Bool {
 		if(!super.removeInstance(ctx))
 			return false;
 		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();
 		}
 		return true;
-	}
+	}*/
 
 	// ---- statics
 
@@ -128,7 +139,7 @@ class Instance extends Object3D {
 		function filter(f: String) {
 			if(f != null) {
 				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 null;
@@ -155,10 +166,10 @@ class Instance extends Object3D {
 		return path;
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "circle", name : "Instance" };
 	}
 	#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;
 
+// NOTE(ces) : Not Tested
+
 typedef Layer2DValue = {
 	index	: Int,
 	name 	: String,
@@ -92,6 +94,7 @@ class LayerView2DRFXShader extends h3d.shader.ScreenShader {
 	}
 }
 
+@:access(h3d.scene.Renderer)
 class Layer2DRFX extends hrt.prefab.rfx.RendererFX {
 
 	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;
 
 	#if editor
-	var storedCtx : hrt.prefab.Context;
 
 	var currentPixels : hxd.Pixels = null;
 	var currentTexture : h3d.mat.Texture = null;
@@ -188,32 +190,29 @@ class Layers2D extends hrt.prefab.Object3D {
 	#end
 
 	#if editor
-	override function save() : {} {
-		var o : Dynamic = super.save();
+	override function save() : Dynamic {
+		var obj = super.save();
 
 		for ( l in layers ) {
 			var pixels = layerTextures.get(l.name);
 			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";
 				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
 
-	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 ) {
-			var path = new haxe.io.Path(ctx.shared.currentPath);
+			var path = new haxe.io.Path(shared.currentPath);
 			path.ext = "dat";
 			var datDir = path.toString();
 			var fileName = "layer_" + l.name + ".png";
@@ -225,7 +224,6 @@ class Layers2D extends hrt.prefab.Object3D {
 			if ( pixels != null )
 				layerTextures.set(l.name, pixels);
 		}
-		return ctx;
 	}
 
 	function loadPixels(path : String) {
@@ -285,7 +283,7 @@ class Layers2D extends hrt.prefab.Object3D {
 			return;
 		if ( b ) {
 			if ( rfx == null ) {
-				rfx = new Layer2DRFX();
+				rfx = new Layer2DRFX(null, null);
 				var renderer = Std.downcast(ectx.scene.s3d.renderer, h3d.scene.pbr.Renderer);
 				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 ) {
 			var sh : LayerView2DRFXShader = cast rfx.pass.shader;
 			if( collideMap == null || collideMap.isDisposed() ) {
 				if ( collidePath != null ) {
-					collideMap = ctx.loadTexture(collidePath);
+					collideMap = shared.loadTexture(collidePath);
 					collideMap.filter = Nearest;
 					collidePixels = loadPixels(collidePath);
 				}
@@ -363,7 +361,7 @@ class Layers2D extends hrt.prefab.Object3D {
 
 			if ( currentLayer == revertDataToApply.layer ) {
 				currentTexture.uploadPixels(currentPixels);
-				updateVisuals(editorCtx.getContext(this));
+				updateVisuals();
 			}
 		}));
 	}
@@ -371,8 +369,7 @@ class Layers2D extends hrt.prefab.Object3D {
 	function createInteractiveBrush(ectx : hide.prefab.EditContext) {
 		if (!enabled) return;
 		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.propagateEvents = true;
 		interactive.cancelEvents = false;
@@ -398,7 +395,7 @@ class Layers2D extends hrt.prefab.Object3D {
 				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) {
@@ -573,16 +570,16 @@ class Layers2D extends hrt.prefab.Object3D {
 				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);
 		if (gBrushes == null || gBrushes.length == 0 || gBrushes[0].scaleX != radius || gBrushes[0].material.color != newColor) {
 			clearBrushes();
 			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.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
@@ -592,7 +589,7 @@ class Layers2D extends hrt.prefab.Object3D {
 			gBrush.material.shadows = false;
 			gBrush.material.color = newColor;
 			gBrushes.push(gBrush);
-			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), ctx.local3d);
+			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), local3d);
 			gBrush.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
 			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 ) {
 			removeInteractiveBrush();
 		}
 		setupRfx(editorCtx, keepVisible || b);
-		updateVisuals(ctx);
+		updateVisuals();
 		return false;
 	}
 
@@ -642,7 +639,6 @@ class Layers2D extends hrt.prefab.Object3D {
 
 	override function edit( ectx : hide.prefab.EditContext ) {
 		super.edit(ectx);
-		var ctx = ectx.getContext(this);
 
 		sceneEditor = ectx.scene.editor;
 
@@ -762,7 +758,7 @@ class Layers2D extends hrt.prefab.Object3D {
 					collideMap = null;
 				}
 			}
-			updateVisuals(ctx);
+			updateVisuals();
 		});
 
 		function selectLayer( name : String ) {
@@ -809,7 +805,7 @@ class Layers2D extends hrt.prefab.Object3D {
 					ectx.properties.build(lValueContent, vLayer, (pname) -> {
 						if (pname == "color") {
 							updateColors();
-							updateVisuals(ctx);
+							updateVisuals();
 						}
 					});
 
@@ -893,7 +889,7 @@ class Layers2D extends hrt.prefab.Object3D {
 		}
 
 		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 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
 
-	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;
 
+/**
+	Alias of Object for compatibility with the old prefab system
+**/
 @:deprecated("Use hrt.prefab.Library instead")
-class Level3D extends hrt.prefab.Library {
-
-	public function new() {
-		super();
-		type = "level3d";
-	}
-
+class Level3D extends Object3D
+{
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "sitemap", name : "Level3D", allowParent: _ -> false};
 	}
 	#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;
 	@: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();
 		return obj;
 	}
@@ -135,19 +135,24 @@ class MeshGenerator extends Object3D {
 		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";
 
 		if( root == null ) {
 			root = new MeshPart();
 			root.socket.type = "Root";
 		}
-		updateInstance(ctx);
+		updateInstance();
 
 		#if editor
 		if( customScene == null ) {
@@ -157,25 +162,23 @@ class MeshGenerator extends Object3D {
 			#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
-		createEmptyMeshPart(ctx, root);
+		createEmptyMeshPart(root);
 		#end
 
-		var rootObject = ctx.local3d.getObjectByName("rootObject");
-		createMeshPart(ctx, root, rootObject);
+		var rootObject = local3d.getObjectByName("rootObject");
+		createMeshPart(root, rootObject);
 
 		#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) {
-			var dummy = Std.downcast(makeInteractive(ctx), h3d.scene.Interactive);
+			var dummy = Std.downcast(makeInteractive(), h3d.scene.Interactive);
 			int.preciseShape = dummy.preciseShape;
 			dummy.remove();
 		}
@@ -201,16 +204,16 @@ class MeshGenerator extends Object3D {
 		return null;
 	}
 
-	function createMeshPart( ctx : Context, mp : MeshPart, parent : h3d.scene.Object ) {
+	function createMeshPart(mp : MeshPart, parent : h3d.scene.Object ) {
 
 		#if editor
 		if( mp.previewPos ) {
 			if( mp.isRoot() )
-				parent.addChild(createPreviewSphere(ctx));
+				parent.addChild(createPreviewSphere());
 			else {
 				var socket = getSocket(parent, mp.socket);
 				if( socket != null )
-					socket.addChild(createPreviewSphere(ctx));
+					socket.addChild(createPreviewSphere());
 			}
 		}
 		#end
@@ -221,7 +224,7 @@ class MeshGenerator extends Object3D {
 		if( mp.meshPath == null )
 			return;
 
-		var obj = ctx.loadModel(mp.meshPath);
+		var obj = shared.loadModel(mp.meshPath);
 		for( m in obj.getMaterials() ) {
 			m.castShadows = shadows;
 		}
@@ -239,11 +242,11 @@ class MeshGenerator extends Object3D {
 		obj.setPosition(mp.offset.x, mp.offset.y, mp.offset.z);
 
 		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 {
@@ -261,18 +264,18 @@ class MeshGenerator extends Object3D {
 
 	#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;
 		curDepth++;
 		mp.meshPath = getRandomMeshPath(ctx.scene.config, mp.socket);
 		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 )
 			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 ) {
 			for( s in sl ) {
 				var b = true;
@@ -291,11 +294,11 @@ class MeshGenerator extends Object3D {
 			}
 		}
 		for( cmp in mp.childParts )
-			createEmptyMeshPart(ctx, cmp);
+			createEmptyMeshPart(cmp);
 	}
 
 	var target : h3d.mat.Texture;
-	function renderMeshThumbnail( ctx : Context, meshPath : String ) {
+	function renderMeshThumbnail(meshPath : String ) {
 
 		if( target == null )
 			target = new h3d.mat.Texture(256, 256, [Target], RGBA);
@@ -303,7 +306,7 @@ class MeshGenerator extends Object3D {
 		if( meshPath == null )
 			return;
 
-		var obj = ctx.loadModel(meshPath);
+		var obj = shared.loadModel(meshPath);
 		if( obj == null )
 			return;
 
@@ -323,7 +326,7 @@ class MeshGenerator extends Object3D {
 		if(sys.FileSystem.exists(file))
 			return;
 
-		var mainScene = @:privateAccess ctx.local3d.getScene();
+		var mainScene = @:privateAccess local3d.getScene();
 		@:privateAccess customScene.children = [];
 		@:privateAccess customScene.children.push(obj);
 
@@ -356,10 +359,10 @@ class MeshGenerator extends Object3D {
 		return false;
 	}
 
-	function createPreviewSphere( ctx : Context ) {
+	function createPreviewSphere() {
 		var root = new h3d.scene.Object();
 		root.setRotation(0,0, hxd.Math.degToRad(180));
-		var m : h3d.scene.Mesh = cast ctx.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
+		var m : h3d.scene.Mesh = cast shared.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
 		m.material.shadows = false;
 		root.addChild(m);
 		m.scale(0.5);
@@ -368,7 +371,7 @@ class MeshGenerator extends Object3D {
 		m.material.mainPass.depthTest = GreaterEqual;
 		m.material.mainPass.depthWrite = false;
 		m.material.mainPass.setPassName("overlay");
-		var m : h3d.scene.Mesh = cast ctx.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
+		var m : h3d.scene.Mesh = cast shared.loadModel("${HIDE}/res/meshGeneratorArrow.fbx");
 		m.material.shadows = false;
 		root.addChild(m);
 		m.scale(0.5);
@@ -386,15 +389,15 @@ class MeshGenerator extends Object3D {
 			resetPreview(cmp);
 	}
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		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 ) {
-			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 ) {
 				s.remove();
 			}
@@ -402,9 +405,9 @@ class MeshGenerator extends Object3D {
 		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;
-		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> {
@@ -441,7 +444,7 @@ class MeshGenerator extends Object3D {
 		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");
 	}
 
@@ -466,7 +469,7 @@ class MeshGenerator extends Object3D {
 		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 ) {
 			var meshList : Array<Dynamic> = ctx.scene.config.get("meshGenerator." + f);
 			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() ) {
 			var rootElement = new hide.Element('
@@ -509,7 +512,7 @@ class MeshGenerator extends Object3D {
 				var previous = mp.clone();
 				var actual = mp;
 				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) {
 					undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
 					ctx.onChange(this, null);
@@ -523,7 +526,7 @@ class MeshGenerator extends Object3D {
 			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 ) {
 			var s = '<div class="group" name="${extractMeshName(mp.meshPath)}">';
 			s += '<div align="center"><div class="meshGenerator-thumbnail"></div></div><dl>';
@@ -617,7 +620,7 @@ class MeshGenerator extends Object3D {
 						var previous = mp.clone();
 						var actual = mp;
 						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) {
 							undo ? mp.loadFrom(previous) : mp.loadFrom(actual);
 							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);
 
 		undo = ctx.properties.undo;
@@ -714,5 +717,5 @@ class MeshGenerator extends Object3D {
 	}
 	#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;
 
 import hrt.prefab.l3d.Spray;
+
 #if !editor
 
 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
 		var curID = 0, curMap = mspray.batchesMap.get(0);
 		if( curMap == null ) {
@@ -73,7 +74,7 @@ class MeshSpray extends Spray {
 				batch.emitCountTip++;
 				return;
 			}
-			var obj = ctx.loadModel(source);
+			var obj = shared.loadModel(source);
 			if ( obj.isMesh() ) {
 				loadBatchMesh( source, obj.toMesh() );
 			} else {
@@ -102,9 +103,9 @@ class MeshSpray extends Spray {
 		return mspray;
 	}
 
-	function loadBinary( ctx : Context ) {
+	function loadBinary() {
 		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 {
 			while( true ) {
 				binaryMeshes.push({
@@ -127,13 +128,13 @@ class MeshSpray extends Spray {
 		return true;
 	}
 
-	override function make( ctx : Context ) {
+	override function make(?sh:hrt.prefab.Prefab.ContextMake) : hrt.prefab.Prefab {
 		if( !enabled )
-			return ctx;
+			return this;
 		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 tmp = new h3d.Matrix();
 		var curID = 0, curMap = mspray.batchesMap.get(0);
@@ -203,16 +204,16 @@ class MeshSpray extends Spray {
 			b.worldPosition = null;
 		if ( clearBinaryMeshes )
 			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" )
 			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;
 	}
 
-	override function save() {
+	override function save() : Dynamic {
 		clearPreview();
 		if( binaryStorage ) saveToBinary();
 		return super.save();
@@ -359,8 +360,9 @@ class MeshSpray extends Spray {
 		for( i => m in this.sources )
 			meshes.set(m.path, i+1);
 		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);
+			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 });
 			children.remove(c);
 			binaryChanged = true;
@@ -398,7 +400,7 @@ class MeshSpray extends Spray {
 		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)) };
 	}
 
@@ -406,7 +408,7 @@ class MeshSpray extends Spray {
 		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.invert();
 
@@ -455,7 +457,7 @@ class MeshSpray extends Spray {
 						removeSourcePath(elt.val());
 						addSourcePath(newPath);
 						for (child in children) {
-							var model = child.to(hrt.prefab.Object3D);
+							var model = child.to(Model);
 							if (model != null && model.source == elt.val()) {
 								model.source = newPath;
 							}
@@ -468,7 +470,7 @@ class MeshSpray extends Spray {
 								removeSourcePath(newPath);
 								addSourcePath(path);
 								for (child in children) {
-									var model = child.to(hrt.prefab.Object3D);
+									var model = child.to(Model);
 									if (model != null && model.source == elt.val()) {
 										model.source = path;
 									}
@@ -481,7 +483,7 @@ class MeshSpray extends Spray {
 								removeSourcePath(elt.val());
 								addSourcePath(newPath);
 								for (child in children) {
-									var model = child.to(hrt.prefab.Object3D);
+									var model = child.to(Model);
 									if (model != null && model.source == elt.val()) {
 										model.source = newPath;
 									}
@@ -687,16 +689,14 @@ class MeshSpray extends Spray {
 		});
 
 		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) {
 			}));
 			for( c in this.children ) {
 				var obj = c.to(Object3D);
 				if( obj == null ) continue;
-				setGroundPos(ectx, obj);
-				var ctx = ectx.getContext(obj);
-				if( ctx != null ) obj.applyTransform(ctx.local3d);
+				setGroundPos(obj);
+				obj.applyTransform();
 				wasEdited = true;
 			}
 			if ( this.binaryMeshes != null ) {
@@ -706,7 +706,7 @@ class MeshSpray extends Spray {
 					pos.x = bm.x + pivot.tx;
 					pos.y = bm.y + pivot.ty;
 					pos.z = bm.z + pivot.tz;
-					var ground = setGroundPos(ectx, null, pos);
+					var ground = setGroundPos(null, pos);
 					bm.z += ground.mz;
 					bm.rotX = ground.rotX;
 					bm.rotY = ground.rotY;
@@ -738,7 +738,7 @@ class MeshSpray extends Spray {
 					}
 				}
 				sceneEditor.deleteElements(meshes);
-				cast(ectx.getContext(this).local3d, MeshSprayObject).redraw();
+				cast(local3d, MeshSprayObject).redraw();
 			}
 		});
 
@@ -773,7 +773,7 @@ class MeshSpray extends Spray {
 			createInteractiveBrush(ectx);
 		super.edit(ectx);
 
-		ectx.properties.add(new Element('
+		ectx.properties.add(new hide.Element('
 		<div class="group" name="Extra">
 		<dl>
 			<dt>Split</dt><dd><input type="range" min="0" max="2048" field="split"/></dd>
@@ -783,12 +783,11 @@ class MeshSpray extends Spray {
 		</div>'), this);
 	}
 
-	override function createInteractiveBrush(ectx : EditContext) {
+	override function createInteractiveBrush(ectx : hide.prefab.EditContext) {
 		super.createInteractiveBrush(ectx);
 		if (!enabled) return;
-		var ctx = ectx.getContext(this);
 
-		var s2d = ctx.shared.root2d.getScene();
+		var s2d = shared.root2d.getScene();
 
 		interactive.onMove = function(e) {
 			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
@@ -800,12 +799,12 @@ class MeshSpray extends Spray {
 				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) {
 				clearPreview();
 				if( !shiftPressed ) {
-					previewItemsAround(ectx, ctx, worldPos);
+					previewItemsAround(ectx, worldPos);
 				}
 
 				if( K.isDown( K.MOUSE_LEFT) ) {
@@ -814,17 +813,17 @@ class MeshSpray extends Spray {
 
 					if (sprayEnable) {
 						if( shiftPressed ) {
-							removeItemsAround(ctx, worldPos);
+							removeItemsAround(worldPos);
 						} else {
 							if (currentConfig.density == 1) {
 								if(lastItemPos.distance(worldPos) > currentConfig.step) {
 									lastItemPos = worldPos.clone();
-									addItems(ctx);
+									addItems();
 								}
 							}
 							else {
 								lastItemPos = worldPos.clone();
-								addItems(ctx);
+								addItems();
 							}
 						}
 					}
@@ -870,7 +869,7 @@ class MeshSpray extends Spray {
 			saveConfigMeshBatch();
 	}
 
-	override function removeItemsAround(ctx : Context, point : h3d.col.Point) {
+	override function removeItemsAround(point : h3d.col.Point) {
 		var vecRelat = point.toVector();
 		vecRelat.transform(invParent);
 		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
@@ -906,7 +905,7 @@ class MeshSpray extends Spray {
 					for( c in toDelete ) {
 						if( undo ) binaryMeshes.push(c) else binaryMeshes.remove(c);
 					}
-					cast(ctx.local3d,MeshSprayObject).redraw();
+					cast(local3d,MeshSprayObject).redraw();
 				}));
 				needRedraw = true;
 			}
@@ -914,36 +913,31 @@ class MeshSpray extends Spray {
 
 		if( needRedraw ) {
 			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) {
 		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 )
 			locked = false;
-		super.updateInstance(ctx, propName);
+		super.updateInstance(propName);
 	}
 
-	override function make(ctx:Context):Context {
-		if( !enabled )
-			return ctx;
+	override function makeInstance() {
 		if( binaryStorage ) {
 			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 {
 				while( true ) {
 					binaryMeshes.push({
@@ -961,25 +955,41 @@ class MeshSpray extends Spray {
 			} 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
 		for( c in children )
 			if( c.type == "model" )
-				makeChild(ctx, c);
-		cast(ctx.local3d, MeshSprayObject).redraw();
+				makeChild(c);
+
+		cast(local3d, MeshSprayObject).redraw();
 		// then add other children (shaders etc.)
 		for( c in children )
 			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;
 	}
 
-	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 mipNumber : Float;
 
-        @input var input2 : {
+		@input var input2 : {
 			var tangent : Vec3;
 			var uv : Vec2;
-        };
+		};
 
 		var calculatedUV : Vec2;
 		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 {
 
 	@:s var bakedMaterials : haxe.DynamicAccess<MaterialData>;
@@ -111,19 +119,27 @@ class ModelLibrary extends Prefab {
 	@:s var mipPower : Float;
 	@: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
 
 	@:s var compress : Bool = true;
 
 	var errors = [];
 
-	override function makeInstance(ctx) {
-		return ctx.clone(this);
-	}
-
 	override function edit(ectx:hide.prefab.EditContext) {
-		var ctx = ectx.getContext(this);
 
 		ectx.properties.add(new hide.Element('
 		<div class="group" name="Params">
@@ -137,13 +153,13 @@ class ModelLibrary extends Prefab {
 			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) {
 			ectx.makeChanges(this, function() {
 				errors = [];
-				rebuildData(ctx.shared, ectx.scene);
+				rebuildData(ectx.scene);
 				if ( compress )
-					compression(ctx.shared, ectx.scene);
+					compression(ectx.scene);
 
 				var ide = hide.Ide.inst;
 				ide.setProgress();
@@ -162,11 +178,11 @@ class ModelLibrary extends Prefab {
 			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) {
 			ectx.makeChanges(this, function() {
 				errors = [];
-				compression(ctx.shared, ectx.scene);
+				compression(ectx.scene);
 
 				var ide = hide.Ide.inst;
 				ide.setProgress();
@@ -176,7 +192,7 @@ class ModelLibrary extends Prefab {
 		});
 		ectx.properties.add(bt);
 
-		var listMaterials = new Element('
+		var listMaterials = new hide.Element('
 		<div class="group" name="Ignored materials"><ul id="ignoreMatList"></ul></div>');
 		ectx.properties.add(listMaterials);
 		for( i in 0...ignoredMaterials.length ) {
@@ -190,7 +206,7 @@ class ModelLibrary extends Prefab {
 			});
 			e.appendTo(listMaterials);
 			ectx.properties.build(e, ignoredMaterials[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 		}
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
@@ -200,7 +216,7 @@ class ModelLibrary extends Prefab {
 			ectx.rebuildProperties();
 		});
 
-		var listPrefabs = new Element('
+		var listPrefabs = new hide.Element('
 		<div class="group" name="Ignored prefabs"><ul id="ignorePrefabList"></ul></div>');
 		ectx.properties.add(listPrefabs);
 		for( i in 0...ignoredPrefabs.length ) {
@@ -215,7 +231,7 @@ class ModelLibrary extends Prefab {
 			});
 			e.appendTo(listPrefabs);
 			ectx.properties.build(e, ignoredPrefabs[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 		}
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
@@ -225,7 +241,7 @@ class ModelLibrary extends Prefab {
 			ectx.rebuildProperties();
 		});
 
-		var listObjectNames = new Element('
+		var listObjectNames = new hide.Element('
 		<div class="group" name="Ignored object names"><ul id="ignoreObjectNames"></ul></div>');
 		ectx.properties.add(listObjectNames);
 		for( i in 0...ignoredObjectNames.length ) {
@@ -239,7 +255,7 @@ class ModelLibrary extends Prefab {
 			});
 			e.appendTo(listObjectNames);
 			ectx.properties.build(e, ignoredObjectNames[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 		}
 		var add = new hide.Element('<li><p><a href="#">[+]</a></p></li>');
@@ -249,7 +265,7 @@ class ModelLibrary extends Prefab {
 			ectx.rebuildProperties();
 		});
 
-		var listpreserveObjectNames = new Element('
+		var listpreserveObjectNames = new hide.Element('
 		<div class="group" name="Preserve object names"><ul id="preserveObjectNames"></ul></div>');
 		ectx.properties.add(listpreserveObjectNames);
 		for( i in 0...preserveObjectNames.length ) {
@@ -263,7 +279,7 @@ class ModelLibrary extends Prefab {
 			});
 			e.appendTo(listpreserveObjectNames);
 			ectx.properties.build(e, preserveObjectNames[i], (pname) -> {
-				updateInstance(ctx, pname);
+				updateInstance(pname);
 			});
 		}
 		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" };
 	}
 
@@ -282,7 +298,7 @@ class ModelLibrary extends Prefab {
 		hide.Ide.inst.setProgress(text);
 	}
 
-	function rebuildData( shared : ContextShared, scene : hide.comp.Scene ) {
+	function rebuildData(scene : hide.comp.Scene ) {
 
 		bakedMaterials = {};
 		materialConfigs = [];
@@ -449,10 +465,10 @@ class ModelLibrary extends Prefab {
 		modelRoot.position.qz = 0;
 		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) )
 				continue;
-			if( m.getParent(hrt.prefab.fx.FX) != null )
+			if( m.findParent(hrt.prefab.fx.FX) != null )
 				continue;
 			var ignoreModel = false;
 			if ( m.animation != null )
@@ -677,7 +693,7 @@ class ModelLibrary extends Prefab {
 		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");
 		convert.params = {format: "BC3"};
 		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
 
 	// 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 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
-		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 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;
@@ -740,32 +755,39 @@ class ModelLibrary extends Prefab {
 			tnormal.wrap = Repeat;
 			tspec.wrap = Repeat;
 			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 {
-				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 curSubMeshes : SubMeshes = null;
 	public function optimize( obj : h3d.scene.Object, isStatic = true ) {
 		if( bakedMaterials == null )
 			throw "Model library was not built or saved";
-		if( !wasMake )
+		if( !cache.wasMade )
 			throw "Please call make() on modelLibrary first";
 
 		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) {
-		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 ) {
 			batch.material.staticShadows = true;
 			batch.fixedPosition = true;
 		}
 		batch.cullingCollider = bounds;
 		batch.name = "modelLibrary";
-		batch.material.mainPass.addShader(shader);
+		batch.material.mainPass.addShader(cache.shader);
 		if ( props != null ) {
 			batch.material.props = props;
 			batch.material.refreshProps();
@@ -917,22 +939,22 @@ class ModelLibrary extends Prefab {
 
 	public function emit(m : MaterialMesh, batch : h3d.scene.MeshBatch, emitCountTip = -1) {
 		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 ) {
 			batch.primitiveSubPart = new h3d.scene.MeshBatch.MeshBatchPart();
 			batch.begin(emitCountTip);
 		}
 		batch.primitiveSubPart.indexCount = bk.indexCount;
 		batch.primitiveSubPart.indexStart = bk.indexStart;
-		batch.primitiveSubPart.bounds = geomBounds[bk.geomId];
+		batch.primitiveSubPart.bounds = cache.geomBounds[bk.geomId];
 		batch.worldPosition = m.mesh.getAbsPos();
 		batch.emitInstance();
 	}
 
 	#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 clear = false;
 
-	public function postMake( ctx : Context ) {
+	override public function postMakeInstance() : Void {
 		modelLibrary = getOpt(ModelLibrary, null, true);
 		if ( modelLibrary == null )
 			throw "Missing modelLibrary as children";
 		modelLibrary.clear = clear;
-		for ( c in @:privateAccess ctx.local3d.children.copy() ) {
+		for ( c in @:privateAccess local3d.children.copy() ) {
 			if ( c != null )
 				modelLibrary.optimize(c);
 		}
 	}
-	override function make( ctx : Context ) : Context {
-		if( !enabled )
-			return ctx;
-		ctx = super.make(ctx);
-		postMake(ctx);
-		return ctx;
-	}
 
 	#else
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "square", name : "Model Library Optimizer" };
 	}
 
 	#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;
 
+// NOTE(ces) : Not Tested
+
 class Particles3D extends Object3D {
 
 	@: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 ) {
 			var src = null;
 			try {
@@ -28,16 +29,14 @@ class Particles3D extends Object3D {
 
 	#if editor
 
-	override function setSelected(ctx:Context, b:Bool):Bool {
+	override function setSelected(b:Bool):Bool {
 		return true;
 	}
 
-	override function edit(ectx:EditContext) {
+	override function edit(ectx:hide.prefab.EditContext) {
 		super.edit(ectx);
 		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) {
 				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 ) {
-				var e = new Element('
+				var e = new hide.Element('
 					<div class="section">
 						<h1><span>${g.name}</span> &nbsp;<input type="checkbox" field="enable"/></h1>
 						<div class="content">
@@ -179,7 +178,7 @@ class Particles3D extends Object3D {
 			for( g in parts.getGroups() )
 				addGroup(g);
 
-			var extra = new Element('
+			var extra = new hide.Element('
 				<div class="section">
 					<h1>Manage</h1>
 					<div class="content">
@@ -222,6 +221,6 @@ class Particles3D extends Object3D {
 	}
 	#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 h2d.col.Point;
 
+#if editor
+import hide.prefab.EditContext;
+#end
+
+import hide.prefab.HideProps;
+
+
 
 enum Shape {
 	Quad(subdivision : Int);
@@ -27,21 +34,16 @@ class Polygon extends Object3D {
 	var prevScale = [1.0, 1.0];
 	#end
 
-	public function new(?parent) {
-		super(parent);
-		type = "polygon";
-	}
-
 	override function save() {
-		var obj : Dynamic = super.save();
-		obj.kind = shape.getIndex();
+		var data = super.save();
+		data.kind = shape.getIndex();
 		switch(shape){
 		case Quad(_), Disc(_), Sphere(_), Capsule(_):
-			obj.args = shape.getParameters();
+			data.args = shape.getParameters();
 		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 ) {
@@ -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();
 		#if editor
-		setColor(ctx, color);
+		setColor(color);
 		if(editor != null)
 			editor.update(propName);
 		#else
@@ -98,7 +107,7 @@ class Polygon extends Object3D {
 		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 col = prim.getCollider();
 		return col.rayIntersection(ray, true);
@@ -234,26 +243,22 @@ class Polygon extends Object3D {
 		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 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.blendMode = Alpha;
 		mesh.material.mainPass.culling = None;
-		ctx.local3d = mesh;
-		ctx.local3d.name = name;
-		updateInstance(ctx);
-		return ctx;
+		return mesh;
 	}
 
 	#if editor
-	public function setColor(ctx: Context, color: Int) {
+	public function setColor(color: Int) {
 		if(hrt.prefab.Material.hasOverride(this))
 			return;
-		if(ctx.local3d == null)
+		if(local3d == null)
 			return;
-		var mesh = Std.downcast(ctx.local3d, h3d.scene.Mesh);
+		var mesh = Std.downcast(local3d, h3d.scene.Mesh);
 		if(mesh != null && hasDebugColor)
 			hrt.prefab.l3d.Box.setDebugColor(color, mesh.material);
 	}
@@ -280,8 +285,8 @@ class Polygon extends Object3D {
 		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);
 	}
 
@@ -293,11 +298,11 @@ class Polygon extends Object3D {
 		}
 	}
 
-	override function setSelected( ctx : Context, b : Bool ) {
+	override function setSelected( b : Bool ) {
 		if (!enabled) return true;
-		super.setSelected(ctx, b);
+		super.setSelected(b);
 		if( editor != null && shape == Custom)
-			editor.setSelected(ctx, b);
+			editor.setSelected(b);
 		return true;
 	}
 
@@ -388,7 +393,7 @@ class Polygon extends Object3D {
 					}
 				}
 				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
 				}
 
@@ -459,7 +464,7 @@ class Polygon extends Object3D {
 				case "Sphere": sphereProps.show();
 				case "Custom":
 					editorProps.show();
-					setSelected(ctx.getContext(this), true);
+					setSelected(true);
 				default:
 			}
 		}
@@ -479,5 +484,5 @@ class Polygon extends Object3D {
 
 	#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 {
 
-	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;
 	}
 
-	override function save() {
+	override function save() : Dynamic {
 		clearPreview();
 		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) };
 	}
 
-	override function edit( ectx : EditContext ) {
+	override function edit( ectx : hide.prefab.EditContext ) {
 
 		invParent = getAbsPos().clone();
 		invParent.invert();
@@ -308,16 +308,14 @@ class PrefabSpray extends Spray {
 		});
 
 		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) {
 			}));
 			for( c in this.children ) {
 				var obj = c.to(Object3D);
 				if( obj == null ) continue;
-				setGroundPos(ectx, obj);
-				var ctx = ectx.getContext(obj);
-				if( ctx != null ) obj.applyTransform(ctx.local3d);
+				setGroundPos(obj);
+				obj.applyTransform();
 				wasEdited = true;
 			}
 			mso.redraw();
@@ -339,7 +337,7 @@ class PrefabSpray extends Spray {
 					prefabs.push(c);
 				}
 				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);
 	}
 
-	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);
 	}
 
-	override public function new(?parent) {
-		super(parent);
-		type = "splinePoint";
-	}
-
-	override function makeInstance(ctx:Context):Context {
+	override function makeInstance() : Void {
 		#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.follow = ctx.local3d;
+		pointViewer.follow = local3d;
 		pointViewer.followPositionOnly = true;
 		pointViewer.name = "pointViewer";
 		pointViewer.material.setDefaultProps("ui");
 		pointViewer.material.color.set(0,0,1,1);
 		pointViewer.material.mainPass.depthTest = Always;
 
-		controlPointsViewer = new h3d.scene.Graphics(ctx.local3d);
+		controlPointsViewer = new h3d.scene.Graphics(local3d);
 		controlPointsViewer.name = "controlPointsViewer";
 		controlPointsViewer.lineStyle(4, 0xffffff);
 		controlPointsViewer.material.mainPass.setPassName("ui");
@@ -98,15 +92,15 @@ class SplinePoint extends Object3D {
 		controlPointsViewer.moveTo(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);
 		t.textColor = 0xff00ff;
 		t.textAlign = Center;
 		t.dropShadow = { dx : 0.5, dy : 0.5, color : 0x202020, alpha : 1.0 };
 		t.setScale(2.5);
-		applyTransform(ctx.local3d);
+		applyTransform();
 		setViewerVisible(false);
-		obj = new SplinePointObject(ctx.local3d);
+		obj = new SplinePointObject(local3d);
 		obj.onSync = function(rctx) {
 			var cam = rctx.camera;
 			var gpos = obj.getAbsPos().getPosition();
@@ -120,33 +114,33 @@ class SplinePoint extends Object3D {
 			indexText.remove();
 			pointViewer.remove();
 		}
-		updateInstance(ctx);
+		updateInstance();
 		#end
-		return ctx;
 	}
 
-	override function applyTransform(o : h3d.scene.Object) {
-		super.applyTransform(o);
+	override function applyTransform() {
+		super.applyTransform();
 		#if editor
 			if (spline.editor != null)
-				@:privateAccess spline.computeSpline(spline.editor.editContext.getContext(spline));
+				@:privateAccess spline.computeSpline();
 		#end
 	}
 
-	override function updateInstance(ctx : Context, ?propName : String) {
-		super.updateInstance(ctx, propName);
+	override function updateInstance(?propName : String) {
+		super.updateInstance(propName);
 		#if editor
 			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) {
-				sp.computeName(ctx);
+				sp.computeName();
 			}
 		#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
 			#if editor
 				if (spline.editor != null && spline.editor.editContext.getContext(spline) != null)
@@ -154,35 +148,36 @@ class SplinePoint extends Object3D {
 			#end
 		}, 0);
 		return super.removeInstance(ctx);
-	}
+	}*/
 
 
 	#if editor
 
-	public function computeName(ctx) {
+	public function computeName() {
+		if( local3d == null ) return;
 		var index = spline.points.indexOf(this);
 		name = "SplinePoint" + index;
-		ctx.local3d.name = name;
+		local3d.name = name;
 		if (indexText != null) {
 			var t = Std.downcast(indexText.getChildAt(0), h2d.Text);
 			t.text = "" + index;
 		}
 	}
 
-	override function edit(ctx : EditContext) {
+	override function edit(ctx : hide.prefab.EditContext) {
 		super.edit(ctx);
 		if( spline.editor == null ) {
 			spline.editor = new hide.prefab.SplineEditor(spline, ctx.properties.undo);
 		}
 		spline.editor.editContext = ctx;
 	}
-	override function getHideProps() : HideProps {
+	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};
 	}
 	#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);
 		return result;
 	}
@@ -224,7 +219,7 @@ class SplinePoint extends Object3D {
 		pointViewer.material.color.setColor(color);
 	}
 
-	static var _ = hrt.prefab.Library.register("splinePoint", SplinePoint);
+	static var _ = Prefab.register("splinePoint", SplinePoint);
 }
 
 class Spline extends Object3D {
@@ -276,8 +271,8 @@ class Spline extends Object3D {
 	#end
 	public var wasEdited = false;
 
-	override function save() {
-		var obj : Dynamic = super.save();
+	override function save() : Dynamic {
+		var obj = super.save();
 
 		obj.shape = shape.getIndex();
 		return obj;
@@ -299,6 +294,12 @@ class Spline extends Object3D {
 		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
 	public function makeFromMatrix( m : h3d.Matrix ) {
 		var tmp = new h3d.Matrix();
@@ -310,39 +311,29 @@ class Spline extends Object3D {
 		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
 		for( pd in pointsData ) {
-			var sp = new SplinePoint(this);
+			var sp = new SplinePoint(this, null);
 			sp.setTransform(pd);
 		}
 
 		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 != null )
-			editor.update(ctx, propName);
+			editor.update(propName);
 		#end
-		computeSpline(ctx);
+		computeSpline();
 	}
 
 	// 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);
 			}
 			else {
-				var t = (l - s1);
+				var t = (l - s1) / segmentLength;
 				pos.lerp(data.samples[s1].pos, data.samples[s2].pos, t);
 				if(tangent != null)
 					tangent.lerp(data.samples[s1].tangent, data.samples[s2].tangent, t);
@@ -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();
 	}
 
-	function generateSplineGraph( ctx : hrt.prefab.Context ) {
-		if (ctx == null) return;
+	function generateSplineGraph() {
 
 		if( !showSpline ) {
 			if( lineGraphics != null ) {
@@ -619,7 +609,7 @@ class Spline extends Object3D {
 		}
 
 		if( lineGraphics == null ) {
-			lineGraphics = new h3d.scene.Graphics(ctx.local3d);
+			lineGraphics = new h3d.scene.Graphics(local3d);
 			lineGraphics.lineStyle(lineThickness, color);
 			lineGraphics.name = "lineGraphics";
 			lineGraphics.material.mainPass.setPassName("overlay");
@@ -631,16 +621,16 @@ class Spline extends Object3D {
 		lineGraphics.clear();
 		var b = true;
 		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 = false;
 		}
 	}
 
-	public function computeSpline(ctx : hrt.prefab.Context) {
+	public function computeSpline() {
 		computeSplineData();
 		#if editor
-			generateSplineGraph(ctx);
+			generateSplineGraph();
 		#end
 	}
 
@@ -650,16 +640,16 @@ class Spline extends Object3D {
 		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 )
-			editor.setSelected(ctx, b);
+			editor.setSelected(b);
 
 		return true;
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		ctx.properties.add( new hide.Element('
@@ -688,10 +678,10 @@ class Spline extends Object3D {
 		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
 
-	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;
 	@:s var customPass : String;
 
-	override function save() {
-		var obj : Dynamic = super.save();
+	override function save() : Dynamic {
+		var obj = super.save();
 		obj.meshScale = meshScale;
 		obj.meshRotation = meshRotation;
 		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);
 	}
 
-	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();
 		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);
 		modelMat.multiply(scale, rot);
 
-		createMeshPrimitive(ctx);
-		createMeshBatch(ctx);
-		createBatches(ctx);
+		createMeshPrimitive();
+		createMeshBatch();
+		createBatches();
 
 		// Remake the material
 		if( meshBatch != null ) {
-			var emptyCtx = new hrt.prefab.Context();
-			emptyCtx.local3d = meshBatch;
-			emptyCtx.shared = ctx.shared;
 			for( c in @:privateAccess children ) {
 				var mat = Std.downcast(c, Material);
 				if( mat != null && mat.enabled )
-					@:privateAccess mat.makeInstance(emptyCtx);
+					@:privateAccess mat.makeInstance();
 				var shader = Std.downcast(c, Shader);
 				if( shader != null && shader.enabled )
-					shader.makeInstance(emptyCtx);
+					shader.makeInstance();
 			}
 		}
 	}
 
-	function createMeshPrimitive( ctx : Context ) {
+	function createMeshPrimitive() {
 		meshPrimitive = null;
 		meshMaterial = 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 ) {
 				meshPrimitive = cast meshTemplate.primitive;
 				meshMaterial = cast meshTemplate.material.clone();
@@ -181,7 +186,7 @@ class SplineMesh extends Spline {
 		}
 	}
 
-	function createMeshBatch( ctx : Context ) {
+	function createMeshBatch() {
 
 		if( meshBatch != null ) {
 			meshBatch.remove();
@@ -199,18 +204,18 @@ class SplineMesh extends Spline {
 
 			if( customPass != null ) {
 				for( p in customPass.split(",") ) {
-					if( ctx.local3d.getScene().renderer.getPassByName(p) != null )
+					if( local3d.getScene().renderer.getPassByName(p) != null )
 						splineMaterial.allocPass(p);
 				}
 			}
 
-			meshBatch = new SplineMeshBatch(meshPrimitive, splineMaterial, ctx.local3d);
+			meshBatch = new SplineMeshBatch(meshPrimitive, splineMaterial, local3d);
 			meshBatch.ignoreParentTransform = true;
 			meshBatch.splineData = this.data;
 		}
 	}
 
-	function createBatches( ctx : Context ) {
+	function createBatches() {
 
 		if( meshBatch == null )
 			return;
@@ -233,7 +238,7 @@ class SplineMesh extends Spline {
 		}
 	}
 
-	function createMultiMeshes( ctx : Context ) {
+	function createMultiMeshes() {
 
 		for( m in meshes )
 			m.remove();
@@ -258,7 +263,7 @@ class SplineMesh extends Spline {
 			var s = createShader();
 			m.material.mainPass.addShader(s);
 			s.splinePos = i * step + minOffset;
-			ctx.local3d.addChild(m);
+			local3d.addChild(m);
 			meshes.push(m);
 		}
 	}
@@ -284,7 +289,7 @@ class SplineMesh extends Spline {
 
 	#if editor
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		var props = new hide.Element('
@@ -314,11 +319,11 @@ class SplineMesh extends Spline {
 		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" };
 	}
 
 	#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 {
 	var prefab : SplineMover;
-	var ctx : Context;
 
 	var state : Spline.MoveAlongSplineState = new Spline.MoveAlongSplineState();
 	public var movables : Array<h3d.scene.Object> = [];
@@ -13,10 +12,9 @@ class SplineMoverObject extends h3d.scene.Object {
 	#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);
 		this.prefab = prefab;
-		this.ctx = ctx;
 
 		#if editor
 		var prim = new h3d.prim.Sphere();
@@ -62,59 +60,30 @@ class SplineMover extends Spline {
 	#if editor
 	@:s public var showDebug : Bool = true;
 	#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
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		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('
 			<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
 
-	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 }> = [];
 
-	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;
 	}
 
-	override function make( ctx : Context ) {
-		if( !enabled )
-			return ctx;
+	override function makeInstance() {
+		super.makeInstance();
 		children.sort(function(c1, c2) {
 			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 invParent : h3d.Matrix;
 
-	var shared : ContextShared;
-
 	function clearPreview() {
 		// prevent saving preview
 		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)
 			throw "setGroundPos should use either object or absPos";
 		var tx : Float; var ty : Float; var tz : Float;
@@ -176,7 +173,7 @@ class Spray extends Object3D {
 			tz = obj.getAbsPos().tz;
 		}
 		var config = currentConfig;
-		var groundZ = ectx.positionToGroundZ(tx, ty);
+		var groundZ = shared.scene.editor.getZ(tx, ty);
 		var mz = config.zOffset + groundZ - tz;
 		if ( obj != null )
 			obj.z += mz;
@@ -184,7 +181,7 @@ class Spray extends Object3D {
 		var tilt = config.tiltAmount;
 
 		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);
 		}
 
@@ -212,10 +209,9 @@ class Spray extends Object3D {
 	var sprayedItems : Array<hrt.prefab.Prefab> = [];
 	var selectElement : hide.Element;
 
-	function createInteractiveBrush(ectx : EditContext) {
+	function createInteractiveBrush(ectx : hide.prefab.EditContext) {
 		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.propagateEvents = true;
 		interactive.cancelEvents = false;
@@ -231,7 +227,7 @@ class Spray extends Object3D {
 					if( !K.isDown( K.SHIFT) ) {
 						clearPreview();
 						var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-						previewItemsAround(ectx, ctx, worldPos);
+						previewItemsAround(ectx, worldPos);
 					}
 					lastSpray = Date.now().getTime();
 					lastItemPos = null;
@@ -243,7 +239,7 @@ class Spray extends Object3D {
 				currentConfig.rotation = currentConfig.rotation % 360;
 				clearPreview();
 				var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
-				previewItemsAround(ectx, ctx, worldPos);
+				previewItemsAround(ectx, worldPos);
 			}
 
 			if (e.keyCode == K.D) {
@@ -252,7 +248,7 @@ class Spray extends Object3D {
 				currentConfig.rotation = currentConfig.rotation % 360;
 				clearPreview();
 				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;
 			var worldPos = ectx.screenToGround(s2d.mouseX, s2d.mouseY);
 			if( K.isDown( K.SHIFT) )
-				removeItemsAround(ctx, worldPos);
+				removeItemsAround(worldPos);
 			else {
 				lastItemPos = worldPos.clone();
-				addItems(ctx);
+				addItems();
 			}
 		};
 
@@ -281,7 +277,7 @@ class Spray extends Object3D {
 					else {
 						sceneEditor.addElements(addedModels, false, true, false);
 					}
-					cast(ctx.local3d,SprayObject).redraw();
+					cast(local3d,SprayObject).redraw();
 				}));
 				sprayedItems = [];
 			}
@@ -298,12 +294,12 @@ class Spray extends Object3D {
 				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) {
 				clearPreview();
 				if( !shiftPressed ) {
-					previewItemsAround(ectx, ctx, worldPos);
+					previewItemsAround(ectx, worldPos);
 				}
 
 				if( K.isDown( K.MOUSE_LEFT) ) {
@@ -311,17 +307,17 @@ class Spray extends Object3D {
 
 					if (sprayEnable) {
 						if( shiftPressed ) {
-							removeItemsAround(ctx, worldPos);
+							removeItemsAround(worldPos);
 						} else {
 							if (currentConfig.density == 1) {
 								if(lastItemPos.distance(worldPos) > currentConfig.step) {
 									lastItemPos = worldPos.clone();
-									addItems(ctx);
+									addItems();
 								}
 							}
 							else {
 								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 )
 			removeInteractiveBrush();
 		return false;
@@ -371,7 +363,7 @@ class Spray extends Object3D {
 	var lastPos : h3d.col.Point;
 	var lastItemId = -1;
 	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) {
 			return;
 		}
@@ -463,11 +455,11 @@ class Spray extends Object3D {
 				var newPrefab : hrt.prefab.Object3D = null;
 
 				if (itemUsed.isRef) {
-					var refPrefab = new hrt.prefab.Reference(this);
+					var refPrefab = new hrt.prefab.Reference(this, null);
 					refPrefab.source = itemUsed.path;
 					newPrefab = refPrefab;
 				} else {
-					var model = new hrt.prefab.Model(this);
+					var model = new hrt.prefab.Model(this, null);
 					model.source = itemUsed.path;
 					newPrefab = model;
 				}
@@ -489,7 +481,7 @@ class Spray extends Object3D {
 				localMat.multiply(localMat, invParent);
 
 				newPrefab.setTransform(localMat);
-				setGroundPos(ectx, newPrefab);
+				setGroundPos(newPrefab);
 
 				previewItems.push(newPrefab);
 				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;
 		if (previewItems.length > 0) {
 			wasEdited = true;
 			sprayedItems = sprayedItems.concat(previewItems);
 			previewItems = [];
 			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();
 		vecRelat.transform(invParent);
 		var point2d = new h2d.col.Point(vecRelat.x, vecRelat.y);
@@ -538,30 +530,30 @@ class Spray extends Object3D {
 
 		if( needRedraw ) {
 			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);
 		if (gBrushes == null || gBrushes.length == 0 || gBrushes[0].scaleX != radius || gBrushes[0].material.color != newColor) {
 			clearBrushes();
 			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.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
 			pass.setPassName("overlay");
-			pass.depthTest = Always;
+			pass.depthTest = h3d.mat.Data.Compare.Always;
 			pass.depthWrite = false;
 			gBrush.material.shadows = false;
 			gBrush.material.color = newColor;
 			gBrushes.push(gBrush);
-			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), ctx.local3d);
+			gBrush = new h3d.scene.Mesh(new h3d.prim.Sphere(Math.min(radius*0.05, 0.35)), local3d);
 			gBrush.ignoreParentTransform = true;
 			var pass = gBrush.material.mainPass;
 			pass.setPassName("overlay");
-			pass.depthTest = Always;
+			pass.depthTest = h3d.mat.Data.Compare.Always;
 			pass.depthWrite = false;
 			gBrush.material.shadows = false;
 			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";
 
-	public function new( ?parent ) {
-		super(parent);
-		type = "text3d";
-	}
+	public var text2d : h2d.Text = null;
 
 	#if editor
 
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { icon : "font", name : "Text3D" };
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		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;
 		tfile.onChange = function() {
 			this.pathFont = tfile.path;
-			updateInstance(ctx.getContext(this), "pathFont");
+			updateInstance("pathFont");
 		}
         new hide.Element('<dt>Align</dt>').appendTo(gr);
 		var element = new hide.Element('<dd></dd>').appendTo(gr);
@@ -136,21 +133,21 @@ class Text3D extends Object3D {
 			leftAlign.attr("disabled", "true");
 			middleAlign.removeAttr("disabled");
 			rightAlign.removeAttr("disabled");
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		middleAlign.on("click", function(e) {
 			align = 1;
 			leftAlign.removeAttr("disabled");
 			middleAlign.attr("disabled", "true");
 			rightAlign.removeAttr("disabled");
-			updateInstance(ctx.getContext(this), "align");
+			updateInstance("align");
 		});
 		rightAlign.on("click", function(e) {
 			align = 2;
 			leftAlign.removeAttr("disabled");
 			middleAlign.removeAttr("disabled");
 			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);
@@ -173,28 +170,28 @@ class Text3D extends Object3D {
 
 	#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) {
 			return;
 		}
 		var text = loadText();
 		if (text == null || text.length == 0)
 			return;
-		var mesh : h3d.scene.Mesh = cast ctx.local3d;
+		var mesh : h3d.scene.Mesh = cast local3d;
 		var h2dFont = loadFont();
-		var h2dText = (cast ctx.local2d : h2d.Text);
+		var h2dText = null/*(cast local2d : h2d.Text)*/;
 		h2dText.font = h2dFont;
 		h2dText.letterSpacing = letterSpacing;
 		h2dText.text = text;
 		h2dText.smooth = true;
         h2dText.textAlign = switch (align) {
 			case 1:
-				Center;
+				h2d.Text.Align.Center;
 			case 2:
-				Right;
+				h2d.Text.Align.Right;
 			default:
-				Left;
+				h2d.Text.Align.Left;
 		}
 		@:privateAccess h2dText.glyphs.content = (cast mesh.primitive : Text3DPrimitive);
 		@:privateAccess {
@@ -247,19 +244,14 @@ class Text3D extends Object3D {
 		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;
-		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;
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		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);
-		applyTransform(tr);
-		tr.name = name;
+		applyTransform();
 		return tr;
 	}
 
-	override function makeInstance(ctx:Context):Context {
-		ctx = ctx.clone(this);
-		var tr = create(ctx.local3d);
-		ctx.local3d = tr;
-		return ctx;
-	}
-
 	#if editor
 
-	override function getHideProps():HideProps {
+	override function getHideProps():hide.prefab.HideProps {
 		return { icon : "toggle-on", name : "Trail" };
 	}
 
-	override public function edit(ctx:EditContext) {
+	override public function edit(ctx:hide.prefab.EditContext) {
 		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('
 		<div class="group" name="Material">
 		</div>
@@ -58,6 +49,6 @@ class Trail extends Object3D {
 
 	#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 prefab : Trails;
 
+
 	public var timeScale : Float = 1.0;
 
 	#if editor
@@ -775,27 +776,22 @@ class TrailsSubTailObj extends h3d.scene.Object {
 
 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
-	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
 
-	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 maxSpeed : Float = 1000.0;
 
-
 	@:s public var uvMode : UVMode = EStretch;
 	@:s public var uvStretch: Float = 1.0;
 	@: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 ) {
 		var tr = new TrailObj(this, parent, numTrails);
-		applyTransform(tr);
+		applyTransform();
 		tr.name = name;
 		tr.updateShader();
 		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
 
-	override function getHideProps():HideProps {
+	override function getHideProps():hide.prefab.HideProps {
 		return { icon : "toggle-on", name : "Trails" };
 	}
 
-	override public function edit(ctx:EditContext) {
+	override public function edit(ctx:hide.prefab.EditContext) {
 		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('
 		<div class="group" name="Trail Properties">
 			<dl>
@@ -882,5 +879,5 @@ class Trails extends Object3D {
 
 	#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 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) ) {
 			var material : Material = cast parent;
-			return material.getMaterials(ctx);
+			return material.getMaterials();
 		}
 		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 as = new AnisotropicForward();
 		var nt = new NoiseTexture();
 		var ff = new FrequencyValue();
 
-		var noiseIntensityTexture = noiseIntensityPath != null ? ctx.loadTexture(noiseIntensityPath) : null;
-		var noiseDirectionTexture = noiseDirectionPath != null ? ctx.loadTexture(noiseDirectionPath) : null;
+		var 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 ) {
 			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);
 			if( fv != null ) {
@@ -104,8 +101,8 @@ class Anisotropy extends Prefab {
 
 			var nt = m.mainPass.getShader(NoiseTexture);
 			if( nt != null ) {
-				nt.noiseIntensityTexture = noiseIntensityPath != null ? ctx.loadTexture(noiseIntensityPath) : null;
-				nt.noiseDirectionTexture = noiseDirectionPath != null ? ctx.loadTexture(noiseDirectionPath) : null;
+				nt.noiseIntensityTexture = noiseIntensityPath != null ? shared.loadTexture(noiseIntensityPath) : null;
+				nt.noiseDirectionTexture = noiseDirectionPath != null ? shared.loadTexture(noiseDirectionPath) : null;
 				nt.intensityFactor = intensityFactor;
 				nt.rotationOffset = hxd.Math.degToRad(rotationOffset);
 			}
@@ -113,13 +110,13 @@ class Anisotropy extends Prefab {
 	}
 
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { 	icon : "cube",
 					name : "Anisotropy",
 					allowParent : function(p) return p.to(Material) != null  };
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		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) {
 			if( pname == "mode" || pname == "noiseIntensityPath" || pname == "noiseDirectionPath" ) {
 				ctx.rebuildProperties();
-				refreshShaders(ctx.getContext(this));
+				refreshShaders();
 			}
 			ctx.onChange(this, pname);
 		});
 	}
 	#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 opacity : Float = 1.0;
 	@: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 )
-			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 ) {
 			var shader = new PointLightVolumeShader();
 			mesh.shader = shader;
 			mesh.material.mainPass.addShader(shader);
 		} else {
-			var spotLight = Std.downcast(ctx.local3d, h3d.scene.pbr.SpotLight);
+			var spotLight = Std.downcast(shared.current3d, h3d.scene.pbr.SpotLight);
 			if ( spotLight != null ) {
 				var shader = new SpotLightVolumeShader();
 				mesh.shader = shader;
 				mesh.material.mainPass.addShader(shader);
 			}
 		}
-		ctx.local3d = mesh;
+
+		local3d = mesh;
 		mesh.material.shadows = false;
 		mesh.material.mainPass.setBlendMode(Add);
 		mesh.material.mainPass.depthTest = Always;
 		mesh.material.mainPass.culling = Front;
 		mesh.material.mainPass.depthWrite = false;
 		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.shader.fallOff = fallOff;
 		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" };
 	}
 
 	#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 mode : SpecularColorMode = Albedo;
 
-	public function new(?parent) {
-		super(parent);
-		type = "specularColor";
-	}
-
-	function getMaterials( ctx : Context ) {
+	function getMaterials() {
 		if( Std.isOfType(parent, Material) ) {
 			var material : Material = cast parent;
-			return material.getMaterials(ctx);
+			return material.getMaterials();
 		}
 		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);
 			if( sca != null ) {
 				// No params
@@ -59,7 +52,7 @@ class SpecularColor extends Prefab {
 			}
 			var sct = m.mainPass.getShader(hrt.shader.SpecularColorTexture);
 			if( sct != null ) {
-				sct.specularColorTexture = ctx.loadTexture(specularColorPath);
+				sct.specularColorTexture = shared.loadTexture(specularColorPath);
 			}
 			var sc = m.mainPass.getShader(hrt.shader.SpecularColor);
 			if( sc != null ) {
@@ -69,16 +62,16 @@ class SpecularColor extends Prefab {
 		}
 	}
 
-	function refreshShaders( ctx : Context ) {
+	function refreshShaders() {
 
 		var sca = new SpecularColorAlbedo();
 		var scf = new SpecularColorFlat();
 		var sct = new SpecularColorTexture();
 		var sc = new hrt.shader.SpecularColor();
 
-		var specularColorTexture = specularColorPath != null ? ctx.loadTexture(specularColorPath) : null;
+		var specularColorTexture = specularColorPath != null ? shared.loadTexture(specularColorPath) : null;
 
-		var mat = getMaterials(ctx);
+		var mat = getMaterials();
 		for( m in mat ) {
 			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorAlbedo));
 			m.mainPass.removeShader(m.mainPass.getShader(SpecularColorFlat));
@@ -101,13 +94,13 @@ class SpecularColor extends Prefab {
 	}
 
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { 	icon : "cube",
 					name : "SpecularColor",
 					allowParent : function(p) return p.to(Material) != null };
 	}
 
-	override function edit( ctx : EditContext ) {
+	override function edit( ctx : hide.prefab.EditContext ) {
 		super.edit(ctx);
 
 		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) {
 			if( pname == "mode" || pname == "specularColorPath" ) {
 				ctx.rebuildProperties();
-				refreshShaders(ctx.getContext(this));
+				refreshShaders();
 			}
 			ctx.onChange(this, pname);
 		});
 	}
 	#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;
 
+@:access(h3d.scene.Renderer)
 class AutoExposure extends RendererFX {
 
 	@:s var lightFront : Float = 0.;
@@ -60,6 +61,6 @@ class AutoExposure extends RendererFX {
 	}
 	#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 {
 
 	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 blurLinear : Float;
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		size = 0.5;
 		blur = 3;
 		threshold = 0.5;
@@ -72,6 +73,6 @@ class Bloom extends RendererFX {
 	}
 	#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 {
 	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.alpha = alpha;
 		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 ) {

+ 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.Renderer)
 class CloudShadow extends RendererFX {
 
 	var dlwc = new DirLightWithClouds();
@@ -56,10 +57,9 @@ class CloudShadow extends RendererFX {
 		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) {
@@ -146,6 +146,6 @@ class CloudShadow extends RendererFX {
 	}
 	#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 {
 
 	var tonemap = new ColorGradingTonemap();
@@ -99,6 +99,6 @@ class ColorGrading extends RendererFX {
 	}
 	#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
 
-
+@:access(h3d.scene.Renderer)
 class Configurator extends RendererFX {
 
 	@:s public var vars : Array<{ name : String, defValue : Float }> = [];
@@ -130,9 +130,8 @@ class Configurator extends RendererFX {
 	#end
 	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 ) {
@@ -190,19 +189,12 @@ class Configurator extends RendererFX {
 		#end
 	}
 
-	override function makeInstance(ctx:Context):Context {
+	override function makeInstance() : Void {
 		for( v in vars )
 			values.set(v.name, v.defValue);
-		rootPrefab = this;
-		var shared = ctx.shared;
-		while( shared.parent != null ) {
-			rootPrefab = shared.parent.prefab;
-			shared = shared.parent.shared;
-		}
-		while( rootPrefab.parent != null )
-			rootPrefab = rootPrefab.parent;
+		rootPrefab = getRoot(true);
 		resetCache();
-		return super.makeInstance(ctx);
+		super.makeInstance();
 	}
 
 	override function begin(r:h3d.scene.Renderer, step:h3d.impl.RendererFX.Step) {
@@ -263,11 +255,11 @@ class Configurator extends RendererFX {
 	#end
 
 	#if editor
-	override function getHideProps() : HideProps {
+	override function getHideProps() : hide.prefab.HideProps {
 		return { name : "Configurator", icon : "dashboard" };
 	}
 
-	override function edit( ectx : EditContext ) {
+	override function edit( ectx : hide.prefab.EditContext ) {
 		var props = new hide.Element('
 		<div>
 			<div class="group" name="Variables">
@@ -327,7 +319,7 @@ class Configurator extends RendererFX {
 	}
 	#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 {
 
 	var blurPass = new h3d.pass.ScreenFx(new DistanceBlurShader());
@@ -70,8 +70,8 @@ class DistanceBlur extends RendererFX {
 	@:s public var blurTextureSize : Float;
 	@:s public var blurRange : Int;
 
-	function new(?parent) {
-		super(parent);
+	function new(parent, shared: ContextShared) {
+		super(parent, shared);
 		nearEndDistance = 10;
 		farStartDistance = 100;
 		farEndDistance = 500;
@@ -132,6 +132,6 @@ class DistanceBlur extends RendererFX {
 	}
 	#end
 
-	static var _ = Library.register("rfx.distanceBlur", DistanceBlur);
+	static var _ = Prefab.register("rfx.distanceBlur", DistanceBlur);
 
 }

部分文件因为文件数量过多而无法显示