BGE patch: Relink actuators with target within group when duplicating group; generali...
authorBenoit Bolsee <benoit.bolsee@online.be>
Sat, 19 Jul 2008 07:45:19 +0000 (07:45 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Sat, 19 Jul 2008 07:45:19 +0000 (07:45 +0000)
Certain actuators hold a pointer to an objects: Property,
SceneCamera, AddObject, Camera, Parent, TractTo. When a
group is duplicated, the actuators that point to objects
within the group will be relinked to point to the
replicated objects and not to the original objects.
This helps to setup self-contained group with a camera
following a character for example.
This feature also works when adding a single object
(and all its children) with the AddObject actuator.

The second part of the patch extends the protection
against object deletion to all the actuators of the above
list (previously, only the TrackTo, AddObject and
Property actuators were protected). In case the target
object of these actuators is deleted, the BGE won't
crash.

18 files changed:
source/gameengine/Converter/BL_DeformableGameObject.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/GameLogic/SCA_ILogicBrick.cpp
source/gameengine/GameLogic/SCA_ILogicBrick.h
source/gameengine/GameLogic/SCA_PropertyActuator.cpp
source/gameengine/GameLogic/SCA_PropertyActuator.h
source/gameengine/Ketsji/KX_CameraActuator.cpp
source/gameengine/Ketsji/KX_CameraActuator.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_ParentActuator.cpp
source/gameengine/Ketsji/KX_ParentActuator.h
source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_SceneActuator.cpp
source/gameengine/Ketsji/KX_SceneActuator.h
source/gameengine/Ketsji/KX_TrackToActuator.cpp
source/gameengine/Ketsji/KX_TrackToActuator.h

index 57a404ad72b64ac6906173c325f8087c3c4f36af..315ad18c42c95ae4c4a3a49ebfb0cdecee04efcd 100644 (file)
@@ -60,6 +60,7 @@ public:
        {
                if (m_pDeformer)
                        m_pDeformer->Relink (map);
+               KX_GameObject::Relink(map);
        };
        void ProcessReplica(KX_GameObject* replica);
 
index 1cc1b2e27a39af20c7f7eb80ad8c15e775716185..8739fb109fd6e57a8fe4a6386dcaa2075595f685 100644 (file)
@@ -503,7 +503,7 @@ void BL_ConvertActuators(char* maggiename,
                case ACT_PROPERTY:
                        {
                                bPropertyActuator* propact = (bPropertyActuator*) bact->data;
-                               CValue* destinationObj = NULL;
+                               SCA_IObject* destinationObj = NULL;
                                
                                /*
                                here the destinationobject is searched. problem with multiple scenes: other scenes
index f6efd485adbd00eae134eced2c5aad673c95df22..e73358bc1e89546aa1f68b859348b6eca9973731 100644 (file)
@@ -82,7 +82,10 @@ void SCA_ILogicBrick::ReParent(SCA_IObject* parent)
        m_gameobj = parent;
 }
 
-
+void SCA_ILogicBrick::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       // nothing to do
+}
 
 CValue* SCA_ILogicBrick::Calc(VALUE_OPERATOR op, CValue *val)
 {
index 80bc6ae3b8637af1196a07e4a1dd17b8d426f003..c28711ac0f6b590410f7ebeb0acaec56e004c09f 100644 (file)
@@ -32,6 +32,8 @@
 #include "Value.h"
 #include "SCA_IObject.h"
 #include "BoolValue.h"
+#include "GEN_Map.h"
+#include "GEN_HashedPtr.h"
 
 class SCA_ILogicBrick : public CValue
 {
@@ -59,6 +61,7 @@ public:
 
        SCA_IObject*    GetParent();
        virtual void    ReParent(SCA_IObject* parent);
+       virtual void    Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
 
        // act as a BoolValue (with value IsPositiveTrigger)
        virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
index ebe1cd518638b6d5c3727e0ac606842de234ee6b..7062f2cef6a04c150c4746c23620b31b70fa9345 100644 (file)
@@ -42,7 +42,7 @@
 /* Native functions                                                          */
 /* ------------------------------------------------------------------------- */
 
-SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,CValue* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T )
+SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T )
    :   SCA_IActuator(gameobj,T),
        m_type(acttype),
        m_propname(propname),
@@ -51,14 +51,14 @@ SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,CValue* sourceOb
 {
        // protect ourselves against someone else deleting the source object
        // don't protect against ourselves: it would create a dead lock
-       if (m_sourceObj && m_sourceObj != GetParent())
-               m_sourceObj->AddRef();
+       if (m_sourceObj)
+               m_sourceObj->RegisterActuator(this);
 }
 
 SCA_PropertyActuator::~SCA_PropertyActuator()
 {
-       if (m_sourceObj && m_sourceObj != GetParent())
-               m_sourceObj->Release();
+       if (m_sourceObj)
+               m_sourceObj->UnregisterActuator(this);
 }
 
 bool SCA_PropertyActuator::Update()
@@ -185,10 +185,31 @@ void SCA_PropertyActuator::ProcessReplica()
        // no need to check for self reference like in the constructor:
        // the replica will always have a different parent
        if (m_sourceObj)
-               m_sourceObj->AddRef();
+               m_sourceObj->RegisterActuator(this);
        SCA_IActuator::ProcessReplica();
 }
 
