PyAPI RNA/BGE

* all mathutils types now have optional callbacks
* PyRNA returns mathutils quat and euler types automatically when they have the rotation subtype.
* PyRNA, reuse the BPy_StructRNA PyObject rather name making a new one for each function returned.
* use more arithb.c functions for Mathutils quaternion type (less inline cruft).
* BGE Mathutils integration mostly finished- KX_PyMath now converts to Mathutils types rather then lists.
* make all mathutils types share the same header so they can share a number of functions - dealloc, getWrapped, getOwner.
This commit is contained in:
2009-06-25 10:11:37 +00:00
parent 7a357cba39
commit d428ba1de8
21 changed files with 714 additions and 611 deletions

View File

@@ -165,7 +165,7 @@ static PyObject *M_Geometry_PolyFill( PyObject * self, PyObject * polyLineSeq )
polyVec= PySequence_GetItem( polyLine, index ); polyVec= PySequence_GetItem( polyLine, index );
if(VectorObject_Check(polyVec)) { if(VectorObject_Check(polyVec)) {
if(!Vector_ReadCallback((VectorObject *)polyVec)) if(!BaseMath_ReadCallback((VectorObject *)polyVec))
ls_error= 1; ls_error= 1;
fp[0] = ((VectorObject *)polyVec)->vec[0]; fp[0] = ((VectorObject *)polyVec)->vec[0];
@@ -238,7 +238,7 @@ static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args )
return NULL; 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; return NULL;
a1x= line_a1->vec[0]; a1x= line_a1->vec[0];
@@ -338,7 +338,7 @@ static PyObject *M_Geometry_ClosestPointOnLine( PyObject * self, PyObject * args
return NULL; 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; return NULL;
/* accept 2d verts */ /* accept 2d verts */
@@ -374,7 +374,7 @@ static PyObject *M_Geometry_PointInTriangle2D( PyObject * self, PyObject * args
return NULL; 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 NULL;
return PyLong_FromLong(IsectPT2Df(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec)); 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; 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 NULL;
return PyLong_FromLong(IsectPQ2Df(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec)); 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; 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; return NULL;
dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size); dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);

View File

@@ -155,10 +155,13 @@ PyObject *quat_rotation(PyObject *arg1, PyObject *arg2)
if(QuaternionObject_Check(arg1)){ if(QuaternionObject_Check(arg1)){
quat = (QuaternionObject*)arg1; quat = (QuaternionObject*)arg1;
if(!BaseMath_ReadCallback(quat))
return NULL;
if(VectorObject_Check(arg2)){ if(VectorObject_Check(arg2)){
vec = (VectorObject*)arg2; vec = (VectorObject*)arg2;
if(!Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(vec))
return NULL; return NULL;
rot[0] = quat->quat[0]*quat->quat[0]*vec->vec[0] + 2*quat->quat[2]*quat->quat[0]*vec->vec[2] - 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)){ }else if(VectorObject_Check(arg1)){
vec = (VectorObject*)arg1; vec = (VectorObject*)arg1;
if(!Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(vec))
return NULL; return NULL;
if(QuaternionObject_Check(arg2)){ if(QuaternionObject_Check(arg2)){
quat = (QuaternionObject*)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] - 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[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] - 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) if(vec1->size != vec2->size)
goto AttributeError1; //bad sizes goto AttributeError1; //bad sizes
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
return NULL; return NULL;
//since size is the same.... //since size is the same....
@@ -296,7 +302,7 @@ static PyObject *M_Mathutils_MidpointVecs(PyObject * self, PyObject * args)
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
return NULL; return NULL;
for(x = 0; x < vec1->size; x++) { for(x = 0; x < vec1->size; x++) {
@@ -322,7 +328,7 @@ static PyObject *M_Mathutils_ProjectVecs(PyObject * self, PyObject * args)
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
return NULL; return NULL;
@@ -389,7 +395,7 @@ static PyObject *M_Mathutils_RotationMatrix(PyObject * self, PyObject * args)
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(vec))
return NULL; return NULL;
} }
@@ -492,7 +498,7 @@ static PyObject *M_Mathutils_TranslationMatrix(PyObject * self, VectorObject * v
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(vec))
return NULL; return NULL;
//create a identity matrix and add translation //create a identity matrix and add translation
@@ -528,7 +534,7 @@ static PyObject *M_Mathutils_ScaleMatrix(PyObject * self, PyObject * args)
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(vec))
return NULL; return NULL;
} }
@@ -607,7 +613,7 @@ static PyObject *M_Mathutils_OrthoProjectionMatrix(PyObject * self, PyObject * a
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(vec))
return NULL; return NULL;
} }
@@ -766,6 +772,10 @@ static PyObject *M_Mathutils_DifferenceQuats(PyObject * self, PyObject * args)
PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types"); PyErr_SetString(PyExc_TypeError, "Mathutils.DifferenceQuats(): expected Quaternion types");
return NULL; return NULL;
} }
if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
return NULL;
tempQuat[0] = quatU->quat[0]; tempQuat[0] = quatU->quat[0];
tempQuat[1] = -quatU->quat[1]; tempQuat[1] = -quatU->quat[1];
tempQuat[2] = -quatU->quat[2]; 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"); PyErr_SetString(PyExc_TypeError, "Mathutils.Slerp(): expected Quaternion types and float");
return NULL; return NULL;
} }
if(!BaseMath_ReadCallback(quatU) || !BaseMath_ReadCallback(quatV))
return NULL;
if(param > 1.0f || param < 0.0f) { if(param > 1.0f || param < 0.0f) {
PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0"); PyErr_SetString(PyExc_AttributeError, "Mathutils.Slerp(): interpolation factor must be between 0.0 and 1.0");
return NULL; return NULL;
@@ -856,7 +870,7 @@ static PyObject *M_Mathutils_Intersect( PyObject * self, PyObject * args )
return NULL; 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; return NULL;
VECCOPY(v1, vec1->vec); VECCOPY(v1, vec1->vec);
@@ -928,7 +942,7 @@ static PyObject *M_Mathutils_LineIntersect( PyObject * self, PyObject * args )
return NULL; 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; return NULL;
if( vec1->size == 3 || vec1->size == 2) { if( vec1->size == 3 || vec1->size == 2) {
@@ -1002,7 +1016,7 @@ static PyObject *M_Mathutils_QuadNormal( PyObject * self, PyObject * args )
return NULL; 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; return NULL;
VECCOPY(v1, vec1->vec); VECCOPY(v1, vec1->vec);
@@ -1050,7 +1064,7 @@ static PyObject *M_Mathutils_TriangleNormal( PyObject * self, PyObject * args )
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
return NULL; return NULL;
VECCOPY(v1, vec1->vec); VECCOPY(v1, vec1->vec);
@@ -1085,7 +1099,7 @@ static PyObject *M_Mathutils_TriangleArea( PyObject * self, PyObject * args )
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2) || !Vector_ReadCallback(vec3)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2) || !BaseMath_ReadCallback(vec3))
return NULL; return NULL;
if (vec1->size == 3) { if (vec1->size == 3) {
@@ -1167,75 +1181,66 @@ int Mathutils_RegisterCallback(Mathutils_Callback *cb)
} }
/* use macros to check for NULL */ /* use macros to check for NULL */
int _Vector_ReadCallback(VectorObject *self) int _BaseMathObject_ReadCallback(BaseMathObject *self)
{ {
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; 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; return 1;
}
else { PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); return 0;
return 0;
}
} }
int _Vector_WriteCallback(VectorObject *self) int _BaseMathObject_WriteCallback(BaseMathObject *self)
{ {
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; 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; return 1;
}
else { PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); return 0;
return 0;
}
} }
int _Vector_ReadIndexCallback(VectorObject *self, int index) int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
{ {
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; 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; return 1;
}
else { PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); return 0;
return 0;
}
} }
int _Vector_WriteIndexCallback(VectorObject *self, int index) int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
{ {
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; 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; return 1;
}
else { PyErr_Format(PyExc_SystemError, "%s user has become invalid", Py_TYPE(self)->tp_name);
PyErr_SetString(PyExc_SystemError, "Vector user has become invalid"); return 0;
return 0;
}
} }
/* matrix callbacks */ /* BaseMathObject generic functions for all mathutils types */
int _Matrix_ReadCallback(MatrixObject *self) PyObject *BaseMathObject_getOwner( BaseMathObject * self, void *type )
{ {
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; PyObject *ret= self->cb_user ? self->cb_user : Py_None;
if(cb->get(self->cb_user, self->cb_subtype, self->contigPtr)) { Py_INCREF(ret);
return 1; return ret;
}
else {
PyErr_SetString(PyExc_SystemError, "Matrix user has become invalid");
return 0;
}
} }
int _Matrix_WriteCallback(MatrixObject *self) PyObject *BaseMathObject_getWrapped( BaseMathObject *self, void *type )
{ {
Mathutils_Callback *cb= mathutils_callbacks[self->cb_type]; PyBool_FromLong((self->wrapped == Py_WRAP) ? 1:0);
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;
}
} }
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);
}

View File

@@ -38,6 +38,24 @@
#include "quat.h" #include "quat.h"
#include "euler.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 *Mathutils_Init( const char * from );
PyObject *quat_rotation(PyObject *arg1, PyObject *arg2); PyObject *quat_rotation(PyObject *arg1, PyObject *arg2);
@@ -75,22 +93,15 @@ struct Mathutils_Callback {
int Mathutils_RegisterCallback(Mathutils_Callback *cb); int Mathutils_RegisterCallback(Mathutils_Callback *cb);
int _Vector_ReadCallback(VectorObject *self); int _BaseMathObject_ReadCallback(BaseMathObject *self);
int _Vector_WriteCallback(VectorObject *self); int _BaseMathObject_WriteCallback(BaseMathObject *self);
int _Vector_ReadIndexCallback(VectorObject *self, int index); int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index);
int _Vector_WriteIndexCallback(VectorObject *self, int index); int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index);
/* since this is called so often avoid where possible */ /* since this is called so often avoid where possible */
#define Vector_ReadCallback(_self) (((_self)->cb_user ? _Vector_ReadCallback(_self):1)) #define BaseMath_ReadCallback(_self) (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):1))
#define Vector_WriteCallback(_self) (((_self)->cb_user ?_Vector_WriteCallback(_self):1)) #define BaseMath_WriteCallback(_self) (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self):1))
#define Vector_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _Vector_ReadIndexCallback(_self, _index):1)) #define BaseMath_ReadIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index):1))
#define Vector_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _Vector_WriteIndexCallback(_self, _index):1)) #define BaseMath_WriteIndexCallback(_self, _index) (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_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))
#endif /* EXPP_Mathutils_H */ #endif /* EXPP_Mathutils_H */

