Selaa lähdekoodia

physics: fix crash in edge case when PhysicalNode dies before Physical
Also add more assertion checks

rdb 8 vuotta sitten
vanhempi
sitoutus
257311cc0c

+ 7 - 6
panda/src/physics/physical.cxx

@@ -30,10 +30,10 @@ TypeHandle Physical::_type_handle;
  * the speed-vs-overhead deal.
  */
 Physical::
-Physical(int total_objects, bool pre_alloc) {
-  _viscosity=0.0;
-  _physical_node = (PhysicalNode *) NULL;
-  _physics_manager = (PhysicsManager *) NULL;
+Physical(int total_objects, bool pre_alloc) :
+  _viscosity(0.0),
+  _physics_manager(nullptr),
+  _physical_node(nullptr) {
 
   if (total_objects == 1) {
     _phys_body = new PhysicsObject;
@@ -55,8 +55,9 @@ Physical(int total_objects, bool pre_alloc) {
  * to its template's physicsmanager.
  */
 Physical::
-Physical(const Physical& copy) {
-  _physics_manager = (PhysicsManager *) NULL;
+Physical(const Physical& copy) :
+  _physics_manager(nullptr),
+  _physical_node(nullptr) {
 
   // copy the forces.
   LinearForceVector::const_iterator lf_cur;

+ 5 - 0
panda/src/physics/physicalNode.I

@@ -16,6 +16,11 @@
  */
 INLINE void PhysicalNode::
 clear() {
+  PhysicalsVector::iterator it;
+  for (it = _physicals.begin(); it != _physicals.end(); ++it) {
+    nassertd((*it)->_physical_node == this) continue;
+    (*it)->_physical_node = nullptr;
+  }
   _physicals.erase(_physicals.begin(), _physicals.end());
 }
 

+ 14 - 1
panda/src/physics/physicalNode.cxx

@@ -38,6 +38,15 @@ PhysicalNode(const PhysicalNode &copy) :
  */
 PhysicalNode::
 ~PhysicalNode() {
+  PhysicalsVector::iterator it;
+  for (it = _physicals.begin(); it != _physicals.end(); ++it) {
+    Physical *physical = *it;
+    nassertd(physical->_physical_node == this) continue;
+    physical->_physical_node = nullptr;
+    if (physical->_physics_manager != nullptr) {
+      physical->_physics_manager->remove_physical(physical);
+    }
+  }
 }
 
 /**
@@ -83,9 +92,13 @@ remove_physical(Physical *physical) {
   pvector< PT(Physical) >::iterator found;
   PT(Physical) ptp = physical;
   found = find(_physicals.begin(), _physicals.end(), ptp);
-  if (found == _physicals.end())
+  if (found == _physicals.end()) {
     return;
+  }
   _physicals.erase(found);
+
+  nassertv(ptp->_physical_node == this);
+  ptp->_physical_node = nullptr;
 }
 
 /**