+bool SCA_PropertyActuator::UnlinkObject(SCA_IObject* clientobj)
+{
+       if (clientobj == m_sourceObj)
+       {
+               // this object is being deleted, we cannot continue to track it.
+               m_sourceObj = NULL;
+               return true;
+       }
+       return false;
+}
+
+void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       void **h_obj = (*obj_map)[m_sourceObj];
+       if (h_obj) {
+               if (m_sourceObj)
+                       m_sourceObj->UnregisterActuator(this);
+               m_sourceObj = (SCA_IObject*)(*h_obj);
+               m_sourceObj->RegisterActuator(this);
+       }
+}
 
 
 /* ------------------------------------------------------------------------- */
index f8305901c51f48166fe6587fd7cd7c2c1c6a5660..1e435684572e8a634da0381b503859514d796618 100644 (file)
@@ -52,7 +52,7 @@ class SCA_PropertyActuator : public SCA_IActuator
        int                     m_type;
        STR_String      m_propname;
        STR_String      m_exprtxt;
-       CValue*         m_sourceObj; // for copy property actuator
+       SCA_IObject* m_sourceObj; // for copy property actuator
 
 public:
 
@@ -60,7 +60,7 @@ public:
 
        SCA_PropertyActuator(
                SCA_IObject* gameobj,
-               CValue* sourceObj,
+               SCA_IObject* sourceObj,
                const STR_String& propname,
                const STR_String& expr,
                int acttype,
@@ -74,7 +74,9 @@ public:
        GetReplica(
        );
 
-       void ProcessReplica();
+       virtual void ProcessReplica();
+       virtual bool UnlinkObject(SCA_IObject* clientobj);
+       virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
 
        virtual bool 
        Update();
index 27f4870de108ab7d2d79a5c2500cf000e33dab45..0a97b6f0a2fad4a07ce4721cb5184ed2dcf50b2d 100644 (file)
@@ -49,7 +49,7 @@ STR_String KX_CameraActuator::Y_AXIS_STRING = "y";
 
 KX_CameraActuator::KX_CameraActuator(
        SCA_IObject* gameobj, 
-       CValue *obj,
+       SCA_IObject *obj,
        MT_Scalar hght,
        MT_Scalar minhght,
        MT_Scalar maxhght,
@@ -63,11 +63,14 @@ KX_CameraActuator::KX_CameraActuator(
        m_maxHeight (maxhght),
        m_x (xytog)
 {
+       if (m_ob)
+               m_ob->RegisterActuator(this);
 }
 
 KX_CameraActuator::~KX_CameraActuator()
 {
-       //nothing to do
+       if (m_ob)
+               m_ob->UnregisterActuator(this);
 }
 
        CValue* 
@@ -81,9 +84,36 @@ GetReplica(
        return replica;
 };
 
+void KX_CameraActuator::ProcessReplica()
+{
+       if (m_ob)
+               m_ob->RegisterActuator(this);
+       SCA_IActuator::ProcessReplica();
+}
 
+bool KX_CameraActuator::UnlinkObject(SCA_IObject* clientobj)
+{
+       if (clientobj == m_ob)
+       {
+               // this object is being deleted, we cannot continue to track it.
+               m_ob = NULL;
+               return true;
+       }
+       return false;
+}
 
 
+void KX_CameraActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       void **h_obj = (*obj_map)[m_ob];
+       if (h_obj) {
+               if (m_ob)
+                       m_ob->UnregisterActuator(this);
+               m_ob = (SCA_IObject*)(*h_obj);
+               m_ob->RegisterActuator(this);
+       }
+}
+
 /* three functions copied from blender arith... don't know if there's an equivalent */
 
 static float Kx_Normalize(float *n)
@@ -181,8 +211,14 @@ static void Kx_VecUpMat3(float *vec, float mat[][3], short axis)
 
 bool KX_CameraActuator::Update(double curtime, bool frame)
 {
-       bool result = true;
+       /* wondering... is it really neccesary/desirable to suppress negative    */
+       /* events here?                                                          */
+       bool bNegativeEvent = IsNegativeEvent();
+       RemoveAllEvents();
 
+       if (bNegativeEvent || !m_ob) 
+               return false;
+       
        KX_GameObject *obj = (KX_GameObject*) GetParent();
        MT_Point3 from = obj->NodeGetWorldPosition();
        MT_Matrix3x3 frommat = obj->NodeGetWorldOrientation();
@@ -195,13 +231,6 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
        float mindistsq, maxdistsq, distsq;
        float mat[3][3];
        
-       /* wondering... is it really neccesary/desirable to suppress negative    */
-       /* events here?                                                          */
-       bool bNegativeEvent = IsNegativeEvent();
-       RemoveAllEvents();
-
-       if (bNegativeEvent) return false;
-       
        /* The rules:                                                            */
        /* CONSTRAINT 1: not implemented */
        /* CONSTRAINT 2: can camera see actor?              */
@@ -315,7 +344,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
        actormat[2][0]= mat[0][2]; actormat[2][1]= mat[1][2]; actormat[2][2]= mat[2][2];
        obj->NodeSetLocalOrientation(actormat);
 
-       return result;
+       return true;
 }
 
 CValue *KX_CameraActuator::findObject(char *obName) 
@@ -404,7 +433,11 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self,
        PyObject* gameobj;
        if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
        {
-               m_ob = (CValue*)gameobj;
+               if (m_ob)
+                       m_ob->UnregisterActuator(this);
+               m_ob = (SCA_IObject*)gameobj;
+               if (m_ob)
+                       m_ob->RegisterActuator(this);
                Py_Return;
        }
        PyErr_Clear();
@@ -412,10 +445,13 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self,
        char* objectname;
        if (PyArg_ParseTuple(args, "s", &objectname))
        {
-               CValue *object = (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
+               SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
                if(object)
                {
+                       if (m_ob != NULL)
+                               m_ob->UnregisterActuator(this);
                        m_ob = object;
+                       m_ob->RegisterActuator(this);
                        Py_Return;
                }
        }
index eb007e403ec220ae720d6a079d8bbbad8695e699..488b36922b00b1729c646adcd10f8a415ff1fd8d 100644 (file)
@@ -49,7 +49,7 @@ class KX_CameraActuator : public SCA_IActuator
        Py_Header;
 private :
        /** Object that will be tracked. */
-       CValue *m_ob;
+       SCA_IObject *m_ob;
 
        /** height (float), */
        //const MT_Scalar m_height;
@@ -87,7 +87,7 @@ private :
 
                SCA_IObject *gameobj,
                //const CValue *ob,
-               CValue *ob,
+               SCA_IObject *ob,
                MT_Scalar hght,
                MT_Scalar minhght,
                MT_Scalar maxhght,
@@ -103,6 +103,7 @@ private :
 
        /** Methods Inherited from  CValue */
        CValue* GetReplica();
+       virtual void ProcessReplica();
        
 
        /** Methods inherited from SCA_IActuator */
@@ -110,7 +111,10 @@ private :
                double curtime,
                bool frame
        );
+       virtual bool    UnlinkObject(SCA_IObject* clientobj);
 
+       /** Methods inherited from SCA_ILogicBrick */
+       virtual void    Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
 
        /* --------------------------------------------------------------------- */
        /* Python interface ---------------------------------------------------- */
index 576ff3ec68f554a884d92ff8c181e50312c695de..1845fdd7b506e57af8ce8078e56b3e6a543bfbf3 100644 (file)
@@ -61,6 +61,8 @@ typedef unsigned long uint_ptr;
 #include "KX_RayCast.h"
 #include "KX_PythonInit.h"
 #include "KX_PyMath.h"
+#include "SCA_IActuator.h"
+#include "SCA_ISensor.h"
 
 // This file defines relationships between parents and children
 // in the game engine.
@@ -1668,6 +1670,20 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
  * --------------------------------------------------------------------- */
 void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)       
 {
-       /* intentionally empty ? */
+       // we will relink the sensors and actuators that use object references
+       // if the object is part of the replicated hierarchy, use the new
+       // object reference instead
+       SCA_SensorList& sensorlist = GetSensors();
+       SCA_SensorList::iterator sit;
+       for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
+       {
+               (*sit)->Relink(map_parameter);
+       }
+       SCA_ActuatorList& actuatorlist = GetActuators();
+       SCA_ActuatorList::iterator ait;
+       for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
+       {
+               (*ait)->Relink(map_parameter);
+       }
 }
 
index 8b379bcd44fbe67098e41862250932c5ca18f35e..fd1b56838e24f4e9cbe9ae725ccf08c8fc94da3c 100644 (file)
 
 KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, 
                                                                         int mode,
-                                                                        CValue *ob,
+                                                                        SCA_IObject *ob,
                                                                         PyTypeObject* T)
        : SCA_IActuator(gameobj, T),
          m_mode(mode),
          m_ob(ob)
 {
+       if (m_ob)
+               m_ob->RegisterActuator(this);
 } 
 
 
 
 KX_ParentActuator::~KX_ParentActuator()
 {
-       /* intentionally empty */ 
+       if (m_ob)
+               m_ob->UnregisterActuator(this);
 } 
 
 
