From 52293831b26f34547acf100603c87296deba7a60 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 9 Mar 2008 21:51:38 +0000 Subject: [PATCH] BGE fix: game object to controller links consistancy maintained regardless of order of deletion AddObject actuator forces last created object to hang in memory even after object is removed from scene => bad link between object and physic controller that causes Blender to crash in case a python script tries to use it (bad programming anyway). This patch avoids the crash by maintaining consistent links at all time. --- .../Ketsji/KX_BulletPhysicsController.cpp | 14 +++++++++- source/gameengine/Ketsji/KX_GameObject.cpp | 14 +++++++++- source/gameengine/Ketsji/KX_Scene.cpp | 27 +++++++++++++------ source/gameengine/Ketsji/KX_Scene.h | 2 +- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index aa5d1f1cec1..aa7c75e9633 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -24,7 +24,18 @@ CcdPhysicsController(ci) KX_BulletPhysicsController::~KX_BulletPhysicsController () { - + // The game object has a direct link to + if (m_pObject) + { + // If we cheat in SetObject, we must also cheat here otherwise the + // object will still things it has a physical controller + // Note that it requires that m_pObject is reset in case the object is deleted + // before the controller (usual case, see KX_Scene::RemoveNodeDestructObjec) + // The non usual case is when the object is not deleted because its reference is hanging + // in a AddObject actuator but the node is deleted. This case is covered here. + KX_GameObject* gameobj = (KX_GameObject*) m_pObject->GetSGClientObject(); + gameobj->SetPhysicsController(NULL,false); + } } void KX_BulletPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) @@ -58,6 +69,7 @@ void KX_BulletPhysicsController::SetObject (SG_IObject* object) } + void KX_BulletPhysicsController::setMargin (float collisionMargin) { CcdPhysicsController::SetMargin(collisionMargin); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 67c82ee2082..bc608d26c50 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -105,7 +105,19 @@ KX_GameObject::~KX_GameObject() delete m_pClient_info; //if (m_pSGNode) // delete m_pSGNode; - + if (m_pSGNode) + { + // must go through controllers and make sure they will not use us anymore + // This is important for KX_BulletPhysicsControllers that unregister themselves + // from the object when they are deleted. + SGControllerList::iterator contit; + SGControllerList& controllers = m_pSGNode->GetSGControllerList(); + for (contit = controllers.begin();contit!=controllers.end();++contit) + { + (*contit)->ClearObject(); + } + m_pSGNode->SetSGClientObject(NULL); + } } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 633b57ef209..526f893df5a 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -410,8 +410,15 @@ void KX_Scene::EnableZBufferClearing(bool isclearingZbuffer) void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gameobj) { KX_GameObject* orgobj = (KX_GameObject*)gameobj; - NewRemoveObject(orgobj); - + if (NewRemoveObject(orgobj) != 0) + { + // object is not yet deleted (this can happen when it hangs in an add object actuator + // last object created reference. It's a bad situation, don't know how to fix it exactly + // The least I can do, is remove the reference to the node in the object as the node + // will in any case be deleted. This ensures that the object will not try to use the node + // when it is finally deleted (see KX_GameObject destructor) + orgobj->SetSGNode(NULL); + } if (node) delete node; } @@ -723,8 +730,9 @@ void KX_Scene::DelayedRemoveObject(class CValue* gameobj) -void KX_Scene::NewRemoveObject(class CValue* gameobj) +int KX_Scene::NewRemoveObject(class CValue* gameobj) { + int ret; KX_GameObject* newobj = (KX_GameObject*) gameobj; //todo: look at this @@ -768,16 +776,17 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj) } newobj->RemoveMeshes(); + ret = 1; if (m_objectlist->RemoveValue(newobj)) - newobj->Release(); + ret = newobj->Release(); if (m_tempObjectList->RemoveValue(newobj)) - newobj->Release(); + ret = newobj->Release(); if (m_parentlist->RemoveValue(newobj)) - newobj->Release(); + ret = newobj->Release(); if (m_inactivelist->RemoveValue(newobj)) - newobj->Release(); + ret = newobj->Release(); if (m_euthanasyobjects->RemoveValue(newobj)) - newobj->Release(); + ret = newobj->Release(); if (newobj == m_active_camera) { @@ -787,6 +796,8 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj) } if (m_sceneConverter) m_sceneConverter->UnregisterGameObject(newobj); + // return value will be 0 if the object is actually deleted (all reference gone) + return ret; } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 4c3b1d2e558..58120d49dc4 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -306,7 +306,7 @@ public: void DelayedReleaseObject(CValue* gameobj); - void NewRemoveObject(CValue* gameobj); + int NewRemoveObject(CValue* gameobj); void ReplaceMesh(CValue* gameobj, void* meshobj); void AddShape(class btCollisionShape* shape);