From 7264716e8666b3a5d80f96f645226235e55c7b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Tue, 25 Jul 2017 04:26:47 +0200 Subject: [PATCH] Improve cleanup of physics constraints Don't abort the loop when one is already released Remove warning on already-released constraint Clean up area's contraints as well Clear the constraint data as well Do the cleanup as soon as the space changes --- servers/physics/area_sw.h | 1 + servers/physics/body_sw.h | 1 + servers/physics/physics_server_sw.cpp | 22 +++++++++++++------ servers/physics_2d/area_2d_sw.h | 1 + servers/physics_2d/body_2d_sw.h | 1 + servers/physics_2d/physics_2d_server_sw.cpp | 24 +++++++++++++++------ 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h index 06e58e3d5ab..3dae1db13fc 100644 --- a/servers/physics/area_sw.h +++ b/servers/physics/area_sw.h @@ -154,6 +154,7 @@ public: _FORCE_INLINE_ void add_constraint(ConstraintSW *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(ConstraintSW *p_constraint) { constraints.erase(p_constraint); } _FORCE_INLINE_ const Set &get_constraints() const { return constraints; } + _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); _FORCE_INLINE_ bool is_monitorable() const { return monitorable; } diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index c3e051c2d02..512b8685705 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -194,6 +194,7 @@ public: _FORCE_INLINE_ void add_constraint(ConstraintSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } _FORCE_INLINE_ void remove_constraint(ConstraintSW *p_constraint) { constraint_map.erase(p_constraint); } const Map &get_constraint_map() const { return constraint_map; } + _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); } _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } _FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; } diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 51d376cfa55..833c77216e3 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -232,6 +232,14 @@ void PhysicsServerSW::area_set_space(RID p_area, RID p_space) { if (area->get_space() == space) return; //pointless + for (Set::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); }; @@ -485,6 +493,14 @@ void PhysicsServerSW::body_set_space(RID p_body, RID p_space) { if (body->get_space() == space) return; //pointless + while (body->get_constraint_map().size()) { + RID self = body->get_constraint_map().front()->key()->get_self(); + if (!self.is_valid()) + continue; + free(self); + } + body->clear_constraint_map(); + body->set_space(space); }; @@ -1333,12 +1349,6 @@ void PhysicsServerSW::free(RID p_rid) { body->remove_shape(0); } - while (body->get_constraint_map().size()) { - RID self = body->get_constraint_map().front()->key()->get_self(); - ERR_FAIL_COND(!self.is_valid()); - free(self); - } - body_owner.free(p_rid); memdelete(body); diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 68b3c61e44e..6d74a4b0f6a 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -153,6 +153,7 @@ public: _FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint) { constraints.insert(p_constraint); } _FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint) { constraints.erase(p_constraint); } _FORCE_INLINE_ const Set &get_constraints() const { return constraints; } + _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); _FORCE_INLINE_ bool is_monitorable() const { return monitorable; } diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 9e5deef3f26..412f2f51cd8 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -181,6 +181,7 @@ public: _FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } _FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint) { constraint_map.erase(p_constraint); } const Map &get_constraint_map() const { return constraint_map; } + _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); } _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } _FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; } diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 98fe7da3ed4..add376bfb20 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -296,6 +296,14 @@ void Physics2DServerSW::area_set_space(RID p_area, RID p_space) { if (area->get_space() == space) return; //pointless + for (Set::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,6 +548,14 @@ void Physics2DServerSW::body_set_space(RID p_body, RID p_space) { if (body->get_space() == space) return; //pointless + while (body->get_constraint_map().size()) { + RID self = body->get_constraint_map().front()->key()->get_self(); + if (!self.is_valid()) + continue; + free(self); + } + body->clear_constraint_map(); + body->set_space(space); }; @@ -1080,19 +1096,13 @@ void Physics2DServerSW::free(RID p_rid) { _clear_query(body->get_direct_state_query()); */ - body->set_space(NULL); + body_set_space(p_rid, RID()); while (body->get_shape_count()) { body->remove_shape(0); } - while (body->get_constraint_map().size()) { - RID self = body->get_constraint_map().front()->key()->get_self(); - ERR_FAIL_COND(!self.is_valid()); - free(self); - } - body_owner.free(p_rid); memdelete(body);