@@ -73,6 +76,36 @@ CValue* KX_ParentActuator::GetReplica()
        return replica;
 }
 
+void KX_ParentActuator::ProcessReplica()
+{
+       if (m_ob)
+               m_ob->RegisterActuator(this);
+       SCA_IActuator::ProcessReplica();
+}
+
+
+bool KX_ParentActuator::UnlinkObject(SCA_IObject* clientobj)
+{
+       if (clientobj == m_ob)
+       {
+               // this object is being deleted, we cannot continue to track it.
+               m_ob = NULL;
+               return true;
+       }
+       return false;
+}
+
+void KX_ParentActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       void **h_obj = (*obj_map)[m_ob];
+       if (h_obj) {
+               if (m_ob)
+                       m_ob->UnregisterActuator(this);
+               m_ob = (SCA_IObject*)(*h_obj);
+               m_ob->RegisterActuator(this);
+       }
+}
+
 
 
 bool KX_ParentActuator::Update()
@@ -87,7 +120,8 @@ bool KX_ParentActuator::Update()
        KX_Scene *scene = PHY_GetActiveScene();
        switch (m_mode) {
                case KX_PARENT_SET:
-                       obj->SetParent(scene, (KX_GameObject*)m_ob);
+                       if (m_ob)
+                               obj->SetParent(scene, (KX_GameObject*)m_ob);
                        break;
                case KX_PARENT_REMOVE:
                        obj->RemoveParent(scene);
@@ -148,7 +182,11 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* args, PyObjec
        PyObject* gameobj;
        if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
        {
-               m_ob = (CValue*)gameobj;
+               if (m_ob != NULL)
+                       m_ob->UnregisterActuator(this);
+               m_ob = (SCA_IObject*)gameobj;
+               if (m_ob)
+                       m_ob->RegisterActuator(this);
                Py_Return;
        }
        PyErr_Clear();
@@ -156,10 +194,13 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* args, PyObjec
        char* objectname;
        if (PyArg_ParseTuple(args, "s", &objectname))
        {
-               CValue *object = (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
+               SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname));
                if(object)
                {
+                       if (m_ob != NULL)
+                               m_ob->UnregisterActuator(this);
                        m_ob = object;
+                       m_ob->RegisterActuator(this);
                        Py_Return;
                }
        }
