~siretart/ubuntu/utopic/blender/libav10

« back to all changes in this revision

Viewing changes to source/blender/python/generic/mathutils_euler.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2012-07-23 08:54:18 UTC
  • mfrom: (14.2.16 sid)
  • mto: (14.2.19 sid)
  • mto: This revision was merged to the branch mainline in revision 42.
  • Revision ID: package-import@ubuntu.com-20120723085418-9foz30v6afaf5ffs
Tags: 2.63a-2
* debian/: Cycles support added (Closes: #658075)
  For now, this top feature has been enabled only
  on [any-amd64 any-i386] architectures because
  of OpenImageIO failing on all others
* debian/: scripts installation path changed
  from /usr/lib to /usr/share:
  + debian/patches/: patchset re-worked for path changing
  + debian/control: "Breaks" field added on yafaray-exporter

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: mathutils_euler.c 28786 2010-05-16 10:09:07Z 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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
 
 
34
 
#ifndef int32_t
35
 
#include "BLO_sys_types.h"
36
 
#endif
37
 
 
38
 
#define EULER_SIZE 3
39
 
 
40
 
//----------------------------------mathutils.Euler() -------------------
41
 
//makes a new euler for you to play with
42
 
static PyObject *Euler_new(PyTypeObject * type, PyObject * args, PyObject * kwargs)
43
 
{
44
 
        PyObject *seq= NULL;
45
 
        char *order_str= NULL;
46
 
 
47
 
        float eul[EULER_SIZE]= {0.0f, 0.0f, 0.0f};
48
 
        short order= EULER_ORDER_XYZ;
49
 
 
50
 
        if(!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str))
51
 
                return NULL;
52
 
 
53
 
        switch(PyTuple_GET_SIZE(args)) {
54
 
        case 0:
55
 
                break;
56
 
        case 2:
57
 
                if((order=euler_order_from_string(order_str, "mathutils.Euler()")) == -1)
58
 
                        return NULL;
59
 
                /* intentionally pass through */
60
 
        case 1:
61
 
                if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1)
62
 
                        return NULL;
63
 
                break;
64
 
        }
65
 
        return newEulerObject(eul, order, Py_NEW, NULL);
66
 
}
67
 
 
68
 
short euler_order_from_string(const char *str, const char *error_prefix)
69
 
{
70
 
        if((str[0] && str[1] && str[2] && str[3]=='\0')) {
71
 
                switch(*((int32_t *)str)) {
72
 
                        case 'X'|'Y'<<8|'Z'<<16:        return EULER_ORDER_XYZ;
73
 
                        case 'X'|'Z'<<8|'Y'<<16:        return EULER_ORDER_XZY;
74
 
                        case 'Y'|'X'<<8|'Z'<<16:        return EULER_ORDER_YXZ;
75
 
                        case 'Y'|'Z'<<8|'X'<<16:        return EULER_ORDER_YZX;
76
 
                        case 'Z'|'X'<<8|'Y'<<16:        return EULER_ORDER_ZXY;
77
 
                        case 'Z'|'Y'<<8|'X'<<16:        return EULER_ORDER_ZYX;
78
 
                }
79
 
        }
80
 
 
81
 
        PyErr_Format(PyExc_TypeError, "%s: invalid euler order '%s'", error_prefix, str);
82
 
        return -1;
83
 
}
84
 
 
85
 
/* note: BaseMath_ReadCallback must be called beforehand */
86
 
static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
87
 
{
88
 
        PyObject *ret;
89
 
        int i;
90
 
 
91
 
        ret= PyTuple_New(EULER_SIZE);
92
 
 
93
 
        if(ndigits >= 0) {
94
 
                for(i= 0; i < EULER_SIZE; i++) {
95
 
                        PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits)));
96
 
                }
97
 
        }
98
 
        else {
99
 
                for(i= 0; i < EULER_SIZE; i++) {
100
 
                        PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i]));
