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:
Diffstat (limited to 'source/gameengine/Expressions')
-rw-r--r--source/gameengine/Expressions/BoolValue.cpp10
-rw-r--r--source/gameengine/Expressions/BoolValue.h5
-rw-r--r--source/gameengine/Expressions/CMakeLists.txt1
-rw-r--r--source/gameengine/Expressions/EmptyValue.cpp2
-rw-r--r--source/gameengine/Expressions/ErrorValue.cpp6
-rw-r--r--source/gameengine/Expressions/ErrorValue.h2
-rw-r--r--source/gameengine/Expressions/FloatValue.cpp6
-rw-r--r--source/gameengine/Expressions/FloatValue.h2
-rw-r--r--source/gameengine/Expressions/IfExpr.cpp7
-rw-r--r--source/gameengine/Expressions/InputParser.cpp45
-rw-r--r--source/gameengine/Expressions/InputParser.h10
-rw-r--r--source/gameengine/Expressions/IntValue.cpp4
-rw-r--r--source/gameengine/Expressions/IntValue.h2
-rw-r--r--source/gameengine/Expressions/ListValue.cpp274
-rw-r--r--source/gameengine/Expressions/ListValue.h4
-rw-r--r--source/gameengine/Expressions/Makefile1
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp239
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h204
-rw-r--r--source/gameengine/Expressions/SConscript2
-rw-r--r--source/gameengine/Expressions/StringValue.cpp4
-rw-r--r--source/gameengine/Expressions/StringValue.h2
-rw-r--r--source/gameengine/Expressions/Value.cpp239
-rw-r--r--source/gameengine/Expressions/Value.h103
-rw-r--r--source/gameengine/Expressions/VectorValue.cpp4
-rw-r--r--source/gameengine/Expressions/VectorValue.h2
25 files changed, 778 insertions, 402 deletions
diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp
index 13c870b68e5..d90da8b3a92 100644
--- a/source/gameengine/Expressions/BoolValue.cpp
+++ b/source/gameengine/Expressions/BoolValue.cpp
@@ -26,6 +26,9 @@
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
+const STR_String CBoolValue::sTrueString = "TRUE";
+const STR_String CBoolValue::sFalseString = "FALSE";
+
CBoolValue::CBoolValue()
/*
@@ -45,7 +48,7 @@ CBoolValue::CBoolValue(bool inBool)
-CBoolValue::CBoolValue(bool innie,STR_String name,AllocationTYPE alloctype)
+CBoolValue::CBoolValue(bool innie,const char *name,AllocationTYPE alloctype)
{
m_bool = innie;
SetName(name);
@@ -190,9 +193,6 @@ double CBoolValue::GetNumber()
const STR_String& CBoolValue::GetText()
{
- static STR_String sTrueString = STR_String("TRUE");
- static STR_String sFalseString = STR_String("FALSE");
-
return m_bool ? sTrueString : sFalseString;
}
@@ -201,7 +201,7 @@ const STR_String& CBoolValue::GetText()
CValue* CBoolValue::GetReplica()
{
CBoolValue* replica = new CBoolValue(*this);
- CValue::AddDataToReplica(replica);
+ replica->ProcessReplica();
return replica;
}
diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h
index 9352b9d4b92..726619e7193 100644
--- a/source/gameengine/Expressions/BoolValue.h
+++ b/source/gameengine/Expressions/BoolValue.h
@@ -28,9 +28,12 @@ class CBoolValue : public CPropValue
//PLUGIN_DECLARE_SERIAL(CBoolValue,CValue)
public:
+ static const STR_String sTrueString;
+ static const STR_String sFalseString;
+
CBoolValue();
CBoolValue(bool inBool);
- CBoolValue(bool innie, STR_String name, AllocationTYPE alloctype = CValue::HEAPVALUE);
+ CBoolValue(bool innie, const char *name, AllocationTYPE alloctype = CValue::HEAPVALUE);
virtual const STR_String& GetText();
virtual double GetNumber();
diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt
index 6b2a835d648..e3942b46557 100644
--- a/source/gameengine/Expressions/CMakeLists.txt
+++ b/source/gameengine/Expressions/CMakeLists.txt
@@ -31,6 +31,7 @@ SET(INC
../../../source/kernel/gen_system
../../../intern/string
../../../intern/moto/include
+ ../../../source/gameengine/SceneGraph
${PYTHON_INC}
)
diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/EmptyValue.cpp
index f72ddc47096..5d1273b5301 100644
--- a/source/gameengine/Expressions/EmptyValue.cpp
+++ b/source/gameengine/Expressions/EmptyValue.cpp
@@ -121,7 +121,7 @@ const STR_String & CEmptyValue::GetText()
CValue* CEmptyValue::GetReplica()
{
CEmptyValue* replica = new CEmptyValue(*this);
- CValue::AddDataToReplica(replica);
+ replica->ProcessReplica();
return replica;
}
diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/ErrorValue.cpp
index 651a772db19..a44abf8b22e 100644
--- a/source/gameengine/Expressions/ErrorValue.cpp
+++ b/source/gameengine/Expressions/ErrorValue.cpp
@@ -34,13 +34,15 @@ effect: constructs a new CErrorValue containing errormessage "Error"
-CErrorValue::CErrorValue(STR_String errmsg)
+CErrorValue::CErrorValue(const char *errmsg)
/*
pre:
effect: constructs a new CErrorValue containing errormessage errmsg
*/
{
- m_strErrorText = "[" + errmsg + "]";
+ m_strErrorText = "[";
+ m_strErrorText += errmsg;
+ m_strErrorText += "]";
SetError(true);
}
diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/ErrorValue.h
index 5b5795196ba..b4b758feea7 100644
--- a/source/gameengine/Expressions/ErrorValue.h
+++ b/source/gameengine/Expressions/ErrorValue.h
@@ -25,7 +25,7 @@ public:
virtual const STR_String & GetText();
virtual double GetNumber();
CErrorValue();
- CErrorValue(STR_String errmsg);
+ CErrorValue(const char *errmsg);
virtual ~CErrorValue();
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/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp
index 212a55fe457..4de685a82c1 100644
--- a/source/gameengine/Expressions/FloatValue.cpp
+++ b/source/gameengine/Expressions/FloatValue.cpp
@@ -50,7 +50,7 @@ effect: constructs a new CFloatValue containing value fl
-CFloatValue::CFloatValue(float fl,STR_String name,AllocationTYPE alloctype)
+CFloatValue::CFloatValue(float fl,const char *name,AllocationTYPE alloctype)
/*
pre:
effect: constructs a new CFloatValue containing value fl
@@ -307,8 +307,8 @@ const STR_String & CFloatValue::GetText()
CValue* CFloatValue::GetReplica()
{
CFloatValue* replica = new CFloatValue(*this);
- replica->m_pstrRep = NULL;
- CValue::AddDataToReplica(replica);
+ replica->m_pstrRep = NULL; /* should be in CFloatValue::ProcessReplica() but its not defined, no matter */
+ replica->ProcessReplica();
return replica;
}
diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/FloatValue.h
index 41f70b5c54c..fb75b7c702b 100644
--- a/source/gameengine/Expressions/FloatValue.h
+++ b/source/gameengine/Expressions/FloatValue.h
@@ -23,7 +23,7 @@ class CFloatValue : public CPropValue
public:
CFloatValue();
CFloatValue(float fl);
- CFloatValue(float fl,STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE);
+ CFloatValue(float fl,const char *name,AllocationTYPE alloctype=CValue::HEAPVALUE);
virtual const STR_String & GetText();
diff --git a/source/gameengine/Expressions/IfExpr.cpp b/source/gameengine/Expressions/IfExpr.cpp
index 5d3eb3641ca..fcb37bff52d 100644
--- a/source/gameengine/Expressions/IfExpr.cpp
+++ b/source/gameengine/Expressions/IfExpr.cpp
@@ -15,6 +15,7 @@
#include "IfExpr.h"
#include "EmptyValue.h"
#include "ErrorValue.h"
+#include "BoolValue.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -72,14 +73,14 @@ ret: a new object containing the value of m_e1 if m_guard is a boolean TRUE
{
CValue *guardval;
guardval = m_guard->Calculate();
- STR_String text = guardval->GetText();
+ const STR_String& text = guardval->GetText();
guardval->Release();
- if (text == STR_String("TRUE"))
+ if (&text == &CBoolValue::sTrueString)
{
return m_e1->Calculate();
}
- else if (text == STR_String("FALSE"))
+ else if (&text == &CBoolValue::sFalseString)
{
return m_e2->Calculate();
}
diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp
index 66075dd8d42..b15b206a38a 100644
--- a/source/gameengine/Expressions/InputParser.cpp
+++ b/source/gameengine/Expressions/InputParser.cpp
@@ -38,7 +38,7 @@
// cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc...
#include "IfExpr.h"
-#if defined(WIN32) || defined(WIN64)
+#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS)
#define strcasecmp _stricmp
#ifndef strtoll
@@ -66,7 +66,7 @@ CParser::~CParser()
-void CParser::ScanError(STR_String str)
+void CParser::ScanError(const char *str)
{
// sets the global variable errmsg to an errormessage with
// contents str, appending if it already exists
@@ -81,7 +81,7 @@ void CParser::ScanError(STR_String str)
-CExpression* CParser::Error(STR_String str)
+CExpression* CParser::Error(const char *str)
{
// makes and returns a new CConstExpr filled with an CErrorValue
// with string str
@@ -537,7 +537,7 @@ CExpression *CParser::Expr() {
}
CExpression* CParser::ProcessText
-(STR_String intext) {
+(const char *intext) {
// and parses the string in intext and returns it.
@@ -574,7 +574,7 @@ CExpression* CParser::ProcessText
-float CParser::GetFloat(STR_String txt)
+float CParser::GetFloat(STR_String& txt)
{
// returns parsed text into a float
// empty string returns -1
@@ -599,7 +599,7 @@ float CParser::GetFloat(STR_String txt)
return result;
}
-CValue* CParser::GetValue(STR_String txt, bool bFallbackToText)
+CValue* CParser::GetValue(STR_String& txt, bool bFallbackToText)
{
// returns parsed text into a value,
// empty string returns NULL value !
@@ -658,10 +658,41 @@ static PyMethodDef CParserMethods[] =
{ NULL,NULL} // Sentinel
};
+
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef Expression_module_def = {
+ {}, /* m_base */
+ "Expression", /* m_name */
+ 0, /* m_doc */
+ 0, /* m_size */
+ CParserMethods, /* m_methods */
+ 0, /* m_reload */
+ 0, /* m_traverse */
+ 0, /* m_clear */
+ 0, /* m_free */
+};
+#endif
+
extern "C" {
void initExpressionModule(void)
{
- Py_InitModule("Expression",CParserMethods);
+ PyObject *m;
+ /* Use existing module where possible
+ * be careful not to init any runtime vars after this */
+ m = PyImport_ImportModule( "Expression" );
+ if(m) {
+ Py_DECREF(m);
+ //return m;
+ }
+ else {
+ PyErr_Clear();
+
+#if (PY_VERSION_HEX >= 0x03000000)
+ PyModule_Create(&Expression_module_def);
+#else
+ Py_InitModule("Expression",CParserMethods);
+#endif
+ }
}
}
diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h
index 3d517222639..810bdc244a8 100644
--- a/source/gameengine/Expressions/InputParser.h
+++ b/source/gameengine/Expressions/InputParser.h
@@ -27,9 +27,9 @@ public:
CParser();
virtual ~CParser();
- float GetFloat(STR_String txt);
- CValue* GetValue(STR_String txt, bool bFallbackToText=false);
- CExpression* ProcessText(STR_String intext);
+ float GetFloat(STR_String& txt);
+ CValue* GetValue(STR_String& txt, bool bFallbackToText=false);
+ CExpression* ProcessText(const char *intext);
void SetContext(CValue* context);
private:
@@ -86,8 +86,8 @@ private:
CValue* m_identifierContext;// context in which identifiers are looked up
- void ScanError(STR_String str);
- CExpression* Error(STR_String str);
+ void ScanError(const char *str);
+ CExpression* Error(const char *str);
void NextCh();
void TermChar(char c);
void DigRep();
diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp
index 4e86f7bf789..227518e9439 100644
--- a/source/gameengine/Expressions/IntValue.cpp
+++ b/source/gameengine/Expressions/IntValue.cpp
@@ -54,7 +54,7 @@ effect: constructs a new CIntValue containing cInt innie
-CIntValue::CIntValue(cInt innie,STR_String name,AllocationTYPE alloctype)
+CIntValue::CIntValue(cInt innie,const char *name,AllocationTYPE alloctype)
{
m_int = innie;
SetName(name);
@@ -311,7 +311,7 @@ const STR_String & CIntValue::GetText()
CValue* CIntValue::GetReplica() {
CIntValue* replica = new CIntValue(*this);
- CValue::AddDataToReplica(replica);
+ replica->ProcessReplica();
replica->m_pstrRep = NULL;
return replica;
diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/IntValue.h
index 0f3a38b274b..06bf1755749 100644
--- a/source/gameengine/Expressions/IntValue.h
+++ b/source/gameengine/Expressions/IntValue.h
@@ -32,7 +32,7 @@ public:
CIntValue();
CIntValue(cInt innie);
CIntValue(cInt innie,
- STR_String name,
+ const char *name,
AllocationTYPE alloctype=CValue::HEAPVALUE);
virtual CValue* Calc(VALUE_OPERATOR op,
diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp
index dd9b296dce1..a0d73c75d60 100644
--- a/source/gameengine/Expressions/ListValue.cpp
+++ b/source/gameengine/Expressions/ListValue.cpp
@@ -18,6 +18,7 @@
#include "StringValue.h"
#include "VoidValue.h"
#include <algorithm>
+#include "BoolValue.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -39,8 +40,10 @@ Py_ssize_t listvalue_bufferlen(PyObject* self)
PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index)
{
CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
+ CValue *cval;
+
if (list==NULL) {
- PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, "val = CList[i], "BGE_PROXY_ERROR_MSG);
return NULL;
}
@@ -49,43 +52,47 @@ PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index)
if (index < 0)
index = count+index;
- if (index >= 0 && index < count)
- {
- PyObject* pyobj = list->GetValue(index)->ConvertValueToPython();
- if (pyobj)
- return pyobj;
- else
- return list->GetValue(index)->GetProxy();
-
+ if (index < 0 || index >= count) {
+ PyErr_SetString(PyExc_IndexError, "CList[i]: Python ListIndex out of range in CValueList");
+ return NULL;
}
- PyErr_SetString(PyExc_IndexError, "list[i]: Python ListIndex out of range in CValueList");
- return NULL;
+
+ cval= list->GetValue(index);
+
+ PyObject* pyobj = cval->ConvertValueToPython();
+ if (pyobj)
+ return pyobj;
+ else
+ return cval->GetProxy();
}
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);
+ PyErr_SetString(PyExc_SystemError, "value = CList[i], "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 item->GetProxy();
-
+ CValue *item = ((CListValue*) list)->FindValue(PyString_AsString(pyindex));
+ if (item) {
+ PyObject* pyobj = item->ConvertValueToPython();
+ if(pyobj)
+ return pyobj;
+ else
+ return item->GetProxy();
+ }
}
- if (PyInt_Check(pyindex))
+ else if (PyInt_Check(pyindex))
{
int index = PyInt_AsLong(pyindex);
- return listvalue_buffer_item(self, index);
+ return listvalue_buffer_item(self, index); /* wont add a ref */
}
PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */
- PyErr_Format(PyExc_KeyError, "list[key]: '%s' key not in list", PyString_AsString(pyindex_str));
+ PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", PyString_AsString(pyindex_str));
Py_DECREF(pyindex_str);
return NULL;
}
@@ -96,7 +103,7 @@ PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihig
{
CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self));
if (list==NULL) {
- PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, "val = CList[i:j], "BGE_PROXY_ERROR_MSG);
return NULL;
}
@@ -127,73 +134,79 @@ PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihig
}
-
-static PyObject *
-listvalue_buffer_concat(PyObject * self, PyObject * other)
+/* clist + list, return a list that python owns */
+static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other)
{
CListValue *listval= static_cast<CListValue *>(BGE_PROXY_REF(self));
+ int i, numitems, numitems_orig;
+
if (listval==NULL) {
- PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, "CList+other, "BGE_PROXY_ERROR_MSG);
return NULL;
}
+ numitems_orig= listval->GetCount();
+
// for now, we support CListValue concatenated with items
// and CListValue concatenated to Python Lists
// and CListValue concatenated with another CListValue
- listval->AddRef();
- if (other->ob_type == &PyList_Type)
+ /* Shallow copy, dont use listval->GetReplica(), it will screw up with KX_GameObjects */
+ CListValue* listval_new = new CListValue();
+
+ if (PyList_Check(other))
{
+ CValue* listitemval;
bool error = false;
-
- int i;
- int numitems = PyList_Size(other);
+
+ numitems = PyList_Size(other);
+
+ /* copy the first part of the list */
+ listval_new->Resize(numitems_orig + numitems);
+ for (i=0;i<numitems_orig;i++)
+ listval_new->SetValue(i, listval->GetValue(i)->AddRef());
+
for (i=0;i<numitems;i++)
{
- PyObject* listitem = PyList_GetItem(other,i);
- CValue* listitemval = listval->ConvertPythonToValue(listitem);
- if (listitemval)
- {
- listval->Add(listitemval);
- } else
- {
- error = true;
+ listitemval = listval->ConvertPythonToValue(PyList_GetItem(other,i), "cList + pyList: CListValue, ");
+
+ if (listitemval) {
+ listval_new->SetValue(i+numitems_orig, listitemval);
+ } else {
+ error= true;
+ break;
}
}
-
+
if (error) {
- PyErr_SetString(PyExc_SystemError, "list.append(val): couldn't add one or more items to this CValueList");
- return NULL;
+ listval_new->Resize(numitems_orig+i); /* resize so we dont try release NULL pointers */
+ listval_new->Release();
+ return NULL; /* ConvertPythonToValue above sets the error */
}
-
- } else
- {
- if (other->ob_type == &CListValue::Type)
- {
- // add items from otherlist to this list
- CListValue* otherval = (CListValue*) other;
-
-
- for (int i=0;i<otherval->GetCount();i++)
- {
- otherval->Add(listval->GetValue(i)->AddRef());
- }
- }
- else
- {
- CValue* objval = listval->ConvertPythonToValue(other);
- if (objval)
- {
- listval->Add(objval);
- } else
- {
- PyErr_SetString(PyExc_SystemError, "list.append(i): couldn't add item to this CValueList");
- return NULL;
- }
+
+ }
+ else if (PyObject_TypeCheck(other, &CListValue::Type)) {
+ // add items from otherlist to this list
+ CListValue* otherval = static_cast<CListValue *>(BGE_PROXY_REF(other));
+ if(otherval==NULL) {
+ listval_new->Release();
+ PyErr_SetString(PyExc_SystemError, "CList+other, "BGE_PROXY_ERROR_MSG);
+ return NULL;
}
+
+ numitems = otherval->GetCount();
+
+ /* copy the first part of the list */
+ listval_new->Resize(numitems_orig + numitems); /* resize so we dont try release NULL pointers */
+ for (i=0;i<numitems_orig;i++)
+ listval_new->SetValue(i, listval->GetValue(i)->AddRef());
+
+ /* now copy the other part of the list */
+ for (i=0;i<numitems;i++)
+ listval_new->SetValue(i+numitems_orig, otherval->GetValue(i)->AddRef());
+
}
-
- return self;
+ return listval_new->NewProxy(true); /* python owns this list */
}
@@ -203,9 +216,15 @@ static PySequenceMethods listvalue_as_sequence = {
listvalue_buffer_concat, /*sq_concat*/
NULL, /*sq_repeat*/
listvalue_buffer_item, /*sq_item*/
+#if (PY_VERSION_HEX >= 0x03000000) // TODO, slicing in py3?
+ NULL,
+ NULL,
+ NULL,
+#else
listvalue_buffer_slice, /*sq_slice*/
NULL, /*sq_ass_item*/
- NULL /*sq_ass_slice*/
+ NULL, /*sq_ass_slice*/
+#endif
};
@@ -220,8 +239,13 @@ static PyMappingMethods instance_as_mapping = {
PyTypeObject CListValue::Type = {
- PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ /* python 2.5 and below */
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
0, /*ob_size*/
+#endif
"CListValue", /*tp_name*/
sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -256,10 +280,17 @@ PyParentObject CListValue::Parents[] = {
PyMethodDef CListValue::Methods[] = {
+ /* List style access */
{"append", (PyCFunction)CListValue::sPyappend,METH_O},
{"reverse", (PyCFunction)CListValue::sPyreverse,METH_NOARGS},
{"index", (PyCFunction)CListValue::sPyindex,METH_O},
{"count", (PyCFunction)CListValue::sPycount,METH_O},
+
+ /* Dict style access */
+ {"get", (PyCFunction)CListValue::sPyget,METH_VARARGS},
+ {"has_key", (PyCFunction)CListValue::sPyhas_key,METH_O},
+
+ /* Own cvalue funcs */
{"from_id", (PyCFunction)CListValue::sPyfrom_id,METH_O},
{NULL,NULL} //Sentinel
@@ -273,6 +304,10 @@ PyObject* CListValue::py_getattro(PyObject* attr) {
py_getattro_up(CValue);
}
+PyObject* CListValue::py_getattro_dict() {
+ py_getattro_dict_up(CValue);
+}
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
@@ -320,7 +355,7 @@ const STR_String & CListValue::GetText()
CValue* CListValue::GetReplica() {
CListValue* replica = new CListValue(*this);
- CValue::AddDataToReplica(replica);
+ replica->ProcessReplica();
replica->m_bReleaseContents=true; // for copy, complete array is copied for now...
// copy all values
@@ -370,23 +405,21 @@ void CListValue::ReleaseAndRemoveAll()
CValue* CListValue::FindValue(const STR_String & name)
{
- CValue* resultval = NULL;
- int i=0;
+ for (int i=0; i < GetCount(); i++)
+ if (GetValue(i)->GetName() == name)
+ return GetValue(i);
- while (!resultval && i < GetCount())
- {
- CValue* myval = GetValue(i);
-
- if (myval->GetName() == name)
- resultval = GetValue(i)->AddRef(); // add referencecount
- else
- i++;
-
- }
- return resultval;
+ return NULL;
}
-
+CValue* CListValue::FindValue(const char * name)
+{
+ for (int i=0; i < GetCount(); i++)
+ if (GetValue(i)->GetName() == name)
+ return GetValue(i);
+
+ return NULL;
+}
bool CListValue::SearchValue(CValue *val)
{
@@ -433,14 +466,24 @@ void CListValue::MergeList(CListValue *otherlist)
{
SetValue(i+numelements,otherlist->GetValue(i)->AddRef());
}
-
}
-
PyObject* CListValue::Pyappend(PyObject* value)
{
- return listvalue_buffer_concat(m_proxy, value); /* m_proxy is the same as self */
+ CValue* objval = ConvertPythonToValue(value, "CList.append(i): CValueList, ");
+
+ if (!objval) /* ConvertPythonToValue sets the error */
+ return NULL;
+
+ if (!BGE_PROXY_PYOWNS(m_proxy)) {
+ PyErr_SetString(PyExc_TypeError, "CList.append(i): this CValueList is used internally for the game engine and can't be modified");
+ return NULL;
+ }
+
+ Add(objval);
+
+ Py_RETURN_NONE;
}
@@ -461,13 +504,12 @@ bool CListValue::CheckEqual(CValue* first,CValue* second)
if (eqval==NULL)
return false;
-
- STR_String txt = eqval->GetText();
- eqval->Release();
- if (txt=="TRUE")
+ const STR_String& text = eqval->GetText();
+ if (&text==&CBoolValue::sTrueString)
{
result = true;
}
+ eqval->Release();
return result;
}
@@ -478,7 +520,7 @@ PyObject* CListValue::Pyindex(PyObject *value)
{
PyObject* result = NULL;
- CValue* checkobj = ConvertPythonToValue(value);
+ CValue* checkobj = ConvertPythonToValue(value, "val = cList[i]: CValueList, ");
if (checkobj==NULL)
return NULL; /* ConvertPythonToValue sets the error */
@@ -495,7 +537,7 @@ PyObject* CListValue::Pyindex(PyObject *value)
checkobj->Release();
if (result==NULL) {
- PyErr_SetString(PyExc_ValueError, "list.index(x): x not in CListValue");
+ PyErr_SetString(PyExc_ValueError, "CList.index(x): x not in CListValue");
}
return result;
@@ -507,7 +549,7 @@ PyObject* CListValue::Pycount(PyObject* value)
{
int numfound = 0;
- CValue* checkobj = ConvertPythonToValue(value);
+ CValue* checkobj = ConvertPythonToValue(value, ""); /* error ignored */
if (checkobj==NULL) { /* in this case just return that there are no items in the list */
PyErr_Clear();
@@ -528,7 +570,35 @@ PyObject* CListValue::Pycount(PyObject* value)
return PyInt_FromLong(numfound);
}
+/* Matches python dict.get(key, [default]) */
+PyObject* CListValue::Pyget(PyObject *args)
+{
+ char *key;
+ PyObject* def = Py_None;
+
+ if (!PyArg_ParseTuple(args, "s|O:get", &key, &def))
+ return NULL;
+
+ CValue *item = FindValue((const char *)key);
+ if (item) {
+ PyObject* pyobj = item->ConvertValueToPython();
+ if (pyobj)
+ return pyobj;
+ else
+ return item->GetProxy();
+ }
+ Py_INCREF(def);
+ return def;
+}
+/* Matches python dict.has_key() */
+PyObject* CListValue::Pyhas_key(PyObject* value)
+{
+ if (PyString_Check(value) && FindValue((const char *)PyString_AsString(value)))
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
PyObject* CListValue::Pyfrom_id(PyObject* value)
{
@@ -555,18 +625,24 @@ PyObject* CListValue::Pyfrom_id(PyObject* value)
CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val)
{
//assert(false); // todo: implement me!
- fprintf(stderr, "CValueList::Calc not yet implimented\n");
+ static int error_printed = 0;
+ if (error_printed==0) {
+ fprintf(stderr, "CValueList::Calc not yet implimented\n");
+ error_printed = 1;
+ }
return NULL;
}
-
-
CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype,
VALUE_OPERATOR op,
CValue* val)
{
//assert(false); // todo: implement me!
- fprintf(stderr, "CValueList::CalcFinal not yet implimented\n");
+ static int error_printed = 0;
+ if (error_printed==0) {
+ fprintf(stderr, "CValueList::CalcFinal not yet implimented\n");
+ error_printed = 1;
+ }
return NULL;
}
diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h
index 2af5a330c43..68e900e25e0 100644
--- a/source/gameengine/Expressions/ListValue.h
+++ b/source/gameengine/Expressions/ListValue.h
@@ -46,6 +46,7 @@ public:
bool SearchValue(CValue* val);
CValue* FindValue(const STR_String & name);
+ CValue* FindValue(const char *name);
void ReleaseAndRemoveAll();
virtual void SetModified(bool bModified);
@@ -60,6 +61,7 @@ public:
bool CheckEqual(CValue* first,CValue* second);
virtual PyObject* py_getattro(PyObject* attr);
+ virtual PyObject* py_getattro_dict();
virtual PyObject* py_repr(void) {
PyObject *py_proxy= this->GetProxy();
PyObject *py_list= PySequence_List(py_proxy);
@@ -73,6 +75,8 @@ public:
KX_PYMETHOD_NOARGS(CListValue,reverse);
KX_PYMETHOD_O(CListValue,index);
KX_PYMETHOD_O(CListValue,count);
+ KX_PYMETHOD_VARARGS(CListValue,get);
+ KX_PYMETHOD_O(CListValue,has_key);
KX_PYMETHOD_O(CListValue,from_id);
diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile
index 6736149bbcd..f46c0037200 100644
--- a/source/gameengine/Expressions/Makefile
+++ b/source/gameengine/Expressions/Makefile
@@ -41,4 +41,5 @@ CPPFLAGS += -I../../blender/makesdna
CPPFLAGS += -I$(NAN_STRING)/include
CPPFLAGS += -I$(NAN_MOTO)/include
CPPFLAGS += -I../../kernel/gen_system
+CPPFLAGS += -I../../gameengine/SceneGraph
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index 6cfa14ddc80..defb6853e67 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -50,14 +50,20 @@
#include "stdlib.h"
#include "PyObjectPlus.h"
#include "STR_String.h"
+#include "MT_Vector3.h"
/*------------------------------
* PyObjectPlus Type -- Every class, even the abstract one should have a Type
------------------------------*/
PyTypeObject PyObjectPlus::Type = {
- PyObject_HEAD_INIT(NULL)
+#if (PY_VERSION_HEX >= 0x02060000)
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ /* python 2.5 and below */
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
0, /*ob_size*/
+#endif
"PyObjectPlus", /*tp_name*/
sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -90,6 +96,7 @@ 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 */
+ self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */
delete self_plus;
}
@@ -98,7 +105,7 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper
PyObject_DEL( self );
};
-PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor
+PyObjectPlus::PyObjectPlus(PyTypeObject *T) : SG_QList() // constructor
{
MT_assert(T != NULL);
m_proxy= NULL;
@@ -113,13 +120,13 @@ PyMethodDef PyObjectPlus::Methods[] = {
};
PyAttributeDef PyObjectPlus::Attributes[] = {
- KX_PYATTRIBUTE_RO_FUNCTION("isValid", PyObjectPlus, pyattr_get_is_valid),
+ KX_PYATTRIBUTE_RO_FUNCTION("invalid", PyObjectPlus, pyattr_get_invalid),
{NULL} //Sentinel
};
-PyObject* PyObjectPlus::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- Py_RETURN_TRUE;
+ Py_RETURN_FALSE;
}
/*------------------------------
@@ -137,13 +144,33 @@ 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))) {
+ if(!strcmp("invalid", PyString_AsString(attr))) {
Py_RETURN_TRUE;
}
- PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
return NULL;
}
- return self_plus->py_getattro(attr);
+
+ PyObject *ret= self_plus->py_getattro(attr);
+
+ /* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */
+ if(ret==NULL) {
+ char *attr_str= PyString_AsString(attr);
+
+ if (strcmp(attr_str, "__dict__")==0)
+ {
+ /* the error string will probably not
+ * be set but just incase clear it */
+ PyErr_Clear();
+ ret= self_plus->py_getattro_dict();
+ }
+ else if (!PyErr_Occurred()) {
+ /* We looked for an attribute but it wasnt found
+ * since py_getattro didnt set the error, set it here */
+ PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str);
+ }
+ }
+ return ret;
}
/* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */
@@ -151,7 +178,7 @@ int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *val
{
PyObjectPlus *self_plus= BGE_PROXY_REF(self);
if(self_plus==NULL) {
- PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
return -1;
}
@@ -166,7 +193,7 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent
PyObjectPlus *self_plus= BGE_PROXY_REF(self);
if(self_plus==NULL) {
- PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
return NULL;
}
@@ -177,11 +204,7 @@ 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;
+ return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */
} else {
/* Copied from py_getattro_up */
if (PyCObject_Check(descr)) {
@@ -189,13 +212,16 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr)
} 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;
+ return NULL;
}
/* end py_getattro_up copy */
}
}
+PyObject* PyObjectPlus::py_getattro_dict() {
+ return py_getattr_dict(NULL, Type.tp_dict);
+}
+
int PyObjectPlus::py_delattro(PyObject* attr)
{
PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted");
@@ -233,14 +259,14 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef
{
bool *val = reinterpret_cast<bool*>(ptr);
ptr += sizeof(bool);
- PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
+ PyList_SET_ITEM(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));
+ PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val));
break;
}
case KX_PYATTRIBUTE_TYPE_ENUM:
@@ -255,14 +281,14 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef
{
int *val = reinterpret_cast<int*>(ptr);
ptr += sizeof(int);
- PyList_SetItem(resultlist,i,PyInt_FromLong(*val));
+ PyList_SET_ITEM(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));
+ PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(*val));
break;
}
default:
@@ -303,6 +329,16 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef
float *val = reinterpret_cast<float*>(ptr);
return PyFloat_FromDouble(*val);
}
+ case KX_PYATTRIBUTE_TYPE_VECTOR:
+ {
+ PyObject* resultlist = PyList_New(3);
+ MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr);
+ for (unsigned int i=0; i<3; i++)
+ {
+ PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
+ }
+ return resultlist;
+ }
case KX_PYATTRIBUTE_TYPE_STRING:
{
STR_String *val = reinterpret_cast<STR_String*>(ptr);
@@ -326,12 +362,12 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
if (!PySequence_Check(value))
{
PyErr_Format(PyExc_TypeError, "expected a sequence for attribute \"%s\"", attrdef->m_name);
- return 1;
+ return PY_SET_ATTR_FAIL;
}
if (PySequence_Size(value) != attrdef->m_length)
{
PyErr_Format(PyExc_TypeError, "incorrect number of elements in sequence for attribute \"%s\"", attrdef->m_name);
- return 1;
+ return PY_SET_ATTR_FAIL;
}
switch (attrdef->m_type)
{
@@ -339,7 +375,7 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
if (attrdef->m_setFunction == NULL)
{
PyErr_Format(PyExc_AttributeError, "function attribute without function for attribute \"%s\", report to blender.org", attrdef->m_name);
- return 1;
+ return PY_SET_ATTR_FAIL;
}
return (*attrdef->m_setFunction)(self, attrdef, value);
case KX_PYATTRIBUTE_TYPE_BOOL:
@@ -358,7 +394,7 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
default:
// should not happen
PyErr_Format(PyExc_AttributeError, "Unsupported attribute type for attribute \"%s\", report to blender.org", attrdef->m_name);
- return 1;
+ return PY_SET_ATTR_FAIL;
}
// let's implement a smart undo method
bufferSize *= attrdef->m_length;
@@ -495,6 +531,10 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
{
if ((*attrdef->m_checkFunction)(self, attrdef) != 0)
{
+ // if the checing function didnt set an error then set a generic one here so we dont set an error with no exception
+ if (PyErr_Occurred()==0)
+ PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", reasion unknown", attrdef->m_name);
+
// post check returned an error, restore values
UNDO_AND_ERROR:
if (undoBuffer)
@@ -502,12 +542,12 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
memcpy(sourceBuffer, undoBuffer, bufferSize);
free(undoBuffer);
}
- return 1;
+ return PY_SET_ATTR_FAIL;
}
}
if (undoBuffer)
free(undoBuffer);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
else // simple attribute value
{
@@ -516,11 +556,11 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
if (attrdef->m_setFunction == NULL)
{
PyErr_Format(PyExc_AttributeError, "function attribute without function \"%s\", report to blender.org", attrdef->m_name);
- return 1;
+ return PY_SET_ATTR_FAIL;
}
return (*attrdef->m_setFunction)(self, attrdef, value);
}
- if (attrdef->m_checkFunction != NULL)
+ if (attrdef->m_checkFunction != NULL || attrdef->m_type == KX_PYATTRIBUTE_TYPE_VECTOR)
{
// post check function is provided, prepare undo buffer
sourceBuffer = ptr;
@@ -544,9 +584,12 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
if (sourceBuffer)
bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1;
break;
+ case KX_PYATTRIBUTE_TYPE_VECTOR:
+ bufferSize = sizeof(MT_Vector3);
+ break;
default:
PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name);
- return 1;
+ return PY_SET_ATTR_FAIL;
}
if (bufferSize)
{
@@ -664,6 +707,42 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb
*var = (float)val;
break;
}
+ case KX_PYATTRIBUTE_TYPE_VECTOR:
+ {
+ if (!PySequence_Check(value) || PySequence_Size(value) != 3)
+ {
+ PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+ MT_Vector3 *var = reinterpret_cast<MT_Vector3*>(ptr);
+ for (int i=0; i<3; 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);
+ double val = PyFloat_AsDouble(item);
+ if (val == -1.0 && PyErr_Occurred())
+ {
+ PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name);
+ goto RESTORE_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 RESTORE_AND_ERROR;
+ }
+ (*var)[i] = (MT_Scalar)val;
+ }
+ break;
+ }
case KX_PYATTRIBUTE_TYPE_STRING:
{
STR_String *var = reinterpret_cast<STR_String*>(ptr);
@@ -791,6 +870,31 @@ PyObject *PyObjectPlus::PyisA(PyObject *value) // Python wrapper for isA
return NULL;
}
+
+void PyObjectPlus::ProcessReplica()
+{
+ /* Clear the proxy, will be created again if needed with GetProxy()
+ * otherwise the PyObject will point to the wrong reference */
+ m_proxy= NULL;
+}
+
+/* Sometimes we might want to manually invalidate a BGE type even if
+ * it hasnt been released by the BGE, say for example when an object
+ * is removed from a scene, accessing it may cause problems.
+ *
+ * In this case the current proxy is made invalid, disowned,
+ * and will raise an error on access. However if python can get access
+ * to this class again it will make a new proxy and work as expected.
+ */
+void PyObjectPlus::InvalidateProxy() // check typename of each parent
+{
+ if(m_proxy) {
+ BGE_PROXY_REF(m_proxy)=NULL;
+ Py_DECREF(m_proxy);
+ m_proxy= NULL;
+ }
+}
+
/* 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
@@ -852,5 +956,80 @@ PyObject *PyObjectPlus::NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool
return self->m_proxy;
}
+///////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////
+/* deprecation warning management */
+
+bool PyObjectPlus::m_ignore_deprecation_warnings(false);
+void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
+{
+ m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
+}
+
+void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way)
+{
+ {
+ printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
+
+ // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
+
+ PyObject *getframe, *frame;
+ PyObject *f_lineno, *f_code, *co_filename;
+
+ getframe = PySys_GetObject((char *)"_getframe"); // borrowed
+ if (getframe) {
+ frame = PyObject_CallObject(getframe, NULL);
+ if (frame) {
+ f_lineno= PyObject_GetAttrString(frame, "f_lineno");
+ f_code= PyObject_GetAttrString(frame, "f_code");
+ if (f_lineno && f_code) {
+ co_filename= PyObject_GetAttrString(f_code, "co_filename");
+ if (co_filename) {
+
+ printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
+
+ Py_DECREF(f_lineno);
+ Py_DECREF(f_code);
+ Py_DECREF(co_filename);
+ Py_DECREF(frame);
+ return;
+ }
+ }
+
+ Py_XDECREF(f_lineno);
+ Py_XDECREF(f_code);
+ Py_DECREF(frame);
+ }
+
+ }
+ PyErr_Clear();
+ printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
+ }
+}
+
+void PyObjectPlus::ClearDeprecationWarning()
+{
+ WarnLink *wlink_next;
+ WarnLink *wlink = GetDeprecationWarningLinkFirst();
+
+ while(wlink)
+ {
+ wlink->warn_done= false; /* no need to NULL the link, its cleared before adding to the list next time round */
+ wlink_next= reinterpret_cast<WarnLink *>(wlink->link);
+ wlink->link= NULL;
+ wlink= wlink_next;
+ }
+ NullDeprecationWarning();
+}
+
+WarnLink* m_base_wlink_first= NULL;
+WarnLink* m_base_wlink_last= NULL;
+
+WarnLink* PyObjectPlus::GetDeprecationWarningLinkFirst(void) {return m_base_wlink_first;}
+WarnLink* PyObjectPlus::GetDeprecationWarningLinkLast(void) {return m_base_wlink_last;}
+void PyObjectPlus::SetDeprecationWarningFirst(WarnLink* wlink) {m_base_wlink_first= wlink;}
+void PyObjectPlus::SetDeprecationWarningLinkLast(WarnLink* wlink) {m_base_wlink_last= wlink;}
+void PyObjectPlus::NullDeprecationWarning() {m_base_wlink_first= m_base_wlink_last= NULL;}
+
#endif //NO_EXP_PYTHON_EMBEDDING
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 370717a919b..369c00782cc 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -38,11 +38,30 @@
#include "KX_Python.h"
#include "STR_String.h"
+#include "MT_Vector3.h"
+#include "SG_QList.h"
/*------------------------------
* Python defines
------------------------------*/
+
+
+#if PY_VERSION_HEX > 0x03000000
+#define PyString_FromString PyUnicode_FromString
+#define PyString_FromFormat PyUnicode_FromFormat
+#define PyString_Check PyUnicode_Check
+#define PyString_Size PyUnicode_GetSize
+
+#define PyInt_FromLong PyLong_FromSsize_t
+#define PyInt_AsLong PyLong_AsSsize_t
+#define PyString_AsString _PyUnicode_AsString
+#define PyInt_Check PyLong_Check
+#define PyInt_AS_LONG PyLong_AsLong // TODO - check this one
+#endif
+
+
+
/*
Py_RETURN_NONE
Python 2.4 macro.
@@ -81,6 +100,36 @@ static inline void Py_Fatal(const char *M) {
exit(-1);
};
+
+/* Use with ShowDeprecationWarning macro */
+typedef struct {
+ bool warn_done;
+ void *link;
+} WarnLink;
+
+#define ShowDeprecationWarning(old_way, new_way) \
+{ \
+ static WarnLink wlink = {false, NULL}; \
+ if ((m_ignore_deprecation_warnings || wlink.warn_done)==0) \
+ { \
+ ShowDeprecationWarning_func(old_way, new_way); \
+ WarnLink *wlink_last= GetDeprecationWarningLinkLast(); \
+ ShowDeprecationWarning_func(old_way, new_way); \
+ wlink.warn_done = true; \
+ wlink.link = NULL; \
+ \
+ if(wlink_last) { \
+ wlink_last->link= (void *)&(wlink); \
+ SetDeprecationWarningLinkLast(&(wlink)); \
+ } else { \
+ SetDeprecationWarningFirst(&(wlink)); \
+ SetDeprecationWarningLinkLast(&(wlink)); \
+ } \
+ } \
+} \
+
+
+
typedef struct {
PyObject_HEAD /* required python macro */
class PyObjectPlus *ref;
@@ -92,7 +141,7 @@ typedef struct {
#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)
+#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == PyObjectPlus::py_base_dealloc)
// This must be the first line of each
@@ -114,6 +163,9 @@ typedef struct {
// This defines the py_getattro_up macro
// which allows attribute and method calls
// to be properly passed up the hierarchy.
+ //
+ // Note, PyDict_GetItem() WONT set an exception!
+ // let the py_base_getattro function do this.
#define py_getattro_up(Parent) \
\
@@ -125,21 +177,14 @@ typedef struct {
} 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; \
+ return NULL; \
} \
} else { \
- PyErr_Clear(); \
- PyObject *rvalue= Parent::py_getattro(attr); \
- \
- if (strcmp(PyString_AsString(attr), "__dict__")==0) { \
- return py_getattr_dict(rvalue, Type.tp_dict); \
- } \
- \
- return rvalue; \
- } \
- return NULL;
+ return Parent::py_getattro(attr); \
+ }
+#define py_getattro_dict_up(Parent) \
+ return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict);
/*
* nonzero values are an error for setattr
@@ -182,30 +227,35 @@ typedef struct {
#define KX_PYMETHOD(class_name, method_name) \
PyObject* Py##method_name(PyObject* args, PyObject* kwds); \
static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
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* args); \
static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args); \
}; \
#define KX_PYMETHOD_NOARGS(class_name, method_name) \
PyObject* Py##method_name(); \
static PyObject* sPy##method_name( PyObject* self) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(); \
}; \
#define KX_PYMETHOD_O(class_name, method_name) \
PyObject* Py##method_name(PyObject* value); \
static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(value) - " BGE_PROXY_ERROR_MSG); return NULL; } \
return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value); \
}; \
#define KX_PYMETHOD_DOC(class_name, method_name) \
PyObject* Py##method_name(PyObject* args, PyObject* kwds); \
static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(...) - " BGE_PROXY_ERROR_MSG); return NULL; } \
return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args, kwds); \
}; \
static const char method_name##_doc[]; \
@@ -213,6 +263,7 @@ typedef struct {
#define KX_PYMETHOD_DOC_VARARGS(class_name, method_name) \
PyObject* Py##method_name(PyObject* args); \
static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(...) - " BGE_PROXY_ERROR_MSG); return NULL; } \
return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args); \
}; \
static const char method_name##_doc[]; \
@@ -220,6 +271,7 @@ typedef struct {
#define KX_PYMETHOD_DOC_O(class_name, method_name) \
PyObject* Py##method_name(PyObject* value); \
static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(value) - " BGE_PROXY_ERROR_MSG); return NULL; } \
return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value); \
}; \
static const char method_name##_doc[]; \
@@ -227,6 +279,7 @@ typedef struct {
#define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \
PyObject* Py##method_name(); \
static PyObject* sPy##method_name( PyObject* self) { \
+ if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \
return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(); \
}; \
static const char method_name##_doc[]; \
@@ -276,6 +329,7 @@ enum KX_PYATTRIBUTE_TYPE {
KX_PYATTRIBUTE_TYPE_STRING,
KX_PYATTRIBUTE_TYPE_DUMMY,
KX_PYATTRIBUTE_TYPE_FUNCTION,
+ KX_PYATTRIBUTE_TYPE_VECTOR,
};
enum KX_PYATTRIBUTE_ACCESS {
@@ -313,97 +367,105 @@ typedef struct KX_PYATTRIBUTE_DEF {
int *m_intPtr;
float *m_floatPtr;
STR_String *m_stringPtr;
+ MT_Vector3 *m_vectorPtr;
} m_typeCheck;
} 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, 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, 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, NULL, 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, 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, NULL, 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, &object::function, NULL, NULL, {&((object *)0)->field, NULL, 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, NULL, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, 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, 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, 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, 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, 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, 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, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, 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, 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, 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, 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, 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, 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, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, 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, 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, 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, {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, 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, {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, 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, {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, 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, {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, 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, {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, 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, {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, 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, {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, 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, {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, 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, {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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, NULL} }
#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, 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, NULL} }
#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, 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, NULL} }
+
+#define KX_PYATTRIBUTE_VECTOR_RW(name,min,max,object,field) \
+ { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} }
+#define KX_PYATTRIBUTE_VECTOR_RW_CHECK(name,min,max,clamp,object,field,function) \
+ { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} }
+#define KX_PYATTRIBUTE_VECTOR_RO(name,object,field) \
+ { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, 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} }
+ { 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, 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} }
+ { 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, 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} }
+ { 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, 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} }
+ { 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, NULL} }
/*------------------------------
@@ -411,7 +473,18 @@ typedef struct KX_PYATTRIBUTE_DEF {
------------------------------*/
typedef PyTypeObject * PyParentObject; // Define the PyParent Object
-class PyObjectPlus
+// By making SG_QList the ultimate parent for PyObjectPlus objects, it
+// allows to put them in 2 different dynamic lists at the same time
+// The use of these links is interesting because they free of memory allocation
+// but it's very important not to mess up with them. If you decide that
+// the SG_QList or SG_DList component is used for something for a certain class,
+// they cannot can be used for anything else at a parent level!
+// What these lists are and what they are used for must be carefully documented
+// at the level where they are used.
+// DON'T MAKE ANY USE OF THESE LIST AT THIS LEVEL, they are already used
+// at SCA_IActuator, SCA_ISensor, SCA_IController level which rules out the
+// possibility to use them at SCA_ILogicBrick, CValue and PyObjectPlus level.
+class PyObjectPlus : public SG_QList
{ // The PyObjectPlus abstract class
Py_Header; // Always start with Py_Header
@@ -434,6 +507,7 @@ public:
/* 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 PyObject* py_getattro_dict();
virtual int py_delattro(PyObject *attr);
virtual int py_setattro(PyObject *attr, PyObject *value);
virtual PyObject* py_repr(void);
@@ -449,12 +523,36 @@ public:
KX_PYMETHOD_O(PyObjectPlus,isA);
/* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */
- static PyObject* pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp);
static PyObject *NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns);
+
+ void InvalidateProxy();
+
+ /**
+ * Makes sure any internal data owned by this class is deep copied.
+ */
+ virtual void ProcessReplica();
+
+
+ static bool m_ignore_deprecation_warnings;
+
+ static WarnLink* GetDeprecationWarningLinkFirst(void);
+ static WarnLink* GetDeprecationWarningLinkLast(void);
+ static void SetDeprecationWarningFirst(WarnLink* wlink);
+ static void SetDeprecationWarningLinkLast(WarnLink* wlink);
+ static void NullDeprecationWarning();
+
+ /** enable/disable display of deprecation warnings */
+ static void SetDeprecationWarnings(bool ignoreDeprecationWarnings);
+ /** Shows a deprecation warning */
+ static void ShowDeprecationWarning_func(const char* method,const char* prop);
+ static void ClearDeprecationWarning();
+
};
+
PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict);
#endif // _adr_py_lib_h_
diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript
index 25adcf3e895..b5c69eafe6b 100644
--- a/source/gameengine/Expressions/SConscript
+++ b/source/gameengine/Expressions/SConscript
@@ -3,7 +3,7 @@ Import ('env')
sources = env.Glob('*.cpp')
-incs ='. #source/kernel/gen_system #intern/string #intern/moto/include'
+incs ='. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/SceneGraph'
incs += ' ' + env['BF_PYTHON_INC']
cxxflags = []
diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/StringValue.cpp
index 2b3c62c411e..a7033fcf11c 100644
--- a/source/gameengine/Expressions/StringValue.cpp
+++ b/source/gameengine/Expressions/StringValue.cpp
@@ -34,7 +34,7 @@ effect: constructs a new CStringValue
m_strString = "[Illegal String constructor call]";
}
-CStringValue::CStringValue(STR_String txt,STR_String name,AllocationTYPE alloctype)
+CStringValue::CStringValue(const char *txt,const char *name,AllocationTYPE alloctype)
/*
pre:
effect: constructs a new CStringValue containing text txt
@@ -133,7 +133,7 @@ bool CStringValue::IsEqual(const STR_String & other)
CValue* CStringValue::GetReplica()
{
CStringValue* replica = new CStringValue(*this);
- CValue::AddDataToReplica(replica);
+ replica->ProcessReplica();
return replica;
};
diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h
index 16575ed7ffa..52f8a580f4d 100644
--- a/source/gameengine/Expressions/StringValue.h
+++ b/source/gameengine/Expressions/StringValue.h
@@ -26,7 +26,7 @@ class CStringValue : public CPropValue
public:
/// Construction / destruction
CStringValue();
- CStringValue (STR_String txt, STR_String name , AllocationTYPE alloctype = CValue::HEAPVALUE);
+ CStringValue (const char *txt, const char *name , AllocationTYPE alloctype = CValue::HEAPVALUE);
virtual ~CStringValue() {
};
diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp
index 7cb97909119..e6ef9733da8 100644
--- a/source/gameengine/Expressions/Value.cpp
+++ b/source/gameengine/Expressions/Value.cpp
@@ -32,13 +32,17 @@
//////////////////////////////////////////////////////////////////////
double CValue::m_sZeroVec[3] = {0.0,0.0,0.0};
-bool CValue::m_ignore_deprecation_warnings(false);
#ifndef NO_EXP_PYTHON_EMBEDDING
PyTypeObject CValue::Type = {
- PyObject_HEAD_INIT(NULL)
- 0,
+#if (PY_VERSION_HEX >= 0x02060000)
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ /* python 2.5 and below */
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
+ 0, /* ob_size */
+#endif
"CValue",
sizeof(PyObjectPlus_Proxy),
0,
@@ -62,13 +66,14 @@ PyParentObject CValue::Parents[] = {
};
PyMethodDef CValue::Methods[] = {
-// { "printHello", (PyCFunction) CValue::sPyPrintHello, METH_VARARGS},
{ "getName", (PyCFunction) CValue::sPyGetName, METH_NOARGS},
{NULL,NULL} //Sentinel
};
PyObject* CValue::PyGetName()
{
+ ShowDeprecationWarning("getName()", "the name property");
+
return PyString_FromString(this->GetName());
}
@@ -287,13 +292,15 @@ CValue* CValue::GetProperty(const char *inName)
//
// Get text description of property with name <inName>, returns an empty string if there is no property named <inName>
//
-STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext)
+const STR_String& CValue::GetPropertyText(const STR_String & inName)
{
+ const static STR_String sEmpty("");
+
CValue *property = GetProperty(inName);
if (property)
return property->GetText();
else
- return deftext;//String::sEmpty;
+ return sEmpty;
}
float CValue::GetPropertyNumber(const STR_String& inName,float defnumber)
@@ -439,27 +446,6 @@ int CValue::GetPropertyCount()
}
-
-
-
-void CValue::CloneProperties(CValue *replica)
-{
-
- if (m_pNamedPropertyArray)
- {
- replica->m_pNamedPropertyArray=NULL;
- 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);
- val->Release();
- }
- }
-
-
-}
-
double* CValue::GetVector3(bool bGetTransformedVec)
{
assertd(false); // don;t get vector from me
@@ -470,50 +456,12 @@ double* CValue::GetVector3(bool bGetTransformedVec)
/*---------------------------------------------------------------------------------------------------------------------
Reference Counting
---------------------------------------------------------------------------------------------------------------------*/
-//
-// Add a reference to this value
-//
-CValue *CValue::AddRef()
-{
- // Increase global reference count, used to see at the end of the program
- // if all CValue-derived classes have been dereferenced to 0
- //debug(gRefCountValue++);
-#ifdef _DEBUG
- //gRefCountValue++;
-#endif
- m_refcount++;
- return this;
-}
//
// Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
//
-int CValue::Release()
-{
- // Decrease global reference count, used to see at the end of the program
- // if all CValue-derived classes have been dereferenced to 0
- //debug(gRefCountValue--);
-#ifdef _DEBUG
- //gRefCountValue--;
-#endif
- // Decrease local reference count, if it reaches 0 the object should be freed
- if (--m_refcount > 0)
- {
- // Reference count normal, return new reference count
- return m_refcount;
- }
- else
- {
- // 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;
- }
-
-}
@@ -534,23 +482,32 @@ void CValue::DisableRefCount()
-void CValue::AddDataToReplica(CValue *replica)
+void CValue::ProcessReplica() /* was AddDataToReplica in 2.48 */
{
- replica->m_refcount = 1;
-
+ m_refcount = 1;
+
#ifdef _DEBUG
//gRefCountValue++;
#endif
- replica->m_ValFlags.RefCountDisabled = false;
+ PyObjectPlus::ProcessReplica();
- replica->ReplicaSetName(GetName());
+ m_ValFlags.RefCountDisabled = false;
- //copy all props
- CloneProperties(replica);
+ /* copy all props */
+ if (m_pNamedPropertyArray)
+ {
+ std::map<STR_String,CValue*> *pOldArray = m_pNamedPropertyArray;
+ m_pNamedPropertyArray=NULL;
+ std::map<STR_String,CValue*>::iterator it;
+ for (it= pOldArray->begin(); (it != pOldArray->end()); it++)
+ {
+ CValue *val = (*it).second->GetReplica();
+ SetProperty((*it).first,val);
+ val->Release();
+ }
+ }
}
-
-
CValue* CValue::FindIdentifier(const STR_String& identifiername)
{
@@ -592,18 +549,22 @@ static PyMethodDef CValueMethods[] =
};
PyAttributeDef CValue::Attributes[] = {
+ KX_PYATTRIBUTE_RO_FUNCTION("name", CValue, pyattr_get_name),
{ NULL } //Sentinel
};
PyObject* CValue::py_getattro(PyObject *attr)
-{
+{
char *attr_str= PyString_AsString(attr);
CValue* resultattr = GetProperty(attr_str);
if (resultattr)
{
+ /* only show the wanting here because python inspects for __class__ and KX_MeshProxy uses CValues name attr */
+ ShowDeprecationWarning("val = ob.attr", "val = ob['attr']");
+
PyObject* pyconvert = resultattr->ConvertValueToPython();
-
+
if (pyconvert)
return pyconvert;
else
@@ -612,7 +573,16 @@ PyObject* CValue::py_getattro(PyObject *attr)
py_getattro_up(PyObjectPlus);
}
-CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
+PyObject* CValue::py_getattro_dict() {
+ py_getattro_dict_up(PyObjectPlus);
+}
+
+PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef) {
+ CValue * self = static_cast<CValue *> (self_v);
+ return PyString_FromString(self->GetName());
+}
+
+CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix)
{
CValue* vallie = NULL;
@@ -628,7 +598,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
for (i=0;i<numitems;i++)
{
PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */
- CValue* listitemval = ConvertPythonToValue(listitem);
+ CValue* listitemval = ConvertPythonToValue(listitem, error_prefix);
if (listitemval)
{
listval->Add(listitemval);
@@ -665,13 +635,22 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
{
vallie = new CStringValue(PyString_AsString(pyobj),"");
} else
- if (pyobj->ob_type==&CValue::Type || pyobj->ob_type==&CListValue::Type)
+ if (BGE_PROXY_CHECK_TYPE(pyobj)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */
{
- vallie = ((CValue*) pyobj)->AddRef();
+ if (BGE_PROXY_REF(pyobj) && (BGE_PROXY_REF(pyobj))->isA(&CValue::Type))
+ {
+ vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef();
+ } else {
+
+ if(BGE_PROXY_REF(pyobj)) /* this is not a CValue */
+ PyErr_Format(PyExc_TypeError, "%sgame engine python type cannot be used as a property", error_prefix);
+ else /* PyObjectPlus_Proxy has been removed, cant use */
+ PyErr_Format(PyExc_SystemError, "%s"BGE_PROXY_ERROR_MSG, error_prefix);
+ }
} else
{
/* return an error value from the caller */
- PyErr_SetString(PyExc_TypeError, "This python type could not be converted to a to a game engine property");
+ PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix);
}
return vallie;
@@ -679,21 +658,26 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
int CValue::py_delattro(PyObject *attr)
{
+ ShowDeprecationWarning("del ob.attr", "del ob['attr']");
+
char *attr_str= PyString_AsString(attr);
- if (RemoveProperty(STR_String(attr_str)))
+ if (RemoveProperty(attr_str))
return 0;
PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str);
- return 1;
+ return PY_SET_ATTR_MISSING;
}
int CValue::py_setattro(PyObject *attr, PyObject* pyobj)
{
- char *attr_str= PyString_AsString(attr);
- CValue* oldprop = GetProperty(attr_str);
+ ShowDeprecationWarning("ob.attr = val", "ob['attr'] = val");
- CValue* vallie = ConvertPythonToValue(pyobj);
- if (vallie)
+ char *attr_str= PyString_AsString(attr);
+ CValue* oldprop = GetProperty(attr_str);
+ CValue* vallie;
+
+ /* Dissallow python to assign GameObjects, Scenes etc as values */
+ if ((BGE_PROXY_CHECK_TYPE(pyobj)==0) && (vallie = ConvertPythonToValue(pyobj, "cvalue.attr = value: ")))
{
if (oldprop)
oldprop->SetValue(vallie);
@@ -750,10 +734,40 @@ PyObject* CValue::PyMake(PyObject* ignored,PyObject* args)
}
*/
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef CValue_module_def = {
+ {}, /* m_base */
+ "CValue", /* m_name */
+ 0, /* m_doc */
+ 0, /* m_size */
+ CValueMethods, /* m_methods */
+ 0, /* m_reload */
+ 0, /* m_traverse */
+ 0, /* m_clear */
+ 0, /* m_free */
+};
+#endif
+
extern "C" {
void initCValue(void)
{
- Py_InitModule("CValue",CValueMethods);
+ PyObject *m;
+ /* Use existing module where possible
+ * be careful not to init any runtime vars after this */
+ m = PyImport_ImportModule( "CValue" );
+ if(m) {
+ Py_DECREF(m);
+ //return m;
+ }
+ else {
+ PyErr_Clear();
+
+#if (PY_VERSION_HEX >= 0x03000000)
+ PyModule_Create(&CValue_module_def);
+#else
+ Py_InitModule("CValue",CValueMethods);
+#endif
+ }
}
}
@@ -779,52 +793,3 @@ void CValue::SetValue(CValue* newval)
// no one should get here
assertd(newval->GetNumber() == 10121969);
}
-///////////////////////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////////////////////
-/* deprecation warning management */
-void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings)
-{
- m_ignore_deprecation_warnings = ignoreDeprecationWarnings;
-}
-
-void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way)
-{
- if (!m_ignore_deprecation_warnings) {
- printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way);
-
- // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno)
-
- PyObject *getframe, *frame;
- PyObject *f_lineno, *f_code, *co_filename;
-
- getframe = PySys_GetObject((char *)"_getframe"); // borrowed
- if (getframe) {
- frame = PyObject_CallObject(getframe, NULL);
- if (frame) {
- f_lineno= PyObject_GetAttrString(frame, "f_lineno");
- f_code= PyObject_GetAttrString(frame, "f_code");
- if (f_lineno && f_code) {
- co_filename= PyObject_GetAttrString(f_code, "co_filename");
- if (co_filename) {
-
- printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno));
-
- Py_DECREF(f_lineno);
- Py_DECREF(f_code);
- Py_DECREF(co_filename);
- Py_DECREF(frame);
- return;
- }
- }
-
- Py_XDECREF(f_lineno);
- Py_XDECREF(f_code);
- Py_DECREF(frame);
- }
-
- }
- PyErr_Clear();
- printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n");
- }
-}
-
diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h
index a687e1a493c..29ef19b46c9 100644
--- a/source/gameengine/Expressions/Value.h
+++ b/source/gameengine/Expressions/Value.h
@@ -225,16 +225,19 @@ public:
virtual PyObject* py_getattro(PyObject *attr);
+ virtual PyObject* py_getattro_dict();
virtual PyObject* ConvertValueToPython() {
return NULL;
}
- virtual CValue* ConvertPythonToValue(PyObject* pyobj);
+ virtual CValue* ConvertPythonToValue(PyObject* pyobj, const char *error_prefix);
virtual int py_delattro(PyObject *attr);
virtual int py_setattro(PyObject *attr, PyObject* value);
+ static PyObject * pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef);
+
virtual PyObject* ConvertKeysToPython( void );
KX_PYMETHOD_NOARGS(CValue,GetName);
@@ -258,17 +261,56 @@ public:
};
/// Reference Counting
- 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)
-
+ int GetRefCount()
+ {
+ return m_refcount;
+ }
+
+ // Add a reference to this value
+ CValue* AddRef()
+ {
+ // Increase global reference count, used to see at the end of the program
+ // if all CValue-derived classes have been dereferenced to 0
+ //debug(gRefCountValue++);
+ #ifdef _DEBUG
+ //gRefCountValue++;
+ #endif
+ m_refcount++;
+ return this;
+ }
+
+ // Release a reference to this value (when reference count reaches 0, the value is removed from the heap)
+ int Release()
+ {
+ // Decrease global reference count, used to see at the end of the program
+ // if all CValue-derived classes have been dereferenced to 0
+ //debug(gRefCountValue--);
+ #ifdef _DEBUG
+ //gRefCountValue--;
+ #endif
+ // Decrease local reference count, if it reaches 0 the object should be freed
+ if (--m_refcount > 0)
+ {
+ // Reference count normal, return new reference count
+ return m_refcount;
+ }
+ else
+ {
+ // 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;
+ }
+ }
+
/// Property Management
virtual void SetProperty(const STR_String& name,CValue* ioProperty); // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed
virtual void SetProperty(const 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>
+ const STR_String& GetPropertyText(const STR_String & inName); // 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 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();
@@ -280,7 +322,6 @@ public:
virtual CValue* GetProperty(int inIndex); // Get property number <inIndex>
virtual int GetPropertyCount(); // Get the amount of properties assiocated with this value
- virtual void CloneProperties(CValue* replica);
virtual CValue* FindIdentifier(const STR_String& identifiername);
/** Set the wireframe color of this value depending on the CSG
* operator type <op>
@@ -292,21 +333,17 @@ public:
double* ZeroVector() { return m_sZeroVec; };
virtual double* GetVector3(bool bGetTransformedVec = false);
- virtual STR_String GetName() = 0; // Retrieve the name of the value
- virtual void SetName(STR_String name) = 0; // Set the name of the value
- virtual void ReplicaSetName(STR_String name) = 0;
+ virtual STR_String& GetName() = 0; // Retrieve the name of the value
+ virtual void SetName(const char *name) = 0; // Set the name of the value
/** Sets the value to this cvalue.
* @attention this particular function should never be called. Why not abstract? */
virtual void SetValue(CValue* newval);
virtual CValue* GetReplica() =0;
+ virtual void ProcessReplica();
//virtual CValue* Copy() = 0;
STR_String op2str(VALUE_OPERATOR op);
- /** enable/disable display of deprecation warnings */
- static void SetDeprecationWarnings(bool ignoreDeprecationWarnings);
- /** Shows a deprecation warning */
- static void ShowDeprecationWarning(const char* method,const char* prop);
// setting / getting flags
inline void SetSelected(bool bSelected) { m_ValFlags.Selected = bSelected; }
@@ -327,10 +364,10 @@ public:
virtual void SetCustomFlag2(bool bCustomFlag) { m_ValFlags.CustomFlag2 = bCustomFlag;};
virtual bool IsCustomFlag2() { return m_ValFlags.CustomFlag2;};
-
+
protected:
virtual void DisableRefCount(); // Disable reference counting for this value
- virtual void AddDataToReplica(CValue* replica);
+ //virtual void AddDataToReplica(CValue* replica);
virtual ~CValue();
private:
// Member variables
@@ -338,7 +375,6 @@ private:
ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage)
int m_refcount; // Reference Counter
static double m_sZeroVec[3];
- static bool m_ignore_deprecation_warnings;
};
@@ -386,49 +422,28 @@ public:
#else
CPropValue() :
#endif //NO_EXP_PYTHON_EMBEDDING
- m_pstrNewName(NULL)
+ m_strNewName()
{
}
virtual ~CPropValue()
{
- if (m_pstrNewName)
- {
- delete m_pstrNewName;
- m_pstrNewName = NULL;
- }
}
- virtual void SetName(STR_String name) {
- if (m_pstrNewName)
- {
- delete m_pstrNewName;
- m_pstrNewName = NULL;
- }
- if (name.Length())
- m_pstrNewName = new STR_String(name);
- }
- virtual void ReplicaSetName(STR_String name) {
- m_pstrNewName=NULL;
- if (name.Length())
- m_pstrNewName = new STR_String(name);
+ virtual void SetName(const char *name) {
+ m_strNewName = name;
}
- virtual STR_String GetName() {
+ virtual STR_String& GetName() {
//STR_String namefromprop = GetPropertyText("Name");
//if (namefromprop.Length() > 0)
// return namefromprop;
-
- if (m_pstrNewName)
- {
- return *m_pstrNewName;
- }
- return STR_String("");
+ return m_strNewName;
}; // name of Value
protected:
- STR_String* m_pstrNewName; // Identification
+ STR_String m_strNewName; // Identification
};
#endif // !defined _VALUEBASECLASS_H
diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/VectorValue.cpp
index 497a50b90e7..c58c78e6ebe 100644
--- a/source/gameengine/Expressions/VectorValue.cpp
+++ b/source/gameengine/Expressions/VectorValue.cpp
@@ -48,7 +48,7 @@ CVectorValue::CVectorValue(float x,float y,float z, AllocationTYPE alloctype)
m_vec[KX_Z] = m_transformedvec[KX_Z] = z;
}
-CVectorValue::CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype) {
+CVectorValue::CVectorValue(double vec[],const char *name,AllocationTYPE alloctype) {
SetCustomFlag1(false);//FancyOutput=false;
@@ -204,7 +204,7 @@ const STR_String & CVectorValue::GetText()
CValue* CVectorValue::GetReplica() {
CVectorValue* replica = new CVectorValue(*this);
- CValue::AddDataToReplica(replica);
+ replica->ProcessReplica();
return replica;
};
diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/VectorValue.h
index 99bf0abb11b..19c7dd30076 100644
--- a/source/gameengine/Expressions/VectorValue.h
+++ b/source/gameengine/Expressions/VectorValue.h
@@ -41,7 +41,7 @@ public:
CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val);
- CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE);
+ CVectorValue(double vec[],const char *name,AllocationTYPE alloctype=CValue::HEAPVALUE);
CVectorValue() {};
CVectorValue(double vec[],AllocationTYPE alloctype=CValue::HEAPVALUE);