PyAPI RNA/BGE
authorCampbell Barton <ideasman42@gmail.com>
Thu, 25 Jun 2009 10:11:37 +0000 (10:11 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 25 Jun 2009 10:11:37 +0000 (10:11 +0000)
* 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.

21 files changed:
source/blender/python/generic/Geometry.c
source/blender/python/generic/Mathutils.c
source/blender/python/generic/Mathutils.h
source/blender/python/generic/euler.c
source/blender/python/generic/euler.h
source/blender/python/generic/matrix.c
source/blender/python/generic/matrix.h
source/blender/python/generic/quat.c
source/blender/python/generic/quat.h
source/blender/python/generic/vector.c
source/blender/python/generic/vector.h
source/blender/python/intern/bpy_rna.c
source/gameengine/Expressions/KX_Python.h
source/gameengine/Expressions/PyObjectPlus.cpp
source/gameengine/Expressions/PyObjectPlus.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_ObjectActuator.cpp
source/gameengine/Ketsji/KX_ObjectActuator.h
source/gameengine/Ketsji/KX_PyMath.cpp
source/gameengine/Ketsji/KX_PyMath.h
source/gameengine/Ketsji/KX_PythonInitTypes.cpp

index ec76675f6522e1e93b6bfaa8a72639faba0e36f6..8a748241570f62bbdf6f760622d6998a88a8c73b 100644 (file)
@@ -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);
index cd9705236d7a162c0a3aa949d52718f7b7462936..d7330ac46c02d218b60bd3525a19ffa5e8f4b759 100644 (file)
@@ -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);
+}
+
index a89b779ecbb2c178f1844bebd92714c4041394d5..d234ebf1452a223a2fedb73a7d4d6d9c8a4edd35 100644 (file)
 #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 */
index e78a57393477f1bd9e1f8c9a3e62495be6de4254..eb9358774e156cee9042f6dc9dad8cb9f240b612 100644 (file)
@@ -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;
+}
index 3be629351cbff336453877ed02c53ab62725bd08..0bff6de6964e0ca59aed9ac9af6c97a3f333bc97 100644 (file)
@@ -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 */
index db5b4ab08bfaef761ee04d1699abb7e3f9bba34a..ef4f7280cdc5acec0967398ac3fbdbfd3fc2d2fa 100644 (file)
@@ -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){
index cc3928f163265d4c7ef5b0326201ebfe7663e0f0..4b07366896953a0d747a7fc6153d61223ba46bbb 100644 (file)
@@ -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
index 8a3ded80455e50ba4b7f941c11f29ebe7c210f65..b1e9f4a1d312760287a89aff6defc8493ad06460 100644 (file)
@@ -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;
+}
index ebbac26e39cb4034478587e2544b1165448694f0..2e74b5fa7f9d1c67ee19d281aa2a31b016431e0e 100644 (file)
@@ -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 */
index dea5bc93898379d54d933a5f2a3cdb2c179e0b81..d68d3f4137074cfab1bcaa40e84b9c37e0d26ada 100644 (file)
@@ -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;
index 82dbf13b9aa222b580f21a311caeae5ae92812aa..f519b2808cbf94e8af540aa2fcec11a5f05abbcd 100644 (file)
@@ -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*/
index 3cef6e148616402479cec0b8afd59ed49245a144..0b8a7df1ae128a3f2c17b1787cc27b975236c036 100644 (file)
@@ -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
        
index b8006fdf0ed7da83ae242fb23bda882b0a4d5721..61f7ef050423915a74bf37da0356052aaac891ae 100644 (file)
@@ -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
index defb6853e67f2e21b19501aa9b29a3eb0649033d..2d4cc612aef2e5db90b84001f90b9b1c278fd166 100644 (file)
@@ -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:
                        {
index 96c75b710a3c3b5f37763a83f8ae8f3d17d7f558..3b5eebe9893d3cc42c786996f044557b7fb6202b 100644 (file)
 #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
index a3b2ba79e11c0654238c97647e0e939328406f2c..577f767b47523e77d3e7307c9b3c6a9e955fbc4b 100644 (file)
@@ -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;
index eaae04d406d4c4029c39e171deaff685cef3b2a6..62e61667c561cc15eeea5dae7f743f4aac33741d 100644 (file)
@@ -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);
index f9bd2a0c74806a123d3a289fbe7c91e883c0016c..6ca442b2ec2cbb5460f59f6e25e1e18cadee01b9 100644 (file)
 #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)
        {
index 051d7ae7dbab2fd0fc8aafe42ea18871a7375d30..ee9fed5d30a4493a37f4d9e6664194869517726b 100644 (file)
 #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]));
index a7ce4bc6930a57cb0c9a4d00124603b721651a30..90a13425aa04a45ae6dcfb9fc82df3e2923193a4 100644 (file)
 #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
index 05cb818fdd983d3310dc9e27246c84d37be709d5..d5d0fe3123cd4a39013645df5c5e11765fd9bbd2 100644 (file)
@@ -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