101
 
                }
102
 
        }
103
 
 
104
 
        return ret;
105
 
}
106
 
 
107
 
//-----------------------------METHODS----------------------------
108
 
//return a quaternion representation of the euler
109
 
 
110
 
static char Euler_ToQuat_doc[] =
111
 
".. method:: to_quat()\n"
112
 
"\n"
113
 
"   Return a quaternion representation of the euler.\n"
114
 
"\n"
115
 
"   :return: Quaternion representation of the euler.\n"
116
 
"   :rtype: :class:`Quaternion`\n";
117
 
 
118
 
static PyObject *Euler_ToQuat(EulerObject * self)
119
 
{
120
 
        float quat[4];
121
 
 
122
 
        if(!BaseMath_ReadCallback(self))
123
 
                return NULL;
124
 
 
125
 
        if(self->order==EULER_ORDER_XYZ)        eul_to_quat(quat, self->eul);
126
 
        else                                                            eulO_to_quat(quat, self->eul, self->order);
127
 
 
128
 
        return newQuaternionObject(quat, Py_NEW, NULL);
129
 
}
130
 
 
131
 
//return a matrix representation of the euler
132
 
static char Euler_ToMatrix_doc[] =
133
 
".. method:: to_matrix()\n"
134
 
"\n"
135
 
"   Return a matrix representation of the euler.\n"
136
 
"\n"
137
 
"   :return: A 3x3 roation matrix representation of the euler.\n"
138
 
"   :rtype: :class:`Matrix`\n";
139
 
 
140
 
static PyObject *Euler_ToMatrix(EulerObject * self)
141
 
{
142
 
        float mat[9] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
143
 
 
144
 
        if(!BaseMath_ReadCallback(self))
145
 
                return NULL;
146
 
 
147
 
        if(self->order==EULER_ORDER_XYZ)        eul_to_mat3((float (*)[3])mat, self->eul);
148
 
        else                                                            eulO_to_mat3((float (*)[3])mat, self->eul, self->order);
149
 
 
150
 
        return newMatrixObject(mat, 3, 3 , Py_NEW, NULL);
151
 
}
152
 
 
153
 
//sets the x,y,z values to a unique euler rotation
154
 
// TODO, check if this works with rotation order!!!
155
 
static char Euler_Unique_doc[] =
156
 
".. method:: unique()\n"
157
 
"\n"
158
 
"   Calculate a unique rotation for this euler. Avoids gimble lock.\n"
159
 
"\n"
160
 
"   :return: an instance of itself\n"
161
 
"   :rtype: :class:`Euler`\n";
162
 
 
163
 
static PyObject *Euler_Unique(EulerObject * self)
164
 
{
165
 
#define PI_2            (Py_PI * 2.0)
166
 
#define PI_HALF         (Py_PI / 2.0)
167
 
#define PI_INV          (1.0 / Py_PI)
168
 
 
169
 
        double heading, pitch, bank;
170
 
 
171
 
        if(!BaseMath_ReadCallback(self))
172
 
                return NULL;
173
 
 
174
 
        heading = self->eul[0];
175
 
        pitch = self->eul[1];
176
 
        bank = self->eul[2];
177
 
 
178
 
        //wrap heading in +180 / -180
179
 
        pitch += Py_PI;
180
 
        pitch -= floor(pitch * PI_INV) * PI_2;
181
 
        pitch -= Py_PI;
182
 
 
183
 
 
184
 
        if(pitch < -PI_HALF) {
185
 
                pitch = -Py_PI - pitch;
186
 
                heading += Py_PI;
187
 
                bank += Py_PI;
188
 
        } else if(pitch > PI_HALF) {
189
 
                pitch = Py_PI - pitch;
190
 
                heading += Py_PI;
191
 
                bank += Py_PI;
192
 
        }
193
 
        //gimbal lock test
194
 
        if(fabs(pitch) > PI_HALF - 1e-4) {
195
 
                heading += bank;
196
 
                bank = 0.0f;
197
 
        } else {
198
 
                bank += Py_PI;
199
 
                bank -= (floor(bank * PI_INV)) * PI_2;
200
 
                bank -= Py_PI;
201
 
        }
202
 
 
203
 
        heading += Py_PI;
204
 
        heading -= (floor(heading * PI_INV)) * PI_2;
205
 
        heading -= Py_PI;
206
 
 
207
 
        BaseMath_WriteCallback(self);
208
 
        Py_INCREF(self);
209
 
        return (PyObject *)self;
210
 
}
211
 
 
212
 
