BGE: Committing patch [#31442] "API improvements: Group references python api, for...
authorMitchell Stokes <mogurijin@gmail.com>
Sun, 7 Oct 2012 00:09:02 +0000 (00:09 +0000)
committerMitchell Stokes <mogurijin@gmail.com>
Sun, 7 Oct 2012 00:09:02 +0000 (00:09 +0000)
  * KX_GameObject.member returns the list of group members if the object is a group object, otherwise None is returned
  * KX_GameObject.group returns the group object that the object belongs to or None if the object is not part of a group

doc/python_api/rst/bge.types.rst
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_Scene.cpp

index f4374f7f355f33f6b7e246916b909d345d74dadb..6599cfeb2b2d7db5ef476fe2bfe87d51d11eeafa 100644 (file)
@@ -986,6 +986,18 @@ Types
       The object's parent object. (read-only).
 
       :type: :class:`KX_GameObject` or None
+         
+   .. attribute:: members
+
+      Returns the list of group members if the object is a group object, otherwise None is returned.
+
+      :type: :class:`CListValue` of :class:`KX_GameObject` or None
+
+   .. attribute:: group
+
+      Returns the group object that the object belongs to or None if the object is not part of a group.
+
+      :type: :class:`KX_GameObject` or None
 
    .. attribute:: visible
 
index fe8419d53437cb84154ca712ec42e96188ba7ae6..80634c3d8fc23a6053dd26b1a81964f591e15eba 100644 (file)
@@ -110,7 +110,9 @@ KX_GameObject::KX_GameObject(
       m_pHitObject(NULL),
       m_pObstacleSimulation(NULL),
       m_actionManager(NULL),
-      m_isDeformable(false)
+      m_isDeformable(false),
+      m_pDupliGroupObject(NULL),
+      m_pInstanceObjects(NULL)
 #ifdef WITH_PYTHON
     , m_attr_dict(NULL)
 #endif
@@ -168,6 +170,16 @@ KX_GameObject::~KX_GameObject()
                KX_GetActiveScene()->RemoveAnimatedObject(this);
                delete m_actionManager;
        }
+
+       if (m_pDupliGroupObject)
+       {
+               m_pDupliGroupObject->Release();
+       }
+
+       if (m_pInstanceObjects)
+       {
+               m_pInstanceObjects->Release();
+       }
 #ifdef WITH_PYTHON
        if (m_attr_dict) {
                PyDict_Clear(m_attr_dict); /* in case of circular refs or other weird cases */
@@ -229,6 +241,46 @@ KX_IPhysicsController* KX_GameObject::GetPhysicsController()
        return m_pPhysicsController1;
 }
 
+KX_GameObject* KX_GameObject::GetDupliGroupObject()
+{ 
+       return m_pDupliGroupObject;     
+}
+
+CListValue* KX_GameObject::GetInstanceObjects()
+{ 
+       return m_pInstanceObjects;
+}
+
+void KX_GameObject::AddInstanceObjects(KX_GameObject* obj)
+{
+       if(!m_pInstanceObjects)
+               m_pInstanceObjects = new CListValue();
+
+       obj->AddRef();
+       m_pInstanceObjects->Add(obj);
+}
+
+void KX_GameObject::RemoveInstanceObject(KX_GameObject* obj)
+{
+       assert(m_pInstanceObjects);
+       m_pInstanceObjects->RemoveValue(obj);
+       obj->Release();
+}
+
+void KX_GameObject::RemoveDupliGroupObject()
+{
+       if(m_pDupliGroupObject) {
+               m_pDupliGroupObject->Release();
+               m_pDupliGroupObject = NULL;
+       }
+}
+
+void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj)
+{
+       obj->AddRef();
+       m_pDupliGroupObject = obj;
+}
+
 KX_GameObject* KX_GameObject::GetParent()
 {
        KX_GameObject* result = NULL;
@@ -1629,6 +1681,8 @@ PyMethodDef KX_GameObject::Methods[] = {
 PyAttributeDef KX_GameObject::Attributes[] = {
        KX_PYATTRIBUTE_RO_FUNCTION("name",              KX_GameObject, pyattr_get_name),
        KX_PYATTRIBUTE_RO_FUNCTION("parent",    KX_GameObject, pyattr_get_parent),
+       KX_PYATTRIBUTE_RO_FUNCTION("members",   KX_GameObject, pyattr_get_instance_objects),
+       KX_PYATTRIBUTE_RO_FUNCTION("group",     KX_GameObject, pyattr_get_dupli_group_object),
        KX_PYATTRIBUTE_RO_FUNCTION("life",              KX_GameObject, pyattr_get_life),
        KX_PYATTRIBUTE_RW_FUNCTION("mass",              KX_GameObject, pyattr_get_mass,         pyattr_set_mass),
        KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",            KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
@@ -1924,6 +1978,26 @@ PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE
        Py_RETURN_NONE;
 }
 
+PyObject *KX_GameObject::pyattr_get_instance_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       CListValue* instances = self->GetInstanceObjects();
+       if (instances) {
+               return instances->GetProxy();
+       }
+       Py_RETURN_NONE;
+}
+
+PyObject *KX_GameObject::pyattr_get_dupli_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       KX_GameObject* pivot = self->GetDupliGroupObject();
+       if (pivot) {
+               return pivot->GetProxy();
+       }
+       Py_RETURN_NONE;
+}
+
 PyObject *KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
