浏览代码

-Properly lock and and warn about switching off contact monitoring, fixes #3041

Juan Linietsky 9 年之前
父节点
当前提交
a625f7d073
共有 5 个文件被更改,包括 53 次插入6 次删除
  1. 4 4
      scene/2d/area_2d.cpp
  2. 23 0
      scene/2d/physics_body_2d.cpp
  3. 1 1
      scene/2d/physics_body_2d.h
  4. 24 0
      scene/3d/physics_body.cpp
  5. 1 1
      scene/3d/physics_body.h

+ 4 - 4
scene/2d/area_2d.cpp

@@ -420,13 +420,13 @@ void Area2D::_notification(int p_what) {
 
 void Area2D::set_enable_monitoring(bool p_enable) {
 
-	if (locked) {
-		ERR_EXPLAIN("This function can't be used during the in/out signal.");
-	}
-	ERR_FAIL_COND(locked);
 
 	if (p_enable==monitoring)
 		return;
+	if (locked) {
+		ERR_EXPLAIN("Function blocked during in/out signal. Use call_deferred(\"set_enable_monitoring\",true/false)");
+	}
+	ERR_FAIL_COND(locked);
 
 	monitoring=p_enable;
 

+ 23 - 0
scene/2d/physics_body_2d.cpp

@@ -310,14 +310,20 @@ void RigidBody2D::_body_enter_tree(ObjectID p_id) {
 	ERR_FAIL_COND(!E);
 	ERR_FAIL_COND(E->get().in_scene);
 
+	contact_monitor->locked=true;
+
 	E->get().in_scene=true;
 	emit_signal(SceneStringNames::get_singleton()->body_enter,node);
 
+
 	for(int i=0;i<E->get().shapes.size();i++) {
 
 		emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
 	}
 
+	contact_monitor->locked=false;
+
+
 }
 
 void RigidBody2D::_body_exit_tree(ObjectID p_id) {
@@ -329,11 +335,18 @@ void RigidBody2D::_body_exit_tree(ObjectID p_id) {
 	ERR_FAIL_COND(!E);
 	ERR_FAIL_COND(!E->get().in_scene);
 	E->get().in_scene=false;
+
+	contact_monitor->locked=true;
+
 	emit_signal(SceneStringNames::get_singleton()->body_exit,node);
+
 	for(int i=0;i<E->get().shapes.size();i++) {
 
 		emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
 	}
+
+	contact_monitor->locked=false;
+
 }
 
 void RigidBody2D::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape) {
@@ -439,6 +452,8 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
 
 	if (contact_monitor) {
 
+		contact_monitor->locked=true;
+
 		//untag all
 		int rc=0;
 		for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
@@ -520,6 +535,8 @@ void RigidBody2D::_direct_state_changed(Object *p_state) {
 			_body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape);
 		}
 
+		contact_monitor->locked=false;
+
 	}
 
 	set_block_transform_notify(true); // don't want notify (would feedback loop)
@@ -803,6 +820,11 @@ void RigidBody2D::set_contact_monitor(bool p_enabled) {
 
 	if (!p_enabled) {
 
+		if (contact_monitor->locked) {
+			ERR_EXPLAIN("Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\",false) instead");
+		}
+		ERR_FAIL_COND(contact_monitor->locked);
+
 		for(Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
 
 			//clean up mess
@@ -813,6 +835,7 @@ void RigidBody2D::set_contact_monitor(bool p_enabled) {
 	} else {
 
 		contact_monitor = memnew( ContactMonitor );
+		contact_monitor->locked=false;
 	}
 
 }

+ 1 - 1
scene/2d/physics_body_2d.h

@@ -190,7 +190,7 @@ private:
 
 	struct ContactMonitor {
 
-
+		bool locked;
 		Map<ObjectID,BodyState> body_map;
 
 	};

+ 24 - 0
scene/3d/physics_body.cpp

@@ -207,6 +207,9 @@ void RigidBody::_body_enter_tree(ObjectID p_id) {
 	ERR_FAIL_COND(E->get().in_tree);
 
 	E->get().in_tree=true;
+
+	contact_monitor->locked=true;
+
 	emit_signal(SceneStringNames::get_singleton()->body_enter,node);
 
 	for(int i=0;i<E->get().shapes.size();i++) {
@@ -214,6 +217,9 @@ void RigidBody::_body_enter_tree(ObjectID p_id) {
 		emit_signal(SceneStringNames::get_singleton()->body_enter_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
 	}
 
+	contact_monitor->locked=false;
+
+
 }
 
 void RigidBody::_body_exit_tree(ObjectID p_id) {
@@ -225,11 +231,18 @@ void RigidBody::_body_exit_tree(ObjectID p_id) {
 	ERR_FAIL_COND(!E);
 	ERR_FAIL_COND(!E->get().in_tree);
 	E->get().in_tree=false;
+
+	contact_monitor->locked=true;
+
 	emit_signal(SceneStringNames::get_singleton()->body_exit,node);
+
 	for(int i=0;i<E->get().shapes.size();i++) {
 
 		emit_signal(SceneStringNames::get_singleton()->body_exit_shape,p_id,node,E->get().shapes[i].body_shape,E->get().shapes[i].local_shape);
 	}
+
+	contact_monitor->locked=false;
+
 }
 
 void RigidBody::_body_inout(int p_status, ObjectID p_instance, int p_body_shape,int p_local_shape) {
@@ -317,6 +330,8 @@ void RigidBody::_direct_state_changed(Object *p_state) {
 
 	if (contact_monitor) {
 
+		contact_monitor->locked=true;
+
 		//untag all
 		int rc=0;
 		for( Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
@@ -396,6 +411,8 @@ void RigidBody::_direct_state_changed(Object *p_state) {
 			_body_inout(1,toadd[i].id,toadd[i].shape,toadd[i].local_shape);
 		}
 
+		contact_monitor->locked=false;
+
 	}
 
 	set_ignore_transform_notification(true);
@@ -648,6 +665,11 @@ void RigidBody::set_contact_monitor(bool p_enabled) {
 
 	if (!p_enabled) {
 
+		if (contact_monitor->locked) {
+			ERR_EXPLAIN("Can't disable contact monitoring during in/out callback. Use call_deferred(\"set_contact_monitor\",false) instead");
+		}
+		ERR_FAIL_COND(contact_monitor->locked);
+
 		for(Map<ObjectID,BodyState>::Element *E=contact_monitor->body_map.front();E;E=E->next()) {
 
 			//clean up mess
@@ -658,6 +680,8 @@ void RigidBody::set_contact_monitor(bool p_enabled) {
 	} else {
 
 		contact_monitor = memnew( ContactMonitor );
+		contact_monitor->locked=false;
+
 	}
 
 }

+ 1 - 1
scene/3d/physics_body.h

@@ -175,7 +175,7 @@ private:
 
 	struct ContactMonitor {
 
-
+		bool locked;
 		Map<ObjectID,BodyState> body_map;
 
 	};