BGE fix: game object to controller links consistancy maintained regardless of order...
authorBenoit Bolsee <benoit.bolsee@online.be>
Sun, 9 Mar 2008 21:51:38 +0000 (21:51 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Sun, 9 Mar 2008 21:51:38 +0000 (21:51 +0000)
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.

source/gameengine/Ketsji/KX_BulletPhysicsController.cpp
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_Scene.h

index aa5d1f1cec1492c9b47238333d59c32bd4fce32a..aa7c75e96337a6c76f75194d5da3ebe75c9ebee4 100644 (file)
@@ -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);
index 67c82ee208269b8b49bbc3528a1fd7c7e05a7d0b..bc608d26c50a623ee9cdfcbfb1e2e831187610c7 100644 (file)
@@ -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);
+       }
 }
 
 
index 633b57ef2099c5f5bd390bcd2bc976afd57d533d..526f893df5a9a82486674c9636fc643ecfaccf72 100644 (file)
@@ -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;
 }
 
 
index 4c3b1d2e55895f7adefc925d02993860ba759faa..58120d49dc4fd128f9cf82c4efe85c5952dbd09f 100644 (file)
@@ -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);