//sets the euler to 0,0,0
213
 
static char Euler_Zero_doc[] =
214
 
".. method:: zero()\n"
215
 
"\n"
216
 
"   Set all values to zero.\n"
217
 
"\n"
218
 
"   :return: an instance of itself\n"
219
 
"   :rtype: :class:`Euler`\n";
220
 
 
221
 
static PyObject *Euler_Zero(EulerObject * self)
222
 
{
223
 
        self->eul[0] = 0.0;
224
 
        self->eul[1] = 0.0;
225
 
        self->eul[2] = 0.0;
226
 
 
227
 
        BaseMath_WriteCallback(self);
228
 
        Py_INCREF(self);
229
 
        return (PyObject *)self;
230
 
}
231
 
 
232
 
static char Euler_Rotate_doc[] =
233
 
".. method:: rotate(angle, axis)\n"
234
 
"\n"
235
 
"   Rotates the euler a certain amount and returning a unique euler rotation (no 720 degree pitches).\n"
236
 
"\n"
237
 
"   :arg angle: angle in radians.\n"
238
 
"   :type angle: float\n"
239
 
"   :arg axis: single character in ['X, 'Y', 'Z'].\n"
240
 
"   :type axis: string\n"
241
 
"   :return: an instance of itself\n"
242
 
"   :rtype: :class:`Euler`";
243
 
 
244
 
static PyObject *Euler_Rotate(EulerObject * self, PyObject *args)
245
 
{
246
 
        float angle = 0.0f;
247
 
        char *axis;
248
 
 
249
 
        if(!PyArg_ParseTuple(args, "fs:rotate", &angle, &axis)){
250
 
                PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected angle (float) and axis (x,y,z)");
251
 
                return NULL;
252
 
        }
253
 
        if(ELEM3(*axis, 'X', 'Y', 'Z') && axis[1]=='\0'){
254
 
                PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'X', 'Y' or 'Z'");
255
 
                return NULL;
256
 
        }
257
 
 
258
 
        if(!BaseMath_ReadCallback(self))
259
 
                return NULL;
260
 
 
261
 
        if(self->order == EULER_ORDER_XYZ)      rotate_eul(self->eul, *axis, angle);
262
 
        else                                                            rotate_eulO(self->eul, self->order, *axis, angle);
263
 
 
264
 
        BaseMath_WriteCallback(self);
265
 
        Py_INCREF(self);
266
 
        return (PyObject *)self;
267
 
}
268
 
 
269
 
static char Euler_MakeCompatible_doc[] =
270
 
".. method:: make_compatible(other)\n"
271
 
"\n"
272
 
"   Make this euler compatible with another, so interpolating between them works as intended.\n"
273
 
"\n"
274
 
"   :arg other: make compatible with this rotation.\n"
275
 
"   :type other: :class:`Euler`\n"
276
 
"   :return: an instance of itself.\n"
277
 
"   :rtype: :class:`Euler`\n"
278
 
"\n"
279
 
"   .. note:: the order of eulers must match or an exception is raised.\n";
280
 
 
281
 
static PyObject *Euler_MakeCompatible(EulerObject * self, EulerObject *value)
282
 
