30 bpy_bm_utils_vert_collapse_edge_doc,
31 ".. method:: vert_collapse_edge(vert, edge)\n"
33 " Collapse a vertex into an edge.\n"
35 " :arg vert: The vert that will be collapsed.\n"
36 " :type vert: :class:`bmesh.types.BMVert`\n"
37 " :arg edge: The edge to collapse into.\n"
38 " :type edge: :class:`bmesh.types.BMEdge`\n"
39 " :return: The resulting edge from the collapse operation.\n"
40 " :rtype: :class:`bmesh.types.BMEdge`\n");
49 if (!PyArg_ParseTuple(
59 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
60 PyErr_SetString(PyExc_ValueError,
61 "vert_collapse_edge(vert, edge): the vertex is not found in the edge");
66 PyErr_SetString(PyExc_ValueError,
67 "vert_collapse_edge(vert, edge): vert has more than 2 connected edges");
79 PyErr_SetString(PyExc_ValueError,
80 "vert_collapse_edge(vert, edge): no new edge created, internal error");
86 bpy_bm_utils_vert_collapse_faces_doc,
87 ".. method:: vert_collapse_faces(vert, edge, fac, join_faces)\n"
89 " Collapses a vertex that has only two manifold edges onto a vertex it shares an "
92 " :arg vert: The vert that will be collapsed.\n"
93 " :type vert: :class:`bmesh.types.BMVert`\n"
94 " :arg edge: The edge to collapse into.\n"
95 " :type edge: :class:`bmesh.types.BMEdge`\n"
96 " :arg fac: The factor to use when merging customdata [0 - 1].\n"
98 " :arg join_faces: When true the faces around the vertex will be joined otherwise "
99 "collapse the vertex by merging the 2 edges this vertex connects to into one.\n"
100 " :type join_faces: bool\n"
101 " :return: The resulting edge from the collapse operation.\n"
102 " :rtype: :class:`bmesh.types.BMEdge`\n");
114 if (!PyArg_ParseTuple(args,
115 "O!O!fi:vert_collapse_faces",
130 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
131 PyErr_SetString(PyExc_ValueError,
132 "vert_collapse_faces(vert, edge): the vertex is not found in the edge");
137 PyErr_SetString(PyExc_ValueError,
138 "vert_collapse_faces(vert, edge): vert has more than 2 connected edges");
145 bm, py_edge->
e, py_vert->
v,
clamp_f(fac, 0.0f, 1.0f),
true, do_join_faces,
true,
true);
151 PyErr_SetString(PyExc_ValueError,
152 "vert_collapse_faces(vert, edge): no new edge created, internal error");
158 bpy_bm_utils_vert_dissolve_doc,
159 ".. method:: vert_dissolve(vert)\n"
161 " Dissolve this vertex (will be removed).\n"
163 " :arg vert: The vert to be dissolved.\n"
164 " :type vert: :class:`bmesh.types.BMVert`\n"
165 " :return: True when the vertex dissolve is successful.\n"
173 if (!PyArg_ParseTuple(args,
"O!:vert_dissolve", &
BPy_BMVert_Type, &py_vert)) {
186 bpy_bm_utils_vert_splice_doc,
187 ".. method:: vert_splice(vert, vert_target)\n"
189 " Splice vert into vert_target.\n"
191 " :arg vert: The vertex to be removed.\n"
192 " :type vert: :class:`bmesh.types.BMVert`\n"
193 " :arg vert_target: The vertex to use.\n"
194 " :type vert_target: :class:`bmesh.types.BMVert`\n"
196 " .. note:: The verts mustn't share an edge or face.\n");
206 if (!PyArg_ParseTuple(
218 if (py_vert->
v == py_vert_target->
v) {
219 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): vert arguments match");
224 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): verts can't share an edge");
229 PyErr_SetString(PyExc_ValueError,
"vert_splice(...): verts can't share a face");
243 bpy_bm_utils_vert_separate_doc,
244 ".. method:: vert_separate(vert, edges)\n"
246 " Separate this vertex at every edge.\n"
248 " :arg vert: The vert to be separated.\n"
249 " :type vert: :class:`bmesh.types.BMVert`\n"
250 " :arg edges: The edges to separated.\n"
251 " :type edges: :class:`bmesh.types.BMEdge`\n"
252 " :return: The newly separated verts (including the vertex passed).\n"
253 " :rtype: tuple[:class:`bmesh.types.BMVert`, ...]\n");
265 Py_ssize_t edge_array_len;
269 if (!PyArg_ParseTuple(args,
"O!O:vert_separate", &
BPy_BMVert_Type, &py_vert, &edge_seq)) {
285 "vert_separate(...)"));
287 if (edge_array ==
nullptr) {
296 PyMem_FREE(edge_array);
303 bpy_bm_utils_edge_split_doc,
304 ".. method:: edge_split(edge, vert, fac)\n"
306 " Split an edge, return the newly created data.\n"
308 " :arg edge: The edge to split.\n"
309 " :type edge: :class:`bmesh.types.BMEdge`\n"
310 " :arg vert: One of the verts on the edge, defines the split direction.\n"
311 " :type vert: :class:`bmesh.types.BMVert`\n"
312 " :arg fac: The point on the edge where the new vert will be created [0 - 1].\n"
313 " :type fac: float\n"
314 " :return: The newly created (edge, vert) pair.\n"
315 " :rtype: tuple[:class:`bmesh.types.BMEdge`, :class:`bmesh.types.BMVert`]\n");
326 if (!PyArg_ParseTuple(
336 if (!(py_edge->
e->
v1 == py_vert->
v || py_edge->
e->
v2 == py_vert->
v)) {
337 PyErr_SetString(PyExc_ValueError,
338 "edge_split(edge, vert): the vertex is not found in the edge");
346 if (v_new && e_new) {
347 PyObject *
ret = PyTuple_New(2);
353 PyErr_SetString(PyExc_ValueError,
354 "edge_split(edge, vert): couldn't split the edge, internal error");
360 bpy_bm_utils_edge_rotate_doc,
361 ".. method:: edge_rotate(edge, ccw=False)\n"
363 " Rotate the edge and return the newly created edge.\n"
364 " If rotating the edge fails, None will be returned.\n"
366 " :arg edge: The edge to rotate.\n"
367 " :type edge: :class:`bmesh.types.BMEdge`\n"
368 " :arg ccw: When True the edge will be rotated counter clockwise.\n"
370 " :return: The newly rotated edge.\n"
371 " :rtype: :class:`bmesh.types.BMEdge`\n");
380 if (!PyArg_ParseTuple(
401 bpy_bm_utils_face_split_doc,
402 ".. method:: face_split(face, vert_a, vert_b, coords=(), use_exist=True, example=None)\n"
404 " Face split with optional intermediate points.\n"
406 " :arg face: The face to cut.\n"
407 " :type face: :class:`bmesh.types.BMFace`\n"
408 " :arg vert_a: First vertex to cut in the face (face must contain the vert).\n"
409 " :type vert_a: :class:`bmesh.types.BMVert`\n"
410 " :arg vert_b: Second vertex to cut in the face (face must contain the vert).\n"
411 " :type vert_b: :class:`bmesh.types.BMVert`\n"
412 " :arg coords: Optional sequence of 3D points in between *vert_a* and *vert_b*.\n"
413 " :type coords: Sequence[Sequence[float]]\n"
414 " :arg use_exist: .Use an existing edge if it exists (Only used when *coords* argument is "
415 "empty or omitted)\n"
416 " :type use_exist: bool\n"
417 " :arg example: Newly created edge will copy settings from this one.\n"
418 " :type example: :class:`bmesh.types.BMEdge`\n"
419 " :return: The newly created face or None on failure.\n"
420 " :rtype: tuple[:class:`bmesh.types.BMFace`, :class:`bmesh.types.BMLoop`]\n");
423 static const char *kwlist[] = {
424 "face",
"vert_a",
"vert_b",
"coords",
"use_exist",
"example",
nullptr};
431 PyObject *py_coords =
nullptr;
432 bool edge_exists =
true;
443 if (!PyArg_ParseTupleAndKeywords(args,
445 "O!O!O!|$OO&O!:face_split",
466 if (py_edge_example) {
477 PyErr_SetString(PyExc_ValueError,
478 "face_split(...): one of the verts passed is not found in the face");
482 if (py_vert_a->
v == py_vert_b->
v) {
483 PyErr_SetString(PyExc_ValueError,
"face_split(...): vert arguments must differ");
495 PyErr_SetString(PyExc_ValueError,
"face_split(...): verts are adjacent in the face");
511 py_edge_example ? py_edge_example->
e :
nullptr);
520 py_edge_example ? py_edge_example->
e :
nullptr,
524 if (f_new && l_new) {
525 PyObject *
ret = PyTuple_New(2);
531 PyErr_SetString(PyExc_ValueError,
"face_split(...): couldn't split the face, internal error");
537 bpy_bm_utils_face_split_edgenet_doc,
538 ".. method:: face_split_edgenet(face, edgenet)\n"
540 " Splits a face into any number of regions defined by an edgenet.\n"
542 " :arg face: The face to split.\n"
543 " :type face: :class:`bmesh.types.BMFace`\n"
544 " :arg face: The face to split.\n"
545 " :type face: :class:`bmesh.types.BMFace`\n"
546 " :arg edgenet: Sequence of edges.\n"
547 " :type edgenet: Sequence[:class:`bmesh.types.BMEdge`]\n"
548 " :return: The newly created faces.\n"
549 " :rtype: tuple[:class:`bmesh.types.BMFace`, ...]\n"
553 " Regions defined by edges need to connect to the face, otherwise they're "
554 "ignored as loose edges.\n");
557 static const char *kwlist[] = {
"face",
"edgenet",
nullptr};
563 Py_ssize_t edge_array_len;
569 if (!PyArg_ParseTupleAndKeywords(args,
571 "O!O:face_split_edgenet",
592 "face_split_edgenet(...)"));
594 if (edge_array ==
nullptr) {
602 PyMem_FREE(edge_array);
609 PyErr_SetString(PyExc_ValueError,
610 "face_split_edgenet(...): couldn't split the face, internal error");
616 bpy_bm_utils_face_join_doc,
617 ".. method:: face_join(faces, remove=True)\n"
619 " Joins a sequence of faces.\n"
621 " :arg faces: Sequence of faces.\n"
622 " :type faces: :class:`bmesh.types.BMFace`\n"
623 " :arg remove: Remove the edges and vertices between the faces.\n"
624 " :type remove: bool\n"
625 " :return: The newly created face or None on failure.\n"
626 " :rtype: :class:`bmesh.types.BMFace`\n");
630 PyObject *py_face_array;
632 Py_ssize_t face_seq_len = 0;
634 bool do_remove =
true;
636 if (!PyArg_ParseTuple(args,
"O|O&:face_join", &py_face_array,
PyC_ParseBool, &do_remove)) {
650 if (face_array ==
nullptr) {
658 PyMem_FREE(face_array);
669 bpy_bm_utils_face_vert_separate_doc,
670 ".. method:: face_vert_separate(face, vert)\n"
672 " Rip a vertex in a face away and add a new vertex.\n"
674 " :arg face: The face to separate.\n"
675 " :type face: :class:`bmesh.types.BMFace`\n"
676 " :arg vert: A vertex in the face to separate.\n"
677 " :type vert: :class:`bmesh.types.BMVert`\n"
678 " :return vert: The newly created vertex or None on failure.\n"
679 " :rtype vert: :class:`bmesh.types.BMVert`\n"
683 " This is the same as loop_separate, and has only been added for convenience.\n");
693 if (!PyArg_ParseTuple(
707 PyErr_SetString(PyExc_ValueError,
"vertex not found in face");
714 if (v_new != v_old) {
723 bpy_bm_utils_face_flip_doc,
724 ".. method:: face_flip(faces)\n"
726 " Flip the faces direction.\n"
728 " :arg face: Face to flip.\n"
729 " :type face: :class:`bmesh.types.BMFace`\n");
733 PyErr_Format(PyExc_TypeError,
734 "face_flip(face): BMFace expected, not '%.200s'",
735 Py_TYPE(value)->tp_name);
748 bpy_bm_utils_loop_separate_doc,
749 ".. method:: loop_separate(loop)\n"
751 " Rip a vertex in a face away and add a new vertex.\n"
753 " :arg loop: The loop to separate.\n"
754 " :type loop: :class:`bmesh.types.BMLoop`\n"
755 " :return vert: The newly created vertex or None on failure.\n"
756 " :rtype vert: :class:`bmesh.types.BMVert`\n");
764 PyErr_Format(PyExc_TypeError,
765 "loop_separate(loop): BMLoop expected, not '%.200s'",
766 Py_TYPE(value)->tp_name);
778 if (v_new != v_old) {
785#if (defined(__GNUC__) && !defined(__clang__))
786# pragma GCC diagnostic push
787# pragma GCC diagnostic ignored "-Wcast-function-type"
791 {
"vert_collapse_edge",
794 bpy_bm_utils_vert_collapse_edge_doc},
795 {
"vert_collapse_faces",
798 bpy_bm_utils_vert_collapse_faces_doc},
802 bpy_bm_utils_vert_dissolve_doc},
806 bpy_bm_utils_vert_splice_doc},
810 bpy_bm_utils_vert_separate_doc},
814 bpy_bm_utils_edge_split_doc},
818 bpy_bm_utils_edge_rotate_doc},
821 METH_VARARGS | METH_KEYWORDS,
822 bpy_bm_utils_face_split_doc},
823 {
"face_split_edgenet",
825 METH_VARARGS | METH_KEYWORDS,
826 bpy_bm_utils_face_split_edgenet_doc},
828 {
"face_vert_separate",
831 bpy_bm_utils_face_vert_separate_doc},
836 bpy_bm_utils_loop_separate_doc},
837 {
nullptr,
nullptr, 0,
nullptr},
840#if (defined(__GNUC__) && !defined(__clang__))
841# pragma GCC diagnostic pop
847 "This module provides access to blenders bmesh data structures.");
849 PyModuleDef_HEAD_INIT,
MINLINE float clamp_f(float value, float min, float max)
#define UNUSED_VARS_NDEBUG(...)
Read Guarded memory(de)allocation.
BMFace * BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
Join Connected Faces.
void BM_vert_separate(BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select, BMVert ***r_vout, int *r_vout_len)
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
Splice Vert.
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMFace * BM_face_split_n(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, float cos[][3], int n, BMLoop **r_l, BMEdge *example)
Face Split with intermediate points.
BMVert * BM_face_loop_separate(BMesh *bm, BMLoop *l_sep)
Rip a single face from a vertex fan.
BMEdge * BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, const bool do_del, const bool join_faces, const bool kill_degenerate_faces, const bool kill_duplicate_faces)
Vert Collapse Faces.
bool BM_vert_dissolve(BMesh *bm, BMVert *v)
Dissolve Vert.
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
BMEdge * BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool do_del, const bool kill_degenerate_faces, const bool kill_duplicate_faces)
Vert Collapse Faces.
BMEdge * BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag)
Rotate Edge.
BMFace * BM_face_split(BMesh *bm, BMFace *f, BMLoop *l_a, BMLoop *l_b, BMLoop **r_l, BMEdge *example, const bool no_double)
Face Split.
void BM_face_normal_flip(BMesh *bm, BMFace *f)
bool BM_face_split_edgenet(BMesh *bm, BMFace *f, BMEdge **edge_net, const int edge_net_len, blender::Vector< BMFace * > *r_face_arr)
PyObject * BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
PyObject * BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len)
PyObject * BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
PyObject * BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
PyObject * BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len)
PyTypeObject BPy_BMEdge_Type
void * BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size, const char htype, const bool do_unique_check, const bool do_bm_check, const char *error_prefix)
PyTypeObject BPy_BMVert_Type
PyTypeObject BPy_BMFace_Type
PyObject * BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
#define BPy_BMFace_Check(v)
#define BPY_BM_CHECK_OBJ(obj)
#define BPy_BMLoop_Check(v)
#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg,...)
PyObject * BPyInit_bmesh_utils()
static PyObject * bpy_bm_utils_vert_splice(PyObject *, PyObject *args)
static PyModuleDef BPy_BM_utils_module_def
static PyObject * bpy_bm_utils_vert_collapse_faces(PyObject *, PyObject *args)
PyDoc_STRVAR(bpy_bm_utils_vert_collapse_edge_doc, ".. method:: vert_collapse_edge(vert, edge)\n" "\n" " Collapse a vertex into an edge.\n" "\n" " :arg vert: The vert that will be collapsed.\n" " :type vert: :class:`bmesh.types.BMVert`\n" " :arg edge: The edge to collapse into.\n" " :type edge: :class:`bmesh.types.BMEdge`\n" " :return: The resulting edge from the collapse operation.\n" " :rtype: :class:`bmesh.types.BMEdge`\n")
static PyObject * bpy_bm_utils_face_split(PyObject *, PyObject *args, PyObject *kw)
static PyObject * bpy_bm_utils_face_join(PyObject *, PyObject *args)
static PyObject * bpy_bm_utils_vert_collapse_edge(PyObject *, PyObject *args)
static PyObject * bpy_bm_utils_vert_dissolve(PyObject *, PyObject *args)
static PyObject * bpy_bm_utils_vert_separate(PyObject *, PyObject *args)
static PyObject * bpy_bm_utils_loop_separate(PyObject *, BPy_BMLoop *value)
static PyObject * bpy_bm_utils_face_flip(PyObject *, BPy_BMFace *value)
static PyObject * bpy_bm_utils_edge_split(PyObject *, PyObject *args)
static PyObject * bpy_bm_utils_face_split_edgenet(PyObject *, PyObject *args, PyObject *kw)
static PyObject * bpy_bm_utils_edge_rotate(PyObject *, PyObject *args)
static PyMethodDef BPy_BM_utils_methods[]
static PyObject * bpy_bm_utils_face_vert_separate(PyObject *, PyObject *args)
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
BMLoop * BM_face_vert_share_loop(BMFace *f, BMVert *v)
Return the Loop Shared by Face and Vertex.
BLI_INLINE bool BM_loop_is_adjacent(const BMLoop *l_a, const BMLoop *l_b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BM_vert_edge_count_is_over(v, n)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
void MEM_freeN(void *vmemh)
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
int PyC_ParseBool(PyObject *o, void *p)
#define PyTuple_SET_ITEMS(op_arg,...)
PyObject_VAR_HEAD BMesh * bm
PyObject_VAR_HEAD BMesh * bm
PyObject_VAR_HEAD BMesh * bm