forked from bartvdbraak/blender
BGE API cleanup: introduction of a generic framework to link Python attributes to logic brick class member. See KX_PYATTRIBUTE macros in PyObjectPlus.h.
This commit is contained in:
parent
eee013d9b9
commit
2dfd34994f
@ -131,6 +131,449 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *PyObjectPlus::_getattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr)
|
||||||
|
{
|
||||||
|
const PyAttributeDef *attrdef;
|
||||||
|
for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++)
|
||||||
|
{
|
||||||
|
if (attr == attrdef->m_name)
|
||||||
|
{
|
||||||
|
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
|
||||||
|
{
|
||||||
|
// fake attribute, ignore
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
|
||||||
|
if (attrdef->m_length > 1)
|
||||||
|
{
|
||||||
|
PyObject* resultlist = PyList_New(attrdef->m_length);
|
||||||
|
for (int i=0; i<attrdef->m_length; i++)
|
||||||
|
{
|
||||||
|
switch (attrdef->m_type) {
|
||||||
|
case KX_PYATTRIBUTE_TYPE_BOOL:
|
||||||
|
{
|
||||||
|
bool *val = reinterpret_cast<bool*>(ptr);
|
||||||
|
ptr += sizeof(bool);
|
||||||
|
PyList_SetItem(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));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_INT:
|
||||||
|
{
|
||||||
|
int *val = reinterpret_cast<int*>(ptr);
|
||||||
|
ptr += sizeof(int);
|
||||||
|
PyList_SetItem(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));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// no support for array of complex data
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultlist;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (attrdef->m_type) {
|
||||||
|
case KX_PYATTRIBUTE_TYPE_BOOL:
|
||||||
|
{
|
||||||
|
bool *val = reinterpret_cast<bool*>(ptr);
|
||||||
|
return PyInt_FromLong(*val);
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_SHORT:
|
||||||
|
{
|
||||||
|
short int *val = reinterpret_cast<short int*>(ptr);
|
||||||
|
return PyInt_FromLong(*val);
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_INT:
|
||||||
|
{
|
||||||
|
int *val = reinterpret_cast<int*>(ptr);
|
||||||
|
return PyInt_FromLong(*val);
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_FLOAT:
|
||||||
|
{
|
||||||
|
float *val = reinterpret_cast<float*>(ptr);
|
||||||
|
return PyFloat_FromDouble(*val);
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_STRING:
|
||||||
|
{
|
||||||
|
STR_String *val = reinterpret_cast<STR_String*>(ptr);
|
||||||
|
return PyString_FromString(*val);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PyObjectPlus::_setattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr, PyObject *value)
|
||||||
|
{
|
||||||
|
const PyAttributeDef *attrdef;
|
||||||
|
void *undoBuffer = NULL;
|
||||||
|
void *sourceBuffer = NULL;
|
||||||
|
size_t bufferSize = 0;
|
||||||
|
|
||||||
|
for (attrdef=attrlist; attrdef->m_name != NULL; attrdef++)
|
||||||
|
{
|
||||||
|
if (attr == attrdef->m_name)
|
||||||
|
{
|
||||||
|
if (attrdef->m_access == KX_PYATTRIBUTE_RO ||
|
||||||
|
attrdef->m_type == KX_PYATTRIBUTE_TYPE_DUMMY)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "property is read-only");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
char *ptr = reinterpret_cast<char*>(self)+attrdef->m_offset;
|
||||||
|
if (attrdef->m_length > 1)
|
||||||
|
{
|
||||||
|
if (!PySequence_Check(value))
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected a sequence");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (PySequence_Size(value) != attrdef->m_length)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "incorrect number of elements in sequence");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
switch (attrdef->m_type)
|
||||||
|
{
|
||||||
|
case KX_PYATTRIBUTE_TYPE_BOOL:
|
||||||
|
bufferSize = sizeof(bool);
|
||||||
|
break;
|
||||||
|
case KX_PYATTRIBUTE_TYPE_SHORT:
|
||||||
|
bufferSize = sizeof(short int);
|
||||||
|
break;
|
||||||
|
case KX_PYATTRIBUTE_TYPE_INT:
|
||||||
|
bufferSize = sizeof(int);
|
||||||
|
break;
|
||||||
|
case KX_PYATTRIBUTE_TYPE_FLOAT:
|
||||||
|
bufferSize = sizeof(float);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// should not happen
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "Unsupported attribute type, report to blender.org");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// let's implement a smart undo method
|
||||||
|
bufferSize *= attrdef->m_length;
|
||||||
|
undoBuffer = malloc(bufferSize);
|
||||||
|
sourceBuffer = ptr;
|
||||||
|
if (undoBuffer)
|
||||||
|
{
|
||||||
|
memcpy(undoBuffer, sourceBuffer, bufferSize);
|
||||||
|
}
|
||||||
|
for (int i=0; i<attrdef->m_length; 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);
|
||||||
|
switch (attrdef->m_type)
|
||||||
|
{
|
||||||
|
case KX_PYATTRIBUTE_TYPE_BOOL:
|
||||||
|
{
|
||||||
|
bool *var = reinterpret_cast<bool*>(ptr);
|
||||||
|
ptr += sizeof(bool);
|
||||||
|
if (PyInt_Check(item))
|
||||||
|
{
|
||||||
|
*var = (PyInt_AsLong(item) != 0);
|
||||||
|
}
|
||||||
|
else if (PyBool_Check(item))
|
||||||
|
{
|
||||||
|
*var = (item == Py_True);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected an integer or a bool");
|
||||||
|
goto UNDO_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_SHORT:
|
||||||
|
{
|
||||||
|
short int *var = reinterpret_cast<short int*>(ptr);
|
||||||
|
ptr += sizeof(short int);
|
||||||
|
if (PyInt_Check(item))
|
||||||
|
{
|
||||||
|
long val = PyInt_AsLong(item);
|
||||||
|
if (val < attrdef->m_imin || val > attrdef->m_imax)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, "item value out of range");
|
||||||
|
goto UNDO_AND_ERROR;
|
||||||
|
}
|
||||||
|
*var = (short int)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
||||||
|
goto UNDO_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_INT:
|
||||||
|
{
|
||||||
|
int *var = reinterpret_cast<int*>(ptr);
|
||||||
|
ptr += sizeof(int);
|
||||||
|
if (PyInt_Check(item))
|
||||||
|
{
|
||||||
|
long val = PyInt_AsLong(item);
|
||||||
|
if (val < attrdef->m_imin || val > attrdef->m_imax)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, "item value out of range");
|
||||||
|
goto UNDO_AND_ERROR;
|
||||||
|
}
|
||||||
|
*var = (int)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
||||||
|
goto UNDO_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_FLOAT:
|
||||||
|
{
|
||||||
|
float *var = reinterpret_cast<float*>(ptr);
|
||||||
|
ptr += sizeof(float);
|
||||||
|
if (PyFloat_Check(item))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected a float");
|
||||||
|
goto UNDO_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// should not happen
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "attribute type check error, report to blender.org");
|
||||||
|
goto UNDO_AND_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// no error, call check function if any
|
||||||
|
if (attrdef->m_function != NULL)
|
||||||
|
{
|
||||||
|
if ((*attrdef->m_function)(self) != 0)
|
||||||
|
{
|
||||||
|
// post check returned an error, restore values
|
||||||
|
UNDO_AND_ERROR:
|
||||||
|
if (undoBuffer)
|
||||||
|
{
|
||||||
|
memcpy(sourceBuffer, undoBuffer, bufferSize);
|
||||||
|
free(undoBuffer);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (undoBuffer)
|
||||||
|
free(undoBuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else // simple attribute value
|
||||||
|
{
|
||||||
|
|
||||||
|
if (attrdef->m_function != NULL)
|
||||||
|
{
|
||||||
|
// post check function is provided, prepare undo buffer
|
||||||
|
sourceBuffer = ptr;
|
||||||
|
switch (attrdef->m_type)
|
||||||
|
{
|
||||||
|
case KX_PYATTRIBUTE_TYPE_BOOL:
|
||||||
|
bufferSize = sizeof(bool);
|
||||||
|
break;
|
||||||
|
case KX_PYATTRIBUTE_TYPE_SHORT:
|
||||||
|
bufferSize = sizeof(short);
|
||||||
|
break;
|
||||||
|
case KX_PYATTRIBUTE_TYPE_INT:
|
||||||
|
bufferSize = sizeof(int);
|
||||||
|
break;
|
||||||
|
case KX_PYATTRIBUTE_TYPE_FLOAT:
|
||||||
|
bufferSize = sizeof(float);
|
||||||
|
break;
|
||||||
|
case KX_PYATTRIBUTE_TYPE_STRING:
|
||||||
|
sourceBuffer = reinterpret_cast<STR_String*>(ptr)->Ptr();
|
||||||
|
if (sourceBuffer)
|
||||||
|
bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (bufferSize)
|
||||||
|
{
|
||||||
|
undoBuffer = malloc(bufferSize);
|
||||||
|
if (undoBuffer)
|
||||||
|
{
|
||||||
|
memcpy(undoBuffer, sourceBuffer, bufferSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (attrdef->m_type)
|
||||||
|
{
|
||||||
|
case KX_PYATTRIBUTE_TYPE_BOOL:
|
||||||
|
{
|
||||||
|
bool *var = reinterpret_cast<bool*>(ptr);
|
||||||
|
if (PyInt_Check(value))
|
||||||
|
{
|
||||||
|
*var = (PyInt_AsLong(value) != 0);
|
||||||
|
}
|
||||||
|
else if (PyBool_Check(value))
|
||||||
|
{
|
||||||
|
*var = (value == Py_True);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected an integer or a bool");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_SHORT:
|
||||||
|
{
|
||||||
|
short int *var = reinterpret_cast<short int*>(ptr);
|
||||||
|
if (PyInt_Check(value))
|
||||||
|
{
|
||||||
|
long val = PyInt_AsLong(value);
|
||||||
|
if (val < attrdef->m_imin || val > attrdef->m_imax)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, "value out of range");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
*var = (short int)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, "value out of range");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
*var = (int)val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_FLOAT:
|
||||||
|
{
|
||||||
|
float *var = reinterpret_cast<float*>(ptr);
|
||||||
|
if (PyFloat_Check(value))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected a float");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KX_PYATTRIBUTE_TYPE_STRING:
|
||||||
|
{
|
||||||
|
STR_String *var = reinterpret_cast<STR_String*>(ptr);
|
||||||
|
if (PyString_Check(value))
|
||||||
|
{
|
||||||
|
char *val = PyString_AsString(value);
|
||||||
|
if (strlen(val) < attrdef->m_imin || strlen(val) > attrdef->m_imax)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, "string length out of range");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
*var = val;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_TypeError, "expected a string");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
// should not happen
|
||||||
|
PyErr_SetString(PyExc_AttributeError, "unknown attribute type, report to blender.org");
|
||||||
|
goto FREE_AND_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if post processing is needed
|
||||||
|
if (attrdef->m_function != NULL)
|
||||||
|
{
|
||||||
|
if ((*attrdef->m_function)(self) != 0)
|
||||||
|
{
|
||||||
|
// restore value
|
||||||
|
if (undoBuffer)
|
||||||
|
{
|
||||||
|
if (attrdef->m_type == KX_PYATTRIBUTE_TYPE_STRING)
|
||||||
|
{
|
||||||
|
// special case for STR_String: restore the string
|
||||||
|
STR_String *var = reinterpret_cast<STR_String*>(ptr);
|
||||||
|
*var = reinterpret_cast<char*>(undoBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// other field type have direct values
|
||||||
|
memcpy(ptr, undoBuffer, bufferSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FREE_AND_ERROR:
|
||||||
|
if (undoBuffer)
|
||||||
|
free(undoBuffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (undoBuffer)
|
||||||
|
free(undoBuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------
|
/*------------------------------
|
||||||
* PyObjectPlus repr -- representations
|
* PyObjectPlus repr -- representations
|
||||||
------------------------------*/
|
------------------------------*/
|
||||||
|
@ -86,6 +86,7 @@ static inline void Py_Fatal(const char *M) {
|
|||||||
public: \
|
public: \
|
||||||
static PyTypeObject Type; \
|
static PyTypeObject Type; \
|
||||||
static PyMethodDef Methods[]; \
|
static PyMethodDef Methods[]; \
|
||||||
|
static PyAttributeDef Attributes[]; \
|
||||||
static PyParentObject Parents[]; \
|
static PyParentObject Parents[]; \
|
||||||
virtual PyTypeObject *GetType(void) {return &Type;}; \
|
virtual PyTypeObject *GetType(void) {return &Type;}; \
|
||||||
virtual PyParentObject *GetParents(void) {return Parents;}
|
virtual PyParentObject *GetParents(void) {return Parents;}
|
||||||
@ -210,6 +211,104 @@ PyObject* class_name::Py##method_name(PyObject*, PyObject* value)
|
|||||||
const char class_name::method_name##_doc[] = doc_string; \
|
const char class_name::method_name##_doc[] = doc_string; \
|
||||||
PyObject* class_name::Py##method_name(PyObject*)
|
PyObject* class_name::Py##method_name(PyObject*)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attribute management
|
||||||
|
*/
|
||||||
|
enum KX_PYATTRIBUTE_TYPE {
|
||||||
|
KX_PYATTRIBUTE_TYPE_BOOL,
|
||||||
|
KX_PYATTRIBUTE_TYPE_SHORT,
|
||||||
|
KX_PYATTRIBUTE_TYPE_INT,
|
||||||
|
KX_PYATTRIBUTE_TYPE_FLOAT,
|
||||||
|
KX_PYATTRIBUTE_TYPE_STRING,
|
||||||
|
KX_PYATTRIBUTE_TYPE_DUMMY,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KX_PYATTRIBUTE_ACCESS {
|
||||||
|
KX_PYATTRIBUTE_RW,
|
||||||
|
KX_PYATTRIBUTE_RO
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int (*KX_PYATTRIBUTE_FUNCTION)(void *self);
|
||||||
|
|
||||||
|
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
|
||||||
|
float m_fmin; // minimum value in case of float attributes
|
||||||
|
float m_fmax; // maximum value in case of float attributes
|
||||||
|
size_t m_offset; // position of field in structure
|
||||||
|
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.
|
||||||
|
// It would have been good to use a union but that would require C99 compatibility
|
||||||
|
// to initialize specific union fields through designated initializers.
|
||||||
|
struct {
|
||||||
|
bool *m_boolPtr;
|
||||||
|
short int *m_shortPtr;
|
||||||
|
int *m_intPtr;
|
||||||
|
float *m_floatPtr;
|
||||||
|
STR_String *m_stringPtr;
|
||||||
|
} m_typeCheck;
|
||||||
|
} 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} }
|
||||||
|
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
|
||||||
|
#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_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} }
|
||||||
|
#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} }
|
||||||
|
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
#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} }
|
||||||
|
|
||||||
|
#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_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} }
|
||||||
|
|
||||||
/*------------------------------
|
/*------------------------------
|
||||||
* PyObjectPlus
|
* PyObjectPlus
|
||||||
------------------------------*/
|
------------------------------*/
|
||||||
@ -240,6 +339,8 @@ public:
|
|||||||
{
|
{
|
||||||
return ((PyObjectPlus*) PyObj)->_getattr(STR_String(attr));
|
return ((PyObjectPlus*) PyObj)->_getattr(STR_String(attr));
|
||||||
}
|
}
|
||||||
|
static PyObject *_getattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr);
|
||||||
|
static int _setattr_self(const PyAttributeDef attrlist[], void *self, const STR_String &attr, PyObject *value);
|
||||||
|
|
||||||
virtual int _delattr(const STR_String& attr);
|
virtual int _delattr(const STR_String& attr);
|
||||||
virtual int _setattr(const STR_String& attr, PyObject *value); // _setattr method
|
virtual int _setattr(const STR_String& attr, PyObject *value); // _setattr method
|
||||||
|
@ -327,6 +327,21 @@ PyMethodDef SCA_JoystickSensor::Methods[] = {
|
|||||||
{NULL,NULL} //Sentinel
|
{NULL,NULL} //Sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PyAttributeDef SCA_JoystickSensor::Attributes[] = {
|
||||||
|
KX_PYATTRIBUTE_SHORT_RW("index",0,JOYINDEX_MAX-1,SCA_JoystickSensor,m_joyindex),
|
||||||
|
KX_PYATTRIBUTE_INT_RW("threshold",0,32768,SCA_JoystickSensor,m_precision),
|
||||||
|
KX_PYATTRIBUTE_INT_RW("button",0,100,SCA_JoystickSensor,m_button),
|
||||||
|
KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("axis",0,3,SCA_JoystickSensor,m_axis,2,CheckAxis),
|
||||||
|
KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK("hat",0,12,SCA_JoystickSensor,m_hat,2,CheckHat),
|
||||||
|
// dummy attributes will just be read-only in _setattr
|
||||||
|
// you still need to defined them in _getattr
|
||||||
|
KX_PYATTRIBUTE_DUMMY("axisPosition"),
|
||||||
|
KX_PYATTRIBUTE_DUMMY("numAxis"),
|
||||||
|
KX_PYATTRIBUTE_DUMMY("numButtons"),
|
||||||
|
KX_PYATTRIBUTE_DUMMY("numHats"),
|
||||||
|
KX_PYATTRIBUTE_DUMMY("connected"),
|
||||||
|
{ NULL } //Sentinel
|
||||||
|
};
|
||||||
|
|
||||||
PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) {
|
PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) {
|
||||||
SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
|
SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex);
|
||||||
@ -348,100 +363,17 @@ PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) {
|
|||||||
if (attr == "connected") {
|
if (attr == "connected") {
|
||||||
return PyBool_FromLong( joy ? joy->Connected() : 0 );
|
return PyBool_FromLong( joy ? joy->Connected() : 0 );
|
||||||
}
|
}
|
||||||
if (attr == "index") {
|
PyObject* object = _getattr_self(Attributes, this, attr);
|
||||||
return PyInt_FromLong(m_joyindex);
|
if (object != NULL)
|
||||||
}
|
return object;
|
||||||
if (attr == "threshold") {
|
|
||||||
return PyInt_FromLong(m_precision);
|
|
||||||
}
|
|
||||||
if (attr == "button") {
|
|
||||||
return PyInt_FromLong(m_button);
|
|
||||||
}
|
|
||||||
if (attr == "axis") {
|
|
||||||
return Py_BuildValue("[ii]",m_axis, m_axisf);
|
|
||||||
}
|
|
||||||
if (attr == "hat") {
|
|
||||||
return Py_BuildValue("[ii]",m_hat, m_hatf);
|
|
||||||
}
|
|
||||||
_getattr_up(SCA_ISensor);
|
_getattr_up(SCA_ISensor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCA_JoystickSensor::_setattr(const STR_String& attr, PyObject *value) {
|
int SCA_JoystickSensor::_setattr(const STR_String& attr, PyObject *value)
|
||||||
if (attr == "axisPosition") {
|
{
|
||||||
PyErr_SetString(PyExc_AttributeError, "axisPosition is read only");
|
int ret = _setattr_self(Attributes, this, attr, value);
|
||||||
return 1;
|
if (ret >= 0)
|
||||||
}
|
return ret;
|
||||||
if (attr == "numAxis") {
|
|
||||||
PyErr_SetString(PyExc_AttributeError, "numaxis is read only");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (attr == "numButtons") {
|
|
||||||
PyErr_SetString(PyExc_AttributeError, "numbuttons is read only");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (attr == "numHats") {
|
|
||||||
PyErr_SetString(PyExc_AttributeError, "numhats is read only");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (attr == "connected") {
|
|
||||||
PyErr_SetString(PyExc_AttributeError, "connected is read only");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (PyInt_Check(value)) {
|
|
||||||
int ival = PyInt_AsLong(value);
|
|
||||||
if (attr == "index") {
|
|
||||||
if (ival < 0 || ival >= JOYINDEX_MAX) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "joystick index out of range");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_joyindex = ival;
|
|
||||||
} else if (attr == "threshold") {
|
|
||||||
m_precision = ival;
|
|
||||||
} else if (attr == "button") {
|
|
||||||
if (ival < 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "button out of range");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_button = ival;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (PySequence_Check(value)) {
|
|
||||||
if (attr == "axis" || attr == "hat") {
|
|
||||||
if (PySequence_Size(value) != 2) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "value must be sequence of 2 integers");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int ival = -1;
|
|
||||||
int ivalf = -1;
|
|
||||||
PyObject *item = PySequence_GetItem(value, 0); /* new ref */
|
|
||||||
ival = PyInt_AsLong(item);
|
|
||||||
Py_DECREF(item);
|
|
||||||
item = PySequence_GetItem(value, 1); /* new ref */
|
|
||||||
ivalf = PyInt_AsLong(item);
|
|
||||||
Py_DECREF(item);
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "one or more of the items in the sequence was not an integer");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (attr == "axis") {
|
|
||||||
if (ival < 1 || ival > 2 || ivalf < 0 || ivalf > 3) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "items in the sequence are out of range");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_axis = ival;
|
|
||||||
m_axisf = ivalf;
|
|
||||||
} else {
|
|
||||||
if (ival < 1 || ival > 2) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "items in the sequence are out of range");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_hat = ival;
|
|
||||||
m_hatf = ivalf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return SCA_ISensor::_setattr(attr, value);
|
return SCA_ISensor::_setattr(attr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,11 +37,11 @@ class SCA_JoystickSensor :public SCA_ISensor
|
|||||||
class SCA_JoystickManager* m_pJoystickMgr;
|
class SCA_JoystickManager* m_pJoystickMgr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Axis 1-or-2
|
* Axis 1-or-2, MUST be followed by m_axisf
|
||||||
*/
|
*/
|
||||||
int m_axis;
|
int m_axis;
|
||||||
/**
|
/**
|
||||||
* Axis flag to find direction
|
* Axis flag to find direction, MUST be an int
|
||||||
*/
|
*/
|
||||||
int m_axisf;
|
int m_axisf;
|
||||||
/**
|
/**
|
||||||
@ -53,11 +53,11 @@ class SCA_JoystickSensor :public SCA_ISensor
|
|||||||
*/
|
*/
|
||||||
int m_buttonf;
|
int m_buttonf;
|
||||||
/**
|
/**
|
||||||
* The actual hat
|
* The actual hat. MUST be followed by m_hatf
|
||||||
*/
|
*/
|
||||||
int m_hat;
|
int m_hat;
|
||||||
/**
|
/**
|
||||||
* Flag to find direction 1-12
|
* Flag to find direction 0-11, MUST be an int
|
||||||
*/
|
*/
|
||||||
int m_hatf;
|
int m_hatf;
|
||||||
/**
|
/**
|
||||||
@ -148,6 +148,28 @@ public:
|
|||||||
KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats);
|
KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats);
|
||||||
KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected);
|
KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected);
|
||||||
|
|
||||||
|
/* attribute check */
|
||||||
|
static int CheckAxis(void *self)
|
||||||
|
{
|
||||||
|
SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self);
|
||||||
|
if (sensor->m_axis < 1 || sensor->m_axis > 2)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, "axis number must be 1 or 2");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int CheckHat(void *self)
|
||||||
|
{
|
||||||
|
SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self);
|
||||||
|
if (sensor->m_hat < 1 || sensor->m_hat > 2)
|
||||||
|
{
|
||||||
|
PyErr_SetString(PyExc_ValueError, "hat number must be 1 or 2");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -820,91 +820,29 @@ PyMethodDef SCA_KeyboardSensor::Methods[] = {
|
|||||||
{NULL,NULL} //Sentinel
|
{NULL,NULL} //Sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PyAttributeDef SCA_KeyboardSensor::Attributes[] = {
|
||||||
|
KX_PYATTRIBUTE_BOOL_RW("useAllKeys",SCA_KeyboardSensor,m_bAllKeys),
|
||||||
|
KX_PYATTRIBUTE_INT_RW("key",0,1000,SCA_KeyboardSensor,m_hotkey),
|
||||||
|
KX_PYATTRIBUTE_SHORT_RW("hold1",0,1000,SCA_KeyboardSensor,m_qual),
|
||||||
|
KX_PYATTRIBUTE_SHORT_RW("hold2",0,1000,SCA_KeyboardSensor,m_qual2),
|
||||||
|
KX_PYATTRIBUTE_STRING_RW("toggleProperty",0,100,SCA_KeyboardSensor,m_toggleprop),
|
||||||
|
KX_PYATTRIBUTE_STRING_RW("targetProperty",0,100,SCA_KeyboardSensor,m_targetprop),
|
||||||
|
{ NULL } //Sentinel
|
||||||
|
};
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
SCA_KeyboardSensor::_getattr(const STR_String& attr)
|
SCA_KeyboardSensor::_getattr(const STR_String& attr)
|
||||||
{
|
{
|
||||||
if (attr == "key")
|
PyObject* object = _getattr_self(Attributes, this, attr);
|
||||||
return PyInt_FromLong(m_hotkey);
|
if (object != NULL)
|
||||||
|
return object;
|
||||||
if (attr == "hold1")
|
|
||||||
return PyInt_FromLong(m_qual);
|
|
||||||
|
|
||||||
if (attr == "hold2")
|
|
||||||
return PyInt_FromLong(m_qual2);
|
|
||||||
|
|
||||||
if (attr == "toggleProperty")
|
|
||||||
return PyString_FromString(m_toggleprop);
|
|
||||||
|
|
||||||
if (attr == "targetProperty")
|
|
||||||
return PyString_FromString(m_targetprop);
|
|
||||||
|
|
||||||
if (attr == "useAllKeys")
|
|
||||||
return PyInt_FromLong(m_bAllKeys);
|
|
||||||
|
|
||||||
_getattr_up(SCA_ISensor);
|
_getattr_up(SCA_ISensor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCA_KeyboardSensor::_setattr(const STR_String& attr, PyObject *value)
|
int SCA_KeyboardSensor::_setattr(const STR_String& attr, PyObject *value)
|
||||||
{
|
{
|
||||||
if (attr == "key")
|
int ret = _setattr_self(Attributes, this, attr, value);
|
||||||
{
|
if (ret >= 0)
|
||||||
if (!PyInt_Check(value)){
|
return ret;
|
||||||
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_hotkey = PyInt_AsLong(value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr == "hold1")
|
|
||||||
{
|
|
||||||
if (!PyInt_Check(value)){
|
|
||||||
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_qual = PyInt_AsLong(value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr == "hold2")
|
|
||||||
{
|
|
||||||
if (!PyInt_Check(value)){
|
|
||||||
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_qual2 = PyInt_AsLong(value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr == "useAllKeys")
|
|
||||||
{
|
|
||||||
if (!PyInt_Check(value)){
|
|
||||||
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_bAllKeys = (PyInt_AsLong(value) != 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr == "logToggleProperty")
|
|
||||||
{
|
|
||||||
if (!PyString_Check(value)){
|
|
||||||
PyErr_SetString(PyExc_TypeError, "expected a string");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_toggleprop = PyString_AsString(value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr == "logTargetProperty")
|
|
||||||
{
|
|
||||||
if (!PyString_Check(value)){
|
|
||||||
PyErr_SetString(PyExc_TypeError, "expected a string");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_targetprop = PyString_AsString(value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SCA_ISensor::_setattr(attr, value);
|
return SCA_ISensor::_setattr(attr, value);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr,
|
|||||||
m_mousemode = mousemode;
|
m_mousemode = mousemode;
|
||||||
m_triggermode = true;
|
m_triggermode = true;
|
||||||
|
|
||||||
UpdateHotkey();
|
UpdateHotkey(this);
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,33 +74,37 @@ SCA_MouseSensor::~SCA_MouseSensor()
|
|||||||
/* Nothing to be done here. */
|
/* Nothing to be done here. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCA_MouseSensor::UpdateHotkey()
|
int SCA_MouseSensor::UpdateHotkey(void *self)
|
||||||
{
|
{
|
||||||
// gosh, this function is so damn stupid
|
// gosh, this function is so damn stupid
|
||||||
// its here because of a design mistake in the mouse sensor, it should only
|
// its here because of a design mistake in the mouse sensor, it should only
|
||||||
// have 3 trigger modes (button, wheel, move), and let the user set the
|
// have 3 trigger modes (button, wheel, move), and let the user set the
|
||||||
// hotkey separately, like the other sensors. but instead it has a mode for
|
// hotkey separately, like the other sensors. but instead it has a mode for
|
||||||
// each friggin key and i have to update the hotkey based on it... genius!
|
// each friggin key and i have to update the hotkey based on it... genius!
|
||||||
|
SCA_MouseSensor* sensor = reinterpret_cast<SCA_MouseSensor*>(self);
|
||||||
|
|
||||||
switch (m_mousemode) {
|
switch (sensor->m_mousemode) {
|
||||||
case KX_MOUSESENSORMODE_LEFTBUTTON:
|
case KX_MOUSESENSORMODE_LEFTBUTTON:
|
||||||
m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE;
|
sensor->m_hotkey = SCA_IInputDevice::KX_LEFTMOUSE;
|
||||||
break;
|
break;
|
||||||
case KX_MOUSESENSORMODE_MIDDLEBUTTON:
|
case KX_MOUSESENSORMODE_MIDDLEBUTTON:
|
||||||
m_hotkey = SCA_IInputDevice::KX_MIDDLEMOUSE;
|
sensor->m_hotkey = SCA_IInputDevice::KX_MIDDLEMOUSE;
|
||||||
break;
|
break;
|
||||||
case KX_MOUSESENSORMODE_RIGHTBUTTON:
|
case KX_MOUSESENSORMODE_RIGHTBUTTON:
|
||||||
m_hotkey = SCA_IInputDevice::KX_RIGHTMOUSE;
|
sensor->m_hotkey = SCA_IInputDevice::KX_RIGHTMOUSE;
|
||||||
break;
|
break;
|
||||||
case KX_MOUSESENSORMODE_WHEELUP:
|
case KX_MOUSESENSORMODE_WHEELUP:
|
||||||
m_hotkey = SCA_IInputDevice::KX_WHEELUPMOUSE;
|
sensor->m_hotkey = SCA_IInputDevice::KX_WHEELUPMOUSE;
|
||||||
break;
|
break;
|
||||||
case KX_MOUSESENSORMODE_WHEELDOWN:
|
case KX_MOUSESENSORMODE_WHEELDOWN:
|
||||||
m_hotkey = SCA_IInputDevice::KX_WHEELDOWNMOUSE;
|
sensor->m_hotkey = SCA_IInputDevice::KX_WHEELDOWNMOUSE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
; /* ignore, no hotkey */
|
; /* ignore, no hotkey */
|
||||||
}
|
}
|
||||||
|
// return value is used in _setattr(),
|
||||||
|
// 0=attribute checked ok (see Attributes array definition)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CValue* SCA_MouseSensor::GetReplica()
|
CValue* SCA_MouseSensor::GetReplica()
|
||||||
@ -331,44 +335,25 @@ PyMethodDef SCA_MouseSensor::Methods[] = {
|
|||||||
{NULL,NULL} //Sentinel
|
{NULL,NULL} //Sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
PyObject* SCA_MouseSensor::_getattr(const STR_String& attr) {
|
PyAttributeDef SCA_MouseSensor::Attributes[] = {
|
||||||
if (attr == "position")
|
KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",KX_MOUSESENSORMODE_NODEF,KX_MOUSESENSORMODE_MAX-1,SCA_MouseSensor,m_mousemode,UpdateHotkey),
|
||||||
return Py_BuildValue("[ii]", m_x, m_y);
|
KX_PYATTRIBUTE_SHORT_ARRAY_RO("position",SCA_MouseSensor,m_x,2),
|
||||||
|
{ NULL } //Sentinel
|
||||||
if (attr == "mode")
|
};
|
||||||
return PyInt_FromLong(m_mousemode);
|
|
||||||
|
|
||||||
|
PyObject* SCA_MouseSensor::_getattr(const STR_String& attr)
|
||||||
|
{
|
||||||
|
PyObject* object = _getattr_self(Attributes, this, attr);
|
||||||
|
if (object != NULL)
|
||||||
|
return object;
|
||||||
_getattr_up(SCA_ISensor);
|
_getattr_up(SCA_ISensor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCA_MouseSensor::_setattr(const STR_String& attr, PyObject *value)
|
int SCA_MouseSensor::_setattr(const STR_String& attr, PyObject *value)
|
||||||
{
|
{
|
||||||
if (attr == "mode")
|
int ret = _setattr_self(Attributes, this, attr, value);
|
||||||
{
|
if (ret >= 0)
|
||||||
if (!PyInt_Check(value)){
|
return ret;
|
||||||
PyErr_SetString(PyExc_TypeError, "expected an integer");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int val = PyInt_AsLong(value);
|
|
||||||
|
|
||||||
if ((val < KX_MOUSESENSORMODE_NODEF)
|
|
||||||
|| (val > KX_MOUSESENSORMODE_MAX)){
|
|
||||||
PyErr_SetString(PyExc_ValueError, "invalid mode specified!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_mousemode = val;
|
|
||||||
UpdateHotkey();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attr == "position")
|
|
||||||
{
|
|
||||||
PyErr_SetString(PyExc_AttributeError, "'position' is a read-only property!");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SCA_ISensor::_setattr(attr, value);
|
return SCA_ISensor::_setattr(attr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ class SCA_MouseSensor : public SCA_ISensor
|
|||||||
SCA_IInputDevice::KX_EnumInputs m_hotkey;
|
SCA_IInputDevice::KX_EnumInputs m_hotkey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* valid x coordinate
|
* valid x coordinate, MUST be followed by y coordinate
|
||||||
*/
|
*/
|
||||||
short m_x;
|
short m_x;
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ class SCA_MouseSensor : public SCA_ISensor
|
|||||||
|
|
||||||
bool isValid(KX_MOUSESENSORMODE);
|
bool isValid(KX_MOUSESENSORMODE);
|
||||||
|
|
||||||
void UpdateHotkey();
|
static int UpdateHotkey(void *self);
|
||||||
|
|
||||||
SCA_MouseSensor(class SCA_MouseManager* keybdmgr,
|
SCA_MouseSensor(class SCA_MouseManager* keybdmgr,
|
||||||
int startx,int starty,
|
int startx,int starty,
|
||||||
|
Loading…
Reference in New Issue
Block a user