BGE: Committing patch [#31442] "API improvements: Group references python api, for better control over groups and instances" by Martin Sell (moerdn). This patch adds a member and a group property to KX_GameObject:

* 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
This commit is contained in:
Mitchell Stokes 2012-10-07 00:09:02 +00:00
parent e7db06ad9d
commit 7beff06950
4 changed files with 140 additions and 1 deletions

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

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

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

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