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. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs
