PyAPI: add utilities PyTuple_SET_ITEMS, Py_INCREF_RET
[blender.git] / source / blender / python / mathutils / mathutils.c
1 /* 
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Joseph Gilbert, Campbell Barton
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/python/mathutils/mathutils.c
24  *  \ingroup pymathutils
25  */
26
27 #include <Python.h>
28
29 #include "mathutils.h"
30
31 #include "BLI_math.h"
32 #include "BLI_utildefines.h"
33
34 #include "../generic/python_utildefines.h"
35
36 #ifndef MATH_STANDALONE
37 #  include "BLI_dynstr.h"
38 #endif
39
40 PyDoc_STRVAR(M_Mathutils_doc,
41 "This module provides access to matrices, eulers, quaternions and vectors."
42 );
43 static int mathutils_array_parse_fast(float *array,
44                                       int size,
45                                       PyObject *value_fast,
46                                       const char *error_prefix)
47 {
48         PyObject *item;
49
50         int i;
51
52         i = size;
53         do {
54                 i--;
55                 if (((array[i] = PyFloat_AsDouble((item = PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) &&
56                     PyErr_Occurred())
57                 {
58                         PyErr_Format(PyExc_TypeError,
59                                      "%.200s: sequence index %d expected a number, "
60                                      "found '%.200s' type, ",
61                                      error_prefix, i, Py_TYPE(item)->tp_name);
62                         Py_DECREF(value_fast);
63                         return -1;
64                 }
65         } while (i);
66
67         Py_XDECREF(value_fast);
68         return size;
69 }
70
71 /* helper functionm returns length of the 'value', -1 on error */
72 int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
73 {
74         const int flag = array_max;
75         int size;
76
77         array_max &= ~MU_ARRAY_FLAGS;
78
79 #if 1 /* approx 6x speedup for mathutils types */
80
81         if ((size = VectorObject_Check(value)     ? ((VectorObject *)value)->size : 0) ||
82             (size = EulerObject_Check(value)      ? 3 : 0) ||
83             (size = QuaternionObject_Check(value) ? 4 : 0) ||
84             (size = ColorObject_Check(value)      ? 3 : 0))
85         {
86                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
87                         return -1;
88                 }
89
90                 if (flag & MU_ARRAY_SPILL) {
91                         CLAMP_MAX(size, array_max);
92                 }
93
94                 if (size > array_max || size < array_min) {
95                         if (array_max == array_min) {
96                                 PyErr_Format(PyExc_ValueError,
97                                              "%.200s: sequence size is %d, expected %d",
98                                              error_prefix, size, array_max);
99                         }
100                         else {
101                                 PyErr_Format(PyExc_ValueError,
102                                              "%.200s: sequence size is %d, expected [%d - %d]",
103                                              error_prefix, size, array_min, array_max);
104                         }
105                         return -1;
106                 }
107
108                 memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
109         }
110         else
111 #endif
112         {
113                 PyObject *value_fast = NULL;
114
115                 /* non list/tuple cases */
116                 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
117                         /* PySequence_Fast sets the error */
118                         return -1;
119                 }
120
121                 size = PySequence_Fast_GET_SIZE(value_fast);
122
123                 if (flag & MU_ARRAY_SPILL) {
124                         CLAMP_MAX(size, array_max);
125                 }
126
127                 if (size > array_max || size < array_min) {
128                         if (array_max == array_min) {
129                                 PyErr_Format(PyExc_ValueError,
130                                              "%.200s: sequence size is %d, expected %d",
131                                              error_prefix, size, array_max);
132                         }
133                         else {
134                                 PyErr_Format(PyExc_ValueError,
135                                              "%.200s: sequence size is %d, expected [%d - %d]",
136                                              error_prefix, size, array_min, array_max);
137                         }
138                         Py_DECREF(value_fast);
139                         return -1;
140                 }
141
142                 size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
143         }
144
145         if (size != -1) {
146                 if (flag & MU_ARRAY_ZERO) {
147                         int size_left = array_max - size;
148                         if (size_left) {
149                                 memset(&array[size], 0, sizeof(float) * size_left);
150                         }
151                 }
152         }
153
154         return size;
155 }
156
157 /* on error, -1 is returned and no allocation is made */
158 int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix)
159 {
160         int size;
161
162 #if 1 /* approx 6x speedup for mathutils types */
163
164         if ((size = VectorObject_Check(value)     ? ((VectorObject *)value)->size : 0) ||
165             (size = EulerObject_Check(value)      ? 3 : 0) ||
166             (size = QuaternionObject_Check(value) ? 4 : 0) ||
167             (size = ColorObject_Check(value)      ? 3 : 0))
168         {
169                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
170                         return -1;
171                 }
172
173                 if (size < array_min) {
174                         PyErr_Format(PyExc_ValueError,
175                                      "%.200s: sequence size is %d, expected > %d",
176                                      error_prefix, size, array_min);
177                         return -1;
178                 }
179                 
180                 *array = PyMem_Malloc(size * sizeof(float));
181                 memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float));
182                 return size;
183         }
184         else
185 #endif
186         {
187                 PyObject *value_fast = NULL;
188                 // *array = NULL;
189                 int ret;
190
191                 /* non list/tuple cases */
192                 if (!(value_fast = PySequence_Fast(value, error_prefix))) {
193                         /* PySequence_Fast sets the error */
194                         return -1;
195                 }
196
197                 size = PySequence_Fast_GET_SIZE(value_fast);
198
199                 if (size < array_min) {
200                         PyErr_Format(PyExc_ValueError,
201                                      "%.200s: sequence size is %d, expected > %d",
202                                      error_prefix, size, array_min);
203                         return -1;
204                 }
205
206                 *array = PyMem_Malloc(size * sizeof(float));
207
208                 ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix);
209
210                 if (ret == -1) {
211                         PyMem_Free(*array);
212                 }
213
214                 return ret;
215         }
216 }
217
218 /* parse an array of vectors */
219 int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
220 {
221         PyObject *value_fast = NULL;
222         const int array_dim_flag = array_dim;
223         int i, size;
224
225         /* non list/tuple cases */
226         if (!(value_fast = PySequence_Fast(value, error_prefix))) {
227                 /* PySequence_Fast sets the error */
228                 return -1;
229         }
230
231         size = PySequence_Fast_GET_SIZE(value_fast);
232
233         if (size != 0) {
234                 float *fp;
235
236                 array_dim &= ~MU_ARRAY_FLAGS;
237
238                 fp = *array = PyMem_Malloc(size * array_dim * sizeof(float));
239
240                 for (i = 0; i < size; i++, fp += array_dim) {
241                         PyObject *item = PySequence_Fast_GET_ITEM(value, i);
242
243                         if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) {
244                                 PyMem_Free(*array);
245                                 *array = NULL;
246                                 size = -1;
247                                 break;
248                         }
249                 }
250         }
251
252         Py_DECREF(value_fast);
253         return size;
254 }
255
256 int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
257 {
258         if (EulerObject_Check(value)) {
259                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
260                         return -1;
261                 }
262                 else {
263                         eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order);
264                         return 0;
265                 }
266         }
267         else if (QuaternionObject_Check(value)) {
268                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
269                         return -1;
270                 }
271                 else {
272                         float tquat[4];
273                         normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat);
274                         quat_to_mat3(rmat, tquat);
275                         return 0;
276                 }
277         }
278         else if (MatrixObject_Check(value)) {
279                 if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
280                         return -1;
281                 }
282                 else if (((MatrixObject *)value)->num_row < 3 || ((MatrixObject *)value)->num_col < 3) {
283                         PyErr_Format(PyExc_ValueError,
284                                      "%.200s: matrix must have minimum 3x3 dimensions",
285                                      error_prefix);
286                         return -1;
287                 }
288                 else {
289                         matrix_as_3x3(rmat, (MatrixObject *)value);
290                         normalize_m3(rmat);
291                         return 0;
292                 }
293         }
294         else {
295                 PyErr_Format(PyExc_TypeError,
296                              "%.200s: expected a Euler, Quaternion or Matrix type, "
297                              "found %.200s", error_prefix, Py_TYPE(value)->tp_name);
298                 return -1;
299         }
300 }
301
302
303 /* ----------------------------------MATRIX FUNCTIONS-------------------- */
304
305
306 /* Utility functions */
307
308 /* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */
309 #define SIGNMASK(i) (-(int)(((unsigned int)(i)) >> 31))
310
311 int EXPP_FloatsAreEqual(float af, float bf, int maxDiff)
312 {
313         /* solid, fast routine across all platforms
314          * with constant time behavior */
315         int ai = *(int *)(&af);
316         int bi = *(int *)(&bf);
317         int test = SIGNMASK(ai ^ bi);
318         int diff, v1, v2;
319
320         assert((0 == test) || (0xFFFFFFFF == test));
321         diff = (ai ^ (test & 0x7fffffff)) - bi;
322         v1 = maxDiff + diff;
323         v2 = maxDiff - diff;
324         return (v1 | v2) >= 0;
325 }
326
327 /*---------------------- EXPP_VectorsAreEqual -------------------------
328  * Builds on EXPP_FloatsAreEqual to test vectors */
329 int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
330 {
331         int x;
332         for (x = 0; x < size; x++) {
333                 if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
334                         return 0;
335         }
336         return 1;
337 }
338
339 #ifndef MATH_STANDALONE
340 /* dynstr as python string utility funcions, frees 'ds'! */
341 PyObject *mathutils_dynstr_to_py(struct DynStr *ds)
342 {
343         const int ds_len = BLI_dynstr_get_len(ds); /* space for \0 */
344         char *ds_buf     = PyMem_Malloc(ds_len + 1);
345         PyObject *ret;
346         BLI_dynstr_get_cstring_ex(ds, ds_buf);
347         BLI_dynstr_free(ds);
348         ret = PyUnicode_FromStringAndSize(ds_buf, ds_len);
349         PyMem_Free(ds_buf);
350         return ret;
351 }
352 #endif
353
354 /* silly function, we dont use arg. just check its compatible with __deepcopy__ */
355 int mathutils_deepcopy_args_check(PyObject *args)
356 {
357         PyObject *dummy_pydict;
358         return PyArg_ParseTuple(args, "|O!:__deepcopy__", &PyDict_Type, &dummy_pydict) != 0;
359 }
360
361 /* Mathutils Callbacks */
362
363 /* for mathutils internal use only, eventually should re-alloc but to start with we only have a few users */
364 #define MATHUTILS_TOT_CB 16
365 static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL};
366
367 unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb)
368 {
369         unsigned char i;
370         
371         /* find the first free slot */
372         for (i = 0; mathutils_callbacks[i]; i++) {
373                 if (mathutils_callbacks[i] == cb) /* already registered? */
374                         return i;
375         }
376
377         BLI_assert(i + 1 < MATHUTILS_TOT_CB);
378
379         mathutils_callbacks[i] = cb;
380         return i;
381 }
382
383 /* use macros to check for NULL */
384 int _BaseMathObject_ReadCallback(BaseMathObject *self)
385 {
386         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
387         if (LIKELY(cb->get(self, self->cb_subtype) != -1)) {
388                 return 0;
389         }
390
391         if (!PyErr_Occurred()) {
392                 PyErr_Format(PyExc_RuntimeError,
393                              "%s read, user has become invalid",
394                              Py_TYPE(self)->tp_name);
395         }
396         return -1;
397 }
398
399 int _BaseMathObject_WriteCallback(BaseMathObject *self)
400 {
401         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
402         if (LIKELY(cb->set(self, self->cb_subtype) != -1)) {
403                 return 0;
404         }
405
406         if (!PyErr_Occurred()) {
407                 PyErr_Format(PyExc_RuntimeError,
408                              "%s write, user has become invalid",
409                              Py_TYPE(self)->tp_name);
410         }
411         return -1;
412 }
413
414 int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index)
415 {
416         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
417         if (LIKELY(cb->get_index(self, self->cb_subtype, index) != -1)) {
418                 return 0;
419         }
420
421         if (!PyErr_Occurred()) {
422                 PyErr_Format(PyExc_RuntimeError,
423                              "%s read index, user has become invalid",
424                              Py_TYPE(self)->tp_name);
425         }
426         return -1;
427 }
428
429 int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index)
430 {
431         Mathutils_Callback *cb = mathutils_callbacks[self->cb_type];
432         if (LIKELY(cb->set_index(self, self->cb_subtype, index) != -1)) {
433                 return 0;
434         }
435
436         if (!PyErr_Occurred()) {
437                 PyErr_Format(PyExc_RuntimeError,
438                              "%s write index, user has become invalid",
439                              Py_TYPE(self)->tp_name);
440         }
441         return -1;
442 }
443
444 /* BaseMathObject generic functions for all mathutils types */
445 char BaseMathObject_owner_doc[] = "The item this is wrapping or None  (read-only).";
446 PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
447 {
448         PyObject *ret = self->cb_user ? self->cb_user : Py_None;
449         return Py_INCREF_RET(ret);
450 }
451
452 char BaseMathObject_is_wrapped_doc[] = "True when this object wraps external data (read-only).\n\n:type: boolean";
453 PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
454 {
455         return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0);
456 }
457
458 int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
459 {
460         Py_VISIT(self->cb_user);
461         return 0;
462 }
463
464 int BaseMathObject_clear(BaseMathObject *self)
465 {
466         Py_CLEAR(self->cb_user);
467         return 0;
468 }
469
470 void BaseMathObject_dealloc(BaseMathObject *self)
471 {
472         /* only free non wrapped */
473         if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) {
474                 PyMem_Free(self->data);
475         }
476
477         if (self->cb_user) {
478                 PyObject_GC_UnTrack(self);
479                 BaseMathObject_clear(self);
480         }
481
482         Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes
483 }
484
485 /*----------------------------MODULE INIT-------------------------*/
486 static struct PyMethodDef M_Mathutils_methods[] = {
487         {NULL, NULL, 0, NULL}
488 };
489
490 static struct PyModuleDef M_Mathutils_module_def = {
491         PyModuleDef_HEAD_INIT,
492         "mathutils",  /* m_name */
493         M_Mathutils_doc,  /* m_doc */
494         0,  /* m_size */
495         M_Mathutils_methods,  /* m_methods */
496         NULL,  /* m_reload */
497         NULL,  /* m_traverse */
498         NULL,  /* m_clear */
499         NULL,  /* m_free */
500 };
501
502
503 /* submodules only */
504 #include "mathutils_geometry.h"
505 #ifndef MATH_STANDALONE
506 #  include "mathutils_kdtree.h"
507 #  include "mathutils_noise.h"
508 #endif
509
510 PyMODINIT_FUNC PyInit_mathutils(void)
511 {
512         PyObject *mod;
513         PyObject *submodule;
514         PyObject *sys_modules = PyThreadState_GET()->interp->modules;
515
516         if (PyType_Ready(&vector_Type) < 0)
517                 return NULL;
518         if (PyType_Ready(&matrix_Type) < 0)
519                 return NULL;
520         if (PyType_Ready(&matrix_access_Type) < 0)
521                 return NULL;
522         if (PyType_Ready(&euler_Type) < 0)
523                 return NULL;
524         if (PyType_Ready(&quaternion_Type) < 0)
525                 return NULL;
526         if (PyType_Ready(&color_Type) < 0)
527                 return NULL;
528
529         mod = PyModule_Create(&M_Mathutils_module_def);
530         
531         /* each type has its own new() function */
532         PyModule_AddObject(mod, vector_Type.tp_name,     (PyObject *)&vector_Type);
533         PyModule_AddObject(mod, matrix_Type.tp_name,     (PyObject *)&matrix_Type);
534         PyModule_AddObject(mod, euler_Type.tp_name,      (PyObject *)&euler_Type);
535         PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type);
536         PyModule_AddObject(mod, color_Type.tp_name,      (PyObject *)&color_Type);
537         
538         /* submodule */
539         PyModule_AddObject(mod, "geometry",       (submodule = PyInit_mathutils_geometry()));
540         /* XXX, python doesnt do imports with this usefully yet
541          * 'from mathutils.geometry import PolyFill'
542          * ...fails without this. */
543         PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
544         Py_INCREF(submodule);
545
546 #ifndef MATH_STANDALONE
547         /* Noise submodule */
548         PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise()));
549         PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
550         Py_INCREF(submodule);
551
552         /* KDTree submodule */
553         PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree()));
554         PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
555         Py_INCREF(submodule);
556 #endif
557
558         mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb);
559         mathutils_matrix_col_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_col_cb);
560         mathutils_matrix_translation_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_translation_cb);
561
562         return mod;
563 }