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

This commit is contained in:
Juan Linietsky 2016-01-12 06:14:15 -03:00
parent eab1e5b596
commit a625f7d073
5 changed files with 53 additions and 6 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

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

View File

@ -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;
}
}

View File

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