From 4a98a59aa6810a679370e3664e89b3d83eb3d879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Tue, 29 Aug 2017 23:15:12 +0200 Subject: [PATCH] Fix joints collision exceptions Fix 3D joint handling of collision exceptions, so that they lose effect when the joint is not valid in every case; also some redundant code removed. Also avoid trying to create the joint when not neither body A nor body B are set. Make 2D joints be handled like their 3D counterparts, which adds the fixes to them while also removing duplicated code. Fixes #2383. --- scene/2d/joints_2d.cpp | 107 ++++++++++++++----------------------- scene/2d/joints_2d.h | 13 +++-- scene/3d/physics_joint.cpp | 31 ++++------- 3 files changed, 59 insertions(+), 92 deletions(-) diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index aeae3a74a39..b1c604081df 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -31,19 +31,49 @@ #include "physics_body_2d.h" #include "servers/physics_2d_server.h" -void Joint2D::_update_joint() { - - if (!is_inside_tree()) - return; +void Joint2D::_update_joint(bool p_only_free) { if (joint.is_valid()) { + if (ba.is_valid() && bb.is_valid()) + Physics2DServer::get_singleton()->body_remove_collision_exception(ba, bb); + Physics2DServer::get_singleton()->free(joint); + joint = RID(); + ba = RID(); + bb = RID(); } - joint = RID(); + if (p_only_free || !is_inside_tree()) + return; + + Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; + Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; + + if (!node_a || !node_b) + return; + + PhysicsBody2D *body_a = node_a ? node_a->cast_to() : (PhysicsBody2D *)NULL; + PhysicsBody2D *body_b = node_b ? node_b->cast_to() : (PhysicsBody2D *)NULL; + + if (!body_a || !body_b) + return; + + if (!body_a) { + SWAP(body_a, body_b); + } + + joint = _configure_joint(body_a, body_b); + + if (!joint.is_valid()) + return; - joint = _configure_joint(); Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint, Physics2DServer::JOINT_PARAM_BIAS, bias); + + ba = body_a->get_rid(); + bb = body_b->get_rid(); + + if (exclude_from_collision) + Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); } void Joint2D::set_node_a(const NodePath &p_node_a) { @@ -81,9 +111,7 @@ void Joint2D::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { if (joint.is_valid()) { - - Physics2DServer::get_singleton()->free(joint); - joint = RID(); + _update_joint(true); } } break; } @@ -162,29 +190,8 @@ void PinJoint2D::_notification(int p_what) { } } -RID PinJoint2D::_configure_joint() { +RID PinJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) { - Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; - Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; - - if (!node_a && !node_b) - return RID(); - - PhysicsBody2D *body_a = node_a ? node_a->cast_to() : (PhysicsBody2D *)NULL; - PhysicsBody2D *body_b = node_b ? node_b->cast_to() : (PhysicsBody2D *)NULL; - - if (!body_a && !body_b) - return RID(); - - if (!body_a) { - SWAP(body_a, body_b); - } else if (body_b) { - //add a collision exception between both - if (get_exclude_nodes_from_collision()) - Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); - else - Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(), body_b->get_rid()); - } RID pj = Physics2DServer::get_singleton()->pin_joint_create(get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID()); Physics2DServer::get_singleton()->pin_joint_set_param(pj, Physics2DServer::PIN_JOINT_SOFTNESS, softness); return pj; @@ -239,24 +246,7 @@ void GrooveJoint2D::_notification(int p_what) { } } -RID GrooveJoint2D::_configure_joint() { - - Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; - Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; - - if (!node_a || !node_b) - return RID(); - - PhysicsBody2D *body_a = node_a->cast_to(); - PhysicsBody2D *body_b = node_b->cast_to(); - - if (!body_a || !body_b) - return RID(); - - if (get_exclude_nodes_from_collision()) - Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); - else - Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(), body_b->get_rid()); +RID GrooveJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) { Matrix32 gt = get_global_transform(); Vector2 groove_A1 = gt.get_origin(); @@ -328,24 +318,7 @@ void DampedSpringJoint2D::_notification(int p_what) { } } -RID DampedSpringJoint2D::_configure_joint() { - - Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; - Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; - - if (!node_a || !node_b) - return RID(); - - PhysicsBody2D *body_a = node_a->cast_to(); - PhysicsBody2D *body_b = node_b->cast_to(); - - if (!body_a || !body_b) - return RID(); - - if (get_exclude_nodes_from_collision()) - Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); - else - Physics2DServer::get_singleton()->body_remove_collision_exception(body_a->get_rid(), body_b->get_rid()); +RID DampedSpringJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) { Matrix32 gt = get_global_transform(); Vector2 anchor_A = gt.get_origin(); diff --git a/scene/2d/joints_2d.h b/scene/2d/joints_2d.h index b714ef42808..a4ca793d858 100644 --- a/scene/2d/joints_2d.h +++ b/scene/2d/joints_2d.h @@ -32,11 +32,14 @@ #include "node_2d.h" +class PhysicsBody2D; + class Joint2D : public Node2D { OBJ_TYPE(Joint2D, Node2D); RID joint; + RID ba, bb; NodePath a; NodePath b; @@ -45,10 +48,10 @@ class Joint2D : public Node2D { bool exclude_from_collision; protected: - void _update_joint(); + void _update_joint(bool p_only_free = false); void _notification(int p_what); - virtual RID _configure_joint() = 0; + virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) = 0; static void _bind_methods(); @@ -77,7 +80,7 @@ class PinJoint2D : public Joint2D { protected: void _notification(int p_what); - virtual RID _configure_joint(); + virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b); static void _bind_methods(); public: @@ -96,7 +99,7 @@ class GrooveJoint2D : public Joint2D { protected: void _notification(int p_what); - virtual RID _configure_joint(); + virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b); static void _bind_methods(); public: @@ -120,7 +123,7 @@ class DampedSpringJoint2D : public Joint2D { protected: void _notification(int p_what); - virtual RID _configure_joint(); + virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b); static void _bind_methods(); public: diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index 2fc4d2880c0..5e71054ee6b 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -32,13 +32,8 @@ void Joint::_update_joint(bool p_only_free) { if (joint.is_valid()) { - if (ba.is_valid() && bb.is_valid()) { - - if (exclude_from_collision) - PhysicsServer::get_singleton()->body_add_collision_exception(ba, bb); - else - PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb); - } + if (ba.is_valid() && bb.is_valid()) + PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb); PhysicsServer::get_singleton()->free(joint); joint = RID(); @@ -52,33 +47,31 @@ void Joint::_update_joint(bool p_only_free) { Node *node_a = has_node(get_node_a()) ? get_node(get_node_a()) : (Node *)NULL; Node *node_b = has_node(get_node_b()) ? get_node(get_node_b()) : (Node *)NULL; - if (!node_a && !node_b) + if (!node_a || !node_b) return; PhysicsBody *body_a = node_a ? node_a->cast_to() : (PhysicsBody *)NULL; PhysicsBody *body_b = node_b ? node_b->cast_to() : (PhysicsBody *)NULL; - if (!body_a && !body_b) + if (!body_a || !body_b) return; if (!body_a) { SWAP(body_a, body_b); - } else if (body_b) { - //add a collision exception between both - PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); } joint = _configure_joint(body_a, body_b); - if (joint.is_valid()) - PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority); + if (!joint.is_valid()) + return; - if (body_b && joint.is_valid()) { + PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority); - ba = body_a->get_rid(); - bb = body_b->get_rid(); + ba = body_a->get_rid(); + bb = body_b->get_rid(); + + if (exclude_from_collision) PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); - } } void Joint::set_node_a(const NodePath &p_node_a) { @@ -129,8 +122,6 @@ void Joint::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { if (joint.is_valid()) { _update_joint(true); - //PhysicsServer::get_singleton()->free(joint); - joint = RID(); } } break; }