BGE Python
authorCampbell Barton <ideasman42@gmail.com>
Fri, 3 Apr 2009 02:16:56 +0000 (02:16 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 3 Apr 2009 02:16:56 +0000 (02:16 +0000)
- Bugfix for running dir() on all BGE python objects. was not getting the immediate methods and attributes for each class.
- Use attributes for KX_Scene (so they are included with dir())
- Override __dict__ attributes for KX_Scene and KX_GameObject so custom properties are included with a dir()

source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/Ketsji/KX_Scene.cpp
source/gameengine/Ketsji/KX_Scene.h

index 6ba80255aa31857a37a4e2ec983c16cb5809d990..345eb8c9c3fb7ea54e5ef28700cb456bc51d88dc 100644 (file)
@@ -100,9 +100,8 @@ static inline void Py_Fatal(const char *M) {
                PyErr_Clear(); \
                rvalue = Parent::_getattr(attr); \
        } \
-       if ((rvalue == NULL) && !strcmp(attr, "__dict__")) {\
-               PyErr_Clear(); \
-               rvalue = _getattr_dict(Parent::_getattr(attr), Methods, Attributes); \
+       if (strcmp(attr, "__dict__")==0) {\
+               rvalue = _getattr_dict(rvalue, Methods, Attributes); \
        } \
        return rvalue; \
 
index 281de1965d41f3fa37632a9f48442b7a053ab6a2..5c9615c408beba5439a161de980d780849fefd09 100644 (file)
@@ -942,14 +942,14 @@ const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
 }
 
 
-
+static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
 {
        // check on valid node in case a python controller holds a reference to a deleted object
        if (GetSGNode())
                return GetSGNode()->GetWorldPosition();
        else
-               return MT_Point3(0.0, 0.0, 0.0);
+               return dummy_point;
 }
 
 /* Suspend/ resume: for the dynamic behaviour, there is a simple
@@ -1043,6 +1043,7 @@ PyAttributeDef KX_GameObject::Attributes[] = {
        KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_scaling,      pyattr_set_scaling),
        KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
        KX_PYATTRIBUTE_RW_FUNCTION("state",             KX_GameObject, pyattr_get_state,        pyattr_set_state),
+       KX_PYATTRIBUTE_RO_FUNCTION("__dict__",  KX_GameObject, pyattr_get_dir_dict),
        {NULL} //Sentinel
 };
 
@@ -1412,16 +1413,37 @@ int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attr
        return 0;
 }
 
+/* __dict__ only for the purpose of giving useful dir() results */
+PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       PyObject *dict= _getattr_dict(self->SCA_IObject::_getattr("__dict__"), KX_GameObject::Methods, KX_GameObject::Attributes);
+       
+       if(dict==NULL)
+               return NULL;
+       
+       /* Not super fast getting as a list then making into dict keys but its only for dir() */
+       PyObject *list= self->ConvertKeysToPython();
+       if(list)
+       {
+               int i;
+               for(i=0; i<PyList_Size(list); i++)
+                       PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
+       }
+       else
+               PyErr_Clear();
+       
+       Py_DECREF(list);
+       
+       return dict;
+}
+
 PyObject* KX_GameObject::_getattr(const char *attr)
 {
        PyObject* object = _getattr_self(Attributes, this, attr);
        if (object != NULL)
                return object;
        
-       if (!strcmp(attr, "__dict__")) { /* python 3.0 uses .__dir__()*/
-               return _getattr_dict(SCA_IObject::_getattr(attr), Methods, Attributes);
-       }
-       
        _getattr_up(SCA_IObject);
 }
 
index 774977f2ecf7b02f8c6d863be137551d592b6ef9..bada19c4895684e6c366191bf9068138c2c083ef 100644 (file)
@@ -822,6 +822,9 @@ public:
        static PyObject*        pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static int                      pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        
+       /* for dir(), python3 uses __dir__() */
+       static PyObject*        pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       
        /* getitem/setitem */
        static int                                      Map_Len(PyObject* self);
        static PyMappingMethods Mapping;
