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