{
283
 
        if(!EulerObject_Check(value)) {
284
 
                PyErr_SetString(PyExc_TypeError, "euler.make_compatible(euler): expected a single euler argument.");
285
 
                return NULL;
286
 
        }
287
 
        
288
 
        if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value))
289
 
                return NULL;
290
 
 
291
 
        if(self->order != value->order) {
292
 
                PyErr_SetString(PyExc_ValueError, "euler.make_compatible(euler): rotation orders don't match\n");
293
 
                return NULL;
294
 
        }
295
 
 
296
 
        compatible_eul(self->eul, value->eul);
297
 
 
298
 
        BaseMath_WriteCallback(self);
299
 
        Py_INCREF(self);
300
 
        return (PyObject *)self;
301
 
}
302
 
 
303
 
//----------------------------Euler.rotate()-----------------------
304
 
// return a copy of the euler
305
 
 
306
 
static char Euler_copy_doc[] =
307
 
".. function:: copy()\n"
308
 
"\n"
309
 
"   Returns a copy of this euler.\n"
310
 
"\n"
311
 
"   :return: A copy of the euler.\n"
312
 
"   :rtype: :class:`Euler`\n"
313
 
"\n"
314
 
"   .. note:: use this to get a copy of a wrapped euler with no reference to the original data.\n";
315
 
 
316
 
static PyObject *Euler_copy(EulerObject * self, PyObject *args)
317
 
{
318
 
        if(!BaseMath_ReadCallback(self))
319
 
                return NULL;
320
 
 
321
 
        return newEulerObject(self->eul, self->order, Py_NEW, Py_TYPE(self));
322
 
}
323
 
 
324
 
//----------------------------print object (internal)--------------
325
 
//print the object to screen
326
 
 
327
 
static PyObject *Euler_repr(EulerObject * self)
328
 
{
329
 
        PyObject *ret, *tuple;
330
 
        
331
 
        if(!BaseMath_ReadCallback(self))
332
 
                return NULL;
333
 
 
334
 
        tuple= Euler_ToTupleExt(self, -1);
335
 
 
336
 
        ret= PyUnicode_FromFormat("Euler(%R)", tuple);
337
 
 
338
 
        Py_DECREF(tuple);
339
 
        return ret;
340
 
}
341
 
 
342
 
//------------------------tp_richcmpr
343
 
//returns -1 execption, 0 false, 1 true
344
 
static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
345
 
{
346
 
        EulerObject *eulA = NULL, *eulB = NULL;
347
 
        int result = 0;
348
 
 
349
 
        if(EulerObject_Check(objectA)) {
350
 
                eulA = (EulerObject*)objectA;
351
 
                if(!BaseMath_ReadCallback(eulA))
352
 
                        return NULL;
353
 
        }
354
 
        if(EulerObject_Check(objectB)) {
355
 
                eulB = (EulerObject*)objectB;
356
 
                if(!BaseMath_ReadCallback(eulB))
357
 
                        return NULL;
358
 
        }
359
 
 
360
 
        if (!eulA || !eulB){
361
 
                if (comparison_type == Py_NE){
362
 
                        Py_RETURN_TRUE;
363
 
                }else{
364
 
                        Py_RETURN_FALSE;
365
 
                }
366
 
        }
367
 
        eulA = (EulerObject*)objectA;
368
 
        eulB = (EulerObject*)objectB;
369
 
 
370
 
        switch (comparison_type){
371
 
                case Py_EQ:
372
 
                        result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1);
373
 
                        break;
374
 
                case Py_NE:
375
 
                        result = !EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1);
376
 
                        break;
377
 
                default:
378
 
                        printf("The result of the comparison could not be evaluated");
379
 
                        break;
380
 
        }
381
 
        if (result == 1){
382
 
                Py_RETURN_TRUE;
383
 
        }else{
384
 
                Py_RETURN_FALSE;
385
 
        }
386
 
}
387
 
 
388
 
//---------------------SEQUENCE PROTOCOLS------------------------
389
 
