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.
This commit is contained in:
parent
213ca00e33
commit
4a98a59aa6
3 changed files with 59 additions and 92 deletions
|
@ -31,19 +31,49 @@
|
||||||
#include "physics_body_2d.h"
|
#include "physics_body_2d.h"
|
||||||
#include "servers/physics_2d_server.h"
|
#include "servers/physics_2d_server.h"
|
||||||
|
|
||||||
void Joint2D::_update_joint() {
|
void Joint2D::_update_joint(bool p_only_free) {
|
||||||
|
|
||||||
if (!is_inside_tree())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (joint.is_valid()) {
|
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);
|
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>() : (PhysicsBody2D *)NULL;
|
||||||
|
PhysicsBody2D *body_b = node_b ? node_b->cast_to<PhysicsBody2D>() : (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);
|
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) {
|
void Joint2D::set_node_a(const NodePath &p_node_a) {
|
||||||
|
@ -81,9 +111,7 @@ void Joint2D::_notification(int p_what) {
|
||||||
} break;
|
} break;
|
||||||
case NOTIFICATION_EXIT_TREE: {
|
case NOTIFICATION_EXIT_TREE: {
|
||||||
if (joint.is_valid()) {
|
if (joint.is_valid()) {
|
||||||
|
_update_joint(true);
|
||||||
Physics2DServer::get_singleton()->free(joint);
|
|
||||||
joint = RID();
|
|
||||||
}
|
}
|
||||||
} break;
|
} 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>() : (PhysicsBody2D *)NULL;
|
|
||||||
PhysicsBody2D *body_b = node_b ? node_b->cast_to<PhysicsBody2D>() : (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());
|
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);
|
Physics2DServer::get_singleton()->pin_joint_set_param(pj, Physics2DServer::PIN_JOINT_SOFTNESS, softness);
|
||||||
return pj;
|
return pj;
|
||||||
|
@ -239,24 +246,7 @@ void GrooveJoint2D::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RID GrooveJoint2D::_configure_joint() {
|
RID GrooveJoint2D::_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->cast_to<PhysicsBody2D>();
|
|
||||||
PhysicsBody2D *body_b = node_b->cast_to<PhysicsBody2D>();
|
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
Matrix32 gt = get_global_transform();
|
Matrix32 gt = get_global_transform();
|
||||||
Vector2 groove_A1 = gt.get_origin();
|
Vector2 groove_A1 = gt.get_origin();
|
||||||
|
@ -328,24 +318,7 @@ void DampedSpringJoint2D::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RID DampedSpringJoint2D::_configure_joint() {
|
RID DampedSpringJoint2D::_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->cast_to<PhysicsBody2D>();
|
|
||||||
PhysicsBody2D *body_b = node_b->cast_to<PhysicsBody2D>();
|
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
Matrix32 gt = get_global_transform();
|
Matrix32 gt = get_global_transform();
|
||||||
Vector2 anchor_A = gt.get_origin();
|
Vector2 anchor_A = gt.get_origin();
|
||||||
|
|
|
@ -32,11 +32,14 @@
|
||||||
|
|
||||||
#include "node_2d.h"
|
#include "node_2d.h"
|
||||||
|
|
||||||
|
class PhysicsBody2D;
|
||||||
|
|
||||||
class Joint2D : public Node2D {
|
class Joint2D : public Node2D {
|
||||||
|
|
||||||
OBJ_TYPE(Joint2D, Node2D);
|
OBJ_TYPE(Joint2D, Node2D);
|
||||||
|
|
||||||
RID joint;
|
RID joint;
|
||||||
|
RID ba, bb;
|
||||||
|
|
||||||
NodePath a;
|
NodePath a;
|
||||||
NodePath b;
|
NodePath b;
|
||||||
|
@ -45,10 +48,10 @@ class Joint2D : public Node2D {
|
||||||
bool exclude_from_collision;
|
bool exclude_from_collision;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _update_joint();
|
void _update_joint(bool p_only_free = false);
|
||||||
|
|
||||||
void _notification(int p_what);
|
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();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
@ -77,7 +80,7 @@ class PinJoint2D : public Joint2D {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
virtual RID _configure_joint();
|
virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -96,7 +99,7 @@ class GrooveJoint2D : public Joint2D {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
virtual RID _configure_joint();
|
virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -120,7 +123,7 @@ class DampedSpringJoint2D : public Joint2D {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
virtual RID _configure_joint();
|
virtual RID _configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b);
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -32,13 +32,8 @@
|
||||||
void Joint::_update_joint(bool p_only_free) {
|
void Joint::_update_joint(bool p_only_free) {
|
||||||
|
|
||||||
if (joint.is_valid()) {
|
if (joint.is_valid()) {
|
||||||
if (ba.is_valid() && bb.is_valid()) {
|
if (ba.is_valid() && bb.is_valid())
|
||||||
|
PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb);
|
||||||
if (exclude_from_collision)
|
|
||||||
PhysicsServer::get_singleton()->body_add_collision_exception(ba, bb);
|
|
||||||
else
|
|
||||||
PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicsServer::get_singleton()->free(joint);
|
PhysicsServer::get_singleton()->free(joint);
|
||||||
joint = RID();
|
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_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;
|
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;
|
return;
|
||||||
|
|
||||||
PhysicsBody *body_a = node_a ? node_a->cast_to<PhysicsBody>() : (PhysicsBody *)NULL;
|
PhysicsBody *body_a = node_a ? node_a->cast_to<PhysicsBody>() : (PhysicsBody *)NULL;
|
||||||
PhysicsBody *body_b = node_b ? node_b->cast_to<PhysicsBody>() : (PhysicsBody *)NULL;
|
PhysicsBody *body_b = node_b ? node_b->cast_to<PhysicsBody>() : (PhysicsBody *)NULL;
|
||||||
|
|
||||||
if (!body_a && !body_b)
|
if (!body_a || !body_b)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!body_a) {
|
if (!body_a) {
|
||||||
SWAP(body_a, body_b);
|
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);
|
joint = _configure_joint(body_a, body_b);
|
||||||
|
|
||||||
if (joint.is_valid())
|
if (!joint.is_valid())
|
||||||
PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority);
|
return;
|
||||||
|
|
||||||
if (body_b && joint.is_valid()) {
|
PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority);
|
||||||
|
|
||||||
ba = body_a->get_rid();
|
ba = body_a->get_rid();
|
||||||
bb = body_b->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());
|
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) {
|
void Joint::set_node_a(const NodePath &p_node_a) {
|
||||||
|
@ -129,8 +122,6 @@ void Joint::_notification(int p_what) {
|
||||||
case NOTIFICATION_EXIT_TREE: {
|
case NOTIFICATION_EXIT_TREE: {
|
||||||
if (joint.is_valid()) {
|
if (joint.is_valid()) {
|
||||||
_update_joint(true);
|
_update_joint(true);
|
||||||
//PhysicsServer::get_singleton()->free(joint);
|
|
||||||
joint = RID();
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue