diff options
33 files changed, 377 insertions, 294 deletions
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 792a3e309f3..9f214721c82 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2354,7 +2354,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // Remove the child reference in the local list! // Note: there may be descendents already if the children of the child were processed // by this loop before the child. In that case, we must remove the children also - CListValue* childrenlist = (CListValue*)childobj->PyGetChildrenRecursive(childobj); + CListValue* childrenlist = childobj->GetChildrenRecursive(); childrenlist->Add(childobj->AddRef()); for ( i=0;i<childrenlist->GetCount();i++) { diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 1698f1919d1..66075dd8d42 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -649,7 +649,7 @@ PyObject* CParserPyMake(PyObject* ignored,PyObject* args) CExpression* expr = parser.ProcessText(txt); CValue* val = expr->Calculate(); expr->Release(); - return val; + return val->GetProxy(); } static PyMethodDef CParserMethods[] = diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index 37feba38f8b..eaed2b5c400 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -27,45 +27,61 @@ #define Py_ssize_t int #endif -Py_ssize_t listvalue_bufferlen(PyObject* list) +Py_ssize_t listvalue_bufferlen(PyObject* self) { - return (Py_ssize_t)( ((CListValue*)list)->GetCount()); + CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self)); + if (list==NULL) + return 0; + + return (Py_ssize_t)list->GetCount(); } -PyObject* listvalue_buffer_item(PyObject* list,Py_ssize_t index) +PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index) { - int count = ((CListValue*) list)->GetCount(); + CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self)); + if (list==NULL) { + PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + int count = list->GetCount(); if (index < 0) index = count+index; if (index >= 0 && index < count) { - PyObject* pyobj = ((CListValue*) list)->GetValue(index)->ConvertValueToPython(); + PyObject* pyobj = list->GetValue(index)->ConvertValueToPython(); if (pyobj) return pyobj; else - return ((CListValue*) list)->GetValue(index)->AddRef(); + return list->GetValue(index)->GetProxy(); } PyErr_SetString(PyExc_IndexError, "Python ListIndex out of range"); return NULL; } -PyObject* listvalue_mapping_subscript(PyObject* list,PyObject* pyindex) +PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) { + CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self)); + if (list==NULL) { + PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + return NULL; + } + if (PyString_Check(pyindex)) { STR_String index(PyString_AsString(pyindex)); CValue *item = ((CListValue*) list)->FindValue(index); if (item) - return (PyObject*) item; + return item->GetProxy(); } if (PyInt_Check(pyindex)) { int index = PyInt_AsLong(pyindex); - return listvalue_buffer_item(list, index); + return listvalue_buffer_item(self, index); } PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */ @@ -76,10 +92,16 @@ PyObject* listvalue_mapping_subscript(PyObject* list,PyObject* pyindex) /* just slice it into a python list... */ -PyObject* listvalue_buffer_slice(PyObject* list,Py_ssize_t ilow, Py_ssize_t ihigh) +PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihigh) { + CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self)); + if (list==NULL) { + PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + return NULL; + } + int i, j; - PyListObject *newlist; + PyObject *newlist; if (ilow < 0) ilow = 0; @@ -90,18 +112,18 @@ PyObject* listvalue_buffer_slice(PyObject* list,Py_ssize_t ilow, Py_ssize_t ihig if (ihigh < ilow) ihigh = ilow; - newlist = (PyListObject *) PyList_New(ihigh - ilow); + newlist = PyList_New(ihigh - ilow); if (!newlist) return NULL; for (i = ilow, j = 0; i < ihigh; i++, j++) { - PyObject* pyobj = ((CListValue*) list)->GetValue(i)->ConvertValueToPython(); + PyObject* pyobj = list->GetValue(i)->ConvertValueToPython(); if (!pyobj) - pyobj = ((CListValue*) list)->GetValue(i)->AddRef(); - newlist->ob_item[j] = pyobj; + pyobj = list->GetValue(i)->GetProxy(); + PyList_SET_ITEM(newlist, i, pyobj); } - return (PyObject *) newlist; + return newlist; } @@ -109,11 +131,16 @@ PyObject* listvalue_buffer_slice(PyObject* list,Py_ssize_t ilow, Py_ssize_t ihig static PyObject * listvalue_buffer_concat(PyObject * self, PyObject * other) { + CListValue *listval= static_cast<CListValue *>(BGE_PROXY_REF(self)); + if (listval==NULL) { + PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + return NULL; + } + // for now, we support CListValue concatenated with items // and CListValue concatenated to Python Lists // and CListValue concatenated with another CListValue - - CListValue* listval = (CListValue*) self; + listval->AddRef(); if (other->ob_type == &PyList_Type) { @@ -519,8 +546,8 @@ PyObject* CListValue::Pyfrom_id(PyObject* self, PyObject* value) int numelem = GetCount(); for (int i=0;i<numelem;i++) { - if (reinterpret_cast<BGE_ID_TYPE>(static_cast<PyObject*>(m_pValueArray[i])) == id) - return GetValue(i); + if (reinterpret_cast<BGE_ID_TYPE>(m_pValueArray[i]->m_proxy) == id) + return GetValue(i)->GetProxy(); } PyErr_SetString(PyExc_IndexError, "from_id(#), id not found in CValueList"); diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index cf2976c2bbb..2af5a330c43 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -61,9 +61,11 @@ public: virtual PyObject* py_getattro(PyObject* attr); virtual PyObject* py_repr(void) { - PyObject *py_list= PySequence_List((PyObject *)this); + PyObject *py_proxy= this->GetProxy(); + PyObject *py_list= PySequence_List(py_proxy); PyObject *py_string= PyObject_Repr(py_list); Py_DECREF(py_list); + Py_DECREF(py_proxy); return py_string; } diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 0db2e8991fc..2c5ba3f39fc 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -54,6 +54,7 @@ * PyObjectPlus Type -- Every class, even the abstract one should have a Type ------------------------------*/ + PyTypeObject PyObjectPlus::Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ @@ -74,21 +75,33 @@ PyTypeObject PyObjectPlus::Type = { Methods }; + PyObjectPlus::~PyObjectPlus() { - if (ob_refcnt) - { - _Py_ForgetReference(this); + if(m_proxy) { + Py_DECREF(m_proxy); /* Remove own reference, python may still have 1 */ + BGE_PROXY_REF(m_proxy)= NULL; } // assert(ob_refcnt==0); } +void PyObjectPlus::PyDestructor(PyObject *self) // python wrapper +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); + if(self_plus) { + if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it */ + delete self_plus; + } + + BGE_PROXY_REF(self)= NULL; // not really needed + } + PyObject_DEL( self ); +}; + PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor { MT_assert(T != NULL); - this->ob_type = T; - _Py_NewReference(this); - SetZombie(false); + m_proxy= NULL; }; /*------------------------------ @@ -131,7 +144,7 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr) 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); + return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); } else { fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)"); return descr; @@ -794,5 +807,47 @@ PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict) return pydict; } + + +PyObject *PyObjectPlus::GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp) +{ + if (self->m_proxy==NULL) + { + self->m_proxy = reinterpret_cast<PyObject *>PyObject_NEW( PyObjectPlus_Proxy, tp); + BGE_PROXY_PYOWNS(self->m_proxy) = false; + } + //PyObject_Print(self->m_proxy, stdout, 0); + //printf("ref %d\n", self->m_proxy->ob_refcnt); + + BGE_PROXY_REF(self->m_proxy) = self; /* Its possible this was set to NULL, so set it back here */ + Py_INCREF(self->m_proxy); /* we own one, thos ones fore the return */ + return self->m_proxy; +} + +PyObject *PyObjectPlus::NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns) +{ + if (self->m_proxy) + { + if(py_owns) + { /* Free */ + BGE_PROXY_REF(self->m_proxy) = NULL; + Py_DECREF(self->m_proxy); + self->m_proxy= NULL; + } + else { + Py_INCREF(self->m_proxy); + return self->m_proxy; + } + + } + + GetProxy_Ext(self, tp); + if(py_owns) { + BGE_PROXY_PYOWNS(self->m_proxy) = py_owns; + Py_DECREF(self->m_proxy); /* could avoid thrashing here but for now its ok */ + } + return self->m_proxy; +} + #endif //NO_EXP_PYTHON_EMBEDDING diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 58a74e4ca74..3be9a2f2bcb 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -81,6 +81,20 @@ static inline void Py_Fatal(const char *M) { exit(-1); }; +typedef struct { + PyObject_HEAD /* required python macro */ + class PyObjectPlus *ref; + bool py_owns; +} PyObjectPlus_Proxy; + +#define BGE_PROXY_ERROR_MSG "Blender Game Engine data has been freed, cannot use this python variable" +#define BGE_PROXY_REF(_self) (((PyObjectPlus_Proxy *)_self)->ref) +#define BGE_PROXY_PYOWNS(_self) (((PyObjectPlus_Proxy *)_self)->py_owns) + +/* Note, sometimes we dont care what BGE type this is as long as its a proxy */ +#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == PyDestructor) + + // This must be the first line of each // PyC++ class #define Py_Header \ @@ -90,7 +104,10 @@ static inline void Py_Fatal(const char *M) { static PyAttributeDef Attributes[]; \ static PyParentObject Parents[]; \ virtual PyTypeObject *GetType(void) {return &Type;}; \ - virtual PyParentObject *GetParents(void) {return Parents;} + virtual PyParentObject *GetParents(void) {return Parents;} \ + virtual PyObject *GetProxy() {return GetProxy_Ext(this, &Type);}; \ + virtual PyObject *NewProxy(bool py_owns) {return NewProxy_Ext(this, &Type, py_owns);}; \ + @@ -106,7 +123,7 @@ static inline void Py_Fatal(const char *M) { 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); \ + return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \ } else { \ fprintf(stderr, "unknown attribute type"); \ return descr; \ @@ -165,52 +182,60 @@ static inline void Py_Fatal(const char *M) { #define KX_PYMETHOD(class_name, method_name) \ PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \ - return ((class_name*) self)->Py##method_name(self, args, kwds); \ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); \ + return ((class_name*)self_plus)->Py##method_name(self, args, kwds); \ }; \ #define KX_PYMETHOD_VARARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* self, PyObject* args); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ - return ((class_name*) self)->Py##method_name(self, args); \ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); \ + return ((class_name*)self_plus)->Py##method_name(self, args); \ }; \ #define KX_PYMETHOD_NOARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* self); \ static PyObject* sPy##method_name( PyObject* self) { \ - return ((class_name*) self)->Py##method_name(self); \ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); \ + return ((class_name*)self_plus)->Py##method_name(self); \ }; \ #define KX_PYMETHOD_O(class_name, method_name) \ PyObject* Py##method_name(PyObject* self, PyObject* value); \ static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \ - return ((class_name*) self)->Py##method_name(self, value); \ + PyObjectPlus *self_plus= ((PyObjectPlus_Proxy *)self)->ref; \ + return ((class_name*) self_plus)->Py##method_name(self, value); \ }; \ #define KX_PYMETHOD_DOC(class_name, method_name) \ PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \ - return ((class_name*) self)->Py##method_name(self, args, kwds); \ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); \ + return ((class_name*)self_plus)->Py##method_name(self, args, kwds); \ }; \ static const char method_name##_doc[]; \ #define KX_PYMETHOD_DOC_VARARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* self, PyObject* args); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ - return ((class_name*) self)->Py##method_name(self, args); \ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); \ + return ((class_name*)self_plus)->Py##method_name(self, args); \ }; \ static const char method_name##_doc[]; \ #define KX_PYMETHOD_DOC_O(class_name, method_name) \ PyObject* Py##method_name(PyObject* self, PyObject* value); \ static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \ - return ((class_name*) self)->Py##method_name(self, value); \ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); \ + return ((class_name*)self_plus)->Py##method_name(self, value); \ }; \ static const char method_name##_doc[]; \ #define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* self); \ static PyObject* sPy##method_name( PyObject* self) { \ - return ((class_name*) self)->Py##method_name(self); \ + PyObjectPlus *self_plus= BGE_PROXY_REF(self); \ + return ((class_name*)self_plus)->Py##method_name(self); \ }; \ static const char method_name##_doc[]; \ @@ -233,19 +258,19 @@ static inline void Py_Fatal(const char *M) { */ #define KX_PYMETHODDEF_DOC(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*) +PyObject* class_name::Py##method_name(PyObject* self, PyObject* args, PyObject*) #define KX_PYMETHODDEF_DOC_VARARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject*, PyObject* args) +PyObject* class_name::Py##method_name(PyObject* self, PyObject* args) #define KX_PYMETHODDEF_DOC_O(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject*, PyObject* value) +PyObject* class_name::Py##method_name(PyObject* self, PyObject* value) #define KX_PYMETHODDEF_DOC_NOARGS(class_name, method_name, doc_string) \ const char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject*) +PyObject* class_name::Py##method_name(PyObject* self) /** * Attribute management @@ -394,19 +419,17 @@ typedef struct KX_PYATTRIBUTE_DEF { ------------------------------*/ typedef PyTypeObject * PyParentObject; // Define the PyParent Object -class PyObjectPlus : public PyObject +class PyObjectPlus { // The PyObjectPlus abstract class Py_Header; // Always start with Py_Header public: PyObjectPlus(PyTypeObject *T); - bool m_zombie; + + PyObject *m_proxy; /* actually a PyObjectPlus_Proxy */ virtual ~PyObjectPlus(); // destructor - static void PyDestructor(PyObject *P) // python wrapper - { - delete ((PyObjectPlus *) P); - }; + static void PyDestructor(PyObject *self); // python wrapper // void INCREF(void) { // Py_INCREF(this); @@ -418,15 +441,15 @@ 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_plus= BGE_PROXY_REF(self); + if(self_plus==NULL) { + if(!strcmp("isValid", PyString_AsString(attr))) { + Py_RETURN_TRUE; } - ((PyObjectPlus*)self)->IsZombiePyErr(); /* raise an error */ + PyErr_SetString(PyExc_RuntimeError, "data has been removed"); return NULL; } - - return ((PyObjectPlus*) self)->py_getattro(attr); + return self_plus->py_getattro(attr); } static PyObject* py_get_attrdef(void *self, const PyAttributeDef *attrdef); @@ -441,22 +464,29 @@ 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(); + PyObjectPlus *self_plus= BGE_PROXY_REF(self); + if(self_plus==NULL) { + PyErr_SetString(PyExc_RuntimeError, "data has been removed"); return -1; } if (value==NULL) - return ((PyObjectPlus*)self)->py_delattro(attr); + return self_plus->py_delattro(attr); - return ((PyObjectPlus*)self)->py_setattro(attr, value); + return self_plus->py_setattro(attr, value); } virtual PyObject *py_repr(void); // py_repr method - static PyObject *py_base_repr(PyObject *PyObj) // This should be the entry in Type. + static PyObject *py_base_repr(PyObject *self) // This should be the entry in Type. { - return ((PyObjectPlus*) PyObj)->py_repr(); + + PyObjectPlus *self_plus= BGE_PROXY_REF(self); + if(self_plus==NULL) { + PyErr_SetString(PyExc_RuntimeError, "data has been removed"); + return NULL; + } + + return self_plus->py_repr(); } // isA methods @@ -465,43 +495,20 @@ public: PyObject *Py_isA(PyObject *value); static PyObject *sPy_isA(PyObject *self, PyObject *value) { - 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."); + PyObjectPlus *self_plus= BGE_PROXY_REF(self); + if(self_plus==NULL) { + PyErr_SetString(PyExc_RuntimeError, "data has been removed"); + return NULL; } - return m_zombie; + return self_plus->Py_isA(value); } - void SetZombie(bool is_zombie) - { - m_zombie= is_zombie; - } + /* 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); + static PyObject *GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp); + static PyObject *NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns); }; PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict); diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 63776c39d70..7958c16ca81 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -501,12 +501,6 @@ 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; } @@ -544,9 +538,6 @@ void CValue::AddDataToReplica(CValue *replica) { replica->m_refcount = 1; - //register with Python - _Py_NewReference(replica); - #ifdef _DEBUG //gRefCountValue++; #endif @@ -616,7 +607,7 @@ PyObject* CValue::py_getattro(PyObject *attr) if (pyconvert) return pyconvert; else - return resultattr; // also check if it's already in pythoninterpreter! + return resultattr->GetProxy(); } py_getattro_up(PyObjectPlus); } diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index bcee355cda2..a687e1a493c 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -225,21 +225,6 @@ public: virtual PyObject* py_getattro(PyObject *attr); - - void SpecialRelease() - { - if (ob_refcnt == 0) /* make sure python always holds a reference */ - { - _Py_NewReference(this); - - } - Release(); - } - static void PyDestructor(PyObject *P) // python wrapper - { - ((CValue*)P)->SpecialRelease(); - }; - virtual PyObject* ConvertValueToPython() { return NULL; } @@ -352,7 +337,6 @@ 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_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 46e132c65fc..7fa55cfb1ee 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -294,8 +294,7 @@ PyObject* SCA_ILogicBrick::PyGetOwner(PyObject* self) CValue* parent = GetParent(); if (parent) { - parent->AddRef(); - return parent; + return parent->GetProxy(); } printf("ERROR: Python scriptblock without owner\n"); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 1c5b597f937..687ae421af1 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -157,7 +157,7 @@ static const char* sPyGetCurrentController__doc__; PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self) { - return m_sCurrentController->AddRef(); + return m_sCurrentController->GetProxy(); } SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) @@ -176,10 +176,10 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) } } } - else { - /* Expecting an actuator type */ + else if (BGE_PROXY_CHECK_TYPE(value)) { + PyObjectPlus *value_plus= BGE_PROXY_REF(value); /* Expecting an actuator type */ // XXX TODO - CHECK TYPE for(it = lacts.begin(); it!= lacts.end(); it++) { - if( static_cast<SCA_IActuator*>(value) == (*it) ) { + if( static_cast<SCA_IActuator*>(value_plus) == (*it) ) { return *it; } } @@ -413,7 +413,7 @@ PyObject* SCA_PythonController::PyGetActuators(PyObject* self) PyObject* resultlist = PyList_New(m_linkedactuators.size()); for (unsigned int index=0;index<m_linkedactuators.size();index++) { - PyList_SET_ITEM(resultlist,index,m_linkedactuators[index]->AddRef()); + PyList_SET_ITEM(resultlist,index, m_linkedactuators[index]->GetProxy()); } return resultlist; @@ -437,7 +437,7 @@ SCA_PythonController::PyGetSensor(PyObject* self, PyObject* value) STR_String realname = sensor->GetName(); if (realname == scriptArg) { - return sensor->AddRef(); + return sensor->GetProxy(); } } @@ -466,7 +466,7 @@ SCA_PythonController::PyGetActuator(PyObject* self, PyObject* value) SCA_IActuator* actua = m_linkedactuators[index]; if (actua->GetName() == scriptArg) { - return actua->AddRef(); + return actua->GetProxy(); } } @@ -484,7 +484,7 @@ SCA_PythonController::PyGetSensors(PyObject* self) PyObject* resultlist = PyList_New(m_linkedsensors.size()); for (unsigned int index=0;index<m_linkedsensors.size();index++) { - PyList_SET_ITEM(resultlist,index,m_linkedsensors[index]->AddRef()); + PyList_SET_ITEM(resultlist,index, m_linkedsensors[index]->GetProxy()); } return resultlist; diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 65600856377..8aca2e372d1 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -235,9 +235,9 @@ PyObject* KX_NetworkMessageSensor::pyattr_get_bodies(void *self_v, const KX_PYAT { KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v); if (self->m_BodyList) { - return ((PyObject*) self->m_BodyList->AddRef()); + return self->m_BodyList->GetProxy(); } else { - return ((PyObject*) new CListValue()); + return (new CListValue())->NewProxy(true); } } @@ -245,9 +245,9 @@ PyObject* KX_NetworkMessageSensor::pyattr_get_subjects(void *self_v, const KX_PY { KX_NetworkMessageSensor *self = static_cast<KX_NetworkMessageSensor*>(self_v); if (self->m_SubjectList) { - return ((PyObject*) self->m_SubjectList->AddRef()); + return self->m_SubjectList->GetProxy(); } else { - return ((PyObject*) new CListValue()); + return (new CListValue())->NewProxy(true); } } @@ -290,9 +290,9 @@ PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* ) { ShowDeprecationWarning("getBodies()", "bodies"); if (m_BodyList) { - return ((PyObject*) m_BodyList->AddRef()); + return m_BodyList->GetProxy(); } else { - return ((PyObject*) new CListValue()); + return (new CListValue())->NewProxy(true); } } @@ -316,9 +316,9 @@ PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* ) { ShowDeprecationWarning("getSubjects()", "subjects"); if (m_SubjectList) { - return ((PyObject*) m_SubjectList->AddRef()); + return m_SubjectList->GetProxy(); } else { - return ((PyObject*) new CListValue()); + return (new CListValue())->NewProxy(true); } } // <----- Deprecated
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 0e417dde5d2..bdad21f76eb 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -827,8 +827,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") m_flag &= ~RAS_BLENDERGLSL; mMaterial->SetSharedMaterial(true); mScene->GetBucketManager()->ReleaseDisplayLists(this); - Py_INCREF(mShader); - return mShader; + return mShader->GetProxy(); }else { // decref all references to the object @@ -836,13 +835,8 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") // We will then go back to fixed functionality // for this material if(mShader) { - if(mShader->ob_refcnt > 1) { - Py_DECREF(mShader); - } - else { - delete mShader; - mShader=0; - } + delete mShader; /* will handle python de-referencing */ + mShader=0; } } Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 329d31cfa25..a1159dbc23f 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -449,7 +449,7 @@ PyObject* KX_CameraActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_ob->GetName()); else - return m_ob->AddRef(); + return m_ob->GetProxy(); } /* set obj ---------------------------------------------------------- */ const char KX_CameraActuator::SetObject_doc[] = @@ -597,7 +597,7 @@ PyObject* KX_CameraActuator::pyattr_get_object(void *self_v, const KX_PYATTRIBUT if (self->m_ob==NULL) Py_RETURN_NONE; else - return self->m_ob->AddRef(); + return self->m_ob->GetProxy(); } int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 3e7c99dc472..402c242315a 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1039,7 +1039,43 @@ void KX_GameObject::Suspend() } } +static void walk_children(SG_Node* node, CListValue* list, bool recursive) +{ + if (!node) + return; + NodeList& children = node->GetSGChildren(); + + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + CValue* childobj = (CValue*)childnode->GetSGClientObject(); + if (childobj != NULL) // This is a GameObject + { + // add to the list + list->Add(childobj->AddRef()); + } + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + if (recursive || childobj==NULL) { + walk_children(childnode, list, recursive); + } + } +} + +CListValue* KX_GameObject::GetChildren() +{ + CListValue* list = new CListValue(); + walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */ + return list; +} +CListValue* KX_GameObject::GetChildrenRecursive() +{ + CListValue* list = new CListValue(); + walk_children(GetSGNode(), list, 1); + return list; +} /* ------- python stuff ---------------------------------------------------*/ @@ -1185,13 +1221,10 @@ PyObject* KX_GameObject::PyGetPosition(PyObject* self) Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v) { - KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); - if (self->IsZombie()) /* not sure what to do here */ - { - PyErr_Clear(); + if (self==NULL) /* not sure what to do here */ return 0; - } Py_ssize_t len= self->GetPropertyCount(); if(self->m_attr_dict) @@ -1202,18 +1235,20 @@ Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v) PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) { - KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); const char *attr_str= PyString_AsString(item); CValue* resultattr; PyObject* pyconvert; - if (self->IsZombiePyErr()) + if (self==NULL) { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); return NULL; + } /* first see if the attributes a string and try get the cvalue attribute */ if(attr_str && (resultattr=self->GetProperty(attr_str))) { pyconvert = resultattr->ConvertValueToPython(); - return pyconvert ? pyconvert:resultattr; + return pyconvert ? pyconvert:resultattr->GetProxy(); } /* 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))) { @@ -1234,13 +1269,15 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) { - KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); const char *attr_str= PyString_AsString(key); if(attr_str==NULL) PyErr_Clear(); - if (self->IsZombiePyErr()) + if (self==NULL) { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); return -1; + } if (val==NULL) { /* del ob["key"] */ int del= 0; @@ -1370,7 +1407,7 @@ PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE KX_GameObject* self= static_cast<KX_GameObject*>(self_v); KX_GameObject* parent = self->GetParent(); if (parent) - return parent->AddRef(); + return parent->GetProxy(); Py_RETURN_NONE; } @@ -1667,7 +1704,7 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE for(i=0; i < self->m_meshes.size(); i++) { KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]); - PyList_SET_ITEM(meshes, i, meshproxy); + PyList_SET_ITEM(meshes, i, meshproxy->GetProxy()); } return meshes; @@ -1681,7 +1718,7 @@ PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_D PyObject* resultlist = PyList_New(sensors.size()); for (unsigned int index=0;index<sensors.size();index++) - PyList_SET_ITEM(resultlist, index, sensors[index]->AddRef()); + PyList_SET_ITEM(resultlist, index, sensors[index]->GetProxy()); return resultlist; } @@ -1693,7 +1730,7 @@ PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBU PyObject* resultlist = PyList_New(controllers.size()); for (unsigned int index=0;index<controllers.size();index++) - PyList_SET_ITEM(resultlist, index, controllers[index]->AddRef()); + PyList_SET_ITEM(resultlist, index, controllers[index]->GetProxy()); return resultlist; } @@ -1705,7 +1742,7 @@ PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE PyObject* resultlist = PyList_New(actuators.size()); for (unsigned int index=0;index<actuators.size();index++) - PyList_SET_ITEM(resultlist, index, actuators[index]->AddRef()); + PyList_SET_ITEM(resultlist, index, actuators[index]->GetProxy()); return resultlist; } @@ -2083,28 +2120,17 @@ PyObject* KX_GameObject::PyGetParent(PyObject* self) ShowDeprecationWarning("getParent()", "the parent property"); KX_GameObject* parent = this->GetParent(); if (parent) - return parent->AddRef(); + return parent->GetProxy(); Py_RETURN_NONE; } PyObject* KX_GameObject::PySetParent(PyObject* self, PyObject* value) { - if (!PyObject_TypeCheck(value, &KX_GameObject::Type)) { - PyErr_SetString(PyExc_TypeError, "expected a KX_GameObject type"); + KX_GameObject *obj; + if (!ConvertPythonToGameObject(value, &obj, false)) return NULL; - } - if (self==value) { - PyErr_SetString(PyExc_ValueError, "cannot set the object to be its own parent!"); - return NULL; - } - // The object we want to set as parent - CValue *m_ob = (CValue*)value; - KX_GameObject *obj = ((KX_GameObject*)m_ob); - KX_Scene *scene = KX_GetActiveScene(); - - this->SetParent(scene, obj); - + this->SetParent(KX_GetActiveScene(), obj); Py_RETURN_NONE; } @@ -2115,43 +2141,14 @@ PyObject* KX_GameObject::PyRemoveParent(PyObject* self) Py_RETURN_NONE; } - -static void walk_children(SG_Node* node, CListValue* list, bool recursive) -{ - if (!node) - return; - NodeList& children = node->GetSGChildren(); - - for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) - { - SG_Node* childnode = (*childit); - CValue* childobj = (CValue*)childnode->GetSGClientObject(); - if (childobj != NULL) // This is a GameObject - { - // add to the list - list->Add(childobj->AddRef()); - } - - // if the childobj is NULL then this may be an inverse parent link - // so a non recursive search should still look down this node. - if (recursive || childobj==NULL) { - walk_children(childnode, list, recursive); - } - } -} - PyObject* KX_GameObject::PyGetChildren(PyObject* self) { - CListValue* list = new CListValue(); - walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */ - return list; + return GetChildren()->NewProxy(true); } PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self) { - CListValue* list = new CListValue(); - walk_children(GetSGNode(), list, 1); - return list; + return GetChildrenRecursive()->NewProxy(true); } PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) @@ -2166,7 +2163,7 @@ PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]); - return meshproxy; + return meshproxy->NewProxy(true); // XXX Todo Python own. } Py_RETURN_NONE; @@ -2516,7 +2513,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); if (m_pHitObject) - return m_pHitObject->AddRef(); + return m_pHitObject->GetProxy(); Py_RETURN_NONE; } @@ -2618,7 +2615,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, { PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3); if (returnValue) { // unlikely this would ever fail, if it does python sets an error - PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); + PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy()); PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint)); PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal)); if (poly) @@ -2628,7 +2625,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, // if this field is set, then we can trust that m_hitPolygon is a valid polygon RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon); - PyTuple_SET_ITEM(returnValue, 3, polyproxy); + PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true)); } else { @@ -2708,7 +2705,7 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py } if (PyString_Check(value)) { - *object = (KX_GameObject *)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) )); + *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) )); if (*object) { return true; @@ -2719,11 +2716,13 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py } if (PyObject_TypeCheck(value, &KX_GameObject::Type)) { - *object = static_cast<KX_GameObject*>(value); + *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value); /* sets the error */ - if ((*object)->IsZombiePyErr()) + if (*object==NULL) { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); return false; + } return true; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index dd85c2f2faa..89517bd76ce 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -807,6 +807,10 @@ public: } KX_ClientObjectInfo* getClientInfo() { return m_pClient_info; } + + CListValue* GetChildren(); + CListValue* GetChildrenRecursive(); + /** * @section Python interface functions. */ @@ -816,8 +820,6 @@ public: virtual int py_delattro(PyObject *attr); virtual PyObject* py_repr(void) { - if (IsZombiePyErr()) - return NULL; return PyString_FromString(GetName().ReadPtr()); } diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 93d92480b3d..09e19933dd9 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -232,7 +232,7 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self, RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex); if (vertex) { - vertexob = new KX_VertexProxy(this, vertex); + vertexob = (new KX_VertexProxy(this, vertex))->NewProxy(true); } } else { @@ -263,7 +263,7 @@ PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self, RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex); if (polygon) { - polyob = new KX_PolyProxy(m_meshobj, polygon); + polyob = (new KX_PolyProxy(m_meshobj, polygon))->NewProxy(true); } else { PyErr_SetString(PyExc_AttributeError, "polygon is NULL, unknown reason"); @@ -297,13 +297,11 @@ PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_ if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *mat = static_cast<KX_BlenderMaterial*>(polymat); - PyList_SET_ITEM(materials, i, mat); - Py_INCREF(mat); + PyList_SET_ITEM(materials, i, mat->GetProxy()); } else { KX_PolygonMaterial *mat = static_cast<KX_PolygonMaterial*>(polymat); - PyList_SET_ITEM(materials, i, mat); - Py_INCREF(mat); + PyList_SET_ITEM(materials, i, mat->GetProxy()); } } return materials; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 65190937f35..e1b89eb3095 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -396,7 +396,7 @@ PyObject* KX_MouseFocusSensor::PyGetHitObject(PyObject* self) ShowDeprecationWarning("GetHitObject()", "the hitObject property"); if (m_hitObject) - return m_hitObject->AddRef(); + return m_hitObject->GetProxy(); Py_RETURN_NONE; } @@ -487,7 +487,7 @@ PyObject* KX_MouseFocusSensor::pyattr_get_hit_object(void *self_v, const KX_PYAT KX_MouseFocusSensor* self= static_cast<KX_MouseFocusSensor*>(self_v); if(self->m_hitObject) - return self->m_hitObject->AddRef(); + return self->m_hitObject->GetProxy(); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index d0d441e2c1c..a667b459c22 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -184,7 +184,7 @@ PyObject* KX_ParentActuator::pyattr_get_object(void *self, const struct KX_PYATT if (!actuator->m_ob) Py_RETURN_NONE; else - return actuator->m_ob->AddRef(); + return actuator->m_ob->GetProxy(); } int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -261,7 +261,7 @@ PyObject* KX_ParentActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_ob->GetName()); else - return m_ob->AddRef(); + return m_ob->GetProxy(); } /* <----- */ diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index e102ca4e0e6..c03d585395c 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -109,14 +109,12 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr) if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } else { KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } } if (!strcmp(attr_str, "matid")) @@ -258,7 +256,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMesh, "getMesh() : returns a mesh proxy\n") { KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh); - return meshproxy; + return meshproxy->NewProxy(true); } KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial, @@ -268,13 +266,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_PolyProxy, getMaterial, if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial* mat = static_cast<KX_BlenderMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } else { KX_PolygonMaterial* mat = static_cast<KX_PolygonMaterial*>(polymat); - Py_INCREF(mat); - return mat; + return mat->GetProxy(); } } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 056442f77d9..bf1fbe386e6 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -98,8 +98,7 @@ bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingI { PyObject *pyRasty = PyCObject_FromVoidPtr((void*)rasty, NULL); /* new reference */ PyObject *pyCachingInfo = PyCObject_FromVoidPtr((void*) &cachingInfo, NULL); /* new reference */ - - PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this); + PyObject *ret = PyObject_CallMethod(m_pymaterial, "activate", "(NNO)", pyRasty, pyCachingInfo, (PyObject*) this->m_proxy); if (ret) { bool value = PyInt_AsLong(ret); diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 34c975f6bf6..2c65c184a9c 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -381,7 +381,7 @@ static PyObject* gPyGetVehicleConstraint(PyObject* self, if (vehicle) { KX_VehicleWrapper* pyWrapper = new KX_VehicleWrapper(vehicle,PHY_GetActiveEnvironment()); - return pyWrapper; + return pyWrapper->NewProxy(true); } } @@ -440,7 +440,7 @@ static PyObject* gPyCreateConstraint(PyObject* self, KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); - return wrap; + return wrap->NewProxy(true); } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 7643a043a7c..1c3bb250b03 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -359,8 +359,7 @@ static STR_String gPyGetCurrentScene_doc = "Gets a reference to the current scene.\n"; static PyObject* gPyGetCurrentScene(PyObject* self) { - Py_INCREF(gp_KetsjiScene); - return (PyObject*) gp_KetsjiScene; + return gp_KetsjiScene->GetProxy(); } static STR_String gPyGetSceneList_doc = @@ -369,7 +368,6 @@ static STR_String gPyGetSceneList_doc = static PyObject* gPyGetSceneList(PyObject* self) { KX_KetsjiEngine* m_engine = KX_GetActiveEngine(); - //CListValue* list = new CListValue(); PyObject* list; KX_SceneList* scenes = m_engine->CurrentScenes(); int numScenes = scenes->size(); @@ -380,13 +378,10 @@ static PyObject* gPyGetSceneList(PyObject* self) for (i=0;i<numScenes;i++) { KX_Scene* scene = scenes->at(i); - //list->Add(scene); - PyList_SET_ITEM(list, i, scene); - Py_INCREF(scene); - + PyList_SET_ITEM(list, i, scene->GetProxy()); } - return (PyObject*)list; + return list; } static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 06163ec8c4f..2bf60dbc102 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -98,7 +98,7 @@ void initPyObjectPlusType(PyTypeObject **parents) } #if 0 - PyObject_Print((PyObject *)parents[i], stderr, 0); + PyObject_Print(reinterpret_cast<PyObject *>parents[i], stderr, 0); fprintf(stderr, "\n"); PyObject_Print(parents[i]->tp_dict, stderr, 0); fprintf(stderr, "\n\n"); @@ -117,7 +117,7 @@ void initPyObjectPlusType(PyTypeObject **parents) dict= parents[i]->tp_dict; #if 1 - PyObject_Print((PyObject *)parents[i], stderr, 0); + PyObject_Print(reinterpret_cast<PyObject *>(parents[i]), stderr, 0); fprintf(stderr, "\n"); PyObject_Print(parents[i]->tp_dict, stderr, 0); fprintf(stderr, "\n\n"); @@ -135,7 +135,7 @@ static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *a PyObject *item; PyType_Ready(tp); - PyDict_SetItemString(dict, tp->tp_name, (PyObject *)tp); + PyDict_SetItemString(dict, tp->tp_name, reinterpret_cast<PyObject *>(tp)); /* store attr defs in the tp_dict for to avoid string lookups */ for(attr= attributes; attr->m_name; attr++) { diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 42e2fdc3e14..9dfc8243330 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -375,7 +375,7 @@ PyObject* KX_RaySensor::pyattr_get_hitobject(void *self_v, const KX_PYATTRIBUTE_ { KX_RaySensor* self = static_cast<KX_RaySensor*>(self_v); if (self->m_hitObject) - return self->m_hitObject->AddRef(); + return self->m_hitObject->GetProxy(); Py_RETURN_NONE; } @@ -389,7 +389,7 @@ PyObject* KX_RaySensor::PyGetHitObject(PyObject* self) ShowDeprecationWarning("getHitObject()", "the hitObject property"); if (m_hitObject) { - return m_hitObject->AddRef(); + return m_hitObject->GetProxy(); } Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index 65b654ccba4..975e6d9d6cc 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -223,7 +223,7 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_object(void *self, const struct K if (!actuator->m_OriginalObject) Py_RETURN_NONE; else - return actuator->m_OriginalObject->AddRef(); + return actuator->m_OriginalObject->GetProxy(); } int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -251,7 +251,7 @@ PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, con if (!actuator->m_lastCreatedObject) Py_RETURN_NONE; else - return actuator->m_lastCreatedObject->AddRef(); + return actuator->m_lastCreatedObject->GetProxy(); } @@ -350,7 +350,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_OriginalObject->GetName()); else - return m_OriginalObject->AddRef(); + return m_OriginalObject->GetProxy(); } @@ -492,8 +492,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self) // it means the object has ended, The BGE python api crashes in many places if the object is returned. if (result && (static_cast<KX_GameObject *>(result))->GetSGNode()) { - result->AddRef(); - return result; + return result->GetProxy(); } // don't return NULL to python anymore, it gives trouble in the scripts Py_RETURN_NONE; diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 9097ca6c85e..999b017b64c 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -110,7 +110,7 @@ PyObject* KX_SCA_ReplaceMeshActuator::pyattr_get_mesh(void *self, const struct K if (!actuator->m_mesh) Py_RETURN_NONE; KX_MeshProxy* meshproxy = new KX_MeshProxy(actuator->m_mesh); - return meshproxy; + return meshproxy->NewProxy(true); } int KX_SCA_ReplaceMeshActuator::pyattr_set_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index c99fa363ffe..d8d6f215213 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -924,8 +924,6 @@ 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 @@ -1623,13 +1621,13 @@ PyObject* KX_Scene::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attr 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(); + return self->GetObjectList()->GetProxy(); } 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(); + return self->GetActiveCamera()->GetProxy(); } /* __dict__ only for the purpose of giving useful dir() results */ @@ -1717,7 +1715,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, "Returns a list of all lights in the scene.\n" ) { - return (PyObject*) m_lightlist->AddRef(); + return m_lightlist->GetProxy(); } KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList, @@ -1726,7 +1724,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList, ) { // ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work? - return (PyObject*) m_objectlist->AddRef(); + return m_objectlist->GetProxy(); } KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, @@ -1755,6 +1753,5 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); - replica->AddRef(); - return replica; + return replica->GetProxy(); }
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 2d3022a68f7..b52cc81f68b 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -291,23 +291,39 @@ PyObject* KX_SceneActuator::pyattr_get_camera(void *self, const struct KX_PYATTR KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self); if (!actuator->m_camera) Py_RETURN_NONE; - actuator->m_camera->AddRef(); - return actuator->m_camera; + + return actuator->m_camera->GetProxy(); } int KX_SceneActuator::pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self); KX_Camera *camOb; - + + if(value==Py_None) + { + if (actuator->m_camera) + actuator->m_camera->UnregisterActuator(actuator); + + actuator->m_camera= NULL; + return 0; + } + if (PyObject_TypeCheck(value, &KX_Camera::Type)) { - camOb = static_cast<KX_Camera*>(value); + KX_Camera *camOb= static_cast<KX_Camera*>BGE_PROXY_REF(value); + + if(camOb==NULL) + { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + return 1; + } + if (actuator->m_camera) actuator->m_camera->UnregisterActuator(actuator); + actuator->m_camera = camOb; - if (actuator->m_camera) - actuator->m_camera->RegisterActuator(actuator); + actuator->m_camera->RegisterActuator(actuator); return 0; } @@ -423,11 +439,21 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, PyObject *cam; if (PyArg_ParseTuple(args, "O!:setCamera", &KX_Camera::Type, &cam)) { + KX_Camera *new_camera; + + new_camera = static_cast<KX_Camera*>BGE_PROXY_REF(cam); + if(new_camera==NULL) + { + PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + return NULL; + } + if (m_camera) m_camera->UnregisterActuator(this); - m_camera = (KX_Camera*) cam; - if (m_camera) - m_camera->RegisterActuator(this); + + m_camera= new_camera; + + m_camera->RegisterActuator(this); Py_RETURN_NONE; } PyErr_Clear(); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 70fa6326c19..7265ade6789 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -342,7 +342,7 @@ PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self) /* otherwise, this leaks memory */ if (m_hitObject) { - return m_hitObject->AddRef(); + return m_hitObject->GetProxy(); } Py_RETURN_NONE; } @@ -356,7 +356,7 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self) ShowDeprecationWarning("getHitObjectList()", "the objectHitList property"); /* to do: do Py_IncRef if the object is already known in Python */ /* otherwise, this leaks memory */ /* Edit, this seems ok and not to leak memory - Campbell */ - return m_colliders->AddRef(); + return m_colliders->GetProxy(); } /*getTouchMaterial and setTouchMaterial were never added to the api, @@ -400,7 +400,7 @@ PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBU KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v); if (self->m_hitObject) - return self->m_hitObject->AddRef(); + return self->m_hitObject->GetProxy(); else Py_RETURN_NONE; } @@ -408,7 +408,7 @@ PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBU PyObject* KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v); - return self->m_colliders->AddRef(); + return self->m_colliders->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 29c6a21b0b3..5ea08f855a3 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -481,7 +481,7 @@ PyObject* KX_TrackToActuator::pyattr_get_object(void *self, const struct KX_PYAT if (!actuator->m_object) Py_RETURN_NONE; else - return actuator->m_object->AddRef(); + return actuator->m_object->GetProxy(); } int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -560,7 +560,7 @@ PyObject* KX_TrackToActuator::PyGetObject(PyObject* self, PyObject* args) if (ret_name_only) return PyString_FromString(m_object->GetName()); else - return m_object->AddRef(); + return m_object->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 98f5a1ea87d..0ba55fe5986 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -48,7 +48,10 @@ PyObject* KX_VehicleWrapper::PyAddWheel(PyObject* self, if (PyArg_ParseTuple(args,"OOOOffi:addWheel",&wheelGameObject,&pylistPos,&pylistDir,&pylistAxleDir,&suspensionRestLength,&wheelRadius,&hasSteering)) { - KX_GameObject* gameOb = (KX_GameObject*) wheelGameObject; + KX_GameObject *gameOb; + if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false)) + return NULL; + if (gameOb->GetSGNode()) { diff --git a/source/gameengine/VideoTexture/FilterSource.h b/source/gameengine/VideoTexture/FilterSource.h index 6385ed5108f..254e0a02679 100644 --- a/source/gameengine/VideoTexture/FilterSource.h +++ b/source/gameengine/VideoTexture/FilterSource.h @@ -225,7 +225,7 @@ protected: // otherwise if only vertical interpolation is needed } } - else if ((y & 1) == 1) + else if ((y & 1) == 1) { // if this pixel is on the edge if (isEdge(x, y, size)) { @@ -239,6 +239,7 @@ protected: d = interpolV(m_buffU + offset) - 128; e = interpolV(m_buffV + offset) - 128; } + } // convert to RGB // R = clip(( 298 * C + 409 * E + 128) >> 8) // G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8) diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 6ef62f64d3f..9a3c4fea70e 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -434,26 +434,35 @@ static int ImageMirror_init (PyObject * pySelf, PyObject * args, PyObject * kwds { // get scene pointer KX_Scene * scenePtr (NULL); - if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) - scenePtr = static_cast<KX_Scene*>(scene); - else + if (scene != NULL && PyObject_TypeCheck(scene, &KX_Scene::Type)) + scenePtr = static_cast<KX_Scene*>BGE_PROXY_REF(scene); + else THRWEXCP(SceneInvalid, S_OK); - + + if(scenePtr==NULL) /* incase the python proxy reference is invalid */ + THRWEXCP(SceneInvalid, S_OK); + // get observer pointer KX_GameObject * observerPtr (NULL); if (observer != NULL && PyObject_TypeCheck(observer, &KX_GameObject::Type)) - observerPtr = static_cast<KX_GameObject*>(observer); + observerPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(observer); else if (observer != NULL && PyObject_TypeCheck(observer, &KX_Camera::Type)) - observerPtr = static_cast<KX_Camera*>(observer); + observerPtr = static_cast<KX_Camera*>BGE_PROXY_REF(observer); else THRWEXCP(ObserverInvalid, S_OK); + + if(observerPtr==NULL) /* incase the python proxy reference is invalid */ + THRWEXCP(ObserverInvalid, S_OK); // get mirror pointer KX_GameObject * mirrorPtr (NULL); if (mirror != NULL && PyObject_TypeCheck(mirror, &KX_GameObject::Type)) - mirrorPtr = static_cast<KX_GameObject*>(mirror); + mirrorPtr = static_cast<KX_GameObject*>BGE_PROXY_REF(mirror); else THRWEXCP(MirrorInvalid, S_OK); + + if(mirrorPtr==NULL) /* incase the python proxy reference is invalid */ + THRWEXCP(MirrorInvalid, S_OK); // locate the material in the mirror RAS_IPolyMaterial * material = getMaterial(mirror, materialID); |