BGE Python API

This changes how the BGE classes and Python work together, which hasnt changed since blender went opensource.
The main difference is PyObjectPlus - the base class for most game engine classes, no longer inherit from PyObject, and cannot be cast to a PyObject.

This has the advantage that the BGE does not have to keep 2 reference counts valid for C++ and Python.

Previously C++ classes would never be freed while python held a reference, however this reference could be problematic eg: a GameObject that isnt in a scene anymore should not be used by python, doing so could even crash blender in some cases.

Instead PyObjectPlus has a member "PyObject *m_proxy" which is lazily initialized when python needs it. m_proxy reference counts are managed by python, though it should never be freed while the C++ class exists since it holds a reference to avoid making and freeing it all the time.
When the C++ class is free'd it sets the m_proxy reference to NULL, If python accesses this variable it will raise a RuntimeError, (check the isValid attribute to see if its valid without raising an error).
- This replaces the m_zombie bool and IsZombie() tests added recently.

In python return values that used to be..
 return value->AddRef();
Are now
 return value->GetProxy();
or...
 return value->NewProxy(true); // true means python owns this C++ value which will be deleted when the PyObject is freed
This commit is contained in:
Campbell Barton 2009-04-19 12:46:39 +00:00
parent 92cea7c1b1
commit 8d2cb5bea4
33 changed files with 378 additions and 295 deletions

@ -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++)
{

@ -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[] =

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -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();
}
/* <----- */

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

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

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

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

@ -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++) {

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

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

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

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

@ -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 (PyObject_TypeCheck(value, &KX_Camera::Type))
if(value==Py_None)
{
camOb = static_cast<KX_Camera*>(value);
if (actuator->m_camera)
actuator->m_camera->UnregisterActuator(actuator);
actuator->m_camera = camOb;
actuator->m_camera= NULL;
return 0;
}
if (PyObject_TypeCheck(value, &KX_Camera::Type))
{
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->RegisterActuator(actuator);
actuator->m_camera->UnregisterActuator(actuator);
actuator->m_camera = camOb;
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();

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

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

@ -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())
{

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

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