Merging r51923 through r52851 from trunk into soc-2011-tomato
[blender.git] / source / blender / python / mathutils / mathutils_Euler.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Joseph Gilbert
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/python/mathutils/mathutils_Euler.c
28  *  \ingroup pymathutils
29  */
30
31
32 #include <Python.h>
33
34 #include "mathutils.h"
35
36 #include "BLI_math.h"
37 #include "BLI_utildefines.h"
38
39 #ifndef MATH_STANDALONE
40 #  include "BLI_dynstr.h"
41 #endif
42
43 #define EULER_SIZE 3
44
45 /* ----------------------------------mathutils.Euler() ------------------- */
46 /* makes a new euler for you to play with */
47 static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
48 {
49         PyObject *seq = NULL;
50         const char *order_str = NULL;
51
52         float eul[EULER_SIZE] = {0.0f, 0.0f, 0.0f};
53         short order = EULER_ORDER_XYZ;
54
55         if (kwds && PyDict_Size(kwds)) {
56                 PyErr_SetString(PyExc_TypeError,
57                                 "mathutils.Euler(): "
58                                 "takes no keyword args");
59                 return NULL;
60         }
61
62         if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str))
63                 return NULL;
64
65         switch (PyTuple_GET_SIZE(args)) {
66                 case 0:
67                         break;
68                 case 2:
69                         if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1)
70                                 return NULL;
71                 /* intentionally pass through */
72                 case 1:
73                         if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1)
74                                 return NULL;
75                         break;
76         }
77         return Euler_CreatePyObject(eul, order, Py_NEW, type);
78 }
79
80 /* internal use, assume read callback is done */
81 static const char *euler_order_str(EulerObject *self)
82 {
83         static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
84         return order[self->order - EULER_ORDER_XYZ];
85 }
86
87 short euler_order_from_string(const char *str, const char *error_prefix)
88 {
89         if ((str[0] && str[1] && str[2] && str[3] == '\0')) {
90                 switch (*((PY_INT32_T *)str)) {
91                         case 'X' | 'Y' << 8 | 'Z' << 16:    return EULER_ORDER_XYZ;
92                         case 'X' | 'Z' << 8 | 'Y' << 16:    return EULER_ORDER_XZY;
93                         case 'Y' | 'X' << 8 | 'Z' << 16:    return EULER_ORDER_YXZ;
94                         case 'Y' | 'Z' << 8 | 'X' << 16:    return EULER_ORDER_YZX;
95                         case 'Z' | 'X' << 8 | 'Y' << 16:    return EULER_ORDER_ZXY;
96                         case 'Z' | 'Y' << 8 | 'X' << 16:    return EULER_ORDER_ZYX;
97                 }
98         }
99
100         PyErr_Format(PyExc_ValueError,
101                      "%s: invalid euler order '%s'",
102                      error_prefix, str);
103         return -1;
104 }
105
106 /* note: BaseMath_ReadCallback must be called beforehand */
107 static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
108 {
109         PyObject *ret;
110         int i;
111
112         ret = PyTuple_New(EULER_SIZE);
113
114         if (ndigits >= 0) {
115                 for (i = 0; i < EULER_SIZE; i++) {
116                         PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits)));
117                 }
118         }
119         else {
120                 for (i = 0; i < EULER_SIZE; i++) {
121                         PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i]));
122                 }
123         }
124
125         return ret;
126 }
127
128 /* -----------------------------METHODS----------------------------
129  * return a quaternion representation of the euler */
130
131 PyDoc_STRVAR(Euler_to_quaternion_doc,
132 ".. method:: to_quaternion()\n"
133 "\n"
134 "   Return a quaternion representation of the euler.\n"
135 "\n"
136 "   :return: Quaternion representation of the euler.\n"
137 "   :rtype: :class:`Quaternion`\n"
138 );
139 static PyObject *Euler_to_quaternion(EulerObject *self)
140 {
141         float quat[4];
142
143         if (BaseMath_ReadCallback(self) == -1)
144                 return NULL;
145
146         eulO_to_quat(quat, self->eul, self->order);
147
148         return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
149 }
150
151 /* return a matrix representation of the euler */
152 PyDoc_STRVAR(Euler_to_matrix_doc,
153 ".. method:: to_matrix()\n"
154 "\n"
155 "   Return a matrix representation of the euler.\n"
156 "\n"
157 "   :return: A 3x3 roation matrix representation of the euler.\n"
158 "   :rtype: :class:`Matrix`\n"
159 );
160 static PyObject *Euler_to_matrix(EulerObject *self)
161 {
162         float mat[9];
163
164         if (BaseMath_ReadCallback(self) == -1)
165                 return NULL;
166
167         eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
168
169         return Matrix_CreatePyObject(mat, 3, 3, Py_NEW, NULL);
170 }
171
172 PyDoc_STRVAR(Euler_zero_doc,
173 ".. method:: zero()\n"
174 "\n"
175 "   Set all values to zero.\n"
176 );
177 static PyObject *Euler_zero(EulerObject *self)
178 {
179         zero_v3(self->eul);
180
181         if (BaseMath_WriteCallback(self) == -1)
182                 return NULL;
183
184         Py_RETURN_NONE;
185 }
186
187 PyDoc_STRVAR(Euler_rotate_axis_doc,
188 ".. method:: rotate_axis(axis, angle)\n"
189 "\n"
190 "   Rotates the euler a certain amount and returning a unique euler rotation\n"
191 "   (no 720 degree pitches).\n"
192 "\n"
193 "   :arg axis: single character in ['X, 'Y', 'Z'].\n"
194 "   :type axis: string\n"
195 "   :arg angle: angle in radians.\n"
196 "   :type angle: float\n"
197 );
198 static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
199 {
200         float angle = 0.0f;
201         int axis; /* actually a character */
202
203         if (!PyArg_ParseTuple(args, "Cf:rotate_axis", &axis, &angle)) {
204                 PyErr_SetString(PyExc_TypeError,
205                                 "Euler.rotate_axis(): "
206                                 "expected an axis 'X', 'Y', 'Z' and an angle (float)");
207                 return NULL;
208         }
209
210         if (!(ELEM3(axis, 'X', 'Y', 'Z'))) {
211                 PyErr_SetString(PyExc_ValueError,
212                                 "Euler.rotate_axis(): "
213                                 "expected axis to be 'X', 'Y' or 'Z'");
214                 return NULL;
215         }
216
217         if (BaseMath_ReadCallback(self) == -1)
218                 return NULL;
219
220
221         rotate_eulO(self->eul, self->order, (char)axis, angle);
222
223         (void)BaseMath_WriteCallback(self);
224
225         Py_RETURN_NONE;
226 }
227
228 PyDoc_STRVAR(Euler_rotate_doc,
229 ".. method:: rotate(other)\n"
230 "\n"
231 "   Rotates the euler a by another mathutils value.\n"
232 "\n"
233 "   :arg other: rotation component of mathutils value\n"
234 "   :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"
235 );
236 static PyObject *Euler_rotate(EulerObject *self, PyObject *value)
237 {
238         float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
239
240         if (BaseMath_ReadCallback(self) == -1)
241                 return NULL;
242
243         if (mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1)
244                 return NULL;
245
246         eulO_to_mat3(self_rmat, self->eul, self->order);
247         mul_m3_m3m3(rmat, other_rmat, self_rmat);
248
249         mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat);
250
251         (void)BaseMath_WriteCallback(self);
252         Py_RETURN_NONE;
253 }
254
255 PyDoc_STRVAR(Euler_make_compatible_doc,
256 ".. method:: make_compatible(other)\n"
257 "\n"
258 "   Make this euler compatible with another,\n"
259 "   so interpolating between them works as intended.\n"
260 "\n"
261 "   .. note:: the rotation order is not taken into account for this function.\n"
262 );
263 static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value)
264 {
265         float teul[EULER_SIZE];
266
267         if (BaseMath_ReadCallback(self) == -1)
268                 return NULL;
269
270         if (mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value,
271                                   "euler.make_compatible(other), invalid 'other' arg") == -1)
272         {
273                 return NULL;
274         }
275
276         compatible_eul(self->eul, teul);
277
278         (void)BaseMath_WriteCallback(self);
279
280         Py_RETURN_NONE;
281 }
282
283 /* ----------------------------Euler.rotate()-----------------------
284  * return a copy of the euler */
285
286 PyDoc_STRVAR(Euler_copy_doc,
287 ".. function:: copy()\n"
288 "\n"
289 "   Returns a copy of this euler.\n"
290 "\n"
291 "   :return: A copy of the euler.\n"
292 "   :rtype: :class:`Euler`\n"
293 "\n"
294 "   .. note:: use this to get a copy of a wrapped euler with\n"
295 "      no reference to the original data.\n"
296 );
297 static PyObject *Euler_copy(EulerObject *self)
298 {
299         if (BaseMath_ReadCallback(self) == -1)
300                 return NULL;
301
302         return Euler_CreatePyObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
303 }
304 static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args)
305 {
306         if (!mathutils_deepcopy_args_check(args))
307                 return NULL;
308         return Euler_copy(self);
309 }
310
311 /* ----------------------------print object (internal)--------------
312  * print the object to screen */
313
314 static PyObject *Euler_repr(EulerObject *self)
315 {
316         PyObject *ret, *tuple;
317
318         if (BaseMath_ReadCallback(self) == -1)
319                 return NULL;
320
321         tuple = Euler_ToTupleExt(self, -1);
322
323         ret = PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self));
324
325         Py_DECREF(tuple);
326         return ret;
327 }
328
329 #ifndef MATH_STANDALONE
330 static PyObject *Euler_str(EulerObject *self)
331 {
332         DynStr *ds;
333
334         if (BaseMath_ReadCallback(self) == -1)
335                 return NULL;
336
337         ds = BLI_dynstr_new();
338
339         BLI_dynstr_appendf(ds, "<Euler (x=%.4f, y=%.4f, z=%.4f), order='%s'>",
340                            self->eul[0], self->eul[1], self->eul[2], euler_order_str(self));
341
342         return mathutils_dynstr_to_py(ds); /* frees ds */
343 }
344 #endif
345
346 static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
347 {
348         PyObject *res;
349         int ok = -1; /* zero is true */
350
351         if (EulerObject_Check(a) && EulerObject_Check(b)) {
352                 EulerObject *eulA = (EulerObject *)a;
353                 EulerObject *eulB = (EulerObject *)b;
354
355                 if (BaseMath_ReadCallback(eulA) == -1 || BaseMath_ReadCallback(eulB) == -1)
356                         return NULL;
357
358                 ok = ((eulA->order == eulB->order) && EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? 0 : -1;
359         }
360
361         switch (op) {
362                 case Py_NE:
363                         ok = !ok; /* pass through */
364                 case Py_EQ:
365                         res = ok ? Py_False : Py_True;
366                         break;
367
368                 case Py_LT:
369                 case Py_LE:
370                 case Py_GT:
371                 case Py_GE:
372                         res = Py_NotImplemented;
373                         break;
374                 default:
375                         PyErr_BadArgument();
376                         return NULL;
377         }
378
379         return Py_INCREF(res), res;
380 }
381
382 /* ---------------------SEQUENCE PROTOCOLS------------------------ */
383 /* ----------------------------len(object)------------------------ */
384 /* sequence length */
385 static int Euler_len(EulerObject *UNUSED(self))
386 {
387         return EULER_SIZE;
388 }
389 /* ----------------------------object[]--------------------------- */
390 /* sequence accessor (get) */
391 static PyObject *Euler_item(EulerObject *self, int i)
392 {
393         if (i < 0) i = EULER_SIZE - i;
394
395         if (i < 0 || i >= EULER_SIZE) {
396                 PyErr_SetString(PyExc_IndexError,
397                                 "euler[attribute]: "
398                                 "array index out of range");
399                 return NULL;
400         }
401
402         if (BaseMath_ReadIndexCallback(self, i) == -1)
403                 return NULL;
404
405         return PyFloat_FromDouble(self->eul[i]);
406
407 }
408 /* ----------------------------object[]------------------------- */
409 /* sequence accessor (set) */
410 static int Euler_ass_item(EulerObject *self, int i, PyObject *value)
411 {
412         float f = PyFloat_AsDouble(value);
413
414         if (f == -1 && PyErr_Occurred()) {  /* parsed item not a number */
415                 PyErr_SetString(PyExc_TypeError,
416                                 "euler[attribute] = x: "
417                                 "argument not a number");
418                 return -1;
419         }
420
421         if (i < 0) i = EULER_SIZE - i;
422
423         if (i < 0 || i >= EULER_SIZE) {
424                 PyErr_SetString(PyExc_IndexError,
425                                 "euler[attribute] = x: "
426                                 "array assignment index out of range");
427                 return -1;
428         }
429
430         self->eul[i] = f;
431
432         if (BaseMath_WriteIndexCallback(self, i) == -1)
433                 return -1;
434
435         return 0;
436 }
437 /* ----------------------------object[z:y]------------------------ */
438 /* sequence slice (get) */
439 static PyObject *Euler_slice(EulerObject *self, int begin, int end)
440 {
441         PyObject *tuple;
442         int count;
443
444         if (BaseMath_ReadCallback(self) == -1)
445                 return NULL;
446
447         CLAMP(begin, 0, EULER_SIZE);
448         if (end < 0) end = (EULER_SIZE + 1) + end;
449         CLAMP(end, 0, EULER_SIZE);
450         begin = MIN2(begin, end);
451
452         tuple = PyTuple_New(end - begin);
453         for (count = begin; count < end; count++) {
454                 PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->eul[count]));
455         }
456
457         return tuple;
458 }
459 /* ----------------------------object[z:y]------------------------ */
460 /* sequence slice (set) */
461 static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
462 {
463         int i, size;
464         float eul[EULER_SIZE];
465
466         if (BaseMath_ReadCallback(self) == -1)
467                 return -1;
468
469         CLAMP(begin, 0, EULER_SIZE);
470         if (end < 0) end = (EULER_SIZE + 1) + end;
471         CLAMP(end, 0, EULER_SIZE);
472         begin = MIN2(begin, end);
473
474         if ((size = mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) == -1)
475                 return -1;
476
477         if (size != (end - begin)) {
478                 PyErr_SetString(PyExc_ValueError,
479                                 "euler[begin:end] = []: "
480                                 "size mismatch in slice assignment");
481                 return -1;
482         }
483
484         for (i = 0; i < EULER_SIZE; i++)
485                 self->eul[begin + i] = eul[i];
486
487         (void)BaseMath_WriteCallback(self);
488         return 0;
489 }
490
491 static PyObject *Euler_subscript(EulerObject *self, PyObject *item)
492 {
493         if (PyIndex_Check(item)) {
494                 Py_ssize_t i;
495                 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
496                 if (i == -1 && PyErr_Occurred())
497                         return NULL;
498                 if (i < 0)
499                         i += EULER_SIZE;
500                 return Euler_item(self, i);
501         }
502         else if (PySlice_Check(item)) {
503                 Py_ssize_t start, stop, step, slicelength;
504
505                 if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
506                         return NULL;
507
508                 if (slicelength <= 0) {
509                         return PyTuple_New(0);
510                 }
511                 else if (step == 1) {
512                         return Euler_slice(self, start, stop);
513                 }
514                 else {
515                         PyErr_SetString(PyExc_IndexError,
516                                         "slice steps not supported with eulers");
517                         return NULL;
518                 }
519         }
520         else {
521                 PyErr_Format(PyExc_TypeError,
522                              "euler indices must be integers, not %.200s",
523                              Py_TYPE(item)->tp_name);
524                 return NULL;
525         }
526 }
527
528
529 static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
530 {
531         if (PyIndex_Check(item)) {
532                 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
533                 if (i == -1 && PyErr_Occurred())
534                         return -1;
535                 if (i < 0)
536                         i += EULER_SIZE;
537                 return Euler_ass_item(self, i, value);
538         }
539         else if (PySlice_Check(item)) {
540                 Py_ssize_t start, stop, step, slicelength;
541
542                 if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
543                         return -1;
544
545                 if (step == 1)
546                         return Euler_ass_slice(self, start, stop, value);
547                 else {
548                         PyErr_SetString(PyExc_IndexError,
549                                         "slice steps not supported with euler");
550                         return -1;
551                 }
552         }
553         else {
554                 PyErr_Format(PyExc_TypeError,
555                              "euler indices must be integers, not %.200s",
556                              Py_TYPE(item)->tp_name);
557                 return -1;
558         }
559 }
560
561 /* -----------------PROTCOL DECLARATIONS-------------------------- */
562 static PySequenceMethods Euler_SeqMethods = {
563         (lenfunc) Euler_len,                    /* sq_length */
564         (binaryfunc) NULL,                      /* sq_concat */
565         (ssizeargfunc) NULL,                    /* sq_repeat */
566         (ssizeargfunc) Euler_item,              /* sq_item */
567         (ssizessizeargfunc) NULL,               /* sq_slice, deprecated  */
568         (ssizeobjargproc) Euler_ass_item,       /* sq_ass_item */
569         (ssizessizeobjargproc) NULL,            /* sq_ass_slice, deprecated */
570         (objobjproc) NULL,                      /* sq_contains */
571         (binaryfunc) NULL,                      /* sq_inplace_concat */
572         (ssizeargfunc) NULL,                    /* sq_inplace_repeat */
573 };
574
575 static PyMappingMethods Euler_AsMapping = {
576         (lenfunc)Euler_len,
577         (binaryfunc)Euler_subscript,
578         (objobjargproc)Euler_ass_subscript
579 };
580
581 /* euler axis, euler.x/y/z */
582
583 PyDoc_STRVAR(Euler_axis_doc,
584 "Euler axis angle in radians.\n\n:type: float"
585 );
586 static PyObject *Euler_axis_get(EulerObject *self, void *type)
587 {
588         return Euler_item(self, GET_INT_FROM_POINTER(type));
589 }
590
591 static int Euler_axis_set(EulerObject *self, PyObject *value, void *type)
592 {
593         return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
594 }
595
596 /* rotation order */
597
598 PyDoc_STRVAR(Euler_order_doc,
599 "Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']"
600 );
601 static PyObject *Euler_order_get(EulerObject *self, void *UNUSED(closure))
602 {
603         if (BaseMath_ReadCallback(self) == -1) /* can read order too */
604                 return NULL;
605
606         return PyUnicode_FromString(euler_order_str(self));
607 }
608
609 static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(closure))
610 {
611         const char *order_str = _PyUnicode_AsString(value);
612         short order = euler_order_from_string(order_str, "euler.order");
613
614         if (order == -1)
615                 return -1;
616
617         self->order = order;
618         (void)BaseMath_WriteCallback(self); /* order can be written back */
619         return 0;
620 }
621
622 /*****************************************************************************/
623 /* Python attributes get/set structure:                                      */
624 /*****************************************************************************/
625 static PyGetSetDef Euler_getseters[] = {
626         {(char *)"x", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)0},
627         {(char *)"y", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)1},
628         {(char *)"z", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)2},
629         {(char *)"order", (getter)Euler_order_get, (setter)Euler_order_set, Euler_order_doc, (void *)NULL},
630
631         {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
632         {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
633         {NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
634 };
635
636
637 /* -----------------------METHOD DEFINITIONS ---------------------- */
638 static struct PyMethodDef Euler_methods[] = {
639         {"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc},
640         {"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
641         {"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc},
642         {"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
643         {"rotate", (PyCFunction) Euler_rotate, METH_O, Euler_rotate_doc},
644         {"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc},
645         {"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
646         {"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc},
647         {"__deepcopy__", (PyCFunction) Euler_deepcopy, METH_VARARGS, Euler_copy_doc},
648         {NULL, NULL, 0, NULL}
649 };
650
651 /* ------------------PY_OBECT DEFINITION-------------------------- */
652 PyDoc_STRVAR(euler_doc,
653 "This object gives access to Eulers in Blender."
654 );
655 PyTypeObject euler_Type = {
656         PyVarObject_HEAD_INIT(NULL, 0)
657         "Euler",                        /* tp_name */
658         sizeof(EulerObject),            /* tp_basicsize */
659         0,                              /* tp_itemsize */
660         (destructor)BaseMathObject_dealloc,     /* tp_dealloc */
661         NULL,                           /* tp_print */
662         NULL,                           /* tp_getattr */
663         NULL,                           /* tp_setattr */
664         NULL,                           /* tp_compare */
665         (reprfunc) Euler_repr,          /* tp_repr */
666         NULL,                           /* tp_as_number */
667         &Euler_SeqMethods,              /* tp_as_sequence */
668         &Euler_AsMapping,               /* tp_as_mapping */
669         NULL,                           /* tp_hash */
670         NULL,                           /* tp_call */
671 #ifndef MATH_STANDALONE
672         (reprfunc) Euler_str,           /* tp_str */
673 #else
674         NULL,                           /* tp_str */
675 #endif
676         NULL,                           /* tp_getattro */
677         NULL,                           /* tp_setattro */
678         NULL,                           /* tp_as_buffer */
679         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
680         euler_doc, /* tp_doc */
681         (traverseproc)BaseMathObject_traverse,  /* tp_traverse */
682         (inquiry)BaseMathObject_clear,  /* tp_clear */
683         (richcmpfunc)Euler_richcmpr,    /* tp_richcompare */
684         0,                              /* tp_weaklistoffset */
685         NULL,                           /* tp_iter */
686         NULL,                           /* tp_iternext */
687         Euler_methods,                  /* tp_methods */
688         NULL,                           /* tp_members */
689         Euler_getseters,                /* tp_getset */
690         NULL,                           /* tp_base */
691         NULL,                           /* tp_dict */
692         NULL,                           /* tp_descr_get */
693         NULL,                           /* tp_descr_set */
694         0,                              /* tp_dictoffset */
695         NULL,                           /* tp_init */
696         NULL,                           /* tp_alloc */
697         Euler_new,                      /* tp_new */
698         NULL,                           /* tp_free */
699         NULL,                           /* tp_is_gc */
700         NULL,                           /* tp_bases */
701         NULL,                           /* tp_mro */
702         NULL,                           /* tp_cache */
703         NULL,                           /* tp_subclasses */
704         NULL,                           /* tp_weaklist */
705         NULL                            /* tp_del */
706 };
707 /* ------------------------Euler_CreatePyObject (internal)------------- */
708 /* creates a new euler object */
709 /* pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
710  * (i.e. it was allocated elsewhere by MEM_mallocN())
711  * pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
712  * (i.e. it must be created here with PyMEM_malloc())*/
713 PyObject *Euler_CreatePyObject(float *eul, const short order, int type, PyTypeObject *base_type)
714 {
715         EulerObject *self;
716
717         self = base_type ?  (EulerObject *)base_type->tp_alloc(base_type, 0) :
718                             (EulerObject *)PyObject_GC_New(EulerObject, &euler_Type);
719
720         if (self) {
721                 /* init callbacks as NULL */
722                 self->cb_user = NULL;
723                 self->cb_type = self->cb_subtype = 0;
724
725                 if (type == Py_WRAP) {
726                         self->eul = eul;
727                         self->wrapped = Py_WRAP;
728                 }
729                 else if (type == Py_NEW) {
730                         self->eul = PyMem_Malloc(EULER_SIZE * sizeof(float));
731                         if (eul) {
732                                 copy_v3_v3(self->eul, eul);
733                         }
734                         else {
735                                 zero_v3(self->eul);
736                         }
737
738                         self->wrapped = Py_NEW;
739                 }
740                 else {
741                         Py_FatalError("Euler(): invalid type!");
742                 }
743
744                 self->order = order;
745         }
746
747         return (PyObject *)self;
748 }
749
750 PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, const short order,
751                                   unsigned char cb_type, unsigned char cb_subtype)
752 {
753         EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, Py_NEW, NULL);
754         if (self) {
755                 Py_INCREF(cb_user);
756                 self->cb_user         = cb_user;
757                 self->cb_type         = cb_type;
758                 self->cb_subtype      = cb_subtype;
759                 PyObject_GC_Track(self);
760         }
761
762         return (PyObject *)self;
763 }