Merge -c 26209,26214,26443 from COLLADA branch into trunk.
[blender.git] / source / blender / python / generic / euler.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Joseph Gilbert
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "Mathutils.h"
30
31 #include "BLI_math.h"
32 #include "BKE_utildefines.h"
33 #include "BLI_blenlib.h"
34
35
36 //----------------------------------Mathutils.Euler() -------------------
37 //makes a new euler for you to play with
38 static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
39 {
40         PyObject *listObject = NULL;
41         int size, i;
42         float eul[3];
43         PyObject *e;
44
45         size = PyTuple_GET_SIZE(args);
46         if (size == 1) {
47                 listObject = PyTuple_GET_ITEM(args, 0);
48                 if (PySequence_Check(listObject)) {
49                         size = PySequence_Length(listObject);
50                 } else { // Single argument was not a sequence
51                         PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
52                         return NULL;
53                 }
54         } else if (size == 0) {
55                 //returns a new empty 3d euler
56                 return newEulerObject(NULL, Py_NEW, NULL);
57         } else {
58                 listObject = args;
59         }
60
61         if (size != 3) { // Invalid euler size
62                 PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
63                 return NULL;
64         }
65
66         for (i=0; i<size; i++) {
67                 e = PySequence_GetItem(listObject, i);
68                 if (e == NULL) { // Failed to read sequence
69                         Py_DECREF(listObject);
70                         PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
71                         return NULL;
72                 }
73
74                 eul[i]= (float)PyFloat_AsDouble(e);
75                 Py_DECREF(e);
76                 
77                 if(eul[i]==-1 && PyErr_Occurred()) { // parsed item is not a number
78                         PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
79                         return NULL;
80                 }
81         }
82         return newEulerObject(eul, Py_NEW, NULL);
83 }
84
85 //-----------------------------METHODS----------------------------
86 //----------------------------Euler.toQuat()----------------------
87 //return a quaternion representation of the euler
88
89 static char Euler_ToQuat_doc[] =
90 ".. method:: to_quat()\n"
91 "\n"
92 "   Return a quaternion representation of the euler.\n"
93 "\n"
94 "   :return: Quaternion representation of the euler.\n"
95 "   :rtype: :class:`Quaternion`\n";
96
97 static PyObject *Euler_ToQuat(EulerObject * self)
98 {
99         float quat[4];
100 #ifdef USE_MATHUTILS_DEG
101         float eul[3];
102         int x;
103 #endif
104
105         if(!BaseMath_ReadCallback(self))
106                 return NULL;
107
108 #ifdef USE_MATHUTILS_DEG
109         for(x = 0; x < 3; x++) {
110                 eul[x] = self->eul[x] * ((float)Py_PI / 180);
111         }
112         eul_to_quat( quat,eul);
113 #else
114         eul_to_quat( quat,self->eul);
115 #endif
116
117         return newQuaternionObject(quat, Py_NEW, NULL);
118 }
119 //----------------------------Euler.toMatrix()---------------------
120 //return a matrix representation of the euler
121 static char Euler_ToMatrix_doc[] =
122 ".. method:: to_matrix()\n"
123 "\n"
124 "   Return a matrix representation of the euler.\n"
125 "\n"
126 "   :return: A 3x3 roation matrix representation of the euler.\n"
127 "   :rtype: :class:`Matrix`\n";
128
129 static PyObject *Euler_ToMatrix(EulerObject * self)
130 {
131         float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
132
133         if(!BaseMath_ReadCallback(self))
134                 return NULL;
135
136 #ifdef USE_MATHUTILS_DEG
137         {
138                 float eul[3];
139                 int x;
140                 
141                 for(x = 0; x < 3; x++) {
142                         eul[x] = self->eul[x] * ((float)Py_PI / 180);
143                 }
144                 eul_to_mat3( (float (*)[3]) mat,eul);
145         }
146 #else
147         eul_to_mat3( (float (*)[3]) mat,self->eul);
148 #endif
149         return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
150 }
151 //----------------------------Euler.unique()-----------------------
152 //sets the x,y,z values to a unique euler rotation
153
154 static char Euler_Unique_doc[] =
155 ".. method:: unique()\n"
156 "\n"
157 "   Calculate a unique rotation for this euler. Avoids gimble lock.\n"
158 "\n"
159 "   :return: an instance of itself\n"
160 "   :rtype: :class:`Euler`\n";
161
162 static PyObject *Euler_Unique(EulerObject * self)
163 {
164 #define PI_2            (Py_PI * 2.0)
165 #define PI_HALF         (Py_PI / 2.0)
166 #define PI_INV          (1.0 / Py_PI)
167
168         double heading, pitch, bank;
169
170         if(!BaseMath_ReadCallback(self))
171                 return NULL;
172
173 #ifdef USE_MATHUTILS_DEG
174         //radians
175         heading = self->eul[0] * (float)Py_PI / 180;
176         pitch = self->eul[1] * (float)Py_PI / 180;
177         bank = self->eul[2] * (float)Py_PI / 180;
178 #else
179         heading = self->eul[0];
180         pitch = self->eul[1];
181         bank = self->eul[2];
182 #endif
183
184         //wrap heading in +180 / -180
185         pitch += Py_PI;
186         pitch -= floor(pitch * PI_INV) * PI_2;
187         pitch -= Py_PI;
188
189
190         if(pitch < -PI_HALF) {
191                 pitch = -Py_PI - pitch;
192                 heading += Py_PI;
193                 bank += Py_PI;
194         } else if(pitch > PI_HALF) {
195                 pitch = Py_PI - pitch;
196                 heading += Py_PI;
197                 bank += Py_PI;
198         }
199         //gimbal lock test
200         if(fabs(pitch) > PI_HALF - 1e-4) {
201                 heading += bank;
202                 bank = 0.0f;
203         } else {
204                 bank += Py_PI;
205                 bank -= (floor(bank * PI_INV)) * PI_2;
206                 bank -= Py_PI;
207         }
208
209         heading += Py_PI;
210         heading -= (floor(heading * PI_INV)) * PI_2;
211         heading -= Py_PI;
212
213 #ifdef USE_MATHUTILS_DEG
214         //back to degrees
215         self->eul[0] = (float)(heading * 180 / (float)Py_PI);
216         self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
217         self->eul[2] = (float)(bank * 180 / (float)Py_PI);
218 #endif
219
220         BaseMath_WriteCallback(self);
221         Py_INCREF(self);
222         return (PyObject *)self;
223 }
224 //----------------------------Euler.zero()-------------------------
225 //sets the euler to 0,0,0
226 static char Euler_Zero_doc[] =
227 ".. method:: zero()\n"
228 "\n"
229 "   Set all values to zero.\n"
230 "\n"
231 "   :return: an instance of itself\n"
232 "   :rtype: :class:`Euler`\n";
233
234 static PyObject *Euler_Zero(EulerObject * self)
235 {
236         self->eul[0] = 0.0;
237         self->eul[1] = 0.0;
238         self->eul[2] = 0.0;
239
240         BaseMath_WriteCallback(self);
241         Py_INCREF(self);
242         return (PyObject *)self;
243 }
244 //----------------------------Euler.rotate()-----------------------
245 //rotates a euler a certain amount and returns the result
246 //should return a unique euler rotation (i.e. no 720 degree pitches :)
247 static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
248 {
249         float angle = 0.0f;
250         char *axis;
251
252         if(!PyArg_ParseTuple(args, "fs", &angle, &axis)){
253                 PyErr_SetString(PyExc_TypeError, "euler.rotate():expected angle (float) and axis (x,y,z)");
254                 return NULL;
255         }
256         if(ELEM3(*axis, 'x', 'y', 'z') && axis[1]=='\0'){
257                 PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'x', 'y' or 'z'");
258                 return NULL;
259         }
260
261         if(!BaseMath_ReadCallback(self))
262                 return NULL;
263
264 #ifdef USE_MATHUTILS_DEG
265         {
266                 int x;
267
268                 //covert to radians
269                 angle *= ((float)Py_PI / 180);
270                 for(x = 0; x < 3; x++) {
271                         self->eul[x] *= ((float)Py_PI / 180);
272                 }
273         }
274 #endif
275         rotate_eul(self->eul, *axis, angle);
276
277 #ifdef USE_MATHUTILS_DEG
278         {
279                 int x;
280                 //convert back from radians
281                 for(x = 0; x < 3; x++) {
282                         self->eul[x] *= (180 / (float)Py_PI);
283                 }
284         }
285 #endif
286
287         BaseMath_WriteCallback(self);
288         Py_INCREF(self);
289         return (PyObject *)self;
290 }
291
292 static char Euler_MakeCompatible_doc[] =
293 ".. method:: make_compatible(other)\n"
294 "\n"
295 "   Make this euler compatible with another, so interpolating between them works as intended.\n"
296 "\n"
297 "   :arg other: make compatible with this rotation.\n"
298 "   :type other: :class:`Euler`\n"
299 "   :return: an instance of itself.\n"
300 "   :rtype: :class:`Euler`\n";
301
302 static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
303 {
304 #ifdef USE_MATHUTILS_DEG
305         float eul_from_rad[3];
306         int x;
307 #endif
308         
309         if(!EulerObject_Check(value)) {
310                 PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
311                 return NULL;
312         }
313         
314         if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
315                 return NULL;
316
317 #ifdef USE_MATHUTILS_DEG
318         //covert to radians
319         for(x = 0; x < 3; x++) {
320                 self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
321                 eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
322         }
323         compatible_eul(self->eul, eul_from_rad);
324 #else
325         compatible_eul(self->eul, value->eul);
326 #endif
327
328 #ifdef USE_MATHUTILS_DEG
329         //convert back from radians
330         for(x = 0; x < 3; x++) {
331                 self->eul[x] *= (180 / (float)Py_PI);
332         }
333 #endif
334         BaseMath_WriteCallback(self);
335         Py_INCREF(self);
336         return (PyObject *)self;
337 }
338
339 //----------------------------Euler.rotate()-----------------------
340 // return a copy of the euler
341
342 static char Euler_copy_doc[] =
343 ".. function:: copy()\n"
344 "\n"
345 "   Returns a copy of this euler.\n"
346 "\n"
347 "   :return: A copy of the euler.\n"
348 "   :rtype: :class:`Euler`\n"
349 "\n"
350 "   .. note:: use this to get a copy of a wrapped euler with no reference to the original data.\n";
351
352 static PyObject *Euler_copy(EulerObject * self, PyObject *args)
353 {
354         if(!BaseMath_ReadCallback(self))
355                 return NULL;
356
357         return newEulerObject(self->eul, Py_NEW, Py_TYPE(self));
358 }
359
360 //----------------------------print object (internal)--------------
361 //print the object to screen
362 static PyObject *Euler_repr(EulerObject * self)
363 {
364         char str[64];
365
366         if(!BaseMath_ReadCallback(self))
367                 return NULL;
368
369         sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
370         return PyUnicode_FromString(str);
371 }
372 //------------------------tp_richcmpr
373 //returns -1 execption, 0 false, 1 true
374 static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
375 {
376         EulerObject *eulA = NULL, *eulB = NULL;
377         int result = 0;
378
379         if(EulerObject_Check(objectA)) {
380                 eulA = (EulerObject*)objectA;
381                 if(!BaseMath_ReadCallback(eulA))
382                         return NULL;
383         }
384         if(EulerObject_Check(objectB)) {
385                 eulB = (EulerObject*)objectB;
386                 if(!BaseMath_ReadCallback(eulB))
387                         return NULL;
388         }
389
390         if (!eulA || !eulB){
391                 if (comparison_type == Py_NE){
392                         Py_RETURN_TRUE;
393                 }else{
394                         Py_RETURN_FALSE;
395                 }
396         }
397         eulA = (EulerObject*)objectA;
398         eulB = (EulerObject*)objectB;
399
400         switch (comparison_type){
401                 case Py_EQ:
402                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
403                         break;
404                 case Py_NE:
405                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
406                         if (result == 0){
407                                 result = 1;
408                         }else{
409                                 result = 0;
410                         }
411                         break;
412                 default:
413                         printf("The result of the comparison could not be evaluated");
414                         break;
415         }
416         if (result == 1){
417                 Py_RETURN_TRUE;
418         }else{
419                 Py_RETURN_FALSE;
420         }
421 }
422
423 //---------------------SEQUENCE PROTOCOLS------------------------
424 //----------------------------len(object)------------------------
425 //sequence length
426 static int Euler_len(EulerObject * self)
427 {
428         return 3;
429 }
430 //----------------------------object[]---------------------------
431 //sequence accessor (get)
432 static PyObject *Euler_item(EulerObject * self, int i)
433 {
434         if(i<0) i= 3-i;
435         
436         if(i < 0 || i >= 3) {
437                 PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
438                 return NULL;
439         }
440
441         if(!BaseMath_ReadIndexCallback(self, i))
442                 return NULL;
443
444         return PyFloat_FromDouble(self->eul[i]);
445
446 }
447 //----------------------------object[]-------------------------
448 //sequence accessor (set)
449 static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
450 {
451         float f = PyFloat_AsDouble(value);
452
453         if(f == -1 && PyErr_Occurred()) { // parsed item not a number
454                 PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
455                 return -1;
456         }
457
458         if(i<0) i= 3-i;
459         
460         if(i < 0 || i >= 3){
461                 PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
462                 return -1;
463         }
464         
465         self->eul[i] = f;
466
467         if(!BaseMath_WriteIndexCallback(self, i))
468                 return -1;
469
470         return 0;
471 }
472 //----------------------------object[z:y]------------------------
473 //sequence slice (get)
474 static PyObject *Euler_slice(EulerObject * self, int begin, int end)
475 {
476         PyObject *list = NULL;
477         int count;
478
479         if(!BaseMath_ReadCallback(self))
480                 return NULL;
481
482         CLAMP(begin, 0, 3);
483         if (end<0) end= 4+end;
484         CLAMP(end, 0, 3);
485         begin = MIN2(begin,end);
486
487         list = PyList_New(end - begin);
488         for(count = begin; count < end; count++) {
489                 PyList_SetItem(list, count - begin,
490                                 PyFloat_FromDouble(self->eul[count]));
491         }
492
493         return list;
494 }
495 //----------------------------object[z:y]------------------------
496 //sequence slice (set)
497 static int Euler_ass_slice(EulerObject * self, int begin, int end,
498                              PyObject * seq)
499 {
500         int i, y, size = 0;
501         float eul[3];
502         PyObject *e;
503
504         if(!BaseMath_ReadCallback(self))
505                 return -1;
506
507         CLAMP(begin, 0, 3);
508         if (end<0) end= 4+end;
509         CLAMP(end, 0, 3);
510         begin = MIN2(begin,end);
511
512         size = PySequence_Length(seq);
513         if(size != (end - begin)){
514                 PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
515                 return -1;
516         }
517
518         for (i = 0; i < size; i++) {
519                 e = PySequence_GetItem(seq, i);
520                 if (e == NULL) { // Failed to read sequence
521                         PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
522                         return -1;
523                 }
524
525                 eul[i] = (float)PyFloat_AsDouble(e);
526                 Py_DECREF(e);
527
528                 if(eul[i]==-1 && PyErr_Occurred()) { // parsed item not a number
529                         PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
530                         return -1;
531                 }
532         }
533         //parsed well - now set in vector
534         for(y = 0; y < 3; y++){
535                 self->eul[begin + y] = eul[y];
536         }
537
538         BaseMath_WriteCallback(self);
539         return 0;
540 }
541 //-----------------PROTCOL DECLARATIONS--------------------------
542 static PySequenceMethods Euler_SeqMethods = {
543         (lenfunc) Euler_len,                                            /* sq_length */
544         (binaryfunc) 0,                                                         /* sq_concat */
545         (ssizeargfunc) 0,                                                               /* sq_repeat */
546         (ssizeargfunc) Euler_item,                                      /* sq_item */
547         (ssizessizeargfunc) Euler_slice,                                /* sq_slice */
548         (ssizeobjargproc) Euler_ass_item,                               /* sq_ass_item */
549         (ssizessizeobjargproc) Euler_ass_slice,                 /* sq_ass_slice */
550 };
551
552
553 /*
554  * vector axis, vector.x/y/z/w
555  */
556 static PyObject *Euler_getAxis( EulerObject * self, void *type )
557 {
558         return Euler_item(self, GET_INT_FROM_POINTER(type));
559 }
560
561 static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
562 {
563         return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
564 }
565
566 /*****************************************************************************/
567 /* Python attributes get/set structure:                                      */
568 /*****************************************************************************/
569 static PyGetSetDef Euler_getseters[] = {
570         {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis in radians. **type** float", (void *)0},
571         {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis in radians. **type** float", (void *)1},
572         {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis in radians. **type** float", (void *)2},
573
574         {"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
575         {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
576         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
577 };
578
579
580 //-----------------------METHOD DEFINITIONS ----------------------
581 static struct PyMethodDef Euler_methods[] = {
582         {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
583         {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
584         {"to_matrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
585         {"to_quat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
586         {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, NULL},
587         {"make_compatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
588         {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
589         {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
590         {NULL, NULL, 0, NULL}
591 };
592
593 //------------------PY_OBECT DEFINITION--------------------------
594 static char euler_doc[] = "This object gives access to Eulers in Blender.";
595
596 PyTypeObject euler_Type = {
597         PyVarObject_HEAD_INIT(NULL, 0)
598         "euler",                                                //tp_name
599         sizeof(EulerObject),                    //tp_basicsize
600         0,                                                              //tp_itemsize
601         (destructor)BaseMathObject_dealloc,             //tp_dealloc
602         0,                                                              //tp_print
603         0,                                                              //tp_getattr
604         0,                                                              //tp_setattr
605         0,                                                              //tp_compare
606         (reprfunc) Euler_repr,                  //tp_repr
607         0,                              //tp_as_number
608         &Euler_SeqMethods,                              //tp_as_sequence
609         0,                                                              //tp_as_mapping
610         0,                                                              //tp_hash
611         0,                                                              //tp_call
612         0,                                                              //tp_str
613         0,                                                              //tp_getattro
614         0,                                                              //tp_setattro
615         0,                                                              //tp_as_buffer
616         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
617         euler_doc, //tp_doc
618         0,                                                              //tp_traverse
619         0,                                                              //tp_clear
620         (richcmpfunc)Euler_richcmpr,    //tp_richcompare
621         0,                                                              //tp_weaklistoffset
622         0,                                                              //tp_iter
623         0,                                                              //tp_iternext
624         Euler_methods,                                  //tp_methods
625         0,                                                              //tp_members
626         Euler_getseters,                                //tp_getset
627         0,                                                              //tp_base
628         0,                                                              //tp_dict
629         0,                                                              //tp_descr_get
630         0,                                                              //tp_descr_set
631         0,                                                              //tp_dictoffset
632         0,                                                              //tp_init
633         0,                                                              //tp_alloc
634         Euler_new,                                              //tp_new
635         0,                                                              //tp_free
636         0,                                                              //tp_is_gc
637         0,                                                              //tp_bases
638         0,                                                              //tp_mro
639         0,                                                              //tp_cache
640         0,                                                              //tp_subclasses
641         0,                                                              //tp_weaklist
642         0                                                               //tp_del
643 };
644 //------------------------newEulerObject (internal)-------------
645 //creates a new euler object
646 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
647  (i.e. it was allocated elsewhere by MEM_mallocN())
648   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
649  (i.e. it must be created here with PyMEM_malloc())*/
650 PyObject *newEulerObject(float *eul, int type, PyTypeObject *base_type)
651 {
652         EulerObject *self;
653         int x;
654
655         if(base_type)   self = (EulerObject *)base_type->tp_alloc(base_type, 0);
656         else                    self = PyObject_NEW(EulerObject, &euler_Type);
657
658         /* init callbacks as NULL */
659         self->cb_user= NULL;
660         self->cb_type= self->cb_subtype= 0;
661
662         if(type == Py_WRAP){
663                 self->eul = eul;
664                 self->wrapped = Py_WRAP;
665         }else if (type == Py_NEW){
666                 self->eul = PyMem_Malloc(3 * sizeof(float));
667                 if(!eul) { //new empty
668                         for(x = 0; x < 3; x++) {
669                                 self->eul[x] = 0.0f;
670                         }
671                 }else{
672                         VECCOPY(self->eul, eul);
673                 }
674                 self->wrapped = Py_NEW;
675         }else{ //bad type
676                 return NULL;
677         }
678         return (PyObject *)self;
679 }
680
681 PyObject *newEulerObject_cb(PyObject *cb_user, int cb_type, int cb_subtype)
682 {
683         EulerObject *self= (EulerObject *)newEulerObject(NULL, Py_NEW, NULL);
684         if(self) {
685                 Py_INCREF(cb_user);
686                 self->cb_user=                  cb_user;
687                 self->cb_type=                  (unsigned char)cb_type;
688                 self->cb_subtype=               (unsigned char)cb_subtype;
689         }
690
691         return (PyObject *)self;
692 }