index 0fded15f1a150b08b602f27aa60ecd24bcd608b7..b24b5cd9693595d011bc369cdf3784e0cc66a30e 100644 (file)
@@ -32,7 +32,6 @@
 #pragma warning (disable : 4786)
 #endif //WIN32
 
-
 #include "KX_Scene.h"
 #include "MT_assert.h"
 
@@ -1551,35 +1550,57 @@ PyMethodDef KX_Scene::Methods[] = {
        {NULL,NULL} //Sentinel
 };
 
+PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_Scene* self= static_cast<KX_Scene*>(self_v);
+       return PyString_FromString(self->GetName().ReadPtr());
+}
+
+PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_Scene* self= static_cast<KX_Scene*>(self_v);
+       return self->GetObjectList()->AddRef();
+}
+
+PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_Scene* self= static_cast<KX_Scene*>(self_v);
+       return self->GetActiveCamera()->AddRef();
+}
+
+/* __dict__ only for the purpose of giving useful dir() results */
+PyObject* KX_Scene::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_Scene* self= static_cast<KX_Scene*>(self_v);
+       /* Useually done by _getattr_up but in this case we want to include m_attrlist dict */
+       PyObject *dict= _getattr_dict(self->PyObjectPlus::_getattr("__dict__"), KX_Scene::Methods, KX_Scene::Attributes);
+       
+       PyDict_Update(dict, self->m_attrlist);
+       return dict;
+}
+
 PyAttributeDef KX_Scene::Attributes[] = {
+       KX_PYATTRIBUTE_RO_FUNCTION("name",                      KX_Scene, pyattr_get_name),
+       KX_PYATTRIBUTE_RO_FUNCTION("objects",           KX_Scene, pyattr_get_objects),
+       KX_PYATTRIBUTE_RO_FUNCTION("active_camera",     KX_Scene, pyattr_get_active_camera),
+       KX_PYATTRIBUTE_BOOL_RO("suspended",                     KX_Scene, m_suspend),
+       KX_PYATTRIBUTE_BOOL_RO("activity_culling",      KX_Scene, m_activity_culling),
+       KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius),
+       KX_PYATTRIBUTE_RO_FUNCTION("__dict__",          KX_Scene, pyattr_get_dir_dict),
        { NULL }        //Sentinel
 };
 
 PyObject* KX_Scene::_getattr(const char *attr)
 {
-       if (!strcmp(attr, "name"))
-               return PyString_FromString(GetName());
-       
-       if (!strcmp(attr, "objects"))
-               return (PyObject*) m_objectlist->AddRef();
-       
-       if (!strcmp(attr, "active_camera"))
-               return (PyObject*) GetActiveCamera()->AddRef();
-       
-       if (!strcmp(attr, "suspended"))
-               return PyInt_FromLong(m_suspend);
-       
-       if (!strcmp(attr, "activity_culling"))
-               return PyInt_FromLong(m_activity_culling);
-       
-       if (!strcmp(attr, "activity_culling_radius"))
-               return PyFloat_FromDouble(m_activity_box_radius);
+       PyObject* object = _getattr_self(Attributes, this, attr);
+       if (object != NULL)
+               return object;
        
-       PyObject* value = PyDict_GetItemString(m_attrlist, attr);
-       if (value)
+       object = PyDict_GetItemString(m_attrlist, attr);
+       if (object)
        {
-               Py_INCREF(value);
-               return value;
+               Py_INCREF(object);
+               return object;
        }
        
        _getattr_up(PyObjectPlus);
index 962db1a9b9641dde422878e3eb9ba319d7472bde..d1da44c600e09c3ad26a052eefc64af61d153a4c 100644 (file)
@@ -565,6 +565,15 @@ public:
        KX_PYMETHOD_DOC(KX_Scene, setSceneViewport);
        */
 
+       /* attributes */
+       static PyObject*        pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static PyObject*        pyattr_get_objects(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static PyObject*        pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       
+       /* for dir(), python3 uses __dir__() */
+       static PyObject*        pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       
+
        virtual PyObject* _getattr(const char *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */
        virtual int _setattr(const char *attr, PyObject *pyvalue);
        virtual int _delattr(const char *attr);