diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-04-18 00:06:06 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-04-18 00:06:06 +0400 |
commit | df8cf26404c7e922751643b1095e38f1ab430811 (patch) | |
tree | b4258cc6c90913c379f5cdd05edebd8785230647 /source/gameengine | |
parent | 90c6cf77f10961de756f6ff06329d3fa65ce3da4 (diff) |
Added m_zombie to the base python class (PyObjectPlus), when this is set all the subclasses will raise an error on access to their members.
Other small changes...
- KX_Camera and KX_Light didnt have get/setitem access in their PyType definition.
- CList.from_id() error checking for a long was checking for -1 against an unsigned value (own fault)
- CValue::SpecialRelease was incrementing an int for no reason.
- renamed m_attrlist to m_attr_dict since its a PyDict type.
- removed custom getattro/setattro functions for KX_Scene and KX_GameObject, use py_base_getattro, py_base_setattro for all subclasses of PyObjectPlus.
- lowercase windows.h in VideoBase.cpp for cross compiling.
Diffstat (limited to 'source/gameengine')
-rw-r--r-- | source/gameengine/Expressions/ListValue.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/Expressions/PyObjectPlus.cpp | 20 | ||||
-rw-r--r-- | source/gameengine/Expressions/PyObjectPlus.h | 56 | ||||
-rw-r--r-- | source/gameengine/Expressions/Value.cpp | 7 | ||||
-rw-r--r-- | source/gameengine/Expressions/Value.h | 10 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_PropertyActuator.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Camera.cpp | 22 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 179 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 26 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Light.cpp | 15 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.cpp | 68 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_Scene.h | 26 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/VideoBase.cpp | 2 |
13 files changed, 233 insertions, 202 deletions
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 0f163ad07c1..37feba38f8b 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -513,7 +513,7 @@ PyObject* CListValue::Pyfrom_id(PyObject* self, PyObject* value) BGE_ID_TYPE id= PyLong_FromUnsignedLongLong(value); #endif - if (id==-1 && PyErr_Occurred()) + if (PyErr_Occurred()) return NULL; int numelem = GetCount(); diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 33335ebef3e..0db2e8991fc 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -88,6 +88,7 @@ PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor MT_assert(T != NULL); this->ob_type = T; _Py_NewReference(this); + SetZombie(false); }; /*------------------------------ @@ -99,9 +100,15 @@ PyMethodDef PyObjectPlus::Methods[] = { }; PyAttributeDef PyObjectPlus::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("isValid", PyObjectPlus, pyattr_get_is_valid), {NULL} //Sentinel }; +PyObject* PyObjectPlus::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + Py_RETURN_TRUE; +} + /*------------------------------ * PyObjectPlus Parents -- Every class, even the abstract one should have parents ------------------------------*/ @@ -117,10 +124,19 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr) if (strcmp(PyString_AsString(attr), "__dict__")==0) { return py_getattr_dict(NULL, Type.tp_dict); /* no Attributes yet */ } - PyErr_SetString(PyExc_AttributeError, "attribute not found"); + PyErr_Format(PyExc_AttributeError, "attribute \"%s\" not found", PyString_AsString(attr)); return NULL; } else { - return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this); \ + /* Copied from py_getattro_up */ + if (PyCObject_Check(descr)) { + return py_get_attrdef((void *)this, (const PyAttributeDef*)PyCObject_AsVoidPtr(descr)); + } else if (descr->ob_type->tp_descr_get) { + return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, (PyObject *)this); + } else { + fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)"); + return descr; + } + /* end py_getattro_up copy */ } //if (streq(attr, "type")) // return Py_BuildValue("s", (*(GetParents()))->tp_name); diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index ea26ea1d201..58a74e4ca74 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -400,10 +400,11 @@ class PyObjectPlus : public PyObject public: PyObjectPlus(PyTypeObject *T); + bool m_zombie; virtual ~PyObjectPlus(); // destructor static void PyDestructor(PyObject *P) // python wrapper - { + { delete ((PyObjectPlus *) P); }; @@ -417,6 +418,14 @@ public: virtual PyObject *py_getattro(PyObject *attr); // py_getattro method static PyObject *py_base_getattro(PyObject * self, PyObject *attr) // This should be the entry in Type. { + if (((PyObjectPlus*)self)->IsZombie()) { + if (!strcmp(PyString_AsString(attr), "isValid")) { + Py_RETURN_FALSE; + } + ((PyObjectPlus*)self)->IsZombiePyErr(); /* raise an error */ + return NULL; + } + return ((PyObjectPlus*) self)->py_getattro(attr); } @@ -432,10 +441,16 @@ public: virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method static int py_base_setattro(PyObject *self, PyObject *attr, PyObject *value) // the PyType should reference this { + if (((PyObjectPlus*)self)->IsZombie()) { + /* you cant set isValid anyway */ + ((PyObjectPlus*)self)->IsZombiePyErr(); + return -1; + } + if (value==NULL) - return ((PyObjectPlus*) self)->py_delattro(attr); + return ((PyObjectPlus*)self)->py_delattro(attr); - return ((PyObjectPlus*) self)->py_setattro(attr, value); + return ((PyObjectPlus*)self)->py_setattro(attr, value); } virtual PyObject *py_repr(void); // py_repr method @@ -452,6 +467,41 @@ public: { return ((PyObjectPlus*)self)->Py_isA(value); } + + /* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */ + static PyObject* pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + + bool IsZombie() + { + return m_zombie; + } + + bool IsZombiePyErr() + { + if(m_zombie) { + /* + PyObject *this_pystr = PyObject_Repr(this); + + PyErr_Format( + PyExc_RuntimeError, + "\"%s\" of type \"%s\" has been freed by the blender game engine, " + "scripts cannot access this anymore, check for this case with the \"isValid\" attribute", + PyString_AsString(this_pystr), ob_type->tp_name ); + + Py_DECREF(this_pystr); + */ + + PyErr_SetString(PyExc_RuntimeError, "This value has been freed by the blender game engine but python is still holding a reference, this value cant be used."); + } + + return m_zombie; + } + + void SetZombie(bool is_zombie) + { + m_zombie= is_zombie; + } + }; PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict); diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index b8b7a05aa64..e969f0c33aa 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -602,6 +602,12 @@ int CValue::Release() // Decrease local reference count, if it reaches 0 the object should be freed if (--m_refcount > 0) { + // Benoit suggest this as a way to automatically set the zombie flag, but I couldnt get it working - Campbell + /* + if (m_refcount == 1 && ob_refcnt > 1) + SetZombie(true); // the remaining refcount is held by Python!! + */ + // Reference count normal, return new reference count return m_refcount; } @@ -609,6 +615,7 @@ int CValue::Release() { // Reference count reached 0, delete ourselves and return 0 // MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much"); + delete this; return 0; } diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index 4cdc80dc9bd..bcee355cda2 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -219,7 +219,7 @@ public: //static PyObject* PyMake(PyObject*,PyObject*); virtual PyObject *py_repr(void) { - return Py_BuildValue("s",(const char*)GetText()); + return PyString_FromString((const char*)GetText()); } @@ -228,14 +228,10 @@ public: void SpecialRelease() { - int i=0; - if (ob_refcnt == 0) + if (ob_refcnt == 0) /* make sure python always holds a reference */ { _Py_NewReference(this); - } else - { - i++; } Release(); } @@ -280,6 +276,7 @@ public: int GetRefCount() { return m_refcount; } virtual CValue* AddRef(); // Add a reference to this value virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) + /// Property Management virtual void SetProperty(const STR_String& name,CValue* ioProperty); // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed @@ -355,6 +352,7 @@ private: std::map<STR_String,CValue*>* m_pNamedPropertyArray; // Properties for user/game etc ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage) int m_refcount; // Reference Counter + bool m_zombie; // Object is invalid put its still being referenced (by python) static double m_sZeroVec[3]; static bool m_ignore_deprecation_warnings; diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index 359ab8adac6..9dbdc0e89d1 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -95,7 +95,7 @@ bool SCA_PropertyActuator::Update() } newval->Release(); } - else if (userexpr = parser.ProcessText(m_exprtxt)) { + else if ((userexpr = parser.ProcessText(m_exprtxt))) { switch (m_type) { diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index befc8462aa3..daa37056d68 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -517,13 +517,20 @@ PyTypeObject KX_Camera::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, + 0,0, + &KX_GameObject::Mapping, + 0,0,0, py_base_getattro, py_base_setattro, 0,0,0,0,0,0,0,0,0, Methods }; + + + + + PyParentObject KX_Camera::Parents[] = { &KX_Camera::Type, &KX_GameObject::Type, @@ -534,22 +541,11 @@ PyParentObject KX_Camera::Parents[] = { PyObject* KX_Camera::py_getattro(PyObject *attr) { - if (ValidPythonToGameObject(this)==false) { - if (!strcmp(PyString_AsString(attr), "isValid")) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; /* ValidPythonToGameObject sets the error */ - } - py_getattro_up(KX_GameObject); } int KX_Camera::py_setattro(PyObject *attr, PyObject *value) -{ - if (ValidPythonToGameObject(this)==false) - return -1; - +{ py_setattro_up(KX_GameObject); } diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 283b78c2947..3e7c99dc472 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -103,7 +103,7 @@ KX_GameObject::KX_GameObject( m_xray(false), m_pHitObject(NULL), m_isDeformable(false), - m_attrlist(NULL) + m_attr_dict(NULL) { m_ignore_activity_culling = false; m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR); @@ -146,9 +146,9 @@ KX_GameObject::~KX_GameObject() delete m_pGraphicController; } - if (m_attrlist) { - PyDict_Clear(m_attrlist); /* incase of circular refs or other weired cases */ - Py_DECREF(m_attrlist); + if (m_attr_dict) { + PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */ + Py_DECREF(m_attr_dict); } } @@ -339,8 +339,8 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica) replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); replica->m_pClient_info->m_gameobject = replica; replica->m_state = 0; - if(m_attrlist) - replica->m_attrlist= PyDict_Copy(m_attrlist); + if(m_attr_dict) + replica->m_attr_dict= PyDict_Copy(m_attr_dict); } @@ -1123,9 +1123,6 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors), KX_PYATTRIBUTE_RO_FUNCTION("controllers", KX_GameObject, pyattr_get_controllers), KX_PYATTRIBUTE_RO_FUNCTION("actuators", KX_GameObject, pyattr_get_actuators), - - KX_PYATTRIBUTE_RO_FUNCTION("isValid", KX_GameObject, pyattr_get_is_valid), - {NULL} //Sentinel }; @@ -1190,14 +1187,15 @@ Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v) { KX_GameObject* self= static_cast<KX_GameObject*>(self_v); - if (ValidPythonToGameObject(self)==false) { + if (self->IsZombie()) /* not sure what to do here */ + { PyErr_Clear(); return 0; } Py_ssize_t len= self->GetPropertyCount(); - if(self->m_attrlist) - len += PyDict_Size(self->m_attrlist); + if(self->m_attr_dict) + len += PyDict_Size(self->m_attr_dict); return len; } @@ -1209,7 +1207,7 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) CValue* resultattr; PyObject* pyconvert; - if (ValidPythonToGameObject(self)==false) + if (self->IsZombiePyErr()) return NULL; /* first see if the attributes a string and try get the cvalue attribute */ @@ -1217,8 +1215,8 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) pyconvert = resultattr->ConvertValueToPython(); return pyconvert ? pyconvert:resultattr; } - /* no CValue attribute, try get the python only m_attrlist attribute */ - else if (self->m_attrlist && (pyconvert=PyDict_GetItem(self->m_attrlist, item))) { + /* no CValue attribute, try get the python only m_attr_dict attribute */ + else if (self->m_attr_dict && (pyconvert=PyDict_GetItem(self->m_attr_dict, item))) { if (attr_str) PyErr_Clear(); @@ -1241,7 +1239,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) if(attr_str==NULL) PyErr_Clear(); - if (ValidPythonToGameObject(self)==false) + if (self->IsZombiePyErr()) return -1; if (val==NULL) { /* del ob["key"] */ @@ -1251,15 +1249,15 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) if(attr_str) del |= (self->RemoveProperty(attr_str)==true) ? 1:0; - if(self->m_attrlist) - del |= (PyDict_DelItem(self->m_attrlist, key)==0) ? 1:0; + if(self->m_attr_dict) + del |= (PyDict_DelItem(self->m_attr_dict, key)==0) ? 1:0; if (del==0) { if(attr_str) PyErr_Format(PyExc_KeyError, "KX_GameObject key \"%s\" not found", attr_str); else PyErr_SetString(PyExc_KeyError, "KX_GameObject key not found"); return -1; } - else if (self->m_attrlist) { + else if (self->m_attr_dict) { PyErr_Clear(); /* PyDict_DelItem sets an error when it fails */ } } @@ -1284,8 +1282,8 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) set= 1; /* try remove dict value to avoid double ups */ - if (self->m_attrlist){ - if (PyDict_DelItem(self->m_attrlist, key) != 0) + if (self->m_attr_dict){ + if (PyDict_DelItem(self->m_attr_dict, key) != 0) PyErr_Clear(); } } @@ -1296,11 +1294,11 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) if(set==0) { - if (self->m_attrlist==NULL) /* lazy init */ - self->m_attrlist= PyDict_New(); + if (self->m_attr_dict==NULL) /* lazy init */ + self->m_attr_dict= PyDict_New(); - if(PyDict_SetItem(self->m_attrlist, key, val)==0) + if(PyDict_SetItem(self->m_attr_dict, key, val)==0) { if(attr_str) self->RemoveProperty(attr_str); /* overwrite the CValue if it exists */ @@ -1343,8 +1341,8 @@ PyTypeObject KX_GameObject::Type = { 0,0, &Mapping, 0,0,0, - py_base_getattro_gameobject, - py_base_setattro_gameobject, + py_base_getattro, + py_base_setattro, 0,0,0,0,0,0,0,0,0, Methods }; @@ -1675,11 +1673,6 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE return meshes; } -PyObject* KX_GameObject::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - Py_RETURN_TRUE; -} - /* experemental! */ PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -1741,47 +1734,36 @@ PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_ Py_DECREF(list); - /* Add m_attrlist if we have it */ - if(self->m_attrlist) - PyDict_Update(dict, self->m_attrlist); + /* Add m_attr_dict if we have it */ + if(self->m_attr_dict) + PyDict_Update(dict, self->m_attr_dict); return dict; } -PyObject* KX_GameObject::py_getattro(PyObject *attr) +/* We need these because the macros have a return in them */ +PyObject* KX_GameObject::py_getattro__internal(PyObject *attr) { py_getattro_up(SCA_IObject); } -int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method +int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value) // py_setattro method { py_setattro_up(SCA_IObject); } -/* we need our own getattr and setattr types */ -/* See m_attrlist definition for rules on how this works */ -PyObject *KX_GameObject::py_base_getattro_gameobject(PyObject * self, PyObject *attr) +PyObject* KX_GameObject::py_getattro(PyObject *attr) { - if(((KX_GameObject *) self)->GetSGNode()==NULL) { - if (!strcmp(PyString_AsString(attr), "isValid")) { - PyErr_Clear(); - Py_INCREF(Py_False); - return Py_False; - } - - ValidPythonToGameObject(((KX_GameObject *) self)); // we know its invalid, just get the error - return NULL; - } - - PyObject *object= ((KX_GameObject *) self)->py_getattro(attr); + PyObject *object= py_getattro__internal(attr); - if (object==NULL && ((KX_GameObject *) self)->m_attrlist) { + if (object==NULL && m_attr_dict) + { /* backup the exception incase the attr doesnt exist in the dict either */ PyObject *err_type, *err_value, *err_tb; PyErr_Fetch(&err_type, &err_value, &err_tb); - object= PyDict_GetItem(((KX_GameObject *) self)->m_attrlist, attr); + object= PyDict_GetItem(m_attr_dict, attr); if (object) { Py_INCREF(object); @@ -1797,62 +1779,33 @@ PyObject *KX_GameObject::py_base_getattro_gameobject(PyObject * self, PyObject * return object; } -int KX_GameObject::py_base_setattro_gameobject(PyObject * self, PyObject *attr, PyObject *value) +int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method { int ret; - /* Delete the item */ - if (value==NULL) - { - ret= ((PyObjectPlus*) self)->py_delattro(attr); - - if (ret != 0) /* CValue attribute failed, try KX_GameObject m_attrlist dict */ - { - if (((KX_GameObject *) self)->m_attrlist) - { - /* backup the exception incase the attr doesnt exist in the dict either */ - PyObject *err_type, *err_value, *err_tb; - PyErr_Fetch(&err_type, &err_value, &err_tb); - - if (PyDict_DelItem(((KX_GameObject *) self)->m_attrlist, attr) == 0) - { - ret= 0; - PyErr_Clear(); - Py_XDECREF( err_type ); - Py_XDECREF( err_value ); - Py_XDECREF( err_tb ); - } - else { - PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */ - } - } - } - return ret; - } - - - ret= ((PyObjectPlus*) self)->py_setattro(attr, value); + ret= py_setattro__internal(attr, value); if (ret==PY_SET_ATTR_SUCCESS) { /* remove attribute in our own dict to avoid double ups */ - if (((KX_GameObject *) self)->m_attrlist) { - if (PyDict_DelItem(((KX_GameObject *) self)->m_attrlist, attr) != 0) + /* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */ + if (m_attr_dict) { + if (PyDict_DelItem(m_attr_dict, attr) != 0) PyErr_Clear(); } } if (ret==PY_SET_ATTR_COERCE_FAIL) { - /* CValue attribute exists, remove and add dict value */ - ((KX_GameObject *) self)->RemoveProperty(STR_String(PyString_AsString(attr))); + /* CValue attribute exists, remove CValue and add PyDict value */ + RemoveProperty(STR_String(PyString_AsString(attr))); ret= PY_SET_ATTR_MISSING; } if (ret==PY_SET_ATTR_MISSING) { /* Lazy initialization */ - if (((KX_GameObject *) self)->m_attrlist==NULL) - ((KX_GameObject *) self)->m_attrlist = PyDict_New(); + if (m_attr_dict==NULL) + m_attr_dict = PyDict_New(); - if (PyDict_SetItem(((KX_GameObject *) self)->m_attrlist, attr, value)==0) { + if (PyDict_SetItem(m_attr_dict, attr, value)==0) { PyErr_Clear(); ret= PY_SET_ATTR_SUCCESS; } @@ -1862,9 +1815,25 @@ int KX_GameObject::py_base_setattro_gameobject(PyObject * self, PyObject *attr, } } - return ret; + return ret; } + +int KX_GameObject::py_delattro(PyObject *attr) +{ + char *attr_str= PyString_AsString(attr); + + if (RemoveProperty(STR_String(attr_str))) // XXX - should call CValues instead but its only 2 lines here + return 0; + + if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0)) + return 0; + + PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str); + return 1; +} + + PyObject* KX_GameObject::PyApplyForce(PyObject* self, PyObject* args) { int local = 0; @@ -2374,11 +2343,11 @@ PyObject* KX_GameObject::PyGetPropertyNames(PyObject* self) { PyObject *list= ConvertKeysToPython(); - if(m_attrlist) { + if(m_attr_dict) { PyObject *key, *value; Py_ssize_t pos = 0; - while (PyDict_Next(m_attrlist, &pos, &key, &value)) { + while (PyDict_Next(m_attr_dict, &pos, &key, &value)) { PyList_Append(list, key); } } @@ -2685,8 +2654,8 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, "to = Name of object to send the message to") { char* subject; - char* body = ""; - char* to = ""; + char* body = (char *)""; + char* to = (char *)""; const STR_String& from = GetName(); if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to)) @@ -2753,7 +2722,7 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py *object = static_cast<KX_GameObject*>(value); /* sets the error */ - if (ValidPythonToGameObject(*object)==false) + if ((*object)->IsZombiePyErr()) return false; return true; @@ -2769,17 +2738,3 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py return false; } - -bool ValidPythonToGameObject(KX_GameObject *object) -{ - if (object->GetSGNode()==NULL) { - PyErr_Format( - PyExc_RuntimeError, - "KX_GameObject \"%s\" is not longer in a scene, " - "check for this case with the \"isValid\" attribute", - object->GetName().ReadPtr() ); - return false; - } - - return true; -}
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index cf0c0e6b0f5..dd85c2f2faa 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -62,7 +62,6 @@ struct Object; /* utility conversion function */ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok); -bool ValidPythonToGameObject(KX_GameObject *object); /** * KX_GameObject is the main class for dynamic objects. @@ -119,15 +118,15 @@ public: // these can be used with property actuators // // For the python API, For types that cannot be converted into CValues (lists, dicts, GameObjects) - // these will be put into "m_attrlist", logic bricks cannot access them. + // these will be put into "m_attr_dict", logic bricks cannot access them. // // rules for setting attributes. // - // * there should NEVER be a CValue and a m_attrlist attribute with matching names. get/sets make sure of this. - // * if CValue conversion fails, use a PyObject in "m_attrlist" - // * when assigning a value, first see if it can be a CValue, if it can remove the "m_attrlist" and set the CValue + // * there should NEVER be a CValue and a m_attr_dict attribute with matching names. get/sets make sure of this. + // * if CValue conversion fails, use a PyObject in "m_attr_dict" + // * when assigning a value, first see if it can be a CValue, if it can remove the "m_attr_dict" and set the CValue // - PyObject* m_attrlist; + PyObject* m_attr_dict; virtual void /* This function should be virtual - derived classed override it */ Relink( @@ -814,16 +813,21 @@ public: virtual PyObject* py_getattro(PyObject *attr); virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method + virtual int py_delattro(PyObject *attr); virtual PyObject* py_repr(void) { - if (ValidPythonToGameObject(this)==false) + if (IsZombiePyErr()) return NULL; return PyString_FromString(GetName().ReadPtr()); } - static PyObject *py_base_getattro_gameobject(PyObject * self, PyObject *attr); - static int py_base_setattro_gameobject(PyObject * self, PyObject *attr, PyObject *value); + /* quite annoying that we need these but the bloody + * py_getattro_up and py_setattro_up macro's have a returns in them! */ + PyObject* py_getattro__internal(PyObject *attr); + int py_setattro__internal(PyObject *attr, PyObject *value); // py_setattro method + + KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); @@ -897,7 +901,6 @@ 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); static PyObject* pyattr_get_meshes(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static PyObject* pyattr_get_is_valid(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); @@ -913,7 +916,6 @@ public: static PyObject* Map_GetItem(PyObject *self_v, PyObject *item); static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val); - private : /** @@ -931,5 +933,7 @@ private : }; + + #endif //__KX_GAMEOBJECT diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 0fcd2c39078..29033c2d802 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -177,14 +177,6 @@ PyObject* KX_LightObject::py_getattro(PyObject *attr) { char *attr_str= PyString_AsString(attr); - if (ValidPythonToGameObject(this)==false) { - if (!strcmp(attr_str, "isValid")) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - return NULL; - } - if (!strcmp(attr_str, "layer")) return PyInt_FromLong(m_lightobj.m_layer); @@ -229,9 +221,6 @@ int KX_LightObject::py_setattro(PyObject *attr, PyObject *pyvalue) { char *attr_str= PyString_AsString(attr); - if (ValidPythonToGameObject(this)==false) - return -1; - if (PyInt_Check(pyvalue)) { int value = PyInt_AsLong(pyvalue); @@ -347,7 +336,9 @@ PyTypeObject KX_LightObject::Type = { 0, 0, py_base_repr, - 0,0,0,0,0,0, + 0,0, + &KX_GameObject::Mapping, + 0,0,0, py_base_getattro, py_base_setattro, 0,0,0,0,0,0,0,0,0, diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index c63167e2d56..c99fa363ffe 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -196,7 +196,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_canvasDesignWidth = 0; m_canvasDesignHeight = 0; - m_attrlist = PyDict_New(); /* new ref */ + m_attr_dict = PyDict_New(); /* new ref */ } @@ -250,8 +250,8 @@ KX_Scene::~KX_Scene() { delete m_bucketmanager; } - PyDict_Clear(m_attrlist); - Py_DECREF(m_attrlist); + PyDict_Clear(m_attr_dict); + Py_DECREF(m_attr_dict); } void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat) @@ -924,6 +924,8 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) { int ret; KX_GameObject* newobj = (KX_GameObject*) gameobj; + + gameobj->SetZombie(true); /* disallow future python access */ // keep the blender->game object association up to date // note that all the replicas of an object will have the same @@ -998,6 +1000,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) if (m_sceneConverter) m_sceneConverter->UnregisterGameObject(newobj); // return value will be 0 if the object is actually deleted (all reference gone) + return ret; } @@ -1591,7 +1594,7 @@ PyTypeObject KX_Scene::Type = { py_base_repr, 0,0,0,0,0,0, py_base_getattro, - py_base_setattro_scene, /* unlike almost all other types we need out own because user attributes are supported */ + py_base_setattro, 0,0,0,0,0,0,0,0,0, Methods }; @@ -1633,12 +1636,12 @@ PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_ 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 py_getattro_up but in this case we want to include m_attrlist dict */ + /* Useually done by py_getattro_up but in this case we want to include m_attr_dict dict */ PyObject *dict_str= PyString_FromString("__dict__"); PyObject *dict= py_getattr_dict(self->PyObjectPlus::py_getattro(dict_str), Type.tp_dict); Py_DECREF(dict_str); - PyDict_Update(dict, self->m_attrlist); + PyDict_Update(dict, self->m_attr_dict); return dict; } @@ -1654,28 +1657,59 @@ PyAttributeDef KX_Scene::Attributes[] = { { NULL } //Sentinel }; + +PyObject* KX_Scene::py_getattro__internal(PyObject *attr) +{ + py_getattro_up(PyObjectPlus); +} + +int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *pyvalue) +{ + return PyObjectPlus::py_setattro(attr, pyvalue); +} + PyObject* KX_Scene::py_getattro(PyObject *attr) { - PyObject *object = PyDict_GetItem(m_attrlist, attr); - if (object) + PyObject *object = py_getattro__internal(attr); + + if (object==NULL) { - Py_INCREF(object); - return object; + PyErr_Clear(); + object = PyDict_GetItem(m_attr_dict, attr); + if(object) { + Py_INCREF(object); + } + else { + PyErr_Format(PyExc_AttributeError, "KX_Scene attribute \"%s\" not found", PyString_AsString(attr)); + } } - py_getattro_up(PyObjectPlus); + return object; } -int KX_Scene::py_delattro(PyObject *attr) + +int KX_Scene::py_setattro(PyObject *attr, PyObject *value) { - PyDict_DelItem(m_attrlist, attr); - return 0; + int ret= py_setattro__internal(attr, value); + + if (ret==PY_SET_ATTR_MISSING) { + if (PyDict_SetItem(m_attr_dict, attr, value)==0) { + PyErr_Clear(); + ret= PY_SET_ATTR_SUCCESS; + } + else { + PyErr_SetString(PyExc_AttributeError, "failed assigning value to KX_Scenes internal dictionary"); + ret= PY_SET_ATTR_FAIL; + } + } + + return ret; } -/* py_base_setattro_scene deals with setting the dict, it will run if this returns an error */ -int KX_Scene::py_setattro(PyObject *attr, PyObject *pyvalue) +int KX_Scene::py_delattro(PyObject *attr) { - return PyObjectPlus::py_setattro(attr, pyvalue); + PyDict_DelItem(m_attr_dict, attr); + return 0; } KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index e1e89e253ed..a06c66ec5dd 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -295,7 +295,7 @@ protected: /** * This stores anything from python */ - PyObject* m_attrlist; + PyObject* m_attr_dict; struct Scene* m_blenderScene; @@ -597,34 +597,14 @@ public: /* for dir(), python3 uses __dir__() */ static PyObject* pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - static int py_base_setattro_scene(PyObject * self, PyObject *attr, PyObject *value) - { - if (value==NULL) - return ((PyObjectPlus*) self)->py_delattro(attr); - - int ret= ((PyObjectPlus*) self)->py_setattro(attr, value); - - if (ret==PY_SET_ATTR_MISSING) { - if (PyDict_SetItem(((KX_Scene *) self)->m_attrlist, attr, value)==0) { - PyErr_Clear(); - ret= PY_SET_ATTR_SUCCESS; - } - else { - PyErr_Format(PyExc_AttributeError, "failed assigning value to KX_Scenes internal dictionary"); - ret= PY_SET_ATTR_FAIL; - } - } - - return ret; - } - - virtual PyObject* py_getattro(PyObject *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ virtual int py_setattro(PyObject *attr, PyObject *pyvalue); virtual int py_delattro(PyObject *attr); virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); } + PyObject* py_getattro__internal(PyObject *attr); + int py_setattro__internal(PyObject *attr, PyObject *pyvalue); /** * Sets the time the scene was suspended diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 10117c3af9e..3c703d75cda 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -22,7 +22,7 @@ http://www.gnu.org/copyleft/lesser.txt. #if defined WIN32 #define WINDOWS_LEAN_AND_MEAN -#include <Windows.h> +#include <windows.h> #endif #include "VideoBase.h" |