[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [18267] trunk/blender/source/gameengine: BGE API Cleanup: update the python attribute definition framework.
Benoit Bolsee
benoit.bolsee at online.be
Fri Jan 2 18:43:57 CET 2009
Revision: 18267
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=18267
Author: ben2610
Date: 2009-01-02 18:43:56 +0100 (Fri, 02 Jan 2009)
Log Message:
-----------
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.
Modified Paths:
--------------
trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp
trunk/blender/source/gameengine/Expressions/PyObjectPlus.h
trunk/blender/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
trunk/blender/source/gameengine/GameLogic/SCA_ActuatorSensor.h
trunk/blender/source/gameengine/GameLogic/SCA_DelaySensor.cpp
trunk/blender/source/gameengine/GameLogic/SCA_ILogicBrick.cpp
trunk/blender/source/gameengine/GameLogic/SCA_ILogicBrick.h
trunk/blender/source/gameengine/GameLogic/SCA_ISensor.cpp
trunk/blender/source/gameengine/GameLogic/SCA_JoystickSensor.cpp
trunk/blender/source/gameengine/GameLogic/SCA_JoystickSensor.h
trunk/blender/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
trunk/blender/source/gameengine/GameLogic/SCA_MouseSensor.cpp
trunk/blender/source/gameengine/GameLogic/SCA_MouseSensor.h
trunk/blender/source/gameengine/GameLogic/SCA_PropertyActuator.cpp
trunk/blender/source/gameengine/GameLogic/SCA_PropertySensor.cpp
trunk/blender/source/gameengine/GameLogic/SCA_PropertySensor.h
trunk/blender/source/gameengine/GameLogic/SCA_RandomActuator.cpp
trunk/blender/source/gameengine/GameLogic/SCA_RandomActuator.h
Modified: trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp
===================================================================
--- trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp 2009-01-02 16:58:09 UTC (rev 18266)
+++ trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp 2009-01-02 17:43:56 UTC (rev 18267)
@@ -164,6 +164,14 @@
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 @@
}
default:
// no support for array of complex data
+ Py_DECREF(resultlist);
return NULL;
}
}
@@ -198,6 +207,13 @@
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 @@
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,8 +330,15 @@
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 @@
}
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,8 +366,15 @@
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 @@
{
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 @@
// 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 @@
case KX_PYATTRIBUTE_TYPE_SHORT:
bufferSize = sizeof(short);
break;
+ case KX_PYATTRIBUTE_TYPE_ENUM:
case KX_PYATTRIBUTE_TYPE_INT:
bufferSize = sizeof(int);
break;
@@ -460,8 +504,15 @@
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,14 +525,29 @@
}
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 @@
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,8 +590,25 @@
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 @@
// 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)
Modified: trunk/blender/source/gameengine/Expressions/PyObjectPlus.h
===================================================================
--- trunk/blender/source/gameengine/Expressions/PyObjectPlus.h 2009-01-02 16:58:09 UTC (rev 18266)
+++ trunk/blender/source/gameengine/Expressions/PyObjectPlus.h 2009-01-02 17:43:56 UTC (rev 18267)
@@ -216,6 +216,7 @@
*/
enum KX_PYATTRIBUTE_TYPE {
KX_PYATTRIBUTE_TYPE_BOOL,
+ KX_PYATTRIBUTE_TYPE_ENUM,
KX_PYATTRIBUTE_TYPE_SHORT,
KX_PYATTRIBUTE_TYPE_INT,
KX_PYATTRIBUTE_TYPE_FLOAT,
@@ -228,17 +229,20 @@
KX_PYATTRIBUTE_RO
};
-typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self);
+struct KX_PYATTRIBUTE_DEF;
+typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef);
typedef struct KX_PYATTRIBUTE_DEF {
const char *m_name; // name of the python attribute
KX_PYATTRIBUTE_TYPE m_type; // type of value
KX_PYATTRIBUTE_ACCESS m_access; // read/write access or read-only
- int m_imin; // minimum value in case of integer attributes
- int m_imax; // maximum value in case of integer attributes
+ int m_imin; // minimum value in case of integer attributes (for string: minimum string length)
+ int m_imax; // maximum value in case of integer attributes (for string: maximum string length)
float m_fmin; // minimum value in case of float attributes
float m_fmax; // maximum value in case of float attributes
+ bool m_clamp; // enforce min/max value by clamping
size_t m_offset; // position of field in structure
+ size_t m_size; // size of field for runtime verification (enum only)
size_t m_length; // length of array, 1=simple attribute
KX_PYATTRIBUTE_FUNCTION m_function; // static function to check the assignment, returns 0 if no error
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list