diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-02-15 03:26:31 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-02-15 06:01:59 +0300 |
commit | a9d979c8ef2b6de25c1953da341dd5e207416540 (patch) | |
tree | 8647bedb1815977967694b302e9d6d2fd98573e6 | |
parent | ce85aef0d9f2df094f2859236dc75a2c7f70bfcd (diff) |
mathutils: add freeze() method, is_frozen attr
This allows you to make any mathutils object immutable.
-rw-r--r-- | source/blender/python/mathutils/mathutils.c | 34 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils.h | 21 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Color.c | 25 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Euler.c | 23 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Matrix.c | 46 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Quaternion.c | 33 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Vector.c | 28 |
7 files changed, 157 insertions, 53 deletions
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index ca20f837b4a..28b2d26d3fd 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -452,6 +452,13 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index) return -1; } +void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self) +{ + PyErr_Format(PyExc_TypeError, + "%s is frozen (immutable)", + 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)) @@ -466,6 +473,33 @@ PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closu 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"; +PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure)) +{ + 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" +; +PyObject *BaseMathObject_freeze(BaseMathObject *self) +{ + if (self->flag & BASE_MATH_FLAG_IS_WRAP) { + PyErr_SetString(PyExc_TypeError, "Cannot freeze wrapped data"); + return NULL; + } + + self->flag |= BASE_MATH_FLAG_IS_FROZEN; + + return Py_INCREF_RET((PyObject *)self);; +} + int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg) { Py_VISIT(self->cb_user); diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index 296b8cf9559..03ce9af3f49 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -34,6 +34,7 @@ struct DynStr; extern char BaseMathObject_is_wrapped_doc[]; +extern char BaseMathObject_is_frozen_doc[]; extern char BaseMathObject_owner_doc[]; #define BASE_MATH_NEW(struct_name, root_type, base_type) \ @@ -43,6 +44,7 @@ extern char BaseMathObject_owner_doc[]; /* BaseMathObject.flag */ enum { BASE_MATH_FLAG_IS_WRAP = (1 << 0), + BASE_MATH_FLAG_IS_FROZEN = (1 << 1), }; #define BASE_MATH_FLAG_DEFAULT 0 @@ -69,6 +71,10 @@ typedef struct { PyObject *BaseMathObject_owner_get(BaseMathObject *self, void *); PyObject *BaseMathObject_is_wrapped_get(BaseMathObject *self, void *); +PyObject *BaseMathObject_is_frozen_get(BaseMathObject *self, void *); + +extern char BaseMathObject_freeze_doc[]; +PyObject *BaseMathObject_freeze(BaseMathObject *self); int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg); int BaseMathObject_clear(BaseMathObject *self); @@ -102,6 +108,8 @@ int _BaseMathObject_WriteCallback(BaseMathObject *self); int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index); int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); +void _BaseMathObject_RaiseFrozenExc(const BaseMathObject *self); + /* since this is called so often avoid where possible */ #define BaseMath_ReadCallback(_self) \ (((_self)->cb_user ? _BaseMathObject_ReadCallback((BaseMathObject *)_self):0)) @@ -112,6 +120,19 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); #define BaseMath_WriteIndexCallback(_self, _index) \ (((_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))) + +#define BaseMath_ReadIndexCallback_ForWrite(_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) + /* 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); diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index ce590999bc1..7fea0e59b82 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -222,8 +222,12 @@ static PyObject *Color_item(ColorObject *self, int i) /* sequence accessor (set) */ static int Color_ass_item(ColorObject *self, int i, PyObject *value) { - float f = PyFloat_AsDouble(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: " @@ -275,7 +279,7 @@ static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq) int i, size; float col[COLOR_SIZE]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; CLAMP(begin, 0, COLOR_SIZE); @@ -431,7 +435,7 @@ static PyObject *Color_iadd(PyObject *v1, PyObject *v2) color1 = (ColorObject *)v1; color2 = (ColorObject *)v2; - if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) + if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) return NULL; add_vn_vn(color1->col, color2->col, COLOR_SIZE); @@ -480,7 +484,7 @@ static PyObject *Color_isub(PyObject *v1, PyObject *v2) color1 = (ColorObject *)v1; color2 = (ColorObject *)v2; - if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) + if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) return NULL; sub_vn_vn(color1->col, color2->col, COLOR_SIZE); @@ -579,7 +583,7 @@ static PyObject *Color_imul(PyObject *v1, PyObject *v2) ColorObject *color = (ColorObject *)v1; float scalar; - if (BaseMath_ReadCallback(color) == -1) + if (BaseMath_ReadCallback_ForWrite(color) == -1) return NULL; /* only support color *= float */ @@ -605,7 +609,7 @@ static PyObject *Color_idiv(PyObject *v1, PyObject *v2) ColorObject *color = (ColorObject *)v1; float scalar; - if (BaseMath_ReadCallback(color) == -1) + if (BaseMath_ReadCallback_ForWrite(color) == -1) return NULL; /* only support color /= float */ @@ -728,7 +732,7 @@ static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type) return -1; } - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; rgb_to_hsv_v(self->col, hsv); @@ -769,6 +773,9 @@ static int Color_hsv_set(ColorObject *self, PyObject *value, void *UNUSED(closur if (mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -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); @@ -796,6 +803,7 @@ static PyGetSetDef Color_getseters[] = { {(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 */ }; @@ -806,6 +814,9 @@ 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}, + + /* base-math methods */ + {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/mathutils/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 24aca88e0f6..ad761baf1ae 100644 --- a/source/blender/python/mathutils/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -182,6 +182,9 @@ PyDoc_STRVAR(Euler_zero_doc, ); static PyObject *Euler_zero(EulerObject *self) { + if (BaseMath_Prepare_ForWrite(self) == -1) + return NULL; + zero_v3(self->eul); if (BaseMath_WriteCallback(self) == -1) @@ -220,7 +223,7 @@ static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args) return NULL; } - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; @@ -243,7 +246,7 @@ static PyObject *Euler_rotate(EulerObject *self, PyObject *value) { float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1) @@ -270,7 +273,7 @@ static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value) { float teul[EULER_SIZE]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (mathutils_array_parse(teul, EULER_SIZE, EULER_SIZE, value, @@ -416,8 +419,12 @@ static PyObject *Euler_item(EulerObject *self, int i) /* sequence accessor (set) */ static int Euler_ass_item(EulerObject *self, int i, PyObject *value) { - float f = PyFloat_AsDouble(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: " @@ -470,7 +477,7 @@ static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq) int i, size; float eul[EULER_SIZE]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; CLAMP(begin, 0, EULER_SIZE); @@ -618,6 +625,9 @@ static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(clos 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)) { @@ -655,6 +665,9 @@ static struct PyMethodDef Euler_methods[] = { {"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} }; diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 95b53256eac..7b72ae5cebe 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -111,7 +111,7 @@ static int mathutils_matrix_row_set(BaseMathObject *bmo, int row) MatrixObject *self = (MatrixObject *)bmo->cb_user; int col; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) return -1; @@ -141,7 +141,7 @@ static int mathutils_matrix_row_set_index(BaseMathObject *bmo, int row, int col) { MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; if (!matrix_row_vector_check(self, (VectorObject *)bmo, row)) return -1; @@ -200,7 +200,7 @@ static int mathutils_matrix_col_set(BaseMathObject *bmo, int col) int num_row; int row; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) return -1; @@ -233,7 +233,7 @@ static int mathutils_matrix_col_set_index(BaseMathObject *bmo, int col, int row) { MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; if (!matrix_col_vector_check(self, (VectorObject *)bmo, col)) return -1; @@ -286,7 +286,7 @@ static int mathutils_matrix_translation_set(BaseMathObject *bmo, int col) MatrixObject *self = (MatrixObject *)bmo->cb_user; int row; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; for (row = 0; row < 3; row++) { @@ -312,7 +312,7 @@ static int mathutils_matrix_translation_set_index(BaseMathObject *bmo, int col, { MatrixObject *self = (MatrixObject *)bmo->cb_user; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; MATRIX_ITEM(self, row, col) = bmo->data[row]; @@ -1385,7 +1385,7 @@ PyDoc_STRVAR(Matrix_invert_doc, ); static PyObject *Matrix_invert(MatrixObject *self, PyObject *args) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (matrix_invert_is_compat(self) == false) { @@ -1466,7 +1466,7 @@ static PyObject *Matrix_inverted(MatrixObject *self, PyObject *args) static PyObject *Matrix_inverted_noargs(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (matrix_invert_is_compat(self) == false) { @@ -1496,7 +1496,7 @@ PyDoc_STRVAR(Matrix_invert_safe_doc, ); static PyObject *Matrix_invert_safe(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (matrix_invert_is_compat(self) == false) { @@ -1547,7 +1547,7 @@ PyDoc_STRVAR(Matrix_adjugate_doc, ); static PyObject *Matrix_adjugate(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (self->num_col != self->num_row) { @@ -1602,7 +1602,7 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) { float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (mathutils_any_to_rotmat(other_rmat, value, "matrix.rotate(value)") == -1) @@ -1746,7 +1746,7 @@ PyDoc_STRVAR(Matrix_transpose_doc, ); static PyObject *Matrix_transpose(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (self->num_col != self->num_row) { @@ -1793,7 +1793,7 @@ PyDoc_STRVAR(Matrix_normalize_doc, ); static PyObject *Matrix_normalize(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (self->num_col != self->num_row) { @@ -1842,6 +1842,9 @@ PyDoc_STRVAR(Matrix_zero_doc, ); static PyObject *Matrix_zero(MatrixObject *self) { + if (BaseMath_Prepare_ForWrite(self) == -1) + return NULL; + fill_vn_fl(self->matrix, self->num_col * self->num_row, 0.0f); if (BaseMath_WriteCallback(self) == -1) @@ -1878,7 +1881,7 @@ PyDoc_STRVAR(Matrix_identity_doc, ); static PyObject *Matrix_identity(MatrixObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (self->num_col != self->num_row) { @@ -2049,7 +2052,7 @@ static int Matrix_len(MatrixObject *self) * the wrapped vector gives direct access to the matrix data */ static PyObject *Matrix_item_row(MatrixObject *self, int row) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (row < 0 || row >= self->num_row) { @@ -2063,7 +2066,7 @@ static PyObject *Matrix_item_row(MatrixObject *self, int row) /* same but column access */ static PyObject *Matrix_item_col(MatrixObject *self, int col) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (col < 0 || col >= self->num_col) { @@ -2082,7 +2085,7 @@ static int Matrix_ass_item_row(MatrixObject *self, int row, PyObject *value) { int col; float vec[MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; if (row >= self->num_row || row < 0) { @@ -2107,7 +2110,7 @@ static int Matrix_ass_item_col(MatrixObject *self, int col, PyObject *value) { int row; float vec[MATRIX_MAX_DIM]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; if (col >= self->num_col || col < 0) { @@ -2159,7 +2162,7 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va { PyObject *value_fast = NULL; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; CLAMP(begin, 0, self->num_row); @@ -2525,7 +2528,7 @@ static int Matrix_translation_set(MatrixObject *self, PyObject *value, void *UNU { float tvec[3]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; /*must be 4x4 square matrix*/ @@ -2704,6 +2707,9 @@ static struct PyMethodDef Matrix_methods[] = { {"__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}, diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 42be316bc9b..8734d190f2f 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -340,7 +340,7 @@ static PyObject *Quaternion_rotate(QuaternionObject *self, PyObject *value) float self_rmat[3][3], other_rmat[3][3], rmat[3][3]; float tquat[4], length; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (mathutils_any_to_rotmat(other_rmat, value, "Quaternion.rotate(value)") == -1) @@ -367,7 +367,7 @@ PyDoc_STRVAR(Quaternion_normalize_doc, ); static PyObject *Quaternion_normalize(QuaternionObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; normalize_qt(self->quat); @@ -395,7 +395,7 @@ PyDoc_STRVAR(Quaternion_invert_doc, ); static PyObject *Quaternion_invert(QuaternionObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; invert_qt(self->quat); @@ -425,7 +425,7 @@ PyDoc_STRVAR(Quaternion_identity_doc, ); static PyObject *Quaternion_identity(QuaternionObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; unit_qt(self->quat); @@ -443,7 +443,7 @@ PyDoc_STRVAR(Quaternion_negate_doc, ); static PyObject *Quaternion_negate(QuaternionObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; mul_qt_fl(self->quat, -1.0f); @@ -459,7 +459,7 @@ PyDoc_STRVAR(Quaternion_conjugate_doc, ); static PyObject *Quaternion_conjugate(QuaternionObject *self) { - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; conjugate_qt(self->quat); @@ -605,8 +605,14 @@ static PyObject *Quaternion_item(QuaternionObject *self, int i) /* sequence accessor (set) */ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob) { - float scalar = (float)PyFloat_AsDouble(ob); - if (scalar == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ + 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"); @@ -621,7 +627,7 @@ static int Quaternion_ass_item(QuaternionObject *self, int i, PyObject *ob) "array assignment index out of range"); return -1; } - self->quat[i] = scalar; + self->quat[i] = f; if (BaseMath_WriteIndexCallback(self, i) == -1) return -1; @@ -657,7 +663,7 @@ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyOb int i, size; float quat[QUAT_SIZE]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; CLAMP(begin, 0, QUAT_SIZE); @@ -1004,7 +1010,7 @@ static int Quaternion_angle_set(QuaternionObject *self, PyObject *value, void *U float axis[3], angle_dummy; float angle; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; len = normalize_qt_qt(tquat, self->quat); @@ -1060,7 +1066,7 @@ static int Quaternion_axis_vector_set(QuaternionObject *self, PyObject *value, v float axis[3]; float angle; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; len = normalize_qt_qt(tquat, self->quat); @@ -1204,6 +1210,9 @@ static struct PyMethodDef Quaternion_methods[] = { {"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}, diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 500a922dac9..91090e53e08 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -336,6 +336,9 @@ PyDoc_STRVAR(Vector_zero_doc, ); static PyObject *Vector_zero(VectorObject *self) { + if (BaseMath_Prepare_ForWrite(self) == -1) + return NULL; + fill_vn_fl(self->vec, self->size, 0.0f); if (BaseMath_WriteCallback(self) == -1) @@ -357,7 +360,7 @@ PyDoc_STRVAR(Vector_normalize_doc, static PyObject *Vector_normalize(VectorObject *self) { int size = (self->size == 4 ? 3 : self->size); - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; normalize_vn(self->vec, size); @@ -1284,7 +1287,7 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value) { float other_rmat[3][3]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return NULL; if (mathutils_any_to_rotmat(other_rmat, value, "Vector.rotate(value)") == -1) @@ -1402,6 +1405,10 @@ static PyObject *Vector_item(VectorObject *self, int i) 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: " @@ -1463,7 +1470,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *se int size = 0; float *vec = NULL; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; CLAMP(begin, 0, self->size); @@ -1556,7 +1563,7 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) return NULL; } - if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) + if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) return NULL; add_vn_vn(vec1->vec, vec2->vec, vec1->size); @@ -1627,7 +1634,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2) return NULL; } - if (BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) + if (BaseMath_ReadCallback_ForWrite(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1) return NULL; sub_vn_vn(vec1->vec, vec2->vec, vec1->size); @@ -1800,7 +1807,7 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) VectorObject *vec = (VectorObject *)v1; float scalar; - if (BaseMath_ReadCallback(vec) == -1) + if (BaseMath_ReadCallback_ForWrite(vec) == -1) return NULL; /* only support vec*=float and vec*=mat @@ -1920,7 +1927,7 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) float scalar; VectorObject *vec1 = (VectorObject *)v1; - if (BaseMath_ReadCallback(vec1) == -1) + if (BaseMath_ReadCallback_ForWrite(vec1) == -1) return NULL; if ((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) { /* parsed item not a number */ @@ -2207,7 +2214,7 @@ static int Vector_length_set(VectorObject *self, PyObject *value) { double dot = 0.0f, param; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; if ((param = PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) { @@ -2313,7 +2320,7 @@ static int Vector_swizzle_set(VectorObject *self, PyObject *value, void *closure float tvec[MAX_DIMENSIONS]; float vec_assign[MAX_DIMENSIONS]; - if (BaseMath_ReadCallback(self) == -1) + if (BaseMath_ReadCallback_ForWrite(self) == -1) return -1; /* Check that the closure can be used with this vector: even 2D vectors have @@ -2872,6 +2879,9 @@ static struct PyMethodDef Vector_methods[] = { {"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}, |