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.

(adapted from commit 4a98a59aa6)
This commit is contained in:
Pedro J. Estébanez 2017-08-29 23:15:12 +02:00
parent 06d7e36898
commit d8584682f0
3 changed files with 59 additions and 92 deletions

View file

@ -33,19 +33,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 = Object::cast_to<PhysicsBody2D>(node_a);
PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
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) {
@ -83,9 +113,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;
}
@ -164,29 +192,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 = Object::cast_to<PhysicsBody2D>(node_a);
PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
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;
@ -241,24 +248,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 = Object::cast_to<PhysicsBody2D>(node_a);
PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
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) {
Transform2D gt = get_global_transform();
Vector2 groove_A1 = gt.get_origin();
@ -330,24 +320,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 = Object::cast_to<PhysicsBody2D>(node_a);
PhysicsBody2D *body_b = Object::cast_to<PhysicsBody2D>(node_b);
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) {
Transform2D gt = get_global_transform();
Vector2 anchor_A = gt.get_origin();

View file

@ -32,11 +32,14 @@
#include "node_2d.h"
class PhysicsBody2D;
class Joint2D : public Node2D {
GDCLASS(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:

View file

@ -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 = Object::cast_to<PhysicsBody>(node_a);
PhysicsBody *body_b = Object::cast_to<PhysicsBody>(node_b);
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;
}