From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- source/blender/python/mathutils/CMakeLists.txt | 64 +- source/blender/python/mathutils/mathutils.c | 941 ++-- source/blender/python/mathutils/mathutils.h | 121 +- source/blender/python/mathutils/mathutils_Color.c | 1520 +++--- source/blender/python/mathutils/mathutils_Color.h | 22 +- source/blender/python/mathutils/mathutils_Euler.c | 1224 ++--- source/blender/python/mathutils/mathutils_Euler.h | 28 +- source/blender/python/mathutils/mathutils_Matrix.c | 5371 ++++++++++---------- source/blender/python/mathutils/mathutils_Matrix.h | 48 +- .../python/mathutils/mathutils_Quaternion.c | 2382 ++++----- .../python/mathutils/mathutils_Quaternion.h | 22 +- source/blender/python/mathutils/mathutils_Vector.c | 5250 ++++++++++--------- source/blender/python/mathutils/mathutils_Vector.h | 40 +- .../blender/python/mathutils/mathutils_bvhtree.c | 2117 ++++---- .../blender/python/mathutils/mathutils_bvhtree.h | 5 +- .../blender/python/mathutils/mathutils_geometry.c | 2702 +++++----- .../python/mathutils/mathutils_interpolate.c | 152 +- source/blender/python/mathutils/mathutils_kdtree.c | 668 ++- source/blender/python/mathutils/mathutils_kdtree.h | 1 - source/blender/python/mathutils/mathutils_noise.c | 1687 +++--- 20 files changed, 12379 insertions(+), 11986 deletions(-) (limited to 'source/blender/python/mathutils') diff --git a/source/blender/python/mathutils/CMakeLists.txt b/source/blender/python/mathutils/CMakeLists.txt index 7b0c042d50a..a58260a84f6 100644 --- a/source/blender/python/mathutils/CMakeLists.txt +++ b/source/blender/python/mathutils/CMakeLists.txt @@ -16,48 +16,48 @@ # ***** END GPL LICENSE BLOCK ***** set(INC - . - ../../blenlib - ../../blenkernel - ../../bmesh - ../../depsgraph - ../../makesdna - ../../../../intern/guardedalloc + . + ../../blenlib + ../../blenkernel + ../../bmesh + ../../depsgraph + ../../makesdna + ../../../../intern/guardedalloc ) set(INC_SYS - ${PYTHON_INCLUDE_DIRS} + ${PYTHON_INCLUDE_DIRS} ) set(SRC - mathutils.c - mathutils_Color.c - mathutils_Euler.c - mathutils_Matrix.c - mathutils_Quaternion.c - mathutils_Vector.c - mathutils_bvhtree.c - mathutils_geometry.c - mathutils_interpolate.c - mathutils_kdtree.c - mathutils_noise.c + mathutils.c + mathutils_Color.c + mathutils_Euler.c + mathutils_Matrix.c + mathutils_Quaternion.c + mathutils_Vector.c + mathutils_bvhtree.c + mathutils_geometry.c + mathutils_interpolate.c + mathutils_kdtree.c + mathutils_noise.c - mathutils.h - mathutils_Color.h - mathutils_Euler.h - mathutils_Matrix.h - mathutils_Quaternion.h - mathutils_Vector.h - mathutils_bvhtree.h - mathutils_geometry.h - mathutils_interpolate.h - mathutils_kdtree.h - mathutils_noise.h + mathutils.h + mathutils_Color.h + mathutils_Euler.h + mathutils_Matrix.h + mathutils_Quaternion.h + mathutils_Vector.h + mathutils_bvhtree.h + mathutils_geometry.h + mathutils_interpolate.h + mathutils_kdtree.h + mathutils_noise.h ) set(LIB - bf_blenlib - bf_python_ext + bf_blenlib + bf_python_ext ) diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 41738ced41a..32ffa4ad2da 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -31,59 +31,60 @@ # include "BLI_dynstr.h" #endif -PyDoc_STRVAR(M_Mathutils_doc, -"This module provides access to math operations.\n" -"\n" -".. note::\n" -"\n" -" Classes, methods and attributes that accept vectors also accept other numeric sequences,\n" -" such as tuples, lists." -"\n\n" -"Submodules:\n" -"\n" -".. toctree::\n" -" :maxdepth: 1\n" -"\n" -" mathutils.geometry.rst\n" -" mathutils.bvhtree.rst\n" -" mathutils.kdtree.rst\n" -" mathutils.interpolate.rst\n" -" mathutils.noise.rst\n" -"\n" -"The :mod:`mathutils` module provides the following classes:\n" -"\n" -"- :class:`Color`,\n" -"- :class:`Euler`,\n" -"- :class:`Matrix`,\n" -"- :class:`Quaternion`,\n" -"- :class:`Vector`,\n" -); +PyDoc_STRVAR( + M_Mathutils_doc, + "This module provides access to math operations.\n" + "\n" + ".. note::\n" + "\n" + " Classes, methods and attributes that accept vectors also accept other numeric sequences,\n" + " such as tuples, lists." + "\n\n" + "Submodules:\n" + "\n" + ".. toctree::\n" + " :maxdepth: 1\n" + "\n" + " mathutils.geometry.rst\n" + " mathutils.bvhtree.rst\n" + " mathutils.kdtree.rst\n" + " mathutils.interpolate.rst\n" + " mathutils.noise.rst\n" + "\n" + "The :mod:`mathutils` module provides the following classes:\n" + "\n" + "- :class:`Color`,\n" + "- :class:`Euler`,\n" + "- :class:`Matrix`,\n" + "- :class:`Quaternion`,\n" + "- :class:`Vector`,\n"); static int mathutils_array_parse_fast(float *array, int size, PyObject *value_fast, const char *error_prefix) { - PyObject *item; - PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); - - int i; - - i = size; - do { - i--; - if (((array[i] = PyFloat_AsDouble((item = value_fast_items[i]))) == -1.0f) && - PyErr_Occurred()) - { - PyErr_Format(PyExc_TypeError, - "%.200s: sequence index %d expected a number, " - "found '%.200s' type, ", - error_prefix, i, Py_TYPE(item)->tp_name); - size = -1; - break; - } - } while (i); - - return size; + PyObject *item; + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); + + int i; + + i = size; + do { + i--; + if (((array[i] = PyFloat_AsDouble((item = value_fast_items[i]))) == -1.0f) && + PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, + "%.200s: sequence index %d expected a number, " + "found '%.200s' type, ", + error_prefix, + i, + Py_TYPE(item)->tp_name); + size = -1; + break; + } + } while (i); + + return size; } /** @@ -93,271 +94,289 @@ static int mathutils_array_parse_fast(float *array, */ Py_hash_t mathutils_array_hash(const float *array, size_t array_len) { - int i; - Py_uhash_t x; /* Unsigned for defined overflow behavior. */ - Py_hash_t y; - Py_uhash_t mult; - Py_ssize_t len; - - mult = _PyHASH_MULTIPLIER; - len = array_len; - x = 0x345678UL; - i = 0; - while (--len >= 0) { - y = _Py_HashDouble((double)(array[i++])); - if (y == -1) { - return -1; - } - x = (x ^ y) * mult; - /* the cast might truncate len; that doesn't change hash stability */ - mult += (Py_hash_t)(82520UL + len + len); - } - x += 97531UL; - if (x == (Py_uhash_t)-1) { - x = -2; - } - return x; + int i; + Py_uhash_t x; /* Unsigned for defined overflow behavior. */ + Py_hash_t y; + Py_uhash_t mult; + Py_ssize_t len; + + mult = _PyHASH_MULTIPLIER; + len = array_len; + x = 0x345678UL; + i = 0; + while (--len >= 0) { + y = _Py_HashDouble((double)(array[i++])); + if (y == -1) { + return -1; + } + x = (x ^ y) * mult; + /* the cast might truncate len; that doesn't change hash stability */ + mult += (Py_hash_t)(82520UL + len + len); + } + x += 97531UL; + if (x == (Py_uhash_t)-1) { + x = -2; + } + return x; } /* helper function returns length of the 'value', -1 on error */ -int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) +int mathutils_array_parse( + float *array, int array_min, int array_max, PyObject *value, const char *error_prefix) { - const unsigned int flag = array_max; - int size; + const unsigned int flag = array_max; + int size; - array_max &= ~MU_ARRAY_FLAGS; + array_max &= ~MU_ARRAY_FLAGS; #if 1 /* approx 6x speedup for mathutils types */ - if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || - (size = EulerObject_Check(value) ? 3 : 0) || - (size = QuaternionObject_Check(value) ? 4 : 0) || - (size = ColorObject_Check(value) ? 3 : 0)) - { - if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { - return -1; - } - - if (flag & MU_ARRAY_SPILL) { - CLAMP_MAX(size, array_max); - } - - if (size > array_max || size < array_min) { - if (array_max == array_min) { - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected %d", - error_prefix, size, array_max); - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected [%d - %d]", - error_prefix, size, array_min, array_max); - } - return -1; - } - - memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float)); - } - else + if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || + (size = EulerObject_Check(value) ? 3 : 0) || + (size = QuaternionObject_Check(value) ? 4 : 0) || + (size = ColorObject_Check(value) ? 3 : 0)) { + if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { + return -1; + } + + if (flag & MU_ARRAY_SPILL) { + CLAMP_MAX(size, array_max); + } + + if (size > array_max || size < array_min) { + if (array_max == array_min) { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected %d", + error_prefix, + size, + array_max); + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected [%d - %d]", + error_prefix, + size, + array_min, + array_max); + } + return -1; + } + + memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float)); + } + else #endif - { - PyObject *value_fast = NULL; - - /* non list/tuple cases */ - if (!(value_fast = PySequence_Fast(value, error_prefix))) { - /* PySequence_Fast sets the error */ - return -1; - } - - size = PySequence_Fast_GET_SIZE(value_fast); - - if (flag & MU_ARRAY_SPILL) { - CLAMP_MAX(size, array_max); - } - - if (size > array_max || size < array_min) { - if (array_max == array_min) { - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected %d", - error_prefix, size, array_max); - } - else { - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected [%d - %d]", - error_prefix, size, array_min, array_max); - } - Py_DECREF(value_fast); - return -1; - } - - size = mathutils_array_parse_fast(array, size, value_fast, error_prefix); - Py_DECREF(value_fast); - } - - if (size != -1) { - if (flag & MU_ARRAY_ZERO) { - int size_left = array_max - size; - if (size_left) { - memset(&array[size], 0, sizeof(float) * size_left); - } - } - } - - return size; + { + PyObject *value_fast = NULL; + + /* non list/tuple cases */ + if (!(value_fast = PySequence_Fast(value, error_prefix))) { + /* PySequence_Fast sets the error */ + return -1; + } + + size = PySequence_Fast_GET_SIZE(value_fast); + + if (flag & MU_ARRAY_SPILL) { + CLAMP_MAX(size, array_max); + } + + if (size > array_max || size < array_min) { + if (array_max == array_min) { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected %d", + error_prefix, + size, + array_max); + } + else { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected [%d - %d]", + error_prefix, + size, + array_min, + array_max); + } + Py_DECREF(value_fast); + return -1; + } + + size = mathutils_array_parse_fast(array, size, value_fast, error_prefix); + Py_DECREF(value_fast); + } + + if (size != -1) { + if (flag & MU_ARRAY_ZERO) { + int size_left = array_max - size; + if (size_left) { + memset(&array[size], 0, sizeof(float) * size_left); + } + } + } + + return size; } /* on error, -1 is returned and no allocation is made */ -int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix) +int mathutils_array_parse_alloc(float **array, + int array_min, + PyObject *value, + const char *error_prefix) { - int size; + int size; #if 1 /* approx 6x speedup for mathutils types */ - if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || - (size = EulerObject_Check(value) ? 3 : 0) || - (size = QuaternionObject_Check(value) ? 4 : 0) || - (size = ColorObject_Check(value) ? 3 : 0)) - { - if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { - return -1; - } - - if (size < array_min) { - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected > %d", - error_prefix, size, array_min); - return -1; - } - - *array = PyMem_Malloc(size * sizeof(float)); - memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float)); - return size; - } - else + if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) || + (size = EulerObject_Check(value) ? 3 : 0) || + (size = QuaternionObject_Check(value) ? 4 : 0) || + (size = ColorObject_Check(value) ? 3 : 0)) { + if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { + return -1; + } + + if (size < array_min) { + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected > %d", + error_prefix, + size, + array_min); + return -1; + } + + *array = PyMem_Malloc(size * sizeof(float)); + memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float)); + return size; + } + else #endif - { - PyObject *value_fast = NULL; - // *array = NULL; - int ret; - - /* non list/tuple cases */ - if (!(value_fast = PySequence_Fast(value, error_prefix))) { - /* PySequence_Fast sets the error */ - return -1; - } - - size = PySequence_Fast_GET_SIZE(value_fast); - - if (size < array_min) { - Py_DECREF(value_fast); - PyErr_Format(PyExc_ValueError, - "%.200s: sequence size is %d, expected > %d", - error_prefix, size, array_min); - return -1; - } - - *array = PyMem_Malloc(size * sizeof(float)); - - ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix); - Py_DECREF(value_fast); - - if (ret == -1) { - PyMem_Free(*array); - } - - return ret; - } + { + PyObject *value_fast = NULL; + // *array = NULL; + int ret; + + /* non list/tuple cases */ + if (!(value_fast = PySequence_Fast(value, error_prefix))) { + /* PySequence_Fast sets the error */ + return -1; + } + + size = PySequence_Fast_GET_SIZE(value_fast); + + if (size < array_min) { + Py_DECREF(value_fast); + PyErr_Format(PyExc_ValueError, + "%.200s: sequence size is %d, expected > %d", + error_prefix, + size, + array_min); + return -1; + } + + *array = PyMem_Malloc(size * sizeof(float)); + + ret = mathutils_array_parse_fast(*array, size, value_fast, error_prefix); + Py_DECREF(value_fast); + + if (ret == -1) { + PyMem_Free(*array); + } + + return ret; + } } /* parse an array of vectors */ -int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix) +int mathutils_array_parse_alloc_v(float **array, + int array_dim, + PyObject *value, + const char *error_prefix) { - PyObject *value_fast; - const int array_dim_flag = array_dim; - int i, size; + PyObject *value_fast; + const int array_dim_flag = array_dim; + int i, size; - /* non list/tuple cases */ - if (!(value_fast = PySequence_Fast(value, error_prefix))) { - /* PySequence_Fast sets the error */ - return -1; - } + /* non list/tuple cases */ + if (!(value_fast = PySequence_Fast(value, error_prefix))) { + /* PySequence_Fast sets the error */ + return -1; + } - size = PySequence_Fast_GET_SIZE(value_fast); + size = PySequence_Fast_GET_SIZE(value_fast); - if (size != 0) { - PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); - float *fp; + if (size != 0) { + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); + float *fp; - array_dim &= ~MU_ARRAY_FLAGS; + array_dim &= ~MU_ARRAY_FLAGS; - fp = *array = PyMem_Malloc(size * array_dim * sizeof(float)); + fp = *array = PyMem_Malloc(size * array_dim * sizeof(float)); - for (i = 0; i < size; i++, fp += array_dim) { - PyObject *item = value_fast_items[i]; + for (i = 0; i < size; i++, fp += array_dim) { + PyObject *item = value_fast_items[i]; - if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) { - PyMem_Free(*array); - *array = NULL; - size = -1; - break; - } - } - } + if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) { + PyMem_Free(*array); + *array = NULL; + size = -1; + break; + } + } + } - Py_DECREF(value_fast); - return size; + Py_DECREF(value_fast); + return size; } int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix) { - if (EulerObject_Check(value)) { - if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { - return -1; - } - else { - eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order); - return 0; - } - } - else if (QuaternionObject_Check(value)) { - if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { - return -1; - } - else { - float tquat[4]; - normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat); - quat_to_mat3(rmat, tquat); - return 0; - } - } - else if (MatrixObject_Check(value)) { - if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { - return -1; - } - else if (((MatrixObject *)value)->num_row < 3 || ((MatrixObject *)value)->num_col < 3) { - PyErr_Format(PyExc_ValueError, - "%.200s: matrix must have minimum 3x3 dimensions", - error_prefix); - return -1; - } - else { - matrix_as_3x3(rmat, (MatrixObject *)value); - normalize_m3(rmat); - return 0; - } - } - else { - PyErr_Format(PyExc_TypeError, - "%.200s: expected a Euler, Quaternion or Matrix type, " - "found %.200s", error_prefix, Py_TYPE(value)->tp_name); - return -1; - } + if (EulerObject_Check(value)) { + if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { + return -1; + } + else { + eulO_to_mat3(rmat, ((EulerObject *)value)->eul, ((EulerObject *)value)->order); + return 0; + } + } + else if (QuaternionObject_Check(value)) { + if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { + return -1; + } + else { + float tquat[4]; + normalize_qt_qt(tquat, ((QuaternionObject *)value)->quat); + quat_to_mat3(rmat, tquat); + return 0; + } + } + else if (MatrixObject_Check(value)) { + if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) { + return -1; + } + else if (((MatrixObject *)value)->num_row < 3 || ((MatrixObject *)value)->num_col < 3) { + PyErr_Format( + PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix); + return -1; + } + else { + matrix_as_3x3(rmat, (MatrixObject *)value); + normalize_m3(rmat); + return 0; + } + } + else { + PyErr_Format(PyExc_TypeError, + "%.200s: expected a Euler, Quaternion or Matrix type, " + "found %.200s", + error_prefix, + Py_TYPE(value)->tp_name); + return -1; + } } - /* ----------------------------------MATRIX FUNCTIONS-------------------- */ - /* Utility functions */ /* LomontRRDCompare4, Ever Faster Float Comparisons by Randy Dillon */ @@ -374,45 +393,45 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error int EXPP_FloatsAreEqual(float af, float bf, int maxDiff) { - /* solid, fast routine across all platforms - * with constant time behavior */ - int ai = *(int *)(&af); - int bi = *(int *)(&bf); - int test = SIGNMASK(ai ^ bi); - int diff, v1, v2; - - assert((0 == test) || (0xFFFFFFFF == test)); - diff = (ai ^ (test & 0x7fffffff)) - bi; - v1 = maxDiff + diff; - v2 = maxDiff - diff; - return (v1 | v2) >= 0; + /* solid, fast routine across all platforms + * with constant time behavior */ + int ai = *(int *)(&af); + int bi = *(int *)(&bf); + int test = SIGNMASK(ai ^ bi); + int diff, v1, v2; + + assert((0 == test) || (0xFFFFFFFF == test)); + diff = (ai ^ (test & 0x7fffffff)) - bi; + v1 = maxDiff + diff; + v2 = maxDiff - diff; + return (v1 | v2) >= 0; } /*---------------------- EXPP_VectorsAreEqual ------------------------- * Builds on EXPP_FloatsAreEqual to test vectors */ int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps) { - int x; - for (x = 0; x < size; x++) { - if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0) { - return 0; - } - } - return 1; + int x; + for (x = 0; x < size; x++) { + if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0) { + return 0; + } + } + return 1; } #ifndef MATH_STANDALONE /* dynstr as python string utility functions, frees 'ds'! */ PyObject *mathutils_dynstr_to_py(struct DynStr *ds) { - const int ds_len = BLI_dynstr_get_len(ds); /* space for \0 */ - char *ds_buf = PyMem_Malloc(ds_len + 1); - PyObject *ret; - BLI_dynstr_get_cstring_ex(ds, ds_buf); - BLI_dynstr_free(ds); - ret = PyUnicode_FromStringAndSize(ds_buf, ds_len); - PyMem_Free(ds_buf); - return ret; + const int ds_len = BLI_dynstr_get_len(ds); /* space for \0 */ + char *ds_buf = PyMem_Malloc(ds_len + 1); + PyObject *ret; + BLI_dynstr_get_cstring_ex(ds, ds_buf); + BLI_dynstr_free(ds); + ret = PyUnicode_FromStringAndSize(ds_buf, ds_len); + PyMem_Free(ds_buf); + return ret; } #endif @@ -424,183 +443,174 @@ static Mathutils_Callback *mathutils_callbacks[MATHUTILS_TOT_CB] = {NULL}; unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb) { - unsigned char i; + unsigned char i; - /* find the first free slot */ - for (i = 0; mathutils_callbacks[i]; i++) { - if (mathutils_callbacks[i] == cb) { - /* already registered? */ - return i; - } - } + /* find the first free slot */ + for (i = 0; mathutils_callbacks[i]; i++) { + if (mathutils_callbacks[i] == cb) { + /* already registered? */ + return i; + } + } - BLI_assert(i + 1 < MATHUTILS_TOT_CB); + BLI_assert(i + 1 < MATHUTILS_TOT_CB); - mathutils_callbacks[i] = cb; - return i; + mathutils_callbacks[i] = cb; + return i; } /* use macros to check for NULL */ int _BaseMathObject_ReadCallback(BaseMathObject *self) { - Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; - if (LIKELY(cb->get(self, self->cb_subtype) != -1)) { - return 0; - } - - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_RuntimeError, - "%s read, user has become invalid", - Py_TYPE(self)->tp_name); - } - return -1; + Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; + if (LIKELY(cb->get(self, self->cb_subtype) != -1)) { + return 0; + } + + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_RuntimeError, "%s read, user has become invalid", Py_TYPE(self)->tp_name); + } + return -1; } int _BaseMathObject_WriteCallback(BaseMathObject *self) { - Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; - if (LIKELY(cb->set(self, self->cb_subtype) != -1)) { - return 0; - } - - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_RuntimeError, - "%s write, user has become invalid", - Py_TYPE(self)->tp_name); - } - return -1; + Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; + if (LIKELY(cb->set(self, self->cb_subtype) != -1)) { + return 0; + } + + if (!PyErr_Occurred()) { + PyErr_Format(PyExc_RuntimeError, "%s write, user has become invalid", Py_TYPE(self)->tp_name); + } + return -1; } int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index) { - Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; - if (LIKELY(cb->get_index(self, self->cb_subtype, index) != -1)) { - return 0; - } - - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_RuntimeError, - "%s read index, user has become invalid", - Py_TYPE(self)->tp_name); - } - return -1; + Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; + if (LIKELY(cb->get_index(self, self->cb_subtype, index) != -1)) { + return 0; + } + + if (!PyErr_Occurred()) { + PyErr_Format( + PyExc_RuntimeError, "%s read index, user has become invalid", Py_TYPE(self)->tp_name); + } + return -1; } int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index) { - Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; - if (LIKELY(cb->set_index(self, self->cb_subtype, index) != -1)) { - return 0; - } - - if (!PyErr_Occurred()) { - PyErr_Format(PyExc_RuntimeError, - "%s write index, user has become invalid", - Py_TYPE(self)->tp_name); - } - return -1; + Mathutils_Callback *cb = mathutils_callbacks[self->cb_type]; + if (LIKELY(cb->set_index(self, self->cb_subtype, index) != -1)) { + return 0; + } + + if (!PyErr_Occurred()) { + PyErr_Format( + PyExc_RuntimeError, "%s write index, user has become invalid", Py_TYPE(self)->tp_name); + } + return -1; } void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self) { - PyErr_Format(PyExc_TypeError, - "%s is frozen (immutable)", - Py_TYPE(self)->tp_name); + PyErr_Format(PyExc_TypeError, "%s is frozen (immutable)", Py_TYPE(self)->tp_name); } void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self) { - PyErr_Format(PyExc_TypeError, - "%s is not frozen (mutable), call freeze first", - Py_TYPE(self)->tp_name); + PyErr_Format( + PyExc_TypeError, "%s is not frozen (mutable), call freeze first", Py_TYPE(self)->tp_name); } /* BaseMathObject generic functions for all mathutils types */ char BaseMathObject_owner_doc[] = "The item this is wrapping or None (read-only)."; PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure)) { - PyObject *ret = self->cb_user ? self->cb_user : Py_None; - return Py_INCREF_RET(ret); + PyObject *ret = self->cb_user ? self->cb_user : Py_None; + return Py_INCREF_RET(ret); } -char BaseMathObject_is_wrapped_doc[] = "True when this object wraps external data (read-only).\n\n:type: boolean"; +char BaseMathObject_is_wrapped_doc[] = + "True when this object wraps external data (read-only).\n\n:type: boolean"; PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure)) { - return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0); + return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_WRAP) != 0); } -char BaseMathObject_is_frozen_doc[] = "True when this object has been frozen (read-only).\n\n:type: boolean"; +char BaseMathObject_is_frozen_doc[] = + "True when this object has been frozen (read-only).\n\n:type: boolean"; PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure)) { - return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_FROZEN) != 0); + return PyBool_FromLong((self->flag & BASE_MATH_FLAG_IS_FROZEN) != 0); } char BaseMathObject_freeze_doc[] = -".. function:: freeze()\n" -"\n" -" Make this object immutable.\n" -"\n" -" After this the object can be hashed, used in dictionaries & sets.\n" -"\n" -" :return: An instance of this object.\n" -; + ".. function:: freeze()\n" + "\n" + " Make this object immutable.\n" + "\n" + " After this the object can be hashed, used in dictionaries & sets.\n" + "\n" + " :return: An instance of this object.\n"; PyObject *BaseMathObject_freeze(BaseMathObject *self) { - if ((self->flag & BASE_MATH_FLAG_IS_WRAP) || (self->cb_user != NULL)) { - PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped/owned data"); - return NULL; - } + if ((self->flag & BASE_MATH_FLAG_IS_WRAP) || (self->cb_user != NULL)) { + PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped/owned data"); + return NULL; + } - self->flag |= BASE_MATH_FLAG_IS_FROZEN; + self->flag |= BASE_MATH_FLAG_IS_FROZEN; - return Py_INCREF_RET((PyObject *)self); + return Py_INCREF_RET((PyObject *)self); } int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg) { - Py_VISIT(self->cb_user); - return 0; + Py_VISIT(self->cb_user); + return 0; } int BaseMathObject_clear(BaseMathObject *self) { - Py_CLEAR(self->cb_user); - return 0; + Py_CLEAR(self->cb_user); + return 0; } void BaseMathObject_dealloc(BaseMathObject *self) { - /* only free non wrapped */ - if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) { - PyMem_Free(self->data); - } + /* only free non wrapped */ + if ((self->flag & BASE_MATH_FLAG_IS_WRAP) == 0) { + PyMem_Free(self->data); + } - if (self->cb_user) { - PyObject_GC_UnTrack(self); - BaseMathObject_clear(self); - } + if (self->cb_user) { + PyObject_GC_UnTrack(self); + BaseMathObject_clear(self); + } - Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes + Py_TYPE(self)->tp_free(self); // PyObject_DEL(self); // breaks subtypes } /*----------------------------MODULE INIT-------------------------*/ static struct PyMethodDef M_Mathutils_methods[] = { - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef M_Mathutils_module_def = { - PyModuleDef_HEAD_INIT, - "mathutils", /* m_name */ - M_Mathutils_doc, /* m_doc */ - 0, /* m_size */ - M_Mathutils_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "mathutils", /* m_name */ + M_Mathutils_doc, /* m_doc */ + 0, /* m_size */ + M_Mathutils_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; - /* submodules only */ #include "mathutils_geometry.h" #include "mathutils_interpolate.h" @@ -612,68 +622,69 @@ static struct PyModuleDef M_Mathutils_module_def = { PyMODINIT_FUNC PyInit_mathutils(void) { - PyObject *mod; - PyObject *submodule; - PyObject *sys_modules = PyImport_GetModuleDict(); - - if (PyType_Ready(&vector_Type) < 0) { - return NULL; - } - if (PyType_Ready(&matrix_Type) < 0) { - return NULL; - } - if (PyType_Ready(&matrix_access_Type) < 0) { - return NULL; - } - if (PyType_Ready(&euler_Type) < 0) { - return NULL; - } - if (PyType_Ready(&quaternion_Type) < 0) { - return NULL; - } - if (PyType_Ready(&color_Type) < 0) { - return NULL; - } - - mod = PyModule_Create(&M_Mathutils_module_def); - - /* each type has its own new() function */ - PyModule_AddObject(mod, vector_Type.tp_name, (PyObject *)&vector_Type); - PyModule_AddObject(mod, matrix_Type.tp_name, (PyObject *)&matrix_Type); - PyModule_AddObject(mod, euler_Type.tp_name, (PyObject *)&euler_Type); - PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type); - PyModule_AddObject(mod, color_Type.tp_name, (PyObject *)&color_Type); - - /* submodule */ - PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry())); - /* XXX, python doesn't do imports with this usefully yet - * 'from mathutils.geometry import PolyFill' - * ...fails without this. */ - PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); - - PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate())); - /* XXX, python doesnt do imports with this usefully yet - * 'from mathutils.geometry import PolyFill' - * ...fails without this. */ - PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + PyObject *mod; + PyObject *submodule; + PyObject *sys_modules = PyImport_GetModuleDict(); + + if (PyType_Ready(&vector_Type) < 0) { + return NULL; + } + if (PyType_Ready(&matrix_Type) < 0) { + return NULL; + } + if (PyType_Ready(&matrix_access_Type) < 0) { + return NULL; + } + if (PyType_Ready(&euler_Type) < 0) { + return NULL; + } + if (PyType_Ready(&quaternion_Type) < 0) { + return NULL; + } + if (PyType_Ready(&color_Type) < 0) { + return NULL; + } + + mod = PyModule_Create(&M_Mathutils_module_def); + + /* each type has its own new() function */ + PyModule_AddObject(mod, vector_Type.tp_name, (PyObject *)&vector_Type); + PyModule_AddObject(mod, matrix_Type.tp_name, (PyObject *)&matrix_Type); + PyModule_AddObject(mod, euler_Type.tp_name, (PyObject *)&euler_Type); + PyModule_AddObject(mod, quaternion_Type.tp_name, (PyObject *)&quaternion_Type); + PyModule_AddObject(mod, color_Type.tp_name, (PyObject *)&color_Type); + + /* submodule */ + PyModule_AddObject(mod, "geometry", (submodule = PyInit_mathutils_geometry())); + /* XXX, python doesn't do imports with this usefully yet + * 'from mathutils.geometry import PolyFill' + * ...fails without this. */ + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + + PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate())); + /* XXX, python doesnt do imports with this usefully yet + * 'from mathutils.geometry import PolyFill' + * ...fails without this. */ + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); #ifndef MATH_STANDALONE - /* Noise submodule */ - PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise())); - PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + /* Noise submodule */ + PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise())); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); - /* BVHTree submodule */ - PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree())); - PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + /* BVHTree submodule */ + PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree())); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); - /* KDTree_3d submodule */ - PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree())); - PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); + /* KDTree_3d submodule */ + PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree())); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); #endif - mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb); - mathutils_matrix_col_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_col_cb); - mathutils_matrix_translation_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_translation_cb); + mathutils_matrix_row_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_row_cb); + mathutils_matrix_col_cb_index = Mathutils_RegisterCallback(&mathutils_matrix_col_cb); + mathutils_matrix_translation_cb_index = Mathutils_RegisterCallback( + &mathutils_matrix_translation_cb); - return mod; + return mod; } diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index bc5490a3acd..4ec2c869499 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -32,37 +32,39 @@ extern char BaseMathObject_is_frozen_doc[]; extern char BaseMathObject_owner_doc[]; #define BASE_MATH_NEW(struct_name, root_type, base_type) \ - (struct_name *)((base_type ? (base_type)->tp_alloc(base_type, 0) : _PyObject_GC_New(&(root_type)))); - + (struct_name *)((base_type ? (base_type)->tp_alloc(base_type, 0) : \ + _PyObject_GC_New(&(root_type)))); /** BaseMathObject.flag */ enum { - /** - * Do not own the memory used in this vector, - * \note This is error prone if the memory may be freed while this vector is in use. - * Prefer using callbacks where possible, see: #Mathutils_RegisterCallback - */ - BASE_MATH_FLAG_IS_WRAP = (1 << 0), - /** - * Prevent changes to the vector so it can be used as a set or dictionary key for example. - * (typical use cases for tuple). - */ - BASE_MATH_FLAG_IS_FROZEN = (1 << 1), + /** + * Do not own the memory used in this vector, + * \note This is error prone if the memory may be freed while this vector is in use. + * Prefer using callbacks where possible, see: #Mathutils_RegisterCallback + */ + BASE_MATH_FLAG_IS_WRAP = (1 << 0), + /** + * Prevent changes to the vector so it can be used as a set or dictionary key for example. + * (typical use cases for tuple). + */ + BASE_MATH_FLAG_IS_FROZEN = (1 << 1), }; #define BASE_MATH_FLAG_DEFAULT 0 -#define BASE_MATH_MEMBERS(_data) \ - PyObject_VAR_HEAD \ - float *_data; /* array of data (alias), wrapped status depends on wrapped status */ \ - PyObject *cb_user; /* if this vector references another object, otherwise NULL, \ - * *Note* this owns its reference */ \ - unsigned char cb_type; /* which user funcs do we adhere to, RNA, etc */ \ - unsigned char cb_subtype; /* subtype: location, rotation... \ - * to avoid defining many new functions for every attribute of the same type */ \ - unsigned char flag /* wrapped data type? */ \ +#define BASE_MATH_MEMBERS(_data) \ + PyObject_VAR_HEAD float \ + *_data; /* array of data (alias), wrapped status depends on wrapped status */ \ + PyObject * \ + cb_user; /* if this vector references another object, otherwise NULL, \ + * *Note* this owns its reference */ \ + unsigned char cb_type; /* which user funcs do we adhere to, RNA, etc */ \ + unsigned char \ + cb_subtype; /* subtype: location, rotation... \ + * to avoid defining many new functions for every attribute of the same type */ \ + unsigned char flag /* wrapped data type? */ typedef struct { - BASE_MATH_MEMBERS(data); + BASE_MATH_MEMBERS(data); } BaseMathObject; /* types */ @@ -73,8 +75,7 @@ typedef struct { #include "mathutils_Color.h" /* avoid checking all types */ -#define BaseMathObject_CheckExact(v) \ - (Py_TYPE(v)->tp_dealloc == (destructor)BaseMathObject_dealloc) +#define BaseMathObject_CheckExact(v) (Py_TYPE(v)->tp_dealloc == (destructor)BaseMathObject_dealloc) PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *); PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *); @@ -94,18 +95,23 @@ int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int flo typedef struct Mathutils_Callback Mathutils_Callback; -typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */ -typedef int (*BaseMathGetFunc)(BaseMathObject *, int); /* gets the vector from the user */ -typedef int (*BaseMathSetFunc)(BaseMathObject *, int); /* sets the users vector values once its modified */ -typedef int (*BaseMathGetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */ -typedef int (*BaseMathSetIndexFunc)(BaseMathObject *, int, int); /* same as above but only for an index */ +typedef int (*BaseMathCheckFunc)(BaseMathObject *); /* checks the user is still valid */ +typedef int (*BaseMathGetFunc)(BaseMathObject *, int); /* gets the vector from the user */ +typedef int (*BaseMathSetFunc)(BaseMathObject *, + int); /* sets the users vector values once its modified */ +typedef int (*BaseMathGetIndexFunc)(BaseMathObject *, + int, + int); /* same as above but only for an index */ +typedef int (*BaseMathSetIndexFunc)(BaseMathObject *, + int, + int); /* same as above but only for an index */ struct Mathutils_Callback { - BaseMathCheckFunc check; - BaseMathGetFunc get; - BaseMathSetFunc set; - BaseMathGetIndexFunc get_index; - BaseMathSetIndexFunc set_index; + BaseMathCheckFunc check; + BaseMathGetFunc get; + BaseMathSetFunc set; + BaseMathGetIndexFunc get_index; + BaseMathSetIndexFunc set_index; }; unsigned char Mathutils_RegisterCallback(Mathutils_Callback *cb); @@ -120,44 +126,55 @@ void _BaseMathObject_RaiseNotFrozenExc(const BaseMathObject *self); /* since this is called so often avoid where possible */ #define BaseMath_ReadCallback(_self) \ - (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self) : 0)) + (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self) : 0)) #define BaseMath_WriteCallback(_self) \ - (((_self)->cb_user ?_BaseMathObject_WriteCallback((BaseMathObject *)_self) : 0)) + (((_self)->cb_user ? _BaseMathObject_WriteCallback((BaseMathObject *)_self) : 0)) #define BaseMath_ReadIndexCallback(_self, _index) \ - (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index) : 0)) + (((_self)->cb_user ? _BaseMathObject_ReadIndexCallback((BaseMathObject *)_self, _index) : 0)) #define BaseMath_WriteIndexCallback(_self, _index) \ - (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index) : 0)) + (((_self)->cb_user ? _BaseMathObject_WriteIndexCallback((BaseMathObject *)_self, _index) : 0)) /* support BASE_MATH_FLAG_IS_FROZEN */ #define BaseMath_ReadCallback_ForWrite(_self) \ - (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \ - (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : (BaseMath_ReadCallback(_self))) + (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \ + (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : \ + (BaseMath_ReadCallback(_self))) #define BaseMath_ReadIndexCallback_ForWrite(_self, _index) \ - (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \ - (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : (BaseMath_ReadIndexCallback(_self, _index))) + (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \ + (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : \ + (BaseMath_ReadIndexCallback(_self, _index))) #define BaseMath_Prepare_ForWrite(_self) \ - (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \ - (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : 0) + (UNLIKELY((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) ? \ + (_BaseMathObject_RaiseFrozenExc((BaseMathObject *)_self), -1) : \ + 0) #define BaseMathObject_Prepare_ForHash(_self) \ - (UNLIKELY(((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) == 0) ? \ - (_BaseMathObject_RaiseNotFrozenExc((BaseMathObject *)_self), -1) : 0) + (UNLIKELY(((_self)->flag & BASE_MATH_FLAG_IS_FROZEN) == 0) ? \ + (_BaseMathObject_RaiseNotFrozenExc((BaseMathObject *)_self), -1) : \ + 0) /* utility func */ -int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); -int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix); -int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix); +int mathutils_array_parse( + float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); +int mathutils_array_parse_alloc(float **array, + int array_min, + PyObject *value, + const char *error_prefix); +int mathutils_array_parse_alloc_v(float **array, + int array_dim, + PyObject *value, + const char *error_prefix); int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix); Py_hash_t mathutils_array_hash(const float *float_array, size_t array_len); /* zero remaining unused elements of the array */ -#define MU_ARRAY_ZERO (1u << 30) +#define MU_ARRAY_ZERO (1u << 30) /* ignore larger py sequences than requested (just use first elements), * handy when using 3d vectors as 2d */ -#define MU_ARRAY_SPILL (1u << 31) +#define MU_ARRAY_SPILL (1u << 31) #define MU_ARRAY_FLAGS (MU_ARRAY_ZERO | MU_ARRAY_SPILL) diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index 98e85782989..4e21a8e0389 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #include #include "mathutils.h" @@ -39,30 +38,32 @@ /* makes a new color for you to play with */ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - float col[3] = {0.0f, 0.0f, 0.0f}; - - if (kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, - "mathutils.Color(): " - "takes no keyword args"); - return NULL; - } - - switch (PyTuple_GET_SIZE(args)) { - case 0: - break; - case 1: - if ((mathutils_array_parse(col, COLOR_SIZE, COLOR_SIZE, PyTuple_GET_ITEM(args, 0), "mathutils.Color()")) == -1) { - return NULL; - } - break; - default: - PyErr_SetString(PyExc_TypeError, - "mathutils.Color(): " - "more than a single arg given"); - return NULL; - } - return Color_CreatePyObject(col, type); + float col[3] = {0.0f, 0.0f, 0.0f}; + + if (kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "mathutils.Color(): " + "takes no keyword args"); + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 1: + if ((mathutils_array_parse( + col, COLOR_SIZE, COLOR_SIZE, PyTuple_GET_ITEM(args, 0), "mathutils.Color()")) == + -1) { + return NULL; + } + break; + default: + PyErr_SetString(PyExc_TypeError, + "mathutils.Color(): " + "more than a single arg given"); + return NULL; + } + return Color_CreatePyObject(col, type); } /* -----------------------------METHODS---------------------------- */ @@ -70,50 +71,49 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) /* note: BaseMath_ReadCallback must be called beforehand */ static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits) { - PyObject *ret; - int i; - - ret = PyTuple_New(COLOR_SIZE); - - if (ndigits >= 0) { - for (i = 0; i < COLOR_SIZE; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->col[i], ndigits))); - } - } - else { - for (i = 0; i < COLOR_SIZE; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->col[i])); - } - } - - return ret; + PyObject *ret; + int i; + + ret = PyTuple_New(COLOR_SIZE); + + if (ndigits >= 0) { + for (i = 0; i < COLOR_SIZE; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->col[i], ndigits))); + } + } + else { + for (i = 0; i < COLOR_SIZE; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->col[i])); + } + } + + return ret; } PyDoc_STRVAR(Color_copy_doc, -".. function:: copy()\n" -"\n" -" Returns a copy of this color.\n" -"\n" -" :return: A copy of the color.\n" -" :rtype: :class:`Color`\n" -"\n" -" .. note:: use this to get a copy of a wrapped color with\n" -" no reference to the original data.\n" -); + ".. function:: copy()\n" + "\n" + " Returns a copy of this color.\n" + "\n" + " :return: A copy of the color.\n" + " :rtype: :class:`Color`\n" + "\n" + " .. note:: use this to get a copy of a wrapped color with\n" + " no reference to the original data.\n"); static PyObject *Color_copy(ColorObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return Color_CreatePyObject(self->col, Py_TYPE(self)); + return Color_CreatePyObject(self->col, Py_TYPE(self)); } static PyObject *Color_deepcopy(ColorObject *self, PyObject *args) { - if (!PyC_CheckArgs_DeepCopy(args)) { - return NULL; - } - return Color_copy(self); + if (!PyC_CheckArgs_DeepCopy(args)) { + return NULL; + } + return Color_copy(self); } /* ----------------------------print object (internal)-------------- */ @@ -121,35 +121,35 @@ static PyObject *Color_deepcopy(ColorObject *self, PyObject *args) static PyObject *Color_repr(ColorObject *self) { - PyObject *ret, *tuple; + PyObject *ret, *tuple; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - tuple = Color_ToTupleExt(self, -1); + tuple = Color_ToTupleExt(self, -1); - ret = PyUnicode_FromFormat("Color(%R)", tuple); + ret = PyUnicode_FromFormat("Color(%R)", tuple); - Py_DECREF(tuple); - return ret; + Py_DECREF(tuple); + return ret; } #ifndef MATH_STANDALONE static PyObject *Color_str(ColorObject *self) { - DynStr *ds; + DynStr *ds; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - ds = BLI_dynstr_new(); + ds = BLI_dynstr_new(); - BLI_dynstr_appendf(ds, "", - self->col[0], self->col[1], self->col[2]); + BLI_dynstr_appendf( + ds, "", self->col[0], self->col[1], self->col[2]); - return mathutils_dynstr_to_py(ds); /* frees ds */ + return mathutils_dynstr_to_py(ds); /* frees ds */ } #endif @@ -157,53 +157,53 @@ static PyObject *Color_str(ColorObject *self) /* returns -1 exception, 0 false, 1 true */ static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ - - if (ColorObject_Check(a) && ColorObject_Check(b)) { - ColorObject *colA = (ColorObject *)a; - ColorObject *colB = (ColorObject *)b; - - if (BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1) { - return NULL; - } - - ok = EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1; - } - - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; - - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } - - return Py_INCREF_RET(res); + PyObject *res; + int ok = -1; /* zero is true */ + + if (ColorObject_Check(a) && ColorObject_Check(b)) { + ColorObject *colA = (ColorObject *)a; + ColorObject *colB = (ColorObject *)b; + + if (BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1) { + return NULL; + } + + ok = EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1; + } + + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; + + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } + + return Py_INCREF_RET(res); } static Py_hash_t Color_hash(ColorObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } - if (BaseMathObject_Prepare_ForHash(self) == -1) { - return -1; - } + if (BaseMathObject_Prepare_ForHash(self) == -1) { + return -1; + } - return mathutils_array_hash(self->col, COLOR_SIZE); + return mathutils_array_hash(self->col, COLOR_SIZE); } /* ---------------------SEQUENCE PROTOCOLS------------------------ */ @@ -211,525 +211,523 @@ static Py_hash_t Color_hash(ColorObject *self) /* sequence length */ static int Color_len(ColorObject *UNUSED(self)) { - return COLOR_SIZE; + return COLOR_SIZE; } /* ----------------------------object[]--------------------------- */ /* sequence accessor (get) */ static PyObject *Color_item(ColorObject *self, int i) { - if (i < 0) { - i = COLOR_SIZE - i; - } - - if (i < 0 || i >= COLOR_SIZE) { - PyErr_SetString(PyExc_IndexError, - "color[item]: " - "array index out of range"); - return NULL; - } - - if (BaseMath_ReadIndexCallback(self, i) == -1) { - return NULL; - } - - return PyFloat_FromDouble(self->col[i]); - + if (i < 0) { + i = COLOR_SIZE - i; + } + + if (i < 0 || i >= COLOR_SIZE) { + PyErr_SetString(PyExc_IndexError, + "color[item]: " + "array index out of range"); + return NULL; + } + + if (BaseMath_ReadIndexCallback(self, i) == -1) { + return NULL; + } + + return PyFloat_FromDouble(self->col[i]); } /* ----------------------------object[]------------------------- */ /* sequence accessor (set) */ static int Color_ass_item(ColorObject *self, int i, PyObject *value) { - float f; - - if (BaseMath_Prepare_ForWrite(self) == -1) { - return -1; - } - - f = PyFloat_AsDouble(value); - if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */ - PyErr_SetString(PyExc_TypeError, - "color[item] = x: " - "assigned value not a number"); - return -1; - } - - if (i < 0) { - i = COLOR_SIZE - i; - } - - if (i < 0 || i >= COLOR_SIZE) { - PyErr_SetString(PyExc_IndexError, "color[item] = x: " - "array assignment index out of range"); - return -1; - } - - self->col[i] = f; - - if (BaseMath_WriteIndexCallback(self, i) == -1) { - return -1; - } - - return 0; + float f; + + if (BaseMath_Prepare_ForWrite(self) == -1) { + return -1; + } + + f = PyFloat_AsDouble(value); + if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, + "color[item] = x: " + "assigned value not a number"); + return -1; + } + + if (i < 0) { + i = COLOR_SIZE - i; + } + + if (i < 0 || i >= COLOR_SIZE) { + PyErr_SetString(PyExc_IndexError, + "color[item] = x: " + "array assignment index out of range"); + return -1; + } + + self->col[i] = f; + + if (BaseMath_WriteIndexCallback(self, i) == -1) { + return -1; + } + + return 0; } /* ----------------------------object[z:y]------------------------ */ /* sequence slice (get) */ static PyObject *Color_slice(ColorObject *self, int begin, int end) { - PyObject *tuple; - int count; - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - CLAMP(begin, 0, COLOR_SIZE); - if (end < 0) { - end = (COLOR_SIZE + 1) + end; - } - CLAMP(end, 0, COLOR_SIZE); - begin = MIN2(begin, end); - - tuple = PyTuple_New(end - begin); - for (count = begin; count < end; count++) { - PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->col[count])); - } - - return tuple; + PyObject *tuple; + int count; + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + CLAMP(begin, 0, COLOR_SIZE); + if (end < 0) { + end = (COLOR_SIZE + 1) + end; + } + CLAMP(end, 0, COLOR_SIZE); + begin = MIN2(begin, end); + + tuple = PyTuple_New(end - begin); + for (count = begin; count < end; count++) { + PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->col[count])); + } + + return tuple; } /* ----------------------------object[z:y]------------------------ */ /* sequence slice (set) */ static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq) { - int i, size; - float col[COLOR_SIZE]; - - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - - CLAMP(begin, 0, COLOR_SIZE); - if (end < 0) { - end = (COLOR_SIZE + 1) + end; - } - CLAMP(end, 0, COLOR_SIZE); - begin = MIN2(begin, end); - - if ((size = mathutils_array_parse(col, 0, COLOR_SIZE, seq, "mathutils.Color[begin:end] = []")) == -1) { - return -1; - } - - if (size != (end - begin)) { - PyErr_SetString(PyExc_ValueError, - "color[begin:end] = []: " - "size mismatch in slice assignment"); - return -1; - } - - for (i = 0; i < COLOR_SIZE; i++) { - self->col[begin + i] = col[i]; - } - - (void)BaseMath_WriteCallback(self); - return 0; + int i, size; + float col[COLOR_SIZE]; + + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + + CLAMP(begin, 0, COLOR_SIZE); + if (end < 0) { + end = (COLOR_SIZE + 1) + end; + } + CLAMP(end, 0, COLOR_SIZE); + begin = MIN2(begin, end); + + if ((size = mathutils_array_parse(col, 0, COLOR_SIZE, seq, "mathutils.Color[begin:end] = []")) == + -1) { + return -1; + } + + if (size != (end - begin)) { + PyErr_SetString(PyExc_ValueError, + "color[begin:end] = []: " + "size mismatch in slice assignment"); + return -1; + } + + for (i = 0; i < COLOR_SIZE; i++) { + self->col[begin + i] = col[i]; + } + + (void)BaseMath_WriteCallback(self); + return 0; } static PyObject *Color_subscript(ColorObject *self, PyObject *item) { - if (PyIndex_Check(item)) { - Py_ssize_t i; - i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - if (i < 0) { - i += COLOR_SIZE; - } - return Color_item(self, i); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyTuple_New(0); - } - else if (step == 1) { - return Color_slice(self, start, stop); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with color"); - return NULL; - } - } - else { - PyErr_Format(PyExc_TypeError, - "color indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return NULL; - } + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + if (i < 0) { + i += COLOR_SIZE; + } + return Color_item(self, i); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) { + return NULL; + } + + if (slicelength <= 0) { + return PyTuple_New(0); + } + else if (step == 1) { + return Color_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with color"); + return NULL; + } + } + else { + PyErr_Format( + PyExc_TypeError, "color indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return NULL; + } } static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value) { - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return -1; - } - if (i < 0) { - i += COLOR_SIZE; - } - return Color_ass_item(self, i, value); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) { - return -1; - } - - if (step == 1) { - return Color_ass_slice(self, start, stop, value); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with color"); - return -1; - } - } - else { - PyErr_Format(PyExc_TypeError, - "color indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return -1; - } + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return -1; + } + if (i < 0) { + i += COLOR_SIZE; + } + return Color_ass_item(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) { + return -1; + } + + if (step == 1) { + return Color_ass_slice(self, start, stop, value); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with color"); + return -1; + } + } + else { + PyErr_Format( + PyExc_TypeError, "color indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return -1; + } } /* -----------------PROTCOL DECLARATIONS-------------------------- */ static PySequenceMethods Color_SeqMethods = { - (lenfunc) Color_len, /* sq_length */ - (binaryfunc) NULL, /* sq_concat */ - (ssizeargfunc) NULL, /* sq_repeat */ - (ssizeargfunc) Color_item, /* sq_item */ - NULL, /* sq_slice, deprecated */ - (ssizeobjargproc) Color_ass_item, /* sq_ass_item */ - NULL, /* sq_ass_slice, deprecated */ - (objobjproc) NULL, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)Color_len, /* sq_length */ + (binaryfunc)NULL, /* sq_concat */ + (ssizeargfunc)NULL, /* sq_repeat */ + (ssizeargfunc)Color_item, /* sq_item */ + NULL, /* sq_slice, deprecated */ + (ssizeobjargproc)Color_ass_item, /* sq_ass_item */ + NULL, /* sq_ass_slice, deprecated */ + (objobjproc)NULL, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PyMappingMethods Color_AsMapping = { - (lenfunc)Color_len, - (binaryfunc)Color_subscript, - (objobjargproc)Color_ass_subscript, + (lenfunc)Color_len, + (binaryfunc)Color_subscript, + (objobjargproc)Color_ass_subscript, }; /* numeric */ - /* addition: obj + obj */ static PyObject *Color_add(PyObject *v1, PyObject *v2) { - ColorObject *color1 = NULL, *color2 = NULL; - float col[COLOR_SIZE]; - - if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_Format(PyExc_TypeError, - "Color addition: (%s + %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - color1 = (ColorObject *)v1; - color2 = (ColorObject *)v2; - - if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { - return NULL; - } - - add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE); - - return Color_CreatePyObject(col, Py_TYPE(v1)); + ColorObject *color1 = NULL, *color2 = NULL; + float col[COLOR_SIZE]; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_Format(PyExc_TypeError, + "Color addition: (%s + %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + color1 = (ColorObject *)v1; + color2 = (ColorObject *)v2; + + if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { + return NULL; + } + + add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE); + + return Color_CreatePyObject(col, Py_TYPE(v1)); } /* addition in-place: obj += obj */ static PyObject *Color_iadd(PyObject *v1, PyObject *v2) { - ColorObject *color1 = NULL, *color2 = NULL; - - if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_Format(PyExc_TypeError, - "Color addition: (%s += %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - color1 = (ColorObject *)v1; - color2 = (ColorObject *)v2; - - if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { - return NULL; - } - - add_vn_vn(color1->col, color2->col, COLOR_SIZE); - - (void)BaseMath_WriteCallback(color1); - Py_INCREF(v1); - return v1; + ColorObject *color1 = NULL, *color2 = NULL; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_Format(PyExc_TypeError, + "Color addition: (%s += %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + color1 = (ColorObject *)v1; + color2 = (ColorObject *)v2; + + if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { + return NULL; + } + + add_vn_vn(color1->col, color2->col, COLOR_SIZE); + + (void)BaseMath_WriteCallback(color1); + Py_INCREF(v1); + return v1; } /* subtraction: obj - obj */ static PyObject *Color_sub(PyObject *v1, PyObject *v2) { - ColorObject *color1 = NULL, *color2 = NULL; - float col[COLOR_SIZE]; - - if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_Format(PyExc_TypeError, - "Color subtraction: (%s - %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - color1 = (ColorObject *)v1; - color2 = (ColorObject *)v2; - - if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { - return NULL; - } - - sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE); - - return Color_CreatePyObject(col, Py_TYPE(v1)); + ColorObject *color1 = NULL, *color2 = NULL; + float col[COLOR_SIZE]; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_Format(PyExc_TypeError, + "Color subtraction: (%s - %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + color1 = (ColorObject *)v1; + color2 = (ColorObject *)v2; + + if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { + return NULL; + } + + sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE); + + return Color_CreatePyObject(col, Py_TYPE(v1)); } /* subtraction in-place: obj -= obj */ static PyObject *Color_isub(PyObject *v1, PyObject *v2) { - ColorObject *color1 = NULL, *color2 = NULL; - - if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_Format(PyExc_TypeError, - "Color subtraction: (%s -= %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - color1 = (ColorObject *)v1; - color2 = (ColorObject *)v2; - - if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { - return NULL; - } - - sub_vn_vn(color1->col, color2->col, COLOR_SIZE); - - (void)BaseMath_WriteCallback(color1); - Py_INCREF(v1); - return v1; + ColorObject *color1 = NULL, *color2 = NULL; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_Format(PyExc_TypeError, + "Color subtraction: (%s -= %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + color1 = (ColorObject *)v1; + color2 = (ColorObject *)v2; + + if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) { + return NULL; + } + + sub_vn_vn(color1->col, color2->col, COLOR_SIZE); + + (void)BaseMath_WriteCallback(color1); + Py_INCREF(v1); + return v1; } static PyObject *color_mul_float(ColorObject *color, const float scalar) { - float tcol[COLOR_SIZE]; - mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar); - return Color_CreatePyObject(tcol, Py_TYPE(color)); + float tcol[COLOR_SIZE]; + mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar); + return Color_CreatePyObject(tcol, Py_TYPE(color)); } - static PyObject *Color_mul(PyObject *v1, PyObject *v2) { - ColorObject *color1 = NULL, *color2 = NULL; - float scalar; - - if (ColorObject_Check(v1)) { - color1 = (ColorObject *)v1; - if (BaseMath_ReadCallback(color1) == -1) { - return NULL; - } - } - if (ColorObject_Check(v2)) { - color2 = (ColorObject *)v2; - if (BaseMath_ReadCallback(color2) == -1) { - return NULL; - } - } - - - /* make sure v1 is always the vector */ - if (color1 && color2) { - /* col * col, don't support yet! */ - } - else if (color1) { - if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */ - return color_mul_float(color1, scalar); - } - } - else if (color2) { - if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * COLOR */ - return color_mul_float(color2, scalar); - } - } - else { - BLI_assert(!"internal error"); - } - - PyErr_Format(PyExc_TypeError, - "Color multiplication: not supported between " - "'%.200s' and '%.200s' types", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; + ColorObject *color1 = NULL, *color2 = NULL; + float scalar; + + if (ColorObject_Check(v1)) { + color1 = (ColorObject *)v1; + if (BaseMath_ReadCallback(color1) == -1) { + return NULL; + } + } + if (ColorObject_Check(v2)) { + color2 = (ColorObject *)v2; + if (BaseMath_ReadCallback(color2) == -1) { + return NULL; + } + } + + /* make sure v1 is always the vector */ + if (color1 && color2) { + /* col * col, don't support yet! */ + } + else if (color1) { + if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */ + return color_mul_float(color1, scalar); + } + } + else if (color2) { + if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * COLOR */ + return color_mul_float(color2, scalar); + } + } + else { + BLI_assert(!"internal error"); + } + + PyErr_Format(PyExc_TypeError, + "Color multiplication: not supported between " + "'%.200s' and '%.200s' types", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; } static PyObject *Color_div(PyObject *v1, PyObject *v2) { - ColorObject *color1 = NULL; - float scalar; - - if (ColorObject_Check(v1)) { - color1 = (ColorObject *)v1; - if (BaseMath_ReadCallback(color1) == -1) { - return NULL; - } - } - else { - PyErr_SetString(PyExc_TypeError, - "Color division not supported in this order"); - return NULL; - } - - /* make sure v1 is always the vector */ - if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */ - if (scalar == 0.0f) { - PyErr_SetString(PyExc_ZeroDivisionError, - "Color division: divide by zero error"); - return NULL; - } - return color_mul_float(color1, 1.0f / scalar); - } - - PyErr_Format(PyExc_TypeError, - "Color multiplication: not supported between " - "'%.200s' and '%.200s' types", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; + ColorObject *color1 = NULL; + float scalar; + + if (ColorObject_Check(v1)) { + color1 = (ColorObject *)v1; + if (BaseMath_ReadCallback(color1) == -1) { + return NULL; + } + } + else { + PyErr_SetString(PyExc_TypeError, "Color division not supported in this order"); + return NULL; + } + + /* make sure v1 is always the vector */ + if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */ + if (scalar == 0.0f) { + PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error"); + return NULL; + } + return color_mul_float(color1, 1.0f / scalar); + } + + PyErr_Format(PyExc_TypeError, + "Color multiplication: not supported between " + "'%.200s' and '%.200s' types", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; } /* multiplication in-place: obj *= obj */ static PyObject *Color_imul(PyObject *v1, PyObject *v2) { - ColorObject *color = (ColorObject *)v1; - float scalar; - - if (BaseMath_ReadCallback_ForWrite(color) == -1) { - return NULL; - } - - /* only support color *= float */ - if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR *= FLOAT */ - mul_vn_fl(color->col, COLOR_SIZE, scalar); - } - else { - PyErr_Format(PyExc_TypeError, - "Color multiplication: (%s *= %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - - (void)BaseMath_WriteCallback(color); - Py_INCREF(v1); - return v1; + ColorObject *color = (ColorObject *)v1; + float scalar; + + if (BaseMath_ReadCallback_ForWrite(color) == -1) { + return NULL; + } + + /* only support color *= float */ + if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR *= FLOAT */ + mul_vn_fl(color->col, COLOR_SIZE, scalar); + } + else { + PyErr_Format(PyExc_TypeError, + "Color multiplication: (%s *= %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + + (void)BaseMath_WriteCallback(color); + Py_INCREF(v1); + return v1; } /* multiplication in-place: obj *= obj */ static PyObject *Color_idiv(PyObject *v1, PyObject *v2) { - ColorObject *color = (ColorObject *)v1; - float scalar; - - if (BaseMath_ReadCallback_ForWrite(color) == -1) { - return NULL; - } - - /* only support color /= float */ - if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR /= FLOAT */ - if (scalar == 0.0f) { - PyErr_SetString(PyExc_ZeroDivisionError, - "Color division: divide by zero error"); - return NULL; - } - - mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar); - } - else { - PyErr_Format(PyExc_TypeError, - "Color division: (%s /= %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - - (void)BaseMath_WriteCallback(color); - Py_INCREF(v1); - return v1; + ColorObject *color = (ColorObject *)v1; + float scalar; + + if (BaseMath_ReadCallback_ForWrite(color) == -1) { + return NULL; + } + + /* only support color /= float */ + if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR /= FLOAT */ + if (scalar == 0.0f) { + PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error"); + return NULL; + } + + mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar); + } + else { + PyErr_Format(PyExc_TypeError, + "Color division: (%s /= %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + + (void)BaseMath_WriteCallback(color); + Py_INCREF(v1); + return v1; } /* -obj * returns the negative of this object */ static PyObject *Color_neg(ColorObject *self) { - float tcol[COLOR_SIZE]; + float tcol[COLOR_SIZE]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - negate_vn_vn(tcol, self->col, COLOR_SIZE); - return Color_CreatePyObject(tcol, Py_TYPE(self)); + negate_vn_vn(tcol, self->col, COLOR_SIZE); + return Color_CreatePyObject(tcol, Py_TYPE(self)); } - static PyNumberMethods Color_NumMethods = { - (binaryfunc) Color_add, /*nb_add*/ - (binaryfunc) Color_sub, /*nb_subtract*/ - (binaryfunc) Color_mul, /*nb_multiply*/ - NULL, /*nb_remainder*/ - NULL, /*nb_divmod*/ - NULL, /*nb_power*/ - (unaryfunc) Color_neg, /*nb_negative*/ - (unaryfunc) Color_copy, /*tp_positive*/ - (unaryfunc) NULL, /*tp_absolute*/ - (inquiry) NULL, /*tp_bool*/ - (unaryfunc) NULL, /*nb_invert*/ - NULL, /*nb_lshift*/ - (binaryfunc)NULL, /*nb_rshift*/ - NULL, /*nb_and*/ - NULL, /*nb_xor*/ - NULL, /*nb_or*/ - NULL, /*nb_int*/ - NULL, /*nb_reserved*/ - NULL, /*nb_float*/ - Color_iadd, /* nb_inplace_add */ - Color_isub, /* nb_inplace_subtract */ - Color_imul, /* nb_inplace_multiply */ - NULL, /* nb_inplace_remainder */ - NULL, /* nb_inplace_power */ - NULL, /* nb_inplace_lshift */ - NULL, /* nb_inplace_rshift */ - NULL, /* nb_inplace_and */ - NULL, /* nb_inplace_xor */ - NULL, /* nb_inplace_or */ - NULL, /* nb_floor_divide */ - Color_div, /* nb_true_divide */ - NULL, /* nb_inplace_floor_divide */ - Color_idiv, /* nb_inplace_true_divide */ - NULL, /* nb_index */ + (binaryfunc)Color_add, /*nb_add*/ + (binaryfunc)Color_sub, /*nb_subtract*/ + (binaryfunc)Color_mul, /*nb_multiply*/ + NULL, /*nb_remainder*/ + NULL, /*nb_divmod*/ + NULL, /*nb_power*/ + (unaryfunc)Color_neg, /*nb_negative*/ + (unaryfunc)Color_copy, /*tp_positive*/ + (unaryfunc)NULL, /*tp_absolute*/ + (inquiry)NULL, /*tp_bool*/ + (unaryfunc)NULL, /*nb_invert*/ + NULL, /*nb_lshift*/ + (binaryfunc)NULL, /*nb_rshift*/ + NULL, /*nb_and*/ + NULL, /*nb_xor*/ + NULL, /*nb_or*/ + NULL, /*nb_int*/ + NULL, /*nb_reserved*/ + NULL, /*nb_float*/ + Color_iadd, /* nb_inplace_add */ + Color_isub, /* nb_inplace_subtract */ + Color_imul, /* nb_inplace_multiply */ + NULL, /* nb_inplace_remainder */ + NULL, /* nb_inplace_power */ + NULL, /* nb_inplace_lshift */ + NULL, /* nb_inplace_rshift */ + NULL, /* nb_inplace_and */ + NULL, /* nb_inplace_xor */ + NULL, /* nb_inplace_or */ + NULL, /* nb_floor_divide */ + Color_div, /* nb_true_divide */ + NULL, /* nb_inplace_floor_divide */ + Color_idiv, /* nb_inplace_true_divide */ + NULL, /* nb_index */ }; /* color channel, vector.r/g/b */ @@ -739,12 +737,12 @@ PyDoc_STRVAR(Color_channel_b_doc, "Blue color channel.\n\n:type: float"); static PyObject *Color_channel_get(ColorObject *self, void *type) { - return Color_item(self, POINTER_AS_INT(type)); + return Color_item(self, POINTER_AS_INT(type)); } static int Color_channel_set(ColorObject *self, PyObject *value, void *type) { - return Color_ass_item(self, POINTER_AS_INT(type), value); + return Color_ass_item(self, POINTER_AS_INT(type), value); } /* color channel (HSV), color.h/s/v */ @@ -754,258 +752,290 @@ PyDoc_STRVAR(Color_channel_hsv_v_doc, "HSV Value component in [0, 1].\n\n:type: static PyObject *Color_channel_hsv_get(ColorObject *self, void *type) { - float hsv[3]; - int i = POINTER_AS_INT(type); + float hsv[3]; + int i = POINTER_AS_INT(type); - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2])); + rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2])); - return PyFloat_FromDouble(hsv[i]); + return PyFloat_FromDouble(hsv[i]); } static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type) { - float hsv[3]; - int i = POINTER_AS_INT(type); - float f = PyFloat_AsDouble(value); - - if (f == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "color.h/s/v = value: " - "assigned value not a number"); - return -1; - } - - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - - rgb_to_hsv_v(self->col, hsv); - CLAMP(f, 0.0f, 1.0f); - hsv[i] = f; - hsv_to_rgb_v(hsv, self->col); - - if (BaseMath_WriteCallback(self) == -1) { - return -1; - } - - return 0; + float hsv[3]; + int i = POINTER_AS_INT(type); + float f = PyFloat_AsDouble(value); + + if (f == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "color.h/s/v = value: " + "assigned value not a number"); + return -1; + } + + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + + rgb_to_hsv_v(self->col, hsv); + CLAMP(f, 0.0f, 1.0f); + hsv[i] = f; + hsv_to_rgb_v(hsv, self->col); + + if (BaseMath_WriteCallback(self) == -1) { + return -1; + } + + return 0; } /* color channel (HSV), color.h/s/v */ PyDoc_STRVAR(Color_hsv_doc, "HSV Values in [0, 1].\n\n:type: float triplet"); static PyObject *Color_hsv_get(ColorObject *self, void *UNUSED(closure)) { - float hsv[3]; - PyObject *ret; + float hsv[3]; + PyObject *ret; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2])); + rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2])); - ret = PyTuple_New(3); - PyTuple_SET_ITEMS(ret, - PyFloat_FromDouble(hsv[0]), - PyFloat_FromDouble(hsv[1]), - PyFloat_FromDouble(hsv[2])); - return ret; + ret = PyTuple_New(3); + PyTuple_SET_ITEMS( + ret, PyFloat_FromDouble(hsv[0]), PyFloat_FromDouble(hsv[1]), PyFloat_FromDouble(hsv[2])); + return ret; } static int Color_hsv_set(ColorObject *self, PyObject *value, void *UNUSED(closure)) { - float hsv[3]; + float hsv[3]; - if (mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1) { - return -1; - } + if (mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1) { + return -1; + } - if (BaseMath_Prepare_ForWrite(self) == -1) { - return -1; - } + if (BaseMath_Prepare_ForWrite(self) == -1) { + return -1; + } - CLAMP(hsv[0], 0.0f, 1.0f); - CLAMP(hsv[1], 0.0f, 1.0f); - CLAMP(hsv[2], 0.0f, 1.0f); + CLAMP(hsv[0], 0.0f, 1.0f); + CLAMP(hsv[1], 0.0f, 1.0f); + CLAMP(hsv[2], 0.0f, 1.0f); - hsv_to_rgb_v(hsv, self->col); + hsv_to_rgb_v(hsv, self->col); - if (BaseMath_WriteCallback(self) == -1) { - return -1; - } + if (BaseMath_WriteCallback(self) == -1) { + return -1; + } - return 0; + return 0; } /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Color_getseters[] = { - {(char *)"r", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_r_doc, (void *)0}, - {(char *)"g", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_g_doc, (void *)1}, - {(char *)"b", (getter)Color_channel_get, (setter)Color_channel_set, Color_channel_b_doc, (void *)2}, - - {(char *)"h", (getter)Color_channel_hsv_get, (setter)Color_channel_hsv_set, (char *)Color_channel_hsv_h_doc, (void *)0}, - {(char *)"s", (getter)Color_channel_hsv_get, (setter)Color_channel_hsv_set, (char *)Color_channel_hsv_s_doc, (void *)1}, - {(char *)"v", (getter)Color_channel_hsv_get, (setter)Color_channel_hsv_set, (char *)Color_channel_hsv_v_doc, (void *)2}, - - {(char *)"hsv", (getter)Color_hsv_get, (setter)Color_hsv_set, (char *)Color_hsv_doc, (void *)0}, - - {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL}, - {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL}, - {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"r", + (getter)Color_channel_get, + (setter)Color_channel_set, + Color_channel_r_doc, + (void *)0}, + {(char *)"g", + (getter)Color_channel_get, + (setter)Color_channel_set, + Color_channel_g_doc, + (void *)1}, + {(char *)"b", + (getter)Color_channel_get, + (setter)Color_channel_set, + Color_channel_b_doc, + (void *)2}, + + {(char *)"h", + (getter)Color_channel_hsv_get, + (setter)Color_channel_hsv_set, + (char *)Color_channel_hsv_h_doc, + (void *)0}, + {(char *)"s", + (getter)Color_channel_hsv_get, + (setter)Color_channel_hsv_set, + (char *)Color_channel_hsv_s_doc, + (void *)1}, + {(char *)"v", + (getter)Color_channel_hsv_get, + (setter)Color_channel_hsv_set, + (char *)Color_channel_hsv_v_doc, + (void *)2}, + + {(char *)"hsv", + (getter)Color_hsv_get, + (setter)Color_hsv_set, + (char *)Color_hsv_doc, + (void *)0}, + + {(char *)"is_wrapped", + (getter)BaseMathObject_is_wrapped_get, + (setter)NULL, + BaseMathObject_is_wrapped_doc, + NULL}, + {(char *)"is_frozen", + (getter)BaseMathObject_is_frozen_get, + (setter)NULL, + BaseMathObject_is_frozen_doc, + NULL}, + {(char *)"owner", + (getter)BaseMathObject_owner_get, + (setter)NULL, + BaseMathObject_owner_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; - /* -----------------------METHOD DEFINITIONS ---------------------- */ static struct PyMethodDef Color_methods[] = { - {"copy", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc}, - {"__copy__", (PyCFunction) Color_copy, METH_NOARGS, Color_copy_doc}, - {"__deepcopy__", (PyCFunction) Color_deepcopy, METH_VARARGS, Color_copy_doc}, + {"copy", (PyCFunction)Color_copy, METH_NOARGS, Color_copy_doc}, + {"__copy__", (PyCFunction)Color_copy, METH_NOARGS, Color_copy_doc}, + {"__deepcopy__", (PyCFunction)Color_deepcopy, METH_VARARGS, Color_copy_doc}, - /* base-math methods */ - {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, - {NULL, NULL, 0, NULL}, + /* base-math methods */ + {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, + {NULL, NULL, 0, NULL}, }; /* ------------------PY_OBECT DEFINITION-------------------------- */ PyDoc_STRVAR(color_doc, -".. class:: Color(rgb)\n" -"\n" -" This object gives access to Colors in Blender.\n" -"\n" -" :param rgb: (r, g, b) color values\n" -" :type rgb: 3d vector\n" -); + ".. class:: Color(rgb)\n" + "\n" + " This object gives access to Colors in Blender.\n" + "\n" + " :param rgb: (r, g, b) color values\n" + " :type rgb: 3d vector\n"); PyTypeObject color_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "Color", /* tp_name */ - sizeof(ColorObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)BaseMathObject_dealloc, /* tp_dealloc */ - NULL, /* tp_print */ - NULL, /* tp_getattr */ - NULL, /* tp_setattr */ - NULL, /* tp_compare */ - (reprfunc) Color_repr, /* tp_repr */ - &Color_NumMethods, /* tp_as_number */ - &Color_SeqMethods, /* tp_as_sequence */ - &Color_AsMapping, /* tp_as_mapping */ - (hashfunc)Color_hash, /* tp_hash */ - NULL, /* tp_call */ + PyVarObject_HEAD_INIT(NULL, 0) "Color", /* tp_name */ + sizeof(ColorObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + (reprfunc)Color_repr, /* tp_repr */ + &Color_NumMethods, /* tp_as_number */ + &Color_SeqMethods, /* tp_as_sequence */ + &Color_AsMapping, /* tp_as_mapping */ + (hashfunc)Color_hash, /* tp_hash */ + NULL, /* tp_call */ #ifndef MATH_STANDALONE - (reprfunc) Color_str, /* tp_str */ + (reprfunc)Color_str, /* tp_str */ #else - NULL, /* tp_str */ + NULL, /* tp_str */ #endif - NULL, /* tp_getattro */ - NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - color_doc, /* tp_doc */ - (traverseproc)BaseMathObject_traverse, /* tp_traverse */ - (inquiry)BaseMathObject_clear, /* tp_clear */ - (richcmpfunc)Color_richcmpr, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - NULL, /* tp_iter */ - NULL, /* tp_iternext */ - Color_methods, /* tp_methods */ - NULL, /* tp_members */ - Color_getseters, /* tp_getset */ - NULL, /* tp_base */ - NULL, /* tp_dict */ - NULL, /* tp_descr_get */ - NULL, /* tp_descr_set */ - 0, /* tp_dictoffset */ - NULL, /* tp_init */ - NULL, /* tp_alloc */ - Color_new, /* tp_new */ - NULL, /* tp_free */ - NULL, /* tp_is_gc */ - NULL, /* tp_bases */ - NULL, /* tp_mro */ - NULL, /* tp_cache */ - NULL, /* tp_subclasses */ - NULL, /* tp_weaklist */ - NULL, /* tp_del */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + color_doc, /* tp_doc */ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /* tp_clear */ + (richcmpfunc)Color_richcmpr, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + Color_methods, /* tp_methods */ + NULL, /* tp_members */ + Color_getseters, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + Color_new, /* tp_new */ + NULL, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + NULL, /* tp_del */ }; -PyObject *Color_CreatePyObject( - const float col[3], - PyTypeObject *base_type) +PyObject *Color_CreatePyObject(const float col[3], PyTypeObject *base_type) { - ColorObject *self; - float *col_alloc; - - col_alloc = PyMem_Malloc(COLOR_SIZE * sizeof(float)); - if (UNLIKELY(col_alloc == NULL)) { - PyErr_SetString(PyExc_MemoryError, - "Color(): " - "problem allocating data"); - return NULL; - } - - self = BASE_MATH_NEW(ColorObject, color_Type, base_type); - if (self) { - self->col = col_alloc; - - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; - - /* NEW */ - if (col) { - copy_v3_v3(self->col, col); - } - else { - zero_v3(self->col); - } - - self->flag = BASE_MATH_FLAG_DEFAULT; - } - else { - PyMem_Free(col_alloc); - } - - return (PyObject *)self; + ColorObject *self; + float *col_alloc; + + col_alloc = PyMem_Malloc(COLOR_SIZE * sizeof(float)); + if (UNLIKELY(col_alloc == NULL)) { + PyErr_SetString(PyExc_MemoryError, + "Color(): " + "problem allocating data"); + return NULL; + } + + self = BASE_MATH_NEW(ColorObject, color_Type, base_type); + if (self) { + self->col = col_alloc; + + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; + + /* NEW */ + if (col) { + copy_v3_v3(self->col, col); + } + else { + zero_v3(self->col); + } + + self->flag = BASE_MATH_FLAG_DEFAULT; + } + else { + PyMem_Free(col_alloc); + } + + return (PyObject *)self; } -PyObject *Color_CreatePyObject_wrap( - float col[3], - PyTypeObject *base_type) +PyObject *Color_CreatePyObject_wrap(float col[3], PyTypeObject *base_type) { - ColorObject *self; + ColorObject *self; - self = BASE_MATH_NEW(ColorObject, color_Type, base_type); - if (self) { - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; + self = BASE_MATH_NEW(ColorObject, color_Type, base_type); + if (self) { + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; - /* WRAP */ - self->col = col; - self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; - } + /* WRAP */ + self->col = col; + self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; + } - return (PyObject *)self; + return (PyObject *)self; } PyObject *Color_CreatePyObject_cb(PyObject *cb_user, - unsigned char cb_type, unsigned char cb_subtype) -{ - ColorObject *self = (ColorObject *)Color_CreatePyObject(NULL, NULL); - if (self) { - Py_INCREF(cb_user); - self->cb_user = cb_user; - self->cb_type = cb_type; - self->cb_subtype = cb_subtype; - PyObject_GC_Track(self); - } - - return (PyObject *)self; + unsigned char cb_type, + unsigned char cb_subtype) +{ + ColorObject *self = (ColorObject *)Color_CreatePyObject(NULL, NULL); + if (self) { + Py_INCREF(cb_user); + self->cb_user = cb_user; + self->cb_type = cb_type; + self->cb_subtype = cb_subtype; + PyObject_GC_Track(self); + } + + return (PyObject *)self; } diff --git a/source/blender/python/mathutils/mathutils_Color.h b/source/blender/python/mathutils/mathutils_Color.h index 6dc56f8aacb..51e1746ae74 100644 --- a/source/blender/python/mathutils/mathutils_Color.h +++ b/source/blender/python/mathutils/mathutils_Color.h @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #ifndef __MATHUTILS_COLOR_H__ #define __MATHUTILS_COLOR_H__ @@ -27,7 +26,7 @@ extern PyTypeObject color_Type; #define ColorObject_CheckExact(v) (Py_TYPE(v) == &color_Type) typedef struct { - BASE_MATH_MEMBERS(col); + BASE_MATH_MEMBERS(col); } ColorObject; /* struct data contains a pointer to the actual data that the @@ -36,17 +35,12 @@ typedef struct { * blender (stored in blend_data). This is an either/or struct not both*/ /* prototypes */ -PyObject *Color_CreatePyObject( - const float col[3], - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT; -PyObject *Color_CreatePyObject_wrap( - float col[3], - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -PyObject *Color_CreatePyObject_cb( - PyObject *cb_user, - unsigned char cb_type, unsigned char cb_subtype - ) ATTR_WARN_UNUSED_RESULT; +PyObject *Color_CreatePyObject(const float col[3], + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; +PyObject *Color_CreatePyObject_wrap(float col[3], PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); +PyObject *Color_CreatePyObject_cb(PyObject *cb_user, + unsigned char cb_type, + unsigned char cb_subtype) ATTR_WARN_UNUSED_RESULT; #endif /* __MATHUTILS_COLOR_H__ */ diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 4177fc489bb..56662465b52 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #include #include "mathutils.h" @@ -38,291 +37,289 @@ /* makes a new euler for you to play with */ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *seq = NULL; - const char *order_str = NULL; - - float eul[EULER_SIZE] = {0.0f, 0.0f, 0.0f}; - short order = EULER_ORDER_XYZ; - - if (kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, - "mathutils.Euler(): " - "takes no keyword args"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str)) { - return NULL; - } - - switch (PyTuple_GET_SIZE(args)) { - case 0: - break; - case 2: - if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1) { - return NULL; - } - ATTR_FALLTHROUGH; - case 1: - if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1) { - return NULL; - } - break; - } - return Euler_CreatePyObject(eul, order, type); + PyObject *seq = NULL; + const char *order_str = NULL; + + float eul[EULER_SIZE] = {0.0f, 0.0f, 0.0f}; + short order = EULER_ORDER_XYZ; + + if (kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "mathutils.Euler(): " + "takes no keyword args"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str)) { + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1) { + return NULL; + } + ATTR_FALLTHROUGH; + case 1: + if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1) { + return NULL; + } + break; + } + return Euler_CreatePyObject(eul, order, type); } /* internal use, assume read callback is done */ static const char *euler_order_str(EulerObject *self) { - static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"}; - return order[self->order - EULER_ORDER_XYZ]; + static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"}; + return order[self->order - EULER_ORDER_XYZ]; } short euler_order_from_string(const char *str, const char *error_prefix) { - if ((str[0] && str[1] && str[2] && str[3] == '\0')) { + if ((str[0] && str[1] && str[2] && str[3] == '\0')) { #ifdef __LITTLE_ENDIAN__ -# define MAKE_ID3(a, b, c) (((a)) | ((b) << 8) | ((c) << 16)) +# define MAKE_ID3(a, b, c) (((a)) | ((b) << 8) | ((c) << 16)) #else -# define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8)) +# define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8)) #endif - switch (*((PY_INT32_T *)str)) { - case MAKE_ID3('X', 'Y', 'Z'): return EULER_ORDER_XYZ; - case MAKE_ID3('X', 'Z', 'Y'): return EULER_ORDER_XZY; - case MAKE_ID3('Y', 'X', 'Z'): return EULER_ORDER_YXZ; - case MAKE_ID3('Y', 'Z', 'X'): return EULER_ORDER_YZX; - case MAKE_ID3('Z', 'X', 'Y'): return EULER_ORDER_ZXY; - case MAKE_ID3('Z', 'Y', 'X'): return EULER_ORDER_ZYX; - } + switch (*((PY_INT32_T *)str)) { + case MAKE_ID3('X', 'Y', 'Z'): + return EULER_ORDER_XYZ; + case MAKE_ID3('X', 'Z', 'Y'): + return EULER_ORDER_XZY; + case MAKE_ID3('Y', 'X', 'Z'): + return EULER_ORDER_YXZ; + case MAKE_ID3('Y', 'Z', 'X'): + return EULER_ORDER_YZX; + case MAKE_ID3('Z', 'X', 'Y'): + return EULER_ORDER_ZXY; + case MAKE_ID3('Z', 'Y', 'X'): + return EULER_ORDER_ZYX; + } #undef MAKE_ID3 - } + } - PyErr_Format(PyExc_ValueError, - "%s: invalid euler order '%s'", - error_prefix, str); - return -1; + PyErr_Format(PyExc_ValueError, "%s: invalid euler order '%s'", error_prefix, str); + return -1; } /* note: BaseMath_ReadCallback must be called beforehand */ static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits) { - PyObject *ret; - int i; - - ret = PyTuple_New(EULER_SIZE); - - if (ndigits >= 0) { - for (i = 0; i < EULER_SIZE; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits))); - } - } - else { - for (i = 0; i < EULER_SIZE; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i])); - } - } - - return ret; + PyObject *ret; + int i; + + ret = PyTuple_New(EULER_SIZE); + + if (ndigits >= 0) { + for (i = 0; i < EULER_SIZE; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits))); + } + } + else { + for (i = 0; i < EULER_SIZE; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i])); + } + } + + return ret; } /* -----------------------------METHODS---------------------------- * return a quaternion representation of the euler */ PyDoc_STRVAR(Euler_to_quaternion_doc, -".. method:: to_quaternion()\n" -"\n" -" Return a quaternion representation of the euler.\n" -"\n" -" :return: Quaternion representation of the euler.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. method:: to_quaternion()\n" + "\n" + " Return a quaternion representation of the euler.\n" + "\n" + " :return: Quaternion representation of the euler.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Euler_to_quaternion(EulerObject *self) { - float quat[4]; + float quat[4]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - eulO_to_quat(quat, self->eul, self->order); + eulO_to_quat(quat, self->eul, self->order); - return Quaternion_CreatePyObject(quat, NULL); + return Quaternion_CreatePyObject(quat, NULL); } /* return a matrix representation of the euler */ PyDoc_STRVAR(Euler_to_matrix_doc, -".. method:: to_matrix()\n" -"\n" -" Return a matrix representation of the euler.\n" -"\n" -" :return: A 3x3 rotation matrix representation of the euler.\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: to_matrix()\n" + "\n" + " Return a matrix representation of the euler.\n" + "\n" + " :return: A 3x3 rotation matrix representation of the euler.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Euler_to_matrix(EulerObject *self) { - float mat[9]; + float mat[9]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - eulO_to_mat3((float (*)[3])mat, self->eul, self->order); + eulO_to_mat3((float(*)[3])mat, self->eul, self->order); - return Matrix_CreatePyObject(mat, 3, 3, NULL); + return Matrix_CreatePyObject(mat, 3, 3, NULL); } PyDoc_STRVAR(Euler_zero_doc, -".. method:: zero()\n" -"\n" -" Set all values to zero.\n" -); + ".. method:: zero()\n" + "\n" + " Set all values to zero.\n"); static PyObject *Euler_zero(EulerObject *self) { - if (BaseMath_Prepare_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_Prepare_ForWrite(self) == -1) { + return NULL; + } - zero_v3(self->eul); + zero_v3(self->eul); - if (BaseMath_WriteCallback(self) == -1) { - return NULL; - } + if (BaseMath_WriteCallback(self) == -1) { + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(Euler_rotate_axis_doc, -".. method:: rotate_axis(axis, angle)\n" -"\n" -" Rotates the euler a certain amount and returning a unique euler rotation\n" -" (no 720 degree pitches).\n" -"\n" -" :arg axis: single character in ['X, 'Y', 'Z'].\n" -" :type axis: string\n" -" :arg angle: angle in radians.\n" -" :type angle: float\n" -); + ".. method:: rotate_axis(axis, angle)\n" + "\n" + " Rotates the euler a certain amount and returning a unique euler rotation\n" + " (no 720 degree pitches).\n" + "\n" + " :arg axis: single character in ['X, 'Y', 'Z'].\n" + " :type axis: string\n" + " :arg angle: angle in radians.\n" + " :type angle: float\n"); static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args) { - float angle = 0.0f; - int axis; /* actually a character */ - - if (!PyArg_ParseTuple(args, "Cf:rotate_axis", &axis, &angle)) { - PyErr_SetString(PyExc_TypeError, - "Euler.rotate_axis(): " - "expected an axis 'X', 'Y', 'Z' and an angle (float)"); - return NULL; - } + float angle = 0.0f; + int axis; /* actually a character */ - if (!(ELEM(axis, 'X', 'Y', 'Z'))) { - PyErr_SetString(PyExc_ValueError, - "Euler.rotate_axis(): " - "expected axis to be 'X', 'Y' or 'Z'"); - return NULL; - } + if (!PyArg_ParseTuple(args, "Cf:rotate_axis", &axis, &angle)) { + PyErr_SetString(PyExc_TypeError, + "Euler.rotate_axis(): " + "expected an axis 'X', 'Y', 'Z' and an angle (float)"); + return NULL; + } - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (!(ELEM(axis, 'X', 'Y', 'Z'))) { + PyErr_SetString(PyExc_ValueError, + "Euler.rotate_axis(): " + "expected axis to be 'X', 'Y' or 'Z'"); + return NULL; + } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - rotate_eulO(self->eul, self->order, (char)axis, angle); + rotate_eulO(self->eul, self->order, (char)axis, angle); - (void)BaseMath_WriteCallback(self); + (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(Euler_rotate_doc, -".. method:: rotate(other)\n" -"\n" -" Rotates the euler by another mathutils value.\n" -"\n" -" :arg other: rotation component of mathutils value\n" -" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" -); + ".. method:: rotate(other)\n" + "\n" + " Rotates the euler by another mathutils value.\n" + "\n" + " :arg other: rotation component of mathutils value\n" + " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"); static PyObject *Euler_rotate(EulerObject *self, PyObject *value) { - float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; + float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1) { - return NULL; - } + if (mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1) { + return NULL; + } - eulO_to_mat3(self_rmat, self->eul, self->order); - mul_m3_m3m3(rmat, other_rmat, self_rmat); + eulO_to_mat3(self_rmat, self->eul, self->order); + mul_m3_m3m3(rmat, other_rmat, self_rmat); - mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat); + mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Euler_make_compatible_doc, -".. method:: make_compatible(other)\n" -"\n" -" Make this euler compatible with another,\n" -" so interpolating between them works as intended.\n" -"\n" -" .. note:: the rotation order is not taken into account for this function.\n" -); + ".. method:: make_compatible(other)\n" + "\n" + " Make this euler compatible with another,\n" + " so interpolating between them works as intended.\n" + "\n" + " .. note:: the rotation order is not taken into account for this function.\n"); static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value) { - float teul[EULER_SIZE]; + float teul[EULER_SIZE]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value, - "euler.make_compatible(other), invalid 'other' arg") == -1) - { - return NULL; - } + if (mathutils_array_parse(teul, + EULER_SIZE, + EULER_SIZE, + value, + "euler.make_compatible(other), invalid 'other' arg") == -1) { + return NULL; + } - compatible_eul(self->eul, teul); + compatible_eul(self->eul, teul); - (void)BaseMath_WriteCallback(self); + (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + Py_RETURN_NONE; } /* ----------------------------Euler.rotate()----------------------- * return a copy of the euler */ PyDoc_STRVAR(Euler_copy_doc, -".. function:: copy()\n" -"\n" -" Returns a copy of this euler.\n" -"\n" -" :return: A copy of the euler.\n" -" :rtype: :class:`Euler`\n" -"\n" -" .. note:: use this to get a copy of a wrapped euler with\n" -" no reference to the original data.\n" -); + ".. function:: copy()\n" + "\n" + " Returns a copy of this euler.\n" + "\n" + " :return: A copy of the euler.\n" + " :rtype: :class:`Euler`\n" + "\n" + " .. note:: use this to get a copy of a wrapped euler with\n" + " no reference to the original data.\n"); static PyObject *Euler_copy(EulerObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return Euler_CreatePyObject(self->eul, self->order, Py_TYPE(self)); + return Euler_CreatePyObject(self->eul, self->order, Py_TYPE(self)); } static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args) { - if (!PyC_CheckArgs_DeepCopy(args)) { - return NULL; - } - return Euler_copy(self); + if (!PyC_CheckArgs_DeepCopy(args)) { + return NULL; + } + return Euler_copy(self); } /* ----------------------------print object (internal)-------------- @@ -330,87 +327,94 @@ static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args) static PyObject *Euler_repr(EulerObject *self) { - PyObject *ret, *tuple; + PyObject *ret, *tuple; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - tuple = Euler_ToTupleExt(self, -1); + tuple = Euler_ToTupleExt(self, -1); - ret = PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self)); + ret = PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self)); - Py_DECREF(tuple); - return ret; + Py_DECREF(tuple); + return ret; } #ifndef MATH_STANDALONE static PyObject *Euler_str(EulerObject *self) { - DynStr *ds; + DynStr *ds; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - ds = BLI_dynstr_new(); + ds = BLI_dynstr_new(); - BLI_dynstr_appendf(ds, "", - self->eul[0], self->eul[1], self->eul[2], euler_order_str(self)); + BLI_dynstr_appendf(ds, + "", + self->eul[0], + self->eul[1], + self->eul[2], + euler_order_str(self)); - return mathutils_dynstr_to_py(ds); /* frees ds */ + return mathutils_dynstr_to_py(ds); /* frees ds */ } #endif static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ - - if (EulerObject_Check(a) && EulerObject_Check(b)) { - EulerObject *eulA = (EulerObject *)a; - EulerObject *eulB = (EulerObject *)b; - - if (BaseMath_ReadCallback(eulA) == -1 || BaseMath_ReadCallback(eulB) == -1) { - return NULL; - } - - ok = ((eulA->order == eulB->order) && EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? 0 : -1; - } - - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; - - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } - - return Py_INCREF_RET(res); + PyObject *res; + int ok = -1; /* zero is true */ + + if (EulerObject_Check(a) && EulerObject_Check(b)) { + EulerObject *eulA = (EulerObject *)a; + EulerObject *eulB = (EulerObject *)b; + + if (BaseMath_ReadCallback(eulA) == -1 || BaseMath_ReadCallback(eulB) == -1) { + return NULL; + } + + ok = ((eulA->order == eulB->order) && + EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ? + 0 : + -1; + } + + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; + + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } + + return Py_INCREF_RET(res); } static Py_hash_t Euler_hash(EulerObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } - if (BaseMathObject_Prepare_ForHash(self) == -1) { - return -1; - } + if (BaseMathObject_Prepare_ForHash(self) == -1) { + return -1; + } - return mathutils_array_hash(self->eul, EULER_SIZE); + return mathutils_array_hash(self->eul, EULER_SIZE); } /* ---------------------SEQUENCE PROTOCOLS------------------------ */ @@ -418,449 +422,451 @@ static Py_hash_t Euler_hash(EulerObject *self) /* sequence length */ static int Euler_len(EulerObject *UNUSED(self)) { - return EULER_SIZE; + return EULER_SIZE; } /* ----------------------------object[]--------------------------- */ /* sequence accessor (get) */ static PyObject *Euler_item(EulerObject *self, int i) { - if (i < 0) { - i = EULER_SIZE - i; - } - - if (i < 0 || i >= EULER_SIZE) { - PyErr_SetString(PyExc_IndexError, - "euler[attribute]: " - "array index out of range"); - return NULL; - } - - if (BaseMath_ReadIndexCallback(self, i) == -1) { - return NULL; - } - - return PyFloat_FromDouble(self->eul[i]); - + if (i < 0) { + i = EULER_SIZE - i; + } + + if (i < 0 || i >= EULER_SIZE) { + PyErr_SetString(PyExc_IndexError, + "euler[attribute]: " + "array index out of range"); + return NULL; + } + + if (BaseMath_ReadIndexCallback(self, i) == -1) { + return NULL; + } + + return PyFloat_FromDouble(self->eul[i]); } /* ----------------------------object[]------------------------- */ /* sequence accessor (set) */ static int Euler_ass_item(EulerObject *self, int i, PyObject *value) { - float f; - - if (BaseMath_Prepare_ForWrite(self) == -1) { - return -1; - } - - f = PyFloat_AsDouble(value); - if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */ - PyErr_SetString(PyExc_TypeError, - "euler[attribute] = x: " - "assigned value not a number"); - return -1; - } - - if (i < 0) { - i = EULER_SIZE - i; - } - - if (i < 0 || i >= EULER_SIZE) { - PyErr_SetString(PyExc_IndexError, - "euler[attribute] = x: " - "array assignment index out of range"); - return -1; - } - - self->eul[i] = f; - - if (BaseMath_WriteIndexCallback(self, i) == -1) { - return -1; - } - - return 0; + float f; + + if (BaseMath_Prepare_ForWrite(self) == -1) { + return -1; + } + + f = PyFloat_AsDouble(value); + if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, + "euler[attribute] = x: " + "assigned value not a number"); + return -1; + } + + if (i < 0) { + i = EULER_SIZE - i; + } + + if (i < 0 || i >= EULER_SIZE) { + PyErr_SetString(PyExc_IndexError, + "euler[attribute] = x: " + "array assignment index out of range"); + return -1; + } + + self->eul[i] = f; + + if (BaseMath_WriteIndexCallback(self, i) == -1) { + return -1; + } + + return 0; } /* ----------------------------object[z:y]------------------------ */ /* sequence slice (get) */ static PyObject *Euler_slice(EulerObject *self, int begin, int end) { - PyObject *tuple; - int count; - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - CLAMP(begin, 0, EULER_SIZE); - if (end < 0) { - end = (EULER_SIZE + 1) + end; - } - CLAMP(end, 0, EULER_SIZE); - begin = MIN2(begin, end); - - tuple = PyTuple_New(end - begin); - for (count = begin; count < end; count++) { - PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->eul[count])); - } - - return tuple; + PyObject *tuple; + int count; + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + CLAMP(begin, 0, EULER_SIZE); + if (end < 0) { + end = (EULER_SIZE + 1) + end; + } + CLAMP(end, 0, EULER_SIZE); + begin = MIN2(begin, end); + + tuple = PyTuple_New(end - begin); + for (count = begin; count < end; count++) { + PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->eul[count])); + } + + return tuple; } /* ----------------------------object[z:y]------------------------ */ /* sequence slice (set) */ static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq) { - int i, size; - float eul[EULER_SIZE]; - - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - - CLAMP(begin, 0, EULER_SIZE); - if (end < 0) { - end = (EULER_SIZE + 1) + end; - } - CLAMP(end, 0, EULER_SIZE); - begin = MIN2(begin, end); - - if ((size = mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) == -1) { - return -1; - } - - if (size != (end - begin)) { - PyErr_SetString(PyExc_ValueError, - "euler[begin:end] = []: " - "size mismatch in slice assignment"); - return -1; - } - - for (i = 0; i < EULER_SIZE; i++) { - self->eul[begin + i] = eul[i]; - } - - (void)BaseMath_WriteCallback(self); - return 0; + int i, size; + float eul[EULER_SIZE]; + + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + + CLAMP(begin, 0, EULER_SIZE); + if (end < 0) { + end = (EULER_SIZE + 1) + end; + } + CLAMP(end, 0, EULER_SIZE); + begin = MIN2(begin, end); + + if ((size = mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) == + -1) { + return -1; + } + + if (size != (end - begin)) { + PyErr_SetString(PyExc_ValueError, + "euler[begin:end] = []: " + "size mismatch in slice assignment"); + return -1; + } + + for (i = 0; i < EULER_SIZE; i++) { + self->eul[begin + i] = eul[i]; + } + + (void)BaseMath_WriteCallback(self); + return 0; } static PyObject *Euler_subscript(EulerObject *self, PyObject *item) { - if (PyIndex_Check(item)) { - Py_ssize_t i; - i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - if (i < 0) { - i += EULER_SIZE; - } - return Euler_item(self, i); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyTuple_New(0); - } - else if (step == 1) { - return Euler_slice(self, start, stop); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with eulers"); - return NULL; - } - } - else { - PyErr_Format(PyExc_TypeError, - "euler indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return NULL; - } + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + if (i < 0) { + i += EULER_SIZE; + } + return Euler_item(self, i); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) { + return NULL; + } + + if (slicelength <= 0) { + return PyTuple_New(0); + } + else if (step == 1) { + return Euler_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with eulers"); + return NULL; + } + } + else { + PyErr_Format( + PyExc_TypeError, "euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return NULL; + } } - static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value) { - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return -1; - } - if (i < 0) { - i += EULER_SIZE; - } - return Euler_ass_item(self, i, value); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) { - return -1; - } - - if (step == 1) { - return Euler_ass_slice(self, start, stop, value); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with euler"); - return -1; - } - } - else { - PyErr_Format(PyExc_TypeError, - "euler indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return -1; - } + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return -1; + } + if (i < 0) { + i += EULER_SIZE; + } + return Euler_ass_item(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) { + return -1; + } + + if (step == 1) { + return Euler_ass_slice(self, start, stop, value); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with euler"); + return -1; + } + } + else { + PyErr_Format( + PyExc_TypeError, "euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return -1; + } } /* -----------------PROTCOL DECLARATIONS-------------------------- */ static PySequenceMethods Euler_SeqMethods = { - (lenfunc) Euler_len, /* sq_length */ - (binaryfunc) NULL, /* sq_concat */ - (ssizeargfunc) NULL, /* sq_repeat */ - (ssizeargfunc) Euler_item, /* sq_item */ - (ssizessizeargfunc) NULL, /* sq_slice, deprecated */ - (ssizeobjargproc) Euler_ass_item, /* sq_ass_item */ - (ssizessizeobjargproc) NULL, /* sq_ass_slice, deprecated */ - (objobjproc) NULL, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)Euler_len, /* sq_length */ + (binaryfunc)NULL, /* sq_concat */ + (ssizeargfunc)NULL, /* sq_repeat */ + (ssizeargfunc)Euler_item, /* sq_item */ + (ssizessizeargfunc)NULL, /* sq_slice, deprecated */ + (ssizeobjargproc)Euler_ass_item, /* sq_ass_item */ + (ssizessizeobjargproc)NULL, /* sq_ass_slice, deprecated */ + (objobjproc)NULL, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PyMappingMethods Euler_AsMapping = { - (lenfunc)Euler_len, - (binaryfunc)Euler_subscript, - (objobjargproc)Euler_ass_subscript, + (lenfunc)Euler_len, + (binaryfunc)Euler_subscript, + (objobjargproc)Euler_ass_subscript, }; /* euler axis, euler.x/y/z */ -PyDoc_STRVAR(Euler_axis_doc, -"Euler axis angle in radians.\n\n:type: float" -); +PyDoc_STRVAR(Euler_axis_doc, "Euler axis angle in radians.\n\n:type: float"); static PyObject *Euler_axis_get(EulerObject *self, void *type) { - return Euler_item(self, POINTER_AS_INT(type)); + return Euler_item(self, POINTER_AS_INT(type)); } static int Euler_axis_set(EulerObject *self, PyObject *value, void *type) { - return Euler_ass_item(self, POINTER_AS_INT(type), value); + return Euler_ass_item(self, POINTER_AS_INT(type), value); } /* rotation order */ -PyDoc_STRVAR(Euler_order_doc, -"Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']" -); +PyDoc_STRVAR( + Euler_order_doc, + "Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']"); static PyObject *Euler_order_get(EulerObject *self, void *UNUSED(closure)) { - if (BaseMath_ReadCallback(self) == -1) { - /* can read order too */ - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + /* can read order too */ + return NULL; + } - return PyUnicode_FromString(euler_order_str(self)); + return PyUnicode_FromString(euler_order_str(self)); } static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(closure)) { - const char *order_str; - short order; - - if (BaseMath_Prepare_ForWrite(self) == -1) { - return -1; - } - - if (((order_str = _PyUnicode_AsString(value)) == NULL) || - ((order = euler_order_from_string(order_str, "euler.order")) == -1)) - { - return -1; - } - - self->order = order; - (void)BaseMath_WriteCallback(self); /* order can be written back */ - return 0; + const char *order_str; + short order; + + if (BaseMath_Prepare_ForWrite(self) == -1) { + return -1; + } + + if (((order_str = _PyUnicode_AsString(value)) == NULL) || + ((order = euler_order_from_string(order_str, "euler.order")) == -1)) { + return -1; + } + + self->order = order; + (void)BaseMath_WriteCallback(self); /* order can be written back */ + return 0; } /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Euler_getseters[] = { - {(char *)"x", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)0}, - {(char *)"y", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)1}, - {(char *)"z", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)2}, - {(char *)"order", (getter)Euler_order_get, (setter)Euler_order_set, Euler_order_doc, (void *)NULL}, - - {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL}, - {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL}, - {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"x", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)0}, + {(char *)"y", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)1}, + {(char *)"z", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)2}, + {(char *)"order", + (getter)Euler_order_get, + (setter)Euler_order_set, + Euler_order_doc, + (void *)NULL}, + + {(char *)"is_wrapped", + (getter)BaseMathObject_is_wrapped_get, + (setter)NULL, + BaseMathObject_is_wrapped_doc, + NULL}, + {(char *)"is_frozen", + (getter)BaseMathObject_is_frozen_get, + (setter)NULL, + BaseMathObject_is_frozen_doc, + NULL}, + {(char *)"owner", + (getter)BaseMathObject_owner_get, + (setter)NULL, + BaseMathObject_owner_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; - /* -----------------------METHOD DEFINITIONS ---------------------- */ static struct PyMethodDef Euler_methods[] = { - {"zero", (PyCFunction) Euler_zero, METH_NOARGS, Euler_zero_doc}, - {"to_matrix", (PyCFunction) Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc}, - {"to_quaternion", (PyCFunction) Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc}, - {"rotate_axis", (PyCFunction) Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc}, - {"rotate", (PyCFunction) Euler_rotate, METH_O, Euler_rotate_doc}, - {"make_compatible", (PyCFunction) Euler_make_compatible, METH_O, Euler_make_compatible_doc}, - {"copy", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc}, - {"__copy__", (PyCFunction) Euler_copy, METH_NOARGS, Euler_copy_doc}, - {"__deepcopy__", (PyCFunction) Euler_deepcopy, METH_VARARGS, Euler_copy_doc}, - - /* base-math methods */ - {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, - {NULL, NULL, 0, NULL}, + {"zero", (PyCFunction)Euler_zero, METH_NOARGS, Euler_zero_doc}, + {"to_matrix", (PyCFunction)Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc}, + {"to_quaternion", (PyCFunction)Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc}, + {"rotate_axis", (PyCFunction)Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc}, + {"rotate", (PyCFunction)Euler_rotate, METH_O, Euler_rotate_doc}, + {"make_compatible", (PyCFunction)Euler_make_compatible, METH_O, Euler_make_compatible_doc}, + {"copy", (PyCFunction)Euler_copy, METH_NOARGS, Euler_copy_doc}, + {"__copy__", (PyCFunction)Euler_copy, METH_NOARGS, Euler_copy_doc}, + {"__deepcopy__", (PyCFunction)Euler_deepcopy, METH_VARARGS, Euler_copy_doc}, + + /* base-math methods */ + {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, + {NULL, NULL, 0, NULL}, }; /* ------------------PY_OBECT DEFINITION-------------------------- */ -PyDoc_STRVAR(euler_doc, -".. class:: Euler(angles, order='XYZ')\n" -"\n" -" This object gives access to Eulers in Blender.\n" -"\n" -" .. seealso:: `Euler angles `__ on Wikipedia.\n" -"\n" -" :param angles: Three angles, in radians.\n" -" :type angles: 3d vector\n" -" :param order: Optional order of the angles, a permutation of ``XYZ``.\n" -" :type order: str\n" -); +PyDoc_STRVAR( + euler_doc, + ".. class:: Euler(angles, order='XYZ')\n" + "\n" + " This object gives access to Eulers in Blender.\n" + "\n" + " .. seealso:: `Euler angles `__ on Wikipedia.\n" + "\n" + " :param angles: Three angles, in radians.\n" + " :type angles: 3d vector\n" + " :param order: Optional order of the angles, a permutation of ``XYZ``.\n" + " :type order: str\n"); PyTypeObject euler_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "Euler", /* tp_name */ - sizeof(EulerObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)BaseMathObject_dealloc, /* tp_dealloc */ - NULL, /* tp_print */ - NULL, /* tp_getattr */ - NULL, /* tp_setattr */ - NULL, /* tp_compare */ - (reprfunc) Euler_repr, /* tp_repr */ - NULL, /* tp_as_number */ - &Euler_SeqMethods, /* tp_as_sequence */ - &Euler_AsMapping, /* tp_as_mapping */ - (hashfunc)Euler_hash, /* tp_hash */ - NULL, /* tp_call */ + PyVarObject_HEAD_INIT(NULL, 0) "Euler", /* tp_name */ + sizeof(EulerObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + (reprfunc)Euler_repr, /* tp_repr */ + NULL, /* tp_as_number */ + &Euler_SeqMethods, /* tp_as_sequence */ + &Euler_AsMapping, /* tp_as_mapping */ + (hashfunc)Euler_hash, /* tp_hash */ + NULL, /* tp_call */ #ifndef MATH_STANDALONE - (reprfunc) Euler_str, /* tp_str */ + (reprfunc)Euler_str, /* tp_str */ #else - NULL, /* tp_str */ + NULL, /* tp_str */ #endif - NULL, /* tp_getattro */ - NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - euler_doc, /* tp_doc */ - (traverseproc)BaseMathObject_traverse, /* tp_traverse */ - (inquiry)BaseMathObject_clear, /* tp_clear */ - (richcmpfunc)Euler_richcmpr, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - NULL, /* tp_iter */ - NULL, /* tp_iternext */ - Euler_methods, /* tp_methods */ - NULL, /* tp_members */ - Euler_getseters, /* tp_getset */ - NULL, /* tp_base */ - NULL, /* tp_dict */ - NULL, /* tp_descr_get */ - NULL, /* tp_descr_set */ - 0, /* tp_dictoffset */ - NULL, /* tp_init */ - NULL, /* tp_alloc */ - Euler_new, /* tp_new */ - NULL, /* tp_free */ - NULL, /* tp_is_gc */ - NULL, /* tp_bases */ - NULL, /* tp_mro */ - NULL, /* tp_cache */ - NULL, /* tp_subclasses */ - NULL, /* tp_weaklist */ - NULL, /* tp_del */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + euler_doc, /* tp_doc */ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /* tp_clear */ + (richcmpfunc)Euler_richcmpr, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + Euler_methods, /* tp_methods */ + NULL, /* tp_members */ + Euler_getseters, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + Euler_new, /* tp_new */ + NULL, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + NULL, /* tp_del */ }; - -PyObject *Euler_CreatePyObject( - const float eul[3], const short order, - PyTypeObject *base_type) +PyObject *Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type) { - EulerObject *self; - float *eul_alloc; - - eul_alloc = PyMem_Malloc(EULER_SIZE * sizeof(float)); - if (UNLIKELY(eul_alloc == NULL)) { - PyErr_SetString(PyExc_MemoryError, - "Euler(): " - "problem allocating data"); - return NULL; - } - - self = BASE_MATH_NEW(EulerObject, euler_Type, base_type); - if (self) { - self->eul = eul_alloc; - - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; - - if (eul) { - copy_v3_v3(self->eul, eul); - } - else { - zero_v3(self->eul); - } - - self->flag = BASE_MATH_FLAG_DEFAULT; - self->order = order; - } - else { - PyMem_Free(eul_alloc); - } - - return (PyObject *)self; + EulerObject *self; + float *eul_alloc; + + eul_alloc = PyMem_Malloc(EULER_SIZE * sizeof(float)); + if (UNLIKELY(eul_alloc == NULL)) { + PyErr_SetString(PyExc_MemoryError, + "Euler(): " + "problem allocating data"); + return NULL; + } + + self = BASE_MATH_NEW(EulerObject, euler_Type, base_type); + if (self) { + self->eul = eul_alloc; + + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; + + if (eul) { + copy_v3_v3(self->eul, eul); + } + else { + zero_v3(self->eul); + } + + self->flag = BASE_MATH_FLAG_DEFAULT; + self->order = order; + } + else { + PyMem_Free(eul_alloc); + } + + return (PyObject *)self; } -PyObject *Euler_CreatePyObject_wrap( - float eul[3], const short order, - PyTypeObject *base_type) +PyObject *Euler_CreatePyObject_wrap(float eul[3], const short order, PyTypeObject *base_type) { - EulerObject *self; + EulerObject *self; - self = BASE_MATH_NEW(EulerObject, euler_Type, base_type); - if (self) { - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; + self = BASE_MATH_NEW(EulerObject, euler_Type, base_type); + if (self) { + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; - self->eul = eul; - self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; + self->eul = eul; + self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; - self->order = order; - } + self->order = order; + } - return (PyObject *)self; + return (PyObject *)self; } -PyObject *Euler_CreatePyObject_cb( - PyObject *cb_user, const short order, - unsigned char cb_type, unsigned char cb_subtype) +PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, + const short order, + unsigned char cb_type, + unsigned char cb_subtype) { - EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, NULL); - if (self) { - Py_INCREF(cb_user); - self->cb_user = cb_user; - self->cb_type = cb_type; - self->cb_subtype = cb_subtype; - PyObject_GC_Track(self); - } - - return (PyObject *)self; + EulerObject *self = (EulerObject *)Euler_CreatePyObject(NULL, order, NULL); + if (self) { + Py_INCREF(cb_user); + self->cb_user = cb_user; + self->cb_type = cb_type; + self->cb_subtype = cb_subtype; + PyObject_GC_Track(self); + } + + return (PyObject *)self; } diff --git a/source/blender/python/mathutils/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h index 55ca3cd6df6..c56962395e5 100644 --- a/source/blender/python/mathutils/mathutils_Euler.h +++ b/source/blender/python/mathutils/mathutils_Euler.h @@ -26,8 +26,8 @@ extern PyTypeObject euler_Type; #define EulerObject_CheckExact(v) (Py_TYPE(v) == &euler_Type) typedef struct { - BASE_MATH_MEMBERS(eul); - unsigned char order; /* rotation order */ + BASE_MATH_MEMBERS(eul); + unsigned char order; /* rotation order */ } EulerObject; @@ -37,20 +37,18 @@ typedef struct { * blender (stored in blend_data). This is an either/or struct not both */ /* prototypes */ -PyObject *Euler_CreatePyObject( - const float eul[3], const short order, - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT; -PyObject *Euler_CreatePyObject_wrap( - float eul[3], const short order, - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -PyObject *Euler_CreatePyObject_cb( - PyObject *cb_user, const short order, - unsigned char cb_type, unsigned char cb_subtype - ) ATTR_WARN_UNUSED_RESULT; +PyObject *Euler_CreatePyObject(const float eul[3], + const short order, + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; +PyObject *Euler_CreatePyObject_wrap(float eul[3], + const short order, + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); +PyObject *Euler_CreatePyObject_cb(PyObject *cb_user, + const short order, + unsigned char cb_type, + unsigned char cb_subtype) ATTR_WARN_UNUSED_RESULT; short euler_order_from_string(const char *str, const char *error_prefix); - #endif /* __MATHUTILS_EULER_H__ */ diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 724fcd263d4..6ccb3c2a291 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #include #include "mathutils.h" @@ -35,8 +34,8 @@ #endif typedef enum eMatrixAccess_t { - MAT_ACCESS_ROW, - MAT_ACCESS_COL, + MAT_ACCESS_ROW, + MAT_ACCESS_COL, } eMatrixAccess_t; static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix); @@ -48,28 +47,28 @@ static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrix static int matrix_row_vector_check(MatrixObject *mat, VectorObject *vec, int row) { - if ((vec->size != mat->num_col) || (row >= mat->num_row)) { - PyErr_SetString(PyExc_AttributeError, - "Matrix(): " - "owner matrix has been resized since this row vector was created"); - return 0; - } - else { - return 1; - } + if ((vec->size != mat->num_col) || (row >= mat->num_row)) { + PyErr_SetString(PyExc_AttributeError, + "Matrix(): " + "owner matrix has been resized since this row vector was created"); + return 0; + } + else { + return 1; + } } static int matrix_col_vector_check(MatrixObject *mat, VectorObject *vec, int col) { - if ((vec->size != mat->num_row) || (col >= mat->num_col)) { - PyErr_SetString(PyExc_AttributeError, - "Matrix(): " - "owner matrix has been resized since this column vector was created"); - return 0; - } - else { - return 1; - } + if ((vec->size != mat->num_row) || (col >= mat->num_col)) { + PyErr_SetString(PyExc_AttributeError, + "Matrix(): " + "owner matrix has been resized since this column vector was created"); + return 0; + } + else { + return 1; + } } /* ---------------------------------------------------------------------------- @@ -80,90 +79,89 @@ unsigned char mathutils_matrix_row_cb_index = -1; static int mathutils_matrix_row_check(BaseMathObject *bmo) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - return BaseMath_ReadCallback(self); + MatrixObject *self = (MatrixObject *)bmo->cb_user; + return BaseMath_ReadCallback(self); } static int mathutils_matrix_row_get(BaseMathObject *bmo, int row) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - int col; + MatrixObject *self = (MatrixObject *)bmo->cb_user; + int col; - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } - if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } + if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { + return -1; + } - for (col = 0; col < self->num_col; col++) { - bmo->data[col] = MATRIX_ITEM(self, row, col); - } + for (col = 0; col < self->num_col; col++) { + bmo->data[col] = MATRIX_ITEM(self, row, col); + } - return 0; + return 0; } static int mathutils_matrix_row_set(BaseMathObject *bmo, int row) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - int col; + MatrixObject *self = (MatrixObject *)bmo->cb_user; + int col; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { + return -1; + } - for (col = 0; col < self->num_col; col++) { - MATRIX_ITEM(self, row, col) = bmo->data[col]; - } + for (col = 0; col < self->num_col; col++) { + MATRIX_ITEM(self, row, col) = bmo->data[col]; + } - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } static int mathutils_matrix_row_get_index(BaseMathObject *bmo, int row, int col) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; + MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } - if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } + if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { + return -1; + } - bmo->data[col] = MATRIX_ITEM(self, row, col); - return 0; + bmo->data[col] = MATRIX_ITEM(self, row, col); + return 0; } static int mathutils_matrix_row_set_index(BaseMathObject *bmo, int row, int col) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; + MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) { + return -1; + } - MATRIX_ITEM(self, row, col) = bmo->data[col]; + MATRIX_ITEM(self, row, col) = bmo->data[col]; - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } Mathutils_Callback mathutils_matrix_row_cb = { - mathutils_matrix_row_check, - mathutils_matrix_row_get, - mathutils_matrix_row_set, - mathutils_matrix_row_get_index, - mathutils_matrix_row_set_index, + mathutils_matrix_row_check, + mathutils_matrix_row_get, + mathutils_matrix_row_set, + mathutils_matrix_row_get_index, + mathutils_matrix_row_set_index, }; - /* ---------------------------------------------------------------------------- * matrix row callbacks * this is so you can do matrix.col[i][j] = val */ @@ -172,98 +170,97 @@ unsigned char mathutils_matrix_col_cb_index = -1; static int mathutils_matrix_col_check(BaseMathObject *bmo) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - return BaseMath_ReadCallback(self); + MatrixObject *self = (MatrixObject *)bmo->cb_user; + return BaseMath_ReadCallback(self); } static int mathutils_matrix_col_get(BaseMathObject *bmo, int col) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - int num_row; - int row; + MatrixObject *self = (MatrixObject *)bmo->cb_user; + int num_row; + int row; - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } - if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } + if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { + return -1; + } - /* for 'translation' size will always be '3' even on 4x4 vec */ - num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size); + /* for 'translation' size will always be '3' even on 4x4 vec */ + num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size); - for (row = 0; row < num_row; row++) { - bmo->data[row] = MATRIX_ITEM(self, row, col); - } + for (row = 0; row < num_row; row++) { + bmo->data[row] = MATRIX_ITEM(self, row, col); + } - return 0; + return 0; } static int mathutils_matrix_col_set(BaseMathObject *bmo, int col) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - int num_row; - int row; + MatrixObject *self = (MatrixObject *)bmo->cb_user; + int num_row; + int row; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { + return -1; + } - /* for 'translation' size will always be '3' even on 4x4 vec */ - num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size); + /* for 'translation' size will always be '3' even on 4x4 vec */ + num_row = min_ii(self->num_row, ((VectorObject *)bmo)->size); - for (row = 0; row < num_row; row++) { - MATRIX_ITEM(self, row, col) = bmo->data[row]; - } + for (row = 0; row < num_row; row++) { + MATRIX_ITEM(self, row, col) = bmo->data[row]; + } - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } static int mathutils_matrix_col_get_index(BaseMathObject *bmo, int col, int row) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; + MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } - if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } + if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { + return -1; + } - bmo->data[row] = MATRIX_ITEM(self, row, col); - return 0; + bmo->data[row] = MATRIX_ITEM(self, row, col); + return 0; } static int mathutils_matrix_col_set_index(BaseMathObject *bmo, int col, int row) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; + MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) { + return -1; + } - MATRIX_ITEM(self, row, col) = bmo->data[row]; + MATRIX_ITEM(self, row, col) = bmo->data[row]; - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } Mathutils_Callback mathutils_matrix_col_cb = { - mathutils_matrix_col_check, - mathutils_matrix_col_get, - mathutils_matrix_col_set, - mathutils_matrix_col_get_index, - mathutils_matrix_col_set_index, + mathutils_matrix_col_check, + mathutils_matrix_col_get, + mathutils_matrix_col_set, + mathutils_matrix_col_get_index, + mathutils_matrix_col_set_index, }; - /* ---------------------------------------------------------------------------- * matrix row callbacks * this is so you can do matrix.translation = val @@ -273,78 +270,77 @@ unsigned char mathutils_matrix_translation_cb_index = -1; static int mathutils_matrix_translation_check(BaseMathObject *bmo) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - return BaseMath_ReadCallback(self); + MatrixObject *self = (MatrixObject *)bmo->cb_user; + return BaseMath_ReadCallback(self); } static int mathutils_matrix_translation_get(BaseMathObject *bmo, int col) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - int row; + MatrixObject *self = (MatrixObject *)bmo->cb_user; + int row; - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } - for (row = 0; row < 3; row++) { - bmo->data[row] = MATRIX_ITEM(self, row, col); - } + for (row = 0; row < 3; row++) { + bmo->data[row] = MATRIX_ITEM(self, row, col); + } - return 0; + return 0; } static int mathutils_matrix_translation_set(BaseMathObject *bmo, int col) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; - int row; + MatrixObject *self = (MatrixObject *)bmo->cb_user; + int row; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - for (row = 0; row < 3; row++) { - MATRIX_ITEM(self, row, col) = bmo->data[row]; - } + for (row = 0; row < 3; row++) { + MATRIX_ITEM(self, row, col) = bmo->data[row]; + } - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } static int mathutils_matrix_translation_get_index(BaseMathObject *bmo, int col, int row) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; + MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } - bmo->data[row] = MATRIX_ITEM(self, row, col); - return 0; + bmo->data[row] = MATRIX_ITEM(self, row, col); + return 0; } static int mathutils_matrix_translation_set_index(BaseMathObject *bmo, int col, int row) { - MatrixObject *self = (MatrixObject *)bmo->cb_user; + MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - MATRIX_ITEM(self, row, col) = bmo->data[row]; + MATRIX_ITEM(self, row, col) = bmo->data[row]; - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } Mathutils_Callback mathutils_matrix_translation_cb = { - mathutils_matrix_translation_check, - mathutils_matrix_translation_get, - mathutils_matrix_translation_set, - mathutils_matrix_translation_get_index, - mathutils_matrix_translation_set_index, + mathutils_matrix_translation_check, + mathutils_matrix_translation_get, + mathutils_matrix_translation_set, + mathutils_matrix_translation_get_index, + mathutils_matrix_translation_set_index, }; - /* matrix column callbacks, this is so you can do matrix.translation = Vector() */ /* ----------------------------------mathutils.Matrix() ----------------- */ @@ -352,644 +348,696 @@ Mathutils_Callback mathutils_matrix_translation_cb = { /* create a new matrix type */ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - if (kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, - "Matrix(): " - "takes no keyword args"); - return NULL; - } - - switch (PyTuple_GET_SIZE(args)) { - case 0: - return Matrix_CreatePyObject(NULL, 4, 4, type); - case 1: - { - PyObject *arg = PyTuple_GET_ITEM(args, 0); - - /* Input is now as a sequence of rows so length of sequence - * is the number of rows */ - /* -1 is an error, size checks will account for this */ - const unsigned short num_row = PySequence_Size(arg); - - if (num_row >= 2 && num_row <= 4) { - PyObject *item = PySequence_GetItem(arg, 0); - /* Since each item is a row, number of items is the - * same as the number of columns */ - const unsigned short num_col = PySequence_Size(item); - Py_XDECREF(item); - - if (num_col >= 2 && num_col <= 4) { - /* sane row & col size, new matrix and assign as slice */ - PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, type); - if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) { - return matrix; - } - else { /* matrix ok, slice assignment not */ - Py_DECREF(matrix); - } - } - } - break; - } - } - - /* will overwrite error */ - PyErr_SetString(PyExc_TypeError, - "Matrix(): " - "expects no args or a single arg containing 2-4 numeric sequences"); - return NULL; + if (kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "Matrix(): " + "takes no keyword args"); + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 0: + return Matrix_CreatePyObject(NULL, 4, 4, type); + case 1: { + PyObject *arg = PyTuple_GET_ITEM(args, 0); + + /* Input is now as a sequence of rows so length of sequence + * is the number of rows */ + /* -1 is an error, size checks will account for this */ + const unsigned short num_row = PySequence_Size(arg); + + if (num_row >= 2 && num_row <= 4) { + PyObject *item = PySequence_GetItem(arg, 0); + /* Since each item is a row, number of items is the + * same as the number of columns */ + const unsigned short num_col = PySequence_Size(item); + Py_XDECREF(item); + + if (num_col >= 2 && num_col <= 4) { + /* sane row & col size, new matrix and assign as slice */ + PyObject *matrix = Matrix_CreatePyObject(NULL, num_col, num_row, type); + if (Matrix_ass_slice((MatrixObject *)matrix, 0, INT_MAX, arg) == 0) { + return matrix; + } + else { /* matrix ok, slice assignment not */ + Py_DECREF(matrix); + } + } + } + break; + } + } + + /* will overwrite error */ + PyErr_SetString(PyExc_TypeError, + "Matrix(): " + "expects no args or a single arg containing 2-4 numeric sequences"); + return NULL; } static PyObject *matrix__apply_to_copy(PyNoArgsFunction matrix_func, MatrixObject *self) { - PyObject *ret = Matrix_copy(self); - if (ret) { - PyObject *ret_dummy = matrix_func(ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); - return (PyObject *)ret; - } - else { /* error */ - Py_DECREF(ret); - return NULL; - } - } - else { - /* copy may fail if the read callback errors out */ - return NULL; - } + PyObject *ret = Matrix_copy(self); + if (ret) { + PyObject *ret_dummy = matrix_func(ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); + return (PyObject *)ret; + } + else { /* error */ + Py_DECREF(ret); + return NULL; + } + } + else { + /* copy may fail if the read callback errors out */ + return NULL; + } } /* when a matrix is 4x4 size but initialized as a 3x3, re-assign values for 4x4 */ static void matrix_3x3_as_4x4(float mat[16]) { - mat[10] = mat[8]; - mat[9] = mat[7]; - mat[8] = mat[6]; - mat[7] = 0.0f; - mat[6] = mat[5]; - mat[5] = mat[4]; - mat[4] = mat[3]; - mat[3] = 0.0f; + mat[10] = mat[8]; + mat[9] = mat[7]; + mat[8] = mat[6]; + mat[7] = 0.0f; + mat[6] = mat[5]; + mat[5] = mat[4]; + mat[4] = mat[3]; + mat[3] = 0.0f; } /*-----------------------CLASS-METHODS----------------------------*/ /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ PyDoc_STRVAR(C_Matrix_Identity_doc, -".. classmethod:: Identity(size)\n" -"\n" -" Create an identity matrix.\n" -"\n" -" :arg size: The size of the identity matrix to construct [2, 4].\n" -" :type size: int\n" -" :return: A new identity matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. classmethod:: Identity(size)\n" + "\n" + " Create an identity matrix.\n" + "\n" + " :arg size: The size of the identity matrix to construct [2, 4].\n" + " :type size: int\n" + " :return: A new identity matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *C_Matrix_Identity(PyObject *cls, PyObject *args) { - int matSize; + int matSize; - if (!PyArg_ParseTuple(args, "i:Matrix.Identity", &matSize)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "i:Matrix.Identity", &matSize)) { + return NULL; + } - if (matSize < 2 || matSize > 4) { - PyErr_SetString(PyExc_RuntimeError, - "Matrix.Identity(): " - "size must be between 2 and 4"); - return NULL; - } + if (matSize < 2 || matSize > 4) { + PyErr_SetString(PyExc_RuntimeError, + "Matrix.Identity(): " + "size must be between 2 and 4"); + return NULL; + } - return Matrix_CreatePyObject(NULL, matSize, matSize, (PyTypeObject *)cls); + return Matrix_CreatePyObject(NULL, matSize, matSize, (PyTypeObject *)cls); } PyDoc_STRVAR(C_Matrix_Rotation_doc, -".. classmethod:: Rotation(angle, size, axis)\n" -"\n" -" Create a matrix representing a rotation.\n" -"\n" -" :arg angle: The angle of rotation desired, in radians.\n" -" :type angle: float\n" -" :arg size: The size of the rotation matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n" -" (optional when size is 2).\n" -" :type axis: string or :class:`Vector`\n" -" :return: A new rotation matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. classmethod:: Rotation(angle, size, axis)\n" + "\n" + " Create a matrix representing a rotation.\n" + "\n" + " :arg angle: The angle of rotation desired, in radians.\n" + " :type angle: float\n" + " :arg size: The size of the rotation matrix to construct [2, 4].\n" + " :type size: int\n" + " :arg axis: a string in ['X', 'Y', 'Z'] or a 3D Vector Object\n" + " (optional when size is 2).\n" + " :type axis: string or :class:`Vector`\n" + " :return: A new rotation matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) { - PyObject *vec = NULL; - const char *axis = NULL; - int matSize; - double angle; /* use double because of precision problems at high values */ - float mat[16] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, - }; - - if (!PyArg_ParseTuple(args, "di|O:Matrix.Rotation", &angle, &matSize, &vec)) { - return NULL; - } - - if (vec && PyUnicode_Check(vec)) { - axis = _PyUnicode_AsString((PyObject *)vec); - if (axis == NULL || axis[0] == '\0' || axis[1] != '\0' || axis[0] < 'X' || axis[0] > 'Z') { - PyErr_SetString(PyExc_ValueError, - "Matrix.Rotation(): " - "3rd argument axis value must be a 3D vector " - "or a string in 'X', 'Y', 'Z'"); - return NULL; - } - else { - /* use the string */ - vec = NULL; - } - } - - angle = angle_wrap_rad(angle); - - if (matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_ValueError, - "Matrix.Rotation(): " - "can only return a 2x2 3x3 or 4x4 matrix"); - return NULL; - } - if (matSize == 2 && (vec != NULL)) { - PyErr_SetString(PyExc_ValueError, - "Matrix.Rotation(): " - "cannot create a 2x2 rotation matrix around arbitrary axis"); - return NULL; - } - if ((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) { - PyErr_SetString(PyExc_ValueError, - "Matrix.Rotation(): " - "axis of rotation for 3d and 4d matrices is required"); - return NULL; - } - - /* check for valid vector/axis above */ - if (vec) { - float tvec[3]; - - if (mathutils_array_parse(tvec, 3, 3, vec, "Matrix.Rotation(angle, size, axis), invalid 'axis' arg") == -1) { - return NULL; - } - - axis_angle_to_mat3((float (*)[3])mat, tvec, angle); - } - else if (matSize == 2) { - angle_to_mat2((float (*)[2])mat, angle); - - } - else { - /* valid axis checked above */ - axis_angle_to_mat3_single((float (*)[3])mat, axis[0], angle); - } - - if (matSize == 4) { - matrix_3x3_as_4x4(mat); - } - /* pass to matrix creation */ - return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); + PyObject *vec = NULL; + const char *axis = NULL; + int matSize; + double angle; /* use double because of precision problems at high values */ + float mat[16] = { + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }; + + if (!PyArg_ParseTuple(args, "di|O:Matrix.Rotation", &angle, &matSize, &vec)) { + return NULL; + } + + if (vec && PyUnicode_Check(vec)) { + axis = _PyUnicode_AsString((PyObject *)vec); + if (axis == NULL || axis[0] == '\0' || axis[1] != '\0' || axis[0] < 'X' || axis[0] > 'Z') { + PyErr_SetString(PyExc_ValueError, + "Matrix.Rotation(): " + "3rd argument axis value must be a 3D vector " + "or a string in 'X', 'Y', 'Z'"); + return NULL; + } + else { + /* use the string */ + vec = NULL; + } + } + + angle = angle_wrap_rad(angle); + + if (matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_ValueError, + "Matrix.Rotation(): " + "can only return a 2x2 3x3 or 4x4 matrix"); + return NULL; + } + if (matSize == 2 && (vec != NULL)) { + PyErr_SetString(PyExc_ValueError, + "Matrix.Rotation(): " + "cannot create a 2x2 rotation matrix around arbitrary axis"); + return NULL; + } + if ((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) { + PyErr_SetString(PyExc_ValueError, + "Matrix.Rotation(): " + "axis of rotation for 3d and 4d matrices is required"); + return NULL; + } + + /* check for valid vector/axis above */ + if (vec) { + float tvec[3]; + + if (mathutils_array_parse( + tvec, 3, 3, vec, "Matrix.Rotation(angle, size, axis), invalid 'axis' arg") == -1) { + return NULL; + } + + axis_angle_to_mat3((float(*)[3])mat, tvec, angle); + } + else if (matSize == 2) { + angle_to_mat2((float(*)[2])mat, angle); + } + else { + /* valid axis checked above */ + axis_angle_to_mat3_single((float(*)[3])mat, axis[0], angle); + } + + if (matSize == 4) { + matrix_3x3_as_4x4(mat); + } + /* pass to matrix creation */ + return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); } - PyDoc_STRVAR(C_Matrix_Translation_doc, -".. classmethod:: Translation(vector)\n" -"\n" -" Create a matrix representing a translation.\n" -"\n" -" :arg vector: The translation vector.\n" -" :type vector: :class:`Vector`\n" -" :return: An identity matrix with a translation.\n" -" :rtype: :class:`Matrix`\n" -); + ".. classmethod:: Translation(vector)\n" + "\n" + " Create a matrix representing a translation.\n" + "\n" + " :arg vector: The translation vector.\n" + " :type vector: :class:`Vector`\n" + " :return: An identity matrix with a translation.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *C_Matrix_Translation(PyObject *cls, PyObject *value) { - float mat[4][4]; + float mat[4][4]; - unit_m4(mat); + unit_m4(mat); - if (mathutils_array_parse(mat[3], 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1) { - return NULL; - } + if (mathutils_array_parse( + mat[3], 3, 4, value, "mathutils.Matrix.Translation(vector), invalid vector arg") == -1) { + return NULL; + } - return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls); + return Matrix_CreatePyObject(&mat[0][0], 4, 4, (PyTypeObject *)cls); } /* ----------------------------------mathutils.Matrix.Scale() ------------- */ /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ PyDoc_STRVAR(C_Matrix_Scale_doc, -".. classmethod:: Scale(factor, size, axis)\n" -"\n" -" Create a matrix representing a scaling.\n" -"\n" -" :arg factor: The factor of scaling to apply.\n" -" :type factor: float\n" -" :arg size: The size of the scale matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg axis: Direction to influence scale. (optional).\n" -" :type axis: :class:`Vector`\n" -" :return: A new scale matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. classmethod:: Scale(factor, size, axis)\n" + "\n" + " Create a matrix representing a scaling.\n" + "\n" + " :arg factor: The factor of scaling to apply.\n" + " :type factor: float\n" + " :arg size: The size of the scale matrix to construct [2, 4].\n" + " :type size: int\n" + " :arg axis: Direction to influence scale. (optional).\n" + " :type axis: :class:`Vector`\n" + " :return: A new scale matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) { - PyObject *vec = NULL; - int vec_size; - float tvec[3]; - float factor; - int matSize; - float mat[16] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, - }; - - if (!PyArg_ParseTuple(args, "fi|O:Matrix.Scale", &factor, &matSize, &vec)) { - return NULL; - } - if (matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_ValueError, - "Matrix.Scale(): " - "can only return a 2x2 3x3 or 4x4 matrix"); - return NULL; - } - if (vec) { - vec_size = (matSize == 2 ? 2 : 3); - if (mathutils_array_parse(tvec, vec_size, vec_size, vec, - "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) - { - return NULL; - } - } - if (vec == NULL) { /* scaling along axis */ - if (matSize == 2) { - mat[0] = factor; - mat[3] = factor; - } - else { - mat[0] = factor; - mat[4] = factor; - mat[8] = factor; - } - } - else { - /* scaling in arbitrary direction - * normalize arbitrary axis */ - float norm = 0.0f; - int x; - for (x = 0; x < vec_size; x++) { - norm += tvec[x] * tvec[x]; - } - norm = sqrtf(norm); - for (x = 0; x < vec_size; x++) { - tvec[x] /= norm; - } - if (matSize == 2) { - mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0])); - mat[1] = ((factor - 1) * (tvec[0] * tvec[1])); - mat[2] = ((factor - 1) * (tvec[0] * tvec[1])); - mat[3] = 1 + ((factor - 1) * (tvec[1] * tvec[1])); - } - else { - mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0])); - mat[1] = ((factor - 1) * (tvec[0] * tvec[1])); - mat[2] = ((factor - 1) * (tvec[0] * tvec[2])); - mat[3] = ((factor - 1) * (tvec[0] * tvec[1])); - mat[4] = 1 + ((factor - 1) * (tvec[1] * tvec[1])); - mat[5] = ((factor - 1) * (tvec[1] * tvec[2])); - mat[6] = ((factor - 1) * (tvec[0] * tvec[2])); - mat[7] = ((factor - 1) * (tvec[1] * tvec[2])); - mat[8] = 1 + ((factor - 1) * (tvec[2] * tvec[2])); - } - } - if (matSize == 4) { - matrix_3x3_as_4x4(mat); - } - /* pass to matrix creation */ - return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); + PyObject *vec = NULL; + int vec_size; + float tvec[3]; + float factor; + int matSize; + float mat[16] = { + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }; + + if (!PyArg_ParseTuple(args, "fi|O:Matrix.Scale", &factor, &matSize, &vec)) { + return NULL; + } + if (matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_ValueError, + "Matrix.Scale(): " + "can only return a 2x2 3x3 or 4x4 matrix"); + return NULL; + } + if (vec) { + vec_size = (matSize == 2 ? 2 : 3); + if (mathutils_array_parse(tvec, + vec_size, + vec_size, + vec, + "Matrix.Scale(factor, size, axis), invalid 'axis' arg") == -1) { + return NULL; + } + } + if (vec == NULL) { /* scaling along axis */ + if (matSize == 2) { + mat[0] = factor; + mat[3] = factor; + } + else { + mat[0] = factor; + mat[4] = factor; + mat[8] = factor; + } + } + else { + /* scaling in arbitrary direction + * normalize arbitrary axis */ + float norm = 0.0f; + int x; + for (x = 0; x < vec_size; x++) { + norm += tvec[x] * tvec[x]; + } + norm = sqrtf(norm); + for (x = 0; x < vec_size; x++) { + tvec[x] /= norm; + } + if (matSize == 2) { + mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0])); + mat[1] = ((factor - 1) * (tvec[0] * tvec[1])); + mat[2] = ((factor - 1) * (tvec[0] * tvec[1])); + mat[3] = 1 + ((factor - 1) * (tvec[1] * tvec[1])); + } + else { + mat[0] = 1 + ((factor - 1) * (tvec[0] * tvec[0])); + mat[1] = ((factor - 1) * (tvec[0] * tvec[1])); + mat[2] = ((factor - 1) * (tvec[0] * tvec[2])); + mat[3] = ((factor - 1) * (tvec[0] * tvec[1])); + mat[4] = 1 + ((factor - 1) * (tvec[1] * tvec[1])); + mat[5] = ((factor - 1) * (tvec[1] * tvec[2])); + mat[6] = ((factor - 1) * (tvec[0] * tvec[2])); + mat[7] = ((factor - 1) * (tvec[1] * tvec[2])); + mat[8] = 1 + ((factor - 1) * (tvec[2] * tvec[2])); + } + } + if (matSize == 4) { + matrix_3x3_as_4x4(mat); + } + /* pass to matrix creation */ + return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); } /* ----------------------------------mathutils.Matrix.OrthoProjection() --- */ /* mat is a 1D array of floats - row[0][0], row[0][1], row[1][0], etc. */ PyDoc_STRVAR(C_Matrix_OrthoProjection_doc, -".. classmethod:: OrthoProjection(axis, size)\n" -"\n" -" Create a matrix to represent an orthographic projection.\n" -"\n" -" :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n" -" where a single axis is for a 2D matrix.\n" -" Or a vector for an arbitrary axis\n" -" :type axis: string or :class:`Vector`\n" -" :arg size: The size of the projection matrix to construct [2, 4].\n" -" :type size: int\n" -" :return: A new projection matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. classmethod:: OrthoProjection(axis, size)\n" + "\n" + " Create a matrix to represent an orthographic projection.\n" + "\n" + " :arg axis: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n" + " where a single axis is for a 2D matrix.\n" + " Or a vector for an arbitrary axis\n" + " :type axis: string or :class:`Vector`\n" + " :arg size: The size of the projection matrix to construct [2, 4].\n" + " :type size: int\n" + " :return: A new projection matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) { - PyObject *axis; - - int matSize, x; - float norm = 0.0f; - float mat[16] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, - }; - - if (!PyArg_ParseTuple(args, "Oi:Matrix.OrthoProjection", &axis, &matSize)) { - return NULL; - } - if (matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_ValueError, - "Matrix.OrthoProjection(): " - "can only return a 2x2 3x3 or 4x4 matrix"); - return NULL; - } - - if (PyUnicode_Check(axis)) { /* ortho projection onto cardinal plane */ - Py_ssize_t plane_len; - const char *plane = _PyUnicode_AsStringAndSize(axis, &plane_len); - if (matSize == 2) { - if (plane_len == 1 && plane[0] == 'X') { - mat[0] = 1.0f; - } - else if (plane_len == 1 && plane[0] == 'Y') { - mat[3] = 1.0f; - } - else { - PyErr_Format(PyExc_ValueError, - "Matrix.OrthoProjection(): " - "unknown plane, expected: X, Y, not '%.200s'", - plane); - return NULL; - } - } - else { - if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Y') { - mat[0] = 1.0f; - mat[4] = 1.0f; - } - else if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Z') { - mat[0] = 1.0f; - mat[8] = 1.0f; - } - else if (plane_len == 2 && plane[0] == 'Y' && plane[1] == 'Z') { - mat[4] = 1.0f; - mat[8] = 1.0f; - } - else { - PyErr_Format(PyExc_ValueError, - "Matrix.OrthoProjection(): " - "unknown plane, expected: XY, XZ, YZ, not '%.200s'", - plane); - return NULL; - } - } - } - else { - /* arbitrary plane */ - - int vec_size = (matSize == 2 ? 2 : 3); - float tvec[4]; - - if (mathutils_array_parse(tvec, vec_size, vec_size, axis, - "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) - { - return NULL; - } - - /* normalize arbitrary axis */ - for (x = 0; x < vec_size; x++) { - norm += tvec[x] * tvec[x]; - } - norm = sqrtf(norm); - for (x = 0; x < vec_size; x++) { - tvec[x] /= norm; - } - if (matSize == 2) { - mat[0] = 1 - (tvec[0] * tvec[0]); - mat[1] = - (tvec[0] * tvec[1]); - mat[2] = - (tvec[0] * tvec[1]); - mat[3] = 1 - (tvec[1] * tvec[1]); - } - else if (matSize > 2) { - mat[0] = 1 - (tvec[0] * tvec[0]); - mat[1] = - (tvec[0] * tvec[1]); - mat[2] = - (tvec[0] * tvec[2]); - mat[3] = - (tvec[0] * tvec[1]); - mat[4] = 1 - (tvec[1] * tvec[1]); - mat[5] = - (tvec[1] * tvec[2]); - mat[6] = - (tvec[0] * tvec[2]); - mat[7] = - (tvec[1] * tvec[2]); - mat[8] = 1 - (tvec[2] * tvec[2]); - } - } - if (matSize == 4) { - matrix_3x3_as_4x4(mat); - } - /* pass to matrix creation */ - return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); + PyObject *axis; + + int matSize, x; + float norm = 0.0f; + float mat[16] = { + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }; + + if (!PyArg_ParseTuple(args, "Oi:Matrix.OrthoProjection", &axis, &matSize)) { + return NULL; + } + if (matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_ValueError, + "Matrix.OrthoProjection(): " + "can only return a 2x2 3x3 or 4x4 matrix"); + return NULL; + } + + if (PyUnicode_Check(axis)) { /* ortho projection onto cardinal plane */ + Py_ssize_t plane_len; + const char *plane = _PyUnicode_AsStringAndSize(axis, &plane_len); + if (matSize == 2) { + if (plane_len == 1 && plane[0] == 'X') { + mat[0] = 1.0f; + } + else if (plane_len == 1 && plane[0] == 'Y') { + mat[3] = 1.0f; + } + else { + PyErr_Format(PyExc_ValueError, + "Matrix.OrthoProjection(): " + "unknown plane, expected: X, Y, not '%.200s'", + plane); + return NULL; + } + } + else { + if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Y') { + mat[0] = 1.0f; + mat[4] = 1.0f; + } + else if (plane_len == 2 && plane[0] == 'X' && plane[1] == 'Z') { + mat[0] = 1.0f; + mat[8] = 1.0f; + } + else if (plane_len == 2 && plane[0] == 'Y' && plane[1] == 'Z') { + mat[4] = 1.0f; + mat[8] = 1.0f; + } + else { + PyErr_Format(PyExc_ValueError, + "Matrix.OrthoProjection(): " + "unknown plane, expected: XY, XZ, YZ, not '%.200s'", + plane); + return NULL; + } + } + } + else { + /* arbitrary plane */ + + int vec_size = (matSize == 2 ? 2 : 3); + float tvec[4]; + + if (mathutils_array_parse(tvec, + vec_size, + vec_size, + axis, + "Matrix.OrthoProjection(axis, size), invalid 'axis' arg") == -1) { + return NULL; + } + + /* normalize arbitrary axis */ + for (x = 0; x < vec_size; x++) { + norm += tvec[x] * tvec[x]; + } + norm = sqrtf(norm); + for (x = 0; x < vec_size; x++) { + tvec[x] /= norm; + } + if (matSize == 2) { + mat[0] = 1 - (tvec[0] * tvec[0]); + mat[1] = -(tvec[0] * tvec[1]); + mat[2] = -(tvec[0] * tvec[1]); + mat[3] = 1 - (tvec[1] * tvec[1]); + } + else if (matSize > 2) { + mat[0] = 1 - (tvec[0] * tvec[0]); + mat[1] = -(tvec[0] * tvec[1]); + mat[2] = -(tvec[0] * tvec[2]); + mat[3] = -(tvec[0] * tvec[1]); + mat[4] = 1 - (tvec[1] * tvec[1]); + mat[5] = -(tvec[1] * tvec[2]); + mat[6] = -(tvec[0] * tvec[2]); + mat[7] = -(tvec[1] * tvec[2]); + mat[8] = 1 - (tvec[2] * tvec[2]); + } + } + if (matSize == 4) { + matrix_3x3_as_4x4(mat); + } + /* pass to matrix creation */ + return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); } PyDoc_STRVAR(C_Matrix_Shear_doc, -".. classmethod:: Shear(plane, size, factor)\n" -"\n" -" Create a matrix to represent an shear transformation.\n" -"\n" -" :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n" -" where a single axis is for a 2D matrix only.\n" -" :type plane: string\n" -" :arg size: The size of the shear matrix to construct [2, 4].\n" -" :type size: int\n" -" :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n" -" pass a pair of floats corresponding with the *plane* axis.\n" -" :type factor: float or float pair\n" -" :return: A new shear matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. classmethod:: Shear(plane, size, factor)\n" + "\n" + " Create a matrix to represent an shear transformation.\n" + "\n" + " :arg plane: Can be any of the following: ['X', 'Y', 'XY', 'XZ', 'YZ'],\n" + " where a single axis is for a 2D matrix only.\n" + " :type plane: string\n" + " :arg size: The size of the shear matrix to construct [2, 4].\n" + " :type size: int\n" + " :arg factor: The factor of shear to apply. For a 3 or 4 *size* matrix\n" + " pass a pair of floats corresponding with the *plane* axis.\n" + " :type factor: float or float pair\n" + " :return: A new shear matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) { - int matSize; - const char *plane; - PyObject *fac; - float mat[16] = { - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f, - }; - - if (!PyArg_ParseTuple(args, "siO:Matrix.Shear", &plane, &matSize, &fac)) { - return NULL; - } - if (matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_ValueError, - "Matrix.Shear(): " - "can only return a 2x2 3x3 or 4x4 matrix"); - return NULL; - } - - if (matSize == 2) { - float const factor = PyFloat_AsDouble(fac); - - if (factor == -1.0f && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "Matrix.Shear(): " - "the factor to be a float"); - return NULL; - } - - /* unit */ - mat[0] = 1.0f; - mat[3] = 1.0f; - - if (STREQ(plane, "X")) { - mat[2] = factor; - } - else if (STREQ(plane, "Y")) { - mat[1] = factor; - } - else { - PyErr_SetString(PyExc_ValueError, - "Matrix.Shear(): " - "expected: X, Y or wrong matrix size for shearing plane"); - return NULL; - } - } - else { - /* 3 or 4, apply as 3x3, resize later if needed */ - float factor[2]; - - if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") == -1) { - return NULL; - } - - /* unit */ - mat[0] = 1.0f; - mat[4] = 1.0f; - mat[8] = 1.0f; - - if (STREQ(plane, "XY")) { - mat[6] = factor[0]; - mat[7] = factor[1]; - } - else if (STREQ(plane, "XZ")) { - mat[3] = factor[0]; - mat[5] = factor[1]; - } - else if (STREQ(plane, "YZ")) { - mat[1] = factor[0]; - mat[2] = factor[1]; - } - else { - PyErr_SetString(PyExc_ValueError, - "Matrix.Shear(): " - "expected: X, Y, XY, XZ, YZ"); - return NULL; - } - } - - if (matSize == 4) { - matrix_3x3_as_4x4(mat); - } - /* pass to matrix creation */ - return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); + int matSize; + const char *plane; + PyObject *fac; + float mat[16] = { + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f, + }; + + if (!PyArg_ParseTuple(args, "siO:Matrix.Shear", &plane, &matSize, &fac)) { + return NULL; + } + if (matSize != 2 && matSize != 3 && matSize != 4) { + PyErr_SetString(PyExc_ValueError, + "Matrix.Shear(): " + "can only return a 2x2 3x3 or 4x4 matrix"); + return NULL; + } + + if (matSize == 2) { + float const factor = PyFloat_AsDouble(fac); + + if (factor == -1.0f && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "Matrix.Shear(): " + "the factor to be a float"); + return NULL; + } + + /* unit */ + mat[0] = 1.0f; + mat[3] = 1.0f; + + if (STREQ(plane, "X")) { + mat[2] = factor; + } + else if (STREQ(plane, "Y")) { + mat[1] = factor; + } + else { + PyErr_SetString(PyExc_ValueError, + "Matrix.Shear(): " + "expected: X, Y or wrong matrix size for shearing plane"); + return NULL; + } + } + else { + /* 3 or 4, apply as 3x3, resize later if needed */ + float factor[2]; + + if (mathutils_array_parse(factor, 2, 2, fac, "Matrix.Shear()") == -1) { + return NULL; + } + + /* unit */ + mat[0] = 1.0f; + mat[4] = 1.0f; + mat[8] = 1.0f; + + if (STREQ(plane, "XY")) { + mat[6] = factor[0]; + mat[7] = factor[1]; + } + else if (STREQ(plane, "XZ")) { + mat[3] = factor[0]; + mat[5] = factor[1]; + } + else if (STREQ(plane, "YZ")) { + mat[1] = factor[0]; + mat[2] = factor[1]; + } + else { + PyErr_SetString(PyExc_ValueError, + "Matrix.Shear(): " + "expected: X, Y, XY, XZ, YZ"); + return NULL; + } + } + + if (matSize == 4) { + matrix_3x3_as_4x4(mat); + } + /* pass to matrix creation */ + return Matrix_CreatePyObject(mat, matSize, matSize, (PyTypeObject *)cls); } void matrix_as_3x3(float mat[3][3], MatrixObject *self) { - copy_v3_v3(mat[0], MATRIX_COL_PTR(self, 0)); - copy_v3_v3(mat[1], MATRIX_COL_PTR(self, 1)); - copy_v3_v3(mat[2], MATRIX_COL_PTR(self, 2)); + copy_v3_v3(mat[0], MATRIX_COL_PTR(self, 0)); + copy_v3_v3(mat[1], MATRIX_COL_PTR(self, 1)); + copy_v3_v3(mat[2], MATRIX_COL_PTR(self, 2)); } static void matrix_copy(MatrixObject *mat_dst, const MatrixObject *mat_src) { - BLI_assert((mat_dst->num_col == mat_src->num_col) && - (mat_dst->num_row == mat_src->num_row)); - BLI_assert(mat_dst != mat_src); + BLI_assert((mat_dst->num_col == mat_src->num_col) && (mat_dst->num_row == mat_src->num_row)); + BLI_assert(mat_dst != mat_src); - memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->num_col * mat_dst->num_row)); + memcpy(mat_dst->matrix, mat_src->matrix, sizeof(float) * (mat_dst->num_col * mat_dst->num_row)); } /* transposes memory layout, rol/col's don't have to match */ static void matrix_transpose_internal(float mat_dst_fl[], const MatrixObject *mat_src) { - unsigned short col, row; - unsigned int i = 0; + unsigned short col, row; + unsigned int i = 0; - for (row = 0; row < mat_src->num_row; row++) { - for (col = 0; col < mat_src->num_col; col++) { - mat_dst_fl[i++] = MATRIX_ITEM(mat_src, row, col); - } - } + for (row = 0; row < mat_src->num_row; row++) { + for (col = 0; col < mat_src->num_col; col++) { + mat_dst_fl[i++] = MATRIX_ITEM(mat_src, row, col); + } + } } /* assumes rowsize == colsize is checked and the read callback has run */ static float matrix_determinant_internal(const MatrixObject *self) { - if (self->num_col == 2) { - return determinant_m2(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), - MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1)); - } - else if (self->num_col == 3) { - return determinant_m3(MATRIX_ITEM(self, 0, 0), MATRIX_ITEM(self, 0, 1), MATRIX_ITEM(self, 0, 2), - MATRIX_ITEM(self, 1, 0), MATRIX_ITEM(self, 1, 1), MATRIX_ITEM(self, 1, 2), - MATRIX_ITEM(self, 2, 0), MATRIX_ITEM(self, 2, 1), MATRIX_ITEM(self, 2, 2)); - } - else { - return determinant_m4((float (*)[4])self->matrix); - } + if (self->num_col == 2) { + return determinant_m2(MATRIX_ITEM(self, 0, 0), + MATRIX_ITEM(self, 0, 1), + MATRIX_ITEM(self, 1, 0), + MATRIX_ITEM(self, 1, 1)); + } + else if (self->num_col == 3) { + return determinant_m3(MATRIX_ITEM(self, 0, 0), + MATRIX_ITEM(self, 0, 1), + MATRIX_ITEM(self, 0, 2), + MATRIX_ITEM(self, 1, 0), + MATRIX_ITEM(self, 1, 1), + MATRIX_ITEM(self, 1, 2), + MATRIX_ITEM(self, 2, 0), + MATRIX_ITEM(self, 2, 1), + MATRIX_ITEM(self, 2, 2)); + } + else { + return determinant_m4((float(*)[4])self->matrix); + } } static void adjoint_matrix_n(float *mat_dst, const float *mat_src, const unsigned short dim) { - /* calculate the classical adjoint */ - switch (dim) { - case 2: - { - adjoint_m2_m2((float (*)[2])mat_dst, (float (*)[2])mat_src); - break; - } - case 3: - { - adjoint_m3_m3((float (*)[3])mat_dst, (float (*)[3])mat_src); - break; - } - case 4: - { - adjoint_m4_m4((float (*)[4])mat_dst, (float (*)[4])mat_src); - break; - } - default: - BLI_assert(0); - } -} - -static void matrix_invert_with_det_n_internal(float *mat_dst, const float *mat_src, const float det, const unsigned short dim) -{ - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - unsigned short i, j, k; - - BLI_assert(det != 0.0f); - - adjoint_matrix_n(mat, mat_src, dim); - - /* divide by determinant & set values */ - k = 0; - for (i = 0; i < dim; i++) { /* num_col */ - for (j = 0; j < dim; j++) { /* num_row */ - mat_dst[MATRIX_ITEM_INDEX_NUMROW(dim, j, i)] = mat[k++] / det; - } - } + /* calculate the classical adjoint */ + switch (dim) { + case 2: { + adjoint_m2_m2((float(*)[2])mat_dst, (float(*)[2])mat_src); + break; + } + case 3: { + adjoint_m3_m3((float(*)[3])mat_dst, (float(*)[3])mat_src); + break; + } + case 4: { + adjoint_m4_m4((float(*)[4])mat_dst, (float(*)[4])mat_src); + break; + } + default: + BLI_assert(0); + } +} + +static void matrix_invert_with_det_n_internal(float *mat_dst, + const float *mat_src, + const float det, + const unsigned short dim) +{ + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + unsigned short i, j, k; + + BLI_assert(det != 0.0f); + + adjoint_matrix_n(mat, mat_src, dim); + + /* divide by determinant & set values */ + k = 0; + for (i = 0; i < dim; i++) { /* num_col */ + for (j = 0; j < dim; j++) { /* num_row */ + mat_dst[MATRIX_ITEM_INDEX_NUMROW(dim, j, i)] = mat[k++] / det; + } + } } /** @@ -997,17 +1045,17 @@ static void matrix_invert_with_det_n_internal(float *mat_dst, const float *mat_s */ static bool matrix_invert_internal(const MatrixObject *self, float *r_mat) { - float det; - BLI_assert(self->num_col == self->num_row); - det = matrix_determinant_internal(self); + float det; + BLI_assert(self->num_col == self->num_row); + det = matrix_determinant_internal(self); - if (det != 0.0f) { - matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->num_col); - return true; - } - else { - return false; - } + if (det != 0.0f) { + matrix_invert_with_det_n_internal(r_mat, self->matrix, det, self->num_col); + return true; + } + else { + return false; + } } /** @@ -1016,358 +1064,347 @@ static bool matrix_invert_internal(const MatrixObject *self, float *r_mat) */ static void matrix_invert_safe_internal(const MatrixObject *self, float *r_mat) { - float det; - float *in_mat = self->matrix; - BLI_assert(self->num_col == self->num_row); - det = matrix_determinant_internal(self); - - if (det == 0.0f) { - const float eps = PSEUDOINVERSE_EPSILON; - - /* We will copy self->matrix into r_mat (if needed), and modify it in place to add diagonal epsilon. */ - in_mat = r_mat; - - switch (self->num_col) { - case 2: - { - float (*mat)[2] = (float (*)[2])in_mat; - - if (in_mat != self->matrix) { - copy_m2_m2(mat, (float (*)[2])self->matrix); - } - mat[0][0] += eps; - mat[1][1] += eps; - - if (UNLIKELY((det = determinant_m2(mat[0][0], mat[0][1], mat[1][0], mat[1][1])) == 0.0f)) { - unit_m2(mat); - det = 1.0f; - } - break; - } - case 3: - { - float (*mat)[3] = (float (*)[3])in_mat; - - if (in_mat != self->matrix) { - copy_m3_m3(mat, (float (*)[3])self->matrix); - } - mat[0][0] += eps; - mat[1][1] += eps; - mat[2][2] += eps; - - if (UNLIKELY((det = determinant_m3_array(mat)) == 0.0f)) { - unit_m3(mat); - det = 1.0f; - } - break; - } - case 4: - { - float (*mat)[4] = (float (*)[4])in_mat; - - if (in_mat != self->matrix) { - copy_m4_m4(mat, (float (*)[4])self->matrix); - } - mat[0][0] += eps; - mat[1][1] += eps; - mat[2][2] += eps; - mat[3][3] += eps; - - if (UNLIKELY(det = determinant_m4(mat)) == 0.0f) { - unit_m4(mat); - det = 1.0f; - } - break; - } - default: - BLI_assert(0); - } - } - - matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->num_col); + float det; + float *in_mat = self->matrix; + BLI_assert(self->num_col == self->num_row); + det = matrix_determinant_internal(self); + + if (det == 0.0f) { + const float eps = PSEUDOINVERSE_EPSILON; + + /* We will copy self->matrix into r_mat (if needed), and modify it in place to add diagonal epsilon. */ + in_mat = r_mat; + + switch (self->num_col) { + case 2: { + float(*mat)[2] = (float(*)[2])in_mat; + + if (in_mat != self->matrix) { + copy_m2_m2(mat, (float(*)[2])self->matrix); + } + mat[0][0] += eps; + mat[1][1] += eps; + + if (UNLIKELY((det = determinant_m2(mat[0][0], mat[0][1], mat[1][0], mat[1][1])) == 0.0f)) { + unit_m2(mat); + det = 1.0f; + } + break; + } + case 3: { + float(*mat)[3] = (float(*)[3])in_mat; + + if (in_mat != self->matrix) { + copy_m3_m3(mat, (float(*)[3])self->matrix); + } + mat[0][0] += eps; + mat[1][1] += eps; + mat[2][2] += eps; + + if (UNLIKELY((det = determinant_m3_array(mat)) == 0.0f)) { + unit_m3(mat); + det = 1.0f; + } + break; + } + case 4: { + float(*mat)[4] = (float(*)[4])in_mat; + + if (in_mat != self->matrix) { + copy_m4_m4(mat, (float(*)[4])self->matrix); + } + mat[0][0] += eps; + mat[1][1] += eps; + mat[2][2] += eps; + mat[3][3] += eps; + + if (UNLIKELY(det = determinant_m4(mat)) == 0.0f) { + unit_m4(mat); + det = 1.0f; + } + break; + } + default: + BLI_assert(0); + } + } + + matrix_invert_with_det_n_internal(r_mat, in_mat, det, self->num_col); } - /*-----------------------------METHODS----------------------------*/ PyDoc_STRVAR(Matrix_to_quaternion_doc, -".. method:: to_quaternion()\n" -"\n" -" Return a quaternion representation of the rotation matrix.\n" -"\n" -" :return: Quaternion representation of the rotation matrix.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. method:: to_quaternion()\n" + "\n" + " Return a quaternion representation of the rotation matrix.\n" + "\n" + " :return: Quaternion representation of the rotation matrix.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Matrix_to_quaternion(MatrixObject *self) { - float quat[4]; + float quat[4]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - /* must be 3-4 cols, 3-4 rows, square matrix */ - if ((self->num_row < 3) || (self->num_col < 3) || (self->num_row != self->num_col)) { - PyErr_SetString(PyExc_ValueError, - "Matrix.to_quat(): " - "inappropriate matrix size - expects 3x3 or 4x4 matrix"); - return NULL; - } - if (self->num_row == 3) { - mat3_to_quat(quat, (float (*)[3])self->matrix); - } - else { - mat4_to_quat(quat, (float (*)[4])self->matrix); - } + /* must be 3-4 cols, 3-4 rows, square matrix */ + if ((self->num_row < 3) || (self->num_col < 3) || (self->num_row != self->num_col)) { + PyErr_SetString(PyExc_ValueError, + "Matrix.to_quat(): " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); + return NULL; + } + if (self->num_row == 3) { + mat3_to_quat(quat, (float(*)[3])self->matrix); + } + else { + mat4_to_quat(quat, (float(*)[4])self->matrix); + } - return Quaternion_CreatePyObject(quat, NULL); + return Quaternion_CreatePyObject(quat, NULL); } /*---------------------------matrix.toEuler() --------------------*/ PyDoc_STRVAR(Matrix_to_euler_doc, -".. method:: to_euler(order, euler_compat)\n" -"\n" -" Return an Euler representation of the rotation matrix\n" -" (3x3 or 4x4 matrix only).\n" -"\n" -" :arg order: Optional rotation order argument in\n" -" ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n" -" :type order: string\n" -" :arg euler_compat: Optional euler argument the new euler will be made\n" -" compatible with (no axis flipping between them).\n" -" Useful for converting a series of matrices to animation curves.\n" -" :type euler_compat: :class:`Euler`\n" -" :return: Euler representation of the matrix.\n" -" :rtype: :class:`Euler`\n" -); + ".. method:: to_euler(order, euler_compat)\n" + "\n" + " Return an Euler representation of the rotation matrix\n" + " (3x3 or 4x4 matrix only).\n" + "\n" + " :arg order: Optional rotation order argument in\n" + " ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n" + " :type order: string\n" + " :arg euler_compat: Optional euler argument the new euler will be made\n" + " compatible with (no axis flipping between them).\n" + " Useful for converting a series of matrices to animation curves.\n" + " :type euler_compat: :class:`Euler`\n" + " :return: Euler representation of the matrix.\n" + " :rtype: :class:`Euler`\n"); static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args) { - const char *order_str = NULL; - short order = EULER_ORDER_XYZ; - float eul[3], eul_compatf[3]; - EulerObject *eul_compat = NULL; - - float mat[3][3]; - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat)) { - return NULL; - } - - if (eul_compat) { - if (BaseMath_ReadCallback(eul_compat) == -1) { - return NULL; - } - - copy_v3_v3(eul_compatf, eul_compat->eul); - } - - /*must be 3-4 cols, 3-4 rows, square matrix */ - if (self->num_row == 3 && self->num_col == 3) { - copy_m3_m3(mat, (float (*)[3])self->matrix); - } - else if (self->num_row == 4 && self->num_col == 4) { - copy_m3_m4(mat, (float (*)[4])self->matrix); - } - else { - PyErr_SetString(PyExc_ValueError, - "Matrix.to_euler(): " - "inappropriate matrix size - expects 3x3 or 4x4 matrix"); - return NULL; - } - - if (order_str) { - order = euler_order_from_string(order_str, "Matrix.to_euler()"); - - if (order == -1) { - return NULL; - } - } - - normalize_m3(mat); - - if (eul_compat) { - if (order == 1) { - mat3_normalized_to_compatible_eul(eul, eul_compatf, mat); - } - else { - mat3_normalized_to_compatible_eulO(eul, eul_compatf, order, mat); - } - } - else { - if (order == 1) { - mat3_normalized_to_eul(eul, mat); - } - else { - mat3_normalized_to_eulO(eul, order, mat); - } - } - - return Euler_CreatePyObject(eul, order, NULL); + const char *order_str = NULL; + short order = EULER_ORDER_XYZ; + float eul[3], eul_compatf[3]; + EulerObject *eul_compat = NULL; + + float mat[3][3]; + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat)) { + return NULL; + } + + if (eul_compat) { + if (BaseMath_ReadCallback(eul_compat) == -1) { + return NULL; + } + + copy_v3_v3(eul_compatf, eul_compat->eul); + } + + /*must be 3-4 cols, 3-4 rows, square matrix */ + if (self->num_row == 3 && self->num_col == 3) { + copy_m3_m3(mat, (float(*)[3])self->matrix); + } + else if (self->num_row == 4 && self->num_col == 4) { + copy_m3_m4(mat, (float(*)[4])self->matrix); + } + else { + PyErr_SetString(PyExc_ValueError, + "Matrix.to_euler(): " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); + return NULL; + } + + if (order_str) { + order = euler_order_from_string(order_str, "Matrix.to_euler()"); + + if (order == -1) { + return NULL; + } + } + + normalize_m3(mat); + + if (eul_compat) { + if (order == 1) { + mat3_normalized_to_compatible_eul(eul, eul_compatf, mat); + } + else { + mat3_normalized_to_compatible_eulO(eul, eul_compatf, order, mat); + } + } + else { + if (order == 1) { + mat3_normalized_to_eul(eul, mat); + } + else { + mat3_normalized_to_eulO(eul, order, mat); + } + } + + return Euler_CreatePyObject(eul, order, NULL); } PyDoc_STRVAR(Matrix_resize_4x4_doc, -".. method:: resize_4x4()\n" -"\n" -" Resize the matrix to 4x4.\n" -); + ".. method:: resize_4x4()\n" + "\n" + " Resize the matrix to 4x4.\n"); static PyObject *Matrix_resize_4x4(MatrixObject *self) { - float mat[4][4]; - int col; + float mat[4][4]; + int col; - if (self->flag & BASE_MATH_FLAG_IS_WRAP) { - PyErr_SetString(PyExc_ValueError, - "Matrix.resize_4x4(): " - "cannot resize wrapped data - make a copy and resize that"); - return NULL; - } - if (self->cb_user) { - PyErr_SetString(PyExc_ValueError, - "Matrix.resize_4x4(): " - "cannot resize owned data - make a copy and resize that"); - return NULL; - } + if (self->flag & BASE_MATH_FLAG_IS_WRAP) { + PyErr_SetString(PyExc_ValueError, + "Matrix.resize_4x4(): " + "cannot resize wrapped data - make a copy and resize that"); + return NULL; + } + if (self->cb_user) { + PyErr_SetString(PyExc_ValueError, + "Matrix.resize_4x4(): " + "cannot resize owned data - make a copy and resize that"); + return NULL; + } - self->matrix = PyMem_Realloc(self->matrix, (sizeof(float) * (MATRIX_MAX_DIM * MATRIX_MAX_DIM))); - if (self->matrix == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Matrix.resize_4x4(): " - "problem allocating pointer space"); - return NULL; - } + self->matrix = PyMem_Realloc(self->matrix, (sizeof(float) * (MATRIX_MAX_DIM * MATRIX_MAX_DIM))); + if (self->matrix == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Matrix.resize_4x4(): " + "problem allocating pointer space"); + return NULL; + } - unit_m4(mat); + unit_m4(mat); - for (col = 0; col < self->num_col; col++) { - memcpy(mat[col], MATRIX_COL_PTR(self, col), self->num_row * sizeof(float)); - } + for (col = 0; col < self->num_col; col++) { + memcpy(mat[col], MATRIX_COL_PTR(self, col), self->num_row * sizeof(float)); + } - copy_m4_m4((float (*)[4])self->matrix, (float (*)[4])mat); + copy_m4_m4((float(*)[4])self->matrix, (float(*)[4])mat); - self->num_col = 4; - self->num_row = 4; + self->num_col = 4; + self->num_row = 4; - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(Matrix_to_4x4_doc, -".. method:: to_4x4()\n" -"\n" -" Return a 4x4 copy of this matrix.\n" -"\n" -" :return: a new matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: to_4x4()\n" + "\n" + " Return a 4x4 copy of this matrix.\n" + "\n" + " :return: a new matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_to_4x4(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (self->num_row == 4 && self->num_col == 4) { - return Matrix_CreatePyObject(self->matrix, 4, 4, Py_TYPE(self)); - } - else if (self->num_row == 3 && self->num_col == 3) { - float mat[4][4]; - copy_m4_m3(mat, (float (*)[3])self->matrix); - return Matrix_CreatePyObject((float *)mat, 4, 4, Py_TYPE(self)); - } - /* TODO, 2x2 matrix */ + if (self->num_row == 4 && self->num_col == 4) { + return Matrix_CreatePyObject(self->matrix, 4, 4, Py_TYPE(self)); + } + else if (self->num_row == 3 && self->num_col == 3) { + float mat[4][4]; + copy_m4_m3(mat, (float(*)[3])self->matrix); + return Matrix_CreatePyObject((float *)mat, 4, 4, Py_TYPE(self)); + } + /* TODO, 2x2 matrix */ - PyErr_SetString(PyExc_ValueError, - "Matrix.to_4x4(): " - "inappropriate matrix size"); - return NULL; + PyErr_SetString(PyExc_ValueError, + "Matrix.to_4x4(): " + "inappropriate matrix size"); + return NULL; } PyDoc_STRVAR(Matrix_to_3x3_doc, -".. method:: to_3x3()\n" -"\n" -" Return a 3x3 copy of this matrix.\n" -"\n" -" :return: a new matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: to_3x3()\n" + "\n" + " Return a 3x3 copy of this matrix.\n" + "\n" + " :return: a new matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_to_3x3(MatrixObject *self) { - float mat[3][3]; + float mat[3][3]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if ((self->num_row < 3) || (self->num_col < 3)) { - PyErr_SetString(PyExc_ValueError, - "Matrix.to_3x3(): inappropriate matrix size"); - return NULL; - } + if ((self->num_row < 3) || (self->num_col < 3)) { + PyErr_SetString(PyExc_ValueError, "Matrix.to_3x3(): inappropriate matrix size"); + return NULL; + } - matrix_as_3x3(mat, self); + matrix_as_3x3(mat, self); - return Matrix_CreatePyObject((float *)mat, 3, 3, Py_TYPE(self)); + return Matrix_CreatePyObject((float *)mat, 3, 3, Py_TYPE(self)); } PyDoc_STRVAR(Matrix_to_translation_doc, -".. method:: to_translation()\n" -"\n" -" Return the translation part of a 4 row matrix.\n" -"\n" -" :return: Return the translation of a matrix.\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: to_translation()\n" + "\n" + " Return the translation part of a 4 row matrix.\n" + "\n" + " :return: Return the translation of a matrix.\n" + " :rtype: :class:`Vector`\n"); static PyObject *Matrix_to_translation(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if ((self->num_row < 3) || self->num_col < 4) { - PyErr_SetString(PyExc_ValueError, - "Matrix.to_translation(): " - "inappropriate matrix size"); - return NULL; - } + if ((self->num_row < 3) || self->num_col < 4) { + PyErr_SetString(PyExc_ValueError, + "Matrix.to_translation(): " + "inappropriate matrix size"); + return NULL; + } - return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, NULL); + return Vector_CreatePyObject(MATRIX_COL_PTR(self, 3), 3, NULL); } PyDoc_STRVAR(Matrix_to_scale_doc, -".. method:: to_scale()\n" -"\n" -" Return the scale part of a 3x3 or 4x4 matrix.\n" -"\n" -" :return: Return the scale of a matrix.\n" -" :rtype: :class:`Vector`\n" -"\n" -" .. note:: This method does not return a negative scale on any axis because it is not possible to obtain this data from the matrix alone.\n" -); + ".. method:: to_scale()\n" + "\n" + " Return the scale part of a 3x3 or 4x4 matrix.\n" + "\n" + " :return: Return the scale of a matrix.\n" + " :rtype: :class:`Vector`\n" + "\n" + " .. note:: This method does not return a negative scale on any axis because it is " + "not possible to obtain this data from the matrix alone.\n"); static PyObject *Matrix_to_scale(MatrixObject *self) { - float rot[3][3]; - float mat[3][3]; - float size[3]; + float rot[3][3]; + float mat[3][3]; + float size[3]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - /*must be 3-4 cols, 3-4 rows, square matrix */ - if ((self->num_row < 3) || (self->num_col < 3)) { - PyErr_SetString(PyExc_ValueError, - "Matrix.to_scale(): " - "inappropriate matrix size, 3x3 minimum size"); - return NULL; - } + /*must be 3-4 cols, 3-4 rows, square matrix */ + if ((self->num_row < 3) || (self->num_col < 3)) { + PyErr_SetString(PyExc_ValueError, + "Matrix.to_scale(): " + "inappropriate matrix size, 3x3 minimum size"); + return NULL; + } - matrix_as_3x3(mat, self); + matrix_as_3x3(mat, self); - /* compatible mat4_to_loc_rot_size */ - mat3_to_rot_size(rot, size, mat); + /* compatible mat4_to_loc_rot_size */ + mat3_to_rot_size(rot, size, mat); - return Vector_CreatePyObject(size, 3, NULL); + return Vector_CreatePyObject(size, 3, NULL); } /*---------------------------matrix.invert() ---------------------*/ @@ -1375,774 +1412,777 @@ static PyObject *Matrix_to_scale(MatrixObject *self) /* re-usable checks for invert */ static bool matrix_invert_is_compat(const MatrixObject *self) { - if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix.invert(ed): " - "only square matrices are supported"); - return false; - } - else { - return true; - } + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.invert(ed): " + "only square matrices are supported"); + return false; + } + else { + return true; + } } static bool matrix_invert_args_check(const MatrixObject *self, PyObject *args, bool check_type) { - switch (PyTuple_GET_SIZE(args)) { - case 0: - return true; - case 1: - if (check_type) { - const MatrixObject *fallback = (MatrixObject *)PyTuple_GET_ITEM(args, 0); - if (!MatrixObject_Check(fallback)) { - PyErr_SetString(PyExc_TypeError, - "Matrix.invert: " - "expects a matrix argument or nothing"); - return false; - } - - if ((self->num_col != fallback->num_col) || - (self->num_row != fallback->num_row)) - { - PyErr_SetString(PyExc_TypeError, - "Matrix.invert: " - "matrix argument has different dimensions"); - return false; - } - } - - return true; - default: - PyErr_SetString(PyExc_ValueError, - "Matrix.invert(ed): " - "takes at most one argument"); - return false; - } + switch (PyTuple_GET_SIZE(args)) { + case 0: + return true; + case 1: + if (check_type) { + const MatrixObject *fallback = (MatrixObject *)PyTuple_GET_ITEM(args, 0); + if (!MatrixObject_Check(fallback)) { + PyErr_SetString(PyExc_TypeError, + "Matrix.invert: " + "expects a matrix argument or nothing"); + return false; + } + + if ((self->num_col != fallback->num_col) || (self->num_row != fallback->num_row)) { + PyErr_SetString(PyExc_TypeError, + "Matrix.invert: " + "matrix argument has different dimensions"); + return false; + } + } + + return true; + default: + PyErr_SetString(PyExc_ValueError, + "Matrix.invert(ed): " + "takes at most one argument"); + return false; + } } static void matrix_invert_raise_degenerate(void) { - PyErr_SetString(PyExc_ValueError, - "Matrix.invert(ed): " - "matrix does not have an inverse"); -} - -PyDoc_STRVAR(Matrix_invert_doc, -".. method:: invert(fallback=None)\n" -"\n" -" Set the matrix to its inverse.\n" -"\n" -" :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n" -" (instead of raising a :exc:`ValueError` exception).\n" -" :type fallback: :class:`Matrix`\n" -"\n" -" .. seealso:: `Inverse matrix ` on Wikipedia.\n" -); + PyErr_SetString(PyExc_ValueError, + "Matrix.invert(ed): " + "matrix does not have an inverse"); +} + +PyDoc_STRVAR( + Matrix_invert_doc, + ".. method:: invert(fallback=None)\n" + "\n" + " Set the matrix to its inverse.\n" + "\n" + " :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n" + " (instead of raising a :exc:`ValueError` exception).\n" + " :type fallback: :class:`Matrix`\n" + "\n" + " .. seealso:: `Inverse matrix ` on " + "Wikipedia.\n"); static PyObject *Matrix_invert(MatrixObject *self, PyObject *args) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (matrix_invert_is_compat(self) == false) { - return NULL; - } + if (matrix_invert_is_compat(self) == false) { + return NULL; + } - if (matrix_invert_args_check(self, args, true) == false) { - return NULL; - } + if (matrix_invert_args_check(self, args, true) == false) { + return NULL; + } - if (matrix_invert_internal(self, self->matrix)) { - /* pass */ - } - else { - if (PyTuple_GET_SIZE(args) == 1) { - MatrixObject *fallback = (MatrixObject *)PyTuple_GET_ITEM(args, 0); + if (matrix_invert_internal(self, self->matrix)) { + /* pass */ + } + else { + if (PyTuple_GET_SIZE(args) == 1) { + MatrixObject *fallback = (MatrixObject *)PyTuple_GET_ITEM(args, 0); - if (BaseMath_ReadCallback(fallback) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(fallback) == -1) { + return NULL; + } - if (self != fallback) { - matrix_copy(self, fallback); - } - } - else { - matrix_invert_raise_degenerate(); - return NULL; - } - } + if (self != fallback) { + matrix_copy(self, fallback); + } + } + else { + matrix_invert_raise_degenerate(); + return NULL; + } + } - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Matrix_inverted_doc, -".. method:: inverted(fallback=None)\n" -"\n" -" Return an inverted copy of the matrix.\n" -"\n" -" :arg fallback: return this when the inverse can't be calculated\n" -" (instead of raising a :exc:`ValueError`).\n" -" :type fallback: any\n" -" :return: the inverted matrix or fallback when given.\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: inverted(fallback=None)\n" + "\n" + " Return an inverted copy of the matrix.\n" + "\n" + " :arg fallback: return this when the inverse can't be calculated\n" + " (instead of raising a :exc:`ValueError`).\n" + " :type fallback: any\n" + " :return: the inverted matrix or fallback when given.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_inverted(MatrixObject *self, PyObject *args) { - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (matrix_invert_args_check(self, args, false) == false) { - return NULL; - } + if (matrix_invert_args_check(self, args, false) == false) { + return NULL; + } - if (matrix_invert_is_compat(self) == false) { - return NULL; - } + if (matrix_invert_is_compat(self) == false) { + return NULL; + } - if (matrix_invert_internal(self, mat)) { - /* pass */ - } - else { - if (PyTuple_GET_SIZE(args) == 1) { - PyObject *fallback = PyTuple_GET_ITEM(args, 0); - Py_INCREF(fallback); - return fallback; - } - else { - matrix_invert_raise_degenerate(); - return NULL; - } - } + if (matrix_invert_internal(self, mat)) { + /* pass */ + } + else { + if (PyTuple_GET_SIZE(args) == 1) { + PyObject *fallback = PyTuple_GET_ITEM(args, 0); + Py_INCREF(fallback); + return fallback; + } + else { + matrix_invert_raise_degenerate(); + return NULL; + } + } - return Matrix_copy_notest(self, mat); + return Matrix_copy_notest(self, mat); } static PyObject *Matrix_inverted_noargs(MatrixObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (matrix_invert_is_compat(self) == false) { - return NULL; - } + if (matrix_invert_is_compat(self) == false) { + return NULL; + } - if (matrix_invert_internal(self, self->matrix)) { - /* pass */ - } - else { - matrix_invert_raise_degenerate(); - return NULL; - } + if (matrix_invert_internal(self, self->matrix)) { + /* pass */ + } + else { + matrix_invert_raise_degenerate(); + return NULL; + } - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Matrix_invert_safe_doc, -".. method:: invert_safe()\n" -"\n" -" Set the matrix to its inverse, will never error.\n" -" If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n" -" If tweaked matrix is still degenerated, set to the identity matrix instead.\n" -"\n" -" .. seealso:: `Inverse Matrix ` on Wikipedia.\n" -); + ".. method:: invert_safe()\n" + "\n" + " Set the matrix to its inverse, will never error.\n" + " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, " + "to get an invertible one.\n" + " If tweaked matrix is still degenerated, set to the identity matrix instead.\n" + "\n" + " .. seealso:: `Inverse Matrix ` on " + "Wikipedia.\n"); static PyObject *Matrix_invert_safe(MatrixObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (matrix_invert_is_compat(self) == false) { - return NULL; - } + if (matrix_invert_is_compat(self) == false) { + return NULL; + } - matrix_invert_safe_internal(self, self->matrix); + matrix_invert_safe_internal(self, self->matrix); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Matrix_inverted_safe_doc, -".. method:: inverted_safe()\n" -"\n" -" Return an inverted copy of the matrix, will never error.\n" -" If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n" -" If tweaked matrix is still degenerated, return the identity matrix instead.\n" -"\n" -" :return: the inverted matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: inverted_safe()\n" + "\n" + " Return an inverted copy of the matrix, will never error.\n" + " If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, " + "to get an invertible one.\n" + " If tweaked matrix is still degenerated, return the identity matrix instead.\n" + "\n" + " :return: the inverted matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_inverted_safe(MatrixObject *self) { - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (matrix_invert_is_compat(self) == false) { - return NULL; - } + if (matrix_invert_is_compat(self) == false) { + return NULL; + } - matrix_invert_safe_internal(self, mat); + matrix_invert_safe_internal(self, mat); - return Matrix_copy_notest(self, mat); + return Matrix_copy_notest(self, mat); } /*---------------------------matrix.adjugate() ---------------------*/ -PyDoc_STRVAR(Matrix_adjugate_doc, -".. method:: adjugate()\n" -"\n" -" Set the matrix to its adjugate.\n" -"\n" -" .. note:: When the matrix cannot be adjugated a :exc:`ValueError` exception is raised.\n" -"\n" -" .. seealso:: `Adjugate matrix ` on Wikipedia.\n" -); +PyDoc_STRVAR( + Matrix_adjugate_doc, + ".. method:: adjugate()\n" + "\n" + " Set the matrix to its adjugate.\n" + "\n" + " .. note:: When the matrix cannot be adjugated a :exc:`ValueError` exception is raised.\n" + "\n" + " .. seealso:: `Adjugate matrix ` on " + "Wikipedia.\n"); static PyObject *Matrix_adjugate(MatrixObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } - - if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix.adjugate(d): " - "only square matrices are supported"); - return NULL; - } - - /* calculate the classical adjoint */ - if (self->num_col <= 4) { - adjoint_matrix_n(self->matrix, self->matrix, self->num_col); - } - else { - PyErr_Format(PyExc_ValueError, - "Matrix adjugate(d): size (%d) unsupported", - (int)self->num_col); - return NULL; - } - - - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; -} - -PyDoc_STRVAR(Matrix_adjugated_doc, -".. method:: adjugated()\n" -"\n" -" Return an adjugated copy of the matrix.\n" -"\n" -" :return: the adjugated matrix.\n" -" :rtype: :class:`Matrix`\n" -"\n" -" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n" -); + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } + + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.adjugate(d): " + "only square matrices are supported"); + return NULL; + } + + /* calculate the classical adjoint */ + if (self->num_col <= 4) { + adjoint_matrix_n(self->matrix, self->matrix, self->num_col); + } + else { + PyErr_Format( + PyExc_ValueError, "Matrix adjugate(d): size (%d) unsupported", (int)self->num_col); + return NULL; + } + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; +} + +PyDoc_STRVAR( + Matrix_adjugated_doc, + ".. method:: adjugated()\n" + "\n" + " Return an adjugated copy of the matrix.\n" + "\n" + " :return: the adjugated matrix.\n" + " :rtype: :class:`Matrix`\n" + "\n" + " .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n"); static PyObject *Matrix_adjugated(MatrixObject *self) { - return matrix__apply_to_copy((PyNoArgsFunction)Matrix_adjugate, self); + return matrix__apply_to_copy((PyNoArgsFunction)Matrix_adjugate, self); } -PyDoc_STRVAR(Matrix_rotate_doc, -".. method:: rotate(other)\n" -"\n" -" Rotates the matrix by another mathutils value.\n" -"\n" -" :arg other: rotation component of mathutils value\n" -" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" -"\n" -" .. note:: If any of the columns are not unit length this may not have desired results.\n" -); +PyDoc_STRVAR( + Matrix_rotate_doc, + ".. method:: rotate(other)\n" + "\n" + " Rotates the matrix by another mathutils value.\n" + "\n" + " :arg other: rotation component of mathutils value\n" + " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" + "\n" + " .. note:: If any of the columns are not unit length this may not have desired results.\n"); static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) { - float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; + float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1) { - return NULL; - } + if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1) { + return NULL; + } - if (self->num_row != 3 || self->num_col != 3) { - PyErr_SetString(PyExc_ValueError, - "Matrix.rotate(): " - "must have 3x3 dimensions"); - return NULL; - } + if (self->num_row != 3 || self->num_col != 3) { + PyErr_SetString(PyExc_ValueError, + "Matrix.rotate(): " + "must have 3x3 dimensions"); + return NULL; + } - matrix_as_3x3(self_rmat, self); - mul_m3_m3m3(rmat, other_rmat, self_rmat); + matrix_as_3x3(self_rmat, self); + mul_m3_m3m3(rmat, other_rmat, self_rmat); - copy_m3_m3((float (*)[3])(self->matrix), rmat); + copy_m3_m3((float(*)[3])(self->matrix), rmat); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } /*---------------------------matrix.decompose() ---------------------*/ PyDoc_STRVAR(Matrix_decompose_doc, -".. method:: decompose()\n" -"\n" -" Return the translation, rotation, and scale components of this matrix.\n" -"\n" -" :return: tuple of translation, rotation, and scale\n" -" :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)" -); + ".. method:: decompose()\n" + "\n" + " Return the translation, rotation, and scale components of this matrix.\n" + "\n" + " :return: tuple of translation, rotation, and scale\n" + " :rtype: (:class:`Vector`, :class:`Quaternion`, :class:`Vector`)"); static PyObject *Matrix_decompose(MatrixObject *self) { - PyObject *ret; - float loc[3]; - float rot[3][3]; - float quat[4]; - float size[3]; + PyObject *ret; + float loc[3]; + float rot[3][3]; + float quat[4]; + float size[3]; - if (self->num_row != 4 || self->num_col != 4) { - PyErr_SetString(PyExc_ValueError, - "Matrix.decompose(): " - "inappropriate matrix size - expects 4x4 matrix"); - return NULL; - } + if (self->num_row != 4 || self->num_col != 4) { + PyErr_SetString(PyExc_ValueError, + "Matrix.decompose(): " + "inappropriate matrix size - expects 4x4 matrix"); + return NULL; + } - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - mat4_to_loc_rot_size(loc, rot, size, (float (*)[4])self->matrix); - mat3_to_quat(quat, rot); + mat4_to_loc_rot_size(loc, rot, size, (float(*)[4])self->matrix); + mat3_to_quat(quat, rot); - ret = PyTuple_New(3); - PyTuple_SET_ITEMS(ret, - Vector_CreatePyObject(loc, 3, NULL), - Quaternion_CreatePyObject(quat, NULL), - Vector_CreatePyObject(size, 3, NULL)); - return ret; + ret = PyTuple_New(3); + PyTuple_SET_ITEMS(ret, + Vector_CreatePyObject(loc, 3, NULL), + Quaternion_CreatePyObject(quat, NULL), + Vector_CreatePyObject(size, 3, NULL)); + return ret; } - - PyDoc_STRVAR(Matrix_lerp_doc, -".. function:: lerp(other, factor)\n" -"\n" -" Returns the interpolation of two matrices. Uses polar decomposition, see" -" \"Matrix Animation and Polar Decomposition\", Shoemake and Duff, 1992.\n" -"\n" -" :arg other: value to interpolate with.\n" -" :type other: :class:`Matrix`\n" -" :arg factor: The interpolation value in [0.0, 1.0].\n" -" :type factor: float\n" -" :return: The interpolated matrix.\n" -" :rtype: :class:`Matrix`\n" -); + ".. function:: lerp(other, factor)\n" + "\n" + " Returns the interpolation of two matrices. Uses polar decomposition, see" + " \"Matrix Animation and Polar Decomposition\", Shoemake and Duff, 1992.\n" + "\n" + " :arg other: value to interpolate with.\n" + " :type other: :class:`Matrix`\n" + " :arg factor: The interpolation value in [0.0, 1.0].\n" + " :type factor: float\n" + " :return: The interpolated matrix.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) { - MatrixObject *mat2 = NULL; - float fac, mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + MatrixObject *mat2 = NULL; + float fac, mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - if (!PyArg_ParseTuple(args, "O!f:lerp", &matrix_Type, &mat2, &fac)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "O!f:lerp", &matrix_Type, &mat2, &fac)) { + return NULL; + } - if (self->num_col != mat2->num_col || self->num_row != mat2->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix.lerp(): " - "expects both matrix objects of the same dimensions"); - return NULL; - } + if (self->num_col != mat2->num_col || self->num_row != mat2->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.lerp(): " + "expects both matrix objects of the same dimensions"); + return NULL; + } - if (BaseMath_ReadCallback(self) == -1 || BaseMath_ReadCallback(mat2) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1 || BaseMath_ReadCallback(mat2) == -1) { + return NULL; + } - /* TODO, different sized matrix */ - if (self->num_col == 4 && self->num_row == 4) { + /* TODO, different sized matrix */ + if (self->num_col == 4 && self->num_row == 4) { #ifdef MATH_STANDALONE - blend_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac); + blend_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac); #else - interp_m4_m4m4((float (*)[4])mat, (float (*)[4])self->matrix, (float (*)[4])mat2->matrix, fac); + interp_m4_m4m4((float(*)[4])mat, (float(*)[4])self->matrix, (float(*)[4])mat2->matrix, fac); #endif - } - else if (self->num_col == 3 && self->num_row == 3) { + } + else if (self->num_col == 3 && self->num_row == 3) { #ifdef MATH_STANDALONE - blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac); + blend_m3_m3m3((float(*)[3])mat, (float(*)[3])self->matrix, (float(*)[3])mat2->matrix, fac); #else - interp_m3_m3m3((float (*)[3])mat, (float (*)[3])self->matrix, (float (*)[3])mat2->matrix, fac); + interp_m3_m3m3((float(*)[3])mat, (float(*)[3])self->matrix, (float(*)[3])mat2->matrix, fac); #endif - } - else { - PyErr_SetString(PyExc_ValueError, - "Matrix.lerp(): " - "only 3x3 and 4x4 matrices supported"); - return NULL; - } + } + else { + PyErr_SetString(PyExc_ValueError, + "Matrix.lerp(): " + "only 3x3 and 4x4 matrices supported"); + return NULL; + } - return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_TYPE(self)); + return Matrix_CreatePyObject(mat, self->num_col, self->num_row, Py_TYPE(self)); } /*---------------------------matrix.determinant() ----------------*/ -PyDoc_STRVAR(Matrix_determinant_doc, -".. method:: determinant()\n" -"\n" -" Return the determinant of a matrix.\n" -"\n" -" :return: Return the determinant of a matrix.\n" -" :rtype: float\n" -"\n" -" .. seealso:: `Determinant ` on Wikipedia.\n" -); +PyDoc_STRVAR( + Matrix_determinant_doc, + ".. method:: determinant()\n" + "\n" + " Return the determinant of a matrix.\n" + "\n" + " :return: Return the determinant of a matrix.\n" + " :rtype: float\n" + "\n" + " .. seealso:: `Determinant ` on Wikipedia.\n"); static PyObject *Matrix_determinant(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix.determinant(): " - "only square matrices are supported"); - return NULL; - } + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.determinant(): " + "only square matrices are supported"); + return NULL; + } - return PyFloat_FromDouble((double)matrix_determinant_internal(self)); + return PyFloat_FromDouble((double)matrix_determinant_internal(self)); } /*---------------------------matrix.transpose() ------------------*/ -PyDoc_STRVAR(Matrix_transpose_doc, -".. method:: transpose()\n" -"\n" -" Set the matrix to its transpose.\n" -"\n" -" .. seealso:: `Transpose ` on Wikipedia.\n" -); +PyDoc_STRVAR( + Matrix_transpose_doc, + ".. method:: transpose()\n" + "\n" + " Set the matrix to its transpose.\n" + "\n" + " .. seealso:: `Transpose ` on Wikipedia.\n"); static PyObject *Matrix_transpose(MatrixObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } - - if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix.transpose(d): " - "only square matrices are supported"); - return NULL; - } - - if (self->num_col == 2) { - const float t = MATRIX_ITEM(self, 1, 0); - MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1); - MATRIX_ITEM(self, 0, 1) = t; - } - else if (self->num_col == 3) { - transpose_m3((float (*)[3])self->matrix); - } - else { - transpose_m4((float (*)[4])self->matrix); - } - - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } + + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.transpose(d): " + "only square matrices are supported"); + return NULL; + } + + if (self->num_col == 2) { + const float t = MATRIX_ITEM(self, 1, 0); + MATRIX_ITEM(self, 1, 0) = MATRIX_ITEM(self, 0, 1); + MATRIX_ITEM(self, 0, 1) = t; + } + else if (self->num_col == 3) { + transpose_m3((float(*)[3])self->matrix); + } + else { + transpose_m4((float(*)[4])self->matrix); + } + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Matrix_transposed_doc, -".. method:: transposed()\n" -"\n" -" Return a new, transposed matrix.\n" -"\n" -" :return: a transposed matrix\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: transposed()\n" + "\n" + " Return a new, transposed matrix.\n" + "\n" + " :return: a transposed matrix\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_transposed(MatrixObject *self) { - return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self); + return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self); } /*---------------------------matrix.normalize() ------------------*/ PyDoc_STRVAR(Matrix_normalize_doc, -".. method:: normalize()\n" -"\n" -" Normalize each of the matrix columns.\n" -); + ".. method:: normalize()\n" + "\n" + " Normalize each of the matrix columns.\n"); static PyObject *Matrix_normalize(MatrixObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } - - if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix.normalize(): " - "only square matrices are supported"); - return NULL; - } - - if (self->num_col == 3) { - normalize_m3((float (*)[3])self->matrix); - } - else if (self->num_col == 4) { - normalize_m4((float (*)[4])self->matrix); - } - else { - PyErr_SetString(PyExc_ValueError, - "Matrix.normalize(): " - "can only use a 3x3 or 4x4 matrix"); - } - - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } + + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.normalize(): " + "only square matrices are supported"); + return NULL; + } + + if (self->num_col == 3) { + normalize_m3((float(*)[3])self->matrix); + } + else if (self->num_col == 4) { + normalize_m4((float(*)[4])self->matrix); + } + else { + PyErr_SetString(PyExc_ValueError, + "Matrix.normalize(): " + "can only use a 3x3 or 4x4 matrix"); + } + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Matrix_normalized_doc, -".. method:: normalized()\n" -"\n" -" Return a column normalized matrix\n" -"\n" -" :return: a column normalized matrix\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: normalized()\n" + "\n" + " Return a column normalized matrix\n" + "\n" + " :return: a column normalized matrix\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_normalized(MatrixObject *self) { - return matrix__apply_to_copy((PyNoArgsFunction)Matrix_normalize, self); + return matrix__apply_to_copy((PyNoArgsFunction)Matrix_normalize, self); } /*---------------------------matrix.zero() -----------------------*/ PyDoc_STRVAR(Matrix_zero_doc, -".. method:: zero()\n" -"\n" -" Set all the matrix values to zero.\n" -"\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: zero()\n" + "\n" + " Set all the matrix values to zero.\n" + "\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_zero(MatrixObject *self) { - if (BaseMath_Prepare_ForWrite(self) == -1) { - return NULL; - } - - copy_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f); + if (BaseMath_Prepare_ForWrite(self) == -1) { + return NULL; + } - if (BaseMath_WriteCallback(self) == -1) { - return NULL; - } + copy_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f); - Py_RETURN_NONE; + if (BaseMath_WriteCallback(self) == -1) { + return NULL; + } + Py_RETURN_NONE; } /*---------------------------matrix.identity(() ------------------*/ static void matrix_identity_internal(MatrixObject *self) { - BLI_assert((self->num_col == self->num_row) && (self->num_row <= 4)); + BLI_assert((self->num_col == self->num_row) && (self->num_row <= 4)); - if (self->num_col == 2) { - unit_m2((float (*)[2])self->matrix); - } - else if (self->num_col == 3) { - unit_m3((float (*)[3])self->matrix); - } - else { - unit_m4((float (*)[4])self->matrix); - } + if (self->num_col == 2) { + unit_m2((float(*)[2])self->matrix); + } + else if (self->num_col == 3) { + unit_m3((float(*)[3])self->matrix); + } + else { + unit_m4((float(*)[4])self->matrix); + } } PyDoc_STRVAR(Matrix_identity_doc, -".. method:: identity()\n" -"\n" -" Set the matrix to the identity matrix.\n" -"\n" -" .. note:: An object with a location and rotation of zero, and a scale of one\n" -" will have an identity matrix.\n" -"\n" -" .. seealso:: `Identity matrix ` on Wikipedia.\n" -); + ".. method:: identity()\n" + "\n" + " Set the matrix to the identity matrix.\n" + "\n" + " .. note:: An object with a location and rotation of zero, and a scale of one\n" + " will have an identity matrix.\n" + "\n" + " .. seealso:: `Identity matrix ` " + "on Wikipedia.\n"); static PyObject *Matrix_identity(MatrixObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix.identity(): " - "only square matrices are supported"); - return NULL; - } + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.identity(): " + "only square matrices are supported"); + return NULL; + } - matrix_identity_internal(self); + matrix_identity_internal(self); - if (BaseMath_WriteCallback(self) == -1) { - return NULL; - } + if (BaseMath_WriteCallback(self) == -1) { + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } /*---------------------------Matrix.copy() ------------------*/ static PyObject *Matrix_copy_notest(MatrixObject *self, const float *matrix) { - return Matrix_CreatePyObject((float *)matrix, self->num_col, self->num_row, Py_TYPE(self)); + return Matrix_CreatePyObject((float *)matrix, self->num_col, self->num_row, Py_TYPE(self)); } PyDoc_STRVAR(Matrix_copy_doc, -".. method:: copy()\n" -"\n" -" Returns a copy of this matrix.\n" -"\n" -" :return: an instance of itself\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: copy()\n" + "\n" + " Returns a copy of this matrix.\n" + "\n" + " :return: an instance of itself\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Matrix_copy(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return Matrix_copy_notest(self, self->matrix); + return Matrix_copy_notest(self, self->matrix); } static PyObject *Matrix_deepcopy(MatrixObject *self, PyObject *args) { - if (!PyC_CheckArgs_DeepCopy(args)) { - return NULL; - } - return Matrix_copy(self); + if (!PyC_CheckArgs_DeepCopy(args)) { + return NULL; + } + return Matrix_copy(self); } /*----------------------------print object (internal)-------------*/ /* print the object to screen */ static PyObject *Matrix_repr(MatrixObject *self) { - int col, row; - PyObject *rows[MATRIX_MAX_DIM] = {NULL}; - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - for (row = 0; row < self->num_row; row++) { - rows[row] = PyTuple_New(self->num_col); - for (col = 0; col < self->num_col; col++) { - PyTuple_SET_ITEM(rows[row], col, PyFloat_FromDouble(MATRIX_ITEM(self, row, col))); - } - } - switch (self->num_row) { - case 2: return PyUnicode_FromFormat("Matrix((%R,\n" - " %R))", rows[0], rows[1]); - - case 3: return PyUnicode_FromFormat("Matrix((%R,\n" - " %R,\n" - " %R))", rows[0], rows[1], rows[2]); - - case 4: return PyUnicode_FromFormat("Matrix((%R,\n" - " %R,\n" - " %R,\n" - " %R))", rows[0], rows[1], rows[2], rows[3]); - } - - Py_FatalError("Matrix(): invalid row size!"); - return NULL; + int col, row; + PyObject *rows[MATRIX_MAX_DIM] = {NULL}; + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + for (row = 0; row < self->num_row; row++) { + rows[row] = PyTuple_New(self->num_col); + for (col = 0; col < self->num_col; col++) { + PyTuple_SET_ITEM(rows[row], col, PyFloat_FromDouble(MATRIX_ITEM(self, row, col))); + } + } + switch (self->num_row) { + case 2: + return PyUnicode_FromFormat( + "Matrix((%R,\n" + " %R))", + rows[0], + rows[1]); + + case 3: + return PyUnicode_FromFormat( + "Matrix((%R,\n" + " %R,\n" + " %R))", + rows[0], + rows[1], + rows[2]); + + case 4: + return PyUnicode_FromFormat( + "Matrix((%R,\n" + " %R,\n" + " %R,\n" + " %R))", + rows[0], + rows[1], + rows[2], + rows[3]); + } + + Py_FatalError("Matrix(): invalid row size!"); + return NULL; } #ifndef MATH_STANDALONE static PyObject *Matrix_str(MatrixObject *self) { - DynStr *ds; + DynStr *ds; - int maxsize[MATRIX_MAX_DIM]; - int row, col; + int maxsize[MATRIX_MAX_DIM]; + int row, col; - char dummy_buf[64]; + char dummy_buf[64]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - ds = BLI_dynstr_new(); + ds = BLI_dynstr_new(); - /* First determine the maximum width for each column */ - for (col = 0; col < self->num_col; col++) { - maxsize[col] = 0; - for (row = 0; row < self->num_row; row++) { - int size = BLI_snprintf(dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col)); - maxsize[col] = max_ii(maxsize[col], size); - } - } + /* First determine the maximum width for each column */ + for (col = 0; col < self->num_col; col++) { + maxsize[col] = 0; + for (row = 0; row < self->num_row; row++) { + int size = BLI_snprintf(dummy_buf, sizeof(dummy_buf), "%.4f", MATRIX_ITEM(self, row, col)); + maxsize[col] = max_ii(maxsize[col], size); + } + } - /* Now write the unicode string to be printed */ - BLI_dynstr_appendf(ds, "num_row, self->num_col); - for (row = 0; row < self->num_row; row++) { - for (col = 0; col < self->num_col; col++) { - BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, row, col)); - } - BLI_dynstr_append(ds, row + 1 != self->num_row ? ")\n (" : ")"); - } - BLI_dynstr_append(ds, ">"); + /* Now write the unicode string to be printed */ + BLI_dynstr_appendf(ds, "num_row, self->num_col); + for (row = 0; row < self->num_row; row++) { + for (col = 0; col < self->num_col; col++) { + BLI_dynstr_appendf(ds, col ? ", %*.4f" : "%*.4f", maxsize[col], MATRIX_ITEM(self, row, col)); + } + BLI_dynstr_append(ds, row + 1 != self->num_row ? ")\n (" : ")"); + } + BLI_dynstr_append(ds, ">"); - return mathutils_dynstr_to_py(ds); /* frees ds */ + return mathutils_dynstr_to_py(ds); /* frees ds */ } #endif static PyObject *Matrix_richcmpr(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ - - if (MatrixObject_Check(a) && MatrixObject_Check(b)) { - MatrixObject *matA = (MatrixObject *)a; - MatrixObject *matB = (MatrixObject *)b; - - if (BaseMath_ReadCallback(matA) == -1 || BaseMath_ReadCallback(matB) == -1) { - return NULL; - } - - ok = ((matA->num_row == matB->num_row) && - (matA->num_col == matB->num_col) && - EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->num_col * matA->num_row), 1) - ) ? 0 : -1; - } - - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; - - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } - - return Py_INCREF_RET(res); + PyObject *res; + int ok = -1; /* zero is true */ + + if (MatrixObject_Check(a) && MatrixObject_Check(b)) { + MatrixObject *matA = (MatrixObject *)a; + MatrixObject *matB = (MatrixObject *)b; + + if (BaseMath_ReadCallback(matA) == -1 || BaseMath_ReadCallback(matB) == -1) { + return NULL; + } + + ok = ((matA->num_row == matB->num_row) && (matA->num_col == matB->num_col) && + EXPP_VectorsAreEqual(matA->matrix, matB->matrix, (matA->num_col * matA->num_row), 1)) ? + 0 : + -1; + } + + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; + + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } + + return Py_INCREF_RET(res); } static Py_hash_t Matrix_hash(MatrixObject *self) { - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } - if (BaseMathObject_Prepare_ForHash(self) == -1) { - return -1; - } + if (BaseMathObject_Prepare_ForHash(self) == -1) { + return -1; + } - matrix_transpose_internal(mat, self); + matrix_transpose_internal(mat, self); - return mathutils_array_hash(mat, self->num_row * self->num_col); + return mathutils_array_hash(mat, self->num_row * self->num_col); } /*---------------------SEQUENCE PROTOCOLS------------------------ @@ -2150,39 +2190,41 @@ static Py_hash_t Matrix_hash(MatrixObject *self) * sequence length */ static int Matrix_len(MatrixObject *self) { - return self->num_row; + return self->num_row; } /*----------------------------object[]--------------------------- * sequence accessor (get) * the wrapped vector gives direct access to the matrix data */ static PyObject *Matrix_item_row(MatrixObject *self, int row) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (row < 0 || row >= self->num_row) { - PyErr_SetString(PyExc_IndexError, - "matrix[attribute]: " - "array index out of range"); - return NULL; - } - return Vector_CreatePyObject_cb((PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, row); + if (row < 0 || row >= self->num_row) { + PyErr_SetString(PyExc_IndexError, + "matrix[attribute]: " + "array index out of range"); + return NULL; + } + return Vector_CreatePyObject_cb( + (PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, row); } /* same but column access */ static PyObject *Matrix_item_col(MatrixObject *self, int col) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (col < 0 || col >= self->num_col) { - PyErr_SetString(PyExc_IndexError, - "matrix[attribute]: " - "array index out of range"); - return NULL; - } - return Vector_CreatePyObject_cb((PyObject *)self, self->num_row, mathutils_matrix_col_cb_index, col); + if (col < 0 || col >= self->num_col) { + PyErr_SetString(PyExc_IndexError, + "matrix[attribute]: " + "array index out of range"); + return NULL; + } + return Vector_CreatePyObject_cb( + (PyObject *)self, self->num_row, mathutils_matrix_col_cb_index, col); } /*----------------------------object[]------------------------- @@ -2190,994 +2232,1031 @@ static PyObject *Matrix_item_col(MatrixObject *self, int col) static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value) { - int col; - float vec[MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + int col; + float vec[MATRIX_MAX_DIM]; + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - if (row >= self->num_row || row < 0) { - PyErr_SetString(PyExc_IndexError, - "matrix[attribute] = x: bad row"); - return -1; - } + if (row >= self->num_row || row < 0) { + PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad row"); + return -1; + } - if (mathutils_array_parse(vec, self->num_col, self->num_col, value, "matrix[i] = value assignment") == -1) { - return -1; - } + if (mathutils_array_parse( + vec, self->num_col, self->num_col, value, "matrix[i] = value assignment") == -1) { + return -1; + } - /* Since we are assigning a row we cannot memcpy */ - for (col = 0; col < self->num_col; col++) { - MATRIX_ITEM(self, row, col) = vec[col]; - } + /* Since we are assigning a row we cannot memcpy */ + for (col = 0; col < self->num_col; col++) { + MATRIX_ITEM(self, row, col) = vec[col]; + } - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value) { - int row; - float vec[MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + int row; + float vec[MATRIX_MAX_DIM]; + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - if (col >= self->num_col || col < 0) { - PyErr_SetString(PyExc_IndexError, - "matrix[attribute] = x: bad col"); - return -1; - } + if (col >= self->num_col || col < 0) { + PyErr_SetString(PyExc_IndexError, "matrix[attribute] = x: bad col"); + return -1; + } - if (mathutils_array_parse(vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") == -1) { - return -1; - } + if (mathutils_array_parse( + vec, self->num_row, self->num_row, value, "matrix[i] = value assignment") == -1) { + return -1; + } - /* Since we are assigning a row we cannot memcpy */ - for (row = 0; row < self->num_row; row++) { - MATRIX_ITEM(self, row, col) = vec[row]; - } + /* Since we are assigning a row we cannot memcpy */ + for (row = 0; row < self->num_row; row++) { + MATRIX_ITEM(self, row, col) = vec[row]; + } - (void)BaseMath_WriteCallback(self); - return 0; + (void)BaseMath_WriteCallback(self); + return 0; } - /*----------------------------object[z:y]------------------------ * sequence slice (get)*/ static PyObject *Matrix_slice(MatrixObject *self, int begin, int end) { - PyObject *tuple; - int count; + PyObject *tuple; + int count; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - CLAMP(begin, 0, self->num_row); - CLAMP(end, 0, self->num_row); - begin = MIN2(begin, end); + CLAMP(begin, 0, self->num_row); + CLAMP(end, 0, self->num_row); + begin = MIN2(begin, end); - tuple = PyTuple_New(end - begin); - for (count = begin; count < end; count++) { - PyTuple_SET_ITEM(tuple, count - begin, - Vector_CreatePyObject_cb((PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, count)); - } + tuple = PyTuple_New(end - begin); + for (count = begin; count < end; count++) { + PyTuple_SET_ITEM(tuple, + count - begin, + Vector_CreatePyObject_cb( + (PyObject *)self, self->num_col, mathutils_matrix_row_cb_index, count)); + } - return tuple; + return tuple; } /*----------------------------object[z:y]------------------------ * sequence slice (set)*/ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *value) { - PyObject *value_fast; - - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - - CLAMP(begin, 0, self->num_row); - CLAMP(end, 0, self->num_row); - begin = MIN2(begin, end); - - /* non list/tuple cases */ - if (!(value_fast = PySequence_Fast(value, "matrix[begin:end] = value"))) { - /* PySequence_Fast sets the error */ - return -1; - } - else { - PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); - const int size = end - begin; - int row, col; - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - float vec[4]; - - if (PySequence_Fast_GET_SIZE(value_fast) != size) { - Py_DECREF(value_fast); - PyErr_SetString(PyExc_ValueError, - "matrix[begin:end] = []: " - "size mismatch in slice assignment"); - return -1; - } - - memcpy(mat, self->matrix, self->num_col * self->num_row * sizeof(float)); - - /* parse sub items */ - for (row = begin; row < end; row++) { - /* parse each sub sequence */ - PyObject *item = value_fast_items[row - begin]; - - if (mathutils_array_parse(vec, self->num_col, self->num_col, item, - "matrix[begin:end] = value assignment") == -1) - { - Py_DECREF(value_fast); - return -1; - } - - for (col = 0; col < self->num_col; col++) { - mat[col * self->num_row + row] = vec[col]; - } - } - - Py_DECREF(value_fast); - - /*parsed well - now set in matrix*/ - memcpy(self->matrix, mat, self->num_col * self->num_row * sizeof(float)); - - (void)BaseMath_WriteCallback(self); - return 0; - } + PyObject *value_fast; + + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + + CLAMP(begin, 0, self->num_row); + CLAMP(end, 0, self->num_row); + begin = MIN2(begin, end); + + /* non list/tuple cases */ + if (!(value_fast = PySequence_Fast(value, "matrix[begin:end] = value"))) { + /* PySequence_Fast sets the error */ + return -1; + } + else { + PyObject **value_fast_items = PySequence_Fast_ITEMS(value_fast); + const int size = end - begin; + int row, col; + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + float vec[4]; + + if (PySequence_Fast_GET_SIZE(value_fast) != size) { + Py_DECREF(value_fast); + PyErr_SetString(PyExc_ValueError, + "matrix[begin:end] = []: " + "size mismatch in slice assignment"); + return -1; + } + + memcpy(mat, self->matrix, self->num_col * self->num_row * sizeof(float)); + + /* parse sub items */ + for (row = begin; row < end; row++) { + /* parse each sub sequence */ + PyObject *item = value_fast_items[row - begin]; + + if (mathutils_array_parse( + vec, self->num_col, self->num_col, item, "matrix[begin:end] = value assignment") == + -1) { + Py_DECREF(value_fast); + return -1; + } + + for (col = 0; col < self->num_col; col++) { + mat[col * self->num_row + row] = vec[col]; + } + } + + Py_DECREF(value_fast); + + /*parsed well - now set in matrix*/ + memcpy(self->matrix, mat, self->num_col * self->num_row * sizeof(float)); + + (void)BaseMath_WriteCallback(self); + return 0; + } } /*------------------------NUMERIC PROTOCOLS---------------------- *------------------------obj + obj------------------------------*/ static PyObject *Matrix_add(PyObject *m1, PyObject *m2) { - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - MatrixObject *mat1 = NULL, *mat2 = NULL; + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + MatrixObject *mat1 = NULL, *mat2 = NULL; - mat1 = (MatrixObject *)m1; - mat2 = (MatrixObject *)m2; + mat1 = (MatrixObject *)m1; + mat2 = (MatrixObject *)m2; - if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) { - PyErr_Format(PyExc_TypeError, - "Matrix addition: (%s + %s) " - "invalid type for this operation", - Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); - return NULL; - } + if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) { + PyErr_Format(PyExc_TypeError, + "Matrix addition: (%s + %s) " + "invalid type for this operation", + Py_TYPE(m1)->tp_name, + Py_TYPE(m2)->tp_name); + return NULL; + } - if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1) { + return NULL; + } - if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix addition: " - "matrices must have the same dimensions for this operation"); - return NULL; - } + if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix addition: " + "matrices must have the same dimensions for this operation"); + return NULL; + } - add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + add_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); - return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); + return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); } /*------------------------obj - obj------------------------------ * subtraction */ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2) { - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - MatrixObject *mat1 = NULL, *mat2 = NULL; + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + MatrixObject *mat1 = NULL, *mat2 = NULL; - mat1 = (MatrixObject *)m1; - mat2 = (MatrixObject *)m2; + mat1 = (MatrixObject *)m1; + mat2 = (MatrixObject *)m2; - if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) { - PyErr_Format(PyExc_TypeError, - "Matrix subtraction: (%s - %s) " - "invalid type for this operation", - Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); - return NULL; - } + if (!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) { + PyErr_Format(PyExc_TypeError, + "Matrix subtraction: (%s - %s) " + "invalid type for this operation", + Py_TYPE(m1)->tp_name, + Py_TYPE(m2)->tp_name); + return NULL; + } - if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(mat1) == -1 || BaseMath_ReadCallback(mat2) == -1) { + return NULL; + } - if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { - PyErr_SetString(PyExc_ValueError, - "Matrix addition: " - "matrices must have the same dimensions for this operation"); - return NULL; - } + if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix addition: " + "matrices must have the same dimensions for this operation"); + return NULL; + } - sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + sub_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); - return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); + return Matrix_CreatePyObject(mat, mat1->num_col, mat1->num_row, Py_TYPE(mat1)); } /*------------------------obj * obj------------------------------ * element-wise multiplication */ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar) { - float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar); - return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat)); + float tmat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + mul_vn_vn_fl(tmat, mat->matrix, mat->num_col * mat->num_row, scalar); + return Matrix_CreatePyObject(tmat, mat->num_col, mat->num_row, Py_TYPE(mat)); } static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) { - float scalar; + float scalar; - MatrixObject *mat1 = NULL, *mat2 = NULL; + MatrixObject *mat1 = NULL, *mat2 = NULL; - if (MatrixObject_Check(m1)) { - mat1 = (MatrixObject *)m1; - if (BaseMath_ReadCallback(mat1) == -1) { - return NULL; - } - } - if (MatrixObject_Check(m2)) { - mat2 = (MatrixObject *)m2; - if (BaseMath_ReadCallback(mat2) == -1) { - return NULL; - } - } + if (MatrixObject_Check(m1)) { + mat1 = (MatrixObject *)m1; + if (BaseMath_ReadCallback(mat1) == -1) { + return NULL; + } + } + if (MatrixObject_Check(m2)) { + mat2 = (MatrixObject *)m2; + if (BaseMath_ReadCallback(mat2) == -1) { + return NULL; + } + } - if (mat1 && mat2) { + if (mat1 && mat2) { #ifdef USE_MATHUTILS_ELEM_MUL - /* MATRIX * MATRIX */ - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + /* MATRIX * MATRIX */ + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { - PyErr_SetString(PyExc_ValueError, - "matrix1 * matrix2: matrix1 number of rows/columns " - "and the matrix2 number of rows/columns must be the same"); - return NULL; - } + if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { + PyErr_SetString(PyExc_ValueError, + "matrix1 * matrix2: matrix1 number of rows/columns " + "and the matrix2 number of rows/columns must be the same"); + return NULL; + } - mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + mul_vn_vnvn(mat, mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); - return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); + return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); #endif - } - else if (mat2) { - /*FLOAT/INT * MATRIX */ - if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) { - return matrix_mul_float(mat2, scalar); - } - } - else if (mat1) { - /* MATRIX * FLOAT/INT */ - if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) { - return matrix_mul_float(mat1, scalar); - } - } - - PyErr_Format(PyExc_TypeError, - "Element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); - return NULL; + } + else if (mat2) { + /*FLOAT/INT * MATRIX */ + if (((scalar = PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred()) == 0) { + return matrix_mul_float(mat2, scalar); + } + } + else if (mat1) { + /* MATRIX * FLOAT/INT */ + if (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0) { + return matrix_mul_float(mat1, scalar); + } + } + + PyErr_Format(PyExc_TypeError, + "Element-wise multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(m1)->tp_name, + Py_TYPE(m2)->tp_name); + return NULL; } /*------------------------obj *= obj------------------------------ * Inplace element-wise multiplication */ static PyObject *Matrix_imul(PyObject *m1, PyObject *m2) { - float scalar; + float scalar; - MatrixObject *mat1 = NULL, *mat2 = NULL; + MatrixObject *mat1 = NULL, *mat2 = NULL; - if (MatrixObject_Check(m1)) { - mat1 = (MatrixObject *)m1; - if (BaseMath_ReadCallback(mat1) == -1) { - return NULL; - } - } - if (MatrixObject_Check(m2)) { - mat2 = (MatrixObject *)m2; - if (BaseMath_ReadCallback(mat2) == -1) { - return NULL; - } - } + if (MatrixObject_Check(m1)) { + mat1 = (MatrixObject *)m1; + if (BaseMath_ReadCallback(mat1) == -1) { + return NULL; + } + } + if (MatrixObject_Check(m2)) { + mat2 = (MatrixObject *)m2; + if (BaseMath_ReadCallback(mat2) == -1) { + return NULL; + } + } - if (mat1 && mat2) { + if (mat1 && mat2) { #ifdef USE_MATHUTILS_ELEM_MUL - /* MATRIX *= MATRIX */ - if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { - PyErr_SetString(PyExc_ValueError, - "matrix1 *= matrix2: matrix1 number of rows/columns " - "and the matrix2 number of rows/columns must be the same"); - return NULL; - } - - mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); + /* MATRIX *= MATRIX */ + if ((mat1->num_row != mat2->num_row) || (mat1->num_col != mat2->num_col)) { + PyErr_SetString(PyExc_ValueError, + "matrix1 *= matrix2: matrix1 number of rows/columns " + "and the matrix2 number of rows/columns must be the same"); + return NULL; + } + + mul_vn_vn(mat1->matrix, mat2->matrix, mat1->num_col * mat1->num_row); #else - PyErr_Format(PyExc_TypeError, - "Inplace element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); - return NULL; + PyErr_Format(PyExc_TypeError, + "Inplace element-wise multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(m1)->tp_name, + Py_TYPE(m2)->tp_name); + return NULL; #endif - } - else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) { - /* MATRIX *= FLOAT/INT */ - mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar); - } - else { - PyErr_Format(PyExc_TypeError, - "Inplace element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); - return NULL; - } - - (void)BaseMath_WriteCallback(mat1); - Py_INCREF(m1); - return m1; + } + else if (mat1 && (((scalar = PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred()) == 0)) { + /* MATRIX *= FLOAT/INT */ + mul_vn_fl(mat1->matrix, mat1->num_row * mat1->num_col, scalar); + } + else { + PyErr_Format(PyExc_TypeError, + "Inplace element-wise multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(m1)->tp_name, + Py_TYPE(m2)->tp_name); + return NULL; + } + + (void)BaseMath_WriteCallback(mat1); + Py_INCREF(m1); + return m1; } /*------------------------obj @ obj------------------------------ * matrix multiplication */ static PyObject *Matrix_matmul(PyObject *m1, PyObject *m2) { - int vec_size; - - MatrixObject *mat1 = NULL, *mat2 = NULL; - - if (MatrixObject_Check(m1)) { - mat1 = (MatrixObject *)m1; - if (BaseMath_ReadCallback(mat1) == -1) { - return NULL; - } - } - if (MatrixObject_Check(m2)) { - mat2 = (MatrixObject *)m2; - if (BaseMath_ReadCallback(mat2) == -1) { - return NULL; - } - } - - if (mat1 && mat2) { - /* MATRIX @ MATRIX */ - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - - int col, row, item; - - if (mat1->num_col != mat2->num_row) { - PyErr_SetString(PyExc_ValueError, - "matrix1 * matrix2: matrix1 number of columns " - "and the matrix2 number of rows must be the same"); - return NULL; - } - - for (col = 0; col < mat2->num_col; col++) { - for (row = 0; row < mat1->num_row; row++) { - double dot = 0.0f; - for (item = 0; item < mat1->num_col; item++) { - dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); - } - mat[(col * mat1->num_row) + row] = (float)dot; - } - } - - return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); - } - else if (mat1) { - /* MATRIX @ VECTOR */ - if (VectorObject_Check(m2)) { - VectorObject *vec2 = (VectorObject *)m2; - float tvec[MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback(vec2) == -1) { - return NULL; - } - if (column_vector_multiplication(tvec, vec2, mat1) == -1) { - return NULL; - } - - if (mat1->num_col == 4 && vec2->size == 3) { - vec_size = 3; - } - else { - vec_size = mat1->num_row; - } - - return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2)); - } - } - - PyErr_Format(PyExc_TypeError, - "Matrix multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); - return NULL; + int vec_size; + + MatrixObject *mat1 = NULL, *mat2 = NULL; + + if (MatrixObject_Check(m1)) { + mat1 = (MatrixObject *)m1; + if (BaseMath_ReadCallback(mat1) == -1) { + return NULL; + } + } + if (MatrixObject_Check(m2)) { + mat2 = (MatrixObject *)m2; + if (BaseMath_ReadCallback(mat2) == -1) { + return NULL; + } + } + + if (mat1 && mat2) { + /* MATRIX @ MATRIX */ + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + + int col, row, item; + + if (mat1->num_col != mat2->num_row) { + PyErr_SetString(PyExc_ValueError, + "matrix1 * matrix2: matrix1 number of columns " + "and the matrix2 number of rows must be the same"); + return NULL; + } + + for (col = 0; col < mat2->num_col; col++) { + for (row = 0; row < mat1->num_row; row++) { + double dot = 0.0f; + for (item = 0; item < mat1->num_col; item++) { + dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); + } + mat[(col * mat1->num_row) + row] = (float)dot; + } + } + + return Matrix_CreatePyObject(mat, mat2->num_col, mat1->num_row, Py_TYPE(mat1)); + } + else if (mat1) { + /* MATRIX @ VECTOR */ + if (VectorObject_Check(m2)) { + VectorObject *vec2 = (VectorObject *)m2; + float tvec[MATRIX_MAX_DIM]; + if (BaseMath_ReadCallback(vec2) == -1) { + return NULL; + } + if (column_vector_multiplication(tvec, vec2, mat1) == -1) { + return NULL; + } + + if (mat1->num_col == 4 && vec2->size == 3) { + vec_size = 3; + } + else { + vec_size = mat1->num_row; + } + + return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(m2)); + } + } + + PyErr_Format(PyExc_TypeError, + "Matrix multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(m1)->tp_name, + Py_TYPE(m2)->tp_name); + return NULL; } /*------------------------obj @= obj------------------------------ * inplace matrix multiplication */ static PyObject *Matrix_imatmul(PyObject *m1, PyObject *m2) { - MatrixObject *mat1 = NULL, *mat2 = NULL; - - if (MatrixObject_Check(m1)) { - mat1 = (MatrixObject *)m1; - if (BaseMath_ReadCallback(mat1) == -1) { - return NULL; - } - } - if (MatrixObject_Check(m2)) { - mat2 = (MatrixObject *)m2; - if (BaseMath_ReadCallback(mat2) == -1) { - return NULL; - } - } - - if (mat1 && mat2) { - /* MATRIX @= MATRIX */ - float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; - int col, row, item; - - if (mat1->num_col != mat2->num_row) { - PyErr_SetString(PyExc_ValueError, - "matrix1 * matrix2: matrix1 number of columns " - "and the matrix2 number of rows must be the same"); - return NULL; - } - - for (col = 0; col < mat2->num_col; col++) { - for (row = 0; row < mat1->num_row; row++) { - double dot = 0.0f; - for (item = 0; item < mat1->num_col; item++) { - dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); - } - /* store in new matrix as overwriting original at this point will cause - * subsequent iterations to use incorrect values */ - mat[(col * mat1->num_row) + row] = (float)dot; - } - } - - /* copy matrix back */ - memcpy(mat1->matrix, mat, (mat1->num_row * mat1->num_col) * sizeof(float)); - } - else { - PyErr_Format(PyExc_TypeError, - "Inplace matrix multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); - return NULL; - } - - (void)BaseMath_WriteCallback(mat1); - Py_INCREF(m1); - return m1; + MatrixObject *mat1 = NULL, *mat2 = NULL; + + if (MatrixObject_Check(m1)) { + mat1 = (MatrixObject *)m1; + if (BaseMath_ReadCallback(mat1) == -1) { + return NULL; + } + } + if (MatrixObject_Check(m2)) { + mat2 = (MatrixObject *)m2; + if (BaseMath_ReadCallback(mat2) == -1) { + return NULL; + } + } + + if (mat1 && mat2) { + /* MATRIX @= MATRIX */ + float mat[MATRIX_MAX_DIM * MATRIX_MAX_DIM]; + int col, row, item; + + if (mat1->num_col != mat2->num_row) { + PyErr_SetString(PyExc_ValueError, + "matrix1 * matrix2: matrix1 number of columns " + "and the matrix2 number of rows must be the same"); + return NULL; + } + + for (col = 0; col < mat2->num_col; col++) { + for (row = 0; row < mat1->num_row; row++) { + double dot = 0.0f; + for (item = 0; item < mat1->num_col; item++) { + dot += (double)(MATRIX_ITEM(mat1, row, item) * MATRIX_ITEM(mat2, item, col)); + } + /* store in new matrix as overwriting original at this point will cause + * subsequent iterations to use incorrect values */ + mat[(col * mat1->num_row) + row] = (float)dot; + } + } + + /* copy matrix back */ + memcpy(mat1->matrix, mat, (mat1->num_row * mat1->num_col) * sizeof(float)); + } + else { + PyErr_Format(PyExc_TypeError, + "Inplace matrix multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(m1)->tp_name, + Py_TYPE(m2)->tp_name); + return NULL; + } + + (void)BaseMath_WriteCallback(mat1); + Py_INCREF(m1); + return m1; } /*-----------------PROTOCOL DECLARATIONS--------------------------*/ static PySequenceMethods Matrix_SeqMethods = { - (lenfunc) Matrix_len, /* sq_length */ - (binaryfunc) NULL, /* sq_concat */ - (ssizeargfunc) NULL, /* sq_repeat */ - (ssizeargfunc) Matrix_item_row, /* sq_item */ - (ssizessizeargfunc) NULL, /* sq_slice, deprecated */ - (ssizeobjargproc) Matrix_ass_item_row, /* sq_ass_item */ - (ssizessizeobjargproc) NULL, /* sq_ass_slice, deprecated */ - (objobjproc) NULL, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)Matrix_len, /* sq_length */ + (binaryfunc)NULL, /* sq_concat */ + (ssizeargfunc)NULL, /* sq_repeat */ + (ssizeargfunc)Matrix_item_row, /* sq_item */ + (ssizessizeargfunc)NULL, /* sq_slice, deprecated */ + (ssizeobjargproc)Matrix_ass_item_row, /* sq_ass_item */ + (ssizessizeobjargproc)NULL, /* sq_ass_slice, deprecated */ + (objobjproc)NULL, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; - static PyObject *Matrix_subscript(MatrixObject *self, PyObject *item) { - if (PyIndex_Check(item)) { - Py_ssize_t i; - i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - if (i < 0) { - i += self->num_row; - } - return Matrix_item_row(self, i); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyTuple_New(0); - } - else if (step == 1) { - return Matrix_slice(self, start, stop); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with matrices"); - return NULL; - } - } - else { - PyErr_Format(PyExc_TypeError, - "matrix indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return NULL; - } + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + if (i < 0) { + i += self->num_row; + } + return Matrix_item_row(self, i); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) { + return NULL; + } + + if (slicelength <= 0) { + return PyTuple_New(0); + } + else if (step == 1) { + return Matrix_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with matrices"); + return NULL; + } + } + else { + PyErr_Format( + PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return NULL; + } } static int Matrix_ass_subscript(MatrixObject *self, PyObject *item, PyObject *value) { - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return -1; - } - if (i < 0) { - i += self->num_row; - } - return Matrix_ass_item_row(self, i, value); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) { - return -1; - } - - if (step == 1) { - return Matrix_ass_slice(self, start, stop, value); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with matrices"); - return -1; - } - } - else { - PyErr_Format(PyExc_TypeError, - "matrix indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return -1; - } + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return -1; + } + if (i < 0) { + i += self->num_row; + } + return Matrix_ass_item_row(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, self->num_row, &start, &stop, &step, &slicelength) < 0) { + return -1; + } + + if (step == 1) { + return Matrix_ass_slice(self, start, stop, value); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with matrices"); + return -1; + } + } + else { + PyErr_Format( + PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return -1; + } } static PyMappingMethods Matrix_AsMapping = { - (lenfunc)Matrix_len, - (binaryfunc)Matrix_subscript, - (objobjargproc)Matrix_ass_subscript, + (lenfunc)Matrix_len, + (binaryfunc)Matrix_subscript, + (objobjargproc)Matrix_ass_subscript, }; - static PyNumberMethods Matrix_NumMethods = { - (binaryfunc) Matrix_add, /*nb_add*/ - (binaryfunc) Matrix_sub, /*nb_subtract*/ - (binaryfunc) Matrix_mul, /*nb_multiply*/ - NULL, /*nb_remainder*/ - NULL, /*nb_divmod*/ - NULL, /*nb_power*/ - (unaryfunc) 0, /*nb_negative*/ - (unaryfunc) 0, /*tp_positive*/ - (unaryfunc) 0, /*tp_absolute*/ - (inquiry) 0, /*tp_bool*/ - (unaryfunc) Matrix_inverted_noargs, /*nb_invert*/ - NULL, /*nb_lshift*/ - (binaryfunc)0, /*nb_rshift*/ - NULL, /*nb_and*/ - NULL, /*nb_xor*/ - NULL, /*nb_or*/ - NULL, /*nb_int*/ - NULL, /*nb_reserved*/ - NULL, /*nb_float*/ - NULL, /* nb_inplace_add */ - NULL, /* nb_inplace_subtract */ - (binaryfunc) Matrix_imul, /* nb_inplace_multiply */ - NULL, /* nb_inplace_remainder */ - NULL, /* nb_inplace_power */ - NULL, /* nb_inplace_lshift */ - NULL, /* nb_inplace_rshift */ - NULL, /* nb_inplace_and */ - NULL, /* nb_inplace_xor */ - NULL, /* nb_inplace_or */ - NULL, /* nb_floor_divide */ - NULL, /* nb_true_divide */ - NULL, /* nb_inplace_floor_divide */ - NULL, /* nb_inplace_true_divide */ - NULL, /* nb_index */ - (binaryfunc) Matrix_matmul, /* nb_matrix_multiply */ - (binaryfunc) Matrix_imatmul, /* nb_inplace_matrix_multiply */ + (binaryfunc)Matrix_add, /*nb_add*/ + (binaryfunc)Matrix_sub, /*nb_subtract*/ + (binaryfunc)Matrix_mul, /*nb_multiply*/ + NULL, /*nb_remainder*/ + NULL, /*nb_divmod*/ + NULL, /*nb_power*/ + (unaryfunc)0, /*nb_negative*/ + (unaryfunc)0, /*tp_positive*/ + (unaryfunc)0, /*tp_absolute*/ + (inquiry)0, /*tp_bool*/ + (unaryfunc)Matrix_inverted_noargs, /*nb_invert*/ + NULL, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + NULL, /*nb_and*/ + NULL, /*nb_xor*/ + NULL, /*nb_or*/ + NULL, /*nb_int*/ + NULL, /*nb_reserved*/ + NULL, /*nb_float*/ + NULL, /* nb_inplace_add */ + NULL, /* nb_inplace_subtract */ + (binaryfunc)Matrix_imul, /* nb_inplace_multiply */ + NULL, /* nb_inplace_remainder */ + NULL, /* nb_inplace_power */ + NULL, /* nb_inplace_lshift */ + NULL, /* nb_inplace_rshift */ + NULL, /* nb_inplace_and */ + NULL, /* nb_inplace_xor */ + NULL, /* nb_inplace_or */ + NULL, /* nb_floor_divide */ + NULL, /* nb_true_divide */ + NULL, /* nb_inplace_floor_divide */ + NULL, /* nb_inplace_true_divide */ + NULL, /* nb_index */ + (binaryfunc)Matrix_matmul, /* nb_matrix_multiply */ + (binaryfunc)Matrix_imatmul, /* nb_inplace_matrix_multiply */ }; -PyDoc_STRVAR(Matrix_translation_doc, -"The translation component of the matrix.\n\n:type: Vector" -); +PyDoc_STRVAR(Matrix_translation_doc, "The translation component of the matrix.\n\n:type: Vector"); static PyObject *Matrix_translation_get(MatrixObject *self, void *UNUSED(closure)) { - PyObject *ret; + PyObject *ret; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - /*must be 4x4 square matrix*/ - if (self->num_row != 4 || self->num_col != 4) { - PyErr_SetString(PyExc_AttributeError, - "Matrix.translation: " - "inappropriate matrix size, must be 4x4"); - return NULL; - } + /*must be 4x4 square matrix*/ + if (self->num_row != 4 || self->num_col != 4) { + PyErr_SetString(PyExc_AttributeError, + "Matrix.translation: " + "inappropriate matrix size, must be 4x4"); + return NULL; + } - ret = (PyObject *)Vector_CreatePyObject_cb((PyObject *)self, 3, mathutils_matrix_translation_cb_index, 3); + ret = (PyObject *)Vector_CreatePyObject_cb( + (PyObject *)self, 3, mathutils_matrix_translation_cb_index, 3); - return ret; + return ret; } static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNUSED(closure)) { - float tvec[3]; + float tvec[3]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - /*must be 4x4 square matrix*/ - if (self->num_row != 4 || self->num_col != 4) { - PyErr_SetString(PyExc_AttributeError, - "Matrix.translation: " - "inappropriate matrix size, must be 4x4"); - return -1; - } + /*must be 4x4 square matrix*/ + if (self->num_row != 4 || self->num_col != 4) { + PyErr_SetString(PyExc_AttributeError, + "Matrix.translation: " + "inappropriate matrix size, must be 4x4"); + return -1; + } - if ((mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation")) == -1) { - return -1; - } + if ((mathutils_array_parse(tvec, 3, 3, value, "Matrix.translation")) == -1) { + return -1; + } - copy_v3_v3(((float (*)[4])self->matrix)[3], tvec); + copy_v3_v3(((float(*)[4])self->matrix)[3], tvec); - (void)BaseMath_WriteCallback(self); + (void)BaseMath_WriteCallback(self); - return 0; + return 0; } PyDoc_STRVAR(Matrix_row_doc, -"Access the matrix by rows (default), (read-only).\n\n:type: Matrix Access" -); + "Access the matrix by rows (default), (read-only).\n\n:type: Matrix Access"); static PyObject *Matrix_row_get(MatrixObject *self, void *UNUSED(closure)) { - return MatrixAccess_CreatePyObject(self, MAT_ACCESS_ROW); + return MatrixAccess_CreatePyObject(self, MAT_ACCESS_ROW); } -PyDoc_STRVAR(Matrix_col_doc, -"Access the matrix by columns, 3x3 and 4x4 only, (read-only).\n\n:type: Matrix Access" -); +PyDoc_STRVAR( + Matrix_col_doc, + "Access the matrix by columns, 3x3 and 4x4 only, (read-only).\n\n:type: Matrix Access"); static PyObject *Matrix_col_get(MatrixObject *self, void *UNUSED(closure)) { - return MatrixAccess_CreatePyObject(self, MAT_ACCESS_COL); + return MatrixAccess_CreatePyObject(self, MAT_ACCESS_COL); } PyDoc_STRVAR(Matrix_median_scale_doc, -"The average scale applied to each axis (read-only).\n\n:type: float" -); + "The average scale applied to each axis (read-only).\n\n:type: float"); static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closure)) { - float mat[3][3]; + float mat[3][3]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - /*must be 3-4 cols, 3-4 rows, square matrix*/ - if ((self->num_row < 3) || (self->num_col < 3)) { - PyErr_SetString(PyExc_AttributeError, - "Matrix.median_scale: " - "inappropriate matrix size, 3x3 minimum"); - return NULL; - } + /*must be 3-4 cols, 3-4 rows, square matrix*/ + if ((self->num_row < 3) || (self->num_col < 3)) { + PyErr_SetString(PyExc_AttributeError, + "Matrix.median_scale: " + "inappropriate matrix size, 3x3 minimum"); + return NULL; + } - matrix_as_3x3(mat, self); + matrix_as_3x3(mat, self); - return PyFloat_FromDouble(mat3_to_scale(mat)); + return PyFloat_FromDouble(mat3_to_scale(mat)); } PyDoc_STRVAR(Matrix_is_negative_doc, -"True if this matrix results in a negative scale, 3x3 and 4x4 only, (read-only).\n\n:type: bool" -); + "True if this matrix results in a negative scale, 3x3 and 4x4 only, " + "(read-only).\n\n:type: bool"); static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure)) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - /*must be 3-4 cols, 3-4 rows, square matrix*/ - if (self->num_row == 4 && self->num_col == 4) { - return PyBool_FromLong(is_negative_m4((float (*)[4])self->matrix)); - } - else if (self->num_row == 3 && self->num_col == 3) { - return PyBool_FromLong(is_negative_m3((float (*)[3])self->matrix)); - } - else { - PyErr_SetString(PyExc_AttributeError, - "Matrix.is_negative: " - "inappropriate matrix size - expects 3x3 or 4x4 matrix"); - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + /*must be 3-4 cols, 3-4 rows, square matrix*/ + if (self->num_row == 4 && self->num_col == 4) { + return PyBool_FromLong(is_negative_m4((float(*)[4])self->matrix)); + } + else if (self->num_row == 3 && self->num_col == 3) { + return PyBool_FromLong(is_negative_m3((float(*)[3])self->matrix)); + } + else { + PyErr_SetString(PyExc_AttributeError, + "Matrix.is_negative: " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); + return NULL; + } } PyDoc_STRVAR(Matrix_is_orthogonal_doc, -"True if this matrix is orthogonal, 3x3 and 4x4 only, (read-only).\n\n:type: bool" -); + "True if this matrix is orthogonal, 3x3 and 4x4 only, (read-only).\n\n:type: bool"); static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closure)) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - /*must be 3-4 cols, 3-4 rows, square matrix*/ - if (self->num_row == 4 && self->num_col == 4) { - return PyBool_FromLong(is_orthonormal_m4((float (*)[4])self->matrix)); - } - else if (self->num_row == 3 && self->num_col == 3) { - return PyBool_FromLong(is_orthonormal_m3((float (*)[3])self->matrix)); - } - else { - PyErr_SetString(PyExc_AttributeError, - "Matrix.is_orthogonal: " - "inappropriate matrix size - expects 3x3 or 4x4 matrix"); - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + /*must be 3-4 cols, 3-4 rows, square matrix*/ + if (self->num_row == 4 && self->num_col == 4) { + return PyBool_FromLong(is_orthonormal_m4((float(*)[4])self->matrix)); + } + else if (self->num_row == 3 && self->num_col == 3) { + return PyBool_FromLong(is_orthonormal_m3((float(*)[3])self->matrix)); + } + else { + PyErr_SetString(PyExc_AttributeError, + "Matrix.is_orthogonal: " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); + return NULL; + } } PyDoc_STRVAR(Matrix_is_orthogonal_axis_vectors_doc, -"True if this matrix has got orthogonal axis vectors, 3x3 and 4x4 only, (read-only).\n\n:type: bool" -); + "True if this matrix has got orthogonal axis vectors, 3x3 and 4x4 only, " + "(read-only).\n\n:type: bool"); static PyObject *Matrix_is_orthogonal_axis_vectors_get(MatrixObject *self, void *UNUSED(closure)) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - /*must be 3-4 cols, 3-4 rows, square matrix*/ - if (self->num_row == 4 && self->num_col == 4) { - return PyBool_FromLong(is_orthogonal_m4((float (*)[4])self->matrix)); - } - else if (self->num_row == 3 && self->num_col == 3) { - return PyBool_FromLong(is_orthogonal_m3((float (*)[3])self->matrix)); - } - else { - PyErr_SetString(PyExc_AttributeError, - "Matrix.is_orthogonal_axis_vectors: " - "inappropriate matrix size - expects 3x3 or 4x4 matrix"); - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + /*must be 3-4 cols, 3-4 rows, square matrix*/ + if (self->num_row == 4 && self->num_col == 4) { + return PyBool_FromLong(is_orthogonal_m4((float(*)[4])self->matrix)); + } + else if (self->num_row == 3 && self->num_col == 3) { + return PyBool_FromLong(is_orthogonal_m3((float(*)[3])self->matrix)); + } + else { + PyErr_SetString(PyExc_AttributeError, + "Matrix.is_orthogonal_axis_vectors: " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); + return NULL; + } } /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Matrix_getseters[] = { - {(char *)"median_scale", (getter)Matrix_median_scale_get, (setter)NULL, Matrix_median_scale_doc, NULL}, - {(char *)"translation", (getter)Matrix_translation_get, (setter)Matrix_translation_set, Matrix_translation_doc, NULL}, - {(char *)"row", (getter)Matrix_row_get, (setter)NULL, Matrix_row_doc, NULL}, - {(char *)"col", (getter)Matrix_col_get, (setter)NULL, Matrix_col_doc, NULL}, - {(char *)"is_negative", (getter)Matrix_is_negative_get, (setter)NULL, Matrix_is_negative_doc, NULL}, - {(char *)"is_orthogonal", (getter)Matrix_is_orthogonal_get, (setter)NULL, Matrix_is_orthogonal_doc, NULL}, - {(char *)"is_orthogonal_axis_vectors", (getter)Matrix_is_orthogonal_axis_vectors_get, (setter)NULL, Matrix_is_orthogonal_axis_vectors_doc, NULL}, - {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL}, - {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL}, - {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"median_scale", + (getter)Matrix_median_scale_get, + (setter)NULL, + Matrix_median_scale_doc, + NULL}, + {(char *)"translation", + (getter)Matrix_translation_get, + (setter)Matrix_translation_set, + Matrix_translation_doc, + NULL}, + {(char *)"row", (getter)Matrix_row_get, (setter)NULL, Matrix_row_doc, NULL}, + {(char *)"col", (getter)Matrix_col_get, (setter)NULL, Matrix_col_doc, NULL}, + {(char *)"is_negative", + (getter)Matrix_is_negative_get, + (setter)NULL, + Matrix_is_negative_doc, + NULL}, + {(char *)"is_orthogonal", + (getter)Matrix_is_orthogonal_get, + (setter)NULL, + Matrix_is_orthogonal_doc, + NULL}, + {(char *)"is_orthogonal_axis_vectors", + (getter)Matrix_is_orthogonal_axis_vectors_get, + (setter)NULL, + Matrix_is_orthogonal_axis_vectors_doc, + NULL}, + {(char *)"is_wrapped", + (getter)BaseMathObject_is_wrapped_get, + (setter)NULL, + BaseMathObject_is_wrapped_doc, + NULL}, + {(char *)"is_frozen", + (getter)BaseMathObject_is_frozen_get, + (setter)NULL, + BaseMathObject_is_frozen_doc, + NULL}, + {(char *)"owner", + (getter)BaseMathObject_owner_get, + (setter)NULL, + BaseMathObject_owner_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; /*-----------------------METHOD DEFINITIONS ----------------------*/ static struct PyMethodDef Matrix_methods[] = { - /* derived values */ - {"determinant", (PyCFunction) Matrix_determinant, METH_NOARGS, Matrix_determinant_doc}, - {"decompose", (PyCFunction) Matrix_decompose, METH_NOARGS, Matrix_decompose_doc}, - - /* in place only */ - {"zero", (PyCFunction) Matrix_zero, METH_NOARGS, Matrix_zero_doc}, - {"identity", (PyCFunction) Matrix_identity, METH_NOARGS, Matrix_identity_doc}, - - /* operate on original or copy */ - {"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc}, - {"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc}, - {"normalize", (PyCFunction) Matrix_normalize, METH_NOARGS, Matrix_normalize_doc}, - {"normalized", (PyCFunction) Matrix_normalized, METH_NOARGS, Matrix_normalized_doc}, - {"invert", (PyCFunction) Matrix_invert, METH_VARARGS, Matrix_invert_doc}, - {"inverted", (PyCFunction) Matrix_inverted, METH_VARARGS, Matrix_inverted_doc}, - {"invert_safe", (PyCFunction) Matrix_invert_safe, METH_NOARGS, Matrix_invert_safe_doc}, - {"inverted_safe", (PyCFunction) Matrix_inverted_safe, METH_NOARGS, Matrix_inverted_safe_doc}, - {"adjugate", (PyCFunction) Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc}, - {"adjugated", (PyCFunction) Matrix_adjugated, METH_NOARGS, Matrix_adjugated_doc}, - {"to_3x3", (PyCFunction) Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc}, - /* TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc}, */ - {"to_4x4", (PyCFunction) Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, - {"resize_4x4", (PyCFunction) Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc}, - {"rotate", (PyCFunction) Matrix_rotate, METH_O, Matrix_rotate_doc}, - - /* return converted representation */ - {"to_euler", (PyCFunction) Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc}, - {"to_quaternion", (PyCFunction) Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc}, - {"to_scale", (PyCFunction) Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc}, - {"to_translation", (PyCFunction) Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc}, - - /* operation between 2 or more types */ - {"lerp", (PyCFunction) Matrix_lerp, METH_VARARGS, Matrix_lerp_doc}, - {"copy", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, - {"__copy__", (PyCFunction) Matrix_copy, METH_NOARGS, Matrix_copy_doc}, - {"__deepcopy__", (PyCFunction) Matrix_deepcopy, METH_VARARGS, Matrix_copy_doc}, - - /* base-math methods */ - {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, - - /* class methods */ - {"Identity", (PyCFunction) C_Matrix_Identity, METH_VARARGS | METH_CLASS, C_Matrix_Identity_doc}, - {"Rotation", (PyCFunction) C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc}, - {"Scale", (PyCFunction) C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc}, - {"Shear", (PyCFunction) C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc}, - {"Translation", (PyCFunction) C_Matrix_Translation, METH_O | METH_CLASS, C_Matrix_Translation_doc}, - {"OrthoProjection", (PyCFunction) C_Matrix_OrthoProjection, METH_VARARGS | METH_CLASS, C_Matrix_OrthoProjection_doc}, - {NULL, NULL, 0, NULL}, + /* derived values */ + {"determinant", (PyCFunction)Matrix_determinant, METH_NOARGS, Matrix_determinant_doc}, + {"decompose", (PyCFunction)Matrix_decompose, METH_NOARGS, Matrix_decompose_doc}, + + /* in place only */ + {"zero", (PyCFunction)Matrix_zero, METH_NOARGS, Matrix_zero_doc}, + {"identity", (PyCFunction)Matrix_identity, METH_NOARGS, Matrix_identity_doc}, + + /* operate on original or copy */ + {"transpose", (PyCFunction)Matrix_transpose, METH_NOARGS, Matrix_transpose_doc}, + {"transposed", (PyCFunction)Matrix_transposed, METH_NOARGS, Matrix_transposed_doc}, + {"normalize", (PyCFunction)Matrix_normalize, METH_NOARGS, Matrix_normalize_doc}, + {"normalized", (PyCFunction)Matrix_normalized, METH_NOARGS, Matrix_normalized_doc}, + {"invert", (PyCFunction)Matrix_invert, METH_VARARGS, Matrix_invert_doc}, + {"inverted", (PyCFunction)Matrix_inverted, METH_VARARGS, Matrix_inverted_doc}, + {"invert_safe", (PyCFunction)Matrix_invert_safe, METH_NOARGS, Matrix_invert_safe_doc}, + {"inverted_safe", (PyCFunction)Matrix_inverted_safe, METH_NOARGS, Matrix_inverted_safe_doc}, + {"adjugate", (PyCFunction)Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc}, + {"adjugated", (PyCFunction)Matrix_adjugated, METH_NOARGS, Matrix_adjugated_doc}, + {"to_3x3", (PyCFunction)Matrix_to_3x3, METH_NOARGS, Matrix_to_3x3_doc}, + /* TODO. {"resize_3x3", (PyCFunction) Matrix_resize3x3, METH_NOARGS, Matrix_resize3x3_doc}, */ + {"to_4x4", (PyCFunction)Matrix_to_4x4, METH_NOARGS, Matrix_to_4x4_doc}, + {"resize_4x4", (PyCFunction)Matrix_resize_4x4, METH_NOARGS, Matrix_resize_4x4_doc}, + {"rotate", (PyCFunction)Matrix_rotate, METH_O, Matrix_rotate_doc}, + + /* return converted representation */ + {"to_euler", (PyCFunction)Matrix_to_euler, METH_VARARGS, Matrix_to_euler_doc}, + {"to_quaternion", (PyCFunction)Matrix_to_quaternion, METH_NOARGS, Matrix_to_quaternion_doc}, + {"to_scale", (PyCFunction)Matrix_to_scale, METH_NOARGS, Matrix_to_scale_doc}, + {"to_translation", (PyCFunction)Matrix_to_translation, METH_NOARGS, Matrix_to_translation_doc}, + + /* operation between 2 or more types */ + {"lerp", (PyCFunction)Matrix_lerp, METH_VARARGS, Matrix_lerp_doc}, + {"copy", (PyCFunction)Matrix_copy, METH_NOARGS, Matrix_copy_doc}, + {"__copy__", (PyCFunction)Matrix_copy, METH_NOARGS, Matrix_copy_doc}, + {"__deepcopy__", (PyCFunction)Matrix_deepcopy, METH_VARARGS, Matrix_copy_doc}, + + /* base-math methods */ + {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, + + /* class methods */ + {"Identity", (PyCFunction)C_Matrix_Identity, METH_VARARGS | METH_CLASS, C_Matrix_Identity_doc}, + {"Rotation", (PyCFunction)C_Matrix_Rotation, METH_VARARGS | METH_CLASS, C_Matrix_Rotation_doc}, + {"Scale", (PyCFunction)C_Matrix_Scale, METH_VARARGS | METH_CLASS, C_Matrix_Scale_doc}, + {"Shear", (PyCFunction)C_Matrix_Shear, METH_VARARGS | METH_CLASS, C_Matrix_Shear_doc}, + {"Translation", + (PyCFunction)C_Matrix_Translation, + METH_O | METH_CLASS, + C_Matrix_Translation_doc}, + {"OrthoProjection", + (PyCFunction)C_Matrix_OrthoProjection, + METH_VARARGS | METH_CLASS, + C_Matrix_OrthoProjection_doc}, + {NULL, NULL, 0, NULL}, }; /*------------------PY_OBECT DEFINITION--------------------------*/ -PyDoc_STRVAR(matrix_doc, -".. class:: Matrix([rows])\n" -"\n" -" This object gives access to Matrices in Blender, supporting square and rectangular\n" -" matrices from 2x2 up to 4x4.\n" -"\n" -" :param rows: Sequence of rows.\n" -" When omitted, a 4x4 identity matrix is constructed.\n" -" :type rows: 2d number sequence\n" -); +PyDoc_STRVAR( + matrix_doc, + ".. class:: Matrix([rows])\n" + "\n" + " This object gives access to Matrices in Blender, supporting square and rectangular\n" + " matrices from 2x2 up to 4x4.\n" + "\n" + " :param rows: Sequence of rows.\n" + " When omitted, a 4x4 identity matrix is constructed.\n" + " :type rows: 2d number sequence\n"); PyTypeObject matrix_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "Matrix", /*tp_name*/ - sizeof(MatrixObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)BaseMathObject_dealloc, /*tp_dealloc*/ - NULL, /*tp_print*/ - NULL, /*tp_getattr*/ - NULL, /*tp_setattr*/ - NULL, /*tp_compare*/ - (reprfunc) Matrix_repr, /*tp_repr*/ - &Matrix_NumMethods, /*tp_as_number*/ - &Matrix_SeqMethods, /*tp_as_sequence*/ - &Matrix_AsMapping, /*tp_as_mapping*/ - (hashfunc)Matrix_hash, /*tp_hash*/ - NULL, /*tp_call*/ + PyVarObject_HEAD_INIT(NULL, 0) "Matrix", /*tp_name*/ + sizeof(MatrixObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)BaseMathObject_dealloc, /*tp_dealloc*/ + NULL, /*tp_print*/ + NULL, /*tp_getattr*/ + NULL, /*tp_setattr*/ + NULL, /*tp_compare*/ + (reprfunc)Matrix_repr, /*tp_repr*/ + &Matrix_NumMethods, /*tp_as_number*/ + &Matrix_SeqMethods, /*tp_as_sequence*/ + &Matrix_AsMapping, /*tp_as_mapping*/ + (hashfunc)Matrix_hash, /*tp_hash*/ + NULL, /*tp_call*/ #ifndef MATH_STANDALONE - (reprfunc) Matrix_str, /*tp_str*/ + (reprfunc)Matrix_str, /*tp_str*/ #else - NULL, /*tp_str*/ + NULL, /*tp_str*/ #endif - NULL, /*tp_getattro*/ - NULL, /*tp_setattro*/ - NULL, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - matrix_doc, /*tp_doc*/ - (traverseproc)BaseMathObject_traverse, /* tp_traverse */ - (inquiry)BaseMathObject_clear, /*tp_clear*/ - (richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - NULL, /*tp_iter*/ - NULL, /*tp_iternext*/ - Matrix_methods, /*tp_methods*/ - NULL, /*tp_members*/ - Matrix_getseters, /*tp_getset*/ - NULL, /*tp_base*/ - NULL, /*tp_dict*/ - NULL, /*tp_descr_get*/ - NULL, /*tp_descr_set*/ - 0, /*tp_dictoffset*/ - NULL, /*tp_init*/ - NULL, /*tp_alloc*/ - Matrix_new, /*tp_new*/ - NULL, /*tp_free*/ - NULL, /*tp_is_gc*/ - NULL, /*tp_bases*/ - NULL, /*tp_mro*/ - NULL, /*tp_cache*/ - NULL, /*tp_subclasses*/ - NULL, /*tp_weaklist*/ - NULL, /*tp_del*/ + NULL, /*tp_getattro*/ + NULL, /*tp_setattro*/ + NULL, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + matrix_doc, /*tp_doc*/ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /*tp_clear*/ + (richcmpfunc)Matrix_richcmpr, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + NULL, /*tp_iter*/ + NULL, /*tp_iternext*/ + Matrix_methods, /*tp_methods*/ + NULL, /*tp_members*/ + Matrix_getseters, /*tp_getset*/ + NULL, /*tp_base*/ + NULL, /*tp_dict*/ + NULL, /*tp_descr_get*/ + NULL, /*tp_descr_set*/ + 0, /*tp_dictoffset*/ + NULL, /*tp_init*/ + NULL, /*tp_alloc*/ + Matrix_new, /*tp_new*/ + NULL, /*tp_free*/ + NULL, /*tp_is_gc*/ + NULL, /*tp_bases*/ + NULL, /*tp_mro*/ + NULL, /*tp_cache*/ + NULL, /*tp_subclasses*/ + NULL, /*tp_weaklist*/ + NULL, /*tp_del*/ }; -PyObject *Matrix_CreatePyObject( - const float *mat, - const unsigned short num_col, const unsigned short num_row, - PyTypeObject *base_type) -{ - MatrixObject *self; - float *mat_alloc; - - /* matrix objects can be any 2-4row x 2-4col matrix */ - if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) { - PyErr_SetString(PyExc_RuntimeError, - "Matrix(): " - "row and column sizes must be between 2 and 4"); - return NULL; - } - - mat_alloc = PyMem_Malloc(num_col * num_row * sizeof(float)); - if (UNLIKELY(mat_alloc == NULL)) { - PyErr_SetString(PyExc_MemoryError, - "Matrix(): " - "problem allocating data"); - return NULL; - } - - self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type); - if (self) { - self->matrix = mat_alloc; - self->num_col = num_col; - self->num_row = num_row; - - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; - - if (mat) { /*if a float array passed*/ - memcpy(self->matrix, mat, num_col * num_row * sizeof(float)); - } - else if (num_col == num_row) { - /* or if no arguments are passed return identity matrix for square matrices */ - matrix_identity_internal(self); - } - else { - /* otherwise zero everything */ - memset(self->matrix, 0, num_col * num_row * sizeof(float)); - } - self->flag = BASE_MATH_FLAG_DEFAULT; - } - else { - PyMem_Free(mat_alloc); - } - - return (PyObject *)self; -} - -PyObject *Matrix_CreatePyObject_wrap( - float *mat, - const unsigned short num_col, const unsigned short num_row, - PyTypeObject *base_type) -{ - MatrixObject *self; - - /* matrix objects can be any 2-4row x 2-4col matrix */ - if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) { - PyErr_SetString(PyExc_RuntimeError, - "Matrix(): " - "row and column sizes must be between 2 and 4"); - return NULL; - } - - self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type); - if (self) { - self->num_col = num_col; - self->num_row = num_row; - - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; - - self->matrix = mat; - self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; - } - return (PyObject *) self; +PyObject *Matrix_CreatePyObject(const float *mat, + const unsigned short num_col, + const unsigned short num_row, + PyTypeObject *base_type) +{ + MatrixObject *self; + float *mat_alloc; + + /* matrix objects can be any 2-4row x 2-4col matrix */ + if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) { + PyErr_SetString(PyExc_RuntimeError, + "Matrix(): " + "row and column sizes must be between 2 and 4"); + return NULL; + } + + mat_alloc = PyMem_Malloc(num_col * num_row * sizeof(float)); + if (UNLIKELY(mat_alloc == NULL)) { + PyErr_SetString(PyExc_MemoryError, + "Matrix(): " + "problem allocating data"); + return NULL; + } + + self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type); + if (self) { + self->matrix = mat_alloc; + self->num_col = num_col; + self->num_row = num_row; + + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; + + if (mat) { /*if a float array passed*/ + memcpy(self->matrix, mat, num_col * num_row * sizeof(float)); + } + else if (num_col == num_row) { + /* or if no arguments are passed return identity matrix for square matrices */ + matrix_identity_internal(self); + } + else { + /* otherwise zero everything */ + memset(self->matrix, 0, num_col * num_row * sizeof(float)); + } + self->flag = BASE_MATH_FLAG_DEFAULT; + } + else { + PyMem_Free(mat_alloc); + } + + return (PyObject *)self; +} + +PyObject *Matrix_CreatePyObject_wrap(float *mat, + const unsigned short num_col, + const unsigned short num_row, + PyTypeObject *base_type) +{ + MatrixObject *self; + + /* matrix objects can be any 2-4row x 2-4col matrix */ + if (num_col < 2 || num_col > 4 || num_row < 2 || num_row > 4) { + PyErr_SetString(PyExc_RuntimeError, + "Matrix(): " + "row and column sizes must be between 2 and 4"); + return NULL; + } + + self = BASE_MATH_NEW(MatrixObject, matrix_Type, base_type); + if (self) { + self->num_col = num_col; + self->num_row = num_row; + + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; + + self->matrix = mat; + self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; + } + return (PyObject *)self; } PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user, - const unsigned short num_col, const unsigned short num_row, - unsigned char cb_type, unsigned char cb_subtype) -{ - MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, NULL); - if (self) { - Py_INCREF(cb_user); - self->cb_user = cb_user; - self->cb_type = cb_type; - self->cb_subtype = cb_subtype; - PyObject_GC_Track(self); - } - return (PyObject *) self; + const unsigned short num_col, + const unsigned short num_row, + unsigned char cb_type, + unsigned char cb_subtype) +{ + MatrixObject *self = (MatrixObject *)Matrix_CreatePyObject(NULL, num_col, num_row, NULL); + if (self) { + Py_INCREF(cb_user); + self->cb_user = cb_user; + self->cb_type = cb_type; + self->cb_subtype = cb_subtype; + PyObject_GC_Track(self); + } + return (PyObject *)self; } /** @@ -3185,288 +3264,278 @@ PyObject *Matrix_CreatePyObject_cb(PyObject *cb_user, */ static bool Matrix_ParseCheck(MatrixObject *pymat) { - if (!MatrixObject_Check(pymat)) { - PyErr_Format(PyExc_TypeError, - "expected a mathutils.Matrix, not a %.200s", - Py_TYPE(pymat)->tp_name); - return 0; - } - /* sets error */ - if (BaseMath_ReadCallback(pymat) == -1) { - return 0; - } - return 1; + if (!MatrixObject_Check(pymat)) { + PyErr_Format( + PyExc_TypeError, "expected a mathutils.Matrix, not a %.200s", Py_TYPE(pymat)->tp_name); + return 0; + } + /* sets error */ + if (BaseMath_ReadCallback(pymat) == -1) { + return 0; + } + return 1; } int Matrix_ParseAny(PyObject *o, void *p) { - MatrixObject **pymat_p = p; - MatrixObject *pymat = (MatrixObject *)o; + MatrixObject **pymat_p = p; + MatrixObject *pymat = (MatrixObject *)o; - if (!Matrix_ParseCheck(pymat)) { - return 0; - } - *pymat_p = pymat; - return 1; + if (!Matrix_ParseCheck(pymat)) { + return 0; + } + *pymat_p = pymat; + return 1; } int Matrix_Parse3x3(PyObject *o, void *p) { - MatrixObject **pymat_p = p; - MatrixObject *pymat = (MatrixObject *)o; + MatrixObject **pymat_p = p; + MatrixObject *pymat = (MatrixObject *)o; - if (!Matrix_ParseCheck(pymat)) { - return 0; - } - if ((pymat->num_col != 3) || - (pymat->num_row != 3)) - { - PyErr_SetString(PyExc_ValueError, "matrix must be 3x3"); - return 0; - } + if (!Matrix_ParseCheck(pymat)) { + return 0; + } + if ((pymat->num_col != 3) || (pymat->num_row != 3)) { + PyErr_SetString(PyExc_ValueError, "matrix must be 3x3"); + return 0; + } - *pymat_p = pymat; - return 1; + *pymat_p = pymat; + return 1; } int Matrix_Parse4x4(PyObject *o, void *p) { - MatrixObject **pymat_p = p; - MatrixObject *pymat = (MatrixObject *)o; + MatrixObject **pymat_p = p; + MatrixObject *pymat = (MatrixObject *)o; - if (!Matrix_ParseCheck(pymat)) { - return 0; - } - if ((pymat->num_col != 4) || - (pymat->num_row != 4)) - { - PyErr_SetString(PyExc_ValueError, "matrix must be 4x4"); - return 0; - } + if (!Matrix_ParseCheck(pymat)) { + return 0; + } + if ((pymat->num_col != 4) || (pymat->num_row != 4)) { + PyErr_SetString(PyExc_ValueError, "matrix must be 4x4"); + return 0; + } - *pymat_p = pymat; - return 1; + *pymat_p = pymat; + return 1; } /* ---------------------------------------------------------------------------- * special type for alternate access */ typedef struct { - PyObject_HEAD /* required python macro */ - MatrixObject *matrix_user; - eMatrixAccess_t type; + PyObject_HEAD /* required python macro */ + MatrixObject *matrix_user; + eMatrixAccess_t type; } MatrixAccessObject; static int MatrixAccess_traverse(MatrixAccessObject *self, visitproc visit, void *arg) { - Py_VISIT(self->matrix_user); - return 0; + Py_VISIT(self->matrix_user); + return 0; } static int MatrixAccess_clear(MatrixAccessObject *self) { - Py_CLEAR(self->matrix_user); - return 0; + Py_CLEAR(self->matrix_user); + return 0; } static void MatrixAccess_dealloc(MatrixAccessObject *self) { - if (self->matrix_user) { - PyObject_GC_UnTrack(self); - MatrixAccess_clear(self); - } + if (self->matrix_user) { + PyObject_GC_UnTrack(self); + MatrixAccess_clear(self); + } - Py_TYPE(self)->tp_free(self); + Py_TYPE(self)->tp_free(self); } /* sequence access */ static int MatrixAccess_len(MatrixAccessObject *self) { - return (self->type == MAT_ACCESS_ROW) ? - self->matrix_user->num_row : - self->matrix_user->num_col; + return (self->type == MAT_ACCESS_ROW) ? self->matrix_user->num_row : self->matrix_user->num_col; } static PyObject *MatrixAccess_slice(MatrixAccessObject *self, int begin, int end) { - PyObject *tuple; - int count; + PyObject *tuple; + int count; - /* row/col access */ - MatrixObject *matrix_user = self->matrix_user; - int matrix_access_len; - PyObject *(*Matrix_item_new)(MatrixObject *, int); + /* row/col access */ + MatrixObject *matrix_user = self->matrix_user; + int matrix_access_len; + PyObject *(*Matrix_item_new)(MatrixObject *, int); - if (self->type == MAT_ACCESS_ROW) { - matrix_access_len = matrix_user->num_row; - Matrix_item_new = Matrix_item_row; - } - else { /* MAT_ACCESS_ROW */ - matrix_access_len = matrix_user->num_col; - Matrix_item_new = Matrix_item_col; - } + if (self->type == MAT_ACCESS_ROW) { + matrix_access_len = matrix_user->num_row; + Matrix_item_new = Matrix_item_row; + } + else { /* MAT_ACCESS_ROW */ + matrix_access_len = matrix_user->num_col; + Matrix_item_new = Matrix_item_col; + } - CLAMP(begin, 0, matrix_access_len); - if (end < 0) { - end = (matrix_access_len + 1) + end; - } - CLAMP(end, 0, matrix_access_len); - begin = MIN2(begin, end); + CLAMP(begin, 0, matrix_access_len); + if (end < 0) { + end = (matrix_access_len + 1) + end; + } + CLAMP(end, 0, matrix_access_len); + begin = MIN2(begin, end); - tuple = PyTuple_New(end - begin); - for (count = begin; count < end; count++) { - PyTuple_SET_ITEM(tuple, count - begin, Matrix_item_new(matrix_user, count)); - } + tuple = PyTuple_New(end - begin); + for (count = begin; count < end; count++) { + PyTuple_SET_ITEM(tuple, count - begin, Matrix_item_new(matrix_user, count)); + } - return tuple; + return tuple; } static PyObject *MatrixAccess_subscript(MatrixAccessObject *self, PyObject *item) { - MatrixObject *matrix_user = self->matrix_user; - - if (PyIndex_Check(item)) { - Py_ssize_t i; - i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - if (self->type == MAT_ACCESS_ROW) { - if (i < 0) { - i += matrix_user->num_row; - } - return Matrix_item_row(matrix_user, i); - } - else { /* MAT_ACCESS_ROW */ - if (i < 0) { - i += matrix_user->num_col; - } - return Matrix_item_col(matrix_user, i); - } - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, MatrixAccess_len(self), &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyTuple_New(0); - } - else if (step == 1) { - return MatrixAccess_slice(self, start, stop); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with matrix accessors"); - return NULL; - } - } - else { - PyErr_Format(PyExc_TypeError, - "matrix indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return NULL; - } + MatrixObject *matrix_user = self->matrix_user; + + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + if (self->type == MAT_ACCESS_ROW) { + if (i < 0) { + i += matrix_user->num_row; + } + return Matrix_item_row(matrix_user, i); + } + else { /* MAT_ACCESS_ROW */ + if (i < 0) { + i += matrix_user->num_col; + } + return Matrix_item_col(matrix_user, i); + } + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, MatrixAccess_len(self), &start, &stop, &step, &slicelength) < + 0) { + return NULL; + } + + if (slicelength <= 0) { + return PyTuple_New(0); + } + else if (step == 1) { + return MatrixAccess_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with matrix accessors"); + return NULL; + } + } + else { + PyErr_Format( + PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return NULL; + } } static int MatrixAccess_ass_subscript(MatrixAccessObject *self, PyObject *item, PyObject *value) { - MatrixObject *matrix_user = self->matrix_user; - - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return -1; - } - - if (self->type == MAT_ACCESS_ROW) { - if (i < 0) { - i += matrix_user->num_row; - } - return Matrix_ass_item_row(matrix_user, i, value); - } - else { /* MAT_ACCESS_ROW */ - if (i < 0) { - i += matrix_user->num_col; - } - return Matrix_ass_item_col(matrix_user, i, value); - } - - } - /* TODO, slice */ - else { - PyErr_Format(PyExc_TypeError, - "matrix indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return -1; - } + MatrixObject *matrix_user = self->matrix_user; + + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return -1; + } + + if (self->type == MAT_ACCESS_ROW) { + if (i < 0) { + i += matrix_user->num_row; + } + return Matrix_ass_item_row(matrix_user, i, value); + } + else { /* MAT_ACCESS_ROW */ + if (i < 0) { + i += matrix_user->num_col; + } + return Matrix_ass_item_col(matrix_user, i, value); + } + } + /* TODO, slice */ + else { + PyErr_Format( + PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + return -1; + } } static PyObject *MatrixAccess_iter(MatrixAccessObject *self) { - /* Try get values from a collection */ - PyObject *ret; - PyObject *iter = NULL; - ret = MatrixAccess_slice(self, 0, MATRIX_MAX_DIM); + /* Try get values from a collection */ + PyObject *ret; + PyObject *iter = NULL; + ret = MatrixAccess_slice(self, 0, MATRIX_MAX_DIM); - /* we know this is a tuple so no need to PyIter_Check - * otherwise it could be NULL (unlikely) if conversion failed */ - if (ret) { - iter = PyObject_GetIter(ret); - Py_DECREF(ret); - } + /* we know this is a tuple so no need to PyIter_Check + * otherwise it could be NULL (unlikely) if conversion failed */ + if (ret) { + iter = PyObject_GetIter(ret); + Py_DECREF(ret); + } - return iter; + return iter; } static PyMappingMethods MatrixAccess_AsMapping = { - (lenfunc)MatrixAccess_len, - (binaryfunc)MatrixAccess_subscript, - (objobjargproc) MatrixAccess_ass_subscript, + (lenfunc)MatrixAccess_len, + (binaryfunc)MatrixAccess_subscript, + (objobjargproc)MatrixAccess_ass_subscript, }; PyTypeObject matrix_access_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "MatrixAccess", /*tp_name*/ - sizeof(MatrixAccessObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)MatrixAccess_dealloc, /*tp_dealloc*/ - NULL, /*tp_print*/ - NULL, /*tp_getattr*/ - NULL, /*tp_setattr*/ - NULL, /*tp_compare*/ - NULL, /*tp_repr*/ - NULL, /*tp_as_number*/ - NULL /*&MatrixAccess_SeqMethods*/ /* TODO */, /*tp_as_sequence*/ - &MatrixAccess_AsMapping, /*tp_as_mapping*/ - NULL, /*tp_hash*/ - NULL, /*tp_call*/ - NULL, /*tp_str*/ - NULL, /*tp_getattro*/ - NULL, /*tp_setattro*/ - NULL, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - NULL, /*tp_doc*/ - (traverseproc)MatrixAccess_traverse,/*tp_traverse*/ - (inquiry)MatrixAccess_clear, /*tp_clear*/ - NULL /* (richcmpfunc)MatrixAccess_richcmpr */ /* TODO*/, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - (getiterfunc)MatrixAccess_iter, /* getiterfunc tp_iter; */ + PyVarObject_HEAD_INIT(NULL, 0) "MatrixAccess", /*tp_name*/ + sizeof(MatrixAccessObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)MatrixAccess_dealloc, /*tp_dealloc*/ + NULL, /*tp_print*/ + NULL, /*tp_getattr*/ + NULL, /*tp_setattr*/ + NULL, /*tp_compare*/ + NULL, /*tp_repr*/ + NULL, /*tp_as_number*/ + NULL /*&MatrixAccess_SeqMethods*/ /* TODO */, /*tp_as_sequence*/ + &MatrixAccess_AsMapping, /*tp_as_mapping*/ + NULL, /*tp_hash*/ + NULL, /*tp_call*/ + NULL, /*tp_str*/ + NULL, /*tp_getattro*/ + NULL, /*tp_setattro*/ + NULL, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ + NULL, /*tp_doc*/ + (traverseproc)MatrixAccess_traverse, /*tp_traverse*/ + (inquiry)MatrixAccess_clear, /*tp_clear*/ + NULL /* (richcmpfunc)MatrixAccess_richcmpr */ /* TODO*/, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + (getiterfunc)MatrixAccess_iter, /* getiterfunc tp_iter; */ }; static PyObject *MatrixAccess_CreatePyObject(MatrixObject *matrix, const eMatrixAccess_t type) { - MatrixAccessObject *matrix_access = (MatrixAccessObject *)PyObject_GC_New(MatrixObject, &matrix_access_Type); + MatrixAccessObject *matrix_access = (MatrixAccessObject *)PyObject_GC_New(MatrixObject, + &matrix_access_Type); - matrix_access->matrix_user = matrix; - Py_INCREF(matrix); + matrix_access->matrix_user = matrix; + Py_INCREF(matrix); - matrix_access->type = type; + matrix_access->type = type; - return (PyObject *)matrix_access; + return (PyObject *)matrix_access; } /* end special access diff --git a/source/blender/python/mathutils/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h index 0f47472c8fd..3b42e22a787 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.h +++ b/source/blender/python/mathutils/mathutils_Matrix.h @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #ifndef __MATHUTILS_MATRIX_H__ #define __MATHUTILS_MATRIX_H__ @@ -33,23 +32,25 @@ extern PyTypeObject matrix_access_Type; /* matrix[row][col] == MATRIX_ITEM_INDEX(matrix, row, col) */ #ifdef DEBUG -# define MATRIX_ITEM_ASSERT(_mat, _row, _col) (BLI_assert(_row < (_mat)->num_row && _col < (_mat)->num_col)) +# define MATRIX_ITEM_ASSERT(_mat, _row, _col) \ + (BLI_assert(_row < (_mat)->num_row && _col < (_mat)->num_col)) #else # define MATRIX_ITEM_ASSERT(_mat, _row, _col) (void)0 #endif #define MATRIX_ITEM_INDEX_NUMROW(_totrow, _row, _col) (((_totrow) * (_col)) + (_row)) -#define MATRIX_ITEM_INDEX(_mat, _row, _col) (MATRIX_ITEM_ASSERT(_mat, _row, _col),(((_mat)->num_row * (_col)) + (_row))) -#define MATRIX_ITEM_PTR( _mat, _row, _col) ((_mat)->matrix + MATRIX_ITEM_INDEX(_mat, _row, _col)) -#define MATRIX_ITEM( _mat, _row, _col) ((_mat)->matrix [MATRIX_ITEM_INDEX(_mat, _row, _col)]) +#define MATRIX_ITEM_INDEX(_mat, _row, _col) \ + (MATRIX_ITEM_ASSERT(_mat, _row, _col), (((_mat)->num_row * (_col)) + (_row))) +#define MATRIX_ITEM_PTR(_mat, _row, _col) ((_mat)->matrix + MATRIX_ITEM_INDEX(_mat, _row, _col)) +#define MATRIX_ITEM(_mat, _row, _col) ((_mat)->matrix[MATRIX_ITEM_INDEX(_mat, _row, _col)]) #define MATRIX_COL_INDEX(_mat, _col) (MATRIX_ITEM_INDEX(_mat, 0, _col)) -#define MATRIX_COL_PTR( _mat, _col) ((_mat)->matrix + MATRIX_COL_INDEX(_mat, _col)) +#define MATRIX_COL_PTR(_mat, _col) ((_mat)->matrix + MATRIX_COL_INDEX(_mat, _col)) typedef struct { - BASE_MATH_MEMBERS(matrix); - unsigned short num_col; - unsigned short num_row; + BASE_MATH_MEMBERS(matrix); + unsigned short num_col; + unsigned short num_row; } MatrixObject; /* struct data contains a pointer to the actual data that the @@ -58,21 +59,20 @@ typedef struct { * blender (stored in blend_data). This is an either/or struct not both */ /* prototypes */ -PyObject *Matrix_CreatePyObject( - const float *mat, - const unsigned short num_col, const unsigned short num_row, - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT; -PyObject *Matrix_CreatePyObject_wrap( - float *mat, - const unsigned short num_col, const unsigned short num_row, - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -PyObject *Matrix_CreatePyObject_cb( - PyObject *user, - const unsigned short num_col, const unsigned short num_row, - unsigned char cb_type, unsigned char cb_subtype - ) ATTR_WARN_UNUSED_RESULT; +PyObject *Matrix_CreatePyObject(const float *mat, + const unsigned short num_col, + const unsigned short num_row, + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; +PyObject *Matrix_CreatePyObject_wrap(float *mat, + const unsigned short num_col, + const unsigned short num_row, + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); +PyObject *Matrix_CreatePyObject_cb(PyObject *user, + const unsigned short num_col, + const unsigned short num_row, + unsigned char cb_type, + unsigned char cb_subtype) ATTR_WARN_UNUSED_RESULT; /* PyArg_ParseTuple's "O&" formatting helpers. */ int Matrix_ParseAny(PyObject *o, void *p); diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 422a1ff28fa..86da4511a2e 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #include #include "mathutils.h" @@ -36,7 +35,7 @@ #define QUAT_SIZE 4 static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self); -static void quat__axis_angle_sanitize(float axis[3], float *angle); +static void quat__axis_angle_sanitize(float axis[3], float *angle); static PyObject *Quaternion_copy(QuaternionObject *self); static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args); @@ -45,569 +44,556 @@ static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args); /* note: BaseMath_ReadCallback must be called beforehand */ static PyObject *Quaternion_to_tuple_ext(QuaternionObject *self, int ndigits) { - PyObject *ret; - int i; - - ret = PyTuple_New(QUAT_SIZE); - - if (ndigits >= 0) { - for (i = 0; i < QUAT_SIZE; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->quat[i], ndigits))); - } - } - else { - for (i = 0; i < QUAT_SIZE; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->quat[i])); - } - } - - return ret; + PyObject *ret; + int i; + + ret = PyTuple_New(QUAT_SIZE); + + if (ndigits >= 0) { + for (i = 0; i < QUAT_SIZE; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->quat[i], ndigits))); + } + } + else { + for (i = 0; i < QUAT_SIZE; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->quat[i])); + } + } + + return ret; } PyDoc_STRVAR(Quaternion_to_euler_doc, -".. method:: to_euler(order, euler_compat)\n" -"\n" -" Return Euler representation of the quaternion.\n" -"\n" -" :arg order: Optional rotation order argument in\n" -" ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n" -" :type order: string\n" -" :arg euler_compat: Optional euler argument the new euler will be made\n" -" compatible with (no axis flipping between them).\n" -" Useful for converting a series of matrices to animation curves.\n" -" :type euler_compat: :class:`Euler`\n" -" :return: Euler representation of the quaternion.\n" -" :rtype: :class:`Euler`\n" -); + ".. method:: to_euler(order, euler_compat)\n" + "\n" + " Return Euler representation of the quaternion.\n" + "\n" + " :arg order: Optional rotation order argument in\n" + " ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX'].\n" + " :type order: string\n" + " :arg euler_compat: Optional euler argument the new euler will be made\n" + " compatible with (no axis flipping between them).\n" + " Useful for converting a series of matrices to animation curves.\n" + " :type euler_compat: :class:`Euler`\n" + " :return: Euler representation of the quaternion.\n" + " :rtype: :class:`Euler`\n"); static PyObject *Quaternion_to_euler(QuaternionObject *self, PyObject *args) { - float tquat[4]; - float eul[3]; - const char *order_str = NULL; - short order = EULER_ORDER_XYZ; - EulerObject *eul_compat = NULL; - - if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat)) { - return NULL; - } - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - if (order_str) { - order = euler_order_from_string(order_str, "Matrix.to_euler()"); - - if (order == -1) { - return NULL; - } - } - - normalize_qt_qt(tquat, self->quat); - - if (eul_compat) { - if (BaseMath_ReadCallback(eul_compat) == -1) { - return NULL; - } - - if (order == EULER_ORDER_XYZ) { - quat_to_compatible_eul(eul, eul_compat->eul, tquat); - } - else { - quat_to_compatible_eulO(eul, eul_compat->eul, order, tquat); - } - } - else { - if (order == EULER_ORDER_XYZ) { - quat_to_eul(eul, tquat); - } - else { - quat_to_eulO(eul, order, tquat); - } - } - - return Euler_CreatePyObject(eul, order, NULL); + float tquat[4]; + float eul[3]; + const char *order_str = NULL; + short order = EULER_ORDER_XYZ; + EulerObject *eul_compat = NULL; + + if (!PyArg_ParseTuple(args, "|sO!:to_euler", &order_str, &euler_Type, &eul_compat)) { + return NULL; + } + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + if (order_str) { + order = euler_order_from_string(order_str, "Matrix.to_euler()"); + + if (order == -1) { + return NULL; + } + } + + normalize_qt_qt(tquat, self->quat); + + if (eul_compat) { + if (BaseMath_ReadCallback(eul_compat) == -1) { + return NULL; + } + + if (order == EULER_ORDER_XYZ) { + quat_to_compatible_eul(eul, eul_compat->eul, tquat); + } + else { + quat_to_compatible_eulO(eul, eul_compat->eul, order, tquat); + } + } + else { + if (order == EULER_ORDER_XYZ) { + quat_to_eul(eul, tquat); + } + else { + quat_to_eulO(eul, order, tquat); + } + } + + return Euler_CreatePyObject(eul, order, NULL); } PyDoc_STRVAR(Quaternion_to_matrix_doc, -".. method:: to_matrix()\n" -"\n" -" Return a matrix representation of the quaternion.\n" -"\n" -" :return: A 3x3 rotation matrix representation of the quaternion.\n" -" :rtype: :class:`Matrix`\n" -); + ".. method:: to_matrix()\n" + "\n" + " Return a matrix representation of the quaternion.\n" + "\n" + " :return: A 3x3 rotation matrix representation of the quaternion.\n" + " :rtype: :class:`Matrix`\n"); static PyObject *Quaternion_to_matrix(QuaternionObject *self) { - float mat[9]; /* all values are set */ + float mat[9]; /* all values are set */ - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - quat_to_mat3((float (*)[3])mat, self->quat); - return Matrix_CreatePyObject(mat, 3, 3, NULL); + quat_to_mat3((float(*)[3])mat, self->quat); + return Matrix_CreatePyObject(mat, 3, 3, NULL); } PyDoc_STRVAR(Quaternion_to_axis_angle_doc, -".. method:: to_axis_angle()\n" -"\n" -" Return the axis, angle representation of the quaternion.\n" -"\n" -" :return: axis, angle.\n" -" :rtype: (:class:`Vector`, float) pair\n" -); + ".. method:: to_axis_angle()\n" + "\n" + " Return the axis, angle representation of the quaternion.\n" + "\n" + " :return: axis, angle.\n" + " :rtype: (:class:`Vector`, float) pair\n"); static PyObject *Quaternion_to_axis_angle(QuaternionObject *self) { - PyObject *ret; + PyObject *ret; - float tquat[4]; + float tquat[4]; - float axis[3]; - float angle; + float axis[3]; + float angle; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - normalize_qt_qt(tquat, self->quat); - quat_to_axis_angle(axis, &angle, tquat); + normalize_qt_qt(tquat, self->quat); + quat_to_axis_angle(axis, &angle, tquat); - quat__axis_angle_sanitize(axis, &angle); + quat__axis_angle_sanitize(axis, &angle); - ret = PyTuple_New(2); - PyTuple_SET_ITEMS(ret, - Vector_CreatePyObject(axis, 3, NULL), - PyFloat_FromDouble(angle)); - return ret; + ret = PyTuple_New(2); + PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(axis, 3, NULL), PyFloat_FromDouble(angle)); + return ret; } -PyDoc_STRVAR(Quaternion_to_exponential_map_doc, -".. method:: to_exponential_map()\n" -"\n" -" Return the exponential map representation of the quaternion.\n" -"\n" -" This representation consist of the rotation axis multiplied by the rotation angle." -" Such a representation is useful for interpolation between multiple orientations.\n" -"\n" -" :return: exponential map.\n" -" :rtype: :class:`Vector` of size 3\n" -"\n" -" To convert back to a quaternion, pass it to the :class:`Quaternion` constructor.\n" -); +PyDoc_STRVAR( + Quaternion_to_exponential_map_doc, + ".. method:: to_exponential_map()\n" + "\n" + " Return the exponential map representation of the quaternion.\n" + "\n" + " This representation consist of the rotation axis multiplied by the rotation angle." + " Such a representation is useful for interpolation between multiple orientations.\n" + "\n" + " :return: exponential map.\n" + " :rtype: :class:`Vector` of size 3\n" + "\n" + " To convert back to a quaternion, pass it to the :class:`Quaternion` constructor.\n"); static PyObject *Quaternion_to_exponential_map(QuaternionObject *self) { - float expmap[3]; + float expmap[3]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - quat_to_expmap(expmap, self->quat); - return Vector_CreatePyObject(expmap, 3, NULL); + quat_to_expmap(expmap, self->quat); + return Vector_CreatePyObject(expmap, 3, NULL); } PyDoc_STRVAR(Quaternion_cross_doc, -".. method:: cross(other)\n" -"\n" -" Return the cross product of this quaternion and another.\n" -"\n" -" :arg other: The other quaternion to perform the cross product with.\n" -" :type other: :class:`Quaternion`\n" -" :return: The cross product.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. method:: cross(other)\n" + "\n" + " Return the cross product of this quaternion and another.\n" + "\n" + " :arg other: The other quaternion to perform the cross product with.\n" + " :type other: :class:`Quaternion`\n" + " :return: The cross product.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_cross(QuaternionObject *self, PyObject *value) { - float quat[QUAT_SIZE], tquat[QUAT_SIZE]; + float quat[QUAT_SIZE], tquat[QUAT_SIZE]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, - "Quaternion.cross(other), invalid 'other' arg") == -1) - { - return NULL; - } + if (mathutils_array_parse( + tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.cross(other), invalid 'other' arg") == + -1) { + return NULL; + } - mul_qt_qtqt(quat, self->quat, tquat); - return Quaternion_CreatePyObject(quat, Py_TYPE(self)); + mul_qt_qtqt(quat, self->quat, tquat); + return Quaternion_CreatePyObject(quat, Py_TYPE(self)); } PyDoc_STRVAR(Quaternion_dot_doc, -".. method:: dot(other)\n" -"\n" -" Return the dot product of this quaternion and another.\n" -"\n" -" :arg other: The other quaternion to perform the dot product with.\n" -" :type other: :class:`Quaternion`\n" -" :return: The dot product.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. method:: dot(other)\n" + "\n" + " Return the dot product of this quaternion and another.\n" + "\n" + " :arg other: The other quaternion to perform the dot product with.\n" + " :type other: :class:`Quaternion`\n" + " :return: The dot product.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_dot(QuaternionObject *self, PyObject *value) { - float tquat[QUAT_SIZE]; + float tquat[QUAT_SIZE]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, - "Quaternion.dot(other), invalid 'other' arg") == -1) - { - return NULL; - } + if (mathutils_array_parse( + tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.dot(other), invalid 'other' arg") == + -1) { + return NULL; + } - return PyFloat_FromDouble(dot_qtqt(self->quat, tquat)); + return PyFloat_FromDouble(dot_qtqt(self->quat, tquat)); } PyDoc_STRVAR(Quaternion_rotation_difference_doc, -".. function:: rotation_difference(other)\n" -"\n" -" Returns a quaternion representing the rotational difference.\n" -"\n" -" :arg other: second quaternion.\n" -" :type other: :class:`Quaternion`\n" -" :return: the rotational difference between the two quat rotations.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. function:: rotation_difference(other)\n" + "\n" + " Returns a quaternion representing the rotational difference.\n" + "\n" + " :arg other: second quaternion.\n" + " :type other: :class:`Quaternion`\n" + " :return: the rotational difference between the two quat rotations.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_rotation_difference(QuaternionObject *self, PyObject *value) { - float tquat[QUAT_SIZE], quat[QUAT_SIZE]; + float tquat[QUAT_SIZE], quat[QUAT_SIZE]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, - "Quaternion.difference(other), invalid 'other' arg") == -1) - { - return NULL; - } + if (mathutils_array_parse(tquat, + QUAT_SIZE, + QUAT_SIZE, + value, + "Quaternion.difference(other), invalid 'other' arg") == -1) { + return NULL; + } - rotation_between_quats_to_quat(quat, self->quat, tquat); + rotation_between_quats_to_quat(quat, self->quat, tquat); - return Quaternion_CreatePyObject(quat, Py_TYPE(self)); + return Quaternion_CreatePyObject(quat, Py_TYPE(self)); } PyDoc_STRVAR(Quaternion_slerp_doc, -".. function:: slerp(other, factor)\n" -"\n" -" Returns the interpolation of two quaternions.\n" -"\n" -" :arg other: value to interpolate with.\n" -" :type other: :class:`Quaternion`\n" -" :arg factor: The interpolation value in [0.0, 1.0].\n" -" :type factor: float\n" -" :return: The interpolated rotation.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. function:: slerp(other, factor)\n" + "\n" + " Returns the interpolation of two quaternions.\n" + "\n" + " :arg other: value to interpolate with.\n" + " :type other: :class:`Quaternion`\n" + " :arg factor: The interpolation value in [0.0, 1.0].\n" + " :type factor: float\n" + " :return: The interpolated rotation.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args) { - PyObject *value; - float tquat[QUAT_SIZE], quat[QUAT_SIZE], fac; - - if (!PyArg_ParseTuple(args, "Of:slerp", &value, &fac)) { - PyErr_SetString(PyExc_TypeError, - "quat.slerp(): " - "expected Quaternion types and float"); - return NULL; - } - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - if (mathutils_array_parse(tquat, QUAT_SIZE, QUAT_SIZE, value, - "Quaternion.slerp(other), invalid 'other' arg") == -1) - { - return NULL; - } - - if (fac > 1.0f || fac < 0.0f) { - PyErr_SetString(PyExc_ValueError, - "quat.slerp(): " - "interpolation factor must be between 0.0 and 1.0"); - return NULL; - } - - interp_qt_qtqt(quat, self->quat, tquat, fac); - - return Quaternion_CreatePyObject(quat, Py_TYPE(self)); + PyObject *value; + float tquat[QUAT_SIZE], quat[QUAT_SIZE], fac; + + if (!PyArg_ParseTuple(args, "Of:slerp", &value, &fac)) { + PyErr_SetString(PyExc_TypeError, + "quat.slerp(): " + "expected Quaternion types and float"); + return NULL; + } + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + if (mathutils_array_parse( + tquat, QUAT_SIZE, QUAT_SIZE, value, "Quaternion.slerp(other), invalid 'other' arg") == + -1) { + return NULL; + } + + if (fac > 1.0f || fac < 0.0f) { + PyErr_SetString(PyExc_ValueError, + "quat.slerp(): " + "interpolation factor must be between 0.0 and 1.0"); + return NULL; + } + + interp_qt_qtqt(quat, self->quat, tquat, fac); + + return Quaternion_CreatePyObject(quat, Py_TYPE(self)); } PyDoc_STRVAR(Quaternion_rotate_doc, -".. method:: rotate(other)\n" -"\n" -" Rotates the quaternion by another mathutils value.\n" -"\n" -" :arg other: rotation component of mathutils value\n" -" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" -); + ".. method:: rotate(other)\n" + "\n" + " Rotates the quaternion by another mathutils value.\n" + "\n" + " :arg other: rotation component of mathutils value\n" + " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"); static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value) { - float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; - float tquat[4], length; + float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; + float tquat[4], length; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (mathutils_any_to_rotmat(other_rmat, value, "Quaternion.rotate(value)") == -1) { - return NULL; - } + if (mathutils_any_to_rotmat(other_rmat, value, "Quaternion.rotate(value)") == -1) { + return NULL; + } - length = normalize_qt_qt(tquat, self->quat); - quat_to_mat3(self_rmat, tquat); - mul_m3_m3m3(rmat, other_rmat, self_rmat); + length = normalize_qt_qt(tquat, self->quat); + quat_to_mat3(self_rmat, tquat); + mul_m3_m3m3(rmat, other_rmat, self_rmat); - mat3_to_quat(self->quat, rmat); - mul_qt_fl(self->quat, length); /* maintain length after rotating */ + mat3_to_quat(self->quat, rmat); + mul_qt_fl(self->quat, length); /* maintain length after rotating */ - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } /* ----------------------------Quaternion.normalize()---------------- */ /* Normalize the quaternion. This may change the angle as well as the * rotation axis, as all of (w, x, y, z) are scaled. */ PyDoc_STRVAR(Quaternion_normalize_doc, -".. function:: normalize()\n" -"\n" -" Normalize the quaternion.\n" -); + ".. function:: normalize()\n" + "\n" + " Normalize the quaternion.\n"); static PyObject *Quaternion_normalize(QuaternionObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - normalize_qt(self->quat); + normalize_qt(self->quat); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Quaternion_normalized_doc, -".. function:: normalized()\n" -"\n" -" Return a new normalized quaternion.\n" -"\n" -" :return: a normalized copy.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. function:: normalized()\n" + "\n" + " Return a new normalized quaternion.\n" + "\n" + " :return: a normalized copy.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_normalized(QuaternionObject *self) { - return quat__apply_to_copy((PyNoArgsFunction)Quaternion_normalize, self); + return quat__apply_to_copy((PyNoArgsFunction)Quaternion_normalize, self); } PyDoc_STRVAR(Quaternion_invert_doc, -".. function:: invert()\n" -"\n" -" Set the quaternion to its inverse.\n" -); + ".. function:: invert()\n" + "\n" + " Set the quaternion to its inverse.\n"); static PyObject *Quaternion_invert(QuaternionObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - invert_qt(self->quat); + invert_qt(self->quat); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Quaternion_inverted_doc, -".. function:: inverted()\n" -"\n" -" Return a new, inverted quaternion.\n" -"\n" -" :return: the inverted value.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. function:: inverted()\n" + "\n" + " Return a new, inverted quaternion.\n" + "\n" + " :return: the inverted value.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_inverted(QuaternionObject *self) { - return quat__apply_to_copy((PyNoArgsFunction)Quaternion_invert, self); + return quat__apply_to_copy((PyNoArgsFunction)Quaternion_invert, self); } PyDoc_STRVAR(Quaternion_identity_doc, -".. function:: identity()\n" -"\n" -" Set the quaternion to an identity quaternion.\n" -"\n" -" :rtype: :class:`Quaternion`\n" -); + ".. function:: identity()\n" + "\n" + " Set the quaternion to an identity quaternion.\n" + "\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_identity(QuaternionObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - unit_qt(self->quat); + unit_qt(self->quat); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Quaternion_negate_doc, -".. function:: negate()\n" -"\n" -" Set the quaternion to its negative.\n" -"\n" -" :rtype: :class:`Quaternion`\n" -); + ".. function:: negate()\n" + "\n" + " Set the quaternion to its negative.\n" + "\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_negate(QuaternionObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - mul_qt_fl(self->quat, -1.0f); + mul_qt_fl(self->quat, -1.0f); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Quaternion_conjugate_doc, -".. function:: conjugate()\n" -"\n" -" Set the quaternion to its conjugate (negate x, y, z).\n" -); + ".. function:: conjugate()\n" + "\n" + " Set the quaternion to its conjugate (negate x, y, z).\n"); static PyObject *Quaternion_conjugate(QuaternionObject *self) { - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - conjugate_qt(self->quat); + conjugate_qt(self->quat); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Quaternion_conjugated_doc, -".. function:: conjugated()\n" -"\n" -" Return a new conjugated quaternion.\n" -"\n" -" :return: a new quaternion.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. function:: conjugated()\n" + "\n" + " Return a new conjugated quaternion.\n" + "\n" + " :return: a new quaternion.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Quaternion_conjugated(QuaternionObject *self) { - return quat__apply_to_copy((PyNoArgsFunction)Quaternion_conjugate, self); + return quat__apply_to_copy((PyNoArgsFunction)Quaternion_conjugate, self); } PyDoc_STRVAR(Quaternion_copy_doc, -".. function:: copy()\n" -"\n" -" Returns a copy of this quaternion.\n" -"\n" -" :return: A copy of the quaternion.\n" -" :rtype: :class:`Quaternion`\n" -"\n" -" .. note:: use this to get a copy of a wrapped quaternion with\n" -" no reference to the original data.\n" -); + ".. function:: copy()\n" + "\n" + " Returns a copy of this quaternion.\n" + "\n" + " :return: A copy of the quaternion.\n" + " :rtype: :class:`Quaternion`\n" + "\n" + " .. note:: use this to get a copy of a wrapped quaternion with\n" + " no reference to the original data.\n"); static PyObject *Quaternion_copy(QuaternionObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return Quaternion_CreatePyObject(self->quat, Py_TYPE(self)); + return Quaternion_CreatePyObject(self->quat, Py_TYPE(self)); } static PyObject *Quaternion_deepcopy(QuaternionObject *self, PyObject *args) { - if (!PyC_CheckArgs_DeepCopy(args)) { - return NULL; - } - return Quaternion_copy(self); + if (!PyC_CheckArgs_DeepCopy(args)) { + return NULL; + } + return Quaternion_copy(self); } /* print the object to screen */ static PyObject *Quaternion_repr(QuaternionObject *self) { - PyObject *ret, *tuple; + PyObject *ret, *tuple; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - tuple = Quaternion_to_tuple_ext(self, -1); + tuple = Quaternion_to_tuple_ext(self, -1); - ret = PyUnicode_FromFormat("Quaternion(%R)", tuple); + ret = PyUnicode_FromFormat("Quaternion(%R)", tuple); - Py_DECREF(tuple); - return ret; + Py_DECREF(tuple); + return ret; } #ifndef MATH_STANDALONE static PyObject *Quaternion_str(QuaternionObject *self) { - DynStr *ds; + DynStr *ds; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - ds = BLI_dynstr_new(); + ds = BLI_dynstr_new(); - BLI_dynstr_appendf(ds, "", - self->quat[0], self->quat[1], self->quat[2], self->quat[3]); + BLI_dynstr_appendf(ds, + "", + self->quat[0], + self->quat[1], + self->quat[2], + self->quat[3]); - return mathutils_dynstr_to_py(ds); /* frees ds */ + return mathutils_dynstr_to_py(ds); /* frees ds */ } #endif static PyObject *Quaternion_richcmpr(PyObject *a, PyObject *b, int op) { - PyObject *res; - int ok = -1; /* zero is true */ - - if (QuaternionObject_Check(a) && QuaternionObject_Check(b)) { - QuaternionObject *quatA = (QuaternionObject *)a; - QuaternionObject *quatB = (QuaternionObject *)b; - - if (BaseMath_ReadCallback(quatA) == -1 || BaseMath_ReadCallback(quatB) == -1) { - return NULL; - } - - ok = (EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1)) ? 0 : -1; - } - - switch (op) { - case Py_NE: - ok = !ok; - ATTR_FALLTHROUGH; - case Py_EQ: - res = ok ? Py_False : Py_True; - break; - - case Py_LT: - case Py_LE: - case Py_GT: - case Py_GE: - res = Py_NotImplemented; - break; - default: - PyErr_BadArgument(); - return NULL; - } - - return Py_INCREF_RET(res); + PyObject *res; + int ok = -1; /* zero is true */ + + if (QuaternionObject_Check(a) && QuaternionObject_Check(b)) { + QuaternionObject *quatA = (QuaternionObject *)a; + QuaternionObject *quatB = (QuaternionObject *)b; + + if (BaseMath_ReadCallback(quatA) == -1 || BaseMath_ReadCallback(quatB) == -1) { + return NULL; + } + + ok = (EXPP_VectorsAreEqual(quatA->quat, quatB->quat, QUAT_SIZE, 1)) ? 0 : -1; + } + + switch (op) { + case Py_NE: + ok = !ok; + ATTR_FALLTHROUGH; + case Py_EQ: + res = ok ? Py_False : Py_True; + break; + + case Py_LT: + case Py_LE: + case Py_GT: + case Py_GE: + res = Py_NotImplemented; + break; + default: + PyErr_BadArgument(); + return NULL; + } + + return Py_INCREF_RET(res); } static Py_hash_t Quaternion_hash(QuaternionObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback(self) == -1) { + return -1; + } - if (BaseMathObject_Prepare_ForHash(self) == -1) { - return -1; - } + if (BaseMathObject_Prepare_ForHash(self) == -1) { + return -1; + } - return mathutils_array_hash(self->quat, QUAT_SIZE); + return mathutils_array_hash(self->quat, QUAT_SIZE); } /* ---------------------SEQUENCE PROTOCOLS------------------------ */ @@ -615,206 +601,202 @@ static Py_hash_t Quaternion_hash(QuaternionObject *self) /* sequence length */ static int Quaternion_len(QuaternionObject *UNUSED(self)) { - return QUAT_SIZE; + return QUAT_SIZE; } /* ----------------------------object[]--------------------------- */ /* sequence accessor (get) */ static PyObject *Quaternion_item(QuaternionObject *self, int i) { - if (i < 0) { - i = QUAT_SIZE - i; - } - - if (i < 0 || i >= QUAT_SIZE) { - PyErr_SetString(PyExc_IndexError, - "quaternion[attribute]: " - "array index out of range"); - return NULL; - } - - if (BaseMath_ReadIndexCallback(self, i) == -1) { - return NULL; - } - - return PyFloat_FromDouble(self->quat[i]); - + if (i < 0) { + i = QUAT_SIZE - i; + } + + if (i < 0 || i >= QUAT_SIZE) { + PyErr_SetString(PyExc_IndexError, + "quaternion[attribute]: " + "array index out of range"); + return NULL; + } + + if (BaseMath_ReadIndexCallback(self, i) == -1) { + return NULL; + } + + return PyFloat_FromDouble(self->quat[i]); } /* ----------------------------object[]------------------------- */ /* sequence accessor (set) */ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob) { - float f; - - if (BaseMath_Prepare_ForWrite(self) == -1) { - return -1; - } - - f = (float)PyFloat_AsDouble(ob); - - if (f == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ - PyErr_SetString(PyExc_TypeError, - "quaternion[index] = x: " - "assigned value not a number"); - return -1; - } - - if (i < 0) { - i = QUAT_SIZE - i; - } - - if (i < 0 || i >= QUAT_SIZE) { - PyErr_SetString(PyExc_IndexError, - "quaternion[attribute] = x: " - "array assignment index out of range"); - return -1; - } - self->quat[i] = f; - - if (BaseMath_WriteIndexCallback(self, i) == -1) { - return -1; - } - - return 0; + float f; + + if (BaseMath_Prepare_ForWrite(self) == -1) { + return -1; + } + + f = (float)PyFloat_AsDouble(ob); + + if (f == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, + "quaternion[index] = x: " + "assigned value not a number"); + return -1; + } + + if (i < 0) { + i = QUAT_SIZE - i; + } + + if (i < 0 || i >= QUAT_SIZE) { + PyErr_SetString(PyExc_IndexError, + "quaternion[attribute] = x: " + "array assignment index out of range"); + return -1; + } + self->quat[i] = f; + + if (BaseMath_WriteIndexCallback(self, i) == -1) { + return -1; + } + + return 0; } /* ----------------------------object[z:y]------------------------ */ /* sequence slice (get) */ static PyObject *Quaternion_slice(QuaternionObject *self, int begin, int end) { - PyObject *tuple; - int count; - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - CLAMP(begin, 0, QUAT_SIZE); - if (end < 0) { - end = (QUAT_SIZE + 1) + end; - } - CLAMP(end, 0, QUAT_SIZE); - begin = MIN2(begin, end); - - tuple = PyTuple_New(end - begin); - for (count = begin; count < end; count++) { - PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->quat[count])); - } - - return tuple; + PyObject *tuple; + int count; + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + CLAMP(begin, 0, QUAT_SIZE); + if (end < 0) { + end = (QUAT_SIZE + 1) + end; + } + CLAMP(end, 0, QUAT_SIZE); + begin = MIN2(begin, end); + + tuple = PyTuple_New(end - begin); + for (count = begin; count < end; count++) { + PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->quat[count])); + } + + return tuple; } /* ----------------------------object[z:y]------------------------ */ /* sequence slice (set) */ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyObject *seq) { - int i, size; - float quat[QUAT_SIZE]; - - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } - - CLAMP(begin, 0, QUAT_SIZE); - if (end < 0) { - end = (QUAT_SIZE + 1) + end; - } - CLAMP(end, 0, QUAT_SIZE); - begin = MIN2(begin, end); - - if ((size = mathutils_array_parse(quat, 0, QUAT_SIZE, seq, "mathutils.Quaternion[begin:end] = []")) == -1) { - return -1; - } - - if (size != (end - begin)) { - PyErr_SetString(PyExc_ValueError, - "quaternion[begin:end] = []: " - "size mismatch in slice assignment"); - return -1; - } - - /* parsed well - now set in vector */ - for (i = 0; i < size; i++) { - self->quat[begin + i] = quat[i]; - } - - (void)BaseMath_WriteCallback(self); - return 0; + int i, size; + float quat[QUAT_SIZE]; + + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } + + CLAMP(begin, 0, QUAT_SIZE); + if (end < 0) { + end = (QUAT_SIZE + 1) + end; + } + CLAMP(end, 0, QUAT_SIZE); + begin = MIN2(begin, end); + + if ((size = mathutils_array_parse( + quat, 0, QUAT_SIZE, seq, "mathutils.Quaternion[begin:end] = []")) == -1) { + return -1; + } + + if (size != (end - begin)) { + PyErr_SetString(PyExc_ValueError, + "quaternion[begin:end] = []: " + "size mismatch in slice assignment"); + return -1; + } + + /* parsed well - now set in vector */ + for (i = 0; i < size; i++) { + self->quat[begin + i] = quat[i]; + } + + (void)BaseMath_WriteCallback(self); + return 0; } - static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item) { - if (PyIndex_Check(item)) { - Py_ssize_t i; - i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return NULL; - } - if (i < 0) { - i += QUAT_SIZE; - } - return Quaternion_item(self, i); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) { - return NULL; - } - - if (slicelength <= 0) { - return PyTuple_New(0); - } - else if (step == 1) { - return Quaternion_slice(self, start, stop); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with quaternions"); - return NULL; - } - } - else { - PyErr_Format(PyExc_TypeError, - "quaternion indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return NULL; - } + if (PyIndex_Check(item)) { + Py_ssize_t i; + i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return NULL; + } + if (i < 0) { + i += QUAT_SIZE; + } + return Quaternion_item(self, i); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) { + return NULL; + } + + if (slicelength <= 0) { + return PyTuple_New(0); + } + else if (step == 1) { + return Quaternion_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with quaternions"); + return NULL; + } + } + else { + PyErr_Format(PyExc_TypeError, + "quaternion indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); + return NULL; + } } - static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyObject *value) { - if (PyIndex_Check(item)) { - Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); - if (i == -1 && PyErr_Occurred()) { - return -1; - } - if (i < 0) { - i += QUAT_SIZE; - } - return Quaternion_ass_item(self, i, value); - } - else if (PySlice_Check(item)) { - Py_ssize_t start, stop, step, slicelength; - - if (PySlice_GetIndicesEx(item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) { - return -1; - } - - if (step == 1) { - return Quaternion_ass_slice(self, start, stop, value); - } - else { - PyErr_SetString(PyExc_IndexError, - "slice steps not supported with quaternion"); - return -1; - } - } - else { - PyErr_Format(PyExc_TypeError, - "quaternion indices must be integers, not %.200s", - Py_TYPE(item)->tp_name); - return -1; - } + if (PyIndex_Check(item)) { + Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); + if (i == -1 && PyErr_Occurred()) { + return -1; + } + if (i < 0) { + i += QUAT_SIZE; + } + return Quaternion_ass_item(self, i, value); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; + + if (PySlice_GetIndicesEx(item, QUAT_SIZE, &start, &stop, &step, &slicelength) < 0) { + return -1; + } + + if (step == 1) { + return Quaternion_ass_slice(self, start, stop, value); + } + else { + PyErr_SetString(PyExc_IndexError, "slice steps not supported with quaternion"); + return -1; + } + } + else { + PyErr_Format(PyExc_TypeError, + "quaternion indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); + return -1; + } } /* ------------------------NUMERIC PROTOCOLS---------------------- */ @@ -822,757 +804,793 @@ static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyOb /* addition */ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2) { - float quat[QUAT_SIZE]; - QuaternionObject *quat1 = NULL, *quat2 = NULL; - - if (!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) { - PyErr_Format(PyExc_TypeError, - "Quaternion addition: (%s + %s) " - "invalid type for this operation", - Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); - return NULL; - } - quat1 = (QuaternionObject *)q1; - quat2 = (QuaternionObject *)q2; - - if (BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1) { - return NULL; - } - - add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f); - return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); + float quat[QUAT_SIZE]; + QuaternionObject *quat1 = NULL, *quat2 = NULL; + + if (!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) { + PyErr_Format(PyExc_TypeError, + "Quaternion addition: (%s + %s) " + "invalid type for this operation", + Py_TYPE(q1)->tp_name, + Py_TYPE(q2)->tp_name); + return NULL; + } + quat1 = (QuaternionObject *)q1; + quat2 = (QuaternionObject *)q2; + + if (BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1) { + return NULL; + } + + add_qt_qtqt(quat, quat1->quat, quat2->quat, 1.0f); + return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); } /* ------------------------obj - obj------------------------------ */ /* subtraction */ static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2) { - int x; - float quat[QUAT_SIZE]; - QuaternionObject *quat1 = NULL, *quat2 = NULL; - - if (!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) { - PyErr_Format(PyExc_TypeError, - "Quaternion subtraction: (%s - %s) " - "invalid type for this operation", - Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); - return NULL; - } - - quat1 = (QuaternionObject *)q1; - quat2 = (QuaternionObject *)q2; - - if (BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1) { - return NULL; - } - - for (x = 0; x < QUAT_SIZE; x++) { - quat[x] = quat1->quat[x] - quat2->quat[x]; - } - - return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); + int x; + float quat[QUAT_SIZE]; + QuaternionObject *quat1 = NULL, *quat2 = NULL; + + if (!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) { + PyErr_Format(PyExc_TypeError, + "Quaternion subtraction: (%s - %s) " + "invalid type for this operation", + Py_TYPE(q1)->tp_name, + Py_TYPE(q2)->tp_name); + return NULL; + } + + quat1 = (QuaternionObject *)q1; + quat2 = (QuaternionObject *)q2; + + if (BaseMath_ReadCallback(quat1) == -1 || BaseMath_ReadCallback(quat2) == -1) { + return NULL; + } + + for (x = 0; x < QUAT_SIZE; x++) { + quat[x] = quat1->quat[x] - quat2->quat[x]; + } + + return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); } static PyObject *quat_mul_float(QuaternionObject *quat, const float scalar) { - float tquat[4]; - copy_qt_qt(tquat, quat->quat); - mul_qt_fl(tquat, scalar); - return Quaternion_CreatePyObject(tquat, Py_TYPE(quat)); + float tquat[4]; + copy_qt_qt(tquat, quat->quat); + mul_qt_fl(tquat, scalar); + return Quaternion_CreatePyObject(tquat, Py_TYPE(quat)); } /*------------------------obj * obj------------------------------ * multiplication */ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) { - float scalar; - QuaternionObject *quat1 = NULL, *quat2 = NULL; - - if (QuaternionObject_Check(q1)) { - quat1 = (QuaternionObject *)q1; - if (BaseMath_ReadCallback(quat1) == -1) { - return NULL; - } - } - if (QuaternionObject_Check(q2)) { - quat2 = (QuaternionObject *)q2; - if (BaseMath_ReadCallback(quat2) == -1) { - return NULL; - } - } - - if (quat1 && quat2) { /* QUAT * QUAT (element-wise product) */ + float scalar; + QuaternionObject *quat1 = NULL, *quat2 = NULL; + + if (QuaternionObject_Check(q1)) { + quat1 = (QuaternionObject *)q1; + if (BaseMath_ReadCallback(quat1) == -1) { + return NULL; + } + } + if (QuaternionObject_Check(q2)) { + quat2 = (QuaternionObject *)q2; + if (BaseMath_ReadCallback(quat2) == -1) { + return NULL; + } + } + + if (quat1 && quat2) { /* QUAT * QUAT (element-wise product) */ #ifdef USE_MATHUTILS_ELEM_MUL - float quat[QUAT_SIZE]; - mul_vn_vnvn(quat, quat1->quat, quat2->quat, QUAT_SIZE); - return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); + float quat[QUAT_SIZE]; + mul_vn_vnvn(quat, quat1->quat, quat2->quat, QUAT_SIZE); + return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); #endif - } - /* the only case this can happen (for a supported type is "FLOAT * QUAT") */ - else if (quat2) { /* FLOAT * QUAT */ - if (((scalar = PyFloat_AsDouble(q1)) == -1.0f && PyErr_Occurred()) == 0) { - return quat_mul_float(quat2, scalar); - } - } - else if (quat1) { /* QUAT * FLOAT */ - if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) { - return quat_mul_float(quat1, scalar); - } - } - - PyErr_Format(PyExc_TypeError, - "Element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); - return NULL; + } + /* the only case this can happen (for a supported type is "FLOAT * QUAT") */ + else if (quat2) { /* FLOAT * QUAT */ + if (((scalar = PyFloat_AsDouble(q1)) == -1.0f && PyErr_Occurred()) == 0) { + return quat_mul_float(quat2, scalar); + } + } + else if (quat1) { /* QUAT * FLOAT */ + if ((((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) { + return quat_mul_float(quat1, scalar); + } + } + + PyErr_Format(PyExc_TypeError, + "Element-wise multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(q1)->tp_name, + Py_TYPE(q2)->tp_name); + return NULL; } /*------------------------obj *= obj------------------------------ * inplace multiplication */ static PyObject *Quaternion_imul(PyObject *q1, PyObject *q2) { - float scalar; - QuaternionObject *quat1 = NULL, *quat2 = NULL; - - if (QuaternionObject_Check(q1)) { - quat1 = (QuaternionObject *)q1; - if (BaseMath_ReadCallback(quat1) == -1) { - return NULL; - } - } - if (QuaternionObject_Check(q2)) { - quat2 = (QuaternionObject *)q2; - if (BaseMath_ReadCallback(quat2) == -1) { - return NULL; - } - } - - if (quat1 && quat2) { /* QUAT *= QUAT (inplace element-wise product) */ + float scalar; + QuaternionObject *quat1 = NULL, *quat2 = NULL; + + if (QuaternionObject_Check(q1)) { + quat1 = (QuaternionObject *)q1; + if (BaseMath_ReadCallback(quat1) == -1) { + return NULL; + } + } + if (QuaternionObject_Check(q2)) { + quat2 = (QuaternionObject *)q2; + if (BaseMath_ReadCallback(quat2) == -1) { + return NULL; + } + } + + if (quat1 && quat2) { /* QUAT *= QUAT (inplace element-wise product) */ #ifdef USE_MATHUTILS_ELEM_MUL - mul_vn_vn(quat1->quat, quat2->quat, QUAT_SIZE); + mul_vn_vn(quat1->quat, quat2->quat, QUAT_SIZE); #else - PyErr_Format(PyExc_TypeError, - "Inplace element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); - return NULL; + PyErr_Format(PyExc_TypeError, + "Inplace element-wise multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(q1)->tp_name, + Py_TYPE(q2)->tp_name); + return NULL; #endif - } - else if (quat1 && (((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) { - /* QUAT *= FLOAT */ - mul_qt_fl(quat1->quat, scalar); - } - else { - PyErr_Format(PyExc_TypeError, - "Element-wise multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); - return NULL; - } - - (void)BaseMath_WriteCallback(quat1); - Py_INCREF(q1); - return q1; + } + else if (quat1 && (((scalar = PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred()) == 0)) { + /* QUAT *= FLOAT */ + mul_qt_fl(quat1->quat, scalar); + } + else { + PyErr_Format(PyExc_TypeError, + "Element-wise multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(q1)->tp_name, + Py_TYPE(q2)->tp_name); + return NULL; + } + + (void)BaseMath_WriteCallback(quat1); + Py_INCREF(q1); + return q1; } /*------------------------obj @ obj------------------------------ * quaternion multiplication */ static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2) { - float quat[QUAT_SIZE]; - QuaternionObject *quat1 = NULL, *quat2 = NULL; - - if (QuaternionObject_Check(q1)) { - quat1 = (QuaternionObject *)q1; - if (BaseMath_ReadCallback(quat1) == -1) { - return NULL; - } - } - if (QuaternionObject_Check(q2)) { - quat2 = (QuaternionObject *)q2; - if (BaseMath_ReadCallback(quat2) == -1) { - return NULL; - } - } - - if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */ - mul_qt_qtqt(quat, quat1->quat, quat2->quat); - return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); - } - else if (quat1) { - /* QUAT @ VEC */ - if (VectorObject_Check(q2)) { - VectorObject *vec2 = (VectorObject *)q2; - float tvec[3]; - - if (vec2->size != 3) { - PyErr_SetString(PyExc_ValueError, - "Vector multiplication: " - "only 3D vector rotations (with quats) " - "currently supported"); - return NULL; - } - if (BaseMath_ReadCallback(vec2) == -1) { - return NULL; - } - - copy_v3_v3(tvec, vec2->vec); - mul_qt_v3(quat1->quat, tvec); - - return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2)); - } - } - - PyErr_Format(PyExc_TypeError, - "Quaternion multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); - return NULL; + float quat[QUAT_SIZE]; + QuaternionObject *quat1 = NULL, *quat2 = NULL; + + if (QuaternionObject_Check(q1)) { + quat1 = (QuaternionObject *)q1; + if (BaseMath_ReadCallback(quat1) == -1) { + return NULL; + } + } + if (QuaternionObject_Check(q2)) { + quat2 = (QuaternionObject *)q2; + if (BaseMath_ReadCallback(quat2) == -1) { + return NULL; + } + } + + if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */ + mul_qt_qtqt(quat, quat1->quat, quat2->quat); + return Quaternion_CreatePyObject(quat, Py_TYPE(q1)); + } + else if (quat1) { + /* QUAT @ VEC */ + if (VectorObject_Check(q2)) { + VectorObject *vec2 = (VectorObject *)q2; + float tvec[3]; + + if (vec2->size != 3) { + PyErr_SetString(PyExc_ValueError, + "Vector multiplication: " + "only 3D vector rotations (with quats) " + "currently supported"); + return NULL; + } + if (BaseMath_ReadCallback(vec2) == -1) { + return NULL; + } + + copy_v3_v3(tvec, vec2->vec); + mul_qt_v3(quat1->quat, tvec); + + return Vector_CreatePyObject(tvec, 3, Py_TYPE(vec2)); + } + } + + PyErr_Format(PyExc_TypeError, + "Quaternion multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(q1)->tp_name, + Py_TYPE(q2)->tp_name); + return NULL; } /*------------------------obj @= obj------------------------------ * inplace quaternion multiplication */ static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2) { - float quat[QUAT_SIZE]; - QuaternionObject *quat1 = NULL, *quat2 = NULL; - - if (QuaternionObject_Check(q1)) { - quat1 = (QuaternionObject *)q1; - if (BaseMath_ReadCallback(quat1) == -1) { - return NULL; - } - } - if (QuaternionObject_Check(q2)) { - quat2 = (QuaternionObject *)q2; - if (BaseMath_ReadCallback(quat2) == -1) { - return NULL; - } - } - - if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */ - mul_qt_qtqt(quat, quat1->quat, quat2->quat); - copy_qt_qt(quat1->quat, quat); - } - else { - PyErr_Format(PyExc_TypeError, - "Inplace quaternion multiplication: " - "not supported between '%.200s' and '%.200s' types", - Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); - return NULL; - } - - (void)BaseMath_WriteCallback(quat1); - Py_INCREF(q1); - return q1; + float quat[QUAT_SIZE]; + QuaternionObject *quat1 = NULL, *quat2 = NULL; + + if (QuaternionObject_Check(q1)) { + quat1 = (QuaternionObject *)q1; + if (BaseMath_ReadCallback(quat1) == -1) { + return NULL; + } + } + if (QuaternionObject_Check(q2)) { + quat2 = (QuaternionObject *)q2; + if (BaseMath_ReadCallback(quat2) == -1) { + return NULL; + } + } + + if (quat1 && quat2) { /* QUAT @ QUAT (cross product) */ + mul_qt_qtqt(quat, quat1->quat, quat2->quat); + copy_qt_qt(quat1->quat, quat); + } + else { + PyErr_Format(PyExc_TypeError, + "Inplace quaternion multiplication: " + "not supported between '%.200s' and '%.200s' types", + Py_TYPE(q1)->tp_name, + Py_TYPE(q2)->tp_name); + return NULL; + } + + (void)BaseMath_WriteCallback(quat1); + Py_INCREF(q1); + return q1; } /* -obj * returns the negative of this object*/ static PyObject *Quaternion_neg(QuaternionObject *self) { - float tquat[QUAT_SIZE]; + float tquat[QUAT_SIZE]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - negate_v4_v4(tquat, self->quat); - return Quaternion_CreatePyObject(tquat, Py_TYPE(self)); + negate_v4_v4(tquat, self->quat); + return Quaternion_CreatePyObject(tquat, Py_TYPE(self)); } - /* -----------------PROTOCOL DECLARATIONS-------------------------- */ static PySequenceMethods Quaternion_SeqMethods = { - (lenfunc) Quaternion_len, /* sq_length */ - (binaryfunc) NULL, /* sq_concat */ - (ssizeargfunc) NULL, /* sq_repeat */ - (ssizeargfunc) Quaternion_item, /* sq_item */ - (ssizessizeargfunc) NULL, /* sq_slice, deprecated */ - (ssizeobjargproc) Quaternion_ass_item, /* sq_ass_item */ - (ssizessizeobjargproc) NULL, /* sq_ass_slice, deprecated */ - (objobjproc) NULL, /* sq_contains */ - (binaryfunc) NULL, /* sq_inplace_concat */ - (ssizeargfunc) NULL, /* sq_inplace_repeat */ + (lenfunc)Quaternion_len, /* sq_length */ + (binaryfunc)NULL, /* sq_concat */ + (ssizeargfunc)NULL, /* sq_repeat */ + (ssizeargfunc)Quaternion_item, /* sq_item */ + (ssizessizeargfunc)NULL, /* sq_slice, deprecated */ + (ssizeobjargproc)Quaternion_ass_item, /* sq_ass_item */ + (ssizessizeobjargproc)NULL, /* sq_ass_slice, deprecated */ + (objobjproc)NULL, /* sq_contains */ + (binaryfunc)NULL, /* sq_inplace_concat */ + (ssizeargfunc)NULL, /* sq_inplace_repeat */ }; static PyMappingMethods Quaternion_AsMapping = { - (lenfunc)Quaternion_len, - (binaryfunc)Quaternion_subscript, - (objobjargproc)Quaternion_ass_subscript, + (lenfunc)Quaternion_len, + (binaryfunc)Quaternion_subscript, + (objobjargproc)Quaternion_ass_subscript, }; static PyNumberMethods Quaternion_NumMethods = { - (binaryfunc) Quaternion_add, /*nb_add*/ - (binaryfunc) Quaternion_sub, /*nb_subtract*/ - (binaryfunc) Quaternion_mul, /*nb_multiply*/ - NULL, /*nb_remainder*/ - NULL, /*nb_divmod*/ - NULL, /*nb_power*/ - (unaryfunc) Quaternion_neg, /*nb_negative*/ - (unaryfunc) Quaternion_copy,/*tp_positive*/ - (unaryfunc) 0, /*tp_absolute*/ - (inquiry) 0, /*tp_bool*/ - (unaryfunc) 0, /*nb_invert*/ - NULL, /*nb_lshift*/ - (binaryfunc)0, /*nb_rshift*/ - NULL, /*nb_and*/ - NULL, /*nb_xor*/ - NULL, /*nb_or*/ - NULL, /*nb_int*/ - NULL, /*nb_reserved*/ - NULL, /*nb_float*/ - NULL, /* nb_inplace_add */ - NULL, /* nb_inplace_subtract */ - (binaryfunc) Quaternion_imul, /* nb_inplace_multiply */ - NULL, /* nb_inplace_remainder */ - NULL, /* nb_inplace_power */ - NULL, /* nb_inplace_lshift */ - NULL, /* nb_inplace_rshift */ - NULL, /* nb_inplace_and */ - NULL, /* nb_inplace_xor */ - NULL, /* nb_inplace_or */ - NULL, /* nb_floor_divide */ - NULL, /* nb_true_divide */ - NULL, /* nb_inplace_floor_divide */ - NULL, /* nb_inplace_true_divide */ - NULL, /* nb_index */ - (binaryfunc) Quaternion_matmul, /* nb_matrix_multiply */ - (binaryfunc) Quaternion_imatmul, /* nb_inplace_matrix_multiply */ + (binaryfunc)Quaternion_add, /*nb_add*/ + (binaryfunc)Quaternion_sub, /*nb_subtract*/ + (binaryfunc)Quaternion_mul, /*nb_multiply*/ + NULL, /*nb_remainder*/ + NULL, /*nb_divmod*/ + NULL, /*nb_power*/ + (unaryfunc)Quaternion_neg, /*nb_negative*/ + (unaryfunc)Quaternion_copy, /*tp_positive*/ + (unaryfunc)0, /*tp_absolute*/ + (inquiry)0, /*tp_bool*/ + (unaryfunc)0, /*nb_invert*/ + NULL, /*nb_lshift*/ + (binaryfunc)0, /*nb_rshift*/ + NULL, /*nb_and*/ + NULL, /*nb_xor*/ + NULL, /*nb_or*/ + NULL, /*nb_int*/ + NULL, /*nb_reserved*/ + NULL, /*nb_float*/ + NULL, /* nb_inplace_add */ + NULL, /* nb_inplace_subtract */ + (binaryfunc)Quaternion_imul, /* nb_inplace_multiply */ + NULL, /* nb_inplace_remainder */ + NULL, /* nb_inplace_power */ + NULL, /* nb_inplace_lshift */ + NULL, /* nb_inplace_rshift */ + NULL, /* nb_inplace_and */ + NULL, /* nb_inplace_xor */ + NULL, /* nb_inplace_or */ + NULL, /* nb_floor_divide */ + NULL, /* nb_true_divide */ + NULL, /* nb_inplace_floor_divide */ + NULL, /* nb_inplace_true_divide */ + NULL, /* nb_index */ + (binaryfunc)Quaternion_matmul, /* nb_matrix_multiply */ + (binaryfunc)Quaternion_imatmul, /* nb_inplace_matrix_multiply */ }; -PyDoc_STRVAR(Quaternion_axis_doc, -"Quaternion axis value.\n\n:type: float" -); +PyDoc_STRVAR(Quaternion_axis_doc, "Quaternion axis value.\n\n:type: float"); static PyObject *Quaternion_axis_get(QuaternionObject *self, void *type) { - return Quaternion_item(self, POINTER_AS_INT(type)); + return Quaternion_item(self, POINTER_AS_INT(type)); } static int Quaternion_axis_set(QuaternionObject *self, PyObject *value, void *type) { - return Quaternion_ass_item(self, POINTER_AS_INT(type), value); + return Quaternion_ass_item(self, POINTER_AS_INT(type), value); } -PyDoc_STRVAR(Quaternion_magnitude_doc, -"Size of the quaternion (read-only).\n\n:type: float" -); +PyDoc_STRVAR(Quaternion_magnitude_doc, "Size of the quaternion (read-only).\n\n:type: float"); static PyObject *Quaternion_magnitude_get(QuaternionObject *self, void *UNUSED(closure)) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return PyFloat_FromDouble(sqrtf(dot_qtqt(self->quat, self->quat))); + return PyFloat_FromDouble(sqrtf(dot_qtqt(self->quat, self->quat))); } -PyDoc_STRVAR(Quaternion_angle_doc, -"Angle of the quaternion.\n\n:type: float" -); +PyDoc_STRVAR(Quaternion_angle_doc, "Angle of the quaternion.\n\n:type: float"); static PyObject *Quaternion_angle_get(QuaternionObject *self, void *UNUSED(closure)) { - float tquat[4]; - float angle; + float tquat[4]; + float angle; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - normalize_qt_qt(tquat, self->quat); + normalize_qt_qt(tquat, self->quat); - angle = 2.0f * saacos(tquat[0]); + angle = 2.0f * saacos(tquat[0]); - quat__axis_angle_sanitize(NULL, &angle); + quat__axis_angle_sanitize(NULL, &angle); - return PyFloat_FromDouble(angle); + return PyFloat_FromDouble(angle); } static int Quaternion_angle_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure)) { - float tquat[4]; - float len; + float tquat[4]; + float len; - float axis[3], angle_dummy; - float angle; + float axis[3], angle_dummy; + float angle; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - len = normalize_qt_qt(tquat, self->quat); - quat_to_axis_angle(axis, &angle_dummy, tquat); + len = normalize_qt_qt(tquat, self->quat); + quat_to_axis_angle(axis, &angle_dummy, tquat); - angle = PyFloat_AsDouble(value); + angle = PyFloat_AsDouble(value); - if (angle == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ - PyErr_SetString(PyExc_TypeError, - "Quaternion.angle = value: float expected"); - return -1; - } + if (angle == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, "Quaternion.angle = value: float expected"); + return -1; + } - angle = angle_wrap_rad(angle); + angle = angle_wrap_rad(angle); - quat__axis_angle_sanitize(axis, &angle); + quat__axis_angle_sanitize(axis, &angle); - axis_angle_to_quat(self->quat, axis, angle); - mul_qt_fl(self->quat, len); + axis_angle_to_quat(self->quat, axis, angle); + mul_qt_fl(self->quat, len); - if (BaseMath_WriteCallback(self) == -1) { - return -1; - } + if (BaseMath_WriteCallback(self) == -1) { + return -1; + } - return 0; + return 0; } -PyDoc_STRVAR(Quaternion_axis_vector_doc, -"Quaternion axis as a vector.\n\n:type: :class:`Vector`" -); +PyDoc_STRVAR(Quaternion_axis_vector_doc, "Quaternion axis as a vector.\n\n:type: :class:`Vector`"); static PyObject *Quaternion_axis_vector_get(QuaternionObject *self, void *UNUSED(closure)) { - float tquat[4]; + float tquat[4]; - float axis[3]; - float angle_dummy; + float axis[3]; + float angle_dummy; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - normalize_qt_qt(tquat, self->quat); - quat_to_axis_angle(axis, &angle_dummy, tquat); + normalize_qt_qt(tquat, self->quat); + quat_to_axis_angle(axis, &angle_dummy, tquat); - quat__axis_angle_sanitize(axis, NULL); + quat__axis_angle_sanitize(axis, NULL); - return Vector_CreatePyObject(axis, 3, NULL); + return Vector_CreatePyObject(axis, 3, NULL); } -static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, void *UNUSED(closure)) +static int Quaternion_axis_vector_set(QuaternionObject *self, + PyObject *value, + void *UNUSED(closure)) { - float tquat[4]; - float len; + float tquat[4]; + float len; - float axis[3]; - float angle; + float axis[3]; + float angle; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - len = normalize_qt_qt(tquat, self->quat); - quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */ + len = normalize_qt_qt(tquat, self->quat); + quat_to_axis_angle(axis, &angle, tquat); /* axis value is unused */ - if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1) { - return -1; - } + if (mathutils_array_parse(axis, 3, 3, value, "quat.axis = other") == -1) { + return -1; + } - quat__axis_angle_sanitize(axis, &angle); + quat__axis_angle_sanitize(axis, &angle); - axis_angle_to_quat(self->quat, axis, angle); - mul_qt_fl(self->quat, len); + axis_angle_to_quat(self->quat, axis, angle); + mul_qt_fl(self->quat, len); - if (BaseMath_WriteCallback(self) == -1) { - return -1; - } + if (BaseMath_WriteCallback(self) == -1) { + return -1; + } - return 0; + return 0; } /* ----------------------------------mathutils.Quaternion() -------------- */ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *seq = NULL; - double angle = 0.0f; - float quat[QUAT_SIZE]; - unit_qt(quat); - - if (kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, - "mathutils.Quaternion(): " - "takes no keyword args"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) { - return NULL; - } - - switch (PyTuple_GET_SIZE(args)) { - case 0: - break; - case 1: - { - int size; - - if ((size = mathutils_array_parse(quat, 3, QUAT_SIZE, seq, "mathutils.Quaternion()")) == -1) { - return NULL; - } - - if (size == 4) { - /* 4d: Quaternion (common case) */ - } - else { - /* 3d: Interpret as exponential map */ - BLI_assert(size == 3); - expmap_to_quat(quat, quat); - } - - break; - } - case 2: - { - float axis[3]; - if (mathutils_array_parse(axis, 3, 3, seq, "mathutils.Quaternion()") == -1) { - return NULL; - } - angle = angle_wrap_rad(angle); /* clamp because of precision issues */ - axis_angle_to_quat(quat, axis, angle); - break; - /* PyArg_ParseTuple assures no more than 2 */ - } - } - return Quaternion_CreatePyObject(quat, type); + PyObject *seq = NULL; + double angle = 0.0f; + float quat[QUAT_SIZE]; + unit_qt(quat); + + if (kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "mathutils.Quaternion(): " + "takes no keyword args"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) { + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 1: { + int size; + + if ((size = mathutils_array_parse(quat, 3, QUAT_SIZE, seq, "mathutils.Quaternion()")) == + -1) { + return NULL; + } + + if (size == 4) { + /* 4d: Quaternion (common case) */ + } + else { + /* 3d: Interpret as exponential map */ + BLI_assert(size == 3); + expmap_to_quat(quat, quat); + } + + break; + } + case 2: { + float axis[3]; + if (mathutils_array_parse(axis, 3, 3, seq, "mathutils.Quaternion()") == -1) { + return NULL; + } + angle = angle_wrap_rad(angle); /* clamp because of precision issues */ + axis_angle_to_quat(quat, axis, angle); + break; + /* PyArg_ParseTuple assures no more than 2 */ + } + } + return Quaternion_CreatePyObject(quat, type); } static PyObject *quat__apply_to_copy(PyNoArgsFunction quat_func, QuaternionObject *self) { - PyObject *ret = Quaternion_copy(self); - PyObject *ret_dummy = quat_func(ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); - return ret; - } - else { /* error */ - Py_DECREF(ret); - return NULL; - } + PyObject *ret = Quaternion_copy(self); + PyObject *ret_dummy = quat_func(ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); + return ret; + } + else { /* error */ + Py_DECREF(ret); + return NULL; + } } /* axis vector suffers from precision errors, use this function to ensure */ static void quat__axis_angle_sanitize(float axis[3], float *angle) { - if (axis) { - if (is_zero_v3(axis) || - !isfinite(axis[0]) || - !isfinite(axis[1]) || - !isfinite(axis[2])) - { - axis[0] = 1.0f; - axis[1] = 0.0f; - axis[2] = 0.0f; - } - else if (EXPP_FloatsAreEqual(axis[0], 0.0f, 10) && - EXPP_FloatsAreEqual(axis[1], 0.0f, 10) && - EXPP_FloatsAreEqual(axis[2], 0.0f, 10)) - { - axis[0] = 1.0f; - } - } - - if (angle) { - if (!isfinite(*angle)) { - *angle = 0.0f; - } - } + if (axis) { + if (is_zero_v3(axis) || !isfinite(axis[0]) || !isfinite(axis[1]) || !isfinite(axis[2])) { + axis[0] = 1.0f; + axis[1] = 0.0f; + axis[2] = 0.0f; + } + else if (EXPP_FloatsAreEqual(axis[0], 0.0f, 10) && EXPP_FloatsAreEqual(axis[1], 0.0f, 10) && + EXPP_FloatsAreEqual(axis[2], 0.0f, 10)) { + axis[0] = 1.0f; + } + } + + if (angle) { + if (!isfinite(*angle)) { + *angle = 0.0f; + } + } } /* -----------------------METHOD DEFINITIONS ---------------------- */ static struct PyMethodDef Quaternion_methods[] = { - /* in place only */ - {"identity", (PyCFunction) Quaternion_identity, METH_NOARGS, Quaternion_identity_doc}, - {"negate", (PyCFunction) Quaternion_negate, METH_NOARGS, Quaternion_negate_doc}, - - /* operate on original or copy */ - {"conjugate", (PyCFunction) Quaternion_conjugate, METH_NOARGS, Quaternion_conjugate_doc}, - {"conjugated", (PyCFunction) Quaternion_conjugated, METH_NOARGS, Quaternion_conjugated_doc}, - - {"invert", (PyCFunction) Quaternion_invert, METH_NOARGS, Quaternion_invert_doc}, - {"inverted", (PyCFunction) Quaternion_inverted, METH_NOARGS, Quaternion_inverted_doc}, - - {"normalize", (PyCFunction) Quaternion_normalize, METH_NOARGS, Quaternion_normalize_doc}, - {"normalized", (PyCFunction) Quaternion_normalized, METH_NOARGS, Quaternion_normalized_doc}, - - /* return converted representation */ - {"to_euler", (PyCFunction) Quaternion_to_euler, METH_VARARGS, Quaternion_to_euler_doc}, - {"to_matrix", (PyCFunction) Quaternion_to_matrix, METH_NOARGS, Quaternion_to_matrix_doc}, - {"to_axis_angle", (PyCFunction) Quaternion_to_axis_angle, METH_NOARGS, Quaternion_to_axis_angle_doc}, - {"to_exponential_map", (PyCFunction) Quaternion_to_exponential_map, METH_NOARGS, Quaternion_to_exponential_map_doc}, - - /* operation between 2 or more types */ - {"cross", (PyCFunction) Quaternion_cross, METH_O, Quaternion_cross_doc}, - {"dot", (PyCFunction) Quaternion_dot, METH_O, Quaternion_dot_doc}, - {"rotation_difference", (PyCFunction) Quaternion_rotation_difference, METH_O, Quaternion_rotation_difference_doc}, - {"slerp", (PyCFunction) Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc}, - {"rotate", (PyCFunction) Quaternion_rotate, METH_O, Quaternion_rotate_doc}, - - /* base-math methods */ - {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, - - {"copy", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, - {"__copy__", (PyCFunction) Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, - {"__deepcopy__", (PyCFunction) Quaternion_deepcopy, METH_VARARGS, Quaternion_copy_doc}, - {NULL, NULL, 0, NULL}, + /* in place only */ + {"identity", (PyCFunction)Quaternion_identity, METH_NOARGS, Quaternion_identity_doc}, + {"negate", (PyCFunction)Quaternion_negate, METH_NOARGS, Quaternion_negate_doc}, + + /* operate on original or copy */ + {"conjugate", (PyCFunction)Quaternion_conjugate, METH_NOARGS, Quaternion_conjugate_doc}, + {"conjugated", (PyCFunction)Quaternion_conjugated, METH_NOARGS, Quaternion_conjugated_doc}, + + {"invert", (PyCFunction)Quaternion_invert, METH_NOARGS, Quaternion_invert_doc}, + {"inverted", (PyCFunction)Quaternion_inverted, METH_NOARGS, Quaternion_inverted_doc}, + + {"normalize", (PyCFunction)Quaternion_normalize, METH_NOARGS, Quaternion_normalize_doc}, + {"normalized", (PyCFunction)Quaternion_normalized, METH_NOARGS, Quaternion_normalized_doc}, + + /* return converted representation */ + {"to_euler", (PyCFunction)Quaternion_to_euler, METH_VARARGS, Quaternion_to_euler_doc}, + {"to_matrix", (PyCFunction)Quaternion_to_matrix, METH_NOARGS, Quaternion_to_matrix_doc}, + {"to_axis_angle", + (PyCFunction)Quaternion_to_axis_angle, + METH_NOARGS, + Quaternion_to_axis_angle_doc}, + {"to_exponential_map", + (PyCFunction)Quaternion_to_exponential_map, + METH_NOARGS, + Quaternion_to_exponential_map_doc}, + + /* operation between 2 or more types */ + {"cross", (PyCFunction)Quaternion_cross, METH_O, Quaternion_cross_doc}, + {"dot", (PyCFunction)Quaternion_dot, METH_O, Quaternion_dot_doc}, + {"rotation_difference", + (PyCFunction)Quaternion_rotation_difference, + METH_O, + Quaternion_rotation_difference_doc}, + {"slerp", (PyCFunction)Quaternion_slerp, METH_VARARGS, Quaternion_slerp_doc}, + {"rotate", (PyCFunction)Quaternion_rotate, METH_O, Quaternion_rotate_doc}, + + /* base-math methods */ + {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, + + {"copy", (PyCFunction)Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, + {"__copy__", (PyCFunction)Quaternion_copy, METH_NOARGS, Quaternion_copy_doc}, + {"__deepcopy__", (PyCFunction)Quaternion_deepcopy, METH_VARARGS, Quaternion_copy_doc}, + {NULL, NULL, 0, NULL}, }; /*****************************************************************************/ /* Python attributes get/set structure: */ /*****************************************************************************/ static PyGetSetDef Quaternion_getseters[] = { - {(char *)"w", (getter)Quaternion_axis_get, (setter)Quaternion_axis_set, Quaternion_axis_doc, (void *)0}, - {(char *)"x", (getter)Quaternion_axis_get, (setter)Quaternion_axis_set, Quaternion_axis_doc, (void *)1}, - {(char *)"y", (getter)Quaternion_axis_get, (setter)Quaternion_axis_set, Quaternion_axis_doc, (void *)2}, - {(char *)"z", (getter)Quaternion_axis_get, (setter)Quaternion_axis_set, Quaternion_axis_doc, (void *)3}, - {(char *)"magnitude", (getter)Quaternion_magnitude_get, (setter)NULL, Quaternion_magnitude_doc, NULL}, - {(char *)"angle", (getter)Quaternion_angle_get, (setter)Quaternion_angle_set, Quaternion_angle_doc, NULL}, - {(char *)"axis", (getter)Quaternion_axis_vector_get, (setter)Quaternion_axis_vector_set, Quaternion_axis_vector_doc, NULL}, - {(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL}, - {(char *)"is_frozen", (getter)BaseMathObject_is_frozen_get, (setter)NULL, BaseMathObject_is_frozen_doc, NULL}, - {(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL}, - {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ + {(char *)"w", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)0}, + {(char *)"x", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)1}, + {(char *)"y", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)2}, + {(char *)"z", + (getter)Quaternion_axis_get, + (setter)Quaternion_axis_set, + Quaternion_axis_doc, + (void *)3}, + {(char *)"magnitude", + (getter)Quaternion_magnitude_get, + (setter)NULL, + Quaternion_magnitude_doc, + NULL}, + {(char *)"angle", + (getter)Quaternion_angle_get, + (setter)Quaternion_angle_set, + Quaternion_angle_doc, + NULL}, + {(char *)"axis", + (getter)Quaternion_axis_vector_get, + (setter)Quaternion_axis_vector_set, + Quaternion_axis_vector_doc, + NULL}, + {(char *)"is_wrapped", + (getter)BaseMathObject_is_wrapped_get, + (setter)NULL, + BaseMathObject_is_wrapped_doc, + NULL}, + {(char *)"is_frozen", + (getter)BaseMathObject_is_frozen_get, + (setter)NULL, + BaseMathObject_is_frozen_doc, + NULL}, + {(char *)"owner", + (getter)BaseMathObject_owner_get, + (setter)NULL, + BaseMathObject_owner_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL} /* Sentinel */ }; /* ------------------PY_OBECT DEFINITION-------------------------- */ PyDoc_STRVAR(quaternion_doc, -".. class:: Quaternion([seq, [angle]])\n" -"\n" -" This object gives access to Quaternions in Blender.\n" -"\n" -" :param seq: size 3 or 4\n" -" :type seq: :class:`Vector`\n" -" :param angle: rotation angle, in radians\n" -" :type angle: float\n" -"\n" -" The constructor takes arguments in various forms:\n" -"\n" -" (), *no args*\n" -" Create an identity quaternion\n" -" (*wxyz*)\n" -" Create a quaternion from a ``(w, x, y, z)`` vector.\n" -" (*exponential_map*)\n" -" Create a quaternion from a 3d exponential map vector.\n" -"\n" -" .. seealso:: :meth:`to_exponential_map`\n" -" (*axis, angle*)\n" -" Create a quaternion representing a rotation of *angle* radians over *axis*.\n" -"\n" -" .. seealso:: :meth:`to_axis_angle`\n" -); + ".. class:: Quaternion([seq, [angle]])\n" + "\n" + " This object gives access to Quaternions in Blender.\n" + "\n" + " :param seq: size 3 or 4\n" + " :type seq: :class:`Vector`\n" + " :param angle: rotation angle, in radians\n" + " :type angle: float\n" + "\n" + " The constructor takes arguments in various forms:\n" + "\n" + " (), *no args*\n" + " Create an identity quaternion\n" + " (*wxyz*)\n" + " Create a quaternion from a ``(w, x, y, z)`` vector.\n" + " (*exponential_map*)\n" + " Create a quaternion from a 3d exponential map vector.\n" + "\n" + " .. seealso:: :meth:`to_exponential_map`\n" + " (*axis, angle*)\n" + " Create a quaternion representing a rotation of *angle* radians over *axis*.\n" + "\n" + " .. seealso:: :meth:`to_axis_angle`\n"); PyTypeObject quaternion_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "Quaternion", /* tp_name */ - sizeof(QuaternionObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)BaseMathObject_dealloc, /* tp_dealloc */ - NULL, /* tp_print */ - NULL, /* tp_getattr */ - NULL, /* tp_setattr */ - NULL, /* tp_compare */ - (reprfunc) Quaternion_repr, /* tp_repr */ - &Quaternion_NumMethods, /* tp_as_number */ - &Quaternion_SeqMethods, /* tp_as_sequence */ - &Quaternion_AsMapping, /* tp_as_mapping */ - (hashfunc)Quaternion_hash, /* tp_hash */ - NULL, /* tp_call */ + PyVarObject_HEAD_INIT(NULL, 0) "Quaternion", /* tp_name */ + sizeof(QuaternionObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)BaseMathObject_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + (reprfunc)Quaternion_repr, /* tp_repr */ + &Quaternion_NumMethods, /* tp_as_number */ + &Quaternion_SeqMethods, /* tp_as_sequence */ + &Quaternion_AsMapping, /* tp_as_mapping */ + (hashfunc)Quaternion_hash, /* tp_hash */ + NULL, /* tp_call */ #ifndef MATH_STANDALONE - (reprfunc) Quaternion_str, /* tp_str */ + (reprfunc)Quaternion_str, /* tp_str */ #else - NULL, /* tp_str */ + NULL, /* tp_str */ #endif - NULL, /* tp_getattro */ - NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - quaternion_doc, /* tp_doc */ - (traverseproc)BaseMathObject_traverse, /* tp_traverse */ - (inquiry)BaseMathObject_clear, /* tp_clear */ - (richcmpfunc)Quaternion_richcmpr, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - NULL, /* tp_iter */ - NULL, /* tp_iternext */ - Quaternion_methods, /* tp_methods */ - NULL, /* tp_members */ - Quaternion_getseters, /* tp_getset */ - NULL, /* tp_base */ - NULL, /* tp_dict */ - NULL, /* tp_descr_get */ - NULL, /* tp_descr_set */ - 0, /* tp_dictoffset */ - NULL, /* tp_init */ - NULL, /* tp_alloc */ - Quaternion_new, /* tp_new */ - NULL, /* tp_free */ - NULL, /* tp_is_gc */ - NULL, /* tp_bases */ - NULL, /* tp_mro */ - NULL, /* tp_cache */ - NULL, /* tp_subclasses */ - NULL, /* tp_weaklist */ - NULL, /* tp_del */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */ + quaternion_doc, /* tp_doc */ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + (inquiry)BaseMathObject_clear, /* tp_clear */ + (richcmpfunc)Quaternion_richcmpr, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + Quaternion_methods, /* tp_methods */ + NULL, /* tp_members */ + Quaternion_getseters, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + NULL, /* tp_alloc */ + Quaternion_new, /* tp_new */ + NULL, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + NULL, /* tp_del */ }; -PyObject *Quaternion_CreatePyObject( - const float quat[4], - PyTypeObject *base_type) +PyObject *Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type) { - QuaternionObject *self; - float *quat_alloc; - - quat_alloc = PyMem_Malloc(QUAT_SIZE * sizeof(float)); - if (UNLIKELY(quat_alloc == NULL)) { - PyErr_SetString(PyExc_MemoryError, - "Quaternion(): " - "problem allocating data"); - return NULL; - } - - self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type); - if (self) { - self->quat = quat_alloc; - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; - - /* NEW */ - if (!quat) { /* new empty */ - unit_qt(self->quat); - } - else { - copy_qt_qt(self->quat, quat); - } - self->flag = BASE_MATH_FLAG_DEFAULT; - } - else { - PyMem_Free(quat_alloc); - } - - return (PyObject *)self; + QuaternionObject *self; + float *quat_alloc; + + quat_alloc = PyMem_Malloc(QUAT_SIZE * sizeof(float)); + if (UNLIKELY(quat_alloc == NULL)) { + PyErr_SetString(PyExc_MemoryError, + "Quaternion(): " + "problem allocating data"); + return NULL; + } + + self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type); + if (self) { + self->quat = quat_alloc; + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; + + /* NEW */ + if (!quat) { /* new empty */ + unit_qt(self->quat); + } + else { + copy_qt_qt(self->quat, quat); + } + self->flag = BASE_MATH_FLAG_DEFAULT; + } + else { + PyMem_Free(quat_alloc); + } + + return (PyObject *)self; } -PyObject *Quaternion_CreatePyObject_wrap( - float quat[4], - PyTypeObject *base_type) +PyObject *Quaternion_CreatePyObject_wrap(float quat[4], PyTypeObject *base_type) { - QuaternionObject *self; - - self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type); - if (self) { - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; - - /* WRAP */ - self->quat = quat; - self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; - } - return (PyObject *) self; + QuaternionObject *self; + + self = BASE_MATH_NEW(QuaternionObject, quaternion_Type, base_type); + if (self) { + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; + + /* WRAP */ + self->quat = quat; + self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; + } + return (PyObject *)self; } PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user, - unsigned char cb_type, unsigned char cb_subtype) + unsigned char cb_type, + unsigned char cb_subtype) { - QuaternionObject *self = (QuaternionObject *)Quaternion_CreatePyObject(NULL, NULL); - if (self) { - Py_INCREF(cb_user); - self->cb_user = cb_user; - self->cb_type = cb_type; - self->cb_subtype = cb_subtype; - PyObject_GC_Track(self); - } - - return (PyObject *)self; + QuaternionObject *self = (QuaternionObject *)Quaternion_CreatePyObject(NULL, NULL); + if (self) { + Py_INCREF(cb_user); + self->cb_user = cb_user; + self->cb_type = cb_type; + self->cb_subtype = cb_subtype; + PyObject_GC_Track(self); + } + + return (PyObject *)self; } diff --git a/source/blender/python/mathutils/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h index a4c55fffccc..bc6bd307ece 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.h +++ b/source/blender/python/mathutils/mathutils_Quaternion.h @@ -27,7 +27,7 @@ extern PyTypeObject quaternion_Type; #define QuaternionObject_CheckExact(v) (Py_TYPE(v) == &quaternion_Type) typedef struct { - BASE_MATH_MEMBERS(quat); + BASE_MATH_MEMBERS(quat); } QuaternionObject; /* struct data contains a pointer to the actual data that the @@ -36,17 +36,13 @@ typedef struct { * blender (stored in blend_data). This is an either/or struct not both */ /* prototypes */ -PyObject *Quaternion_CreatePyObject( - const float quat[4], - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT; -PyObject *Quaternion_CreatePyObject_wrap( - float quat[4], - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -PyObject *Quaternion_CreatePyObject_cb( - PyObject *cb_user, - unsigned char cb_type, unsigned char cb_subtype - ) ATTR_WARN_UNUSED_RESULT; +PyObject *Quaternion_CreatePyObject(const float quat[4], + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; +PyObject *Quaternion_CreatePyObject_wrap(float quat[4], + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); +PyObject *Quaternion_CreatePyObject_cb(PyObject *cb_user, + unsigned char cb_type, + unsigned char cb_subtype) ATTR_WARN_UNUSED_RESULT; #endif /* __MATHUTILS_QUATERNION_H__ */ diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 1dd578096f9..7d73f165c1e 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #include #include "mathutils.h" @@ -44,12 +43,14 @@ * used as a sentinel: if it is unset, the axis is not valid. */ #define SWIZZLE_BITS_PER_AXIS 3 #define SWIZZLE_VALID_AXIS 0x4 -#define SWIZZLE_AXIS 0x3 +#define SWIZZLE_AXIS 0x3 static PyObject *Vector_copy(VectorObject *self); static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args); static PyObject *Vector_to_tuple_ext(VectorObject *self, int ndigits); -static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat); +static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], + VectorObject *vec, + MatrixObject *mat); /** * Supports 2D, 3D, and 4D vector objects both int and float values @@ -57,803 +58,780 @@ static int row_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject *v */ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - float *vec = NULL; - int size = 3; /* default to a 3D vector */ - - if (kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, - "Vector(): " - "takes no keyword args"); - return NULL; - } - - switch (PyTuple_GET_SIZE(args)) { - case 0: - vec = PyMem_Malloc(size * sizeof(float)); - - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector(): " - "problem allocating pointer space"); - return NULL; - } - - copy_vn_fl(vec, size, 0.0f); - break; - case 1: - if ((size = mathutils_array_parse_alloc(&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) { - return NULL; - } - break; - default: - PyErr_SetString(PyExc_TypeError, - "mathutils.Vector(): " - "more than a single arg given"); - return NULL; - } - return Vector_CreatePyObject_alloc(vec, size, type); + float *vec = NULL; + int size = 3; /* default to a 3D vector */ + + if (kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "Vector(): " + "takes no keyword args"); + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 0: + vec = PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector(): " + "problem allocating pointer space"); + return NULL; + } + + copy_vn_fl(vec, size, 0.0f); + break; + case 1: + if ((size = mathutils_array_parse_alloc( + &vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) { + return NULL; + } + break; + default: + PyErr_SetString(PyExc_TypeError, + "mathutils.Vector(): " + "more than a single arg given"); + return NULL; + } + return Vector_CreatePyObject_alloc(vec, size, type); } static PyObject *vec__apply_to_copy(PyNoArgsFunction vec_func, VectorObject *self) { - PyObject *ret = Vector_copy(self); - PyObject *ret_dummy = vec_func(ret); - if (ret_dummy) { - Py_DECREF(ret_dummy); - return (PyObject *)ret; - } - else { /* error */ - Py_DECREF(ret); - return NULL; - } + PyObject *ret = Vector_copy(self); + PyObject *ret_dummy = vec_func(ret); + if (ret_dummy) { + Py_DECREF(ret_dummy); + return (PyObject *)ret; + } + else { /* error */ + Py_DECREF(ret); + return NULL; + } } /*-----------------------CLASS-METHODS----------------------------*/ PyDoc_STRVAR(C_Vector_Fill_doc, -".. classmethod:: Fill(size, fill=0.0)\n" -"\n" -" Create a vector of length size with all values set to fill.\n" -"\n" -" :arg size: The length of the vector to be created.\n" -" :type size: int\n" -" :arg fill: The value used to fill the vector.\n" -" :type fill: float\n" -); + ".. classmethod:: Fill(size, fill=0.0)\n" + "\n" + " Create a vector of length size with all values set to fill.\n" + "\n" + " :arg size: The length of the vector to be created.\n" + " :type size: int\n" + " :arg fill: The value used to fill the vector.\n" + " :type fill: float\n"); static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args) { - float *vec; - int size; - float fill = 0.0f; + float *vec; + int size; + float fill = 0.0f; - if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) { + return NULL; + } - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector(): invalid size"); - return NULL; - } + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); + return NULL; + } - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(size * sizeof(float)); - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.Fill(): " - "problem allocating pointer space"); - return NULL; - } + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Fill(): " + "problem allocating pointer space"); + return NULL; + } - copy_vn_fl(vec, size, fill); + copy_vn_fl(vec, size, fill); - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); } PyDoc_STRVAR(C_Vector_Range_doc, -".. classmethod:: Range(start=0, stop, step=1)\n" -"\n" -" Create a filled with a range of values.\n" -"\n" -" :arg start: The start of the range used to fill the vector.\n" -" :type start: int\n" -" :arg stop: The end of the range used to fill the vector.\n" -" :type stop: int\n" -" :arg step: The step between successive values in the vector.\n" -" :type step: int\n" -); + ".. classmethod:: Range(start=0, stop, step=1)\n" + "\n" + " Create a filled with a range of values.\n" + "\n" + " :arg start: The start of the range used to fill the vector.\n" + " :type start: int\n" + " :arg stop: The end of the range used to fill the vector.\n" + " :type stop: int\n" + " :arg step: The step between successive values in the vector.\n" + " :type step: int\n"); static PyObject *C_Vector_Range(PyObject *cls, PyObject *args) { - float *vec; - int stop, size; - int start = 0; - int step = 1; - - if (!PyArg_ParseTuple(args, "i|ii:Vector.Range", &start, &stop, &step)) { - return NULL; - } - - switch (PyTuple_GET_SIZE(args)) { - case 1: - size = start; - start = 0; - break; - case 2: - if (start >= stop) { - PyErr_SetString(PyExc_RuntimeError, - "Start value is larger " - "than the stop value"); - return NULL; - } - - size = stop - start; - break; - default: - if (start >= stop) { - PyErr_SetString(PyExc_RuntimeError, - "Start value is larger " - "than the stop value"); - return NULL; - } - - size = (stop - start); - - if ((size % step) != 0) { - size += step; - } - - size /= step; - - break; - } - - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector(): invalid size"); - return NULL; - } - - vec = PyMem_Malloc(size * sizeof(float)); - - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.Range(): " - "problem allocating pointer space"); - return NULL; - } - - range_vn_fl(vec, size, (float)start, (float)step); - - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + float *vec; + int stop, size; + int start = 0; + int step = 1; + + if (!PyArg_ParseTuple(args, "i|ii:Vector.Range", &start, &stop, &step)) { + return NULL; + } + + switch (PyTuple_GET_SIZE(args)) { + case 1: + size = start; + start = 0; + break; + case 2: + if (start >= stop) { + PyErr_SetString(PyExc_RuntimeError, + "Start value is larger " + "than the stop value"); + return NULL; + } + + size = stop - start; + break; + default: + if (start >= stop) { + PyErr_SetString(PyExc_RuntimeError, + "Start value is larger " + "than the stop value"); + return NULL; + } + + size = (stop - start); + + if ((size % step) != 0) { + size += step; + } + + size /= step; + + break; + } + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); + return NULL; + } + + vec = PyMem_Malloc(size * sizeof(float)); + + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Range(): " + "problem allocating pointer space"); + return NULL; + } + + range_vn_fl(vec, size, (float)start, (float)step); + + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); } PyDoc_STRVAR(C_Vector_Linspace_doc, -".. classmethod:: Linspace(start, stop, size)\n" -"\n" -" Create a vector of the specified size which is filled with linearly spaced values between start and stop values.\n" -"\n" -" :arg start: The start of the range used to fill the vector.\n" -" :type start: int\n" -" :arg stop: The end of the range used to fill the vector.\n" -" :type stop: int\n" -" :arg size: The size of the vector to be created.\n" -" :type size: int\n" -); + ".. classmethod:: Linspace(start, stop, size)\n" + "\n" + " Create a vector of the specified size which is filled with linearly spaced " + "values between start and stop values.\n" + "\n" + " :arg start: The start of the range used to fill the vector.\n" + " :type start: int\n" + " :arg stop: The end of the range used to fill the vector.\n" + " :type stop: int\n" + " :arg size: The size of the vector to be created.\n" + " :type size: int\n"); static PyObject *C_Vector_Linspace(PyObject *cls, PyObject *args) { - float *vec; - int size; - float start, end, step; + float *vec; + int size; + float start, end, step; - if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &size)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "ffi:Vector.Linspace", &start, &end, &size)) { + return NULL; + } - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector.Linspace(): invalid size"); - return NULL; - } + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector.Linspace(): invalid size"); + return NULL; + } - step = (end - start) / (float)(size - 1); + step = (end - start) / (float)(size - 1); - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(size * sizeof(float)); - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.Linspace(): " - "problem allocating pointer space"); - return NULL; - } + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Linspace(): " + "problem allocating pointer space"); + return NULL; + } - range_vn_fl(vec, size, start, step); + range_vn_fl(vec, size, start, step); - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); } -PyDoc_STRVAR(C_Vector_Repeat_doc, -".. classmethod:: Repeat(vector, size)\n" -"\n" -" Create a vector by repeating the values in vector until the required size is reached.\n" -"\n" -" :arg tuple: The vector to draw values from.\n" -" :type tuple: :class:`mathutils.Vector`\n" -" :arg size: The size of the vector to be created.\n" -" :type size: int\n" -); +PyDoc_STRVAR( + C_Vector_Repeat_doc, + ".. classmethod:: Repeat(vector, size)\n" + "\n" + " Create a vector by repeating the values in vector until the required size is reached.\n" + "\n" + " :arg tuple: The vector to draw values from.\n" + " :type tuple: :class:`mathutils.Vector`\n" + " :arg size: The size of the vector to be created.\n" + " :type size: int\n"); static PyObject *C_Vector_Repeat(PyObject *cls, PyObject *args) { - float *vec; - float *iter_vec = NULL; - int i, size, value_size; - PyObject *value; + float *vec; + float *iter_vec = NULL; + int i, size, value_size; + PyObject *value; - if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &size)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "Oi:Vector.Repeat", &value, &size)) { + return NULL; + } - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector.Repeat(): invalid size"); - return NULL; - } + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector.Repeat(): invalid size"); + return NULL; + } - if ((value_size = mathutils_array_parse_alloc(&iter_vec, 2, value, - "Vector.Repeat(vector, size), invalid 'vector' arg")) == -1) - { - return NULL; - } + if ((value_size = mathutils_array_parse_alloc( + &iter_vec, 2, value, "Vector.Repeat(vector, size), invalid 'vector' arg")) == -1) { + return NULL; + } - if (iter_vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.Repeat(): " - "problem allocating pointer space"); - return NULL; - } + if (iter_vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.Repeat(): " + "problem allocating pointer space"); + return NULL; + } - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(size * sizeof(float)); - if (vec == NULL) { - PyMem_Free(iter_vec); - PyErr_SetString(PyExc_MemoryError, - "Vector.Repeat(): " - "problem allocating pointer space"); - return NULL; - } + if (vec == NULL) { + PyMem_Free(iter_vec); + PyErr_SetString(PyExc_MemoryError, + "Vector.Repeat(): " + "problem allocating pointer space"); + return NULL; + } - i = 0; - while (i < size) { - vec[i] = iter_vec[i % value_size]; - i++; - } + i = 0; + while (i < size) { + vec[i] = iter_vec[i % value_size]; + i++; + } - PyMem_Free(iter_vec); + PyMem_Free(iter_vec); - return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); + return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls); } /*-----------------------------METHODS---------------------------- */ PyDoc_STRVAR(Vector_zero_doc, -".. method:: zero()\n" -"\n" -" Set all values to zero.\n" -); + ".. method:: zero()\n" + "\n" + " Set all values to zero.\n"); static PyObject *Vector_zero(VectorObject *self) { - if (BaseMath_Prepare_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_Prepare_ForWrite(self) == -1) { + return NULL; + } - copy_vn_fl(self->vec, self->size, 0.0f); + copy_vn_fl(self->vec, self->size, 0.0f); - if (BaseMath_WriteCallback(self) == -1) { - return NULL; - } + if (BaseMath_WriteCallback(self) == -1) { + return NULL; + } - Py_RETURN_NONE; + Py_RETURN_NONE; } PyDoc_STRVAR(Vector_normalize_doc, -".. method:: normalize()\n" -"\n" -" Normalize the vector, making the length of the vector always 1.0.\n" -"\n" -" .. warning:: Normalizing a vector where all values are zero has no effect.\n" -"\n" -" .. note:: Normalize works for vectors of all sizes,\n" -" however 4D Vectors w axis is left untouched.\n" -); + ".. method:: normalize()\n" + "\n" + " Normalize the vector, making the length of the vector always 1.0.\n" + "\n" + " .. warning:: Normalizing a vector where all values are zero has no effect.\n" + "\n" + " .. note:: Normalize works for vectors of all sizes,\n" + " however 4D Vectors w axis is left untouched.\n"); static PyObject *Vector_normalize(VectorObject *self) { - int size = (self->size == 4 ? 3 : self->size); - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + int size = (self->size == 4 ? 3 : self->size); + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - normalize_vn(self->vec, size); + normalize_vn(self->vec, size); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Vector_normalized_doc, -".. method:: normalized()\n" -"\n" -" Return a new, normalized vector.\n" -"\n" -" :return: a normalized copy of the vector\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: normalized()\n" + "\n" + " Return a new, normalized vector.\n" + "\n" + " :return: a normalized copy of the vector\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_normalized(VectorObject *self) { - return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self); + return vec__apply_to_copy((PyNoArgsFunction)Vector_normalize, self); } PyDoc_STRVAR(Vector_resize_doc, -".. method:: resize(size=3)\n" -"\n" -" Resize the vector to have size number of elements.\n" -); + ".. method:: resize(size=3)\n" + "\n" + " Resize the vector to have size number of elements.\n"); static PyObject *Vector_resize(VectorObject *self, PyObject *value) { - int size; - - if (self->flag & BASE_MATH_FLAG_IS_WRAP) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize(): " - "cannot resize wrapped data - only python vectors"); - return NULL; - } - if (self->cb_user) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize(): " - "cannot resize a vector that has an owner"); - return NULL; - } - - if ((size = PyC_Long_AsI32(value)) == -1) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize(size): " - "expected size argument to be an integer"); - return NULL; - } - - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector.resize(): invalid size"); - return NULL; - } - - self->vec = PyMem_Realloc(self->vec, (size * sizeof(float))); - if (self->vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.resize(): " - "problem allocating pointer space"); - return NULL; - } - - /* If the vector has increased in length, set all new elements to 0.0f */ - if (size > self->size) { - copy_vn_fl(self->vec + self->size, size - self->size, 0.0f); - } - - self->size = size; - Py_RETURN_NONE; + int size; + + if (self->flag & BASE_MATH_FLAG_IS_WRAP) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize(): " + "cannot resize wrapped data - only python vectors"); + return NULL; + } + if (self->cb_user) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize(): " + "cannot resize a vector that has an owner"); + return NULL; + } + + if ((size = PyC_Long_AsI32(value)) == -1) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize(size): " + "expected size argument to be an integer"); + return NULL; + } + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector.resize(): invalid size"); + return NULL; + } + + self->vec = PyMem_Realloc(self->vec, (size * sizeof(float))); + if (self->vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.resize(): " + "problem allocating pointer space"); + return NULL; + } + + /* If the vector has increased in length, set all new elements to 0.0f */ + if (size > self->size) { + copy_vn_fl(self->vec + self->size, size - self->size, 0.0f); + } + + self->size = size; + Py_RETURN_NONE; } PyDoc_STRVAR(Vector_resized_doc, -".. method:: resized(size=3)\n" -"\n" -" Return a resized copy of the vector with size number of elements.\n" -"\n" -" :return: a new vector\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: resized(size=3)\n" + "\n" + " Return a resized copy of the vector with size number of elements.\n" + "\n" + " :return: a new vector\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_resized(VectorObject *self, PyObject *value) { - int size; - float *vec; + int size; + float *vec; - if ((size = PyLong_AsLong(value)) == -1) { - return NULL; - } + if ((size = PyLong_AsLong(value)) == -1) { + return NULL; + } - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector.resized(): invalid size"); - return NULL; - } + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector.resized(): invalid size"); + return NULL; + } - vec = PyMem_Malloc(size * sizeof(float)); + vec = PyMem_Malloc(size * sizeof(float)); - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.resized(): " - "problem allocating pointer space"); - return NULL; - } + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.resized(): " + "problem allocating pointer space"); + return NULL; + } - copy_vn_fl(vec, size, 0.0f); - memcpy(vec, self->vec, self->size * sizeof(float)); + copy_vn_fl(vec, size, 0.0f); + memcpy(vec, self->vec, self->size * sizeof(float)); - return Vector_CreatePyObject_alloc(vec, size, NULL); + return Vector_CreatePyObject_alloc(vec, size, NULL); } PyDoc_STRVAR(Vector_resize_2d_doc, -".. method:: resize_2d()\n" -"\n" -" Resize the vector to 2D (x, y).\n" -); + ".. method:: resize_2d()\n" + "\n" + " Resize the vector to 2D (x, y).\n"); static PyObject *Vector_resize_2d(VectorObject *self) { - if (self->flag & BASE_MATH_FLAG_IS_WRAP) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize_2d(): " - "cannot resize wrapped data - only python vectors"); - return NULL; - } - if (self->cb_user) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize_2d(): " - "cannot resize a vector that has an owner"); - return NULL; - } - - self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2)); - if (self->vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.resize_2d(): " - "problem allocating pointer space"); - return NULL; - } - - self->size = 2; - Py_RETURN_NONE; + if (self->flag & BASE_MATH_FLAG_IS_WRAP) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize_2d(): " + "cannot resize wrapped data - only python vectors"); + return NULL; + } + if (self->cb_user) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize_2d(): " + "cannot resize a vector that has an owner"); + return NULL; + } + + self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 2)); + if (self->vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.resize_2d(): " + "problem allocating pointer space"); + return NULL; + } + + self->size = 2; + Py_RETURN_NONE; } PyDoc_STRVAR(Vector_resize_3d_doc, -".. method:: resize_3d()\n" -"\n" -" Resize the vector to 3D (x, y, z).\n" -); + ".. method:: resize_3d()\n" + "\n" + " Resize the vector to 3D (x, y, z).\n"); static PyObject *Vector_resize_3d(VectorObject *self) { - if (self->flag & BASE_MATH_FLAG_IS_WRAP) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize_3d(): " - "cannot resize wrapped data - only python vectors"); - return NULL; - } - if (self->cb_user) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize_3d(): " - "cannot resize a vector that has an owner"); - return NULL; - } - - self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3)); - if (self->vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.resize_3d(): " - "problem allocating pointer space"); - return NULL; - } - - if (self->size == 2) { - self->vec[2] = 0.0f; - } - - self->size = 3; - Py_RETURN_NONE; + if (self->flag & BASE_MATH_FLAG_IS_WRAP) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize_3d(): " + "cannot resize wrapped data - only python vectors"); + return NULL; + } + if (self->cb_user) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize_3d(): " + "cannot resize a vector that has an owner"); + return NULL; + } + + self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 3)); + if (self->vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.resize_3d(): " + "problem allocating pointer space"); + return NULL; + } + + if (self->size == 2) { + self->vec[2] = 0.0f; + } + + self->size = 3; + Py_RETURN_NONE; } PyDoc_STRVAR(Vector_resize_4d_doc, -".. method:: resize_4d()\n" -"\n" -" Resize the vector to 4D (x, y, z, w).\n" -); + ".. method:: resize_4d()\n" + "\n" + " Resize the vector to 4D (x, y, z, w).\n"); static PyObject *Vector_resize_4d(VectorObject *self) { - if (self->flag & BASE_MATH_FLAG_IS_WRAP) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize_4d(): " - "cannot resize wrapped data - only python vectors"); - return NULL; - } - if (self->cb_user) { - PyErr_SetString(PyExc_TypeError, - "Vector.resize_4d(): " - "cannot resize a vector that has an owner"); - return NULL; - } - - self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4)); - if (self->vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector.resize_4d(): " - "problem allocating pointer space"); - return NULL; - } - - if (self->size == 2) { - self->vec[2] = 0.0f; - self->vec[3] = 1.0f; - } - else if (self->size == 3) { - self->vec[3] = 1.0f; - } - self->size = 4; - Py_RETURN_NONE; + if (self->flag & BASE_MATH_FLAG_IS_WRAP) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize_4d(): " + "cannot resize wrapped data - only python vectors"); + return NULL; + } + if (self->cb_user) { + PyErr_SetString(PyExc_TypeError, + "Vector.resize_4d(): " + "cannot resize a vector that has an owner"); + return NULL; + } + + self->vec = PyMem_Realloc(self->vec, (sizeof(float) * 4)); + if (self->vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector.resize_4d(): " + "problem allocating pointer space"); + return NULL; + } + + if (self->size == 2) { + self->vec[2] = 0.0f; + self->vec[3] = 1.0f; + } + else if (self->size == 3) { + self->vec[3] = 1.0f; + } + self->size = 4; + Py_RETURN_NONE; } PyDoc_STRVAR(Vector_to_2d_doc, -".. method:: to_2d()\n" -"\n" -" Return a 2d copy of the vector.\n" -"\n" -" :return: a new vector\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: to_2d()\n" + "\n" + " Return a 2d copy of the vector.\n" + "\n" + " :return: a new vector\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_to_2d(VectorObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return Vector_CreatePyObject(self->vec, 2, Py_TYPE(self)); + return Vector_CreatePyObject(self->vec, 2, Py_TYPE(self)); } PyDoc_STRVAR(Vector_to_3d_doc, -".. method:: to_3d()\n" -"\n" -" Return a 3d copy of the vector.\n" -"\n" -" :return: a new vector\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: to_3d()\n" + "\n" + " Return a 3d copy of the vector.\n" + "\n" + " :return: a new vector\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_to_3d(VectorObject *self) { - float tvec[3] = {0.0f}; + float tvec[3] = {0.0f}; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3)); - return Vector_CreatePyObject(tvec, 3, Py_TYPE(self)); + memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 3)); + return Vector_CreatePyObject(tvec, 3, Py_TYPE(self)); } PyDoc_STRVAR(Vector_to_4d_doc, -".. method:: to_4d()\n" -"\n" -" Return a 4d copy of the vector.\n" -"\n" -" :return: a new vector\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: to_4d()\n" + "\n" + " Return a 4d copy of the vector.\n" + "\n" + " :return: a new vector\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_to_4d(VectorObject *self) { - float tvec[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + float tvec[4] = {0.0f, 0.0f, 0.0f, 1.0f}; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4)); - return Vector_CreatePyObject(tvec, 4, Py_TYPE(self)); + memcpy(tvec, self->vec, sizeof(float) * MIN2(self->size, 4)); + return Vector_CreatePyObject(tvec, 4, Py_TYPE(self)); } PyDoc_STRVAR(Vector_to_tuple_doc, -".. method:: to_tuple(precision=-1)\n" -"\n" -" Return this vector as a tuple with.\n" -"\n" -" :arg precision: The number to round the value to in [-1, 21].\n" -" :type precision: int\n" -" :return: the values of the vector rounded by *precision*\n" -" :rtype: tuple\n" -); + ".. method:: to_tuple(precision=-1)\n" + "\n" + " Return this vector as a tuple with.\n" + "\n" + " :arg precision: The number to round the value to in [-1, 21].\n" + " :type precision: int\n" + " :return: the values of the vector rounded by *precision*\n" + " :rtype: tuple\n"); /* note: BaseMath_ReadCallback must be called beforehand */ static PyObject *Vector_to_tuple_ext(VectorObject *self, int ndigits) { - PyObject *ret; - int i; + PyObject *ret; + int i; - ret = PyTuple_New(self->size); + ret = PyTuple_New(self->size); - if (ndigits >= 0) { - for (i = 0; i < self->size; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->vec[i], ndigits))); - } - } - else { - for (i = 0; i < self->size; i++) { - PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->vec[i])); - } - } + if (ndigits >= 0) { + for (i = 0; i < self->size; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->vec[i], ndigits))); + } + } + else { + for (i = 0; i < self->size; i++) { + PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->vec[i])); + } + } - return ret; + return ret; } static PyObject *Vector_to_tuple(VectorObject *self, PyObject *args) { - int ndigits = 0; + int ndigits = 0; - if (!PyArg_ParseTuple(args, "|i:to_tuple", &ndigits)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "|i:to_tuple", &ndigits)) { + return NULL; + } - if (ndigits > 22 || ndigits < 0) { - PyErr_SetString(PyExc_ValueError, - "Vector.to_tuple(ndigits): " - "ndigits must be between 0 and 21"); - return NULL; - } + if (ndigits > 22 || ndigits < 0) { + PyErr_SetString(PyExc_ValueError, + "Vector.to_tuple(ndigits): " + "ndigits must be between 0 and 21"); + return NULL; + } - if (PyTuple_GET_SIZE(args) == 0) { - ndigits = -1; - } + if (PyTuple_GET_SIZE(args) == 0) { + ndigits = -1; + } - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return Vector_to_tuple_ext(self, ndigits); + return Vector_to_tuple_ext(self, ndigits); } PyDoc_STRVAR(Vector_to_track_quat_doc, -".. method:: to_track_quat(track, up)\n" -"\n" -" Return a quaternion rotation from the vector and the track and up axis.\n" -"\n" -" :arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].\n" -" :type track: string\n" -" :arg up: Up axis in ['X', 'Y', 'Z'].\n" -" :type up: string\n" -" :return: rotation from the vector and the track and up axis.\n" -" :rtype: :class:`Quaternion`\n" -); + ".. method:: to_track_quat(track, up)\n" + "\n" + " Return a quaternion rotation from the vector and the track and up axis.\n" + "\n" + " :arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].\n" + " :type track: string\n" + " :arg up: Up axis in ['X', 'Y', 'Z'].\n" + " :type up: string\n" + " :return: rotation from the vector and the track and up axis.\n" + " :rtype: :class:`Quaternion`\n"); static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) { - float vec[3], quat[4]; - const char *strack, *sup; - short track = 2, up = 1; - - if (!PyArg_ParseTuple(args, "|ss:to_track_quat", &strack, &sup)) { - return NULL; - } - - if (self->size != 3) { - PyErr_SetString(PyExc_TypeError, - "Vector.to_track_quat(): " - "only for 3D vectors"); - return NULL; - } - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - if (strack) { - const char *axis_err_msg = "only X, -X, Y, -Y, Z or -Z for track axis"; - - if (strlen(strack) == 2) { - if (strack[0] == '-') { - switch (strack[1]) { - case 'X': - track = 3; - break; - case 'Y': - track = 4; - break; - case 'Z': - track = 5; - break; - default: - PyErr_SetString(PyExc_ValueError, axis_err_msg); - return NULL; - } - } - else { - PyErr_SetString(PyExc_ValueError, axis_err_msg); - return NULL; - } - } - else if (strlen(strack) == 1) { - switch (strack[0]) { - case '-': - case 'X': - track = 0; - break; - case 'Y': - track = 1; - break; - case 'Z': - track = 2; - break; - default: - PyErr_SetString(PyExc_ValueError, axis_err_msg); - return NULL; - } - } - else { - PyErr_SetString(PyExc_ValueError, axis_err_msg); - return NULL; - } - } - - if (sup) { - const char *axis_err_msg = "only X, Y or Z for up axis"; - if (strlen(sup) == 1) { - switch (*sup) { - case 'X': - up = 0; - break; - case 'Y': - up = 1; - break; - case 'Z': - up = 2; - break; - default: - PyErr_SetString(PyExc_ValueError, axis_err_msg); - return NULL; - } - } - else { - PyErr_SetString(PyExc_ValueError, axis_err_msg); - return NULL; - } - } - - if (track == up) { - PyErr_SetString(PyExc_ValueError, - "Can't have the same axis for track and up"); - return NULL; - } - - /* - * flip vector around, since vectoquat expect a vector from target to tracking object - * and the python function expects the inverse (a vector to the target). - */ - negate_v3_v3(vec, self->vec); - - vec_to_quat(quat, vec, track, up); - - return Quaternion_CreatePyObject(quat, NULL); -} - -PyDoc_STRVAR(Vector_orthogonal_doc, -".. method:: orthogonal()\n" -"\n" -" Return a perpendicular vector.\n" -"\n" -" :return: a new vector 90 degrees from this vector.\n" -" :rtype: :class:`Vector`\n" -"\n" -" .. note:: the axis is undefined, only use when any orthogonal vector is acceptable.\n" -); + float vec[3], quat[4]; + const char *strack, *sup; + short track = 2, up = 1; + + if (!PyArg_ParseTuple(args, "|ss:to_track_quat", &strack, &sup)) { + return NULL; + } + + if (self->size != 3) { + PyErr_SetString(PyExc_TypeError, + "Vector.to_track_quat(): " + "only for 3D vectors"); + return NULL; + } + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + if (strack) { + const char *axis_err_msg = "only X, -X, Y, -Y, Z or -Z for track axis"; + + if (strlen(strack) == 2) { + if (strack[0] == '-') { + switch (strack[1]) { + case 'X': + track = 3; + break; + case 'Y': + track = 4; + break; + case 'Z': + track = 5; + break; + default: + PyErr_SetString(PyExc_ValueError, axis_err_msg); + return NULL; + } + } + else { + PyErr_SetString(PyExc_ValueError, axis_err_msg); + return NULL; + } + } + else if (strlen(strack) == 1) { + switch (strack[0]) { + case '-': + case 'X': + track = 0; + break; + case 'Y': + track = 1; + break; + case 'Z': + track = 2; + break; + default: + PyErr_SetString(PyExc_ValueError, axis_err_msg); + return NULL; + } + } + else { + PyErr_SetString(PyExc_ValueError, axis_err_msg); + return NULL; + } + } + + if (sup) { + const char *axis_err_msg = "only X, Y or Z for up axis"; + if (strlen(sup) == 1) { + switch (*sup) { + case 'X': + up = 0; + break; + case 'Y': + up = 1; + break; + case 'Z': + up = 2; + break; + default: + PyErr_SetString(PyExc_ValueError, axis_err_msg); + return NULL; + } + } + else { + PyErr_SetString(PyExc_ValueError, axis_err_msg); + return NULL; + } + } + + if (track == up) { + PyErr_SetString(PyExc_ValueError, "Can't have the same axis for track and up"); + return NULL; + } + + /* + * flip vector around, since vectoquat expect a vector from target to tracking object + * and the python function expects the inverse (a vector to the target). + */ + negate_v3_v3(vec, self->vec); + + vec_to_quat(quat, vec, track, up); + + return Quaternion_CreatePyObject(quat, NULL); +} + +PyDoc_STRVAR( + Vector_orthogonal_doc, + ".. method:: orthogonal()\n" + "\n" + " Return a perpendicular vector.\n" + "\n" + " :return: a new vector 90 degrees from this vector.\n" + " :rtype: :class:`Vector`\n" + "\n" + " .. note:: the axis is undefined, only use when any orthogonal vector is acceptable.\n"); static PyObject *Vector_orthogonal(VectorObject *self) { - float vec[3]; + float vec[3]; - if (self->size > 3) { - PyErr_SetString(PyExc_TypeError, - "Vector.orthogonal(): " - "Vector must be 3D or 2D"); - return NULL; - } + if (self->size > 3) { + PyErr_SetString(PyExc_TypeError, + "Vector.orthogonal(): " + "Vector must be 3D or 2D"); + return NULL; + } - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (self->size == 3) { - ortho_v3_v3(vec, self->vec); - } - else { - ortho_v2_v2(vec, self->vec); - } + if (self->size == 3) { + ortho_v3_v3(vec, self->vec); + } + else { + ortho_v2_v2(vec, self->vec); + } - return Vector_CreatePyObject(vec, self->size, Py_TYPE(self)); + return Vector_CreatePyObject(vec, self->size, Py_TYPE(self)); } - /** * Vector.reflect(mirror): return a reflected vector on the mirror normal. *
@@ -861,541 +839,533 @@ static PyObject *Vector_orthogonal(VectorObject *self)
  * 
*/ PyDoc_STRVAR(Vector_reflect_doc, -".. method:: reflect(mirror)\n" -"\n" -" Return the reflection vector from the *mirror* argument.\n" -"\n" -" :arg mirror: This vector could be a normal from the reflecting surface.\n" -" :type mirror: :class:`Vector`\n" -" :return: The reflected vector matching the size of this vector.\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: reflect(mirror)\n" + "\n" + " Return the reflection vector from the *mirror* argument.\n" + "\n" + " :arg mirror: This vector could be a normal from the reflecting surface.\n" + " :type mirror: :class:`Vector`\n" + " :return: The reflected vector matching the size of this vector.\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_reflect(VectorObject *self, PyObject *value) { - int value_size; - float mirror[3], vec[3]; - float reflect[3] = {0.0f}; - float tvec[MAX_DIMENSIONS]; + int value_size; + float mirror[3], vec[3]; + float reflect[3] = {0.0f}; + float tvec[MAX_DIMENSIONS]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if ((value_size = mathutils_array_parse(tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1) { - return NULL; - } + if ((value_size = mathutils_array_parse( + tvec, 2, 4, value, "Vector.reflect(other), invalid 'other' arg")) == -1) { + return NULL; + } - if (self->size < 2 || self->size > 4) { - PyErr_SetString(PyExc_ValueError, - "Vector must be 2D, 3D or 4D"); - return NULL; - } + if (self->size < 2 || self->size > 4) { + PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D"); + return NULL; + } - mirror[0] = tvec[0]; - mirror[1] = tvec[1]; - mirror[2] = (value_size > 2) ? tvec[2] : 0.0f; + mirror[0] = tvec[0]; + mirror[1] = tvec[1]; + mirror[2] = (value_size > 2) ? tvec[2] : 0.0f; - vec[0] = self->vec[0]; - vec[1] = self->vec[1]; - vec[2] = (value_size > 2) ? self->vec[2] : 0.0f; + vec[0] = self->vec[0]; + vec[1] = self->vec[1]; + vec[2] = (value_size > 2) ? self->vec[2] : 0.0f; - normalize_v3(mirror); - reflect_v3_v3v3(reflect, vec, mirror); + normalize_v3(mirror); + reflect_v3_v3v3(reflect, vec, mirror); - return Vector_CreatePyObject(reflect, self->size, Py_TYPE(self)); + return Vector_CreatePyObject(reflect, self->size, Py_TYPE(self)); } PyDoc_STRVAR(Vector_cross_doc, -".. method:: cross(other)\n" -"\n" -" Return the cross product of this vector and another.\n" -"\n" -" :arg other: The other vector to perform the cross product with.\n" -" :type other: :class:`Vector`\n" -" :return: The cross product.\n" -" :rtype: :class:`Vector` or float when 2D vectors are used\n" -"\n" -" .. note:: both vectors must be 2D or 3D\n" -); + ".. method:: cross(other)\n" + "\n" + " Return the cross product of this vector and another.\n" + "\n" + " :arg other: The other vector to perform the cross product with.\n" + " :type other: :class:`Vector`\n" + " :return: The cross product.\n" + " :rtype: :class:`Vector` or float when 2D vectors are used\n" + "\n" + " .. note:: both vectors must be 2D or 3D\n"); static PyObject *Vector_cross(VectorObject *self, PyObject *value) { - PyObject *ret; - float tvec[3]; + PyObject *ret; + float tvec[3]; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (self->size > 3) { - PyErr_SetString(PyExc_ValueError, - "Vector must be 2D or 3D"); - return NULL; - } + if (self->size > 3) { + PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D"); + return NULL; + } - if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1) { - return NULL; - } + if (mathutils_array_parse( + tvec, self->size, self->size, value, "Vector.cross(other), invalid 'other' arg") == -1) { + return NULL; + } - if (self->size == 3) { - ret = Vector_CreatePyObject(NULL, 3, Py_TYPE(self)); - cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec); - } - else { - /* size == 2 */ - ret = PyFloat_FromDouble(cross_v2v2(self->vec, tvec)); - } - return ret; + if (self->size == 3) { + ret = Vector_CreatePyObject(NULL, 3, Py_TYPE(self)); + cross_v3_v3v3(((VectorObject *)ret)->vec, self->vec, tvec); + } + else { + /* size == 2 */ + ret = PyFloat_FromDouble(cross_v2v2(self->vec, tvec)); + } + return ret; } PyDoc_STRVAR(Vector_dot_doc, -".. method:: dot(other)\n" -"\n" -" Return the dot product of this vector and another.\n" -"\n" -" :arg other: The other vector to perform the dot product with.\n" -" :type other: :class:`Vector`\n" -" :return: The dot product.\n" -" :rtype: :class:`Vector`\n" -); + ".. method:: dot(other)\n" + "\n" + " Return the dot product of this vector and another.\n" + "\n" + " :arg other: The other vector to perform the dot product with.\n" + " :type other: :class:`Vector`\n" + " :return: The dot product.\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_dot(VectorObject *self, PyObject *value) { - float *tvec; - PyObject *ret; - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - if (mathutils_array_parse_alloc(&tvec, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) { - return NULL; - } - - ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size)); - PyMem_Free(tvec); - return ret; -} - -PyDoc_STRVAR(Vector_angle_doc, -".. function:: angle(other, fallback=None)\n" -"\n" -" Return the angle between two vectors.\n" -"\n" -" :arg other: another vector to compare the angle with\n" -" :type other: :class:`Vector`\n" -" :arg fallback: return this when the angle can't be calculated (zero length vector),\n" -" (instead of raising a :exc:`ValueError`).\n" -" :type fallback: any\n" -" :return: angle in radians or fallback when given\n" -" :rtype: float\n" -); + float *tvec; + PyObject *ret; + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + if (mathutils_array_parse_alloc( + &tvec, self->size, value, "Vector.dot(other), invalid 'other' arg") == -1) { + return NULL; + } + + ret = PyFloat_FromDouble(dot_vn_vn(self->vec, tvec, self->size)); + PyMem_Free(tvec); + return ret; +} + +PyDoc_STRVAR( + Vector_angle_doc, + ".. function:: angle(other, fallback=None)\n" + "\n" + " Return the angle between two vectors.\n" + "\n" + " :arg other: another vector to compare the angle with\n" + " :type other: :class:`Vector`\n" + " :arg fallback: return this when the angle can't be calculated (zero length vector),\n" + " (instead of raising a :exc:`ValueError`).\n" + " :type fallback: any\n" + " :return: angle in radians or fallback when given\n" + " :rtype: float\n"); static PyObject *Vector_angle(VectorObject *self, PyObject *args) { - const int size = MIN2(self->size, 3); /* 4D angle makes no sense */ - float tvec[MAX_DIMENSIONS]; - PyObject *value; - double dot = 0.0f, dot_self = 0.0f, dot_other = 0.0f; - int x; - PyObject *fallback = NULL; - - if (!PyArg_ParseTuple(args, "O|O:angle", &value, &fallback)) { - return NULL; - } - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - /* don't use clamped size, rule of thumb is vector sizes must match, - * even though n this case 'w' is ignored */ - if (mathutils_array_parse(tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1) { - return NULL; - } - - if (self->size > 4) { - PyErr_SetString(PyExc_ValueError, - "Vector must be 2D, 3D or 4D"); - return NULL; - } - - for (x = 0; x < size; x++) { - dot_self += (double)self->vec[x] * (double)self->vec[x]; - dot_other += (double)tvec[x] * (double)tvec[x]; - dot += (double)self->vec[x] * (double)tvec[x]; - } - - if (!dot_self || !dot_other) { - /* avoid exception */ - if (fallback) { - Py_INCREF(fallback); - return fallback; - } - else { - PyErr_SetString(PyExc_ValueError, - "Vector.angle(other): " - "zero length vectors have no valid angle"); - return NULL; - } - } - - return PyFloat_FromDouble(saacos(dot / (sqrt(dot_self) * sqrt(dot_other)))); -} - -PyDoc_STRVAR(Vector_angle_signed_doc, -".. function:: angle_signed(other, fallback)\n" -"\n" -" Return the signed angle between two 2D vectors (clockwise is positive).\n" -"\n" -" :arg other: another vector to compare the angle with\n" -" :type other: :class:`Vector`\n" -" :arg fallback: return this when the angle can't be calculated (zero length vector),\n" -" (instead of raising a :exc:`ValueError`).\n" -" :type fallback: any\n" -" :return: angle in radians or fallback when given\n" -" :rtype: float\n" -); + const int size = MIN2(self->size, 3); /* 4D angle makes no sense */ + float tvec[MAX_DIMENSIONS]; + PyObject *value; + double dot = 0.0f, dot_self = 0.0f, dot_other = 0.0f; + int x; + PyObject *fallback = NULL; + + if (!PyArg_ParseTuple(args, "O|O:angle", &value, &fallback)) { + return NULL; + } + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + /* don't use clamped size, rule of thumb is vector sizes must match, + * even though n this case 'w' is ignored */ + if (mathutils_array_parse( + tvec, self->size, self->size, value, "Vector.angle(other), invalid 'other' arg") == -1) { + return NULL; + } + + if (self->size > 4) { + PyErr_SetString(PyExc_ValueError, "Vector must be 2D, 3D or 4D"); + return NULL; + } + + for (x = 0; x < size; x++) { + dot_self += (double)self->vec[x] * (double)self->vec[x]; + dot_other += (double)tvec[x] * (double)tvec[x]; + dot += (double)self->vec[x] * (double)tvec[x]; + } + + if (!dot_self || !dot_other) { + /* avoid exception */ + if (fallback) { + Py_INCREF(fallback); + return fallback; + } + else { + PyErr_SetString(PyExc_ValueError, + "Vector.angle(other): " + "zero length vectors have no valid angle"); + return NULL; + } + } + + return PyFloat_FromDouble(saacos(dot / (sqrt(dot_self) * sqrt(dot_other)))); +} + +PyDoc_STRVAR( + Vector_angle_signed_doc, + ".. function:: angle_signed(other, fallback)\n" + "\n" + " Return the signed angle between two 2D vectors (clockwise is positive).\n" + "\n" + " :arg other: another vector to compare the angle with\n" + " :type other: :class:`Vector`\n" + " :arg fallback: return this when the angle can't be calculated (zero length vector),\n" + " (instead of raising a :exc:`ValueError`).\n" + " :type fallback: any\n" + " :return: angle in radians or fallback when given\n" + " :rtype: float\n"); static PyObject *Vector_angle_signed(VectorObject *self, PyObject *args) { - float tvec[2]; - - PyObject *value; - PyObject *fallback = NULL; + float tvec[2]; - if (!PyArg_ParseTuple(args, "O|O:angle_signed", &value, &fallback)) { - return NULL; - } + PyObject *value; + PyObject *fallback = NULL; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (!PyArg_ParseTuple(args, "O|O:angle_signed", &value, &fallback)) { + return NULL; + } - if (mathutils_array_parse(tvec, 2, 2, value, "Vector.angle_signed(other), invalid 'other' arg") == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (self->size != 2) { - PyErr_SetString(PyExc_ValueError, - "Vector must be 2D"); - return NULL; - } + if (mathutils_array_parse( + tvec, 2, 2, value, "Vector.angle_signed(other), invalid 'other' arg") == -1) { + return NULL; + } - if (is_zero_v2(self->vec) || is_zero_v2(tvec)) { - /* avoid exception */ - if (fallback) { - Py_INCREF(fallback); - return fallback; - } - else { - PyErr_SetString(PyExc_ValueError, - "Vector.angle_signed(other): " - "zero length vectors have no valid angle"); - return NULL; - } - } + if (self->size != 2) { + PyErr_SetString(PyExc_ValueError, "Vector must be 2D"); + return NULL; + } + if (is_zero_v2(self->vec) || is_zero_v2(tvec)) { + /* avoid exception */ + if (fallback) { + Py_INCREF(fallback); + return fallback; + } + else { + PyErr_SetString(PyExc_ValueError, + "Vector.angle_signed(other): " + "zero length vectors have no valid angle"); + return NULL; + } + } - return PyFloat_FromDouble(angle_signed_v2v2(self->vec, tvec)); + return PyFloat_FromDouble(angle_signed_v2v2(self->vec, tvec)); } - PyDoc_STRVAR(Vector_rotation_difference_doc, -".. function:: rotation_difference(other)\n" -"\n" -" Returns a quaternion representing the rotational difference between this\n" -" vector and another.\n" -"\n" -" :arg other: second vector.\n" -" :type other: :class:`Vector`\n" -" :return: the rotational difference between the two vectors.\n" -" :rtype: :class:`Quaternion`\n" -"\n" -" .. note:: 2D vectors raise an :exc:`AttributeError`.\n" -); + ".. function:: rotation_difference(other)\n" + "\n" + " Returns a quaternion representing the rotational difference between this\n" + " vector and another.\n" + "\n" + " :arg other: second vector.\n" + " :type other: :class:`Vector`\n" + " :return: the rotational difference between the two vectors.\n" + " :rtype: :class:`Quaternion`\n" + "\n" + " .. note:: 2D vectors raise an :exc:`AttributeError`.\n"); static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value) { - float quat[4], vec_a[3], vec_b[3]; + float quat[4], vec_a[3], vec_b[3]; - if (self->size < 3 || self->size > 4) { - PyErr_SetString(PyExc_ValueError, - "vec.difference(value): " - "expects both vectors to be size 3 or 4"); - return NULL; - } + if (self->size < 3 || self->size > 4) { + PyErr_SetString(PyExc_ValueError, + "vec.difference(value): " + "expects both vectors to be size 3 or 4"); + return NULL; + } - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (mathutils_array_parse(vec_b, 3, MAX_DIMENSIONS, value, "Vector.difference(other), invalid 'other' arg") == -1) { - return NULL; - } + if (mathutils_array_parse( + vec_b, 3, MAX_DIMENSIONS, value, "Vector.difference(other), invalid 'other' arg") == + -1) { + return NULL; + } - normalize_v3_v3(vec_a, self->vec); - normalize_v3(vec_b); + normalize_v3_v3(vec_a, self->vec); + normalize_v3(vec_b); - rotation_between_vecs_to_quat(quat, vec_a, vec_b); + rotation_between_vecs_to_quat(quat, vec_a, vec_b); - return Quaternion_CreatePyObject(quat, NULL); + return Quaternion_CreatePyObject(quat, NULL); } PyDoc_STRVAR(Vector_project_doc, -".. function:: project(other)\n" -"\n" -" Return the projection of this vector onto the *other*.\n" -"\n" -" :arg other: second vector.\n" -" :type other: :class:`Vector`\n" -" :return: the parallel projection vector\n" -" :rtype: :class:`Vector`\n" -); + ".. function:: project(other)\n" + "\n" + " Return the projection of this vector onto the *other*.\n" + "\n" + " :arg other: second vector.\n" + " :type other: :class:`Vector`\n" + " :return: the parallel projection vector\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_project(VectorObject *self, PyObject *value) { - const int size = self->size; - float *tvec; - double dot = 0.0f, dot2 = 0.0f; - int x; - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.project(other), invalid 'other' arg") == -1) { - return NULL; - } - - /* get dot products */ - for (x = 0; x < size; x++) { - dot += (double)(self->vec[x] * tvec[x]); - dot2 += (double)(tvec[x] * tvec[x]); - } - /* projection */ - dot /= dot2; - for (x = 0; x < size; x++) { - tvec[x] *= (float)dot; - } - return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self)); + const int size = self->size; + float *tvec; + double dot = 0.0f, dot2 = 0.0f; + int x; + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + if (mathutils_array_parse_alloc( + &tvec, size, value, "Vector.project(other), invalid 'other' arg") == -1) { + return NULL; + } + + /* get dot products */ + for (x = 0; x < size; x++) { + dot += (double)(self->vec[x] * tvec[x]); + dot2 += (double)(tvec[x] * tvec[x]); + } + /* projection */ + dot /= dot2; + for (x = 0; x < size; x++) { + tvec[x] *= (float)dot; + } + return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self)); } PyDoc_STRVAR(Vector_lerp_doc, -".. function:: lerp(other, factor)\n" -"\n" -" Returns the interpolation of two vectors.\n" -"\n" -" :arg other: value to interpolate with.\n" -" :type other: :class:`Vector`\n" -" :arg factor: The interpolation value in [0.0, 1.0].\n" -" :type factor: float\n" -" :return: The interpolated vector.\n" -" :rtype: :class:`Vector`\n" -); + ".. function:: lerp(other, factor)\n" + "\n" + " Returns the interpolation of two vectors.\n" + "\n" + " :arg other: value to interpolate with.\n" + " :type other: :class:`Vector`\n" + " :arg factor: The interpolation value in [0.0, 1.0].\n" + " :type factor: float\n" + " :return: The interpolated vector.\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_lerp(VectorObject *self, PyObject *args) { - const int size = self->size; - PyObject *value = NULL; - float fac; - float *tvec; + const int size = self->size; + PyObject *value = NULL; + float fac; + float *tvec; - if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "Of:lerp", &value, &fac)) { + return NULL; + } - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.lerp(other), invalid 'other' arg") == -1) { - return NULL; - } + if (mathutils_array_parse_alloc(&tvec, size, value, "Vector.lerp(other), invalid 'other' arg") == + -1) { + return NULL; + } - interp_vn_vn(tvec, self->vec, 1.0f - fac, size); + interp_vn_vn(tvec, self->vec, 1.0f - fac, size); - return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self)); + return Vector_CreatePyObject_alloc(tvec, size, Py_TYPE(self)); } PyDoc_STRVAR(Vector_slerp_doc, -".. function:: slerp(other, factor, fallback=None)\n" -"\n" -" Returns the interpolation of two non-zero vectors (spherical coordinates).\n" -"\n" -" :arg other: value to interpolate with.\n" -" :type other: :class:`Vector`\n" -" :arg factor: The interpolation value typically in [0.0, 1.0].\n" -" :type factor: float\n" -" :arg fallback: return this when the vector can't be calculated (zero length vector or direct opposites),\n" -" (instead of raising a :exc:`ValueError`).\n" -" :type fallback: any\n" -" :return: The interpolated vector.\n" -" :rtype: :class:`Vector`\n" -); + ".. function:: slerp(other, factor, fallback=None)\n" + "\n" + " Returns the interpolation of two non-zero vectors (spherical coordinates).\n" + "\n" + " :arg other: value to interpolate with.\n" + " :type other: :class:`Vector`\n" + " :arg factor: The interpolation value typically in [0.0, 1.0].\n" + " :type factor: float\n" + " :arg fallback: return this when the vector can't be calculated (zero length " + "vector or direct opposites),\n" + " (instead of raising a :exc:`ValueError`).\n" + " :type fallback: any\n" + " :return: The interpolated vector.\n" + " :rtype: :class:`Vector`\n"); static PyObject *Vector_slerp(VectorObject *self, PyObject *args) { - const int size = self->size; - PyObject *value = NULL; - float fac, cosom, w[2]; - float self_vec[3], other_vec[3], ret_vec[3]; - float self_len_sq, other_len_sq; - int x; - PyObject *fallback = NULL; - - if (!PyArg_ParseTuple(args, "Of|O:slerp", &value, &fac, &fallback)) { - return NULL; - } - - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } - - if (self->size > 3) { - PyErr_SetString(PyExc_ValueError, - "Vector must be 2D or 3D"); - return NULL; - } - - if (mathutils_array_parse(other_vec, size, size, value, "Vector.slerp(other), invalid 'other' arg") == -1) { - return NULL; - } - - self_len_sq = normalize_vn_vn(self_vec, self->vec, size); - other_len_sq = normalize_vn(other_vec, size); - - /* use fallbacks for zero length vectors */ - if (UNLIKELY((self_len_sq < FLT_EPSILON) || - (other_len_sq < FLT_EPSILON))) - { - /* avoid exception */ - if (fallback) { - Py_INCREF(fallback); - return fallback; - } - else { - PyErr_SetString(PyExc_ValueError, - "Vector.slerp(): " - "zero length vectors unsupported"); - return NULL; - } - } - - /* We have sane state, execute slerp */ - cosom = (float)dot_vn_vn(self_vec, other_vec, size); - - /* direct opposite, can't slerp */ - if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) { - /* avoid exception */ - if (fallback) { - Py_INCREF(fallback); - return fallback; - } - else { - PyErr_SetString(PyExc_ValueError, - "Vector.slerp(): " - "opposite vectors unsupported"); - return NULL; - } - } - - interp_dot_slerp(fac, cosom, w); - - for (x = 0; x < size; x++) { - ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]); - } - - return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self)); + const int size = self->size; + PyObject *value = NULL; + float fac, cosom, w[2]; + float self_vec[3], other_vec[3], ret_vec[3]; + float self_len_sq, other_len_sq; + int x; + PyObject *fallback = NULL; + + if (!PyArg_ParseTuple(args, "Of|O:slerp", &value, &fac, &fallback)) { + return NULL; + } + + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } + + if (self->size > 3) { + PyErr_SetString(PyExc_ValueError, "Vector must be 2D or 3D"); + return NULL; + } + + if (mathutils_array_parse( + other_vec, size, size, value, "Vector.slerp(other), invalid 'other' arg") == -1) { + return NULL; + } + + self_len_sq = normalize_vn_vn(self_vec, self->vec, size); + other_len_sq = normalize_vn(other_vec, size); + + /* use fallbacks for zero length vectors */ + if (UNLIKELY((self_len_sq < FLT_EPSILON) || (other_len_sq < FLT_EPSILON))) { + /* avoid exception */ + if (fallback) { + Py_INCREF(fallback); + return fallback; + } + else { + PyErr_SetString(PyExc_ValueError, + "Vector.slerp(): " + "zero length vectors unsupported"); + return NULL; + } + } + + /* We have sane state, execute slerp */ + cosom = (float)dot_vn_vn(self_vec, other_vec, size); + + /* direct opposite, can't slerp */ + if (UNLIKELY(cosom < (-1.0f + FLT_EPSILON))) { + /* avoid exception */ + if (fallback) { + Py_INCREF(fallback); + return fallback; + } + else { + PyErr_SetString(PyExc_ValueError, + "Vector.slerp(): " + "opposite vectors unsupported"); + return NULL; + } + } + + interp_dot_slerp(fac, cosom, w); + + for (x = 0; x < size; x++) { + ret_vec[x] = (w[0] * self_vec[x]) + (w[1] * other_vec[x]); + } + + return Vector_CreatePyObject(ret_vec, size, Py_TYPE(self)); } PyDoc_STRVAR(Vector_rotate_doc, -".. function:: rotate(other)\n" -"\n" -" Rotate the vector by a rotation value.\n" -"\n" -" :arg other: rotation component of mathutils value\n" -" :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" -); + ".. function:: rotate(other)\n" + "\n" + " Rotate the vector by a rotation value.\n" + "\n" + " :arg other: rotation component of mathutils value\n" + " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n"); static PyObject *Vector_rotate(VectorObject *self, PyObject *value) { - float other_rmat[3][3]; + float other_rmat[3][3]; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return NULL; + } - if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) { - return NULL; - } + if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) { + return NULL; + } - if (self->size < 3 || self->size > 4) { - PyErr_SetString(PyExc_ValueError, - "Vector must be 3D or 4D"); - return NULL; - } + if (self->size < 3 || self->size > 4) { + PyErr_SetString(PyExc_ValueError, "Vector must be 3D or 4D"); + return NULL; + } - mul_m3_v3(other_rmat, self->vec); + mul_m3_v3(other_rmat, self->vec); - (void)BaseMath_WriteCallback(self); - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; } PyDoc_STRVAR(Vector_copy_doc, -".. function:: copy()\n" -"\n" -" Returns a copy of this vector.\n" -"\n" -" :return: A copy of the vector.\n" -" :rtype: :class:`Vector`\n" -"\n" -" .. note:: use this to get a copy of a wrapped vector with\n" -" no reference to the original data.\n" -); + ".. function:: copy()\n" + "\n" + " Returns a copy of this vector.\n" + "\n" + " :return: A copy of the vector.\n" + " :rtype: :class:`Vector`\n" + "\n" + " .. note:: use this to get a copy of a wrapped vector with\n" + " no reference to the original data.\n"); static PyObject *Vector_copy(VectorObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - return Vector_CreatePyObject(self->vec, self->size, Py_TYPE(self)); + return Vector_CreatePyObject(self->vec, self->size, Py_TYPE(self)); } static PyObject *Vector_deepcopy(VectorObject *self, PyObject *args) { - if (!PyC_CheckArgs_DeepCopy(args)) { - return NULL; - } - return Vector_copy(self); + if (!PyC_CheckArgs_DeepCopy(args)) { + return NULL; + } + return Vector_copy(self); } static PyObject *Vector_repr(VectorObject *self) { - PyObject *ret, *tuple; + PyObject *ret, *tuple; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - tuple = Vector_to_tuple_ext(self, -1); - ret = PyUnicode_FromFormat("Vector(%R)", tuple); - Py_DECREF(tuple); - return ret; + tuple = Vector_to_tuple_ext(self, -1); + ret = PyUnicode_FromFormat("Vector(%R)", tuple); + Py_DECREF(tuple); + return ret; } #ifndef MATH_STANDALONE static PyObject *Vector_str(VectorObject *self) { - int i; + int i; - DynStr *ds; + DynStr *ds; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - ds = BLI_dynstr_new(); + ds = BLI_dynstr_new(); - BLI_dynstr_append(ds, "size; i++) { - BLI_dynstr_appendf(ds, i ? ", %.4f" : "%.4f", self->vec[i]); - } + for (i = 0; i < self->size; i++) { + BLI_dynstr_appendf(ds, i ? ", %.4f" : "%.4f", self->vec[i]); + } - BLI_dynstr_append(ds, ")>"); + BLI_dynstr_append(ds, ")>"); - return mathutils_dynstr_to_py(ds); /* frees ds */ + return mathutils_dynstr_to_py(ds); /* frees ds */ } #endif @@ -1403,299 +1373,304 @@ static PyObject *Vector_str(VectorObject *self) /* sequence length len(vector) */ static int Vector_len(VectorObject *self) { - return self->size; + return self->size; } /* sequence accessor (get): vector[index] */ static PyObject *vector_item_internal(VectorObject *self, int i, const bool is_attr) { - if (i < 0) { - i = self->size - i; - } + if (i < 0) { + i = self->size - i; + } - if (i < 0 || i >= self->size) { - if (is_attr) { - PyErr_Format(PyExc_AttributeError, - "Vector.%c: unavailable on %dd vector", - *(((char *)"xyzw") + i), self->size); - } - else { - PyErr_SetString(PyExc_IndexError, - "vector[index]: out of range"); - } - return NULL; - } + if (i < 0 || i >= self->size) { + if (is_attr) { + PyErr_Format(PyExc_AttributeError, + "Vector.%c: unavailable on %dd vector", + *(((char *)"xyzw") + i), + self->size); + } + else { + PyErr_SetString(PyExc_IndexError, "vector[index]: out of range"); + } + return NULL; + } - if (BaseMath_ReadIndexCallback(self, i) == -1) { - return NULL; - } + if (BaseMath_ReadIndexCallback(self, i) == -1) { + return NULL; + } - return PyFloat_FromDouble(self->vec[i]); + return PyFloat_FromDouble(self->vec[i]); } static PyObject *Vector_item(VectorObject *self, int i) { - return vector_item_internal(self, i, false); + return vector_item_internal(self, i, false); } /* sequence accessor (set): vector[index] = value */ static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, const bool is_attr) { - float scalar; - - if (BaseMath_Prepare_ForWrite(self) == -1) { - return -1; - } - - if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ - PyErr_SetString(PyExc_TypeError, - "vector[index] = x: " - "assigned value not a number"); - return -1; - } - - if (i < 0) { - i = self->size - i; - } - - if (i < 0 || i >= self->size) { - if (is_attr) { - PyErr_Format(PyExc_AttributeError, - "Vector.%c = x: unavailable on %dd vector", - *(((char *)"xyzw") + i), self->size); - } - else { - PyErr_SetString(PyExc_IndexError, - "vector[index] = x: " - "assignment index out of range"); - } - return -1; - } - self->vec[i] = scalar; - - if (BaseMath_WriteIndexCallback(self, i) == -1) { - return -1; - } - return 0; + float scalar; + + if (BaseMath_Prepare_ForWrite(self) == -1) { + return -1; + } + + if ((scalar = PyFloat_AsDouble(value)) == -1.0f && + PyErr_Occurred()) { /* parsed item not a number */ + PyErr_SetString(PyExc_TypeError, + "vector[index] = x: " + "assigned value not a number"); + return -1; + } + + if (i < 0) { + i = self->size - i; + } + + if (i < 0 || i >= self->size) { + if (is_attr) { + PyErr_Format(PyExc_AttributeError, + "Vector.%c = x: unavailable on %dd vector", + *(((char *)"xyzw") + i), + self->size); + } + else { + PyErr_SetString(PyExc_IndexError, + "vector[index] = x: " + "assignment index out of range"); + } + return -1; + } + self->vec[i] = scalar; + + if (BaseMath_WriteIndexCallback(self, i) == -1) { + return -1; + } + return 0; } static int Vector_ass_item(VectorObject *self, int i, PyObject *value) { - return vector_ass_item_internal(self, i, value, false); + return vector_ass_item_internal(self, i, value, false); } /* sequence slice (get): vector[a:b] */ static PyObject *Vector_slice(VectorObject *self, int begin, int end) { - PyObject *tuple; - int count; + PyObject *tuple; + int count; - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - CLAMP(begin, 0, self->size); - if (end < 0) { - end = self->size + end + 1; - } - CLAMP(end, 0, self->size); - begin = MIN2(begin, end); + CLAMP(begin, 0, self->size); + if (end < 0) { + end = self->size + end + 1; + } + CLAMP(end, 0, self->size); + begin = MIN2(begin, end); - tuple = PyTuple_New(end - begin); - for (count = begin; count < end; count++) { - PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->vec[count])); - } + tuple = PyTuple_New(end - begin); + for (count = begin; count < end; count++) { + PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->vec[count])); + } - return tuple; + return tuple; } /* sequence slice (set): vector[a:b] = value */ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq) { - int size = 0; - float *vec = NULL; + int size = 0; + float *vec = NULL; - if (BaseMath_ReadCallback_ForWrite(self) == -1) { - return -1; - } + if (BaseMath_ReadCallback_ForWrite(self) == -1) { + return -1; + } - CLAMP(begin, 0, self->size); - CLAMP(end, 0, self->size); - begin = MIN2(begin, end); + CLAMP(begin, 0, self->size); + CLAMP(end, 0, self->size); + begin = MIN2(begin, end); - size = (end - begin); - if (mathutils_array_parse_alloc(&vec, size, seq, "vector[begin:end] = [...]") == -1) { - return -1; - } + size = (end - begin); + if (mathutils_array_parse_alloc(&vec, size, seq, "vector[begin:end] = [...]") == -1) { + return -1; + } - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "vec[:] = seq: " - "problem allocating pointer space"); - return -1; - } + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "vec[:] = seq: " + "problem allocating pointer space"); + return -1; + } - /*parsed well - now set in vector*/ - memcpy(self->vec + begin, vec, size * sizeof(float)); + /*parsed well - now set in vector*/ + memcpy(self->vec + begin, vec, size * sizeof(float)); - PyMem_Free(vec); + PyMem_Free(vec); - if (BaseMath_WriteCallback(self) == -1) { - return -1; - } + if (BaseMath_WriteCallback(self) == -1) { + return -1; + } - return 0; + return 0; } /* Numeric Protocols */ /* addition: obj + obj */ static PyObject *Vector_add(PyObject *v1, PyObject *v2) { - VectorObject *vec1 = NULL, *vec2 = NULL; - float *vec = NULL; - - if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_Format(PyExc_AttributeError, - "Vector addition: (%s + %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - vec1 = (VectorObject *)v1; - vec2 = (VectorObject *)v2; - - if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { - return NULL; - } - - /*VECTOR + VECTOR*/ - if (vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, - "Vector addition: " - "vectors must have the same dimensions for this operation"); - return NULL; - } - - vec = PyMem_Malloc(vec1->size * sizeof(float)); - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector(): " - "problem allocating pointer space"); - return NULL; - } - - add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); - - return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); + VectorObject *vec1 = NULL, *vec2 = NULL; + float *vec = NULL; + + if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { + PyErr_Format(PyExc_AttributeError, + "Vector addition: (%s + %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + vec1 = (VectorObject *)v1; + vec2 = (VectorObject *)v2; + + if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { + return NULL; + } + + /*VECTOR + VECTOR*/ + if (vec1->size != vec2->size) { + PyErr_SetString(PyExc_AttributeError, + "Vector addition: " + "vectors must have the same dimensions for this operation"); + return NULL; + } + + vec = PyMem_Malloc(vec1->size * sizeof(float)); + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector(): " + "problem allocating pointer space"); + return NULL; + } + + add_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); + + return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); } /* addition in-place: obj += obj */ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) { - VectorObject *vec1 = NULL, *vec2 = NULL; + VectorObject *vec1 = NULL, *vec2 = NULL; - if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_Format(PyExc_AttributeError, - "Vector addition: (%s += %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - vec1 = (VectorObject *)v1; - vec2 = (VectorObject *)v2; + if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { + PyErr_Format(PyExc_AttributeError, + "Vector addition: (%s += %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + vec1 = (VectorObject *)v1; + vec2 = (VectorObject *)v2; - if (vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, - "Vector addition: " - "vectors must have the same dimensions for this operation"); - return NULL; - } + if (vec1->size != vec2->size) { + PyErr_SetString(PyExc_AttributeError, + "Vector addition: " + "vectors must have the same dimensions for this operation"); + return NULL; + } - if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { + return NULL; + } - add_vn_vn(vec1->vec, vec2->vec, vec1->size); + add_vn_vn(vec1->vec, vec2->vec, vec1->size); - (void)BaseMath_WriteCallback(vec1); - Py_INCREF(v1); - return v1; + (void)BaseMath_WriteCallback(vec1); + Py_INCREF(v1); + return v1; } /* subtraction: obj - obj */ static PyObject *Vector_sub(PyObject *v1, PyObject *v2) { - VectorObject *vec1 = NULL, *vec2 = NULL; - float *vec; + VectorObject *vec1 = NULL, *vec2 = NULL; + float *vec; - if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_Format(PyExc_AttributeError, - "Vector subtraction: (%s - %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - vec1 = (VectorObject *)v1; - vec2 = (VectorObject *)v2; + if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { + PyErr_Format(PyExc_AttributeError, + "Vector subtraction: (%s - %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + vec1 = (VectorObject *)v1; + vec2 = (VectorObject *)v2; - if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { + return NULL; + } - if (vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, - "Vector subtraction: " - "vectors must have the same dimensions for this operation"); - return NULL; - } + if (vec1->size != vec2->size) { + PyErr_SetString(PyExc_AttributeError, + "Vector subtraction: " + "vectors must have the same dimensions for this operation"); + return NULL; + } - vec = PyMem_Malloc(vec1->size * sizeof(float)); - if (vec == NULL) { - PyErr_SetString(PyExc_MemoryError, - "Vector(): " - "problem allocating pointer space"); - return NULL; - } + vec = PyMem_Malloc(vec1->size * sizeof(float)); + if (vec == NULL) { + PyErr_SetString(PyExc_MemoryError, + "Vector(): " + "problem allocating pointer space"); + return NULL; + } - sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); + sub_vn_vnvn(vec, vec1->vec, vec2->vec, vec1->size); - return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); + return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1)); } /* subtraction in-place: obj -= obj */ static PyObject *Vector_isub(PyObject *v1, PyObject *v2) { - VectorObject *vec1 = NULL, *vec2 = NULL; + VectorObject *vec1 = NULL, *vec2 = NULL; - if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_Format(PyExc_AttributeError, - "Vector subtraction: (%s -= %s) " - "invalid type for this operation", - Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); - return NULL; - } - vec1 = (VectorObject *)v1; - vec2 = (VectorObject *)v2; + if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { + PyErr_Format(PyExc_AttributeError, + "Vector subtraction: (%s -= %s) " + "invalid type for this operation", + Py_TYPE(v1)->tp_name, + Py_TYPE(v2)->tp_name); + return NULL; + } + vec1 = (VectorObject *)v1; + vec2 = (VectorObject *)v2; - if (vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, - "Vector subtraction: " - "vectors must have the same dimensions for this operation"); - return NULL; - } + if (vec1->size != vec2->size) { + PyErr_SetString(PyExc_AttributeError, + "Vector subtraction: " + "vectors must have the same dimensions for this operation"); + return NULL; + } - if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { - return NULL; - } + if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) { + return NULL; + } - sub_vn_vn(vec1->vec, vec2->vec, vec1->size); + sub_vn_vn(vec1->vec, vec2->vec, vec1->size); - (void)BaseMath_WriteCallback(vec1); - Py_INCREF(v1); - return v1; + (void)BaseMath_WriteCallback(vec1); + Py_INCREF(v1); + return v1; } /*------------------------obj * obj------------------------------ * multiplication */ - /** * Column vector multiplication (Matrix * Vector). *
@@ -1709,576 +1684,577 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2)
  */
 int column_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat)
 {
-	float vec_cpy[MAX_DIMENSIONS];
-	int row, col, z = 0;
+  float vec_cpy[MAX_DIMENSIONS];
+  int row, col, z = 0;
 
-	if (mat->num_col != vec->size) {
-		if (mat->num_col == 4 && vec->size == 3) {
-			vec_cpy[3] = 1.0f;
-		}
-		else {
-			PyErr_SetString(PyExc_ValueError,
-			                "matrix * vector: "
-			                "len(matrix.col) and len(vector) must be the same, "
-			                "except for 4x4 matrix * 3D vector.");
-			return -1;
-		}
-	}
+  if (mat->num_col != vec->size) {
+    if (mat->num_col == 4 && vec->size == 3) {
+      vec_cpy[3] = 1.0f;
+    }
+    else {
+      PyErr_SetString(PyExc_ValueError,
+                      "matrix * vector: "
+                      "len(matrix.col) and len(vector) must be the same, "
+                      "except for 4x4 matrix * 3D vector.");
+      return -1;
+    }
+  }
 
-	memcpy(vec_cpy, vec->vec, vec->size * sizeof(float));
+  memcpy(vec_cpy, vec->vec, vec->size * sizeof(float));
 
-	r_vec[3] = 1.0f;
+  r_vec[3] = 1.0f;
 
-	for (row = 0; row < mat->num_row; row++) {
-		double dot = 0.0f;
-		for (col = 0; col < mat->num_col; col++) {
-			dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[col]);
-		}
-		r_vec[z++] = (float)dot;
-	}
+  for (row = 0; row < mat->num_row; row++) {
+    double dot = 0.0f;
+    for (col = 0; col < mat->num_col; col++) {
+      dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[col]);
+    }
+    r_vec[z++] = (float)dot;
+  }
 
-	return 0;
+  return 0;
 }
 
 static PyObject *vector_mul_float(VectorObject *vec, const float scalar)
 {
-	float *tvec = PyMem_Malloc(vec->size * sizeof(float));
-	if (tvec == NULL) {
-		PyErr_SetString(PyExc_MemoryError,
-		                "vec * float: "
-		                "problem allocating pointer space");
-		return NULL;
-	}
+  float *tvec = PyMem_Malloc(vec->size * sizeof(float));
+  if (tvec == NULL) {
+    PyErr_SetString(PyExc_MemoryError,
+                    "vec * float: "
+                    "problem allocating pointer space");
+    return NULL;
+  }
 
-	mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
-	return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
+  mul_vn_vn_fl(tvec, vec->vec, vec->size, scalar);
+  return Vector_CreatePyObject_alloc(tvec, vec->size, Py_TYPE(vec));
 }
 #ifdef USE_MATHUTILS_ELEM_MUL
 static PyObject *vector_mul_vec(VectorObject *vec1, VectorObject *vec2)
 {
-	float *tvec = PyMem_Malloc(vec1->size * sizeof(float));
-	if (tvec == NULL) {
-		PyErr_SetString(PyExc_MemoryError,
-		                "vec * vec: "
-		                "problem allocating pointer space");
-		return NULL;
-	}
+  float *tvec = PyMem_Malloc(vec1->size * sizeof(float));
+  if (tvec == NULL) {
+    PyErr_SetString(PyExc_MemoryError,
+                    "vec * vec: "
+                    "problem allocating pointer space");
+    return NULL;
+  }
 
-	mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size);
-	return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1));
+  mul_vn_vnvn(tvec, vec1->vec, vec2->vec, vec1->size);
+  return Vector_CreatePyObject_alloc(tvec, vec1->size, Py_TYPE(vec1));
 }
 #endif
 static PyObject *Vector_mul(PyObject *v1, PyObject *v2)
 {
-	VectorObject *vec1 = NULL, *vec2 = NULL;
-	float scalar;
-
-	if (VectorObject_Check(v1)) {
-		vec1 = (VectorObject *)v1;
-		if (BaseMath_ReadCallback(vec1) == -1) {
-			return NULL;
-		}
-	}
-	if (VectorObject_Check(v2)) {
-		vec2 = (VectorObject *)v2;
-		if (BaseMath_ReadCallback(vec2) == -1) {
-			return NULL;
-		}
-	}
-
-
-	/* Intentionally don't support (Quaternion) here, uses reverse order instead. */
-
-	/* make sure v1 is always the vector */
-	if (vec1 && vec2) {
+  VectorObject *vec1 = NULL, *vec2 = NULL;
+  float scalar;
+
+  if (VectorObject_Check(v1)) {
+    vec1 = (VectorObject *)v1;
+    if (BaseMath_ReadCallback(vec1) == -1) {
+      return NULL;
+    }
+  }
+  if (VectorObject_Check(v2)) {
+    vec2 = (VectorObject *)v2;
+    if (BaseMath_ReadCallback(vec2) == -1) {
+      return NULL;
+    }
+  }
+
+  /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
+
+  /* make sure v1 is always the vector */
+  if (vec1 && vec2) {
 #ifdef USE_MATHUTILS_ELEM_MUL
-		if (vec1->size != vec2->size) {
-			PyErr_SetString(PyExc_ValueError,
-			                "Vector multiplication: "
-			                "vectors must have the same dimensions for this operation");
-			return NULL;
-		}
-
-		/* element-wise product */
-		return vector_mul_vec(vec1, vec2);
+    if (vec1->size != vec2->size) {
+      PyErr_SetString(PyExc_ValueError,
+                      "Vector multiplication: "
+                      "vectors must have the same dimensions for this operation");
+      return NULL;
+    }
+
+    /* element-wise product */
+    return vector_mul_vec(vec1, vec2);
 #endif
-	}
-	else if (vec1) {
-		if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
-			return vector_mul_float(vec1, scalar);
-		}
-	}
-	else if (vec2) {
-		if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * VEC */
-			return vector_mul_float(vec2, scalar);
-		}
-	}
-
-	PyErr_Format(PyExc_TypeError,
-	             "Element-wise multiplication: "
-	             "not supported between '%.200s' and '%.200s' types",
-	             Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
-	return NULL;
+  }
+  else if (vec1) {
+    if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* VEC * FLOAT */
+      return vector_mul_float(vec1, scalar);
+    }
+  }
+  else if (vec2) {
+    if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * VEC */
+      return vector_mul_float(vec2, scalar);
+    }
+  }
+
+  PyErr_Format(PyExc_TypeError,
+               "Element-wise multiplication: "
+               "not supported between '%.200s' and '%.200s' types",
+               Py_TYPE(v1)->tp_name,
+               Py_TYPE(v2)->tp_name);
+  return NULL;
 }
 
 /* multiplication in-place: obj *= obj */
 static PyObject *Vector_imul(PyObject *v1, PyObject *v2)
 {
-	VectorObject *vec1 = NULL, *vec2 = NULL;
-	float scalar;
-
-	if (VectorObject_Check(v1)) {
-		vec1 = (VectorObject *)v1;
-		if (BaseMath_ReadCallback(vec1) == -1) {
-			return NULL;
-		}
-	}
-	if (VectorObject_Check(v2)) {
-		vec2 = (VectorObject *)v2;
-		if (BaseMath_ReadCallback(vec2) == -1) {
-			return NULL;
-		}
-	}
-
-	if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
-		return NULL;
-	}
-
-	/* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
-
-	if (vec1 && vec2) {
+  VectorObject *vec1 = NULL, *vec2 = NULL;
+  float scalar;
+
+  if (VectorObject_Check(v1)) {
+    vec1 = (VectorObject *)v1;
+    if (BaseMath_ReadCallback(vec1) == -1) {
+      return NULL;
+    }
+  }
+  if (VectorObject_Check(v2)) {
+    vec2 = (VectorObject *)v2;
+    if (BaseMath_ReadCallback(vec2) == -1) {
+      return NULL;
+    }
+  }
+
+  if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
+    return NULL;
+  }
+
+  /* Intentionally don't support (Quaternion, Matrix) here, uses reverse order instead. */
+
+  if (vec1 && vec2) {
 #ifdef USE_MATHUTILS_ELEM_MUL
-		if (vec1->size != vec2->size) {
-			PyErr_SetString(PyExc_ValueError,
-			                "Vector multiplication: "
-			                "vectors must have the same dimensions for this operation");
-			return NULL;
-		}
-
-		/* element-wise product inplace */
-		mul_vn_vn(vec1->vec, vec2->vec, vec1->size);
+    if (vec1->size != vec2->size) {
+      PyErr_SetString(PyExc_ValueError,
+                      "Vector multiplication: "
+                      "vectors must have the same dimensions for this operation");
+      return NULL;
+    }
+
+    /* element-wise product inplace */
+    mul_vn_vn(vec1->vec, vec2->vec, vec1->size);
 #else
-		PyErr_Format(PyExc_TypeError,
-		             "Inplace element-wise multiplication: "
-		             "not supported between '%.200s' and '%.200s' types",
-		             Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
-		return NULL;
+    PyErr_Format(PyExc_TypeError,
+                 "Inplace element-wise multiplication: "
+                 "not supported between '%.200s' and '%.200s' types",
+                 Py_TYPE(v1)->tp_name,
+                 Py_TYPE(v2)->tp_name);
+    return NULL;
 #endif
-	}
-	else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0)) { /* VEC *= FLOAT */
-		mul_vn_fl(vec1->vec, vec1->size, scalar);
-	}
-	else {
-		PyErr_Format(PyExc_TypeError,
-		             "Inplace element-wise multiplication: "
-		             "not supported between '%.200s' and '%.200s' types",
-		             Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
-		return NULL;
-	}
-
-	(void)BaseMath_WriteCallback(vec1);
-	Py_INCREF(v1);
-	return v1;
+  }
+  else if (vec1 && (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) ==
+                    0)) { /* VEC *= FLOAT */
+    mul_vn_fl(vec1->vec, vec1->size, scalar);
+  }
+  else {
+    PyErr_Format(PyExc_TypeError,
+                 "Inplace element-wise multiplication: "
+                 "not supported between '%.200s' and '%.200s' types",
+                 Py_TYPE(v1)->tp_name,
+                 Py_TYPE(v2)->tp_name);
+    return NULL;
+  }
+
+  (void)BaseMath_WriteCallback(vec1);
+  Py_INCREF(v1);
+  return v1;
 }
 
 static PyObject *Vector_matmul(PyObject *v1, PyObject *v2)
 {
-	VectorObject *vec1 = NULL, *vec2 = NULL;
-	int vec_size;
-
-	if (VectorObject_Check(v1)) {
-		vec1 = (VectorObject *)v1;
-		if (BaseMath_ReadCallback(vec1) == -1) {
-			return NULL;
-		}
-	}
-	if (VectorObject_Check(v2)) {
-		vec2 = (VectorObject *)v2;
-		if (BaseMath_ReadCallback(vec2) == -1) {
-			return NULL;
-		}
-	}
-
-
-	/* Intentionally don't support (Quaternion) here, uses reverse order instead. */
-
-	/* make sure v1 is always the vector */
-	if (vec1 && vec2) {
-		if (vec1->size != vec2->size) {
-			PyErr_SetString(PyExc_ValueError,
-			                "Vector multiplication: "
-			                "vectors must have the same dimensions for this operation");
-			return NULL;
-		}
-
-		/*dot product*/
-		return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
-	}
-	else if (vec1) {
-		if (MatrixObject_Check(v2)) {
-			/* VEC @ MATRIX */
-			float tvec[MAX_DIMENSIONS];
-
-			if (BaseMath_ReadCallback((MatrixObject *)v2) == -1) {
-				return NULL;
-			}
-			if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
-				return NULL;
-			}
-
-			if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
-				vec_size = 3;
-			}
-			else {
-				vec_size = ((MatrixObject *)v2)->num_col;
-			}
-
-			return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
-		}
-	}
-
-	PyErr_Format(PyExc_TypeError,
-	             "Vector multiplication: "
-	             "not supported between '%.200s' and '%.200s' types",
-	             Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
-	return NULL;
+  VectorObject *vec1 = NULL, *vec2 = NULL;
+  int vec_size;
+
+  if (VectorObject_Check(v1)) {
+    vec1 = (VectorObject *)v1;
+    if (BaseMath_ReadCallback(vec1) == -1) {
+      return NULL;
+    }
+  }
+  if (VectorObject_Check(v2)) {
+    vec2 = (VectorObject *)v2;
+    if (BaseMath_ReadCallback(vec2) == -1) {
+      return NULL;
+    }
+  }
+
+  /* Intentionally don't support (Quaternion) here, uses reverse order instead. */
+
+  /* make sure v1 is always the vector */
+  if (vec1 && vec2) {
+    if (vec1->size != vec2->size) {
+      PyErr_SetString(PyExc_ValueError,
+                      "Vector multiplication: "
+                      "vectors must have the same dimensions for this operation");
+      return NULL;
+    }
+
+    /*dot product*/
+    return PyFloat_FromDouble(dot_vn_vn(vec1->vec, vec2->vec, vec1->size));
+  }
+  else if (vec1) {
+    if (MatrixObject_Check(v2)) {
+      /* VEC @ MATRIX */
+      float tvec[MAX_DIMENSIONS];
+
+      if (BaseMath_ReadCallback((MatrixObject *)v2) == -1) {
+        return NULL;
+      }
+      if (row_vector_multiplication(tvec, vec1, (MatrixObject *)v2) == -1) {
+        return NULL;
+      }
+
+      if (((MatrixObject *)v2)->num_row == 4 && vec1->size == 3) {
+        vec_size = 3;
+      }
+      else {
+        vec_size = ((MatrixObject *)v2)->num_col;
+      }
+
+      return Vector_CreatePyObject(tvec, vec_size, Py_TYPE(vec1));
+    }
+  }
+
+  PyErr_Format(PyExc_TypeError,
+               "Vector multiplication: "
+               "not supported between '%.200s' and '%.200s' types",
+               Py_TYPE(v1)->tp_name,
+               Py_TYPE(v2)->tp_name);
+  return NULL;
 }
 
 static PyObject *Vector_imatmul(PyObject *v1, PyObject *v2)
 {
-	PyErr_Format(PyExc_TypeError,
-	             "Inplace vector multiplication: "
-	             "not supported between '%.200s' and '%.200s' types",
-	             Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name);
-	return NULL;
+  PyErr_Format(PyExc_TypeError,
+               "Inplace vector multiplication: "
+               "not supported between '%.200s' and '%.200s' types",
+               Py_TYPE(v1)->tp_name,
+               Py_TYPE(v2)->tp_name);
+  return NULL;
 }
 
 /* divid: obj / obj */
 static PyObject *Vector_div(PyObject *v1, PyObject *v2)
 {
-	float *vec = NULL, scalar;
-	VectorObject *vec1 = NULL;
+  float *vec = NULL, scalar;
+  VectorObject *vec1 = NULL;
 
-	if (!VectorObject_Check(v1)) { /* not a vector */
-		PyErr_SetString(PyExc_TypeError,
-		                "Vector division: "
-		                "Vector must be divided by a float");
-		return NULL;
-	}
-	vec1 = (VectorObject *)v1; /* vector */
+  if (!VectorObject_Check(v1)) { /* not a vector */
+    PyErr_SetString(PyExc_TypeError,
+                    "Vector division: "
+                    "Vector must be divided by a float");
+    return NULL;
+  }
+  vec1 = (VectorObject *)v1; /* vector */
 
-	if (BaseMath_ReadCallback(vec1) == -1) {
-		return NULL;
-	}
+  if (BaseMath_ReadCallback(vec1) == -1) {
+    return NULL;
+  }
 
-	if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
-		PyErr_SetString(PyExc_TypeError,
-		                "Vector division: "
-		                "Vector must be divided by a float");
-		return NULL;
-	}
+  if ((scalar = PyFloat_AsDouble(v2)) == -1.0f &&
+      PyErr_Occurred()) { /* parsed item not a number */
+    PyErr_SetString(PyExc_TypeError,
+                    "Vector division: "
+                    "Vector must be divided by a float");
+    return NULL;
+  }
 
-	if (scalar == 0.0f) {
-		PyErr_SetString(PyExc_ZeroDivisionError,
-		                "Vector division: "
-		                "divide by zero error");
-		return NULL;
-	}
+  if (scalar == 0.0f) {
+    PyErr_SetString(PyExc_ZeroDivisionError,
+                    "Vector division: "
+                    "divide by zero error");
+    return NULL;
+  }
 
-	vec = PyMem_Malloc(vec1->size * sizeof(float));
+  vec = PyMem_Malloc(vec1->size * sizeof(float));
 
-	if (vec == NULL) {
-		PyErr_SetString(PyExc_MemoryError,
-		                "vec / value: "
-		                "problem allocating pointer space");
-		return NULL;
-	}
+  if (vec == NULL) {
+    PyErr_SetString(PyExc_MemoryError,
+                    "vec / value: "
+                    "problem allocating pointer space");
+    return NULL;
+  }
 
-	mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f / scalar);
+  mul_vn_vn_fl(vec, vec1->vec, vec1->size, 1.0f / scalar);
 
-	return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
+  return Vector_CreatePyObject_alloc(vec, vec1->size, Py_TYPE(v1));
 }
 
 /* divide in-place: obj /= obj */
 static PyObject *Vector_idiv(PyObject *v1, PyObject *v2)
 {
-	float scalar;
-	VectorObject *vec1 = (VectorObject *)v1;
+  float scalar;
+  VectorObject *vec1 = (VectorObject *)v1;
 
-	if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
-		return NULL;
-	}
+  if (BaseMath_ReadCallback_ForWrite(vec1) == -1) {
+    return NULL;
+  }
 
-	if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */
-		PyErr_SetString(PyExc_TypeError,
-		                "Vector division: "
-		                "Vector must be divided by a float");
-		return NULL;
-	}
+  if ((scalar = PyFloat_AsDouble(v2)) == -1.0f &&
+      PyErr_Occurred()) { /* parsed item not a number */
+    PyErr_SetString(PyExc_TypeError,
+                    "Vector division: "
+                    "Vector must be divided by a float");
+    return NULL;
+  }
 
-	if (scalar == 0.0f) {
-		PyErr_SetString(PyExc_ZeroDivisionError,
-		                "Vector division: "
-		                "divide by zero error");
-		return NULL;
-	}
+  if (scalar == 0.0f) {
+    PyErr_SetString(PyExc_ZeroDivisionError,
+                    "Vector division: "
+                    "divide by zero error");
+    return NULL;
+  }
 
-	mul_vn_fl(vec1->vec, vec1->size, 1.0f / scalar);
+  mul_vn_fl(vec1->vec, vec1->size, 1.0f / scalar);
 
-	(void)BaseMath_WriteCallback(vec1);
+  (void)BaseMath_WriteCallback(vec1);
 
-	Py_INCREF(v1);
-	return v1;
+  Py_INCREF(v1);
+  return v1;
 }
 
 /* -obj
  * returns the negative of this object*/
 static PyObject *Vector_neg(VectorObject *self)
 {
-	float *tvec;
+  float *tvec;
 
-	if (BaseMath_ReadCallback(self) == -1) {
-		return NULL;
-	}
+  if (BaseMath_ReadCallback(self) == -1) {
+    return NULL;
+  }
 
-	tvec = PyMem_Malloc(self->size * sizeof(float));
-	negate_vn_vn(tvec, self->vec, self->size);
-	return Vector_CreatePyObject_alloc(tvec, self->size, Py_TYPE(self));
+  tvec = PyMem_Malloc(self->size * sizeof(float));
+  negate_vn_vn(tvec, self->vec, self->size);
+  return Vector_CreatePyObject_alloc(tvec, self->size, Py_TYPE(self));
 }
 
 /*------------------------tp_richcmpr
  * returns -1 exception, 0 false, 1 true */
 static PyObject *Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
 {
-	VectorObject *vecA = NULL, *vecB = NULL;
-	int result = 0;
-	double epsilon = 0.000001f;
-	double lenA, lenB;
-
-	if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)) {
-		if (comparison_type == Py_NE) {
-			Py_RETURN_TRUE;
-		}
-		else {
-			Py_RETURN_FALSE;
-		}
-	}
-	vecA = (VectorObject *)objectA;
-	vecB = (VectorObject *)objectB;
-
-	if (BaseMath_ReadCallback(vecA) == -1 || BaseMath_ReadCallback(vecB) == -1) {
-		return NULL;
-	}
-
-	if (vecA->size != vecB->size) {
-		if (comparison_type == Py_NE) {
-			Py_RETURN_TRUE;
-		}
-		else {
-			Py_RETURN_FALSE;
-		}
-	}
-
-	switch (comparison_type) {
-		case Py_LT:
-			lenA = len_squared_vn(vecA->vec, vecA->size);
-			lenB = len_squared_vn(vecB->vec, vecB->size);
-			if (lenA < lenB) {
-				result = 1;
-			}
-			break;
-		case Py_LE:
-			lenA = len_squared_vn(vecA->vec, vecA->size);
-			lenB = len_squared_vn(vecB->vec, vecB->size);
-			if (lenA < lenB) {
-				result = 1;
-			}
-			else {
-				result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
-			}
-			break;
-		case Py_EQ:
-			result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
-			break;
-		case Py_NE:
-			result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
-			break;
-		case Py_GT:
-			lenA = len_squared_vn(vecA->vec, vecA->size);
-			lenB = len_squared_vn(vecB->vec, vecB->size);
-			if (lenA > lenB) {
-				result = 1;
-			}
-			break;
-		case Py_GE:
-			lenA = len_squared_vn(vecA->vec, vecA->size);
-			lenB = len_squared_vn(vecB->vec, vecB->size);
-			if (lenA > lenB) {
-				result = 1;
-			}
-			else {
-				result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
-			}
-			break;
-		default:
-			printf("The result of the comparison could not be evaluated");
-			break;
-	}
-	if (result == 1) {
-		Py_RETURN_TRUE;
-	}
-	else {
-		Py_RETURN_FALSE;
-	}
+  VectorObject *vecA = NULL, *vecB = NULL;
+  int result = 0;
+  double epsilon = 0.000001f;
+  double lenA, lenB;
+
+  if (!VectorObject_Check(objectA) || !VectorObject_Check(objectB)) {
+    if (comparison_type == Py_NE) {
+      Py_RETURN_TRUE;
+    }
+    else {
+      Py_RETURN_FALSE;
+    }
+  }
+  vecA = (VectorObject *)objectA;
+  vecB = (VectorObject *)objectB;
+
+  if (BaseMath_ReadCallback(vecA) == -1 || BaseMath_ReadCallback(vecB) == -1) {
+    return NULL;
+  }
+
+  if (vecA->size != vecB->size) {
+    if (comparison_type == Py_NE) {
+      Py_RETURN_TRUE;
+    }
+    else {
+      Py_RETURN_FALSE;
+    }
+  }
+
+  switch (comparison_type) {
+    case Py_LT:
+      lenA = len_squared_vn(vecA->vec, vecA->size);
+      lenB = len_squared_vn(vecB->vec, vecB->size);
+      if (lenA < lenB) {
+        result = 1;
+      }
+      break;
+    case Py_LE:
+      lenA = len_squared_vn(vecA->vec, vecA->size);
+      lenB = len_squared_vn(vecB->vec, vecB->size);
+      if (lenA < lenB) {
+        result = 1;
+      }
+      else {
+        result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
+      }
+      break;
+    case Py_EQ:
+      result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
+      break;
+    case Py_NE:
+      result = !EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
+      break;
+    case Py_GT:
+      lenA = len_squared_vn(vecA->vec, vecA->size);
+      lenB = len_squared_vn(vecB->vec, vecB->size);
+      if (lenA > lenB) {
+        result = 1;
+      }
+      break;
+    case Py_GE:
+      lenA = len_squared_vn(vecA->vec, vecA->size);
+      lenB = len_squared_vn(vecB->vec, vecB->size);
+      if (lenA > lenB) {
+        result = 1;
+      }
+      else {
+        result = (((lenA + epsilon) > lenB) && ((lenA - epsilon) < lenB));
+      }
+      break;
+    default:
+      printf("The result of the comparison could not be evaluated");
+      break;
+  }
+  if (result == 1) {
+    Py_RETURN_TRUE;
+  }
+  else {
+    Py_RETURN_FALSE;
+  }
 }
 
 static Py_hash_t Vector_hash(VectorObject *self)
 {
-	if (BaseMath_ReadCallback(self) == -1) {
-		return -1;
-	}
+  if (BaseMath_ReadCallback(self) == -1) {
+    return -1;
+  }
 
-	if (BaseMathObject_Prepare_ForHash(self) == -1) {
-		return -1;
-	}
+  if (BaseMathObject_Prepare_ForHash(self) == -1) {
+    return -1;
+  }
 
-	return mathutils_array_hash(self->vec, self->size);
+  return mathutils_array_hash(self->vec, self->size);
 }
 
 /*-----------------PROTCOL DECLARATIONS--------------------------*/
 static PySequenceMethods Vector_SeqMethods = {
-	(lenfunc) Vector_len,               /* sq_length */
-	(binaryfunc) NULL,                  /* sq_concat */
-	(ssizeargfunc) NULL,                /* sq_repeat */
-	(ssizeargfunc) Vector_item,         /* sq_item */
-	NULL,                               /* py3 deprecated slice func */
-	(ssizeobjargproc) Vector_ass_item,  /* sq_ass_item */
-	NULL,                               /* py3 deprecated slice assign func */
-	(objobjproc) NULL,                  /* sq_contains */
-	(binaryfunc) NULL,                  /* sq_inplace_concat */
-	(ssizeargfunc) NULL,                /* sq_inplace_repeat */
+    (lenfunc)Vector_len,              /* sq_length */
+    (binaryfunc)NULL,                 /* sq_concat */
+    (ssizeargfunc)NULL,               /* sq_repeat */
+    (ssizeargfunc)Vector_item,        /* sq_item */
+    NULL,                             /* py3 deprecated slice func */
+    (ssizeobjargproc)Vector_ass_item, /* sq_ass_item */
+    NULL,                             /* py3 deprecated slice assign func */
+    (objobjproc)NULL,                 /* sq_contains */
+    (binaryfunc)NULL,                 /* sq_inplace_concat */
+    (ssizeargfunc)NULL,               /* sq_inplace_repeat */
 };
 
 static PyObject *Vector_subscript(VectorObject *self, PyObject *item)
 {
-	if (PyIndex_Check(item)) {
-		Py_ssize_t i;
-		i = PyNumber_AsSsize_t(item, PyExc_IndexError);
-		if (i == -1 && PyErr_Occurred()) {
-			return NULL;
-		}
-		if (i < 0) {
-			i += self->size;
-		}
-		return Vector_item(self, i);
-	}
-	else if (PySlice_Check(item)) {
-		Py_ssize_t start, stop, step, slicelength;
-
-		if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) {
-			return NULL;
-		}
-
-		if (slicelength <= 0) {
-			return PyTuple_New(0);
-		}
-		else if (step == 1) {
-			return Vector_slice(self, start, stop);
-		}
-		else {
-			PyErr_SetString(PyExc_IndexError,
-			                "slice steps not supported with vectors");
-			return NULL;
-		}
-	}
-	else {
-		PyErr_Format(PyExc_TypeError,
-		             "vector indices must be integers, not %.200s",
-		             Py_TYPE(item)->tp_name);
-		return NULL;
-	}
+  if (PyIndex_Check(item)) {
+    Py_ssize_t i;
+    i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+    if (i == -1 && PyErr_Occurred()) {
+      return NULL;
+    }
+    if (i < 0) {
+      i += self->size;
+    }
+    return Vector_item(self, i);
+  }
+  else if (PySlice_Check(item)) {
+    Py_ssize_t start, stop, step, slicelength;
+
+    if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) {
+      return NULL;
+    }
+
+    if (slicelength <= 0) {
+      return PyTuple_New(0);
+    }
+    else if (step == 1) {
+      return Vector_slice(self, start, stop);
+    }
+    else {
+      PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
+      return NULL;
+    }
+  }
+  else {
+    PyErr_Format(
+        PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
+    return NULL;
+  }
 }
 
 static int Vector_ass_subscript(VectorObject *self, PyObject *item, PyObject *value)
 {
-	if (PyIndex_Check(item)) {
-		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
-		if (i == -1 && PyErr_Occurred()) {
-			return -1;
-		}
-		if (i < 0) {
-			i += self->size;
-		}
-		return Vector_ass_item(self, i, value);
-	}
-	else if (PySlice_Check(item)) {
-		Py_ssize_t start, stop, step, slicelength;
-
-		if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) {
-			return -1;
-		}
-
-		if (step == 1) {
-			return Vector_ass_slice(self, start, stop, value);
-		}
-		else {
-			PyErr_SetString(PyExc_IndexError,
-			                "slice steps not supported with vectors");
-			return -1;
-		}
-	}
-	else {
-		PyErr_Format(PyExc_TypeError,
-		             "vector indices must be integers, not %.200s",
-		             Py_TYPE(item)->tp_name);
-		return -1;
-	}
+  if (PyIndex_Check(item)) {
+    Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+    if (i == -1 && PyErr_Occurred()) {
+      return -1;
+    }
+    if (i < 0) {
+      i += self->size;
+    }
+    return Vector_ass_item(self, i, value);
+  }
+  else if (PySlice_Check(item)) {
+    Py_ssize_t start, stop, step, slicelength;
+
+    if (PySlice_GetIndicesEx(item, self->size, &start, &stop, &step, &slicelength) < 0) {
+      return -1;
+    }
+
+    if (step == 1) {
+      return Vector_ass_slice(self, start, stop, value);
+    }
+    else {
+      PyErr_SetString(PyExc_IndexError, "slice steps not supported with vectors");
+      return -1;
+    }
+  }
+  else {
+    PyErr_Format(
+        PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
+    return -1;
+  }
 }
 
 static PyMappingMethods Vector_AsMapping = {
-	(lenfunc)Vector_len,
-	(binaryfunc)Vector_subscript,
-	(objobjargproc)Vector_ass_subscript,
+    (lenfunc)Vector_len,
+    (binaryfunc)Vector_subscript,
+    (objobjargproc)Vector_ass_subscript,
 };
 
-
 static PyNumberMethods Vector_NumMethods = {
-	(binaryfunc)    Vector_add, /*nb_add*/
-	(binaryfunc)    Vector_sub, /*nb_subtract*/
-	(binaryfunc)    Vector_mul, /*nb_multiply*/
-	NULL,                       /*nb_remainder*/
-	NULL,                       /*nb_divmod*/
-	NULL,                       /*nb_power*/
-	(unaryfunc)     Vector_neg, /*nb_negative*/
-	(unaryfunc)     Vector_copy,/*tp_positive*/
-	(unaryfunc)     NULL,       /*tp_absolute*/
-	(inquiry)   NULL,           /*tp_bool*/
-	(unaryfunc) NULL,           /*nb_invert*/
-	NULL,                       /*nb_lshift*/
-	(binaryfunc)NULL,           /*nb_rshift*/
-	NULL,                       /*nb_and*/
-	NULL,                       /*nb_xor*/
-	NULL,                       /*nb_or*/
-	NULL,                       /*nb_int*/
-	NULL,                       /*nb_reserved*/
-	NULL,                       /*nb_float*/
-	Vector_iadd,                /* nb_inplace_add */
-	Vector_isub,                /* nb_inplace_subtract */
-	Vector_imul,                /* nb_inplace_multiply */
-	NULL,                       /* nb_inplace_remainder */
-	NULL,                       /* nb_inplace_power */
-	NULL,                       /* nb_inplace_lshift */
-	NULL,                       /* nb_inplace_rshift */
-	NULL,                       /* nb_inplace_and */
-	NULL,                       /* nb_inplace_xor */
-	NULL,                       /* nb_inplace_or */
-	NULL,                       /* nb_floor_divide */
-	Vector_div,                 /* nb_true_divide */
-	NULL,                       /* nb_inplace_floor_divide */
-	Vector_idiv,                /* nb_inplace_true_divide */
-	NULL,                       /* nb_index */
-	(binaryfunc) Vector_matmul, /* nb_matrix_multiply */
-	(binaryfunc) Vector_imatmul, /* nb_inplace_matrix_multiply */
+    (binaryfunc)Vector_add,     /*nb_add*/
+    (binaryfunc)Vector_sub,     /*nb_subtract*/
+    (binaryfunc)Vector_mul,     /*nb_multiply*/
+    NULL,                       /*nb_remainder*/
+    NULL,                       /*nb_divmod*/
+    NULL,                       /*nb_power*/
+    (unaryfunc)Vector_neg,      /*nb_negative*/
+    (unaryfunc)Vector_copy,     /*tp_positive*/
+    (unaryfunc)NULL,            /*tp_absolute*/
+    (inquiry)NULL,              /*tp_bool*/
+    (unaryfunc)NULL,            /*nb_invert*/
+    NULL,                       /*nb_lshift*/
+    (binaryfunc)NULL,           /*nb_rshift*/
+    NULL,                       /*nb_and*/
+    NULL,                       /*nb_xor*/
+    NULL,                       /*nb_or*/
+    NULL,                       /*nb_int*/
+    NULL,                       /*nb_reserved*/
+    NULL,                       /*nb_float*/
+    Vector_iadd,                /* nb_inplace_add */
+    Vector_isub,                /* nb_inplace_subtract */
+    Vector_imul,                /* nb_inplace_multiply */
+    NULL,                       /* nb_inplace_remainder */
+    NULL,                       /* nb_inplace_power */
+    NULL,                       /* nb_inplace_lshift */
+    NULL,                       /* nb_inplace_rshift */
+    NULL,                       /* nb_inplace_and */
+    NULL,                       /* nb_inplace_xor */
+    NULL,                       /* nb_inplace_or */
+    NULL,                       /* nb_floor_divide */
+    Vector_div,                 /* nb_true_divide */
+    NULL,                       /* nb_inplace_floor_divide */
+    Vector_idiv,                /* nb_inplace_true_divide */
+    NULL,                       /* nb_index */
+    (binaryfunc)Vector_matmul,  /* nb_matrix_multiply */
+    (binaryfunc)Vector_imatmul, /* nb_inplace_matrix_multiply */
 };
 
 /*------------------PY_OBECT DEFINITION--------------------------*/
@@ -2292,88 +2268,81 @@ PyDoc_STRVAR(Vector_axis_w_doc, "Vector W axis (4D Vectors only).\n\n:type: floa
 
 static PyObject *Vector_axis_get(VectorObject *self, void *type)
 {
-	return vector_item_internal(self, POINTER_AS_INT(type), true);
+  return vector_item_internal(self, POINTER_AS_INT(type), true);
 }
 
 static int Vector_axis_set(VectorObject *self, PyObject *value, void *type)
 {
-	return vector_ass_item_internal(self, POINTER_AS_INT(type), value, true);
+  return vector_ass_item_internal(self, POINTER_AS_INT(type), value, true);
 }
 
 /* vector.length */
 
-PyDoc_STRVAR(Vector_length_doc,
-"Vector Length.\n\n:type: float"
-);
+PyDoc_STRVAR(Vector_length_doc, "Vector Length.\n\n:type: float");
 static PyObject *Vector_length_get(VectorObject *self, void *UNUSED(closure))
 {
-	if (BaseMath_ReadCallback(self) == -1) {
-		return NULL;
-	}
+  if (BaseMath_ReadCallback(self) == -1) {
+    return NULL;
+  }
 
-	return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->size)));
+  return PyFloat_FromDouble(sqrt(dot_vn_vn(self->vec, self->vec, self->size)));
 }
 
 static int Vector_length_set(VectorObject *self, PyObject *value)
 {
-	double dot = 0.0f, param;
+  double dot = 0.0f, param;
 
-	if (BaseMath_ReadCallback_ForWrite(self) == -1) {
-		return -1;
-	}
+  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
+    return -1;
+  }
 
-	if ((param = PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) {
-		PyErr_SetString(PyExc_TypeError,
-		                "length must be set to a number");
-		return -1;
-	}
+  if ((param = PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) {
+    PyErr_SetString(PyExc_TypeError, "length must be set to a number");
+    return -1;
+  }
 
-	if (param < 0.0) {
-		PyErr_SetString(PyExc_ValueError,
-		                "cannot set a vectors length to a negative value");
-		return -1;
-	}
-	if (param == 0.0) {
-		copy_vn_fl(self->vec, self->size, 0.0f);
-		return 0;
-	}
+  if (param < 0.0) {
+    PyErr_SetString(PyExc_ValueError, "cannot set a vectors length to a negative value");
+    return -1;
+  }
+  if (param == 0.0) {
+    copy_vn_fl(self->vec, self->size, 0.0f);
+    return 0;
+  }
 
-	dot = dot_vn_vn(self->vec, self->vec, self->size);
+  dot = dot_vn_vn(self->vec, self->vec, self->size);
 
-	if (!dot) {
-		/* cant sqrt zero */
-		return 0;
-	}
+  if (!dot) {
+    /* cant sqrt zero */
+    return 0;
+  }
 
-	dot = sqrt(dot);
+  dot = sqrt(dot);
 
-	if (dot == param) {
-		return 0;
-	}
+  if (dot == param) {
+    return 0;
+  }
 
-	dot = dot / param;
+  dot = dot / param;
 
-	mul_vn_fl(self->vec, self->size, 1.0 / dot);
+  mul_vn_fl(self->vec, self->size, 1.0 / dot);
 
-	(void)BaseMath_WriteCallback(self); /* checked already */
+  (void)BaseMath_WriteCallback(self); /* checked already */
 
-	return 0;
+  return 0;
 }
 
 /* vector.length_squared */
-PyDoc_STRVAR(Vector_length_squared_doc,
-"Vector length squared (v.dot(v)).\n\n:type: float"
-);
+PyDoc_STRVAR(Vector_length_squared_doc, "Vector length squared (v.dot(v)).\n\n:type: float");
 static PyObject *Vector_length_squared_get(VectorObject *self, void *UNUSED(closure))
 {
-	if (BaseMath_ReadCallback(self) == -1) {
-		return NULL;
-	}
+  if (BaseMath_ReadCallback(self) == -1) {
+    return NULL;
+  }
 
-	return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->size));
+  return PyFloat_FromDouble(dot_vn_vn(self->vec, self->vec, self->size));
 }
 
-
 /**
  * Python script used to make swizzle array:
  *
@@ -2434,33 +2403,33 @@ static PyObject *Vector_length_squared_get(VectorObject *self, void *UNUSED(clos
  */
 static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
 {
-	size_t axis_to;
-	size_t axis_from;
-	float vec[MAX_DIMENSIONS];
-	unsigned int swizzleClosure;
+  size_t axis_to;
+  size_t axis_from;
+  float vec[MAX_DIMENSIONS];
+  unsigned int swizzleClosure;
 
-	if (BaseMath_ReadCallback(self) == -1) {
-		return NULL;
-	}
+  if (BaseMath_ReadCallback(self) == -1) {
+    return NULL;
+  }
 
-	/* Unpack the axes from the closure into an array. */
-	axis_to = 0;
-	swizzleClosure = POINTER_AS_INT(closure);
-	while (swizzleClosure & SWIZZLE_VALID_AXIS) {
-		axis_from = swizzleClosure & SWIZZLE_AXIS;
-		if (axis_from >= self->size) {
-			PyErr_SetString(PyExc_AttributeError,
-			                "Vector swizzle: "
-			                "specified axis not present");
-			return NULL;
-		}
+  /* Unpack the axes from the closure into an array. */
+  axis_to = 0;
+  swizzleClosure = POINTER_AS_INT(closure);
+  while (swizzleClosure & SWIZZLE_VALID_AXIS) {
+    axis_from = swizzleClosure & SWIZZLE_AXIS;
+    if (axis_from >= self->size) {
+      PyErr_SetString(PyExc_AttributeError,
+                      "Vector swizzle: "
+                      "specified axis not present");
+      return NULL;
+    }
 
-		vec[axis_to] = self->vec[axis_from];
-		swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
-		axis_to++;
-	}
+    vec[axis_to] = self->vec[axis_from];
+    swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+    axis_to++;
+  }
 
-	return Vector_CreatePyObject(vec, axis_to, Py_TYPE(self));
+  return Vector_CreatePyObject(vec, axis_to, Py_TYPE(self));
 }
 
 /**
@@ -2476,450 +2445,666 @@ static PyObject *Vector_swizzle_get(VectorObject *self, void *closure)
  */
 static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure)
 {
-	size_t size_from;
-	float scalarVal;
-
-	size_t axis_from;
-	size_t axis_to;
-
-	unsigned int swizzleClosure;
-
-	float tvec[MAX_DIMENSIONS];
-	float vec_assign[MAX_DIMENSIONS];
-
-	if (BaseMath_ReadCallback_ForWrite(self) == -1) {
-		return -1;
-	}
-
-	/* Check that the closure can be used with this vector: even 2D vectors have
-	 * swizzles defined for axes z and w, but they would be invalid. */
-	swizzleClosure = POINTER_AS_INT(closure);
-	axis_from = 0;
-
-	while (swizzleClosure & SWIZZLE_VALID_AXIS) {
-		axis_to = swizzleClosure & SWIZZLE_AXIS;
-		if (axis_to >= self->size) {
-			PyErr_SetString(PyExc_AttributeError,
-			                "Vector swizzle: "
-			                "specified axis not present");
-			return -1;
-		}
-		swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
-		axis_from++;
-	}
-
-	if (((scalarVal = PyFloat_AsDouble(value)) == -1 && PyErr_Occurred()) == 0) {
-		int i;
-
-		for (i = 0; i < MAX_DIMENSIONS; i++) {
-			vec_assign[i] = scalarVal;
-		}
-
-		size_from = axis_from;
-	}
-	else if (((void)PyErr_Clear()), /* run but ignore the result */
-	         (size_from = mathutils_array_parse(vec_assign, 2, 4, value,
-	                                            "mathutils.Vector.**** = swizzle assignment")) == -1)
-	{
-		return -1;
-	}
-
-	if (axis_from != size_from) {
-		PyErr_SetString(PyExc_AttributeError,
-		                "Vector swizzle: size does not match swizzle");
-		return -1;
-	}
-
-	/* Copy vector contents onto swizzled axes. */
-	axis_from = 0;
-	swizzleClosure = POINTER_AS_INT(closure);
-
-	/* We must first copy current vec into tvec, else some org values may be lost.
-	 * See [#31760].
-	 * Assuming self->size can't be higher than MAX_DIMENSIONS! */
-	memcpy(tvec, self->vec, self->size * sizeof(float));
-
-	while (swizzleClosure & SWIZZLE_VALID_AXIS) {
-		axis_to = swizzleClosure & SWIZZLE_AXIS;
-		tvec[axis_to] = vec_assign[axis_from];
-		swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
-		axis_from++;
-	}
-
-	/* We must copy back the whole tvec into vec, else some changes may be lost (e.g. xz...).
-	 * See [#31760]. */
-	memcpy(self->vec, tvec, self->size * sizeof(float));
-	/* continue with BaseMathObject_WriteCallback at the end */
-
-	if (BaseMath_WriteCallback(self) == -1) {
-		return -1;
-	}
-	else {
-		return 0;
-	}
-}
-
-#define _SWIZZLE1(a)                                 ((a) | SWIZZLE_VALID_AXIS)
-#define _SWIZZLE2(a, b)       (_SWIZZLE1(a)       | (((b) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS)))
-#define _SWIZZLE3(a, b, c)    (_SWIZZLE2(a, b)    | (((c) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))
-#define _SWIZZLE4(a, b, c, d) (_SWIZZLE3(a, b, c) | (((d) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3)))
-
-#define SWIZZLE2(a, b)       POINTER_FROM_INT(_SWIZZLE2(a, b))
-#define SWIZZLE3(a, b, c)    POINTER_FROM_INT(_SWIZZLE3(a, b, c))
+  size_t size_from;
+  float scalarVal;
+
+  size_t axis_from;
+  size_t axis_to;
+
+  unsigned int swizzleClosure;
+
+  float tvec[MAX_DIMENSIONS];
+  float vec_assign[MAX_DIMENSIONS];
+
+  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
+    return -1;
+  }
+
+  /* Check that the closure can be used with this vector: even 2D vectors have
+   * swizzles defined for axes z and w, but they would be invalid. */
+  swizzleClosure = POINTER_AS_INT(closure);
+  axis_from = 0;
+
+  while (swizzleClosure & SWIZZLE_VALID_AXIS) {
+    axis_to = swizzleClosure & SWIZZLE_AXIS;
+    if (axis_to >= self->size) {
+      PyErr_SetString(PyExc_AttributeError,
+                      "Vector swizzle: "
+                      "specified axis not present");
+      return -1;
+    }
+    swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+    axis_from++;
+  }
+
+  if (((scalarVal = PyFloat_AsDouble(value)) == -1 && PyErr_Occurred()) == 0) {
+    int i;
+
+    for (i = 0; i < MAX_DIMENSIONS; i++) {
+      vec_assign[i] = scalarVal;
+    }
+
+    size_from = axis_from;
+  }
+  else if (((void)PyErr_Clear()), /* run but ignore the result */
+           (size_from = mathutils_array_parse(
+                vec_assign, 2, 4, value, "mathutils.Vector.**** = swizzle assignment")) == -1) {
+    return -1;
+  }
+
+  if (axis_from != size_from) {
+    PyErr_SetString(PyExc_AttributeError, "Vector swizzle: size does not match swizzle");
+    return -1;
+  }
+
+  /* Copy vector contents onto swizzled axes. */
+  axis_from = 0;
+  swizzleClosure = POINTER_AS_INT(closure);
+
+  /* We must first copy current vec into tvec, else some org values may be lost.
+   * See [#31760].
+   * Assuming self->size can't be higher than MAX_DIMENSIONS! */
+  memcpy(tvec, self->vec, self->size * sizeof(float));
+
+  while (swizzleClosure & SWIZZLE_VALID_AXIS) {
+    axis_to = swizzleClosure & SWIZZLE_AXIS;
+    tvec[axis_to] = vec_assign[axis_from];
+    swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS;
+    axis_from++;
+  }
+
+  /* We must copy back the whole tvec into vec, else some changes may be lost (e.g. xz...).
+   * See [#31760]. */
+  memcpy(self->vec, tvec, self->size * sizeof(float));
+  /* continue with BaseMathObject_WriteCallback at the end */
+
+  if (BaseMath_WriteCallback(self) == -1) {
+    return -1;
+  }
+  else {
+    return 0;
+  }
+}
+
+#define _SWIZZLE1(a) ((a) | SWIZZLE_VALID_AXIS)
+#define _SWIZZLE2(a, b) (_SWIZZLE1(a) | (((b) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS)))
+#define _SWIZZLE3(a, b, c) \
+  (_SWIZZLE2(a, b) | (((c) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 2)))
+#define _SWIZZLE4(a, b, c, d) \
+  (_SWIZZLE3(a, b, c) | (((d) | SWIZZLE_VALID_AXIS) << (SWIZZLE_BITS_PER_AXIS * 3)))
+
+#define SWIZZLE2(a, b) POINTER_FROM_INT(_SWIZZLE2(a, b))
+#define SWIZZLE3(a, b, c) POINTER_FROM_INT(_SWIZZLE3(a, b, c))
 #define SWIZZLE4(a, b, c, d) POINTER_FROM_INT(_SWIZZLE4(a, b, c, d))
 
 /*****************************************************************************/
 /* Python attributes get/set structure:                                      */
 /*****************************************************************************/
 static PyGetSetDef Vector_getseters[] = {
-	{(char *)"x", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_x_doc, (void *)0},
-	{(char *)"y", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_y_doc, (void *)1},
-	{(char *)"z", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_z_doc, (void *)2},
-	{(char *)"w", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_w_doc, (void *)3},
-	{(char *)"length", (getter)Vector_length_get, (setter)Vector_length_set, Vector_length_doc, NULL},
-	{(char *)"length_squared", (getter)Vector_length_squared_get, (setter)NULL, Vector_length_squared_doc, NULL},
-	{(char *)"magnitude", (getter)Vector_length_get, (setter)Vector_length_set, Vector_length_doc, NULL},
-	{(char *)"is_wrapped", (getter)BaseMathObject_is_wrapped_get, (setter)NULL, BaseMathObject_is_wrapped_doc, NULL},
-	{(char *)"is_frozen",  (getter)BaseMathObject_is_frozen_get,  (setter)NULL, BaseMathObject_is_frozen_doc, NULL},
-	{(char *)"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
-
-	/* autogenerated swizzle attrs, see Python script above */
-	{(char *)"xx",   (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(0, 0)},
-	{(char *)"xxx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 0)},
-	{(char *)"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 0)},
-	{(char *)"xxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 1)},
-	{(char *)"xxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 2)},
-	{(char *)"xxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 3)},
-	{(char *)"xxy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 1)},
-	{(char *)"xxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 0)},
-	{(char *)"xxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 1)},
-	{(char *)"xxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 2)},
-	{(char *)"xxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 3)},
-	{(char *)"xxz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 2)},
-	{(char *)"xxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 0)},
-	{(char *)"xxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 1)},
-	{(char *)"xxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 2)},
-	{(char *)"xxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 3)},
-	{(char *)"xxw",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 3)},
-	{(char *)"xxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 0)},
-	{(char *)"xxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 1)},
-	{(char *)"xxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 2)},
-	{(char *)"xxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 3)},
-	{(char *)"xy",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 1)},
-	{(char *)"xyx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 0)},
-	{(char *)"xyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 0)},
-	{(char *)"xyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 1)},
-	{(char *)"xyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 2)},
-	{(char *)"xyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 3)},
-	{(char *)"xyy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 1)},
-	{(char *)"xyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 0)},
-	{(char *)"xyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 1)},
-	{(char *)"xyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 2)},
-	{(char *)"xyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 3)},
-	{(char *)"xyz",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 1, 2)},
-	{(char *)"xyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 0)},
-	{(char *)"xyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 1)},
-	{(char *)"xyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 2)},
-	{(char *)"xyzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 1, 2, 3)},
-	{(char *)"xyw",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 1, 3)},
-	{(char *)"xywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 0)},
-	{(char *)"xywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 1)},
-	{(char *)"xywz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 1, 3, 2)},
-	{(char *)"xyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 3)},
-	{(char *)"xz",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 2)},
-	{(char *)"xzx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 0)},
-	{(char *)"xzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 0)},
-	{(char *)"xzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 1)},
-	{(char *)"xzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 2)},
-	{(char *)"xzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 3)},
-	{(char *)"xzy",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 2, 1)},
-	{(char *)"xzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 0)},
-	{(char *)"xzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 1)},
-	{(char *)"xzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 2)},
-	{(char *)"xzyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 2, 1, 3)},
-	{(char *)"xzz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 2)},
-	{(char *)"xzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 0)},
-	{(char *)"xzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 1)},
-	{(char *)"xzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 2)},
-	{(char *)"xzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 3)},
-	{(char *)"xzw",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 2, 3)},
-	{(char *)"xzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 0)},
-	{(char *)"xzwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 2, 3, 1)},
-	{(char *)"xzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 2)},
-	{(char *)"xzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 3)},
-	{(char *)"xw",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 3)},
-	{(char *)"xwx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 0)},
-	{(char *)"xwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 0)},
-	{(char *)"xwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 1)},
-	{(char *)"xwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 2)},
-	{(char *)"xwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 3)},
-	{(char *)"xwy",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 3, 1)},
-	{(char *)"xwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 0)},
-	{(char *)"xwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 1)},
-	{(char *)"xwyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 3, 1, 2)},
-	{(char *)"xwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 3)},
-	{(char *)"xwz",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(0, 3, 2)},
-	{(char *)"xwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 0)},
-	{(char *)"xwzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(0, 3, 2, 1)},
-	{(char *)"xwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 2)},
-	{(char *)"xwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 3)},
-	{(char *)"xww",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 3)},
-	{(char *)"xwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 0)},
-	{(char *)"xwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 1)},
-	{(char *)"xwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 2)},
-	{(char *)"xwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 3)},
-	{(char *)"yx",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 0)},
-	{(char *)"yxx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 0)},
-	{(char *)"yxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 0)},
-	{(char *)"yxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 1)},
-	{(char *)"yxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 2)},
-	{(char *)"yxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 3)},
-	{(char *)"yxy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 1)},
-	{(char *)"yxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 0)},
-	{(char *)"yxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 1)},
-	{(char *)"yxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 2)},
-	{(char *)"yxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 3)},
-	{(char *)"yxz",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 0, 2)},
-	{(char *)"yxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 0)},
-	{(char *)"yxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 1)},
-	{(char *)"yxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 2)},
-	{(char *)"yxzw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 0, 2, 3)},
-	{(char *)"yxw",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 0, 3)},
-	{(char *)"yxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 0)},
-	{(char *)"yxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 1)},
-	{(char *)"yxwz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 0, 3, 2)},
-	{(char *)"yxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 3)},
-	{(char *)"yy",   (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(1, 1)},
-	{(char *)"yyx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 0)},
-	{(char *)"yyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 0)},
-	{(char *)"yyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 1)},
-	{(char *)"yyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 2)},
-	{(char *)"yyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 3)},
-	{(char *)"yyy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 1)},
-	{(char *)"yyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 0)},
-	{(char *)"yyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 1)},
-	{(char *)"yyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 2)},
-	{(char *)"yyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 3)},
-	{(char *)"yyz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 2)},
-	{(char *)"yyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 0)},
-	{(char *)"yyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 1)},
-	{(char *)"yyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 2)},
-	{(char *)"yyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 3)},
-	{(char *)"yyw",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 3)},
-	{(char *)"yywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 0)},
-	{(char *)"yywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 1)},
-	{(char *)"yywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 2)},
-	{(char *)"yyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 3)},
-	{(char *)"yz",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 2)},
-	{(char *)"yzx",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 2, 0)},
-	{(char *)"yzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 0)},
-	{(char *)"yzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 1)},
-	{(char *)"yzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 2)},
-	{(char *)"yzxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 2, 0, 3)},
-	{(char *)"yzy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 1)},
-	{(char *)"yzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 0)},
-	{(char *)"yzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 1)},
-	{(char *)"yzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 2)},
-	{(char *)"yzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 3)},
-	{(char *)"yzz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 2)},
-	{(char *)"yzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 0)},
-	{(char *)"yzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 1)},
-	{(char *)"yzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 2)},
-	{(char *)"yzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 3)},
-	{(char *)"yzw",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 2, 3)},
-	{(char *)"yzwx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 2, 3, 0)},
-	{(char *)"yzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 1)},
-	{(char *)"yzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 2)},
-	{(char *)"yzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 3)},
-	{(char *)"yw",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 3)},
-	{(char *)"ywx",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 3, 0)},
-	{(char *)"ywxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 0)},
-	{(char *)"ywxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 1)},
-	{(char *)"ywxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 3, 0, 2)},
-	{(char *)"ywxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 3)},
-	{(char *)"ywy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 1)},
-	{(char *)"ywyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 0)},
-	{(char *)"ywyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 1)},
-	{(char *)"ywyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 2)},
-	{(char *)"ywyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 3)},
-	{(char *)"ywz",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(1, 3, 2)},
-	{(char *)"ywzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(1, 3, 2, 0)},
-	{(char *)"ywzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 1)},
-	{(char *)"ywzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 2)},
-	{(char *)"ywzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 3)},
-	{(char *)"yww",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 3)},
-	{(char *)"ywwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 0)},
-	{(char *)"ywwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 1)},
-	{(char *)"ywwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 2)},
-	{(char *)"ywww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 3)},
-	{(char *)"zx",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 0)},
-	{(char *)"zxx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 0)},
-	{(char *)"zxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 0)},
-	{(char *)"zxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 1)},
-	{(char *)"zxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 2)},
-	{(char *)"zxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 3)},
-	{(char *)"zxy",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 0, 1)},
-	{(char *)"zxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 0)},
-	{(char *)"zxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 1)},
-	{(char *)"zxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 2)},
-	{(char *)"zxyw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 0, 1, 3)},
-	{(char *)"zxz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 2)},
-	{(char *)"zxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 0)},
-	{(char *)"zxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 1)},
-	{(char *)"zxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 2)},
-	{(char *)"zxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 3)},
-	{(char *)"zxw",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 0, 3)},
-	{(char *)"zxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 0)},
-	{(char *)"zxwy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 0, 3, 1)},
-	{(char *)"zxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 2)},
-	{(char *)"zxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 3)},
-	{(char *)"zy",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 1)},
-	{(char *)"zyx",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 1, 0)},
-	{(char *)"zyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 0)},
-	{(char *)"zyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 1)},
-	{(char *)"zyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 2)},
-	{(char *)"zyxw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 1, 0, 3)},
-	{(char *)"zyy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 1)},
-	{(char *)"zyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 0)},
-	{(char *)"zyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 1)},
-	{(char *)"zyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 2)},
-	{(char *)"zyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 3)},
-	{(char *)"zyz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 2)},
-	{(char *)"zyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 0)},
-	{(char *)"zyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 1)},
-	{(char *)"zyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 2)},
-	{(char *)"zyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 3)},
-	{(char *)"zyw",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 1, 3)},
-	{(char *)"zywx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 1, 3, 0)},
-	{(char *)"zywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 1)},
-	{(char *)"zywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 2)},
-	{(char *)"zyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 3)},
-	{(char *)"zz",   (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(2, 2)},
-	{(char *)"zzx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 0)},
-	{(char *)"zzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 0)},
-	{(char *)"zzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 1)},
-	{(char *)"zzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 2)},
-	{(char *)"zzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 3)},
-	{(char *)"zzy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 1)},
-	{(char *)"zzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 0)},
-	{(char *)"zzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 1)},
-	{(char *)"zzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 2)},
-	{(char *)"zzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 3)},
-	{(char *)"zzz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 2)},
-	{(char *)"zzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 0)},
-	{(char *)"zzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 1)},
-	{(char *)"zzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 2)},
-	{(char *)"zzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 3)},
-	{(char *)"zzw",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 3)},
-	{(char *)"zzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 0)},
-	{(char *)"zzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 1)},
-	{(char *)"zzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 2)},
-	{(char *)"zzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 3)},
-	{(char *)"zw",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 3)},
-	{(char *)"zwx",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 3, 0)},
-	{(char *)"zwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 0)},
-	{(char *)"zwxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 3, 0, 1)},
-	{(char *)"zwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 2)},
-	{(char *)"zwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 3)},
-	{(char *)"zwy",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(2, 3, 1)},
-	{(char *)"zwyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(2, 3, 1, 0)},
-	{(char *)"zwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 1)},
-	{(char *)"zwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 2)},
-	{(char *)"zwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 3)},
-	{(char *)"zwz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 2)},
-	{(char *)"zwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 0)},
-	{(char *)"zwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 1)},
-	{(char *)"zwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 2)},
-	{(char *)"zwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 3)},
-	{(char *)"zww",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 3)},
-	{(char *)"zwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 0)},
-	{(char *)"zwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 1)},
-	{(char *)"zwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 2)},
-	{(char *)"zwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 3)},
-	{(char *)"wx",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 0)},
-	{(char *)"wxx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 0)},
-	{(char *)"wxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 0)},
-	{(char *)"wxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 1)},
-	{(char *)"wxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 2)},
-	{(char *)"wxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 3)},
-	{(char *)"wxy",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 0, 1)},
-	{(char *)"wxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 0)},
-	{(char *)"wxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 1)},
-	{(char *)"wxyz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 0, 1, 2)},
-	{(char *)"wxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 3)},
-	{(char *)"wxz",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 0, 2)},
-	{(char *)"wxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 0)},
-	{(char *)"wxzy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 0, 2, 1)},
-	{(char *)"wxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 2)},
-	{(char *)"wxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 3)},
-	{(char *)"wxw",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 3)},
-	{(char *)"wxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 0)},
-	{(char *)"wxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 1)},
-	{(char *)"wxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 2)},
-	{(char *)"wxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 3)},
-	{(char *)"wy",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 1)},
-	{(char *)"wyx",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 1, 0)},
-	{(char *)"wyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 0)},
-	{(char *)"wyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 1)},
-	{(char *)"wyxz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 1, 0, 2)},
-	{(char *)"wyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 3)},
-	{(char *)"wyy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 1)},
-	{(char *)"wyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 0)},
-	{(char *)"wyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 1)},
-	{(char *)"wyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 2)},
-	{(char *)"wyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 3)},
-	{(char *)"wyz",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 1, 2)},
-	{(char *)"wyzx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 1, 2, 0)},
-	{(char *)"wyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 1)},
-	{(char *)"wyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 2)},
-	{(char *)"wyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 3)},
-	{(char *)"wyw",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 3)},
-	{(char *)"wywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 0)},
-	{(char *)"wywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 1)},
-	{(char *)"wywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 2)},
-	{(char *)"wyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 3)},
-	{(char *)"wz",   (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 2)},
-	{(char *)"wzx",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 2, 0)},
-	{(char *)"wzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 0)},
-	{(char *)"wzxy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 2, 0, 1)},
-	{(char *)"wzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 2)},
-	{(char *)"wzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 3)},
-	{(char *)"wzy",  (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE3(3, 2, 1)},
-	{(char *)"wzyx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE4(3, 2, 1, 0)},
-	{(char *)"wzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 1)},
-	{(char *)"wzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 2)},
-	{(char *)"wzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 3)},
-	{(char *)"wzz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 2)},
-	{(char *)"wzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 0)},
-	{(char *)"wzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 1)},
-	{(char *)"wzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 2)},
-	{(char *)"wzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 3)},
-	{(char *)"wzw",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 3)},
-	{(char *)"wzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 0)},
-	{(char *)"wzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 1)},
-	{(char *)"wzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 2)},
-	{(char *)"wzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 3)},
-	{(char *)"ww",   (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(3, 3)},
-	{(char *)"wwx",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 0)},
-	{(char *)"wwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 0)},
-	{(char *)"wwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 1)},
-	{(char *)"wwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 2)},
-	{(char *)"wwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 3)},
-	{(char *)"wwy",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 1)},
-	{(char *)"wwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 0)},
-	{(char *)"wwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 1)},
-	{(char *)"wwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 2)},
-	{(char *)"wwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 3)},
-	{(char *)"wwz",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 2)},
-	{(char *)"wwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 0)},
-	{(char *)"wwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 1)},
-	{(char *)"wwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 2)},
-	{(char *)"wwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 3)},
-	{(char *)"www",  (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 3)},
-	{(char *)"wwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 0)},
-	{(char *)"wwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 1)},
-	{(char *)"wwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 2)},
-	{(char *)"wwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 3)},
+    {(char *)"x", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_x_doc, (void *)0},
+    {(char *)"y", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_y_doc, (void *)1},
+    {(char *)"z", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_z_doc, (void *)2},
+    {(char *)"w", (getter)Vector_axis_get, (setter)Vector_axis_set, Vector_axis_w_doc, (void *)3},
+    {(char *)"length",
+     (getter)Vector_length_get,
+     (setter)Vector_length_set,
+     Vector_length_doc,
+     NULL},
+    {(char *)"length_squared",
+     (getter)Vector_length_squared_get,
+     (setter)NULL,
+     Vector_length_squared_doc,
+     NULL},
+    {(char *)"magnitude",
+     (getter)Vector_length_get,
+     (setter)Vector_length_set,
+     Vector_length_doc,
+     NULL},
+    {(char *)"is_wrapped",
+     (getter)BaseMathObject_is_wrapped_get,
+     (setter)NULL,
+     BaseMathObject_is_wrapped_doc,
+     NULL},
+    {(char *)"is_frozen",
+     (getter)BaseMathObject_is_frozen_get,
+     (setter)NULL,
+     BaseMathObject_is_frozen_doc,
+     NULL},
+    {(char *)"owner",
+     (getter)BaseMathObject_owner_get,
+     (setter)NULL,
+     BaseMathObject_owner_doc,
+     NULL},
+
+    /* autogenerated swizzle attrs, see Python script above */
+    {(char *)"xx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(0, 0)},
+    {(char *)"xxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 0)},
+    {(char *)"xxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 0)},
+    {(char *)"xxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 1)},
+    {(char *)"xxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 2)},
+    {(char *)"xxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 0, 3)},
+    {(char *)"xxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 1)},
+    {(char *)"xxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 0)},
+    {(char *)"xxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 1)},
+    {(char *)"xxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 2)},
+    {(char *)"xxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 1, 3)},
+    {(char *)"xxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 2)},
+    {(char *)"xxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 0)},
+    {(char *)"xxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 1)},
+    {(char *)"xxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 2)},
+    {(char *)"xxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 2, 3)},
+    {(char *)"xxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 0, 3)},
+    {(char *)"xxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 0)},
+    {(char *)"xxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 1)},
+    {(char *)"xxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 2)},
+    {(char *)"xxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 0, 3, 3)},
+    {(char *)"xy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 1)},
+    {(char *)"xyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 0)},
+    {(char *)"xyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 0)},
+    {(char *)"xyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 1)},
+    {(char *)"xyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 2)},
+    {(char *)"xyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 0, 3)},
+    {(char *)"xyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 1, 1)},
+    {(char *)"xyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 0)},
+    {(char *)"xyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 1)},
+    {(char *)"xyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 2)},
+    {(char *)"xyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 1, 3)},
+    {(char *)"xyz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(0, 1, 2)},
+    {(char *)"xyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 0)},
+    {(char *)"xyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 1)},
+    {(char *)"xyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 2, 2)},
+    {(char *)"xyzw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(0, 1, 2, 3)},
+    {(char *)"xyw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(0, 1, 3)},
+    {(char *)"xywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 0)},
+    {(char *)"xywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 1)},
+    {(char *)"xywz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(0, 1, 3, 2)},
+    {(char *)"xyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 1, 3, 3)},
+    {(char *)"xz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 2)},
+    {(char *)"xzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 0)},
+    {(char *)"xzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 0)},
+    {(char *)"xzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 1)},
+    {(char *)"xzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 2)},
+    {(char *)"xzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 0, 3)},
+    {(char *)"xzy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(0, 2, 1)},
+    {(char *)"xzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 0)},
+    {(char *)"xzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 1)},
+    {(char *)"xzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 1, 2)},
+    {(char *)"xzyw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(0, 2, 1, 3)},
+    {(char *)"xzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 2, 2)},
+    {(char *)"xzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 0)},
+    {(char *)"xzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 1)},
+    {(char *)"xzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 2)},
+    {(char *)"xzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 2, 3)},
+    {(char *)"xzw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(0, 2, 3)},
+    {(char *)"xzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 0)},
+    {(char *)"xzwy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(0, 2, 3, 1)},
+    {(char *)"xzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 2)},
+    {(char *)"xzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 2, 3, 3)},
+    {(char *)"xw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(0, 3)},
+    {(char *)"xwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 0)},
+    {(char *)"xwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 0)},
+    {(char *)"xwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 1)},
+    {(char *)"xwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 2)},
+    {(char *)"xwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 0, 3)},
+    {(char *)"xwy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(0, 3, 1)},
+    {(char *)"xwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 0)},
+    {(char *)"xwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 1)},
+    {(char *)"xwyz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(0, 3, 1, 2)},
+    {(char *)"xwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 1, 3)},
+    {(char *)"xwz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(0, 3, 2)},
+    {(char *)"xwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 0)},
+    {(char *)"xwzy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(0, 3, 2, 1)},
+    {(char *)"xwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 2)},
+    {(char *)"xwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 2, 3)},
+    {(char *)"xww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(0, 3, 3)},
+    {(char *)"xwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 0)},
+    {(char *)"xwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 1)},
+    {(char *)"xwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 2)},
+    {(char *)"xwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(0, 3, 3, 3)},
+    {(char *)"yx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 0)},
+    {(char *)"yxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 0)},
+    {(char *)"yxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 0)},
+    {(char *)"yxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 1)},
+    {(char *)"yxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 2)},
+    {(char *)"yxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 0, 3)},
+    {(char *)"yxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 0, 1)},
+    {(char *)"yxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 0)},
+    {(char *)"yxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 1)},
+    {(char *)"yxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 2)},
+    {(char *)"yxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 1, 3)},
+    {(char *)"yxz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(1, 0, 2)},
+    {(char *)"yxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 0)},
+    {(char *)"yxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 1)},
+    {(char *)"yxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 2, 2)},
+    {(char *)"yxzw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(1, 0, 2, 3)},
+    {(char *)"yxw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(1, 0, 3)},
+    {(char *)"yxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 0)},
+    {(char *)"yxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 1)},
+    {(char *)"yxwz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(1, 0, 3, 2)},
+    {(char *)"yxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 0, 3, 3)},
+    {(char *)"yy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(1, 1)},
+    {(char *)"yyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 0)},
+    {(char *)"yyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 0)},
+    {(char *)"yyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 1)},
+    {(char *)"yyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 2)},
+    {(char *)"yyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 0, 3)},
+    {(char *)"yyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 1)},
+    {(char *)"yyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 0)},
+    {(char *)"yyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 1)},
+    {(char *)"yyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 2)},
+    {(char *)"yyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 1, 3)},
+    {(char *)"yyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 2)},
+    {(char *)"yyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 0)},
+    {(char *)"yyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 1)},
+    {(char *)"yyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 2)},
+    {(char *)"yyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 2, 3)},
+    {(char *)"yyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 1, 3)},
+    {(char *)"yywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 0)},
+    {(char *)"yywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 1)},
+    {(char *)"yywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 2)},
+    {(char *)"yyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 1, 3, 3)},
+    {(char *)"yz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 2)},
+    {(char *)"yzx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(1, 2, 0)},
+    {(char *)"yzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 0)},
+    {(char *)"yzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 1)},
+    {(char *)"yzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 0, 2)},
+    {(char *)"yzxw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(1, 2, 0, 3)},
+    {(char *)"yzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 1)},
+    {(char *)"yzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 0)},
+    {(char *)"yzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 1)},
+    {(char *)"yzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 2)},
+    {(char *)"yzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 1, 3)},
+    {(char *)"yzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 2, 2)},
+    {(char *)"yzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 0)},
+    {(char *)"yzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 1)},
+    {(char *)"yzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 2)},
+    {(char *)"yzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 2, 3)},
+    {(char *)"yzw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(1, 2, 3)},
+    {(char *)"yzwx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(1, 2, 3, 0)},
+    {(char *)"yzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 1)},
+    {(char *)"yzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 2)},
+    {(char *)"yzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 2, 3, 3)},
+    {(char *)"yw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(1, 3)},
+    {(char *)"ywx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(1, 3, 0)},
+    {(char *)"ywxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 0)},
+    {(char *)"ywxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 1)},
+    {(char *)"ywxz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(1, 3, 0, 2)},
+    {(char *)"ywxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 0, 3)},
+    {(char *)"ywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 1)},
+    {(char *)"ywyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 0)},
+    {(char *)"ywyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 1)},
+    {(char *)"ywyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 2)},
+    {(char *)"ywyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 1, 3)},
+    {(char *)"ywz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(1, 3, 2)},
+    {(char *)"ywzx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(1, 3, 2, 0)},
+    {(char *)"ywzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 1)},
+    {(char *)"ywzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 2)},
+    {(char *)"ywzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 2, 3)},
+    {(char *)"yww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(1, 3, 3)},
+    {(char *)"ywwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 0)},
+    {(char *)"ywwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 1)},
+    {(char *)"ywwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 2)},
+    {(char *)"ywww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(1, 3, 3, 3)},
+    {(char *)"zx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 0)},
+    {(char *)"zxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 0)},
+    {(char *)"zxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 0)},
+    {(char *)"zxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 1)},
+    {(char *)"zxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 2)},
+    {(char *)"zxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 0, 3)},
+    {(char *)"zxy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(2, 0, 1)},
+    {(char *)"zxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 0)},
+    {(char *)"zxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 1)},
+    {(char *)"zxyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 1, 2)},
+    {(char *)"zxyw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(2, 0, 1, 3)},
+    {(char *)"zxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 0, 2)},
+    {(char *)"zxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 0)},
+    {(char *)"zxzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 1)},
+    {(char *)"zxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 2)},
+    {(char *)"zxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 2, 3)},
+    {(char *)"zxw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(2, 0, 3)},
+    {(char *)"zxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 0)},
+    {(char *)"zxwy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(2, 0, 3, 1)},
+    {(char *)"zxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 2)},
+    {(char *)"zxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 0, 3, 3)},
+    {(char *)"zy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 1)},
+    {(char *)"zyx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(2, 1, 0)},
+    {(char *)"zyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 0)},
+    {(char *)"zyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 1)},
+    {(char *)"zyxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 0, 2)},
+    {(char *)"zyxw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(2, 1, 0, 3)},
+    {(char *)"zyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 1)},
+    {(char *)"zyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 0)},
+    {(char *)"zyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 1)},
+    {(char *)"zyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 2)},
+    {(char *)"zyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 1, 3)},
+    {(char *)"zyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 1, 2)},
+    {(char *)"zyzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 0)},
+    {(char *)"zyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 1)},
+    {(char *)"zyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 2)},
+    {(char *)"zyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 2, 3)},
+    {(char *)"zyw",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(2, 1, 3)},
+    {(char *)"zywx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(2, 1, 3, 0)},
+    {(char *)"zywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 1)},
+    {(char *)"zywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 2)},
+    {(char *)"zyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 1, 3, 3)},
+    {(char *)"zz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(2, 2)},
+    {(char *)"zzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 0)},
+    {(char *)"zzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 0)},
+    {(char *)"zzxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 1)},
+    {(char *)"zzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 2)},
+    {(char *)"zzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 0, 3)},
+    {(char *)"zzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 1)},
+    {(char *)"zzyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 0)},
+    {(char *)"zzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 1)},
+    {(char *)"zzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 2)},
+    {(char *)"zzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 1, 3)},
+    {(char *)"zzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 2)},
+    {(char *)"zzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 0)},
+    {(char *)"zzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 1)},
+    {(char *)"zzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 2)},
+    {(char *)"zzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 2, 3)},
+    {(char *)"zzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 2, 3)},
+    {(char *)"zzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 0)},
+    {(char *)"zzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 1)},
+    {(char *)"zzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 2)},
+    {(char *)"zzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 2, 3, 3)},
+    {(char *)"zw", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(2, 3)},
+    {(char *)"zwx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(2, 3, 0)},
+    {(char *)"zwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 0)},
+    {(char *)"zwxy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(2, 3, 0, 1)},
+    {(char *)"zwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 2)},
+    {(char *)"zwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 0, 3)},
+    {(char *)"zwy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(2, 3, 1)},
+    {(char *)"zwyx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(2, 3, 1, 0)},
+    {(char *)"zwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 1)},
+    {(char *)"zwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 2)},
+    {(char *)"zwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 1, 3)},
+    {(char *)"zwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 2)},
+    {(char *)"zwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 0)},
+    {(char *)"zwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 1)},
+    {(char *)"zwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 2)},
+    {(char *)"zwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 2, 3)},
+    {(char *)"zww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(2, 3, 3)},
+    {(char *)"zwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 0)},
+    {(char *)"zwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 1)},
+    {(char *)"zwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 2)},
+    {(char *)"zwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(2, 3, 3, 3)},
+    {(char *)"wx", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 0)},
+    {(char *)"wxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 0)},
+    {(char *)"wxxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 0)},
+    {(char *)"wxxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 1)},
+    {(char *)"wxxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 2)},
+    {(char *)"wxxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 0, 3)},
+    {(char *)"wxy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(3, 0, 1)},
+    {(char *)"wxyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 0)},
+    {(char *)"wxyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 1)},
+    {(char *)"wxyz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(3, 0, 1, 2)},
+    {(char *)"wxyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 1, 3)},
+    {(char *)"wxz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(3, 0, 2)},
+    {(char *)"wxzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 0)},
+    {(char *)"wxzy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(3, 0, 2, 1)},
+    {(char *)"wxzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 2)},
+    {(char *)"wxzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 2, 3)},
+    {(char *)"wxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 0, 3)},
+    {(char *)"wxwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 0)},
+    {(char *)"wxwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 1)},
+    {(char *)"wxwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 2)},
+    {(char *)"wxww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 0, 3, 3)},
+    {(char *)"wy", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 1)},
+    {(char *)"wyx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(3, 1, 0)},
+    {(char *)"wyxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 0)},
+    {(char *)"wyxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 1)},
+    {(char *)"wyxz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(3, 1, 0, 2)},
+    {(char *)"wyxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 0, 3)},
+    {(char *)"wyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 1)},
+    {(char *)"wyyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 0)},
+    {(char *)"wyyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 1)},
+    {(char *)"wyyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 2)},
+    {(char *)"wyyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 1, 3)},
+    {(char *)"wyz",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(3, 1, 2)},
+    {(char *)"wyzx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(3, 1, 2, 0)},
+    {(char *)"wyzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 1)},
+    {(char *)"wyzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 2)},
+    {(char *)"wyzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 2, 3)},
+    {(char *)"wyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 1, 3)},
+    {(char *)"wywx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 0)},
+    {(char *)"wywy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 1)},
+    {(char *)"wywz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 2)},
+    {(char *)"wyww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 1, 3, 3)},
+    {(char *)"wz", (getter)Vector_swizzle_get, (setter)Vector_swizzle_set, NULL, SWIZZLE2(3, 2)},
+    {(char *)"wzx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(3, 2, 0)},
+    {(char *)"wzxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 0)},
+    {(char *)"wzxy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(3, 2, 0, 1)},
+    {(char *)"wzxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 2)},
+    {(char *)"wzxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 0, 3)},
+    {(char *)"wzy",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE3(3, 2, 1)},
+    {(char *)"wzyx",
+     (getter)Vector_swizzle_get,
+     (setter)Vector_swizzle_set,
+     NULL,
+     SWIZZLE4(3, 2, 1, 0)},
+    {(char *)"wzyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 1)},
+    {(char *)"wzyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 2)},
+    {(char *)"wzyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 1, 3)},
+    {(char *)"wzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 2)},
+    {(char *)"wzzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 0)},
+    {(char *)"wzzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 1)},
+    {(char *)"wzzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 2)},
+    {(char *)"wzzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 2, 3)},
+    {(char *)"wzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 2, 3)},
+    {(char *)"wzwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 0)},
+    {(char *)"wzwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 1)},
+    {(char *)"wzwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 2)},
+    {(char *)"wzww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 2, 3, 3)},
+    {(char *)"ww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE2(3, 3)},
+    {(char *)"wwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 0)},
+    {(char *)"wwxx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 0)},
+    {(char *)"wwxy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 1)},
+    {(char *)"wwxz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 2)},
+    {(char *)"wwxw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 0, 3)},
+    {(char *)"wwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 1)},
+    {(char *)"wwyx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 0)},
+    {(char *)"wwyy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 1)},
+    {(char *)"wwyz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 2)},
+    {(char *)"wwyw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 1, 3)},
+    {(char *)"wwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 2)},
+    {(char *)"wwzx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 0)},
+    {(char *)"wwzy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 1)},
+    {(char *)"wwzz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 2)},
+    {(char *)"wwzw", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 2, 3)},
+    {(char *)"www", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE3(3, 3, 3)},
+    {(char *)"wwwx", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 0)},
+    {(char *)"wwwy", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 1)},
+    {(char *)"wwwz", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 2)},
+    {(char *)"wwww", (getter)Vector_swizzle_get, (setter)NULL, NULL, SWIZZLE4(3, 3, 3, 3)},
 
 #undef AXIS_FROM_CHAR
 #undef SWIZZLE1
@@ -2931,7 +3116,7 @@ static PyGetSetDef Vector_getseters[] = {
 #undef _SWIZZLE3
 #undef _SWIZZLE4
 
-	{NULL, NULL, NULL, NULL, NULL}  /* Sentinel */
+    {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
 };
 
 /**
@@ -2943,108 +3128,111 @@ static PyGetSetDef Vector_getseters[] = {
  * 
* \note vector/matrix multiplication is not commutative. */ -static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], VectorObject *vec, MatrixObject *mat) -{ - float vec_cpy[MAX_DIMENSIONS]; - int row, col, z = 0, vec_size = vec->size; - - if (mat->num_row != vec_size) { - if (mat->num_row == 4 && vec_size == 3) { - vec_cpy[3] = 1.0f; - } - else { - PyErr_SetString(PyExc_ValueError, - "vector * matrix: matrix column size " - "and the vector size must be the same"); - return -1; - } - } - - if (BaseMath_ReadCallback(vec) == -1 || BaseMath_ReadCallback(mat) == -1) { - return -1; - } - - memcpy(vec_cpy, vec->vec, vec_size * sizeof(float)); - - r_vec[3] = 1.0f; - /* muliplication */ - for (col = 0; col < mat->num_col; col++) { - double dot = 0.0; - for (row = 0; row < mat->num_row; row++) { - dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[row]); - } - r_vec[z++] = (float)dot; - } - return 0; +static int row_vector_multiplication(float r_vec[MAX_DIMENSIONS], + VectorObject *vec, + MatrixObject *mat) +{ + float vec_cpy[MAX_DIMENSIONS]; + int row, col, z = 0, vec_size = vec->size; + + if (mat->num_row != vec_size) { + if (mat->num_row == 4 && vec_size == 3) { + vec_cpy[3] = 1.0f; + } + else { + PyErr_SetString(PyExc_ValueError, + "vector * matrix: matrix column size " + "and the vector size must be the same"); + return -1; + } + } + + if (BaseMath_ReadCallback(vec) == -1 || BaseMath_ReadCallback(mat) == -1) { + return -1; + } + + memcpy(vec_cpy, vec->vec, vec_size * sizeof(float)); + + r_vec[3] = 1.0f; + /* muliplication */ + for (col = 0; col < mat->num_col; col++) { + double dot = 0.0; + for (row = 0; row < mat->num_row; row++) { + dot += (double)(MATRIX_ITEM(mat, row, col) * vec_cpy[row]); + } + r_vec[z++] = (float)dot; + } + return 0; } /*----------------------------Vector.negate() -------------------- */ PyDoc_STRVAR(Vector_negate_doc, -".. method:: negate()\n" -"\n" -" Set all values to their negative.\n" -); + ".. method:: negate()\n" + "\n" + " Set all values to their negative.\n"); static PyObject *Vector_negate(VectorObject *self) { - if (BaseMath_ReadCallback(self) == -1) { - return NULL; - } + if (BaseMath_ReadCallback(self) == -1) { + return NULL; + } - negate_vn(self->vec, self->size); + negate_vn(self->vec, self->size); - (void)BaseMath_WriteCallback(self); /* already checked for error */ - Py_RETURN_NONE; + (void)BaseMath_WriteCallback(self); /* already checked for error */ + Py_RETURN_NONE; } static struct PyMethodDef Vector_methods[] = { - /* Class Methods */ - {"Fill", (PyCFunction) C_Vector_Fill, METH_VARARGS | METH_CLASS, C_Vector_Fill_doc}, - {"Range", (PyCFunction) C_Vector_Range, METH_VARARGS | METH_CLASS, C_Vector_Range_doc}, - {"Linspace", (PyCFunction) C_Vector_Linspace, METH_VARARGS | METH_CLASS, C_Vector_Linspace_doc}, - {"Repeat", (PyCFunction) C_Vector_Repeat, METH_VARARGS | METH_CLASS, C_Vector_Repeat_doc}, - - /* in place only */ - {"zero", (PyCFunction) Vector_zero, METH_NOARGS, Vector_zero_doc}, - {"negate", (PyCFunction) Vector_negate, METH_NOARGS, Vector_negate_doc}, - - /* operate on original or copy */ - {"normalize", (PyCFunction) Vector_normalize, METH_NOARGS, Vector_normalize_doc}, - {"normalized", (PyCFunction) Vector_normalized, METH_NOARGS, Vector_normalized_doc}, - - {"resize", (PyCFunction) Vector_resize, METH_O, Vector_resize_doc}, - {"resized", (PyCFunction) Vector_resized, METH_O, Vector_resized_doc}, - {"to_2d", (PyCFunction) Vector_to_2d, METH_NOARGS, Vector_to_2d_doc}, - {"resize_2d", (PyCFunction) Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc}, - {"to_3d", (PyCFunction) Vector_to_3d, METH_NOARGS, Vector_to_3d_doc}, - {"resize_3d", (PyCFunction) Vector_resize_3d, METH_NOARGS, Vector_resize_3d_doc}, - {"to_4d", (PyCFunction) Vector_to_4d, METH_NOARGS, Vector_to_4d_doc}, - {"resize_4d", (PyCFunction) Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc}, - {"to_tuple", (PyCFunction) Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc}, - {"to_track_quat", (PyCFunction) Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc}, - {"orthogonal", (PyCFunction) Vector_orthogonal, METH_NOARGS, Vector_orthogonal_doc}, - - /* operation between 2 or more types */ - {"reflect", (PyCFunction) Vector_reflect, METH_O, Vector_reflect_doc}, - {"cross", (PyCFunction) Vector_cross, METH_O, Vector_cross_doc}, - {"dot", (PyCFunction) Vector_dot, METH_O, Vector_dot_doc}, - {"angle", (PyCFunction) Vector_angle, METH_VARARGS, Vector_angle_doc}, - {"angle_signed", (PyCFunction) Vector_angle_signed, METH_VARARGS, Vector_angle_signed_doc}, - {"rotation_difference", (PyCFunction) Vector_rotation_difference, METH_O, Vector_rotation_difference_doc}, - {"project", (PyCFunction) Vector_project, METH_O, Vector_project_doc}, - {"lerp", (PyCFunction) Vector_lerp, METH_VARARGS, Vector_lerp_doc}, - {"slerp", (PyCFunction) Vector_slerp, METH_VARARGS, Vector_slerp_doc}, - {"rotate", (PyCFunction) Vector_rotate, METH_O, Vector_rotate_doc}, - - /* base-math methods */ - {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, - - {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, - {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, - {"__deepcopy__", (PyCFunction) Vector_deepcopy, METH_VARARGS, NULL}, - {NULL, NULL, 0, NULL}, + /* Class Methods */ + {"Fill", (PyCFunction)C_Vector_Fill, METH_VARARGS | METH_CLASS, C_Vector_Fill_doc}, + {"Range", (PyCFunction)C_Vector_Range, METH_VARARGS | METH_CLASS, C_Vector_Range_doc}, + {"Linspace", (PyCFunction)C_Vector_Linspace, METH_VARARGS | METH_CLASS, C_Vector_Linspace_doc}, + {"Repeat", (PyCFunction)C_Vector_Repeat, METH_VARARGS | METH_CLASS, C_Vector_Repeat_doc}, + + /* in place only */ + {"zero", (PyCFunction)Vector_zero, METH_NOARGS, Vector_zero_doc}, + {"negate", (PyCFunction)Vector_negate, METH_NOARGS, Vector_negate_doc}, + + /* operate on original or copy */ + {"normalize", (PyCFunction)Vector_normalize, METH_NOARGS, Vector_normalize_doc}, + {"normalized", (PyCFunction)Vector_normalized, METH_NOARGS, Vector_normalized_doc}, + + {"resize", (PyCFunction)Vector_resize, METH_O, Vector_resize_doc}, + {"resized", (PyCFunction)Vector_resized, METH_O, Vector_resized_doc}, + {"to_2d", (PyCFunction)Vector_to_2d, METH_NOARGS, Vector_to_2d_doc}, + {"resize_2d", (PyCFunction)Vector_resize_2d, METH_NOARGS, Vector_resize_2d_doc}, + {"to_3d", (PyCFunction)Vector_to_3d, METH_NOARGS, Vector_to_3d_doc}, + {"resize_3d", (PyCFunction)Vector_resize_3d, METH_NOARGS, Vector_resize_3d_doc}, + {"to_4d", (PyCFunction)Vector_to_4d, METH_NOARGS, Vector_to_4d_doc}, + {"resize_4d", (PyCFunction)Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc}, + {"to_tuple", (PyCFunction)Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc}, + {"to_track_quat", (PyCFunction)Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc}, + {"orthogonal", (PyCFunction)Vector_orthogonal, METH_NOARGS, Vector_orthogonal_doc}, + + /* operation between 2 or more types */ + {"reflect", (PyCFunction)Vector_reflect, METH_O, Vector_reflect_doc}, + {"cross", (PyCFunction)Vector_cross, METH_O, Vector_cross_doc}, + {"dot", (PyCFunction)Vector_dot, METH_O, Vector_dot_doc}, + {"angle", (PyCFunction)Vector_angle, METH_VARARGS, Vector_angle_doc}, + {"angle_signed", (PyCFunction)Vector_angle_signed, METH_VARARGS, Vector_angle_signed_doc}, + {"rotation_difference", + (PyCFunction)Vector_rotation_difference, + METH_O, + Vector_rotation_difference_doc}, + {"project", (PyCFunction)Vector_project, METH_O, Vector_project_doc}, + {"lerp", (PyCFunction)Vector_lerp, METH_VARARGS, Vector_lerp_doc}, + {"slerp", (PyCFunction)Vector_slerp, METH_VARARGS, Vector_slerp_doc}, + {"rotate", (PyCFunction)Vector_rotate, METH_O, Vector_rotate_doc}, + + /* base-math methods */ + {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, + + {"copy", (PyCFunction)Vector_copy, METH_NOARGS, Vector_copy_doc}, + {"__copy__", (PyCFunction)Vector_copy, METH_NOARGS, NULL}, + {"__deepcopy__", (PyCFunction)Vector_deepcopy, METH_VARARGS, NULL}, + {NULL, NULL, 0, NULL}, }; - /** * Note: * #Py_TPFLAGS_CHECKTYPES allows us to avoid casting all types to Vector when coercing @@ -3053,144 +3241,140 @@ static struct PyMethodDef Vector_methods[] = { */ PyDoc_STRVAR(vector_doc, -".. class:: Vector(seq)\n" -"\n" -" This object gives access to Vectors in Blender.\n" -"\n" -" :param seq: Components of the vector, must be a sequence of at least two\n" -" :type seq: sequence of numbers\n" -); + ".. class:: Vector(seq)\n" + "\n" + " This object gives access to Vectors in Blender.\n" + "\n" + " :param seq: Components of the vector, must be a sequence of at least two\n" + " :type seq: sequence of numbers\n"); PyTypeObject vector_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - /* For printing, in format "." */ - "Vector", /* char *tp_name; */ - sizeof(VectorObject), /* int tp_basicsize; */ - 0, /* tp_itemsize; For allocation */ + PyVarObject_HEAD_INIT(NULL, 0) + /* For printing, in format "." */ + "Vector", /* char *tp_name; */ + sizeof(VectorObject), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ - /* Methods to implement standard operations */ + /* Methods to implement standard operations */ - (destructor) BaseMathObject_dealloc, /* destructor tp_dealloc; */ - NULL, /* printfunc tp_print; */ - NULL, /* getattrfunc tp_getattr; */ - NULL, /* setattrfunc tp_setattr; */ - NULL, /* cmpfunc tp_compare; */ - (reprfunc)Vector_repr, /* reprfunc tp_repr; */ + (destructor)BaseMathObject_dealloc, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ + (reprfunc)Vector_repr, /* reprfunc tp_repr; */ - /* Method suites for standard classes */ + /* Method suites for standard classes */ - &Vector_NumMethods, /* PyNumberMethods *tp_as_number; */ - &Vector_SeqMethods, /* PySequenceMethods *tp_as_sequence; */ - &Vector_AsMapping, /* PyMappingMethods *tp_as_mapping; */ + &Vector_NumMethods, /* PyNumberMethods *tp_as_number; */ + &Vector_SeqMethods, /* PySequenceMethods *tp_as_sequence; */ + &Vector_AsMapping, /* PyMappingMethods *tp_as_mapping; */ - /* More standard operations (here for binary compatibility) */ + /* More standard operations (here for binary compatibility) */ - (hashfunc)Vector_hash, /* hashfunc tp_hash; */ - NULL, /* ternaryfunc tp_call; */ + (hashfunc)Vector_hash, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ #ifndef MATH_STANDALONE - (reprfunc)Vector_str, /* reprfunc tp_str; */ + (reprfunc)Vector_str, /* reprfunc tp_str; */ #else - NULL, /* reprfunc tp_str; */ + NULL, /* reprfunc tp_str; */ #endif - NULL, /* getattrofunc tp_getattro; */ - NULL, /* setattrofunc tp_setattro; */ - - /* Functions to access object as input/output buffer */ - NULL, /* PyBufferProcs *tp_as_buffer; */ - - /*** Flags to define presence of optional/expanded features ***/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, - vector_doc, /* char *tp_doc; Documentation string */ - /*** Assigned meaning in release 2.0 ***/ - - /* call function for all accessible objects */ - (traverseproc)BaseMathObject_traverse, /* tp_traverse */ - - /* delete references to contained objects */ - (inquiry)BaseMathObject_clear, /* tp_clear */ - - /*** Assigned meaning in release 2.1 ***/ - /*** rich comparisons ***/ - (richcmpfunc)Vector_richcmpr, /* richcmpfunc tp_richcompare; */ - - /*** weak reference enabler ***/ - 0, /* long tp_weaklistoffset; */ - - /*** Added in release 2.2 ***/ - /* Iterators */ - NULL, /* getiterfunc tp_iter; */ - NULL, /* iternextfunc tp_iternext; */ - - /*** Attribute descriptor and subclassing stuff ***/ - Vector_methods, /* struct PyMethodDef *tp_methods; */ - NULL, /* struct PyMemberDef *tp_members; */ - Vector_getseters, /* struct PyGetSetDef *tp_getset; */ - NULL, /* struct _typeobject *tp_base; */ - NULL, /* PyObject *tp_dict; */ - NULL, /* descrgetfunc tp_descr_get; */ - NULL, /* descrsetfunc tp_descr_set; */ - 0, /* long tp_dictoffset; */ - NULL, /* initproc tp_init; */ - NULL, /* allocfunc tp_alloc; */ - Vector_new, /* newfunc tp_new; */ - /* Low-level free-memory routine */ - NULL, /* freefunc tp_free; */ - /* For PyObject_IS_GC */ - NULL, /* inquiry tp_is_gc; */ - NULL, /* PyObject *tp_bases; */ - /* method resolution order */ - NULL, /* PyObject *tp_mro; */ - NULL, /* PyObject *tp_cache; */ - NULL, /* PyObject *tp_subclasses; */ - NULL, /* PyObject *tp_weaklist; */ - NULL, + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + vector_doc, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + + /* call function for all accessible objects */ + (traverseproc)BaseMathObject_traverse, /* tp_traverse */ + + /* delete references to contained objects */ + (inquiry)BaseMathObject_clear, /* tp_clear */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + (richcmpfunc)Vector_richcmpr, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + Vector_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + Vector_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + Vector_new, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL, }; -PyObject *Vector_CreatePyObject( - const float *vec, const int size, - PyTypeObject *base_type) -{ - VectorObject *self; - float *vec_alloc; - - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector(): invalid size"); - return NULL; - } - - vec_alloc = PyMem_Malloc(size * sizeof(float)); - if (UNLIKELY(vec_alloc == NULL)) { - PyErr_SetString(PyExc_MemoryError, - "Vector(): " - "problem allocating data"); - return NULL; - } - - self = BASE_MATH_NEW(VectorObject, vector_Type, base_type); - if (self) { - self->vec = vec_alloc; - self->size = size; - - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; - - if (vec) { - memcpy(self->vec, vec, size * sizeof(float)); - } - else { /* new empty */ - copy_vn_fl(self->vec, size, 0.0f); - if (size == 4) { /* do the homogeneous thing */ - self->vec[3] = 1.0f; - } - } - self->flag = BASE_MATH_FLAG_DEFAULT; - } - else { - PyMem_Free(vec_alloc); - } - - return (PyObject *)self; +PyObject *Vector_CreatePyObject(const float *vec, const int size, PyTypeObject *base_type) +{ + VectorObject *self; + float *vec_alloc; + + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); + return NULL; + } + + vec_alloc = PyMem_Malloc(size * sizeof(float)); + if (UNLIKELY(vec_alloc == NULL)) { + PyErr_SetString(PyExc_MemoryError, + "Vector(): " + "problem allocating data"); + return NULL; + } + + self = BASE_MATH_NEW(VectorObject, vector_Type, base_type); + if (self) { + self->vec = vec_alloc; + self->size = size; + + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; + + if (vec) { + memcpy(self->vec, vec, size * sizeof(float)); + } + else { /* new empty */ + copy_vn_fl(self->vec, size, 0.0f); + if (size == 4) { /* do the homogeneous thing */ + self->vec[3] = 1.0f; + } + } + self->flag = BASE_MATH_FLAG_DEFAULT; + } + else { + PyMem_Free(vec_alloc); + } + + return (PyObject *)self; } /** @@ -3198,64 +3382,60 @@ PyObject *Vector_CreatePyObject( * * \param vec: Use this vector in-place. */ -PyObject *Vector_CreatePyObject_wrap( - float *vec, const int size, - PyTypeObject *base_type) +PyObject *Vector_CreatePyObject_wrap(float *vec, const int size, PyTypeObject *base_type) { - VectorObject *self; + VectorObject *self; - if (size < 2) { - PyErr_SetString(PyExc_RuntimeError, - "Vector(): invalid size"); - return NULL; - } + if (size < 2) { + PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); + return NULL; + } - self = BASE_MATH_NEW(VectorObject, vector_Type, base_type); - if (self) { - self->size = size; + self = BASE_MATH_NEW(VectorObject, vector_Type, base_type); + if (self) { + self->size = size; - /* init callbacks as NULL */ - self->cb_user = NULL; - self->cb_type = self->cb_subtype = 0; + /* init callbacks as NULL */ + self->cb_user = NULL; + self->cb_type = self->cb_subtype = 0; - self->vec = vec; - self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; - } - return (PyObject *) self; + self->vec = vec; + self->flag = BASE_MATH_FLAG_DEFAULT | BASE_MATH_FLAG_IS_WRAP; + } + return (PyObject *)self; } /** * Create a vector where the value is defined by registered callbacks, * see: #Mathutils_RegisterCallback */ -PyObject *Vector_CreatePyObject_cb( - PyObject *cb_user, int size, - unsigned char cb_type, unsigned char cb_subtype) +PyObject *Vector_CreatePyObject_cb(PyObject *cb_user, + int size, + unsigned char cb_type, + unsigned char cb_subtype) { - VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, size, NULL); - if (self) { - Py_INCREF(cb_user); - self->cb_user = cb_user; - self->cb_type = cb_type; - self->cb_subtype = cb_subtype; - PyObject_GC_Track(self); - } + VectorObject *self = (VectorObject *)Vector_CreatePyObject(NULL, size, NULL); + if (self) { + Py_INCREF(cb_user); + self->cb_user = cb_user; + self->cb_type = cb_type; + self->cb_subtype = cb_subtype; + PyObject_GC_Track(self); + } - return (PyObject *)self; + return (PyObject *)self; } /** * \param vec: Initialized vector value to use in-place, allocated with: PyMem_Malloc */ -PyObject *Vector_CreatePyObject_alloc( - float *vec, const int size, - PyTypeObject *base_type) +PyObject *Vector_CreatePyObject_alloc(float *vec, const int size, PyTypeObject *base_type) { - VectorObject *self; - self = (VectorObject *)Vector_CreatePyObject_wrap(vec, size, base_type); - if (self) { - self->flag = BASE_MATH_FLAG_DEFAULT; - } + VectorObject *self; + self = (VectorObject *)Vector_CreatePyObject_wrap(vec, size, base_type); + if (self) { + self->flag = BASE_MATH_FLAG_DEFAULT; + } - return (PyObject *)self; + return (PyObject *)self; } diff --git a/source/blender/python/mathutils/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h index 7ebc3fbf1d6..f75702bc54c 100644 --- a/source/blender/python/mathutils/mathutils_Vector.h +++ b/source/blender/python/mathutils/mathutils_Vector.h @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #ifndef __MATHUTILS_VECTOR_H__ #define __MATHUTILS_VECTOR_H__ @@ -28,27 +27,26 @@ extern PyTypeObject vector_Type; #define VectorObject_CheckExact(v) (Py_TYPE(v) == &vector_Type) typedef struct { - BASE_MATH_MEMBERS(vec); + BASE_MATH_MEMBERS(vec); - int size; /* vec size 2 or more */ + int size; /* vec size 2 or more */ } VectorObject; /*prototypes*/ -PyObject *Vector_CreatePyObject( - const float *vec, const int size, - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT; -PyObject *Vector_CreatePyObject_wrap( - float *vec, const int size, - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -PyObject *Vector_CreatePyObject_cb( - PyObject *user, int size, - unsigned char cb_type, unsigned char subtype - ) ATTR_WARN_UNUSED_RESULT; -PyObject *Vector_CreatePyObject_alloc( - float *vec, const int size, - PyTypeObject *base_type - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); - -#endif /* __MATHUTILS_VECTOR_H__ */ +PyObject *Vector_CreatePyObject(const float *vec, + const int size, + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT; +PyObject *Vector_CreatePyObject_wrap(float *vec, + const int size, + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); +PyObject *Vector_CreatePyObject_cb(PyObject *user, + int size, + unsigned char cb_type, + unsigned char subtype) ATTR_WARN_UNUSED_RESULT; +PyObject *Vector_CreatePyObject_alloc(float *vec, + const int size, + PyTypeObject *base_type) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); + +#endif /* __MATHUTILS_VECTOR_H__ */ diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c index b1420f316e6..cdb3035c0ca 100644 --- a/source/blender/python/mathutils/mathutils_bvhtree.c +++ b/source/blender/python/mathutils/mathutils_bvhtree.c @@ -38,52 +38,50 @@ #include "../generic/python_utildefines.h" #include "mathutils.h" -#include "mathutils_bvhtree.h" /* own include */ +#include "mathutils_bvhtree.h" /* own include */ #ifndef MATH_STANDALONE -#include "DNA_object_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" +# include "DNA_object_types.h" +# include "DNA_mesh_types.h" +# include "DNA_meshdata_types.h" -#include "BKE_customdata.h" -#include "BKE_editmesh_bvh.h" -#include "BKE_library.h" -#include "BKE_mesh.h" -#include "BKE_mesh_runtime.h" +# include "BKE_customdata.h" +# include "BKE_editmesh_bvh.h" +# include "BKE_library.h" +# include "BKE_mesh.h" +# include "BKE_mesh_runtime.h" -#include "DEG_depsgraph_query.h" +# include "DEG_depsgraph_query.h" -#include "bmesh.h" - -#include "../bmesh/bmesh_py_types.h" -#endif /* MATH_STANDALONE */ +# include "bmesh.h" +# include "../bmesh/bmesh_py_types.h" +#endif /* MATH_STANDALONE */ #include "BLI_strict_flags.h" - /* -------------------------------------------------------------------- */ /** \name Docstring (snippets) * \{ */ #define PYBVH_FIND_GENERIC_DISTANCE_DOC \ -" :arg distance: Maximum distance threshold.\n" \ -" :type distance: float\n" + " :arg distance: Maximum distance threshold.\n" \ + " :type distance: float\n" #define PYBVH_FIND_GENERIC_RETURN_DOC \ -" :return: Returns a tuple\n" \ -" (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \ -" Values will all be None if no hit is found.\n" \ -" :rtype: :class:`tuple`\n" + " :return: Returns a tuple\n" \ + " (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \ + " Values will all be None if no hit is found.\n" \ + " :rtype: :class:`tuple`\n" #define PYBVH_FIND_GENERIC_RETURN_LIST_DOC \ -" :return: Returns a list of tuples\n" \ -" (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \ -" :rtype: :class:`list`\n" + " :return: Returns a list of tuples\n" \ + " (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \ + " :rtype: :class:`list`\n" #define PYBVH_FROM_GENERIC_EPSILON_DOC \ -" :arg epsilon: Increase the threshold for detecting overlap and raycast hits.\n" \ -" :type epsilon: float\n" + " :arg epsilon: Increase the threshold for detecting overlap and raycast hits.\n" \ + " :type epsilon: float\n" /** \} */ @@ -95,160 +93,157 @@ static const char PY_BVH_TREE_TYPE_DEFAULT = 4; static const char PY_BVH_AXIS_DEFAULT = 6; typedef struct { - PyObject_HEAD - BVHTree *tree; - float epsilon; - - float (*coords)[3]; - unsigned int (*tris)[3]; - unsigned int coords_len, tris_len; - - /* Optional members */ - /* aligned with 'tris' */ - int *orig_index; - /* aligned with array that 'orig_index' points to */ - float (*orig_normal)[3]; + PyObject_HEAD BVHTree *tree; + float epsilon; + + float (*coords)[3]; + unsigned int (*tris)[3]; + unsigned int coords_len, tris_len; + + /* Optional members */ + /* aligned with 'tris' */ + int *orig_index; + /* aligned with array that 'orig_index' points to */ + float (*orig_normal)[3]; } PyBVHTree; - /* -------------------------------------------------------------------- */ /** \name Utility helper functions * \{ */ -static PyObject *bvhtree_CreatePyObject( - BVHTree *tree, float epsilon, +static PyObject *bvhtree_CreatePyObject(BVHTree *tree, + float epsilon, - float (*coords)[3], unsigned int coords_len, - unsigned int (*tris)[3], unsigned int tris_len, + float (*coords)[3], + unsigned int coords_len, + unsigned int (*tris)[3], + unsigned int tris_len, - /* optional arrays */ - int *orig_index, float (*orig_normal)[3]) + /* optional arrays */ + int *orig_index, + float (*orig_normal)[3]) { - PyBVHTree *result = PyObject_New(PyBVHTree, &PyBVHTree_Type); + PyBVHTree *result = PyObject_New(PyBVHTree, &PyBVHTree_Type); - result->tree = tree; - result->epsilon = epsilon; + result->tree = tree; + result->epsilon = epsilon; - result->coords = coords; - result->tris = tris; - result->coords_len = coords_len; - result->tris_len = tris_len; + result->coords = coords; + result->tris = tris; + result->coords_len = coords_len; + result->tris_len = tris_len; - result->orig_index = orig_index; - result->orig_normal = orig_normal; + result->orig_index = orig_index; + result->orig_normal = orig_normal; - return (PyObject *)result; + return (PyObject *)result; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name BVHTreeRayHit to Python utilities * \{ */ static void py_bvhtree_raycast_to_py_tuple(const BVHTreeRayHit *hit, PyObject *py_retval) { - BLI_assert(hit->index >= 0); - BLI_assert(PyTuple_GET_SIZE(py_retval) == 4); - - PyTuple_SET_ITEMS(py_retval, - Vector_CreatePyObject(hit->co, 3, NULL), - Vector_CreatePyObject(hit->no, 3, NULL), - PyLong_FromLong(hit->index), - PyFloat_FromDouble(hit->dist)); - + BLI_assert(hit->index >= 0); + BLI_assert(PyTuple_GET_SIZE(py_retval) == 4); + + PyTuple_SET_ITEMS(py_retval, + Vector_CreatePyObject(hit->co, 3, NULL), + Vector_CreatePyObject(hit->no, 3, NULL), + PyLong_FromLong(hit->index), + PyFloat_FromDouble(hit->dist)); } static PyObject *py_bvhtree_raycast_to_py(const BVHTreeRayHit *hit) { - PyObject *py_retval = PyTuple_New(4); + PyObject *py_retval = PyTuple_New(4); - py_bvhtree_raycast_to_py_tuple(hit, py_retval); + py_bvhtree_raycast_to_py_tuple(hit, py_retval); - return py_retval; + return py_retval; } static PyObject *py_bvhtree_raycast_to_py_none(void) { - PyObject *py_retval = PyTuple_New(4); + PyObject *py_retval = PyTuple_New(4); - PyC_Tuple_Fill(py_retval, Py_None); + PyC_Tuple_Fill(py_retval, Py_None); - return py_retval; + return py_retval; } #if 0 static PyObject *py_bvhtree_raycast_to_py_and_check(const BVHTreeRayHit *hit) { - PyObject *py_retval; + PyObject *py_retval; - py_retval = PyTuple_New(4); + py_retval = PyTuple_New(4); - if (hit->index != -1) { - py_bvhtree_raycast_to_py_tuple(hit, py_retval); - } - else { - PyC_Tuple_Fill(py_retval, Py_None); - } + if (hit->index != -1) { + py_bvhtree_raycast_to_py_tuple(hit, py_retval); + } + else { + PyC_Tuple_Fill(py_retval, Py_None); + } - return py_retval; + return py_retval; } #endif /** \} */ - /* -------------------------------------------------------------------- */ /** \name BVHTreeNearest to Python utilities * \{ */ static void py_bvhtree_nearest_to_py_tuple(const BVHTreeNearest *nearest, PyObject *py_retval) { - BLI_assert(nearest->index >= 0); - BLI_assert(PyTuple_GET_SIZE(py_retval) == 4); - - PyTuple_SET_ITEMS(py_retval, - Vector_CreatePyObject(nearest->co, 3, NULL), - Vector_CreatePyObject(nearest->no, 3, NULL), - PyLong_FromLong(nearest->index), - PyFloat_FromDouble(sqrtf(nearest->dist_sq))); - + BLI_assert(nearest->index >= 0); + BLI_assert(PyTuple_GET_SIZE(py_retval) == 4); + + PyTuple_SET_ITEMS(py_retval, + Vector_CreatePyObject(nearest->co, 3, NULL), + Vector_CreatePyObject(nearest->no, 3, NULL), + PyLong_FromLong(nearest->index), + PyFloat_FromDouble(sqrtf(nearest->dist_sq))); } static PyObject *py_bvhtree_nearest_to_py(const BVHTreeNearest *nearest) { - PyObject *py_retval = PyTuple_New(4); + PyObject *py_retval = PyTuple_New(4); - py_bvhtree_nearest_to_py_tuple(nearest, py_retval); + py_bvhtree_nearest_to_py_tuple(nearest, py_retval); - return py_retval; + return py_retval; } static PyObject *py_bvhtree_nearest_to_py_none(void) { - PyObject *py_retval = PyTuple_New(4); + PyObject *py_retval = PyTuple_New(4); - PyC_Tuple_Fill(py_retval, Py_None); + PyC_Tuple_Fill(py_retval, Py_None); - return py_retval; + return py_retval; } #if 0 static PyObject *py_bvhtree_nearest_to_py_and_check(const BVHTreeNearest *nearest) { - PyObject *py_retval; + PyObject *py_retval; - py_retval = PyTuple_New(4); + py_retval = PyTuple_New(4); - if (nearest->index != -1) { - py_bvhtree_nearest_to_py_tuple(nearest, py_retval); - } - else { - PyC_Tuple_Fill(py_retval, Py_None); - } + if (nearest->index != -1) { + py_bvhtree_nearest_to_py_tuple(nearest, py_retval); + } + else { + PyC_Tuple_Fill(py_retval, Py_None); + } - return py_retval; + return py_retval; } #endif @@ -256,1082 +251,1098 @@ static PyObject *py_bvhtree_nearest_to_py_and_check(const BVHTreeNearest *neares static void py_bvhtree__tp_dealloc(PyBVHTree *self) { - if (self->tree) { - BLI_bvhtree_free(self->tree); - } + if (self->tree) { + BLI_bvhtree_free(self->tree); + } - MEM_SAFE_FREE(self->coords); - MEM_SAFE_FREE(self->tris); + MEM_SAFE_FREE(self->coords); + MEM_SAFE_FREE(self->tris); - MEM_SAFE_FREE(self->orig_index); - MEM_SAFE_FREE(self->orig_normal); + MEM_SAFE_FREE(self->orig_index); + MEM_SAFE_FREE(self->orig_normal); - Py_TYPE(self)->tp_free((PyObject *)self); + Py_TYPE(self)->tp_free((PyObject *)self); } - /* -------------------------------------------------------------------- */ /** \name Methods * \{ */ -static void py_bvhtree_raycast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +static void py_bvhtree_raycast_cb(void *userdata, + int index, + const BVHTreeRay *ray, + BVHTreeRayHit *hit) { - const PyBVHTree *self = userdata; - - const float (*coords)[3] = (const float (*)[3])self->coords; - const unsigned int *tri = self->tris[index]; - const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]}; - float dist; - - if (self->epsilon == 0.0f) { - dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(tri_co)); - } - else { - dist = bvhtree_sphereray_tri_intersection(ray, self->epsilon, hit->dist, UNPACK3(tri_co)); - } - - if (dist >= 0 && dist < hit->dist) { - hit->index = self->orig_index ? self->orig_index[index] : index; - hit->dist = dist; - madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist); - if (self->orig_normal) { - copy_v3_v3(hit->no, self->orig_normal[hit->index]); - } - else { - normal_tri_v3(hit->no, UNPACK3(tri_co)); - } - } + const PyBVHTree *self = userdata; + + const float(*coords)[3] = (const float(*)[3])self->coords; + const unsigned int *tri = self->tris[index]; + const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]}; + float dist; + + if (self->epsilon == 0.0f) { + dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(tri_co)); + } + else { + dist = bvhtree_sphereray_tri_intersection(ray, self->epsilon, hit->dist, UNPACK3(tri_co)); + } + + if (dist >= 0 && dist < hit->dist) { + hit->index = self->orig_index ? self->orig_index[index] : index; + hit->dist = dist; + madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist); + if (self->orig_normal) { + copy_v3_v3(hit->no, self->orig_normal[hit->index]); + } + else { + normal_tri_v3(hit->no, UNPACK3(tri_co)); + } + } } -static void py_bvhtree_nearest_point_cb(void *userdata, int index, const float co[3], BVHTreeNearest *nearest) +static void py_bvhtree_nearest_point_cb(void *userdata, + int index, + const float co[3], + BVHTreeNearest *nearest) { - PyBVHTree *self = userdata; - - const float (*coords)[3] = (const float (*)[3])self->coords; - const unsigned int *tri = self->tris[index]; - const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]}; - float nearest_tmp[3], dist_sq; - - closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co)); - dist_sq = len_squared_v3v3(co, nearest_tmp); - - if (dist_sq < nearest->dist_sq) { - nearest->index = self->orig_index ? self->orig_index[index] : index; - nearest->dist_sq = dist_sq; - copy_v3_v3(nearest->co, nearest_tmp); - if (self->orig_normal) { - copy_v3_v3(nearest->no, self->orig_normal[nearest->index]); - } - else { - normal_tri_v3(nearest->no, UNPACK3(tri_co)); - } - } + PyBVHTree *self = userdata; + + const float(*coords)[3] = (const float(*)[3])self->coords; + const unsigned int *tri = self->tris[index]; + const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]}; + float nearest_tmp[3], dist_sq; + + closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co)); + dist_sq = len_squared_v3v3(co, nearest_tmp); + + if (dist_sq < nearest->dist_sq) { + nearest->index = self->orig_index ? self->orig_index[index] : index; + nearest->dist_sq = dist_sq; + copy_v3_v3(nearest->co, nearest_tmp); + if (self->orig_normal) { + copy_v3_v3(nearest->no, self->orig_normal[nearest->index]); + } + else { + normal_tri_v3(nearest->no, UNPACK3(tri_co)); + } + } } PyDoc_STRVAR(py_bvhtree_ray_cast_doc, -".. method:: ray_cast(origin, direction, distance=sys.float_info.max)\n" -"\n" -" Cast a ray onto the mesh.\n" -"\n" -" :arg co: Start location of the ray in object space.\n" -" :type co: :class:`Vector`\n" -" :arg direction: Direction of the ray in object space.\n" -" :type direction: :class:`Vector`\n" -PYBVH_FIND_GENERIC_DISTANCE_DOC -PYBVH_FIND_GENERIC_RETURN_DOC -); + ".. method:: ray_cast(origin, direction, distance=sys.float_info.max)\n" + "\n" + " Cast a ray onto the mesh.\n" + "\n" + " :arg co: Start location of the ray in object space.\n" + " :type co: :class:`Vector`\n" + " :arg direction: Direction of the ray in object space.\n" + " :type direction: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC + PYBVH_FIND_GENERIC_RETURN_DOC); static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args) { - const char *error_prefix = "ray_cast"; - float co[3], direction[3]; - float max_dist = FLT_MAX; - BVHTreeRayHit hit; - - /* parse args */ - { - PyObject *py_co, *py_direction; - - if (!PyArg_ParseTuple( - args, (char *)"OO|f:ray_cast", - &py_co, &py_direction, &max_dist)) - { - return NULL; - } - - if ((mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) || - (mathutils_array_parse(direction, 2, 3 | MU_ARRAY_ZERO, py_direction, error_prefix) == -1)) - { - return NULL; - } - - normalize_v3(direction); - } - - hit.dist = max_dist; - hit.index = -1; - - /* may fail if the mesh has no faces, in that case the ray-cast misses */ - if (self->tree) { - if (BLI_bvhtree_ray_cast( - self->tree, co, direction, 0.0f, &hit, - py_bvhtree_raycast_cb, self) != -1) - { - return py_bvhtree_raycast_to_py(&hit); - } - } - - return py_bvhtree_raycast_to_py_none(); + const char *error_prefix = "ray_cast"; + float co[3], direction[3]; + float max_dist = FLT_MAX; + BVHTreeRayHit hit; + + /* parse args */ + { + PyObject *py_co, *py_direction; + + if (!PyArg_ParseTuple(args, (char *)"OO|f:ray_cast", &py_co, &py_direction, &max_dist)) { + return NULL; + } + + if ((mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) || + (mathutils_array_parse(direction, 2, 3 | MU_ARRAY_ZERO, py_direction, error_prefix) == + -1)) { + return NULL; + } + + normalize_v3(direction); + } + + hit.dist = max_dist; + hit.index = -1; + + /* may fail if the mesh has no faces, in that case the ray-cast misses */ + if (self->tree) { + if (BLI_bvhtree_ray_cast(self->tree, co, direction, 0.0f, &hit, py_bvhtree_raycast_cb, self) != + -1) { + return py_bvhtree_raycast_to_py(&hit); + } + } + + return py_bvhtree_raycast_to_py_none(); } PyDoc_STRVAR(py_bvhtree_find_nearest_doc, -".. method:: find_nearest(origin, distance=" PYBVH_MAX_DIST_STR ")\n" -"\n" -" Find the nearest element (typically face index) to a point.\n" -"\n" -" :arg co: Find nearest element to this point.\n" -" :type co: :class:`Vector`\n" -PYBVH_FIND_GENERIC_DISTANCE_DOC -PYBVH_FIND_GENERIC_RETURN_DOC -); + ".. method:: find_nearest(origin, distance=" PYBVH_MAX_DIST_STR + ")\n" + "\n" + " Find the nearest element (typically face index) to a point.\n" + "\n" + " :arg co: Find nearest element to this point.\n" + " :type co: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC + PYBVH_FIND_GENERIC_RETURN_DOC); static PyObject *py_bvhtree_find_nearest(PyBVHTree *self, PyObject *args) { - const char *error_prefix = "find_nearest"; - float co[3]; - float max_dist = max_dist_default; - - BVHTreeNearest nearest; - - /* parse args */ - { - PyObject *py_co; - - if (!PyArg_ParseTuple( - args, (char *)"O|f:find_nearest", - &py_co, &max_dist)) - { - return NULL; - } - - if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) { - return NULL; - } - } - - nearest.index = -1; - nearest.dist_sq = max_dist * max_dist; - - /* may fail if the mesh has no faces, in that case the ray-cast misses */ - if (self->tree) { - if (BLI_bvhtree_find_nearest( - self->tree, co, &nearest, - py_bvhtree_nearest_point_cb, self) != -1) - { - return py_bvhtree_nearest_to_py(&nearest); - } - } - - return py_bvhtree_nearest_to_py_none(); + const char *error_prefix = "find_nearest"; + float co[3]; + float max_dist = max_dist_default; + + BVHTreeNearest nearest; + + /* parse args */ + { + PyObject *py_co; + + if (!PyArg_ParseTuple(args, (char *)"O|f:find_nearest", &py_co, &max_dist)) { + return NULL; + } + + if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) { + return NULL; + } + } + + nearest.index = -1; + nearest.dist_sq = max_dist * max_dist; + + /* may fail if the mesh has no faces, in that case the ray-cast misses */ + if (self->tree) { + if (BLI_bvhtree_find_nearest(self->tree, co, &nearest, py_bvhtree_nearest_point_cb, self) != + -1) { + return py_bvhtree_nearest_to_py(&nearest); + } + } + + return py_bvhtree_nearest_to_py_none(); } struct PyBVH_RangeData { - PyBVHTree *self; - PyObject *result; - float dist_sq; + PyBVHTree *self; + PyObject *result; + float dist_sq; }; -static void py_bvhtree_nearest_point_range_cb(void *userdata, int index, const float co[3], float UNUSED(dist_sq_bvh)) +static void py_bvhtree_nearest_point_range_cb(void *userdata, + int index, + const float co[3], + float UNUSED(dist_sq_bvh)) { - struct PyBVH_RangeData *data = userdata; - PyBVHTree *self = data->self; - - const float (*coords)[3] = (const float (*)[3])self->coords; - const unsigned int *tri = self->tris[index]; - const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]}; - float nearest_tmp[3], dist_sq; - - closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co)); - dist_sq = len_squared_v3v3(co, nearest_tmp); - - if (dist_sq < data->dist_sq) { - BVHTreeNearest nearest; - nearest.index = self->orig_index ? self->orig_index[index] : index; - nearest.dist_sq = dist_sq; - copy_v3_v3(nearest.co, nearest_tmp); - if (self->orig_normal) { - copy_v3_v3(nearest.no, self->orig_normal[nearest.index]); - } - else { - normal_tri_v3(nearest.no, UNPACK3(tri_co)); - } - - PyList_APPEND(data->result, py_bvhtree_nearest_to_py(&nearest)); - } + struct PyBVH_RangeData *data = userdata; + PyBVHTree *self = data->self; + + const float(*coords)[3] = (const float(*)[3])self->coords; + const unsigned int *tri = self->tris[index]; + const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]}; + float nearest_tmp[3], dist_sq; + + closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co)); + dist_sq = len_squared_v3v3(co, nearest_tmp); + + if (dist_sq < data->dist_sq) { + BVHTreeNearest nearest; + nearest.index = self->orig_index ? self->orig_index[index] : index; + nearest.dist_sq = dist_sq; + copy_v3_v3(nearest.co, nearest_tmp); + if (self->orig_normal) { + copy_v3_v3(nearest.no, self->orig_normal[nearest.index]); + } + else { + normal_tri_v3(nearest.no, UNPACK3(tri_co)); + } + + PyList_APPEND(data->result, py_bvhtree_nearest_to_py(&nearest)); + } } -PyDoc_STRVAR(py_bvhtree_find_nearest_range_doc, -".. method:: find_nearest_range(origin, distance=" PYBVH_MAX_DIST_STR ")\n" -"\n" -" Find the nearest elements (typically face index) to a point in the distance range.\n" -"\n" -" :arg co: Find nearest elements to this point.\n" -" :type co: :class:`Vector`\n" -PYBVH_FIND_GENERIC_DISTANCE_DOC -PYBVH_FIND_GENERIC_RETURN_LIST_DOC -); +PyDoc_STRVAR( + py_bvhtree_find_nearest_range_doc, + ".. method:: find_nearest_range(origin, distance=" PYBVH_MAX_DIST_STR + ")\n" + "\n" + " Find the nearest elements (typically face index) to a point in the distance range.\n" + "\n" + " :arg co: Find nearest elements to this point.\n" + " :type co: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC + PYBVH_FIND_GENERIC_RETURN_LIST_DOC); static PyObject *py_bvhtree_find_nearest_range(PyBVHTree *self, PyObject *args) { - const char *error_prefix = "find_nearest_range"; - float co[3]; - float max_dist = max_dist_default; - - /* parse args */ - { - PyObject *py_co; - - if (!PyArg_ParseTuple( - args, (char *)"O|f:find_nearest_range", - &py_co, &max_dist)) - { - return NULL; - } - - if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) { - return NULL; - } - } - - PyObject *ret = PyList_New(0); - - if (self->tree) { - struct PyBVH_RangeData data = { - .self = self, - .result = ret, - .dist_sq = SQUARE(max_dist), - }; - - BLI_bvhtree_range_query( - self->tree, co, max_dist, - py_bvhtree_nearest_point_range_cb, &data); - } - - return ret; -} + const char *error_prefix = "find_nearest_range"; + float co[3]; + float max_dist = max_dist_default; + + /* parse args */ + { + PyObject *py_co; + + if (!PyArg_ParseTuple(args, (char *)"O|f:find_nearest_range", &py_co, &max_dist)) { + return NULL; + } + + if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) { + return NULL; + } + } + + PyObject *ret = PyList_New(0); + if (self->tree) { + struct PyBVH_RangeData data = { + .self = self, + .result = ret, + .dist_sq = SQUARE(max_dist), + }; + + BLI_bvhtree_range_query(self->tree, co, max_dist, py_bvhtree_nearest_point_range_cb, &data); + } + + return ret; +} BLI_INLINE unsigned int overlap_hash(const void *overlap_v) { - const BVHTreeOverlap *overlap = overlap_v; - /* same constants as edge-hash */ - return (((unsigned int)overlap->indexA * 65) ^ ((unsigned int)overlap->indexA * 31)); + const BVHTreeOverlap *overlap = overlap_v; + /* same constants as edge-hash */ + return (((unsigned int)overlap->indexA * 65) ^ ((unsigned int)overlap->indexA * 31)); } BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v) { - const BVHTreeOverlap *a = a_v; - const BVHTreeOverlap *b = b_v; - return (memcmp(a, b, sizeof(*a)) != 0); + const BVHTreeOverlap *a = a_v; + const BVHTreeOverlap *b = b_v; + return (memcmp(a, b, sizeof(*a)) != 0); } struct PyBVHTree_OverlapData { - PyBVHTree *tree_pair[2]; - float epsilon; + PyBVHTree *tree_pair[2]; + float epsilon; }; static bool py_bvhtree_overlap_cb(void *userdata, int index_a, int index_b, int UNUSED(thread)) { - struct PyBVHTree_OverlapData *data = userdata; - PyBVHTree *tree_a = data->tree_pair[0]; - PyBVHTree *tree_b = data->tree_pair[1]; - const unsigned int *tri_a = tree_a->tris[index_a]; - const unsigned int *tri_b = tree_b->tris[index_b]; - const float *tri_a_co[3] = {tree_a->coords[tri_a[0]], tree_a->coords[tri_a[1]], tree_a->coords[tri_a[2]]}; - const float *tri_b_co[3] = {tree_b->coords[tri_b[0]], tree_b->coords[tri_b[1]], tree_b->coords[tri_b[2]]}; - float ix_pair[2][3]; - int verts_shared = 0; - - if (tree_a == tree_b) { - if (UNLIKELY(index_a == index_b)) { - return false; - } - - verts_shared = ( - ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + - ELEM(tri_a_co[1], UNPACK3(tri_b_co)) + - ELEM(tri_a_co[2], UNPACK3(tri_b_co))); - - /* if 2 points are shared, bail out */ - if (verts_shared >= 2) { - return false; - } - } - - return (isect_tri_tri_epsilon_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1], data->epsilon) && - ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon))); + struct PyBVHTree_OverlapData *data = userdata; + PyBVHTree *tree_a = data->tree_pair[0]; + PyBVHTree *tree_b = data->tree_pair[1]; + const unsigned int *tri_a = tree_a->tris[index_a]; + const unsigned int *tri_b = tree_b->tris[index_b]; + const float *tri_a_co[3] = { + tree_a->coords[tri_a[0]], tree_a->coords[tri_a[1]], tree_a->coords[tri_a[2]]}; + const float *tri_b_co[3] = { + tree_b->coords[tri_b[0]], tree_b->coords[tri_b[1]], tree_b->coords[tri_b[2]]}; + float ix_pair[2][3]; + int verts_shared = 0; + + if (tree_a == tree_b) { + if (UNLIKELY(index_a == index_b)) { + return false; + } + + verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) + + ELEM(tri_a_co[2], UNPACK3(tri_b_co))); + + /* if 2 points are shared, bail out */ + if (verts_shared >= 2) { + return false; + } + } + + return (isect_tri_tri_epsilon_v3( + UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1], data->epsilon) && + ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon))); } -PyDoc_STRVAR(py_bvhtree_overlap_doc, -".. method:: overlap(other_tree)\n" -"\n" -" Find overlapping indices between 2 trees.\n" -"\n" -" :arg other_tree: Other tree to perform overlap test on.\n" -" :type other_tree: :class:`BVHTree`\n" -" :return: Returns a list of unique index pairs," -" the first index referencing this tree, the second referencing the **other_tree**.\n" -" :rtype: :class:`list`\n" -); +PyDoc_STRVAR( + py_bvhtree_overlap_doc, + ".. method:: overlap(other_tree)\n" + "\n" + " Find overlapping indices between 2 trees.\n" + "\n" + " :arg other_tree: Other tree to perform overlap test on.\n" + " :type other_tree: :class:`BVHTree`\n" + " :return: Returns a list of unique index pairs," + " the first index referencing this tree, the second referencing the **other_tree**.\n" + " :rtype: :class:`list`\n"); static PyObject *py_bvhtree_overlap(PyBVHTree *self, PyBVHTree *other) { - struct PyBVHTree_OverlapData data; - BVHTreeOverlap *overlap; - unsigned int overlap_len = 0; - PyObject *ret; - - if (!PyBVHTree_CheckExact(other)) { - PyErr_SetString(PyExc_ValueError, "Expected a BVHTree argument"); - return NULL; - } - - data.tree_pair[0] = self; - data.tree_pair[1] = other; - data.epsilon = max_ff(self->epsilon, other->epsilon); - - overlap = BLI_bvhtree_overlap(self->tree, other->tree, &overlap_len, py_bvhtree_overlap_cb, &data); - - ret = PyList_New(0); - - if (overlap == NULL) { - /* pass */ - } - else { - bool use_unique = (self->orig_index || other->orig_index); - GSet *pair_test = use_unique ? BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, overlap_len) : NULL; - /* simple case, no index remapping */ - unsigned int i; - - for (i = 0; i < overlap_len; i++) { - PyObject *item; - if (use_unique) { - if (self->orig_index) { - overlap[i].indexA = self->orig_index[overlap[i].indexA]; - } - if (other->orig_index) { - overlap[i].indexB = other->orig_index[overlap[i].indexB]; - } - - /* skip if its already added */ - if (!BLI_gset_add(pair_test, &overlap[i])) { - continue; - } - } - - item = PyTuple_New(2); - PyTuple_SET_ITEMS(item, - PyLong_FromLong(overlap[i].indexA), - PyLong_FromLong(overlap[i].indexB)); - - PyList_Append(ret, item); - Py_DECREF(item); - } - - if (pair_test) { - BLI_gset_free(pair_test, NULL); - } - } - - if (overlap) { - MEM_freeN(overlap); - } - - return ret; + struct PyBVHTree_OverlapData data; + BVHTreeOverlap *overlap; + unsigned int overlap_len = 0; + PyObject *ret; + + if (!PyBVHTree_CheckExact(other)) { + PyErr_SetString(PyExc_ValueError, "Expected a BVHTree argument"); + return NULL; + } + + data.tree_pair[0] = self; + data.tree_pair[1] = other; + data.epsilon = max_ff(self->epsilon, other->epsilon); + + overlap = BLI_bvhtree_overlap( + self->tree, other->tree, &overlap_len, py_bvhtree_overlap_cb, &data); + + ret = PyList_New(0); + + if (overlap == NULL) { + /* pass */ + } + else { + bool use_unique = (self->orig_index || other->orig_index); + GSet *pair_test = use_unique ? + BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, overlap_len) : + NULL; + /* simple case, no index remapping */ + unsigned int i; + + for (i = 0; i < overlap_len; i++) { + PyObject *item; + if (use_unique) { + if (self->orig_index) { + overlap[i].indexA = self->orig_index[overlap[i].indexA]; + } + if (other->orig_index) { + overlap[i].indexB = other->orig_index[overlap[i].indexB]; + } + + /* skip if its already added */ + if (!BLI_gset_add(pair_test, &overlap[i])) { + continue; + } + } + + item = PyTuple_New(2); + PyTuple_SET_ITEMS( + item, PyLong_FromLong(overlap[i].indexA), PyLong_FromLong(overlap[i].indexB)); + + PyList_Append(ret, item); + Py_DECREF(item); + } + + if (pair_test) { + BLI_gset_free(pair_test, NULL); + } + } + + if (overlap) { + MEM_freeN(overlap); + } + + return ret; } /** \} */ - /* -------------------------------------------------------------------- */ /** \name Class Methods * \{ */ -PyDoc_STRVAR(C_BVHTree_FromPolygons_doc, -".. classmethod:: FromPolygons(vertices, polygons, all_triangles=False, epsilon=0.0)\n" -"\n" -" BVH tree constructed geometry passed in as arguments.\n" -"\n" -" :arg vertices: float triplets each representing ``(x, y, z)``\n" -" :type vertices: float triplet sequence\n" -" :arg polygons: Sequence of polyugons, each containing indices to the vertices argument.\n" -" :type polygons: Sequence of sequences containing ints\n" -" :arg all_triangles: Use when all **polygons** are triangles for more efficient conversion.\n" -" :type all_triangles: bool\n" -PYBVH_FROM_GENERIC_EPSILON_DOC -); +PyDoc_STRVAR( + C_BVHTree_FromPolygons_doc, + ".. classmethod:: FromPolygons(vertices, polygons, all_triangles=False, epsilon=0.0)\n" + "\n" + " BVH tree constructed geometry passed in as arguments.\n" + "\n" + " :arg vertices: float triplets each representing ``(x, y, z)``\n" + " :type vertices: float triplet sequence\n" + " :arg polygons: Sequence of polyugons, each containing indices to the vertices argument.\n" + " :type polygons: Sequence of sequences containing ints\n" + " :arg all_triangles: Use when all **polygons** are triangles for more efficient " + "conversion.\n" + " :type all_triangles: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC); static PyObject *C_BVHTree_FromPolygons(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs) { - const char *error_prefix = "BVHTree.FromPolygons"; - const char *keywords[] = {"vertices", "polygons", "all_triangles", "epsilon", NULL}; - - PyObject *py_coords, *py_tris; - PyObject *py_coords_fast = NULL, *py_tris_fast = NULL; - - MemArena *poly_arena = NULL; - MemArena *pf_arena = NULL; - - float (*coords)[3] = NULL; - unsigned int (*tris)[3] = NULL; - unsigned int coords_len, tris_len; - float epsilon = 0.0f; - bool all_triangles = false; - - /* when all_triangles is False */ - int *orig_index = NULL; - float (*orig_normal)[3] = NULL; - - unsigned int i; - bool valid = true; - - - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, (char *)"OO|$O&f:BVHTree.FromPolygons", (char **)keywords, - &py_coords, &py_tris, - PyC_ParseBool, &all_triangles, - &epsilon)) - { - return NULL; - } - - if (!(py_coords_fast = PySequence_Fast(py_coords, error_prefix)) || - !(py_tris_fast = PySequence_Fast(py_tris, error_prefix))) - { - Py_XDECREF(py_coords_fast); - return NULL; - } - - if (valid) { - PyObject **py_coords_fast_items = PySequence_Fast_ITEMS(py_coords_fast); - coords_len = (unsigned int)PySequence_Fast_GET_SIZE(py_coords_fast); - coords = MEM_mallocN((size_t)coords_len * sizeof(*coords), __func__); - - for (i = 0; i < coords_len; i++) { - PyObject *py_vert = py_coords_fast_items[i]; - - if (mathutils_array_parse(coords[i], 3, 3, py_vert, "BVHTree vertex: ") == -1) { - valid = false; - break; - } - } - } - - if (valid == false) { - /* pass */ - } - else if (all_triangles) { - /* all triangles, simple case */ - PyObject **py_tris_fast_items = PySequence_Fast_ITEMS(py_tris_fast); - tris_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tris_fast); - tris = MEM_mallocN((size_t)tris_len * sizeof(*tris), __func__); - - for (i = 0; i < tris_len; i++) { - PyObject *py_tricoords = py_tris_fast_items[i]; - PyObject *py_tricoords_fast; - PyObject **py_tricoords_fast_items; - unsigned int *tri = tris[i]; - int j; - - if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) { - valid = false; - break; - } - - if (PySequence_Fast_GET_SIZE(py_tricoords_fast) != 3) { - Py_DECREF(py_tricoords_fast); - PyErr_Format(PyExc_ValueError, - "%s: non triangle found at index %d with length of %d", - error_prefix, i, PySequence_Fast_GET_SIZE(py_tricoords_fast)); - valid = false; - break; - } - - py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast); - - for (j = 0; j < 3; j++) { - tri[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]); - if (UNLIKELY(tri[j] >= (unsigned int)coords_len)) { - PyErr_Format(PyExc_ValueError, - "%s: index %d must be less than %d", - error_prefix, tri[j], coords_len); - - /* decref below */ - valid = false; - break; - } - } - - Py_DECREF(py_tricoords_fast); - } - } - else { - /* ngon support (much more involved) */ - const unsigned int polys_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tris_fast); - struct PolyLink { - struct PolyLink *next; - unsigned int len; - unsigned int poly[0]; - } *plink_first = NULL, **p_plink_prev = &plink_first, *plink = NULL; - int poly_index; - - tris_len = 0; - - poly_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - - for (i = 0; i < polys_len; i++) { - PyObject *py_tricoords = PySequence_Fast_GET_ITEM(py_tris_fast, i); - PyObject *py_tricoords_fast; - PyObject **py_tricoords_fast_items; - unsigned int py_tricoords_len; - unsigned int j; - - if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) { - valid = false; - break; - } - - py_tricoords_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tricoords_fast); - py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast); - - plink = BLI_memarena_alloc(poly_arena, sizeof(*plink) + (sizeof(int) * (size_t)py_tricoords_len)); - - plink->len = (unsigned int)py_tricoords_len; - *p_plink_prev = plink; - p_plink_prev = &plink->next; - - for (j = 0; j < py_tricoords_len; j++) { - plink->poly[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]); - if (UNLIKELY(plink->poly[j] >= (unsigned int)coords_len)) { - PyErr_Format(PyExc_ValueError, - "%s: index %d must be less than %d", - error_prefix, plink->poly[j], coords_len); - /* decref below */ - valid = false; - break; - } - } - - Py_DECREF(py_tricoords_fast); - - if (py_tricoords_len >= 3) { - tris_len += (py_tricoords_len - 2); - } - } - *p_plink_prev = NULL; - - /* all ngon's are parsed, now tessellate */ - - pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); - tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__); - - orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__); - orig_normal = MEM_mallocN(sizeof(*orig_normal) * (size_t)polys_len, __func__); - - for (plink = plink_first, poly_index = 0, i = 0; plink; plink = plink->next, poly_index++) { - if (plink->len == 3) { - unsigned int *tri = tris[i]; - memcpy(tri, plink->poly, sizeof(unsigned int[3])); - orig_index[i] = poly_index; - normal_tri_v3(orig_normal[poly_index], coords[tri[0]], coords[tri[1]], coords[tri[2]]); - i++; - } - else if (plink->len > 3) { - float (*proj_coords)[2] = BLI_memarena_alloc(pf_arena, sizeof(*proj_coords) * plink->len); - float *normal = orig_normal[poly_index]; - const float *co_prev; - const float *co_curr; - float axis_mat[3][3]; - unsigned int (*tris_offset)[3] = &tris[i]; - unsigned int j; - - /* calc normal and setup 'proj_coords' */ - zero_v3(normal); - co_prev = coords[plink->poly[plink->len - 1]]; - for (j = 0; j < plink->len; j++) { - co_curr = coords[plink->poly[j]]; - add_newell_cross_v3_v3v3(normal, co_prev, co_curr); - co_prev = co_curr; - } - normalize_v3(normal); - - axis_dominant_v3_to_m3_negate(axis_mat, normal); - - for (j = 0; j < plink->len; j++) { - mul_v2_m3v3(proj_coords[j], axis_mat, coords[plink->poly[j]]); - } - - BLI_polyfill_calc_arena(proj_coords, plink->len, 1, tris_offset, pf_arena); - - j = plink->len - 2; - while (j--) { - unsigned int *tri = tris_offset[j]; - /* remap to global indices */ - tri[0] = plink->poly[tri[0]]; - tri[1] = plink->poly[tri[1]]; - tri[2] = plink->poly[tri[2]]; - - orig_index[i] = poly_index; - i++; - } - - BLI_memarena_clear(pf_arena); - } - else { - zero_v3(orig_normal[poly_index]); - } - } - } - - Py_DECREF(py_coords_fast); - Py_DECREF(py_tris_fast); - - if (pf_arena) { - BLI_memarena_free(pf_arena); - } - - if (poly_arena) { - BLI_memarena_free(poly_arena); - } - - if (valid) { - BVHTree *tree; - - tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT); - if (tree) { - for (i = 0; i < tris_len; i++) { - float co[3][3]; - - copy_v3_v3(co[0], coords[tris[i][0]]); - copy_v3_v3(co[1], coords[tris[i][1]]); - copy_v3_v3(co[2], coords[tris[i][2]]); - - BLI_bvhtree_insert(tree, (int)i, co[0], 3); - } - - BLI_bvhtree_balance(tree); - } - - return bvhtree_CreatePyObject( - tree, epsilon, - coords, coords_len, - tris, tris_len, - orig_index, orig_normal); - } - else { - if (coords) { - MEM_freeN(coords); - } - if (tris) { - MEM_freeN(tris); - } - - return NULL; - } + const char *error_prefix = "BVHTree.FromPolygons"; + const char *keywords[] = {"vertices", "polygons", "all_triangles", "epsilon", NULL}; + + PyObject *py_coords, *py_tris; + PyObject *py_coords_fast = NULL, *py_tris_fast = NULL; + + MemArena *poly_arena = NULL; + MemArena *pf_arena = NULL; + + float(*coords)[3] = NULL; + unsigned int(*tris)[3] = NULL; + unsigned int coords_len, tris_len; + float epsilon = 0.0f; + bool all_triangles = false; + + /* when all_triangles is False */ + int *orig_index = NULL; + float(*orig_normal)[3] = NULL; + + unsigned int i; + bool valid = true; + + if (!PyArg_ParseTupleAndKeywords(args, + kwargs, + (char *)"OO|$O&f:BVHTree.FromPolygons", + (char **)keywords, + &py_coords, + &py_tris, + PyC_ParseBool, + &all_triangles, + &epsilon)) { + return NULL; + } + + if (!(py_coords_fast = PySequence_Fast(py_coords, error_prefix)) || + !(py_tris_fast = PySequence_Fast(py_tris, error_prefix))) { + Py_XDECREF(py_coords_fast); + return NULL; + } + + if (valid) { + PyObject **py_coords_fast_items = PySequence_Fast_ITEMS(py_coords_fast); + coords_len = (unsigned int)PySequence_Fast_GET_SIZE(py_coords_fast); + coords = MEM_mallocN((size_t)coords_len * sizeof(*coords), __func__); + + for (i = 0; i < coords_len; i++) { + PyObject *py_vert = py_coords_fast_items[i]; + + if (mathutils_array_parse(coords[i], 3, 3, py_vert, "BVHTree vertex: ") == -1) { + valid = false; + break; + } + } + } + + if (valid == false) { + /* pass */ + } + else if (all_triangles) { + /* all triangles, simple case */ + PyObject **py_tris_fast_items = PySequence_Fast_ITEMS(py_tris_fast); + tris_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tris_fast); + tris = MEM_mallocN((size_t)tris_len * sizeof(*tris), __func__); + + for (i = 0; i < tris_len; i++) { + PyObject *py_tricoords = py_tris_fast_items[i]; + PyObject *py_tricoords_fast; + PyObject **py_tricoords_fast_items; + unsigned int *tri = tris[i]; + int j; + + if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) { + valid = false; + break; + } + + if (PySequence_Fast_GET_SIZE(py_tricoords_fast) != 3) { + Py_DECREF(py_tricoords_fast); + PyErr_Format(PyExc_ValueError, + "%s: non triangle found at index %d with length of %d", + error_prefix, + i, + PySequence_Fast_GET_SIZE(py_tricoords_fast)); + valid = false; + break; + } + + py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast); + + for (j = 0; j < 3; j++) { + tri[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]); + if (UNLIKELY(tri[j] >= (unsigned int)coords_len)) { + PyErr_Format(PyExc_ValueError, + "%s: index %d must be less than %d", + error_prefix, + tri[j], + coords_len); + + /* decref below */ + valid = false; + break; + } + } + + Py_DECREF(py_tricoords_fast); + } + } + else { + /* ngon support (much more involved) */ + const unsigned int polys_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tris_fast); + struct PolyLink { + struct PolyLink *next; + unsigned int len; + unsigned int poly[0]; + } *plink_first = NULL, **p_plink_prev = &plink_first, *plink = NULL; + int poly_index; + + tris_len = 0; + + poly_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + + for (i = 0; i < polys_len; i++) { + PyObject *py_tricoords = PySequence_Fast_GET_ITEM(py_tris_fast, i); + PyObject *py_tricoords_fast; + PyObject **py_tricoords_fast_items; + unsigned int py_tricoords_len; + unsigned int j; + + if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) { + valid = false; + break; + } + + py_tricoords_len = (unsigned int)PySequence_Fast_GET_SIZE(py_tricoords_fast); + py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast); + + plink = BLI_memarena_alloc(poly_arena, + sizeof(*plink) + (sizeof(int) * (size_t)py_tricoords_len)); + + plink->len = (unsigned int)py_tricoords_len; + *p_plink_prev = plink; + p_plink_prev = &plink->next; + + for (j = 0; j < py_tricoords_len; j++) { + plink->poly[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]); + if (UNLIKELY(plink->poly[j] >= (unsigned int)coords_len)) { + PyErr_Format(PyExc_ValueError, + "%s: index %d must be less than %d", + error_prefix, + plink->poly[j], + coords_len); + /* decref below */ + valid = false; + break; + } + } + + Py_DECREF(py_tricoords_fast); + + if (py_tricoords_len >= 3) { + tris_len += (py_tricoords_len - 2); + } + } + *p_plink_prev = NULL; + + /* all ngon's are parsed, now tessellate */ + + pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__); + tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__); + + orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__); + orig_normal = MEM_mallocN(sizeof(*orig_normal) * (size_t)polys_len, __func__); + + for (plink = plink_first, poly_index = 0, i = 0; plink; plink = plink->next, poly_index++) { + if (plink->len == 3) { + unsigned int *tri = tris[i]; + memcpy(tri, plink->poly, sizeof(unsigned int[3])); + orig_index[i] = poly_index; + normal_tri_v3(orig_normal[poly_index], coords[tri[0]], coords[tri[1]], coords[tri[2]]); + i++; + } + else if (plink->len > 3) { + float(*proj_coords)[2] = BLI_memarena_alloc(pf_arena, sizeof(*proj_coords) * plink->len); + float *normal = orig_normal[poly_index]; + const float *co_prev; + const float *co_curr; + float axis_mat[3][3]; + unsigned int(*tris_offset)[3] = &tris[i]; + unsigned int j; + + /* calc normal and setup 'proj_coords' */ + zero_v3(normal); + co_prev = coords[plink->poly[plink->len - 1]]; + for (j = 0; j < plink->len; j++) { + co_curr = coords[plink->poly[j]]; + add_newell_cross_v3_v3v3(normal, co_prev, co_curr); + co_prev = co_curr; + } + normalize_v3(normal); + + axis_dominant_v3_to_m3_negate(axis_mat, normal); + + for (j = 0; j < plink->len; j++) { + mul_v2_m3v3(proj_coords[j], axis_mat, coords[plink->poly[j]]); + } + + BLI_polyfill_calc_arena(proj_coords, plink->len, 1, tris_offset, pf_arena); + + j = plink->len - 2; + while (j--) { + unsigned int *tri = tris_offset[j]; + /* remap to global indices */ + tri[0] = plink->poly[tri[0]]; + tri[1] = plink->poly[tri[1]]; + tri[2] = plink->poly[tri[2]]; + + orig_index[i] = poly_index; + i++; + } + + BLI_memarena_clear(pf_arena); + } + else { + zero_v3(orig_normal[poly_index]); + } + } + } + + Py_DECREF(py_coords_fast); + Py_DECREF(py_tris_fast); + + if (pf_arena) { + BLI_memarena_free(pf_arena); + } + + if (poly_arena) { + BLI_memarena_free(poly_arena); + } + + if (valid) { + BVHTree *tree; + + tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT); + if (tree) { + for (i = 0; i < tris_len; i++) { + float co[3][3]; + + copy_v3_v3(co[0], coords[tris[i][0]]); + copy_v3_v3(co[1], coords[tris[i][1]]); + copy_v3_v3(co[2], coords[tris[i][2]]); + + BLI_bvhtree_insert(tree, (int)i, co[0], 3); + } + + BLI_bvhtree_balance(tree); + } + + return bvhtree_CreatePyObject( + tree, epsilon, coords, coords_len, tris, tris_len, orig_index, orig_normal); + } + else { + if (coords) { + MEM_freeN(coords); + } + if (tris) { + MEM_freeN(tris); + } + + return NULL; + } } - #ifndef MATH_STANDALONE PyDoc_STRVAR(C_BVHTree_FromBMesh_doc, -".. classmethod:: FromBMesh(bmesh, epsilon=0.0)\n" -"\n" -" BVH tree based on :class:`BMesh` data.\n" -"\n" -" :arg bmesh: BMesh data.\n" -" :type bmesh: :class:`BMesh`\n" -PYBVH_FROM_GENERIC_EPSILON_DOC -); + ".. classmethod:: FromBMesh(bmesh, epsilon=0.0)\n" + "\n" + " BVH tree based on :class:`BMesh` data.\n" + "\n" + " :arg bmesh: BMesh data.\n" + " :type bmesh: :class:`BMesh`\n" PYBVH_FROM_GENERIC_EPSILON_DOC); static PyObject *C_BVHTree_FromBMesh(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs) { - const char *keywords[] = {"bmesh", "epsilon", NULL}; + const char *keywords[] = {"bmesh", "epsilon", NULL}; - BPy_BMesh *py_bm; + BPy_BMesh *py_bm; - float (*coords)[3] = NULL; - unsigned int (*tris)[3] = NULL; - unsigned int coords_len, tris_len; - float epsilon = 0.0f; + float(*coords)[3] = NULL; + unsigned int(*tris)[3] = NULL; + unsigned int coords_len, tris_len; + float epsilon = 0.0f; - BMesh *bm; - BMLoop *(*looptris)[3]; + BMesh *bm; + BMLoop *(*looptris)[3]; - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, (char *)"O!|$f:BVHTree.FromBMesh", (char **)keywords, - &BPy_BMesh_Type, &py_bm, &epsilon)) - { - return NULL; - } + if (!PyArg_ParseTupleAndKeywords(args, + kwargs, + (char *)"O!|$f:BVHTree.FromBMesh", + (char **)keywords, + &BPy_BMesh_Type, + &py_bm, + &epsilon)) { + return NULL; + } - bm = py_bm->bm; + bm = py_bm->bm; - /* Get data for tessellation */ - { - int tris_len_dummy; + /* Get data for tessellation */ + { + int tris_len_dummy; - coords_len = (unsigned int)bm->totvert; - tris_len = (unsigned int)poly_to_tri_count(bm->totface, bm->totloop); + coords_len = (unsigned int)bm->totvert; + tris_len = (unsigned int)poly_to_tri_count(bm->totface, bm->totloop); - coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__); - tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__); + coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__); + tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__); - looptris = MEM_mallocN(sizeof(*looptris) * (size_t)tris_len, __func__); + looptris = MEM_mallocN(sizeof(*looptris) * (size_t)tris_len, __func__); - BM_mesh_calc_tessellation(bm, looptris, &tris_len_dummy); - BLI_assert(tris_len_dummy == (int)tris_len); - } + BM_mesh_calc_tessellation(bm, looptris, &tris_len_dummy); + BLI_assert(tris_len_dummy == (int)tris_len); + } - { - BMIter iter; - BVHTree *tree; - unsigned int i; + { + BMIter iter; + BVHTree *tree; + unsigned int i; - int *orig_index = NULL; - float (*orig_normal)[3] = NULL; + int *orig_index = NULL; + float(*orig_normal)[3] = NULL; - tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT); - if (tree) { - BMFace *f; - BMVert *v; + tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT); + if (tree) { + BMFace *f; + BMVert *v; - orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__); - orig_normal = MEM_mallocN(sizeof(*orig_normal) * (size_t)bm->totface, __func__); + orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__); + orig_normal = MEM_mallocN(sizeof(*orig_normal) * (size_t)bm->totface, __func__); - BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - copy_v3_v3(coords[i], v->co); - BM_elem_index_set(v, (int)i); /* set_inline */ - } - BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { - copy_v3_v3(orig_normal[i], f->no); - BM_elem_index_set(f, (int)i); /* set_inline */ - } - bm->elem_index_dirty &= (char)~(BM_VERT | BM_FACE); + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + copy_v3_v3(coords[i], v->co); + BM_elem_index_set(v, (int)i); /* set_inline */ + } + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) { + copy_v3_v3(orig_normal[i], f->no); + BM_elem_index_set(f, (int)i); /* set_inline */ + } + bm->elem_index_dirty &= (char)~(BM_VERT | BM_FACE); - for (i = 0; i < tris_len; i++) { - float co[3][3]; + for (i = 0; i < tris_len; i++) { + float co[3][3]; - tris[i][0] = (unsigned int)BM_elem_index_get(looptris[i][0]->v); - tris[i][1] = (unsigned int)BM_elem_index_get(looptris[i][1]->v); - tris[i][2] = (unsigned int)BM_elem_index_get(looptris[i][2]->v); + tris[i][0] = (unsigned int)BM_elem_index_get(looptris[i][0]->v); + tris[i][1] = (unsigned int)BM_elem_index_get(looptris[i][1]->v); + tris[i][2] = (unsigned int)BM_elem_index_get(looptris[i][2]->v); - copy_v3_v3(co[0], coords[tris[i][0]]); - copy_v3_v3(co[1], coords[tris[i][1]]); - copy_v3_v3(co[2], coords[tris[i][2]]); + copy_v3_v3(co[0], coords[tris[i][0]]); + copy_v3_v3(co[1], coords[tris[i][1]]); + copy_v3_v3(co[2], coords[tris[i][2]]); - BLI_bvhtree_insert(tree, (int)i, co[0], 3); - orig_index[i] = BM_elem_index_get(looptris[i][0]->f); - } + BLI_bvhtree_insert(tree, (int)i, co[0], 3); + orig_index[i] = BM_elem_index_get(looptris[i][0]->f); + } - BLI_bvhtree_balance(tree); - } + BLI_bvhtree_balance(tree); + } - MEM_freeN(looptris); + MEM_freeN(looptris); - return bvhtree_CreatePyObject( - tree, epsilon, - coords, coords_len, - tris, tris_len, - orig_index, orig_normal); - } + return bvhtree_CreatePyObject( + tree, epsilon, coords, coords_len, tris, tris_len, orig_index, orig_normal); + } } /* return various derived meshes based on requested settings */ -static Mesh *bvh_get_mesh( - const char *funcname, struct Depsgraph *depsgraph, struct Scene *scene, Object *ob, - const bool use_deform, const bool use_cage, bool *r_free_mesh) +static Mesh *bvh_get_mesh(const char *funcname, + struct Depsgraph *depsgraph, + struct Scene *scene, + Object *ob, + const bool use_deform, + const bool use_cage, + bool *r_free_mesh) { - Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - /* we only need minimum mesh data for topology and vertex locations */ - CustomData_MeshMasks data_masks = CD_MASK_BAREMESH; - const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER; - *r_free_mesh = false; - - /* Write the display mesh into the dummy mesh */ - if (use_deform) { - if (use_render) { - if (use_cage) { - PyErr_Format(PyExc_ValueError, - "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", funcname); - return NULL; - } - else { - *r_free_mesh = true; - return mesh_create_eval_final_render(depsgraph, scene, ob, &data_masks); - } - } - else if (ob_eval != NULL) { - if (use_cage) { - return mesh_get_eval_deform(depsgraph, scene, ob_eval, &data_masks); - } - else { - return mesh_get_eval_final(depsgraph, scene, ob_eval, &data_masks); - } - } - else { - PyErr_Format(PyExc_ValueError, - "%s(...): Cannot get evaluated data from given dependency graph / object pair", funcname); - return NULL; - } - } - else { - /* !use_deform */ - if (use_render) { - if (use_cage) { - PyErr_Format(PyExc_ValueError, - "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", funcname); - return NULL; - } - else { - *r_free_mesh = true; - return mesh_create_eval_no_deform_render(depsgraph, scene, ob, &data_masks); - } - } - else { - if (use_cage) { - PyErr_Format(PyExc_ValueError, - "%s(...): cage arg is unsupported when deform=False and dependency graph evaluation mode is not RENDER", funcname); - return NULL; - } - else { - *r_free_mesh = true; - return mesh_create_eval_no_deform(depsgraph, scene, ob, &data_masks); - } - } - } + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + /* we only need minimum mesh data for topology and vertex locations */ + CustomData_MeshMasks data_masks = CD_MASK_BAREMESH; + const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER; + *r_free_mesh = false; + + /* Write the display mesh into the dummy mesh */ + if (use_deform) { + if (use_render) { + if (use_cage) { + PyErr_Format( + PyExc_ValueError, + "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", + funcname); + return NULL; + } + else { + *r_free_mesh = true; + return mesh_create_eval_final_render(depsgraph, scene, ob, &data_masks); + } + } + else if (ob_eval != NULL) { + if (use_cage) { + return mesh_get_eval_deform(depsgraph, scene, ob_eval, &data_masks); + } + else { + return mesh_get_eval_final(depsgraph, scene, ob_eval, &data_masks); + } + } + else { + PyErr_Format(PyExc_ValueError, + "%s(...): Cannot get evaluated data from given dependency graph / object pair", + funcname); + return NULL; + } + } + else { + /* !use_deform */ + if (use_render) { + if (use_cage) { + PyErr_Format( + PyExc_ValueError, + "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER", + funcname); + return NULL; + } + else { + *r_free_mesh = true; + return mesh_create_eval_no_deform_render(depsgraph, scene, ob, &data_masks); + } + } + else { + if (use_cage) { + PyErr_Format(PyExc_ValueError, + "%s(...): cage arg is unsupported when deform=False and dependency graph " + "evaluation mode is not RENDER", + funcname); + return NULL; + } + else { + *r_free_mesh = true; + return mesh_create_eval_no_deform(depsgraph, scene, ob, &data_masks); + } + } + } } PyDoc_STRVAR(C_BVHTree_FromObject_doc, -".. classmethod:: FromObject(object, depsgraph, deform=True, render=False, cage=False, epsilon=0.0)\n" -"\n" -" BVH tree based on :class:`Object` data.\n" -"\n" -" :arg object: Object data.\n" -" :type object: :class:`Object`\n" -" :arg depsgraph: Depsgraph to use for evaluating the mesh.\n" -" :type depsgraph: :class:`Depsgraph`\n" -" :arg deform: Use mesh with deformations.\n" -" :type deform: bool\n" -" :arg cage: Use modifiers cage.\n" -" :type cage: bool\n" -PYBVH_FROM_GENERIC_EPSILON_DOC -); + ".. classmethod:: FromObject(object, depsgraph, deform=True, render=False, " + "cage=False, epsilon=0.0)\n" + "\n" + " BVH tree based on :class:`Object` data.\n" + "\n" + " :arg object: Object data.\n" + " :type object: :class:`Object`\n" + " :arg depsgraph: Depsgraph to use for evaluating the mesh.\n" + " :type depsgraph: :class:`Depsgraph`\n" + " :arg deform: Use mesh with deformations.\n" + " :type deform: bool\n" + " :arg cage: Use modifiers cage.\n" + " :type cage: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC); static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyObject *kwargs) { - /* note, options here match 'bpy_bmesh_from_object' */ - const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", NULL}; - - PyObject *py_ob, *py_depsgraph; - Object *ob; - struct Depsgraph *depsgraph; - struct Scene *scene; - Mesh *mesh; - bool use_deform = true; - bool use_cage = false; - bool free_mesh = false; - - const MLoopTri *lt; - const MLoop *mloop; - - float (*coords)[3] = NULL; - unsigned int (*tris)[3] = NULL; - unsigned int coords_len, tris_len; - float epsilon = 0.0f; - - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, (char *)"OO|$O&O&f:BVHTree.FromObject", (char **)keywords, - &py_ob, &py_depsgraph, - PyC_ParseBool, &use_deform, - PyC_ParseBool, &use_cage, - &epsilon) || - ((ob = PyC_RNA_AsPointer(py_ob, "Object")) == NULL) || - ((depsgraph = PyC_RNA_AsPointer(py_depsgraph, "Depsgraph")) == NULL)) - { - return NULL; - } - - scene = DEG_get_evaluated_scene(depsgraph); - mesh = bvh_get_mesh("BVHTree", depsgraph, scene, ob, use_deform, use_cage, &free_mesh); - - if (mesh == NULL) { - return NULL; - } - - /* Get data for tessellation */ - { - lt = BKE_mesh_runtime_looptri_ensure(mesh); - - tris_len = (unsigned int)BKE_mesh_runtime_looptri_len(mesh); - coords_len = (unsigned int)mesh->totvert; - - coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__); - tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__); - - MVert *mv = mesh->mvert; - for (int i = 0; i < mesh->totvert; i++, mv++) { - copy_v3_v3(coords[i], mv->co); - } - - mloop = mesh->mloop; - } - - { - BVHTree *tree; - unsigned int i; - - int *orig_index = NULL; - float (*orig_normal)[3] = NULL; - - tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT); - if (tree) { - orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__); - CustomData *pdata = &mesh->pdata; - orig_normal = CustomData_get_layer(pdata, CD_NORMAL); /* can be NULL */ - if (orig_normal) { - orig_normal = MEM_dupallocN(orig_normal); - } - - for (i = 0; i < tris_len; i++, lt++) { - float co[3][3]; - - tris[i][0] = mloop[lt->tri[0]].v; - tris[i][1] = mloop[lt->tri[1]].v; - tris[i][2] = mloop[lt->tri[2]].v; - - copy_v3_v3(co[0], coords[tris[i][0]]); - copy_v3_v3(co[1], coords[tris[i][1]]); - copy_v3_v3(co[2], coords[tris[i][2]]); - - BLI_bvhtree_insert(tree, (int)i, co[0], 3); - orig_index[i] = (int)lt->poly; - } - - BLI_bvhtree_balance(tree); - } - - if (free_mesh) { - BKE_id_free(NULL, mesh); - } - - return bvhtree_CreatePyObject( - tree, epsilon, - coords, coords_len, - tris, tris_len, - orig_index, orig_normal); - } + /* note, options here match 'bpy_bmesh_from_object' */ + const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", NULL}; + + PyObject *py_ob, *py_depsgraph; + Object *ob; + struct Depsgraph *depsgraph; + struct Scene *scene; + Mesh *mesh; + bool use_deform = true; + bool use_cage = false; + bool free_mesh = false; + + const MLoopTri *lt; + const MLoop *mloop; + + float(*coords)[3] = NULL; + unsigned int(*tris)[3] = NULL; + unsigned int coords_len, tris_len; + float epsilon = 0.0f; + + if (!PyArg_ParseTupleAndKeywords(args, + kwargs, + (char *)"OO|$O&O&f:BVHTree.FromObject", + (char **)keywords, + &py_ob, + &py_depsgraph, + PyC_ParseBool, + &use_deform, + PyC_ParseBool, + &use_cage, + &epsilon) || + ((ob = PyC_RNA_AsPointer(py_ob, "Object")) == NULL) || + ((depsgraph = PyC_RNA_AsPointer(py_depsgraph, "Depsgraph")) == NULL)) { + return NULL; + } + + scene = DEG_get_evaluated_scene(depsgraph); + mesh = bvh_get_mesh("BVHTree", depsgraph, scene, ob, use_deform, use_cage, &free_mesh); + + if (mesh == NULL) { + return NULL; + } + + /* Get data for tessellation */ + { + lt = BKE_mesh_runtime_looptri_ensure(mesh); + + tris_len = (unsigned int)BKE_mesh_runtime_looptri_len(mesh); + coords_len = (unsigned int)mesh->totvert; + + coords = MEM_mallocN(sizeof(*coords) * (size_t)coords_len, __func__); + tris = MEM_mallocN(sizeof(*tris) * (size_t)tris_len, __func__); + + MVert *mv = mesh->mvert; + for (int i = 0; i < mesh->totvert; i++, mv++) { + copy_v3_v3(coords[i], mv->co); + } + + mloop = mesh->mloop; + } + + { + BVHTree *tree; + unsigned int i; + + int *orig_index = NULL; + float(*orig_normal)[3] = NULL; + + tree = BLI_bvhtree_new((int)tris_len, epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT); + if (tree) { + orig_index = MEM_mallocN(sizeof(*orig_index) * (size_t)tris_len, __func__); + CustomData *pdata = &mesh->pdata; + orig_normal = CustomData_get_layer(pdata, CD_NORMAL); /* can be NULL */ + if (orig_normal) { + orig_normal = MEM_dupallocN(orig_normal); + } + + for (i = 0; i < tris_len; i++, lt++) { + float co[3][3]; + + tris[i][0] = mloop[lt->tri[0]].v; + tris[i][1] = mloop[lt->tri[1]].v; + tris[i][2] = mloop[lt->tri[2]].v; + + copy_v3_v3(co[0], coords[tris[i][0]]); + copy_v3_v3(co[1], coords[tris[i][1]]); + copy_v3_v3(co[2], coords[tris[i][2]]); + + BLI_bvhtree_insert(tree, (int)i, co[0], 3); + orig_index[i] = (int)lt->poly; + } + + BLI_bvhtree_balance(tree); + } + + if (free_mesh) { + BKE_id_free(NULL, mesh); + } + + return bvhtree_CreatePyObject( + tree, epsilon, coords, coords_len, tris, tris_len, orig_index, orig_normal); + } } -#endif /* MATH_STANDALONE */ +#endif /* MATH_STANDALONE */ /** \} */ - /* -------------------------------------------------------------------- */ /** \name Module & Type definition * \{ */ static PyMethodDef py_bvhtree_methods[] = { - {"ray_cast", (PyCFunction)py_bvhtree_ray_cast, METH_VARARGS, py_bvhtree_ray_cast_doc}, - {"find_nearest", (PyCFunction)py_bvhtree_find_nearest, METH_VARARGS, py_bvhtree_find_nearest_doc}, - {"find_nearest_range", (PyCFunction)py_bvhtree_find_nearest_range, METH_VARARGS, py_bvhtree_find_nearest_range_doc}, - {"overlap", (PyCFunction)py_bvhtree_overlap, METH_O, py_bvhtree_overlap_doc}, - - /* class methods */ - {"FromPolygons", (PyCFunction) C_BVHTree_FromPolygons, METH_VARARGS | METH_KEYWORDS | METH_CLASS, C_BVHTree_FromPolygons_doc}, + {"ray_cast", (PyCFunction)py_bvhtree_ray_cast, METH_VARARGS, py_bvhtree_ray_cast_doc}, + {"find_nearest", + (PyCFunction)py_bvhtree_find_nearest, + METH_VARARGS, + py_bvhtree_find_nearest_doc}, + {"find_nearest_range", + (PyCFunction)py_bvhtree_find_nearest_range, + METH_VARARGS, + py_bvhtree_find_nearest_range_doc}, + {"overlap", (PyCFunction)py_bvhtree_overlap, METH_O, py_bvhtree_overlap_doc}, + + /* class methods */ + {"FromPolygons", + (PyCFunction)C_BVHTree_FromPolygons, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, + C_BVHTree_FromPolygons_doc}, #ifndef MATH_STANDALONE - {"FromBMesh", (PyCFunction) C_BVHTree_FromBMesh, METH_VARARGS | METH_KEYWORDS | METH_CLASS, C_BVHTree_FromBMesh_doc}, - {"FromObject", (PyCFunction) C_BVHTree_FromObject, METH_VARARGS | METH_KEYWORDS | METH_CLASS, C_BVHTree_FromObject_doc}, + {"FromBMesh", + (PyCFunction)C_BVHTree_FromBMesh, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, + C_BVHTree_FromBMesh_doc}, + {"FromObject", + (PyCFunction)C_BVHTree_FromObject, + METH_VARARGS | METH_KEYWORDS | METH_CLASS, + C_BVHTree_FromObject_doc}, #endif - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; PyTypeObject PyBVHTree_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "BVHTree", /* tp_name */ - sizeof(PyBVHTree), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)py_bvhtree__tp_dealloc, /* tp_dealloc */ - NULL, /* tp_print */ - NULL, /* tp_getattr */ - NULL, /* tp_setattr */ - NULL, /* tp_compare */ - NULL, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - NULL, /* tp_hash */ - NULL, /* tp_call */ - NULL, /* tp_str */ - NULL, /* tp_getattro */ - NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - NULL, /* Documentation string */ - NULL, /* tp_traverse */ - NULL, /* tp_clear */ - NULL, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - NULL, /* tp_iter */ - NULL, /* tp_iternext */ - py_bvhtree_methods, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - NULL, /* tp_base */ - NULL, /* tp_dict */ - NULL, /* tp_descr_get */ - NULL, /* tp_descr_set */ - 0, /* tp_dictoffset */ - NULL, /* tp_init */ - (allocfunc)PyType_GenericAlloc, /* tp_alloc */ - (newfunc)PyType_GenericNew, /* tp_new */ - (freefunc)0, /* tp_free */ - NULL, /* tp_is_gc */ - NULL, /* tp_bases */ - NULL, /* tp_mro */ - NULL, /* tp_cache */ - NULL, /* tp_subclasses */ - NULL, /* tp_weaklist */ - (destructor)NULL, /* tp_del */ + PyVarObject_HEAD_INIT(NULL, 0) "BVHTree", /* tp_name */ + sizeof(PyBVHTree), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)py_bvhtree__tp_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + NULL, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + NULL, /* Documentation string */ + NULL, /* tp_traverse */ + NULL, /* tp_clear */ + NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + py_bvhtree_methods, /* tp_methods */ + NULL, /* tp_members */ + NULL, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + NULL, /* tp_init */ + (allocfunc)PyType_GenericAlloc, /* tp_alloc */ + (newfunc)PyType_GenericNew, /* tp_new */ + (freefunc)0, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + (destructor)NULL, /* tp_del */ }; /* -------------------------------------------------------------------- */ /* Module definition */ PyDoc_STRVAR(py_bvhtree_doc, -"BVH tree structures for proximity searches and ray casts on geometry." -); + "BVH tree structures for proximity searches and ray casts on geometry."); static struct PyModuleDef bvhtree_moduledef = { - PyModuleDef_HEAD_INIT, - "mathutils.bvhtree", /* m_name */ - py_bvhtree_doc, /* m_doc */ - 0, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "mathutils.bvhtree", /* m_name */ + py_bvhtree_doc, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; PyMODINIT_FUNC PyInit_mathutils_bvhtree(void) { - PyObject *m = PyModule_Create(&bvhtree_moduledef); + PyObject *m = PyModule_Create(&bvhtree_moduledef); - if (m == NULL) { - return NULL; - } + if (m == NULL) { + return NULL; + } - /* Register classes */ - if (PyType_Ready(&PyBVHTree_Type) < 0) { - return NULL; - } + /* Register classes */ + if (PyType_Ready(&PyBVHTree_Type) < 0) { + return NULL; + } - PyModule_AddObject(m, "BVHTree", (PyObject *)&PyBVHTree_Type); + PyModule_AddObject(m, "BVHTree", (PyObject *)&PyBVHTree_Type); - return m; + return m; } /** \} */ diff --git a/source/blender/python/mathutils/mathutils_bvhtree.h b/source/blender/python/mathutils/mathutils_bvhtree.h index 6971eb5ccd4..2991982f3a2 100644 --- a/source/blender/python/mathutils/mathutils_bvhtree.h +++ b/source/blender/python/mathutils/mathutils_bvhtree.h @@ -14,7 +14,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - /** \file * \ingroup mathutils */ @@ -26,7 +25,7 @@ PyMODINIT_FUNC PyInit_mathutils_bvhtree(void); extern PyTypeObject PyBVHTree_Type; -#define PyBVHTree_Check(v) PyObject_TypeCheck((v), &PyBVHTree_Type) -#define PyBVHTree_CheckExact(v) (Py_TYPE(v) == &PyBVHTree_Type) +#define PyBVHTree_Check(v) PyObject_TypeCheck((v), &PyBVHTree_Type) +#define PyBVHTree_CheckExact(v) (Py_TYPE(v) == &PyBVHTree_Type) #endif /* __MATHUTILS_BVHTREE_H__ */ diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 05ec57a004a..5fe3536d899 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #include #include "mathutils.h" @@ -41,1497 +40,1534 @@ #include "../generic/python_utildefines.h" /*-------------------------DOC STRINGS ---------------------------*/ -PyDoc_STRVAR(M_Geometry_doc, -"The Blender geometry module" -); +PyDoc_STRVAR(M_Geometry_doc, "The Blender geometry module"); /* ---------------------------------INTERSECTION FUNCTIONS-------------------- */ PyDoc_STRVAR(M_Geometry_intersect_ray_tri_doc, -".. function:: intersect_ray_tri(v1, v2, v3, ray, orig, clip=True)\n" -"\n" -" Returns the intersection between a ray and a triangle, if possible, returns None otherwise.\n" -"\n" -" :arg v1: Point1\n" -" :type v1: :class:`mathutils.Vector`\n" -" :arg v2: Point2\n" -" :type v2: :class:`mathutils.Vector`\n" -" :arg v3: Point3\n" -" :type v3: :class:`mathutils.Vector`\n" -" :arg ray: Direction of the projection\n" -" :type ray: :class:`mathutils.Vector`\n" -" :arg orig: Origin\n" -" :type orig: :class:`mathutils.Vector`\n" -" :arg clip: When False, don't restrict the intersection to the area of the triangle, use the infinite plane defined by the triangle.\n" -" :type clip: boolean\n" -" :return: The point of intersection or None if no intersection is found\n" -" :rtype: :class:`mathutils.Vector` or None\n" -); + ".. function:: intersect_ray_tri(v1, v2, v3, ray, orig, clip=True)\n" + "\n" + " Returns the intersection between a ray and a triangle, if possible, returns None " + "otherwise.\n" + "\n" + " :arg v1: Point1\n" + " :type v1: :class:`mathutils.Vector`\n" + " :arg v2: Point2\n" + " :type v2: :class:`mathutils.Vector`\n" + " :arg v3: Point3\n" + " :type v3: :class:`mathutils.Vector`\n" + " :arg ray: Direction of the projection\n" + " :type ray: :class:`mathutils.Vector`\n" + " :arg orig: Origin\n" + " :type orig: :class:`mathutils.Vector`\n" + " :arg clip: When False, don't restrict the intersection to the area of the " + "triangle, use the infinite plane defined by the triangle.\n" + " :type clip: boolean\n" + " :return: The point of intersection or None if no intersection is found\n" + " :rtype: :class:`mathutils.Vector` or None\n"); static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_ray_tri"; - PyObject *py_ray, *py_ray_off, *py_tri[3]; - float dir[3], orig[3], tri[3][3], e1[3], e2[3], pvec[3], tvec[3], qvec[3]; - float det, inv_det, u, v, t; - bool clip = true; - int i; - - if (!PyArg_ParseTuple( - args, "OOOOO|O&:intersect_ray_tri", - UNPACK3_EX(&, py_tri, ), - &py_ray, &py_ray_off, - PyC_ParseBool, &clip)) - { - return NULL; - } - - if (((mathutils_array_parse(dir, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_ray, error_prefix) != -1) && - (mathutils_array_parse(orig, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_ray_off, error_prefix) != -1)) == 0) - { - return NULL; - } - - for (i = 0; i < ARRAY_SIZE(tri); i++) { - if (mathutils_array_parse(tri[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_tri[i], error_prefix) == -1) { - return NULL; - } - } - - normalize_v3(dir); - - /* find vectors for two edges sharing v1 */ - sub_v3_v3v3(e1, tri[1], tri[0]); - sub_v3_v3v3(e2, tri[2], tri[0]); - - /* begin calculating determinant - also used to calculated U parameter */ - cross_v3_v3v3(pvec, dir, e2); - - /* if determinant is near zero, ray lies in plane of triangle */ - det = dot_v3v3(e1, pvec); - - if (det > -0.000001f && det < 0.000001f) { - Py_RETURN_NONE; - } - - inv_det = 1.0f / det; - - /* calculate distance from v1 to ray origin */ - sub_v3_v3v3(tvec, orig, tri[0]); - - /* calculate U parameter and test bounds */ - u = dot_v3v3(tvec, pvec) * inv_det; - if (clip && (u < 0.0f || u > 1.0f)) { - Py_RETURN_NONE; - } - - /* prepare to test the V parameter */ - cross_v3_v3v3(qvec, tvec, e1); - - /* calculate V parameter and test bounds */ - v = dot_v3v3(dir, qvec) * inv_det; - - if (clip && (v < 0.0f || u + v > 1.0f)) { - Py_RETURN_NONE; - } - - /* calculate t, ray intersects triangle */ - t = dot_v3v3(e2, qvec) * inv_det; - - /* ray hit behind */ - if (t < 0.0f) { - Py_RETURN_NONE; - } - - mul_v3_fl(dir, t); - add_v3_v3v3(pvec, orig, dir); - - return Vector_CreatePyObject(pvec, 3, NULL); + const char *error_prefix = "intersect_ray_tri"; + PyObject *py_ray, *py_ray_off, *py_tri[3]; + float dir[3], orig[3], tri[3][3], e1[3], e2[3], pvec[3], tvec[3], qvec[3]; + float det, inv_det, u, v, t; + bool clip = true; + int i; + + if (!PyArg_ParseTuple(args, + "OOOOO|O&:intersect_ray_tri", + UNPACK3_EX(&, py_tri, ), + &py_ray, + &py_ray_off, + PyC_ParseBool, + &clip)) { + return NULL; + } + + if (((mathutils_array_parse(dir, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_ray, error_prefix) != + -1) && + (mathutils_array_parse( + orig, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_ray_off, error_prefix) != -1)) == 0) { + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(tri); i++) { + if (mathutils_array_parse( + tri[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_tri[i], error_prefix) == -1) { + return NULL; + } + } + + normalize_v3(dir); + + /* find vectors for two edges sharing v1 */ + sub_v3_v3v3(e1, tri[1], tri[0]); + sub_v3_v3v3(e2, tri[2], tri[0]); + + /* begin calculating determinant - also used to calculated U parameter */ + cross_v3_v3v3(pvec, dir, e2); + + /* if determinant is near zero, ray lies in plane of triangle */ + det = dot_v3v3(e1, pvec); + + if (det > -0.000001f && det < 0.000001f) { + Py_RETURN_NONE; + } + + inv_det = 1.0f / det; + + /* calculate distance from v1 to ray origin */ + sub_v3_v3v3(tvec, orig, tri[0]); + + /* calculate U parameter and test bounds */ + u = dot_v3v3(tvec, pvec) * inv_det; + if (clip && (u < 0.0f || u > 1.0f)) { + Py_RETURN_NONE; + } + + /* prepare to test the V parameter */ + cross_v3_v3v3(qvec, tvec, e1); + + /* calculate V parameter and test bounds */ + v = dot_v3v3(dir, qvec) * inv_det; + + if (clip && (v < 0.0f || u + v > 1.0f)) { + Py_RETURN_NONE; + } + + /* calculate t, ray intersects triangle */ + t = dot_v3v3(e2, qvec) * inv_det; + + /* ray hit behind */ + if (t < 0.0f) { + Py_RETURN_NONE; + } + + mul_v3_fl(dir, t); + add_v3_v3v3(pvec, orig, dir); + + return Vector_CreatePyObject(pvec, 3, NULL); } /* Line-Line intersection using algorithm from mathworld.wolfram.com */ PyDoc_STRVAR(M_Geometry_intersect_line_line_doc, -".. function:: intersect_line_line(v1, v2, v3, v4)\n" -"\n" -" Returns a tuple with the points on each line respectively closest to the other.\n" -"\n" -" :arg v1: First point of the first line\n" -" :type v1: :class:`mathutils.Vector`\n" -" :arg v2: Second point of the first line\n" -" :type v2: :class:`mathutils.Vector`\n" -" :arg v3: First point of the second line\n" -" :type v3: :class:`mathutils.Vector`\n" -" :arg v4: Second point of the second line\n" -" :type v4: :class:`mathutils.Vector`\n" -" :rtype: tuple of :class:`mathutils.Vector`'s\n" -); + ".. function:: intersect_line_line(v1, v2, v3, v4)\n" + "\n" + " Returns a tuple with the points on each line respectively closest to the other.\n" + "\n" + " :arg v1: First point of the first line\n" + " :type v1: :class:`mathutils.Vector`\n" + " :arg v2: Second point of the first line\n" + " :type v2: :class:`mathutils.Vector`\n" + " :arg v3: First point of the second line\n" + " :type v3: :class:`mathutils.Vector`\n" + " :arg v4: Second point of the second line\n" + " :type v4: :class:`mathutils.Vector`\n" + " :rtype: tuple of :class:`mathutils.Vector`'s\n"); static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_line_line"; - PyObject *tuple; - PyObject *py_lines[4]; - float lines[4][3], i1[3], i2[3]; - int len; - int result; - - if (!PyArg_ParseTuple( - args, "OOOO:intersect_line_line", - UNPACK4_EX(&, py_lines, ))) - { - return NULL; - } - - if ((((len = mathutils_array_parse(lines[0], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[0], error_prefix)) != -1) && - (mathutils_array_parse(lines[1], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[1], error_prefix) != -1) && - (mathutils_array_parse(lines[2], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[2], error_prefix) != -1) && - (mathutils_array_parse(lines[3], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[3], error_prefix) != -1)) == 0) - { - return NULL; - } - - result = isect_line_line_v3(UNPACK4(lines), i1, i2); - /* The return-code isnt exposed, - * this way we can check know how close the lines are. */ - if (result == 1) { - closest_to_line_v3(i2, i1, lines[2], lines[3]); - } - - if (result == 0) { - /* collinear */ - Py_RETURN_NONE; - } - else { - tuple = PyTuple_New(2); - PyTuple_SET_ITEMS(tuple, - Vector_CreatePyObject(i1, len, NULL), - Vector_CreatePyObject(i2, len, NULL)); - return tuple; - } + const char *error_prefix = "intersect_line_line"; + PyObject *tuple; + PyObject *py_lines[4]; + float lines[4][3], i1[3], i2[3]; + int len; + int result; + + if (!PyArg_ParseTuple(args, "OOOO:intersect_line_line", UNPACK4_EX(&, py_lines, ))) { + return NULL; + } + + if ((((len = mathutils_array_parse( + lines[0], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[0], error_prefix)) != -1) && + (mathutils_array_parse( + lines[1], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[1], error_prefix) != + -1) && + (mathutils_array_parse( + lines[2], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[2], error_prefix) != + -1) && + (mathutils_array_parse( + lines[3], len, len | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_lines[3], error_prefix) != + -1)) == 0) { + return NULL; + } + + result = isect_line_line_v3(UNPACK4(lines), i1, i2); + /* The return-code isnt exposed, + * this way we can check know how close the lines are. */ + if (result == 1) { + closest_to_line_v3(i2, i1, lines[2], lines[3]); + } + + if (result == 0) { + /* collinear */ + Py_RETURN_NONE; + } + else { + tuple = PyTuple_New(2); + PyTuple_SET_ITEMS( + tuple, Vector_CreatePyObject(i1, len, NULL), Vector_CreatePyObject(i2, len, NULL)); + return tuple; + } } /* Line-Line intersection using algorithm from mathworld.wolfram.com */ -PyDoc_STRVAR(M_Geometry_intersect_sphere_sphere_2d_doc, -".. function:: intersect_sphere_sphere_2d(p_a, radius_a, p_b, radius_b)\n" -"\n" -" Returns 2 points on between intersecting circles.\n" -"\n" -" :arg p_a: Center of the first circle\n" -" :type p_a: :class:`mathutils.Vector`\n" -" :arg radius_a: Radius of the first circle\n" -" :type radius_a: float\n" -" :arg p_b: Center of the second circle\n" -" :type p_b: :class:`mathutils.Vector`\n" -" :arg radius_b: Radius of the second circle\n" -" :type radius_b: float\n" -" :rtype: tuple of :class:`mathutils.Vector`'s or None when there is no intersection\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_sphere_sphere_2d_doc, + ".. function:: intersect_sphere_sphere_2d(p_a, radius_a, p_b, radius_b)\n" + "\n" + " Returns 2 points on between intersecting circles.\n" + "\n" + " :arg p_a: Center of the first circle\n" + " :type p_a: :class:`mathutils.Vector`\n" + " :arg radius_a: Radius of the first circle\n" + " :type radius_a: float\n" + " :arg p_b: Center of the second circle\n" + " :type p_b: :class:`mathutils.Vector`\n" + " :arg radius_b: Radius of the second circle\n" + " :type radius_b: float\n" + " :rtype: tuple of :class:`mathutils.Vector`'s or None when there is no intersection\n"); static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_sphere_sphere_2d"; - PyObject *ret; - PyObject *py_v_a, *py_v_b; - float v_a[2], v_b[2]; - float rad_a, rad_b; - float v_ab[2]; - float dist; - - if (!PyArg_ParseTuple( - args, "OfOf:intersect_sphere_sphere_2d", - &py_v_a, &rad_a, - &py_v_b, &rad_b)) - { - return NULL; - } - - if (((mathutils_array_parse(v_a, 2, 2, py_v_a, error_prefix) != -1) && - (mathutils_array_parse(v_b, 2, 2, py_v_b, error_prefix) != -1)) == 0) - { - return NULL; - } - - ret = PyTuple_New(2); - - sub_v2_v2v2(v_ab, v_b, v_a); - dist = len_v2(v_ab); - - if (/* out of range */ - (dist > rad_a + rad_b) || - /* fully-contained in the other */ - (dist < fabsf(rad_a - rad_b)) || - /* co-incident */ - (dist < FLT_EPSILON)) - { - /* out of range */ - PyTuple_SET_ITEMS(ret, - Py_INCREF_RET(Py_None), - Py_INCREF_RET(Py_None)); - } - else { - const float dist_delta = ((rad_a * rad_a) - (rad_b * rad_b) + (dist * dist)) / (2.0f * dist); - const float h = powf(fabsf((rad_a * rad_a) - (dist_delta * dist_delta)), 0.5f); - float i_cent[2]; - float i1[2], i2[2]; - - i_cent[0] = v_a[0] + ((v_ab[0] * dist_delta) / dist); - i_cent[1] = v_a[1] + ((v_ab[1] * dist_delta) / dist); - - i1[0] = i_cent[0] + h * v_ab[1] / dist; - i1[1] = i_cent[1] - h * v_ab[0] / dist; - - i2[0] = i_cent[0] - h * v_ab[1] / dist; - i2[1] = i_cent[1] + h * v_ab[0] / dist; - - PyTuple_SET_ITEMS(ret, - Vector_CreatePyObject(i1, 2, NULL), - Vector_CreatePyObject(i2, 2, NULL)); - } - - return ret; + const char *error_prefix = "intersect_sphere_sphere_2d"; + PyObject *ret; + PyObject *py_v_a, *py_v_b; + float v_a[2], v_b[2]; + float rad_a, rad_b; + float v_ab[2]; + float dist; + + if (!PyArg_ParseTuple( + args, "OfOf:intersect_sphere_sphere_2d", &py_v_a, &rad_a, &py_v_b, &rad_b)) { + return NULL; + } + + if (((mathutils_array_parse(v_a, 2, 2, py_v_a, error_prefix) != -1) && + (mathutils_array_parse(v_b, 2, 2, py_v_b, error_prefix) != -1)) == 0) { + return NULL; + } + + ret = PyTuple_New(2); + + sub_v2_v2v2(v_ab, v_b, v_a); + dist = len_v2(v_ab); + + if (/* out of range */ + (dist > rad_a + rad_b) || + /* fully-contained in the other */ + (dist < fabsf(rad_a - rad_b)) || + /* co-incident */ + (dist < FLT_EPSILON)) { + /* out of range */ + PyTuple_SET_ITEMS(ret, Py_INCREF_RET(Py_None), Py_INCREF_RET(Py_None)); + } + else { + const float dist_delta = ((rad_a * rad_a) - (rad_b * rad_b) + (dist * dist)) / (2.0f * dist); + const float h = powf(fabsf((rad_a * rad_a) - (dist_delta * dist_delta)), 0.5f); + float i_cent[2]; + float i1[2], i2[2]; + + i_cent[0] = v_a[0] + ((v_ab[0] * dist_delta) / dist); + i_cent[1] = v_a[1] + ((v_ab[1] * dist_delta) / dist); + + i1[0] = i_cent[0] + h * v_ab[1] / dist; + i1[1] = i_cent[1] - h * v_ab[0] / dist; + + i2[0] = i_cent[0] - h * v_ab[1] / dist; + i2[1] = i_cent[1] + h * v_ab[0] / dist; + + PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(i1, 2, NULL), Vector_CreatePyObject(i2, 2, NULL)); + } + + return ret; } PyDoc_STRVAR(M_Geometry_normal_doc, -".. function:: normal(vectors)\n" -"\n" -" Returns the normal of a 3D polygon.\n" -"\n" -" :arg vectors: Vectors to calculate normals with\n" -" :type vectors: sequence of 3 or more 3d vector\n" -" :rtype: :class:`mathutils.Vector`\n" -); + ".. function:: normal(vectors)\n" + "\n" + " Returns the normal of a 3D polygon.\n" + "\n" + " :arg vectors: Vectors to calculate normals with\n" + " :type vectors: sequence of 3 or more 3d vector\n" + " :rtype: :class:`mathutils.Vector`\n"); static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject *args) { - float (*coords)[3]; - int coords_len; - float n[3]; - PyObject *ret = NULL; + float(*coords)[3]; + int coords_len; + float n[3]; + PyObject *ret = NULL; - /* use */ - if (PyTuple_GET_SIZE(args) == 1) { - args = PyTuple_GET_ITEM(args, 0); - } + /* use */ + if (PyTuple_GET_SIZE(args) == 1) { + args = PyTuple_GET_ITEM(args, 0); + } - if ((coords_len = mathutils_array_parse_alloc_v((float **)&coords, 3 | MU_ARRAY_SPILL, args, "normal")) == -1) { - return NULL; - } + if ((coords_len = mathutils_array_parse_alloc_v( + (float **)&coords, 3 | MU_ARRAY_SPILL, args, "normal")) == -1) { + return NULL; + } - if (coords_len < 3) { - PyErr_SetString(PyExc_ValueError, - "Expected 3 or more vectors"); - goto finally; - } + if (coords_len < 3) { + PyErr_SetString(PyExc_ValueError, "Expected 3 or more vectors"); + goto finally; + } - normal_poly_v3(n, (const float (*)[3])coords, coords_len); - ret = Vector_CreatePyObject(n, 3, NULL); + normal_poly_v3(n, (const float(*)[3])coords, coords_len); + ret = Vector_CreatePyObject(n, 3, NULL); finally: - PyMem_Free(coords); - return ret; + PyMem_Free(coords); + return ret; } /* --------------------------------- AREA FUNCTIONS-------------------- */ PyDoc_STRVAR(M_Geometry_area_tri_doc, -".. function:: area_tri(v1, v2, v3)\n" -"\n" -" Returns the area size of the 2D or 3D triangle defined.\n" -"\n" -" :arg v1: Point1\n" -" :type v1: :class:`mathutils.Vector`\n" -" :arg v2: Point2\n" -" :type v2: :class:`mathutils.Vector`\n" -" :arg v3: Point3\n" -" :type v3: :class:`mathutils.Vector`\n" -" :rtype: float\n" -); + ".. function:: area_tri(v1, v2, v3)\n" + "\n" + " Returns the area size of the 2D or 3D triangle defined.\n" + "\n" + " :arg v1: Point1\n" + " :type v1: :class:`mathutils.Vector`\n" + " :arg v2: Point2\n" + " :type v2: :class:`mathutils.Vector`\n" + " :arg v3: Point3\n" + " :type v3: :class:`mathutils.Vector`\n" + " :rtype: float\n"); static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "area_tri"; - PyObject *py_tri[3]; - float tri[3][3]; - int len; - - if (!PyArg_ParseTuple( - args, "OOO:area_tri", - UNPACK3_EX(&, py_tri, ))) - { - return NULL; - } - - if ((((len = mathutils_array_parse(tri[0], 2, 3, py_tri[0], error_prefix)) != -1) && - (mathutils_array_parse(tri[1], len, len, py_tri[1], error_prefix) != -1) && - (mathutils_array_parse(tri[2], len, len, py_tri[2], error_prefix) != -1)) == 0) - { - return NULL; - } - - return PyFloat_FromDouble((len == 3 ? area_tri_v3 : area_tri_v2)(UNPACK3(tri))); + const char *error_prefix = "area_tri"; + PyObject *py_tri[3]; + float tri[3][3]; + int len; + + if (!PyArg_ParseTuple(args, "OOO:area_tri", UNPACK3_EX(&, py_tri, ))) { + return NULL; + } + + if ((((len = mathutils_array_parse(tri[0], 2, 3, py_tri[0], error_prefix)) != -1) && + (mathutils_array_parse(tri[1], len, len, py_tri[1], error_prefix) != -1) && + (mathutils_array_parse(tri[2], len, len, py_tri[2], error_prefix) != -1)) == 0) { + return NULL; + } + + return PyFloat_FromDouble((len == 3 ? area_tri_v3 : area_tri_v2)(UNPACK3(tri))); } PyDoc_STRVAR(M_Geometry_volume_tetrahedron_doc, -".. function:: volume_tetrahedron(v1, v2, v3, v4)\n" -"\n" -" Return the volume formed by a tetrahedron (points can be in any order).\n" -"\n" -" :arg v1: Point1\n" -" :type v1: :class:`mathutils.Vector`\n" -" :arg v2: Point2\n" -" :type v2: :class:`mathutils.Vector`\n" -" :arg v3: Point3\n" -" :type v3: :class:`mathutils.Vector`\n" -" :arg v4: Point4\n" -" :type v4: :class:`mathutils.Vector`\n" -" :rtype: float\n" -); + ".. function:: volume_tetrahedron(v1, v2, v3, v4)\n" + "\n" + " Return the volume formed by a tetrahedron (points can be in any order).\n" + "\n" + " :arg v1: Point1\n" + " :type v1: :class:`mathutils.Vector`\n" + " :arg v2: Point2\n" + " :type v2: :class:`mathutils.Vector`\n" + " :arg v3: Point3\n" + " :type v3: :class:`mathutils.Vector`\n" + " :arg v4: Point4\n" + " :type v4: :class:`mathutils.Vector`\n" + " :rtype: float\n"); static PyObject *M_Geometry_volume_tetrahedron(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "volume_tetrahedron"; - PyObject *py_tet[4]; - float tet[4][3]; - int i; - - if (!PyArg_ParseTuple( - args, "OOOO:volume_tetrahedron", - UNPACK4_EX(&, py_tet, ))) - { - return NULL; - } - - for (i = 0; i < ARRAY_SIZE(tet); i++) { - if (mathutils_array_parse(tet[i], 3, 3 | MU_ARRAY_SPILL, py_tet[i], error_prefix) == -1) { - return NULL; - } - } - - return PyFloat_FromDouble(volume_tetrahedron_v3(UNPACK4(tet))); + const char *error_prefix = "volume_tetrahedron"; + PyObject *py_tet[4]; + float tet[4][3]; + int i; + + if (!PyArg_ParseTuple(args, "OOOO:volume_tetrahedron", UNPACK4_EX(&, py_tet, ))) { + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(tet); i++) { + if (mathutils_array_parse(tet[i], 3, 3 | MU_ARRAY_SPILL, py_tet[i], error_prefix) == -1) { + return NULL; + } + } + + return PyFloat_FromDouble(volume_tetrahedron_v3(UNPACK4(tet))); } -PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc, -".. function:: intersect_line_line_2d(lineA_p1, lineA_p2, lineB_p1, lineB_p2)\n" -"\n" -" Takes 2 segments (defined by 4 vectors) and returns a vector for their point of intersection or None.\n" -"\n" -" .. warning:: Despite its name, this function works on segments, and not on lines.\n" -"\n" -" :arg lineA_p1: First point of the first line\n" -" :type lineA_p1: :class:`mathutils.Vector`\n" -" :arg lineA_p2: Second point of the first line\n" -" :type lineA_p2: :class:`mathutils.Vector`\n" -" :arg lineB_p1: First point of the second line\n" -" :type lineB_p1: :class:`mathutils.Vector`\n" -" :arg lineB_p2: Second point of the second line\n" -" :type lineB_p2: :class:`mathutils.Vector`\n" -" :return: The point of intersection or None when not found\n" -" :rtype: :class:`mathutils.Vector` or None\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_line_line_2d_doc, + ".. function:: intersect_line_line_2d(lineA_p1, lineA_p2, lineB_p1, lineB_p2)\n" + "\n" + " Takes 2 segments (defined by 4 vectors) and returns a vector for their point of " + "intersection or None.\n" + "\n" + " .. warning:: Despite its name, this function works on segments, and not on lines.\n" + "\n" + " :arg lineA_p1: First point of the first line\n" + " :type lineA_p1: :class:`mathutils.Vector`\n" + " :arg lineA_p2: Second point of the first line\n" + " :type lineA_p2: :class:`mathutils.Vector`\n" + " :arg lineB_p1: First point of the second line\n" + " :type lineB_p1: :class:`mathutils.Vector`\n" + " :arg lineB_p2: Second point of the second line\n" + " :type lineB_p2: :class:`mathutils.Vector`\n" + " :return: The point of intersection or None when not found\n" + " :rtype: :class:`mathutils.Vector` or None\n"); static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_line_line_2d"; - PyObject *py_lines[4]; - float lines[4][2]; - float vi[2]; - int i; - - if (!PyArg_ParseTuple( - args, "OOOO:intersect_line_line_2d", - UNPACK4_EX(&, py_lines, ))) - { - return NULL; - } - - for (i = 0; i < ARRAY_SIZE(lines); i++) { - if (mathutils_array_parse(lines[i], 2, 2 | MU_ARRAY_SPILL, py_lines[i], error_prefix) == -1) { - return NULL; - } - } - - if (isect_seg_seg_v2_point(UNPACK4(lines), vi) == 1) { - return Vector_CreatePyObject(vi, 2, NULL); - } - else { - Py_RETURN_NONE; - } + const char *error_prefix = "intersect_line_line_2d"; + PyObject *py_lines[4]; + float lines[4][2]; + float vi[2]; + int i; + + if (!PyArg_ParseTuple(args, "OOOO:intersect_line_line_2d", UNPACK4_EX(&, py_lines, ))) { + return NULL; + } + + for (i = 0; i < ARRAY_SIZE(lines); i++) { + if (mathutils_array_parse(lines[i], 2, 2 | MU_ARRAY_SPILL, py_lines[i], error_prefix) == -1) { + return NULL; + } + } + + if (isect_seg_seg_v2_point(UNPACK4(lines), vi) == 1) { + return Vector_CreatePyObject(vi, 2, NULL); + } + else { + Py_RETURN_NONE; + } } - -PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc, -".. function:: intersect_line_plane(line_a, line_b, plane_co, plane_no, no_flip=False)\n" -"\n" -" Calculate the intersection between a line (as 2 vectors) and a plane.\n" -" Returns a vector for the intersection or None.\n" -"\n" -" :arg line_a: First point of the first line\n" -" :type line_a: :class:`mathutils.Vector`\n" -" :arg line_b: Second point of the first line\n" -" :type line_b: :class:`mathutils.Vector`\n" -" :arg plane_co: A point on the plane\n" -" :type plane_co: :class:`mathutils.Vector`\n" -" :arg plane_no: The direction the plane is facing\n" -" :type plane_no: :class:`mathutils.Vector`\n" -" :return: The point of intersection or None when not found\n" -" :rtype: :class:`mathutils.Vector` or None\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_line_plane_doc, + ".. function:: intersect_line_plane(line_a, line_b, plane_co, plane_no, no_flip=False)\n" + "\n" + " Calculate the intersection between a line (as 2 vectors) and a plane.\n" + " Returns a vector for the intersection or None.\n" + "\n" + " :arg line_a: First point of the first line\n" + " :type line_a: :class:`mathutils.Vector`\n" + " :arg line_b: Second point of the first line\n" + " :type line_b: :class:`mathutils.Vector`\n" + " :arg plane_co: A point on the plane\n" + " :type plane_co: :class:`mathutils.Vector`\n" + " :arg plane_no: The direction the plane is facing\n" + " :type plane_no: :class:`mathutils.Vector`\n" + " :return: The point of intersection or None when not found\n" + " :rtype: :class:`mathutils.Vector` or None\n"); static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_line_plane"; - PyObject *py_line_a, *py_line_b, *py_plane_co, *py_plane_no; - float line_a[3], line_b[3], plane_co[3], plane_no[3]; - float isect[3]; - bool no_flip = false; - - if (!PyArg_ParseTuple( - args, "OOOO|O&:intersect_line_plane", - &py_line_a, &py_line_b, &py_plane_co, &py_plane_no, - PyC_ParseBool, &no_flip)) - { - return NULL; - } - - if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) && - (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) && - (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) && - (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0) - { - return NULL; - } - - /* TODO: implements no_flip */ - if (isect_line_plane_v3(isect, line_a, line_b, plane_co, plane_no) == 1) { - return Vector_CreatePyObject(isect, 3, NULL); - } - else { - Py_RETURN_NONE; - } + const char *error_prefix = "intersect_line_plane"; + PyObject *py_line_a, *py_line_b, *py_plane_co, *py_plane_no; + float line_a[3], line_b[3], plane_co[3], plane_no[3]; + float isect[3]; + bool no_flip = false; + + if (!PyArg_ParseTuple(args, + "OOOO|O&:intersect_line_plane", + &py_line_a, + &py_line_b, + &py_plane_co, + &py_plane_no, + PyC_ParseBool, + &no_flip)) { + return NULL; + } + + if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) && + (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) && + (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) && + (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != + -1)) == 0) { + return NULL; + } + + /* TODO: implements no_flip */ + if (isect_line_plane_v3(isect, line_a, line_b, plane_co, plane_no) == 1) { + return Vector_CreatePyObject(isect, 3, NULL); + } + else { + Py_RETURN_NONE; + } } -PyDoc_STRVAR(M_Geometry_intersect_plane_plane_doc, -".. function:: intersect_plane_plane(plane_a_co, plane_a_no, plane_b_co, plane_b_no)\n" -"\n" -" Return the intersection between two planes\n" -"\n" -" :arg plane_a_co: Point on the first plane\n" -" :type plane_a_co: :class:`mathutils.Vector`\n" -" :arg plane_a_no: Normal of the first plane\n" -" :type plane_a_no: :class:`mathutils.Vector`\n" -" :arg plane_b_co: Point on the second plane\n" -" :type plane_b_co: :class:`mathutils.Vector`\n" -" :arg plane_b_no: Normal of the second plane\n" -" :type plane_b_no: :class:`mathutils.Vector`\n" -" :return: The line of the intersection represented as a point and a vector\n" -" :rtype: tuple pair of :class:`mathutils.Vector` or None if the intersection can't be calculated\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_plane_plane_doc, + ".. function:: intersect_plane_plane(plane_a_co, plane_a_no, plane_b_co, plane_b_no)\n" + "\n" + " Return the intersection between two planes\n" + "\n" + " :arg plane_a_co: Point on the first plane\n" + " :type plane_a_co: :class:`mathutils.Vector`\n" + " :arg plane_a_no: Normal of the first plane\n" + " :type plane_a_no: :class:`mathutils.Vector`\n" + " :arg plane_b_co: Point on the second plane\n" + " :type plane_b_co: :class:`mathutils.Vector`\n" + " :arg plane_b_no: Normal of the second plane\n" + " :type plane_b_no: :class:`mathutils.Vector`\n" + " :return: The line of the intersection represented as a point and a vector\n" + " :rtype: tuple pair of :class:`mathutils.Vector` or None if the intersection can't be " + "calculated\n"); static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_plane_plane"; - PyObject *ret, *ret_co, *ret_no; - PyObject *py_plane_a_co, *py_plane_a_no, *py_plane_b_co, *py_plane_b_no; - float plane_a_co[3], plane_a_no[3], plane_b_co[3], plane_b_no[3]; - float plane_a[4], plane_b[4]; - - float isect_co[3]; - float isect_no[3]; - - if (!PyArg_ParseTuple( - args, "OOOO:intersect_plane_plane", - &py_plane_a_co, &py_plane_a_no, &py_plane_b_co, &py_plane_b_no)) - { - return NULL; - } - - if (((mathutils_array_parse(plane_a_co, 3, 3 | MU_ARRAY_SPILL, py_plane_a_co, error_prefix) != -1) && - (mathutils_array_parse(plane_a_no, 3, 3 | MU_ARRAY_SPILL, py_plane_a_no, error_prefix) != -1) && - (mathutils_array_parse(plane_b_co, 3, 3 | MU_ARRAY_SPILL, py_plane_b_co, error_prefix) != -1) && - (mathutils_array_parse(plane_b_no, 3, 3 | MU_ARRAY_SPILL, py_plane_b_no, error_prefix) != -1)) == 0) - { - return NULL; - } - - plane_from_point_normal_v3(plane_a, plane_a_co, plane_a_no); - plane_from_point_normal_v3(plane_b, plane_b_co, plane_b_no); - - if (isect_plane_plane_v3( - plane_a, plane_b, - isect_co, isect_no)) - { - normalize_v3(isect_no); - - ret_co = Vector_CreatePyObject(isect_co, 3, NULL); - ret_no = Vector_CreatePyObject(isect_no, 3, NULL); - } - else { - ret_co = Py_INCREF_RET(Py_None); - ret_no = Py_INCREF_RET(Py_None); - } - - ret = PyTuple_New(2); - PyTuple_SET_ITEMS(ret, - ret_co, - ret_no); - return ret; + const char *error_prefix = "intersect_plane_plane"; + PyObject *ret, *ret_co, *ret_no; + PyObject *py_plane_a_co, *py_plane_a_no, *py_plane_b_co, *py_plane_b_no; + float plane_a_co[3], plane_a_no[3], plane_b_co[3], plane_b_no[3]; + float plane_a[4], plane_b[4]; + + float isect_co[3]; + float isect_no[3]; + + if (!PyArg_ParseTuple(args, + "OOOO:intersect_plane_plane", + &py_plane_a_co, + &py_plane_a_no, + &py_plane_b_co, + &py_plane_b_no)) { + return NULL; + } + + if (((mathutils_array_parse(plane_a_co, 3, 3 | MU_ARRAY_SPILL, py_plane_a_co, error_prefix) != + -1) && + (mathutils_array_parse(plane_a_no, 3, 3 | MU_ARRAY_SPILL, py_plane_a_no, error_prefix) != + -1) && + (mathutils_array_parse(plane_b_co, 3, 3 | MU_ARRAY_SPILL, py_plane_b_co, error_prefix) != + -1) && + (mathutils_array_parse(plane_b_no, 3, 3 | MU_ARRAY_SPILL, py_plane_b_no, error_prefix) != + -1)) == 0) { + return NULL; + } + + plane_from_point_normal_v3(plane_a, plane_a_co, plane_a_no); + plane_from_point_normal_v3(plane_b, plane_b_co, plane_b_no); + + if (isect_plane_plane_v3(plane_a, plane_b, isect_co, isect_no)) { + normalize_v3(isect_no); + + ret_co = Vector_CreatePyObject(isect_co, 3, NULL); + ret_no = Vector_CreatePyObject(isect_no, 3, NULL); + } + else { + ret_co = Py_INCREF_RET(Py_None); + ret_no = Py_INCREF_RET(Py_None); + } + + ret = PyTuple_New(2); + PyTuple_SET_ITEMS(ret, ret_co, ret_no); + return ret; } -PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc, -".. function:: intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)\n" -"\n" -" Takes a line (as 2 points) and a sphere (as a point and a radius) and\n" -" returns the intersection\n" -"\n" -" :arg line_a: First point of the line\n" -" :type line_a: :class:`mathutils.Vector`\n" -" :arg line_b: Second point of the line\n" -" :type line_b: :class:`mathutils.Vector`\n" -" :arg sphere_co: The center of the sphere\n" -" :type sphere_co: :class:`mathutils.Vector`\n" -" :arg sphere_radius: Radius of the sphere\n" -" :type sphere_radius: sphere_radius\n" -" :return: The intersection points as a pair of vectors or None when there is no intersection\n" -" :rtype: A tuple pair containing :class:`mathutils.Vector` or None\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_line_sphere_doc, + ".. function:: intersect_line_sphere(line_a, line_b, sphere_co, sphere_radius, clip=True)\n" + "\n" + " Takes a line (as 2 points) and a sphere (as a point and a radius) and\n" + " returns the intersection\n" + "\n" + " :arg line_a: First point of the line\n" + " :type line_a: :class:`mathutils.Vector`\n" + " :arg line_b: Second point of the line\n" + " :type line_b: :class:`mathutils.Vector`\n" + " :arg sphere_co: The center of the sphere\n" + " :type sphere_co: :class:`mathutils.Vector`\n" + " :arg sphere_radius: Radius of the sphere\n" + " :type sphere_radius: sphere_radius\n" + " :return: The intersection points as a pair of vectors or None when there is no " + "intersection\n" + " :rtype: A tuple pair containing :class:`mathutils.Vector` or None\n"); static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_line_sphere"; - PyObject *py_line_a, *py_line_b, *py_sphere_co; - float line_a[3], line_b[3], sphere_co[3]; - float sphere_radius; - bool clip = true; - - float isect_a[3]; - float isect_b[3]; - - if (!PyArg_ParseTuple( - args, "OOOf|O&:intersect_line_sphere", - &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius, - PyC_ParseBool, &clip)) - { - return NULL; - } - - if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) && - (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) && - (mathutils_array_parse(sphere_co, 3, 3 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0) - { - return NULL; - } - else { - bool use_a = true; - bool use_b = true; - float lambda; - - PyObject *ret = PyTuple_New(2); - - switch (isect_line_sphere_v3(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) { - case 1: - if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) { use_a = false; } - use_b = false; - break; - case 2: - if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) { use_a = false; } - if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) { use_b = false; } - break; - default: - use_a = false; - use_b = false; - break; - } - - PyTuple_SET_ITEMS(ret, - use_a ? Vector_CreatePyObject(isect_a, 3, NULL) : Py_INCREF_RET(Py_None), - use_b ? Vector_CreatePyObject(isect_b, 3, NULL) : Py_INCREF_RET(Py_None)); - - return ret; - } + const char *error_prefix = "intersect_line_sphere"; + PyObject *py_line_a, *py_line_b, *py_sphere_co; + float line_a[3], line_b[3], sphere_co[3]; + float sphere_radius; + bool clip = true; + + float isect_a[3]; + float isect_b[3]; + + if (!PyArg_ParseTuple(args, + "OOOf|O&:intersect_line_sphere", + &py_line_a, + &py_line_b, + &py_sphere_co, + &sphere_radius, + PyC_ParseBool, + &clip)) { + return NULL; + } + + if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) && + (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) && + (mathutils_array_parse(sphere_co, 3, 3 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != + -1)) == 0) { + return NULL; + } + else { + bool use_a = true; + bool use_b = true; + float lambda; + + PyObject *ret = PyTuple_New(2); + + switch (isect_line_sphere_v3(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) { + case 1: + if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && + (lambda <= 1.0f)))) { + use_a = false; + } + use_b = false; + break; + case 2: + if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && + (lambda <= 1.0f)))) { + use_a = false; + } + if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a, line_b)) >= 0.0f) && + (lambda <= 1.0f)))) { + use_b = false; + } + break; + default: + use_a = false; + use_b = false; + break; + } + + PyTuple_SET_ITEMS(ret, + use_a ? Vector_CreatePyObject(isect_a, 3, NULL) : Py_INCREF_RET(Py_None), + use_b ? Vector_CreatePyObject(isect_b, 3, NULL) : Py_INCREF_RET(Py_None)); + + return ret; + } } /* keep in sync with M_Geometry_intersect_line_sphere */ -PyDoc_STRVAR(M_Geometry_intersect_line_sphere_2d_doc, -".. function:: intersect_line_sphere_2d(line_a, line_b, sphere_co, sphere_radius, clip=True)\n" -"\n" -" Takes a line (as 2 points) and a sphere (as a point and a radius) and\n" -" returns the intersection\n" -"\n" -" :arg line_a: First point of the line\n" -" :type line_a: :class:`mathutils.Vector`\n" -" :arg line_b: Second point of the line\n" -" :type line_b: :class:`mathutils.Vector`\n" -" :arg sphere_co: The center of the sphere\n" -" :type sphere_co: :class:`mathutils.Vector`\n" -" :arg sphere_radius: Radius of the sphere\n" -" :type sphere_radius: sphere_radius\n" -" :return: The intersection points as a pair of vectors or None when there is no intersection\n" -" :rtype: A tuple pair containing :class:`mathutils.Vector` or None\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_line_sphere_2d_doc, + ".. function:: intersect_line_sphere_2d(line_a, line_b, sphere_co, sphere_radius, clip=True)\n" + "\n" + " Takes a line (as 2 points) and a sphere (as a point and a radius) and\n" + " returns the intersection\n" + "\n" + " :arg line_a: First point of the line\n" + " :type line_a: :class:`mathutils.Vector`\n" + " :arg line_b: Second point of the line\n" + " :type line_b: :class:`mathutils.Vector`\n" + " :arg sphere_co: The center of the sphere\n" + " :type sphere_co: :class:`mathutils.Vector`\n" + " :arg sphere_radius: Radius of the sphere\n" + " :type sphere_radius: sphere_radius\n" + " :return: The intersection points as a pair of vectors or None when there is no " + "intersection\n" + " :rtype: A tuple pair containing :class:`mathutils.Vector` or None\n"); static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_line_sphere_2d"; - PyObject *py_line_a, *py_line_b, *py_sphere_co; - float line_a[2], line_b[2], sphere_co[2]; - float sphere_radius; - bool clip = true; - - float isect_a[2]; - float isect_b[2]; - - if (!PyArg_ParseTuple( - args, "OOOf|O&:intersect_line_sphere_2d", - &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius, - PyC_ParseBool, &clip)) - { - return NULL; - } - - if (((mathutils_array_parse(line_a, 2, 2 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) && - (mathutils_array_parse(line_b, 2, 2 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) && - (mathutils_array_parse(sphere_co, 2, 2 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0) - { - return NULL; - } - else { - bool use_a = true; - bool use_b = true; - float lambda; - - PyObject *ret = PyTuple_New(2); - - switch (isect_line_sphere_v2(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) { - case 1: - if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) { use_a = false; } - use_b = false; - break; - case 2: - if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) { use_a = false; } - if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) { use_b = false; } - break; - default: - use_a = false; - use_b = false; - break; - } - - PyTuple_SET_ITEMS(ret, - use_a ? Vector_CreatePyObject(isect_a, 2, NULL) : Py_INCREF_RET(Py_None), - use_b ? Vector_CreatePyObject(isect_b, 2, NULL) : Py_INCREF_RET(Py_None)); - - return ret; - } + const char *error_prefix = "intersect_line_sphere_2d"; + PyObject *py_line_a, *py_line_b, *py_sphere_co; + float line_a[2], line_b[2], sphere_co[2]; + float sphere_radius; + bool clip = true; + + float isect_a[2]; + float isect_b[2]; + + if (!PyArg_ParseTuple(args, + "OOOf|O&:intersect_line_sphere_2d", + &py_line_a, + &py_line_b, + &py_sphere_co, + &sphere_radius, + PyC_ParseBool, + &clip)) { + return NULL; + } + + if (((mathutils_array_parse(line_a, 2, 2 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) && + (mathutils_array_parse(line_b, 2, 2 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) && + (mathutils_array_parse(sphere_co, 2, 2 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != + -1)) == 0) { + return NULL; + } + else { + bool use_a = true; + bool use_b = true; + float lambda; + + PyObject *ret = PyTuple_New(2); + + switch (isect_line_sphere_v2(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) { + case 1: + if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && + (lambda <= 1.0f)))) { + use_a = false; + } + use_b = false; + break; + case 2: + if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && + (lambda <= 1.0f)))) { + use_a = false; + } + if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a, line_b)) >= 0.0f) && + (lambda <= 1.0f)))) { + use_b = false; + } + break; + default: + use_a = false; + use_b = false; + break; + } + + PyTuple_SET_ITEMS(ret, + use_a ? Vector_CreatePyObject(isect_a, 2, NULL) : Py_INCREF_RET(Py_None), + use_b ? Vector_CreatePyObject(isect_b, 2, NULL) : Py_INCREF_RET(Py_None)); + + return ret; + } } -PyDoc_STRVAR(M_Geometry_intersect_point_line_doc, -".. function:: intersect_point_line(pt, line_p1, line_p2)\n" -"\n" -" Takes a point and a line and returns a tuple with the closest point on the line and its distance from the first point of the line as a percentage of the length of the line.\n" -"\n" -" :arg pt: Point\n" -" :type pt: :class:`mathutils.Vector`\n" -" :arg line_p1: First point of the line\n" -" :type line_p1: :class:`mathutils.Vector`\n" -" :arg line_p1: Second point of the line\n" -" :type line_p1: :class:`mathutils.Vector`\n" -" :rtype: (:class:`mathutils.Vector`, float)\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_point_line_doc, + ".. function:: intersect_point_line(pt, line_p1, line_p2)\n" + "\n" + " Takes a point and a line and returns a tuple with the closest point on the line and its " + "distance from the first point of the line as a percentage of the length of the line.\n" + "\n" + " :arg pt: Point\n" + " :type pt: :class:`mathutils.Vector`\n" + " :arg line_p1: First point of the line\n" + " :type line_p1: :class:`mathutils.Vector`\n" + " :arg line_p1: Second point of the line\n" + " :type line_p1: :class:`mathutils.Vector`\n" + " :rtype: (:class:`mathutils.Vector`, float)\n"); static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_point_line"; - PyObject *py_pt, *py_line_a, *py_line_b; - float pt[3], pt_out[3], line_a[3], line_b[3]; - float lambda; - PyObject *ret; - int size = 2; - - if (!PyArg_ParseTuple( - args, "OOO:intersect_point_line", - &py_pt, &py_line_a, &py_line_b)) - { - return NULL; - } - - /* accept 2d verts */ - if ((((size = mathutils_array_parse(pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix)) != -1) && - (mathutils_array_parse(line_a, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_a, error_prefix) != -1) && - (mathutils_array_parse(line_b, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_b, error_prefix) != -1)) == 0) - { - return NULL; - } - - /* do the calculation */ - lambda = closest_to_line_v3(pt_out, pt, line_a, line_b); - - ret = PyTuple_New(2); - PyTuple_SET_ITEMS(ret, - Vector_CreatePyObject(pt_out, size, NULL), - PyFloat_FromDouble(lambda)); - return ret; + const char *error_prefix = "intersect_point_line"; + PyObject *py_pt, *py_line_a, *py_line_b; + float pt[3], pt_out[3], line_a[3], line_b[3]; + float lambda; + PyObject *ret; + int size = 2; + + if (!PyArg_ParseTuple(args, "OOO:intersect_point_line", &py_pt, &py_line_a, &py_line_b)) { + return NULL; + } + + /* accept 2d verts */ + if ((((size = mathutils_array_parse( + pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix)) != -1) && + (mathutils_array_parse( + line_a, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_a, error_prefix) != -1) && + (mathutils_array_parse( + line_b, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_b, error_prefix) != -1)) == 0) { + return NULL; + } + + /* do the calculation */ + lambda = closest_to_line_v3(pt_out, pt, line_a, line_b); + + ret = PyTuple_New(2); + PyTuple_SET_ITEMS(ret, Vector_CreatePyObject(pt_out, size, NULL), PyFloat_FromDouble(lambda)); + return ret; } PyDoc_STRVAR(M_Geometry_intersect_point_tri_doc, -".. function:: intersect_point_tri(pt, tri_p1, tri_p2, tri_p3)\n" -"\n" -" Takes 4 vectors: one is the point and the next 3 define the triangle.\n" -"\n" -" :arg pt: Point\n" -" :type pt: :class:`mathutils.Vector`\n" -" :arg tri_p1: First point of the triangle\n" -" :type tri_p1: :class:`mathutils.Vector`\n" -" :arg tri_p2: Second point of the triangle\n" -" :type tri_p2: :class:`mathutils.Vector`\n" -" :arg tri_p3: Third point of the triangle\n" -" :type tri_p3: :class:`mathutils.Vector`\n" -" :return: Point on the triangles plane or None if its outside the triangle\n" -" :rtype: :class:`mathutils.Vector` or None\n" -); + ".. function:: intersect_point_tri(pt, tri_p1, tri_p2, tri_p3)\n" + "\n" + " Takes 4 vectors: one is the point and the next 3 define the triangle.\n" + "\n" + " :arg pt: Point\n" + " :type pt: :class:`mathutils.Vector`\n" + " :arg tri_p1: First point of the triangle\n" + " :type tri_p1: :class:`mathutils.Vector`\n" + " :arg tri_p2: Second point of the triangle\n" + " :type tri_p2: :class:`mathutils.Vector`\n" + " :arg tri_p3: Third point of the triangle\n" + " :type tri_p3: :class:`mathutils.Vector`\n" + " :return: Point on the triangles plane or None if its outside the triangle\n" + " :rtype: :class:`mathutils.Vector` or None\n"); static PyObject *M_Geometry_intersect_point_tri(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_point_tri"; - PyObject *py_pt, *py_tri[3]; - float pt[3], tri[3][3]; - float vi[3]; - int i; - - if (!PyArg_ParseTuple( - args, "OOOO:intersect_point_tri", - &py_pt, UNPACK3_EX(&, py_tri, ))) - { - return NULL; - } - - if (mathutils_array_parse(pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix) == -1) { - return NULL; - } - for (i = 0; i < ARRAY_SIZE(tri); i++) { - if (mathutils_array_parse(tri[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_tri[i], error_prefix) == -1) { - return NULL; - } - } - - if (isect_point_tri_v3(pt, UNPACK3(tri), vi)) { - return Vector_CreatePyObject(vi, 3, NULL); - } - else { - Py_RETURN_NONE; - } + const char *error_prefix = "intersect_point_tri"; + PyObject *py_pt, *py_tri[3]; + float pt[3], tri[3][3]; + float vi[3]; + int i; + + if (!PyArg_ParseTuple(args, "OOOO:intersect_point_tri", &py_pt, UNPACK3_EX(&, py_tri, ))) { + return NULL; + } + + if (mathutils_array_parse(pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix) == + -1) { + return NULL; + } + for (i = 0; i < ARRAY_SIZE(tri); i++) { + if (mathutils_array_parse( + tri[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_tri[i], error_prefix) == -1) { + return NULL; + } + } + + if (isect_point_tri_v3(pt, UNPACK3(tri), vi)) { + return Vector_CreatePyObject(vi, 3, NULL); + } + else { + Py_RETURN_NONE; + } } -PyDoc_STRVAR(M_Geometry_intersect_point_tri_2d_doc, -".. function:: intersect_point_tri_2d(pt, tri_p1, tri_p2, tri_p3)\n" -"\n" -" Takes 4 vectors (using only the x and y coordinates): one is the point and the next 3 define the triangle. Returns 1 if the point is within the triangle, otherwise 0.\n" -"\n" -" :arg pt: Point\n" -" :type pt: :class:`mathutils.Vector`\n" -" :arg tri_p1: First point of the triangle\n" -" :type tri_p1: :class:`mathutils.Vector`\n" -" :arg tri_p2: Second point of the triangle\n" -" :type tri_p2: :class:`mathutils.Vector`\n" -" :arg tri_p3: Third point of the triangle\n" -" :type tri_p3: :class:`mathutils.Vector`\n" -" :rtype: int\n" -); +PyDoc_STRVAR( + M_Geometry_intersect_point_tri_2d_doc, + ".. function:: intersect_point_tri_2d(pt, tri_p1, tri_p2, tri_p3)\n" + "\n" + " Takes 4 vectors (using only the x and y coordinates): one is the point and the next 3 " + "define the triangle. Returns 1 if the point is within the triangle, otherwise 0.\n" + "\n" + " :arg pt: Point\n" + " :type pt: :class:`mathutils.Vector`\n" + " :arg tri_p1: First point of the triangle\n" + " :type tri_p1: :class:`mathutils.Vector`\n" + " :arg tri_p2: Second point of the triangle\n" + " :type tri_p2: :class:`mathutils.Vector`\n" + " :arg tri_p3: Third point of the triangle\n" + " :type tri_p3: :class:`mathutils.Vector`\n" + " :rtype: int\n"); static PyObject *M_Geometry_intersect_point_tri_2d(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_point_tri_2d"; - PyObject *py_pt, *py_tri[3]; - float pt[2], tri[3][2]; - int i; - - if (!PyArg_ParseTuple( - args, "OOOO:intersect_point_tri_2d", - &py_pt, UNPACK3_EX(&, py_tri, ))) - { - return NULL; - } - - if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) { - return NULL; - } - for (i = 0; i < ARRAY_SIZE(tri); i++) { - if (mathutils_array_parse(tri[i], 2, 2 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) { - return NULL; - } - } - - return PyLong_FromLong(isect_point_tri_v2(pt, UNPACK3(tri))); + const char *error_prefix = "intersect_point_tri_2d"; + PyObject *py_pt, *py_tri[3]; + float pt[2], tri[3][2]; + int i; + + if (!PyArg_ParseTuple(args, "OOOO:intersect_point_tri_2d", &py_pt, UNPACK3_EX(&, py_tri, ))) { + return NULL; + } + + if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) { + return NULL; + } + for (i = 0; i < ARRAY_SIZE(tri); i++) { + if (mathutils_array_parse(tri[i], 2, 2 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) { + return NULL; + } + } + + return PyLong_FromLong(isect_point_tri_v2(pt, UNPACK3(tri))); } PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc, -".. function:: intersect_point_quad_2d(pt, quad_p1, quad_p2, quad_p3, quad_p4)\n" -"\n" -" Takes 5 vectors (using only the x and y coordinates): one is the point and the next 4 define the quad,\n" -" only the x and y are used from the vectors. Returns 1 if the point is within the quad, otherwise 0.\n" -" Works only with convex quads without singular edges.\n" -"\n" -" :arg pt: Point\n" -" :type pt: :class:`mathutils.Vector`\n" -" :arg quad_p1: First point of the quad\n" -" :type quad_p1: :class:`mathutils.Vector`\n" -" :arg quad_p2: Second point of the quad\n" -" :type quad_p2: :class:`mathutils.Vector`\n" -" :arg quad_p3: Third point of the quad\n" -" :type quad_p3: :class:`mathutils.Vector`\n" -" :arg quad_p4: Fourth point of the quad\n" -" :type quad_p4: :class:`mathutils.Vector`\n" -" :rtype: int\n" -); + ".. function:: intersect_point_quad_2d(pt, quad_p1, quad_p2, quad_p3, quad_p4)\n" + "\n" + " Takes 5 vectors (using only the x and y coordinates): one is the point and the " + "next 4 define the quad,\n" + " only the x and y are used from the vectors. Returns 1 if the point is within the " + "quad, otherwise 0.\n" + " Works only with convex quads without singular edges.\n" + "\n" + " :arg pt: Point\n" + " :type pt: :class:`mathutils.Vector`\n" + " :arg quad_p1: First point of the quad\n" + " :type quad_p1: :class:`mathutils.Vector`\n" + " :arg quad_p2: Second point of the quad\n" + " :type quad_p2: :class:`mathutils.Vector`\n" + " :arg quad_p3: Third point of the quad\n" + " :type quad_p3: :class:`mathutils.Vector`\n" + " :arg quad_p4: Fourth point of the quad\n" + " :type quad_p4: :class:`mathutils.Vector`\n" + " :rtype: int\n"); static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "intersect_point_quad_2d"; - PyObject *py_pt, *py_quad[4]; - float pt[2], quad[4][2]; - int i; - - if (!PyArg_ParseTuple( - args, "OOOOO:intersect_point_quad_2d", - &py_pt, UNPACK4_EX(&, py_quad, ))) - { - return NULL; - } - - if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) { - return NULL; - } - for (i = 0; i < ARRAY_SIZE(quad); i++) { - if (mathutils_array_parse(quad[i], 2, 2 | MU_ARRAY_SPILL, py_quad[i], error_prefix) == -1) { - return NULL; - } - } - - return PyLong_FromLong(isect_point_quad_v2(pt, UNPACK4(quad))); + const char *error_prefix = "intersect_point_quad_2d"; + PyObject *py_pt, *py_quad[4]; + float pt[2], quad[4][2]; + int i; + + if (!PyArg_ParseTuple(args, "OOOOO:intersect_point_quad_2d", &py_pt, UNPACK4_EX(&, py_quad, ))) { + return NULL; + } + + if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) { + return NULL; + } + for (i = 0; i < ARRAY_SIZE(quad); i++) { + if (mathutils_array_parse(quad[i], 2, 2 | MU_ARRAY_SPILL, py_quad[i], error_prefix) == -1) { + return NULL; + } + } + + return PyLong_FromLong(isect_point_quad_v2(pt, UNPACK4(quad))); } PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc, -".. function:: distance_point_to_plane(pt, plane_co, plane_no)\n" -"\n" -" Returns the signed distance between a point and a plane " -" (negative when below the normal).\n" -"\n" -" :arg pt: Point\n" -" :type pt: :class:`mathutils.Vector`\n" -" :arg plane_co: A point on the plane\n" -" :type plane_co: :class:`mathutils.Vector`\n" -" :arg plane_no: The direction the plane is facing\n" -" :type plane_no: :class:`mathutils.Vector`\n" -" :rtype: float\n" -); + ".. function:: distance_point_to_plane(pt, plane_co, plane_no)\n" + "\n" + " Returns the signed distance between a point and a plane " + " (negative when below the normal).\n" + "\n" + " :arg pt: Point\n" + " :type pt: :class:`mathutils.Vector`\n" + " :arg plane_co: A point on the plane\n" + " :type plane_co: :class:`mathutils.Vector`\n" + " :arg plane_no: The direction the plane is facing\n" + " :type plane_no: :class:`mathutils.Vector`\n" + " :rtype: float\n"); static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "distance_point_to_plane"; - PyObject *py_pt, *py_plane_co, *py_plane_no; - float pt[3], plane_co[3], plane_no[3]; - float plane[4]; - - if (!PyArg_ParseTuple( - args, "OOO:distance_point_to_plane", - &py_pt, &py_plane_co, &py_plane_no)) - { - return NULL; - } - - if (((mathutils_array_parse(pt, 3, 3 | MU_ARRAY_SPILL, py_pt, error_prefix) != -1) && - (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) && - (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0) - { - return NULL; - } - - plane_from_point_normal_v3(plane, plane_co, plane_no); - return PyFloat_FromDouble(dist_signed_to_plane_v3(pt, plane)); + const char *error_prefix = "distance_point_to_plane"; + PyObject *py_pt, *py_plane_co, *py_plane_no; + float pt[3], plane_co[3], plane_no[3]; + float plane[4]; + + if (!PyArg_ParseTuple(args, "OOO:distance_point_to_plane", &py_pt, &py_plane_co, &py_plane_no)) { + return NULL; + } + + if (((mathutils_array_parse(pt, 3, 3 | MU_ARRAY_SPILL, py_pt, error_prefix) != -1) && + (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) && + (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != + -1)) == 0) { + return NULL; + } + + plane_from_point_normal_v3(plane, plane_co, plane_no); + return PyFloat_FromDouble(dist_signed_to_plane_v3(pt, plane)); } -PyDoc_STRVAR(M_Geometry_barycentric_transform_doc, -".. function:: barycentric_transform(point, tri_a1, tri_a2, tri_a3, tri_b1, tri_b2, tri_b3)\n" -"\n" -" Return a transformed point, the transformation is defined by 2 triangles.\n" -"\n" -" :arg point: The point to transform.\n" -" :type point: :class:`mathutils.Vector`\n" -" :arg tri_a1: source triangle vertex.\n" -" :type tri_a1: :class:`mathutils.Vector`\n" -" :arg tri_a2: source triangle vertex.\n" -" :type tri_a2: :class:`mathutils.Vector`\n" -" :arg tri_a3: source triangle vertex.\n" -" :type tri_a3: :class:`mathutils.Vector`\n" -" :arg tri_b1: target triangle vertex.\n" -" :type tri_b1: :class:`mathutils.Vector`\n" -" :arg tri_b2: target triangle vertex.\n" -" :type tri_b2: :class:`mathutils.Vector`\n" -" :arg tri_b3: target triangle vertex.\n" -" :type tri_b3: :class:`mathutils.Vector`\n" -" :return: The transformed point\n" -" :rtype: :class:`mathutils.Vector`'s\n" -); +PyDoc_STRVAR( + M_Geometry_barycentric_transform_doc, + ".. function:: barycentric_transform(point, tri_a1, tri_a2, tri_a3, tri_b1, tri_b2, tri_b3)\n" + "\n" + " Return a transformed point, the transformation is defined by 2 triangles.\n" + "\n" + " :arg point: The point to transform.\n" + " :type point: :class:`mathutils.Vector`\n" + " :arg tri_a1: source triangle vertex.\n" + " :type tri_a1: :class:`mathutils.Vector`\n" + " :arg tri_a2: source triangle vertex.\n" + " :type tri_a2: :class:`mathutils.Vector`\n" + " :arg tri_a3: source triangle vertex.\n" + " :type tri_a3: :class:`mathutils.Vector`\n" + " :arg tri_b1: target triangle vertex.\n" + " :type tri_b1: :class:`mathutils.Vector`\n" + " :arg tri_b2: target triangle vertex.\n" + " :type tri_b2: :class:`mathutils.Vector`\n" + " :arg tri_b3: target triangle vertex.\n" + " :type tri_b3: :class:`mathutils.Vector`\n" + " :return: The transformed point\n" + " :rtype: :class:`mathutils.Vector`'s\n"); static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "barycentric_transform"; - PyObject *py_pt_src, *py_tri_src[3], *py_tri_dst[3]; - float pt_src[3], pt_dst[3], tri_src[3][3], tri_dst[3][3]; - int i; - - if (!PyArg_ParseTuple( - args, "OOOOOOO:barycentric_transform", - &py_pt_src, - UNPACK3_EX(&, py_tri_src, ), - UNPACK3_EX(&, py_tri_dst, ))) - { - return NULL; - } - - if (mathutils_array_parse(pt_src, 3, 3 | MU_ARRAY_SPILL, py_pt_src, error_prefix) == -1) { - return NULL; - } - for (i = 0; i < ARRAY_SIZE(tri_src); i++) { - if (((mathutils_array_parse(tri_src[i], 3, 3 | MU_ARRAY_SPILL, py_tri_src[i], error_prefix) != -1) && - (mathutils_array_parse(tri_dst[i], 3, 3 | MU_ARRAY_SPILL, py_tri_dst[i], error_prefix) != -1)) == 0) - { - return NULL; - } - } - - transform_point_by_tri_v3( - pt_dst, pt_src, - UNPACK3(tri_dst), - UNPACK3(tri_src)); - - return Vector_CreatePyObject(pt_dst, 3, NULL); + const char *error_prefix = "barycentric_transform"; + PyObject *py_pt_src, *py_tri_src[3], *py_tri_dst[3]; + float pt_src[3], pt_dst[3], tri_src[3][3], tri_dst[3][3]; + int i; + + if (!PyArg_ParseTuple(args, + "OOOOOOO:barycentric_transform", + &py_pt_src, + UNPACK3_EX(&, py_tri_src, ), + UNPACK3_EX(&, py_tri_dst, ))) { + return NULL; + } + + if (mathutils_array_parse(pt_src, 3, 3 | MU_ARRAY_SPILL, py_pt_src, error_prefix) == -1) { + return NULL; + } + for (i = 0; i < ARRAY_SIZE(tri_src); i++) { + if (((mathutils_array_parse(tri_src[i], 3, 3 | MU_ARRAY_SPILL, py_tri_src[i], error_prefix) != + -1) && + (mathutils_array_parse(tri_dst[i], 3, 3 | MU_ARRAY_SPILL, py_tri_dst[i], error_prefix) != + -1)) == 0) { + return NULL; + } + } + + transform_point_by_tri_v3(pt_dst, pt_src, UNPACK3(tri_dst), UNPACK3(tri_src)); + + return Vector_CreatePyObject(pt_dst, 3, NULL); } PyDoc_STRVAR(M_Geometry_points_in_planes_doc, -".. function:: points_in_planes(planes)\n" -"\n" -" Returns a list of points inside all planes given and a list of index values for the planes used.\n" -"\n" -" :arg planes: List of planes (4D vectors).\n" -" :type planes: list of :class:`mathutils.Vector`\n" -" :return: two lists, once containing the vertices inside the planes, another containing the plane indices used\n" -" :rtype: pair of lists\n" -); + ".. function:: points_in_planes(planes)\n" + "\n" + " Returns a list of points inside all planes given and a list of index values for " + "the planes used.\n" + "\n" + " :arg planes: List of planes (4D vectors).\n" + " :type planes: list of :class:`mathutils.Vector`\n" + " :return: two lists, once containing the vertices inside the planes, another " + "containing the plane indices used\n" + " :rtype: pair of lists\n"); /* note: this function could be optimized by some spatial structure */ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *args) { - PyObject *py_planes; - float (*planes)[4]; - unsigned int planes_len; - - if (!PyArg_ParseTuple( - args, "O:points_in_planes", - &py_planes)) - { - return NULL; - } - - if ((planes_len = mathutils_array_parse_alloc_v((float **)&planes, 4, py_planes, "points_in_planes")) == -1) { - return NULL; - } - else { - /* note, this could be refactored into plain C easy - py bits are noted */ - const float eps = 0.0001f; - const unsigned int len = (unsigned int)planes_len; - unsigned int i, j, k, l; - - float n1n2[3], n2n3[3], n3n1[3]; - float potentialVertex[3]; - char *planes_used = PyMem_Malloc(sizeof(char) * len); - - /* python */ - PyObject *py_verts = PyList_New(0); - PyObject *py_plane_index = PyList_New(0); - - memset(planes_used, 0, sizeof(char) * len); - - for (i = 0; i < len; i++) { - const float *N1 = planes[i]; - for (j = i + 1; j < len; j++) { - const float *N2 = planes[j]; - cross_v3_v3v3(n1n2, N1, N2); - if (len_squared_v3(n1n2) > eps) { - for (k = j + 1; k < len; k++) { - const float *N3 = planes[k]; - cross_v3_v3v3(n2n3, N2, N3); - if (len_squared_v3(n2n3) > eps) { - cross_v3_v3v3(n3n1, N3, N1); - if (len_squared_v3(n3n1) > eps) { - const float quotient = dot_v3v3(N1, n2n3); - if (fabsf(quotient) > eps) { - /* potentialVertex = (n2n3 * N1[3] + n3n1 * N2[3] + n1n2 * N3[3]) * (-1.0 / quotient); */ - const float quotient_ninv = -1.0f / quotient; - potentialVertex[0] = ((n2n3[0] * N1[3]) + (n3n1[0] * N2[3]) + (n1n2[0] * N3[3])) * quotient_ninv; - potentialVertex[1] = ((n2n3[1] * N1[3]) + (n3n1[1] * N2[3]) + (n1n2[1] * N3[3])) * quotient_ninv; - potentialVertex[2] = ((n2n3[2] * N1[3]) + (n3n1[2] * N2[3]) + (n1n2[2] * N3[3])) * quotient_ninv; - for (l = 0; l < len; l++) { - const float *NP = planes[l]; - if ((dot_v3v3(NP, potentialVertex) + NP[3]) > 0.000001f) { - break; - } - } - - if (l == len) { /* ok */ - /* python */ - PyList_APPEND(py_verts, Vector_CreatePyObject(potentialVertex, 3, NULL)); - planes_used[i] = planes_used[j] = planes_used[k] = true; - } - } - } - } - } - } - } - } - - PyMem_Free(planes); - - /* now make a list of used planes */ - for (i = 0; i < len; i++) { - if (planes_used[i]) { - PyList_APPEND(py_plane_index, PyLong_FromLong(i)); - } - } - PyMem_Free(planes_used); - - { - PyObject *ret = PyTuple_New(2); - PyTuple_SET_ITEMS(ret, - py_verts, - py_plane_index); - return ret; - } - } + PyObject *py_planes; + float(*planes)[4]; + unsigned int planes_len; + + if (!PyArg_ParseTuple(args, "O:points_in_planes", &py_planes)) { + return NULL; + } + + if ((planes_len = mathutils_array_parse_alloc_v( + (float **)&planes, 4, py_planes, "points_in_planes")) == -1) { + return NULL; + } + else { + /* note, this could be refactored into plain C easy - py bits are noted */ + const float eps = 0.0001f; + const unsigned int len = (unsigned int)planes_len; + unsigned int i, j, k, l; + + float n1n2[3], n2n3[3], n3n1[3]; + float potentialVertex[3]; + char *planes_used = PyMem_Malloc(sizeof(char) * len); + + /* python */ + PyObject *py_verts = PyList_New(0); + PyObject *py_plane_index = PyList_New(0); + + memset(planes_used, 0, sizeof(char) * len); + + for (i = 0; i < len; i++) { + const float *N1 = planes[i]; + for (j = i + 1; j < len; j++) { + const float *N2 = planes[j]; + cross_v3_v3v3(n1n2, N1, N2); + if (len_squared_v3(n1n2) > eps) { + for (k = j + 1; k < len; k++) { + const float *N3 = planes[k]; + cross_v3_v3v3(n2n3, N2, N3); + if (len_squared_v3(n2n3) > eps) { + cross_v3_v3v3(n3n1, N3, N1); + if (len_squared_v3(n3n1) > eps) { + const float quotient = dot_v3v3(N1, n2n3); + if (fabsf(quotient) > eps) { + /* potentialVertex = (n2n3 * N1[3] + n3n1 * N2[3] + n1n2 * N3[3]) * (-1.0 / quotient); */ + const float quotient_ninv = -1.0f / quotient; + potentialVertex[0] = ((n2n3[0] * N1[3]) + (n3n1[0] * N2[3]) + + (n1n2[0] * N3[3])) * + quotient_ninv; + potentialVertex[1] = ((n2n3[1] * N1[3]) + (n3n1[1] * N2[3]) + + (n1n2[1] * N3[3])) * + quotient_ninv; + potentialVertex[2] = ((n2n3[2] * N1[3]) + (n3n1[2] * N2[3]) + + (n1n2[2] * N3[3])) * + quotient_ninv; + for (l = 0; l < len; l++) { + const float *NP = planes[l]; + if ((dot_v3v3(NP, potentialVertex) + NP[3]) > 0.000001f) { + break; + } + } + + if (l == len) { /* ok */ + /* python */ + PyList_APPEND(py_verts, Vector_CreatePyObject(potentialVertex, 3, NULL)); + planes_used[i] = planes_used[j] = planes_used[k] = true; + } + } + } + } + } + } + } + } + + PyMem_Free(planes); + + /* now make a list of used planes */ + for (i = 0; i < len; i++) { + if (planes_used[i]) { + PyList_APPEND(py_plane_index, PyLong_FromLong(i)); + } + } + PyMem_Free(planes_used); + + { + PyObject *ret = PyTuple_New(2); + PyTuple_SET_ITEMS(ret, py_verts, py_plane_index); + return ret; + } + } } #ifndef MATH_STANDALONE PyDoc_STRVAR(M_Geometry_interpolate_bezier_doc, -".. function:: interpolate_bezier(knot1, handle1, handle2, knot2, resolution)\n" -"\n" -" Interpolate a bezier spline segment.\n" -"\n" -" :arg knot1: First bezier spline point.\n" -" :type knot1: :class:`mathutils.Vector`\n" -" :arg handle1: First bezier spline handle.\n" -" :type handle1: :class:`mathutils.Vector`\n" -" :arg handle2: Second bezier spline handle.\n" -" :type handle2: :class:`mathutils.Vector`\n" -" :arg knot2: Second bezier spline point.\n" -" :type knot2: :class:`mathutils.Vector`\n" -" :arg resolution: Number of points to return.\n" -" :type resolution: int\n" -" :return: The interpolated points\n" -" :rtype: list of :class:`mathutils.Vector`'s\n" -); + ".. function:: interpolate_bezier(knot1, handle1, handle2, knot2, resolution)\n" + "\n" + " Interpolate a bezier spline segment.\n" + "\n" + " :arg knot1: First bezier spline point.\n" + " :type knot1: :class:`mathutils.Vector`\n" + " :arg handle1: First bezier spline handle.\n" + " :type handle1: :class:`mathutils.Vector`\n" + " :arg handle2: Second bezier spline handle.\n" + " :type handle2: :class:`mathutils.Vector`\n" + " :arg knot2: Second bezier spline point.\n" + " :type knot2: :class:`mathutils.Vector`\n" + " :arg resolution: Number of points to return.\n" + " :type resolution: int\n" + " :return: The interpolated points\n" + " :rtype: list of :class:`mathutils.Vector`'s\n"); static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject *args) { - const char *error_prefix = "interpolate_bezier"; - PyObject *py_data[4]; - float data[4][4] = {{0.0f}}; - int resolu; - int dims = 0; - int i; - float *coord_array, *fp; - PyObject *list; - - if (!PyArg_ParseTuple( - args, "OOOOi:interpolate_bezier", - UNPACK4_EX(&, py_data, ), &resolu)) - { - return NULL; - } - - for (i = 0; i < 4; i++) { - int dims_tmp; - if ((dims_tmp = mathutils_array_parse(data[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_data[i], error_prefix)) == -1) { - return NULL; - } - dims = max_ii(dims, dims_tmp); - } - - if (resolu <= 1) { - PyErr_SetString(PyExc_ValueError, - "resolution must be 2 or over"); - return NULL; - } - - coord_array = MEM_callocN(dims * (resolu) * sizeof(float), error_prefix); - for (i = 0; i < dims; i++) { - BKE_curve_forward_diff_bezier(UNPACK4_EX(, data, [i]), coord_array + i, resolu - 1, sizeof(float) * dims); - } - - list = PyList_New(resolu); - fp = coord_array; - for (i = 0; i < resolu; i++, fp = fp + dims) { - PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, NULL)); - } - MEM_freeN(coord_array); - return list; + const char *error_prefix = "interpolate_bezier"; + PyObject *py_data[4]; + float data[4][4] = {{0.0f}}; + int resolu; + int dims = 0; + int i; + float *coord_array, *fp; + PyObject *list; + + if (!PyArg_ParseTuple(args, "OOOOi:interpolate_bezier", UNPACK4_EX(&, py_data, ), &resolu)) { + return NULL; + } + + for (i = 0; i < 4; i++) { + int dims_tmp; + if ((dims_tmp = mathutils_array_parse( + data[i], 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_data[i], error_prefix)) == -1) { + return NULL; + } + dims = max_ii(dims, dims_tmp); + } + + if (resolu <= 1) { + PyErr_SetString(PyExc_ValueError, "resolution must be 2 or over"); + return NULL; + } + + coord_array = MEM_callocN(dims * (resolu) * sizeof(float), error_prefix); + for (i = 0; i < dims; i++) { + BKE_curve_forward_diff_bezier( + UNPACK4_EX(, data, [i]), coord_array + i, resolu - 1, sizeof(float) * dims); + } + + list = PyList_New(resolu); + fp = coord_array; + for (i = 0; i < resolu; i++, fp = fp + dims) { + PyList_SET_ITEM(list, i, Vector_CreatePyObject(fp, dims, NULL)); + } + MEM_freeN(coord_array); + return list; } - PyDoc_STRVAR(M_Geometry_tessellate_polygon_doc, -".. function:: tessellate_polygon(veclist_list)\n" -"\n" -" Takes a list of polylines (each point a vector) and returns the point indices for a polyline filled with triangles.\n" -"\n" -" :arg veclist_list: list of polylines\n" -" :rtype: list\n" -); + ".. function:: tessellate_polygon(veclist_list)\n" + "\n" + " Takes a list of polylines (each point a vector) and returns the point indices " + "for a polyline filled with triangles.\n" + "\n" + " :arg veclist_list: list of polylines\n" + " :rtype: list\n"); /* PolyFill function, uses Blenders scanfill to fill multiple poly lines */ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject *polyLineSeq) { - PyObject *tri_list; /*return this list of tri's */ - PyObject *polyLine, *polyVec; - int i, len_polylines, len_polypoints, ls_error = 0; - - /* display listbase */ - ListBase dispbase = {NULL, NULL}; - DispList *dl; - float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */ - int index, *dl_face, totpoints = 0; - - if (!PySequence_Check(polyLineSeq)) { - PyErr_SetString(PyExc_TypeError, - "expected a sequence of poly lines"); - return NULL; - } - - len_polylines = PySequence_Size(polyLineSeq); - - for (i = 0; i < len_polylines; i++) { - polyLine = PySequence_GetItem(polyLineSeq, i); - if (!PySequence_Check(polyLine)) { - BKE_displist_free(&dispbase); - Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/ - PyErr_SetString(PyExc_TypeError, - "One or more of the polylines is not a sequence of mathutils.Vector's"); - return NULL; - } - - len_polypoints = PySequence_Size(polyLine); - if (len_polypoints > 0) { /* don't bother adding edges as polylines */ -#if 0 - if (EXPP_check_sequence_consistency(polyLine, &vector_Type) != 1) { - freedisplist(&dispbase); - Py_DECREF(polyLine); - PyErr_SetString(PyExc_TypeError, - "A point in one of the polylines is not a mathutils.Vector type"); - return NULL; - } -#endif - dl = MEM_callocN(sizeof(DispList), "poly disp"); - BLI_addtail(&dispbase, dl); - dl->type = DL_INDEX3; - dl->nr = len_polypoints; - dl->type = DL_POLY; - dl->parts = 1; /* no faces, 1 edge loop */ - dl->col = 0; /* no material */ - dl->verts = fp = MEM_callocN(sizeof(float) * 3 * len_polypoints, "dl verts"); - dl->index = MEM_callocN(sizeof(int) * 3 * len_polypoints, "dl index"); - - for (index = 0; index < len_polypoints; index++, fp += 3) { - polyVec = PySequence_GetItem(polyLine, index); - if (VectorObject_Check(polyVec)) { - - if (BaseMath_ReadCallback((VectorObject *)polyVec) == -1) { - ls_error = 1; - } - - fp[0] = ((VectorObject *)polyVec)->vec[0]; - fp[1] = ((VectorObject *)polyVec)->vec[1]; - if (((VectorObject *)polyVec)->size > 2) { - fp[2] = ((VectorObject *)polyVec)->vec[2]; - } - else { - /* if its a 2d vector then set the z to be zero */ - fp[2] = 0.0f; - } - } - else { - ls_error = 1; - } - - totpoints++; - Py_DECREF(polyVec); - } - } - Py_DECREF(polyLine); - } - - if (ls_error) { - BKE_displist_free(&dispbase); /* possible some dl was allocated */ - PyErr_SetString(PyExc_TypeError, - "A point in one of the polylines " - "is not a mathutils.Vector type"); - return NULL; - } - else if (totpoints) { - /* now make the list to return */ - /* TODO, add normal arg */ - BKE_displist_fill(&dispbase, &dispbase, NULL, false); - - /* The faces are stored in a new DisplayList - * that's added to the head of the listbase */ - dl = dispbase.first; - - tri_list = PyList_New(dl->parts); - if (!tri_list) { - BKE_displist_free(&dispbase); - PyErr_SetString(PyExc_RuntimeError, - "failed to make a new list"); - return NULL; - } - - index = 0; - dl_face = dl->index; - while (index < dl->parts) { - PyList_SET_ITEM(tri_list, index, PyC_Tuple_Pack_I32(dl_face[0], dl_face[1], dl_face[2])); - dl_face += 3; - index++; - } - BKE_displist_free(&dispbase); - } - else { - /* no points, do this so scripts don't barf */ - BKE_displist_free(&dispbase); /* possible some dl was allocated */ - tri_list = PyList_New(0); - } - - return tri_list; + PyObject *tri_list; /*return this list of tri's */ + PyObject *polyLine, *polyVec; + int i, len_polylines, len_polypoints, ls_error = 0; + + /* display listbase */ + ListBase dispbase = {NULL, NULL}; + DispList *dl; + float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */ + int index, *dl_face, totpoints = 0; + + if (!PySequence_Check(polyLineSeq)) { + PyErr_SetString(PyExc_TypeError, "expected a sequence of poly lines"); + return NULL; + } + + len_polylines = PySequence_Size(polyLineSeq); + + for (i = 0; i < len_polylines; i++) { + polyLine = PySequence_GetItem(polyLineSeq, i); + if (!PySequence_Check(polyLine)) { + BKE_displist_free(&dispbase); + Py_XDECREF(polyLine); /* may be null so use Py_XDECREF*/ + PyErr_SetString(PyExc_TypeError, + "One or more of the polylines is not a sequence of mathutils.Vector's"); + return NULL; + } + + len_polypoints = PySequence_Size(polyLine); + if (len_polypoints > 0) { /* don't bother adding edges as polylines */ +# if 0 + if (EXPP_check_sequence_consistency(polyLine, &vector_Type) != 1) { + freedisplist(&dispbase); + Py_DECREF(polyLine); + PyErr_SetString(PyExc_TypeError, + "A point in one of the polylines is not a mathutils.Vector type"); + return NULL; + } +# endif + dl = MEM_callocN(sizeof(DispList), "poly disp"); + BLI_addtail(&dispbase, dl); + dl->type = DL_INDEX3; + dl->nr = len_polypoints; + dl->type = DL_POLY; + dl->parts = 1; /* no faces, 1 edge loop */ + dl->col = 0; /* no material */ + dl->verts = fp = MEM_callocN(sizeof(float) * 3 * len_polypoints, "dl verts"); + dl->index = MEM_callocN(sizeof(int) * 3 * len_polypoints, "dl index"); + + for (index = 0; index < len_polypoints; index++, fp += 3) { + polyVec = PySequence_GetItem(polyLine, index); + if (VectorObject_Check(polyVec)) { + + if (BaseMath_ReadCallback((VectorObject *)polyVec) == -1) { + ls_error = 1; + } + + fp[0] = ((VectorObject *)polyVec)->vec[0]; + fp[1] = ((VectorObject *)polyVec)->vec[1]; + if (((VectorObject *)polyVec)->size > 2) { + fp[2] = ((VectorObject *)polyVec)->vec[2]; + } + else { + /* if its a 2d vector then set the z to be zero */ + fp[2] = 0.0f; + } + } + else { + ls_error = 1; + } + + totpoints++; + Py_DECREF(polyVec); + } + } + Py_DECREF(polyLine); + } + + if (ls_error) { + BKE_displist_free(&dispbase); /* possible some dl was allocated */ + PyErr_SetString(PyExc_TypeError, + "A point in one of the polylines " + "is not a mathutils.Vector type"); + return NULL; + } + else if (totpoints) { + /* now make the list to return */ + /* TODO, add normal arg */ + BKE_displist_fill(&dispbase, &dispbase, NULL, false); + + /* The faces are stored in a new DisplayList + * that's added to the head of the listbase */ + dl = dispbase.first; + + tri_list = PyList_New(dl->parts); + if (!tri_list) { + BKE_displist_free(&dispbase); + PyErr_SetString(PyExc_RuntimeError, "failed to make a new list"); + return NULL; + } + + index = 0; + dl_face = dl->index; + while (index < dl->parts) { + PyList_SET_ITEM(tri_list, index, PyC_Tuple_Pack_I32(dl_face[0], dl_face[1], dl_face[2])); + dl_face += 3; + index++; + } + BKE_displist_free(&dispbase); + } + else { + /* no points, do this so scripts don't barf */ + BKE_displist_free(&dispbase); /* possible some dl was allocated */ + tri_list = PyList_New(0); + } + + return tri_list; } - static int boxPack_FromPyObject(PyObject *value, BoxPack **boxarray) { - Py_ssize_t len, i; - PyObject *list_item, *item_1, *item_2; - BoxPack *box; - - - /* Error checking must already be done */ - if (!PyList_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "can only back a list of [x, y, w, h]"); - return -1; - } - - len = PyList_GET_SIZE(value); - - *boxarray = MEM_mallocN(len * sizeof(BoxPack), "BoxPack box"); - - - for (i = 0; i < len; i++) { - list_item = PyList_GET_ITEM(value, i); - if (!PyList_Check(list_item) || PyList_GET_SIZE(list_item) < 4) { - MEM_freeN(*boxarray); - PyErr_SetString(PyExc_TypeError, - "can only pack a list of [x, y, w, h]"); - return -1; - } - - box = (*boxarray) + i; - - item_1 = PyList_GET_ITEM(list_item, 2); - item_2 = PyList_GET_ITEM(list_item, 3); - - box->w = (float)PyFloat_AsDouble(item_1); - box->h = (float)PyFloat_AsDouble(item_2); - box->index = i; - - /* accounts for error case too and overwrites with own error */ - if (box->w < 0.0f || box->h < 0.0f) { - MEM_freeN(*boxarray); - PyErr_SetString(PyExc_TypeError, - "error parsing width and height values from list: " - "[x, y, w, h], not numbers or below zero"); - return -1; - } - - /* verts will be added later */ - } - return 0; + Py_ssize_t len, i; + PyObject *list_item, *item_1, *item_2; + BoxPack *box; + + /* Error checking must already be done */ + if (!PyList_Check(value)) { + PyErr_SetString(PyExc_TypeError, "can only back a list of [x, y, w, h]"); + return -1; + } + + len = PyList_GET_SIZE(value); + + *boxarray = MEM_mallocN(len * sizeof(BoxPack), "BoxPack box"); + + for (i = 0; i < len; i++) { + list_item = PyList_GET_ITEM(value, i); + if (!PyList_Check(list_item) || PyList_GET_SIZE(list_item) < 4) { + MEM_freeN(*boxarray); + PyErr_SetString(PyExc_TypeError, "can only pack a list of [x, y, w, h]"); + return -1; + } + + box = (*boxarray) + i; + + item_1 = PyList_GET_ITEM(list_item, 2); + item_2 = PyList_GET_ITEM(list_item, 3); + + box->w = (float)PyFloat_AsDouble(item_1); + box->h = (float)PyFloat_AsDouble(item_2); + box->index = i; + + /* accounts for error case too and overwrites with own error */ + if (box->w < 0.0f || box->h < 0.0f) { + MEM_freeN(*boxarray); + PyErr_SetString(PyExc_TypeError, + "error parsing width and height values from list: " + "[x, y, w, h], not numbers or below zero"); + return -1; + } + + /* verts will be added later */ + } + return 0; } static void boxPack_ToPyObject(PyObject *value, BoxPack **boxarray) { - Py_ssize_t len, i; - PyObject *list_item; - BoxPack *box; - - len = PyList_GET_SIZE(value); - - for (i = 0; i < len; i++) { - box = (*boxarray) + i; - list_item = PyList_GET_ITEM(value, box->index); - PyList_SET_ITEM(list_item, 0, PyFloat_FromDouble(box->x)); - PyList_SET_ITEM(list_item, 1, PyFloat_FromDouble(box->y)); - } - MEM_freeN(*boxarray); + Py_ssize_t len, i; + PyObject *list_item; + BoxPack *box; + + len = PyList_GET_SIZE(value); + + for (i = 0; i < len; i++) { + box = (*boxarray) + i; + list_item = PyList_GET_ITEM(value, box->index); + PyList_SET_ITEM(list_item, 0, PyFloat_FromDouble(box->x)); + PyList_SET_ITEM(list_item, 1, PyFloat_FromDouble(box->y)); + } + MEM_freeN(*boxarray); } PyDoc_STRVAR(M_Geometry_box_pack_2d_doc, -".. function:: box_pack_2d(boxes)\n" -"\n" -" Returns the normal of the 3D tri or quad.\n" -"\n" -" :arg boxes: list of boxes, each box is a list where the first 4 items are [x, y, width, height, ...] other items are ignored.\n" -" :type boxes: list\n" -" :return: the width and height of the packed bounding box\n" -" :rtype: tuple, pair of floats\n" -); + ".. function:: box_pack_2d(boxes)\n" + "\n" + " Returns the normal of the 3D tri or quad.\n" + "\n" + " :arg boxes: list of boxes, each box is a list where the first 4 items are [x, y, " + "width, height, ...] other items are ignored.\n" + " :type boxes: list\n" + " :return: the width and height of the packed bounding box\n" + " :rtype: tuple, pair of floats\n"); static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlist) { - float tot_width = 0.0f, tot_height = 0.0f; - Py_ssize_t len; - - PyObject *ret; - - if (!PyList_Check(boxlist)) { - PyErr_SetString(PyExc_TypeError, - "expected a list of boxes [[x, y, w, h], ... ]"); - return NULL; - } - - len = PyList_GET_SIZE(boxlist); - if (len) { - BoxPack *boxarray = NULL; - if (boxPack_FromPyObject(boxlist, &boxarray) == -1) { - return NULL; /* exception set */ - } - - /* Non Python function */ - BLI_box_pack_2d(boxarray, len, &tot_width, &tot_height); - - boxPack_ToPyObject(boxlist, &boxarray); - } - - ret = PyTuple_New(2); - PyTuple_SET_ITEMS(ret, - PyFloat_FromDouble(tot_width), - PyFloat_FromDouble(tot_height)); - return ret; + float tot_width = 0.0f, tot_height = 0.0f; + Py_ssize_t len; + + PyObject *ret; + + if (!PyList_Check(boxlist)) { + PyErr_SetString(PyExc_TypeError, "expected a list of boxes [[x, y, w, h], ... ]"); + return NULL; + } + + len = PyList_GET_SIZE(boxlist); + if (len) { + BoxPack *boxarray = NULL; + if (boxPack_FromPyObject(boxlist, &boxarray) == -1) { + return NULL; /* exception set */ + } + + /* Non Python function */ + BLI_box_pack_2d(boxarray, len, &tot_width, &tot_height); + + boxPack_ToPyObject(boxlist, &boxarray); + } + + ret = PyTuple_New(2); + PyTuple_SET_ITEMS(ret, PyFloat_FromDouble(tot_width), PyFloat_FromDouble(tot_height)); + return ret; } PyDoc_STRVAR(M_Geometry_box_fit_2d_doc, -".. function:: box_fit_2d(points)\n" -"\n" -" Returns an angle that best fits the points to an axis aligned rectangle\n" -"\n" -" :arg points: list of 2d points.\n" -" :type points: list\n" -" :return: angle\n" -" :rtype: float\n" -); + ".. function:: box_fit_2d(points)\n" + "\n" + " Returns an angle that best fits the points to an axis aligned rectangle\n" + "\n" + " :arg points: list of 2d points.\n" + " :type points: list\n" + " :return: angle\n" + " :rtype: float\n"); static PyObject *M_Geometry_box_fit_2d(PyObject *UNUSED(self), PyObject *pointlist) { - float (*points)[2]; - Py_ssize_t len; + float(*points)[2]; + Py_ssize_t len; - float angle = 0.0f; + float angle = 0.0f; - len = mathutils_array_parse_alloc_v(((float **)&points), 2, pointlist, "box_fit_2d"); - if (len == -1) { - return NULL; - } + len = mathutils_array_parse_alloc_v(((float **)&points), 2, pointlist, "box_fit_2d"); + if (len == -1) { + return NULL; + } - if (len) { - /* Non Python function */ - angle = BLI_convexhull_aabb_fit_points_2d(points, len); + if (len) { + /* Non Python function */ + angle = BLI_convexhull_aabb_fit_points_2d(points, len); - PyMem_Free(points); - } + PyMem_Free(points); + } - - return PyFloat_FromDouble(angle); + return PyFloat_FromDouble(angle); } PyDoc_STRVAR(M_Geometry_convex_hull_2d_doc, -".. function:: convex_hull_2d(points)\n" -"\n" -" Returns a list of indices into the list given\n" -"\n" -" :arg points: list of 2d points.\n" -" :type points: list\n" -" :return: a list of indices\n" -" :rtype: list of ints\n" -); + ".. function:: convex_hull_2d(points)\n" + "\n" + " Returns a list of indices into the list given\n" + "\n" + " :arg points: list of 2d points.\n" + " :type points: list\n" + " :return: a list of indices\n" + " :rtype: list of ints\n"); static PyObject *M_Geometry_convex_hull_2d(PyObject *UNUSED(self), PyObject *pointlist) { - float (*points)[2]; - Py_ssize_t len; - - PyObject *ret; + float(*points)[2]; + Py_ssize_t len; - len = mathutils_array_parse_alloc_v(((float **)&points), 2, pointlist, "convex_hull_2d"); - if (len == -1) { - return NULL; - } + PyObject *ret; - if (len) { - int *index_map; - Py_ssize_t len_ret, i; + len = mathutils_array_parse_alloc_v(((float **)&points), 2, pointlist, "convex_hull_2d"); + if (len == -1) { + return NULL; + } - index_map = MEM_mallocN(sizeof(*index_map) * len * 2, __func__); + if (len) { + int *index_map; + Py_ssize_t len_ret, i; - /* Non Python function */ - len_ret = BLI_convexhull_2d(points, len, index_map); + index_map = MEM_mallocN(sizeof(*index_map) * len * 2, __func__); - ret = PyList_New(len_ret); - for (i = 0; i < len_ret; i++) { - PyList_SET_ITEM(ret, i, PyLong_FromLong(index_map[i])); - } + /* Non Python function */ + len_ret = BLI_convexhull_2d(points, len, index_map); - MEM_freeN(index_map); + ret = PyList_New(len_ret); + for (i = 0; i < len_ret; i++) { + PyList_SET_ITEM(ret, i, PyLong_FromLong(index_map[i])); + } - PyMem_Free(points); - } - else { - ret = PyList_New(0); - } + MEM_freeN(index_map); + PyMem_Free(points); + } + else { + ret = PyList_New(0); + } - return ret; + return ret; } #endif /* MATH_STANDALONE */ - static PyMethodDef M_Geometry_methods[] = { - {"intersect_ray_tri", (PyCFunction) M_Geometry_intersect_ray_tri, METH_VARARGS, M_Geometry_intersect_ray_tri_doc}, - {"intersect_point_line", (PyCFunction) M_Geometry_intersect_point_line, METH_VARARGS, M_Geometry_intersect_point_line_doc}, - {"intersect_point_tri", (PyCFunction) M_Geometry_intersect_point_tri, METH_VARARGS, M_Geometry_intersect_point_tri_doc}, - {"intersect_point_tri_2d", (PyCFunction) M_Geometry_intersect_point_tri_2d, METH_VARARGS, M_Geometry_intersect_point_tri_2d_doc}, - {"intersect_point_quad_2d", (PyCFunction) M_Geometry_intersect_point_quad_2d, METH_VARARGS, M_Geometry_intersect_point_quad_2d_doc}, - {"intersect_line_line", (PyCFunction) M_Geometry_intersect_line_line, METH_VARARGS, M_Geometry_intersect_line_line_doc}, - {"intersect_line_line_2d", (PyCFunction) M_Geometry_intersect_line_line_2d, METH_VARARGS, M_Geometry_intersect_line_line_2d_doc}, - {"intersect_line_plane", (PyCFunction) M_Geometry_intersect_line_plane, METH_VARARGS, M_Geometry_intersect_line_plane_doc}, - {"intersect_plane_plane", (PyCFunction) M_Geometry_intersect_plane_plane, METH_VARARGS, M_Geometry_intersect_plane_plane_doc}, - {"intersect_line_sphere", (PyCFunction) M_Geometry_intersect_line_sphere, METH_VARARGS, M_Geometry_intersect_line_sphere_doc}, - {"intersect_line_sphere_2d", (PyCFunction) M_Geometry_intersect_line_sphere_2d, METH_VARARGS, M_Geometry_intersect_line_sphere_2d_doc}, - {"distance_point_to_plane", (PyCFunction) M_Geometry_distance_point_to_plane, METH_VARARGS, M_Geometry_distance_point_to_plane_doc}, - {"intersect_sphere_sphere_2d", (PyCFunction) M_Geometry_intersect_sphere_sphere_2d, METH_VARARGS, M_Geometry_intersect_sphere_sphere_2d_doc}, - {"area_tri", (PyCFunction) M_Geometry_area_tri, METH_VARARGS, M_Geometry_area_tri_doc}, - {"volume_tetrahedron", (PyCFunction) M_Geometry_volume_tetrahedron, METH_VARARGS, M_Geometry_volume_tetrahedron_doc}, - {"normal", (PyCFunction) M_Geometry_normal, METH_VARARGS, M_Geometry_normal_doc}, - {"barycentric_transform", (PyCFunction) M_Geometry_barycentric_transform, METH_VARARGS, M_Geometry_barycentric_transform_doc}, - {"points_in_planes", (PyCFunction) M_Geometry_points_in_planes, METH_VARARGS, M_Geometry_points_in_planes_doc}, + {"intersect_ray_tri", + (PyCFunction)M_Geometry_intersect_ray_tri, + METH_VARARGS, + M_Geometry_intersect_ray_tri_doc}, + {"intersect_point_line", + (PyCFunction)M_Geometry_intersect_point_line, + METH_VARARGS, + M_Geometry_intersect_point_line_doc}, + {"intersect_point_tri", + (PyCFunction)M_Geometry_intersect_point_tri, + METH_VARARGS, + M_Geometry_intersect_point_tri_doc}, + {"intersect_point_tri_2d", + (PyCFunction)M_Geometry_intersect_point_tri_2d, + METH_VARARGS, + M_Geometry_intersect_point_tri_2d_doc}, + {"intersect_point_quad_2d", + (PyCFunction)M_Geometry_intersect_point_quad_2d, + METH_VARARGS, + M_Geometry_intersect_point_quad_2d_doc}, + {"intersect_line_line", + (PyCFunction)M_Geometry_intersect_line_line, + METH_VARARGS, + M_Geometry_intersect_line_line_doc}, + {"intersect_line_line_2d", + (PyCFunction)M_Geometry_intersect_line_line_2d, + METH_VARARGS, + M_Geometry_intersect_line_line_2d_doc}, + {"intersect_line_plane", + (PyCFunction)M_Geometry_intersect_line_plane, + METH_VARARGS, + M_Geometry_intersect_line_plane_doc}, + {"intersect_plane_plane", + (PyCFunction)M_Geometry_intersect_plane_plane, + METH_VARARGS, + M_Geometry_intersect_plane_plane_doc}, + {"intersect_line_sphere", + (PyCFunction)M_Geometry_intersect_line_sphere, + METH_VARARGS, + M_Geometry_intersect_line_sphere_doc}, + {"intersect_line_sphere_2d", + (PyCFunction)M_Geometry_intersect_line_sphere_2d, + METH_VARARGS, + M_Geometry_intersect_line_sphere_2d_doc}, + {"distance_point_to_plane", + (PyCFunction)M_Geometry_distance_point_to_plane, + METH_VARARGS, + M_Geometry_distance_point_to_plane_doc}, + {"intersect_sphere_sphere_2d", + (PyCFunction)M_Geometry_intersect_sphere_sphere_2d, + METH_VARARGS, + M_Geometry_intersect_sphere_sphere_2d_doc}, + {"area_tri", (PyCFunction)M_Geometry_area_tri, METH_VARARGS, M_Geometry_area_tri_doc}, + {"volume_tetrahedron", + (PyCFunction)M_Geometry_volume_tetrahedron, + METH_VARARGS, + M_Geometry_volume_tetrahedron_doc}, + {"normal", (PyCFunction)M_Geometry_normal, METH_VARARGS, M_Geometry_normal_doc}, + {"barycentric_transform", + (PyCFunction)M_Geometry_barycentric_transform, + METH_VARARGS, + M_Geometry_barycentric_transform_doc}, + {"points_in_planes", + (PyCFunction)M_Geometry_points_in_planes, + METH_VARARGS, + M_Geometry_points_in_planes_doc}, #ifndef MATH_STANDALONE - {"interpolate_bezier", (PyCFunction) M_Geometry_interpolate_bezier, METH_VARARGS, M_Geometry_interpolate_bezier_doc}, - {"tessellate_polygon", (PyCFunction) M_Geometry_tessellate_polygon, METH_O, M_Geometry_tessellate_polygon_doc}, - {"convex_hull_2d", (PyCFunction) M_Geometry_convex_hull_2d, METH_O, M_Geometry_convex_hull_2d_doc}, - {"box_fit_2d", (PyCFunction) M_Geometry_box_fit_2d, METH_O, M_Geometry_box_fit_2d_doc}, - {"box_pack_2d", (PyCFunction) M_Geometry_box_pack_2d, METH_O, M_Geometry_box_pack_2d_doc}, + {"interpolate_bezier", + (PyCFunction)M_Geometry_interpolate_bezier, + METH_VARARGS, + M_Geometry_interpolate_bezier_doc}, + {"tessellate_polygon", + (PyCFunction)M_Geometry_tessellate_polygon, + METH_O, + M_Geometry_tessellate_polygon_doc}, + {"convex_hull_2d", + (PyCFunction)M_Geometry_convex_hull_2d, + METH_O, + M_Geometry_convex_hull_2d_doc}, + {"box_fit_2d", (PyCFunction)M_Geometry_box_fit_2d, METH_O, M_Geometry_box_fit_2d_doc}, + {"box_pack_2d", (PyCFunction)M_Geometry_box_pack_2d, METH_O, M_Geometry_box_pack_2d_doc}, #endif - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef M_Geometry_module_def = { - PyModuleDef_HEAD_INIT, - "mathutils.geometry", /* m_name */ - M_Geometry_doc, /* m_doc */ - 0, /* m_size */ - M_Geometry_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "mathutils.geometry", /* m_name */ + M_Geometry_doc, /* m_doc */ + 0, /* m_size */ + M_Geometry_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; /*----------------------------MODULE INIT-------------------------*/ PyMODINIT_FUNC PyInit_mathutils_geometry(void) { - PyObject *submodule = PyModule_Create(&M_Geometry_module_def); - return submodule; + PyObject *submodule = PyModule_Create(&M_Geometry_module_def); + return submodule; } diff --git a/source/blender/python/mathutils/mathutils_interpolate.c b/source/blender/python/mathutils/mathutils_interpolate.c index 792f8b1f065..6abb66899d5 100644 --- a/source/blender/python/mathutils/mathutils_interpolate.c +++ b/source/blender/python/mathutils/mathutils_interpolate.c @@ -18,7 +18,6 @@ * \ingroup pymathutils */ - #include #include "mathutils.h" @@ -32,105 +31,100 @@ #endif /*-------------------------DOC STRINGS ---------------------------*/ -PyDoc_STRVAR(M_Interpolate_doc, -"The Blender interpolate module" -); +PyDoc_STRVAR(M_Interpolate_doc, "The Blender interpolate module"); /* ---------------------------------WEIGHT CALCULATION ----------------------- */ #ifndef MATH_STANDALONE PyDoc_STRVAR(M_Interpolate_poly_3d_calc_doc, -".. function:: poly_3d_calc(veclist, pt)\n" -"\n" -" Calculate barycentric weights for a point on a polygon.\n" -"\n" -" :arg veclist: list of vectors\n" -" :arg pt: point" -" :rtype: list of per-vector weights\n" -); + ".. function:: poly_3d_calc(veclist, pt)\n" + "\n" + " Calculate barycentric weights for a point on a polygon.\n" + "\n" + " :arg veclist: list of vectors\n" + " :arg pt: point" + " :rtype: list of per-vector weights\n"); static PyObject *M_Interpolate_poly_3d_calc(PyObject *UNUSED(self), PyObject *args) { - float fp[3]; - float (*vecs)[3]; - Py_ssize_t len; - - PyObject *point, *veclist, *ret; - int i; - - if (!PyArg_ParseTuple( - args, "OO!:poly_3d_calc", - &veclist, - &vector_Type, &point)) - { - return NULL; - } - - if (BaseMath_ReadCallback((VectorObject *)point) == -1) { - return NULL; - } - - fp[0] = ((VectorObject *)point)->vec[0]; - fp[1] = ((VectorObject *)point)->vec[1]; - if (((VectorObject *)point)->size > 2) { - fp[2] = ((VectorObject *)point)->vec[2]; - } - else { - /* if its a 2d vector then set the z to be zero */ - fp[2] = 0.0f; - } - - len = mathutils_array_parse_alloc_v(((float **)&vecs), 3, veclist, __func__); - if (len == -1) { - return NULL; - } - - if (len) { - float *weights = MEM_mallocN(sizeof(float) * len, __func__); - - interp_weights_poly_v3(weights, vecs, len, fp); - - ret = PyList_New(len); - for (i = 0; i < len; i++) { - PyList_SET_ITEM(ret, i, PyFloat_FromDouble(weights[i])); - } - - MEM_freeN(weights); - - PyMem_Free(vecs); - } - else { - ret = PyList_New(0); - } - - return ret; + float fp[3]; + float(*vecs)[3]; + Py_ssize_t len; + + PyObject *point, *veclist, *ret; + int i; + + if (!PyArg_ParseTuple(args, "OO!:poly_3d_calc", &veclist, &vector_Type, &point)) { + return NULL; + } + + if (BaseMath_ReadCallback((VectorObject *)point) == -1) { + return NULL; + } + + fp[0] = ((VectorObject *)point)->vec[0]; + fp[1] = ((VectorObject *)point)->vec[1]; + if (((VectorObject *)point)->size > 2) { + fp[2] = ((VectorObject *)point)->vec[2]; + } + else { + /* if its a 2d vector then set the z to be zero */ + fp[2] = 0.0f; + } + + len = mathutils_array_parse_alloc_v(((float **)&vecs), 3, veclist, __func__); + if (len == -1) { + return NULL; + } + + if (len) { + float *weights = MEM_mallocN(sizeof(float) * len, __func__); + + interp_weights_poly_v3(weights, vecs, len, fp); + + ret = PyList_New(len); + for (i = 0; i < len; i++) { + PyList_SET_ITEM(ret, i, PyFloat_FromDouble(weights[i])); + } + + MEM_freeN(weights); + + PyMem_Free(vecs); + } + else { + ret = PyList_New(0); + } + + return ret; } #endif /* MATH_STANDALONE */ - static PyMethodDef M_Interpolate_methods[] = { #ifndef MATH_STANDALONE - {"poly_3d_calc", (PyCFunction) M_Interpolate_poly_3d_calc, METH_VARARGS, M_Interpolate_poly_3d_calc_doc}, + {"poly_3d_calc", + (PyCFunction)M_Interpolate_poly_3d_calc, + METH_VARARGS, + M_Interpolate_poly_3d_calc_doc}, #endif - {NULL, NULL, 0, NULL}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef M_Interpolate_module_def = { - PyModuleDef_HEAD_INIT, - "mathutils.interpolate", /* m_name */ - M_Interpolate_doc, /* m_doc */ - 0, /* m_size */ - M_Interpolate_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "mathutils.interpolate", /* m_name */ + M_Interpolate_doc, /* m_doc */ + 0, /* m_size */ + M_Interpolate_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; /*----------------------------MODULE INIT-------------------------*/ PyMODINIT_FUNC PyInit_mathutils_interpolate(void) { - PyObject *submodule = PyModule_Create(&M_Interpolate_module_def); - return submodule; + PyObject *submodule = PyModule_Create(&M_Interpolate_module_def); + return submodule; } diff --git a/source/blender/python/mathutils/mathutils_kdtree.c b/source/blender/python/mathutils/mathutils_kdtree.c index b1cda85f6ea..b8a7f4d8708 100644 --- a/source/blender/python/mathutils/mathutils_kdtree.c +++ b/source/blender/python/mathutils/mathutils_kdtree.c @@ -32,61 +32,58 @@ #include "../generic/python_utildefines.h" #include "mathutils.h" -#include "mathutils_kdtree.h" /* own include */ +#include "mathutils_kdtree.h" /* own include */ #include "BLI_strict_flags.h" typedef struct { - PyObject_HEAD - KDTree_3d *obj; - unsigned int maxsize; - unsigned int count; - unsigned int count_balance; /* size when we last balanced */ + PyObject_HEAD KDTree_3d *obj; + unsigned int maxsize; + unsigned int count; + unsigned int count_balance; /* size when we last balanced */ } PyKDTree; - /* -------------------------------------------------------------------- */ /* Utility helper functions */ static void kdtree_nearest_to_py_tuple(const KDTreeNearest_3d *nearest, PyObject *py_retval) { - BLI_assert(nearest->index >= 0); - BLI_assert(PyTuple_GET_SIZE(py_retval) == 3); + BLI_assert(nearest->index >= 0); + BLI_assert(PyTuple_GET_SIZE(py_retval) == 3); - PyTuple_SET_ITEMS(py_retval, - Vector_CreatePyObject((float *)nearest->co, 3, NULL), - PyLong_FromLong(nearest->index), - PyFloat_FromDouble(nearest->dist)); + PyTuple_SET_ITEMS(py_retval, + Vector_CreatePyObject((float *)nearest->co, 3, NULL), + PyLong_FromLong(nearest->index), + PyFloat_FromDouble(nearest->dist)); } static PyObject *kdtree_nearest_to_py(const KDTreeNearest_3d *nearest) { - PyObject *py_retval; + PyObject *py_retval; - py_retval = PyTuple_New(3); + py_retval = PyTuple_New(3); - kdtree_nearest_to_py_tuple(nearest, py_retval); + kdtree_nearest_to_py_tuple(nearest, py_retval); - return py_retval; + return py_retval; } static PyObject *kdtree_nearest_to_py_and_check(const KDTreeNearest_3d *nearest) { - PyObject *py_retval; + PyObject *py_retval; - py_retval = PyTuple_New(3); + py_retval = PyTuple_New(3); - if (nearest->index != -1) { - kdtree_nearest_to_py_tuple(nearest, py_retval); - } - else { - PyC_Tuple_Fill(py_retval, Py_None); - } + if (nearest->index != -1) { + kdtree_nearest_to_py_tuple(nearest, py_retval); + } + else { + PyC_Tuple_Fill(py_retval, Py_None); + } - return py_retval; + return py_retval; } - /* -------------------------------------------------------------------- */ /* KDTree */ @@ -95,395 +92,376 @@ static PyObject *kdtree_nearest_to_py_and_check(const KDTreeNearest_3d *nearest) static int PyKDTree__tp_init(PyKDTree *self, PyObject *args, PyObject *kwargs) { - unsigned int maxsize; - const char *keywords[] = {"size", NULL}; - - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, "I:KDTree", (char **)keywords, - &maxsize)) - { - return -1; - } - - if (UINT_IS_NEG(maxsize)) { - PyErr_SetString(PyExc_ValueError, "negative 'size' given"); - return -1; - } - - self->obj = BLI_kdtree_3d_new(maxsize); - self->maxsize = maxsize; - self->count = 0; - self->count_balance = 0; - - return 0; + unsigned int maxsize; + const char *keywords[] = {"size", NULL}; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "I:KDTree", (char **)keywords, &maxsize)) { + return -1; + } + + if (UINT_IS_NEG(maxsize)) { + PyErr_SetString(PyExc_ValueError, "negative 'size' given"); + return -1; + } + + self->obj = BLI_kdtree_3d_new(maxsize); + self->maxsize = maxsize; + self->count = 0; + self->count_balance = 0; + + return 0; } static void PyKDTree__tp_dealloc(PyKDTree *self) { - BLI_kdtree_3d_free(self->obj); - Py_TYPE(self)->tp_free((PyObject *)self); + BLI_kdtree_3d_free(self->obj); + Py_TYPE(self)->tp_free((PyObject *)self); } PyDoc_STRVAR(py_kdtree_insert_doc, -".. method:: insert(co, index)\n" -"\n" -" Insert a point into the KDTree.\n" -"\n" -" :arg co: Point 3d position.\n" -" :type co: float triplet\n" -" :arg index: The index of the point.\n" -" :type index: int\n" -); + ".. method:: insert(co, index)\n" + "\n" + " Insert a point into the KDTree.\n" + "\n" + " :arg co: Point 3d position.\n" + " :type co: float triplet\n" + " :arg index: The index of the point.\n" + " :type index: int\n"); static PyObject *py_kdtree_insert(PyKDTree *self, PyObject *args, PyObject *kwargs) { - PyObject *py_co; - float co[3]; - int index; - const char *keywords[] = {"co", "index", NULL}; - - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, (char *) "Oi:insert", (char **)keywords, - &py_co, &index)) - { - return NULL; - } - - if (mathutils_array_parse(co, 3, 3, py_co, "insert: invalid 'co' arg") == -1) { - return NULL; - } - - if (index < 0) { - PyErr_SetString(PyExc_ValueError, "negative index given"); - return NULL; - } - - if (self->count >= self->maxsize) { - PyErr_SetString(PyExc_RuntimeError, "Trying to insert more items than KDTree has room for"); - return NULL; - } - - BLI_kdtree_3d_insert(self->obj, index, co); - self->count++; - - Py_RETURN_NONE; + PyObject *py_co; + float co[3]; + int index; + const char *keywords[] = {"co", "index", NULL}; + + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, (char *)"Oi:insert", (char **)keywords, &py_co, &index)) { + return NULL; + } + + if (mathutils_array_parse(co, 3, 3, py_co, "insert: invalid 'co' arg") == -1) { + return NULL; + } + + if (index < 0) { + PyErr_SetString(PyExc_ValueError, "negative index given"); + return NULL; + } + + if (self->count >= self->maxsize) { + PyErr_SetString(PyExc_RuntimeError, "Trying to insert more items than KDTree has room for"); + return NULL; + } + + BLI_kdtree_3d_insert(self->obj, index, co); + self->count++; + + Py_RETURN_NONE; } PyDoc_STRVAR(py_kdtree_balance_doc, -".. method:: balance()\n" -"\n" -" Balance the tree.\n" -"\n" -".. note::\n" -"\n" -" This builds the entire tree, avoid calling after each insertion.\n" -); + ".. method:: balance()\n" + "\n" + " Balance the tree.\n" + "\n" + ".. note::\n" + "\n" + " This builds the entire tree, avoid calling after each insertion.\n"); static PyObject *py_kdtree_balance(PyKDTree *self) { - BLI_kdtree_3d_balance(self->obj); - self->count_balance = self->count; - Py_RETURN_NONE; + BLI_kdtree_3d_balance(self->obj); + self->count_balance = self->count; + Py_RETURN_NONE; } struct PyKDTree_NearestData { - PyObject *py_filter; - bool is_error; + PyObject *py_filter; + bool is_error; }; static int py_find_nearest_cb(void *user_data, int index, const float co[3], float dist_sq) { - UNUSED_VARS(co, dist_sq); - - struct PyKDTree_NearestData *data = user_data; - - PyObject *py_args = PyTuple_New(1); - PyTuple_SET_ITEM(py_args, 0, PyLong_FromLong(index)); - PyObject *result = PyObject_CallObject(data->py_filter, py_args); - Py_DECREF(py_args); - - if (result) { - bool use_node; - int ok = PyC_ParseBool(result, &use_node); - Py_DECREF(result); - if (ok) { - return (int)use_node; - } - } - - data->is_error = true; - return -1; + UNUSED_VARS(co, dist_sq); + + struct PyKDTree_NearestData *data = user_data; + + PyObject *py_args = PyTuple_New(1); + PyTuple_SET_ITEM(py_args, 0, PyLong_FromLong(index)); + PyObject *result = PyObject_CallObject(data->py_filter, py_args); + Py_DECREF(py_args); + + if (result) { + bool use_node; + int ok = PyC_ParseBool(result, &use_node); + Py_DECREF(result); + if (ok) { + return (int)use_node; + } + } + + data->is_error = true; + return -1; } PyDoc_STRVAR(py_kdtree_find_doc, -".. method:: find(co, filter=None)\n" -"\n" -" Find nearest point to ``co``.\n" -"\n" -" :arg co: 3d coordinates.\n" -" :type co: float triplet\n" -" :arg filter: function which takes an index and returns True for indices to include in the search.\n" -" :type filter: callable\n" -" :return: Returns (:class:`Vector`, index, distance).\n" -" :rtype: :class:`tuple`\n" -); + ".. method:: find(co, filter=None)\n" + "\n" + " Find nearest point to ``co``.\n" + "\n" + " :arg co: 3d coordinates.\n" + " :type co: float triplet\n" + " :arg filter: function which takes an index and returns True for indices to " + "include in the search.\n" + " :type filter: callable\n" + " :return: Returns (:class:`Vector`, index, distance).\n" + " :rtype: :class:`tuple`\n"); static PyObject *py_kdtree_find(PyKDTree *self, PyObject *args, PyObject *kwargs) { - PyObject *py_co, *py_filter = NULL; - float co[3]; - KDTreeNearest_3d nearest; - const char *keywords[] = {"co", "filter", NULL}; - - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, (char *) "O|O:find", (char **)keywords, - &py_co, &py_filter)) - { - return NULL; - } - - if (mathutils_array_parse(co, 3, 3, py_co, "find: invalid 'co' arg") == -1) { - return NULL; - } - - if (self->count != self->count_balance) { - PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find()"); - return NULL; - } - - nearest.index = -1; - - if (py_filter == NULL) { - BLI_kdtree_3d_find_nearest(self->obj, co, &nearest); - } - else { - struct PyKDTree_NearestData data = {0}; - - data.py_filter = py_filter; - data.is_error = false; - - BLI_kdtree_3d_find_nearest_cb( - self->obj, co, - py_find_nearest_cb, &data, - &nearest); - - if (data.is_error) { - return NULL; - } - } - - return kdtree_nearest_to_py_and_check(&nearest); + PyObject *py_co, *py_filter = NULL; + float co[3]; + KDTreeNearest_3d nearest; + const char *keywords[] = {"co", "filter", NULL}; + + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, (char *)"O|O:find", (char **)keywords, &py_co, &py_filter)) { + return NULL; + } + + if (mathutils_array_parse(co, 3, 3, py_co, "find: invalid 'co' arg") == -1) { + return NULL; + } + + if (self->count != self->count_balance) { + PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find()"); + return NULL; + } + + nearest.index = -1; + + if (py_filter == NULL) { + BLI_kdtree_3d_find_nearest(self->obj, co, &nearest); + } + else { + struct PyKDTree_NearestData data = {0}; + + data.py_filter = py_filter; + data.is_error = false; + + BLI_kdtree_3d_find_nearest_cb(self->obj, co, py_find_nearest_cb, &data, &nearest); + + if (data.is_error) { + return NULL; + } + } + + return kdtree_nearest_to_py_and_check(&nearest); } PyDoc_STRVAR(py_kdtree_find_n_doc, -".. method:: find_n(co, n)\n" -"\n" -" Find nearest ``n`` points to ``co``.\n" -"\n" -" :arg co: 3d coordinates.\n" -" :type co: float triplet\n" -" :arg n: Number of points to find.\n" -" :type n: int\n" -" :return: Returns a list of tuples (:class:`Vector`, index, distance).\n" -" :rtype: :class:`list`\n" -); + ".. method:: find_n(co, n)\n" + "\n" + " Find nearest ``n`` points to ``co``.\n" + "\n" + " :arg co: 3d coordinates.\n" + " :type co: float triplet\n" + " :arg n: Number of points to find.\n" + " :type n: int\n" + " :return: Returns a list of tuples (:class:`Vector`, index, distance).\n" + " :rtype: :class:`list`\n"); static PyObject *py_kdtree_find_n(PyKDTree *self, PyObject *args, PyObject *kwargs) { - PyObject *py_list; - PyObject *py_co; - float co[3]; - KDTreeNearest_3d *nearest; - unsigned int n; - int i, found; - const char *keywords[] = {"co", "n", NULL}; + PyObject *py_list; + PyObject *py_co; + float co[3]; + KDTreeNearest_3d *nearest; + unsigned int n; + int i, found; + const char *keywords[] = {"co", "n", NULL}; - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, (char *) "OI:find_n", (char **)keywords, - &py_co, &n)) - { - return NULL; - } + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, (char *)"OI:find_n", (char **)keywords, &py_co, &n)) { + return NULL; + } - if (mathutils_array_parse(co, 3, 3, py_co, "find_n: invalid 'co' arg") == -1) { - return NULL; - } + if (mathutils_array_parse(co, 3, 3, py_co, "find_n: invalid 'co' arg") == -1) { + return NULL; + } - if (UINT_IS_NEG(n)) { - PyErr_SetString(PyExc_RuntimeError, "negative 'n' given"); - return NULL; - } + if (UINT_IS_NEG(n)) { + PyErr_SetString(PyExc_RuntimeError, "negative 'n' given"); + return NULL; + } - if (self->count != self->count_balance) { - PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find_n()"); - return NULL; - } + if (self->count != self->count_balance) { + PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find_n()"); + return NULL; + } - nearest = MEM_mallocN(sizeof(KDTreeNearest_3d) * n, __func__); + nearest = MEM_mallocN(sizeof(KDTreeNearest_3d) * n, __func__); - found = BLI_kdtree_3d_find_nearest_n(self->obj, co, nearest, n); + found = BLI_kdtree_3d_find_nearest_n(self->obj, co, nearest, n); - py_list = PyList_New(found); + py_list = PyList_New(found); - for (i = 0; i < found; i++) { - PyList_SET_ITEM(py_list, i, kdtree_nearest_to_py(&nearest[i])); - } + for (i = 0; i < found; i++) { + PyList_SET_ITEM(py_list, i, kdtree_nearest_to_py(&nearest[i])); + } - MEM_freeN(nearest); + MEM_freeN(nearest); - return py_list; + return py_list; } PyDoc_STRVAR(py_kdtree_find_range_doc, -".. method:: find_range(co, radius)\n" -"\n" -" Find all points within ``radius`` of ``co``.\n" -"\n" -" :arg co: 3d coordinates.\n" -" :type co: float triplet\n" -" :arg radius: Distance to search for points.\n" -" :type radius: float\n" -" :return: Returns a list of tuples (:class:`Vector`, index, distance).\n" -" :rtype: :class:`list`\n" -); + ".. method:: find_range(co, radius)\n" + "\n" + " Find all points within ``radius`` of ``co``.\n" + "\n" + " :arg co: 3d coordinates.\n" + " :type co: float triplet\n" + " :arg radius: Distance to search for points.\n" + " :type radius: float\n" + " :return: Returns a list of tuples (:class:`Vector`, index, distance).\n" + " :rtype: :class:`list`\n"); static PyObject *py_kdtree_find_range(PyKDTree *self, PyObject *args, PyObject *kwargs) { - PyObject *py_list; - PyObject *py_co; - float co[3]; - KDTreeNearest_3d *nearest = NULL; - float radius; - int i, found; + PyObject *py_list; + PyObject *py_co; + float co[3]; + KDTreeNearest_3d *nearest = NULL; + float radius; + int i, found; - const char *keywords[] = {"co", "radius", NULL}; + const char *keywords[] = {"co", "radius", NULL}; - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, (char *) "Of:find_range", (char **)keywords, - &py_co, &radius)) - { - return NULL; - } + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, (char *)"Of:find_range", (char **)keywords, &py_co, &radius)) { + return NULL; + } - if (mathutils_array_parse(co, 3, 3, py_co, "find_range: invalid 'co' arg") == -1) { - return NULL; - } + if (mathutils_array_parse(co, 3, 3, py_co, "find_range: invalid 'co' arg") == -1) { + return NULL; + } - if (radius < 0.0f) { - PyErr_SetString(PyExc_RuntimeError, "negative radius given"); - return NULL; - } + if (radius < 0.0f) { + PyErr_SetString(PyExc_RuntimeError, "negative radius given"); + return NULL; + } - if (self->count != self->count_balance) { - PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find_range()"); - return NULL; - } + if (self->count != self->count_balance) { + PyErr_SetString(PyExc_RuntimeError, "KDTree must be balanced before calling find_range()"); + return NULL; + } - found = BLI_kdtree_3d_range_search(self->obj, co, &nearest, radius); + found = BLI_kdtree_3d_range_search(self->obj, co, &nearest, radius); - py_list = PyList_New(found); + py_list = PyList_New(found); - for (i = 0; i < found; i++) { - PyList_SET_ITEM(py_list, i, kdtree_nearest_to_py(&nearest[i])); - } + for (i = 0; i < found; i++) { + PyList_SET_ITEM(py_list, i, kdtree_nearest_to_py(&nearest[i])); + } - if (nearest) { - MEM_freeN(nearest); - } + if (nearest) { + MEM_freeN(nearest); + } - return py_list; + return py_list; } - static PyMethodDef PyKDTree_methods[] = { - {"insert", (PyCFunction)py_kdtree_insert, METH_VARARGS | METH_KEYWORDS, py_kdtree_insert_doc}, - {"balance", (PyCFunction)py_kdtree_balance, METH_NOARGS, py_kdtree_balance_doc}, - {"find", (PyCFunction)py_kdtree_find, METH_VARARGS | METH_KEYWORDS, py_kdtree_find_doc}, - {"find_n", (PyCFunction)py_kdtree_find_n, METH_VARARGS | METH_KEYWORDS, py_kdtree_find_n_doc}, - {"find_range", (PyCFunction)py_kdtree_find_range, METH_VARARGS | METH_KEYWORDS, py_kdtree_find_range_doc}, - {NULL, NULL, 0, NULL}, + {"insert", (PyCFunction)py_kdtree_insert, METH_VARARGS | METH_KEYWORDS, py_kdtree_insert_doc}, + {"balance", (PyCFunction)py_kdtree_balance, METH_NOARGS, py_kdtree_balance_doc}, + {"find", (PyCFunction)py_kdtree_find, METH_VARARGS | METH_KEYWORDS, py_kdtree_find_doc}, + {"find_n", (PyCFunction)py_kdtree_find_n, METH_VARARGS | METH_KEYWORDS, py_kdtree_find_n_doc}, + {"find_range", + (PyCFunction)py_kdtree_find_range, + METH_VARARGS | METH_KEYWORDS, + py_kdtree_find_range_doc}, + {NULL, NULL, 0, NULL}, }; PyDoc_STRVAR(py_KDtree_doc, -"KdTree(size) -> new kd-tree initialized to hold ``size`` items.\n" -"\n" -".. note::\n" -"\n" -" :class:`KDTree.balance` must have been called before using any of the ``find`` methods.\n" -); + "KdTree(size) -> new kd-tree initialized to hold ``size`` items.\n" + "\n" + ".. note::\n" + "\n" + " :class:`KDTree.balance` must have been called before using any of the ``find`` " + "methods.\n"); PyTypeObject PyKDTree_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "KDTree", /* tp_name */ - sizeof(PyKDTree), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)PyKDTree__tp_dealloc, /* tp_dealloc */ - NULL, /* tp_print */ - NULL, /* tp_getattr */ - NULL, /* tp_setattr */ - NULL, /* tp_compare */ - NULL, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - NULL, /* tp_hash */ - NULL, /* tp_call */ - NULL, /* tp_str */ - NULL, /* tp_getattro */ - NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - py_KDtree_doc, /* Documentation string */ - NULL, /* tp_traverse */ - NULL, /* tp_clear */ - NULL, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - NULL, /* tp_iter */ - NULL, /* tp_iternext */ - (struct PyMethodDef *)PyKDTree_methods, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - NULL, /* tp_base */ - NULL, /* tp_dict */ - NULL, /* tp_descr_get */ - NULL, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)PyKDTree__tp_init, /* tp_init */ - (allocfunc)PyType_GenericAlloc, /* tp_alloc */ - (newfunc)PyType_GenericNew, /* tp_new */ - (freefunc)0, /* tp_free */ - NULL, /* tp_is_gc */ - NULL, /* tp_bases */ - NULL, /* tp_mro */ - NULL, /* tp_cache */ - NULL, /* tp_subclasses */ - NULL, /* tp_weaklist */ - (destructor)NULL, /* tp_del */ + PyVarObject_HEAD_INIT(NULL, 0) "KDTree", /* tp_name */ + sizeof(PyKDTree), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)PyKDTree__tp_dealloc, /* tp_dealloc */ + NULL, /* tp_print */ + NULL, /* tp_getattr */ + NULL, /* tp_setattr */ + NULL, /* tp_compare */ + NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + NULL, /* tp_hash */ + NULL, /* tp_call */ + NULL, /* tp_str */ + NULL, /* tp_getattro */ + NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + py_KDtree_doc, /* Documentation string */ + NULL, /* tp_traverse */ + NULL, /* tp_clear */ + NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + NULL, /* tp_iter */ + NULL, /* tp_iternext */ + (struct PyMethodDef *)PyKDTree_methods, /* tp_methods */ + NULL, /* tp_members */ + NULL, /* tp_getset */ + NULL, /* tp_base */ + NULL, /* tp_dict */ + NULL, /* tp_descr_get */ + NULL, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)PyKDTree__tp_init, /* tp_init */ + (allocfunc)PyType_GenericAlloc, /* tp_alloc */ + (newfunc)PyType_GenericNew, /* tp_new */ + (freefunc)0, /* tp_free */ + NULL, /* tp_is_gc */ + NULL, /* tp_bases */ + NULL, /* tp_mro */ + NULL, /* tp_cache */ + NULL, /* tp_subclasses */ + NULL, /* tp_weaklist */ + (destructor)NULL, /* tp_del */ }; -PyDoc_STRVAR(py_kdtree_doc, -"Generic 3-dimentional kd-tree to perform spatial searches." -); +PyDoc_STRVAR(py_kdtree_doc, "Generic 3-dimentional kd-tree to perform spatial searches."); static struct PyModuleDef kdtree_moduledef = { - PyModuleDef_HEAD_INIT, - "mathutils.kdtree", /* m_name */ - py_kdtree_doc, /* m_doc */ - 0, /* m_size */ - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "mathutils.kdtree", /* m_name */ + py_kdtree_doc, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; PyMODINIT_FUNC PyInit_mathutils_kdtree(void) { - PyObject *m = PyModule_Create(&kdtree_moduledef); + PyObject *m = PyModule_Create(&kdtree_moduledef); - if (m == NULL) { - return NULL; - } + if (m == NULL) { + return NULL; + } - /* Register the 'KDTree' class */ - if (PyType_Ready(&PyKDTree_Type)) { - return NULL; - } - PyModule_AddObject(m, "KDTree", (PyObject *) &PyKDTree_Type); + /* Register the 'KDTree' class */ + if (PyType_Ready(&PyKDTree_Type)) { + return NULL; + } + PyModule_AddObject(m, "KDTree", (PyObject *)&PyKDTree_Type); - return m; + return m; } diff --git a/source/blender/python/mathutils/mathutils_kdtree.h b/source/blender/python/mathutils/mathutils_kdtree.h index 4a4e1740ad8..99411997282 100644 --- a/source/blender/python/mathutils/mathutils_kdtree.h +++ b/source/blender/python/mathutils/mathutils_kdtree.h @@ -14,7 +14,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - /** \file * \ingroup mathutils */ diff --git a/source/blender/python/mathutils/mathutils_noise.c b/source/blender/python/mathutils/mathutils_noise.c index 04cadb9b592..b890295d32f 100644 --- a/source/blender/python/mathutils/mathutils_noise.c +++ b/source/blender/python/mathutils/mathutils_noise.c @@ -21,7 +21,6 @@ * blenders noise functions. */ - /************************/ /* Blender Noise Module */ /************************/ @@ -88,13 +87,13 @@ /* Period parameters */ #define N 624 #define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UMASK 0x80000000UL /* most significant w-r bits */ -#define LMASK 0x7fffffffUL /* least significant r bits */ -#define MIXBITS(u, v) (((u) & UMASK) | ((v) & LMASK)) -#define TWIST(u, v) ((MIXBITS(u, v) >> 1) ^ ((v) & 1UL ? MATRIX_A : 0UL)) +#define MATRIX_A 0x9908b0dfUL /* constant vector a */ +#define UMASK 0x80000000UL /* most significant w-r bits */ +#define LMASK 0x7fffffffUL /* least significant r bits */ +#define MIXBITS(u, v) (((u)&UMASK) | ((v)&LMASK)) +#define TWIST(u, v) ((MIXBITS(u, v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) -static unsigned long state[N]; /* the array for the state vector */ +static unsigned long state[N]; /* the array for the state vector */ static int left = 1; static int initf = 0; static unsigned long *next; @@ -103,86 +102,84 @@ static float state_offset_vector[3 * 3]; /* initializes state[N] with a seed */ static void init_genrand(unsigned long s) { - int j; - state[0] = s & 0xffffffffUL; - for (j = 1; j < N; j++) { - state[j] = - (1812433253UL * - (state[j - 1] ^ (state[j - 1] >> 30)) + j); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array state[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - state[j] &= 0xffffffffUL; /* for >32 bit machines */ - } - left = 1; - initf = 1; - - /* update vector offset */ - { - const unsigned long *state_offset = &state[N - ARRAY_SIZE(state_offset_vector)]; - const float range = 32; /* range in both pos/neg direction */ - for (j = 0; j < ARRAY_SIZE(state_offset_vector); j++, state_offset++) { - /* overflow is fine here */ - state_offset_vector[j] = (float)(int)(*state_offset) * (1.0f / (INT_MAX / range)); - } - } + int j; + state[0] = s & 0xffffffffUL; + for (j = 1; j < N; j++) { + state[j] = (1812433253UL * (state[j - 1] ^ (state[j - 1] >> 30)) + j); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array state[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + state[j] &= 0xffffffffUL; /* for >32 bit machines */ + } + left = 1; + initf = 1; + + /* update vector offset */ + { + const unsigned long *state_offset = &state[N - ARRAY_SIZE(state_offset_vector)]; + const float range = 32; /* range in both pos/neg direction */ + for (j = 0; j < ARRAY_SIZE(state_offset_vector); j++, state_offset++) { + /* overflow is fine here */ + state_offset_vector[j] = (float)(int)(*state_offset) * (1.0f / (INT_MAX / range)); + } + } } static void next_state(void) { - unsigned long *p = state; - int j; + unsigned long *p = state; + int j; - /* if init_genrand() has not been called, */ - /* a default initial seed is used */ - if (initf == 0) { - init_genrand(5489UL); - } + /* if init_genrand() has not been called, */ + /* a default initial seed is used */ + if (initf == 0) { + init_genrand(5489UL); + } - left = N; - next = state; + left = N; + next = state; - for (j = N - M + 1; --j; p++) { - *p = p[M] ^ TWIST(p[0], p[1]); - } + for (j = N - M + 1; --j; p++) { + *p = p[M] ^ TWIST(p[0], p[1]); + } - for (j = M; --j; p++) { - *p = p[M - N] ^ TWIST(p[0], p[1]); - } + for (j = M; --j; p++) { + *p = p[M - N] ^ TWIST(p[0], p[1]); + } - *p = p[M - N] ^ TWIST(p[0], state[0]); + *p = p[M - N] ^ TWIST(p[0], state[0]); } /*------------------------------------------------------------*/ static void setRndSeed(int seed) { - if (seed == 0) { - init_genrand(time(NULL)); - } - else { - init_genrand(seed); - } + if (seed == 0) { + init_genrand(time(NULL)); + } + else { + init_genrand(seed); + } } /* float number in range [0, 1) using the mersenne twister rng */ static float frand(void) { - unsigned long y; + unsigned long y; - if (--left == 0) { - next_state(); - } - y = *next++; + if (--left == 0) { + next_state(); + } + y = *next++; - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - y ^= (y >> 18); + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); - return (float) y / 4294967296.f; + return (float)y / 4294967296.f; } /*------------------------------------------------------------*/ @@ -190,898 +187,960 @@ static float frand(void) /*------------------------------------------------------------*/ #define BPY_NOISE_BASIS_ENUM_DOC \ -" :arg noise_basis: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \ - "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \ - "'CELLNOISE'].\n" \ -" :type noise_basis: string\n" \ + " :arg noise_basis: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', " \ + "'VORONOI_F1', 'VORONOI_F2', " \ + "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \ + "'CELLNOISE'].\n" \ + " :type noise_basis: string\n" #define BPY_NOISE_METRIC_ENUM_DOC \ -" :arg distance_metric: Enumerator in ['DISTANCE', 'DISTANCE_SQUARED', 'MANHATTAN', 'CHEBYCHEV', " \ - "'MINKOVSKY', 'MINKOVSKY_HALF', 'MINKOVSKY_FOUR'].\n" \ -" :type distance_metric: string\n" \ + " :arg distance_metric: Enumerator in ['DISTANCE', 'DISTANCE_SQUARED', 'MANHATTAN', " \ + "'CHEBYCHEV', " \ + "'MINKOVSKY', 'MINKOVSKY_HALF', 'MINKOVSKY_FOUR'].\n" \ + " :type distance_metric: string\n" /* Noise basis enum */ #define DEFAULT_NOISE_TYPE TEX_STDPERLIN static PyC_FlagSet bpy_noise_types[] = { - {TEX_BLENDER, "BLENDER"}, - {TEX_STDPERLIN, "PERLIN_ORIGINAL"}, - {TEX_NEWPERLIN, "PERLIN_NEW"}, - {TEX_VORONOI_F1, "VORONOI_F1"}, - {TEX_VORONOI_F2, "VORONOI_F2"}, - {TEX_VORONOI_F3, "VORONOI_F3"}, - {TEX_VORONOI_F4, "VORONOI_F4"}, - {TEX_VORONOI_F2F1, "VORONOI_F2F1"}, - {TEX_VORONOI_CRACKLE, "VORONOI_CRACKLE"}, - {TEX_CELLNOISE, "CELLNOISE"}, - {0, NULL}, + {TEX_BLENDER, "BLENDER"}, + {TEX_STDPERLIN, "PERLIN_ORIGINAL"}, + {TEX_NEWPERLIN, "PERLIN_NEW"}, + {TEX_VORONOI_F1, "VORONOI_F1"}, + {TEX_VORONOI_F2, "VORONOI_F2"}, + {TEX_VORONOI_F3, "VORONOI_F3"}, + {TEX_VORONOI_F4, "VORONOI_F4"}, + {TEX_VORONOI_F2F1, "VORONOI_F2F1"}, + {TEX_VORONOI_CRACKLE, "VORONOI_CRACKLE"}, + {TEX_CELLNOISE, "CELLNOISE"}, + {0, NULL}, }; /* Metric basis enum */ #define DEFAULT_METRIC_TYPE TEX_DISTANCE static PyC_FlagSet bpy_noise_metrics[] = { - {TEX_DISTANCE, "DISTANCE"}, - {TEX_DISTANCE_SQUARED, "DISTANCE_SQUARED"}, - {TEX_MANHATTAN, "MANHATTAN"}, - {TEX_CHEBYCHEV, "CHEBYCHEV"}, - {TEX_MINKOVSKY, "MINKOVSKY"}, - {TEX_MINKOVSKY_HALF, "MINKOVSKY_HALF"}, - {TEX_MINKOVSKY_FOUR, "MINKOVSKY_FOUR"}, - {0, NULL}, + {TEX_DISTANCE, "DISTANCE"}, + {TEX_DISTANCE_SQUARED, "DISTANCE_SQUARED"}, + {TEX_MANHATTAN, "MANHATTAN"}, + {TEX_CHEBYCHEV, "CHEBYCHEV"}, + {TEX_MINKOVSKY, "MINKOVSKY"}, + {TEX_MINKOVSKY_HALF, "MINKOVSKY_HALF"}, + {TEX_MINKOVSKY_FOUR, "MINKOVSKY_FOUR"}, + {0, NULL}, }; /* Fills an array of length size with random numbers in the range (-1, 1)*/ static void rand_vn(float *array_tar, const int size) { - float *array_pt = array_tar + (size - 1); - int i = size; - while (i--) { *(array_pt--) = 2.0f * frand() - 1.0f; } + float *array_pt = array_tar + (size - 1); + int i = size; + while (i--) { + *(array_pt--) = 2.0f * frand() - 1.0f; + } } /* Fills an array of length 3 with noise values */ static void noise_vector(float x, float y, float z, int nb, float v[3]) { - /* Simply evaluate noise at 3 different positions */ - const float *ofs = state_offset_vector; - for (int j = 0; j < 3; j++) { - v[j] = (2.0f * BLI_gNoise(1.0f, x + ofs[0], y + ofs[1], z + ofs[2], 0, nb) - 1.0f); - ofs += 3; - } + /* Simply evaluate noise at 3 different positions */ + const float *ofs = state_offset_vector; + for (int j = 0; j < 3; j++) { + v[j] = (2.0f * BLI_gNoise(1.0f, x + ofs[0], y + ofs[1], z + ofs[2], 0, nb) - 1.0f); + ofs += 3; + } } /* Returns a turbulence value for a given position (x, y, z) */ static float turb( - float x, float y, float z, int oct, int hard, int nb, - float ampscale, float freqscale) + float x, float y, float z, int oct, int hard, int nb, float ampscale, float freqscale) { - float amp, out, t; - int i; - amp = 1.f; - out = (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); - if (hard) { - out = fabsf(out); - } - for (i = 1; i < oct; i++) { - amp *= ampscale; - x *= freqscale; - y *= freqscale; - z *= freqscale; - t = (float)(amp * (2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f)); - if (hard) { - t = fabsf(t); - } - out += t; - } - return out; + float amp, out, t; + int i; + amp = 1.f; + out = (float)(2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f); + if (hard) { + out = fabsf(out); + } + for (i = 1; i < oct; i++) { + amp *= ampscale; + x *= freqscale; + y *= freqscale; + z *= freqscale; + t = (float)(amp * (2.0f * BLI_gNoise(1.f, x, y, z, 0, nb) - 1.0f)); + if (hard) { + t = fabsf(t); + } + out += t; + } + return out; } /* Fills an array of length 3 with the turbulence vector for a given * position (x, y, z) */ -static void vTurb( - float x, float y, float z, int oct, int hard, int nb, - float ampscale, float freqscale, float v[3]) +static void vTurb(float x, + float y, + float z, + int oct, + int hard, + int nb, + float ampscale, + float freqscale, + float v[3]) { - float amp, t[3]; - int i; - amp = 1.f; - noise_vector(x, y, z, nb, v); - if (hard) { - v[0] = fabsf(v[0]); - v[1] = fabsf(v[1]); - v[2] = fabsf(v[2]); - } - for (i = 1; i < oct; i++) { - amp *= ampscale; - x *= freqscale; - y *= freqscale; - z *= freqscale; - noise_vector(x, y, z, nb, t); - if (hard) { - t[0] = fabsf(t[0]); - t[1] = fabsf(t[1]); - t[2] = fabsf(t[2]); - } - v[0] += amp * t[0]; - v[1] += amp * t[1]; - v[2] += amp * t[2]; - } + float amp, t[3]; + int i; + amp = 1.f; + noise_vector(x, y, z, nb, v); + if (hard) { + v[0] = fabsf(v[0]); + v[1] = fabsf(v[1]); + v[2] = fabsf(v[2]); + } + for (i = 1; i < oct; i++) { + amp *= ampscale; + x *= freqscale; + y *= freqscale; + z *= freqscale; + noise_vector(x, y, z, nb, t); + if (hard) { + t[0] = fabsf(t[0]); + t[1] = fabsf(t[1]); + t[2] = fabsf(t[2]); + } + v[0] += amp * t[0]; + v[1] += amp * t[1]; + v[2] += amp * t[2]; + } } /*-------------------------DOC STRINGS ---------------------------*/ -PyDoc_STRVAR(M_Noise_doc, -"The Blender noise module" -); +PyDoc_STRVAR(M_Noise_doc, "The Blender noise module"); /*------------------------------------------------------------*/ /* Python Functions */ /*------------------------------------------------------------*/ PyDoc_STRVAR(M_Noise_random_doc, -".. function:: random()\n" -"\n" -" Returns a random number in the range [0, 1).\n" -"\n" -" :return: The random number.\n" -" :rtype: float\n" -); + ".. function:: random()\n" + "\n" + " Returns a random number in the range [0, 1).\n" + "\n" + " :return: The random number.\n" + " :rtype: float\n"); static PyObject *M_Noise_random(PyObject *UNUSED(self)) { - return PyFloat_FromDouble(frand()); + return PyFloat_FromDouble(frand()); } PyDoc_STRVAR(M_Noise_random_unit_vector_doc, -".. function:: random_unit_vector(size=3)\n" -"\n" -" Returns a unit vector with random entries.\n" -"\n" -" :arg size: The size of the vector to be produced, in the range [2, 4].\n" -" :type size: int\n" -" :return: The random unit vector.\n" -" :rtype: :class:`mathutils.Vector`\n" -); + ".. function:: random_unit_vector(size=3)\n" + "\n" + " Returns a unit vector with random entries.\n" + "\n" + " :arg size: The size of the vector to be produced, in the range [2, 4].\n" + " :type size: int\n" + " :return: The random unit vector.\n" + " :rtype: :class:`mathutils.Vector`\n"); static PyObject *M_Noise_random_unit_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"size", NULL}; - float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - float norm = 2.0f; - int size = 3; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "|$i:random_unit_vector", (char **)kwlist, - &size)) - { - return NULL; - } - - if (size > 4 || size < 2) { - PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); - return NULL; - } - - while (norm == 0.0f || norm > 1.0f) { - rand_vn(vec, size); - norm = normalize_vn(vec, size); - } - - return Vector_CreatePyObject(vec, size, NULL); + static const char *kwlist[] = {"size", NULL}; + float vec[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float norm = 2.0f; + int size = 3; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_unit_vector", (char **)kwlist, &size)) { + return NULL; + } + + if (size > 4 || size < 2) { + PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); + return NULL; + } + + while (norm == 0.0f || norm > 1.0f) { + rand_vn(vec, size); + norm = normalize_vn(vec, size); + } + + return Vector_CreatePyObject(vec, size, NULL); } PyDoc_STRVAR(M_Noise_random_vector_doc, -".. function:: random_vector(size=3)\n" -"\n" -" Returns a vector with random entries in the range (-1, 1).\n" -"\n" -" :arg size: The size of the vector to be produced.\n" -" :type size: int\n" -" :return: The random vector.\n" -" :rtype: :class:`mathutils.Vector`\n" -); + ".. function:: random_vector(size=3)\n" + "\n" + " Returns a vector with random entries in the range (-1, 1).\n" + "\n" + " :arg size: The size of the vector to be produced.\n" + " :type size: int\n" + " :return: The random vector.\n" + " :rtype: :class:`mathutils.Vector`\n"); static PyObject *M_Noise_random_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"size", NULL}; - float *vec = NULL; - int size = 3; + static const char *kwlist[] = {"size", NULL}; + float *vec = NULL; + int size = 3; - if (!PyArg_ParseTupleAndKeywords( - args, kw, "|$i:random_vector", (char **)kwlist, - &size)) - { - return NULL; - } + if (!PyArg_ParseTupleAndKeywords(args, kw, "|$i:random_vector", (char **)kwlist, &size)) { + return NULL; + } - if (size < 2) { - PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); - return NULL; - } + if (size < 2) { + PyErr_SetString(PyExc_ValueError, "Vector(): invalid size"); + return NULL; + } - vec = PyMem_New(float, size); + vec = PyMem_New(float, size); - rand_vn(vec, size); + rand_vn(vec, size); - return Vector_CreatePyObject_alloc(vec, size, NULL); + return Vector_CreatePyObject_alloc(vec, size, NULL); } PyDoc_STRVAR(M_Noise_seed_set_doc, -".. function:: seed_set(seed)\n" -"\n" -" Sets the random seed used for random_unit_vector, and random.\n" -"\n" -" :arg seed: Seed used for the random generator.\n" -" When seed is zero, the current time will be used instead.\n" -" :type seed: int\n" -); + ".. function:: seed_set(seed)\n" + "\n" + " Sets the random seed used for random_unit_vector, and random.\n" + "\n" + " :arg seed: Seed used for the random generator.\n" + " When seed is zero, the current time will be used instead.\n" + " :type seed: int\n"); static PyObject *M_Noise_seed_set(PyObject *UNUSED(self), PyObject *args) { - int s; - if (!PyArg_ParseTuple(args, "i:seed_set", &s)) { - return NULL; - } - setRndSeed(s); - Py_RETURN_NONE; + int s; + if (!PyArg_ParseTuple(args, "i:seed_set", &s)) { + return NULL; + } + setRndSeed(s); + Py_RETURN_NONE; } PyDoc_STRVAR(M_Noise_noise_doc, -".. function:: noise(position, noise_basis='PERLIN_ORIGINAL')\n" -"\n" -" Returns noise value from the noise basis at the position specified.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -BPY_NOISE_BASIS_ENUM_DOC -" :return: The noise value.\n" -" :rtype: float\n" -); + ".. function:: noise(position, noise_basis='PERLIN_ORIGINAL')\n" + "\n" + " Returns noise value from the noise basis at the position specified.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" BPY_NOISE_BASIS_ENUM_DOC + " :return: The noise value.\n" + " :rtype: float\n"); static PyObject *M_Noise_noise(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "noise_basis", NULL}; - PyObject *value; - float vec[3]; - const char *noise_basis_str = NULL; - int noise_basis_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "O|$s:noise", (char **)kwlist, - &value, &noise_basis_str)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "noise: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble((2.0f * BLI_gNoise(1.0f, vec[0], vec[1], vec[2], 0, noise_basis_enum) - 1.0f)); + static const char *kwlist[] = {"", "noise_basis", NULL}; + PyObject *value; + float vec[3]; + const char *noise_basis_str = NULL; + int noise_basis_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "O|$s:noise", (char **)kwlist, &value, &noise_basis_str)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID(bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise") == + -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "noise: invalid 'position' arg") == -1) { + return NULL; + } + + return PyFloat_FromDouble( + (2.0f * BLI_gNoise(1.0f, vec[0], vec[1], vec[2], 0, noise_basis_enum) - 1.0f)); } PyDoc_STRVAR(M_Noise_noise_vector_doc, -".. function:: noise_vector(position, noise_basis='PERLIN_ORIGINAL')\n" -"\n" -" Returns the noise vector from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -BPY_NOISE_BASIS_ENUM_DOC -" :return: The noise vector.\n" -" :rtype: :class:`mathutils.Vector`\n" -); + ".. function:: noise_vector(position, noise_basis='PERLIN_ORIGINAL')\n" + "\n" + " Returns the noise vector from the noise basis at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" BPY_NOISE_BASIS_ENUM_DOC + " :return: The noise vector.\n" + " :rtype: :class:`mathutils.Vector`\n"); static PyObject *M_Noise_noise_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "noise_basis", NULL}; - PyObject *value; - float vec[3], r_vec[3]; - const char *noise_basis_str = NULL; - int noise_basis_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "O|$s:noise_vector", (char **)kwlist, - &value, &noise_basis_str)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise_vector") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "noise_vector: invalid 'position' arg") == -1) { - return NULL; - } - - noise_vector(vec[0], vec[1], vec[2], noise_basis_enum, r_vec); - - return Vector_CreatePyObject(r_vec, 3, NULL); + static const char *kwlist[] = {"", "noise_basis", NULL}; + PyObject *value; + float vec[3], r_vec[3]; + const char *noise_basis_str = NULL; + int noise_basis_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "O|$s:noise_vector", (char **)kwlist, &value, &noise_basis_str)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "noise_vector") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "noise_vector: invalid 'position' arg") == -1) { + return NULL; + } + + noise_vector(vec[0], vec[1], vec[2], noise_basis_enum, r_vec); + + return Vector_CreatePyObject(r_vec, 3, NULL); } PyDoc_STRVAR(M_Noise_turbulence_doc, -".. function:: turbulence(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)\n" -"\n" -" Returns the turbulence value from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg octaves: The number of different noise frequencies used.\n" -" :type octaves: int\n" -" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n" -" :type hard: boolean\n" -BPY_NOISE_BASIS_ENUM_DOC -" :arg amplitude_scale: The amplitude scaling factor.\n" -" :type amplitude_scale: float\n" -" :arg frequency_scale: The frequency scaling factor\n" -" :type frequency_scale: float\n" -" :return: The turbulence value.\n" -" :rtype: float\n" -); + ".. function:: turbulence(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', " + "amplitude_scale=0.5, frequency_scale=2.0)\n" + "\n" + " Returns the turbulence value from the noise basis at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg octaves: The number of different noise frequencies used.\n" + " :type octaves: int\n" + " :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or " + "soft (smooth transitions).\n" + " :type hard: boolean\n" BPY_NOISE_BASIS_ENUM_DOC + " :arg amplitude_scale: The amplitude scaling factor.\n" + " :type amplitude_scale: float\n" + " :arg frequency_scale: The frequency scaling factor\n" + " :type frequency_scale: float\n" + " :return: The turbulence value.\n" + " :rtype: float\n"); static PyObject *M_Noise_turbulence(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL}; - PyObject *value; - float vec[3]; - const char *noise_basis_str = NULL; - int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE; - float as = 0.5f, fs = 2.0f; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Oii|$sff:turbulence", (char **)kwlist, - &value, &oct, &hd, &noise_basis_str, &as, &fs)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "turbulence: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble(turb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs)); + static const char *kwlist[] = { + "", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL}; + PyObject *value; + float vec[3]; + const char *noise_basis_str = NULL; + int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE; + float as = 0.5f, fs = 2.0f; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Oii|$sff:turbulence", + (char **)kwlist, + &value, + &oct, + &hd, + &noise_basis_str, + &as, + &fs)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "turbulence: invalid 'position' arg") == -1) { + return NULL; + } + + return PyFloat_FromDouble(turb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs)); } PyDoc_STRVAR(M_Noise_turbulence_vector_doc, -".. function:: turbulence_vector(position, octaves, hard, noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)\n" -"\n" -" Returns the turbulence vector from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg octaves: The number of different noise frequencies used.\n" -" :type octaves: int\n" -" :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or soft (smooth transitions).\n" -" :type hard: :boolean\n" -BPY_NOISE_BASIS_ENUM_DOC -" :arg amplitude_scale: The amplitude scaling factor.\n" -" :type amplitude_scale: float\n" -" :arg frequency_scale: The frequency scaling factor\n" -" :type frequency_scale: float\n" -" :return: The turbulence vector.\n" -" :rtype: :class:`mathutils.Vector`\n" -); + ".. function:: turbulence_vector(position, octaves, hard, " + "noise_basis='PERLIN_ORIGINAL', amplitude_scale=0.5, frequency_scale=2.0)\n" + "\n" + " Returns the turbulence vector from the noise basis at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg octaves: The number of different noise frequencies used.\n" + " :type octaves: int\n" + " :arg hard: Specifies whether returned turbulence is hard (sharp transitions) or " + "soft (smooth transitions).\n" + " :type hard: :boolean\n" BPY_NOISE_BASIS_ENUM_DOC + " :arg amplitude_scale: The amplitude scaling factor.\n" + " :type amplitude_scale: float\n" + " :arg frequency_scale: The frequency scaling factor\n" + " :type frequency_scale: float\n" + " :return: The turbulence vector.\n" + " :rtype: :class:`mathutils.Vector`\n"); static PyObject *M_Noise_turbulence_vector(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL}; - PyObject *value; - float vec[3], r_vec[3]; - const char *noise_basis_str = NULL; - int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE; - float as = 0.5f, fs = 2.0f; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Oii|$sff:turbulence_vector", (char **)kwlist, - &value, &oct, &hd, &noise_basis_str, &as, &fs)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence_vector") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "turbulence_vector: invalid 'position' arg") == -1) { - return NULL; - } - - vTurb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs, r_vec); - - return Vector_CreatePyObject(r_vec, 3, NULL); + static const char *kwlist[] = { + "", "", "", "noise_basis", "amplitude_scale", "frequency_scale", NULL}; + PyObject *value; + float vec[3], r_vec[3]; + const char *noise_basis_str = NULL; + int oct, hd, noise_basis_enum = DEFAULT_NOISE_TYPE; + float as = 0.5f, fs = 2.0f; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Oii|$sff:turbulence_vector", + (char **)kwlist, + &value, + &oct, + &hd, + &noise_basis_str, + &as, + &fs)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "turbulence_vector") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "turbulence_vector: invalid 'position' arg") == -1) { + return NULL; + } + + vTurb(vec[0], vec[1], vec[2], oct, hd, noise_basis_enum, as, fs, r_vec); + + return Vector_CreatePyObject(r_vec, 3, NULL); } /* F. Kenton Musgrave's fractal functions */ -PyDoc_STRVAR(M_Noise_fractal_doc, -".. function:: fractal(position, H, lacunarity, octaves, noise_basis='PERLIN_ORIGINAL')\n" -"\n" -" Returns the fractal Brownian motion (fBm) noise value from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg H: The fractal increment factor.\n" -" :type H: float\n" -" :arg lacunarity: The gap between successive frequencies.\n" -" :type lacunarity: float\n" -" :arg octaves: The number of different noise frequencies used.\n" -" :type octaves: int\n" -BPY_NOISE_BASIS_ENUM_DOC -" :return: The fractal Brownian motion noise value.\n" -" :rtype: float\n" -); +PyDoc_STRVAR( + M_Noise_fractal_doc, + ".. function:: fractal(position, H, lacunarity, octaves, noise_basis='PERLIN_ORIGINAL')\n" + "\n" + " Returns the fractal Brownian motion (fBm) noise value from the noise basis at the " + "specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg H: The fractal increment factor.\n" + " :type H: float\n" + " :arg lacunarity: The gap between successive frequencies.\n" + " :type lacunarity: float\n" + " :arg octaves: The number of different noise frequencies used.\n" + " :type octaves: int\n" BPY_NOISE_BASIS_ENUM_DOC + " :return: The fractal Brownian motion noise value.\n" + " :rtype: float\n"); static PyObject *M_Noise_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL}; - PyObject *value; - float vec[3]; - const char *noise_basis_str = NULL; - float H, lac, oct; - int noise_basis_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Offf|$s:fractal", (char **)kwlist, - &value, &H, &lac, &oct, &noise_basis_str)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "fractal") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "fractal: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble(mg_fBm(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum)); + static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL}; + PyObject *value; + float vec[3]; + const char *noise_basis_str = NULL; + float H, lac, oct; + int noise_basis_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Offf|$s:fractal", + (char **)kwlist, + &value, + &H, + &lac, + &oct, + &noise_basis_str)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "fractal") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "fractal: invalid 'position' arg") == -1) { + return NULL; + } + + return PyFloat_FromDouble(mg_fBm(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum)); } -PyDoc_STRVAR(M_Noise_multi_fractal_doc, -".. function:: multi_fractal(position, H, lacunarity, octaves, noise_basis='PERLIN_ORIGINAL')\n" -"\n" -" Returns multifractal noise value from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg H: The fractal increment factor.\n" -" :type H: float\n" -" :arg lacunarity: The gap between successive frequencies.\n" -" :type lacunarity: float\n" -" :arg octaves: The number of different noise frequencies used.\n" -" :type octaves: int\n" -BPY_NOISE_BASIS_ENUM_DOC -" :return: The multifractal noise value.\n" -" :rtype: float\n" -); +PyDoc_STRVAR( + M_Noise_multi_fractal_doc, + ".. function:: multi_fractal(position, H, lacunarity, octaves, " + "noise_basis='PERLIN_ORIGINAL')\n" + "\n" + " Returns multifractal noise value from the noise basis at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg H: The fractal increment factor.\n" + " :type H: float\n" + " :arg lacunarity: The gap between successive frequencies.\n" + " :type lacunarity: float\n" + " :arg octaves: The number of different noise frequencies used.\n" + " :type octaves: int\n" BPY_NOISE_BASIS_ENUM_DOC + " :return: The multifractal noise value.\n" + " :rtype: float\n"); static PyObject *M_Noise_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL}; - PyObject *value; - float vec[3]; - const char *noise_basis_str = NULL; - float H, lac, oct; - int noise_basis_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Offf|$s:multi_fractal", (char **)kwlist, - &value, &H, &lac, &oct, &noise_basis_str)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "multi_fractal") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "multi_fractal: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble(mg_MultiFractal(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum)); + static const char *kwlist[] = {"", "", "", "", "noise_basis", NULL}; + PyObject *value; + float vec[3]; + const char *noise_basis_str = NULL; + float H, lac, oct; + int noise_basis_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Offf|$s:multi_fractal", + (char **)kwlist, + &value, + &H, + &lac, + &oct, + &noise_basis_str)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "multi_fractal") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "multi_fractal: invalid 'position' arg") == -1) { + return NULL; + } + + return PyFloat_FromDouble( + mg_MultiFractal(vec[0], vec[1], vec[2], H, lac, oct, noise_basis_enum)); } PyDoc_STRVAR(M_Noise_variable_lacunarity_doc, -".. function:: variable_lacunarity(position, distortion, noise_type1='PERLIN_ORIGINAL', noise_type2='PERLIN_ORIGINAL')\n" -"\n" -" Returns variable lacunarity noise value, a distorted variety of noise, from noise type 1 distorted by noise type 2 at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg distortion: The amount of distortion.\n" -" :type distortion: float\n" -" :arg noise_type1: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \ - "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \ - "'CELLNOISE'].\n" -" :type noise_type1: string\n" -" :arg noise_type2: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', 'VORONOI_F1', 'VORONOI_F2', " \ - "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " \ - "'CELLNOISE'].\n" -" :type noise_type2: string\n" -" :return: The variable lacunarity noise value.\n" -" :rtype: float\n" -); + ".. function:: variable_lacunarity(position, distortion, " + "noise_type1='PERLIN_ORIGINAL', noise_type2='PERLIN_ORIGINAL')\n" + "\n" + " Returns variable lacunarity noise value, a distorted variety of noise, from " + "noise type 1 distorted by noise type 2 at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg distortion: The amount of distortion.\n" + " :type distortion: float\n" + " :arg noise_type1: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', " + "'VORONOI_F1', 'VORONOI_F2', " + "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " + "'CELLNOISE'].\n" + " :type noise_type1: string\n" + " :arg noise_type2: Enumerator in ['BLENDER', 'PERLIN_ORIGINAL', 'PERLIN_NEW', " + "'VORONOI_F1', 'VORONOI_F2', " + "'VORONOI_F3', 'VORONOI_F4', 'VORONOI_F2F1', 'VORONOI_CRACKLE', " + "'CELLNOISE'].\n" + " :type noise_type2: string\n" + " :return: The variable lacunarity noise value.\n" + " :rtype: float\n"); static PyObject *M_Noise_variable_lacunarity(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "noise_type1", "noise_type2", NULL}; - PyObject *value; - float vec[3]; - const char *noise_type1_str = NULL, *noise_type2_str = NULL; - float d; - int noise_type1_enum = DEFAULT_NOISE_TYPE, noise_type2_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Of|$ss:variable_lacunarity", (char **)kwlist, - &value, &d, &noise_type1_str, &noise_type2_str)) - { - return NULL; - } - - if (!noise_type1_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_type1_str, &noise_type1_enum, "variable_lacunarity") == -1) - { - return NULL; - } - - if (!noise_type2_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_type2_str, &noise_type2_enum, "variable_lacunarity") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "variable_lacunarity: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble(mg_VLNoise(vec[0], vec[1], vec[2], d, noise_type1_enum, noise_type2_enum)); + static const char *kwlist[] = {"", "", "noise_type1", "noise_type2", NULL}; + PyObject *value; + float vec[3]; + const char *noise_type1_str = NULL, *noise_type2_str = NULL; + float d; + int noise_type1_enum = DEFAULT_NOISE_TYPE, noise_type2_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Of|$ss:variable_lacunarity", + (char **)kwlist, + &value, + &d, + &noise_type1_str, + &noise_type2_str)) { + return NULL; + } + + if (!noise_type1_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_type1_str, &noise_type1_enum, "variable_lacunarity") == -1) { + return NULL; + } + + if (!noise_type2_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_type2_str, &noise_type2_enum, "variable_lacunarity") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "variable_lacunarity: invalid 'position' arg") == + -1) { + return NULL; + } + + return PyFloat_FromDouble( + mg_VLNoise(vec[0], vec[1], vec[2], d, noise_type1_enum, noise_type2_enum)); } -PyDoc_STRVAR(M_Noise_hetero_terrain_doc, -".. function:: hetero_terrain(position, H, lacunarity, octaves, offset, noise_basis='PERLIN_ORIGINAL')\n" -"\n" -" Returns the heterogeneous terrain value from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg H: The fractal dimension of the roughest areas.\n" -" :type H: float\n" -" :arg lacunarity: The gap between successive frequencies.\n" -" :type lacunarity: float\n" -" :arg octaves: The number of different noise frequencies used.\n" -" :type octaves: int\n" -" :arg offset: The height of the terrain above 'sea level'.\n" -" :type offset: float\n" -BPY_NOISE_BASIS_ENUM_DOC -" :return: The heterogeneous terrain value.\n" -" :rtype: float\n" -); +PyDoc_STRVAR( + M_Noise_hetero_terrain_doc, + ".. function:: hetero_terrain(position, H, lacunarity, octaves, offset, " + "noise_basis='PERLIN_ORIGINAL')\n" + "\n" + " Returns the heterogeneous terrain value from the noise basis at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg H: The fractal dimension of the roughest areas.\n" + " :type H: float\n" + " :arg lacunarity: The gap between successive frequencies.\n" + " :type lacunarity: float\n" + " :arg octaves: The number of different noise frequencies used.\n" + " :type octaves: int\n" + " :arg offset: The height of the terrain above 'sea level'.\n" + " :type offset: float\n" BPY_NOISE_BASIS_ENUM_DOC + " :return: The heterogeneous terrain value.\n" + " :rtype: float\n"); static PyObject *M_Noise_hetero_terrain(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "", "", "", "noise_basis", NULL}; - PyObject *value; - float vec[3]; - const char *noise_basis_str = NULL; - float H, lac, oct, ofs; - int noise_basis_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Offff|$s:hetero_terrain", (char **)kwlist, - &value, &H, &lac, &oct, &ofs, &noise_basis_str)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "hetero_terrain") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "hetero_terrain: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble(mg_HeteroTerrain(vec[0], vec[1], vec[2], H, lac, oct, ofs, noise_basis_enum)); + static const char *kwlist[] = {"", "", "", "", "", "noise_basis", NULL}; + PyObject *value; + float vec[3]; + const char *noise_basis_str = NULL; + float H, lac, oct, ofs; + int noise_basis_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Offff|$s:hetero_terrain", + (char **)kwlist, + &value, + &H, + &lac, + &oct, + &ofs, + &noise_basis_str)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "hetero_terrain") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "hetero_terrain: invalid 'position' arg") == -1) { + return NULL; + } + + return PyFloat_FromDouble( + mg_HeteroTerrain(vec[0], vec[1], vec[2], H, lac, oct, ofs, noise_basis_enum)); } -PyDoc_STRVAR(M_Noise_hybrid_multi_fractal_doc, -".. function:: hybrid_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis='PERLIN_ORIGINAL')\n" -"\n" -" Returns hybrid multifractal value from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg H: The fractal dimension of the roughest areas.\n" -" :type H: float\n" -" :arg lacunarity: The gap between successive frequencies.\n" -" :type lacunarity: float\n" -" :arg octaves: The number of different noise frequencies used.\n" -" :type octaves: int\n" -" :arg offset: The height of the terrain above 'sea level'.\n" -" :type offset: float\n" -" :arg gain: Scaling applied to the values.\n" -" :type gain: float\n" -BPY_NOISE_BASIS_ENUM_DOC -" :return: The hybrid multifractal value.\n" -" :rtype: float\n" -); +PyDoc_STRVAR( + M_Noise_hybrid_multi_fractal_doc, + ".. function:: hybrid_multi_fractal(position, H, lacunarity, octaves, offset, gain, " + "noise_basis='PERLIN_ORIGINAL')\n" + "\n" + " Returns hybrid multifractal value from the noise basis at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg H: The fractal dimension of the roughest areas.\n" + " :type H: float\n" + " :arg lacunarity: The gap between successive frequencies.\n" + " :type lacunarity: float\n" + " :arg octaves: The number of different noise frequencies used.\n" + " :type octaves: int\n" + " :arg offset: The height of the terrain above 'sea level'.\n" + " :type offset: float\n" + " :arg gain: Scaling applied to the values.\n" + " :type gain: float\n" BPY_NOISE_BASIS_ENUM_DOC + " :return: The hybrid multifractal value.\n" + " :rtype: float\n"); static PyObject *M_Noise_hybrid_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL}; - PyObject *value; - float vec[3]; - const char *noise_basis_str = NULL; - float H, lac, oct, ofs, gn; - int noise_basis_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Offfff|$s:hybrid_multi_fractal", (char **)kwlist, - &value, &H, &lac, &oct, &ofs, &gn, &noise_basis_str)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "hybrid_multi_fractal") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "hybrid_multi_fractal: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble(mg_HybridMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum)); + static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL}; + PyObject *value; + float vec[3]; + const char *noise_basis_str = NULL; + float H, lac, oct, ofs, gn; + int noise_basis_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Offfff|$s:hybrid_multi_fractal", + (char **)kwlist, + &value, + &H, + &lac, + &oct, + &ofs, + &gn, + &noise_basis_str)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "hybrid_multi_fractal") == + -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "hybrid_multi_fractal: invalid 'position' arg") == + -1) { + return NULL; + } + + return PyFloat_FromDouble( + mg_HybridMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum)); } -PyDoc_STRVAR(M_Noise_ridged_multi_fractal_doc, -".. function:: ridged_multi_fractal(position, H, lacunarity, octaves, offset, gain, noise_basis='PERLIN_ORIGINAL')\n" -"\n" -" Returns ridged multifractal value from the noise basis at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :arg H: The fractal dimension of the roughest areas.\n" -" :type H: float\n" -" :arg lacunarity: The gap between successive frequencies.\n" -" :type lacunarity: float\n" -" :arg octaves: The number of different noise frequencies used.\n" -" :type octaves: int\n" -" :arg offset: The height of the terrain above 'sea level'.\n" -" :type offset: float\n" -" :arg gain: Scaling applied to the values.\n" -" :type gain: float\n" -BPY_NOISE_BASIS_ENUM_DOC -" :return: The ridged multifractal value.\n" -" :rtype: float\n" -); +PyDoc_STRVAR( + M_Noise_ridged_multi_fractal_doc, + ".. function:: ridged_multi_fractal(position, H, lacunarity, octaves, offset, gain, " + "noise_basis='PERLIN_ORIGINAL')\n" + "\n" + " Returns ridged multifractal value from the noise basis at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :arg H: The fractal dimension of the roughest areas.\n" + " :type H: float\n" + " :arg lacunarity: The gap between successive frequencies.\n" + " :type lacunarity: float\n" + " :arg octaves: The number of different noise frequencies used.\n" + " :type octaves: int\n" + " :arg offset: The height of the terrain above 'sea level'.\n" + " :type offset: float\n" + " :arg gain: Scaling applied to the values.\n" + " :type gain: float\n" BPY_NOISE_BASIS_ENUM_DOC + " :return: The ridged multifractal value.\n" + " :rtype: float\n"); static PyObject *M_Noise_ridged_multi_fractal(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL}; - PyObject *value; - float vec[3]; - const char *noise_basis_str = NULL; - float H, lac, oct, ofs, gn; - int noise_basis_enum = DEFAULT_NOISE_TYPE; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "Offfff|$s:ridged_multi_fractal", (char **)kwlist, - &value, &H, &lac, &oct, &ofs, &gn, &noise_basis_str)) - { - return NULL; - } - - if (!noise_basis_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_types, noise_basis_str, &noise_basis_enum, "ridged_multi_fractal") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "ridged_multi_fractal: invalid 'position' arg") == -1) { - return NULL; - } - - return PyFloat_FromDouble(mg_RidgedMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum)); + static const char *kwlist[] = {"", "", "", "", "", "", "noise_basis", NULL}; + PyObject *value; + float vec[3]; + const char *noise_basis_str = NULL; + float H, lac, oct, ofs, gn; + int noise_basis_enum = DEFAULT_NOISE_TYPE; + + if (!PyArg_ParseTupleAndKeywords(args, + kw, + "Offfff|$s:ridged_multi_fractal", + (char **)kwlist, + &value, + &H, + &lac, + &oct, + &ofs, + &gn, + &noise_basis_str)) { + return NULL; + } + + if (!noise_basis_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID( + bpy_noise_types, noise_basis_str, &noise_basis_enum, "ridged_multi_fractal") == + -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "ridged_multi_fractal: invalid 'position' arg") == + -1) { + return NULL; + } + + return PyFloat_FromDouble( + mg_RidgedMultiFractal(vec[0], vec[1], vec[2], H, lac, oct, ofs, gn, noise_basis_enum)); } PyDoc_STRVAR(M_Noise_voronoi_doc, -".. function:: voronoi(position, distance_metric='DISTANCE', exponent=2.5)\n" -"\n" -" Returns a list of distances to the four closest features and their locations.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -BPY_NOISE_METRIC_ENUM_DOC -" :arg exponent: The exponent for Minkowski distance metric.\n" -" :type exponent: float\n" -" :return: A list of distances to the four closest features and their locations.\n" -" :rtype: list of four floats, list of four :class:`mathutils.Vector` types\n" -); + ".. function:: voronoi(position, distance_metric='DISTANCE', exponent=2.5)\n" + "\n" + " Returns a list of distances to the four closest features and their locations.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" BPY_NOISE_METRIC_ENUM_DOC + " :arg exponent: The exponent for Minkowski distance metric.\n" + " :type exponent: float\n" + " :return: A list of distances to the four closest features and their locations.\n" + " :rtype: list of four floats, list of four :class:`mathutils.Vector` types\n"); static PyObject *M_Noise_voronoi(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { - static const char *kwlist[] = {"", "distance_metric", "exponent", NULL}; - PyObject *value; - PyObject *list; - PyObject *ret; - float vec[3]; - const char *metric_str = NULL; - float da[4], pa[12]; - int metric_enum = DEFAULT_METRIC_TYPE; - float me = 2.5f; /* default minkowski exponent */ - - int i; - - if (!PyArg_ParseTupleAndKeywords( - args, kw, "O|$sf:voronoi", (char **)kwlist, - &value, &metric_str, &me)) - { - return NULL; - } - - if (!metric_str) { - /* pass through */ - } - else if (PyC_FlagSet_ValueFromID( - bpy_noise_metrics, metric_str, &metric_enum, "voronoi") == -1) - { - return NULL; - } - - if (mathutils_array_parse(vec, 3, 3, value, "voronoi: invalid 'position' arg") == -1) { - return NULL; - } - - list = PyList_New(4); - - voronoi(vec[0], vec[1], vec[2], da, pa, me, metric_enum); - - for (i = 0; i < 4; i++) { - PyObject *v = Vector_CreatePyObject(pa + 3 * i, 3, NULL); - PyList_SET_ITEM(list, i, v); - } - - ret = Py_BuildValue("[[ffff]O]", da[0], da[1], da[2], da[3], list); - Py_DECREF(list); - return ret; + static const char *kwlist[] = {"", "distance_metric", "exponent", NULL}; + PyObject *value; + PyObject *list; + PyObject *ret; + float vec[3]; + const char *metric_str = NULL; + float da[4], pa[12]; + int metric_enum = DEFAULT_METRIC_TYPE; + float me = 2.5f; /* default minkowski exponent */ + + int i; + + if (!PyArg_ParseTupleAndKeywords( + args, kw, "O|$sf:voronoi", (char **)kwlist, &value, &metric_str, &me)) { + return NULL; + } + + if (!metric_str) { + /* pass through */ + } + else if (PyC_FlagSet_ValueFromID(bpy_noise_metrics, metric_str, &metric_enum, "voronoi") == -1) { + return NULL; + } + + if (mathutils_array_parse(vec, 3, 3, value, "voronoi: invalid 'position' arg") == -1) { + return NULL; + } + + list = PyList_New(4); + + voronoi(vec[0], vec[1], vec[2], da, pa, me, metric_enum); + + for (i = 0; i < 4; i++) { + PyObject *v = Vector_CreatePyObject(pa + 3 * i, 3, NULL); + PyList_SET_ITEM(list, i, v); + } + + ret = Py_BuildValue("[[ffff]O]", da[0], da[1], da[2], da[3], list); + Py_DECREF(list); + return ret; } PyDoc_STRVAR(M_Noise_cell_doc, -".. function:: cell(position)\n" -"\n" -" Returns cell noise value at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :return: The cell noise value.\n" -" :rtype: float\n" -); + ".. function:: cell(position)\n" + "\n" + " Returns cell noise value at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :return: The cell noise value.\n" + " :rtype: float\n"); static PyObject *M_Noise_cell(PyObject *UNUSED(self), PyObject *args) { - PyObject *value; - float vec[3]; + PyObject *value; + float vec[3]; - if (!PyArg_ParseTuple(args, "O:cell", &value)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "O:cell", &value)) { + return NULL; + } - if (mathutils_array_parse(vec, 3, 3, value, "cell: invalid 'position' arg") == -1) { - return NULL; - } + if (mathutils_array_parse(vec, 3, 3, value, "cell: invalid 'position' arg") == -1) { + return NULL; + } - return PyFloat_FromDouble(cellNoise(vec[0], vec[1], vec[2])); + return PyFloat_FromDouble(cellNoise(vec[0], vec[1], vec[2])); } PyDoc_STRVAR(M_Noise_cell_vector_doc, -".. function:: cell_vector(position)\n" -"\n" -" Returns cell noise vector at the specified position.\n" -"\n" -" :arg position: The position to evaluate the selected noise function.\n" -" :type position: :class:`mathutils.Vector`\n" -" :return: The cell noise vector.\n" -" :rtype: :class:`mathutils.Vector`\n" -); + ".. function:: cell_vector(position)\n" + "\n" + " Returns cell noise vector at the specified position.\n" + "\n" + " :arg position: The position to evaluate the selected noise function.\n" + " :type position: :class:`mathutils.Vector`\n" + " :return: The cell noise vector.\n" + " :rtype: :class:`mathutils.Vector`\n"); static PyObject *M_Noise_cell_vector(PyObject *UNUSED(self), PyObject *args) { - PyObject *value; - float vec[3], r_vec[3]; + PyObject *value; + float vec[3], r_vec[3]; - if (!PyArg_ParseTuple(args, "O:cell_vector", &value)) { - return NULL; - } + if (!PyArg_ParseTuple(args, "O:cell_vector", &value)) { + return NULL; + } - if (mathutils_array_parse(vec, 3, 3, value, "cell_vector: invalid 'position' arg") == -1) { - return NULL; - } + if (mathutils_array_parse(vec, 3, 3, value, "cell_vector: invalid 'position' arg") == -1) { + return NULL; + } - cellNoiseV(vec[0], vec[1], vec[2], r_vec); - return Vector_CreatePyObject(r_vec, 3, NULL); + cellNoiseV(vec[0], vec[1], vec[2], r_vec); + return Vector_CreatePyObject(r_vec, 3, NULL); } static PyMethodDef M_Noise_methods[] = { - {"seed_set", (PyCFunction) M_Noise_seed_set, METH_VARARGS, M_Noise_seed_set_doc}, - {"random", (PyCFunction) M_Noise_random, METH_NOARGS, M_Noise_random_doc}, - {"random_unit_vector", (PyCFunction) M_Noise_random_unit_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_random_unit_vector_doc}, - {"random_vector", (PyCFunction) M_Noise_random_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_random_vector_doc}, - {"noise", (PyCFunction) M_Noise_noise, METH_VARARGS | METH_KEYWORDS, M_Noise_noise_doc}, - {"noise_vector", (PyCFunction) M_Noise_noise_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_noise_vector_doc}, - {"turbulence", (PyCFunction) M_Noise_turbulence, METH_VARARGS | METH_KEYWORDS, M_Noise_turbulence_doc}, - {"turbulence_vector", (PyCFunction) M_Noise_turbulence_vector, METH_VARARGS | METH_KEYWORDS, M_Noise_turbulence_vector_doc}, - {"fractal", (PyCFunction) M_Noise_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_fractal_doc}, - {"multi_fractal", (PyCFunction) M_Noise_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_multi_fractal_doc}, - {"variable_lacunarity", (PyCFunction) M_Noise_variable_lacunarity, METH_VARARGS | METH_KEYWORDS, M_Noise_variable_lacunarity_doc}, - {"hetero_terrain", (PyCFunction) M_Noise_hetero_terrain, METH_VARARGS | METH_KEYWORDS, M_Noise_hetero_terrain_doc}, - {"hybrid_multi_fractal", (PyCFunction) M_Noise_hybrid_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_hybrid_multi_fractal_doc}, - {"ridged_multi_fractal", (PyCFunction) M_Noise_ridged_multi_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_ridged_multi_fractal_doc}, - {"voronoi", (PyCFunction) M_Noise_voronoi, METH_VARARGS | METH_KEYWORDS, M_Noise_voronoi_doc}, - {"cell", (PyCFunction) M_Noise_cell, METH_VARARGS, M_Noise_cell_doc}, - {"cell_vector", (PyCFunction) M_Noise_cell_vector, METH_VARARGS, M_Noise_cell_vector_doc}, - {NULL, NULL, 0, NULL}, + {"seed_set", (PyCFunction)M_Noise_seed_set, METH_VARARGS, M_Noise_seed_set_doc}, + {"random", (PyCFunction)M_Noise_random, METH_NOARGS, M_Noise_random_doc}, + {"random_unit_vector", + (PyCFunction)M_Noise_random_unit_vector, + METH_VARARGS | METH_KEYWORDS, + M_Noise_random_unit_vector_doc}, + {"random_vector", + (PyCFunction)M_Noise_random_vector, + METH_VARARGS | METH_KEYWORDS, + M_Noise_random_vector_doc}, + {"noise", (PyCFunction)M_Noise_noise, METH_VARARGS | METH_KEYWORDS, M_Noise_noise_doc}, + {"noise_vector", + (PyCFunction)M_Noise_noise_vector, + METH_VARARGS | METH_KEYWORDS, + M_Noise_noise_vector_doc}, + {"turbulence", + (PyCFunction)M_Noise_turbulence, + METH_VARARGS | METH_KEYWORDS, + M_Noise_turbulence_doc}, + {"turbulence_vector", + (PyCFunction)M_Noise_turbulence_vector, + METH_VARARGS | METH_KEYWORDS, + M_Noise_turbulence_vector_doc}, + {"fractal", (PyCFunction)M_Noise_fractal, METH_VARARGS | METH_KEYWORDS, M_Noise_fractal_doc}, + {"multi_fractal", + (PyCFunction)M_Noise_multi_fractal, + METH_VARARGS | METH_KEYWORDS, + M_Noise_multi_fractal_doc}, + {"variable_lacunarity", + (PyCFunction)M_Noise_variable_lacunarity, + METH_VARARGS | METH_KEYWORDS, + M_Noise_variable_lacunarity_doc}, + {"hetero_terrain", + (PyCFunction)M_Noise_hetero_terrain, + METH_VARARGS | METH_KEYWORDS, + M_Noise_hetero_terrain_doc}, + {"hybrid_multi_fractal", + (PyCFunction)M_Noise_hybrid_multi_fractal, + METH_VARARGS | METH_KEYWORDS, + M_Noise_hybrid_multi_fractal_doc}, + {"ridged_multi_fractal", + (PyCFunction)M_Noise_ridged_multi_fractal, + METH_VARARGS | METH_KEYWORDS, + M_Noise_ridged_multi_fractal_doc}, + {"voronoi", (PyCFunction)M_Noise_voronoi, METH_VARARGS | METH_KEYWORDS, M_Noise_voronoi_doc}, + {"cell", (PyCFunction)M_Noise_cell, METH_VARARGS, M_Noise_cell_doc}, + {"cell_vector", (PyCFunction)M_Noise_cell_vector, METH_VARARGS, M_Noise_cell_vector_doc}, + {NULL, NULL, 0, NULL}, }; static struct PyModuleDef M_Noise_module_def = { - PyModuleDef_HEAD_INIT, - "mathutils.noise", /* m_name */ - M_Noise_doc, /* m_doc */ - 0, /* m_size */ - M_Noise_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ + PyModuleDef_HEAD_INIT, + "mathutils.noise", /* m_name */ + M_Noise_doc, /* m_doc */ + 0, /* m_size */ + M_Noise_methods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; /*----------------------------MODULE INIT-------------------------*/ PyMODINIT_FUNC PyInit_mathutils_noise(void) { - PyObject *submodule = PyModule_Create(&M_Noise_module_def); + PyObject *submodule = PyModule_Create(&M_Noise_module_def); - /* use current time as seed for random number generator by default */ - setRndSeed(0); + /* use current time as seed for random number generator by default */ + setRndSeed(0); - return submodule; + return submodule; } -- cgit v1.2.3