diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-03-09 04:01:38 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-03-09 04:01:38 +0400 |
commit | 27d43f3fd3a6fbda95cdb87e4672fe34f19c2205 (patch) | |
tree | 818a5c1744ea0471093fde5387e57c92f7f00546 /source/blender | |
parent | 06b2343b50ff502390b8c7cd62f8e103d03cec51 (diff) |
added API function to C and python
* C: BM_vert_separate(...)
* py: bmesh.utils.vert_separate(vert, edges)
This splits off regions around the vertex, splitting on connected edges passed in a sequence.
also made minor changes
- rename python api functions _rip to _separate
- fixed bmesh iterator being iterable its self (some parts of python expect this)
- fix memory leak in bmesh python api.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.c | 70 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.h | 16 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.c | 13 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.h | 3 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_utils.c | 100 | ||||
-rw-r--r-- | source/blender/python/generic/idprop_py_api.c | 8 |
6 files changed, 154 insertions, 56 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 31c8e1f8119..3ca7750f571 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -41,7 +41,7 @@ * TESTING ONLY! */ // #define USE_DEBUG_INDEX_MEMCHECK -int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget); +static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep); #ifdef USE_DEBUG_INDEX_MEMCHECK #define DEBUG_MEMCHECK_INDEX_INVALIDATE(ele) \ @@ -1739,14 +1739,16 @@ static int bm_vert_splice(BMesh *bm, BMVert *v, BMVert *vtarget) } /** - * \brief Cut Vert + * \brief Separate Vert * - * Cut all disjoint fans that meet at a vertex, making a unique + * Separates all disjoint fans that meet at a vertex, making a unique * vertex for each region. returns an array of all resulting vertices. * + * \note this is a low level function, bm_edge_separate needs to run on edges first + * * \return Success */ -static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) +int bm_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) { BMEdge **stack = NULL; BLI_array_declare(stack); @@ -1758,7 +1760,7 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) int i, maxindex; BMLoop *nl; - visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh_vert_cut visithash"); + visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); maxindex = 0; BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, v) { @@ -1786,7 +1788,7 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) } /* Make enough verts to split v for each group */ - verts = MEM_callocN(sizeof(BMVert *) * maxindex, "bmesh_vert_cut"); + verts = MEM_callocN(sizeof(BMVert *) * maxindex, __func__); verts[0] = v; for (i = 1; i < maxindex; i++) { verts[i] = BM_vert_create(bm, v->co, v); @@ -1829,12 +1831,12 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) BM_CHECK_ELEMENT(bm, verts[i]); } - if (len != NULL) { - *len = maxindex; + if (r_vout_len != NULL) { + *r_vout_len = maxindex; } - if (vout != NULL) { - *vout = verts; + if (r_vout != NULL) { + *r_vout = verts; } else { MEM_freeN(verts); @@ -1844,6 +1846,24 @@ static int bm_vert_cut(BMesh *bm, BMVert *v, BMVert ***vout, int *len) } /** + * High level function which wraps both #bm_vert_separate and #bm_edge_separate + */ +int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + BMEdge **e_in, int e_in_len) +{ + int i; + + for (i = 0; i < e_in_len; i++) { + BMEdge *e = e_in[i]; + if (e->l && BM_vert_in_edge(e, v)) { + bm_edge_separate(bm, e, e->l); + } + } + + return bm_vert_separate(bm, v, r_vout, r_vout_len); +} + +/** * \brief Splice Edge * * Splice two unique edges which share the same two vertices into one edge. @@ -1881,22 +1901,22 @@ int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget) } /** - * \brief Cut Edge + * \brief Separate Edge * - * Cuts a single edge into two edge: the original edge and - * a new edge that has only \a cutl in its radial. + * Separates a single edge into two edge: the original edge and + * a new edge that has only \a l_sep in its radial. * * \return Success * - * \note Does nothing if \a cutl is already the only loop in the + * \note Does nothing if \a l_sep is already the only loop in the * edge radial. */ -static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl) +static int bm_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) { BMEdge *ne; int radlen; - BLI_assert(cutl->e == e); + BLI_assert(l_sep->e == e); BLI_assert(e->l); radlen = bmesh_radial_length(e->l); @@ -1905,14 +1925,14 @@ static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl) return TRUE; } - if (cutl == e->l) { - e->l = cutl->radial_next; + if (l_sep == e->l) { + e->l = l_sep->radial_next; } ne = BM_edge_create(bm, e->v1, e->v2, e, FALSE); - bmesh_radial_loop_remove(cutl, e); - bmesh_radial_append(ne, cutl); - cutl->e = ne; + bmesh_radial_loop_remove(l_sep, e); + bmesh_radial_append(ne, l_sep); + l_sep->e = ne; BLI_assert(bmesh_radial_length(e->l) == radlen - 1); BLI_assert(bmesh_radial_length(ne->l) == 1); @@ -1939,8 +1959,8 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) /* peel the face from the edge radials on both sides of the * loop vert, disconnecting the face from its fan */ - bm_edge_cut(bm, sl->e, sl); - bm_edge_cut(bm, sl->prev->e, sl->prev); + bm_edge_separate(bm, sl->e, sl); + bm_edge_separate(bm, sl->prev->e, sl->prev); if (bmesh_disk_count(sv) == 2) { /* If there are still only two edges out of sv, then @@ -1949,7 +1969,7 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) } /* Update the disk start, so that v->e points to an edge - * not touching the split loop. This is so that bmesh_vert_cut + * not touching the split loop. This is so that BM_vert_split * will leave the original sv on some *other* fan (not the * one-face fan that holds the unglue face). */ while (sv->e == sl->e || sv->e == sl->prev->e) { @@ -1958,7 +1978,7 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) /* Split all fans connected to the vert, duplicating it for * each fans. */ - bm_vert_cut(bm, sv, &vtar, &len); + bm_vert_separate(bm, sv, &vtar, &len); /* There should have been at least two fans cut apart here, * otherwise the early exit would have kicked in. */ diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index fe05c69bcae..11f3e052bff 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -33,18 +33,20 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example); BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble); BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble); -void BM_face_edges_kill(BMesh *bm, BMFace *f); -void BM_face_verts_kill(BMesh *bm, BMFace *f); +void BM_face_edges_kill(BMesh *bm, BMFace *f); +void BM_face_verts_kill(BMesh *bm, BMFace *f); -void BM_face_kill(BMesh *bm, BMFace *f); -void BM_edge_kill(BMesh *bm, BMEdge *e); -void BM_vert_kill(BMesh *bm, BMVert *v); +void BM_face_kill(BMesh *bm, BMFace *f); +void BM_edge_kill(BMesh *bm, BMEdge *e); +void BM_vert_kill(BMesh *bm, BMVert *v); -int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget); +int BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *etarget); -int bmesh_loop_reverse(BMesh *bm, BMFace *f); +int bmesh_loop_reverse(BMesh *bm, BMFace *f); BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface); +int BM_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, + BMEdge **e_in, int e_in_len); /* EULER API - For modifying structure */ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index bb3da095847..812e958dea3 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -2309,6 +2309,7 @@ void BPy_BM_init_types(void) /* only 1 iteratir so far */ BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next; + BPy_BMIter_Type.tp_iter = PyObject_SelfIter; BPy_BMesh_Type.tp_dealloc = (destructor)bpy_bmesh_dealloc; BPy_BMVert_Type.tp_dealloc = (destructor)bpy_bmvert_dealloc; @@ -2673,3 +2674,15 @@ err_cleanup: return NULL; } } + + +PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len) +{ + Py_ssize_t i; + PyObject *ret = PyTuple_New(elem_len); + for (i = 0; i < elem_len; i++) { + PyTuple_SET_ITEM(ret, i, BPy_BMElem_CreatePyObject(bm, elem[i])); + } + + return ret; +} diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index d7deb41c4e3..f496527768d 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -137,6 +137,9 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ const char do_unique_check, const char do_bm_check, const char *error_prefix); +PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len); + + #define BPY_BM_CHECK_OBJ(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return NULL; } (void)0 #define BPY_BM_CHECK_INT(obj) if (UNLIKELY(bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1)) { return -1; } (void)0 diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index ad65f68f4db..8e9537f1d86 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -38,6 +38,8 @@ #include "BLI_utildefines.h" +#include "MEM_guardedalloc.h" + #include "bmesh_py_utils.h" /* own include */ @@ -196,6 +198,67 @@ static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *ar return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v))); } +PyDoc_STRVAR(bpy_bm_utils_vert_separate_doc, +".. method:: vert_separate(vert, edges)\n" +"\n" +" Separate this vertex at every edge.\n" +"\n" +" :arg vert: The vert to be separated.\n" +" :type vert: :class:`BMVert`\n" +" :arg edges: The edges to separated.\n" +" :type edges: :class:`BMEdge`\n" +" :return: The newly separated verts (including the vertex passed).\n" +" :rtype: tuple of :class:`BMVert`\n" +); +static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *args) +{ + BPy_BMVert *py_vert; + PyObject *edge_seq; + + BMesh *bm; + BMVert **elem; + int elem_len; + + /* edges to split */ + BMEdge **edge_array; + Py_ssize_t edge_array_len; + + PyObject *ret; + + + if (!PyArg_ParseTuple(args, "O!O:vert_separate", + &BPy_BMVert_Type, &py_vert, + &edge_seq)) + { + return NULL; + } + + BPY_BM_CHECK_OBJ(py_vert); + + bm = py_vert->bm; + + edge_array = BPy_BMElem_PySeq_As_Array(&bm, edge_seq, 0, PY_SSIZE_T_MAX, + &edge_array_len, &BPy_BMEdge_Type, + TRUE, TRUE, "vert_separate(...)"); + + if (edge_array == NULL) { + return NULL; + } + + if (BM_vert_separate(bm, py_vert->v, &elem, &elem_len, edge_array, edge_array_len)) { + /* return collected verts */ + ret = BPy_BMElem_Array_As_Tuple(bm, (BMHeader **)elem, elem_len); + MEM_freeN(elem); + } + else { + ret = PyTuple_New(0); + } + + PyMem_FREE(edge_array); + + return ret; +} + PyDoc_STRVAR(bpy_bm_utils_edge_split_doc, ".. method:: edge_split(edge, vert, fac)\n" @@ -408,6 +471,8 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *value) * --------------------------- */ f_new = BM_faces_join(bm, face_array, (int)face_seq_len); + PyMem_FREE(face_array); + if (f_new) { return BPy_BMFace_CreatePyObject(bm, f_new); } @@ -417,23 +482,23 @@ static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *value) } -PyDoc_STRVAR(bpy_bm_utils_face_vert_rip_doc, -".. method:: face_vert_rip(face, vert)\n" +PyDoc_STRVAR(bpy_bm_utils_face_vert_separate_doc, +".. method:: face_vert_separate(face, vert)\n" "\n" " Rip a vertex in a face away and add a new vertex.\n" "\n" -" :arg face: The face to rip.\n" +" :arg face: The face to separate.\n" " :type face: :class:`BMFace`\n" -" :arg vert: A vertex in the face to rip.\n" +" :arg vert: A vertex in the face to separate.\n" " :type vert: :class:`BMVert`\n" " :return vert: The newly created vertex or None of failure.\n" " :rtype vert: :class:`BMVert`\n" "\n" " .. note::\n" "\n" -" This is the same as loop_rip, and has only been added for convenience.\n" +" This is the same as loop_separate, and has only been added for convenience.\n" ); -static PyObject *bpy_bm_utils_face_vert_rip(PyObject *UNUSED(self), PyObject *args) +static PyObject *bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObject *args) { BPy_BMFace *py_face; BPy_BMVert *py_vert; @@ -442,7 +507,7 @@ static PyObject *bpy_bm_utils_face_vert_rip(PyObject *UNUSED(self), PyObject *ar BMLoop *l; BMVert *v_new; - if (!PyArg_ParseTuple(args, "O!O!:face_vert_rip", + if (!PyArg_ParseTuple(args, "O!O!:face_vert_separate", &BPy_BMFace_Type, &py_face, &BPy_BMVert_Type, &py_vert)) { @@ -468,7 +533,7 @@ static PyObject *bpy_bm_utils_face_vert_rip(PyObject *UNUSED(self), PyObject *ar return NULL; } - v_new = BM_face_loop_rip(bm, l); + v_new = BM_face_loop_separate(bm, l); if (v_new != l->v) { return BPy_BMVert_CreatePyObject(bm, v_new); @@ -505,24 +570,24 @@ static PyObject *bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *valu -PyDoc_STRVAR(bpy_bm_utils_loop_rip_doc, -".. method:: loop_rip(loop)\n" +PyDoc_STRVAR(bpy_bm_utils_loop_separate_doc, +".. method:: loop_separate(loop)\n" "\n" " Rip a vertex in a face away and add a new vertex.\n" "\n" -" :arg loop: The to rip.\n" +" :arg loop: The to separate.\n" " :type loop: :class:`BMFace`\n" " :return vert: The newly created vertex or None of failure.\n" " :rtype vert: :class:`BMVert`\n" ); -static PyObject *bpy_bm_utils_loop_rip(PyObject *UNUSED(self), BPy_BMLoop *value) +static PyObject *bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value) { BMesh *bm; BMVert *v_new; if (!BPy_BMLoop_Check(value)) { PyErr_Format(PyExc_TypeError, - "loop_rip(loop): BMLoop expected, not '%.200s'", + "loop_separate(loop): BMLoop expected, not '%.200s'", Py_TYPE(value)->tp_name); return NULL; } @@ -531,7 +596,7 @@ static PyObject *bpy_bm_utils_loop_rip(PyObject *UNUSED(self), BPy_BMLoop *value bm = value->bm; - v_new = BM_face_loop_rip(bm, value->l); + v_new = BM_face_loop_separate(bm, value->l); if (v_new != value->l->v) { return BPy_BMVert_CreatePyObject(bm, v_new); @@ -545,14 +610,15 @@ static PyObject *bpy_bm_utils_loop_rip(PyObject *UNUSED(self), BPy_BMLoop *value static struct PyMethodDef BPy_BM_utils_methods[] = { {"vert_collapse_edge", (PyCFunction)bpy_bm_utils_vert_collapse_edge, METH_VARARGS, bpy_bm_utils_vert_collapse_edge_doc}, {"vert_collapse_faces", (PyCFunction)bpy_bm_utils_vert_collapse_faces, METH_VARARGS, bpy_bm_utils_vert_collapse_faces_doc}, - {"vert_dissolve", (PyCFunction)bpy_bm_utils_vert_dissolve, METH_VARARGS, bpy_bm_utils_vert_dissolve_doc}, + {"vert_dissolve", (PyCFunction)bpy_bm_utils_vert_dissolve, METH_VARARGS, bpy_bm_utils_vert_dissolve_doc}, /* could use METH_O */ + {"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_join", (PyCFunction)bpy_bm_utils_face_join, METH_O, bpy_bm_utils_face_join_doc}, - {"face_vert_rip", (PyCFunction)bpy_bm_utils_face_vert_rip, METH_VARARGS, bpy_bm_utils_face_vert_rip_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}, - {"loop_rip", (PyCFunction)bpy_bm_utils_loop_rip, METH_O, bpy_bm_utils_loop_rip_doc}, + {"loop_separate", (PyCFunction)bpy_bm_utils_loop_separate, METH_O, bpy_bm_utils_loop_separate_doc}, {NULL, NULL, 0, NULL} }; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index 3462e6ee5d4..33c5d3bd06d 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -1324,12 +1324,6 @@ PyTypeObject BPy_IDArray_Type = { /*********** ID Property Group iterator ********/ -static PyObject *IDGroup_Iter_iterself(PyObject *self) -{ - Py_XINCREF(self); - return self; -} - static PyObject *IDGroup_Iter_repr(BPy_IDGroup_Iter *self) { return PyUnicode_FromFormat("(ID Property Group Iter \"%s\")", self->group->prop->name); @@ -1412,7 +1406,7 @@ PyTypeObject BPy_IDGroup_Iter_Type = { /*** Added in release 2.2 ***/ /* Iterators */ - IDGroup_Iter_iterself, /* getiterfunc tp_iter; */ + PyObject_SelfIter, /* getiterfunc tp_iter; */ (iternextfunc) BPy_Group_Iter_Next, /* iternextfunc tp_iternext; */ }; |