diff options
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.c | 20 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.h | 1 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mods.c | 12 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mods.h | 3 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.c | 23 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_queries.h | 1 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_structure.c | 21 | ||||
-rw-r--r-- | source/blender/editors/mesh/bmesh_tools.c | 2 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.c | 4 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_utils.c | 102 |
10 files changed, 146 insertions, 43 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 16bc163ba34..31c8e1f8119 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1930,7 +1930,7 @@ static int bm_edge_cut(BMesh *bm, BMEdge *e, BMLoop *cutl) * * \return The newly created BMVert */ -static BMVert *bm_urmv_loop(BMesh *bm, BMLoop *sl) +BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) { BMVert **vtar; int len, i; @@ -2007,20 +2007,6 @@ static BMVert *bm_urmv_loop(BMesh *bm, BMLoop *sl) */ BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv) { - BMLoop *l_first; - BMLoop *l_iter; - - l_iter = l_first = BM_FACE_FIRST_LOOP(sf); - do { - if (l_iter->v == sv) { - break; - } - } while ((l_iter = l_iter->next) != l_first); - - if (l_iter->v != sv) { - /* sv is not part of sf */ - return NULL; - } - - return bm_urmv_loop(bm, l_iter); + BMLoop *l = BM_face_vert_share_loop(sf, sv); + return bmesh_urmv_loop(bm, l); } diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index f1ff506e590..fe05c69bcae 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -60,5 +60,6 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_splice); BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv); +BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl); #endif /* __BMESH_CORE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index b686a4b88e0..deed825aa0a 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -1073,7 +1073,17 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const short ccw, const short check_ /** * \brief Rip a single face from a vertex fan */ -BMVert *BM_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv) +BMVert *BM_face_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv) { return bmesh_urmv(bm, sf, sv); } + +/** + * \brief Rip a single face from a vertex fan + * + * \note same as #BM_face_vert_rip but faster (avoids a loop lookup) + */ +BMVert *BM_face_loop_rip(BMesh *bm, BMLoop *sl) +{ + return bmesh_urmv_loop(bm, sl); +} diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index db418a26341..994456f5917 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -77,6 +77,7 @@ enum { }; -BMVert *BM_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv); +BMVert *BM_face_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv); +BMVert *BM_face_loop_rip(BMesh *bm, BMLoop *sl); #endif /* __BMESH_MODS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index b80d6fe6e47..e6dc1e1dd80 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -557,6 +557,29 @@ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) } /** + * \brief Radial Find a Vertex Loop in Face + * + * Finds the loop used which uses \a v in face loop \a l + * + * \note currenly this just uses simple loop in future may be speeded up + * using radial vars + */ +BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v) +{ + BMLoop *l_first; + BMLoop *l_iter; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (l_iter->v == v) { + return l_iter; + } + } while ((l_iter = l_iter->next) != l_first); + + return NULL; +} + +/** * Returns the verts of an edge as used in a face * if used in a face at all, otherwise just assign as used in the edge. * diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 6cad93d2658..a394999d439 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -72,6 +72,7 @@ int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2); int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2); +BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v); void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2); diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index fa6d9315fab..eca90e8e7f2 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -450,27 +450,6 @@ BMLoop *bmesh_radial_faceloop_find_next(BMLoop *l, BMVert *v) return l; } -/* NOTE: this function has not been used or tested - so take care but it should work ok, - * I wrote it for some tool that ended up not using it, however this seems like a reasonable - * thing to be able to find the loop between a vertex and a face so keeping - campbell */ -/** - * \brief Radial Find a Vertex Loop in Face - * - * Finds the loop used which uses \a v in face loop \a l - */ -BMLoop *bmesh_radial_faceloop_find_vert(BMFace *f, BMVert *v) /* name is a bit awkward */ -{ - BMLoop *l_iter, *l_first; - if (v->e && (l_iter = l_first = v->e->l)) { - do { - if (l_iter->v == v && l_iter->f == f) { - return l_iter; - } - } while ((l_iter = l_iter->radial_next) != l_first); - } - return NULL; -} - int bmesh_radial_length(BMLoop *l) { BMLoop *l_iter = l; diff --git a/source/blender/editors/mesh/bmesh_tools.c b/source/blender/editors/mesh/bmesh_tools.c index 858e39defd0..41eb85007f2 100644 --- a/source/blender/editors/mesh/bmesh_tools.c +++ b/source/blender/editors/mesh/bmesh_tools.c @@ -2409,7 +2409,7 @@ static int mesh_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) /* rip two adjacent edges */ if (BM_edge_face_count(e2) == 1 || BM_vert_face_count(v) == 2) { l = e2->l; - ripvert = BM_vert_rip(bm, l->f, v); + ripvert = BM_face_vert_rip(bm, l->f, v); BLI_assert(ripvert); if (!ripvert) { diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 5dc4e94c98a..bb3da095847 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -961,7 +961,7 @@ static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value) BPY_BM_CHECK_OBJ(value); if (self->bm != value->bm) { - PyErr_SetString(PyExc_TypeError, + PyErr_SetString(PyExc_ValueError, "BMEdge.other_vert(vert): vert is from another mesh"); return NULL; } @@ -2625,7 +2625,7 @@ void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ /* trick so we can ensure all items have the same mesh, * and allows us to pass the 'bm' as NULL. */ else if (do_bm_check && (bm && bm != item->bm)) { - PyErr_Format(PyExc_TypeError, + PyErr_Format(PyExc_ValueError, "%s: %d %s is from another mesh", error_prefix, i, type->tp_name); goto err_cleanup; diff --git a/source/blender/python/bmesh/bmesh_py_utils.c b/source/blender/python/bmesh/bmesh_py_utils.c index 3fc4b7003fb..ad65f68f4db 100644 --- a/source/blender/python/bmesh/bmesh_py_utils.c +++ b/source/blender/python/bmesh/bmesh_py_utils.c @@ -417,6 +417,68 @@ 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" +"\n" +" Rip a vertex in a face away and add a new vertex.\n" +"\n" +" :arg face: The face to rip.\n" +" :type face: :class:`BMFace`\n" +" :arg vert: A vertex in the face to rip.\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" +); +static PyObject *bpy_bm_utils_face_vert_rip(PyObject *UNUSED(self), PyObject *args) +{ + BPy_BMFace *py_face; + BPy_BMVert *py_vert; + + BMesh *bm; + BMLoop *l; + BMVert *v_new; + + if (!PyArg_ParseTuple(args, "O!O!:face_vert_rip", + &BPy_BMFace_Type, &py_face, + &BPy_BMVert_Type, &py_vert)) + { + return NULL; + } + + BPY_BM_CHECK_OBJ(py_face); + BPY_BM_CHECK_OBJ(py_vert); + + bm = py_face->bm; + + if (bm != py_vert->bm) { + PyErr_SetString(PyExc_ValueError, + "mesh elements are from different meshes"); + return NULL; + } + + l = BM_face_vert_share_loop(py_face->f, py_vert->v); + + if (l == NULL) { + PyErr_SetString(PyExc_ValueError, + "vertex not found in face"); + return NULL; + } + + v_new = BM_face_loop_rip(bm, l); + + if (v_new != l->v) { + return BPy_BMVert_CreatePyObject(bm, v_new); + } + else { + Py_RETURN_NONE; + } +} + + PyDoc_STRVAR(bpy_bm_utils_face_flip_doc, ".. method:: face_flip(faces)\n" "\n" @@ -442,6 +504,44 @@ 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" +"\n" +" Rip a vertex in a face away and add a new vertex.\n" +"\n" +" :arg loop: The to rip.\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) +{ + BMesh *bm; + BMVert *v_new; + + if (!BPy_BMLoop_Check(value)) { + PyErr_Format(PyExc_TypeError, + "loop_rip(loop): BMLoop expected, not '%.200s'", + Py_TYPE(value)->tp_name); + return NULL; + } + + BPY_BM_CHECK_OBJ(value); + + bm = value->bm; + + v_new = BM_face_loop_rip(bm, value->l); + + if (v_new != value->l->v) { + return BPy_BMVert_CreatePyObject(bm, v_new); + } + else { + Py_RETURN_NONE; + } +} + + 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}, @@ -450,7 +550,9 @@ static struct PyMethodDef BPy_BM_utils_methods[] = { {"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_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}, {NULL, NULL, 0, NULL} }; |