diff options
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/SConscript | 121 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_api.c | 16 | ||||
-rw-r--r-- | source/blender/python/intern/CMakeLists.txt | 124 | ||||
-rw-r--r-- | source/blender/python/intern/bpy.c | 10 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_app.c | 3 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_app_build_options.c | 176 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_app_build_options.h | 32 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 23 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Matrix.c | 83 |
9 files changed, 545 insertions, 43 deletions
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index b0164d24852..21af50dbf10 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -1,4 +1,29 @@ -#!/usr/bin/python +#!/usr/bin/env python +# +# ***** 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. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Nathan Letwory. +# +# ***** END GPL LICENSE BLOCK ***** # TODO, split into 3 files. @@ -47,16 +72,100 @@ if env['WITH_BF_PYTHON_SAFETY']: if env['BF_BUILDINFO']: defs.append('BUILD_DATE') -if env['WITH_BF_INTERNATIONAL']: - defs.append('WITH_INTERNATIONAL') -if env['WITH_BF_CYCLES']: - defs.append('WITH_CYCLES') +# Audaspace is always on currently + +if env['WITH_BF_BULLET']: + defs.append('WITH_BULLET') + +# AVI is always on currently if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') incs += ' ' + env['BF_FFMPEG_INC'] - + +if env['WITH_BF_QUICKTIME']: + defs.append('WITH_QUICKTIME') + +if env['WITH_BF_SNDFILE']: + defs.append('WITH_SNDFILE') + +if env['WITH_BF_COMPOSITOR']: + defs.append('WITH_COMPOSITOR') + +if env['WITH_BF_CYCLES']: + defs.append('WITH_CYCLES') + +if env['WITH_BF_CYCLES']: + defs.append('WITH_CYCLES') + +if env['WITH_BF_CYCLES_OSL']: + defs.append('WITH_CYCLES_OSL') + +if env['WITH_BF_GAMEENGINE']: + defs.append('WITH_GAMEENGINE') + +if env['WITH_BF_CINEON']: + defs.append('WITH_CINEON') + +if env['WITH_BF_DDS']: + defs.append('WITH_DDS') + +if env['WITH_BF_FRAMESERVER']: + defs.append('WITH_FRAMESERVER') + +if env['WITH_BF_HDR']: + defs.append('WITH_HDR') + +if env['WITH_BF_OPENEXR']: + defs.append('WITH_OPENEXR') + +if env['WITH_BF_OPENJPEG']: + defs.append('WITH_OPENJPEG') + +if env['WITH_BF_REDCODE']: + defs.append('WITH_REDCODE') + +if env['WITH_BF_TIFF']: + defs.append('WITH_TIFF') + +# NDof is always on currently + +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + +if env['WITH_BF_JACK']: + defs.append('WITH_JACK') + +if env['WITH_BF_LIBMV']: + defs.append('WITH_LIBMV') + +if env['WITH_BF_BOOLEAN']: + defs.append('WITH_MOD_BOOLEAN') + +if env['WITH_BF_FLUID']: + defs.append('WITH_MOD_FLUID') + +if env['WITH_BF_OCEANSIM']: + defs.append('WITH_OCEANSIM') + +if env['WITH_BF_REMESH']: + defs.append('WITH_MOD_REMESH') + +if env['WITH_BF_SMOKE']: + defs.append('WITH_SMOKE') + +if env['WITH_BF_OPENAL']: + defs.append('WITH_OPENAL') + +if env['WITH_BF_COLLADA']: + defs.append('WITH_COLLADA') + +if env['WITH_BF_PLAYER']: + defs.append('WITH_PLAYER') + + + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index 18f5d895132..9abb13731af 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -98,7 +98,7 @@ static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value) } PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc, -".. method:: update_edit_mesh(mesh, tessface=True)\n" +".. method:: update_edit_mesh(mesh, tessface=True, destructive=True)\n" "\n" " Update the mesh after changes to the BMesh in editmode, \n" " optionally recalculating n-gon tessellation.\n" @@ -107,14 +107,17 @@ PyDoc_STRVAR(bpy_bm_update_edit_mesh_doc, " :type mesh: :class:`bpy.types.Mesh`\n" " :arg tessface: Option to recalculate n-gon tessellation.\n" " :type tessface: boolean\n" +" :arg destructive: Use when grometry has been added or removed.\n" +" :type destructive: boolean\n" ); static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args) { PyObject *py_me; Mesh *me; int do_tessface = TRUE; + int is_destructive = TRUE; - if (!PyArg_ParseTuple(args, "O|i:update_edit_mesh", &py_me, &do_tessface)) { + if (!PyArg_ParseTuple(args, "O|ii:update_edit_mesh", &py_me, &do_tessface, &is_destructive)) { return NULL; } @@ -131,13 +134,8 @@ static PyObject *bpy_bm_update_edit_mesh(PyObject *UNUSED(self), PyObject *args) } { - /* XXX, not great - infact this function could just not use the context at all - * postpone that change until after release: BMESH_TODO - campbell */ - extern struct bContext *BPy_GetContext(void); - extern void EDBM_update_generic(struct bContext *C, BMEditMesh *em, const short do_tessface); - - struct bContext *C = BPy_GetContext(); - EDBM_update_generic(C, me->edit_btmesh, do_tessface); + extern void EDBM_update_generic(BMEditMesh *em, const short do_tessface, const short is_destructive); + EDBM_update_generic(me->edit_btmesh, do_tessface, is_destructive); } Py_RETURN_NONE; diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt index bd660b94321..b2ce33b08c7 100644 --- a/source/blender/python/intern/CMakeLists.txt +++ b/source/blender/python/intern/CMakeLists.txt @@ -48,6 +48,7 @@ set(SRC bpy.c bpy_app.c bpy_app_ffmpeg.c + bpy_app_build_options.c bpy_app_handlers.c bpy_driver.c bpy_interface.c @@ -69,6 +70,7 @@ set(SRC bpy.h bpy_app.h bpy_app_ffmpeg.h + bpy_app_build_options.h bpy_app_handlers.h bpy_driver.h bpy_intern_string.h @@ -97,24 +99,136 @@ if(WITH_PYTHON_SAFETY) add_definitions(-DWITH_PYTHON_SAFETY) endif() + + if(WITH_AUDASPACE) add_definitions(-DWITH_AUDASPACE) endif() -if(WITH_CYCLES) - add_definitions(-DWITH_CYCLES) +if(WITH_BULLET) + add_definitions(-DWITH_BULLET) endif() -if(WITH_INTERNATIONAL) - add_definitions(-DWITH_INTERNATIONAL) +if(WITH_CODEC_AVI) + add_definitions(-DWITH_AVI) endif() if(WITH_CODEC_FFMPEG) list(APPEND INC_SYS ${FFMPEG_INCLUDE_DIRS} ) - add_definitions(-DWITH_FFMPEG) endif() +if(WITH_CODEC_QUICKTIME) + add_definitions(-DWITH_QUICKTIME) +endif() + +if(WITH_CODEC_SNDFILE) + add_definitions(-DWITH_SNDFILE) +endif() + +if(WITH_COMPOSITOR) + add_definitions(-DWITH_COMPOSITOR) +endif() + +if(WITH_CYCLES) + add_definitions(-DWITH_CYCLES) +endif() + +if(WITH_CYCLES_OSL) + add_definitions(-DWITH_CYCLES_OSL) +endif() + +if(WITH_GAMEENGINE) + add_definitions(-DWITH_GAMEENGINE) +endif() + +if(WITH_IMAGE_CINEON) + add_definitions(-DWITH_CINEON) +endif() + +if(WITH_IMAGE_DDS) + add_definitions(-DWITH_DDS) +endif() + +if(WITH_IMAGE_FRAMESERVER) + add_definitions(-DWITH_FRAMESERVER) +endif() + +if(WITH_IMAGE_HDR) + add_definitions(-DWITH_HDR) +endif() + +if(WITH_IMAGE_OPENEXR) + add_definitions(-DWITH_OPENEXR) +endif() + +if(WITH_IMAGE_OPENJPEG) + add_definitions(-DWITH_OPENJPEG) +endif() + +if(WITH_IMAGE_REDCODE) + add_definitions(-DWITH_REDCODE) +endif() + +if(WITH_IMAGE_TIFF) + add_definitions(-DWITH_TIFF) +endif() + +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() + +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + +if(WITH_JACK) + add_definitions(-DWITH_JACK) +endif() + +if(WITH_LIBMV) + add_definitions(-DWITH_LIBMV) +endif() + +if(WITH_LIBMV) + add_definitions(-DWITH_LIBMV) +endif() + +if(WITH_MOD_BOOLEAN) + add_definitions(-DWITH_MOD_BOOLEAN) +endif() + +if(WITH_MOD_FLUID) + add_definitions(-DWITH_MOD_FLUID) +endif() + +if(WITH_MOD_OCEANSIM) + add_definitions(-DWITH_OCEANSIM) +endif() + +if(WITH_MOD_REMESH) + add_definitions(-DWITH_MOD_REMESH) +endif() + +if(WITH_MOD_SMOKE) + add_definitions(-DWITH_SMOKE) +endif() + +if(WITH_OPENAL) + add_definitions(-DWITH_OPENAL) +endif() + +if(WITH_OPENCOLLADA) + add_definitions(-DWITH_COLLADA) +endif() + +if(WITH_PLAYER) + add_definitions(-DWITH_PLAYER) +endif() + + + + blender_add_lib(bf_python "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 6897a8591b0..b0dd8a29fbe 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -45,7 +45,7 @@ #include "BLI_path_util.h" #include "BLI_string.h" -#include "BLI_bpath.h" +#include "BKE_bpath.h" #include "BLI_utildefines.h" #include "BKE_main.h" @@ -129,13 +129,13 @@ static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObjec return NULL; } - if (absolute) flag |= BLI_BPATH_TRAVERSE_ABS; - if (!packed) flag |= BLI_BPATH_TRAVERSE_SKIP_PACKED; - if (local) flag |= BLI_BPATH_TRAVERSE_SKIP_LIBRARY; + if (absolute) flag |= BKE_BPATH_TRAVERSE_ABS; + if (!packed) flag |= BKE_BPATH_TRAVERSE_SKIP_PACKED; + if (local) flag |= BKE_BPATH_TRAVERSE_SKIP_LIBRARY; list = PyList_New(0); - BLI_bpath_traverse_main(G.main, bpy_blend_paths_visit_cb, flag, (void *)list); + BKE_bpath_traverse_main(G.main, bpy_blend_paths_visit_cb, flag, (void *)list); return list; } diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index b1eeff8b3ae..bea63d2b6e8 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -34,6 +34,7 @@ #include "bpy_app.h" #include "bpy_app_ffmpeg.h" +#include "bpy_app_build_options.h" #include "bpy_app_handlers.h" #include "bpy_driver.h" @@ -83,6 +84,7 @@ static PyStructSequence_Field app_info_fields[] = { /* submodules */ {(char *)"ffmpeg", (char *)"FFmpeg library information backend"}, + {(char *)"build_options", (char *)"A set containing most important enabled optional build features"}, {(char *)"handlers", (char *)"Application handler callbacks"}, {NULL} }; @@ -148,6 +150,7 @@ static PyObject *make_app_info(void) #endif SetObjItem(BPY_app_ffmpeg_struct()); + SetObjItem(BPY_app_build_options_struct()); SetObjItem(BPY_app_handlers_struct()); #undef SetIntItem diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c new file mode 100644 index 00000000000..607613b592c --- /dev/null +++ b/source/blender/python/intern/bpy_app_build_options.c @@ -0,0 +1,176 @@ +/* + * ***** 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): Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_build_options.c + * \ingroup pythonintern + */ + +#include <Python.h> +#include "BLI_utildefines.h" + +#include "bpy_app_build_options.h" + +static PyObject *make_build_options(void) +{ + PyObject *build_options = PyFrozenSet_New(NULL); + +#define SetStrItem(str) \ + PySet_Add(build_options, PyUnicode_FromString(str)); + +#ifdef WITH_AUDASPACE + SetStrItem("AUDASPACE"); +#endif + +#ifdef WITH_BULLET + SetStrItem("BULLET"); +#endif + +#ifdef WITH_AVI + SetStrItem("CODEC_AVI"); +#endif + +#ifdef WITH_FFMPEG + SetStrItem("CODEC_FFMPEG"); +#endif + +#ifdef WITH_QUICKTIME + SetStrItem("CODEC_QUICKTIME"); +#endif + +#ifdef WITH_SNDFILE + SetStrItem("CODEC_SNDFILE"); +#endif + +#ifdef WITH_COMPOSITOR + SetStrItem("COMPOSITOR"); +#endif + +#ifdef WITH_CYCLES + SetStrItem("CYCLES"); +#endif + +#ifdef WITH_CYCLES_OSL + SetStrItem("CYCLES_OSL"); +#endif + +#ifdef WITH_GAMEENGINE + SetStrItem("GAMEENGINE"); +#endif + +#ifdef WITH_CINEON + SetStrItem("IMAGE_CINEON"); +#endif + +#ifdef WITH_DDS + SetStrItem("IMAGE_DDS"); +#endif + +#ifdef WITH_FRAMESERVER + SetStrItem("IMAGE_FRAMESERVER"); +#endif + +#ifdef WITH_HDR + SetStrItem("IMAGE_HDR"); +#endif + +#ifdef WITH_OPENEXR + SetStrItem("IMAGE_OPENEXR"); +#endif + +#ifdef WITH_OPENJPEG + SetStrItem("IMAGE_OPENJPEG"); +#endif + +#ifdef WITH_REDCODE + SetStrItem("IMAGE_REDCODE"); +#endif + +#ifdef WITH_TIFF + SetStrItem("IMAGE_TIFF"); +#endif + +#ifdef WITH_INPUT_NDOF + SetStrItem("INPUT_NDOF"); +#endif + +#ifdef WITH_INTERNATIONAL + SetStrItem("INTERNATIONAL"); +#endif + +#ifdef WITH_JACK + SetStrItem("JACK"); +#endif + +#ifdef WITH_LIBMV + SetStrItem("LIBMV"); +#endif + +#ifdef WITH_MOD_BOOLEAN + SetStrItem("MOD_BOOLEAN"); +#endif + +#ifdef WITH_MOD_FLUID + SetStrItem("MOD_FLUID"); +#endif + +#ifdef WITH_OCEANSIM + SetStrItem("MOD_OCEANSIM"); +#endif + +#ifdef WITH_MOD_REMESH + SetStrItem("MOD_REMESH"); +#endif + +#ifdef WITH_SMOKE + SetStrItem("MOD_SMOKE"); +#endif + +#ifdef WITH_OPENAL + SetStrItem("OPENAL"); +#endif + +#ifdef WITH_COLLADA + SetStrItem("COLLADA"); +#endif + +#ifdef WITH_PLAYER + SetStrItem("PLAYER"); +#endif + +#undef SetStrItem + + if (PyErr_Occurred()) { + Py_CLEAR(build_options); + return NULL; + } + + return build_options; +} + +PyObject *BPY_app_build_options_struct(void) +{ + PyObject *ret; + + ret = make_build_options(); + + return ret; +} diff --git a/source/blender/python/intern/bpy_app_build_options.h b/source/blender/python/intern/bpy_app_build_options.h new file mode 100644 index 00000000000..82a1417ea2c --- /dev/null +++ b/source/blender/python/intern/bpy_app_build_options.h @@ -0,0 +1,32 @@ +/* + * ***** 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): Bastien Montagne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/python/intern/bpy_app_build_options.h + * \ingroup pythonintern + */ + +#ifndef __BPY_APP_BUILD_OPTIONS_H__ +#define __BPY_APP_BUILD_OPTIONS_H__ + +PyObject *BPY_app_build_options_struct(void); + +#endif /* __BPY_APP_BUILD_OPTIONS_H__ */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index a0df8988068..55983c73895 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1478,7 +1478,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha } -static PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func) +static PyObject *pyrna_func_to_py(const PointerRNA *ptr, FunctionRNA *func) { BPy_FunctionRNA *pyfunc = (BPy_FunctionRNA *) PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type); pyfunc->ptr = *ptr; @@ -6029,6 +6029,27 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna) PyObject_SetAttr(newclass, bpy_intern_str_bl_rna, item); Py_DECREF(item); + /* add classmethods */ + { + const PointerRNA func_ptr = {{NULL}, srna, NULL}; + const ListBase *lb; + Link *link; + + lb = RNA_struct_type_functions(srna); + for (link = lb->first; link; link = link->next) { + FunctionRNA *func = (FunctionRNA *)link; + const int flag = RNA_function_flag(func); + if ((flag & FUNC_NO_SELF) && /* is classmethod */ + (flag & FUNC_REGISTER) == FALSE) /* is not for registration */ + { + /* we may went to set the type of this later */ + PyObject *func_py = pyrna_func_to_py(&func_ptr, func); + PyObject_SetAttrString(newclass, RNA_function_identifier(func), func_py); + Py_DECREF(func_py); + } + } + } + /* done with rna instance */ } diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 05306f230d1..da2888045d0 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -1025,13 +1025,13 @@ static PyObject *Matrix_resize_4x4(MatrixObject *self) int col; if (self->wrapped == Py_WRAP) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.resize_4x4(): " "cannot resize wrapped data - make a copy and resize that"); return NULL; } if (self->cb_user) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.resize_4x4(): " "cannot resize owned data - make a copy and resize that"); return NULL; @@ -1080,7 +1080,7 @@ static PyObject *Matrix_to_4x4(MatrixObject *self) } /* TODO, 2x2 matrix */ - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.to_4x4(): " "inappropriate matrix size"); return NULL; @@ -1102,7 +1102,7 @@ static PyObject *Matrix_to_3x3(MatrixObject *self) return NULL; if ((self->num_row < 3) || (self->num_col < 3)) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.to_3x3(): inappropriate matrix size"); return NULL; } @@ -1126,7 +1126,7 @@ static PyObject *Matrix_to_translation(MatrixObject *self) return NULL; if ((self->num_row < 3) || self->num_col < 4) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.to_translation(): " "inappropriate matrix size"); return NULL; @@ -1156,7 +1156,7 @@ static PyObject *Matrix_to_scale(MatrixObject *self) /*must be 3-4 cols, 3-4 rows, square matrix */ if ((self->num_row < 3) || (self->num_col < 3)) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.to_scale(): " "inappropriate matrix size, 3x3 minimum size"); return NULL; @@ -1194,7 +1194,7 @@ static PyObject *Matrix_invert(MatrixObject *self) return NULL; if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.invert(ed): " "only square matrices are supported"); return NULL; @@ -1222,7 +1222,7 @@ static PyObject *Matrix_invert(MatrixObject *self) break; } default: - PyErr_Format(PyExc_TypeError, + PyErr_Format(PyExc_ValueError, "Matrix invert(ed): size (%d) unsupported", (int)self->num_col); return NULL; @@ -1281,7 +1281,7 @@ static PyObject *Matrix_adjugate(MatrixObject *self) return NULL; if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.adjugate(d): " "only square matrices are supported"); return NULL; @@ -1311,7 +1311,7 @@ static PyObject *Matrix_adjugate(MatrixObject *self) break; } default: - PyErr_Format(PyExc_TypeError, + PyErr_Format(PyExc_ValueError, "Matrix adjugate(d): size (%d) unsupported", (int)self->num_col); return NULL; @@ -1357,7 +1357,7 @@ static PyObject *Matrix_rotate(MatrixObject *self, PyObject *value) return NULL; if (self->num_row != 3 || self->num_col != 3) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.rotate(): " "must have 3x3 dimensions"); return NULL; @@ -1390,7 +1390,7 @@ static PyObject *Matrix_decompose(MatrixObject *self) float size[3]; if (self->num_row != 4 || self->num_col != 4) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.decompose(): " "inappropriate matrix size - expects 4x4 matrix"); return NULL; @@ -1476,7 +1476,7 @@ static PyObject *Matrix_determinant(MatrixObject *self) return NULL; if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.determinant(): " "only square matrices are supported"); return NULL; @@ -1498,7 +1498,7 @@ static PyObject *Matrix_transpose(MatrixObject *self) return NULL; if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.transpose(d): " "only square matrices are supported"); return NULL; @@ -1533,6 +1533,53 @@ static PyObject *Matrix_transposed(MatrixObject *self) return matrix__apply_to_copy((PyNoArgsFunction)Matrix_transpose, self); } +/*---------------------------matrix.normalize() ------------------*/ +PyDoc_STRVAR(Matrix_normalize_doc, +".. method:: normalize()\n" +"\n" +" Normalize each of the matrix columns.\n" +); +static PyObject *Matrix_normalize(MatrixObject *self) +{ + if (BaseMath_ReadCallback(self) == -1) + return NULL; + + if (self->num_col != self->num_row) { + PyErr_SetString(PyExc_ValueError, + "Matrix.normalize(): " + "only square matrices are supported"); + return NULL; + } + + if (self->num_col == 3) { + normalize_m3((float (*)[3])self->matrix); + } + else if (self->num_col == 4) { + normalize_m4((float (*)[4])self->matrix); + } + else { + PyErr_SetString(PyExc_ValueError, + "Matrix.normalize(): " + "can only use a 3x3 or 4x4 matrix"); + } + + (void)BaseMath_WriteCallback(self); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(Matrix_normalized_doc, +".. method:: normalized()\n" +"\n" +" Return a column normalized matrix\n" +"\n" +" :return: a column normalized matrix\n" +" :rtype: :class:`Matrix`\n" +); +static PyObject *Matrix_normalized(MatrixObject *self) +{ + return matrix__apply_to_copy((PyNoArgsFunction)Matrix_normalize, self); +} + /*---------------------------matrix.zero() -----------------------*/ PyDoc_STRVAR(Matrix_zero_doc, ".. method:: zero()\n" @@ -1568,7 +1615,7 @@ static PyObject *Matrix_identity(MatrixObject *self) return NULL; if (self->num_col != self->num_row) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix.identity(): " "only square matrices are supported"); return NULL; @@ -1924,7 +1971,7 @@ static PyObject *Matrix_add(PyObject *m1, PyObject *m2) return NULL; if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix addition: " "matrices must have the same dimensions for this operation"); return NULL; @@ -1956,7 +2003,7 @@ static PyObject *Matrix_sub(PyObject *m1, PyObject *m2) return NULL; if (mat1->num_col != mat2->num_col || mat1->num_row != mat2->num_row) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "Matrix addition: " "matrices must have the same dimensions for this operation"); return NULL; @@ -2371,6 +2418,8 @@ static struct PyMethodDef Matrix_methods[] = { /* operate on original or copy */ {"transpose", (PyCFunction) Matrix_transpose, METH_NOARGS, Matrix_transpose_doc}, {"transposed", (PyCFunction) Matrix_transposed, METH_NOARGS, Matrix_transposed_doc}, + {"normalize", (PyCFunction) Matrix_normalize, METH_NOARGS, Matrix_normalize_doc}, + {"normalized", (PyCFunction) Matrix_normalized, METH_NOARGS, Matrix_normalized_doc}, {"invert", (PyCFunction) Matrix_invert, METH_NOARGS, Matrix_invert_doc}, {"inverted", (PyCFunction) Matrix_inverted, METH_NOARGS, Matrix_inverted_doc}, {"adjugate", (PyCFunction) Matrix_adjugate, METH_NOARGS, Matrix_adjugate_doc}, |