forked from LeenkxTeam/LNXSDK
		
	Compare commits
	
		
			21 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 48f5575e4e | |||
| f2c4be6336 | |||
| 2ddc938db8 | |||
| 5eb735ada2 | |||
| 9894cc20f2 | |||
| dbe6d0829a | |||
| 6f383e2ab2 | |||
| 5c2d29d7ce | |||
| 28579e14d7 | |||
| 2ec6f43cc5 | |||
| 027021815a | |||
| b9b387803f | |||
| e05d9d0237 | |||
| c908e6cad2 | |||
| 506a0a0245 | |||
| 5cf33724e4 | |||
| ac5aa3d19c | |||
| 0c534ee632 | |||
| e3e7855d26 | |||
| f7917974f8 | |||
| fa2d8f05d5 | 
@ -24,6 +24,9 @@ class ObjectAnimation extends Animation {
 | 
			
		||||
 | 
			
		||||
	public var transformMap: Map<String, FastFloat>;
 | 
			
		||||
 | 
			
		||||
	var defaultSampler: ActionSampler = null;
 | 
			
		||||
	static inline var DEFAULT_SAMPLER_ID = "__object_default_action__";
 | 
			
		||||
 | 
			
		||||
	public static var trackNames: Array<String> = [	"xloc", "yloc", "zloc",
 | 
			
		||||
											   		"xrot", "yrot", "zrot",
 | 
			
		||||
											   		"qwrot", "qxrot", "qyrot", "qzrot",
 | 
			
		||||
@ -39,7 +42,6 @@ class ObjectAnimation extends Animation {
 | 
			
		||||
		isSkinned = false;
 | 
			
		||||
		super();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function getAction(action: String): TObj {
 | 
			
		||||
		for (a in oactions) if (a != null && a.objects[0].name == action) return a.objects[0];
 | 
			
		||||
		return null;
 | 
			
		||||
@ -47,10 +49,29 @@ class ObjectAnimation extends Animation {
 | 
			
		||||
 | 
			
		||||
	override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.0, speed = 1.0, loop = true) {
 | 
			
		||||
		super.play(action, onComplete, blendTime, speed, loop);
 | 
			
		||||
		if (this.action == "" && oactions[0] != null) this.action = oactions[0].objects[0].name;
 | 
			
		||||
		if (this.action == "" && oactions != null && oactions[0] != null){
 | 
			
		||||
			this.action = oactions[0].objects[0].name;
 | 
			
		||||
		}
 | 
			
		||||
		oaction = getAction(this.action);
 | 
			
		||||
		if (oaction != null) {
 | 
			
		||||
			isSampled = oaction.sampled != null && oaction.sampled;
 | 
			
		||||
			if (defaultSampler != null) {
 | 
			
		||||
				deRegisterAction(DEFAULT_SAMPLER_ID);
 | 
			
		||||
			}
 | 
			
		||||
			var callbacks = onComplete != null ? [onComplete] : null;
 | 
			
		||||
			defaultSampler = new ActionSampler(this.action, speed, loop, false, callbacks);
 | 
			
		||||
			registerAction(DEFAULT_SAMPLER_ID, defaultSampler);
 | 
			
		||||
			if (paused) defaultSampler.paused = true;
 | 
			
		||||
			updateAnimation = function(map: Map<String, FastFloat>) {
 | 
			
		||||
				sampleAction(defaultSampler, map);
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			if (defaultSampler != null) {
 | 
			
		||||
				deRegisterAction(DEFAULT_SAMPLER_ID);
 | 
			
		||||
				defaultSampler = null;
 | 
			
		||||
			}
 | 
			
		||||
			updateAnimation = null;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -61,12 +82,13 @@ class ObjectAnimation extends Animation {
 | 
			
		||||
		Animation.beginProfile();
 | 
			
		||||
		#end
 | 
			
		||||
 | 
			
		||||
		if(transformMap == null) transformMap = new Map();
 | 
			
		||||
		if (transformMap == null) transformMap = new Map();
 | 
			
		||||
		transformMap = initTransformMap();
 | 
			
		||||
 | 
			
		||||
		super.update(delta);
 | 
			
		||||
		if (defaultSampler != null) defaultSampler.paused = paused;
 | 
			
		||||
		if (paused) return;
 | 
			
		||||
		if(updateAnimation == null) return;
 | 
			
		||||
		if (updateAnimation == null) return;
 | 
			
		||||
		if (!isSkinned) updateObjectAnimation();
 | 
			
		||||
 | 
			
		||||
		#if lnx_debug
 | 
			
		||||
 | 
			
		||||
@ -71,11 +71,12 @@ class ParticleSystem {
 | 
			
		||||
		Data.getParticle(sceneName, pref.particle, function(b: ParticleData) {
 | 
			
		||||
			data = b;
 | 
			
		||||
			r = data.raw;
 | 
			
		||||
			if (r.dynamic_emitter != null){
 | 
			
		||||
				dynamicEmitter = r.dynamic_emitter; 
 | 
			
		||||
			} else {
 | 
			
		||||
				dynamicEmitter = true;
 | 
			
		||||
			var dyn: Null<Bool> = r.dynamic_emitter;
 | 
			
		||||
			var dynValue: Bool = true;
 | 
			
		||||
			if (dyn != null) {
 | 
			
		||||
				dynValue = dyn;
 | 
			
		||||
			}
 | 
			
		||||
			dynamicEmitter = dynValue;
 | 
			
		||||
			if (Scene.active.raw.gravity != null) {
 | 
			
		||||
				gx = Scene.active.raw.gravity[0] * r.weight_gravity;
 | 
			
		||||
				gy = Scene.active.raw.gravity[1] * r.weight_gravity;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								leenkx/Sources/leenkx/logicnode/AnyContactNode.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								leenkx/Sources/leenkx/logicnode/AnyContactNode.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
package leenkx.logicnode;
 | 
			
		||||
import iron.object.Object;
 | 
			
		||||
 | 
			
		||||
#if lnx_physics
 | 
			
		||||
import leenkx.trait.physics.PhysicsCache;
 | 
			
		||||
import leenkx.trait.physics.RigidBody;
 | 
			
		||||
#end
 | 
			
		||||
 | 
			
		||||
class AnyContactNode extends LogicNode {
 | 
			
		||||
 | 
			
		||||
	public var property0: String; 
 | 
			
		||||
	var lastContact = false;
 | 
			
		||||
 | 
			
		||||
	public function new(tree: LogicTree) {
 | 
			
		||||
		super(tree);
 | 
			
		||||
		tree.notifyOnUpdate(update);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function update() {
 | 
			
		||||
		var object1: Object = inputs[0].get();
 | 
			
		||||
		if (object1 == null) object1 = tree.object;
 | 
			
		||||
		if (object1 == null) return;
 | 
			
		||||
 | 
			
		||||
		var contact = false;
 | 
			
		||||
 | 
			
		||||
		#if lnx_physics
 | 
			
		||||
		var rb1 = PhysicsCache.getCachedRigidBody(object1);
 | 
			
		||||
		if (rb1 != null) {
 | 
			
		||||
			var rbs = PhysicsCache.getCachedContacts(rb1);
 | 
			
		||||
			contact = (rbs != null && rbs.length > 0);
 | 
			
		||||
		}
 | 
			
		||||
		#end
 | 
			
		||||
 | 
			
		||||
		var shouldTrigger = false;
 | 
			
		||||
		switch (property0) {
 | 
			
		||||
		case "begin":
 | 
			
		||||
			shouldTrigger = contact && !lastContact;
 | 
			
		||||
		case "overlap":
 | 
			
		||||
			shouldTrigger = contact;
 | 
			
		||||
		case "end":
 | 
			
		||||
			shouldTrigger = !contact && lastContact;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		lastContact = contact;
 | 
			
		||||
 | 
			
		||||
		if (shouldTrigger) runOutput(0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -1,7 +1,10 @@
 | 
			
		||||
package leenkx.logicnode;
 | 
			
		||||
 | 
			
		||||
import iron.object.Object;
 | 
			
		||||
 | 
			
		||||
#if lnx_physics
 | 
			
		||||
import leenkx.trait.physics.PhysicsCache;
 | 
			
		||||
import leenkx.trait.physics.RigidBody;
 | 
			
		||||
#end
 | 
			
		||||
 | 
			
		||||
class HasContactNode extends LogicNode {
 | 
			
		||||
 | 
			
		||||
@ -15,12 +18,15 @@ class HasContactNode extends LogicNode {
 | 
			
		||||
 | 
			
		||||
		if (object1 == null || object2 == null) return false;
 | 
			
		||||
 | 
			
		||||
#if lnx_physics
 | 
			
		||||
		var physics = leenkx.trait.physics.PhysicsWorld.active;
 | 
			
		||||
		var rb2 = object2.getTrait(RigidBody);
 | 
			
		||||
		var rbs = physics.getContacts(object1.getTrait(RigidBody));
 | 
			
		||||
		if (rbs != null) for (rb in rbs) if (rb == rb2) return true;
 | 
			
		||||
#end
 | 
			
		||||
		#if lnx_physics
 | 
			
		||||
		var rb1 = PhysicsCache.getCachedRigidBody(object1);
 | 
			
		||||
		var rb2 = PhysicsCache.getCachedRigidBody(object2);
 | 
			
		||||
		
 | 
			
		||||
		if (rb1 != null && rb2 != null) {
 | 
			
		||||
			var rbs = PhysicsCache.getCachedContacts(rb1);
 | 
			
		||||
			return PhysicsCache.hasContactWith(rbs, rb2);
 | 
			
		||||
		}
 | 
			
		||||
		#end
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,11 @@
 | 
			
		||||
package leenkx.logicnode;
 | 
			
		||||
 | 
			
		||||
import iron.object.Object;
 | 
			
		||||
 | 
			
		||||
#if lnx_physics
 | 
			
		||||
import leenkx.trait.physics.PhysicsCache;
 | 
			
		||||
import leenkx.trait.physics.RigidBody;
 | 
			
		||||
#end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class OnContactNode extends LogicNode {
 | 
			
		||||
 | 
			
		||||
@ -23,22 +27,15 @@ class OnContactNode extends LogicNode {
 | 
			
		||||
 | 
			
		||||
		var contact = false;
 | 
			
		||||
 | 
			
		||||
#if lnx_physics
 | 
			
		||||
		var physics = leenkx.trait.physics.PhysicsWorld.active;
 | 
			
		||||
		var rb1 = object1.getTrait(RigidBody);
 | 
			
		||||
		if (rb1 != null) {
 | 
			
		||||
			var rbs = physics.getContacts(rb1);
 | 
			
		||||
			if (rbs != null) {
 | 
			
		||||
				var rb2 = object2.getTrait(RigidBody);
 | 
			
		||||
				for (rb in rbs) {
 | 
			
		||||
					if (rb == rb2) {
 | 
			
		||||
						contact = true;
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
		#if lnx_physics
 | 
			
		||||
			var rb1 = PhysicsCache.getCachedRigidBody(object1);
 | 
			
		||||
			var rb2 = PhysicsCache.getCachedRigidBody(object2);
 | 
			
		||||
			
 | 
			
		||||
			if (rb1 != null && rb2 != null) {
 | 
			
		||||
				var rbs = PhysicsCache.getCachedContacts(rb1);
 | 
			
		||||
				contact = PhysicsCache.hasContactWith(rbs, rb2);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
#end
 | 
			
		||||
		#end
 | 
			
		||||
 | 
			
		||||
		var b = false;
 | 
			
		||||
		switch (property0) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										98
									
								
								leenkx/Sources/leenkx/trait/physics/PhysicsCache.hx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								leenkx/Sources/leenkx/trait/physics/PhysicsCache.hx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,98 @@
 | 
			
		||||
package leenkx.trait.physics;
 | 
			
		||||
 | 
			
		||||
import iron.object.Object;
 | 
			
		||||
 | 
			
		||||
class PhysicsCache {
 | 
			
		||||
	#if lnx_physics
 | 
			
		||||
	static var rbCache: Map<Int, Dynamic> = new Map();
 | 
			
		||||
	static var contactsCache: Map<Int, Array<Dynamic>> = new Map();
 | 
			
		||||
	static var physicsFrame: Int = 0;
 | 
			
		||||
	static var lastQueryFrame: Int = -1;
 | 
			
		||||
	#end
 | 
			
		||||
	
 | 
			
		||||
	public static function getCachedRigidBody(object: Object): Dynamic {
 | 
			
		||||
		#if (!lnx_physics)
 | 
			
		||||
		return null;
 | 
			
		||||
		#else
 | 
			
		||||
		if (object == null) return null;
 | 
			
		||||
		
 | 
			
		||||
		var cached = rbCache.get(object.uid);
 | 
			
		||||
		if (cached != null) return cached;
 | 
			
		||||
		
 | 
			
		||||
		#if lnx_bullet
 | 
			
		||||
		var rb = object.getTrait(leenkx.trait.physics.bullet.RigidBody);
 | 
			
		||||
		#else
 | 
			
		||||
		var rb = object.getTrait(leenkx.trait.physics.oimo.RigidBody);
 | 
			
		||||
		#end
 | 
			
		||||
		
 | 
			
		||||
		if (rb != null) rbCache.set(object.uid, rb);
 | 
			
		||||
		return rb;
 | 
			
		||||
		#end
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static function getCachedContacts(rb: Dynamic): Array<Dynamic> {
 | 
			
		||||
		#if (!lnx_physics)
 | 
			
		||||
		return null;
 | 
			
		||||
		#else
 | 
			
		||||
		if (rb == null) return null;
 | 
			
		||||
		
 | 
			
		||||
		var rbObjectId = (rb.object != null) ? rb.object.uid : -1;
 | 
			
		||||
		
 | 
			
		||||
		if (rbObjectId == -1) {
 | 
			
		||||
			#if lnx_bullet
 | 
			
		||||
			if (leenkx.trait.physics.bullet.PhysicsWorld.active == null) return null;
 | 
			
		||||
			return leenkx.trait.physics.bullet.PhysicsWorld.active.getContacts(rb);
 | 
			
		||||
			#else
 | 
			
		||||
			if (leenkx.trait.physics.oimo.PhysicsWorld.active == null) return null;
 | 
			
		||||
			return leenkx.trait.physics.oimo.PhysicsWorld.active.getContacts(rb);
 | 
			
		||||
			#end
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (lastQueryFrame == physicsFrame) {
 | 
			
		||||
			var cached = contactsCache.get(rbObjectId);
 | 
			
		||||
			if (cached != null) return cached;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		lastQueryFrame = physicsFrame;
 | 
			
		||||
		
 | 
			
		||||
		var cached = contactsCache.get(rbObjectId);
 | 
			
		||||
		if (cached != null) return cached;
 | 
			
		||||
		
 | 
			
		||||
		#if lnx_bullet
 | 
			
		||||
		if (leenkx.trait.physics.bullet.PhysicsWorld.active == null) return null;
 | 
			
		||||
		var contacts = leenkx.trait.physics.bullet.PhysicsWorld.active.getContacts(rb);
 | 
			
		||||
		#else
 | 
			
		||||
		if (leenkx.trait.physics.oimo.PhysicsWorld.active == null) return null;
 | 
			
		||||
		var contacts = leenkx.trait.physics.oimo.PhysicsWorld.active.getContacts(rb);
 | 
			
		||||
		#end
 | 
			
		||||
		
 | 
			
		||||
		if (contacts != null) {
 | 
			
		||||
			contactsCache.set(rbObjectId, contacts);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		return contacts;
 | 
			
		||||
		#end
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static inline function hasContactWith(contacts: Array<Dynamic>, target: Dynamic): Bool {
 | 
			
		||||
		#if (!lnx_physics)
 | 
			
		||||
		return false;
 | 
			
		||||
		#else
 | 
			
		||||
		return contacts != null && target != null && contacts.indexOf(target) >= 0;
 | 
			
		||||
		#end
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static function clearCache() {
 | 
			
		||||
		#if lnx_physics
 | 
			
		||||
		rbCache.clear();
 | 
			
		||||
		contactsCache.clear();
 | 
			
		||||
		#end
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static function clearContactsCache() {
 | 
			
		||||
		#if lnx_physics
 | 
			
		||||
		physicsFrame++;
 | 
			
		||||
		contactsCache.clear();
 | 
			
		||||
		#end
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -8,11 +8,9 @@ class PhysicsWorld extends iron.Trait { public function new() { super(); } }
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
	#if lnx_bullet
 | 
			
		||||
 | 
			
		||||
	typedef PhysicsWorld = leenkx.trait.physics.bullet.PhysicsWorld;
 | 
			
		||||
	typedef Hit = leenkx.trait.physics.bullet.PhysicsWorld.Hit;
 | 
			
		||||
	#else
 | 
			
		||||
 | 
			
		||||
	typedef PhysicsWorld = leenkx.trait.physics.oimo.PhysicsWorld;
 | 
			
		||||
	typedef Hit = leenkx.trait.physics.oimo.PhysicsWorld.Hit;
 | 
			
		||||
	#end
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import iron.system.Time;
 | 
			
		||||
import iron.math.Vec4;
 | 
			
		||||
import iron.math.Quat;
 | 
			
		||||
import iron.math.RayCaster;
 | 
			
		||||
import leenkx.trait.physics.PhysicsCache;
 | 
			
		||||
 | 
			
		||||
class Hit {
 | 
			
		||||
 | 
			
		||||
@ -145,6 +146,7 @@ class PhysicsWorld extends Trait {
 | 
			
		||||
 | 
			
		||||
		iron.Scene.active.notifyOnRemove(function() {
 | 
			
		||||
			sceneRemoved = true;
 | 
			
		||||
			PhysicsCache.clearCache();
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -303,6 +305,8 @@ class PhysicsWorld extends Trait {
 | 
			
		||||
		var t = Time.fixedStep * timeScale * Time.scale;
 | 
			
		||||
		if (t == 0.0) return; // Simulation paused
 | 
			
		||||
 | 
			
		||||
		PhysicsCache.clearContactsCache();
 | 
			
		||||
 | 
			
		||||
		#if lnx_debug
 | 
			
		||||
		var startTime = kha.Scheduler.realTime();
 | 
			
		||||
		#end
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										25
									
								
								leenkx/blender/lnx/logicnode/physics/LN_any_contact.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								leenkx/blender/lnx/logicnode/physics/LN_any_contact.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
from lnx.logicnode.lnx_nodes import *
 | 
			
		||||
 | 
			
		||||
class AnyContactNode(LnxLogicTreeNode):
 | 
			
		||||
    """Activates the output when the rigid body of the connected object makes contact with
 | 
			
		||||
    any other rigid body.
 | 
			
		||||
    """
 | 
			
		||||
    bl_idname = 'LNAnyContactNode'
 | 
			
		||||
    bl_label = 'Any Contact'
 | 
			
		||||
    lnx_section = 'contact'
 | 
			
		||||
    lnx_version = 1
 | 
			
		||||
 | 
			
		||||
    property0: HaxeEnumProperty(
 | 
			
		||||
        'property0',
 | 
			
		||||
        items = [('begin', 'Begin', 'Contact with any object begins'),
 | 
			
		||||
                 ('overlap', 'Overlap', 'Contact with any object is happening'),
 | 
			
		||||
                 ('end', 'End', 'Contact with any object ends')],
 | 
			
		||||
        name='', default='begin')
 | 
			
		||||
 | 
			
		||||
    def lnx_init(self, context):
 | 
			
		||||
        self.add_input('LnxNodeSocketObject', 'RB')
 | 
			
		||||
 | 
			
		||||
        self.add_output('LnxNodeSocketAction', 'Out')
 | 
			
		||||
 | 
			
		||||
    def draw_buttons(self, context, layout):
 | 
			
		||||
        layout.prop(self, 'property0')
 | 
			
		||||
		Reference in New Issue
	
	Block a user