index 86dcd4e6c127c5fcb7d36b370dd12ffa26a4cbe0..5255abf2e426ed0a22a4d6ec02b7d9c33e2ed9c8 100644 (file)
@@ -47,7 +47,7 @@ class KX_ParentActuator : public SCA_IActuator
        int m_mode;
        
        /** Object to set as parent */
-       CValue *m_ob;
+       SCA_IObject *m_ob;
        
        
 
@@ -62,12 +62,15 @@ class KX_ParentActuator : public SCA_IActuator
  
        KX_ParentActuator(class SCA_IObject* gameobj,
                                                int mode,
-                                               CValue *ob,
+                                               SCA_IObject *ob,
                                                PyTypeObject* T=&Type);
        virtual ~KX_ParentActuator();
        virtual bool Update();
        
        virtual CValue* GetReplica();
+       virtual void ProcessReplica();
+       virtual void KX_ParentActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
+       virtual bool KX_ParentActuator::UnlinkObject(SCA_IObject* clientobj);
        
        /* --------------------------------------------------------------------- */
        /* Python interface ---------------------------------------------------- */
index e5ee4cbddf10ae5caf2293c2159c3a3850f6075b..e36891b56f44c1f836db80226b761e4b34e59a95 100644 (file)
@@ -137,6 +137,17 @@ bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj)
        return false;
 }
 
+void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       void **h_obj = (*obj_map)[m_OriginalObject];
+       if (h_obj) {
+               if (m_OriginalObject)
+                       m_OriginalObject->UnregisterActuator(this);
+               m_OriginalObject = (SCA_IObject*)(*h_obj);
+               m_OriginalObject->RegisterActuator(this);
+       }
+}
+
 
 /* ------------------------------------------------------------------------- */
 /* Python functions                                                          */
index 42123b94a6854e4012cf3dea4d34ed5074ef8122..1359f39278dc246b4071cb24f54c26337e6965ac 100644 (file)
@@ -95,6 +95,9 @@ public:
        virtual bool 
        UnlinkObject(SCA_IObject* clientobj);
 
+       virtual void 
+       Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
+
        virtual bool 
        Update();
 
index 200883a094c82ca64a71760d7e528ed1766f358c..1bdd400280586880e131b993bfbab2977d4e3599 100644 (file)
@@ -724,21 +724,23 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
                replica->Release();
        }
 
-       //      relink any pointers as necessary, sort of a temporary solution
+       // the logic must be replicated first because we need
+       // the new logic bricks before relinking
        vector<KX_GameObject*>::iterator git;
        for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
        {
+               (*git)->ReParentLogic();
+       }
+       
+       //      relink any pointers as necessary, sort of a temporary solution
+       for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
+       {
+               // this will also relink the actuator to objects within the hierarchy
                (*git)->Relink(&m_map_gameobject_to_replica);
                // add the object in the layer of the parent
                (*git)->SetLayer(groupobj->GetLayer());
        }
 
-       // now replicate logic
-       for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
-       {
-               (*git)->ReParentLogic();
-       }
-       
        // replicate crosslinks etc. between logic bricks
        for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
        {
@@ -805,21 +807,22 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
                        replica->GetSGNode()->AddChild(childreplicanode);
        }
 
-       //      relink any pointers as necessary, sort of a temporary solution
+       // now replicate logic
        vector<KX_GameObject*>::iterator git;
        for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
        {
+               (*git)->ReParentLogic();
+       }
+       
+       //      relink any pointers as necessary, sort of a temporary solution
+       for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
+       {
+               // this will also relink the actuators in the hierarchy
                (*git)->Relink(&m_map_gameobject_to_replica);
                // add the object in the layer of the parent
                (*git)->SetLayer(parentobj->GetLayer());
        }
 
