diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index 464553b9821..50a115174d0 100644 --- a/scene/2d/area_2d.cpp +++ b/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; diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 71a45024c4e..cc2e5c0d724 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/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;iget().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;iget().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::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::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; } } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index fc337915c53..999e63dd5d1 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -190,7 +190,7 @@ private: struct ContactMonitor { - + bool locked; Map body_map; }; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index de777604b07..1a2665b6ad5 100644 --- a/scene/3d/physics_body.cpp +++ b/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;iget().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;iget().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::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::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; + } } diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index 0d6c358e286..da79d63f00e 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -175,7 +175,7 @@ private: struct ContactMonitor { - + bool locked; Map body_map; };