diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2011-07-21 03:33:10 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2011-07-21 03:33:10 +0400 |
commit | ce03ec4b866a3e1a6f19a266bf2c38c2c4b4afd0 (patch) | |
tree | c25f25286bde21fa170dc4a8582a12c19388f4e7 /source/blender/python | |
parent | 4c3140004aa61169061ddd2628a4f2c8d88f46a1 (diff) | |
parent | 76e91d7a5f8c253543bd1c938c8e74872d7a6c81 (diff) |
Merged changes in the trunk up to revision 38543.
Conflicts resolved:
doc/python_api/sphinx_doc_gen.py
source/blender/blenkernel/CMakeLists.txt
source/blender/makesdna/DNA_material_types.h
source/blender/render/intern/source/pipeline.c
source/creator/CMakeLists.txt
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/python/SConscript | 11 | ||||
-rw-r--r-- | source/blender/python/generic/CMakeLists.txt | 18 | ||||
-rw-r--r-- | source/blender/python/generic/bgl.c | 523 | ||||
-rw-r--r-- | source/blender/python/generic/py_capi_utils.c | 2 | ||||
-rw-r--r-- | source/blender/python/generic/py_capi_utils.h | 2 | ||||
-rw-r--r-- | source/blender/python/intern/CMakeLists.txt | 9 | ||||
-rw-r--r-- | source/blender/python/intern/bpy.c | 4 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_driver.c | 8 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_interface.c | 27 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 8 | ||||
-rw-r--r-- | source/blender/python/mathutils/CMakeLists.txt | 52 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils.c (renamed from source/blender/python/generic/mathutils.c) | 69 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils.h (renamed from source/blender/python/generic/mathutils.h) | 2 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Color.c (renamed from source/blender/python/generic/mathutils_Color.c) | 87 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Color.h (renamed from source/blender/python/generic/mathutils_Color.h) | 0 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Euler.c (renamed from source/blender/python/generic/mathutils_Euler.c) | 54 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Euler.h (renamed from source/blender/python/generic/mathutils_Euler.h) | 0 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Matrix.c (renamed from source/blender/python/generic/mathutils_Matrix.c) | 269 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Matrix.h (renamed from source/blender/python/generic/mathutils_Matrix.h) | 0 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Quaternion.c (renamed from source/blender/python/generic/mathutils_Quaternion.c) | 61 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Quaternion.h (renamed from source/blender/python/generic/mathutils_Quaternion.h) | 0 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Vector.c (renamed from source/blender/python/generic/mathutils_Vector.c) | 227 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Vector.h (renamed from source/blender/python/generic/mathutils_Vector.h) | 0 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_geometry.c (renamed from source/blender/python/generic/mathutils_geometry.c) | 763 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_geometry.h (renamed from source/blender/python/generic/mathutils_geometry.h) | 2 |
26 files changed, 1458 insertions, 741 deletions
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index fe9e0307703..8071edb378f 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -18,3 +18,4 @@ add_subdirectory(intern) add_subdirectory(generic) +add_subdirectory(mathutils) diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 54fc9e7853d..bacd7550aef 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -1,6 +1,6 @@ #!/usr/bin/python -# TODO, split into 2 files. +# TODO, split into 3 files. Import ('env') @@ -19,7 +19,14 @@ if is_debug: defs.append('_DEBUG') sources = env.Glob('generic/*.c') -env.BlenderLib( libname = 'bf_python_ext', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [362,165]) # ketsji is 360 +env.BlenderLib( libname = 'bf_python_ext', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [363,165]) # ketsji is 360 + + +# mathutils +defs = [] + +sources = env.Glob('mathutils/*.c') +env.BlenderLib( libname = 'bf_python_mathutils', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [362,165]) # bpy diff --git a/source/blender/python/generic/CMakeLists.txt b/source/blender/python/generic/CMakeLists.txt index 0889c77f9ad..8dfbf476995 100644 --- a/source/blender/python/generic/CMakeLists.txt +++ b/source/blender/python/generic/CMakeLists.txt @@ -20,10 +20,10 @@ set(INC . - ../../blenlib - ../../makesdna ../../blenkernel + ../../blenlib ../../blenloader + ../../makesdna ../../../../intern/guardedalloc ) @@ -37,13 +37,6 @@ set(SRC bgl.c blf_py_api.c bpy_internal_import.c - mathutils.c - mathutils_Color.c - mathutils_Euler.c - mathutils_Matrix.c - mathutils_Quaternion.c - mathutils_Vector.c - mathutils_geometry.c noise_py_api.c py_capi_utils.c @@ -51,13 +44,6 @@ set(SRC bgl.h blf_py_api.h bpy_internal_import.h - mathutils.h - mathutils_Color.h - mathutils_Euler.h - mathutils_Matrix.h - mathutils_Quaternion.h - mathutils_Vector.h - mathutils_geometry.h noise_py_api.h py_capi_utils.h ) diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index b5a693c397c..09432e0b316 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -44,69 +44,179 @@ #include "BLI_utildefines.h" - -PyDoc_STRVAR(Method_Buffer_doc, - "(type, dimensions, [template]) - Create a new Buffer object\n\n\ -(type) - The format to store data in\n\ -(dimensions) - An int or sequence specifying the dimensions of the buffer\n\ -[template] - A sequence of matching dimensions to the buffer to be created\n\ - which will be used to initialize the Buffer.\n\n\ -If a template is not passed in all fields will be initialized to 0.\n\n\ -The type should be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, or GL_DOUBLE.\n\ -If the dimensions are specified as an int a linear buffer will be\n\ -created. If a sequence is passed for the dimensions the buffer\n\ -will have len(sequence) dimensions, where the size for each dimension\n\ -is determined by the value in the sequence at that index.\n\n\ -For example, passing [100, 100] will create a 2 dimensional\n\ -square buffer. Passing [16, 16, 32] will create a 3 dimensional\n\ -buffer which is twice as deep as it is wide or high." -); - -static PyObject *Method_Buffer(PyObject *self, PyObject *args); +static PyObject *Buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds); /* Buffer sequence methods */ -static int Buffer_len(PyObject *self); -static PyObject *Buffer_item(PyObject *self, int i); -static PyObject *Buffer_slice(PyObject *self, int begin, int end); -static int Buffer_ass_item(PyObject *self, int i, PyObject *v); -static int Buffer_ass_slice(PyObject *self, int begin, int end, - PyObject *seq); +static int Buffer_len(Buffer *self); +static PyObject *Buffer_item(Buffer *self, int i); +static PyObject *Buffer_slice(Buffer *self, int begin, int end); +static int Buffer_ass_item(Buffer *self, int i, PyObject *v); +static int Buffer_ass_slice(Buffer *self, int begin, int end, + PyObject *seq); +static PyObject *Buffer_subscript(Buffer *self, PyObject *item); +static int Buffer_ass_subscript(Buffer *self, PyObject *item, + PyObject *value); static PySequenceMethods Buffer_SeqMethods = { - ( lenfunc ) Buffer_len, /*sq_length */ - ( binaryfunc ) NULL, /*sq_concat */ - ( ssizeargfunc ) NULL, /*sq_repeat */ - ( ssizeargfunc ) Buffer_item, /*sq_item */ - ( ssizessizeargfunc ) Buffer_slice, /*sq_slice, deprecated TODO, replace */ - ( ssizeobjargproc ) Buffer_ass_item, /*sq_ass_item */ - ( ssizessizeobjargproc ) Buffer_ass_slice, /*sq_ass_slice, deprecated TODO, replace */ + (lenfunc) Buffer_len, /*sq_length */ + (binaryfunc) NULL, /*sq_concat */ + (ssizeargfunc) NULL, /*sq_repeat */ + (ssizeargfunc) Buffer_item, /*sq_item */ + (ssizessizeargfunc) Buffer_slice, /*sq_slice, deprecated TODO, replace */ + (ssizeobjargproc) Buffer_ass_item, /*sq_ass_item */ + (ssizessizeobjargproc) Buffer_ass_slice, /*sq_ass_slice, deprecated TODO, replace */ (objobjproc) NULL, /* sq_contains */ (binaryfunc) NULL, /* sq_inplace_concat */ (ssizeargfunc) NULL, /* sq_inplace_repeat */ }; -static void Buffer_dealloc(PyObject *self); -static PyObject *Buffer_tolist(PyObject *self); -static PyObject *Buffer_dimensions(PyObject *self); -static PyObject *Buffer_getattr(PyObject *self, char *name); -static PyObject *Buffer_repr(PyObject *self); + +static PyMappingMethods Buffer_AsMapping = { + (lenfunc)Buffer_len, + (binaryfunc)Buffer_subscript, + (objobjargproc)Buffer_ass_subscript +}; + +static void Buffer_dealloc(Buffer *self); +static PyObject *Buffer_repr(Buffer *self); + +static PyObject *Buffer_to_list(Buffer *self) +{ + int i, len= self->dimensions[0]; + PyObject *list= PyList_New(len); + + for (i=0; i<len; i++) { + PyList_SET_ITEM(list, i, Buffer_item(self, i)); + } + + return list; +} + +static PyObject *Buffer_to_list_recursive(Buffer *self) +{ + PyObject *list; + + if(self->ndimensions > 1) { + int i, len= self->dimensions[0]; + list= PyList_New(len); + + for (i=0; i<len; i++) { + Buffer *sub= (Buffer *)Buffer_item(self, i); + PyList_SET_ITEM(list, i, Buffer_to_list_recursive(sub)); + Py_DECREF(sub); + } + } + else { + list= Buffer_to_list(self); + } + + return list; +} + +/* *DEPRECATED* 2011/7/17 bgl.Buffer.list */ +static PyObject *Buffer_list(Buffer *self, void *UNUSED(arg)) +{ + fprintf(stderr, "Warning: 'Buffer.list' deprecated, use '[:]' instead\n"); + return Buffer_to_list(self); +} + +static PyObject *Buffer_dimensions(Buffer *self, void *UNUSED(arg)) +{ + PyObject *list= PyList_New(self->ndimensions); + int i; + + for (i= 0; i<self->ndimensions; i++) { + PyList_SET_ITEM(list, i, PyLong_FromLong(self->dimensions[i])); + } + + return list; +} + +static PyMethodDef Buffer_methods[] = { + {"to_list", (PyCFunction)Buffer_to_list_recursive, METH_NOARGS, + "return the buffer as a list"}, + {NULL, NULL, 0, NULL} +}; + +static PyGetSetDef Buffer_getseters[] = { + {(char *)"list", (getter)Buffer_list, NULL, NULL, NULL}, + {(char *)"dimensions", (getter)Buffer_dimensions, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL, NULL} +}; + PyTypeObject BGL_bufferType = { PyVarObject_HEAD_INIT(NULL, 0) - "buffer", /*tp_name */ - sizeof( Buffer ), /*tp_basicsize */ - 0, /*tp_itemsize */ - ( destructor ) Buffer_dealloc, /*tp_dealloc */ - ( printfunc ) 0, /*tp_print */ - ( getattrfunc ) Buffer_getattr, /*tp_getattr */ - ( setattrfunc ) 0, /*tp_setattr */ + "bgl.Buffer", /*tp_name */ + sizeof(Buffer), /*tp_basicsize */ + 0, /*tp_itemsize */ + (destructor)Buffer_dealloc, /*tp_dealloc */ + (printfunc)NULL, /*tp_print */ + NULL, /*tp_getattr */ + NULL, /*tp_setattr */ NULL, /*tp_compare */ - ( reprfunc ) Buffer_repr, /*tp_repr */ + (reprfunc) Buffer_repr, /*tp_repr */ NULL, /*tp_as_number */ &Buffer_SeqMethods, /*tp_as_sequence */ + &Buffer_AsMapping, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + 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, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* 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 ***/ + Buffer_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + Buffer_getseters, /* struct PyGetSetDef *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*/ + Buffer_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*/ }; + /* #ifndef __APPLE__ */ #define BGL_Wrap(nargs, funcname, ret, arg_list) \ @@ -174,26 +284,13 @@ Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuf } else { memset(buffer->buf.asvoid, 0, length*size); - /* - for (i= 0; i<length; i++) { - if (type==GL_BYTE) - buffer->buf.asbyte[i]= 0; - else if (type==GL_SHORT) - buffer->buf.asshort[i]= 0; - else if (type==GL_INT) - buffer->buf.asint[i]= 0; - else if (type==GL_FLOAT) - buffer->buf.asfloat[i]= 0.0f; - else if (type==GL_DOUBLE) - buffer->buf.asdouble[i]= 0.0; - } - */ } return buffer; } + #define MAX_DIMENSIONS 256 -static PyObject *Method_Buffer (PyObject *UNUSED(self), PyObject *args) +static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { PyObject *length_ob= NULL, *init= NULL; Buffer *buffer; @@ -201,31 +298,41 @@ static PyObject *Method_Buffer (PyObject *UNUSED(self), PyObject *args) int i, type; int ndimensions = 0; - - if (!PyArg_ParseTuple(args, "iO|O", &type, &length_ob, &init)) { - PyErr_SetString(PyExc_AttributeError, "expected an int and one or two PyObjects"); + + if(kwds && PyDict_Size(kwds)) { + PyErr_SetString(PyExc_TypeError, + "bgl.Buffer(): takes no keyword args"); + return NULL; + } + + if (!PyArg_ParseTuple(args, "iO|O: bgl.Buffer", &type, &length_ob, &init)) { return NULL; } if (!ELEM5(type, GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE)) { - PyErr_SetString(PyExc_AttributeError, "invalid first argument type, should be one of GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE"); + PyErr_SetString(PyExc_AttributeError, + "invalid first argument type, should be one of " + "GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT or GL_DOUBLE"); return NULL; } if (PyLong_Check(length_ob)) { ndimensions= 1; if(((dimensions[0]= PyLong_AsLong(length_ob)) < 1)) { - PyErr_SetString(PyExc_AttributeError, "dimensions must be between 1 and "STRINGIFY(MAX_DIMENSIONS)); + PyErr_SetString(PyExc_AttributeError, + "dimensions must be between 1 and "STRINGIFY(MAX_DIMENSIONS)); return NULL; } } else if (PySequence_Check(length_ob)) { ndimensions= PySequence_Size(length_ob); if (ndimensions > MAX_DIMENSIONS) { - PyErr_SetString(PyExc_AttributeError, "too many dimensions, max is "STRINGIFY(MAX_DIMENSIONS)); + PyErr_SetString(PyExc_AttributeError, + "too many dimensions, max is "STRINGIFY(MAX_DIMENSIONS)); return NULL; } else if (ndimensions < 1) { - PyErr_SetString(PyExc_AttributeError, "sequence must have at least one dimension"); + PyErr_SetString(PyExc_AttributeError, + "sequence must have at least one dimension"); return NULL; } for (i=0; i<ndimensions; i++) { @@ -236,19 +343,22 @@ static PyObject *Method_Buffer (PyObject *UNUSED(self), PyObject *args) Py_DECREF(ob); if(dimensions[i] < 1) { - PyErr_SetString(PyExc_AttributeError, "dimensions must be between 1 and "STRINGIFY(MAX_DIMENSIONS)); + PyErr_SetString(PyExc_AttributeError, + "dimensions must be between 1 and "STRINGIFY(MAX_DIMENSIONS)); return NULL; } } } else { - PyErr_Format(PyExc_TypeError, "invalid second argument argument expected a sequence or an int, not a %.200s", Py_TYPE(length_ob)->tp_name); + PyErr_Format(PyExc_TypeError, + "invalid second argument argument expected a sequence " + "or an int, not a %.200s", Py_TYPE(length_ob)->tp_name); return NULL; } buffer= BGL_MakeBuffer(type, ndimensions, dimensions, NULL); if (init && ndimensions) { - if (Buffer_ass_slice((PyObject *) buffer, 0, dimensions[0], init)) { + if (Buffer_ass_slice(buffer, 0, dimensions[0], init)) { Py_DECREF(buffer); return NULL; } @@ -259,51 +369,48 @@ static PyObject *Method_Buffer (PyObject *UNUSED(self), PyObject *args) /*@ Buffer sequence methods */ -static int Buffer_len(PyObject *self) +static int Buffer_len(Buffer *self) { - Buffer *buf= (Buffer *) self; - return buf->dimensions[0]; + return self->dimensions[0]; } -static PyObject *Buffer_item(PyObject *self, int i) +static PyObject *Buffer_item(Buffer *self, int i) { - Buffer *buf= (Buffer *) self; - - if (i >= buf->dimensions[0]) { + if (i >= self->dimensions[0] || i < 0) { PyErr_SetString(PyExc_IndexError, "array index out of range"); return NULL; } - if (buf->ndimensions==1) { - switch (buf->type) { - case GL_BYTE: return Py_BuildValue("b", buf->buf.asbyte[i]); - case GL_SHORT: return Py_BuildValue("h", buf->buf.asshort[i]); - case GL_INT: return Py_BuildValue("i", buf->buf.asint[i]); - case GL_FLOAT: return PyFloat_FromDouble(buf->buf.asfloat[i]); - case GL_DOUBLE: return Py_BuildValue("d", buf->buf.asdouble[i]); + if (self->ndimensions==1) { + switch (self->type) { + case GL_BYTE: return Py_BuildValue("b", self->buf.asbyte[i]); + case GL_SHORT: return Py_BuildValue("h", self->buf.asshort[i]); + case GL_INT: return Py_BuildValue("i", self->buf.asint[i]); + case GL_FLOAT: return PyFloat_FromDouble(self->buf.asfloat[i]); + case GL_DOUBLE: return Py_BuildValue("d", self->buf.asdouble[i]); } } else { Buffer *newbuf; int j, length, size; - + length= 1; - for (j=1; j<buf->ndimensions; j++) { - length*= buf->dimensions[j]; + for (j=1; j < self->ndimensions; j++) { + length *= self->dimensions[j]; } - size= BGL_typeSize(buf->type); + size= BGL_typeSize(self->type); newbuf= (Buffer *) PyObject_NEW(Buffer, &BGL_bufferType); Py_INCREF(self); - newbuf->parent= self; + newbuf->parent= (PyObject *)self; - newbuf->ndimensions= buf->ndimensions-1; - newbuf->type= buf->type; - newbuf->buf.asvoid= buf->buf.asbyte + i*length*size; + newbuf->ndimensions= self->ndimensions - 1; + newbuf->type= self->type; + newbuf->buf.asvoid= self->buf.asbyte + i*length*size; newbuf->dimensions= MEM_mallocN(newbuf->ndimensions*sizeof(int), "Buffer dimensions"); - memcpy(newbuf->dimensions, buf->dimensions+1, + memcpy(newbuf->dimensions, self->dimensions+1, newbuf->ndimensions*sizeof(int)); return (PyObject *) newbuf; @@ -312,16 +419,14 @@ static PyObject *Buffer_item(PyObject *self, int i) return NULL; } -static PyObject *Buffer_slice(PyObject *self, int begin, int end) +static PyObject *Buffer_slice(Buffer *self, int begin, int end) { - Buffer *buf= (Buffer *) self; PyObject *list; int count; - if (begin<0) begin= 0; - if (end>buf->dimensions[0]) - end= buf->dimensions[0]; - if (begin>end) begin= end; + if (begin < 0) begin= 0; + if (end > self->dimensions[0]) end= self->dimensions[0]; + if (begin > end) begin= end; list= PyList_New(end-begin); @@ -331,134 +436,180 @@ static PyObject *Buffer_slice(PyObject *self, int begin, int end) return list; } -static int Buffer_ass_item(PyObject *self, int i, PyObject *v) +static int Buffer_ass_item(Buffer *self, int i, PyObject *v) { - Buffer *buf= (Buffer *) self; - - if (i >= buf->dimensions[0]) { - PyErr_SetString(PyExc_IndexError, "array assignment index out of range"); + if (i >= self->dimensions[0] || i < 0) { + PyErr_SetString(PyExc_IndexError, + "array assignment index out of range"); return -1; } - - if (buf->ndimensions!=1) { - PyObject *row= Buffer_item(self, i); - int ret; - - if (!row) return -1; - ret= Buffer_ass_slice(row, 0, buf->dimensions[1], v); - Py_DECREF(row); - return ret; - } - if (buf->type==GL_BYTE) { - if (!PyArg_Parse(v, "b:Coordinates must be ints", &buf->buf.asbyte[i])) - return -1; - } - else if (buf->type==GL_SHORT) { - if (!PyArg_Parse(v, "h:Coordinates must be ints", &buf->buf.asshort[i])) - return -1; - - } - else if (buf->type==GL_INT) { - if (!PyArg_Parse(v, "i:Coordinates must be ints", &buf->buf.asint[i])) - return -1; - } - else if (buf->type==GL_FLOAT) { - if (!PyArg_Parse(v, "f:Coordinates must be floats", &buf->buf.asfloat[i])) + if (self->ndimensions!=1) { + Buffer *row= (Buffer *)Buffer_item(self, i); + + if (row) { + int ret= Buffer_ass_slice(row, 0, self->dimensions[1], v); + Py_DECREF(row); + return ret; + } + else { return -1; + } } - else if (buf->type==GL_DOUBLE) { - if (!PyArg_Parse(v, "d:Coordinates must be floats", &buf->buf.asdouble[i])) - return -1; + + switch(self->type) { + case GL_BYTE: + return PyArg_Parse(v, "b:Expected ints", &self->buf.asbyte[i]) ? 0:-1; + case GL_SHORT: + return PyArg_Parse(v, "h:Expected ints", &self->buf.asshort[i]) ? 0:-1; + case GL_INT: + return PyArg_Parse(v, "i:Expected ints", &self->buf.asint[i]) ? 0:-1; + case GL_FLOAT: + return PyArg_Parse(v, "f:Expected floats", &self->buf.asfloat[i]) ? 0:-1; + case GL_DOUBLE: + return PyArg_Parse(v, "d:Expected floats", &self->buf.asdouble[i]) ? 0:-1; + default: + return 0; /* should never happen */ } - return 0; } -static int Buffer_ass_slice(PyObject *self, int begin, int end, PyObject *seq) +static int Buffer_ass_slice(Buffer *self, int begin, int end, PyObject *seq) { - Buffer *buf= (Buffer *) self; PyObject *item; int count, err=0; - if (begin<0) begin= 0; - if (end>buf->dimensions[0]) end= buf->dimensions[0]; - if (begin>end) begin= end; + if (begin < 0) begin= 0; + if (end > self->dimensions[0]) end= self->dimensions[0]; + if (begin > end) begin= end; if (!PySequence_Check(seq)) { - PyErr_SetString(PyExc_TypeError, - "illegal argument type for built-in operation"); + PyErr_Format(PyExc_TypeError, + "buffer[:] = value, invalid assignment. " + "Expected a sequence, not an %.200s type", + Py_TYPE(seq)->tp_name); return -1; } - if (PySequence_Size(seq)!=(end-begin)) { - int seq_len = PySequence_Size(seq); - char err_str[128]; - sprintf(err_str, "size mismatch in assignment. Expected size: %d (size provided: %d)", seq_len, (end-begin)); - PyErr_SetString(PyExc_TypeError, err_str); + /* re-use count var */ + if ((count= PySequence_Size(seq)) != (end - begin)) { + PyErr_Format(PyExc_TypeError, + "buffer[:] = value, size mismatch in assignment. " + "Expected: %d (given: %d)", count, end - begin); return -1; } - for (count= begin; count<end; count++) { - item= PySequence_GetItem(seq, count-begin); - err= Buffer_ass_item(self, count, item); - Py_DECREF(item); + for (count= begin; count < end; count++) { + item= PySequence_GetItem(seq, count - begin); + if(item) { + err= Buffer_ass_item(self, count, item); + Py_DECREF(item); + } + else { + err= -1; + } if (err) break; } return err; } -static void Buffer_dealloc(PyObject *self) +static PyObject *Buffer_subscript(Buffer *self, PyObject *item) { - Buffer *buf = (Buffer *)self; + 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->dimensions[0]; + return Buffer_item(self, i); + } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; - if (buf->parent) Py_DECREF (buf->parent); - else MEM_freeN (buf->buf.asvoid); + if (PySlice_GetIndicesEx((void *)item, self->dimensions[0], &start, &stop, &step, &slicelength) < 0) + return NULL; - MEM_freeN (buf->dimensions); - - PyObject_DEL (self); + if (slicelength <= 0) { + return PyTuple_New(0); + } + else if (step == 1) { + return Buffer_slice(self, start, stop); + } + else { + PyErr_SetString(PyExc_IndexError, + "slice steps not supported with vectors"); + return NULL; + } + } + else { + PyErr_Format(PyExc_TypeError, + "buffer indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); + return NULL; + } } -static PyObject *Buffer_tolist(PyObject *self) +static int Buffer_ass_subscript(Buffer *self, PyObject *item, PyObject *value) { - int i, len= ((Buffer *)self)->dimensions[0]; - PyObject *list= PyList_New(len); - - for (i=0; i<len; i++) { - PyList_SET_ITEM(list, i, Buffer_item(self, i)); + 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->dimensions[0]; + return Buffer_ass_item(self, i, value); } + else if (PySlice_Check(item)) { + Py_ssize_t start, stop, step, slicelength; - return list; + if (PySlice_GetIndicesEx((void *)item, self->dimensions[0], &start, &stop, &step, &slicelength) < 0) + return -1; + + if (step == 1) + return Buffer_ass_slice(self, start, stop, value); + else { + PyErr_SetString(PyExc_IndexError, + "slice steps not supported with vectors"); + return -1; + } + } + else { + PyErr_Format(PyExc_TypeError, + "buffer indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); + return -1; + } } -static PyObject *Buffer_dimensions(PyObject *self) + +static void Buffer_dealloc(Buffer *self) { - Buffer *buffer= (Buffer *) self; - PyObject *list= PyList_New(buffer->ndimensions); - int i; + if (self->parent) Py_DECREF(self->parent); + else MEM_freeN (self->buf.asvoid); - for (i= 0; i<buffer->ndimensions; i++) { - PyList_SET_ITEM(list, i, PyLong_FromLong(buffer->dimensions[i])); - } + MEM_freeN(self->dimensions); - return list; + PyObject_DEL(self); } -static PyObject *Buffer_getattr(PyObject *self, char *name) -{ - if (strcmp(name, "list")==0) return Buffer_tolist(self); - else if (strcmp(name, "dimensions")==0) return Buffer_dimensions(self); - - PyErr_SetString(PyExc_AttributeError, name); - return NULL; -} -static PyObject *Buffer_repr(PyObject *self) +static PyObject *Buffer_repr(Buffer *self) { - PyObject *list= Buffer_tolist(self); - PyObject *repr= PyObject_Repr(list); + PyObject *list= Buffer_to_list_recursive(self); + PyObject *repr; + const char *typestr= "UNKNOWN"; + + switch(self->type) { + case GL_BYTE: typestr= "GL_BYTE"; break; + case GL_SHORT: typestr= "GL_SHORT"; break; + case GL_INT: typestr= "GL_BYTE"; break; + case GL_FLOAT: typestr= "GL_FLOAT"; break; + case GL_DOUBLE: typestr= "GL_DOUBLE"; break; + } + + repr= PyUnicode_FromFormat("Buffer(%s, %R)", typestr, list); Py_DECREF(list); - + return repr; } @@ -805,7 +956,6 @@ BGLU_Wrap(9, UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdo * {"glAccum", Method_Accumfunc, METH_VARARGS} */ static struct PyMethodDef BGL_methods[] = { - {"Buffer", Method_Buffer, METH_VARARGS, Method_Buffer_doc}, /* #ifndef __APPLE__ */ MethodDef(Accum), @@ -1153,9 +1303,12 @@ PyObject *BPyInit_bgl(void) submodule= PyModule_Create(&BGL_module_def); dict= PyModule_GetDict(submodule); - if( PyType_Ready( &BGL_bufferType) < 0) + if(PyType_Ready(&BGL_bufferType) < 0) return NULL; /* should never happen */ + + PyModule_AddObject(submodule, "Buffer", (PyObject *)&BGL_bufferType); + #define EXPP_ADDCONST(x) PyDict_SetItemString(dict, #x, item=PyLong_FromLong((int)x)); Py_DECREF(item) /* So, for example: diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 801e44bd008..81aea8571f8 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -36,8 +36,6 @@ #include "BLI_path_util.h" #endif -#define PYC_INTERPRETER_ACTIVE (((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL) - /* array utility function */ int PyC_AsArray(void *array, PyObject *value, const int length, const PyTypeObject *type, const short is_double, const char *error_prefix) { diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index bf2eb175882..96c93ab71f8 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -50,4 +50,6 @@ void PyC_MainModule_Restore(PyObject *main_mod); void PyC_SetHomePath(const char *py_path_bundle); +#define PYC_INTERPRETER_ACTIVE (((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)) != NULL) + #endif // PY_CAPI_UTILS_H diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index 31a4b623798..d6a41b561fd 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -25,13 +25,13 @@ set(INC .. + ../../blenkernel ../../blenlib + ../../blenloader + ../../editors/include ../../makesdna ../../makesrna - ../../blenkernel - ../../blenloader ../../windowmanager - ../../editors/include ../../freestyle/intern/python ../../../../intern/guardedalloc ) @@ -89,9 +89,6 @@ if(WITH_PYTHON_SAFETY) endif() if(WITH_AUDASPACE) - list(APPEND INC - ../../../intern/audaspace/intern - ) add_definitions(-DWITH_AUDASPACE) endif() diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index fb94b827dea..a9b75734288 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -55,10 +55,10 @@ #include "MEM_guardedalloc.h" /* external util modules */ -#include "../generic/mathutils.h" +#include "../generic/IDProp.h" #include "../generic/bgl.h" #include "../generic/blf_py_api.h" -#include "../generic/IDProp.h" +#include "../mathutils/mathutils.h" #include "BPy_Freestyle.h" diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index dec393bd1e4..bcd5df97c2c 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -41,6 +41,8 @@ #include "bpy_driver.h" +#include "../generic/py_capi_utils.h" + /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */ PyObject *bpy_pydriver_Dict= NULL; @@ -87,7 +89,7 @@ int bpy_pydriver_create_dict(void) void BPY_driver_reset(void) { PyGILState_STATE gilstate; - int use_gil= 1; // (PyThreadState_Get()==NULL); + int use_gil= !PYC_INTERPRETER_ACTIVE; if(use_gil) gilstate= PyGILState_Ensure(); @@ -120,7 +122,7 @@ static void pydriver_error(ChannelDriver *driver) * * note: PyGILState_Ensure() isnt always called because python can call the * bake operator which intern starts a thread which calls scene update which - * does a driver update. to avoid a deadlock check PyThreadState_Get() if PyGILState_Ensure() is needed. + * does a driver update. to avoid a deadlock check PYC_INTERPRETER_ACTIVE if PyGILState_Ensure() is needed. */ float BPY_driver_exec(ChannelDriver *driver) { @@ -147,7 +149,7 @@ float BPY_driver_exec(ChannelDriver *driver) return 0.0f; } - use_gil= 1; //(PyThreadState_Get()==NULL); + use_gil= !PYC_INTERPRETER_ACTIVE; if(use_gil) gilstate= PyGILState_Ensure(); diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 51bf02ad37f..8bd6e6c611c 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -66,10 +66,10 @@ #include "../generic/py_capi_utils.h" /* inittab initialization functions */ -#include "../generic/noise_py_api.h" -#include "../generic/mathutils.h" #include "../generic/bgl.h" #include "../generic/blf_py_api.h" +#include "../generic/noise_py_api.h" +#include "../mathutils/mathutils.h" /* for internal use, when starting and ending python scripts */ @@ -175,8 +175,8 @@ extern PyObject *AUD_initPython(void); static struct _inittab bpy_internal_modules[]= { {(char *)"noise", BPyInit_noise}, - {(char *)"mathutils", BPyInit_mathutils}, -// {(char *)"mathutils.geometry", BPyInit_mathutils_geometry}, + {(char *)"mathutils", PyInit_mathutils}, +// {(char *)"mathutils.geometry", PyInit_mathutils_geometry}, {(char *)"bgl", BPyInit_bgl}, {(char *)"blf", BPyInit_blf}, #ifdef WITH_AUDASPACE @@ -209,8 +209,6 @@ void BPY_python_start(int argc, const char **argv) Py_Initialize(); - bpy_intern_string_init(); - // PySys_SetArgv(argc, argv); // broken in py3, not a huge deal /* sigh, why do python guys not have a char** version anymore? :( */ { @@ -233,6 +231,8 @@ void BPY_python_start(int argc, const char **argv) PyImport_ExtendInittab(bpy_internal_modules); #endif + bpy_intern_string_init(); + /* bpy.* and lets us import it */ BPy_init_modules(); @@ -663,7 +663,9 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * #include "BLI_storage.h" /* TODO, reloading the module isnt functional at the moment. */ -extern int main_python(int argc, const char **argv); +static void bpy_module_free(void *mod); +extern int main_python_enter(int argc, const char **argv); +extern void main_python_exit(void); static struct PyModuleDef bpy_proxy_def= { PyModuleDef_HEAD_INIT, "bpy", /* m_name */ @@ -673,8 +675,8 @@ static struct PyModuleDef bpy_proxy_def= { NULL, /* m_reload */ NULL, /* m_traverse */ NULL, /* m_clear */ - NULL, /* m_free */ -}; + bpy_module_free, /* m_free */ +}; typedef struct { PyObject_HEAD @@ -699,7 +701,7 @@ void bpy_module_delay_init(PyObject *bpy_proxy) // printf("module found %s\n", argv[0]); - main_python(argc, argv); + main_python_enter(argc, argv); /* initialized in BPy_init_modules() */ PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py)); @@ -756,4 +758,9 @@ PyInit_bpy(void) return bpy_proxy; } +static void bpy_module_free(void *UNUSED(mod)) +{ + main_python_exit(); +} + #endif diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index c1c7e0ea740..6e1b9c807f3 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -346,7 +346,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item); #ifdef USE_MATHUTILS -#include "../generic/mathutils.h" /* so we can have mathutils callbacks */ +#include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */ static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length); static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, short order_fallback); @@ -3847,9 +3847,11 @@ static PyObject *foreach_getset(BPy_PropertyRNA *self, PyObject *args, int set) case PROP_RAW_DOUBLE: item= PyFloat_FromDouble((double) ((double *)array)[i]); break; - case PROP_RAW_UNSET: + default: /* PROP_RAW_UNSET */ /* should never happen */ BLI_assert(!"Invalid array type - get"); + item= Py_None; + Py_INCREF(item); break; } @@ -4546,7 +4548,7 @@ PyTypeObject pyrna_struct_meta_idprop_Type= { NULL, /* printfunc tp_print; */ NULL, /* getattrfunc tp_getattr; */ NULL, /* setattrfunc tp_setattr; */ - NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ + NULL, /* tp_compare */ /* deprecated in python 3.0! */ NULL, /* tp_repr */ /* Method suites for standard classes */ diff --git a/source/blender/python/mathutils/CMakeLists.txt b/source/blender/python/mathutils/CMakeLists.txt new file mode 100644 index 00000000000..b28496d612e --- /dev/null +++ b/source/blender/python/mathutils/CMakeLists.txt @@ -0,0 +1,52 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Contributor(s): Campbell Barton +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + ../../blenlib + ../../blenkernel + ../../makesdna + ../../../../intern/guardedalloc +) + +set(INC_SYS + ${PYTHON_INCLUDE_DIRS} +) + +set(SRC + mathutils.c + mathutils_Color.c + mathutils_Euler.c + mathutils_Matrix.c + mathutils_Quaternion.c + mathutils_Vector.c + mathutils_geometry.c + + mathutils.h + mathutils_Color.h + mathutils_Euler.h + mathutils_Matrix.h + mathutils_Quaternion.h + mathutils_Vector.h + mathutils_geometry.h +) + + +blender_add_lib(bf_python_mathutils "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/python/generic/mathutils.c b/source/blender/python/mathutils/mathutils.c index 30f4e5b7ffe..50b75b09cb2 100644 --- a/source/blender/python/generic/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -57,8 +57,16 @@ static int mathutils_array_parse_fast(float *array, int array_min, int array_max size= PySequence_Fast_GET_SIZE(value_fast); 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); + 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; } @@ -67,7 +75,10 @@ static int mathutils_array_parse_fast(float *array, int array_min, int array_max do { i--; if(((array[i]= PyFloat_AsDouble((item= PySequence_Fast_GET_ITEM(value_fast, i)))) == -1.0f) && PyErr_Occurred()) { - PyErr_Format(PyExc_ValueError, "%.200s: sequence index %d expected a number, found '%.200s' type, ", error_prefix, i, Py_TYPE(item)->tp_name); + PyErr_Format(PyExc_TypeError, + "%.200s: sequence index %d expected a number, " + "found '%.200s' type, ", + error_prefix, i, Py_TYPE(item)->tp_name); Py_DECREF(value_fast); return -1; } @@ -93,8 +104,16 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject * } 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); + 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; } @@ -135,7 +154,9 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error return -1; } else if(((MatrixObject *)value)->col_size < 3 || ((MatrixObject *)value)->row_size < 3) { - PyErr_Format(PyExc_ValueError, "%.200s: matrix must have minimum 3x3 dimensions", error_prefix); + PyErr_Format(PyExc_ValueError, + "%.200s: matrix must have minimum 3x3 dimensions", + error_prefix); return -1; } else { @@ -145,7 +166,9 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error } } else { - PyErr_Format(PyExc_TypeError, "%.200s: expected a Euler, Quaternion or Matrix type, found %.200s", error_prefix, Py_TYPE(value)->tp_name); + PyErr_Format(PyExc_TypeError, + "%.200s: expected a Euler, Quaternion or Matrix type, " + "found %.200s", error_prefix, Py_TYPE(value)->tp_name); return -1; } } @@ -213,8 +236,11 @@ int _BaseMathObject_ReadCallback(BaseMathObject *self) if(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); + if(!PyErr_Occurred()) { + PyErr_Format(PyExc_RuntimeError, + "%s read, user has become invalid", + Py_TYPE(self)->tp_name); + } return -1; } @@ -224,8 +250,11 @@ int _BaseMathObject_WriteCallback(BaseMathObject *self) if(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); + if(!PyErr_Occurred()) { + PyErr_Format(PyExc_RuntimeError, + "%s write, user has become invalid", + Py_TYPE(self)->tp_name); + } return -1; } @@ -235,8 +264,11 @@ int _BaseMathObject_ReadIndexCallback(BaseMathObject *self, int index) if(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); + if(!PyErr_Occurred()) { + PyErr_Format(PyExc_RuntimeError, + "%s read index, user has become invalid", + Py_TYPE(self)->tp_name); + } return -1; } @@ -246,8 +278,11 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index) if(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); + if(!PyErr_Occurred()) { + PyErr_Format(PyExc_RuntimeError, + "%s write index, user has become invalid", + Py_TYPE(self)->tp_name); + } return -1; } @@ -310,7 +345,7 @@ static struct PyModuleDef M_Mathutils_module_def = { NULL, /* m_free */ }; -PyMODINIT_FUNC BPyInit_mathutils(void) +PyMODINIT_FUNC PyInit_mathutils(void) { PyObject *submodule; PyObject *item; @@ -336,7 +371,7 @@ PyMODINIT_FUNC BPyInit_mathutils(void) PyModule_AddObject(submodule, "Color", (PyObject *)&color_Type); /* submodule */ - PyModule_AddObject(submodule, "geometry", (item=BPyInit_mathutils_geometry())); + PyModule_AddObject(submodule, "geometry", (item=PyInit_mathutils_geometry())); /* XXX, python doesnt do imports with this usefully yet * 'from mathutils.geometry import PolyFill' * ...fails without this. */ diff --git a/source/blender/python/generic/mathutils.h b/source/blender/python/mathutils/mathutils.h index 449708d1ac1..7454cfe78b3 100644 --- a/source/blender/python/generic/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -67,7 +67,7 @@ int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg); int BaseMathObject_clear(BaseMathObject *self); void BaseMathObject_dealloc(BaseMathObject * self); -PyMODINIT_FUNC BPyInit_mathutils(void); +PyMODINIT_FUNC PyInit_mathutils(void); int EXPP_FloatsAreEqual(float A, float B, int floatSteps); int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps); diff --git a/source/blender/python/generic/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index c59cb501d86..d0c7ec72cea 100644 --- a/source/blender/python/generic/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -43,7 +43,9 @@ 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"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Color(): " + "takes no keyword args"); return NULL; } @@ -55,7 +57,9 @@ static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; break; default: - PyErr_SetString(PyExc_TypeError, "mathutils.Color(): more then a single arg given"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Color(): " + "more then a single arg given"); return NULL; } return newColorObject(col, Py_NEW, type); @@ -174,7 +178,9 @@ 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[attribute]: array index out of range"); + PyErr_SetString(PyExc_IndexError, + "color[attribute]: " + "array index out of range"); return NULL; } @@ -191,14 +197,17 @@ static int Color_ass_item(ColorObject * self, int i, PyObject *value) float f = PyFloat_AsDouble(value); if(f == -1 && PyErr_Occurred()) { // parsed item not a number - PyErr_SetString(PyExc_TypeError, "color[attribute] = x: argument not a number"); + PyErr_SetString(PyExc_TypeError, + "color[attribute] = x: " + "argument not a number"); return -1; } if(i<0) i= COLOR_SIZE-i; if(i < 0 || i >= COLOR_SIZE){ - PyErr_SetString(PyExc_IndexError, "color[attribute] = x: array assignment index out of range"); + PyErr_SetString(PyExc_IndexError, "color[attribute] = x: " + "array assignment index out of range"); return -1; } @@ -250,7 +259,9 @@ static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq) return -1; if(size != (end - begin)){ - PyErr_SetString(PyExc_TypeError, "color[begin:end] = []: size mismatch in slice assignment"); + PyErr_SetString(PyExc_ValueError, + "color[begin:end] = []: " + "size mismatch in slice assignment"); return -1; } @@ -285,12 +296,15 @@ static PyObject *Color_subscript(ColorObject *self, PyObject *item) return Color_slice(self, start, stop); } else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with color"); + 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); + PyErr_Format(PyExc_TypeError, + "color indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return NULL; } } @@ -314,12 +328,15 @@ static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *valu if (step == 1) return Color_ass_slice(self, start, stop, value); else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with color"); + 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); + PyErr_Format(PyExc_TypeError, + "color indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return -1; } } @@ -354,7 +371,9 @@ static PyObject *Color_add(PyObject *v1, PyObject *v2) float col[COLOR_SIZE]; if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Color addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Color addition: " + "arguments not valid for this operation"); return NULL; } color1 = (ColorObject*)v1; @@ -374,7 +393,9 @@ static PyObject *Color_iadd(PyObject *v1, PyObject *v2) ColorObject *color1 = NULL, *color2 = NULL; if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Color addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Color addition: " + "arguments not valid for this operation"); return NULL; } color1 = (ColorObject*)v1; @@ -397,7 +418,9 @@ static PyObject *Color_sub(PyObject *v1, PyObject *v2) float col[COLOR_SIZE]; if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Color subtraction: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Color subtraction: " + "arguments not valid for this operation"); return NULL; } color1 = (ColorObject*)v1; @@ -417,7 +440,9 @@ static PyObject *Color_isub(PyObject *v1, PyObject *v2) ColorObject *color1= NULL, *color2= NULL; if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Color subtraction: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Color subtraction: " + "arguments not valid for this operation"); return NULL; } color1 = (ColorObject*)v1; @@ -476,7 +501,10 @@ static PyObject *Color_mul(PyObject *v1, PyObject *v2) 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); + 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; } @@ -491,20 +519,25 @@ static PyObject *Color_div(PyObject *v1, PyObject *v2) return NULL; } else { - PyErr_SetString(PyExc_TypeError, "Color division not supported in this order"); + 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"); + 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); + 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; } @@ -522,7 +555,9 @@ static PyObject *Color_imul(PyObject *v1, PyObject *v2) mul_vn_fl(color->col, COLOR_SIZE, scalar); } else { - PyErr_SetString(PyExc_TypeError, "Color multiplication: arguments not acceptable for this operation"); + PyErr_SetString(PyExc_TypeError, + "Color multiplication: " + "arguments not acceptable for this operation"); return NULL; } @@ -543,14 +578,17 @@ static PyObject *Color_idiv(PyObject *v1, PyObject *v2) /* 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"); + PyErr_SetString(PyExc_ZeroDivisionError, + "Color division: divide by zero error"); return NULL; } mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar); } else { - PyErr_SetString(PyExc_TypeError, "Color multiplication: arguments not acceptable for this operation"); + PyErr_SetString(PyExc_TypeError, + "Color multiplication: " + "arguments not acceptable for this operation"); return NULL; } @@ -642,7 +680,9 @@ static int Color_setChannelHSV(ColorObject * self, PyObject *value, void * type) float f = PyFloat_AsDouble(value); if(f == -1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "color.h/s/v = value: argument not a number"); + PyErr_SetString(PyExc_TypeError, + "color.h/s/v = value: " + "argument not a number"); return -1; } @@ -808,8 +848,7 @@ PyObject *newColorObject(float *col, int type, PyTypeObject *base_type) self->wrapped = Py_NEW; } else { - PyErr_SetString(PyExc_RuntimeError, "Color(): invalid type"); - return NULL; + Py_FatalError("Color(): invalid type!"); } } diff --git a/source/blender/python/generic/mathutils_Color.h b/source/blender/python/mathutils/mathutils_Color.h index 0fc880363f4..0fc880363f4 100644 --- a/source/blender/python/generic/mathutils_Color.h +++ b/source/blender/python/mathutils/mathutils_Color.h diff --git a/source/blender/python/generic/mathutils_Euler.c b/source/blender/python/mathutils/mathutils_Euler.c index 4281c7bf6c5..5c609d8961f 100644 --- a/source/blender/python/generic/mathutils_Euler.c +++ b/source/blender/python/mathutils/mathutils_Euler.c @@ -38,10 +38,6 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#ifndef int32_t -#include "BLO_sys_types.h" -#endif - #define EULER_SIZE 3 //----------------------------------mathutils.Euler() ------------------- @@ -55,7 +51,9 @@ static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds) short order= EULER_ORDER_XYZ; if(kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, "mathutils.Euler(): takes no keyword args"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Euler(): " + "takes no keyword args"); return NULL; } @@ -87,7 +85,7 @@ static const char *euler_order_str(EulerObject *self) short euler_order_from_string(const char *str, const char *error_prefix) { if((str[0] && str[1] && str[2] && str[3]=='\0')) { - switch(*((int32_t *)str)) { + switch(*((PY_INT32_T *)str)) { case 'X'|'Y'<<8|'Z'<<16: return EULER_ORDER_XYZ; case 'X'|'Z'<<8|'Y'<<16: return EULER_ORDER_XZY; case 'Y'|'X'<<8|'Z'<<16: return EULER_ORDER_YXZ; @@ -97,7 +95,9 @@ short euler_order_from_string(const char *str, const char *error_prefix) } } - PyErr_Format(PyExc_TypeError, "%s: invalid euler order '%s'", error_prefix, str); + PyErr_Format(PyExc_ValueError, + "%s: invalid euler order '%s'", + error_prefix, str); return -1; } @@ -199,11 +199,14 @@ static PyObject *Euler_rotate_axis(EulerObject * self, PyObject *args) const char *axis; if(!PyArg_ParseTuple(args, "sf:rotate", &axis, &angle)){ - PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected angle (float) and axis (x, y, z)"); + PyErr_SetString(PyExc_TypeError, + "euler.rotate(): " + "expected angle (float) and axis (x, y, z)"); return NULL; } if(!(ELEM3(*axis, 'X', 'Y', 'Z') && axis[1]=='\0')){ - PyErr_SetString(PyExc_TypeError, "euler.rotate(): expected axis to be 'X', 'Y' or 'Z'"); + PyErr_SetString(PyExc_ValueError, "euler.rotate(): " + "expected axis to be 'X', 'Y' or 'Z'"); return NULL; } @@ -360,7 +363,9 @@ 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"); + PyErr_SetString(PyExc_IndexError, + "euler[attribute]: " + "array index out of range"); return NULL; } @@ -377,14 +382,18 @@ static int Euler_ass_item(EulerObject * self, int i, PyObject *value) float f = PyFloat_AsDouble(value); if(f == -1 && PyErr_Occurred()) { // parsed item not a number - PyErr_SetString(PyExc_TypeError, "euler[attribute] = x: argument not a number"); + PyErr_SetString(PyExc_TypeError, + "euler[attribute] = x: " + "argument 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"); + PyErr_SetString(PyExc_IndexError, + "euler[attribute] = x: " + "array assignment index out of range"); return -1; } @@ -436,7 +445,9 @@ static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq) return -1; if(size != (end - begin)){ - PyErr_SetString(PyExc_TypeError, "euler[begin:end] = []: size mismatch in slice assignment"); + PyErr_SetString(PyExc_ValueError, + "euler[begin:end] = []: " + "size mismatch in slice assignment"); return -1; } @@ -471,12 +482,15 @@ static PyObject *Euler_subscript(EulerObject *self, PyObject *item) return Euler_slice(self, start, stop); } else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with eulers"); + 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); + PyErr_Format(PyExc_TypeError, + "euler indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return NULL; } } @@ -501,12 +515,15 @@ static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *valu if (step == 1) return Euler_ass_slice(self, start, stop, value); else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with euler"); + 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); + PyErr_Format(PyExc_TypeError, + "euler indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return -1; } } @@ -680,8 +697,7 @@ PyObject *newEulerObject(float *eul, short order, int type, PyTypeObject *base_t self->wrapped = Py_NEW; } else { - PyErr_SetString(PyExc_RuntimeError, "Euler(): invalid type"); - return NULL; + Py_FatalError("Euler(): invalid type!"); } self->order= order; diff --git a/source/blender/python/generic/mathutils_Euler.h b/source/blender/python/mathutils/mathutils_Euler.h index 849e16c2bb7..849e16c2bb7 100644 --- a/source/blender/python/generic/mathutils_Euler.h +++ b/source/blender/python/mathutils/mathutils_Euler.h diff --git a/source/blender/python/generic/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 4b7f9dc0d97..a7ed63776a5 100644 --- a/source/blender/python/generic/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -35,7 +35,6 @@ #include "mathutils.h" #include "BLI_math.h" -#include "BLI_blenlib.h" #include "BLI_utildefines.h" static PyObject *Matrix_copy(MatrixObject *self); @@ -119,7 +118,9 @@ Mathutils_Callback mathutils_matrix_vector_cb = { static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { if(kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, "mathutils.Matrix(): takes no keyword args"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Matrix(): " + "takes no keyword args"); return NULL; } @@ -130,7 +131,8 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *arg= PyTuple_GET_ITEM(args, 0); - const unsigned short row_size= PySequence_Size(arg); /* -1 is an error, size checks will accunt for this */ + /* -1 is an error, size checks will accunt for this */ + const unsigned short row_size= PySequence_Size(arg); if(row_size >= 2 && row_size <= 4) { PyObject *item= PySequence_GetItem(arg, 0); @@ -152,7 +154,9 @@ static PyObject *Matrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } /* will overwrite error */ - PyErr_SetString(PyExc_TypeError, "mathutils.Matrix(): expects no args or 2-4 numeric sequences"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Matrix(): " + "expects no args or 2-4 numeric sequences"); return NULL; } @@ -211,14 +215,19 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; if(!PyArg_ParseTuple(args, "di|O", &angle, &matSize, &vec)) { - PyErr_SetString(PyExc_TypeError, "mathutils.RotationMatrix(angle, size, axis): expected float int and a string or vector"); + PyErr_SetString(PyExc_TypeError, + "mathutils.RotationMatrix(angle, size, axis): " + "expected float int and a string or vector"); 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_TypeError, "mathutils.RotationMatrix(): 3rd argument axis value must be a 3D vector or a string in 'X', 'Y', 'Z'"); + PyErr_SetString(PyExc_ValueError, + "mathutils.RotationMatrix(): " + "3rd argument axis value must be a 3D vector " + "or a string in 'X', 'Y', 'Z'"); return NULL; } else { @@ -230,15 +239,21 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) angle= angle_wrap_rad(angle); if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): can only return a 2x2 3x3 or 4x4 matrix"); + PyErr_SetString(PyExc_ValueError, + "mathutils.RotationMatrix(): " + "can only return a 2x2 3x3 or 4x4 matrix"); return NULL; } if(matSize == 2 && (vec != NULL)) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): cannot create a 2x2 rotation matrix around arbitrary axis"); + PyErr_SetString(PyExc_ValueError, + "mathutils.RotationMatrix(): " + "cannot create a 2x2 rotation matrix around arbitrary axis"); return NULL; } if((matSize == 3 || matSize == 4) && (axis == NULL) && (vec == NULL)) { - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): axis of rotation for 3d and 4d matrices is required"); + PyErr_SetString(PyExc_ValueError, + "mathutils.RotationMatrix(): " + "axis of rotation for 3d and 4d matrices is required"); return NULL; } @@ -284,7 +299,8 @@ static PyObject *C_Matrix_Rotation(PyObject *cls, PyObject *args) } else { /* should never get here */ - PyErr_SetString(PyExc_AttributeError, "mathutils.RotationMatrix(): unknown error"); + PyErr_SetString(PyExc_ValueError, + "mathutils.RotationMatrix(): unknown error"); return NULL; } @@ -348,7 +364,9 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) return NULL; } if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError, "Matrix.Scale(): can only return a 2x2 3x3 or 4x4 matrix"); + PyErr_SetString(PyExc_ValueError, + "Matrix.Scale(): " + "can only return a 2x2 3x3 or 4x4 matrix"); return NULL; } if(vec) { @@ -361,7 +379,8 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) if(matSize == 2) { mat[0] = factor; mat[3] = factor; - } else { + } + else { mat[0] = factor; mat[4] = factor; mat[8] = factor; @@ -383,7 +402,8 @@ static PyObject *C_Matrix_Scale(PyObject *cls, PyObject *args) 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 { + } + 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])); @@ -430,7 +450,9 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) return NULL; } if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError,"mathutils.Matrix.OrthoProjection(): can only return a 2x2 3x3 or 4x4 matrix"); + PyErr_SetString(PyExc_ValueError, + "mathutils.Matrix.OrthoProjection(): " + "can only return a 2x2 3x3 or 4x4 matrix"); return NULL; } @@ -445,7 +467,10 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) mat[3]= 1.0f; } else { - PyErr_Format(PyExc_ValueError, "mathutils.Matrix.OrthoProjection(): unknown plane, expected: X, Y, not '%.200s'", plane); + PyErr_Format(PyExc_ValueError, + "mathutils.Matrix.OrthoProjection(): " + "unknown plane, expected: X, Y, not '%.200s'", + plane); return NULL; } } @@ -463,7 +488,10 @@ static PyObject *C_Matrix_OrthoProjection(PyObject *cls, PyObject *args) mat[8]= 1.0f; } else { - PyErr_Format(PyExc_ValueError, "mathutils.Matrix.OrthoProjection(): unknown plane, expected: XY, XZ, YZ, not '%.200s'", plane); + PyErr_Format(PyExc_ValueError, + "mathutils.Matrix.OrthoProjection(): " + "unknown plane, expected: XY, XZ, YZ, not '%.200s'", + plane); return NULL; } } @@ -539,7 +567,9 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) return NULL; } if(matSize != 2 && matSize != 3 && matSize != 4) { - PyErr_SetString(PyExc_AttributeError,"mathutils.Matrix.Shear(): can only return a 2x2 3x3 or 4x4 matrix"); + PyErr_SetString(PyExc_ValueError, + "mathutils.Matrix.Shear(): " + "can only return a 2x2 3x3 or 4x4 matrix"); return NULL; } @@ -547,7 +577,9 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) float const factor= PyFloat_AsDouble(fac); if(factor==-1.0f && PyErr_Occurred()) { - PyErr_SetString(PyExc_AttributeError, "mathutils.Matrix.Shear(): the factor to be a float"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Matrix.Shear(): " + "the factor to be a float"); return NULL; } @@ -562,7 +594,9 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) mat[1] = factor; } else { - PyErr_SetString(PyExc_AttributeError, "Matrix.Shear(): expected: X, Y or wrong matrix size for shearing plane"); + PyErr_SetString(PyExc_ValueError, + "Matrix.Shear(): " + "expected: X, Y or wrong matrix size for shearing plane"); return NULL; } } @@ -592,7 +626,9 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) mat[2] = factor[1]; } else { - PyErr_SetString(PyExc_AttributeError, "mathutils.Matrix.Shear(): expected: X, Y, XY, XZ, YZ"); + PyErr_SetString(PyExc_ValueError, + "mathutils.Matrix.Shear(): " + "expected: X, Y, XY, XZ, YZ"); return NULL; } } @@ -624,7 +660,8 @@ static float matrix_determinant_internal(MatrixObject *self) self->matrix[1][1], self->matrix[1][2], self->matrix[2][0], self->matrix[2][1], self->matrix[2][2]); - } else { + } + else { return determinant_m4((float (*)[4])self->contigPtr); } } @@ -648,7 +685,9 @@ static PyObject *Matrix_to_quaternion(MatrixObject *self) /*must be 3-4 cols, 3-4 rows, square matrix*/ if((self->col_size < 3) || (self->row_size < 3) || (self->col_size != self->row_size)) { - PyErr_SetString(PyExc_AttributeError, "Matrix.to_quat(): inappropriate matrix size - expects 3x3 or 4x4 matrix"); + PyErr_SetString(PyExc_ValueError, + "matrix.to_quat(): " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); return NULL; } if(self->col_size == 3){ @@ -661,7 +700,7 @@ static PyObject *Matrix_to_quaternion(MatrixObject *self) return newQuaternionObject(quat, Py_NEW, NULL); } -/*---------------------------Matrix.toEuler() --------------------*/ +/*---------------------------matrix.toEuler() --------------------*/ PyDoc_STRVAR(Matrix_to_euler_doc, ".. method:: to_euler(order, euler_compat)\n" "\n" @@ -710,12 +749,14 @@ static PyObject *Matrix_to_euler(MatrixObject *self, PyObject *args) mat= tmat; } else { - PyErr_SetString(PyExc_AttributeError, "Matrix.to_euler(): inappropriate matrix size - expects 3x3 or 4x4 matrix"); + 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()"); + order= euler_order_from_string(order_str, "matrix.to_euler()"); if(order == -1) return NULL; @@ -743,17 +784,20 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self) int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index; if(self->wrapped==Py_WRAP){ - PyErr_SetString(PyExc_TypeError, "cannot resize wrapped data - make a copy and resize that"); + PyErr_SetString(PyExc_TypeError, + "cannot resize wrapped data - make a copy and resize that"); return NULL; } if(self->cb_user){ - PyErr_SetString(PyExc_TypeError, "cannot resize owned data - make a copy and resize that"); + PyErr_SetString(PyExc_TypeError, + "cannot resize owned data - make a copy and resize that"); return NULL; } self->contigPtr = PyMem_Realloc(self->contigPtr, (sizeof(float) * 16)); if(self->contigPtr == NULL) { - PyErr_SetString(PyExc_MemoryError, "matrix.resize_4x4(): problem allocating pointer space"); + PyErr_SetString(PyExc_MemoryError, + "matrix.resize_4x4(): problem allocating pointer space"); return NULL; } /*set row pointers*/ @@ -779,7 +823,7 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self) for(blank_columns = (4 - self->col_size); blank_columns > 0; blank_columns--){ self->contigPtr[new_pos + blank_columns] = 0.0f; } - for(curr_pos = curr_pos; curr_pos >= first_row_elem; curr_pos--){ + for( ; curr_pos >= first_row_elem; curr_pos--){ self->contigPtr[new_pos] = self->contigPtr[curr_pos]; new_pos--; } @@ -813,7 +857,8 @@ static PyObject *Matrix_to_4x4(MatrixObject *self) } /* TODO, 2x2 matrix */ - PyErr_SetString(PyExc_TypeError, "Matrix.to_4x4(): inappropriate matrix size"); + PyErr_SetString(PyExc_TypeError, + "matrix.to_4x4(): inappropriate matrix size"); return NULL; } @@ -833,7 +878,8 @@ static PyObject *Matrix_to_3x3(MatrixObject *self) return NULL; if((self->col_size < 3) || (self->row_size < 3)) { - PyErr_SetString(PyExc_AttributeError, "Matrix.to_3x3(): inappropriate matrix size"); + PyErr_SetString(PyExc_TypeError, + "matrix.to_3x3(): inappropriate matrix size"); return NULL; } @@ -856,7 +902,9 @@ static PyObject *Matrix_to_translation(MatrixObject *self) return NULL; if((self->col_size < 3) || self->row_size < 4){ - PyErr_SetString(PyExc_AttributeError, "Matrix.to_translation(): inappropriate matrix size"); + PyErr_SetString(PyExc_TypeError, + "matrix.to_translation(): " + "inappropriate matrix size"); return NULL; } @@ -884,7 +932,9 @@ static PyObject *Matrix_to_scale(MatrixObject *self) /*must be 3-4 cols, 3-4 rows, square matrix*/ if((self->col_size < 3) || (self->row_size < 3)) { - PyErr_SetString(PyExc_AttributeError, "Matrix.to_scale(): inappropriate matrix size, 3x3 minimum size"); + PyErr_SetString(PyExc_TypeError, + "matrix.to_scale(): " + "inappropriate matrix size, 3x3 minimum size"); return NULL; } @@ -896,7 +946,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self) return newVectorObject(size, 3, Py_NEW, NULL); } -/*---------------------------Matrix.invert() ---------------------*/ +/*---------------------------matrix.invert() ---------------------*/ PyDoc_STRVAR(Matrix_invert_doc, ".. method:: invert()\n" "\n" @@ -918,7 +968,9 @@ static PyObject *Matrix_invert(MatrixObject *self) return NULL; if(self->row_size != self->col_size){ - PyErr_SetString(PyExc_AttributeError, "Matrix.invert(ed): only square matrices are supported"); + PyErr_SetString(PyExc_TypeError, + "matrix.invert(ed): " + "only square matrices are supported"); return NULL; } @@ -950,8 +1002,10 @@ static PyObject *Matrix_invert(MatrixObject *self) } /*transpose Matrix_transpose(self);*/ - } else { - PyErr_SetString(PyExc_ValueError, "matrix does not have an inverse"); + } + else { + PyErr_SetString(PyExc_ValueError, + "matrix does not have an inverse"); return NULL; } @@ -995,7 +1049,8 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) return NULL; if(self->col_size != 3 || self->row_size != 3) { - PyErr_SetString(PyExc_ValueError, "Matrix must have 3x3 dimensions"); + PyErr_SetString(PyExc_TypeError, + "Matrix must have 3x3 dimensions"); return NULL; } @@ -1008,7 +1063,7 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) Py_RETURN_NONE; } -/*---------------------------Matrix.decompose() ---------------------*/ +/*---------------------------matrix.decompose() ---------------------*/ PyDoc_STRVAR(Matrix_decompose_doc, ".. method:: decompose()\n" "\n" @@ -1026,7 +1081,9 @@ static PyObject *Matrix_decompose(MatrixObject *self) float size[3]; if(self->col_size != 4 || self->row_size != 4) { - PyErr_SetString(PyExc_AttributeError, "Matrix.decompose(): inappropriate matrix size - expects 4x4 matrix"); + PyErr_SetString(PyExc_TypeError, + "matrix.decompose(): " + "inappropriate matrix size - expects 4x4 matrix"); return NULL; } @@ -1067,7 +1124,9 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) return NULL; if(self->row_size != mat2->row_size || self->col_size != mat2->col_size) { - PyErr_SetString(PyExc_AttributeError, "matrix.lerp(): expects both matrix objects of the same dimensions"); + PyErr_SetString(PyExc_ValueError, + "matrix.lerp(): " + "expects both matrix objects of the same dimensions"); return NULL; } @@ -1082,14 +1141,16 @@ static PyObject *Matrix_lerp(MatrixObject *self, PyObject *args) blend_m3_m3m3((float (*)[3])mat, (float (*)[3])self->contigPtr, (float (*)[3])mat2->contigPtr, fac); } else { - PyErr_SetString(PyExc_AttributeError, "matrix.lerp(): only 3x3 and 4x4 matrices supported"); + PyErr_SetString(PyExc_ValueError, + "matrix.lerp(): " + "only 3x3 and 4x4 matrices supported"); return NULL; } return (PyObject*)newMatrixObject(mat, self->row_size, self->col_size, Py_NEW, Py_TYPE(self)); } -/*---------------------------Matrix.determinant() ----------------*/ +/*---------------------------matrix.determinant() ----------------*/ PyDoc_STRVAR(Matrix_determinant_doc, ".. method:: determinant()\n" "\n" @@ -1106,13 +1167,15 @@ static PyObject *Matrix_determinant(MatrixObject *self) return NULL; if(self->row_size != self->col_size){ - PyErr_SetString(PyExc_AttributeError, "Matrix.determinant: only square matrices are supported"); + PyErr_SetString(PyExc_TypeError, + "matrix.determinant: " + "only square matrices are supported"); return NULL; } return PyFloat_FromDouble((double)matrix_determinant_internal(self)); } -/*---------------------------Matrix.transpose() ------------------*/ +/*---------------------------matrix.transpose() ------------------*/ PyDoc_STRVAR(Matrix_transpose_doc, ".. method:: transpose()\n" "\n" @@ -1128,7 +1191,9 @@ static PyObject *Matrix_transpose(MatrixObject *self) return NULL; if(self->row_size != self->col_size){ - PyErr_SetString(PyExc_AttributeError, "Matrix.transpose(d): only square matrices are supported"); + PyErr_SetString(PyExc_TypeError, + "matrix.transpose(d): " + "only square matrices are supported"); return NULL; } @@ -1138,7 +1203,8 @@ static PyObject *Matrix_transpose(MatrixObject *self) self->matrix[0][1] = t; } else if(self->row_size == 3) { transpose_m3((float (*)[3])self->contigPtr); - } else { + } + else { transpose_m4((float (*)[4])self->contigPtr); } @@ -1159,7 +1225,7 @@ static PyObject *Matrix_transposed(MatrixObject *self) return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self); } -/*---------------------------Matrix.zero() -----------------------*/ +/*---------------------------matrix.zero() -----------------------*/ PyDoc_STRVAR(Matrix_zero_doc, ".. method:: zero()\n" "\n" @@ -1177,7 +1243,7 @@ static PyObject *Matrix_zero(MatrixObject *self) Py_RETURN_NONE; } -/*---------------------------Matrix.identity(() ------------------*/ +/*---------------------------matrix.identity(() ------------------*/ PyDoc_STRVAR(Matrix_identity_doc, ".. method:: identity()\n" "\n" @@ -1194,7 +1260,9 @@ static PyObject *Matrix_identity(MatrixObject *self) return NULL; if(self->row_size != self->col_size){ - PyErr_SetString(PyExc_AttributeError, "Matrix.identity: only square matrices are supported"); + PyErr_SetString(PyExc_TypeError, + "matrix.identity: " + "only square matrices are supported"); return NULL; } @@ -1205,7 +1273,8 @@ static PyObject *Matrix_identity(MatrixObject *self) self->matrix[1][1] = 1.0f; } else if(self->row_size == 3) { unit_m3((float (*)[3])self->contigPtr); - } else { + } + else { unit_m4((float (*)[4])self->contigPtr); } @@ -1262,7 +1331,8 @@ static PyObject *Matrix_repr(MatrixObject *self) " %R)", rows[0], rows[1], rows[2], rows[3]); } - PyErr_SetString(PyExc_RuntimeError, "invalid matrix size"); + PyErr_SetString(PyExc_RuntimeError, + "internal error!"); return NULL; } @@ -1321,7 +1391,9 @@ static PyObject *Matrix_item(MatrixObject *self, int i) return NULL; if(i < 0 || i >= self->row_size) { - PyErr_SetString(PyExc_IndexError, "matrix[attribute]: array index out of range"); + PyErr_SetString(PyExc_IndexError, + "matrix[attribute]: " + "array index out of range"); return NULL; } return newVectorObject_cb((PyObject *)self, self->col_size, mathutils_matrix_vector_cb_index, i); @@ -1336,7 +1408,8 @@ static int Matrix_ass_item(MatrixObject *self, int i, PyObject *value) return -1; if(i >= self->row_size || i < 0){ - PyErr_SetString(PyExc_TypeError, "matrix[attribute] = x: bad column"); + PyErr_SetString(PyExc_IndexError, + "matrix[attribute] = x: bad column"); return -1; } @@ -1399,7 +1472,9 @@ static int Matrix_ass_slice(MatrixObject *self, int begin, int end, PyObject *va if(PySequence_Fast_GET_SIZE(value_fast) != size) { Py_DECREF(value_fast); - PyErr_SetString(PyExc_TypeError, "matrix[begin:end] = []: size mismatch in slice assignment"); + PyErr_SetString(PyExc_ValueError, + "matrix[begin:end] = []: " + "size mismatch in slice assignment"); return -1; } @@ -1433,7 +1508,9 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2) mat2 = (MatrixObject*)m2; if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) { - PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Matrix addition: " + "arguments not valid for this operation"); return NULL; } @@ -1441,7 +1518,9 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2) return NULL; if(mat1->row_size != mat2->row_size || mat1->col_size != mat2->col_size){ - PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation"); + PyErr_SetString(PyExc_TypeError, + "Matrix addition: " + "matrices must have the same dimensions for this operation"); return NULL; } @@ -1460,7 +1539,9 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2) mat2 = (MatrixObject*)m2; if(!MatrixObject_Check(m1) || !MatrixObject_Check(m2)) { - PyErr_SetString(PyExc_AttributeError, "Matrix addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Matrix addition: " + "arguments not valid for this operation"); return NULL; } @@ -1468,7 +1549,9 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2) return NULL; if(mat1->row_size != mat2->row_size || mat1->col_size != mat2->col_size){ - PyErr_SetString(PyExc_AttributeError, "Matrix addition: matrices must have the same dimensions for this operation"); + PyErr_SetString(PyExc_TypeError, + "Matrix addition: " + "matrices must have the same dimensions for this operation"); return NULL; } @@ -1502,39 +1585,38 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) return NULL; } - if(mat1 && mat2) { /*MATRIX * MATRIX*/ - if(mat1->row_size != mat2->col_size){ - PyErr_SetString(PyExc_AttributeError,"Matrix multiplication: matrix A rowsize must equal matrix B colsize"); + if(mat1 && mat2) { + /*MATRIX * MATRIX*/ + if(mat2->row_size != mat1->col_size){ + PyErr_SetString(PyExc_ValueError, + "Matrix multiplication: " + "matrix A rowsize must equal matrix B colsize"); return NULL; } else { - 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}; - double dot = 0.0f; + float mat[16]= {0.0f}; int x, y, z; for(x = 0; x < mat2->row_size; x++) { for(y = 0; y < mat1->col_size; y++) { for(z = 0; z < mat1->row_size; z++) { - dot += (mat1->matrix[z][y] * mat2->matrix[x][z]); + mat[x * mat2->col_size + y] += (mat2->matrix[x][z] * mat1->matrix[z][y]); } - mat[((x * mat1->col_size) + y)] = (float)dot; - dot = 0.0f; } } - return newMatrixObject(mat, mat2->row_size, mat1->col_size, Py_NEW, Py_TYPE(mat1)); + return newMatrixObject(mat, mat1->row_size, mat2->col_size, Py_NEW, Py_TYPE(mat1)); } } else if(mat2) { - if (((scalar= PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred())==0) { /*FLOAT/INT * MATRIX */ + /*FLOAT/INT * MATRIX */ + if (((scalar= PyFloat_AsDouble(m1)) == -1.0f && PyErr_Occurred())==0) { return matrix_mul_float(mat2, scalar); } } else if(mat1) { - if (((scalar= PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred())==0) { /*FLOAT/INT * MATRIX */ + /*FLOAT/INT * MATRIX */ + if (((scalar= PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred())==0) { return matrix_mul_float(mat1, scalar); } } @@ -1542,7 +1624,10 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) BLI_assert(!"internal error"); } - PyErr_Format(PyExc_TypeError, "Matrix multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(m1)->tp_name, Py_TYPE(m2)->tp_name); + 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; } static PyObject* Matrix_inv(MatrixObject *self) @@ -1591,12 +1676,15 @@ static PyObject *Matrix_subscript(MatrixObject* self, PyObject* item) return Matrix_slice(self, start, stop); } else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies"); + PyErr_SetString(PyExc_IndexError, + "slice steps not supported with matricies"); return NULL; } } else { - PyErr_Format(PyExc_TypeError, "vector indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + PyErr_Format(PyExc_TypeError, + "matrix indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return NULL; } } @@ -1620,12 +1708,15 @@ static int Matrix_ass_subscript(MatrixObject* self, PyObject* item, PyObject* va if (step == 1) return Matrix_ass_slice(self, start, stop, value); else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with matricies"); + PyErr_SetString(PyExc_IndexError, + "slice steps not supported with matricies"); return -1; } } else { - PyErr_Format(PyExc_TypeError, "matrix indices must be integers, not %.200s", Py_TYPE(item)->tp_name); + PyErr_Format(PyExc_TypeError, + "matrix indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return -1; } } @@ -1693,7 +1784,9 @@ static PyObject *Matrix_median_scale_get(MatrixObject *self, void *UNUSED(closur /*must be 3-4 cols, 3-4 rows, square matrix*/ if((self->col_size < 3) || (self->row_size < 3)) { - PyErr_SetString(PyExc_AttributeError, "Matrix.median_scale: inappropriate matrix size, 3x3 minimum"); + PyErr_SetString(PyExc_AttributeError, + "matrix.median_scale: " + "inappropriate matrix size, 3x3 minimum"); return NULL; } @@ -1713,7 +1806,9 @@ static PyObject *Matrix_is_negative_get(MatrixObject *self, void *UNUSED(closure else if(self->col_size == 3 && self->row_size == 3) return PyBool_FromLong(is_negative_m3((float (*)[3])self->contigPtr)); else { - PyErr_SetString(PyExc_AttributeError, "Matrix.is_negative: inappropriate matrix size - expects 3x3 or 4x4 matrix"); + PyErr_SetString(PyExc_AttributeError, + "matrix.is_negative: " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); return NULL; } } @@ -1729,7 +1824,9 @@ static PyObject *Matrix_is_orthogonal_get(MatrixObject *self, void *UNUSED(closu else if(self->col_size == 3 && self->row_size == 3) return PyBool_FromLong(is_orthogonal_m3((float (*)[3])self->contigPtr)); else { - PyErr_SetString(PyExc_AttributeError, "Matrix.is_orthogonal: inappropriate matrix size - expects 3x3 or 4x4 matrix"); + PyErr_SetString(PyExc_AttributeError, + "matrix.is_orthogonal: " + "inappropriate matrix size - expects 3x3 or 4x4 matrix"); return NULL; } } @@ -1865,7 +1962,9 @@ PyObject *newMatrixObject(float *mat, const unsigned short rowSize, const unsign /*matrix objects can be any 2-4row x 2-4col matrix*/ if(rowSize < 2 || rowSize > 4 || colSize < 2 || colSize > 4) { - PyErr_SetString(PyExc_RuntimeError, "matrix(): row and column sizes must be between 2 and 4"); + PyErr_SetString(PyExc_RuntimeError, + "Matrix(): " + "row and column sizes must be between 2 and 4"); return NULL; } @@ -1891,7 +1990,9 @@ PyObject *newMatrixObject(float *mat, const unsigned short rowSize, const unsign else if (type == Py_NEW){ self->contigPtr = PyMem_Malloc(rowSize * colSize * sizeof(float)); if(self->contigPtr == NULL) { /*allocation failure*/ - PyErr_SetString(PyExc_MemoryError, "matrix(): problem allocating pointer space"); + PyErr_SetString(PyExc_MemoryError, + "Matrix(): " + "problem allocating pointer space"); return NULL; } /*pointer array points to contigous memory*/ @@ -1913,7 +2014,7 @@ PyObject *newMatrixObject(float *mat, const unsigned short rowSize, const unsign self->wrapped = Py_NEW; } else { - PyErr_SetString(PyExc_RuntimeError, "Matrix(): invalid type"); + Py_FatalError("Matrix(): invalid type!"); return NULL; } } diff --git a/source/blender/python/generic/mathutils_Matrix.h b/source/blender/python/mathutils/mathutils_Matrix.h index aa736d1e959..aa736d1e959 100644 --- a/source/blender/python/generic/mathutils_Matrix.h +++ b/source/blender/python/mathutils/mathutils_Matrix.h diff --git a/source/blender/python/generic/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 90447e7093a..3b05b9a250b 100644 --- a/source/blender/python/generic/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -235,7 +235,9 @@ static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args) 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"); + PyErr_SetString(PyExc_TypeError, + "quat.slerp(): " + "expected Quaternion types and float"); return NULL; } @@ -246,7 +248,9 @@ static PyObject *Quaternion_slerp(QuaternionObject *self, PyObject *args) return NULL; if(fac > 1.0f || fac < 0.0f) { - PyErr_SetString(PyExc_AttributeError, "quat.slerp(): interpolation factor must be between 0.0 and 1.0"); + PyErr_SetString(PyExc_ValueError, + "quat.slerp(): " + "interpolation factor must be between 0.0 and 1.0"); return NULL; } @@ -498,7 +502,9 @@ 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"); + PyErr_SetString(PyExc_IndexError, + "quaternion[attribute]: " + "array index out of range"); return NULL; } @@ -514,14 +520,18 @@ 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 */ - PyErr_SetString(PyExc_TypeError, "quaternion[index] = x: index argument not a number"); + PyErr_SetString(PyExc_TypeError, + "quaternion[index] = x: " + "index argument 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"); + PyErr_SetString(PyExc_IndexError, + "quaternion[attribute] = x: " + "array assignment index out of range"); return -1; } self->quat[i] = scalar; @@ -572,7 +582,9 @@ static int Quaternion_ass_slice(QuaternionObject *self, int begin, int end, PyOb return -1; if(size != (end - begin)){ - PyErr_SetString(PyExc_TypeError, "quaternion[begin:end] = []: size mismatch in slice assignment"); + PyErr_SetString(PyExc_ValueError, + "quaternion[begin:end] = []: " + "size mismatch in slice assignment"); return -1; } @@ -608,12 +620,15 @@ static PyObject *Quaternion_subscript(QuaternionObject *self, PyObject *item) return Quaternion_slice(self, start, stop); } else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with quaternions"); + 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); + PyErr_Format(PyExc_TypeError, + "quaternion indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return NULL; } } @@ -638,12 +653,15 @@ static int Quaternion_ass_subscript(QuaternionObject *self, PyObject *item, PyOb if (step == 1) return Quaternion_ass_slice(self, start, stop, value); else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with quaternion"); + 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); + PyErr_Format(PyExc_TypeError, + "quaternion indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return -1; } } @@ -657,7 +675,9 @@ static PyObject *Quaternion_add(PyObject *q1, PyObject *q2) QuaternionObject *quat1 = NULL, *quat2 = NULL; if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) { - PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Quaternion addition: " + "arguments not valid for this operation"); return NULL; } quat1 = (QuaternionObject*)q1; @@ -678,7 +698,9 @@ static PyObject *Quaternion_sub(PyObject *q1, PyObject *q2) QuaternionObject *quat1 = NULL, *quat2 = NULL; if(!QuaternionObject_Check(q1) || !QuaternionObject_Check(q2)) { - PyErr_SetString(PyExc_AttributeError, "Quaternion addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_TypeError, + "Quaternion addition: " + "arguments not valid for this operation"); return NULL; } @@ -740,7 +762,10 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) BLI_assert(!"internal error"); } - PyErr_Format(PyExc_TypeError, "Quaternion multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(q1)->tp_name, Py_TYPE(q2)->tp_name); + 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; } @@ -861,7 +886,8 @@ static int Quaternion_setAngle(QuaternionObject *self, PyObject *value, void *UN angle= PyFloat_AsDouble(value); if(angle==-1.0 && PyErr_Occurred()) { /* parsed item not a number */ - PyErr_SetString(PyExc_TypeError, "quaternion.angle = value: float expected"); + PyErr_SetString(PyExc_TypeError, + "quaternion.angle = value: float expected"); return -1; } @@ -942,7 +968,9 @@ static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, PyObject *kw float quat[QUAT_SIZE]= {0.0f, 0.0f, 0.0f, 0.0f}; if(kwds && PyDict_Size(kwds)) { - PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): takes no keyword args"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Quaternion(): " + "takes no keyword args"); return NULL; } @@ -1114,8 +1142,7 @@ PyObject *newQuaternionObject(float *quat, int type, PyTypeObject *base_type) self->wrapped = Py_NEW; } else { - PyErr_SetString(PyExc_RuntimeError, "Quaternion(): invalid type"); - return NULL; + Py_FatalError("Quaternion(): invalid type!"); } } return (PyObject *) self; diff --git a/source/blender/python/generic/mathutils_Quaternion.h b/source/blender/python/mathutils/mathutils_Quaternion.h index d606621390a..d606621390a 100644 --- a/source/blender/python/generic/mathutils_Quaternion.h +++ b/source/blender/python/mathutils/mathutils_Quaternion.h diff --git a/source/blender/python/generic/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index e07b51c9e4b..e2c958adaa5 100644 --- a/source/blender/python/generic/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -34,7 +34,6 @@ #include "mathutils.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -66,7 +65,9 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED return NULL; break; default: - PyErr_SetString(PyExc_TypeError, "mathutils.Vector(): more then a single arg given"); + PyErr_SetString(PyExc_TypeError, + "mathutils.Vector(): " + "more then a single arg given"); return NULL; } return newVectorObject(vec, size, Py_NEW, type); @@ -156,17 +157,23 @@ PyDoc_STRVAR(Vector_resize_2d_doc, static PyObject *Vector_resize_2d(VectorObject *self) { if(self->wrapped==Py_WRAP) { - PyErr_SetString(PyExc_TypeError, "vector.resize_2d(): cannot resize wrapped data - only python vectors"); + 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"); + 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"); + PyErr_SetString(PyExc_MemoryError, + "vector.resize_2d(): " + "problem allocating pointer space"); return NULL; } @@ -185,17 +192,23 @@ PyDoc_STRVAR(Vector_resize_3d_doc, static PyObject *Vector_resize_3d(VectorObject *self) { if (self->wrapped==Py_WRAP) { - PyErr_SetString(PyExc_TypeError, "vector.resize_3d(): cannot resize wrapped data - only python vectors"); + 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"); + 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"); + PyErr_SetString(PyExc_MemoryError, + "vector.resize_3d(): " + "problem allocating pointer space"); return NULL; } @@ -217,17 +230,23 @@ PyDoc_STRVAR(Vector_resize_4d_doc, static PyObject *Vector_resize_4d(VectorObject *self) { if(self->wrapped==Py_WRAP) { - PyErr_SetString(PyExc_TypeError, "vector.resize_4d(): cannot resize wrapped data - only python vectors"); + 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"); + 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"); + PyErr_SetString(PyExc_MemoryError, + "vector.resize_4d(): " + "problem allocating pointer space"); return NULL; } @@ -333,7 +352,9 @@ static PyObject *Vector_to_tuple(VectorObject *self, PyObject *args) return NULL; if(ndigits > 22 || ndigits < 0) { - PyErr_SetString(PyExc_ValueError, "vector.to_tuple(ndigits): ndigits must be between 0 and 21"); + PyErr_SetString(PyExc_ValueError, + "vector.to_tuple(ndigits): " + "ndigits must be between 0 and 21"); return NULL; } @@ -368,7 +389,9 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) return NULL; if (self->size != 3) { - PyErr_SetString(PyExc_TypeError, "only for 3D vectors"); + PyErr_SetString(PyExc_TypeError, + "vector.to_track_quat(): " + "only for 3D vectors"); return NULL; } @@ -376,6 +399,8 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) 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]) { @@ -389,12 +414,12 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) track = 5; break; default: - PyErr_SetString(PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis"); + PyErr_SetString(PyExc_ValueError, axis_err_msg); return NULL; } } else { - PyErr_SetString(PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis"); + PyErr_SetString(PyExc_ValueError, axis_err_msg); return NULL; } } @@ -411,17 +436,18 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) track = 2; break; default: - PyErr_SetString(PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis"); + PyErr_SetString(PyExc_ValueError, axis_err_msg); return NULL; } } else { - PyErr_SetString(PyExc_ValueError, "only X, -X, Y, -Y, Z or -Z for track axis"); + 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': @@ -434,18 +460,19 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args) up = 2; break; default: - PyErr_SetString(PyExc_ValueError, "only X, Y or Z for up axis"); + PyErr_SetString(PyExc_ValueError, axis_err_msg); return NULL; } } else { - PyErr_SetString(PyExc_ValueError, "only X, Y or Z for up axis"); + 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"); + PyErr_SetString(PyExc_ValueError, + "Can't have the same axis for track and up"); return NULL; } @@ -604,7 +631,9 @@ static PyObject *Vector_angle(VectorObject *self, PyObject *args) return fallback; } else { - PyErr_SetString(PyExc_ValueError, "vector.angle(other): zero length vectors have no valid angle"); + PyErr_SetString(PyExc_ValueError, + "vector.angle(other): " + "zero length vectors have no valid angle"); return NULL; } } @@ -636,7 +665,9 @@ static PyObject *Vector_rotation_difference(VectorObject *self, PyObject *value) float quat[4], vec_a[3], vec_b[3]; if(self->size < 3) { - PyErr_SetString(PyExc_AttributeError, "vec.difference(value): expects both vectors to be size 3 or 4"); + PyErr_SetString(PyExc_ValueError, + "vec.difference(value): " + "expects both vectors to be size 3 or 4"); return NULL; } @@ -750,7 +781,8 @@ static PyObject *Vector_rotate(VectorObject *self, PyObject *value) return NULL; if(self->size < 3) { - PyErr_SetString(PyExc_ValueError, "Vector must be 3D or 4D"); + PyErr_SetString(PyExc_ValueError, + "Vector must be 3D or 4D"); return NULL; } @@ -804,8 +836,15 @@ static PyObject *vector_item_internal(VectorObject *self, int i, const int is_at 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"); + 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; } @@ -824,15 +863,25 @@ static int vector_ass_item_internal(VectorObject *self, int i, PyObject *value, { float scalar; if((scalar=PyFloat_AsDouble(value))==-1.0f && PyErr_Occurred()) { /* parsed item not a number */ - PyErr_SetString(PyExc_TypeError, "vector[index] = x: index argument not a number"); + PyErr_SetString(PyExc_TypeError, + "vector[index] = x: " + "index argument 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"); + 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; @@ -904,7 +953,9 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2) float vec[MAX_DIMENSIONS]; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_AttributeError, + "Vector addition: " + "arguments not valid for this operation"); return NULL; } vec1 = (VectorObject*)v1; @@ -915,7 +966,9 @@ static PyObject *Vector_add(PyObject *v1, PyObject *v2) /*VECTOR + VECTOR*/ if(vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, "Vector addition: vectors must have the same dimensions for this operation"); + PyErr_SetString(PyExc_AttributeError, + "Vector addition: " + "vectors must have the same dimensions for this operation"); return NULL; } @@ -930,14 +983,18 @@ static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) VectorObject *vec1 = NULL, *vec2 = NULL; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Vector addition: arguments not valid for this operation"); + PyErr_SetString(PyExc_AttributeError, + "Vector addition: " + "arguments not valid for this operation"); 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"); + PyErr_SetString(PyExc_AttributeError, + "Vector addition: " + "vectors must have the same dimensions for this operation"); return NULL; } @@ -958,7 +1015,9 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2) float vec[MAX_DIMENSIONS]; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation"); + PyErr_SetString(PyExc_AttributeError, + "Vector subtraction: " + "arguments not valid for this operation"); return NULL; } vec1 = (VectorObject*)v1; @@ -968,7 +1027,9 @@ static PyObject *Vector_sub(PyObject *v1, PyObject *v2) return NULL; if(vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, "Vector subtraction: vectors must have the same dimensions for this operation"); + PyErr_SetString(PyExc_AttributeError, + "Vector subtraction: " + "vectors must have the same dimensions for this operation"); return NULL; } @@ -983,14 +1044,18 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2) VectorObject *vec1= NULL, *vec2= NULL; if (!VectorObject_Check(v1) || !VectorObject_Check(v2)) { - PyErr_SetString(PyExc_AttributeError, "Vector subtraction: arguments not valid for this operation"); + PyErr_SetString(PyExc_AttributeError, + "Vector subtraction: " + "arguments not valid for this operation"); 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"); + PyErr_SetString(PyExc_AttributeError, + "Vector subtraction: " + "vectors must have the same dimensions for this operation"); return NULL; } @@ -1027,7 +1092,10 @@ static int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject vec_cpy[3] = 1.0f; } else { - PyErr_SetString(PyExc_AttributeError, "matrix * vector: matrix.row_size and len(vector) must be the same, except for 3D vector * 4x4 matrix."); + PyErr_SetString(PyExc_TypeError, + "matrix * vector: " + "matrix.row_size and len(vector) must be the same, " + "except for 3D vector * 4x4 matrix."); return -1; } } @@ -1077,7 +1145,9 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) double dot = 0.0f; if(vec1->size != vec2->size) { - PyErr_SetString(PyExc_AttributeError, "Vector multiplication: vectors must have the same dimensions for this operation"); + PyErr_SetString(PyExc_ValueError, + "Vector multiplication: " + "vectors must have the same dimensions for this operation"); return NULL; } @@ -1105,7 +1175,9 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) float tvec[3]; if(vec1->size != 3) { - PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported"); + PyErr_SetString(PyExc_ValueError, + "Vector multiplication: " + "only 3D vector rotations (with quats) currently supported"); return NULL; } if(BaseMath_ReadCallback(quat2) == -1) { @@ -1128,7 +1200,10 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) BLI_assert(!"internal error"); } - PyErr_Format(PyExc_TypeError, "Vector multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); + 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; } @@ -1158,7 +1233,9 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) QuaternionObject *quat2 = (QuaternionObject*)v2; if(vec->size != 3) { - PyErr_SetString(PyExc_TypeError, "Vector multiplication: only 3D vector rotations (with quats) currently supported"); + PyErr_SetString(PyExc_ValueError, + "Vector multiplication: " + "only 3D vector rotations (with quats) currently supported"); return NULL; } @@ -1171,7 +1248,9 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) mul_vn_fl(vec->vec, vec->size, scalar); } else { - PyErr_SetString(PyExc_TypeError, "Vector multiplication: arguments not acceptable for this operation"); + PyErr_SetString(PyExc_TypeError, + "Vector multiplication: " + "arguments not acceptable for this operation"); return NULL; } @@ -1188,7 +1267,9 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2) VectorObject *vec1 = NULL; if(!VectorObject_Check(v1)) { /* not a vector */ - PyErr_SetString(PyExc_TypeError, "Vector division: Vector must be divided by a float"); + PyErr_SetString(PyExc_TypeError, + "Vector division: " + "Vector must be divided by a float"); return NULL; } vec1 = (VectorObject*)v1; /* vector */ @@ -1197,12 +1278,16 @@ static PyObject *Vector_div(PyObject *v1, PyObject *v2) 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"); + 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"); + PyErr_SetString(PyExc_ZeroDivisionError, + "Vector division: " + "divide by zero error"); return NULL; } @@ -1223,12 +1308,16 @@ static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) 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"); + 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"); + PyErr_SetString(PyExc_ZeroDivisionError, + "Vector division: " + "divide by zero error"); return NULL; } for(i = 0; i < vec1->size; i++) { @@ -1394,12 +1483,15 @@ static PyObject *Vector_subscript(VectorObject* self, PyObject* item) return Vector_slice(self, start, stop); } else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); + 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); + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return NULL; } } @@ -1423,12 +1515,15 @@ static int Vector_ass_subscript(VectorObject* self, PyObject* item, PyObject* va if (step == 1) return Vector_ass_slice(self, start, stop, value); else { - PyErr_SetString(PyExc_TypeError, "slice steps not supported with vectors"); + 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); + PyErr_Format(PyExc_TypeError, + "vector indices must be integers, not %.200s", + Py_TYPE(item)->tp_name); return -1; } } @@ -1517,12 +1612,14 @@ static int Vector_setLength(VectorObject *self, PyObject *value) return -1; if((param=PyFloat_AsDouble(value)) == -1.0 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "length must be set to a number"); + PyErr_SetString(PyExc_TypeError, + "length must be set to a number"); return -1; } if (param < 0.0) { - PyErr_SetString(PyExc_TypeError, "cannot set a vectors length to a negative value"); + PyErr_SetString(PyExc_ValueError, + "cannot set a vectors length to a negative value"); return -1; } if (param == 0.0) { @@ -1573,7 +1670,9 @@ static PyObject *Vector_getSwizzle(VectorObject *self, void *closure) { axis_from = swizzleClosure & SWIZZLE_AXIS; if(axis_from >= self->size) { - PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis"); + PyErr_SetString(PyExc_AttributeError, + "Vector swizzle: " + "specified axis not present"); return NULL; } @@ -1615,12 +1714,13 @@ static int Vector_setSwizzle(VectorObject *self, PyObject *value, void *closure) swizzles defined for axes z and w, but they would be invalid. */ swizzleClosure = GET_INT_FROM_POINTER(closure); axis_from= 0; - while (swizzleClosure & SWIZZLE_VALID_AXIS) - { + while (swizzleClosure & SWIZZLE_VALID_AXIS) { axis_to = swizzleClosure & SWIZZLE_AXIS; if (axis_to >= self->size) { - PyErr_SetString(PyExc_AttributeError, "Error: vector does not have specified axis"); + PyErr_SetString(PyExc_AttributeError, + "Vector swizzle: " + "specified axis not present"); return -1; } swizzleClosure = swizzleClosure >> SWIZZLE_BITS_PER_AXIS; @@ -1639,7 +1739,8 @@ static int Vector_setSwizzle(VectorObject *self, PyObject *value, void *closure) } if(axis_from != size_from) { - PyErr_SetString(PyExc_AttributeError, "Error: vector size does not match swizzle"); + PyErr_SetString(PyExc_AttributeError, + "Vector swizzle: size does not match swizzle"); return -1; } @@ -2071,7 +2172,9 @@ static int row_vector_multiplication(float rvec[4], VectorObject* vec, MatrixObj if(mat->colSize != vec_size){ if(mat->colSize == 4 && vec_size != 3){ - PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); + PyErr_SetString(PyExc_ValueError, + "vector * matrix: matrix column size " + "and the vector size must be the same"); return -1; } else { @@ -2252,7 +2355,8 @@ PyObject *newVectorObject(float *vec, const int size, const int type, PyTypeObje VectorObject *self; if(size > 4 || size < 2) { - PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid size"); + PyErr_SetString(PyExc_RuntimeError, + "Vector(): invalid size"); return NULL; } @@ -2284,8 +2388,7 @@ PyObject *newVectorObject(float *vec, const int size, const int type, PyTypeObje self->wrapped = Py_NEW; } else { - PyErr_SetString(PyExc_RuntimeError, "Vector(): invalid type"); - return NULL; + Py_FatalError("Vector(): invalid type!"); } } return (PyObject *) self; diff --git a/source/blender/python/generic/mathutils_Vector.h b/source/blender/python/mathutils/mathutils_Vector.h index 0ede836ce44..0ede836ce44 100644 --- a/source/blender/python/generic/mathutils_Vector.h +++ b/source/blender/python/mathutils/mathutils_Vector.h diff --git a/source/blender/python/generic/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 53c066d1a85..bcdfe020e1a 100644 --- a/source/blender/python/generic/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -1,4 +1,4 @@ -/* +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -37,16 +37,16 @@ #include "mathutils_geometry.h" /* Used for PolyFill */ -#include "MEM_guardedalloc.h" +#ifndef MATH_STANDALONE /* define when building outside blender */ +# include "MEM_guardedalloc.h" +# include "BLI_blenlib.h" +# include "BLI_boxpack2d.h" +# include "BKE_displist.h" +# include "BKE_curve.h" +#endif -#include "BLI_blenlib.h" -#include "BLI_boxpack2d.h" #include "BLI_math.h" #include "BLI_utildefines.h" - -#include "BKE_displist.h" - -#include "BKE_curve.h" #define SWAP_FLOAT(a, b, tmp) tmp=a; a=b; b=tmp #define eps 0.000001 @@ -90,7 +90,8 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject* return NULL; } if(vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) { - PyErr_SetString(PyExc_ValueError, "only 3D vectors for all parameters"); + PyErr_SetString(PyExc_ValueError, + "only 3D vectors for all parameters"); return NULL; } @@ -177,7 +178,8 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject return NULL; } if(vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) { - PyErr_SetString(PyExc_ValueError,"vectors must be of the same size"); + PyErr_SetString(PyExc_ValueError, + "vectors must be of the same size"); return NULL; } @@ -225,7 +227,8 @@ static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject } } else { - PyErr_SetString(PyExc_ValueError, "2D/3D vectors only"); + PyErr_SetString(PyExc_ValueError, + "2D/3D vectors only"); return NULL; } } @@ -259,11 +262,13 @@ static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args) return NULL; } if(vec1->size != vec2->size || vec1->size != vec3->size) { - PyErr_SetString(PyExc_ValueError, "vectors must be of the same size"); + PyErr_SetString(PyExc_ValueError, + "vectors must be of the same size"); return NULL; } if(vec1->size < 3) { - PyErr_SetString(PyExc_ValueError, "2D vectors unsupported"); + PyErr_SetString(PyExc_ValueError, + "2D vectors unsupported"); return NULL; } @@ -277,11 +282,13 @@ static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args) return NULL; } if(vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) { - PyErr_SetString(PyExc_ValueError,"vectors must be of the same size"); + PyErr_SetString(PyExc_ValueError, + "vectors must be of the same size"); return NULL; } if(vec1->size < 3) { - PyErr_SetString(PyExc_ValueError, "2D vectors unsupported"); + PyErr_SetString(PyExc_ValueError, + "2D vectors unsupported"); return NULL; } @@ -318,7 +325,8 @@ static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject* args) } if(vec1->size != vec2->size || vec1->size != vec3->size) { - PyErr_SetString(PyExc_ValueError, "vectors must be of the same size"); + PyErr_SetString(PyExc_ValueError, + "vectors must be of the same size"); return NULL; } @@ -332,131 +340,12 @@ static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject* args) return PyFloat_FromDouble(area_tri_v2(vec1->vec, vec2->vec, vec3->vec)); } else { - PyErr_SetString(PyExc_ValueError, "only 2D,3D vectors are supported"); + PyErr_SetString(PyExc_ValueError, + "only 2D,3D vectors are supported"); return NULL; } } -/*----------------------------------geometry.PolyFill() -------------------*/ -PyDoc_STRVAR(M_Geometry_tesselate_polygon_doc, -".. function:: tesselate_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_tesselate_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)) { - freedisplist(&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) { /* dont 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 - fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */ - } - else { - ls_error= 1; - } - - totpoints++; - Py_DECREF(polyVec); - } - } - Py_DECREF(polyLine); - } - - if(ls_error) { - freedisplist(&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 */ - filldisplist(&dispbase, &dispbase, 0); - - /* The faces are stored in a new DisplayList - thats added to the head of the listbase */ - dl= dispbase.first; - - tri_list= PyList_New(dl->parts); - if(!tri_list) { - freedisplist(&dispbase); - PyErr_SetString(PyExc_RuntimeError, "geometry.PolyFill failed to make a new list"); - return NULL; - } - - index= 0; - dl_face= dl->index; - while(index < dl->parts) { - PyList_SET_ITEM(tri_list, index, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2])); - dl_face+= 3; - index++; - } - freedisplist(&dispbase); - } - else { - /* no points, do this so scripts dont barf */ - freedisplist(&dispbase); /* possible some dl was allocated */ - tri_list= PyList_New(0); - } - - return tri_list; -} PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc, ".. function:: intersect_line_line_2d(lineA_p1, lineA_p2, lineB_p1, lineB_p2)\n" @@ -522,7 +411,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec VectorObject *line_a, *line_b, *plane_co, *plane_no; int no_flip= 0; float isect[3]; - if(!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_line_2d", + if(!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane", &vector_Type, &line_a, &vector_Type, &line_b, &vector_Type, &plane_co, @@ -541,7 +430,9 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec } if(ELEM4(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) { - PyErr_SetString(PyExc_RuntimeError, "geometry.intersect_line_plane(...) can't use 2D Vectors"); + PyErr_SetString(PyExc_ValueError, + "geometry.intersect_line_plane(...): " + " can't use 2D Vectors"); return NULL; } @@ -553,6 +444,159 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec } } + +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 lines (as 2 vectors), a sphere as a point and a radius and\n" +" returns the intersection\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 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) +{ + VectorObject *line_a, *line_b, *sphere_co; + float sphere_radius; + int clip= TRUE; + + float isect_a[3]; + float isect_b[3]; + + if(!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere", + &vector_Type, &line_a, + &vector_Type, &line_b, + &vector_Type, &sphere_co, + &sphere_radius, &clip) + ) { + return NULL; + } + + if( BaseMath_ReadCallback(line_a) == -1 || + BaseMath_ReadCallback(line_b) == -1 || + BaseMath_ReadCallback(sphere_co) == -1 + ) { + return NULL; + } + + if(ELEM3(2, line_a->size, line_b->size, sphere_co->size)) { + PyErr_SetString(PyExc_ValueError, + "geometry.intersect_line_sphere(...): " + " can't use 2D Vectors"); + return NULL; + } + else { + short use_a= TRUE; + short use_b= TRUE; + float lambda; + + PyObject *ret= PyTuple_New(2); + + switch(isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { + case 1: + if(!(!clip || (((lambda= line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 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->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE; + if(!(!clip || (((lambda= line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b= FALSE; + break; + default: + use_a= FALSE; + use_b= FALSE; + } + + if(use_a) { PyTuple_SET_ITEM(ret, 0, newVectorObject(isect_a, 3, Py_NEW, NULL)); } + else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); } + + if(use_b) { PyTuple_SET_ITEM(ret, 1, newVectorObject(isect_b, 3, Py_NEW, NULL)); } + else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(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 lines (as 2 vectors), a sphere as a point and a radius and\n" +" returns the intersection\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 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) +{ + VectorObject *line_a, *line_b, *sphere_co; + float sphere_radius; + int clip= TRUE; + + float isect_a[3]; + float isect_b[3]; + + if(!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere_2d", + &vector_Type, &line_a, + &vector_Type, &line_b, + &vector_Type, &sphere_co, + &sphere_radius, &clip) + ) { + return NULL; + } + + if( BaseMath_ReadCallback(line_a) == -1 || + BaseMath_ReadCallback(line_b) == -1 || + BaseMath_ReadCallback(sphere_co) == -1 + ) { + return NULL; + } + else { + short use_a= TRUE; + short use_b= TRUE; + float lambda; + + PyObject *ret= PyTuple_New(2); + + switch(isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) { + case 1: + if(!(!clip || (((lambda= line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 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->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a= FALSE; + if(!(!clip || (((lambda= line_point_factor_v2(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b= FALSE; + break; + default: + use_a= FALSE; + use_b= FALSE; + } + + if(use_a) { PyTuple_SET_ITEM(ret, 0, newVectorObject(isect_a, 2, Py_NEW, NULL)); } + else { PyTuple_SET_ITEM(ret, 0, Py_None); Py_INCREF(Py_None); } + + if(use_b) { PyTuple_SET_ITEM(ret, 1, newVectorObject(isect_b, 2, Py_NEW, NULL)); } + else { PyTuple_SET_ITEM(ret, 1, Py_None); Py_INCREF(Py_None); } + + return ret; + } +} + PyDoc_STRVAR(M_Geometry_intersect_point_line_doc, ".. function:: intersect_point_line(pt, line_p1, line_p2)\n" "\n" @@ -674,110 +718,69 @@ static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyOb return PyLong_FromLong(isect_point_quad_v2(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec)); } -static int boxPack_FromPyObject(PyObject *value, boxPack **boxarray) -{ - int 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_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_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; - - 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) -{ - int len, i; - PyObject *list_item; - boxPack *box; - - len= PyList_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" +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" -" Returns the normal of the 3D tri or quad.\n" +" Return a transformed point, the transformation is defined by 2 triangles.\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" +" :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_a1: target triangle vertex.\n" +" :type tri_a1: :class:`mathutils.Vector`\n" +" :arg tri_a2: target triangle vertex.\n" +" :type tri_a2: :class:`mathutils.Vector`\n" +" :arg tri_a3: target triangle vertex.\n" +" :type tri_a3: :class:`mathutils.Vector`\n" +" :return: The transformed point\n" +" :rtype: :class:`mathutils.Vector`'s\n" ); -static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlist) +static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args) { - float tot_width= 0.0f, tot_height= 0.0f; - int len; + VectorObject *vec_pt; + VectorObject *vec_t1_tar, *vec_t2_tar, *vec_t3_tar; + VectorObject *vec_t1_src, *vec_t2_src, *vec_t3_src; + float vec[3]; - PyObject *ret; - - if(!PyList_Check(boxlist)) { - PyErr_SetString(PyExc_TypeError, "expected a list of boxes [[x, y, w, h], ... ]"); + if(!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!:barycentric_transform", + &vector_Type, &vec_pt, + &vector_Type, &vec_t1_src, + &vector_Type, &vec_t2_src, + &vector_Type, &vec_t3_src, + &vector_Type, &vec_t1_tar, + &vector_Type, &vec_t2_tar, + &vector_Type, &vec_t3_tar) + ) { 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 */ - boxPack2D(boxarray, len, &tot_width, &tot_height); - - boxPack_ToPyObject(boxlist, &boxarray); + if( vec_pt->size != 3 || + vec_t1_src->size != 3 || + vec_t2_src->size != 3 || + vec_t3_src->size != 3 || + vec_t1_tar->size != 3 || + vec_t2_tar->size != 3 || + vec_t3_tar->size != 3) + { + PyErr_SetString(PyExc_ValueError, + "One of more of the vector arguments wasn't a 3D vector"); + return NULL; } - ret= PyTuple_New(2); - PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(tot_width)); - PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(tot_width)); - return ret; + barycentric_transform(vec, vec_pt->vec, + vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec, + vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec); + + return newVectorObject(vec, 3, Py_NEW, NULL); } +#ifndef MATH_STANDALONE + PyDoc_STRVAR(M_Geometry_interpolate_bezier_doc, ".. function:: interpolate_bezier(knot1, handle1, handle2, knot2, resolution)\n" "\n" @@ -804,13 +807,13 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject* int i; float *coord_array, *fp; PyObject *list; - + float k1[4]= {0.0, 0.0, 0.0, 0.0}; float h1[4]= {0.0, 0.0, 0.0, 0.0}; float k2[4]= {0.0, 0.0, 0.0, 0.0}; float h2[4]= {0.0, 0.0, 0.0, 0.0}; - - + + if(!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier", &vector_Type, &vec_k1, &vector_Type, &vec_h1, @@ -821,7 +824,8 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject* } if(resolu <= 1) { - PyErr_SetString(PyExc_ValueError, "resolution must be 2 or over"); + PyErr_SetString(PyExc_ValueError, + "resolution must be 2 or over"); return NULL; } @@ -829,17 +833,17 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject* return NULL; dims= MAX4(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size); - + for(i=0; i < vec_k1->size; i++) k1[i]= vec_k1->vec[i]; for(i=0; i < vec_h1->size; i++) h1[i]= vec_h1->vec[i]; for(i=0; i < vec_k2->size; i++) k2[i]= vec_k2->vec[i]; for(i=0; i < vec_h2->size; i++) h2[i]= vec_h2->vec[i]; - + coord_array= MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier"); for(i=0; i<dims; i++) { forward_diff_bezier(k1[i], h1[i], h2[i], k2[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) { @@ -849,66 +853,247 @@ static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject* return list; } -PyDoc_STRVAR(M_Geometry_barycentric_transform_doc, -".. function:: barycentric_transform(point, tri_a1, tri_a2, tri_a3, tri_b1, tri_b2, tri_b3)\n" + +PyDoc_STRVAR(M_Geometry_tesselate_polygon_doc, +".. function:: tesselate_polygon(veclist_list)\n" "\n" -" Return a transformed point, the transformation is defined by 2 triangles.\n" +" Takes a list of polylines (each point a vector) and returns the point indices for a polyline filled with 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_a1: target triangle vertex.\n" -" :type tri_a1: :class:`mathutils.Vector`\n" -" :arg tri_a2: target triangle vertex.\n" -" :type tri_a2: :class:`mathutils.Vector`\n" -" :arg tri_a3: target triangle vertex.\n" -" :type tri_a3: :class:`mathutils.Vector`\n" -" :return: The transformed point\n" -" :rtype: :class:`mathutils.Vector`'s\n" +" :arg veclist_list: list of polylines\n" +" :rtype: list\n" ); -static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args) +/* PolyFill function, uses Blenders scanfill to fill multiple poly lines */ +static PyObject *M_Geometry_tesselate_polygon(PyObject *UNUSED(self), PyObject *polyLineSeq) { - VectorObject *vec_pt; - VectorObject *vec_t1_tar, *vec_t2_tar, *vec_t3_tar; - VectorObject *vec_t1_src, *vec_t2_src, *vec_t3_src; - float vec[3]; + PyObject *tri_list; /*return this list of tri's */ + PyObject *polyLine, *polyVec; + int i, len_polylines, len_polypoints, ls_error= 0; - if(!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!:barycentric_transform", - &vector_Type, &vec_pt, - &vector_Type, &vec_t1_src, - &vector_Type, &vec_t2_src, - &vector_Type, &vec_t3_src, - &vector_Type, &vec_t1_tar, - &vector_Type, &vec_t2_tar, - &vector_Type, &vec_t3_tar) - ) { + /* 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; } - if( vec_pt->size != 3 || - vec_t1_src->size != 3 || - vec_t2_src->size != 3 || - vec_t3_src->size != 3 || - vec_t1_tar->size != 3 || - vec_t2_tar->size != 3 || - vec_t3_tar->size != 3) - { - PyErr_SetString(PyExc_ValueError, "One of more of the vector arguments wasnt a 3D vector"); + len_polylines= PySequence_Size(polyLineSeq); + + for(i= 0; i < len_polylines; ++i) { + polyLine= PySequence_GetItem(polyLineSeq, i); + if (!PySequence_Check(polyLine)) { + freedisplist(&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) { /* dont 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 + fp[2]= 0.0f; /* if its a 2d vector then set the z to be zero */ + } + else { + ls_error= 1; + } + + totpoints++; + Py_DECREF(polyVec); + } + } + Py_DECREF(polyLine); + } + + if(ls_error) { + freedisplist(&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 */ + filldisplist(&dispbase, &dispbase, 0); - barycentric_transform(vec, vec_pt->vec, - vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec, - vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec); + /* The faces are stored in a new DisplayList + thats added to the head of the listbase */ + dl= dispbase.first; - return newVectorObject(vec, 3, Py_NEW, NULL); + tri_list= PyList_New(dl->parts); + if(!tri_list) { + freedisplist(&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, Py_BuildValue("iii", dl_face[0], dl_face[1], dl_face[2])); + dl_face+= 3; + index++; + } + freedisplist(&dispbase); + } + else { + /* no points, do this so scripts dont barf */ + freedisplist(&dispbase); /* possible some dl was allocated */ + tri_list= PyList_New(0); + } + + return tri_list; +} + + +static int boxPack_FromPyObject(PyObject *value, boxPack **boxarray) +{ + int 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_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_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) +{ + int len, i; + PyObject *list_item; + boxPack *box; + + len= PyList_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" +); +static PyObject *M_Geometry_box_pack_2d(PyObject *UNUSED(self), PyObject *boxlist) +{ + float tot_width= 0.0f, tot_height= 0.0f; + int 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 */ + boxPack2D(boxarray, len, &tot_width, &tot_height); + + boxPack_ToPyObject(boxlist, &boxarray); + } + + ret= PyTuple_New(2); + PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(tot_width)); + PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(tot_width)); + 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}, @@ -917,12 +1102,16 @@ static PyMethodDef M_Geometry_methods[]= { {"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}, - {"interpolate_bezier", (PyCFunction) M_Geometry_interpolate_bezier, METH_VARARGS, M_Geometry_interpolate_bezier_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}, {"area_tri", (PyCFunction) M_Geometry_area_tri, METH_VARARGS, M_Geometry_area_tri_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}, +#ifndef MATH_STANDALONE + {"interpolate_bezier", (PyCFunction) M_Geometry_interpolate_bezier, METH_VARARGS, M_Geometry_interpolate_bezier_doc}, {"tesselate_polygon", (PyCFunction) M_Geometry_tesselate_polygon, METH_O, M_Geometry_tesselate_polygon_doc}, {"box_pack_2d", (PyCFunction) M_Geometry_box_pack_2d, METH_O, M_Geometry_box_pack_2d_doc}, - {"barycentric_transform", (PyCFunction) M_Geometry_barycentric_transform, METH_VARARGS, M_Geometry_barycentric_transform_doc}, +#endif {NULL, NULL, 0, NULL} }; @@ -939,7 +1128,7 @@ static struct PyModuleDef M_Geometry_module_def= { }; /*----------------------------MODULE INIT-------------------------*/ -PyMODINIT_FUNC BPyInit_mathutils_geometry(void) +PyMODINIT_FUNC PyInit_mathutils_geometry(void) { PyObject *submodule= PyModule_Create(&M_Geometry_module_def); return submodule; diff --git a/source/blender/python/generic/mathutils_geometry.h b/source/blender/python/mathutils/mathutils_geometry.h index 929b8cc8d75..c963a63ce7f 100644 --- a/source/blender/python/generic/mathutils_geometry.h +++ b/source/blender/python/mathutils/mathutils_geometry.h @@ -38,6 +38,6 @@ #include "mathutils.h" -PyMODINIT_FUNC BPyInit_mathutils_geometry(void); +PyMODINIT_FUNC PyInit_mathutils_geometry(void); #endif /* MATHUTILS_GEOMETRY_H */ |