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:
authorBenoit Bolsee <benoit.bolsee@online.be>2009-01-02 20:43:56 +0300
committerBenoit Bolsee <benoit.bolsee@online.be>2009-01-02 20:43:56 +0300
commitcc569504d0468ec19a1018ea804aa418c134cb0f (patch)
tree732f5d6fe3d742f63dae5f6e899aea566ae52b0f /source/gameengine/Expressions/PyObjectPlus.cpp
parentabd4934d1aeceafaa2fc242f00db0ba53a7e24db (diff)
BGE API Cleanup: update the python attribute definition framework.
* Value clamping to min/max is now supported as an option for integer, float and string attribute (for string clamping=trim to max length) * Post check function now take PyAttributeDef parameter so that more generic function can be written. * Definition of SCA_ILogicBrick::CheckProperty() function to check that a string attribute contains a valid property name of the parent game object. * Definition of enum attribute vi KX_PYATTRIBUTE_ENUM... macros. Enum are handled just like integer but to be totally paranoid, the sizeof() of the enum member is check at run time to match integer size. * More bricks updated to use the framework.
Diffstat (limited to 'source/gameengine/Expressions/PyObjectPlus.cpp')
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp142
1 files changed, 115 insertions, 27 deletions
diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp
index c31587628b0..8fd99c8d267 100644
--- a/source/gameengine/Expressions/PyObjectPlus.cpp
+++ b/source/gameengine/Expressions/PyObjectPlus.cpp
@@ -164,6 +164,14 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel
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);
@@ -180,6 +188,7 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel
}
default:
// no support for array of complex data
+ Py_DECREF(resultlist);
return NULL;
}
}
@@ -198,6 +207,13 @@ PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *sel
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);
@@ -260,6 +276,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
case KX_PYATTRIBUTE_TYPE_SHORT:
bufferSize = sizeof(short int);
break;
+ case KX_PYATTRIBUTE_TYPE_ENUM:
case KX_PYATTRIBUTE_TYPE_INT:
bufferSize = sizeof(int);
break;
@@ -313,7 +330,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
if (PyInt_Check(item))
{
long val = PyInt_AsLong(item);
- if (val < attrdef->m_imin || val > attrdef->m_imax)
+ 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;
@@ -327,6 +351,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
}
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_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org");
+ goto UNDO_AND_ERROR;
+ }
+ // walkthrough
case KX_PYATTRIBUTE_TYPE_INT:
{
int *var = reinterpret_cast<int*>(ptr);
@@ -334,7 +366,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
if (PyInt_Check(item))
{
long val = PyInt_AsLong(item);
- if (val < attrdef->m_imin || val > attrdef->m_imax)
+ 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;
@@ -352,21 +391,25 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
{
float *var = reinterpret_cast<float*>(ptr);
ptr += sizeof(float);
- if (PyFloat_Check(item))
+ double val = PyFloat_AsDouble(item);
+ if (val == -1.0 && PyErr_Occurred())
{
- double val = PyFloat_AsDouble(item);
- 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;
+ PyErr_SetString(PyExc_TypeError, "expected a float");
+ goto UNDO_AND_ERROR;
}
- else
+ else if (attrdef->m_clamp)
{
- PyErr_SetString(PyExc_TypeError, "expected a float");
+ 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;
}
default:
@@ -378,7 +421,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
// no error, call check function if any
if (attrdef->m_function != NULL)
{
- if ((*attrdef->m_function)(self) != 0)
+ if ((*attrdef->m_function)(self, attrdef) != 0)
{
// post check returned an error, restore values
UNDO_AND_ERROR:
@@ -409,6 +452,7 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
case KX_PYATTRIBUTE_TYPE_SHORT:
bufferSize = sizeof(short);
break;
+ case KX_PYATTRIBUTE_TYPE_ENUM:
case KX_PYATTRIBUTE_TYPE_INT:
bufferSize = sizeof(int);
break;
@@ -460,7 +504,14 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
if (PyInt_Check(value))
{
long val = PyInt_AsLong(value);
- if (val < attrdef->m_imin || val > attrdef->m_imax)
+ 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;
@@ -474,13 +525,28 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
}
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_SetString(PyExc_AttributeError, "attribute size check error, report to blender.org");
+ 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 (val < attrdef->m_imin || val > attrdef->m_imax)
+ 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;
@@ -497,21 +563,25 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
case KX_PYATTRIBUTE_TYPE_FLOAT:
{
float *var = reinterpret_cast<float*>(ptr);
- if (PyFloat_Check(value))
+ double val = PyFloat_AsDouble(value);
+ if (val == -1.0 && PyErr_Occurred())
{
- double val = PyFloat_AsDouble(value);
- if (val < attrdef->m_fmin || val > attrdef->m_fmax)
- {
- PyErr_SetString(PyExc_ValueError, "value out of range");
- goto FREE_AND_ERROR;
- }
- *var = (float)val;
+ PyErr_SetString(PyExc_TypeError, "expected a float");
+ goto FREE_AND_ERROR;
}
- else
+ else if (attrdef->m_clamp)
{
- PyErr_SetString(PyExc_TypeError, "expected a float");
+ 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:
@@ -520,7 +590,24 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
if (PyString_Check(value))
{
char *val = PyString_AsString(value);
- if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax)
+ 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;
@@ -543,9 +630,10 @@ int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, con
// check if post processing is needed
if (attrdef->m_function != NULL)
{
- if ((*attrdef->m_function)(self) != 0)
+ if ((*attrdef->m_function)(self, attrdef) != 0)
{
// restore value
+ RESTORE_AND_ERROR:
if (undoBuffer)
{
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING)