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