Revision: 18203
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=18203
Author:   ben2610
Date:     2008-12-31 21:35:20 +0100 (Wed, 31 Dec 2008)

Log Message:
-----------
BGE API cleanup: introduction of a generic framework to link Python attributes 
to logic brick class member. See KX_PYATTRIBUTE macros in PyObjectPlus.h.

Modified Paths:
--------------
    trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp
    trunk/blender/source/gameengine/Expressions/PyObjectPlus.h
    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

Modified: trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp
===================================================================
--- trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp        
2008-12-31 18:52:15 UTC (rev 18202)
+++ trunk/blender/source/gameengine/Expressions/PyObjectPlus.cpp        
2008-12-31 20:35:20 UTC (rev 18203)
@@ -131,6 +131,449 @@
        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)
+                                                       {

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to