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
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')
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.cpp142
-rw-r--r--source/gameengine/Expressions/PyObjectPlus.h92
2 files changed, 168 insertions, 66 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)
diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h
index 016fa293d73..e0e2213d984 100644
--- a/source/gameengine/Expressions/PyObjectPlus.h
+++ b/source/gameengine/Expressions/PyObjectPlus.h
@@ -216,6 +216,7 @@ PyObject* class_name::Py##method_name(PyObject*)
*/
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 @@ enum KX_PYATTRIBUTE_ACCESS {
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
// The following pointers are just used to have compile time check for attribute type.
@@ -254,60 +258,70 @@ typedef struct KX_PYATTRIBUTE_DEF {
} PyAttributeDef;
#define KX_PYATTRIBUTE_DUMMY(name) \
- { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, 0, 1, NULL, {NULL, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, {NULL, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, offsetof(object,field), 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, offsetof(object,field), 1, &object::function, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, offsetof(object,field), 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
-
-#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} }
+
+// 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} }
+#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} }
+#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} }
+
+#define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, &object::function, {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, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+#define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
#define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_RW(name,min,max,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
-#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), length, &object::function, {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, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+#define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
#define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} }
+// always clamp for float
#define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), 1, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, offsetof(object,field), length, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
#define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \
- { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
+ { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} }
-#define KX_PYATTRIBUTE_STRING_RW(name,min,max,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
-#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,object,field,function) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, offsetof(object,field), 1, &object::function, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+#define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+#define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
#define KX_PYATTRIBUTE_STRING_RO(name,object,field) \
- { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, offsetof(object,field), 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
+ { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} }
/*------------------------------
* PyObjectPlus