index ea75ca4a91764b6ada0adac35888b3848aeb7958..4fde0752a130a6abeb7b3203e82241ae22a409de 100644 (file)
@@ -116,6 +116,8 @@ protected:
 
        KX_ObstacleSimulation*                          m_pObstacleSimulation;
 
+       CListValue*                                             m_pInstanceObjects;
+       KX_GameObject*                                          m_pDupliGroupObject;
 
        // The action manager is used to play/stop/update actions
        BL_ActionManager*                               m_actionManager;
@@ -207,6 +209,33 @@ public:
         */
        void RemoveParent(KX_Scene *scene);
 
+       /*********************************
+        * group reference API
+        *********************************/
+
+               KX_GameObject*
+       GetDupliGroupObject(
+       );
+
+               CListValue*
+       GetInstanceObjects(
+       );
+
+               void    
+       SetDupliGroupObject(KX_GameObject*
+       );
+
+               void                            
+       AddInstanceObjects(KX_GameObject*
+       );
+               
+               void 
+       RemoveDupliGroupObject(
+       );
+
+               void
+       RemoveInstanceObject(KX_GameObject*
+       );
        /*********************************
         * Animation API
         *********************************/
@@ -949,6 +978,9 @@ public:
        static PyObject*        pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static PyObject*        pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
 
+       static PyObject*        pyattr_get_dupli_group_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static PyObject*        pyattr_get_instance_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+
        static PyObject*        pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static PyObject*        pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static int                      pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
index 652ed2ab2dd0f3f54335c76e167a3ecbaeed3886..a4237f9fabea072b3f4a120b520d0523523e0b70 100644 (file)
@@ -769,6 +769,13 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
                // we can now add the graphic controller to the physic engine
                replica->ActivateGraphicController(true);
 
+               // set references for dupli-group
+               // groupobj holds a list of all objects, that belongs to this group
+               groupobj->AddInstanceObjects(replica);
+
+               // every object gets the reference to its dupli-group object
+               replica->SetDupliGroupObject(groupobj);
+
                // done with replica
                replica->Release();
        }
@@ -1017,6 +1024,20 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
                        m_timemgr->RemoveTimeProperty(propval);
                }
        }
+
+       // if the object is the dupligroup proxy, you have to cleanup all m_pDupliGroupObject's in all
+       // instances refering to this group
+       if(newobj->GetInstanceObjects()) {
+               for (int i = 0; i < newobj->GetInstanceObjects()->GetCount(); i++) {
+                       KX_GameObject* instance = (KX_GameObject*)newobj->GetInstanceObjects()->GetValue(i);
+                       instance->RemoveDupliGroupObject();
+               }
+       }
+
+       // if this object was part of a group, make sure to remove it from that group's instance list
+       KX_GameObject* group = newobj->GetDupliGroupObject();
+       if (group)
+               group->RemoveInstanceObject(newobj);
        
        newobj->RemoveMeshes();
        ret = 1;