Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-04-20 19:06:46 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-04-20 19:06:46 +0400
commit874c29cea8e6f9bc411fccf2d6f4cb07e94328d0 (patch)
tree5971e577cf7c02e05a1e37b5ad058c71a6744877 /source/gameengine/Expressions
parent7555bfa793a2b0fc187c6211c56986f35b2d7b09 (diff)
parentc5bc4e4fb1a33eda8c31f2ea02e91f32f74c8fa5 (diff)
2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19323:HEAD
Notes: * blenderbuttons and ICON_SNAP_PEEL_OBJECT were not merged.
Diffstat (limited to 'source/gameengine/Expressions')
-rw-r--r--source/gameengine/Expressions/BoolValue.cpp4
-rw-r--r--source/gameengine/Expressions/BoolValue.h2
-rw-r--r--source/gameengine/Expressions/ConstExpr.cpp2
-rw-r--r--source/gameengine/Expressions/ConstExpr.h2
-rw-r--r--source/gameengine/Expressions/EmptyValue.cpp2
-rw-r--r--source/gameengine/Expressions/EmptyValue.h2
-rw-r--r--source/gameengine/Expressions/ErrorValue.cpp2
-rw-r--r--source/gameengine/Expressions/ErrorValue.h2
-rw-r--r--source/gameengine/Expressions/FloatValue.cpp4
-rw-r--r--source/gameengine/Expressions/FloatValue.h2
-rw-r--r--source/gameengine/Expressions/InputParser.cpp17
-rw-r--r--source/gameengine/Expressions/InputParser.h2
-rw-r--r--source/gameengine/Expressions/IntValue.cpp21
-rw-r--r--source/gameengine/Expressions/IntValue.h12
-rw-r--r--source/gameengine/Expressions/ListValue.cpp138
-rw-r--r--source/gameengine/Expressions/ListValue.h13
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp1137
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h298
-rw-r--r--source/gameengine/Expressions/StringValue.cpp2
-rw-r--r--source/gameengine/Expressions/StringValue.h2
-rw-r--r--source/gameengine/Expressions/Value.cpp357
-rw-r--r--source/gameengine/Expressions/Value.h38
-rw-r--r--source/gameengine/Expressions/VectorValue.cpp2
-rw-r--r--source/gameengine/Expressions/VectorValue.h2
-rw-r--r--source/gameengine/Expressions/VoidValue.h2
25 files changed, 1118 insertions, 949 deletions
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp
index cadb34d7e8f..13c870b68e5 100644
--- a/source/gameengine/Expressions/BoolValue.cpp
+++ b/source/gameengine/Expressions/BoolValue.cpp
@@ -181,9 +181,9 @@ ret: the bool stored in the object
-float CBoolValue::GetNumber()
+double CBoolValue::GetNumber()
{
- return (float)m_bool;
+ return (double)m_bool;
}
diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h
index 6c4d964249f..9352b9d4b92 100644
--- a/source/gameengine/Expressions/BoolValue.h
+++ b/source/gameengine/Expressions/BoolValue.h
@@ -33,7 +33,7 @@ public:
CBoolValue(bool innie, STR_String name, AllocationTYPE alloctype = CValue::HEAPVALUE);
virtual const STR_String& GetText();
- virtual float GetNumber();
+ virtual double GetNumber();
bool GetBool();
virtual void SetValue(CValue* newval);
diff --git a/source/gameengine/Expressions/ConstExpr.cpp b/source/gameengine/Expressions/ConstExpr.cpp
index e33ba091ac4..6b64be9c9a9 100644
--- a/source/gameengine/Expressions/ConstExpr.cpp
+++ b/source/gameengine/Expressions/ConstExpr.cpp
@@ -84,7 +84,7 @@ void CConstExpr::ClearModified()
-float CConstExpr::GetNumber()
+double CConstExpr::GetNumber()
{
return -1;
}
diff --git a/source/gameengine/Expressions/ConstExpr.h b/source/gameengine/Expressions/ConstExpr.h
index e27ece52a83..b117140fe70 100644
--- a/source/gameengine/Expressions/ConstExpr.h
+++ b/source/gameengine/Expressions/ConstExpr.h
@@ -32,7 +32,7 @@ public:
//bool IsInside(float x,float y,float z,bool bBorderInclude=true);
bool NeedsRecalculated();
void ClearModified();
- virtual float GetNumber();
+ virtual double GetNumber();
virtual CValue* Calculate();
CConstExpr(CValue* constval);
CConstExpr();
diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/EmptyValue.cpp
index c2b60e590a4..f72ddc47096 100644
--- a/source/gameengine/Expressions/EmptyValue.cpp
+++ b/source/gameengine/Expressions/EmptyValue.cpp
@@ -76,7 +76,7 @@ this object
-float CEmptyValue::GetNumber()
+double CEmptyValue::GetNumber()
{
return 0;
}
diff --git a/source/gameengine/Expressions/EmptyValue.h b/source/gameengine/Expressions/EmptyValue.h
index b9cca0e57e5..fb6b4a477a6 100644
--- a/source/gameengine/Expressions/EmptyValue.h
+++ b/source/gameengine/Expressions/EmptyValue.h
@@ -27,7 +27,7 @@ public:
virtual ~CEmptyValue();
virtual const STR_String & GetText();
- virtual float GetNumber();
+ virtual double GetNumber();
CListValue* GetPolySoup();
virtual double* GetVector3(bool bGetTransformedVec=false);
bool IsInside(CValue* testpoint,bool bBorderInclude=true);
diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/ErrorValue.cpp
index e52be4c8021..651a772db19 100644
--- a/source/gameengine/Expressions/ErrorValue.cpp
+++ b/source/gameengine/Expressions/ErrorValue.cpp
@@ -99,7 +99,7 @@ ret: a new object containing the result of applying operator op to val and
-float CErrorValue::GetNumber()
+double CErrorValue::GetNumber()
{
return -1;
}
diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/ErrorValue.h
index 16e608ca01a..5b5795196ba 100644
--- a/source/gameengine/Expressions/ErrorValue.h
+++ b/source/gameengine/Expressions/ErrorValue.h
@@ -23,7 +23,7 @@ class CErrorValue : public CPropValue
public:
virtual const STR_String & GetText();
- virtual float GetNumber();
+ virtual double GetNumber();
CErrorValue();
CErrorValue(STR_String errmsg);
virtual ~CErrorValue();
diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp
index 460eaa73f35..212a55fe457 100644
--- a/source/gameengine/Expressions/FloatValue.cpp
+++ b/source/gameengine/Expressions/FloatValue.cpp
@@ -278,7 +278,7 @@ ret: the float stored in the object
-float CFloatValue::GetNumber()
+double CFloatValue::GetNumber()
{
return m_float;
}
@@ -287,7 +287,7 @@ float CFloatValue::GetNumber()
void CFloatValue::SetValue(CValue* newval)
{
- m_float = newval->GetNumber();
+ m_float = (float)newval->GetNumber();
SetModified(true);
}
diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/FloatValue.h
index 33f05f1d7f2..41f70b5c54c 100644
--- a/source/gameengine/Expressions/FloatValue.h
+++ b/source/gameengine/Expressions/FloatValue.h
@@ -28,7 +28,7 @@ public:
virtual const STR_String & GetText();
void Configure(CValue* menuvalue);
- virtual float GetNumber();
+ virtual double GetNumber();
virtual void SetValue(CValue* newval);
float GetFloat();
void SetFloat(float fl);
diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp
index 94663c4a365..66075dd8d42 100644
--- a/source/gameengine/Expressions/InputParser.cpp
+++ b/source/gameengine/Expressions/InputParser.cpp
@@ -39,7 +39,12 @@
#include "IfExpr.h"
#if defined(WIN32) || defined(WIN64)
-#define strcasecmp _stricmp
+#define strcasecmp _stricmp
+
+#ifndef strtoll
+#define strtoll _strtoi64
+#endif
+
#endif /* Def WIN32 or Def WIN64 */
#define NUM_PRIORITY 6
@@ -319,12 +324,14 @@ void CParser::NextSym()
}
}
+#if 0
int CParser::MakeInt() {
// returns the integer representation of the value in the global
// variable const_as_string
// pre: const_as_string contains only numercal chars
return atoi(const_as_string);
}
+#endif
STR_String CParser::Symbol2Str(int s) {
// returns a string representation of of symbol s,
@@ -436,8 +443,8 @@ CExpression *CParser::Ex(int i) {
break;
case inttype:
{
- int temp;
- temp = atoi(const_as_string);
+ cInt temp;
+ temp = strtoll(const_as_string, NULL, 10); /* atoi is for int only */
e1 = new CConstExpr(new CIntValue(temp));
break;
}
@@ -580,7 +587,7 @@ float CParser::GetFloat(STR_String txt)
CExpression* expr = ProcessText(txt);
if (expr) {
val = expr->Calculate();
- result=val->GetNumber();
+ result=(float)val->GetNumber();
@@ -642,7 +649,7 @@ PyObject* CParserPyMake(PyObject* ignored,PyObject* args)
CExpression* expr = parser.ProcessText(txt);
CValue* val = expr->Calculate();
expr->Release();
- return val;
+ return val->GetProxy();
}
static PyMethodDef CParserMethods[] =
diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h
index f51c473ba18..3d517222639 100644
--- a/source/gameengine/Expressions/InputParser.h
+++ b/source/gameengine/Expressions/InputParser.h
@@ -94,7 +94,9 @@ private:
void CharRep();
void GrabString(int start);
void NextSym();
+#if 0 /* not used yet */
int MakeInt();
+#endif
STR_String Symbol2Str(int s);
void Term(int s);
int Priority(int optor);
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
index fb586cb4979..4e86f7bf789 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -42,10 +42,10 @@ effect: constructs a new CIntValue
-CIntValue::CIntValue(int innie)
+CIntValue::CIntValue(cInt innie)
/*
pre:
-effect: constructs a new CIntValue containing int innie
+effect: constructs a new CIntValue containing cInt innie
*/
{
m_int = innie;
@@ -54,7 +54,7 @@ effect: constructs a new CIntValue containing int innie
-CIntValue::CIntValue(int innie,STR_String name,AllocationTYPE alloctype)
+CIntValue::CIntValue(cInt innie,STR_String name,AllocationTYPE alloctype)
{
m_int = innie;
SetName(name);
@@ -280,10 +280,10 @@ this object
-int CIntValue::GetInt()
+cInt CIntValue::GetInt()
/*
pre:
-ret: the int stored in the object
+ret: the cInt stored in the object
*/
{
return m_int;
@@ -291,7 +291,7 @@ ret: the int stored in the object
-float CIntValue::GetNumber()
+double CIntValue::GetNumber()
{
return (float) m_int;
}
@@ -302,7 +302,7 @@ const STR_String & CIntValue::GetText()
{
if (!m_pstrRep)
m_pstrRep=new STR_String();
- m_pstrRep->Format("%d",m_int);
+ m_pstrRep->Format("%lld",m_int);
return *m_pstrRep;
}
@@ -321,7 +321,7 @@ CValue* CIntValue::GetReplica() {
void CIntValue::SetValue(CValue* newval)
{
- m_int = (int)newval->GetNumber();
+ m_int = (cInt)newval->GetNumber();
SetModified(true);
}
@@ -329,5 +329,8 @@ void CIntValue::SetValue(CValue* newval)
PyObject* CIntValue::ConvertValueToPython()
{
- return PyInt_FromLong(m_int);
+ if((m_int > INT_MIN) && (m_int < INT_MAX))
+ return PyInt_FromLong(m_int);
+ else
+ return PyLong_FromLongLong(m_int);
}
diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/IntValue.h
index 4fdc1089857..0f3a38b274b 100644
--- a/source/gameengine/Expressions/IntValue.h
+++ b/source/gameengine/Expressions/IntValue.h
@@ -18,18 +18,20 @@
#include "Value.h"
+typedef long long cInt;
+
class CIntValue : public CPropValue
{
//PLUGIN_DECLARE_SERIAL (CIntValue,CValue)
public:
virtual const STR_String& GetText();
- virtual float GetNumber();
+ virtual double GetNumber();
- int GetInt();
+ cInt GetInt();
CIntValue();
- CIntValue(int innie);
- CIntValue(int innie,
+ CIntValue(cInt innie);
+ CIntValue(cInt innie,
STR_String name,
AllocationTYPE alloctype=CValue::HEAPVALUE);
@@ -51,7 +53,7 @@ protected:
virtual ~CIntValue();
private:
- int m_int;
+ cInt m_int;
STR_String* m_pstrRep;
};
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index 90a939af236..dd9b296dce1 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -27,59 +27,81 @@
#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");
+ PyErr_SetString(PyExc_IndexError, "list[i]: Python ListIndex out of range in CValueList");
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 */
- PyErr_Format(PyExc_KeyError, "'%s' not in list", PyString_AsString(pyindex_str));
+ PyErr_Format(PyExc_KeyError, "list[key]: '%s' key not in list", PyString_AsString(pyindex_str));
Py_DECREF(pyindex_str);
return NULL;
}
/* 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)
{
@@ -135,7 +162,7 @@ listvalue_buffer_concat(PyObject * self, PyObject * other)
}
if (error) {
- PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add one or more items to a list");
+ PyErr_SetString(PyExc_SystemError, "list.append(val): couldn't add one or more items to this CValueList");
return NULL;
}
@@ -160,7 +187,7 @@ listvalue_buffer_concat(PyObject * self, PyObject * other)
listval->Add(objval);
} else
{
- PyErr_SetString(PyExc_SystemError, "Python Error: couldn't add item to a list");
+ PyErr_SetString(PyExc_SystemError, "list.append(i): couldn't add item to this CValueList");
return NULL;
}
}
@@ -193,23 +220,28 @@ static PyMappingMethods instance_as_mapping = {
PyTypeObject CListValue::Type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"CListValue", /*tp_name*/
- sizeof(CListValue), /*tp_basicsize*/
+ sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
- PyDestructor, /*tp_dealloc*/
+ py_base_dealloc, /*tp_dealloc*/
0, /*tp_print*/
- __getattr, /*tp_getattr*/
- __setattr, /*tp_setattr*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
0, /*tp_compare*/
- __repr, /*tp_repr*/
+ py_base_repr, /*tp_repr*/
0, /*tp_as_number*/
&listvalue_as_sequence, /*tp_as_sequence*/
&instance_as_mapping, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call */
+ 0,
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
@@ -228,6 +260,7 @@ PyMethodDef CListValue::Methods[] = {
{"reverse", (PyCFunction)CListValue::sPyreverse,METH_NOARGS},
{"index", (PyCFunction)CListValue::sPyindex,METH_O},
{"count", (PyCFunction)CListValue::sPycount,METH_O},
+ {"from_id", (PyCFunction)CListValue::sPyfrom_id,METH_O},
{NULL,NULL} //Sentinel
};
@@ -236,8 +269,8 @@ PyAttributeDef CListValue::Attributes[] = {
{ NULL } //Sentinel
};
-PyObject* CListValue::_getattr(const char *attr) {
- _getattr_up(CValue);
+PyObject* CListValue::py_getattro(PyObject* attr) {
+ py_getattro_up(CValue);
}
@@ -405,14 +438,14 @@ void CListValue::MergeList(CListValue *otherlist)
-PyObject* CListValue::Pyappend(PyObject* self, PyObject* value)
+PyObject* CListValue::Pyappend(PyObject* value)
{
- return listvalue_buffer_concat(self, value);
+ return listvalue_buffer_concat(m_proxy, value); /* m_proxy is the same as self */
}
-PyObject* CListValue::Pyreverse(PyObject* self)
+PyObject* CListValue::Pyreverse()
{
std::reverse(m_pValueArray.begin(),m_pValueArray.end());
Py_RETURN_NONE;
@@ -425,6 +458,10 @@ bool CListValue::CheckEqual(CValue* first,CValue* second)
bool result = false;
CValue* eqval = ((CValue*)first)->Calc(VALUE_EQL_OPERATOR,(CValue*)second);
+
+ if (eqval==NULL)
+ return false;
+
STR_String txt = eqval->GetText();
eqval->Release();
if (txt=="TRUE")
@@ -437,7 +474,7 @@ bool CListValue::CheckEqual(CValue* first,CValue* second)
-PyObject* CListValue::Pyindex(PyObject* self, PyObject *value)
+PyObject* CListValue::Pyindex(PyObject *value)
{
PyObject* result = NULL;
@@ -458,7 +495,7 @@ PyObject* CListValue::Pyindex(PyObject* self, PyObject *value)
checkobj->Release();
if (result==NULL) {
- PyErr_SetString(PyExc_ValueError, "ValueError: list.index(x): x not in CListValue");
+ PyErr_SetString(PyExc_ValueError, "list.index(x): x not in CListValue");
}
return result;
@@ -466,7 +503,7 @@ PyObject* CListValue::Pyindex(PyObject* self, PyObject *value)
-PyObject* CListValue::Pycount(PyObject* self, PyObject* value)
+PyObject* CListValue::Pycount(PyObject* value)
{
int numfound = 0;
@@ -474,7 +511,7 @@ PyObject* CListValue::Pycount(PyObject* self, PyObject* value)
if (checkobj==NULL) { /* in this case just return that there are no items in the list */
PyErr_Clear();
- PyInt_FromLong(0);
+ return PyInt_FromLong(0);
}
int numelem = GetCount();
@@ -493,12 +530,32 @@ PyObject* CListValue::Pycount(PyObject* self, PyObject* value)
+PyObject* CListValue::Pyfrom_id(PyObject* value)
+{
+ uintptr_t id= (uintptr_t)PyLong_AsVoidPtr(value);
+
+ if (PyErr_Occurred())
+ return NULL;
+
+ int numelem = GetCount();
+ for (int i=0;i<numelem;i++)
+ {
+ if (reinterpret_cast<uintptr_t>(m_pValueArray[i]->m_proxy) == id)
+ return GetValue(i)->GetProxy();
+ }
+ PyErr_SetString(PyExc_IndexError, "from_id(#): id not found in CValueList");
+ return NULL;
+
+}
+
+
/* ---------------------------------------------------------------------
* Some stuff taken from the header
* --------------------------------------------------------------------- */
CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val)
{
- assert(false); // todo: implement me!
+ //assert(false); // todo: implement me!
+ fprintf(stderr, "CValueList::Calc not yet implimented\n");
return NULL;
}
@@ -508,7 +565,8 @@ CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype,
VALUE_OPERATOR op,
CValue* val)
{
- assert(false); // todo: implement me!
+ //assert(false); // todo: implement me!
+ fprintf(stderr, "CValueList::CalcFinal not yet implimented\n");
return NULL;
}
@@ -521,7 +579,7 @@ void CListValue::Add(CValue* value)
-float CListValue::GetNumber()
+double CListValue::GetNumber()
{
return -1;
}
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h
index 104e3e63283..2af5a330c43 100644
--- a/source/gameengine/Expressions/ListValue.h
+++ b/source/gameengine/Expressions/ListValue.h
@@ -36,7 +36,7 @@ public:
virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype,
VALUE_OPERATOR op,
CValue* val);
- virtual float GetNumber();
+ virtual double GetNumber();
virtual CValue* GetReplica();
public:
@@ -59,12 +59,21 @@ public:
bool CheckEqual(CValue* first,CValue* second);
- virtual PyObject* _getattr(const char *attr);
+ virtual PyObject* py_getattro(PyObject* attr);
+ virtual PyObject* py_repr(void) {
+ 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;
+ }
KX_PYMETHOD_O(CListValue,append);
KX_PYMETHOD_NOARGS(CListValue,reverse);
KX_PYMETHOD_O(CListValue,index);
KX_PYMETHOD_O(CListValue,count);
+ KX_PYMETHOD_O(CListValue,from_id);
private:
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index 1bead0a7664..6cfa14ddc80 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -54,50 +54,74 @@
* PyObjectPlus Type -- Every class, even the abstract one should have a Type
------------------------------*/
+
PyTypeObject PyObjectPlus::Type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"PyObjectPlus", /*tp_name*/
- sizeof(PyObjectPlus), /*tp_basicsize*/
+ sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
- PyDestructor, /*tp_dealloc*/
- 0, /*tp_print*/
- __getattr, /*tp_getattr*/
- __setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- __repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call */
+ py_base_dealloc,
+ 0,
+ 0,
+ 0,
+ 0,
+ py_base_repr,
+ 0,0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ 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::py_base_dealloc(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);
+ m_proxy= NULL;
};
/*------------------------------
* PyObjectPlus Methods -- Every class, even the abstract one should have a Methods
------------------------------*/
PyMethodDef PyObjectPlus::Methods[] = {
- {"isA", (PyCFunction) sPy_isA, METH_O},
+ {"isA", (PyCFunction) sPyisA, METH_O},
{NULL, NULL} /* Sentinel */
};
+PyAttributeDef PyObjectPlus::Attributes[] = {
+ KX_PYATTRIBUTE_RO_FUNCTION("isValid", PyObjectPlus, pyattr_get_is_valid),
+ {NULL} //Sentinel
+};
+
+PyObject* PyObjectPlus::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ Py_RETURN_TRUE;
+}
+
/*------------------------------
* PyObjectPlus Parents -- Every class, even the abstract one should have parents
------------------------------*/
@@ -106,566 +130,621 @@ PyParentObject PyObjectPlus::Parents[] = {&PyObjectPlus::Type, NULL};
/*------------------------------
* PyObjectPlus attributes -- attributes
------------------------------*/
-PyObject *PyObjectPlus::_getattr(const char *attr)
+
+
+/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
+PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr)
+{
+ PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+ if(self_plus==NULL) {
+ if(!strcmp("isValid", PyString_AsString(attr))) {
+ Py_RETURN_TRUE;
+ }
+ PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ return NULL;
+ }
+ return self_plus->py_getattro(attr);
+}
+
+/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
+int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *value)
{
- if (!strcmp(attr, "__doc__") && GetType()->tp_doc)
- return PyString_FromString(GetType()->tp_doc);
+ PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+ if(self_plus==NULL) {
+ PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ return -1;
+ }
+
+ if (value==NULL)
+ return self_plus->py_delattro(attr);
+
+ return self_plus->py_setattro(attr, value);
+}
- //if (streq(attr, "type"))
- // return Py_BuildValue("s", (*(GetParents()))->tp_name);
+PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the entry in Type.
+{
+
+ PyObjectPlus *self_plus= BGE_PROXY_REF(self);
+ if(self_plus==NULL) {
+ PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ return NULL;
+ }
+
+ return self_plus->py_repr();
+}
- return Py_FindMethod(Methods, this, attr);
+PyObject *PyObjectPlus::py_getattro(PyObject* attr)
+{
+ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
+ if (descr == NULL) {
+ if (strcmp(PyString_AsString(attr), "__dict__")==0) {
+ return py_getattr_dict(NULL, Type.tp_dict); /* no Attributes yet */
+ }
+ PyErr_Format(PyExc_AttributeError, "attribute \"%s\" not found", PyString_AsString(attr));
+ return NULL;
+ } else {
+ /* 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, this->m_proxy);
+ } else {
+ fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)");
+ return descr;
+ }
+ /* end py_getattro_up copy */
+ }
}
-int PyObjectPlus::_delattr(const char *attr)
+int PyObjectPlus::py_delattro(PyObject* attr)
{
PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted");
return 1;
}
-int PyObjectPlus::_setattr(const char *attr, PyObject *value)
+int PyObjectPlus::py_setattro(PyObject *attr, PyObject* value)
{
- //return PyObject::_setattr(attr,value);
- //cerr << "Unknown attribute" << endl;
PyErr_SetString(PyExc_AttributeError, "attribute cant be set");
- return 1;
+ return PY_SET_ATTR_MISSING;
}
-PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr)
+PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef)
{
- const PyAttributeDef *attrdef;
- for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++)
+ if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
+ {
+ // fake attribute, ignore
+ return NULL;
+ }
+ if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
+ {
+ // the attribute has no field correspondance, handover processing to function.
+ if (attrdef->m_getFunction == NULL)
+ return NULL;
+ return (*attrdef->m_getFunction)(self, attrdef);
+ }
+ char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
+ if (attrdef->m_length > 1)
{
- if (!strcmp(attr, attrdef->m_name))
+ PyObject* resultlist = PyList_New(attrdef->m_length);
+ for (unsigned int i=0; i<attrdef->m_length; i++)
{
- if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
+ switch (attrdef->m_type) {
+ case KX_PYATTRIBUTE_TYPE_BOOL:
+ {
+ bool *val = reinterpret_cast<bool*>(ptr);
+ ptr += sizeof(bool);
+ PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_SHORT:
+ {
+ short int *val = reinterpret_cast<short int*>(ptr);
+ ptr += sizeof(short int);
+ PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_ENUM:
+ // enum are like int, just make sure the field size is the same
+ if (sizeof(int) != attrdef->m_size)
+ {
+ Py_DECREF(resultlist);
+ return NULL;
+ }
+ // walkthrough
+ case KX_PYATTRIBUTE_TYPE_INT:
+ {
+ int *val = reinterpret_cast<int*>(ptr);
+ ptr += sizeof(int);
+ PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_FLOAT:
+ {
+ float *val = reinterpret_cast<float*>(ptr);
+ ptr += sizeof(float);
+ PyList_SetItem(resultlist,i,PyFloat_FromDouble(*val));
+ break;
+ }
+ default:
+ // no support for array of complex data
+ Py_DECREF(resultlist);
+ return NULL;
+ }
+ }
+ return resultlist;
+ }
+ else
+ {
+ switch (attrdef->m_type) {
+ case KX_PYATTRIBUTE_TYPE_BOOL:
+ {
+ bool *val = reinterpret_cast<bool*>(ptr);
+ return PyInt_FromLong(*val);
+ }
+ case KX_PYATTRIBUTE_TYPE_SHORT:
+ {
+ short int *val = reinterpret_cast<short int*>(ptr);
+ return PyInt_FromLong(*val);
+ }
+ case KX_PYATTRIBUTE_TYPE_ENUM:
+ // enum are like int, just make sure the field size is the same
+ if (sizeof(int) != attrdef->m_size)
{
- // fake attribute, ignore
return NULL;
}
- char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
- if (attrdef->m_length > 1)
+ // walkthrough
+ case KX_PYATTRIBUTE_TYPE_INT:
{
- PyObject* resultlist = PyList_New(attrdef->m_length);
- for (unsigned int i=0; i<attrdef->m_length; i++)
- {
- switch (attrdef->m_type) {
- case KX_PYATTRIBUTE_TYPE_BOOL:
- {
- bool *val = reinterpret_cast<bool*>(ptr);
- ptr += sizeof(bool);
- PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
- break;
- }
- case KX_PYATTRIBUTE_TYPE_SHORT:
- {
- short int *val = reinterpret_cast<short int*>(ptr);
- ptr += sizeof(short int);
- PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
- break;
- }
- case KX_PYATTRIBUTE_TYPE_ENUM:
- // enum are like int, just make sure the field size is the same
- if (sizeof(int) != attrdef->m_size)
- {
- Py_DECREF(resultlist);
- return NULL;
- }
- // walkthrough
- case KX_PYATTRIBUTE_TYPE_INT:
- {
- int *val = reinterpret_cast<int*>(ptr);
- ptr += sizeof(int);
- PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
- break;
- }
- case KX_PYATTRIBUTE_TYPE_FLOAT:
- {
- float *val = reinterpret_cast<float*>(ptr);
- ptr += sizeof(float);
- PyList_SetItem(resultlist,i,PyFloat_FromDouble(*val));
- break;
- }
- default:
- // no support for array of complex data
- Py_DECREF(resultlist);
- return NULL;
- }
- }
- return resultlist;
+ int *val = reinterpret_cast<int*>(ptr);
+ return PyInt_FromLong(*val);
}
- else
+ case KX_PYATTRIBUTE_TYPE_FLOAT:
{
- switch (attrdef->m_type) {
- case KX_PYATTRIBUTE_TYPE_BOOL:
- {
- bool *val = reinterpret_cast<bool*>(ptr);
- return PyInt_FromLong(*val);
- }
- case KX_PYATTRIBUTE_TYPE_SHORT:
- {
- short int *val = reinterpret_cast<short int*>(ptr);
- return PyInt_FromLong(*val);
- }
- case KX_PYATTRIBUTE_TYPE_ENUM:
- // enum are like int, just make sure the field size is the same
- if (sizeof(int) != attrdef->m_size)
- {
- return NULL;
- }
- // walkthrough
- case KX_PYATTRIBUTE_TYPE_INT:
- {
- int *val = reinterpret_cast<int*>(ptr);
- return PyInt_FromLong(*val);
- }
- case KX_PYATTRIBUTE_TYPE_FLOAT:
- {
- float *val = reinterpret_cast<float*>(ptr);
- return PyFloat_FromDouble(*val);
- }
- case KX_PYATTRIBUTE_TYPE_STRING:
- {
- STR_String *val = reinterpret_cast<STR_String*>(ptr);
- return PyString_FromString(*val);
- }
- default:
- return NULL;
- }
+ float *val = reinterpret_cast<float*>(ptr);
+ return PyFloat_FromDouble(*val);
}
+ case KX_PYATTRIBUTE_TYPE_STRING:
+ {
+ STR_String *val = reinterpret_cast<STR_String*>(ptr);
+ return PyString_FromString(*val);
+ }
+ default:
+ return NULL;
}
}
- return NULL;
}
-int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value)
+int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value)
{
- const PyAttributeDef *attrdef;
void *undoBuffer = NULL;
void *sourceBuffer = NULL;
size_t bufferSize = 0;
-
- for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++)
+
+ char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
+ if (attrdef->m_length > 1)
{
- if (!strcmp(attr, attrdef->m_name))
+ if (!PySequence_Check(value))
+ {
+ PyErr_Format(PyExc_TypeError, "expected a sequence for attribute \"%s\"", attrdef->m_name);
+ return 1;
+ }
+ if (PySequence_Size(value) != attrdef->m_length)
{
- if (attrdef->m_access == KX_PYATTRIBUTE_RO ||
- attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
+ PyErr_Format(PyExc_TypeError, "incorrect number of elements in sequence for attribute \"%s\"", attrdef->m_name);
+ return 1;
+ }
+ switch (attrdef->m_type)
+ {
+ case KX_PYATTRIBUTE_TYPE_FUNCTION:
+ if (attrdef->m_setFunction == NULL)
{
- PyErr_SetString(PyExc_AttributeError, "property is read-only");
+ PyErr_Format(PyExc_AttributeError, "function attribute without function for attribute \"%s\", report to blender.org", attrdef->m_name);
return 1;
}
- char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
- if (attrdef->m_length > 1)
+ return (*attrdef->m_setFunction)(self, attrdef, value);
+ case KX_PYATTRIBUTE_TYPE_BOOL:
+ bufferSize = sizeof(bool);
+ break;
+ case KX_PYATTRIBUTE_TYPE_SHORT:
+ bufferSize = sizeof(short int);
+ break;
+ case KX_PYATTRIBUTE_TYPE_ENUM:
+ case KX_PYATTRIBUTE_TYPE_INT:
+ bufferSize = sizeof(int);
+ break;
+ case KX_PYATTRIBUTE_TYPE_FLOAT:
+ bufferSize = sizeof(float);
+ break;
+ default:
+ // should not happen
+ PyErr_Format(PyExc_AttributeError, "Unsupported attribute type for attribute \"%s\", report to blender.org", attrdef->m_name);
+ return 1;
+ }
+ // let's implement a smart undo method
+ bufferSize *= attrdef->m_length;
+ undoBuffer = malloc(bufferSize);
+ sourceBuffer = ptr;
+ if (undoBuffer)
+ {
+ memcpy(undoBuffer, sourceBuffer, bufferSize);
+ }
+ for (int i=0; i<attrdef->m_length; i++)
+ {
+ PyObject *item = PySequence_GetItem(value, i); /* new ref */
+ // we can decrement the reference immediately, the reference count
+ // is at least 1 because the item is part of an array
+ Py_DECREF(item);
+ switch (attrdef->m_type)
{
- if (!PySequence_Check(value))
- {
- PyErr_SetString(PyExc_TypeError, "expected a sequence");
- return 1;
- }
- if (PySequence_Size(value) != attrdef->m_length)
- {
- PyErr_SetString(PyExc_TypeError, "incorrect number of elements in sequence");
- return 1;
- }
- switch (attrdef->m_type)
+ case KX_PYATTRIBUTE_TYPE_BOOL:
{
- case KX_PYATTRIBUTE_TYPE_BOOL:
- bufferSize = sizeof(bool);
- break;
- case KX_PYATTRIBUTE_TYPE_SHORT:
- bufferSize = sizeof(short int);
- break;
- case KX_PYATTRIBUTE_TYPE_ENUM:
- case KX_PYATTRIBUTE_TYPE_INT:
- bufferSize = sizeof(int);
- break;
- case KX_PYATTRIBUTE_TYPE_FLOAT:
- bufferSize = sizeof(float);
+ bool *var = reinterpret_cast<bool*>(ptr);
+ ptr += sizeof(bool);
+ if (PyInt_Check(item))
+ {
+ *var = (PyInt_AsLong(item) != 0);
+ }
+ else if (PyBool_Check(item))
+ {
+ *var = (item == Py_True);
+ }
+ else
+ {
+ PyErr_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name);
+ goto UNDO_AND_ERROR;
+ }
break;
- default:
- // should not happen
- PyErr_SetString(PyExc_AttributeError, "Unsupported attribute type, report to blender.org");
- return 1;
}
- // let's implement a smart undo method
- bufferSize *= attrdef->m_length;
- undoBuffer = malloc(bufferSize);
- sourceBuffer = ptr;
- if (undoBuffer)
+ case KX_PYATTRIBUTE_TYPE_SHORT:
{
- memcpy(undoBuffer, sourceBuffer, bufferSize);
- }
- for (int i=0; i<attrdef->m_length; i++)
- {
- PyObject *item = PySequence_GetItem(value, i); /* new ref */
- // we can decrement the reference immediately, the reference count
- // is at least 1 because the item is part of an array
- Py_DECREF(item);
- switch (attrdef->m_type)
+ short int *var = reinterpret_cast<short int*>(ptr);
+ ptr += sizeof(short int);
+ if (PyInt_Check(item))
{
- case KX_PYATTRIBUTE_TYPE_BOOL:
- {
- bool *var = reinterpret_cast<bool*>(ptr);
- ptr += sizeof(bool);
- if (PyInt_Check(item))
- {
- *var = (PyInt_AsLong(item) != 0);
- }
- else if (PyBool_Check(item))
- {
- *var = (item == Py_True);
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "expected an integer or a bool");
- goto UNDO_AND_ERROR;
- }
- break;
- }
- case KX_PYATTRIBUTE_TYPE_SHORT:
+ long val = PyInt_AsLong(item);
+ if (attrdef->m_clamp)
{
- short int *var = reinterpret_cast<short int*>(ptr);
- ptr += sizeof(short int);
- if (PyInt_Check(item))
- {
- long val = PyInt_AsLong(item);
- if (attrdef->m_clamp)
- {
- if (val < attrdef->m_imin)
- val = attrdef->m_imin;
- else if (val > attrdef->m_imax)
- val = attrdef->m_imax;
- }
- else if (val < attrdef->m_imin || val > attrdef->m_imax)
- {
- PyErr_SetString(PyExc_ValueError, "item value out of range");
- goto UNDO_AND_ERROR;
- }
- *var = (short int)val;
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "expected an integer");
- goto UNDO_AND_ERROR;
- }
- break;
+ if (val < attrdef->m_imin)
+ val = attrdef->m_imin;
+ else if (val > attrdef->m_imax)
+ val = attrdef->m_imax;
}
- case KX_PYATTRIBUTE_TYPE_ENUM:
- // enum are equivalent to int, just make sure that the field size matches:
- if (sizeof(int) != attrdef->m_size)
+ else if (val < attrdef->m_imin || val > attrdef->m_imax)
{
- PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org");
+ PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
goto UNDO_AND_ERROR;
}
- // walkthrough
- case KX_PYATTRIBUTE_TYPE_INT:
+ *var = (short int)val;
+ }
+ else
+ {
+ PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
+ goto UNDO_AND_ERROR;
+ }
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_ENUM:
+ // enum are equivalent to int, just make sure that the field size matches:
+ if (sizeof(int) != attrdef->m_size)
+ {
+ PyErr_Format(PyExc_AttributeError, "Size check error for attribute, \"%s\", report to blender.org", attrdef->m_name);
+ goto UNDO_AND_ERROR;
+ }
+ // walkthrough
+ case KX_PYATTRIBUTE_TYPE_INT:
+ {
+ int *var = reinterpret_cast<int*>(ptr);
+ ptr += sizeof(int);
+ if (PyInt_Check(item))
+ {
+ long val = PyInt_AsLong(item);
+ if (attrdef->m_clamp)
{
- int *var = reinterpret_cast<int*>(ptr);
- ptr += sizeof(int);
- if (PyInt_Check(item))
- {
- long val = PyInt_AsLong(item);
- if (attrdef->m_clamp)
- {
- if (val < attrdef->m_imin)
- val = attrdef->m_imin;
- else if (val > attrdef->m_imax)
- val = attrdef->m_imax;
- }
- else if (val < attrdef->m_imin || val > attrdef->m_imax)
- {
- PyErr_SetString(PyExc_ValueError, "item value out of range");
- goto UNDO_AND_ERROR;
- }
- *var = (int)val;
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "expected an integer");
- goto UNDO_AND_ERROR;
- }
- break;
+ if (val < attrdef->m_imin)
+ val = attrdef->m_imin;
+ else if (val > attrdef->m_imax)
+ val = attrdef->m_imax;
}
- case KX_PYATTRIBUTE_TYPE_FLOAT:
+ else if (val < attrdef->m_imin || val > attrdef->m_imax)
{
- float *var = reinterpret_cast<float*>(ptr);
- ptr += sizeof(float);
- double val = PyFloat_AsDouble(item);
- if (val == -1.0 && PyErr_Occurred())
- {
- PyErr_SetString(PyExc_TypeError, "expected a float");
- goto UNDO_AND_ERROR;
- }
- else if (attrdef->m_clamp)
- {
- if (val < attrdef->m_fmin)
- val = attrdef->m_fmin;
- else if (val > attrdef->m_fmax)
- val = attrdef->m_fmax;
- }
- else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
- {
- PyErr_SetString(PyExc_ValueError, "item value out of range");
- goto UNDO_AND_ERROR;
- }
- *var = (float)val;
- break;
+ PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
+ goto UNDO_AND_ERROR;
}
- default:
- // should not happen
- PyErr_SetString(PyExc_AttributeError, "attribute type check error, report to blender.org");
+ *var = (int)val;
+ }
+ else
+ {
+ PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
goto UNDO_AND_ERROR;
}
+ break;
}
- // no error, call check function if any
- if (attrdef->m_function != NULL)
+ case KX_PYATTRIBUTE_TYPE_FLOAT:
{
- if ((*attrdef->m_function)(self, attrdef) != 0)
+ float *var = reinterpret_cast<float*>(ptr);
+ ptr += sizeof(float);
+ double val = PyFloat_AsDouble(item);
+ if (val == -1.0 && PyErr_Occurred())
{
- // post check returned an error, restore values
- UNDO_AND_ERROR:
- if (undoBuffer)
- {
- memcpy(sourceBuffer, undoBuffer, bufferSize);
- free(undoBuffer);
- }
- return 1;
+ PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name);
+ goto UNDO_AND_ERROR;
}
+ else if (attrdef->m_clamp)
+ {
+ if (val < attrdef->m_fmin)
+ val = attrdef->m_fmin;
+ else if (val > attrdef->m_fmax)
+ val = attrdef->m_fmax;
+ }
+ else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
+ {
+ PyErr_Format(PyExc_ValueError, "item value out of range for attribute \"%s\"", attrdef->m_name);
+ goto UNDO_AND_ERROR;
+ }
+ *var = (float)val;
+ break;
}
+ default:
+ // should not happen
+ PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", report to blender.org", attrdef->m_name);
+ goto UNDO_AND_ERROR;
+ }
+ }
+ // no error, call check function if any
+ if (attrdef->m_checkFunction != NULL)
+ {
+ if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
+ {
+ // post check returned an error, restore values
+ UNDO_AND_ERROR:
if (undoBuffer)
+ {
+ memcpy(sourceBuffer, undoBuffer, bufferSize);
free(undoBuffer);
- return 0;
+ }
+ return 1;
+ }
+ }
+ if (undoBuffer)
+ free(undoBuffer);
+ return 0;
+ }
+ else // simple attribute value
+ {
+ if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_FUNCTION)
+ {
+ if (attrdef->m_setFunction == NULL)
+ {
+ PyErr_Format(PyExc_AttributeError, "function attribute without function \"%s\", report to blender.org", attrdef->m_name);
+ return 1;
}
- else // simple attribute value
+ return (*attrdef->m_setFunction)(self, attrdef, value);
+ }
+ if (attrdef->m_checkFunction != NULL)
+ {
+ // post check function is provided, prepare undo buffer
+ sourceBuffer = ptr;
+ switch (attrdef->m_type)
{
-
- if (attrdef->m_function != NULL)
+ case KX_PYATTRIBUTE_TYPE_BOOL:
+ bufferSize = sizeof(bool);
+ break;
+ case KX_PYATTRIBUTE_TYPE_SHORT:
+ bufferSize = sizeof(short);
+ break;
+ case KX_PYATTRIBUTE_TYPE_ENUM:
+ case KX_PYATTRIBUTE_TYPE_INT:
+ bufferSize = sizeof(int);
+ break;
+ case KX_PYATTRIBUTE_TYPE_FLOAT:
+ bufferSize = sizeof(float);
+ break;
+ case KX_PYATTRIBUTE_TYPE_STRING:
+ sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr();
+ if (sourceBuffer)
+ bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1;
+ break;
+ default:
+ PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name);
+ return 1;
+ }
+ if (bufferSize)
+ {
+ undoBuffer = malloc(bufferSize);
+ if (undoBuffer)
+ {
+ memcpy(undoBuffer, sourceBuffer, bufferSize);
+ }
+ }
+ }
+
+ switch (attrdef->m_type)
+ {
+ case KX_PYATTRIBUTE_TYPE_BOOL:
+ {
+ bool *var = reinterpret_cast<bool*>(ptr);
+ if (PyInt_Check(value))
+ {
+ *var = (PyInt_AsLong(value) != 0);
+ }
+ else if (PyBool_Check(value))
+ {
+ *var = (value == Py_True);
+ }
+ else
+ {
+ PyErr_Format(PyExc_TypeError, "expected an integer or a bool for attribute \"%s\"", attrdef->m_name);
+ goto FREE_AND_ERROR;
+ }
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_SHORT:
+ {
+ short int *var = reinterpret_cast<short int*>(ptr);
+ if (PyInt_Check(value))
{
- // post check function is provided, prepare undo buffer
- sourceBuffer = ptr;
- switch (attrdef->m_type)
+ long val = PyInt_AsLong(value);
+ if (attrdef->m_clamp)
{
- case KX_PYATTRIBUTE_TYPE_BOOL:
- bufferSize = sizeof(bool);
- break;
- case KX_PYATTRIBUTE_TYPE_SHORT:
- bufferSize = sizeof(short);
- break;
- case KX_PYATTRIBUTE_TYPE_ENUM:
- case KX_PYATTRIBUTE_TYPE_INT:
- bufferSize = sizeof(int);
- break;
- case KX_PYATTRIBUTE_TYPE_FLOAT:
- bufferSize = sizeof(float);
- break;
- case KX_PYATTRIBUTE_TYPE_STRING:
- sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr();
- if (sourceBuffer)
- bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1;
- break;
- default:
- PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org");
- return 1;
+ if (val < attrdef->m_imin)
+ val = attrdef->m_imin;
+ else if (val > attrdef->m_imax)
+ val = attrdef->m_imax;
}
- if (bufferSize)
+ else if (val < attrdef->m_imin || val > attrdef->m_imax)
{
- undoBuffer = malloc(bufferSize);
- if (undoBuffer)
- {
- memcpy(undoBuffer, sourceBuffer, bufferSize);
- }
+ PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
+ goto FREE_AND_ERROR;
}
+ *var = (short int)val;
}
-
- switch (attrdef->m_type)
+ else
{
- case KX_PYATTRIBUTE_TYPE_BOOL:
- {
- bool *var = reinterpret_cast<bool*>(ptr);
- if (PyInt_Check(value))
- {
- *var = (PyInt_AsLong(value) != 0);
- }
- else if (PyBool_Check(value))
- {
- *var = (value == Py_True);
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "expected an integer or a bool");
- goto FREE_AND_ERROR;
- }
- break;
- }
- case KX_PYATTRIBUTE_TYPE_SHORT:
+ PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
+ goto FREE_AND_ERROR;
+ }
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_ENUM:
+ // enum are equivalent to int, just make sure that the field size matches:
+ if (sizeof(int) != attrdef->m_size)
+ {
+ PyErr_Format(PyExc_AttributeError, "attribute size check error for attribute \"%s\", report to blender.org", attrdef->m_name);
+ goto FREE_AND_ERROR;
+ }
+ // walkthrough
+ case KX_PYATTRIBUTE_TYPE_INT:
+ {
+ int *var = reinterpret_cast<int*>(ptr);
+ if (PyInt_Check(value))
+ {
+ long val = PyInt_AsLong(value);
+ if (attrdef->m_clamp)
{
- short int *var = reinterpret_cast<short int*>(ptr);
- if (PyInt_Check(value))
- {
- long val = PyInt_AsLong(value);
- if (attrdef->m_clamp)
- {
- if (val < attrdef->m_imin)
- val = attrdef->m_imin;
- else if (val > attrdef->m_imax)
- val = attrdef->m_imax;
- }
- else if (val < attrdef->m_imin || val > attrdef->m_imax)
- {
- PyErr_SetString(PyExc_ValueError, "value out of range");
- goto FREE_AND_ERROR;
- }
- *var = (short int)val;
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "expected an integer");
- goto FREE_AND_ERROR;
- }
- break;
+ if (val < attrdef->m_imin)
+ val = attrdef->m_imin;
+ else if (val > attrdef->m_imax)
+ val = attrdef->m_imax;
}
- case KX_PYATTRIBUTE_TYPE_ENUM:
- // enum are equivalent to int, just make sure that the field size matches:
- if (sizeof(int) != attrdef->m_size)
+ else if (val < attrdef->m_imin || val > attrdef->m_imax)
{
- PyErr_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org");
+ PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
goto FREE_AND_ERROR;
}
- // walkthrough
- case KX_PYATTRIBUTE_TYPE_INT:
- {
- int *var = reinterpret_cast<int*>(ptr);
- if (PyInt_Check(value))
- {
- long val = PyInt_AsLong(value);
- if (attrdef->m_clamp)
- {
- if (val < attrdef->m_imin)
- val = attrdef->m_imin;
- else if (val > attrdef->m_imax)
- val = attrdef->m_imax;
- }
- else if (val < attrdef->m_imin || val > attrdef->m_imax)
- {
- PyErr_SetString(PyExc_ValueError, "value out of range");
- goto FREE_AND_ERROR;
- }
- *var = (int)val;
- }
- else
- {
- PyErr_SetString(PyExc_TypeError, "expected an integer");
- goto FREE_AND_ERROR;
- }
- break;
- }
- case KX_PYATTRIBUTE_TYPE_FLOAT:
+ *var = (int)val;
+ }
+ else
+ {
+ PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name);
+ goto FREE_AND_ERROR;
+ }
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_FLOAT:
+ {
+ float *var = reinterpret_cast<float*>(ptr);
+ double val = PyFloat_AsDouble(value);
+ if (val == -1.0 && PyErr_Occurred())
+ {
+ PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name);
+ goto FREE_AND_ERROR;
+ }
+ else if (attrdef->m_clamp)
+ {
+ if (val < attrdef->m_fmin)
+ val = attrdef->m_fmin;
+ else if (val > attrdef->m_fmax)
+ val = attrdef->m_fmax;
+ }
+ else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
+ {
+ PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name);
+ goto FREE_AND_ERROR;
+ }
+ *var = (float)val;
+ break;
+ }
+ case KX_PYATTRIBUTE_TYPE_STRING:
+ {
+ STR_String *var = reinterpret_cast<STR_String*>(ptr);
+ if (PyString_Check(value))
+ {
+ char *val = PyString_AsString(value);
+ if (attrdef->m_clamp)
{
- float *var = reinterpret_cast<float*>(ptr);
- double val = PyFloat_AsDouble(value);
- if (val == -1.0 && PyErr_Occurred())
+ if (strlen(val) < attrdef->m_imin)
{
- PyErr_SetString(PyExc_TypeError, "expected a float");
+ // can't increase the length of the string
+ PyErr_Format(PyExc_ValueError, "string length too short for attribute \"%s\"", attrdef->m_name);
goto FREE_AND_ERROR;
}
- else if (attrdef->m_clamp)
- {
- if (val < attrdef->m_fmin)
- val = attrdef->m_fmin;
- else if (val > attrdef->m_fmax)
- val = attrdef->m_fmax;
- }
- else if (val < attrdef->m_fmin || val > attrdef->m_fmax)
- {
- PyErr_SetString(PyExc_ValueError, "value out of range");
- goto FREE_AND_ERROR;
- }
- *var = (float)val;
- break;
- }
- case KX_PYATTRIBUTE_TYPE_STRING:
- {
- STR_String *var = reinterpret_cast<STR_String*>(ptr);
- if (PyString_Check(value))
+ else if (strlen(val) > attrdef->m_imax)
{
- char *val = PyString_AsString(value);
- if (attrdef->m_clamp)
- {
- if (strlen(val) < attrdef->m_imin)
- {
- // can't increase the length of the string
- PyErr_SetString(PyExc_ValueError, "string length too short");
- goto FREE_AND_ERROR;
- }
- else if (strlen(val) > attrdef->m_imax)
- {
- // trim the string
- char c = val[attrdef->m_imax];
- val[attrdef->m_imax] = 0;
- *var = val;
- val[attrdef->m_imax] = c;
- break;
- }
- } else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax)
- {
- PyErr_SetString(PyExc_ValueError, "string length out of range");
- goto FREE_AND_ERROR;
- }
+ // trim the string
+ char c = val[attrdef->m_imax];
+ val[attrdef->m_imax] = 0;
*var = val;
+ val[attrdef->m_imax] = c;
+ break;
}
- else
- {
- PyErr_SetString(PyExc_TypeError, "expected a string");
- goto FREE_AND_ERROR;
- }
- break;
+ } else if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax)
+ {
+ PyErr_Format(PyExc_ValueError, "string length out of range for attribute \"%s\"", attrdef->m_name);
+ goto FREE_AND_ERROR;
}
- default:
- // should not happen
- PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org");
+ *var = val;
+ }
+ else
+ {
+ PyErr_Format(PyExc_TypeError, "expected a string for attribute \"%s\"", attrdef->m_name);
goto FREE_AND_ERROR;
}
+ break;
}
- // check if post processing is needed
- if (attrdef->m_function != NULL)
+ default:
+ // should not happen
+ PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name);
+ goto FREE_AND_ERROR;
+ }
+ }
+ // check if post processing is needed
+ if (attrdef->m_checkFunction != NULL)
+ {
+ if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
+ {
+ // restore value
+ RESTORE_AND_ERROR:
+ if (undoBuffer)
{
- if ((*attrdef->m_function)(self, attrdef) != 0)
+ if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING)
{
- // restore value
- RESTORE_AND_ERROR:
- if (undoBuffer)
- {
- if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING)
- {
- // special case for STR_String: restore the string
- STR_String *var = reinterpret_cast<STR_String*>(ptr);
- *var = reinterpret_cast<char*>(undoBuffer);
- }
- else
- {
- // other field type have direct values
- memcpy(ptr, undoBuffer, bufferSize);
- }
- }
- FREE_AND_ERROR:
- if (undoBuffer)
- free(undoBuffer);
- return 1;
+ // special case for STR_String: restore the string
+ STR_String *var = reinterpret_cast<STR_String*>(ptr);
+ *var = reinterpret_cast<char*>(undoBuffer);
+ }
+ else
+ {
+ // other field type have direct values
+ memcpy(ptr, undoBuffer, bufferSize);
}
}
+ FREE_AND_ERROR:
if (undoBuffer)
free(undoBuffer);
- return 0;
+ return 1;
}
}
- return -1;
+ if (undoBuffer)
+ free(undoBuffer);
+ return 0;
}
+
+
/*------------------------------
* PyObjectPlus repr -- representations
------------------------------*/
-PyObject *PyObjectPlus::_repr(void)
+PyObject *PyObjectPlus::py_repr(void)
{
PyErr_SetString(PyExc_SystemError, "Representation not overridden by object.");
return NULL;
@@ -676,38 +755,43 @@ PyObject *PyObjectPlus::_repr(void)
------------------------------*/
bool PyObjectPlus::isA(PyTypeObject *T) // if called with a Type, use "typename"
{
- return isA(T->tp_name);
+ int i;
+ PyParentObject P;
+ PyParentObject *Ps = GetParents();
+
+ for (P = Ps[i=0]; P != NULL; P = Ps[i++])
+ if (P==T)
+ return true;
+
+ return false;
}
bool PyObjectPlus::isA(const char *mytypename) // check typename of each parent
{
- int i;
- PyParentObject P;
- PyParentObject *Ps = GetParents();
+ int i;
+ PyParentObject P;
+ PyParentObject *Ps = GetParents();
- for (P = Ps[i=0]; P != NULL; P = Ps[i++])
- {
- if (strcmp(P->tp_name, mytypename)==0)
- return true;
- }
-
- return false;
+ for (P = Ps[i=0]; P != NULL; P = Ps[i++])
+ if (strcmp(P->tp_name, mytypename)==0)
+ return true;
+
+ return false;
}
-PyObject *PyObjectPlus::Py_isA(PyObject *value) // Python wrapper for isA
+PyObject *PyObjectPlus::PyisA(PyObject *value) // Python wrapper for isA
{
- if (!PyString_Check(value)) {
- PyErr_SetString(PyExc_TypeError, "expected a string");
- return NULL;
- }
- if(isA(PyString_AsString(value)))
- Py_RETURN_TRUE;
- else
- Py_RETURN_FALSE;
+ if (PyType_Check(value)) {
+ return PyBool_FromLong(isA((PyTypeObject *)value));
+ } else if (PyString_Check(value)) {
+ return PyBool_FromLong(isA(PyString_AsString(value)));
+ }
+ PyErr_SetString(PyExc_TypeError, "object.isA(value): expected a type or a string");
+ return NULL;
}
-/* Utility function called by the macro _getattr_up()
+/* Utility function called by the macro py_getattro_up()
* for getting ob.__dict__() values from our PyObject
* this is used by python for doing dir() on an object, so its good
* if we return a list of attributes and methods.
@@ -715,26 +799,57 @@ PyObject *PyObjectPlus::Py_isA(PyObject *value) // Python wrapper for isA
* Other then making dir() useful the value returned from __dict__() is not useful
* since every value is a Py_None
* */
-PyObject *_getattr_dict(PyObject *pydict, PyMethodDef *meth, PyAttributeDef *attrdef)
+PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict)
{
if(pydict==NULL) { /* incase calling __dict__ on the parent of this object raised an error */
PyErr_Clear();
pydict = PyDict_New();
}
- if(meth) {
- for (; meth->ml_name != NULL; meth++) {
- PyDict_SetItemString(pydict, meth->ml_name, Py_None);
- }
+ PyDict_Update(pydict, 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);
- if(attrdef) {
- for (; attrdef->m_name != NULL; attrdef++) {
- PyDict_SetItemString(pydict, attrdef->m_name, Py_None);
+ 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;
}
+
}
-
- return pydict;
+
+ GetProxy_Ext(self, tp);
+ if(py_owns) {
+ BGE_PROXY_PYOWNS(self->m_proxy) = py_owns;
+ Py_DECREF(self->m_proxy); /* could avoid thrashing here but for now its ok */
+ }
+ return self->m_proxy;
}
#endif //NO_EXP_PYTHON_EMBEDDING
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 1a5f50a3d23..370717a919b 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -50,18 +50,19 @@
also in api2_2x/gen_utils.h
*/
#ifndef Py_RETURN_NONE
-#define Py_RETURN_NONE return Py_BuildValue("O", Py_None)
+#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
#endif
#ifndef Py_RETURN_FALSE
-#define Py_RETURN_FALSE return PyBool_FromLong(0)
+#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
#endif
#ifndef Py_RETURN_TRUE
-#define Py_RETURN_TRUE return PyBool_FromLong(1)
+#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#endif
/* for pre Py 2.5 */
#if PY_VERSION_HEX < 0x02050000
typedef int Py_ssize_t;
+typedef Py_ssize_t (*lenfunc)(PyObject *);
#define PY_SSIZE_T_MAX INT_MAX
#define PY_SSIZE_T_MIN INT_MIN
#define PY_METHODCHAR char *
@@ -72,11 +73,28 @@ typedef int Py_ssize_t;
#define PY_METHODCHAR const char *
#endif
+#include "descrobject.h"
+
+
static inline void Py_Fatal(const char *M) {
fprintf(stderr, "%s\n", 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 == py_base_dealloc)
+
+
// This must be the first line of each
// PyC++ class
#define Py_Header \
@@ -86,79 +104,130 @@ 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);}; \
- // This defines the _getattr_up macro
+
+ // This defines the py_getattro_up macro
// which allows attribute and method calls
// to be properly passed up the hierarchy.
-#define _getattr_up(Parent) \
- PyObject *rvalue = Py_FindMethod(Methods, this, attr); \
+
+#define py_getattro_up(Parent) \
+ \
+ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
\
- if (rvalue == NULL) { \
+ if(descr) { \
+ 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, this->m_proxy); \
+ } else { \
+ fprintf(stderr, "unknown attribute type"); \
+ return descr; \
+ } \
+ } else { \
PyErr_Clear(); \
- rvalue = Parent::_getattr(attr); \
+ PyObject *rvalue= Parent::py_getattro(attr); \
+ \
+ if (strcmp(PyString_AsString(attr), "__dict__")==0) { \
+ return py_getattr_dict(rvalue, Type.tp_dict); \
+ } \
+ \
+ return rvalue; \
} \
- if ((rvalue == NULL) && !strcmp(attr, "__dict__")) {\
+ return NULL;
+
+
+/*
+ * nonzero values are an error for setattr
+ * however because of the nested lookups we need to know if the errors
+ * was because the attribute didnt exits of if there was some problem setting the value
+ */
+
+#define PY_SET_ATTR_COERCE_FAIL 2
+#define PY_SET_ATTR_FAIL 1
+#define PY_SET_ATTR_MISSING -1
+#define PY_SET_ATTR_SUCCESS 0
+
+#define py_setattro_up(Parent) \
+ PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \
+ \
+ if(descr) { \
+ if (PyCObject_Check(descr)) { \
+ const PyAttributeDef* attrdef= reinterpret_cast<const PyAttributeDef *>(PyCObject_AsVoidPtr(descr)); \
+ if (attrdef->m_access == KX_PYATTRIBUTE_RO) { \
+ PyErr_Format(PyExc_AttributeError, "\"%s\" is read only", PyString_AsString(attr)); \
+ return PY_SET_ATTR_FAIL; \
+ } \
+ else { \
+ return py_set_attrdef((void *)this, attrdef, value); \
+ } \
+ } else { \
+ PyErr_Format(PyExc_AttributeError, "\"%s\" cannot be set", PyString_AsString(attr)); \
+ return PY_SET_ATTR_FAIL; \
+ } \
+ } else { \
PyErr_Clear(); \
- rvalue = _getattr_dict(Parent::_getattr(attr), Methods, Attributes); \
- } \
- return rvalue; \
+ return Parent::py_setattro(attr, value); \
+ }
+
/**
* These macros are helpfull when embedding Python routines. The second
* macro is one that also requires a documentation string
*/
#define KX_PYMETHOD(class_name, method_name) \
- PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \
+ PyObject* Py##method_name(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); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args, kwds); \
}; \
#define KX_PYMETHOD_VARARGS(class_name, method_name) \
- PyObject* Py##method_name(PyObject* self, PyObject* args); \
+ PyObject* Py##method_name(PyObject* args); \
static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
- return ((class_name*) self)->Py##method_name(self, args); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args); \
}; \
#define KX_PYMETHOD_NOARGS(class_name, method_name) \
- PyObject* Py##method_name(PyObject* self); \
+ PyObject* Py##method_name(); \
static PyObject* sPy##method_name( PyObject* self) { \
- return ((class_name*) self)->Py##method_name(self); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(); \
}; \
#define KX_PYMETHOD_O(class_name, method_name) \
- PyObject* Py##method_name(PyObject* self, PyObject* value); \
+ PyObject* Py##method_name(PyObject* value); \
static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \
- return ((class_name*) self)->Py##method_name(self, value); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value); \
}; \
#define KX_PYMETHOD_DOC(class_name, method_name) \
- PyObject* Py##method_name(PyObject* self, PyObject* args, PyObject* kwds); \
+ PyObject* Py##method_name(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); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(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); \
+ PyObject* Py##method_name(PyObject* args); \
static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
- return ((class_name*) self)->Py##method_name(self, args); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args); \
}; \
static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_O(class_name, method_name) \
- PyObject* Py##method_name(PyObject* self, PyObject* value); \
+ PyObject* Py##method_name(PyObject* value); \
static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \
- return ((class_name*) self)->Py##method_name(self, value); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value); \
}; \
static const char method_name##_doc[]; \
#define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \
- PyObject* Py##method_name(PyObject* self); \
+ PyObject* Py##method_name(); \
static PyObject* sPy##method_name( PyObject* self) { \
- return ((class_name*) self)->Py##method_name(self); \
+ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(); \
}; \
static const char method_name##_doc[]; \
@@ -181,19 +250,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* 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* 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* 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()
/**
* Attribute management
@@ -206,6 +275,7 @@ enum KX_PYATTRIBUTE_TYPE {
KX_PYATTRIBUTE_TYPE_FLOAT,
KX_PYATTRIBUTE_TYPE_STRING,
KX_PYATTRIBUTE_TYPE_DUMMY,
+ KX_PYATTRIBUTE_TYPE_FUNCTION,
};
enum KX_PYATTRIBUTE_ACCESS {
@@ -214,7 +284,9 @@ enum KX_PYATTRIBUTE_ACCESS {
};
struct KX_PYATTRIBUTE_DEF;
-typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+typedef int (*KX_PYATTRIBUTE_CHECK_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
+typedef int (*KX_PYATTRIBUTE_SET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+typedef PyObject* (*KX_PYATTRIBUTE_GET_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
typedef struct KX_PYATTRIBUTE_DEF {
const char *m_name; // name of the python attribute
@@ -228,7 +300,10 @@ typedef struct KX_PYATTRIBUTE_DEF {
size_t m_offset; // position of field in structure
size_t m_size; // size of field for runtime verification (enum only)
size_t m_length; // length of array, 1=simple attribute
- KX_PYATTRIBUTE_FUNCTION m_function; // static function to check the assignment, returns 0 if no error
+ KX_PYATTRIBUTE_CHECK_FUNCTION m_checkFunction; // static function to check the assignment, returns 0 if no error
+ KX_PYATTRIBUTE_SET_FUNCTION m_setFunction; // static function to check the assignment, returns 0 if no error
+ KX_PYATTRIBUTE_GET_FUNCTION m_getFunction; // static function to check the assignment, returns 0 if no error
+
// The following pointers are just used to have compile time check for attribute type.
// It would have been good to use a union but that would require C99 compatibility
// to initialize specific union fields through designated initializers.
@@ -242,150 +317,145 @@ typedef struct KX_PYATTRIBUTE_DEF {
} PyAttributeDef;
#define KX_PYATTRIBUTE_DUMMY(name) \
- { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, {NULL, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
// enum field cannot be mapped to pointer (because we would need a pointer for each enum)
// use field size to verify mapping at runtime only, assuming enum size is equal to int size.
#define KX_PYATTRIBUTE_ENUM_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, {NULL, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_ENUM_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, {NULL, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_ENUM_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, {NULL, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} }
// SHORT_LIST
#define KX_PYATTRIBUTE_SHORT_LIST_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_LIST_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} }
// INT_LIST
#define KX_PYATTRIBUTE_INT_LIST_RW(name,min,max,clamp,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_LIST_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
// always clamp for float
#define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
#define KX_PYATTRIBUTE_STRING_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+
+#define KX_PYATTRIBUTE_RW_FUNCTION(name,object,getfunction,setfunction) \
+ { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_RO_FUNCTION(name,object,getfunction) \
+ { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ARRAY_RW_FUNCTION(name,object,length,getfunction,setfunction) \
+ { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_ARRAY_RO_FUNCTION(name,object,length,getfunction) \
+ { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} }
-//Multiple integer
-#define KX_PYATTRIBUTE_MINT_RW_CHECK(name,min,max,clamp,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
/*------------------------------
* PyObjectPlus
------------------------------*/
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);
+
+ PyObject *m_proxy; /* actually a PyObjectPlus_Proxy */
virtual ~PyObjectPlus(); // destructor
- static void PyDestructor(PyObject *P) // python wrapper
- {
- delete ((PyObjectPlus *) P);
- };
-// void INCREF(void) {
-// Py_INCREF(this);
-// }; // incref method
-// void DECREF(void) {
-// Py_DECREF(this);
-// }; // decref method
+ /* These static functions are referenced by ALL PyObjectPlus_Proxy types
+ * they take the C++ reference from the PyObjectPlus_Proxy and call
+ * its own virtual py_getattro, py_setattro etc. functions.
+ */
+ static void py_base_dealloc(PyObject *self);
+ static PyObject* py_base_getattro(PyObject * self, PyObject *attr);
+ static int py_base_setattro(PyObject *self, PyObject *attr, PyObject *value);
+ static PyObject* py_base_repr(PyObject *self);
+
+ /* These are all virtual python methods that are defined in each class
+ * Our own fake subclassing calls these on each class, then calls the parent */
+ virtual PyObject* py_getattro(PyObject *attr);
+ virtual int py_delattro(PyObject *attr);
+ virtual int py_setattro(PyObject *attr, PyObject *value);
+ virtual PyObject* py_repr(void);
+
+ static PyObject* py_get_attrdef(void *self, const PyAttributeDef *attrdef);
+ static int py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyObject *value);
- virtual PyObject *_getattr(const char *attr); // _getattr method
- static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type.
- {
- return ((PyObjectPlus*) PyObj)->_getattr(attr);
- }
- static PyObject *_getattr_self(const PyAttributeDef attrlist[], void *self, const char *attr);
- static int _setattr_self(const PyAttributeDef attrlist[], void *self, const char *attr, PyObject *value);
+ /* isA() methods, shonky replacement for pythons issubclass()
+ * which we cant use because we have our own subclass system */
+ bool isA(PyTypeObject *T);
+ bool isA(const char *mytypename);
- virtual int _delattr(const char *attr);
- virtual int _setattr(const char *attr, PyObject *value); // _setattr method
- static int __setattr(PyObject *PyObj, // This should be the entry in Type.
- char *attr,
- PyObject *value)
- {
- if (!value)
- return ((PyObjectPlus*) PyObj)->_delattr(attr);
- return ((PyObjectPlus*) PyObj)->_setattr(attr, value);
- }
+ KX_PYMETHOD_O(PyObjectPlus,isA);
- virtual PyObject *_repr(void); // _repr method
- static PyObject *__repr(PyObject *PyObj) // This should be the entry in Type.
- {
- return ((PyObjectPlus*) PyObj)->_repr();
- }
+ /* 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);
- // isA methods
- bool isA(PyTypeObject *T);
- bool isA(const char *mytypename);
- PyObject *Py_isA(PyObject *value);
- static PyObject *sPy_isA(PyObject *self, PyObject *value)
- {
- return ((PyObjectPlus*)self)->Py_isA(value);
- }
+ static PyObject *GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp);
+ static PyObject *NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns);
};
-PyObject *_getattr_dict(PyObject *pydict, PyMethodDef *meth, PyAttributeDef *attrdef);
+PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict);
#endif // _adr_py_lib_h_
diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/StringValue.cpp
index 1ef8c5629a0..2b3c62c411e 100644
--- a/source/gameengine/Expressions/StringValue.cpp
+++ b/source/gameengine/Expressions/StringValue.cpp
@@ -113,7 +113,7 @@ this object
-float CStringValue::GetNumber()
+double CStringValue::GetNumber()
{
return -1;
}
diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h
index b824d4ef86d..16575ed7ffa 100644
--- a/source/gameengine/Expressions/StringValue.h
+++ b/source/gameengine/Expressions/StringValue.h
@@ -33,7 +33,7 @@ public:
/// CValue implementation
virtual bool IsEqual(const STR_String & other);
virtual const STR_String & GetText();
- virtual float GetNumber();
+ virtual double GetNumber();
virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);
virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index ebb12636ac2..7cb97909119 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -36,125 +36,24 @@ bool CValue::m_ignore_deprecation_warnings(false);
#ifndef NO_EXP_PYTHON_EMBEDDING
-PyObject* cvalue_add(PyObject*v, PyObject*w)
-{
- return ((CValue*)v)->Calc(VALUE_ADD_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_sub(PyObject*v, PyObject*w)
-{
- return ((CValue*)v)->Calc(VALUE_SUB_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_mul(PyObject*v, PyObject*w)
-{
- return ((CValue*)v)->Calc(VALUE_MUL_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_div(PyObject*v, PyObject*w)
-{
- return ((CValue*)v)->Calc(VALUE_DIV_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_mod(PyObject*v, PyObject*w)
-{
- return ((CValue*)v)->Calc(VALUE_MOD_OPERATOR,(CValue*)w);
-}
-PyObject* cvalue_neg(PyObject*v)
-{
- return ((CValue*)v)->Calc(VALUE_NEG_OPERATOR,(CValue*)v);
-}
-PyObject* cvalue_pos(PyObject*v)
-{
- return ((CValue*)v)->Calc(VALUE_POS_OPERATOR,(CValue*)v);
-}
-
-
-int MyPyCompare (PyObject* v,PyObject* w)
-{
- CValue* eqval = ((CValue*)v)->Calc(VALUE_EQL_OPERATOR,(CValue*)w);
- STR_String txt = eqval->GetText();
- eqval->Release();
- if (txt=="TRUE")
- return 0;
- CValue* lessval = ((CValue*)v)->Calc(VALUE_LES_OPERATOR,(CValue*)w);
- txt = lessval->GetText();
- lessval->Release();
- if (txt=="TRUE")
- return -1;
-
- return 1;
-}
-
-
-int cvalue_coerce(PyObject** pv,PyObject** pw)
-{
- if (PyInt_Check(*pw)) {
- double db = (double)PyInt_AsLong(*pw);
- *pw = new CIntValue((int) db);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyLong_Check(*pw)) {
- double db = PyLong_AsDouble(*pw);
- *pw = new CFloatValue(db);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyFloat_Check(*pw)) {
- double db = PyFloat_AsDouble(*pw);
- *pw = new CFloatValue(db);
- Py_INCREF(*pv);
- return 0;
- } else if (PyString_Check(*pw)) {
- const STR_String str = PyString_AsString(*pw);
- *pw = new CStringValue(str,"");
- Py_INCREF(*pv);
- return 0;
- }
- return 1; /* Can't do it */
-
-}
-static PyNumberMethods cvalue_as_number = {
- (binaryfunc)cvalue_add, /*nb_add*/
- (binaryfunc)cvalue_sub, /*nb_subtract*/
- (binaryfunc)cvalue_mul, /*nb_multiply*/
- (binaryfunc)cvalue_div, /*nb_divide*/
- (binaryfunc)cvalue_mod, /*nb_remainder*/
- 0,//(binaryfunc)cvalue_divmod, /*nb_divmod*/
- 0,//0,//0,//0,//(ternaryfunc)cvalue_pow, /*nb_power*/
- (unaryfunc)cvalue_neg, /*nb_negative*/
- 0,//(unaryfunc)cvalue_pos, /*nb_positive*/
- 0,//(unaryfunc)cvalue_abs, /*nb_absolute*/
- 0,//(inquiry)cvalue_nonzero, /*nb_nonzero*/
- 0, /*nb_invert*/
- 0, /*nb_lshift*/
- 0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- (coercion)cvalue_coerce, /*nb_coerce*/
- 0,//(unaryfunc)cvalue_int, /*nb_int*/
- 0,//(unaryfunc)cvalue_long, /*nb_long*/
- 0,//(unaryfunc)cvalue_float, /*nb_float*/
- 0, /*nb_oct*/
- 0, /*nb_hex*/
-};
-
-
PyTypeObject CValue::Type = {
- PyObject_HEAD_INIT(&PyType_Type)
+ PyObject_HEAD_INIT(NULL)
0,
"CValue",
- sizeof(CValue),
+ sizeof(PyObjectPlus_Proxy),
+ 0,
+ py_base_dealloc,
0,
- PyDestructor,
0,
- __getattr,
- __setattr,
- &MyPyCompare,
- __repr,
- &cvalue_as_number,
0,
0,
+ py_base_repr,
0,
- 0
+ 0,0,0,0,0,
+ py_base_getattro,
+ py_base_setattro,
+ 0,0,0,0,0,0,0,0,0,
+ Methods
};
PyParentObject CValue::Parents[] = {
@@ -168,7 +67,7 @@ PyMethodDef CValue::Methods[] = {
{NULL,NULL} //Sentinel
};
-PyObject* CValue::PyGetName(PyObject* self)
+PyObject* CValue::PyGetName()
{
return PyString_FromString(this->GetName());
}
@@ -320,55 +219,70 @@ STR_String CValue::op2str (VALUE_OPERATOR op)
//
void CValue::SetProperty(const STR_String & name,CValue* ioProperty)
{
- // Check if somebody is setting an empty property
if (ioProperty==NULL)
- {
+ { // Check if somebody is setting an empty property
trace("Warning:trying to set empty property!");
return;
}
- // Make sure we have a property array
- if (m_pNamedPropertyArray == NULL)
+ if (m_pNamedPropertyArray)
+ { // Try to replace property (if so -> exit as soon as we replaced it)
+ CValue* oldval = (*m_pNamedPropertyArray)[name];
+ if (oldval)
+ oldval->Release();
+ }
+ else { // Make sure we have a property array
m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
-
- // Try to replace property (if so -> exit as soon as we replaced it)
- CValue* oldval = (*m_pNamedPropertyArray)[name];
- if (oldval)
- {
- oldval->Release();
}
// Add property at end of array
(*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
}
+void CValue::SetProperty(const char* name,CValue* ioProperty)
+{
+ if (ioProperty==NULL)
+ { // Check if somebody is setting an empty property
+ trace("Warning:trying to set empty property!");
+ return;
+ }
+ if (m_pNamedPropertyArray)
+ { // Try to replace property (if so -> exit as soon as we replaced it)
+ CValue* oldval = (*m_pNamedPropertyArray)[name];
+ if (oldval)
+ oldval->Release();
+ }
+ else { // Make sure we have a property array
+ m_pNamedPropertyArray = new std::map<STR_String,CValue *>;
+ }
+
+ // Add property at end of array
+ (*m_pNamedPropertyArray)[name] = ioProperty->AddRef();//->Add(ioProperty);
+}
//
// Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
//
CValue* CValue::GetProperty(const STR_String & inName)
{
- // Check properties, as soon as we found it -> Return a pointer to the property
- CValue* result = NULL;
- if (m_pNamedPropertyArray)
- {
- std::map<STR_String,CValue*>::iterator it = (*m_pNamedPropertyArray).find(inName);
- if (!( it==m_pNamedPropertyArray->end()))
- {
- result = (*it).second;
- }
-
+ if (m_pNamedPropertyArray) {
+ std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
+ if (it != m_pNamedPropertyArray->end())
+ return (*it).second;
}
- //for (int i=0; i<m_pValuePropertyArray->size(); i++)
- // if ((*m_pValuePropertyArray)[i]->GetName() == inName)
- // return (*m_pValuePropertyArray)[i];
-
- // Did not find property with name <inName>, return NULL property pointer
- return result;
+ return NULL;
}
-
+CValue* CValue::GetProperty(const char *inName)
+{
+ if (m_pNamedPropertyArray) {
+ std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
+ if (it != m_pNamedPropertyArray->end())
+ return (*it).second;
+ }
+ return NULL;
+}
//
// Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
@@ -386,7 +300,7 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
{
CValue *property = GetProperty(inName);
if (property)
- return property->GetNumber();
+ return property->GetNumber();
else
return defnumber;
}
@@ -396,26 +310,20 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
//
// Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
//
-bool CValue::RemoveProperty(const STR_String & inName)
+bool CValue::RemoveProperty(const char *inName)
{
// Check if there are properties at all which can be removed
- if (m_pNamedPropertyArray) {
- CValue* val = GetProperty(inName);
- if (NULL != val)
+ if (m_pNamedPropertyArray)
+ {
+ std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->find(inName);
+ if (it != m_pNamedPropertyArray->end())
{
- val->Release();
- m_pNamedPropertyArray->erase(inName);
+ ((*it).second)->Release();
+ m_pNamedPropertyArray->erase(it);
return true;
}
- }
-
- char err[128];
- if (m_pNamedPropertyArray)
- sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr());
- else
- sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr());
+ }
- PyErr_SetString(PyExc_AttributeError, err);
return false;
}
@@ -426,8 +334,10 @@ vector<STR_String> CValue::GetPropertyNames()
{
vector<STR_String> result;
if(!m_pNamedPropertyArray) return result;
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ result.reserve(m_pNamedPropertyArray->size());
+
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
result.push_back((*it).first);
}
@@ -444,8 +354,8 @@ void CValue::ClearProperties()
return;
// Remove all properties
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
{
CValue* tmpval = (*it).second;
//STR_String name = (*it).first;
@@ -464,9 +374,11 @@ void CValue::ClearProperties()
//
void CValue::SetPropertiesModified(bool inModified)
{
- int numprops = GetPropertyCount();
- for (int i=0; i<numprops; i++)
- GetProperty(i)->SetModified(inModified);
+ if(!m_pNamedPropertyArray) return;
+ std::map<STR_String,CValue*>::iterator it;
+
+ for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
+ ((*it).second)->SetModified(inModified);
}
@@ -476,11 +388,13 @@ void CValue::SetPropertiesModified(bool inModified)
//
bool CValue::IsAnyPropertyModified()
{
- int numprops = GetPropertyCount();
- for (int i=0;i<numprops;i++)
- if (GetProperty(i)->IsModified())
+ if(!m_pNamedPropertyArray) return false;
+ std::map<STR_String,CValue*>::iterator it;
+
+ for (it= m_pNamedPropertyArray->begin();(it != m_pNamedPropertyArray->end()); it++)
+ if (((*it).second)->IsModified())
return true;
-
+
return false;
}
@@ -489,7 +403,6 @@ bool CValue::IsAnyPropertyModified()
//
// Get property number <inIndex>
//
-
CValue* CValue::GetProperty(int inIndex)
{
@@ -498,8 +411,8 @@ CValue* CValue::GetProperty(int inIndex)
if (m_pNamedPropertyArray)
{
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
if (count++==inIndex)
{
@@ -535,8 +448,8 @@ void CValue::CloneProperties(CValue *replica)
if (m_pNamedPropertyArray)
{
replica->m_pNamedPropertyArray=NULL;
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
CValue *val = (*it).second->GetReplica();
replica->SetProperty((*it).first,val);
@@ -595,6 +508,7 @@ int CValue::Release()
{
// Reference count reached 0, delete ourselves and return 0
// MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much");
+
delete this;
return 0;
}
@@ -624,9 +538,6 @@ void CValue::AddDataToReplica(CValue *replica)
{
replica->m_refcount = 1;
- //register with Python
- _Py_NewReference(replica);
-
#ifdef _DEBUG
//gRefCountValue++;
#endif
@@ -685,39 +596,28 @@ PyAttributeDef CValue::Attributes[] = {
};
-PyObject* CValue::_getattr(const char *attr)
+PyObject* CValue::py_getattro(PyObject *attr)
{
- CValue* resultattr = FindIdentifier(STR_String(attr));
- STR_String text;
+ char *attr_str= PyString_AsString(attr);
+ CValue* resultattr = GetProperty(attr_str);
if (resultattr)
{
- if (resultattr->IsError())
- {
- resultattr->Release();
- } else
- {
- // to avoid some compare problems, return a real pythonthing
- PyObject* pyconvert = resultattr->ConvertValueToPython();
- if (pyconvert)
- {
- resultattr->Release();
- return pyconvert;
- } else
- {
- // also check if it's already in pythoninterpreter!
- return resultattr;
- }
-
- }
+ PyObject* pyconvert = resultattr->ConvertValueToPython();
+
+ if (pyconvert)
+ return pyconvert;
+ else
+ return resultattr->GetProxy();
}
- _getattr_up(PyObjectPlus);
+ py_getattro_up(PyObjectPlus);
}
CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
{
CValue* vallie = NULL;
-
+ /* refcounting is broking here! - this crashes anyway, just store a python list for KX_GameObject */
+#if 0
if (PyList_Check(pyobj))
{
CListValue* listval = new CListValue();
@@ -748,13 +648,18 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
}
} else
+#endif
if (PyFloat_Check(pyobj))
{
vallie = new CFloatValue( (float)PyFloat_AsDouble(pyobj) );
} else
if (PyInt_Check(pyobj))
{
- vallie = new CIntValue( (int)PyInt_AS_LONG(pyobj) );
+ vallie = new CIntValue( (cInt)PyInt_AS_LONG(pyobj) );
+ } else
+ if (PyLong_Check(pyobj))
+ {
+ vallie = new CIntValue( (cInt)PyLong_AsLongLong(pyobj) );
} else
if (PyString_Check(pyobj))
{
@@ -766,42 +671,56 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
} else
{
/* return an error value from the caller */
- PyErr_SetString(PyExc_TypeError, "This python value could not be assigned to a game engine property");
+ PyErr_SetString(PyExc_TypeError, "This python type could not be converted to a to a game engine property");
}
return vallie;
}
-int CValue::_delattr(const char *attr)
+int CValue::py_delattro(PyObject *attr)
{
- if (!RemoveProperty(STR_String(attr))) /* sets error */
- return 1;
- return 0;
+ char *attr_str= PyString_AsString(attr);
+ if (RemoveProperty(STR_String(attr_str)))
+ return 0;
+
+ PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str);
+ return 1;
}
-int CValue::_setattr(const char *attr,PyObject* pyobj)
+int CValue::py_setattro(PyObject *attr, PyObject* pyobj)
{
+ char *attr_str= PyString_AsString(attr);
+ CValue* oldprop = GetProperty(attr_str);
+
CValue* vallie = ConvertPythonToValue(pyobj);
if (vallie)
{
- STR_String attr_str = attr;
- CValue* oldprop = GetProperty(attr_str);
-
if (oldprop)
- {
oldprop->SetValue(vallie);
- } else
- {
+ else
SetProperty(attr_str, vallie);
- }
+
vallie->Release();
- } else
- {
- return 1; /* ConvertPythonToValue sets the error message */
+ }
+ else {
+ // ConvertPythonToValue sets the error message
+ // must return missing so KX_GameObect knows this
+ // attribute was not a function or bult in attribute,
+ //
+ // CValue attributes override internal attributes
+ // so if it exists as a CValue attribute already,
+ // assume your trying to set it to a differnt CValue attribute
+ // otherwise return PY_SET_ATTR_MISSING so children
+ // classes know they can set it without conflict
+
+ if (GetProperty(attr_str))
+ return PY_SET_ATTR_COERCE_FAIL; /* failed to set an existing attribute */
+ else
+ return PY_SET_ATTR_MISSING; /* allow the KX_GameObject dict to set */
}
- //PyObjectPlus::_setattr(attr,value);
- return 0;
+ //PyObjectPlus::py_setattro(attr,value);
+ return PY_SET_ATTR_SUCCESS;
};
PyObject* CValue::ConvertKeysToPython( void )
@@ -811,8 +730,8 @@ PyObject* CValue::ConvertKeysToPython( void )
if (m_pNamedPropertyArray)
{
- for ( std::map<STR_String,CValue*>::iterator it = m_pNamedPropertyArray->begin();
- !(it == m_pNamedPropertyArray->end());it++)
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++)
{
pystr = PyString_FromString( (*it).first );
PyList_Append(pylist, pystr);
@@ -826,7 +745,7 @@ PyObject* CValue::ConvertKeysToPython( void )
PyObject* CValue::PyMake(PyObject* ignored,PyObject* args)
{
- //if (!PyArg_ParseTuple(args,"s",&name)) return NULL;
+ //if (!PyArg_ParseTuple(args,"s:make",&name)) return NULL;
Py_RETURN_NONE;//new CValue();
}
*/
@@ -878,7 +797,7 @@ void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way)
PyObject *getframe, *frame;
PyObject *f_lineno, *f_code, *co_filename;
- getframe = PySys_GetObject("_getframe"); // borrowed
+ getframe = PySys_GetObject((char *)"_getframe"); // borrowed
if (getframe) {
frame = PyObject_CallObject(getframe, NULL);
if (frame) {
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index caf1064dc32..a687e1a493c 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -217,33 +217,14 @@ public:
CValue(PyTypeObject *T = &Type);
//static PyObject* PyMake(PyObject*,PyObject*);
- virtual PyObject *_repr(void)
+ virtual PyObject *py_repr(void)
{
- return Py_BuildValue("s",(const char*)GetText());
+ return PyString_FromString((const char*)GetText());
}
- virtual PyObject* _getattr(const char *attr);
-
- void SpecialRelease()
- {
- int i=0;
- if (ob_refcnt == 0)
- {
- _Py_NewReference(this);
-
- } else
- {
- i++;
- }
- Release();
- }
- static void PyDestructor(PyObject *P) // python wrapper
- {
- ((CValue*)P)->SpecialRelease();
- };
-
+ virtual PyObject* py_getattro(PyObject *attr);
virtual PyObject* ConvertValueToPython() {
return NULL;
}
@@ -251,8 +232,8 @@ public:
virtual CValue* ConvertPythonToValue(PyObject* pyobj);
- virtual int _delattr(const char *attr);
- virtual int _setattr(const char *attr, PyObject* value);
+ virtual int py_delattro(PyObject *attr);
+ virtual int py_setattro(PyObject *attr, PyObject* value);
virtual PyObject* ConvertKeysToPython( void );
@@ -280,13 +261,16 @@ public:
int GetRefCount() { return m_refcount; }
virtual CValue* AddRef(); // Add a reference to this value
virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+
/// Property Management
virtual void SetProperty(const STR_String& name,CValue* ioProperty); // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
- virtual CValue* GetProperty(const STR_String & inName); // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
+ virtual void SetProperty(const char* name,CValue* ioProperty);
+ virtual CValue* GetProperty(const char* inName); // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName>
+ virtual CValue* GetProperty(const STR_String & inName);
STR_String GetPropertyText(const STR_String & inName,const STR_String& deftext=""); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
float GetPropertyNumber(const STR_String& inName,float defnumber);
- virtual bool RemoveProperty(const STR_String & inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
+ virtual bool RemoveProperty(const char *inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed
virtual vector<STR_String> GetPropertyNames();
virtual void ClearProperties(); // Clear all properties
@@ -304,7 +288,7 @@ public:
virtual void SetColorOperator(VALUE_OPERATOR op);
virtual const STR_String & GetText() = 0;
- virtual float GetNumber() = 0;
+ virtual double GetNumber() = 0;
double* ZeroVector() { return m_sZeroVec; };
virtual double* GetVector3(bool bGetTransformedVec = false);
diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/VectorValue.cpp
index bea6902eba8..497a50b90e7 100644
--- a/source/gameengine/Expressions/VectorValue.cpp
+++ b/source/gameengine/Expressions/VectorValue.cpp
@@ -156,7 +156,7 @@ this object
return ret;
}
-float CVectorValue::GetNumber()
+double CVectorValue::GetNumber()
{
return m_vec[KX_X];
}
diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/VectorValue.h
index 5d9b2a98891..99bf0abb11b 100644
--- a/source/gameengine/Expressions/VectorValue.h
+++ b/source/gameengine/Expressions/VectorValue.h
@@ -32,7 +32,7 @@ public:
void SetVector(double newvec[]);
void Configure(CValue* menuvalue);
virtual double* GetVector3(bool bGetTransformedVec=false);
- virtual float GetNumber();
+ virtual double GetNumber();
CValue* Calc(VALUE_OPERATOR op, CValue *val) {
return val->CalcFinal(VALUE_VECTOR_TYPE, op, this);
diff --git a/source/gameengine/Expressions/VoidValue.h b/source/gameengine/Expressions/VoidValue.h
index 4bde0254787..10a6ff9ad3d 100644
--- a/source/gameengine/Expressions/VoidValue.h
+++ b/source/gameengine/Expressions/VoidValue.h
@@ -47,7 +47,7 @@ public:
/// Value -> String or number
virtual const STR_String & GetText(); // Get string description of void value (unimplemented)
- virtual float GetNumber() { return -1; }
+ virtual double GetNumber() { return -1; }
/// Value calculation
virtual CValue* Calc(VALUE_OPERATOR op, CValue *val);