View File

@@ -123,6 +123,9 @@ static PyObject *Euler_ToQuat(EulerObject * self)
float eul[3], quat[4]; float eul[3], quat[4];
int x; int x;
if(!BaseMath_ReadCallback(self))
return NULL;
for(x = 0; x < 3; x++) { for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180); 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}; float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
int x; int x;
if(!BaseMath_ReadCallback(self))
return NULL;
for(x = 0; x < 3; x++) { for(x = 0; x < 3; x++) {
eul[x] = self->eul[x] * ((float)Py_PI / 180); 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 piO2 = Py_PI / 2.0f;
double Opi2 = 1.0f / pi2; double Opi2 = 1.0f / pi2;
if(!BaseMath_ReadCallback(self))
return NULL;
//radians //radians
heading = self->eul[0] * (float)Py_PI / 180; heading = self->eul[0] * (float)Py_PI / 180;
pitch = self->eul[1] * (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[1] = (float)(pitch * 180 / (float)Py_PI);
self->eul[2] = (float)(bank * 180 / (float)Py_PI); self->eul[2] = (float)(bank * 180 / (float)Py_PI);
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
@@ -202,6 +212,7 @@ static PyObject *Euler_Zero(EulerObject * self)
self->eul[1] = 0.0; self->eul[1] = 0.0;
self->eul[2] = 0.0; self->eul[2] = 0.0;
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
@@ -223,6 +234,9 @@ static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
return NULL; return NULL;
} }
if(!BaseMath_ReadCallback(self))
return NULL;
//covert to radians //covert to radians
angle *= ((float)Py_PI / 180); angle *= ((float)Py_PI / 180);
for(x = 0; x < 3; x++) { 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); self->eul[x] *= (180 / (float)Py_PI);
} }
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
@@ -248,6 +263,9 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
return NULL; return NULL;
} }
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
//covert to radians //covert to radians
for(x = 0; x < 3; x++) { for(x = 0; x < 3; x++) {
self->eul[x] = self->eul[x] * ((float)Py_PI / 180); 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); self->eul[x] *= (180 / (float)Py_PI);
} }
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
@@ -267,26 +286,21 @@ static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
// return a copy of the euler // return a copy of the euler
static PyObject *Euler_copy(EulerObject * self, PyObject *args) static PyObject *Euler_copy(EulerObject * self, PyObject *args)
{ {
if(!BaseMath_ReadCallback(self))
return NULL;
return newEulerObject(self->eul, Py_NEW); return newEulerObject(self->eul, Py_NEW);
} }
//----------------------------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);
}
//----------------------------print object (internal)-------------- //----------------------------print object (internal)--------------
//print the object to screen //print the object to screen
static PyObject *Euler_repr(EulerObject * self) static PyObject *Euler_repr(EulerObject * self)
{ {
char str[64]; char str[64];
if(!BaseMath_ReadCallback(self))
return NULL;
sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]); sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
return PyUnicode_FromString(str); return PyUnicode_FromString(str);
} }
@@ -297,7 +311,18 @@ static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int compar
EulerObject *eulA = NULL, *eulB = NULL; EulerObject *eulA = NULL, *eulB = NULL;
int result = 0; 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){ if (comparison_type == Py_NE){
Py_RETURN_TRUE; Py_RETURN_TRUE;
}else{ }else{
@@ -342,13 +367,16 @@ static int Euler_len(EulerObject * self)
//sequence accessor (get) //sequence accessor (get)
static PyObject *Euler_item(EulerObject * self, int i) static PyObject *Euler_item(EulerObject * self, int i)
{ {
if(i<0) if(i<0) i= 3-i;
i= 3-i;
if(i < 0 || i >= 3) { if(i < 0 || i >= 3) {
PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range"); PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
return NULL; return NULL;
} }
if(!BaseMath_ReadIndexCallback(self, i))
return NULL;
return PyFloat_FromDouble(self->eul[i]); return PyFloat_FromDouble(self->eul[i]);
} }
@@ -363,8 +391,7 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
return -1; return -1;
} }
if(i<0) if(i<0) i= 3-i;
i= 3-i;
if(i < 0 || i >= 3){ if(i < 0 || i >= 3){
PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n"); 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; self->eul[i] = f;
if(!BaseMath_WriteIndexCallback(self, i))
return -1;
return 0; return 0;
} }
//----------------------------object[z:y]------------------------ //----------------------------object[z:y]------------------------
@@ -381,6 +412,9 @@ static PyObject *Euler_slice(EulerObject * self, int begin, int end)
PyObject *list = NULL; PyObject *list = NULL;
int count; int count;
if(!BaseMath_ReadCallback(self))
return NULL;
CLAMP(begin, 0, 3); CLAMP(begin, 0, 3);
if (end<0) end= 4+end; if (end<0) end= 4+end;
CLAMP(end, 0, 3); CLAMP(end, 0, 3);
@@ -401,7 +435,10 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end,
{ {
int i, y, size = 0; int i, y, size = 0;
float eul[3]; float eul[3];
PyObject *e, *f; PyObject *e;
if(!BaseMath_ReadCallback(self))
return NULL;
CLAMP(begin, 0, 3); CLAMP(begin, 0, 3);
if (end<0) end= 4+end; if (end<0) end= 4+end;
@@ -421,21 +458,20 @@ static int Euler_ass_slice(EulerObject * self, int begin, int end,
return -1; return -1;
} }
f = PyNumber_Float(e); eul[i] = (float)PyFloat_AsDouble(e);
if(f == NULL) { // parsed item not a number Py_DECREF(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"); PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
return -1; return -1;
} }
eul[i] = (float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
Py_DECREF(e);
} }
//parsed well - now set in vector //parsed well - now set in vector
for(y = 0; y < 3; y++){ for(y = 0; y < 3; y++){
self->eul[begin + y] = eul[y]; self->eul[begin + y] = eul[y];
} }
BaseMath_WriteCallback(self);
return 0; return 0;
} }
//-----------------PROTCOL DECLARATIONS-------------------------- //-----------------PROTCOL DECLARATIONS--------------------------
@@ -450,79 +486,30 @@ static PySequenceMethods Euler_SeqMethods = {
}; };
/* /*
* vector axis, vector.x/y/z/w * vector axis, vector.x/y/z/w
*/ */
static PyObject *Euler_getAxis( EulerObject * self, void *type ) static PyObject *Euler_getAxis( EulerObject * self, void *type )
{ {
switch( (long)type ) { return Euler_item(self, GET_INT_FROM_POINTER(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;
} }
static int Euler_setAxis( EulerObject * self, PyObject * value, void * type ) static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
{ {
float param= (float)PyFloat_AsDouble( value ); return Euler_ass_item(self, GET_INT_FROM_POINTER(type), 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;
}
/*****************************************************************************/ /*****************************************************************************/
/* Python attributes get/set structure: */ /* Python attributes get/set structure: */
/*****************************************************************************/ /*****************************************************************************/
static PyGetSetDef Euler_getseters[] = { static PyGetSetDef Euler_getseters[] = {
{"x", {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis", (void *)0},
(getter)Euler_getAxis, (setter)Euler_setAxis, {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis", (void *)1},
"Euler X axis", {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis", (void *)2},
(void *)'X'},
{"y", {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "True when this wraps blenders internal data", NULL},
(getter)Euler_getAxis, (setter)Euler_setAxis, {"__owner__", (getter)BaseMathObject_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL},
"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},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */ {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
}; };
@@ -538,7 +525,7 @@ PyTypeObject euler_Type = {
"euler", //tp_name "euler", //tp_name
sizeof(EulerObject), //tp_basicsize sizeof(EulerObject), //tp_basicsize
0, //tp_itemsize 0, //tp_itemsize
(destructor)Euler_dealloc, //tp_dealloc (destructor)BaseMathObject_dealloc, //tp_dealloc
0, //tp_print 0, //tp_print
0, //tp_getattr 0, //tp_getattr
0, //tp_setattr 0, //tp_setattr
@@ -593,24 +580,22 @@ PyObject *newEulerObject(float *eul, int type)
int x; int x;
self = PyObject_NEW(EulerObject, &euler_Type); 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){ if(type == Py_WRAP){
self->data.blend_data = eul; self->eul = eul;
self->eul = self->data.blend_data;
self->wrapped = Py_WRAP; self->wrapped = Py_WRAP;
}else if (type == Py_NEW){ }else if (type == Py_NEW){
self->data.py_data = PyMem_Malloc(3 * sizeof(float)); self->eul = PyMem_Malloc(3 * sizeof(float));
self->eul = self->data.py_data;
if(!eul) { //new empty if(!eul) { //new empty
for(x = 0; x < 3; x++) { for(x = 0; x < 3; x++) {
self->eul[x] = 0.0f; self->eul[x] = 0.0f;
} }
}else{ }else{
for(x = 0; x < 3; x++){ VECCOPY(self->eul, eul);
self->eul[x] = eul[x];
}
} }
self->wrapped = Py_NEW; self->wrapped = Py_NEW;
}else{ //bad type }else{ //bad type
@@ -618,3 +603,16 @@ PyObject *newEulerObject(float *eul, int type)
} }
return (PyObject *)self; 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;
}

View File

@@ -40,12 +40,13 @@ extern PyTypeObject euler_Type;
typedef struct { typedef struct {
PyObject_VAR_HEAD PyObject_VAR_HEAD
struct{ float *eul; /*1D array of data */
float *py_data; //python managed PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
float *blend_data; //blender managed unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
}data; unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
float *eul; //1D array of data (alias) unsigned char wrapped; /* wrapped data type? */
int wrapped; //is wrapped data? /* end BaseMathObject */
} EulerObject; } EulerObject;
/*struct data contains a pointer to the actual data that the /*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 //prototypes
PyObject *newEulerObject( float *eul, int type ); PyObject *newEulerObject( float *eul, int type );
PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* EXPP_euler_h */ #endif /* EXPP_euler_h */

View File

@@ -39,13 +39,13 @@ int mathutils_matrix_vector_cb_index= -1;
static int mathutils_matrix_vector_check(MatrixObject *self) 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) static int mathutils_matrix_vector_get(MatrixObject *self, int subtype, float *vec_from)
{ {
int i; int i;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return 0; return 0;
for(i=0; i<self->colSize; i++) 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) static int mathutils_matrix_vector_set(MatrixObject *self, int subtype, float *vec_to)
{ {
int i; int i;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return 0; return 0;
for(i=0; i<self->colSize; i++) for(i=0; i<self->colSize; i++)
self->matrix[subtype][i]= vec_to[i]; self->matrix[subtype][i]= vec_to[i];
Matrix_WriteCallback(self); BaseMath_WriteCallback(self);
return 1; return 1;
} }
static int mathutils_matrix_vector_get_index(MatrixObject *self, int subtype, float *vec_from, int index) 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; return 0;
vec_from[index]= self->matrix[subtype][index]; 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) 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; return 0;
self->matrix[subtype][index]= vec_to[index]; self->matrix[subtype][index]= vec_to[index];
Matrix_WriteCallback(self); BaseMath_WriteCallback(self);
return 1; return 1;
} }
@@ -164,7 +164,7 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
argObject = PyTuple_GET_ITEM(args, 0); argObject = PyTuple_GET_ITEM(args, 0);
if(MatrixObject_Check(argObject)){ if(MatrixObject_Check(argObject)){
mat = (MatrixObject*)argObject; mat = (MatrixObject*)argObject;
if(!Matrix_ReadCallback(mat)) if(!BaseMath_ReadCallback(mat))
return NULL; return NULL;
argSize = mat->rowSize; //rows argSize = mat->rowSize; //rows
@@ -225,7 +225,7 @@ static PyObject *Matrix_toQuat(MatrixObject * self)
{ {
float quat[4]; float quat[4];
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/ /*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; EulerObject *eul_compat = NULL;
int x; int x;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat)) if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
return NULL; return NULL;
if(eul_compat) { if(eul_compat) {
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
for(x = 0; x < 3; x++) { for(x = 0; x < 3; x++) {
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180); eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180);
} }
@@ -343,7 +346,7 @@ PyObject *Matrix_TranslationPart(MatrixObject * self)
{ {
float vec[4]; float vec[4];
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
if(self->colSize < 3 || self->rowSize < 4){ 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, 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}; 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; return NULL;
if(self->colSize < 3 || self->rowSize < 3){ if(self->colSize < 3 || self->rowSize < 3){
@@ -389,7 +392,7 @@ PyObject *Matrix_scalePart(MatrixObject * self)
float scale[3], rot[3]; float scale[3], rot[3];
float mat[3][3], imat[3][3], tmat[3][3]; float mat[3][3], imat[3][3], tmat[3][3];
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
/*must be 3-4 cols, 3-4 rows, square matrix*/ /*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, 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}; 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; return NULL;
if(self->rowSize != self->colSize){ if(self->rowSize != self->colSize){
@@ -465,7 +468,7 @@ PyObject *Matrix_Invert(MatrixObject * self)
return NULL; return NULL;
} }
Matrix_WriteCallback(self); BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
@@ -476,7 +479,7 @@ PyObject *Matrix_Determinant(MatrixObject * self)
{ {
float det = 0.0f; float det = 0.0f;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
if(self->rowSize != self->colSize){ if(self->rowSize != self->colSize){
@@ -504,7 +507,7 @@ PyObject *Matrix_Transpose(MatrixObject * self)
{ {
float t = 0.0f; float t = 0.0f;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
if(self->rowSize != self->colSize){ if(self->rowSize != self->colSize){
@@ -522,7 +525,7 @@ PyObject *Matrix_Transpose(MatrixObject * self)
Mat4Transp((float (*)[4])*self->matrix); Mat4Transp((float (*)[4])*self->matrix);
} }
Matrix_WriteCallback(self); BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject *)self; return (PyObject *)self;
} }
@@ -539,7 +542,7 @@ PyObject *Matrix_Zero(MatrixObject * self)
} }
} }
if(!Matrix_WriteCallback(self)) if(!BaseMath_WriteCallback(self))
return NULL; return NULL;
Py_INCREF(self); Py_INCREF(self);
@@ -548,7 +551,7 @@ PyObject *Matrix_Zero(MatrixObject * self)
/*---------------------------Matrix.identity(() ------------------*/ /*---------------------------Matrix.identity(() ------------------*/
PyObject *Matrix_Identity(MatrixObject * self) PyObject *Matrix_Identity(MatrixObject * self)
{ {
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
if(self->rowSize != self->colSize){ if(self->rowSize != self->colSize){
@@ -567,7 +570,7 @@ PyObject *Matrix_Identity(MatrixObject * self)
Mat4One((float (*)[4]) *self->matrix); Mat4One((float (*)[4]) *self->matrix);
} }
if(!Matrix_WriteCallback(self)) if(!BaseMath_WriteCallback(self))
return NULL; return NULL;
Py_INCREF(self); Py_INCREF(self);
@@ -577,25 +580,12 @@ PyObject *Matrix_Identity(MatrixObject * self)
/*---------------------------Matrix.inverted() ------------------*/ /*---------------------------Matrix.inverted() ------------------*/
PyObject *Matrix_copy(MatrixObject * self) PyObject *Matrix_copy(MatrixObject * self)
{ {
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
return (PyObject*)(MatrixObject*)newMatrixObject((float (*))*self->matrix, self->rowSize, self->colSize, Py_NEW); 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 object (internal)-------------*/
/*print the object to screen*/ /*print the object to screen*/
static PyObject *Matrix_repr(MatrixObject * self) static PyObject *Matrix_repr(MatrixObject * self)
@@ -603,7 +593,7 @@ static PyObject *Matrix_repr(MatrixObject * self)
int x, y; int x, y;
char buffer[48], str[1024]; char buffer[48], str[1024];
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
BLI_strncpy(str,"",1024); BLI_strncpy(str,"",1024);
@@ -642,7 +632,7 @@ static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int compa
matA = (MatrixObject*)objectA; matA = (MatrixObject*)objectA;
matB = (MatrixObject*)objectB; matB = (MatrixObject*)objectB;
if(!Matrix_ReadCallback(matA) || !Matrix_ReadCallback(matB)) if(!BaseMath_ReadCallback(matA) || !BaseMath_ReadCallback(matB))
return NULL; return NULL;
if (matA->colSize != matB->colSize || matA->rowSize != matB->rowSize){ 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*/ the wrapped vector gives direct access to the matrix data*/
static PyObject *Matrix_item(MatrixObject * self, int i) static PyObject *Matrix_item(MatrixObject * self, int i)
{ {
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
if(i < 0 || i >= self->rowSize) { if(i < 0 || i >= self->rowSize) {
@@ -709,7 +699,7 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
float vec[4]; float vec[4];
PyObject *m, *f; PyObject *m, *f;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return -1; return -1;
if(i >= self->rowSize || i < 0){ 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]; self->matrix[i][y] = vec[y];
} }
Matrix_WriteCallback(self); BaseMath_WriteCallback(self);
return 0; return 0;
}else{ }else{
PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: expects a sequence of column size\n"); 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; PyObject *list = NULL;
int count; int count;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
CLAMP(begin, 0, self->rowSize); CLAMP(begin, 0, self->rowSize);
@@ -787,7 +777,7 @@ static int Matrix_ass_slice(MatrixObject * self, int begin, int end,
PyObject *subseq; PyObject *subseq;
PyObject *m; PyObject *m;
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return -1; return -1;
CLAMP(begin, 0, self->rowSize); 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]; self->matrix[begin + (int)floor(x / self->colSize)][x % self->colSize] = mat[x];
} }
Matrix_WriteCallback(self); BaseMath_WriteCallback(self);
return 0; return 0;
}else{ }else{
PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: illegal argument type for built-in operation\n"); 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; return NULL;
} }
if(!Matrix_ReadCallback(mat1) || !Matrix_ReadCallback(mat2)) if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
return NULL; return NULL;
if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){ if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){
@@ -905,7 +895,7 @@ static PyObject *Matrix_sub(PyObject * m1, PyObject * m2)
return NULL; return NULL;
} }
if(!Matrix_ReadCallback(mat1) || !Matrix_ReadCallback(mat2)) if(!BaseMath_ReadCallback(mat1) || !BaseMath_ReadCallback(mat2))
return NULL; return NULL;
if(mat1->rowSize != mat2->rowSize || mat1->colSize != mat2->colSize){ 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)) { if(MatrixObject_Check(m1)) {
mat1 = (MatrixObject*)m1; mat1 = (MatrixObject*)m1;
if(!Matrix_ReadCallback(mat1)) if(!BaseMath_ReadCallback(mat1))
return NULL; return NULL;
} }
if(MatrixObject_Check(m2)) { if(MatrixObject_Check(m2)) {
mat2 = (MatrixObject*)m2; mat2 = (MatrixObject*)m2;
if(!Matrix_ReadCallback(mat2)) if(!BaseMath_ReadCallback(mat2))
return NULL; return NULL;
} }
@@ -1000,7 +990,7 @@ static PyObject *Matrix_mul(PyObject * m1, PyObject * m2)
} }
static PyObject* Matrix_inv(MatrixObject *self) static PyObject* Matrix_inv(MatrixObject *self)
{ {
if(!Matrix_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
return Matrix_Invert(self); return Matrix_Invert(self);
@@ -1052,33 +1042,15 @@ static PyObject *Matrix_getColSize( MatrixObject * self, void *type )
return PyLong_FromLong((long) self->colSize); 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: */ /* Python attributes get/set structure: */
/*****************************************************************************/ /*****************************************************************************/
static PyGetSetDef Matrix_getseters[] = { static PyGetSetDef Matrix_getseters[] = {
{"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL}, {"rowSize", (getter)Matrix_getRowSize, (setter)NULL, "", NULL},
{"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL}, {"colSize", (getter)Matrix_getColSize, (setter)NULL, "", NULL},
{"wrapped", (getter)Matrix_getWrapped, (setter)NULL, "", NULL}, {"wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, "", NULL},
{"__owner__",(getter)Matrix_getOwner, (setter)NULL, "Read only owner for vectors that depend on another object", NULL}, {"__owner__",(getter)BaseMathObject_getOwner, (setter)NULL, "",
NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */ {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
}; };
@@ -1094,7 +1066,7 @@ PyTypeObject matrix_Type = {
"matrix", /*tp_name*/ "matrix", /*tp_name*/
sizeof(MatrixObject), /*tp_basicsize*/ sizeof(MatrixObject), /*tp_basicsize*/
0, /*tp_itemsize*/ 0, /*tp_itemsize*/
(destructor)Matrix_dealloc, /*tp_dealloc*/ (destructor)BaseMathObject_dealloc, /*tp_dealloc*/
0, /*tp_print*/ 0, /*tp_print*/
0, /*tp_getattr*/ 0, /*tp_getattr*/
0, /*tp_setattr*/ 0, /*tp_setattr*/
@@ -1245,7 +1217,7 @@ static PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject*
double dot = 0.0f; double dot = 0.0f;
int x, y, z = 0; int x, y, z = 0;
if(!Matrix_ReadCallback(mat) || !Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(mat) || !BaseMath_ReadCallback(vec))
return NULL; return NULL;
if(mat->rowSize != vec->size){ if(mat->rowSize != vec->size){

View File

@@ -37,16 +37,19 @@ extern PyTypeObject matrix_Type;
#define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type) #define MatrixObject_Check(v) ((v)->ob_type == &matrix_Type)
typedef float **ptRow; typedef float **ptRow;
typedef struct _Matrix { typedef struct _Matrix { /* keep aligned with BaseMathObject in Mathutils.h */
PyObject_VAR_HEAD PyObject_VAR_HEAD
ptRow matrix; /*ptr to the contigPtr (accessor)*/ float *contigPtr; /*1D array of data (alias)*/
float* contigPtr; /*1D array of data (alias)*/ PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
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?*/
unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */ 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; } MatrixObject;
/*struct data contains a pointer to the actual data that the /*struct data contains a pointer to the actual data that the

View File

@@ -78,7 +78,7 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
PyObject *listObject = NULL, *n, *q; PyObject *listObject = NULL, *n, *q;
int size, i; int size, i;
float quat[4], scalar; float quat[4], scalar;
double norm = 0.0f, angle = 0.0f; double angle = 0.0f;
size = PyTuple_GET_SIZE(args); size = PyTuple_GET_SIZE(args);
if (size == 1 || size == 2) { //seq? if (size == 1 || size == 2) { //seq?
@@ -152,27 +152,18 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw
} }
scalar = PyFloat_AsDouble(q); scalar = PyFloat_AsDouble(q);
Py_DECREF(q);
if (scalar==-1 && PyErr_Occurred()) { if (scalar==-1 && PyErr_Occurred()) {
Py_DECREF(q);
PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n"); PyErr_SetString(PyExc_TypeError, "Mathutils.Quaternion(): 4d numeric sequence expected or 3d vector and number\n");
return NULL; return NULL;
} }
quat[i] = scalar; 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); if(size == 3) //calculate the quat based on axis/angle
quat[3] =(float) (sin(angle/ 2.0f)) * quat[2]; AxisAngleToQuat(quat, quat, angle * (Py_PI / 180)); // TODO - 2.5 use radians, note using quat for src and target is ok here
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));
}
return newQuaternionObject(quat, Py_NEW); 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)) if(!PyArg_ParseTuple(args, "|O!:toEuler", &euler_Type, &eul_compat))
return NULL; return NULL;
if(!BaseMath_ReadCallback(self))
return NULL;
if(eul_compat) { if(eul_compat) {
float mat[3][3], eul_compatf[3]; float mat[3][3], eul_compatf[3];
if(!BaseMath_ReadCallback(eul_compat))
return NULL;
for(x = 0; x < 3; x++) { for(x = 0; x < 3; x++) {
eul_compatf[x] = eul_compat->eul[x] * ((float)Py_PI / 180); 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) 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}; 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); return newMatrixObject(mat, 3, 3, Py_NEW);
} }
@@ -230,6 +230,9 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va
return NULL; return NULL;
} }
if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL;
QuatMul(quat, self->quat, value->quat); QuatMul(quat, self->quat, value->quat);
return newQuaternionObject(quat, Py_NEW); return newQuaternionObject(quat, Py_NEW);
} }
@@ -238,25 +241,27 @@ static PyObject *Quaternion_Cross(QuaternionObject * self, QuaternionObject * va
//return the dot quat //return the dot quat
static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value) static PyObject *Quaternion_Dot(QuaternionObject * self, QuaternionObject * value)
{ {
int x;
double dot = 0.0;
if (!QuaternionObject_Check(value)) { if (!QuaternionObject_Check(value)) {
PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" ); PyErr_SetString( PyExc_TypeError, "quat.dot(value): expected a quaternion argument" );
return NULL; return NULL;
} }
for(x = 0; x < 4; x++) { if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
dot += self->quat[x] * value->quat[x]; return NULL;
}
return PyFloat_FromDouble(dot); return PyFloat_FromDouble(QuatDot(self->quat, value->quat));
} }
//----------------------------Quaternion.normalize()---------------- //----------------------------Quaternion.normalize()----------------
//normalize the axis of rotation of [theta,vector] //normalize the axis of rotation of [theta,vector]
static PyObject *Quaternion_Normalize(QuaternionObject * self) static PyObject *Quaternion_Normalize(QuaternionObject * self)
{ {
if(!BaseMath_ReadCallback(self))
return NULL;
NormalQuat(self->quat); NormalQuat(self->quat);
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;
} }
@@ -264,20 +269,12 @@ static PyObject *Quaternion_Normalize(QuaternionObject * self)
//invert the quat //invert the quat
static PyObject *Quaternion_Inverse(QuaternionObject * self) static PyObject *Quaternion_Inverse(QuaternionObject * self)
{ {
double mag = 0.0f; if(!BaseMath_ReadCallback(self))
int x; return NULL;
for(x = 1; x < 4; x++) { QuatInv(self->quat);
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);
}
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;
} }
@@ -285,11 +282,12 @@ static PyObject *Quaternion_Inverse(QuaternionObject * self)
//generate the identity quaternion //generate the identity quaternion
static PyObject *Quaternion_Identity(QuaternionObject * self) static PyObject *Quaternion_Identity(QuaternionObject * self)
{ {
self->quat[0] = 1.0; if(!BaseMath_ReadCallback(self))
self->quat[1] = 0.0; return NULL;
self->quat[2] = 0.0;
self->quat[3] = 0.0;
QuatOne(self->quat);
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;
} }
@@ -297,10 +295,12 @@ static PyObject *Quaternion_Identity(QuaternionObject * self)
//negate the quat //negate the quat
static PyObject *Quaternion_Negate(QuaternionObject * self) static PyObject *Quaternion_Negate(QuaternionObject * self)
{ {
int x; if(!BaseMath_ReadCallback(self))
for(x = 0; x < 4; x++) { return NULL;
self->quat[x] = -self->quat[x];
} QuatMulf(self->quat, -1.0f);
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;
} }
@@ -308,10 +308,12 @@ static PyObject *Quaternion_Negate(QuaternionObject * self)
//negate the vector part //negate the vector part
static PyObject *Quaternion_Conjugate(QuaternionObject * self) static PyObject *Quaternion_Conjugate(QuaternionObject * self)
{ {
int x; if(!BaseMath_ReadCallback(self))
for(x = 1; x < 4; x++) { return NULL;
self->quat[x] = -self->quat[x];
} QuatConj(self->quat);
BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;
} }
@@ -319,18 +321,10 @@ static PyObject *Quaternion_Conjugate(QuaternionObject * self)
//return a copy of the quat //return a copy of the quat
static PyObject *Quaternion_copy(QuaternionObject * self) static PyObject *Quaternion_copy(QuaternionObject * self)
{ {
return newQuaternionObject(self->quat, Py_NEW); if(!BaseMath_ReadCallback(self))
} return NULL;
//----------------------------dealloc()(internal) ------------------ return newQuaternionObject(self->quat, Py_NEW);
//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);
} }
//----------------------------print object (internal)-------------- //----------------------------print object (internal)--------------
@@ -338,6 +332,10 @@ static void Quaternion_dealloc(QuaternionObject * self)
static PyObject *Quaternion_repr(QuaternionObject * self) static PyObject *Quaternion_repr(QuaternionObject * self)
{ {
char str[64]; 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]); sprintf(str, "[%.6f, %.6f, %.6f, %.6f](quaternion)", self->quat[0], self->quat[1], self->quat[2], self->quat[3]);
return PyUnicode_FromString(str); return PyUnicode_FromString(str);
} }
@@ -348,15 +346,24 @@ static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int c
QuaternionObject *quatA = NULL, *quatB = NULL; QuaternionObject *quatA = NULL, *quatB = NULL;
int result = 0; 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){ if (comparison_type == Py_NE){
Py_RETURN_TRUE; Py_RETURN_TRUE;
}else{ }else{
Py_RETURN_FALSE; Py_RETURN_FALSE;
} }
} }
quatA = (QuaternionObject*)objectA;
quatB = (QuaternionObject*)objectB;
switch (comparison_type){ switch (comparison_type){
case Py_EQ: case Py_EQ:
@@ -393,10 +400,16 @@ static int Quaternion_len(QuaternionObject * self)
//sequence accessor (get) //sequence accessor (get)
static PyObject *Quaternion_item(QuaternionObject * self, int i) static PyObject *Quaternion_item(QuaternionObject * self, int i)
{ {
if(i<0) i= 4-i;
if(i < 0 || i >= 4) { if(i < 0 || i >= 4) {
PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n"); PyErr_SetString(PyExc_IndexError, "quaternion[attribute]: array index out of range\n");
return NULL; return NULL;
} }
if(!BaseMath_ReadIndexCallback(self, i))
return NULL;
return PyFloat_FromDouble(self->quat[i]); return PyFloat_FromDouble(self->quat[i]);
} }
@@ -404,21 +417,23 @@ static PyObject *Quaternion_item(QuaternionObject * self, int i)
//sequence accessor (set) //sequence accessor (set)
static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob) static int Quaternion_ass_item(QuaternionObject * self, int i, PyObject * ob)
{ {
PyObject *f = NULL; float scalar= (float)PyFloat_AsDouble(ob);
if(scalar==-1.0f && PyErr_Occurred()) { /* parsed item not a number */
f = PyNumber_Float(ob); PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number\n");
if(f == NULL) { // parsed item not a number
PyErr_SetString(PyExc_TypeError, "quaternion[attribute] = x: argument not a number\n");
return -1; return -1;
} }
if(i<0) i= 4-i;
if(i < 0 || i >= 4){ if(i < 0 || i >= 4){
Py_DECREF(f);
PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n"); PyErr_SetString(PyExc_IndexError, "quaternion[attribute] = x: array assignment index out of range\n");
return -1; return -1;
} }
self->quat[i] = (float)PyFloat_AS_DOUBLE(f); self->quat[i] = scalar;
Py_DECREF(f);
if(!BaseMath_WriteIndexCallback(self, i))
return -1;
return 0; return 0;
} }
//----------------------------object[z:y]------------------------ //----------------------------object[z:y]------------------------
@@ -428,6 +443,9 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
PyObject *list = NULL; PyObject *list = NULL;
int count; int count;
if(!BaseMath_ReadCallback(self))
return NULL;
CLAMP(begin, 0, 4); CLAMP(begin, 0, 4);
if (end<0) end= 5+end; if (end<0) end= 5+end;
CLAMP(end, 0, 4); CLAMP(end, 0, 4);
@@ -443,12 +461,14 @@ static PyObject *Quaternion_slice(QuaternionObject * self, int begin, int end)
} }
//----------------------------object[z:y]------------------------ //----------------------------object[z:y]------------------------
//sequence slice (set) //sequence slice (set)
static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end, PyObject * seq)
PyObject * seq)
{ {
int i, y, size = 0; int i, y, size = 0;
float quat[4]; float quat[4];
PyObject *q, *f; PyObject *q;
if(!BaseMath_ReadCallback(self))
return -1;
CLAMP(begin, 0, 4); CLAMP(begin, 0, 4);
if (end<0) end= 5+end; if (end<0) end= 5+end;
@@ -468,21 +488,19 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
return -1; return -1;
} }
f = PyNumber_Float(q); quat[i]= (float)PyFloat_AsDouble(q);
if(f == NULL) { // parsed item not a number Py_DECREF(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"); PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: sequence argument not a number\n");
return -1; return -1;
} }
quat[i] = (float)PyFloat_AS_DOUBLE(f);
Py_DECREF(f);
Py_DECREF(q);
} }
//parsed well - now set in vector //parsed well - now set in vector
for(y = 0; y < size; y++){ for(y = 0; y < size; y++)
self->quat[begin + y] = quat[y]; self->quat[begin + y] = quat[y];
}
BaseMath_WriteCallback(self);
return 0; return 0;
} }
//------------------------NUMERIC PROTOCOLS---------------------- //------------------------NUMERIC PROTOCOLS----------------------
@@ -490,7 +508,6 @@ static int Quaternion_ass_slice(QuaternionObject * self, int begin, int end,
//addition //addition
static PyObject *Quaternion_add(PyObject * q1, PyObject * q2) static PyObject *Quaternion_add(PyObject * q1, PyObject * q2)
{ {
int x;
float quat[4]; float quat[4];
QuaternionObject *quat1 = NULL, *quat2 = NULL; 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"); PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation....\n");
return NULL; return NULL;
} }
quat1 = (QuaternionObject*)q1; quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2; quat2 = (QuaternionObject*)q2;
for(x = 0; x < 4; x++) { if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
quat[x] = quat1->quat[x] + quat2->quat[x]; return NULL;
}
QuatAdd(quat, quat1->quat, quat2->quat, 1.0f);
return newQuaternionObject(quat, Py_NEW); return newQuaternionObject(quat, Py_NEW);
} }
//------------------------obj - obj------------------------------ //------------------------obj - obj------------------------------
@@ -524,6 +540,9 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
quat1 = (QuaternionObject*)q1; quat1 = (QuaternionObject*)q1;
quat2 = (QuaternionObject*)q2; quat2 = (QuaternionObject*)q2;
if(!BaseMath_ReadCallback(quat1) || !BaseMath_ReadCallback(quat2))
return NULL;
for(x = 0; x < 4; x++) { for(x = 0; x < 4; x++) {
quat[x] = quat1->quat[x] - quat2->quat[x]; quat[x] = quat1->quat[x] - quat2->quat[x];
} }
@@ -534,29 +553,31 @@ static PyObject *Quaternion_sub(PyObject * q1, PyObject * q2)
//mulplication //mulplication
static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2) static PyObject *Quaternion_mul(PyObject * q1, PyObject * q2)
{ {
int x;
float quat[4], scalar; float quat[4], scalar;
double dot = 0.0f;
QuaternionObject *quat1 = NULL, *quat2 = NULL; QuaternionObject *quat1 = NULL, *quat2 = NULL;
VectorObject *vec = NULL; VectorObject *vec = NULL;
quat1 = (QuaternionObject*)q1; if(QuaternionObject_Check(q1)) {
quat2 = (QuaternionObject*)q2; 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) */ if(quat1 && quat2) { /* QUAT*QUAT (dot product) */
for(x = 0; x < 4; x++) { return PyFloat_FromDouble(QuatDot(quat1->quat, quat2->quat));
dot += quat1->quat[x] * quat1->quat[x];
}
return PyFloat_FromDouble(dot);
} }
/* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */ /* the only case this can happen (for a supported type is "FLOAT*QUAT" ) */
if(!QuaternionObject_Check(q1)) { if(!QuaternionObject_Check(q1)) {
scalar= PyFloat_AsDouble(q1); scalar= PyFloat_AsDouble(q1);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */ if ((scalar == -1.0 && PyErr_Occurred())==0) { /* FLOAT*QUAT */
for(x = 0; x < 4; x++) { QUATCOPY(quat, quat2->quat);
quat[x] = quat2->quat[x] * scalar; QuatMulf(quat, scalar);
}
return newQuaternionObject(quat, Py_NEW); return newQuaternionObject(quat, Py_NEW);
} }
PyErr_SetString(PyExc_TypeError, "Quaternion multiplication: val * quat, val is not an acceptable type"); 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); scalar= PyFloat_AsDouble(q2);
if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */ if ((scalar == -1.0 && PyErr_Occurred())==0) { /* QUAT*FLOAT */
for(x = 0; x < 4; x++) { QUATCOPY(quat, quat1->quat);
quat[x] = quat1->quat[x] * scalar; QuatMulf(quat, scalar);
}
return newQuaternionObject(quat, Py_NEW); return newQuaternionObject(quat, Py_NEW);
} }
} }
@@ -625,63 +645,17 @@ static PyNumberMethods Quaternion_NumMethods = {
static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type ) static PyObject *Quaternion_getAxis( QuaternionObject * self, void *type )
{ {
switch( (long)type ) { return Quaternion_item(self, GET_INT_FROM_POINTER(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;
} }
static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type ) static int Quaternion_setAxis( QuaternionObject * self, PyObject * value, void * type )
{ {
float param= (float)PyFloat_AsDouble( value ); return Quaternion_ass_item(self, GET_INT_FROM_POINTER(type), 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;
} }
static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type ) static PyObject *Quaternion_getMagnitude( QuaternionObject * self, void *type )
{ {
double mag = 0.0; return PyFloat_FromDouble(sqrt(QuatDot(self->quat, self->quat)));
int i;
for(i = 0; i < 4; i++) {
mag += self->quat[i] * self->quat[i];
}
return PyFloat_FromDouble(sqrt(mag));
} }
static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type ) static PyObject *Quaternion_getAngle( QuaternionObject * self, void *type )
@@ -720,19 +694,19 @@ static PyGetSetDef Quaternion_getseters[] = {
{"w", {"w",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion W value", "Quaternion W value",
(void *)'W'}, (void *)0},
{"x", {"x",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion X axis", "Quaternion X axis",
(void *)'X'}, (void *)1},
{"y", {"y",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion Y axis", "Quaternion Y axis",
(void *)'Y'}, (void *)2},
{"z", {"z",
(getter)Quaternion_getAxis, (setter)Quaternion_setAxis, (getter)Quaternion_getAxis, (setter)Quaternion_setAxis,
"Quaternion Z axis", "Quaternion Z axis",
(void *)'Z'}, (void *)3},
{"magnitude", {"magnitude",
(getter)Quaternion_getMagnitude, (setter)NULL, (getter)Quaternion_getMagnitude, (setter)NULL,
"Size of the quaternion", "Size of the quaternion",
@@ -746,9 +720,14 @@ static PyGetSetDef Quaternion_getseters[] = {
"quaternion axis as a vector", "quaternion axis as a vector",
NULL}, NULL},
{"wrapped", {"wrapped",
(getter)Quaternion_getWrapped, (setter)NULL, (getter)BaseMathObject_getWrapped, (setter)NULL,
"True when this wraps blenders internal data", "True when this wraps blenders internal data",
NULL}, NULL},
{"__owner__",
(getter)BaseMathObject_getOwner, (setter)NULL,
"Read only owner for vectors that depend on another object",
NULL},
{NULL,NULL,NULL,NULL,NULL} /* Sentinel */ {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
}; };
@@ -765,7 +744,7 @@ PyTypeObject quaternion_Type = {
"quaternion", //tp_name "quaternion", //tp_name
sizeof(QuaternionObject), //tp_basicsize sizeof(QuaternionObject), //tp_basicsize
0, //tp_itemsize 0, //tp_itemsize
(destructor)Quaternion_dealloc, //tp_dealloc (destructor)BaseMathObject_dealloc, //tp_dealloc
0, //tp_print 0, //tp_print
0, //tp_getattr 0, //tp_getattr
0, //tp_setattr 0, //tp_setattr
@@ -817,26 +796,22 @@ PyTypeObject quaternion_Type = {
PyObject *newQuaternionObject(float *quat, int type) PyObject *newQuaternionObject(float *quat, int type)
{ {
QuaternionObject *self; QuaternionObject *self;
int x;
self = PyObject_NEW(QuaternionObject, &quaternion_Type); 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){ if(type == Py_WRAP){
self->data.blend_data = quat; self->quat = quat;
self->quat = self->data.blend_data;
self->wrapped = Py_WRAP; self->wrapped = Py_WRAP;
}else if (type == Py_NEW){ }else if (type == Py_NEW){
self->data.py_data = PyMem_Malloc(4 * sizeof(float)); self->quat = PyMem_Malloc(4 * sizeof(float));
self->quat = self->data.py_data;
if(!quat) { //new empty if(!quat) { //new empty
Quaternion_Identity(self); QuatOne(self->quat);
Py_DECREF(self);
}else{ }else{
for(x = 0; x < 4; x++){ QUATCOPY(self->quat, quat);
self->quat[x] = quat[x];
}
} }
self->wrapped = Py_NEW; self->wrapped = Py_NEW;
}else{ //bad type }else{ //bad type
@@ -844,3 +819,16 @@ PyObject *newQuaternionObject(float *quat, int type)
} }
return (PyObject *) self; 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;
}

View File

@@ -38,14 +38,15 @@ extern PyTypeObject quaternion_Type;
#define QuaternionObject_Check(v) (Py_TYPE(v) == &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 PyObject_VAR_HEAD
struct{ float *quat; /* 1D array of data (alias) */
float *py_data; //python managed PyObject *cb_user; /* if this vector references another object, otherwise NULL, *Note* this owns its reference */
float *blend_data; //blender managed unsigned char cb_type; /* which user funcs do we adhere to, RNA, GameObject, etc */
}data; unsigned char cb_subtype; /* subtype: location, rotation... to avoid defining many new functions for every attribute of the same type */
float *quat; //1D array of data (alias) unsigned char wrapped; /* wrapped data type? */
int wrapped; //is wrapped data? /* end BaseMathObject */
} QuaternionObject; } QuaternionObject;
/*struct data contains a pointer to the actual data that the /*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 //prototypes
PyObject *newQuaternionObject( float *quat, int type ); PyObject *newQuaternionObject( float *quat, int type );
PyObject *newQuaternionObject_cb(PyObject *cb_user, int cb_type, int cb_subtype);
#endif /* EXPP_quat_h */ #endif /* EXPP_quat_h */

View File

@@ -144,7 +144,7 @@ static PyObject *Vector_Zero(VectorObject * self)
self->vec[i] = 0.0f; self->vec[i] = 0.0f;
} }
Vector_WriteCallback(self); BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;
} }
@@ -155,7 +155,7 @@ static PyObject *Vector_Normalize(VectorObject * self)
int i; int i;
float norm = 0.0f; float norm = 0.0f;
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
for(i = 0; i < self->size; i++) { for(i = 0; i < self->size; i++) {
@@ -166,7 +166,7 @@ static PyObject *Vector_Normalize(VectorObject * self)
self->vec[i] /= norm; self->vec[i] /= norm;
} }
Vector_WriteCallback(self); BaseMath_WriteCallback(self);
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;
} }
@@ -266,7 +266,7 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args )
return NULL; return NULL;
} }
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
if (strack) { if (strack) {
@@ -385,7 +385,7 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value )
return NULL; return NULL;
} }
if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value)) if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL; return NULL;
mirror[0] = value->vec[0]; mirror[0] = value->vec[0];
@@ -431,7 +431,7 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value )
return NULL; return NULL;
} }
if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value)) if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL; return NULL;
vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW); vecCross = (VectorObject *)newVectorObject(NULL, 3, Py_NEW);
@@ -454,7 +454,7 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value )
return NULL; return NULL;
} }
if(!Vector_ReadCallback(self) || !Vector_ReadCallback(value)) if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
return NULL; return NULL;
for(x = 0; x < self->size; x++) { 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 */ return a copy of the vector */
static PyObject *Vector_copy(VectorObject * self) static PyObject *Vector_copy(VectorObject * self)
{ {
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
return newVectorObject(self->vec, self->size, Py_NEW); 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 object (internal)-------------
print the object to screen */ print the object to screen */
static PyObject *Vector_repr(VectorObject * self) static PyObject *Vector_repr(VectorObject * self)
@@ -492,7 +480,7 @@ static PyObject *Vector_repr(VectorObject * self)
int i; int i;
char buffer[48], str[1024]; char buffer[48], str[1024];
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
BLI_strncpy(str,"[",1024); BLI_strncpy(str,"[",1024);
@@ -520,12 +508,14 @@ static int Vector_len(VectorObject * self)
sequence accessor (get)*/ sequence accessor (get)*/
static PyObject *Vector_item(VectorObject * self, int i) static PyObject *Vector_item(VectorObject * self, int i)
{ {
if(i<0) i= self->size-i;
if(i < 0 || i >= self->size) { if(i < 0 || i >= self->size) {
PyErr_SetString(PyExc_IndexError,"vector[index]: out of range\n"); PyErr_SetString(PyExc_IndexError,"vector[index]: out of range\n");
return NULL; return NULL;
} }
if(!Vector_ReadIndexCallback(self, i)) if(!BaseMath_ReadIndexCallback(self, i))
return NULL; return NULL;
return PyFloat_FromDouble(self->vec[i]); return PyFloat_FromDouble(self->vec[i]);
@@ -541,13 +531,15 @@ static int Vector_ass_item(VectorObject * self, int i, PyObject * ob)
return -1; return -1;
} }
if(i<0) i= self->size-i;
if(i < 0 || i >= self->size){ if(i < 0 || i >= self->size){
PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n"); PyErr_SetString(PyExc_IndexError, "vector[index] = x: assignment index out of range\n");
return -1; return -1;
} }
self->vec[i] = scalar; self->vec[i] = scalar;
if(!Vector_WriteIndexCallback(self, i)) if(!BaseMath_WriteIndexCallback(self, i))
return -1; return -1;
return 0; return 0;
} }
@@ -559,7 +551,7 @@ static PyObject *Vector_slice(VectorObject * self, int begin, int end)
PyObject *list = NULL; PyObject *list = NULL;
int count; int count;
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
CLAMP(begin, 0, self->size); CLAMP(begin, 0, self->size);
@@ -584,7 +576,7 @@ static int Vector_ass_slice(VectorObject * self, int begin, int end,
float vec[4], scalar; float vec[4], scalar;
PyObject *v; PyObject *v;
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return -1; return -1;
CLAMP(begin, 0, self->size); 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]; self->vec[begin + y] = vec[y];
} }
if(!Vector_WriteCallback(self)) if(!BaseMath_WriteCallback(self))
return -1; return -1;
return 0; return 0;
@@ -644,7 +636,7 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2)
/* make sure v1 is always the vector */ /* make sure v1 is always the vector */
if (vec1 && vec2 ) { if (vec1 && vec2 ) {
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
return NULL; return NULL;
/*VECTOR + VECTOR*/ /*VECTOR + VECTOR*/
@@ -679,7 +671,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
/* make sure v1 is always the vector */ /* make sure v1 is always the vector */
if (vec1 && vec2 ) { if (vec1 && vec2 ) {
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
return NULL; return NULL;
/*VECTOR + VECTOR*/ /*VECTOR + VECTOR*/
@@ -694,7 +686,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2)
return v1; return v1;
} }
Vector_WriteCallback(vec1); BaseMath_WriteCallback(vec1);
PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n"); PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation....\n");
return NULL; return NULL;
} }
@@ -714,7 +706,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2)
vec1 = (VectorObject*)v1; vec1 = (VectorObject*)v1;
vec2 = (VectorObject*)v2; vec2 = (VectorObject*)v2;
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
return NULL; return NULL;
if(vec1->size != vec2->size) { if(vec1->size != vec2->size) {
@@ -747,14 +739,14 @@ static PyObject *Vector_isub(PyObject * v1, PyObject * v2)
return NULL; return NULL;
} }
if(!Vector_ReadCallback(vec1) || !Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec1) || !BaseMath_ReadCallback(vec2))
return NULL; return NULL;
for(i = 0; i < vec1->size; i++) { for(i = 0; i < vec1->size; i++) {
vec1->vec[i] = vec1->vec[i] - vec2->vec[i]; vec1->vec[i] = vec1->vec[i] - vec2->vec[i];
} }
Vector_WriteCallback(vec1); BaseMath_WriteCallback(vec1);
Py_INCREF( v1 ); Py_INCREF( v1 );
return v1; return v1;
} }
@@ -768,12 +760,12 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
if VectorObject_Check(v1) { if VectorObject_Check(v1) {
vec1= (VectorObject *)v1; vec1= (VectorObject *)v1;
if(!Vector_ReadCallback(vec1)) if(!BaseMath_ReadCallback(vec1))
return NULL; return NULL;
} }
if VectorObject_Check(v2) { if VectorObject_Check(v2) {
vec2= (VectorObject *)v2; vec2= (VectorObject *)v2;
if(!Vector_ReadCallback(vec2)) if(!BaseMath_ReadCallback(vec2))
return NULL; return NULL;
} }
@@ -805,7 +797,8 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2)
/* VEC * MATRIX */ /* VEC * MATRIX */
return row_vector_multiplication(vec1, (MatrixObject*)v2); return row_vector_multiplication(vec1, (MatrixObject*)v2);
} else if (QuaternionObject_Check(v2)) { } else if (QuaternionObject_Check(v2)) {
QuaternionObject *quat = (QuaternionObject*)v2; QuaternionObject *quat = (QuaternionObject*)v2; /* quat_rotation validates */
if(vec1->size != 3) { if(vec1->size != 3) {
PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n"); PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported\n");
return NULL; return NULL;
@@ -835,7 +828,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
int i; int i;
float scalar; float scalar;
if(!Vector_ReadCallback(vec)) if(!BaseMath_ReadCallback(vec))
return NULL; return NULL;
/* only support vec*=float and vec*=mat /* 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; int x,y, size = vec->size;
MatrixObject *mat= (MatrixObject*)v2; MatrixObject *mat= (MatrixObject*)v2;
if(!Vector_ReadCallback(mat)) if(!BaseMath_ReadCallback(mat))
return NULL; return NULL;
if(mat->colSize != size){ if(mat->colSize != size){
@@ -883,7 +876,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2)
return NULL; return NULL;
} }
Vector_WriteCallback(vec); BaseMath_WriteCallback(vec);
Py_INCREF( v1 ); Py_INCREF( v1 );
return v1; return v1;
} }
@@ -902,7 +895,7 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2)
} }
vec1 = (VectorObject*)v1; /* vector */ vec1 = (VectorObject*)v1; /* vector */
if(!Vector_ReadCallback(vec1)) if(!BaseMath_ReadCallback(vec1))
return NULL; return NULL;
scalar = (float)PyFloat_AsDouble(v2); scalar = (float)PyFloat_AsDouble(v2);
@@ -930,7 +923,7 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
float scalar; float scalar;
VectorObject *vec1 = (VectorObject*)v1; VectorObject *vec1 = (VectorObject*)v1;
if(!Vector_ReadCallback(vec1)) if(!BaseMath_ReadCallback(vec1))
return NULL; return NULL;
scalar = (float)PyFloat_AsDouble(v2); scalar = (float)PyFloat_AsDouble(v2);
@@ -947,7 +940,7 @@ static PyObject *Vector_idiv(PyObject * v1, PyObject * v2)
vec1->vec[i] /= scalar; vec1->vec[i] /= scalar;
} }
Vector_WriteCallback(vec1); BaseMath_WriteCallback(vec1);
Py_INCREF( v1 ); Py_INCREF( v1 );
return v1; return v1;
@@ -960,7 +953,7 @@ static PyObject *Vector_neg(VectorObject *self)
int i; int i;
float vec[4]; float vec[4];
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
for(i = 0; i < self->size; i++){ for(i = 0; i < self->size; i++){
@@ -1008,7 +1001,7 @@ static PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int compa
vecA = (VectorObject*)objectA; vecA = (VectorObject*)objectA;
vecB = (VectorObject*)objectB; vecB = (VectorObject*)objectB;
if(!Vector_ReadCallback(vecA) || !Vector_ReadCallback(vecB)) if(!BaseMath_ReadCallback(vecA) || !BaseMath_ReadCallback(vecB))
return NULL; return NULL;
if (vecA->size != vecB->size){ if (vecA->size != vecB->size){
@@ -1137,12 +1130,12 @@ static PyNumberMethods Vector_NumMethods = {
static PyObject *Vector_getAxis( VectorObject * self, void *type ) 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 ) 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 */ /* vector.length */
@@ -1151,7 +1144,7 @@ static PyObject *Vector_getLength( VectorObject * self, void *type )
double dot = 0.0f; double dot = 0.0f;
int i; int i;
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
for(i = 0; i < self->size; i++){ for(i = 0; i < self->size; i++){
@@ -1165,7 +1158,7 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
double dot = 0.0f, param; double dot = 0.0f, param;
int i; int i;
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return -1; return -1;
param= PyFloat_AsDouble( value ); param= PyFloat_AsDouble( value );
@@ -1203,30 +1196,11 @@ static int Vector_setLength( VectorObject * self, PyObject * value )
self->vec[i]= self->vec[i] / (float)dot; self->vec[i]= self->vec[i] / (float)dot;
} }
Vector_WriteCallback(self); /* checked alredy */ BaseMath_WriteCallback(self); /* checked alredy */
return 0; 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 /* 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 error checking, as we are in control of the inputs: the closure is set by us
in Vector_createSwizzleGetSeter. */ in Vector_createSwizzleGetSeter. */
@@ -1237,7 +1211,7 @@ static PyObject *Vector_getSwizzle(VectorObject * self, void *closure)
float vec[MAX_DIMENSIONS]; float vec[MAX_DIMENSIONS];
unsigned int swizzleClosure; unsigned int swizzleClosure;
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
/* Unpack the axes from the closure into an array. */ /* 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]; float vecTemp[MAX_DIMENSIONS];
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return -1; return -1;
/* Check that the closure can be used with this vector: even 2D vectors have /* 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++; axisB++;
} }
memcpy(self->vec, vecTemp, axisB * sizeof(float)); 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)) else if (PyList_Check(value))
{ {
@@ -1335,7 +1309,7 @@ static int Vector_setSwizzle(VectorObject * self, PyObject * value, void *closur
axisB++; axisB++;
} }
memcpy(self->vec, vecTemp, axisB * sizeof(float)); 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) 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; swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
} }
/* continue with Vector_WriteCallback at the end */ /* continue with BaseMathObject_WriteCallback at the end */
} }
else { else {
PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." ); PyErr_SetString( PyExc_TypeError, "Expected a Vector, list or scalar value." );
return -1; return -1;
} }
if(!Vector_WriteCallback(vecVal)) if(!BaseMath_WriteCallback(vecVal))
return -1; return -1;
else else
return 0; return 0;
@@ -1390,11 +1364,11 @@ static PyGetSetDef Vector_getseters[] = {
"Vector Length", "Vector Length",
NULL}, NULL},
{"wrapped", {"wrapped",
(getter)Vector_getWrapped, (setter)NULL, (getter)BaseMathObject_getWrapped, (setter)NULL,
"True when this wraps blenders internal data", "True when this wraps blenders internal data",
NULL}, NULL},
{"__owner__", {"__owner__",
(getter)Vector_getOwner, (setter)NULL, (getter)BaseMathObject_getOwner, (setter)NULL,
"Read only owner for vectors that depend on another object", "Read only owner for vectors that depend on another object",
NULL}, NULL},
@@ -1803,7 +1777,7 @@ PyTypeObject vector_Type = {
/* Methods to implement standard operations */ /* Methods to implement standard operations */
( destructor ) Vector_dealloc,/* destructor tp_dealloc; */ ( destructor ) BaseMathObject_dealloc,/* destructor tp_dealloc; */
NULL, /* printfunc tp_print; */ NULL, /* printfunc tp_print; */
NULL, /* getattrfunc tp_getattr; */ NULL, /* getattrfunc tp_getattr; */
NULL, /* setattrfunc tp_setattr; */ 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) 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 */ 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) { if(self) {
Py_INCREF(cb_user); Py_INCREF(cb_user);
self->cb_user= 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; self->cb_subtype= (unsigned char)cb_subtype;
} }
return self; return (PyObject *)self;
} }
//-----------------row_vector_multiplication (internal)----------- //-----------------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; return NULL;
for(x = 0; x < vec_size; x++){ 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) static PyObject *Vector_Negate(VectorObject * self)
{ {
int i; int i;
if(!Vector_ReadCallback(self)) if(!BaseMath_ReadCallback(self))
return NULL; return NULL;
for(i = 0; i < self->size; i++) for(i = 0; i < self->size; i++)
self->vec[i] = -(self->vec[i]); self->vec[i] = -(self->vec[i]);
Vector_WriteCallback(self); // alredy checked for error BaseMath_WriteCallback(self); // alredy checked for error
Py_INCREF(self); Py_INCREF(self);
return (PyObject*)self; return (PyObject*)self;

View File

@@ -37,15 +37,16 @@ extern PyTypeObject vector_Type;
#define VectorObject_Check(v) (((PyObject *)v)->ob_type == &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 PyObject_VAR_HEAD
float *vec; /*1D array of data (alias), wrapped status depends on wrapped status */ 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 */ 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_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 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; } VectorObject;
/*prototypes*/ /*prototypes*/

View File

@@ -44,8 +44,8 @@
#ifdef USE_MATHUTILS #ifdef USE_MATHUTILS
#include "../generic/Mathutils.h" /* so we can have mathutils callbacks */ #include "../generic/Mathutils.h" /* so we can have mathutils callbacks */
/* bpyrna vector callbacks */ /* bpyrna vector/euler/quat callbacks */
static int mathutils_rna_vector_cb_index= -1; /* index for our callbacks */ static int mathutils_rna_array_cb_index= -1; /* index for our callbacks */
static int mathutils_rna_generic_check(BPy_PropertyRNA *self) 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; return 1;
} }
Mathutils_Callback mathutils_rna_vector_cb = { Mathutils_Callback mathutils_rna_array_cb = {
mathutils_rna_generic_check, mathutils_rna_generic_check,
mathutils_rna_vector_get, mathutils_rna_vector_get,
mathutils_rna_vector_set, mathutils_rna_vector_set,
@@ -234,26 +234,41 @@ PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
PyObject *ret = pyrna_prop_CreatePyObject(ptr, prop); PyObject *ret = pyrna_prop_CreatePyObject(ptr, prop);
#ifdef USE_MATHUTILS #ifdef USE_MATHUTILS
/* return a mathutils vector where possible */ /* return a mathutils vector where possible */
if(RNA_property_type(prop)==PROP_FLOAT) { 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) { 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 */ Py_DECREF(ret); /* the vector owns now */
ret= vec_cb; /* return the vector instead */ ret= vec_cb; /* return the vector instead */
} }
} break;
else if(RNA_property_subtype(prop)==PROP_MATRIX) { case PROP_MATRIX:
if(len==16) { 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 */ Py_DECREF(ret); /* the matrix owns now */
ret= mat_cb; /* return the matrix instead */ ret= mat_cb; /* return the matrix instead */
} }
else if (len==9) { 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 */ Py_DECREF(ret); /* the matrix owns now */
ret= mat_cb; /* return the matrix instead */ 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); 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"}; static PyMethodDef func_meth = {"<generic rna function>", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"};
PyObject *self= PyTuple_New(2); PyObject *self= PyTuple_New(2);
PyObject *ret; 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)); PyTuple_SET_ITEM(self, 1, PyCObject_FromVoidPtr((void *)func, NULL));
ret= PyCFunction_New(&func_meth, self); 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 #ifdef USE_MATHUTILS
if(MatrixObject_Check(value)) { if(MatrixObject_Check(value)) {
MatrixObject *mat = (MatrixObject*)value; MatrixObject *mat = (MatrixObject*)value;
if(!Matrix_ReadCallback(mat)) if(!BaseMath_ReadCallback(mat))
return -1; return -1;
py_len = mat->rowSize * mat->colSize; py_len = mat->rowSize * mat->colSize;
} else // continue... } else /* continue... */
#endif #endif
if (PySequence_Check(value)) { if (PySequence_Check(value)) {
py_len= (int)PySequence_Length(value); py_len= (int)PySequence_Length(value);
} }
else { 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; return -1;
} }
/* done getting the length */ /* done getting the length */
if (py_len != len) { 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; 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) { if(MatrixObject_Check(value) && RNA_property_subtype(prop) == PROP_MATRIX) {
MatrixObject *mat = (MatrixObject*)value; MatrixObject *mat = (MatrixObject*)value;
memcpy(param_arr, mat->contigPtr, sizeof(float) * len); memcpy(param_arr, mat->contigPtr, sizeof(float) * len);
} else // continue... } else /* continue... */
#endif #endif
{ {
/* collect the variables */ /* 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); ret = pyrna_prop_to_py(&self->ptr, prop);
} }
else if ((func = RNA_struct_find_function(&self->ptr, name))) { 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) { else if (self->ptr.type == &RNA_Context) {
PointerRNA newptr; PointerRNA newptr;
@@ -1786,7 +1804,7 @@ PyObject *BPY_rna_module( void )
PointerRNA ptr; PointerRNA ptr;
#ifdef USE_MATHUTILS // register mathutils callbacks, ok to run more then once. #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); mathutils_rna_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_rna_matrix_cb);
#endif #endif

View File

@@ -32,6 +32,8 @@
//#define USE_DL_EXPORT //#define USE_DL_EXPORT
#include "Python.h" #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__ #ifdef __FreeBSD__
#include <osreldate.h> #include <osreldate.h>
#if __FreeBSD_version > 500039 #if __FreeBSD_version > 500039

View File

@@ -331,13 +331,18 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef
} }
case KX_PYATTRIBUTE_TYPE_VECTOR: case KX_PYATTRIBUTE_TYPE_VECTOR:
{ {
PyObject* resultlist = PyList_New(3);
MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr); 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++) for (unsigned int i=0; i<3; i++)
{ {
PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i])); PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i]));
} }
return resultlist; return resultlist;
#endif
} }
case KX_PYATTRIBUTE_TYPE_STRING: case KX_PYATTRIBUTE_TYPE_STRING:
{ {

View File

@@ -41,13 +41,15 @@
#include "MT_Vector3.h" #include "MT_Vector3.h"
#include "SG_QList.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 * 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 #if PY_VERSION_HEX > 0x03000000
#define PyString_FromString PyUnicode_FromString #define PyString_FromString PyUnicode_FromString

View File

@@ -1184,11 +1184,7 @@ CListValue* KX_GameObject::GetChildrenRecursive()
return list; return list;
} }
#ifdef USE_MATHUTILS #ifdef USE_MATHUTILS
extern "C" {
#include "../../blender/python/generic/Mathutils.h" /* so we can have mathutils callbacks */
}
/* These require an SGNode */ /* These require an SGNode */
#define MATHUTILS_VEC_CB_POS_LOCAL 1 #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, ")) if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
return PY_SET_ATTR_FAIL; return PY_SET_ATTR_FAIL;
if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) { self->NodeSetGlobalOrientation(rot);
self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
}
else {
self->NodeSetLocalOrientation(rot);
}
self->NodeUpdateGS(0.f); self->NodeUpdateGS(0.f);
return PY_SET_ATTR_SUCCESS; return PY_SET_ATTR_SUCCESS;

View File

@@ -396,9 +396,14 @@ PyAttributeDef KX_ObjectActuator::Attributes[] = {
KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc), 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_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags),
KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot), 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_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), 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_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity),
KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping), 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), 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 */ /* 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) PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{ {
KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);

View File

@@ -35,6 +35,10 @@
#include "SCA_IActuator.h" #include "SCA_IActuator.h"
#include "MT_Vector3.h" #include "MT_Vector3.h"
#ifdef USE_MATHUTILS
void KX_ObjectActuator_Mathutils_Callback_Init(void);
#endif
class KX_GameObject; class KX_GameObject;
// //
@@ -197,6 +201,13 @@ public:
static PyObject* pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); 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); 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() // This lets the attribute macros use UpdateFuzzyFlags()
static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef) static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef)
{ {

View File

@@ -46,35 +46,6 @@
#include "KX_Python.h" #include "KX_Python.h"
#include "KX_PyMath.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) bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix)
{ {
int size= PySequence_Size(pyval); 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) PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
{ {
#if 0 #ifdef USE_MATHUTILS
return Py_BuildValue("[[ffff][ffff][ffff][ffff]]", float fmat[16];
mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat.getValue(fmat);
mat[1][0], mat[1][1], mat[1][2], mat[1][3], return newMatrixObject(fmat, 4, 4, Py_NEW);
mat[2][0], mat[2][1], mat[2][2], mat[2][3],
mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
#else #else
PyObject *list = PyList_New(4); PyObject *list = PyList_New(4);
PyObject *sublist; PyObject *sublist;
@@ -136,11 +105,10 @@ PyObject* PyObjectFrom(const MT_Matrix4x4 &mat)
PyObject* PyObjectFrom(const MT_Matrix3x3 &mat) PyObject* PyObjectFrom(const MT_Matrix3x3 &mat)
{ {
#if 0 #ifdef USE_MATHUTILS
return Py_BuildValue("[[fff][fff][fff]]", float fmat[9];
mat[0][0], mat[0][1], mat[0][2], mat.getValue3x3(fmat);
mat[1][0], mat[1][1], mat[1][2], return newMatrixObject(fmat, 3, 3, Py_NEW);
mat[2][0], mat[2][1], mat[2][2]);
#else #else
PyObject *list = PyList_New(3); PyObject *list = PyList_New(3);
PyObject *sublist; PyObject *sublist;
@@ -160,9 +128,9 @@ PyObject* PyObjectFrom(const MT_Matrix3x3 &mat)
PyObject* PyObjectFrom(const MT_Tuple4 &vec) PyObject* PyObjectFrom(const MT_Tuple4 &vec)
{ {
#if 0 #ifdef USE_MATHUTILS
return Py_BuildValue("[ffff]", float fvec[4]= {vec[0], vec[1], vec[2], vec[3]};
vec[0], vec[1], vec[2], vec[3]); return newVectorObject(fvec, 4, Py_WRAP);
#else #else
PyObject *list = PyList_New(4); PyObject *list = PyList_New(4);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); 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) PyObject* PyObjectFrom(const MT_Tuple3 &vec)
{ {
#if 0 #ifdef USE_MATHUTILS
return Py_BuildValue("[fff]", float fvec[3]= {vec[0], vec[1], vec[2]};
vec[0], vec[1], vec[2]); return newVectorObject(fvec, 3, Py_WRAP);
#else #else
PyObject *list = PyList_New(3); PyObject *list = PyList_New(3);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); 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) PyObject* PyObjectFrom(const MT_Tuple2 &vec)
{ {
#if 0 #ifdef USE_MATHUTILS
return Py_BuildValue("[ff]", float fvec[2]= {vec[0], vec[1]};
vec[0], vec[1]); return newVectorObject(fvec, 2, Py_WRAP);
#else #else
PyObject *list = PyList_New(2); PyObject *list = PyList_New(2);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));

View File

@@ -31,6 +31,12 @@
#ifndef __KX_PYMATH_H__ #ifndef __KX_PYMATH_H__
#define __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_Point2.h"
#include "MT_Point3.h" #include "MT_Point3.h"
#include "MT_Vector2.h" #include "MT_Vector2.h"
@@ -98,7 +104,28 @@ bool PyMatTo(PyObject* pymat, T& mat)
template<class T> template<class T>
bool PyVecTo(PyObject* pyval, T& vec) 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)) if(PyTuple_Check(pyval))
{ {
unsigned int numitems = PyTuple_GET_SIZE(pyval); unsigned int numitems = PyTuple_GET_SIZE(pyval);
@@ -186,10 +213,4 @@ PyObject* PyObjectFrom(const MT_Tuple3 &vec);
*/ */
PyObject* PyObjectFrom(const MT_Tuple4 &pos); 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 #endif

View File

@@ -235,7 +235,8 @@ void initPyTypes(void)
#ifdef USE_MATHUTILS #ifdef USE_MATHUTILS
/* Init mathutils callbacks */ /* Init mathutils callbacks */
KX_GameObject_Mathutils_Callback_Init(); KX_GameObject_Mathutils_Callback_Init();
KX_ObjectActuator_Mathutils_Callback_Init();
#endif #endif
} }
#endif #endif