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.
This commit is contained in:
Benoit Bolsee 2008-03-09 21:51:38 +00:00
parent 822e51bd2d
commit 52293831b2
4 changed files with 46 additions and 11 deletions

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

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

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

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