|
@@ -1,413 +0,0 @@
|
|
|
-package hxd.prefab;
|
|
|
-
|
|
|
-/**
|
|
|
- Prefab is an data-oriented tree container capable of creating instances of Heaps objects.
|
|
|
-**/
|
|
|
-@:keepSub
|
|
|
-class Prefab {
|
|
|
-
|
|
|
- /**
|
|
|
- The type of prefab, allows to identify which class it should be loaded with.
|
|
|
- **/
|
|
|
- public var type(default, null) : String;
|
|
|
-
|
|
|
- /**
|
|
|
- The name of the prefab in the tree view
|
|
|
- **/
|
|
|
- public var name(default, set) : String;
|
|
|
-
|
|
|
- /**
|
|
|
- The parent of the prefab in the tree view
|
|
|
- **/
|
|
|
- public var parent(default, set) : Prefab;
|
|
|
-
|
|
|
- /**
|
|
|
- The associated source file (an image, a 3D model, etc.) if the prefab type needs it.
|
|
|
- **/
|
|
|
- public var source(default, set) : String;
|
|
|
-
|
|
|
- /**
|
|
|
- The list of children prefab in the tree view
|
|
|
- **/
|
|
|
- public var children(default, null) : Array<Prefab>;
|
|
|
-
|
|
|
- /**
|
|
|
- Tells if the prefab will create an instance when calling make() or be ignored. Also apply to this prefab children.
|
|
|
- **/
|
|
|
- public var enabled : Bool = true;
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- A storage for some extra properties
|
|
|
- **/
|
|
|
- public var props : Any;
|
|
|
-
|
|
|
- /**
|
|
|
- Creates a new prefab with the given parent.
|
|
|
- **/
|
|
|
- public function new(?parent) {
|
|
|
- this.parent = parent;
|
|
|
- children = [];
|
|
|
- }
|
|
|
-
|
|
|
- function set_name(n) {
|
|
|
- return name = n;
|
|
|
- }
|
|
|
-
|
|
|
- function set_source(f) {
|
|
|
- return source = f;
|
|
|
- }
|
|
|
-
|
|
|
- function set_parent(p) {
|
|
|
- if( parent != null )
|
|
|
- parent.children.remove(this);
|
|
|
- parent = p;
|
|
|
- if( parent != null )
|
|
|
- parent.children.push(this);
|
|
|
- return p;
|
|
|
- }
|
|
|
-
|
|
|
- #if editor
|
|
|
-
|
|
|
- /**
|
|
|
- Allows to customize how the prefab object is edited within Hide
|
|
|
- **/
|
|
|
- public function edit( ctx : hide.prefab.EditContext ) {
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Allows to customize how the prefab object is displayed / handled within Hide
|
|
|
- **/
|
|
|
- public function getHideProps() : hide.prefab.HideProps {
|
|
|
- return { icon : "question-circle", name : "Unknown" };
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Allows to customize how the prefab instance changes when selected/unselected within Hide
|
|
|
- **/
|
|
|
- public function setSelected( ctx : Context, b : Bool ) {
|
|
|
- var materials = ctx.shared.getMaterials(this);
|
|
|
-
|
|
|
- if( !b ) {
|
|
|
- for( m in materials ) {
|
|
|
- m.mainPass.stencil = null;
|
|
|
- m.removePass(m.getPass("highlight"));
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- var shader = new h3d.shader.FixedColor(0xffffff);
|
|
|
- for( m in materials ) {
|
|
|
- var p = m.allocPass("highlight");
|
|
|
- p.culling = None;
|
|
|
- p.depthWrite = false;
|
|
|
- p.addShader(shader);
|
|
|
- }
|
|
|
- }
|
|
|
- #end
|
|
|
-
|
|
|
- /**
|
|
|
- Iterate over children prefab
|
|
|
- **/
|
|
|
- public inline function iterator() : Iterator<Prefab> {
|
|
|
- return children.iterator();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Override to implement your custom prefab data loading
|
|
|
- **/
|
|
|
- function load( v : Dynamic ) {
|
|
|
- throw "Not implemented";
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Override to implement your custom prefab data saving
|
|
|
- **/
|
|
|
- function save() : {} {
|
|
|
- throw "Not implemented";
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Creates an instance for this prefab only (and not its children).
|
|
|
- Use make(ctx) to creates the whole instances tree;
|
|
|
- **/
|
|
|
- public function makeInstance( ctx : Context ) : Context {
|
|
|
- return ctx;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 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.
|
|
|
- **/
|
|
|
- public function updateInstance( ctx : Context, ?propName : String ) {
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 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
|
|
|
- **/
|
|
|
- public function removeInstance( ctx : Context ) : Bool {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Save the whole prefab data and its children.
|
|
|
- **/
|
|
|
- @:final public function saveData() : {} {
|
|
|
- var obj : Dynamic = save();
|
|
|
- obj.type = type;
|
|
|
- if( !enabled )
|
|
|
- obj.enabled = false;
|
|
|
- if( name != null )
|
|
|
- obj.name = name;
|
|
|
- if( source != null )
|
|
|
- obj.source = source;
|
|
|
- if( children.length > 0 )
|
|
|
- obj.children = [for( s in children ) s.saveData()];
|
|
|
- if( props != null && obj.props == null )
|
|
|
- obj.props = props;
|
|
|
- return obj;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Load the whole prefab data and creates its children.
|
|
|
- **/
|
|
|
- @:final public function loadData( v : Dynamic ) {
|
|
|
- type = v.type;
|
|
|
- name = v.name;
|
|
|
- enabled = v.enabled == null ? true : v.enabled;
|
|
|
- props = v.props;
|
|
|
- source = v.source;
|
|
|
- load(v);
|
|
|
- if( children.length > 0 )
|
|
|
- children = [];
|
|
|
- var children : Array<Dynamic> = v.children;
|
|
|
- if( children != null )
|
|
|
- for( v in children )
|
|
|
- loadPrefab(v, this);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Updates in-place the whole prefab data and its children.
|
|
|
- **/
|
|
|
- public function reload( p : Dynamic ) {
|
|
|
- name = p.name;
|
|
|
- enabled = p.enabled == null ? true : p.enabled;
|
|
|
- props = p.props;
|
|
|
- source = p.source;
|
|
|
- load(p);
|
|
|
- var childData : Array<Dynamic> = p.children;
|
|
|
- if( childData == null ) {
|
|
|
- if( this.children.length > 0 ) this.children = [];
|
|
|
- return;
|
|
|
- }
|
|
|
- var curChild = new Map();
|
|
|
- for( c in children )
|
|
|
- curChild.set(c.name, c);
|
|
|
- var newchild = [];
|
|
|
- for( v in childData ) {
|
|
|
- var name : String = v.name;
|
|
|
- var prev = curChild.get(name);
|
|
|
- if( prev != null && prev.type == v.type ) {
|
|
|
- curChild.remove(name);
|
|
|
- prev.reload(v);
|
|
|
- newchild.push(prev);
|
|
|
- } else {
|
|
|
- newchild.push(loadPrefab(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.
|
|
|
- **/
|
|
|
- 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 = hxd.prefab.Unknown;
|
|
|
- var p = Type.createInstance(pcl, [parent]);
|
|
|
- p.loadData(v);
|
|
|
- return p;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Creates an instance for this prefab and its children.
|
|
|
- **/
|
|
|
- public function make( ctx : Context ) : Context {
|
|
|
- if( !enabled )
|
|
|
- return ctx;
|
|
|
- if( ctx == null ) {
|
|
|
- ctx = new Context();
|
|
|
- ctx.init();
|
|
|
- }
|
|
|
- ctx = makeInstance(ctx);
|
|
|
- for( c in children )
|
|
|
- c.make(ctx);
|
|
|
- return ctx;
|
|
|
- }
|
|
|
-
|
|
|
- #if castle
|
|
|
- /**
|
|
|
- Returns which CDB model this prefab props represents
|
|
|
- **/
|
|
|
- public function getCdbModel( ?p : Prefab ) : cdb.Sheet {
|
|
|
- if( p == null )
|
|
|
- p = this;
|
|
|
- if( parent != null )
|
|
|
- return parent.getCdbModel(p);
|
|
|
- return null;
|
|
|
- }
|
|
|
- #end
|
|
|
-
|
|
|
- /**
|
|
|
- Search the prefab tree for the prefab matching the given name, returns null if not found
|
|
|
- **/
|
|
|
- public function getPrefabByName( name : String ) {
|
|
|
- if( this.name == name )
|
|
|
- return this;
|
|
|
- for( c in children ) {
|
|
|
- var p = c.getPrefabByName(name);
|
|
|
- if( p != null )
|
|
|
- return p;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Simlar to get() but returns null if not found.
|
|
|
- **/
|
|
|
- public function getOpt<T:Prefab>( cl : Class<T>, ?name : String ) : 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);
|
|
|
- if( p != null )
|
|
|
- return p;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Return all prefabs in the tree matching the given prefab class.
|
|
|
- **/
|
|
|
- public function getAll<T:Prefab>( cl : Class<T>, ?arr: Array<T> ) : Array<T> {
|
|
|
- return findAll(function(p) return p.to(cl));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 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.
|
|
|
- **/
|
|
|
- public function find<T>( f : Prefab -> Null<T> ) : Null<T> {
|
|
|
- var v = f(this);
|
|
|
- if( v != null )
|
|
|
- return v;
|
|
|
- for( p in children ) {
|
|
|
- var v = p.find(f);
|
|
|
- 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.
|
|
|
- **/
|
|
|
- public function findAll<T>( f : Prefab -> Null<T>, ?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,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);
|
|
|
- }
|
|
|
- for(c in children)
|
|
|
- c.flatten(cl, arr);
|
|
|
- return arr;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Returns the first parent in the tree matching the specified class or null if not found.
|
|
|
- **/
|
|
|
- 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;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Converts the prefab to another prefab class.
|
|
|
- Returns null if not of this type.
|
|
|
- **/
|
|
|
- public function to<T:Prefab>( c : Class<T> ) : Null<T> {
|
|
|
- return Std.instance(this, c);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Returns the absolute name path for this prefab
|
|
|
- **/
|
|
|
- public function getAbsPath() {
|
|
|
- var p = this;
|
|
|
- var path = [];
|
|
|
- while(p.parent != null) {
|
|
|
- var n = p.name;
|
|
|
- if( n == null ) n = getDefaultName();
|
|
|
- path.unshift(n);
|
|
|
- p = p.parent;
|
|
|
- }
|
|
|
- return path.join('.');
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Returns the default name for this prefab
|
|
|
- **/
|
|
|
- public function getDefaultName() : String {
|
|
|
- if(source != null) {
|
|
|
- var f = new haxe.io.Path(source).file;
|
|
|
- f = f.split(" ")[0].split("-")[0];
|
|
|
- return f;
|
|
|
- }
|
|
|
- return type.split(".").pop();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- Clone this prefab and all its children
|
|
|
- **/
|
|
|
- public function clone() : Prefab {
|
|
|
- var obj = saveData();
|
|
|
- return loadPrefab(haxe.Json.parse(haxe.Json.stringify(obj)));
|
|
|
- }
|
|
|
-}
|