From 49ff0eeec443ebe5003ec09bc655d73abc69a327 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 22 Apr 2012 10:19:24 +0000 Subject: bmesh py api: expose BM_face_split_n() to the python api; face_fill(..., coords=(v1, v2, ...)) This is the same function the knife tool uses. should be handy for dicing up geometry in py. --- source/blender/python/bmesh/bmesh_py_utils.c | 64 ++++++++++++++++++++++------ source/blender/python/mathutils/mathutils.c | 35 +++++++++++++++ source/blender/python/mathutils/mathutils.h | 1 + 3 files changed, 86 insertions(+), 14 deletions(-) (limited to 'source/blender') diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index fcc4ebc67e1..9fecc0cdeda 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -36,6 +36,8 @@ #include "MEM_guardedalloc.h" +#include "../mathutils/mathutils.h" + #include "bmesh.h" #include "bmesh_py_types.h" @@ -366,7 +368,7 @@ static PyObject *bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args PyDoc_STRVAR(bpy_bm_utils_face_split_doc, -".. method:: face_split(face, vert, vert_a, vert_b, edge_example)\n" +".. method:: face_split(face, vert_a, vert_b, coords=(), use_exist=True, example=None)\n" "\n" " Split an edge, return the newly created data.\n" "\n" @@ -376,25 +378,43 @@ PyDoc_STRVAR(bpy_bm_utils_face_split_doc, " :type vert_a: :class:`bmesh.types.BMVert`\n" " :arg vert_b: Second vertex to cut in the face (face must contain the vert).\n" " :type vert_b: :class:`bmesh.types.BMVert`\n" -" :arg edge_example: Optional edge argument, newly created edge will copy settings from this one.\n" -" :type edge_example: :class:`bmesh.types.BMEdge`\n" +" :arg coords: Optional argument to define points inbetween *vert_a* and *vert_b*.\n" +" :type coords: sequence of float triplets\n" +" :arg use_exist: .Use an existing edge if it exists (Only used when *coords* argument is empty or omitted)\n" +" :type use_exist: boolean\n" +" :arg example: Newly created edge will copy settings from this one.\n" +" :type example: :class:`bmesh.types.BMEdge`\n" +" :return: The newly created face or None on failure.\n" +" :rtype: (:class:`bmesh.types.BMFace`, :class:`bmesh.types.BMLoop`) pair\n" ); -static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args) +static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { + static const char *kwlist[] = {"face", "vert_a", "vert_b", + "coords", "use_exist", "example", NULL}; + BPy_BMFace *py_face; BPy_BMVert *py_vert_a; BPy_BMVert *py_vert_b; - BPy_BMEdge *py_edge_example = NULL; /* optional */ + + /* optional */ + PyObject *py_coords = NULL; + int edge_exists = TRUE; + BPy_BMEdge *py_edge_example = NULL; + + float *coords; + int ncoords = 0; BMesh *bm; BMFace *f_new = NULL; BMLoop *l_new = NULL; - if (!PyArg_ParseTuple(args, "O!O!O!|O!:face_split", - &BPy_BMFace_Type, &py_face, - &BPy_BMVert_Type, &py_vert_a, - &BPy_BMVert_Type, &py_vert_b, - &BPy_BMEdge_Type, &py_edge_example)) + if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!O!|OiO!:face_split", (char **)kwlist, + &BPy_BMFace_Type, &py_face, + &BPy_BMVert_Type, &py_vert_a, + &BPy_BMVert_Type, &py_vert_b, + &py_coords, + &edge_exists, + &BPy_BMEdge_Type, &py_edge_example)) { return NULL; } @@ -422,11 +442,27 @@ static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args) return NULL; } + if (py_coords) { + ncoords = mathutils_array_parse_alloc_v(&coords, 3, py_coords, "face_split(...): "); + if (ncoords == -1) { + return NULL; + } + } + + /* --- main function body --- */ bm = py_face->bm; - f_new = BM_face_split(bm, py_face->f, - py_vert_a->v, py_vert_b->v, - &l_new, py_edge_example ? py_edge_example->e : NULL, FALSE); /* BMESH_TODO, make arg */ + if (ncoords) { + f_new = BM_face_split_n(bm, py_face->f, + py_vert_a->v, py_vert_b->v, + (float (*)[3])coords, ncoords, + &l_new, py_edge_example ? py_edge_example->e : NULL); + } + else { + f_new = BM_face_split(bm, py_face->f, + py_vert_a->v, py_vert_b->v, + &l_new, py_edge_example ? py_edge_example->e : NULL, edge_exists); + } if (f_new && l_new) { PyObject *ret = PyTuple_New(2); @@ -622,7 +658,7 @@ static struct PyMethodDef BPy_BM_utils_methods[] = { {"vert_separate", (PyCFunction)bpy_bm_utils_vert_separate, METH_VARARGS, bpy_bm_utils_vert_separate_doc}, {"edge_split", (PyCFunction)bpy_bm_utils_edge_split, METH_VARARGS, bpy_bm_utils_edge_split_doc}, {"edge_rotate", (PyCFunction)bpy_bm_utils_edge_rotate, METH_VARARGS, bpy_bm_utils_edge_rotate_doc}, - {"face_split", (PyCFunction)bpy_bm_utils_face_split, METH_VARARGS, bpy_bm_utils_face_split_doc}, + {"face_split", (PyCFunction)bpy_bm_utils_face_split, METH_VARARGS | METH_KEYWORDS, bpy_bm_utils_face_split_doc}, {"face_join", (PyCFunction)bpy_bm_utils_face_join, METH_VARARGS, bpy_bm_utils_face_join_doc}, {"face_vert_separate", (PyCFunction)bpy_bm_utils_face_vert_separate, METH_VARARGS, bpy_bm_utils_face_vert_separate_doc}, {"face_flip", (PyCFunction)bpy_bm_utils_face_flip, METH_O, bpy_bm_utils_face_flip_doc}, diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index f78050a7639..8b79301f264 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -186,6 +186,41 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c } } +/* parse an array of vectors */ +int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix) +{ + PyObject *value_fast = NULL; + int i, size; + + /* non list/tuple cases */ + if (!(value_fast = PySequence_Fast(value, error_prefix))) { + /* PySequence_Fast sets the error */ + return -1; + } + + size = PySequence_Fast_GET_SIZE(value_fast); + + if (size != 0) { + float *fp; + + fp = *array = PyMem_Malloc(size * array_dim * sizeof(float)); + + for (i = 0; i < size; i++, fp += array_dim) { + PyObject *item = PySequence_Fast_GET_ITEM(value, i); + + if (mathutils_array_parse(fp, array_dim, array_dim, item, error_prefix) == -1) { + PyMem_Free(*array); + *array = NULL; + size = -1; + break; + } + } + } + + Py_DECREF(value_fast); + return size; +} + int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix) { if (EulerObject_Check(value)) { diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index b98928eb79d..e8d128b431e 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -118,6 +118,7 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); /* utility func */ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix); +int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix); int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix); int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat); -- cgit v1.2.3