//----------------------------len(object)------------------------
390
 
//sequence length
391
 
static int Euler_len(EulerObject * self)
392
 
{
393
 
        return EULER_SIZE;
394
 
}
395
 
//----------------------------object[]---------------------------
396
 
//sequence accessor (get)
397
 
static PyObject *Euler_item(EulerObject * self, int i)
398
 
{
399
 
        if(i<0) i= EULER_SIZE-i;
400
 
        
401
 
        if(i < 0 || i >= EULER_SIZE) {
402
 
                PyErr_SetString(PyExc_IndexError, "euler[attribute]: array index out of range");
403
 
                return NULL;
404
 
        }
405
 
 
406
 
        if(!BaseMath_ReadIndexCallback(self, i))
407
 
                return NULL;
408
 
 
409
 
        return PyFloat_FromDouble(self->eul[i]);
410
 
 
411
 
}
412
 
//----------------------------object[]-------------------------
413
 
//sequence accessor (set)
414
 
static int Euler_ass_item(EulerObject * self, int i, PyObject * value)
415
 
{
416
 
        float f = PyFloat_AsDouble(value);
417
 
 
418
 
        if(f == -1 && PyErr_Occurred()) { // parsed item not a number
419
 
                PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number");
420
 
                return -1;
421
 
        }
422
 
 
423
 
        if(i<0) i= EULER_SIZE-i;
424
 
        
425
 
        if(i < 0 || i >= EULER_SIZE){
426
 
                PyErr_SetString(PyExc_IndexError, "euler[attribute] = x: array assignment index out of range\n");
427
 
                return -1;
428
 
        }
429
 
        
430
 
        self->eul[i] = f;
431
 
 
432
 
        if(!BaseMath_WriteIndexCallback(self, i))
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 *list = NULL;
442
 
        int count;
443
 
 
444
 
        if(!BaseMath_ReadCallback(self))
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
 
        list = PyList_New(end - begin);
453
 
        for(count = begin; count < end; count++) {
454
 
                PyList_SetItem(list, count - begin,
455
 
                                PyFloat_FromDouble(self->eul[count]));
456
 
        }
457
 
 
458
 
        return list;
459
 
}
460
 
//----------------------------object[z:y]------------------------
461
 
//sequence slice (set)
462
 
static int Euler_ass_slice(EulerObject * self, int begin, int end, PyObject * seq)
463
 
{
464
 
        int i, size;
465
 
        float eul[EULER_SIZE];
466
 
 
467
 
        if(!BaseMath_ReadCallback(self))
468
 
                return -1;
469
 
 
470
 
        CLAMP(begin, 0, EULER_SIZE);
471
 
        if (end<0) end= (EULER_SIZE + 1) + end;
472
 
        CLAMP(end, 0, EULER_SIZE);
473
 
        begin = MIN2(begin,end);
474
 
 
475
 
        if((size=mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) == -1)
476
 
                return -1;
477
 
 
478
 
        if(size != (end - begin)){
479
 
                PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment");
480
 
                return -1;
481
 
        }
482
 
 
483
 
        for(i= 0; i < EULER_SIZE; i++)
484
 
                self->eul[begin + i] = eul[i];
485
 
 
486
 
        BaseMath_WriteCallback(self);
487
 
        return 0;
488
 
}
489
 
 
490
 
static PyObject *Euler_subscript(EulerObject *self, PyObject *item)
491
 
