Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Bolsee <benoit.bolsee@online.be>2008-03-01 22:46:50 +0300
committerBenoit Bolsee <benoit.bolsee@online.be>2008-03-01 22:46:50 +0300
commit0db0f5734d358676b11eccc702cf02adb3174b7e (patch)
treedbed0e86663eeabe8d333892958310878bfbe533 /source/gameengine
parent44314581dc934dc99c9504edf671118a9f988b68 (diff)
Various mem leaks related to CValue reference count fixed
Diffstat (limited to 'source/gameengine')
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp29
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp2
-rw-r--r--source/gameengine/Converter/KX_ConvertControllers.cpp2
-rw-r--r--source/gameengine/Converter/KX_ConvertProperties.cpp7
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp2
-rw-r--r--source/gameengine/Expressions/Expression.cpp4
-rw-r--r--source/gameengine/Expressions/Value.cpp86
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.cpp3
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp3
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.cpp9
-rw-r--r--source/gameengine/GameLogic/SCA_PropertyActuator.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp20
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp75
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h13
17 files changed, 224 insertions, 49 deletions
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index fde54025fc7..271385bb144 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -1514,7 +1514,8 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
default:
break;
}
-
+ delete shapeprops;
+ delete smmaterial;
}
@@ -1599,7 +1600,8 @@ static KX_GameObject *gameobject_from_blenderobject(
KX_Camera* gamecamera = gamecamera_from_bcamera(static_cast<Camera*>(ob->data), kxscene, converter);
gameobj = gamecamera;
- gamecamera->AddRef();
+ //don't add a reference: the camera list in kxscene->m_cameras is not released at the end
+ //gamecamera->AddRef();
kxscene->AddCamera(gamecamera);
break;
@@ -1845,6 +1847,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
vector<parentChildLink> vec_parent_child;
CListValue* objectlist = kxscene->GetObjectList();
+ CListValue* inactivelist = kxscene->GetInactiveList();
CListValue* parentlist = kxscene->GetRootParentList();
SCA_LogicManager* logicmgr = kxscene->GetLogicManager();
@@ -1852,7 +1855,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
CListValue* logicbrick_conversionlist = new CListValue();
- SG_TreeFactory tf;
+ //SG_TreeFactory tf;
// Convert actions to actionmap
bAction *curAct;
@@ -1990,19 +1993,35 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
if (isInActiveLayer)
{
objectlist->Add(gameobj->AddRef());
- tf.Add(gameobj->GetSGNode());
+ //tf.Add(gameobj->GetSGNode());
gameobj->NodeUpdateGS(0,true);
gameobj->Bucketize();
}
+ else
+ {
+ //we must store this object otherwise it will be deleted
+ //at the end of this function if it is not a root object
+ inactivelist->Add(gameobj->AddRef());
+ }
if (converter->addInitFromFrame){
gameobj->NodeSetLocalPosition(posPrev);
gameobj->NodeSetLocalOrientation(angor);
}
}
-
+ /* Note about memory leak issues:
+ When a CValue derived class is created, m_refcount is initialized to 1
+ so the class must be released after being used to make sure that it won't
+ hang in memory. If the object needs to be stored for a long time,
+ use AddRef() so that this Release() does not free the object.
+ Make sure that for any AddRef() there is a Release()!!!!
+ Do the same for any object derived from CValue, CExpression and NG_NetworkMessage
+ */
+ if (gameobj)
+ gameobj->Release();
+
base = base->next;
}
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 89a07abe21d..f76a0fb82e5 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -934,6 +934,8 @@ void BL_ConvertActuators(char* maggiename,
gameobj->AddActuator(baseact);
converter->RegisterGameActuator(baseact, bact);
+ // done with baseact, release it
+ baseact->Release();
}
bact = bact->next;
diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp
index 5b30f5a4a2e..b277af7dbc2 100644
--- a/source/gameengine/Converter/KX_ConvertControllers.cpp
+++ b/source/gameengine/Converter/KX_ConvertControllers.cpp
@@ -174,6 +174,8 @@ void BL_ConvertControllers(
gameobj->AddController(gamecontroller);
converter->RegisterGameController(gamecontroller, bcontr);
+ //done with gamecontroller
+ gamecontroller->Release();
}
bcontr = bcontr->next;
diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp
index a1807732416..ebfb45066b7 100644
--- a/source/gameengine/Converter/KX_ConvertProperties.cpp
+++ b/source/gameengine/Converter/KX_ConvertProperties.cpp
@@ -105,8 +105,9 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan
// set a subproperty called 'timer' so that
// we can register the replica of this property
// at the time a game object is replicated (AddObjectActuator triggers this)
-
- timeval->SetProperty("timer",new CBoolValue(true));
+ CValue *bval = new CBoolValue(true);
+ timeval->SetProperty("timer",bval);
+ bval->Release();
if (isInActiveLayer)
{
timemgr->AddTimeProperty(timeval);
@@ -128,6 +129,8 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan
{
scene->AddDebugProperty(gameobj,STR_String(prop->name));
}
+ // done with propval, release it
+ propval->Release();
}
prop = prop->next;
diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp
index d9c49217042..61759ddf654 100644
--- a/source/gameengine/Converter/KX_ConvertSensors.cpp
+++ b/source/gameengine/Converter/KX_ConvertSensors.cpp
@@ -733,6 +733,8 @@ void BL_ConvertSensors(struct Object* blenderobject,
logicmgr->RegisterToSensor(gamecont,gamesensor);
}
}
+ // done with gamesensor
+ gamesensor->Release();
}
sens=sens->next;
diff --git a/source/gameengine/Expressions/Expression.cpp b/source/gameengine/Expressions/Expression.cpp
index 5c5e1abea34..f16f572c322 100644
--- a/source/gameengine/Expressions/Expression.cpp
+++ b/source/gameengine/Expressions/Expression.cpp
@@ -22,7 +22,9 @@
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
-
+#ifdef _DEBUG
+//int gRefCountExpr;
+#endif
CExpression::CExpression()// : m_cached_calculate(NULL)
{
m_refcount = 1;
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index 48898dfc1f5..56208ab4ad5 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -169,7 +169,28 @@ PyObject* CValue::PyGetName(PyObject* self,PyObject* args,PyObject* kwds)
return pyname;
}
+/*#define CVALUE_DEBUG*/
+#ifdef CVALUE_DEBUG
+int gRefCount;
+struct SmartCValueRef
+{
+ CValue *m_ref;
+ int m_count;
+ SmartCValueRef(CValue *ref)
+ {
+ m_ref = ref;
+ m_count = gRefCount++;
+ }
+};
+#include <vector>
+
+std::vector<SmartCValueRef> gRefList;
+#endif
+
+#ifdef _DEBUG
+//int gRefCountValue;
+#endif
CValue::CValue(PyTypeObject *T)
: PyObjectPlus(T),
@@ -186,6 +207,12 @@ effect: constucts a CValue
*/
{
//debug(gRefCountValue++) // debugging
+#ifdef _DEBUG
+ //gRefCountValue++;
+#ifdef CVALUE_DEBUG
+ gRefList.push_back(SmartCValueRef(this));
+#endif
+#endif
}
@@ -199,6 +226,18 @@ effect: deletes the object
ClearProperties();
assertd (m_refcount==0);
+#ifdef CVALUE_DEBUG
+ std::vector<SmartCValueRef>::iterator it;
+ for (it=gRefList.begin(); it!=gRefList.end(); it++)
+ {
+ if (it->m_ref == this)
+ {
+ *it = gRefList.back();
+ gRefList.pop_back();
+ break;
+ }
+ }
+#endif
}
@@ -293,7 +332,7 @@ void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
}
// Add property at end of array
- (*m_pNamedPropertyArray)[name] = ioProperty;//->Add(ioProperty);
+ (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
}
@@ -356,10 +395,13 @@ bool CValue::RemoveProperty(const STR_String & inName)
if (m_pNamedPropertyArray == NULL)
return false;
- // Scan all properties, as soon as we find one with <inName> -> Remove it
-// CValue* val = (*m_pNamedPropertyArray)[inName];
- if (m_pNamedPropertyArray->erase(inName)) return true;
-
+ CValue* val = GetProperty(inName);
+ if (NULL != val)
+ {
+ val->Release();
+ m_pNamedPropertyArray->erase(inName);
+ return true;
+ }
return false;
}
@@ -379,7 +421,7 @@ void CValue::ClearProperties()
!(it == m_pNamedPropertyArray->end());it++)
{
CValue* tmpval = (*it).second;
- STR_String name = (*it).first;
+ //STR_String name = (*it).first;
tmpval->Release();
}
@@ -469,8 +511,9 @@ void CValue::CloneProperties(CValue *replica)
for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
!(it == m_pNamedPropertyArray->end());it++)
{
-
- replica->SetProperty((*it).first,(*it).second->GetReplica());
+ CValue *val = (*it).second->GetReplica();
+ replica->SetProperty((*it).first,val);
+ val->Release();
}
}
@@ -489,10 +532,6 @@ double* CValue::GetVector3(bool bGetTransformedVec)
}
-
-
-
-
/*---------------------------------------------------------------------------------------------------------------------
Reference Counting
---------------------------------------------------------------------------------------------------------------------*/
@@ -504,6 +543,9 @@ CValue *CValue::AddRef()
// Increase global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
//debug(gRefCountValue++);
+#ifdef _DEBUG
+ //gRefCountValue++;
+#endif
m_refcount++;
return this;
}
@@ -518,7 +560,9 @@ int CValue::Release()
// Decrease global reference count, used to see at the end of the program
// if all CValue-derived classes have been dereferenced to 0
//debug(gRefCountValue--);
-
+#ifdef _DEBUG
+ //gRefCountValue--;
+#endif
// Decrease local reference count, if it reaches 0 the object should be freed
if (--m_refcount > 0)
{
@@ -546,6 +590,9 @@ void CValue::DisableRefCount()
m_refcount--;
//debug(gRefCountValue--);
+#ifdef _DEBUG
+ //gRefCountValue--;
+#endif
m_ValFlags.RefCountDisabled=true;
}
@@ -590,11 +637,14 @@ CValue* CValue::FindIdentifier(const STR_String& identifiername)
} else
{
result = GetProperty(identifiername);
+ if (result)
+ return result->AddRef();
+ }
+ if (!result)
+ {
+ // warning here !!!
+ result = new CErrorValue(identifiername+" not found");
}
- if (result)
- return result->AddRef();
- // warning here !!!
- result = new CErrorValue(identifiername+" not found");
return result;
}
@@ -717,7 +767,7 @@ int CValue::_setattr(const STR_String& attr,PyObject* pyobj)
oldprop->SetValue(vallie);
} else
{
- SetProperty(attr,vallie->AddRef());
+ SetProperty(attr,vallie);
}
vallie->Release();
}
diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp
index 8971135ecda..fae1b5dfa6b 100644
--- a/source/gameengine/GameLogic/SCA_IObject.cpp
+++ b/source/gameengine/GameLogic/SCA_IObject.cpp
@@ -101,6 +101,7 @@ SCA_ActuatorList& SCA_IObject::GetActuators()
void SCA_IObject::AddSensor(SCA_ISensor* act)
{
+ act->AddRef();
m_sensors.push_back(act);
}
@@ -108,6 +109,7 @@ void SCA_IObject::AddSensor(SCA_ISensor* act)
void SCA_IObject::AddController(SCA_IController* act)
{
+ act->AddRef();
m_controllers.push_back(act);
}
@@ -115,6 +117,7 @@ void SCA_IObject::AddController(SCA_IController* act)
void SCA_IObject::AddActuator(SCA_IActuator* act)
{
+ act->AddRef();
m_actuators.push_back(act);
}
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index fb8c340b09e..4898dbed95f 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -212,6 +212,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
newprop.SetLength(oldlength - 1);
CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
GetParent()->SetProperty(m_targetprop, newstringprop);
+ newstringprop->Release();
}
} else {
/* append */
@@ -219,6 +220,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
STR_String newprop = tprop->GetText() + pchar;
CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
GetParent()->SetProperty(m_targetprop, newstringprop);
+ newstringprop->Release();
}
} else {
if (!IsDelete(keyIndex)) {
@@ -227,6 +229,7 @@ void SCA_KeyboardSensor::AddToTargetProp(int keyIndex)
STR_String newprop = pchar;
CStringValue * newstringprop = new CStringValue(newprop, m_targetprop);
GetParent()->SetProperty(m_targetprop, newstringprop);
+ newstringprop->Release();
}
}
}
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp
index 8b79703a6fc..048d6992c73 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.cpp
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -51,6 +51,10 @@ SCA_LogicManager::SCA_LogicManager()
SCA_LogicManager::~SCA_LogicManager()
{
+ /* AddRef() is not used when the objects are added to m_mapStringToGameObjects
+ so Release() should not be used either. The memory leak big is fixed
+ in BL_ConvertBlenderObjects()
+
int numgameobj = m_mapStringToGameObjects.size();
for (int i = 0; i < numgameobj; i++)
{
@@ -58,8 +62,9 @@ SCA_LogicManager::~SCA_LogicManager()
assert(gameobjptr);
if (gameobjptr)
(*gameobjptr)->Release();
-
+
}
+ */
/*for (int i=0;i<m_sensorcontrollermap.size();i++)
{
vector<SCA_IController*>* controllerarray = *(m_sensorcontrollermap[i]);
@@ -72,6 +77,8 @@ SCA_LogicManager::~SCA_LogicManager()
}
m_eventmanagers.clear();
m_sensorcontrollermapje.clear();
+ m_removedActuators.clear();
+ m_activeActuators.clear();
}
diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
index c3e2066fc65..c798503ae8a 100644
--- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
+++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
@@ -90,12 +90,11 @@ bool SCA_PropertyActuator::Update()
if (oldprop)
{
oldprop->SetValue(newval);
- newval->Release();
} else
{
propowner->SetProperty(m_propname,newval);
}
-
+ newval->Release();
break;
}
case KX_ACT_PROP_ADD:
@@ -123,9 +122,11 @@ bool SCA_PropertyActuator::Update()
CValue* copyprop = m_sourceObj->GetProperty(m_exprtxt);
if (copyprop)
{
+ CValue *val = copyprop->GetReplica();
GetParent()->SetProperty(
m_propname,
- copyprop->GetReplica());
+ val);
+ val->Release();
}
}
@@ -239,11 +240,12 @@ PyObject* SCA_PropertyActuator::PySetProperty(PyObject* self, PyObject* args, Py
CValue* prop = GetParent()->FindIdentifier(nameArg);
- if (prop) {
+ if (!prop->IsError()) {
m_propname = nameArg;
} else {
; /* not found ... */
}
+ prop->Release();
Py_Return;
}
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index bb8ea7f23b3..b75662f01c9 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -58,7 +58,9 @@ KX_Camera::KX_Camera(void* sgReplicationInfo,
m_name = "cam";
m_projection_matrix.setIdentity();
m_modelview_matrix.setIdentity();
- SetProperty("camera",new CIntValue(1));
+ CValue* val = new CIntValue(1);
+ SetProperty("camera",val);
+ val->Release();
}
diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
index 5de2ab1b2dc..7b2c514db8a 100644
--- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
+++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp
@@ -858,6 +858,8 @@ static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool
//concaveShape = new btTriangleMeshShape( collisionMeshData );
concaveShape->recalcLocalAabb();
+ if (collisionMeshShape)
+ delete collisionMeshShape;
collisionMeshShape = concaveShape;
}
@@ -866,8 +868,10 @@ static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool
return collisionMeshShape;
}
-
- delete collisionMeshShape;
+ if (collisionMeshShape)
+ delete collisionMeshShape;
+ if (collisionMeshData)
+ delete collisionMeshData;
return NULL;
}
@@ -1021,7 +1025,10 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
// ci.m_localInertiaTensor.setValue(0.1f,0.1f,0.1f);
if (!bm)
+ {
+ delete motionstate;
return;
+ }
bm->setMargin(0.06);
@@ -1057,6 +1064,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
compoundShape->addChildShape(childTrans,bm);
+ kxscene->AddShape(bm);
//do some recalc?
//recalc inertia for rigidbody
if (!rigidbody->isStaticOrKinematicObject())
@@ -1076,6 +1084,9 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
btTransform identTrans;
identTrans.setIdentity();
compoundShape->addChildShape(identTrans,bm);
+ //note abount compoundShape: Bullet does not delete the child shapes when
+ //the compound shape is deleted, so insert also the child shapes
+ kxscene->AddShape(bm);
bm = compoundShape;
}
@@ -1112,9 +1123,6 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_collisionShape = bm;
-
-
-
ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice
ci.m_restitution = smmaterial->m_restitution;
ci.m_physicsEnv = env;
@@ -1127,6 +1135,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna);
+ //remember that we created a shape so that we can delete it when the scene is removed (bullet will not delete it)
+ kxscene->AddShape(bm);
if (objprop->m_in_active_layer)
{
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
index 8febc0e10cd..9e5efad803b 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -1047,6 +1047,8 @@ void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
scene->SetActiveCamera(activecam);
scene->GetObjectList()->Add(activecam->AddRef());
scene->GetRootParentList()->Add(activecam->AddRef());
+ //done with activecam
+ activecam->Release();
}
scene->UpdateParents(0.0);
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index 45b2db10b33..7366e374a10 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -326,6 +326,8 @@ void KX_SCA_AddObjectActuator::InstantAddObject()
m_lastCreatedObject = replica;
m_lastCreatedObject->AddRef();
+ // finished using replica? then release it
+ replica->Release();
}
}
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index f9c2f8e571b..f9fc503f406 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -35,6 +35,7 @@
#pragma warning (disable : 4786)
#endif //WIN32
+
#include "KX_Scene.h"
#include "MT_assert.h"
@@ -78,6 +79,13 @@
#include "BL_SkinDeformer.h"
#include "BL_DeformableGameObject.h"
+// to get USE_BULLET!
+#include "KX_ConvertPhysicsObject.h"
+
+#ifdef USE_BULLET
+#include "CcdPhysicsEnvironment.h"
+#include "CcdPhysicsController.h"
+#endif
void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene)
{
@@ -124,6 +132,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_objectlist = new CListValue();
m_parentlist = new CListValue();
m_lightlist= new CListValue();
+ m_inactivelist = new CListValue();
m_euthanasyobjects = new CListValue();
m_delayReleaseObjects = new CListValue();
@@ -183,6 +192,9 @@ KX_Scene::~KX_Scene()
if (m_parentlist)
m_parentlist->Release();
+ if (m_inactivelist)
+ m_inactivelist->Release();
+
if (m_lightlist)
m_lightlist->Release();
@@ -210,11 +222,38 @@ KX_Scene::~KX_Scene()
{
delete m_bucketmanager;
}
-
+#ifdef USE_BULLET
+ // This is a fix for memory leaks in bullet: the collision shapes is not destroyed
+ // when the physical controllers are destroyed. The reason is that shapes are shared
+ // between replicas of an object. There is no reference count in Bullet so the
+ // only workaround that does not involve changes in Bullet is to save in this array
+ // the list of shapes that are created when the scene is created (see KX_ConvertPhysicsObjects.cpp)
+ class btCollisionShape* shape;
+ class btTriangleMeshShape* meshShape;
+ vector<class btCollisionShape*>::iterator it = m_shapes.begin();
+ while (it != m_shapes.end()) {
+ shape = *it;
+ if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+ {
+ meshShape = static_cast<btTriangleMeshShape*>(shape);
+ // shapes based on meshes use an interface that contains the vertices.
+ // Again the idea is to be able to share the interface between shapes but
+ // this is not used in Blender: each base object will have its own interface
+ btStridingMeshInterface* meshInterface = meshShape->getMeshInterface();
+ if (meshInterface)
+ delete meshInterface;
+ }
+ delete shape;
+ it++;
+ }
+#endif
//Py_DECREF(m_attrlist);
}
-
+void KX_Scene::AddShape(class btCollisionShape*shape)
+{
+ m_shapes.push_back(shape);
+}
void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat)
@@ -243,6 +282,11 @@ CListValue* KX_Scene::GetRootParentList()
return m_parentlist;
}
+CListValue* KX_Scene::GetInactiveList()
+{
+ return m_inactivelist;
+}
+
CListValue* KX_Scene::GetLightList()
@@ -415,7 +459,7 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
replicanode->SetSGClientObject(newobj);
// this is the list of object that are send to the graphics pipeline
- m_objectlist->Add(newobj);
+ m_objectlist->Add(newobj->AddRef());
newobj->Bucketize();
// logic cannot be replicated, until the whole hierarchy is replicated.
@@ -571,7 +615,9 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
// add a timebomb to this object
// for now, convert between so called frames and realtime
m_tempObjectList->Add(replica->AddRef());
- replica->SetProperty("::timebomb",new CFloatValue(lifespan*0.02));
+ CValue *fval = new CFloatValue(lifespan*0.02);
+ replica->SetProperty("::timebomb",fval);
+ fval->Release();
}
// add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame)
@@ -634,7 +680,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
replica->GetSGNode()->UpdateWorldData(0);
replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox());
replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius());
-
+ // don't release replica here because we are returning it, not done with it...
return replica;
}
@@ -654,7 +700,8 @@ void KX_Scene::RemoveObject(class CValue* gameobj)
// recursively destruct
node->Destruct();
}
- newobj->SetSGNode(0);
+ //no need to do that: the object is destroyed and memory released
+ //newobj->SetSGNode(0);
}
void KX_Scene::DelayedReleaseObject(CValue* gameobj)
@@ -704,6 +751,7 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj)
{
m_logicmgr->RemoveDestroyedActuator(*ita);
}
+ // the sensors/controllers/actuators must also be released, this is done in ~SCA_IObject
// now remove the timer properties from the time manager
int numprops = newobj->GetPropertyCount();
@@ -724,12 +772,15 @@ void KX_Scene::NewRemoveObject(class CValue* gameobj)
newobj->Release();
if (m_parentlist->RemoveValue(newobj))
newobj->Release();
+ if (m_inactivelist->RemoveValue(newobj))
+ newobj->Release();
if (m_euthanasyobjects->RemoveValue(newobj))
newobj->Release();
if (newobj == m_active_camera)
{
- m_active_camera->Release();
+ //no AddRef done on m_active_camera so no Release
+ //m_active_camera->Release();
m_active_camera = NULL;
}
}
@@ -1108,6 +1159,8 @@ void KX_Scene::LogicEndFrame()
for (i = numobj - 1; i >= 0; i--)
{
KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i);
+ // KX_Scene::RemoveObject will also remove the object from this list
+ // that's why we start from the end
this->RemoveObject(gameobj);
}
@@ -1115,11 +1168,11 @@ void KX_Scene::LogicEndFrame()
for (i = numobj-1;i>=0;i--)
{
KX_GameObject* gameobj = (KX_GameObject*)m_delayReleaseObjects->GetValue(i);
- m_delayReleaseObjects->RemoveValue(gameobj);
-
+ // This list is not for object removal, but just object release
+ gameobj->Release();
}
-
-
+ // empty the list as we have removed all references
+ m_delayReleaseObjects->Resize(0);
}
diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h
index 50fcf1a3c40..b857f4f591e 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -85,6 +85,7 @@ class RAS_IPolyMaterial;
class RAS_IRasterizer;
class RAS_IRenderTools;
class SCA_JoystickManager;
+class btCollisionShape;
/**
* The KX_Scene holds all data for an independent scene. It relates
* KX_Objects to the specific objects in the modules.
@@ -111,6 +112,7 @@ protected:
CListValue* m_objectlist;
CListValue* m_parentlist; // all 'root' parents
CListValue* m_lightlist;
+ CListValue* m_inactivelist; // all objects that are not in the active layer
/**
* The tree of objects in the scene.
@@ -121,7 +123,11 @@ protected:
* The set of cameras for this scene
*/
list<class KX_Camera*> m_cameras;
-
+ /**
+ * The set of bullet shapes that must be deleted at the end of the scene
+ * to avoid memory leak (not deleted by bullet because shape are shared between replicas)
+ */
+ vector<class btCollisionShape*> m_shapes;
/**
* Various SCA managers used by the scene
*/
@@ -300,6 +306,7 @@ public:
void NewRemoveObject(CValue* gameobj);
void ReplaceMesh(CValue* gameobj,
void* meshobj);
+ void AddShape(class btCollisionShape* shape);
/**
* @section Logic stuff
* Initiate an update of the logic system.
@@ -316,6 +323,10 @@ public:
);
CListValue*
+ GetInactiveList(
+ );
+
+ CListValue*
GetRootParentList(
);