ObColor wasnt converted into an RNA string.
[blender.git] / source / blender / python / generic / euler.c
1 /*
2  * $Id: euler.c 20248 2009-05-18 04:11:54Z campbellbarton $
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_arithb.h"
32 #include "BKE_utildefines.h"
33 #include "BLI_blenlib.h"
34
35
36 //-------------------------DOC STRINGS ---------------------------
37 static char Euler_Zero_doc[] = "() - set all values in the euler to 0";
38 static char Euler_Unique_doc[] ="() - sets the euler rotation a unique shortest arc rotation - tests for gimbal lock";
39 static char Euler_ToMatrix_doc[] =      "() - returns a rotation matrix representing the euler rotation";
40 static char Euler_ToQuat_doc[] = "() - returns a quaternion representing the euler rotation";
41 static char Euler_Rotate_doc[] = "() - rotate a euler by certain amount around an axis of rotation";
42 static char Euler_copy_doc[] = "() - returns a copy of the euler.";
43 static char Euler_MakeCompatible_doc[] = "(euler) - Make this user compatible with another (no axis flipping).";
44
45 static PyObject *Euler_Zero( EulerObject * self );
46 static PyObject *Euler_Unique( EulerObject * self );
47 static PyObject *Euler_ToMatrix( EulerObject * self );
48 static PyObject *Euler_ToQuat( EulerObject * self );
49 static PyObject *Euler_Rotate( EulerObject * self, PyObject *args );
50 static PyObject *Euler_MakeCompatible( EulerObject * self, EulerObject *value );
51 static PyObject *Euler_copy( EulerObject * self, PyObject *args );
52
53 //-----------------------METHOD DEFINITIONS ----------------------
54 static struct PyMethodDef Euler_methods[] = {
55         {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
56         {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
57         {"toMatrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
58         {"toQuat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
59         {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc},
60         {"makeCompatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
61         {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
62         {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
63         {NULL, NULL, 0, NULL}
64 };
65
66 //----------------------------------Mathutils.Euler() -------------------
67 //makes a new euler for you to play with
68 static PyObject *Euler_new(PyObject * self, PyObject * args)
69 {
70
71         PyObject *listObject = NULL;
72         int size, i;
73         float eul[3], scalar;
74         PyObject *e;
75
76         size = PyTuple_GET_SIZE(args);
77         if (size == 1) {
78                 listObject = PyTuple_GET_ITEM(args, 0);
79                 if (PySequence_Check(listObject)) {
80                         size = PySequence_Length(listObject);
81                 } else { // Single argument was not a sequence
82                         PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
83                         return NULL;
84                 }
85         } else if (size == 0) {
86                 //returns a new empty 3d euler
87                 return newEulerObject(NULL, Py_NEW); 
88         } else {
89                 listObject = args;
90         }
91
92         if (size != 3) { // Invalid euler size
93                 PyErr_SetString(PyExc_AttributeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
94                 return NULL;
95         }
96
97         for (i=0; i<size; i++) {
98                 e = PySequence_GetItem(listObject, i);
99                 if (e == NULL) { // Failed to read sequence
100                         Py_DECREF(listObject);
101                         PyErr_SetString(PyExc_RuntimeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
102                         return NULL;
103                 }
104
105                 scalar= (float)PyFloat_AsDouble(e);
106                 Py_DECREF(e);
107                 
108                 if(scalar==-1 && PyErr_Occurred()) { // parsed item is not a number
109                         PyErr_SetString(PyExc_TypeError, "Mathutils.Euler(): 3d numeric sequence expected\n");
110                         return NULL;
111                 }
112
113                 eul[i]= scalar;
114         }
115         return newEulerObject(eul, Py_NEW);
116 }
117
118 //-----------------------------METHODS----------------------------
119 //----------------------------Euler.toQuat()----------------------
120 //return a quaternion representation of the euler
121 static PyObject *Euler_ToQuat(EulerObject * self)
122 {
123         float eul[3], quat[4];
124         int x;
125
126         for(x = 0; x < 3; x++) {
127                 eul[x] = self->eul[x] * ((float)Py_PI / 180);
128         }
129         EulToQuat(eul, quat);
130         return newQuaternionObject(quat, Py_NEW);
131 }
132 //----------------------------Euler.toMatrix()---------------------
133 //return a matrix representation of the euler
134 static PyObject *Euler_ToMatrix(EulerObject * self)
135 {
136         float eul[3];
137         float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
138         int x;
139
140         for(x = 0; x < 3; x++) {
141                 eul[x] = self->eul[x] * ((float)Py_PI / 180);
142         }
143         EulToMat3(eul, (float (*)[3]) mat);
144         return newMatrixObject(mat, 3, 3 , Py_NEW);
145 }
146 //----------------------------Euler.unique()-----------------------
147 //sets the x,y,z values to a unique euler rotation
148 static PyObject *Euler_Unique(EulerObject * self)
149 {
150         double heading, pitch, bank;
151         double pi2 =  Py_PI * 2.0f;
152         double piO2 = Py_PI / 2.0f;
153         double Opi2 = 1.0f / pi2;
154
155         //radians
156         heading = self->eul[0] * (float)Py_PI / 180;
157         pitch = self->eul[1] * (float)Py_PI / 180;
158         bank = self->eul[2] * (float)Py_PI / 180;
159
160         //wrap heading in +180 / -180
161         pitch += Py_PI;
162         pitch -= floor(pitch * Opi2) * pi2;
163         pitch -= Py_PI;
164
165
166         if(pitch < -piO2) {
167                 pitch = -Py_PI - pitch;
168                 heading += Py_PI;
169                 bank += Py_PI;
170         } else if(pitch > piO2) {
171                 pitch = Py_PI - pitch;
172                 heading += Py_PI;
173                 bank += Py_PI;
174         }
175         //gimbal lock test
176         if(fabs(pitch) > piO2 - 1e-4) {
177                 heading += bank;
178                 bank = 0.0f;
179         } else {
180                 bank += Py_PI;
181                 bank -= (floor(bank * Opi2)) * pi2;
182                 bank -= Py_PI;
183         }
184
185         heading += Py_PI;
186         heading -= (floor(heading * Opi2)) * pi2;
187         heading -= Py_PI;
188
189         //back to degrees
190         self->eul[0] = (float)(heading * 180 / (float)Py_PI);
191         self->eul[1] = (float)(pitch * 180 / (float)Py_PI);
192         self->eul[2] = (float)(bank * 180 / (float)Py_PI);
193
194         Py_INCREF(self);
195         return (PyObject *)self;
196 }
197 //----------------------------Euler.zero()-------------------------
198 //sets the euler to 0,0,0
199 static PyObject *Euler_Zero(EulerObject * self)
200 {
201         self->eul[0] = 0.0;
202         self->eul[1] = 0.0;
203         self->eul[2] = 0.0;
204
205         Py_INCREF(self);
206         return (PyObject *)self;
207 }
208 //----------------------------Euler.rotate()-----------------------
209 //rotates a euler a certain amount and returns the result
210 //should return a unique euler rotation (i.e. no 720 degree pitches :)
211 static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
212 {
213         float angle = 0.0f;
214         char *axis;
215         int x;
216
217         if(!PyArg_ParseTuple(args, "fs", &angle, &axis)){
218                 PyErr_SetString(PyExc_TypeError, "euler.rotate():expected angle (float) and axis (x,y,z)");
219                 return NULL;
220         }
221         if(!STREQ3(axis,"x","y","z")){
222                 PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'x', 'y' or 'z'");
223                 return NULL;
224         }
225
226         //covert to radians
227         angle *= ((float)Py_PI / 180);
228         for(x = 0; x < 3; x++) {
229                 self->eul[x] *= ((float)Py_PI / 180);
230         }
231         euler_rot(self->eul, angle, *axis);
232         //convert back from radians
233         for(x = 0; x < 3; x++) {
234                 self->eul[x] *= (180 / (float)Py_PI);
235         }
236
237         Py_INCREF(self);
238         return (PyObject *)self;
239 }
240
241 static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
242 {
243         float eul_from_rad[3];
244         int x;
245         
246         if(!EulerObject_Check(value)) {
247                 PyErr_SetString(PyExc_TypeError, "euler.makeCompatible(euler):expected a single euler argument.");
248                 return NULL;
249         }
250         
251         //covert to radians
252         for(x = 0; x < 3; x++) {
253                 self->eul[x] = self->eul[x] * ((float)Py_PI / 180);
254                 eul_from_rad[x] = value->eul[x] * ((float)Py_PI / 180);
255         }
256         compatible_eul(self->eul, eul_from_rad);
257         //convert back from radians
258         for(x = 0; x < 3; x++) {
259                 self->eul[x] *= (180 / (float)Py_PI);
260         }
261         
262         Py_INCREF(self);
263         return (PyObject *)self;
264 }
265
266 //----------------------------Euler.rotate()-----------------------
267 // return a copy of the euler
268 static PyObject *Euler_copy(EulerObject * self, PyObject *args)
269 {
270         return newEulerObject(self->eul, Py_NEW);
271 }
272
273
274 //----------------------------dealloc()(internal) ------------------
275 //free the py_object
276 static void Euler_dealloc(EulerObject * self)
277 {
278         //only free py_data
279         if(self->data.py_data){
280                 PyMem_Free(self->data.py_data);
281         }
282         PyObject_DEL(self);
283 }
284
285 //----------------------------print object (internal)--------------
286 //print the object to screen
287 static PyObject *Euler_repr(EulerObject * self)
288 {
289         char str[64];
290         sprintf(str, "[%.6f, %.6f, %.6f](euler)", self->eul[0], self->eul[1], self->eul[2]);
291         return PyUnicode_FromString(str);
292 }
293 //------------------------tp_richcmpr
294 //returns -1 execption, 0 false, 1 true
295 static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
296 {
297         EulerObject *eulA = NULL, *eulB = NULL;
298         int result = 0;
299
300         if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){
301                 if (comparison_type == Py_NE){
302                         Py_RETURN_TRUE;
303                 }else{
304                         Py_RETURN_FALSE;
305                 }
306         }
307         eulA = (EulerObject*)objectA;
308         eulB = (EulerObject*)objectB;
309
310         switch (comparison_type){
311                 case Py_EQ:
312                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
313                         break;
314                 case Py_NE:
315                         result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
316                         if (result == 0){
317                                 result = 1;
318                         }else{
319                                 result = 0;
320                         }
321                         break;
322                 default:
323                         printf("The result of the comparison could not be evaluated");
324                         break;
325         }
326         if (result == 1){
327                 Py_RETURN_TRUE;
328         }else{
329                 Py_RETURN_FALSE;
330         }
331 }
332 //------------------------tp_doc
333 static char EulerObject_doc[] = "This is a wrapper for euler objects.";
334 //---------------------SEQUENCE PROTOCOLS------------------------
335 //----------------------------len(object)------------------------
336 //sequence length
337 static int Euler_len(EulerObject * self)
338 {
339         return 3;
340 }
341 //----------------------------object[]---------------------------
342 //sequence accessor (get)
343 static PyObject *Euler_item(EulerObject * self, int i)
344 {
345         if(i<0)
346                 i= 3-i;
347         
348         if(i < 0 || i >= 3) {
349                 PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
350                 return NULL;
351         }
352         return PyFloat_FromDouble(self->eul[i]);
353
354 }
355 //----------------------------object[]-------------------------
356 //sequence accessor (set)
357 static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
358 {
359         float f = PyFloat_AsDouble(value);
360
361         if(f == -1 && PyErr_Occurred()) { // parsed item not a number
362                 PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
363                 return -1;
364         }
365
366         if(i<0)
367                 i= 3-i;
368         
369         if(i < 0 || i >= 3){
370                 PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
371                 return -1;
372         }
373         
374         self->eul[i] = f;
375         return 0;
376 }
377 //----------------------------object[z:y]------------------------
378 //sequence slice (get)
379 static PyObject *Euler_slice(EulerObject * self, int begin, int end)
380 {
381         PyObject *list = NULL;
382         int count;
383
384         CLAMP(begin, 0, 3);
385         if (end<0) end= 4+end;
386         CLAMP(end, 0, 3);
387         begin = MIN2(begin,end);
388
389         list = PyList_New(end - begin);
390         for(count = begin; count < end; count++) {
391                 PyList_SetItem(list, count - begin,
392                                 PyFloat_FromDouble(self->eul[count]));
393         }
394
395         return list;
396 }
397 //----------------------------object[z:y]------------------------
398 //sequence slice (set)
399 static int Euler_ass_slice(EulerObject * self, int begin, int end,
400                              PyObject * seq)
401 {
402         int i, y, size = 0;
403         float eul[3];
404         PyObject *e, *f;
405
406         CLAMP(begin, 0, 3);
407         if (end<0) end= 4+end;
408         CLAMP(end, 0, 3);
409         begin = MIN2(begin,end);
410
411         size = PySequence_Length(seq);
412         if(size != (end - begin)){
413                 PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
414                 return -1;
415         }
416
417         for (i = 0; i < size; i++) {
418                 e = PySequence_GetItem(seq, i);
419                 if (e == NULL) { // Failed to read sequence
420                         PyErr_SetString(PyExc_RuntimeError, "euler[begin:end] = []: unable to read sequence");
421                         return -1;
422                 }
423
424                 f = PyNumber_Float(e);
425                 if(f == NULL) { // parsed item not a number
426                         Py_DECREF(e);
427                         PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: sequence argument not a number");
428                         return -1;
429                 }
430
431                 eul[i] = (float)PyFloat_AS_DOUBLE(f);
432                 Py_DECREF(f);
433                 Py_DECREF(e);
434         }
435         //parsed well - now set in vector
436         for(y = 0; y < 3; y++){
437                 self->eul[begin + y] = eul[y];
438         }
439         return 0;
440 }
441 //-----------------PROTCOL DECLARATIONS--------------------------
442 static PySequenceMethods Euler_SeqMethods = {
443         (inquiry) Euler_len,                                            /* sq_length */
444         (binaryfunc) 0,                                                         /* sq_concat */
445         (ssizeargfunc) 0,                                                               /* sq_repeat */
446         (ssizeargfunc) Euler_item,                                      /* sq_item */
447         (ssizessizeargfunc) Euler_slice,                                /* sq_slice */
448         (ssizeobjargproc) Euler_ass_item,                               /* sq_ass_item */
449         (ssizessizeobjargproc) Euler_ass_slice,                 /* sq_ass_slice */
450 };
451
452
453
454 /*
455  * vector axis, vector.x/y/z/w
456  */
457         
458 static PyObject *Euler_getAxis( EulerObject * self, void *type )
459 {
460         switch( (long)type ) {
461     case 'X':   /* these are backwards, but that how it works */
462                 return PyFloat_FromDouble(self->eul[0]);
463     case 'Y':
464                 return PyFloat_FromDouble(self->eul[1]);
465     case 'Z':
466                 return PyFloat_FromDouble(self->eul[2]);
467         }
468         
469         PyErr_SetString(PyExc_SystemError, "corrupt euler, cannot get axis");
470         return NULL;
471 }
472
473 static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
474 {
475         float param= (float)PyFloat_AsDouble( value );
476         
477         if (param==-1 && PyErr_Occurred()) {
478                 PyErr_SetString(PyExc_TypeError, "expected a number for the vector axis");
479                 return -1;
480         }
481         
482         switch( (long)type ) {
483     case 'X':   /* these are backwards, but that how it works */
484                 self->eul[0]= param;
485                 break;
486     case 'Y':
487                 self->eul[1]= param;
488                 break;
489     case 'Z':
490                 self->eul[2]= param;
491                 break;
492         }
493
494         return 0;
495 }
496
497 static PyObject *Euler_getWrapped( VectorObject * self, void *type )
498 {
499         if (self->wrapped == Py_WRAP)
500                 Py_RETURN_TRUE;
501         else
502                 Py_RETURN_FALSE;
503 }
504
505
506 /*****************************************************************************/
507 /* Python attributes get/set structure:                                      */
508 /*****************************************************************************/
509 static PyGetSetDef Euler_getseters[] = {
510         {"x",
511          (getter)Euler_getAxis, (setter)Euler_setAxis,
512          "Euler X axis",
513          (void *)'X'},
514         {"y",
515          (getter)Euler_getAxis, (setter)Euler_setAxis,
516          "Euler Y axis",
517          (void *)'Y'},
518         {"z",
519          (getter)Euler_getAxis, (setter)Euler_setAxis,
520          "Euler Z axis",
521          (void *)'Z'},
522         {"wrapped",
523          (getter)Euler_getWrapped, (setter)NULL,
524          "True when this wraps blenders internal data",
525          NULL},
526         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
527 };
528
529 //------------------PY_OBECT DEFINITION--------------------------
530 PyTypeObject euler_Type = {
531 #if (PY_VERSION_HEX >= 0x02060000)
532         PyVarObject_HEAD_INIT(NULL, 0)
533 #else
534         /* python 2.5 and below */
535         PyObject_HEAD_INIT( NULL )  /* required py macro */
536         0,                          /* ob_size */
537 #endif
538         "euler",                                                //tp_name
539         sizeof(EulerObject),                    //tp_basicsize
540         0,                                                              //tp_itemsize
541         (destructor)Euler_dealloc,              //tp_dealloc
542         0,                                                              //tp_print
543         0,                                                              //tp_getattr
544         0,                                                              //tp_setattr
545         0,                                                              //tp_compare
546         (reprfunc) Euler_repr,                  //tp_repr
547         0,                              //tp_as_number
548         &Euler_SeqMethods,                              //tp_as_sequence
549         0,                                                              //tp_as_mapping
550         0,                                                              //tp_hash
551         0,                                                              //tp_call
552         0,                                                              //tp_str
553         0,                                                              //tp_getattro
554         0,                                                              //tp_setattro
555         0,                                                              //tp_as_buffer
556         Py_TPFLAGS_DEFAULT,                             //tp_flags
557         EulerObject_doc,                                //tp_doc
558         0,                                                              //tp_traverse
559         0,                                                              //tp_clear
560         (richcmpfunc)Euler_richcmpr,    //tp_richcompare
561         0,                                                              //tp_weaklistoffset
562         0,                                                              //tp_iter
563         0,                                                              //tp_iternext
564         Euler_methods,                                  //tp_methods
565         0,                                                              //tp_members
566         Euler_getseters,                                //tp_getset
567         0,                                                              //tp_base
568         0,                                                              //tp_dict
569         0,                                                              //tp_descr_get
570         0,                                                              //tp_descr_set
571         0,                                                              //tp_dictoffset
572         0,                                                              //tp_init
573         0,                                                              //tp_alloc
574         Euler_new,                                              //tp_new
575         0,                                                              //tp_free
576         0,                                                              //tp_is_gc
577         0,                                                              //tp_bases
578         0,                                                              //tp_mro
579         0,                                                              //tp_cache
580         0,                                                              //tp_subclasses
581         0,                                                              //tp_weaklist
582         0                                                               //tp_del
583 };
584 //------------------------newEulerObject (internal)-------------
585 //creates a new euler object
586 /*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
587  (i.e. it was allocated elsewhere by MEM_mallocN())
588   pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
589  (i.e. it must be created here with PyMEM_malloc())*/
590 PyObject *newEulerObject(float *eul, int type)
591 {
592         EulerObject *self;
593         int x;
594
595         self = PyObject_NEW(EulerObject, &euler_Type);
596         self->data.blend_data = NULL;
597         self->data.py_data = NULL;
598
599         if(type == Py_WRAP){
600                 self->data.blend_data = eul;
601                 self->eul = self->data.blend_data;
602                 self->wrapped = Py_WRAP;
603         }else if (type == Py_NEW){
604                 self->data.py_data = PyMem_Malloc(3 * sizeof(float));
605                 self->eul = self->data.py_data;
606                 if(!eul) { //new empty
607                         for(x = 0; x < 3; x++) {
608                                 self->eul[x] = 0.0f;
609                         }
610                 }else{
611                         for(x = 0; x < 3; x++){
612                                 self->eul[x] = eul[x];
613                         }
614                 }
615                 self->wrapped = Py_NEW;
616         }else{ //bad type
617                 return NULL;
618         }
619         return (PyObject *)self;
620 }