-       // now replicate logic
-       for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
-       {
-               (*git)->ReParentLogic();
-       }
-       
        // replicate crosslinks etc. between logic bricks
        for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
        {
index 8f7cffd506ff8187be07ba3e299c46863539b2c3..d6164dc812ab70706ef830ea9e2f84f0675053cc 100644 (file)
@@ -58,13 +58,16 @@ KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj,
        m_KetsjiEngine=ketsjiEngine;
        m_camera = camera;
        m_nextSceneName = nextSceneName;
+       if (m_camera)
+               m_camera->RegisterActuator(this);
 } /* End of constructor */
 
 
 
 KX_SceneActuator::~KX_SceneActuator()
 { 
-       // there's nothing to be done here, really....
+       if (m_camera)
+               m_camera->UnregisterActuator(this);
 } /* end of destructor */
 
 
@@ -79,6 +82,34 @@ CValue* KX_SceneActuator::GetReplica()
        return replica;
 }
 
+void KX_SceneActuator::ProcessReplica()
+{
+       if (m_camera)
+               m_camera->RegisterActuator(this);
+       SCA_IActuator::ProcessReplica();
+}
+
+bool KX_SceneActuator::UnlinkObject(SCA_IObject* clientobj)
+{
+       if (clientobj == (SCA_IObject*)m_camera)
+       {
+               // this object is being deleted, we cannot continue to track it.
+               m_camera = NULL;
+               return true;
+       }
+       return false;
+}
+
+void KX_SceneActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       void **h_obj = (*obj_map)[m_camera];
+       if (h_obj) {
+               if (m_camera)
+                       m_camera->UnregisterActuator(this);
+               m_camera = (KX_Camera*)(*h_obj);
+               m_camera->RegisterActuator(this);
+       }
+}
 
 
 bool KX_SceneActuator::Update()
@@ -332,7 +363,11 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self,
        PyObject *cam;
        if (PyArg_ParseTuple(args, "O!", &KX_Camera::Type, &cam))
        {
+               if (m_camera)
+                       m_camera->UnregisterActuator(this);
                m_camera = (KX_Camera*) cam;
+               if (m_camera)
+                       m_camera->RegisterActuator(this);
                Py_Return;
        }
        PyErr_Clear();
@@ -345,7 +380,13 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self,
        }
 
        KX_Camera *camOb = FindCamera(camName);
-       if (camOb) m_camera = camOb;
+       if (camOb) 
+       {
+               if (m_camera)
+                       m_camera->UnregisterActuator(this);
+               m_camera = camOb;
+               m_camera->RegisterActuator(this);
+       }
 
        Py_Return;
 }
index cfc79b93f8e7e1f9ba62c88539b68b76934f7cfc..55aaf629d7c7409ea45dafa5a9887b4323747902 100644 (file)
@@ -82,6 +82,9 @@ class KX_SceneActuator : public SCA_IActuator
        virtual ~KX_SceneActuator();
 
        virtual CValue* GetReplica();
+       virtual void ProcessReplica();
+       virtual bool UnlinkObject(SCA_IObject* clientobj);
+       virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
 
        virtual bool Update();
        
index 731a610c2eb375ca374dbc058e4542c1358143cb..c580aa4d4e5eea1bdc4fc20227da0e58052869b0 100644 (file)
@@ -210,6 +210,18 @@ bool KX_TrackToActuator::UnlinkObject(SCA_IObject* clientobj)
        return false;
 }
 
+void KX_TrackToActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       void **h_obj = (*obj_map)[m_object];
+       if (h_obj) {
+               if (m_object)
+                       m_object->UnregisterActuator(this);
+               m_object = (SCA_IObject*)(*h_obj);
+               m_object->RegisterActuator(this);
+       }
+}
+
+
 bool KX_TrackToActuator::Update(double curtime, bool frame)
 {
        bool result = false;    
index a03aa115baa514307227256d71a4d455e00d6820..1d1cf46d21b4ca8023db4aad64b39633eeb78cc7 100644 (file)
@@ -68,6 +68,7 @@ class KX_TrackToActuator : public SCA_IActuator
 
        virtual void ProcessReplica();
        virtual bool UnlinkObject(SCA_IObject* clientobj);
+       virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map);
        virtual bool Update(double curtime, bool frame);
 
        /* Python part */