diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-06-25 14:11:37 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-06-25 14:11:37 +0400 |
commit | d428ba1de8074e8b0ca2b7c0b060c18ebf7d6b0c (patch) | |
tree | 0200656374d9d08125eba99ecc009ca3e70cc7fb /source | |
parent | 7a357cba3994bee7d05c7a8bf5736eb94067d564 (diff) |
PyAPI RNA/BGE
* all mathutils types now have optional callbacks
* PyRNA returns mathutils quat and euler types automatically when they have the rotation subtype.
* PyRNA, reuse the BPy_StructRNA PyObject rather name making a new one for each function returned.
* use more arithb.c functions for Mathutils quaternion type (less inline cruft).
* BGE Mathutils integration mostly finished- KX_PyMath now converts to Mathutils types rather then lists.
* make all mathutils types share the same header so they can share a number of functions - dealloc, getWrapped, getOwner.
Diffstat (limited to 'source')
21 files changed, 715 insertions, 612 deletions
diff --git a/source/blender/python/generic/Geometry.c b/source/blender/python/generic/Geometry.c index ec76675f652..8a748241570 100644 --- a/source/blender/python/generic/Geometry.c +++ b/source/blender/python/generic/Geometry.c @@ -165,7 +165,7 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq ) polyVec= PySequence_GetItem( polyLine, index ); if(VectorObject_Check(polyVec)) { - if(!Vector_ReadCallback((VectorObject *)polyVec)) + if(!BaseMath_ReadCallback((VectorObject *)polyVec)) ls_error= 1; fp[0] = ((VectorObject *)polyVec)->vec[0]; @@ -238,7 +238,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(line_a1) || !Vector_ReadCallback(line_a2) || !Vector_ReadCallback(line_b1) || !Vector_ReadCallback(line_b2)) + if(!BaseMath_ReadCallback(line_a1) || !BaseMath_ReadCallback(line_a2) || !BaseMath_ReadCallback(line_b1) || !BaseMath_ReadCallback(line_b2)) return NULL; a1x= line_a1->vec[0]; @@ -338,7 +338,7 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args return NULL; } - if(!Vector_ReadCallback(pt) || !Vector_ReadCallback(line_1) || !Vector_ReadCallback(line_2)) + if(!BaseMath_ReadCallback(pt) || !BaseMath_ReadCallback(line_1) || !BaseMath_ReadCallback(line_2)) return NULL; /* accept 2d verts */ @@ -374,7 +374,7 @@ static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args return NULL; } - if(!Vector_ReadCallback(pt_vec) || !Vector_ReadCallback(tri_p1) || !Vector_ReadCallback(tri_p2) || !Vector_ReadCallback(tri_p3)) + if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(tri_p1) || !BaseMath_ReadCallback(tri_p2) || !BaseMath_ReadCallback(tri_p3)) return NULL; return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec)); @@ -395,7 +395,7 @@ static PyObject *M_Geometry_PointInQuad2D( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(pt_vec) || !Vector_ReadCallback(quad_p1) || !Vector_ReadCallback(quad_p2) || !Vector_ReadCallback(quad_p3) || !Vector_ReadCallback(quad_p4)) + if(!BaseMath_ReadCallback(pt_vec) || !BaseMath_ReadCallback(quad_p1) || !BaseMath_ReadCallback(quad_p2) || !BaseMath_ReadCallback(quad_p3) || !BaseMath_ReadCallback(quad_p4)) return NULL; return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec)); @@ -517,7 +517,7 @@ static PyObject *M_Geometry_BezierInterp( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(vec_k1) || !Vector_ReadCallback(vec_h1) || !Vector_ReadCallback(vec_k2) || !Vector_ReadCallback(vec_h2)) + if(!BaseMath_ReadCallback(vec_k1) || !BaseMath_ReadCallback(vec_h1) || !BaseMath_ReadCallback(vec_k2) || !BaseMath_ReadCallback(vec_h2)) return NULL; dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size); diff --git a/source/blender/python/generic/Mathutils.c b/source/blender/python/generic/Mathutils.c index cd9705236d7..d7330ac46c0 100644 --- a/source/blender/python/generic/Mathutils.c +++ b/source/blender/python/generic/Mathutils.c @@ -155,10 +155,13 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2) if(QuaternionObject_Check(arg1)){ quat = (QuaternionObject*)arg1; + if(!BaseMath_ReadCallback(quat)) + return NULL; + if(VectorObject_Check(arg2)){ vec = (VectorObject*)arg2; - if(!Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(vec)) return NULL; rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - @@ -178,11 +181,14 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2) }else if(VectorObject_Check(arg1)){ vec = (VectorObject*)arg1; - if(!Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(vec)) return NULL; if(QuaternionObject_Check(arg2)){ quat = (QuaternionObject*)arg2; + if(!BaseMath_ReadCallback(quat)) + return NULL; + rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 2*quat->quat[3]*quat->quat[0]*vec->vec[1] + quat->quat[1]*quat->quat[1]*vec->vec[0] + 2*quat->quat[2]*quat->quat[1]*vec->vec[1] + 2*quat->quat[3]*quat->quat[1]*vec->vec[2] - @@ -247,7 +253,7 @@ static PyObject *M_Mathutils_AngleBetweenVecs(PyObject * self, PyObject * args) if(vec1->size != vec2->size) goto AttributeError1; //bad sizes - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; //since size is the same.... @@ -296,7 +302,7 @@ static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; for(x = 0; x < vec1->size; x++) { @@ -322,7 +328,7 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; @@ -389,7 +395,7 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args) return NULL; } - if(!Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(vec)) return NULL; } @@ -492,7 +498,7 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v return NULL; } - if(!Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(vec)) return NULL; //create a identity matrix and add translation @@ -528,7 +534,7 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args) return NULL; } - if(!Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(vec)) return NULL; } @@ -607,7 +613,7 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a return NULL; } - if(!Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(vec)) return NULL; } @@ -766,6 +772,10 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args) PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types"); return NULL; } + + if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV)) + return NULL; + tempQuat[0] = quatU->quat[0]; tempQuat[1] = -quatU->quat[1]; tempQuat[2] = -quatU->quat[2]; @@ -793,6 +803,10 @@ static PyObject *M_Mathutils_Slerp(PyObject * self, PyObject * args) PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float"); return NULL; } + + if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV)) + return NULL; + if(param > 1.0f || param < 0.0f) { PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0"); return NULL; @@ -856,7 +870,7 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3) || !Vector_ReadCallback(ray) || !Vector_ReadCallback(ray_off)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(ray) || !BaseMath_ReadCallback(ray_off)) return NULL; VECCOPY(v1, vec1->vec); @@ -928,7 +942,7 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3) || !Vector_ReadCallback(vec4)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4)) return NULL; if( vec1->size == 3 || vec1->size == 2) { @@ -1002,7 +1016,7 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3) || !Vector_ReadCallback(vec4)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3) || !BaseMath_ReadCallback(vec4)) return NULL; VECCOPY(v1, vec1->vec); @@ -1050,7 +1064,7 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3)) return NULL; VECCOPY(v1, vec1->vec); @@ -1085,7 +1099,7 @@ static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3)) return NULL; if (vec1->size == 3) { @@ -1167,75 +1181,66 @@ int Mathutils_RegisterCallback(Mathutils_Callback *cb) } /* use macros to check for NULL */ -int _Vector_ReadCallback(VectorObject *self) +int _BaseMathObject_ReadCallback(BaseMathObject *self) { Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; - if(cb->get(self->cb_user, self->cb_subtype, self->vec)) { + if(cb->get(self->cb_user, self->cb_subtype, self->data)) return 1; - } - else { - PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); - return 0; - } + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; } -int _Vector_WriteCallback(VectorObject *self) +int _BaseMathObject_WriteCallback(BaseMathObject *self) { Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; - if(cb->set(self->cb_user, self->cb_subtype, self->vec)) { + if(cb->set(self->cb_user, self->cb_subtype, self->data)) return 1; - } - else { - PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); - return 0; - } + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; } -int _Vector_ReadIndexCallback(VectorObject *self, int index) +int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index) { Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; - if(cb->get_index(self->cb_user, self->cb_subtype, self->vec, index)) { + if(cb->get_index(self->cb_user, self->cb_subtype, self->data, index)) return 1; - } - else { - PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); - return 0; - } + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; } -int _Vector_WriteIndexCallback(VectorObject *self, int index) +int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index) { Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; - if(cb->set_index(self->cb_user, self->cb_subtype, self->vec, index)) { + if(cb->set_index(self->cb_user, self->cb_subtype, self->data, index)) return 1; - } - else { - PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); - return 0; - } + + PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name); + return 0; } -/* matrix callbacks */ -int _Matrix_ReadCallback(MatrixObject *self) +/* BaseMathObject generic functions for all mathutils types */ +PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type ) { - Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; - if(cb->get(self->cb_user, self->cb_subtype, self->contigPtr)) { - return 1; - } - else { - PyErr_SetString(PyExc_SystemError, "Matrix user has become invalid"); - return 0; - } + PyObject *ret= self->cb_user ? self->cb_user : Py_None; + Py_INCREF(ret); + return ret; } -int _Matrix_WriteCallback(MatrixObject *self) +PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type ) { - Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; - if(cb->set(self->cb_user, self->cb_subtype, self->contigPtr)) { - return 1; - } - else { - PyErr_SetString(PyExc_SystemError, "Matrix user has become invalid"); - return 0; - } + PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0); } + +void BaseMathObject_dealloc(BaseMathObject * self) +{ + /* only free non wrapped */ + if(self->wrapped != Py_WRAP) + PyMem_Free(self->data); + + Py_XDECREF(self->cb_user); + PyObject_DEL(self); +} + diff --git a/source/blender/python/generic/Mathutils.h b/source/blender/python/generic/Mathutils.h index a89b779ecbb..d234ebf1452 100644 --- a/source/blender/python/generic/Mathutils.h +++ b/source/blender/python/generic/Mathutils.h @@ -38,6 +38,24 @@ #include "quat.h" #include "euler.h" +/* Can cast different mathutils types to this, use for generic funcs */ + +typedef struct { + PyObject_VAR_HEAD + float *data; /*array of data (alias), wrapped status depends on wrapped status */ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /* wrapped data type? */ +} BaseMathObject; + +PyObject *BaseMathObject_getOwner( BaseMathObject * self, void * ); +PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void * ); +void BaseMathObject_dealloc(BaseMathObject * self); + + + + PyObject *Mathutils_Init( const char * from ); PyObject *quat_rotation(PyObject *arg1, PyObject *arg2); @@ -75,22 +93,15 @@ struct Mathutils_Callback { int Mathutils_RegisterCallback(Mathutils_Callback *cb); -int _Vector_ReadCallback(VectorObject *self); -int _Vector_WriteCallback(VectorObject *self); -int _Vector_ReadIndexCallback(VectorObject *self, int index); -int _Vector_WriteIndexCallback(VectorObject *self, int index); +int _BaseMathObject_ReadCallback(BaseMathObject *self); +int _BaseMathObject_WriteCallback(BaseMathObject *self); +int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index); +int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); /* since this is called so often avoid where possible */ -#define Vector_ReadCallback(_self) (((_self)->cb_user ? _Vector_ReadCallback(_self):1)) -#define Vector_WriteCallback(_self) (((_self)->cb_user ?_Vector_WriteCallback(_self):1)) -#define Vector_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _Vector_ReadIndexCallback(_self, _index):1)) -#define Vector_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _Vector_WriteIndexCallback(_self, _index):1)) - - -int _Matrix_ReadCallback(MatrixObject *self); -int _Matrix_WriteCallback(MatrixObject *self); - -#define Matrix_ReadCallback(_self) (((_self)->cb_user ?_Matrix_ReadCallback(_self):1)) -#define Matrix_WriteCallback(_self) (((_self)->cb_user ?_Matrix_WriteCallback(_self):1)) +#define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):1)) +#define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):1)) +#define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1)) +#define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index):1)) #endif /* EXPP_Mathutils_H */ diff --git a/source/blender/python/generic/euler.c b/source/blender/python/generic/euler.c index e78a5739347..eb9358774e1 100644 --- a/source/blender/python/generic/euler.c +++ b/source/blender/python/generic/euler.c @@ -123,6 +123,9 @@ static PyObject *Euler_ToQuat(EulerObject * self) float eul[3], quat[4]; int x; + if(!BaseMath_ReadCallback(self)) + return NULL; + for(x = 0; x < 3; x++) { eul[x] = self->eul[x] * ((float)Py_PI / 180); } @@ -137,6 +140,9 @@ static PyObject *Euler_ToMatrix(EulerObject * self) float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; int x; + if(!BaseMath_ReadCallback(self)) + return NULL; + for(x = 0; x < 3; x++) { eul[x] = self->eul[x] * ((float)Py_PI / 180); } @@ -152,6 +158,9 @@ static PyObject *Euler_Unique(EulerObject * self) double piO2 = Py_PI / 2.0f; double Opi2 = 1.0f / pi2; + if(!BaseMath_ReadCallback(self)) + return NULL; + //radians heading = self->eul[0] * (float)Py_PI / 180; pitch = self->eul[1] * (float)Py_PI / 180; @@ -191,6 +200,7 @@ static PyObject *Euler_Unique(EulerObject * self) self->eul[1] = (float)(pitch * 180 / (float)Py_PI); self->eul[2] = (float)(bank * 180 / (float)Py_PI); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -202,6 +212,7 @@ static PyObject *Euler_Zero(EulerObject * self) self->eul[1] = 0.0; self->eul[2] = 0.0; + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -223,6 +234,9 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args) return NULL; } + if(!BaseMath_ReadCallback(self)) + return NULL; + //covert to radians angle *= ((float)Py_PI / 180); for(x = 0; x < 3; x++) { @@ -234,6 +248,7 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args) self->eul[x] *= (180 / (float)Py_PI); } + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -248,6 +263,9 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value) return NULL; } + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + //covert to radians for(x = 0; x < 3; x++) { self->eul[x] = self->eul[x] * ((float)Py_PI / 180); @@ -259,6 +277,7 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value) self->eul[x] *= (180 / (float)Py_PI); } + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -267,19 +286,10 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value) // return a copy of the euler static PyObject *Euler_copy(EulerObject * self, PyObject *args) { - return newEulerObject(self->eul, Py_NEW); -} - + if(!BaseMath_ReadCallback(self)) + return NULL; -//----------------------------dealloc()(internal) ------------------ -//free the py_object -static void Euler_dealloc(EulerObject * self) -{ - //only free py_data - if(self->data.py_data){ - PyMem_Free(self->data.py_data); - } - PyObject_DEL(self); + return newEulerObject(self->eul, Py_NEW); } //----------------------------print object (internal)-------------- @@ -287,6 +297,10 @@ static void Euler_dealloc(EulerObject * self) static PyObject *Euler_repr(EulerObject * self) { char str[64]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]); return PyUnicode_FromString(str); } @@ -297,7 +311,18 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar EulerObject *eulA = NULL, *eulB = NULL; int result = 0; - if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){ + if(EulerObject_Check(objectA)) { + eulA = (EulerObject*)objectA; + if(!BaseMath_ReadCallback(eulA)) + return NULL; + } + if(EulerObject_Check(objectB)) { + eulB = (EulerObject*)objectB; + if(!BaseMath_ReadCallback(eulB)) + return NULL; + } + + if (!eulA || !eulB){ if (comparison_type == Py_NE){ Py_RETURN_TRUE; }else{ @@ -342,13 +367,16 @@ static int Euler_len(EulerObject * self) //sequence accessor (get) static PyObject *Euler_item(EulerObject * self, int i) { - if(i<0) - i= 3-i; + if(i<0) i= 3-i; if(i < 0 || i >= 3) { PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range"); return NULL; } + + if(!BaseMath_ReadIndexCallback(self, i)) + return NULL; + return PyFloat_FromDouble(self->eul[i]); } @@ -363,8 +391,7 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value) return -1; } - if(i<0) - i= 3-i; + if(i<0) i= 3-i; if(i < 0 || i >= 3){ PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n"); @@ -372,6 +399,10 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value) } self->eul[i] = f; + + if(!BaseMath_WriteIndexCallback(self, i)) + return -1; + return 0; } //----------------------------object[z:y]------------------------ @@ -381,6 +412,9 @@ static PyObject *Euler_slice(EulerObject * self, int begin, int end) PyObject *list = NULL; int count; + if(!BaseMath_ReadCallback(self)) + return NULL; + CLAMP(begin, 0, 3); if (end<0) end= 4+end; CLAMP(end, 0, 3); @@ -401,7 +435,10 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end, { int i, y, size = 0; float eul[3]; - PyObject *e, *f; + PyObject *e; + + if(!BaseMath_ReadCallback(self)) + return NULL; CLAMP(begin, 0, 3); if (end<0) end= 4+end; @@ -421,21 +458,20 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end, return -1; } - f = PyNumber_Float(e); - if(f == NULL) { // parsed item not a number - Py_DECREF(e); + eul[i] = (float)PyFloat_AsDouble(e); + Py_DECREF(e); + + if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number"); return -1; } - - eul[i] = (float)PyFloat_AS_DOUBLE(f); - Py_DECREF(f); - Py_DECREF(e); } //parsed well - now set in vector for(y = 0; y < 3; y++){ self->eul[begin + y] = eul[y]; } + + BaseMath_WriteCallback(self); return 0; } //-----------------PROTCOL DECLARATIONS-------------------------- @@ -450,79 +486,30 @@ static PySequenceMethods Euler_SeqMethods = { }; - /* * vector axis, vector.x/y/z/w */ static PyObject *Euler_getAxis( EulerObject * self, void *type ) { - switch( (long)type ) { - case 'X': /* these are backwards, but that how it works */ - return PyFloat_FromDouble(self->eul[0]); - case 'Y': - return PyFloat_FromDouble(self->eul[1]); - case 'Z': - return PyFloat_FromDouble(self->eul[2]); - } - - PyErr_SetString(PyExc_SystemError, "corrupt euler, cannot get axis"); - return NULL; + return Euler_item(self, GET_INT_FROM_POINTER(type)); } static int Euler_setAxis( EulerObject * self, PyObject * value, void * type ) { - float param= (float)PyFloat_AsDouble( value ); - - if (param==-1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected a number for the vector axis"); - return -1; - } - - switch( (long)type ) { - case 'X': /* these are backwards, but that how it works */ - self->eul[0]= param; - break; - case 'Y': - self->eul[1]= param; - break; - case 'Z': - self->eul[2]= param; - break; - } - - return 0; -} - -static PyObject *Euler_getWrapped( VectorObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value); } - /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Euler_getseters[] = { - {"x", - (getter)Euler_getAxis, (setter)Euler_setAxis, - "Euler X axis", - (void *)'X'}, - {"y", - (getter)Euler_getAxis, (setter)Euler_setAxis, - "Euler Y axis", - (void *)'Y'}, - {"z", - (getter)Euler_getAxis, (setter)Euler_setAxis, - "Euler Z axis", - (void *)'Z'}, - {"wrapped", - (getter)Euler_getWrapped, (setter)NULL, - "True when this wraps blenders internal data", - NULL}, + {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0}, + {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1}, + {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2}, + + {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, + {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -538,7 +525,7 @@ PyTypeObject euler_Type = { "euler", //tp_name sizeof(EulerObject), //tp_basicsize 0, //tp_itemsize - (destructor)Euler_dealloc, //tp_dealloc + (destructor)BaseMathObject_dealloc, //tp_dealloc 0, //tp_print 0, //tp_getattr 0, //tp_setattr @@ -593,24 +580,22 @@ PyObject *newEulerObject(float *eul, int type) int x; self = PyObject_NEW(EulerObject, &euler_Type); - self->data.blend_data = NULL; - self->data.py_data = NULL; + + /* init callbacks as NULL */ + self->cb_user= NULL; + self->cb_type= self->cb_subtype= 0; if(type == Py_WRAP){ - self->data.blend_data = eul; - self->eul = self->data.blend_data; + self->eul = eul; self->wrapped = Py_WRAP; }else if (type == Py_NEW){ - self->data.py_data = PyMem_Malloc(3 * sizeof(float)); - self->eul = self->data.py_data; + self->eul = PyMem_Malloc(3 * sizeof(float)); if(!eul) { //new empty for(x = 0; x < 3; x++) { self->eul[x] = 0.0f; } }else{ - for(x = 0; x < 3; x++){ - self->eul[x] = eul[x]; - } + VECCOPY(self->eul, eul); } self->wrapped = Py_NEW; }else{ //bad type @@ -618,3 +603,16 @@ PyObject *newEulerObject(float *eul, int type) } return (PyObject *)self; } + +PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype) +{ + EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW); + if(self) { + Py_INCREF(cb_user); + self->cb_user= cb_user; + self->cb_type= (unsigned char)cb_type; + self->cb_subtype= (unsigned char)cb_subtype; + } + + return self; +} diff --git a/source/blender/python/generic/euler.h b/source/blender/python/generic/euler.h index 3be629351cb..0bff6de6964 100644 --- a/source/blender/python/generic/euler.h +++ b/source/blender/python/generic/euler.h @@ -40,12 +40,13 @@ extern PyTypeObject euler_Type; typedef struct { PyObject_VAR_HEAD - struct{ - float *py_data; //python managed - float *blend_data; //blender managed - }data; - float *eul; //1D array of data (alias) - int wrapped; //is wrapped data? + float *eul; /*1D array of data */ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /* wrapped data type? */ + /* end BaseMathObject */ + } EulerObject; /*struct data contains a pointer to the actual data that the @@ -55,5 +56,6 @@ blender (stored in blend_data). This is an either/or struct not both*/ //prototypes PyObject *newEulerObject( float *eul, int type ); +PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype); #endif /* EXPP_euler_h */ diff --git a/source/blender/python/generic/matrix.c b/source/blender/python/generic/matrix.c index db5b4ab08bf..ef4f7280cdc 100644 --- a/source/blender/python/generic/matrix.c +++ b/source/blender/python/generic/matrix.c @@ -39,13 +39,13 @@ int mathutils_matrix_vector_cb_index= -1; static int mathutils_matrix_vector_check(MatrixObject *self) { - return Matrix_ReadCallback(self); + return BaseMath_ReadCallback(self); } static int mathutils_matrix_vector_get(MatrixObject *self, int subtype, float *vec_from) { int i; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return 0; for(i=0; i<self->colSize; i++) @@ -57,19 +57,19 @@ static int mathutils_matrix_vector_get(MatrixObject *self, int subtype, float *v static int mathutils_matrix_vector_set(MatrixObject *self, int subtype, float *vec_to) { int i; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return 0; for(i=0; i<self->colSize; i++) self->matrix[subtype][i]= vec_to[i]; - Matrix_WriteCallback(self); + BaseMath_WriteCallback(self); return 1; } static int mathutils_matrix_vector_get_index(MatrixObject *self, int subtype, float *vec_from, int index) { - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return 0; vec_from[index]= self->matrix[subtype][index]; @@ -78,12 +78,12 @@ static int mathutils_matrix_vector_get_index(MatrixObject *self, int subtype, fl static int mathutils_matrix_vector_set_index(MatrixObject *self, int subtype, float *vec_to, int index) { - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return 0; self->matrix[subtype][index]= vec_to[index]; - Matrix_WriteCallback(self); + BaseMath_WriteCallback(self); return 1; } @@ -164,7 +164,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) argObject = PyTuple_GET_ITEM(args, 0); if(MatrixObject_Check(argObject)){ mat = (MatrixObject*)argObject; - if(!Matrix_ReadCallback(mat)) + if(!BaseMath_ReadCallback(mat)) return NULL; argSize = mat->rowSize; //rows @@ -225,7 +225,7 @@ static PyObject *Matrix_toQuat(MatrixObject * self) { float quat[4]; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; /*must be 3-4 cols, 3-4 rows, square matrix*/ @@ -248,13 +248,16 @@ PyObject *Matrix_toEuler(MatrixObject * self, PyObject *args) EulerObject *eul_compat = NULL; int x; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat)) return NULL; if(eul_compat) { + if(!BaseMath_ReadCallback(eul_compat)) + return NULL; + for(x = 0; x < 3; x++) { eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180); } @@ -343,7 +346,7 @@ PyObject *Matrix_TranslationPart(MatrixObject * self) { float vec[4]; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(self->colSize < 3 || self->rowSize < 4){ @@ -363,7 +366,7 @@ PyObject *Matrix_RotationPart(MatrixObject * self) float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(self->colSize < 3 || self->rowSize < 3){ @@ -389,7 +392,7 @@ PyObject *Matrix_scalePart(MatrixObject * self) float scale[3], rot[3]; float mat[3][3], imat[3][3], tmat[3][3]; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; /*must be 3-4 cols, 3-4 rows, square matrix*/ @@ -422,7 +425,7 @@ PyObject *Matrix_Invert(MatrixObject * self) float mat[16] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(self->rowSize != self->colSize){ @@ -465,7 +468,7 @@ PyObject *Matrix_Invert(MatrixObject * self) return NULL; } - Matrix_WriteCallback(self); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -476,7 +479,7 @@ PyObject *Matrix_Determinant(MatrixObject * self) { float det = 0.0f; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(self->rowSize != self->colSize){ @@ -504,7 +507,7 @@ PyObject *Matrix_Transpose(MatrixObject * self) { float t = 0.0f; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(self->rowSize != self->colSize){ @@ -522,7 +525,7 @@ PyObject *Matrix_Transpose(MatrixObject * self) Mat4Transp((float (*)[4])*self->matrix); } - Matrix_WriteCallback(self); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject *)self; } @@ -539,7 +542,7 @@ PyObject *Matrix_Zero(MatrixObject * self) } } - if(!Matrix_WriteCallback(self)) + if(!BaseMath_WriteCallback(self)) return NULL; Py_INCREF(self); @@ -548,7 +551,7 @@ PyObject *Matrix_Zero(MatrixObject * self) /*---------------------------Matrix.identity(() ------------------*/ PyObject *Matrix_Identity(MatrixObject * self) { - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(self->rowSize != self->colSize){ @@ -567,7 +570,7 @@ PyObject *Matrix_Identity(MatrixObject * self) Mat4One((float (*)[4]) *self->matrix); } - if(!Matrix_WriteCallback(self)) + if(!BaseMath_WriteCallback(self)) return NULL; Py_INCREF(self); @@ -577,25 +580,12 @@ PyObject *Matrix_Identity(MatrixObject * self) /*---------------------------Matrix.inverted() ------------------*/ PyObject *Matrix_copy(MatrixObject * self) { - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; return (PyObject*)(MatrixObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW); } -/*----------------------------dealloc()(internal) ----------------*/ -/*free the py_object*/ -static void Matrix_dealloc(MatrixObject * self) -{ - PyMem_Free(self->matrix); - /*only free py_data*/ - if(self->wrapped==Py_WRAP) - PyMem_Free(self->contigPtr); - - Py_XDECREF(self->cb_user); - PyObject_DEL(self); -} - /*----------------------------print object (internal)-------------*/ /*print the object to screen*/ static PyObject *Matrix_repr(MatrixObject * self) @@ -603,7 +593,7 @@ static PyObject *Matrix_repr(MatrixObject * self) int x, y; char buffer[48], str[1024]; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; BLI_strncpy(str,"",1024); @@ -642,7 +632,7 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa matA = (MatrixObject*)objectA; matB = (MatrixObject*)objectB; - if(!Matrix_ReadCallback(matA) || !Matrix_ReadCallback(matB)) + if(!BaseMath_ReadCallback(matA) || !BaseMath_ReadCallback(matB)) return NULL; if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){ @@ -692,7 +682,7 @@ static int Matrix_len(MatrixObject * self) the wrapped vector gives direct access to the matrix data*/ static PyObject *Matrix_item(MatrixObject * self, int i) { - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if(i < 0 || i >= self->rowSize) { @@ -709,7 +699,7 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob) float vec[4]; PyObject *m, *f; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return -1; if(i >= self->rowSize || i < 0){ @@ -746,7 +736,7 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob) self->matrix[i][y] = vec[y]; } - Matrix_WriteCallback(self); + BaseMath_WriteCallback(self); return 0; }else{ PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n"); @@ -761,7 +751,7 @@ static PyObject *Matrix_slice(MatrixObject * self, int begin, int end) PyObject *list = NULL; int count; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; CLAMP(begin, 0, self->rowSize); @@ -787,7 +777,7 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end, PyObject *subseq; PyObject *m; - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return -1; CLAMP(begin, 0, self->rowSize); @@ -848,7 +838,7 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end, self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x]; } - Matrix_WriteCallback(self); + BaseMath_WriteCallback(self); return 0; }else{ PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n"); @@ -872,7 +862,7 @@ static PyObject *Matrix_add(PyObject * m1, PyObject * m2) return NULL; } - if(!Matrix_ReadCallback(mat1) || !Matrix_ReadCallback(mat2)) + if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2)) return NULL; if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){ @@ -905,7 +895,7 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2) return NULL; } - if(!Matrix_ReadCallback(mat1) || !Matrix_ReadCallback(mat2)) + if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2)) return NULL; if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){ @@ -934,12 +924,12 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) if(MatrixObject_Check(m1)) { mat1 = (MatrixObject*)m1; - if(!Matrix_ReadCallback(mat1)) + if(!BaseMath_ReadCallback(mat1)) return NULL; } if(MatrixObject_Check(m2)) { mat2 = (MatrixObject*)m2; - if(!Matrix_ReadCallback(mat2)) + if(!BaseMath_ReadCallback(mat2)) return NULL; } @@ -1000,7 +990,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) } static PyObject* Matrix_inv(MatrixObject *self) { - if(!Matrix_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; return Matrix_Invert(self); @@ -1052,33 +1042,15 @@ static PyObject *Matrix_getColSize( MatrixObject * self, void *type ) return PyLong_FromLong((long) self->colSize); } -static PyObject *Matrix_getOwner( MatrixObject * self, void *type ) -{ - if(self->cb_user==NULL) { - Py_RETURN_NONE; - } - else { - Py_INCREF(self->cb_user); - return self->cb_user; - } -} - -static PyObject *Matrix_getWrapped( MatrixObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Matrix_getseters[] = { {"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL}, {"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL}, - {"wrapped", (getter)Matrix_getWrapped, (setter)NULL, "", NULL}, - {"__owner__",(getter)Matrix_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, + {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL}, + {"__owner__",(getter)BaseMathObject_getOwner, (setter)NULL, "", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -1094,7 +1066,7 @@ PyTypeObject matrix_Type = { "matrix", /*tp_name*/ sizeof(MatrixObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ - (destructor)Matrix_dealloc, /*tp_dealloc*/ + (destructor)BaseMathObject_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ @@ -1245,7 +1217,7 @@ static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* double dot = 0.0f; int x, y, z = 0; - if(!Matrix_ReadCallback(mat) || !Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(mat) || !BaseMath_ReadCallback(vec)) return NULL; if(mat->rowSize != vec->size){ diff --git a/source/blender/python/generic/matrix.h b/source/blender/python/generic/matrix.h index cc3928f1632..4b073668969 100644 --- a/source/blender/python/generic/matrix.h +++ b/source/blender/python/generic/matrix.h @@ -37,16 +37,19 @@ extern PyTypeObject matrix_Type; #define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type) typedef float **ptRow; -typedef struct _Matrix { - PyObject_VAR_HEAD - ptRow matrix; /*ptr to the contigPtr (accessor)*/ - float* contigPtr; /*1D array of data (alias)*/ - PyObject* cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ - unsigned char rowSize; - unsigned char colSize; - unsigned char wrapped; /*is wrapped data?*/ +typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */ + PyObject_VAR_HEAD + float *contigPtr; /*1D array of data (alias)*/ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ - unsigned int cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /*is wrapped data?*/ + /* end BaseMathObject */ + + unsigned char rowSize; + unsigned int colSize; + ptRow matrix; /*ptr to the contigPtr (accessor)*/ + } MatrixObject; /*struct data contains a pointer to the actual data that the diff --git a/source/blender/python/generic/quat.c b/source/blender/python/generic/quat.c index 8a3ded80455..b1e9f4a1d31 100644 --- a/source/blender/python/generic/quat.c +++ b/source/blender/python/generic/quat.c @@ -78,7 +78,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw PyObject *listObject = NULL, *n, *q; int size, i; float quat[4], scalar; - double norm = 0.0f, angle = 0.0f; + double angle = 0.0f; size = PyTuple_GET_SIZE(args); if (size == 1 || size == 2) { //seq? @@ -152,28 +152,19 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw } scalar = PyFloat_AsDouble(q); + Py_DECREF(q); + if (scalar==-1 && PyErr_Occurred()) { - Py_DECREF(q); PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); return NULL; } - quat[i] = scalar; - Py_DECREF(q); - } - if(size == 3){ //calculate the quat based on axis/angle - norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * quat[2]); - quat[0] /= (float)norm; - quat[1] /= (float)norm; - quat[2] /= (float)norm; - - angle = angle * (Py_PI / 180); - quat[3] =(float) (sin(angle/ 2.0f)) * quat[2]; - quat[2] =(float) (sin(angle/ 2.0f)) * quat[1]; - quat[1] =(float) (sin(angle/ 2.0f)) * quat[0]; - quat[0] =(float) (cos(angle/ 2.0f)); } + if(size == 3) //calculate the quat based on axis/angle + AxisAngleToQuat(quat, quat, angle * (Py_PI / 180)); // TODO - 2.5 use radians, note using quat for src and target is ok here + + return newQuaternionObject(quat, Py_NEW); } @@ -189,9 +180,15 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args) if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat)) return NULL; + if(!BaseMath_ReadCallback(self)) + return NULL; + if(eul_compat) { float mat[3][3], eul_compatf[3]; + if(!BaseMath_ReadCallback(eul_compat)) + return NULL; + for(x = 0; x < 3; x++) { eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180); } @@ -214,8 +211,11 @@ static PyObject *Quaternion_ToEuler(QuaternionObject * self, PyObject *args) static PyObject *Quaternion_ToMatrix(QuaternionObject * self) { float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; - QuatToMat3(self->quat, (float (*)[3]) mat); + if(!BaseMath_ReadCallback(self)) + return NULL; + + QuatToMat3(self->quat, (float (*)[3]) mat); return newMatrixObject(mat, 3, 3, Py_NEW); } @@ -230,6 +230,9 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va return NULL; } + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + QuatMul(quat, self->quat, value->quat); return newQuaternionObject(quat, Py_NEW); } @@ -238,25 +241,27 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va //return the dot quat static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value) { - int x; - double dot = 0.0; - if (!QuaternionObject_Check(value)) { PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" ); return NULL; } - - for(x = 0; x < 4; x++) { - dot += self->quat[x] * value->quat[x]; - } - return PyFloat_FromDouble(dot); + + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + + return PyFloat_FromDouble(QuatDot(self->quat, value->quat)); } //----------------------------Quaternion.normalize()---------------- //normalize the axis of rotation of [theta,vector] static PyObject *Quaternion_Normalize(QuaternionObject * self) { + if(!BaseMath_ReadCallback(self)) + return NULL; + NormalQuat(self->quat); + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -264,20 +269,12 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self) //invert the quat static PyObject *Quaternion_Inverse(QuaternionObject * self) { - double mag = 0.0f; - int x; + if(!BaseMath_ReadCallback(self)) + return NULL; - for(x = 1; x < 4; x++) { - self->quat[x] = -self->quat[x]; - } - for(x = 0; x < 4; x++) { - mag += (self->quat[x] * self->quat[x]); - } - mag = sqrt(mag); - for(x = 0; x < 4; x++) { - self->quat[x] /= (float)(mag * mag); - } + QuatInv(self->quat); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -285,11 +282,12 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self) //generate the identity quaternion static PyObject *Quaternion_Identity(QuaternionObject * self) { - self->quat[0] = 1.0; - self->quat[1] = 0.0; - self->quat[2] = 0.0; - self->quat[3] = 0.0; + if(!BaseMath_ReadCallback(self)) + return NULL; + + QuatOne(self->quat); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -297,10 +295,12 @@ static PyObject *Quaternion_Identity(QuaternionObject * self) //negate the quat static PyObject *Quaternion_Negate(QuaternionObject * self) { - int x; - for(x = 0; x < 4; x++) { - self->quat[x] = -self->quat[x]; - } + if(!BaseMath_ReadCallback(self)) + return NULL; + + QuatMulf(self->quat, -1.0f); + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -308,10 +308,12 @@ static PyObject *Quaternion_Negate(QuaternionObject * self) //negate the vector part static PyObject *Quaternion_Conjugate(QuaternionObject * self) { - int x; - for(x = 1; x < 4; x++) { - self->quat[x] = -self->quat[x]; - } + if(!BaseMath_ReadCallback(self)) + return NULL; + + QuatConj(self->quat); + + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -319,18 +321,10 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self) //return a copy of the quat static PyObject *Quaternion_copy(QuaternionObject * self) { - return newQuaternionObject(self->quat, Py_NEW); -} + if(!BaseMath_ReadCallback(self)) + return NULL; -//----------------------------dealloc()(internal) ------------------ -//free the py_object -static void Quaternion_dealloc(QuaternionObject * self) -{ - //only free py_data - if(self->data.py_data){ - PyMem_Free(self->data.py_data); - } - PyObject_DEL(self); + return newQuaternionObject(self->quat, Py_NEW); } //----------------------------print object (internal)-------------- @@ -338,6 +332,10 @@ static void Quaternion_dealloc(QuaternionObject * self) static PyObject *Quaternion_repr(QuaternionObject * self) { char str[64]; + + if(!BaseMath_ReadCallback(self)) + return NULL; + sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]); return PyUnicode_FromString(str); } @@ -348,15 +346,24 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c QuaternionObject *quatA = NULL, *quatB = NULL; int result = 0; - if (!QuaternionObject_Check(objectA) || !QuaternionObject_Check(objectB)){ + if(QuaternionObject_Check(objectA)) { + quatA = (QuaternionObject*)objectA; + if(!BaseMath_ReadCallback(quatA)) + return NULL; + } + if(QuaternionObject_Check(objectB)) { + quatB = (QuaternionObject*)objectB; + if(!BaseMath_ReadCallback(quatB)) + return NULL; + } + + if (!quatA || !quatB){ if (comparison_type == Py_NE){ Py_RETURN_TRUE; }else{ Py_RETURN_FALSE; } } - quatA = (QuaternionObject*)objectA; - quatB = (QuaternionObject*)objectB; switch (comparison_type){ case Py_EQ: @@ -393,10 +400,16 @@ static int Quaternion_len(QuaternionObject * self) //sequence accessor (get) static PyObject *Quaternion_item(QuaternionObject * self, int i) { + if(i<0) i= 4-i; + if(i < 0 || i >= 4) { PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n"); return NULL; } + + if(!BaseMath_ReadIndexCallback(self, i)) + return NULL; + return PyFloat_FromDouble(self->quat[i]); } @@ -404,21 +417,23 @@ static PyObject *Quaternion_item(QuaternionObject * self, int i) //sequence accessor (set) static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob) { - PyObject *f = NULL; - - f = PyNumber_Float(ob); - if(f == NULL) { // parsed item not a number - PyErr_SetString(PyExc_TypeError, "quaternion[attribute] = x: argument not a number\n"); + float scalar= (float)PyFloat_AsDouble(ob); + if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n"); return -1; } + if(i<0) i= 4-i; + if(i < 0 || i >= 4){ - Py_DECREF(f); PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n"); return -1; } - self->quat[i] = (float)PyFloat_AS_DOUBLE(f); - Py_DECREF(f); + self->quat[i] = scalar; + + if(!BaseMath_WriteIndexCallback(self, i)) + return -1; + return 0; } //----------------------------object[z:y]------------------------ @@ -428,6 +443,9 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end) PyObject *list = NULL; int count; + if(!BaseMath_ReadCallback(self)) + return NULL; + CLAMP(begin, 0, 4); if (end<0) end= 5+end; CLAMP(end, 0, 4); @@ -443,12 +461,14 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end) } //----------------------------object[z:y]------------------------ //sequence slice (set) -static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, - PyObject * seq) +static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq) { int i, y, size = 0; float quat[4]; - PyObject *q, *f; + PyObject *q; + + if(!BaseMath_ReadCallback(self)) + return -1; CLAMP(begin, 0, 4); if (end<0) end= 5+end; @@ -468,21 +488,19 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, return -1; } - f = PyNumber_Float(q); - if(f == NULL) { // parsed item not a number - Py_DECREF(q); + quat[i]= (float)PyFloat_AsDouble(q); + Py_DECREF(q); + + if(quat[i]==-1.0f && PyErr_Occurred()) { /* parsed item not a number */ PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n"); return -1; } - - quat[i] = (float)PyFloat_AS_DOUBLE(f); - Py_DECREF(f); - Py_DECREF(q); } //parsed well - now set in vector - for(y = 0; y < size; y++){ + for(y = 0; y < size; y++) self->quat[begin + y] = quat[y]; - } + + BaseMath_WriteCallback(self); return 0; } //------------------------NUMERIC PROTOCOLS---------------------- @@ -490,7 +508,6 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, //addition static PyObject *Quaternion_add(PyObject * q1, PyObject * q2) { - int x; float quat[4]; QuaternionObject *quat1 = NULL, *quat2 = NULL; @@ -498,14 +515,13 @@ static PyObject *Quaternion_add(PyObject * q1, PyObject * q2) PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n"); return NULL; } - quat1 = (QuaternionObject*)q1; quat2 = (QuaternionObject*)q2; - for(x = 0; x < 4; x++) { - quat[x] = quat1->quat[x] + quat2->quat[x]; - } + if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2)) + return NULL; + QuatAdd(quat, quat1->quat, quat2->quat, 1.0f); return newQuaternionObject(quat, Py_NEW); } //------------------------obj - obj------------------------------ @@ -524,6 +540,9 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2) quat1 = (QuaternionObject*)q1; quat2 = (QuaternionObject*)q2; + if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2)) + return NULL; + for(x = 0; x < 4; x++) { quat[x] = quat1->quat[x] - quat2->quat[x]; } @@ -534,29 +553,31 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2) //mulplication static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) { - int x; float quat[4], scalar; - double dot = 0.0f; QuaternionObject *quat1 = NULL, *quat2 = NULL; VectorObject *vec = NULL; - quat1 = (QuaternionObject*)q1; - quat2 = (QuaternionObject*)q2; + if(QuaternionObject_Check(q1)) { + quat1 = (QuaternionObject*)q1; + if(!BaseMath_ReadCallback(quat1)) + return NULL; + } + if(QuaternionObject_Check(q2)) { + quat2 = (QuaternionObject*)q2; + if(!BaseMath_ReadCallback(quat2)) + return NULL; + } - if(QuaternionObject_Check(q1) && QuaternionObject_Check(q2)) { /* QUAT*QUAT (dot product) */ - for(x = 0; x < 4; x++) { - dot += quat1->quat[x] * quat1->quat[x]; - } - return PyFloat_FromDouble(dot); + if(quat1 && quat2) { /* QUAT*QUAT (dot product) */ + return PyFloat_FromDouble(QuatDot(quat1->quat, quat2->quat)); } /* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */ if(!QuaternionObject_Check(q1)) { scalar= PyFloat_AsDouble(q1); if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */ - for(x = 0; x < 4; x++) { - quat[x] = quat2->quat[x] * scalar; - } + QUATCOPY(quat, quat2->quat); + QuatMulf(quat, scalar); return newQuaternionObject(quat, Py_NEW); } PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type"); @@ -574,9 +595,8 @@ static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) scalar= PyFloat_AsDouble(q2); if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */ - for(x = 0; x < 4; x++) { - quat[x] = quat1->quat[x] * scalar; - } + QUATCOPY(quat, quat1->quat); + QuatMulf(quat, scalar); return newQuaternionObject(quat, Py_NEW); } } @@ -625,63 +645,17 @@ static PyNumberMethods Quaternion_NumMethods = { static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type ) { - switch( (long)type ) { - case 'W': - return PyFloat_FromDouble(self->quat[0]); - case 'X': - return PyFloat_FromDouble(self->quat[1]); - case 'Y': - return PyFloat_FromDouble(self->quat[2]); - case 'Z': - return PyFloat_FromDouble(self->quat[3]); - } - - PyErr_SetString(PyExc_SystemError, "corrupt quaternion, cannot get axis"); - return NULL; + return Quaternion_item(self, GET_INT_FROM_POINTER(type)); } static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type ) { - float param= (float)PyFloat_AsDouble( value ); - - if (param==-1 && PyErr_Occurred()) { - PyErr_SetString( PyExc_TypeError, "expected a number for the vector axis" ); - return -1; - } - switch( (long)type ) { - case 'W': - self->quat[0]= param; - break; - case 'X': - self->quat[1]= param; - break; - case 'Y': - self->quat[2]= param; - break; - case 'Z': - self->quat[3]= param; - break; - } - - return 0; -} - -static PyObject *Quaternion_getWrapped( QuaternionObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; + return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), value); } static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type ) { - double mag = 0.0; - int i; - for(i = 0; i < 4; i++) { - mag += self->quat[i] * self->quat[i]; - } - return PyFloat_FromDouble(sqrt(mag)); + return PyFloat_FromDouble(sqrt(QuatDot(self->quat, self->quat))); } static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type ) @@ -720,19 +694,19 @@ static PyGetSetDef Quaternion_getseters[] = { {"w", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion W value", - (void *)'W'}, + (void *)0}, {"x", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion X axis", - (void *)'X'}, + (void *)1}, {"y", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Y axis", - (void *)'Y'}, + (void *)2}, {"z", (getter)Quaternion_getAxis, (setter)Quaternion_setAxis, "Quaternion Z axis", - (void *)'Z'}, + (void *)3}, {"magnitude", (getter)Quaternion_getMagnitude, (setter)NULL, "Size of the quaternion", @@ -746,9 +720,14 @@ static PyGetSetDef Quaternion_getseters[] = { "quaternion axis as a vector", NULL}, {"wrapped", - (getter)Quaternion_getWrapped, (setter)NULL, + (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, + {"__owner__", + (getter)BaseMathObject_getOwner, (setter)NULL, + "Read only owner for vectors that depend on another object", + NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -765,7 +744,7 @@ PyTypeObject quaternion_Type = { "quaternion", //tp_name sizeof(QuaternionObject), //tp_basicsize 0, //tp_itemsize - (destructor)Quaternion_dealloc, //tp_dealloc + (destructor)BaseMathObject_dealloc, //tp_dealloc 0, //tp_print 0, //tp_getattr 0, //tp_setattr @@ -817,26 +796,22 @@ PyTypeObject quaternion_Type = { PyObject *newQuaternionObject(float *quat, int type) { QuaternionObject *self; - int x; self = PyObject_NEW(QuaternionObject, &quaternion_Type); - self->data.blend_data = NULL; - self->data.py_data = NULL; + + /* init callbacks as NULL */ + self->cb_user= NULL; + self->cb_type= self->cb_subtype= 0; if(type == Py_WRAP){ - self->data.blend_data = quat; - self->quat = self->data.blend_data; + self->quat = quat; self->wrapped = Py_WRAP; }else if (type == Py_NEW){ - self->data.py_data = PyMem_Malloc(4 * sizeof(float)); - self->quat = self->data.py_data; + self->quat = PyMem_Malloc(4 * sizeof(float)); if(!quat) { //new empty - Quaternion_Identity(self); - Py_DECREF(self); + QuatOne(self->quat); }else{ - for(x = 0; x < 4; x++){ - self->quat[x] = quat[x]; - } + QUATCOPY(self->quat, quat); } self->wrapped = Py_NEW; }else{ //bad type @@ -844,3 +819,16 @@ PyObject *newQuaternionObject(float *quat, int type) } return (PyObject *) self; } + +PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype) +{ + QuaternionObject *self= (QuaternionObject *)newQuaternionObject(NULL, Py_NEW); + if(self) { + Py_INCREF(cb_user); + self->cb_user= cb_user; + self->cb_type= (unsigned char)cb_type; + self->cb_subtype= (unsigned char)cb_subtype; + } + + return (PyObject *)self; +} diff --git a/source/blender/python/generic/quat.h b/source/blender/python/generic/quat.h index ebbac26e39c..2e74b5fa7f9 100644 --- a/source/blender/python/generic/quat.h +++ b/source/blender/python/generic/quat.h @@ -38,14 +38,15 @@ extern PyTypeObject quaternion_Type; #define QuaternionObject_Check(v) (Py_TYPE(v) == &quaternion_Type) -typedef struct { +typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */ PyObject_VAR_HEAD - struct{ - float *py_data; //python managed - float *blend_data; //blender managed - }data; - float *quat; //1D array of data (alias) - int wrapped; //is wrapped data? + float *quat; /* 1D array of data (alias) */ + PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ + unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ + unsigned char wrapped; /* wrapped data type? */ + /* end BaseMathObject */ + } QuaternionObject; /*struct data contains a pointer to the actual data that the @@ -55,5 +56,6 @@ blender (stored in blend_data). This is an either/or struct not both*/ //prototypes PyObject *newQuaternionObject( float *quat, int type ); +PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype); #endif /* EXPP_quat_h */ diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c index dea5bc93898..d68d3f41370 100644 --- a/source/blender/python/generic/vector.c +++ b/source/blender/python/generic/vector.c @@ -144,7 +144,7 @@ static PyObject *Vector_Zero(VectorObject * self) self->vec[i] = 0.0f; } - Vector_WriteCallback(self); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -155,7 +155,7 @@ static PyObject *Vector_Normalize(VectorObject * self) int i; float norm = 0.0f; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; for(i = 0; i < self->size; i++) { @@ -166,7 +166,7 @@ static PyObject *Vector_Normalize(VectorObject * self) self->vec[i] /= norm; } - Vector_WriteCallback(self); + BaseMath_WriteCallback(self); Py_INCREF(self); return (PyObject*)self; } @@ -266,7 +266,7 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) return NULL; } - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; if (strack) { @@ -385,7 +385,7 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value ) return NULL; } - if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value)) + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) return NULL; mirror[0] = value->vec[0]; @@ -431,7 +431,7 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ) return NULL; } - if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value)) + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) return NULL; vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW); @@ -454,7 +454,7 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ) return NULL; } - if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value)) + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) return NULL; for(x = 0; x < self->size; x++) { @@ -467,24 +467,12 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ) return a copy of the vector */ static PyObject *Vector_copy(VectorObject * self) { - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; return newVectorObject(self->vec, self->size, Py_NEW); } -/*----------------------------dealloc()(internal) ---------------- - free the py_object */ -static void Vector_dealloc(VectorObject * self) -{ - /* only free non wrapped */ - if(self->wrapped != Py_WRAP) - PyMem_Free(self->vec); - - Py_XDECREF(self->cb_user); - PyObject_DEL(self); -} - /*----------------------------print object (internal)------------- print the object to screen */ static PyObject *Vector_repr(VectorObject * self) @@ -492,7 +480,7 @@ static PyObject *Vector_repr(VectorObject * self) int i; char buffer[48], str[1024]; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; BLI_strncpy(str,"[",1024); @@ -520,12 +508,14 @@ static int Vector_len(VectorObject * self) sequence accessor (get)*/ static PyObject *Vector_item(VectorObject * self, int i) { + if(i<0) i= self->size-i; + if(i < 0 || i >= self->size) { PyErr_SetString(PyExc_IndexError,"vector[index]: out of range\n"); return NULL; } - if(!Vector_ReadIndexCallback(self, i)) + if(!BaseMath_ReadIndexCallback(self, i)) return NULL; return PyFloat_FromDouble(self->vec[i]); @@ -541,13 +531,15 @@ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob) return -1; } + if(i<0) i= self->size-i; + if(i < 0 || i >= self->size){ PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n"); return -1; } self->vec[i] = scalar; - if(!Vector_WriteIndexCallback(self, i)) + if(!BaseMath_WriteIndexCallback(self, i)) return -1; return 0; } @@ -559,7 +551,7 @@ static PyObject *Vector_slice(VectorObject * self, int begin, int end) PyObject *list = NULL; int count; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; CLAMP(begin, 0, self->size); @@ -584,7 +576,7 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end, float vec[4], scalar; PyObject *v; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return -1; CLAMP(begin, 0, self->size); @@ -620,7 +612,7 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end, self->vec[begin + y] = vec[y]; } - if(!Vector_WriteCallback(self)) + if(!BaseMath_WriteCallback(self)) return -1; return 0; @@ -644,7 +636,7 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) /* make sure v1 is always the vector */ if (vec1 && vec2 ) { - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; /*VECTOR + VECTOR*/ @@ -679,7 +671,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) /* make sure v1 is always the vector */ if (vec1 && vec2 ) { - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; /*VECTOR + VECTOR*/ @@ -694,7 +686,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) return v1; } - Vector_WriteCallback(vec1); + BaseMath_WriteCallback(vec1); PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n"); return NULL; } @@ -714,7 +706,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) vec1 = (VectorObject*)v1; vec2 = (VectorObject*)v2; - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; if(vec1->size != vec2->size) { @@ -747,14 +739,14 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2) return NULL; } - if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2)) return NULL; for(i = 0; i < vec1->size; i++) { vec1->vec[i] = vec1->vec[i] - vec2->vec[i]; } - Vector_WriteCallback(vec1); + BaseMath_WriteCallback(vec1); Py_INCREF( v1 ); return v1; } @@ -768,12 +760,12 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) if VectorObject_Check(v1) { vec1= (VectorObject *)v1; - if(!Vector_ReadCallback(vec1)) + if(!BaseMath_ReadCallback(vec1)) return NULL; } if VectorObject_Check(v2) { vec2= (VectorObject *)v2; - if(!Vector_ReadCallback(vec2)) + if(!BaseMath_ReadCallback(vec2)) return NULL; } @@ -805,7 +797,8 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) /* VEC * MATRIX */ return row_vector_multiplication(vec1, (MatrixObject*)v2); } else if (QuaternionObject_Check(v2)) { - QuaternionObject *quat = (QuaternionObject*)v2; + QuaternionObject *quat = (QuaternionObject*)v2; /* quat_rotation validates */ + if(vec1->size != 3) { PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n"); return NULL; @@ -835,7 +828,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) int i; float scalar; - if(!Vector_ReadCallback(vec)) + if(!BaseMath_ReadCallback(vec)) return NULL; /* only support vec*=float and vec*=mat @@ -845,7 +838,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) int x,y, size = vec->size; MatrixObject *mat= (MatrixObject*)v2; - if(!Vector_ReadCallback(mat)) + if(!BaseMath_ReadCallback(mat)) return NULL; if(mat->colSize != size){ @@ -883,7 +876,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) return NULL; } - Vector_WriteCallback(vec); + BaseMath_WriteCallback(vec); Py_INCREF( v1 ); return v1; } @@ -902,7 +895,7 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2) } vec1 = (VectorObject*)v1; /* vector */ - if(!Vector_ReadCallback(vec1)) + if(!BaseMath_ReadCallback(vec1)) return NULL; scalar = (float)PyFloat_AsDouble(v2); @@ -930,7 +923,7 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) float scalar; VectorObject *vec1 = (VectorObject*)v1; - if(!Vector_ReadCallback(vec1)) + if(!BaseMath_ReadCallback(vec1)) return NULL; scalar = (float)PyFloat_AsDouble(v2); @@ -947,7 +940,7 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) vec1->vec[i] /= scalar; } - Vector_WriteCallback(vec1); + BaseMath_WriteCallback(vec1); Py_INCREF( v1 ); return v1; @@ -960,7 +953,7 @@ static PyObject *Vector_neg(VectorObject *self) int i; float vec[4]; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; for(i = 0; i < self->size; i++){ @@ -1008,7 +1001,7 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa vecA = (VectorObject*)objectA; vecB = (VectorObject*)objectB; - if(!Vector_ReadCallback(vecA) || !Vector_ReadCallback(vecB)) + if(!BaseMath_ReadCallback(vecA) || !BaseMath_ReadCallback(vecB)) return NULL; if (vecA->size != vecB->size){ @@ -1137,12 +1130,12 @@ static PyNumberMethods Vector_NumMethods = { static PyObject *Vector_getAxis( VectorObject * self, void *type ) { - return Vector_item(self, (int)type); + return Vector_item(self, GET_INT_FROM_POINTER(type)); } static int Vector_setAxis( VectorObject * self, PyObject * value, void * type ) { - return Vector_ass_item(self, (int)type, value); + return Vector_ass_item(self, GET_INT_FROM_POINTER(type), value); } /* vector.length */ @@ -1151,7 +1144,7 @@ static PyObject *Vector_getLength( VectorObject * self, void *type ) double dot = 0.0f; int i; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; for(i = 0; i < self->size; i++){ @@ -1165,7 +1158,7 @@ static int Vector_setLength( VectorObject * self, PyObject * value ) double dot = 0.0f, param; int i; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return -1; param= PyFloat_AsDouble( value ); @@ -1203,30 +1196,11 @@ static int Vector_setLength( VectorObject * self, PyObject * value ) self->vec[i]= self->vec[i] / (float)dot; } - Vector_WriteCallback(self); /* checked alredy */ + BaseMath_WriteCallback(self); /* checked alredy */ return 0; } -static PyObject *Vector_getWrapped( VectorObject * self, void *type ) -{ - if (self->wrapped == Py_WRAP) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -static PyObject *Vector_getOwner( VectorObject * self, void *type ) -{ - if(self->cb_user==NULL) { - Py_RETURN_NONE; - } - else { - Py_INCREF(self->cb_user); - return self->cb_user; - } -} - /* Get a new Vector according to the provided swizzle. This function has little error checking, as we are in control of the inputs: the closure is set by us in Vector_createSwizzleGetSeter. */ @@ -1237,7 +1211,7 @@ static PyObject *Vector_getSwizzle(VectorObject * self, void *closure) float vec[MAX_DIMENSIONS]; unsigned int swizzleClosure; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; /* Unpack the axes from the closure into an array. */ @@ -1277,7 +1251,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur float vecTemp[MAX_DIMENSIONS]; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return -1; /* Check that the closure can be used with this vector: even 2D vectors have @@ -1309,7 +1283,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur axisB++; } memcpy(self->vec, vecTemp, axisB * sizeof(float)); - /* continue with Vector_WriteCallback at the end */ + /* continue with BaseMathObject_WriteCallback at the end */ } else if (PyList_Check(value)) { @@ -1335,7 +1309,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur axisB++; } memcpy(self->vec, vecTemp, axisB * sizeof(float)); - /* continue with Vector_WriteCallback at the end */ + /* continue with BaseMathObject_WriteCallback at the end */ } else if (((scalarVal = (float)PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred())==0) { @@ -1348,14 +1322,14 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; } - /* continue with Vector_WriteCallback at the end */ + /* continue with BaseMathObject_WriteCallback at the end */ } else { PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." ); return -1; } - if(!Vector_WriteCallback(vecVal)) + if(!BaseMath_WriteCallback(vecVal)) return -1; else return 0; @@ -1390,11 +1364,11 @@ static PyGetSetDef Vector_getseters[] = { "Vector Length", NULL}, {"wrapped", - (getter)Vector_getWrapped, (setter)NULL, + (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL}, {"__owner__", - (getter)Vector_getOwner, (setter)NULL, + (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, @@ -1803,7 +1777,7 @@ PyTypeObject vector_Type = { /* Methods to implement standard operations */ - ( destructor ) Vector_dealloc,/* destructor tp_dealloc; */ + ( destructor ) BaseMathObject_dealloc,/* destructor tp_dealloc; */ NULL, /* printfunc tp_print; */ NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ @@ -1920,7 +1894,7 @@ PyObject *newVectorObject(float *vec, int size, int type) PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_subtype) { float dummy[4] = {0.0, 0.0, 0.0, 0.0}; /* dummy init vector, callbacks will be used on access */ - VectorObject *self= newVectorObject(dummy, size, Py_NEW); + VectorObject *self= (VectorObject *)newVectorObject(dummy, size, Py_NEW); if(self) { Py_INCREF(cb_user); self->cb_user= cb_user; @@ -1928,7 +1902,7 @@ PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_su self->cb_subtype= (unsigned char)cb_subtype; } - return self; + return (PyObject *)self; } //-----------------row_vector_multiplication (internal)----------- @@ -1952,7 +1926,7 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat } } - if(!Vector_ReadCallback(vec) || !Matrix_ReadCallback(mat)) + if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat)) return NULL; for(x = 0; x < vec_size; x++){ @@ -1975,13 +1949,13 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat static PyObject *Vector_Negate(VectorObject * self) { int i; - if(!Vector_ReadCallback(self)) + if(!BaseMath_ReadCallback(self)) return NULL; for(i = 0; i < self->size; i++) self->vec[i] = -(self->vec[i]); - Vector_WriteCallback(self); // alredy checked for error + BaseMath_WriteCallback(self); // alredy checked for error Py_INCREF(self); return (PyObject*)self; diff --git a/source/blender/python/generic/vector.h b/source/blender/python/generic/vector.h index 82dbf13b9aa..f519b2808cb 100644 --- a/source/blender/python/generic/vector.h +++ b/source/blender/python/generic/vector.h @@ -37,15 +37,16 @@ extern PyTypeObject vector_Type; #define VectorObject_Check(v) (((PyObject *)v)->ob_type == &vector_Type) -typedef struct { +typedef struct { /* keep aligned with BaseMathObject in Mathutils.h */ PyObject_VAR_HEAD float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */ PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */ - unsigned char size; /* vec size 2,3 or 4 */ - unsigned char wrapped; /* wrapped data type? */ unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */ - + unsigned char wrapped; /* wrapped data type? */ + /* end BaseMathObject */ + + unsigned char size; /* vec size 2,3 or 4 */ } VectorObject; /*prototypes*/ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 3cef6e14861..0b8a7df1ae1 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -44,8 +44,8 @@ #ifdef USE_MATHUTILS #include "../generic/Mathutils.h" /* so we can have mathutils callbacks */ -/* bpyrna vector callbacks */ -static int mathutils_rna_vector_cb_index= -1; /* index for our callbacks */ +/* bpyrna vector/euler/quat callbacks */ +static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */ static int mathutils_rna_generic_check(BPy_PropertyRNA *self) { @@ -88,7 +88,7 @@ static int mathutils_rna_vector_set_index(BPy_PropertyRNA *self, int subtype, fl return 1; } -Mathutils_Callback mathutils_rna_vector_cb = { +Mathutils_Callback mathutils_rna_array_cb = { mathutils_rna_generic_check, mathutils_rna_vector_get, mathutils_rna_vector_set, @@ -234,26 +234,41 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) PyObject *ret = pyrna_prop_CreatePyObject(ptr, prop); #ifdef USE_MATHUTILS + /* return a mathutils vector where possible */ if(RNA_property_type(prop)==PROP_FLOAT) { - if(RNA_property_subtype(prop)==PROP_VECTOR) { + switch(RNA_property_subtype(prop)) { + case PROP_VECTOR: if(len>=2 && len <= 4) { - PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_vector_cb_index, 0); + PyObject *vec_cb= newVectorObject_cb(ret, len, mathutils_rna_array_cb_index, 0); Py_DECREF(ret); /* the vector owns now */ ret= vec_cb; /* return the vector instead */ } - } - else if(RNA_property_subtype(prop)==PROP_MATRIX) { + break; + case PROP_MATRIX: if(len==16) { - PyObject *mat_cb= newMatrixObject_cb(ret, 4,4, mathutils_rna_vector_cb_index, 0); + PyObject *mat_cb= newMatrixObject_cb(ret, 4,4, mathutils_rna_matrix_cb_index, 0); Py_DECREF(ret); /* the matrix owns now */ ret= mat_cb; /* return the matrix instead */ } else if (len==9) { - PyObject *mat_cb= newMatrixObject_cb(ret, 3,3, mathutils_rna_vector_cb_index, 0); + PyObject *mat_cb= newMatrixObject_cb(ret, 3,3, mathutils_rna_matrix_cb_index, 0); Py_DECREF(ret); /* the matrix owns now */ ret= mat_cb; /* return the matrix instead */ } + break; + case PROP_ROTATION: + if(len==3) { /* euler */ + PyObject *eul_cb= newEulerObject_cb(ret, mathutils_rna_array_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret= eul_cb; /* return the matrix instead */ + } + else if (len==4) { + PyObject *quat_cb= newQuaternionObject_cb(ret, mathutils_rna_array_cb_index, 0); + Py_DECREF(ret); /* the matrix owns now */ + ret= quat_cb; /* return the matrix instead */ + } + break; } } @@ -377,12 +392,15 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const char *error_prefi static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw); -PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func) +PyObject *pyrna_func_to_py(BPy_StructRNA *pyrna, FunctionRNA *func) { static PyMethodDef func_meth = {"<generic rna function>", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"}; PyObject *self= PyTuple_New(2); PyObject *ret; - PyTuple_SET_ITEM(self, 0, pyrna_struct_CreatePyObject(ptr)); + + PyTuple_SET_ITEM(self, 0, (PyObject *)pyrna); + Py_INCREF(pyrna); + PyTuple_SET_ITEM(self, 1, PyCObject_FromVoidPtr((void *)func, NULL)); ret= PyCFunction_New(&func_meth, self); @@ -407,23 +425,23 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v #ifdef USE_MATHUTILS if(MatrixObject_Check(value)) { MatrixObject *mat = (MatrixObject*)value; - if(!Matrix_ReadCallback(mat)) + if(!BaseMath_ReadCallback(mat)) return -1; py_len = mat->rowSize * mat->colSize; - } else // continue... + } else /* continue... */ #endif if (PySequence_Check(value)) { py_len= (int)PySequence_Length(value); } else { - PyErr_SetString(PyExc_TypeError, "expected a python sequence type assigned to an RNA array."); + PyErr_Format(PyExc_TypeError, "RNA array assignment expected a sequence instead of %s instance.", Py_TYPE(value)->tp_name); return -1; } /* done getting the length */ if (py_len != len) { - PyErr_SetString(PyExc_AttributeError, "python sequence length did not match the RNA array."); + PyErr_Format(PyExc_AttributeError, "python sequence length %d did not match the RNA array length %d.", py_len, len); return -1; } @@ -493,7 +511,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v if(MatrixObject_Check(value) && RNA_property_subtype(prop) == PROP_MATRIX) { MatrixObject *mat = (MatrixObject*)value; memcpy(param_arr, mat->contigPtr, sizeof(float) * len); - } else // continue... + } else /* continue... */ #endif { /* collect the variables */ @@ -1036,7 +1054,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) ret = pyrna_prop_to_py(&self->ptr, prop); } else if ((func = RNA_struct_find_function(&self->ptr, name))) { - ret = pyrna_func_to_py(&self->ptr, func); + ret = pyrna_func_to_py(self, func); } else if (self->ptr.type == &RNA_Context) { PointerRNA newptr; @@ -1786,7 +1804,7 @@ PyObject *BPY_rna_module( void ) PointerRNA ptr; #ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once. - mathutils_rna_vector_cb_index= Mathutils_RegisterCallback(&mathutils_rna_vector_cb); + mathutils_rna_array_cb_index= Mathutils_RegisterCallback(&mathutils_rna_array_cb); mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb); #endif diff --git a/source/gameengine/Expressions/KX_Python.h b/source/gameengine/Expressions/KX_Python.h index b8006fdf0ed..61f7ef05042 100644 --- a/source/gameengine/Expressions/KX_Python.h +++ b/source/gameengine/Expressions/KX_Python.h @@ -32,6 +32,8 @@ //#define USE_DL_EXPORT #include "Python.h" +#define USE_MATHUTILS // Blender 2.5x api will use mathutils, for a while we might want to test without it + #ifdef __FreeBSD__ #include <osreldate.h> #if __FreeBSD_version > 500039 diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index defb6853e67..2d4cc612aef 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -331,13 +331,18 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef } case KX_PYATTRIBUTE_TYPE_VECTOR: { - PyObject* resultlist = PyList_New(3); MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr); +#ifdef USE_MATHUTILS + float fval[3]= {(*val)[0], (*val)[1], (*val)[2]}; + return newVectorObject(fval, 3, Py_NEW); +#else + PyObject* resultlist = PyList_New(3); for (unsigned int i=0; i<3; i++) { PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i])); } return resultlist; +#endif } case KX_PYATTRIBUTE_TYPE_STRING: { diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 96c75b710a3..3b5eebe9893 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -41,13 +41,15 @@ #include "MT_Vector3.h" #include "SG_QList.h" -#define USE_MATHUTILS // Blender 2.5x api will use mathutils, for a while we might want to test without it - /*------------------------------ * Python defines ------------------------------*/ - +#ifdef USE_MATHUTILS +extern "C" { +#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */ +} +#endif #if PY_VERSION_HEX > 0x03000000 #define PyString_FromString PyUnicode_FromString diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index a3b2ba79e11..577f767b475 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -1184,11 +1184,7 @@ CListValue* KX_GameObject::GetChildrenRecursive() return list; } - #ifdef USE_MATHUTILS -extern "C" { -#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */ -} /* These require an SGNode */ #define MATHUTILS_VEC_CB_POS_LOCAL 1 @@ -1880,12 +1876,7 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, ")) return PY_SET_ATTR_FAIL; - if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) { - self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot); - } - else { - self->NodeSetLocalOrientation(rot); - } + self->NodeSetGlobalOrientation(rot); self->NodeUpdateGS(0.f); return PY_SET_ATTR_SUCCESS; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index eaae04d406d..62e61667c56 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -396,9 +396,14 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc), KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags), KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot), +#ifdef USE_MATHUTILS + KX_PYATTRIBUTE_RW_FUNCTION("linV", KX_ObjectActuator, pyattr_get_linV, pyattr_set_linV), + KX_PYATTRIBUTE_RW_FUNCTION("angV", KX_ObjectActuator, pyattr_get_angV, pyattr_set_angV), +#else KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags), - KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity), KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags), +#endif + KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity), KX_PYATTRIBUTE_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity), KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping), KX_PYATTRIBUTE_RW_FUNCTION("forceLimitX", KX_ObjectActuator, pyattr_get_forceLimitX, pyattr_set_forceLimitX), @@ -425,6 +430,129 @@ int KX_ObjectActuator::py_setattro(PyObject *attr, PyObject *value) /* Attribute get/set functions */ +#ifdef USE_MATHUTILS + +/* These require an SGNode */ +#define MATHUTILS_VEC_CB_LINV 1 +#define MATHUTILS_VEC_CB_ANGV 2 + +static int mathutils_kxobactu_vector_cb_index= -1; /* index for our callbacks */ + +static int mathutils_obactu_generic_check(PyObject *self_v) +{ + KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + return 1; +} + +static int mathutils_obactu_vector_get(PyObject *self_v, int subtype, float *vec_from) +{ + KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + switch(subtype) { + case MATHUTILS_VEC_CB_LINV: + self->m_linear_velocity.getValue(vec_from); + break; + case MATHUTILS_VEC_CB_ANGV: + self->m_angular_velocity.getValue(vec_from); + break; + } + + return 1; +} + +static int mathutils_obactu_vector_set(PyObject *self_v, int subtype, float *vec_to) +{ + KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(self_v); + if(self==NULL) + return 0; + + switch(subtype) { + case MATHUTILS_VEC_CB_LINV: + self->m_linear_velocity.setValue(vec_to); + break; + case MATHUTILS_VEC_CB_ANGV: + self->m_angular_velocity.setValue(vec_to); + break; + } + + return 1; +} + +static int mathutils_obactu_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index) +{ + float f[4]; + /* lazy, avoid repeteing the case statement */ + if(!mathutils_obactu_vector_get(self_v, subtype, f)) + return 0; + + vec_from[index]= f[index]; + return 1; +} + +static int mathutils_obactu_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index) +{ + float f= vec_to[index]; + + /* lazy, avoid repeteing the case statement */ + if(!mathutils_obactu_vector_get(self_v, subtype, vec_to)) + return 0; + + vec_to[index]= f; + mathutils_obactu_vector_set(self_v, subtype, vec_to); + + return 1; +} + +Mathutils_Callback mathutils_obactu_vector_cb = { + mathutils_obactu_generic_check, + mathutils_obactu_vector_get, + mathutils_obactu_vector_set, + mathutils_obactu_vector_get_index, + mathutils_obactu_vector_set_index +}; + +PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); +} + +int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v); + if (!PyVecTo(value, self->m_linear_velocity)) + return PY_SET_ATTR_FAIL; + + return PY_SET_ATTR_SUCCESS; +} + +PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); +} + +int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v); + if (!PyVecTo(value, self->m_angular_velocity)) + return PY_SET_ATTR_FAIL; + + return PY_SET_ATTR_SUCCESS; +} + + +void KX_ObjectActuator_Mathutils_Callback_Init(void) +{ + // register mathutils callbacks, ok to run more then once. + mathutils_kxobactu_vector_cb_index= Mathutils_RegisterCallback(&mathutils_obactu_vector_cb); +} + +#endif // USE_MATHUTILS + PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index f9bd2a0c748..6ca442b2ec2 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -35,6 +35,10 @@ #include "SCA_IActuator.h" #include "MT_Vector3.h" +#ifdef USE_MATHUTILS +void KX_ObjectActuator_Mathutils_Callback_Init(void); +#endif + class KX_GameObject; // @@ -197,6 +201,13 @@ public: static PyObject* pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); +#ifdef USE_MATHUTILS + static PyObject* pyattr_get_linV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_linV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_angV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_angV(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); +#endif + // This lets the attribute macros use UpdateFuzzyFlags() static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef) { diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 051d7ae7dba..ee9fed5d30a 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -46,35 +46,6 @@ #include "KX_Python.h" #include "KX_PyMath.h" -bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) -{ - if (!pymat) - return false; - - unsigned int y; - if (PySequence_Check(pymat)) - { - unsigned int rows = PySequence_Size(pymat); - if (rows != rank) - return false; - - bool ismatrix = true; - for (y = 0; y < rank && ismatrix; y++) - { - PyObject *pyrow = PySequence_GetItem(pymat, y); /* new ref */ - if (PySequence_Check(pyrow)) - { - if (((unsigned int)PySequence_Size(pyrow)) != rank) - ismatrix = false; - } else - ismatrix = false; - Py_DECREF(pyrow); - } - return ismatrix; - } - return false; -} - bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix) { int size= PySequence_Size(pyval); @@ -110,12 +81,10 @@ bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefi PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) { -#if 0 - return Py_BuildValue("[[ffff][ffff][ffff][ffff]]", - mat[0][0], mat[0][1], mat[0][2], mat[0][3], - mat[1][0], mat[1][1], mat[1][2], mat[1][3], - mat[2][0], mat[2][1], mat[2][2], mat[2][3], - mat[3][0], mat[3][1], mat[3][2], mat[3][3]); +#ifdef USE_MATHUTILS + float fmat[16]; + mat.getValue(fmat); + return newMatrixObject(fmat, 4, 4, Py_NEW); #else PyObject *list = PyList_New(4); PyObject *sublist; @@ -136,11 +105,10 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat) PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) { -#if 0 - return Py_BuildValue("[[fff][fff][fff]]", - mat[0][0], mat[0][1], mat[0][2], - mat[1][0], mat[1][1], mat[1][2], - mat[2][0], mat[2][1], mat[2][2]); +#ifdef USE_MATHUTILS + float fmat[9]; + mat.getValue3x3(fmat); + return newMatrixObject(fmat, 3, 3, Py_NEW); #else PyObject *list = PyList_New(3); PyObject *sublist; @@ -160,9 +128,9 @@ PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) PyObject* PyObjectFrom(const MT_Tuple4 &vec) { -#if 0 - return Py_BuildValue("[ffff]", - vec[0], vec[1], vec[2], vec[3]); +#ifdef USE_MATHUTILS + float fvec[4]= {vec[0], vec[1], vec[2], vec[3]}; + return newVectorObject(fvec, 4, Py_WRAP); #else PyObject *list = PyList_New(4); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -175,9 +143,9 @@ PyObject* PyObjectFrom(const MT_Tuple4 &vec) PyObject* PyObjectFrom(const MT_Tuple3 &vec) { -#if 0 - return Py_BuildValue("[fff]", - vec[0], vec[1], vec[2]); +#ifdef USE_MATHUTILS + float fvec[3]= {vec[0], vec[1], vec[2]}; + return newVectorObject(fvec, 3, Py_WRAP); #else PyObject *list = PyList_New(3); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -189,9 +157,9 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec) PyObject* PyObjectFrom(const MT_Tuple2 &vec) { -#if 0 - return Py_BuildValue("[ff]", - vec[0], vec[1]); +#ifdef USE_MATHUTILS + float fvec[2]= {vec[0], vec[1]}; + return newVectorObject(fvec, 2, Py_WRAP); #else PyObject *list = PyList_New(2); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index a7ce4bc6930..90a13425aa0 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -31,6 +31,12 @@ #ifndef __KX_PYMATH_H__ #define __KX_PYMATH_H__ +#ifdef USE_MATHUTILS +extern "C" { +#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */ +} +#endif + #include "MT_Point2.h" #include "MT_Point3.h" #include "MT_Vector2.h" @@ -98,7 +104,28 @@ bool PyMatTo(PyObject* pymat, T& mat) template<class T> bool PyVecTo(PyObject* pyval, T& vec) { - +#ifdef USE_MATHUTILS + /* no need for BaseMath_ReadCallback() here, reading the sequences will do this */ + + if(VectorObject_Check(pyval)) { + VectorObject *pyvec= (VectorObject *)pyval; + if (pyvec->size != Size(vec)) { + PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", pyvec->size, Size(vec)); + return false; + } + vec.getValue((float *) pyvec->vec); + return true; + } + else if(EulerObject_Check(pyval)) { + EulerObject *pyeul= (EulerObject *)pyval; + if (3 != Size(vec)) { + PyErr_Format(PyExc_AttributeError, "error setting vector, %d args, should be %d", 3, Size(vec)); + return false; + } + vec.getValue((float *) pyeul->eul); + return true; + } else +#endif if(PyTuple_Check(pyval)) { unsigned int numitems = PyTuple_GET_SIZE(pyval); @@ -186,10 +213,4 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec); */ PyObject* PyObjectFrom(const MT_Tuple4 &pos); -/** - * True if the given PyObject can be converted to an MT_Matrix - * @param rank = 3 (for MT_Matrix3x3) or 4 (for MT_Matrix4x4) - */ -bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank); - #endif diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 05cb818fdd9..d5d0fe3123c 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -235,7 +235,8 @@ void initPyTypes(void) #ifdef USE_MATHUTILS /* Init mathutils callbacks */ KX_GameObject_Mathutils_Callback_Init(); + KX_ObjectActuator_Mathutils_Callback_Init(); #endif } -#endif
\ No newline at end of file +#endif |