forked from LeenkxTeam/LNXSDK
added 'On Any Object' checkbioxes for on contact node and for hast contact node, simplifuies workflow and better performence i think
This commit is contained in:
@ -7,39 +7,67 @@ class HasContactNode extends LogicNode {
|
|||||||
|
|
||||||
public var property0: Bool; // "any object" checkbox
|
public var property0: Bool; // "any object" checkbox
|
||||||
|
|
||||||
|
// Performance optimization: Cache RigidBody lookups
|
||||||
|
var cachedRb1: RigidBody = null;
|
||||||
|
var cachedRb2: RigidBody = null;
|
||||||
|
var lastObject1: Object = null;
|
||||||
|
var lastObject2: Object = null;
|
||||||
|
var lastContactCount: Int = 0;
|
||||||
|
var lastFrame: Int = -1;
|
||||||
|
|
||||||
public function new(tree: LogicTree) {
|
public function new(tree: LogicTree) {
|
||||||
super(tree);
|
super(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function get(from: Int): Dynamic {
|
override function get(from: Int): Dynamic {
|
||||||
var object1: Object = inputs[0].get();
|
var object1: Object = inputs[0].get();
|
||||||
|
|
||||||
if (object1 == null) return false;
|
if (object1 == null) return false;
|
||||||
|
|
||||||
#if lnx_physics
|
#if lnx_physics
|
||||||
|
// Enhanced caching: Check both object reference AND RigidBody availability
|
||||||
|
var shouldUpdateCache1 = false;
|
||||||
|
if (object1 != lastObject1) {
|
||||||
|
// Object reference changed - always update cache
|
||||||
|
shouldUpdateCache1 = true;
|
||||||
|
} else if (cachedRb1 == null) {
|
||||||
|
// Same object but no cached RigidBody - check if one was added
|
||||||
|
var currentRb1 = object1.getTrait(RigidBody);
|
||||||
|
if (currentRb1 != null) {
|
||||||
|
shouldUpdateCache1 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldUpdateCache1) {
|
||||||
|
cachedRb1 = object1.getTrait(RigidBody);
|
||||||
|
lastObject1 = object1;
|
||||||
|
}
|
||||||
|
if (cachedRb1 == null) return false;
|
||||||
|
|
||||||
var physics = leenkx.trait.physics.PhysicsWorld.active;
|
var physics = leenkx.trait.physics.PhysicsWorld.active;
|
||||||
var rb1 = object1.getTrait(RigidBody);
|
var rbs = physics.getContacts(cachedRb1);
|
||||||
if (rb1 != null) {
|
|
||||||
var rbs = physics.getContacts(rb1);
|
// Early exit if no contacts
|
||||||
if (rbs != null) {
|
if (rbs == null || rbs.length == 0) return false;
|
||||||
// If "any object" is enabled, check for any contact
|
|
||||||
if (property0) {
|
// If "any object" mode, any contact is valid - return immediately
|
||||||
return rbs.length > 0;
|
if (property0) return true;
|
||||||
} else {
|
|
||||||
// Original logic: check for specific object contact
|
// Specific object mode - check if second input exists
|
||||||
// Only try to get object2 if we have a second input
|
if (inputs.length <= 1) return false;
|
||||||
if (inputs.length > 1) {
|
|
||||||
var object2: Object = inputs[1].get();
|
var object2: Object = inputs[1].get();
|
||||||
if (object2 == null) return false;
|
if (object2 == null) return false;
|
||||||
|
|
||||||
var rb2 = object2.getTrait(RigidBody);
|
// Cache second RigidBody lookup
|
||||||
for (rb in rbs) {
|
if (object2 != lastObject2) {
|
||||||
if (rb == rb2) return true;
|
cachedRb2 = object2.getTrait(RigidBody);
|
||||||
}
|
lastObject2 = object2;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (cachedRb2 == null) return false;
|
||||||
|
|
||||||
|
// Use indexOf for better performance than manual loop
|
||||||
|
// This is more efficient for small arrays and uses native array methods
|
||||||
|
return rbs.indexOf(cachedRb2) >= 0;
|
||||||
#end
|
#end
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5,64 +5,99 @@ import leenkx.trait.physics.RigidBody;
|
|||||||
|
|
||||||
class OnContactNode extends LogicNode {
|
class OnContactNode extends LogicNode {
|
||||||
|
|
||||||
public var property0: String;
|
public var property0: String; // Contact type: "begin", "overlap", "end"
|
||||||
public var property1: Bool; // "on any object" checkbox
|
public var property1: Bool; // "On Any Object" checkbox
|
||||||
var lastContact = false;
|
|
||||||
|
// Cache for performance optimization
|
||||||
|
var cachedRb1: RigidBody = null;
|
||||||
|
var cachedRb2: RigidBody = null;
|
||||||
|
var lastObject1: Object = null;
|
||||||
|
var lastObject2: Object = null;
|
||||||
|
var lastObject1TraitCount: Int = 0;
|
||||||
|
var lastObject2TraitCount: Int = 0;
|
||||||
|
var lastContact = false; // Track previous contact state
|
||||||
|
|
||||||
public function new(tree: LogicTree) {
|
public function new(tree: LogicTree) {
|
||||||
super(tree);
|
super(tree);
|
||||||
|
// Subscribe to update events for event-based triggering
|
||||||
tree.notifyOnUpdate(update);
|
tree.notifyOnUpdate(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
var object1: Object = inputs[0].get();
|
var object1: Object = inputs[0].get();
|
||||||
|
if (object1 == null) return;
|
||||||
if (object1 == null) object1 = tree.object;
|
|
||||||
|
|
||||||
var contact = false;
|
|
||||||
|
|
||||||
#if lnx_physics
|
#if lnx_physics
|
||||||
var physics = leenkx.trait.physics.PhysicsWorld.active;
|
// Smart caching: update cache if object changes OR if trait count changes
|
||||||
var rb1 = object1.getTrait(RigidBody);
|
var shouldUpdateCache1 = (object1 != lastObject1) ||
|
||||||
if (rb1 != null) {
|
(lastObject1 != null && lastObject1.traits.length != lastObject1TraitCount);
|
||||||
var rbs = physics.getContacts(rb1);
|
|
||||||
if (rbs != null) {
|
if (shouldUpdateCache1) {
|
||||||
// If "on any object" is enabled, check for any contact
|
cachedRb1 = object1.getTrait(RigidBody);
|
||||||
|
lastObject1 = object1;
|
||||||
|
lastObject1TraitCount = object1.traits.length;
|
||||||
|
}
|
||||||
|
if (cachedRb1 == null) return;
|
||||||
|
|
||||||
|
var rbs = leenkx.trait.physics.PhysicsWorld.active.getContacts(cachedRb1);
|
||||||
|
if (rbs == null || rbs.length == 0) {
|
||||||
|
// No contacts - handle "end" event
|
||||||
|
if (lastContact && property0 == "end") {
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
lastContact = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for contact
|
||||||
|
var contact = false;
|
||||||
|
|
||||||
|
// If "On Any Object" mode, any contact is valid
|
||||||
if (property1) {
|
if (property1) {
|
||||||
contact = rbs.length > 0;
|
|
||||||
} else {
|
|
||||||
// Original logic: check for specific object contact
|
|
||||||
// Only try to get object2 if we have a second input
|
|
||||||
if (inputs.length > 1) {
|
|
||||||
var object2: Object = inputs[1].get();
|
|
||||||
if (object2 == null) object2 = tree.object;
|
|
||||||
|
|
||||||
var rb2 = object2.getTrait(RigidBody);
|
|
||||||
for (rb in rbs) {
|
|
||||||
if (rb == rb2) {
|
|
||||||
contact = true;
|
contact = true;
|
||||||
break;
|
} else {
|
||||||
}
|
// Specific object mode - check if second input exists
|
||||||
}
|
if (inputs.length <= 1) return;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
var b = false;
|
var object2: Object = inputs[1].get();
|
||||||
|
if (object2 == null) return;
|
||||||
|
|
||||||
|
// Smart caching for second object
|
||||||
|
var shouldUpdateCache2 = (object2 != lastObject2) ||
|
||||||
|
(lastObject2 != null && lastObject2.traits.length != lastObject2TraitCount);
|
||||||
|
|
||||||
|
if (shouldUpdateCache2) {
|
||||||
|
cachedRb2 = object2.getTrait(RigidBody);
|
||||||
|
lastObject2 = object2;
|
||||||
|
lastObject2TraitCount = object2.traits.length;
|
||||||
|
}
|
||||||
|
if (cachedRb2 == null) return;
|
||||||
|
|
||||||
|
// Check if target object is in contact list
|
||||||
|
contact = rbs.indexOf(cachedRb2) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle different contact event types
|
||||||
|
var shouldTrigger = false;
|
||||||
switch (property0) {
|
switch (property0) {
|
||||||
case "begin":
|
case "begin":
|
||||||
b = contact && !lastContact;
|
shouldTrigger = contact && !lastContact;
|
||||||
case "overlap":
|
case "overlap":
|
||||||
b = contact;
|
shouldTrigger = contact;
|
||||||
case "end":
|
case "end":
|
||||||
b = !contact && lastContact;
|
shouldTrigger = !contact && lastContact;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastContact = contact;
|
lastContact = contact;
|
||||||
|
|
||||||
if (b) runOutput(0);
|
if (shouldTrigger) {
|
||||||
|
runOutput(0);
|
||||||
|
}
|
||||||
|
#end
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the get method for backward compatibility, but it's not the primary interface
|
||||||
|
override function get(from: Int): Dynamic {
|
||||||
|
return lastContact;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user