Kaynağa Gözat

Merge pull request #10769 from RandomShaper/fix-joints-2.1

Fix joints collision exceptions, plus a bit more (2.1)
Rémi Verschelde 7 yıl önce
ebeveyn
işleme
fb9e830b08

+ 40 - 67
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>() : (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);
+
+	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() {
-
-	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();
+RID PinJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
 
-	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>();
-	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());
+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>();
-	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());
+RID DampedSpringJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) {
 
 	Matrix32 gt = get_global_transform();
 	Vector2 anchor_A = gt.get_origin();

+ 8 - 5
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:

+ 11 - 20
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>() : (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;
 
 	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;
+
+	PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority);
 
-	if (body_b && joint.is_valid()) {
+	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;
 	}

+ 0 - 14
servers/physics/physics_server_sw.cpp

@@ -232,14 +232,7 @@ void PhysicsServerSW::area_set_space(RID p_area, RID p_space) {
 	if (area->get_space() == space)
 		return; //pointless
 
-	for (Set<ConstraintSW *>::Element *E = area->get_constraints().front(); E; E = E->next()) {
-		RID self = E->get()->get_self();
-		if (!self.is_valid())
-			continue;
-		free(self);
-	}
 	area->clear_constraints();
-
 	area->set_space(space);
 };
 
@@ -486,14 +479,7 @@ void PhysicsServerSW::body_set_space(RID p_body, RID p_space) {
 	if (body->get_space() == space)
 		return; //pointless
 
-	for (Map<ConstraintSW *, int>::Element *E = body->get_constraint_map().front(); E; E = E->next()) {
-		RID self = E->key()->get_self();
-		if (!self.is_valid())
-			continue;
-		free(self);
-	}
 	body->clear_constraint_map();
-
 	body->set_space(space);
 };
 

+ 0 - 14
servers/physics_2d/physics_2d_server_sw.cpp

@@ -296,14 +296,7 @@ void Physics2DServerSW::area_set_space(RID p_area, RID p_space) {
 	if (area->get_space() == space)
 		return; //pointless
 
-	for (Set<Constraint2DSW *>::Element *E = area->get_constraints().front(); E; E = E->next()) {
-		RID self = E->get()->get_self();
-		if (!self.is_valid())
-			continue;
-		free(self);
-	}
 	area->clear_constraints();
-
 	area->set_space(space);
 };
 
@@ -540,14 +533,7 @@ void Physics2DServerSW::body_set_space(RID p_body, RID p_space) {
 	if (body->get_space() == space)
 		return; //pointless
 
-	for (Map<Constraint2DSW *, int>::Element *E = body->get_constraint_map().front(); E; E = E->next()) {
-		RID self = E->key()->get_self();
-		if (!self.is_valid())
-			continue;
-		free(self);
-	}
 	body->clear_constraint_map();
-
 	body->set_space(space);
 };