Blender V2.61 - r43446

mathutils_Euler.c

Go to the documentation of this file.
00001 /*
00002  *
00003  * ***** BEGIN GPL LICENSE BLOCK *****
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  *
00019  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00020  * All rights reserved.
00021  *
00022  *
00023  * Contributor(s): Joseph Gilbert
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <Python.h>
00034 
00035 #include "mathutils.h"
00036 
00037 #include "BLI_math.h"
00038 #include "BLI_utildefines.h"
00039 #include "BLI_dynstr.h"
00040 
00041 #define EULER_SIZE 3
00042 
00043 //----------------------------------mathutils.Euler() -------------------
00044 //makes a new euler for you to play with
00045 static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
00046 {
00047     PyObject *seq = NULL;
00048     const char *order_str = NULL;
00049 
00050     float eul[EULER_SIZE] = {0.0f, 0.0f, 0.0f};
00051     short order = EULER_ORDER_XYZ;
00052 
00053     if (kwds && PyDict_Size(kwds)) {
00054         PyErr_SetString(PyExc_TypeError,
00055                         "mathutils.Euler(): "
00056                         "takes no keyword args");
00057         return NULL;
00058     }
00059 
00060     if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str))
00061         return NULL;
00062 
00063     switch (PyTuple_GET_SIZE(args)) {
00064     case 0:
00065         break;
00066     case 2:
00067         if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1)
00068             return NULL;
00069         /* intentionally pass through */
00070     case 1:
00071         if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1)
00072             return NULL;
00073         break;
00074     }
00075     return Euler_CreatePyObject(eul, order, Py_NEW, type);
00076 }
00077 
00078 /* internal use, assume read callback is done */
00079 static const char *euler_order_str(EulerObject *self)
00080 {
00081     static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
00082     return order[self->order - EULER_ORDER_XYZ];
00083 }
00084 
00085 short euler_order_from_string(const char *str, const char *error_prefix)
00086 {
00087     if ((str[0] && str[1] && str[2] && str[3] == '\0')) {
00088         switch (*((PY_INT32_T *)str)) {
00089             case 'X'|'Y'<<8|'Z'<<16:    return EULER_ORDER_XYZ;
00090             case 'X'|'Z'<<8|'Y'<<16:    return EULER_ORDER_XZY;
00091             case 'Y'|'X'<<8|'Z'<<16:    return EULER_ORDER_YXZ;
00092             case 'Y'|'Z'<<8|'X'<<16:    return EULER_ORDER_YZX;
00093             case 'Z'|'X'<<8|'Y'<<16:    return EULER_ORDER_ZXY;
00094             case 'Z'|'Y'<<8|'X'<<16:    return EULER_ORDER_ZYX;
00095         }
00096     }
00097 
00098     PyErr_Format(PyExc_ValueError,
00099                  "%s: invalid euler order '%s'",
00100                  error_prefix, str);
00101     return -1;
00102 }
00103 
00104 /* note: BaseMath_ReadCallback must be called beforehand */
00105 static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
00106 {
00107     PyObject *ret;
00108     int i;
00109 
00110     ret = PyTuple_New(EULER_SIZE);
00111 
00112     if (ndigits >= 0) {
00113         for (i = 0; i < EULER_SIZE; i++) {
00114             PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits)));
00115         }
00116     }
00117     else {
00118         for (i = 0; i < EULER_SIZE; i++) {
00119             PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i]));
00120         }
00121     }
00122 
00123     return ret;
00124 }
00125 
00126 //-----------------------------METHODS----------------------------
00127 //return a quaternion representation of the euler
00128 
00129 PyDoc_STRVAR(Euler_to_quaternion_doc,
00130 ".. method:: to_quaternion()\n"
00131 "\n"
00132 "   Return a quaternion representation of the euler.\n"
00133 "\n"
00134 "   :return: Quaternion representation of the euler.\n"
00135 "   :rtype: :class:`Quaternion`\n"
00136 );
00137 static PyObject *Euler_to_quaternion(EulerObject *self)
00138 {
00139     float quat[4];
00140 
00141     if (BaseMath_ReadCallback(self) == -1)
00142         return NULL;
00143 
00144     eulO_to_quat(quat, self->eul, self->order);
00145 
00146     return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
00147 }
00148 
00149 //return a matrix representation of the euler
00150 PyDoc_STRVAR(Euler_to_matrix_doc,
00151 ".. method:: to_matrix()\n"
00152 "\n"
00153 "   Return a matrix representation of the euler.\n"
00154 "\n"
00155 "   :return: A 3x3 roation matrix representation of the euler.\n"
00156 "   :rtype: :class:`Matrix`\n"
00157 );
00158 static PyObject *Euler_to_matrix(EulerObject *self)
00159 {
00160     float mat[9];
00161 
00162     if (BaseMath_ReadCallback(self) == -1)
00163         return NULL;
00164 
00165     eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
00166 
00167     return Matrix_CreatePyObject(mat, 3, 3 , Py_NEW, NULL);
00168 }
00169 
00170 PyDoc_STRVAR(Euler_zero_doc,
00171 ".. method:: zero()\n"
00172 "\n"
00173 "   Set all values to zero.\n"
00174 );
00175 static PyObject *Euler_zero(EulerObject *self)
00176 {
00177     zero_v3(self->eul);
00178 
00179     if (BaseMath_WriteCallback(self) == -1)
00180         return NULL;
00181 
00182     Py_RETURN_NONE;
00183 }
00184 
00185 PyDoc_STRVAR(Euler_rotate_axis_doc,
00186 ".. method:: rotate_axis(axis, angle)\n"
00187 "\n"
00188 "   Rotates the euler a certain amount and returning a unique euler rotation\n"
00189 "   (no 720 degree pitches).\n"
00190 "\n"
00191 "   :arg axis: single character in ['X, 'Y', 'Z'].\n"
00192 "   :type axis: string\n"
00193 "   :arg angle: angle in radians.\n"
00194 "   :type angle: float\n"
00195 );
00196 static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
00197 {
00198     float angle = 0.0f;
00199     int axis; /* actually a character */
00200 
00201     if (!PyArg_ParseTuple(args, "Cf:rotate_axis", &axis, &angle)) {
00202         PyErr_SetString(PyExc_TypeError,
00203                         "Euler.rotate_axis(): "
00204                         "expected an axis 'X', 'Y', 'Z' and an angle (float)");
00205         return NULL;
00206     }
00207 
00208     if (!(ELEM3(axis, 'X', 'Y', 'Z'))) {
00209         PyErr_SetString(PyExc_ValueError,
00210                         "Euler.rotate_axis(): "
00211                         "expected axis to be 'X', 'Y' or 'Z'");
00212         return NULL;
00213     }
00214 
00215     if (BaseMath_ReadCallback(self) == -1)
00216         return NULL;
00217 
00218 
00219     rotate_eulO(self->eul, self->order, (char)axis, angle);
00220 
00221     (void)BaseMath_WriteCallback(self);
00222 
00223     Py_RETURN_NONE;
00224 }
00225 
00226 PyDoc_STRVAR(Euler_rotate_doc,
00227 ".. method:: rotate(other)\n"
00228 "\n"
00229 "   Rotates the euler a by another mathutils value.\n"
00230 "\n"
00231 "   :arg other: rotation component of mathutils value\n"
00232 "   :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
00233 );
00234 static PyObject *Euler_rotate(EulerObject *self, PyObject *value)
00235 {
00236     float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
00237 
00238     if (BaseMath_ReadCallback(self) == -1)
00239         return NULL;
00240 
00241     if (mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1)
00242         return NULL;
00243 
00244     eulO_to_mat3(self_rmat, self->eul, self->order);
00245     mul_m3_m3m3(rmat, other_rmat, self_rmat);
00246 
00247     mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat);
00248 
00249     (void)BaseMath_WriteCallback(self);
00250     Py_RETURN_NONE;
00251 }
00252 
00253 PyDoc_STRVAR(Euler_make_compatible_doc,
00254 ".. method:: make_compatible(other)\n"
00255 "\n"
00256 "   Make this euler compatible with another,\n"
00257 "   so interpolating between them works as intended.\n"
00258 "\n"
00259 "   .. note:: the rotation order is not taken into account for this function.\n"
00260 );
00261 static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value)
00262 {
00263     float teul[EULER_SIZE];
00264 
00265     if (BaseMath_ReadCallback(self) == -1)
00266         return NULL;
00267 
00268     if (mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value,
00269                               "euler.make_compatible(other), invalid 'other' arg") == -1)
00270     {
00271         return NULL;
00272     }
00273 
00274     compatible_eul(self->eul, teul);
00275 
00276     (void)BaseMath_WriteCallback(self);
00277 
00278     Py_RETURN_NONE;
00279 }
00280 
00281 //----------------------------Euler.rotate()-----------------------
00282 // return a copy of the euler
00283 
00284 PyDoc_STRVAR(Euler_copy_doc,
00285 ".. function:: copy()\n"
00286 "\n"
00287 "   Returns a copy of this euler.\n"
00288 "\n"
00289 "   :return: A copy of the euler.\n"
00290 "   :rtype: :class:`Euler`\n"
00291 "\n"
00292 "   .. note:: use this to get a copy of a wrapped euler with\n"
00293 "      no reference to the original data.\n"
00294 );
00295 static PyObject *Euler_copy(EulerObject *self)
00296 {
00297     if (BaseMath_ReadCallback(self) == -1)
00298         return NULL;
00299 
00300     return Euler_CreatePyObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
00301 }
00302 
00303 //----------------------------print object (internal)--------------
00304 //print the object to screen
00305 
00306 static PyObject *Euler_repr(EulerObject *self)
00307 {
00308     PyObject *ret, *tuple;
00309 
00310     if (BaseMath_ReadCallback(self) == -1)
00311         return NULL;
00312 
00313     tuple = Euler_ToTupleExt(self, -1);
00314 
00315     ret = PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self));
00316 
00317     Py_DECREF(tuple);
00318     return ret;
00319 }
00320 
00321 static PyObject *Euler_str(EulerObject *self)
00322 {
00323     DynStr *ds;
00324 
00325     if (BaseMath_ReadCallback(self) == -1)
00326         return NULL;
00327 
00328     ds = BLI_dynstr_new();
00329 
00330     BLI_dynstr_appendf(ds, "<Euler (x=%.4f, y=%.4f, z=%.4f), order='%s'>",
00331                        self->eul[0], self->eul[1], self->eul[2], euler_order_str(self));
00332 
00333     return mathutils_dynstr_to_py(ds); /* frees ds */
00334 }
00335 
00336 static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
00337 {
00338     PyObject *res;
00339     int ok = -1; /* zero is true */
00340 
00341     if (EulerObject_Check(a) && EulerObject_Check(b)) {
00342         EulerObject *eulA = (EulerObject *)a;
00343         EulerObject *eulB = (EulerObject *)b;
00344 
00345         if (BaseMath_ReadCallback(eulA) == -1 || BaseMath_ReadCallback(eulB) == -1)
00346             return NULL;
00347 
00348         ok = ((eulA->order == eulB->order) && EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? 0 : -1;
00349     }
00350 
00351     switch (op) {
00352     case Py_NE:
00353         ok = !ok; /* pass through */
00354     case Py_EQ:
00355         res = ok ? Py_False : Py_True;
00356         break;
00357 
00358     case Py_LT:
00359     case Py_LE:
00360     case Py_GT:
00361     case Py_GE:
00362         res = Py_NotImplemented;
00363         break;
00364     default:
00365         PyErr_BadArgument();
00366         return NULL;
00367     }
00368 
00369     return Py_INCREF(res), res;
00370 }
00371 
00372 //---------------------SEQUENCE PROTOCOLS------------------------
00373 //----------------------------len(object)------------------------
00374 //sequence length
00375 static int Euler_len(EulerObject *UNUSED(self))
00376 {
00377     return EULER_SIZE;
00378 }
00379 //----------------------------object[]---------------------------
00380 //sequence accessor (get)
00381 static PyObject *Euler_item(EulerObject *self, int i)
00382 {
00383     if (i < 0) i = EULER_SIZE - i;
00384 
00385     if (i < 0 || i >= EULER_SIZE) {
00386         PyErr_SetString(PyExc_IndexError,
00387                         "euler[attribute]: "
00388                         "array index out of range");
00389         return NULL;
00390     }
00391 
00392     if (BaseMath_ReadIndexCallback(self, i) == -1)
00393         return NULL;
00394 
00395     return PyFloat_FromDouble(self->eul[i]);
00396 
00397 }
00398 //----------------------------object[]-------------------------
00399 //sequence accessor (set)
00400 static int Euler_ass_item(EulerObject *self, int i, PyObject *value)
00401 {
00402     float f = PyFloat_AsDouble(value);
00403 
00404     if (f == -1 && PyErr_Occurred()) { // parsed item not a number
00405         PyErr_SetString(PyExc_TypeError,
00406                         "euler[attribute] = x: "
00407                         "argument not a number");
00408         return -1;
00409     }
00410 
00411     if (i < 0) i = EULER_SIZE - i;
00412 
00413     if (i < 0 || i >= EULER_SIZE) {
00414         PyErr_SetString(PyExc_IndexError,
00415                         "euler[attribute] = x: "
00416                         "array assignment index out of range");
00417         return -1;
00418     }
00419 
00420     self->eul[i] = f;
00421 
00422     if (BaseMath_WriteIndexCallback(self, i) == -1)
00423         return -1;
00424 
00425     return 0;
00426 }
00427 //----------------------------object[z:y]------------------------
00428 //sequence slice (get)
00429 static PyObject *Euler_slice(EulerObject *self, int begin, int end)
00430 {
00431     PyObject *tuple;
00432     int count;
00433 
00434     if (BaseMath_ReadCallback(self) == -1)
00435         return NULL;
00436 
00437     CLAMP(begin, 0, EULER_SIZE);
00438     if (end < 0) end = (EULER_SIZE + 1) + end;
00439     CLAMP(end, 0, EULER_SIZE);
00440     begin = MIN2(begin, end);
00441 
00442     tuple = PyTuple_New(end - begin);
00443     for (count = begin; count < end; count++) {
00444         PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->eul[count]));
00445     }
00446 
00447     return tuple;
00448 }
00449 //----------------------------object[z:y]------------------------
00450 //sequence slice (set)
00451 static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
00452 {
00453     int i, size;
00454     float eul[EULER_SIZE];
00455 
00456     if (BaseMath_ReadCallback(self) == -1)
00457         return -1;
00458 
00459     CLAMP(begin, 0, EULER_SIZE);
00460     if (end < 0) end = (EULER_SIZE + 1) + end;
00461     CLAMP(end, 0, EULER_SIZE);
00462     begin = MIN2(begin, end);
00463 
00464     if ((size = mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) == -1)
00465         return -1;
00466 
00467     if (size != (end - begin)) {
00468         PyErr_SetString(PyExc_ValueError,
00469                         "euler[begin:end] = []: "
00470                         "size mismatch in slice assignment");
00471         return -1;
00472     }
00473 
00474     for (i = 0; i < EULER_SIZE; i++)
00475         self->eul[begin + i] = eul[i];
00476 
00477     (void)BaseMath_WriteCallback(self);
00478     return 0;
00479 }
00480 
00481 static PyObject *Euler_subscript(EulerObject *self, PyObject *item)
00482 {
00483     if (PyIndex_Check(item)) {
00484         Py_ssize_t i;
00485         i = PyNumber_AsSsize_t(item, PyExc_IndexError);
00486         if (i == -1 && PyErr_Occurred())
00487             return NULL;
00488         if (i < 0)
00489             i += EULER_SIZE;
00490         return Euler_item(self, i);
00491     }
00492     else if (PySlice_Check(item)) {
00493         Py_ssize_t start, stop, step, slicelength;
00494 
00495         if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
00496             return NULL;
00497 
00498         if (slicelength <= 0) {
00499             return PyTuple_New(0);
00500         }
00501         else if (step == 1) {
00502             return Euler_slice(self, start, stop);
00503         }
00504         else {
00505             PyErr_SetString(PyExc_IndexError,
00506                             "slice steps not supported with eulers");
00507             return NULL;
00508         }
00509     }
00510     else {
00511         PyErr_Format(PyExc_TypeError,
00512                      "euler indices must be integers, not %.200s",
00513                      Py_TYPE(item)->tp_name);
00514         return NULL;
00515     }
00516 }
00517 
00518 
00519 static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
00520 {
00521     if (PyIndex_Check(item)) {
00522         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
00523         if (i == -1 && PyErr_Occurred())
00524             return -1;
00525         if (i < 0)
00526             i += EULER_SIZE;
00527         return Euler_ass_item(self, i, value);
00528     }
00529     else if (PySlice_Check(item)) {
00530         Py_ssize_t start, stop, step, slicelength;
00531 
00532         if (PySlice_GetIndicesEx((void *)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
00533             return -1;
00534 
00535         if (step == 1)
00536             return Euler_ass_slice(self, start, stop, value);
00537         else {
00538             PyErr_SetString(PyExc_IndexError,
00539                             "slice steps not supported with euler");
00540             return -1;
00541         }
00542     }
00543     else {
00544         PyErr_Format(PyExc_TypeError,
00545                      "euler indices must be integers, not %.200s",
00546                      Py_TYPE(item)->tp_name);
00547         return -1;
00548     }
00549 }
00550 
00551 //-----------------PROTCOL DECLARATIONS--------------------------
00552 static PySequenceMethods Euler_SeqMethods = {
00553     (lenfunc) Euler_len,                    /* sq_length */
00554     (binaryfunc) NULL,                      /* sq_concat */
00555     (ssizeargfunc) NULL,                    /* sq_repeat */
00556     (ssizeargfunc) Euler_item,              /* sq_item */
00557     (ssizessizeargfunc) NULL,               /* sq_slice, deprecated  */
00558     (ssizeobjargproc) Euler_ass_item,       /* sq_ass_item */
00559     (ssizessizeobjargproc) NULL,            /* sq_ass_slice, deprecated */
00560     (objobjproc) NULL,                      /* sq_contains */
00561     (binaryfunc) NULL,                      /* sq_inplace_concat */
00562     (ssizeargfunc) NULL,                    /* sq_inplace_repeat */
00563 };
00564 
00565 static PyMappingMethods Euler_AsMapping = {
00566     (lenfunc)Euler_len,
00567     (binaryfunc)Euler_subscript,
00568     (objobjargproc)Euler_ass_subscript
00569 };
00570 
00571 /* euler axis, euler.x/y/z */
00572 
00573 PyDoc_STRVAR(Euler_axis_doc,
00574 "Euler axis angle in radians.\n\n:type: float"
00575 );
00576 static PyObject *Euler_axis_get(EulerObject *self, void *type)
00577 {
00578     return Euler_item(self, GET_INT_FROM_POINTER(type));
00579 }
00580 
00581 static int Euler_axis_set(EulerObject *self, PyObject *value, void *type)
00582 {
00583     return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
00584 }
00585 
00586 /* rotation order */
00587 
00588 PyDoc_STRVAR(Euler_order_doc,
00589 "Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']"
00590 );
00591 static PyObject *Euler_order_get(EulerObject *self, void *UNUSED(closure))
00592 {
00593     if (BaseMath_ReadCallback(self) == -1) /* can read order too */
00594         return NULL;
00595 
00596     return PyUnicode_FromString(euler_order_str(self));
00597 }
00598 
00599 static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(closure))
00600 {
00601     const char *order_str = _PyUnicode_AsString(value);
00602     short order = euler_order_from_string(order_str, "euler.order");
00603 
00604     if (order == -1)
00605         return -1;
00606 
00607     self->order = order;
00608     (void)BaseMath_WriteCallback(self); /* order can be written back */
00609     return 0;
00610 }
00611 
00612 /*****************************************************************************/
00613 /* Python attributes get/set structure:                                      */
00614 /*****************************************************************************/
00615 static PyGetSetDef Euler_getseters[] = {
00616     {(char *)"x", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)0},
00617     {(char *)"y", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)1},
00618     {(char *)"z", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)2},
00619     {(char *)"order", (getter)Euler_order_get, (setter)Euler_order_set, Euler_order_doc, (void *)NULL},
00620 
00621     {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
00622     {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
00623     {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
00624 };
00625 
00626 
00627 //-----------------------METHOD DEFINITIONS ----------------------
00628 static struct PyMethodDef Euler_methods[] = {
00629     {"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc},
00630     {"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
00631     {"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc},
00632     {"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
00633     {"rotate", (PyCFunction) Euler_rotate, METH_O, Euler_rotate_doc},
00634     {"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc},
00635     {"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
00636     {"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
00637     {NULL, NULL, 0, NULL}
00638 };
00639 
00640 //------------------PY_OBECT DEFINITION--------------------------
00641 PyDoc_STRVAR(euler_doc,
00642 "This object gives access to Eulers in Blender."
00643 );
00644 PyTypeObject euler_Type = {
00645     PyVarObject_HEAD_INIT(NULL, 0)
00646     "mathutils.Euler",              //tp_name
00647     sizeof(EulerObject),            //tp_basicsize
00648     0,                              //tp_itemsize
00649     (destructor)BaseMathObject_dealloc,     //tp_dealloc
00650     NULL,                           //tp_print
00651     NULL,                           //tp_getattr
00652     NULL,                           //tp_setattr
00653     NULL,                           //tp_compare
00654     (reprfunc) Euler_repr,          //tp_repr
00655     NULL,                           //tp_as_number
00656     &Euler_SeqMethods,              //tp_as_sequence
00657     &Euler_AsMapping,               //tp_as_mapping
00658     NULL,                           //tp_hash
00659     NULL,                           //tp_call
00660     (reprfunc) Euler_str,           //tp_str
00661     NULL,                           //tp_getattro
00662     NULL,                           //tp_setattro
00663     NULL,                           //tp_as_buffer
00664     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, //tp_flags
00665     euler_doc, //tp_doc
00666     (traverseproc)BaseMathObject_traverse,  //tp_traverse
00667     (inquiry)BaseMathObject_clear,  //tp_clear
00668     (richcmpfunc)Euler_richcmpr,    //tp_richcompare
00669     0,                              //tp_weaklistoffset
00670     NULL,                           //tp_iter
00671     NULL,                           //tp_iternext
00672     Euler_methods,                  //tp_methods
00673     NULL,                           //tp_members
00674     Euler_getseters,                //tp_getset
00675     NULL,                           //tp_base
00676     NULL,                           //tp_dict
00677     NULL,                           //tp_descr_get
00678     NULL,                           //tp_descr_set
00679     0,                              //tp_dictoffset
00680     NULL,                           //tp_init
00681     NULL,                           //tp_alloc
00682     Euler_new,                      //tp_new
00683     NULL,                           //tp_free
00684     NULL,                           //tp_is_gc
00685     NULL,                           //tp_bases
00686     NULL,                           //tp_mro
00687     NULL,                           //tp_cache
00688     NULL,                           //tp_subclasses
00689     NULL,                           //tp_weaklist
00690     NULL                            //tp_del
00691 };
00692 //------------------------Euler_CreatePyObject (internal)-------------
00693 //creates a new euler object
00694 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
00695  (i.e. it was allocated elsewhere by MEM_mallocN())
00696   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
00697  (i.e. it must be created here with PyMEM_malloc())*/
00698 PyObject *Euler_CreatePyObject(float *eul, short order, int type, PyTypeObject *base_type)
00699 {
00700     EulerObject *self;
00701 
00702     self = base_type ?  (EulerObject *)base_type->tp_alloc(base_type, 0) :
00703                         (EulerObject *)PyObject_GC_New(EulerObject, &euler_Type);
00704 
00705     if (self) {
00706         /* init callbacks as NULL */
00707         self->cb_user = NULL;
00708         self->cb_type = self->cb_subtype = 0;
00709 
00710         if (type == Py_WRAP) {
00711             self->eul = eul;
00712             self->wrapped = Py_WRAP;
00713         }
00714         else if (type == Py_NEW) {
00715             self->eul = PyMem_Malloc(EULER_SIZE * sizeof(float));
00716             if (eul) {
00717                 copy_v3_v3(self->eul, eul);
00718             }
00719             else {
00720                 zero_v3(self->eul);
00721             }
00722 
00723             self->wrapped = Py_NEW;
00724         }
00725         else {
00726             Py_FatalError("Euler(): invalid type!");
00727         }
00728 
00729         self->order = order;
00730     }
00731 
00732     return (PyObject *)self;
00733 }
00734 
00735 PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype)
00736 {
00737     EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, Py_NEW, NULL);
00738     if (self) {
00739         Py_INCREF(cb_user);
00740         self->cb_user =         cb_user;
00741         self->cb_type =         (unsigned char)cb_type;
00742         self->cb_subtype =      (unsigned char)cb_subtype;
00743         PyObject_GC_Track(self);
00744     }
00745 
00746     return (PyObject *)self;
00747 }