{
492
 
        if (PyIndex_Check(item)) {
493
 
                Py_ssize_t i;
494
 
                i = PyNumber_AsSsize_t(item, PyExc_IndexError);
495
 
                if (i == -1 && PyErr_Occurred())
496
 
                        return NULL;
497
 
                if (i < 0)
498
 
                        i += EULER_SIZE;
499
 
                return Euler_item(self, i);
500
 
        } else if (PySlice_Check(item)) {
501
 
                Py_ssize_t start, stop, step, slicelength;
502
 
 
503
 
                if (PySlice_GetIndicesEx((PySliceObject*)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
504
 
                        return NULL;
505
 
 
506
 
                if (slicelength <= 0) {
507
 
                        return PyList_New(0);
508
 
                }
509
 
                else if (step == 1) {
510
 
                        return Euler_slice(self, start, stop);
511
 
                }
512
 
                else {
513
 
                        PyErr_SetString(PyExc_TypeError, "slice steps not supported with eulers");
514
 
                        return NULL;
515
 
                }
516
 
        }
517
 
        else {
518
 
                PyErr_Format(PyExc_TypeError,
519
 
                                 "euler indices must be integers, not %.200s",
520
 
                                 item->ob_type->tp_name);
521
 
                return NULL;
522
 
        }
523
 
}
524
 
 
525
 
 
526
 
static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
527
 
{
528
 
        if (PyIndex_Check(item)) {
529
 
                Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
530
 
                if (i == -1 && PyErr_Occurred())
531
 
                        return -1;
532
 
                if (i < 0)
533
 
                        i += EULER_SIZE;
534
 
                return Euler_ass_item(self, i, value);
535
 
        }
536
 
        else if (PySlice_Check(item)) {
537
 
                Py_ssize_t start, stop, step, slicelength;
538
 
 
539
 
                if (PySlice_GetIndicesEx((PySliceObject*)item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0)
540
 
                        return -1;
541
 
 
542
 
                if (step == 1)
543
 
                        return Euler_ass_slice(self, start, stop, value);
544
 
                else {
545
 
                        PyErr_SetString(PyExc_TypeError, "slice steps not supported with euler");
546
 
                        return -1;
547
 
                }
548
 
        }
549
 
        else {
550
 
                PyErr_Format(PyExc_TypeError,
551
 
                                 "euler indices must be integers, not %.200s",
552
 
                                 item->ob_type->tp_name);
553
 
                return -1;
554
 
        }
555
 
}
556
 
 
557
 
//-----------------PROTCOL DECLARATIONS--------------------------
558
 
static PySequenceMethods Euler_SeqMethods = {
559
 
        (lenfunc) Euler_len,                                    /* sq_length */
560
 
        (binaryfunc) NULL,                                              /* sq_concat */
561
 
        (ssizeargfunc) NULL,                                    /* sq_repeat */
562
 
        (ssizeargfunc) Euler_item,                              /* sq_item */
563
 
        (ssizessizeargfunc) NULL,                               /* sq_slice, deprecated  */
564
 
        (ssizeobjargproc) Euler_ass_item,               /* sq_ass_item */
565
 
        (ssizessizeobjargproc) NULL,                    /* sq_ass_slice, deprecated */
566
 
        (objobjproc) NULL,                                              /* sq_contains */
567
 
        (binaryfunc) NULL,                                              /* sq_inplace_concat */
568
 
        (ssizeargfunc) NULL,                                    /* sq_inplace_repeat */
569
 
};
570
 
 
571
 
static PyMappingMethods Euler_AsMapping = {
572
 
        (lenfunc)Euler_len,
573
 
        (binaryfunc)Euler_subscript,
574
 
        (objobjargproc)Euler_ass_subscript
575
 
};
576
 
 
577
 
/*
578
 
 * euler axis, euler.x/y/z
579
 
 */
580
 
static PyObject *Euler_getAxis( EulerObject * self, void *type )
581
 
{
582
 
        return Euler_item(self, GET_INT_FROM_POINTER(type));
583
 
}
584
 
 
585
 
static int Euler_setAxis( EulerObject * self, PyObject * value, void * type )
586
 
{
587
 
        return Euler_ass_item(self, GET_INT_FROM_POINTER(type), value);
588
 
}
589
 
 
590
 
/* rotation order */
591
 
static PyObject *Euler_getOrder(EulerObject *self, void *type)
592
 
{
593
 
        const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
594
 
 
595
 
        if(!BaseMath_ReadCallback(self)) /* can read order too */
596
 
                return NULL;
597
 
 
598
 
        return PyUnicode_FromString(order[self->order-EULER_ORDER_XYZ]);
599
 
}
600
 
 
601
 
static int Euler_setOrder( EulerObject * self, PyObject * value, void * type )
602
 
{
603
 
        char *order_str= _PyUnicode_AsString(value);
604
 
        short order= euler_order_from_string(order_str, "euler.order");
605
 
 
606
 
        if(order == -1)
607
 
                return -1;
608
 
 
609
 
        self->order= order;
610
 
        BaseMath_WriteCallback(self); /* order can be written back */
611
 
        return 0;
612
 
}
613
 
 
614
 
/*****************************************************************************/
615
 
/* Python attributes get/set structure:                                      */
616
 
/*****************************************************************************/
617
 
static PyGetSetDef Euler_getseters[] = {
618
 
        {"x", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler X axis in radians. **type** float", (void *)0},
619
 
        {"y", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Y axis in radians. **type** float", (void *)1},
620
 
        {"z", (getter)Euler_getAxis, (setter)Euler_setAxis, "Euler Z axis in radians. **type** float", (void *)2},
621
 
        {"order", (getter)Euler_getOrder, (setter)Euler_setOrder, "Euler rotation order. **type** string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']", (void *)NULL},
622
 
 
623
 
        {"is_wrapped", (getter)BaseMathObject_getWrapped, (setter)NULL, BaseMathObject_Wrapped_doc, NULL},
624
 
        {"_owner", (getter)BaseMathObject_getOwner, (setter)NULL, BaseMathObject_Owner_doc, NULL},
625
 
        {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
626
 
};
627
 
 
628
 
 
629
 
//-----------------------METHOD DEFINITIONS ----------------------
630
 
static struct PyMethodDef Euler_methods[] = {
631
 
        {"zero", (PyCFunction) Euler_Zero, METH_NOARGS, Euler_Zero_doc},
632
 
        {"unique", (PyCFunction) Euler_Unique, METH_NOARGS, Euler_Unique_doc},
633
 
        {"to_matrix", (PyCFunction) Euler_ToMatrix, METH_NOARGS, Euler_ToMatrix_doc},
634
 
        {"to_quat", (PyCFunction) Euler_ToQuat, METH_NOARGS, Euler_ToQuat_doc},
635
 
        {"rotate", (PyCFunction) Euler_Rotate, METH_VARARGS, Euler_Rotate_doc},
636
 
        {"make_compatible", (PyCFunction) Euler_MakeCompatible, METH_O, Euler_MakeCompatible_doc},
637
 
        {"__copy__", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
638
 
        {"copy", (PyCFunction) Euler_copy, METH_VARARGS, Euler_copy_doc},
639
 
        {NULL, NULL, 0, NULL}
640
 
};
641
 
 
642
 
//------------------PY_OBECT DEFINITION--------------------------
643
 
static char euler_doc[] =
644
 
"This object gives access to Eulers in Blender.";
645
 
 
646
 
PyTypeObject euler_Type = {
647
 
        PyVarObject_HEAD_INIT(NULL, 0)
648
 
        "euler",                                                //tp_name
649
 
        sizeof(EulerObject),                    //tp_basicsize
650
 
        0,                                                              //tp_itemsize
651
 
        (destructor)BaseMathObject_dealloc,             //tp_dealloc
652
 
        0,                                                              //tp_print
653
 
        0,                                                              //tp_getattr
654
 
        0,                                                              //tp_setattr
655
 
        0,                                                              //tp_compare
656
 
        (reprfunc) Euler_repr,                  //tp_repr
657
 
        0,                              //tp_as_number
658
 
        &Euler_SeqMethods,                              //tp_as_sequence
659
 
        &Euler_AsMapping,                               //tp_as_mapping
660
 
        0,                                                              //tp_hash
661
 
        0,                                                              //tp_call
662
 
        0,                                                              //tp_str
663
 
        0,                                                              //tp_getattro
664
 
        0,                                                              //tp_setattro
665
 
        0,                                                              //tp_as_buffer
666
 
        Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, //tp_flags
667
 
        euler_doc, //tp_doc
668
 
        0,                                                              //tp_traverse
669
 
        0,                                                              //tp_clear
670
 
        (richcmpfunc)Euler_richcmpr,    //tp_richcompare
671
 
        0,                                                              //tp_weaklistoffset
672
 
        0,                                                              //tp_iter
673
 
        0,                                                              //tp_iternext
674
 
        Euler_methods,                                  //tp_methods
675
 
        0,                                                              //tp_members
676
 
        Euler_getseters,                                //tp_getset
677
 
        0,                                                              //tp_base
678
 
        0,                                                              //tp_dict
679
 
        0,                                                              //tp_descr_get
680
 
        0,                                                              //tp_descr_set
681
 
        0,                                                              //tp_dictoffset
682
 
        0,                                                              //tp_init
683
 
        0,                                                              //tp_alloc
684
 
        Euler_new,                                              //tp_new
685
 
        0,                                                              //tp_free
686
 
        0,                                                              //tp_is_gc
687
 
        0,                                                              //tp_bases
688
 
        0,                                                              //tp_mro
689
 
        0,                                                              //tp_cache
690
 
        0,                                                              //tp_subclasses
691
 
        0,                                                              //tp_weaklist
692
 
        0                                                               //tp_del
693
 
};
694
 
//------------------------newEulerObject (internal)-------------
695
 
//creates a new euler object
696
 
/*pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER
697
 
 (i.e. it was allocated elsewhere by MEM_mallocN())
698
 
  pass Py_NEW - if vector is not a WRAPPER and managed by PYTHON
699
 
 (i.e. it must be created here with PyMEM_malloc())*/
700
 
PyObject *newEulerObject(float *eul, short order, int type, PyTypeObject *base_type)
701
 
{
702
 
        EulerObject *self;
703
 
 
704
 
        if(base_type)   self = (EulerObject *)base_type->tp_alloc(base_type, 0);
705
 
        else                    self = PyObject_NEW(EulerObject, &euler_Type);
706
 
 
707
 
        /* init callbacks as NULL */
708
 
        self->cb_user= NULL;
709
 
        self->cb_type= self->cb_subtype= 0;
710
 
 
711
 
        if(type == Py_WRAP) {
712
 
                self->eul = eul;
713
 
                self->wrapped = Py_WRAP;
714
 
        }
715
 
        else if (type == Py_NEW){
716
 
                self->eul = PyMem_Malloc(EULER_SIZE * sizeof(float));
717
 
                if(eul)
718
 
                        copy_v3_v3(self->eul, eul);
719
 
                else
720
 
                        zero_v3(self->eul);
721
 
 
722
 
                self->wrapped = Py_NEW;
723
 
        }
724
 
        else{
725
 
                return NULL;
726
 
        }
727
 
 
728
 
        self->order= order;
729
 
        return (PyObject *)self;
730
 
}
731
 
 
732
 
PyObject *newEulerObject_cb(PyObject *cb_user, short order, int cb_type, int cb_subtype)
733
 
{
734
 
        EulerObject *self= (EulerObject *)newEulerObject(NULL, order, Py_NEW, NULL);
735
 
        if(self) {
736
 
                Py_INCREF(cb_user);
737
 
                self->cb_user=                  cb_user;
738
 
                self->cb_type=                  (unsigned char)cb_type;
739
 
                self->cb_subtype=               (unsigned char)cb_subtype;
740
 
        }
741
 
 
742
 
        return (PyObject *)self;
743
 
}