forked from LeenkxTeam/LNXSDK
		
	
		
			
	
	
		
			249 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			249 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
|  | package iron.object; | ||
|  | 
 | ||
|  | import iron.Trait; | ||
|  | import iron.data.SceneFormat; | ||
|  | import iron.math.Vec4; | ||
|  | 
 | ||
|  | class Object { | ||
|  | 	static var uidCounter = 0; | ||
|  | 	public var uid: Int; | ||
|  | 	public var urandom: Float; | ||
|  | 	public var raw: TObj = null; | ||
|  | 
 | ||
|  | 	public var name: String = ""; | ||
|  | 	public var transform: Transform; | ||
|  | 	public var constraints: Array<Constraint> = null; | ||
|  | 	public var traits: Array<Trait> = []; | ||
|  | 
 | ||
|  | 	public var parent: Object = null; | ||
|  | 	public var children: Array<Object> = []; | ||
|  | 	public var lods: Array<Object> = null; | ||
|  | 
 | ||
|  | 	public var animation: Animation = null; | ||
|  | 	public var visible = true; // Skip render, keep updating | ||
|  | 	public var visibleMesh = true; | ||
|  | 	public var visibleShadow = true; | ||
|  | 	public var culled = false; // Object was culled last frame | ||
|  | 	public var culledMesh = false; | ||
|  | 	public var culledShadow = false; | ||
|  | 	public var vertex_groups: Map<String, Array<Vec4>> = null; | ||
|  | 	public var properties: Map<String, Dynamic> = null; | ||
|  | 	var isEmpty = false; | ||
|  | 
 | ||
|  | 	public function new() { | ||
|  | 		uid = uidCounter++; | ||
|  | 		urandom = seededRandom(); // Math.random(); | ||
|  | 		transform = new Transform(this); | ||
|  | 		isEmpty = Type.getClass(this) == Object; | ||
|  | 		if (isEmpty && Scene.active != null) Scene.active.empties.push(this); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Set the given `parentObject` as the parent of this object. | ||
|  | 
 | ||
|  | 		If `parentObject` is `null`, the object is parented to the scene's
 | ||
|  | 		`sceneParent`, which is the topmost object of the scene tree. | ||
|  | 		If you want to remove it from the scene, use `Object.remove()` instead. | ||
|  | 
 | ||
|  | 		If `parentObject` is the object on which this function is called, | ||
|  | 		nothing happens. | ||
|  | 
 | ||
|  | 		@param parentObject The new parent object. | ||
|  | 		@param parentInverse (Optional) Change the scale of the child object to be relative to the new parents 3D space or use the original scale. | ||
|  | 		@param keepTransform (Optional) When unparenting from the old parent, keep the transform given by the old parent or revert to the object's default.
 | ||
|  | 	**/ | ||
|  | 	public function setParent(parentObject: Object, parentInverse = false, keepTransform = false) { | ||
|  | 		if (parentObject == this || parentObject == parent) return; | ||
|  | 
 | ||
|  | 		if (parent != null) { | ||
|  | 			parent.children.remove(this); | ||
|  | 			if (keepTransform) this.transform.applyParent(); | ||
|  | 			this.parent = null; // rebuild matrix without a parent | ||
|  | 			this.transform.buildMatrix(); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (parentObject == null) { | ||
|  | 			parentObject = Scene.active.sceneParent; | ||
|  | 		} | ||
|  | 		parent = parentObject; | ||
|  | 		parent.children.push(this); | ||
|  | 		if (parentInverse) this.transform.applyParentInverse(); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Add a game Object as a child of this game Object. | ||
|  | 		@param	o The game Object instance to be added as a child. | ||
|  | 		@param	parentInverse Optional (default false) change the scale of the child object to be relative to the parents 3D space or use the original scale. | ||
|  | 	**/ | ||
|  | 	@:deprecated("addChild() is deprecated, please use setParent() instead") | ||
|  | 	public inline function addChild(o: Object, parentInverse = false) { | ||
|  | 		o.setParent(this, parentInverse, false); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Remove a child game Object from it's parentage. Does not remove the object from the scene.
 | ||
|  | 		@param	o The game Object instance to be removed. | ||
|  | 		@param	keepTransform Optional (defaut false) keep the transform given by the parent or revert to the objects default. | ||
|  | 	**/ | ||
|  | 	@:deprecated("removeChild() is deprecated, please use setParent(null) instead") | ||
|  | 	public inline function removeChild(o: Object, keepTransform = false) { | ||
|  | 		o.setParent(null, false, keepTransform); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Removes the game object from the scene. | ||
|  | 	**/ | ||
|  | 	public function remove() { | ||
|  | 		if (isEmpty && Scene.active != null) Scene.active.empties.remove(this); | ||
|  | 		if (animation != null) animation.remove(); | ||
|  | 		while (children.length > 0) children[0].remove(); | ||
|  | 		while (traits.length > 0) traits[0].remove(); | ||
|  | 		if (parent != null) { | ||
|  | 			parent.children.remove(this); | ||
|  | 			parent = null; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Get a child game Object of this game Object. Using the childs name property as a lookup. | ||
|  | 		@param	name A string matching the name property of the game Object to fetch. | ||
|  | 		@return	Object or null | ||
|  | 	**/ | ||
|  | 	public function getChild(name: String): Object { | ||
|  | 		if (this.name == name) return this; | ||
|  | 		else { | ||
|  | 			for (c in children) { | ||
|  | 				var r = c.getChild(name); | ||
|  | 				if (r != null) return r; | ||
|  | 			} | ||
|  | 		} | ||
|  | 		return null; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Returns the children of the object. | ||
|  | 
 | ||
|  | 		If 'recursive' is set to `false`, only direct children will be included | ||
|  | 		in the returned array. If `recursive` is `true`, children of children and | ||
|  | 		so on will be included too. | ||
|  | 
 | ||
|  | 		@param recursive = false Include children of children | ||
|  | 		@return `Array<Object>` | ||
|  | 	**/ | ||
|  | 	public function getChildren(?recursive = false): Array<Object> { | ||
|  | 		if (!recursive) return children; | ||
|  | 
 | ||
|  | 		var retChildren = children.copy(); | ||
|  | 		for (child in children) { | ||
|  | 			retChildren = retChildren.concat(child.getChildren(recursive)); | ||
|  | 		} | ||
|  | 		return retChildren; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function getChildOfType<T: Object>(type: Class<T>): T { | ||
|  | 		if (Std.isOfType(this, type)) return cast this; | ||
|  | 		else { | ||
|  | 			for (c in children) { | ||
|  | 				var r = c.getChildOfType(type); | ||
|  | 				if (r != null) return r; | ||
|  | 			} | ||
|  | 		} | ||
|  | 		return null; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	@:access(iron.Trait) | ||
|  | 	public function addTrait(t: Trait) { | ||
|  | 		traits.push(t); | ||
|  | 		t.object = this; | ||
|  | 
 | ||
|  | 		if (t._add != null) { | ||
|  | 			for (f in t._add) f(); | ||
|  | 			t._add = null; | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Remove the Trait from the Object. | ||
|  | 		@param	t The Trait to be removed from the game Object. | ||
|  | 	**/ | ||
|  | 	@:access(iron.Trait) | ||
|  | 	public function removeTrait(t: Trait) { | ||
|  | 		if (t._init != null) { | ||
|  | 			for (f in t._init) App.removeInit(f); | ||
|  | 			t._init = null; | ||
|  | 		} | ||
|  | 		if (t._update != null) { | ||
|  | 			for (f in t._update) App.removeUpdate(f); | ||
|  | 			t._update = null; | ||
|  | 		} | ||
|  | 		if (t._lateUpdate != null) { | ||
|  | 			for (f in t._lateUpdate) App.removeLateUpdate(f); | ||
|  | 			t._lateUpdate = null; | ||
|  | 		} | ||
|  | 		if (t._render != null) { | ||
|  | 			for (f in t._render) App.removeRender(f); | ||
|  | 			t._render = null; | ||
|  | 		} | ||
|  | 		if (t._render2D != null) { | ||
|  | 			for (f in t._render2D) App.removeRender2D(f); | ||
|  | 			t._render2D = null; | ||
|  | 		} | ||
|  | 		if (t._remove != null) { | ||
|  | 			for (f in t._remove) f(); | ||
|  | 			t._remove = null; | ||
|  | 		} | ||
|  | 		traits.remove(t); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	/** | ||
|  | 		Get the Trait instance that is attached to this game Object. | ||
|  | 		@param	c The class of type Trait to attempt to retrieve. | ||
|  | 		@return	Trait or null | ||
|  | 	**/ | ||
|  | 	public function getTrait<T: Trait>(c: Class<T>): T { | ||
|  | 		for (t in traits) if (Type.getClass(t) == cast c) return cast t; | ||
|  | 		return null; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	#if lnx_skin | ||
|  | 	public function getBoneAnimation(armatureUid): BoneAnimation { | ||
|  | 		for (a in Scene.active.animations) if (a.armature != null && a.armature.uid == armatureUid) return cast a; | ||
|  | 		return null; | ||
|  | 	} | ||
|  | 	#else | ||
|  | 	public function getBoneAnimation(armatureUid): Animation { | ||
|  | 		return null; | ||
|  | 	} | ||
|  | 	#end | ||
|  | 
 | ||
|  | 	public function getObjectAnimation(): ObjectAnimation { | ||
|  | 		if(animation != null) return cast animation; | ||
|  | 		return null; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	public function setupAnimation(oactions: Array<TSceneFormat> = null) { | ||
|  | 		// Parented to bone | ||
|  | 		#if lnx_skin | ||
|  | 		if (raw.parent_bone != null) { | ||
|  | 			Scene.active.notifyOnInit(function() { | ||
|  | 				var banim = getBoneAnimation(parent.uid); | ||
|  | 				if (banim != null) banim.addBoneChild(raw.parent_bone, this); | ||
|  | 			}); | ||
|  | 		} | ||
|  | 		#end | ||
|  | 		// Object actions | ||
|  | 		if (oactions == null) return; | ||
|  | 		animation = new ObjectAnimation(this, oactions); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	#if lnx_morph_target | ||
|  | 	public function setupMorphTargets() {} | ||
|  | 	#end | ||
|  | 
 | ||
|  | 	static var seed = 1; // cpp / js not consistent | ||
|  | 	static function seededRandom(): Float { | ||
|  | 		seed = (seed * 9301 + 49297) % 233280; | ||
|  | 		return seed / 233280.0; | ||
|  | 	} | ||
|  | } |