Blender  V2.93
bmesh_py_utils.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2012 Blender Foundation.
17  * All rights reserved.
18  */
19 
27 #include <Python.h>
28 
29 #include "BLI_math_base.h"
30 #include "BLI_utildefines.h"
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "../mathutils/mathutils.h"
35 
36 #include "bmesh.h"
37 #include "bmesh_py_types.h"
38 #include "bmesh_py_utils.h" /* own include */
39 
40 #include "../generic/py_capi_utils.h"
41 #include "../generic/python_utildefines.h"
42 
43 PyDoc_STRVAR(bpy_bm_utils_vert_collapse_edge_doc,
44  ".. method:: vert_collapse_edge(vert, edge)\n"
45  "\n"
46  " Collapse a vertex into an edge.\n"
47  "\n"
48  " :arg vert: The vert that will be collapsed.\n"
49  " :type vert: :class:`bmesh.types.BMVert`\n"
50  " :arg edge: The edge to collapse into.\n"
51  " :type edge: :class:`bmesh.types.BMEdge`\n"
52  " :return: The resulting edge from the collapse operation.\n"
53  " :rtype: :class:`bmesh.types.BMEdge`\n");
54 static PyObject *bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObject *args)
55 {
56  BPy_BMEdge *py_edge;
57  BPy_BMVert *py_vert;
58 
59  BMesh *bm;
60  BMEdge *e_new = NULL;
61 
62  if (!PyArg_ParseTuple(args,
63  "O!O!:vert_collapse_edge",
65  &py_vert,
67  &py_edge)) {
68  return NULL;
69  }
70 
71  BPY_BM_CHECK_OBJ(py_edge);
72  BPY_BM_CHECK_OBJ(py_vert);
73 
74  /* this doubles for checking that the verts are in the same mesh */
75  if (!(py_edge->e->v1 == py_vert->v || py_edge->e->v2 == py_vert->v)) {
76  PyErr_SetString(PyExc_ValueError,
77  "vert_collapse_edge(vert, edge): the vertex is not found in the edge");
78  return NULL;
79  }
80 
81  if (BM_vert_edge_count_is_over(py_vert->v, 2)) {
82  PyErr_SetString(PyExc_ValueError,
83  "vert_collapse_edge(vert, edge): vert has more than 2 connected edges");
84  return NULL;
85  }
86 
87  bm = py_edge->bm;
88 
89  e_new = BM_vert_collapse_edge(bm, py_edge->e, py_vert->v, true, true, true);
90 
91  if (e_new) {
92  return BPy_BMEdge_CreatePyObject(bm, e_new);
93  }
94 
95  PyErr_SetString(PyExc_ValueError,
96  "vert_collapse_edge(vert, edge): no new edge created, internal error");
97  return NULL;
98 }
99 
100 PyDoc_STRVAR(bpy_bm_utils_vert_collapse_faces_doc,
101  ".. method:: vert_collapse_faces(vert, edge, fac, join_faces)\n"
102  "\n"
103  " Collapses a vertex that has only two manifold edges onto a vertex it shares an "
104  "edge with.\n"
105  "\n"
106  " :arg vert: The vert that will be collapsed.\n"
107  " :type vert: :class:`bmesh.types.BMVert`\n"
108  " :arg edge: The edge to collapse into.\n"
109  " :type edge: :class:`bmesh.types.BMEdge`\n"
110  " :arg fac: The factor to use when merging customdata [0 - 1].\n"
111  " :type fac: float\n"
112  " :arg join_faces: When true the faces around the vertex will be joined otherwise "
113  "collapse the vertex by merging the 2 edges this vertex connects to into one.\n"
114  " :type join_faces: bool\n"
115  " :return: The resulting edge from the collapse operation.\n"
116  " :rtype: :class:`bmesh.types.BMEdge`\n");
117 static PyObject *bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObject *args)
118 {
119  BPy_BMEdge *py_edge;
120  BPy_BMVert *py_vert;
121 
122  float fac;
123  int do_join_faces;
124 
125  BMesh *bm;
126  BMEdge *e_new = NULL;
127 
128  if (!PyArg_ParseTuple(args,
129  "O!O!fi:vert_collapse_faces",
131  &py_vert,
133  &py_edge,
134  &fac,
135  &do_join_faces)) {
136  return NULL;
137  }
138 
139  BPY_BM_CHECK_OBJ(py_edge);
140  BPY_BM_CHECK_OBJ(py_vert);
141 
142  /* this doubles for checking that the verts are in the same mesh */
143  if (!(py_edge->e->v1 == py_vert->v || py_edge->e->v2 == py_vert->v)) {
144  PyErr_SetString(PyExc_ValueError,
145  "vert_collapse_faces(vert, edge): the vertex is not found in the edge");
146  return NULL;
147  }
148 
149  if (BM_vert_edge_count_is_over(py_vert->v, 2)) {
150  PyErr_SetString(PyExc_ValueError,
151  "vert_collapse_faces(vert, edge): vert has more than 2 connected edges");
152  return NULL;
153  }
154 
155  bm = py_edge->bm;
156 
157  e_new = BM_vert_collapse_faces(
158  bm, py_edge->e, py_vert->v, clamp_f(fac, 0.0f, 1.0f), true, do_join_faces, true, true);
159 
160  if (e_new) {
161  return BPy_BMEdge_CreatePyObject(bm, e_new);
162  }
163 
164  PyErr_SetString(PyExc_ValueError,
165  "vert_collapse_faces(vert, edge): no new edge created, internal error");
166  return NULL;
167 }
168 
169 PyDoc_STRVAR(bpy_bm_utils_vert_dissolve_doc,
170  ".. method:: vert_dissolve(vert)\n"
171  "\n"
172  " Dissolve this vertex (will be removed).\n"
173  "\n"
174  " :arg vert: The vert to be dissolved.\n"
175  " :type vert: :class:`bmesh.types.BMVert`\n"
176  " :return: True when the vertex dissolve is successful.\n"
177  " :rtype: boolean\n");
178 static PyObject *bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *args)
179 {
180  BPy_BMVert *py_vert;
181 
182  BMesh *bm;
183 
184  if (!PyArg_ParseTuple(args, "O!:vert_dissolve", &BPy_BMVert_Type, &py_vert)) {
185  return NULL;
186  }
187 
188  BPY_BM_CHECK_OBJ(py_vert);
189 
190  bm = py_vert->bm;
191 
192  return PyBool_FromLong((BM_vert_dissolve(bm, py_vert->v)));
193 }
194 
195 PyDoc_STRVAR(bpy_bm_utils_vert_splice_doc,
196  ".. method:: vert_splice(vert, vert_target)\n"
197  "\n"
198  " Splice vert into vert_target.\n"
199  "\n"
200  " :arg vert: The vertex to be removed.\n"
201  " :type vert: :class:`bmesh.types.BMVert`\n"
202  " :arg vert_target: The vertex to use.\n"
203  " :type vert_target: :class:`bmesh.types.BMVert`\n"
204  "\n"
205  " .. note:: The verts mustn't share an edge or face.\n");
206 static PyObject *bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args)
207 {
208  BPy_BMVert *py_vert;
209  BPy_BMVert *py_vert_target;
210 
211  BMesh *bm;
212 
213  bool ok;
214 
215  if (!PyArg_ParseTuple(args,
216  "O!O!:vert_splice",
218  &py_vert,
220  &py_vert_target)) {
221  return NULL;
222  }
223 
224  BPY_BM_CHECK_OBJ(py_vert);
225  BPY_BM_CHECK_OBJ(py_vert_target);
226 
227  bm = py_vert->bm;
228  BPY_BM_CHECK_SOURCE_OBJ(bm, "vert_splice", py_vert_target);
229 
230  if (py_vert->v == py_vert_target->v) {
231  PyErr_SetString(PyExc_ValueError, "vert_splice(...): vert arguments match");
232  return NULL;
233  }
234 
235  if (BM_edge_exists(py_vert->v, py_vert_target->v)) {
236  PyErr_SetString(PyExc_ValueError, "vert_splice(...): verts can't share an edge");
237  return NULL;
238  }
239 
240  if (BM_vert_pair_share_face_check(py_vert->v, py_vert_target->v)) {
241  PyErr_SetString(PyExc_ValueError, "vert_splice(...): verts can't share a face");
242  return NULL;
243  }
244 
245  /* should always succeed */
246  ok = BM_vert_splice(bm, py_vert_target->v, py_vert->v);
247  BLI_assert(ok == true);
248  UNUSED_VARS_NDEBUG(ok);
249 
250  Py_RETURN_NONE;
251 }
252 
253 PyDoc_STRVAR(bpy_bm_utils_vert_separate_doc,
254  ".. method:: vert_separate(vert, edges)\n"
255  "\n"
256  " Separate this vertex at every edge.\n"
257  "\n"
258  " :arg vert: The vert to be separated.\n"
259  " :type vert: :class:`bmesh.types.BMVert`\n"
260  " :arg edges: The edges to separated.\n"
261  " :type edges: :class:`bmesh.types.BMEdge`\n"
262  " :return: The newly separated verts (including the vertex passed).\n"
263  " :rtype: tuple of :class:`bmesh.types.BMVert`\n");
264 static PyObject *bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *args)
265 {
266  BPy_BMVert *py_vert;
267  PyObject *edge_seq;
268 
269  BMesh *bm;
270  BMVert **elem;
271  int elem_len;
272 
273  /* edges to split */
274  BMEdge **edge_array;
275  Py_ssize_t edge_array_len;
276 
277  PyObject *ret;
278 
279  if (!PyArg_ParseTuple(args, "O!O:vert_separate", &BPy_BMVert_Type, &py_vert, &edge_seq)) {
280  return NULL;
281  }
282 
283  BPY_BM_CHECK_OBJ(py_vert);
284 
285  bm = py_vert->bm;
286 
287  edge_array = BPy_BMElem_PySeq_As_Array(&bm,
288  edge_seq,
289  0,
290  PY_SSIZE_T_MAX,
291  &edge_array_len,
292  BM_EDGE,
293  true,
294  true,
295  "vert_separate(...)");
296 
297  if (edge_array == NULL) {
298  return NULL;
299  }
300 
301  BM_vert_separate(bm, py_vert->v, edge_array, edge_array_len, false, &elem, &elem_len);
302  /* return collected verts */
303  ret = BPy_BMVert_Array_As_Tuple(bm, elem, elem_len);
304  MEM_freeN(elem);
305 
306  PyMem_FREE(edge_array);
307 
308  return ret;
309 }
310 
311 PyDoc_STRVAR(bpy_bm_utils_edge_split_doc,
312  ".. method:: edge_split(edge, vert, fac)\n"
313  "\n"
314  " Split an edge, return the newly created data.\n"
315  "\n"
316  " :arg edge: The edge to split.\n"
317  " :type edge: :class:`bmesh.types.BMEdge`\n"
318  " :arg vert: One of the verts on the edge, defines the split direction.\n"
319  " :type vert: :class:`bmesh.types.BMVert`\n"
320  " :arg fac: The point on the edge where the new vert will be created [0 - 1].\n"
321  " :type fac: float\n"
322  " :return: The newly created (edge, vert) pair.\n"
323  " :rtype: tuple\n");
324 static PyObject *bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args)
325 {
326  BPy_BMEdge *py_edge;
327  BPy_BMVert *py_vert;
328  float fac;
329 
330  BMesh *bm;
331  BMVert *v_new = NULL;
332  BMEdge *e_new = NULL;
333 
334  if (!PyArg_ParseTuple(args,
335  "O!O!f:edge_split",
337  &py_edge,
339  &py_vert,
340  &fac)) {
341  return NULL;
342  }
343 
344  BPY_BM_CHECK_OBJ(py_edge);
345  BPY_BM_CHECK_OBJ(py_vert);
346 
347  /* this doubles for checking that the verts are in the same mesh */
348  if (!(py_edge->e->v1 == py_vert->v || py_edge->e->v2 == py_vert->v)) {
349  PyErr_SetString(PyExc_ValueError,
350  "edge_split(edge, vert): the vertex is not found in the edge");
351  return NULL;
352  }
353 
354  bm = py_edge->bm;
355 
356  v_new = BM_edge_split(bm, py_edge->e, py_vert->v, &e_new, clamp_f(fac, 0.0f, 1.0f));
357 
358  if (v_new && e_new) {
359  PyObject *ret = PyTuple_New(2);
362  return ret;
363  }
364 
365  PyErr_SetString(PyExc_ValueError,
366  "edge_split(edge, vert): couldn't split the edge, internal error");
367  return NULL;
368 }
369 
370 PyDoc_STRVAR(bpy_bm_utils_edge_rotate_doc,
371  ".. method:: edge_rotate(edge, ccw=False)\n"
372  "\n"
373  " Rotate the edge and return the newly created edge.\n"
374  " If rotating the edge fails, None will be returned.\n"
375  "\n"
376  " :arg edge: The edge to rotate.\n"
377  " :type edge: :class:`bmesh.types.BMEdge`\n"
378  " :arg ccw: When True the edge will be rotated counter clockwise.\n"
379  " :type ccw: boolean\n"
380  " :return: The newly rotated edge.\n"
381  " :rtype: :class:`bmesh.types.BMEdge`\n");
382 static PyObject *bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args)
383 {
384  BPy_BMEdge *py_edge;
385  bool do_ccw = false;
386 
387  BMesh *bm;
388  BMEdge *e_new = NULL;
389 
390  if (!PyArg_ParseTuple(
391  args, "O!|O&:edge_rotate", &BPy_BMEdge_Type, &py_edge, PyC_ParseBool, &do_ccw)) {
392  return NULL;
393  }
394 
395  BPY_BM_CHECK_OBJ(py_edge);
396 
397  bm = py_edge->bm;
398 
399  e_new = BM_edge_rotate(bm, py_edge->e, do_ccw, 0);
400 
401  if (e_new) {
402  return BPy_BMEdge_CreatePyObject(bm, e_new);
403  }
404 
405  Py_RETURN_NONE;
406 }
407 
409  bpy_bm_utils_face_split_doc,
410  ".. method:: face_split(face, vert_a, vert_b, coords=(), use_exist=True, example=None)\n"
411  "\n"
412  " Face split with optional intermediate points.\n"
413  "\n"
414  " :arg face: The face to cut.\n"
415  " :type face: :class:`bmesh.types.BMFace`\n"
416  " :arg vert_a: First vertex to cut in the face (face must contain the vert).\n"
417  " :type vert_a: :class:`bmesh.types.BMVert`\n"
418  " :arg vert_b: Second vertex to cut in the face (face must contain the vert).\n"
419  " :type vert_b: :class:`bmesh.types.BMVert`\n"
420  " :arg coords: Optional argument to define points in between *vert_a* and *vert_b*.\n"
421  " :type coords: sequence of float triplets\n"
422  " :arg use_exist: .Use an existing edge if it exists (Only used when *coords* argument is "
423  "empty or omitted)\n"
424  " :type use_exist: boolean\n"
425  " :arg example: Newly created edge will copy settings from this one.\n"
426  " :type example: :class:`bmesh.types.BMEdge`\n"
427  " :return: The newly created face or None on failure.\n"
428  " :rtype: (:class:`bmesh.types.BMFace`, :class:`bmesh.types.BMLoop`) pair\n");
429 static PyObject *bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
430 {
431  static const char *kwlist[] = {
432  "face", "vert_a", "vert_b", "coords", "use_exist", "example", NULL};
433 
434  BPy_BMFace *py_face;
435  BPy_BMVert *py_vert_a;
436  BPy_BMVert *py_vert_b;
437 
438  /* optional */
439  PyObject *py_coords = NULL;
440  bool edge_exists = true;
441  BPy_BMEdge *py_edge_example = NULL;
442 
443  float *coords;
444  int ncoords = 0;
445 
446  BMesh *bm;
447  BMFace *f_new = NULL;
448  BMLoop *l_new = NULL;
449  BMLoop *l_a, *l_b;
450 
451  if (!PyArg_ParseTupleAndKeywords(args,
452  kw,
453  "O!O!O!|OO&O!:face_split",
454  (char **)kwlist,
456  &py_face,
458  &py_vert_a,
460  &py_vert_b,
461  &py_coords,
463  &edge_exists,
465  &py_edge_example)) {
466  return NULL;
467  }
468 
469  BPY_BM_CHECK_OBJ(py_face);
470  BPY_BM_CHECK_OBJ(py_vert_a);
471  BPY_BM_CHECK_OBJ(py_vert_b);
472 
473  if (py_edge_example) {
474  BPY_BM_CHECK_OBJ(py_edge_example);
475  }
476 
477  /* this doubles for checking that the verts are in the same mesh */
478  if ((l_a = BM_face_vert_share_loop(py_face->f, py_vert_a->v)) &&
479  (l_b = BM_face_vert_share_loop(py_face->f, py_vert_b->v))) {
480  /* pass */
481  }
482  else {
483  PyErr_SetString(PyExc_ValueError,
484  "face_split(...): one of the verts passed is not found in the face");
485  return NULL;
486  }
487 
488  if (py_vert_a->v == py_vert_b->v) {
489  PyErr_SetString(PyExc_ValueError, "face_split(...): vert arguments must differ");
490  return NULL;
491  }
492 
493  if (py_coords) {
494  ncoords = mathutils_array_parse_alloc_v(&coords, 3, py_coords, "face_split(...): ");
495  if (ncoords == -1) {
496  return NULL;
497  }
498  }
499  else {
500  if (BM_loop_is_adjacent(l_a, l_b)) {
501  PyErr_SetString(PyExc_ValueError, "face_split(...): verts are adjacent in the face");
502  return NULL;
503  }
504  }
505 
506  /* --- main function body --- */
507  bm = py_face->bm;
508 
509  if (ncoords) {
510  f_new = BM_face_split_n(bm,
511  py_face->f,
512  l_a,
513  l_b,
514  (float(*)[3])coords,
515  ncoords,
516  &l_new,
517  py_edge_example ? py_edge_example->e : NULL);
518  PyMem_Free(coords);
519  }
520  else {
521  f_new = BM_face_split(bm,
522  py_face->f,
523  l_a,
524  l_b,
525  &l_new,
526  py_edge_example ? py_edge_example->e : NULL,
527  edge_exists);
528  }
529 
530  if (f_new && l_new) {
531  PyObject *ret = PyTuple_New(2);
534  return ret;
535  }
536 
537  PyErr_SetString(PyExc_ValueError, "face_split(...): couldn't split the face, internal error");
538  return NULL;
539 }
540 
541 PyDoc_STRVAR(bpy_bm_utils_face_split_edgenet_doc,
542  ".. method:: face_split_edgenet(face, edgenet)\n"
543  "\n"
544  " Splits a face into any number of regions defined by an edgenet.\n"
545  "\n"
546  " :arg face: The face to split.\n"
547  " :type face: :class:`bmesh.types.BMFace`\n"
548  " :arg face: The face to split.\n"
549  " :type face: :class:`bmesh.types.BMFace`\n"
550  " :arg edgenet: Sequence of edges.\n"
551  " :type edgenet: :class:`bmesh.types.BMEdge`\n"
552  " :return: The newly created faces.\n"
553  " :rtype: tuple of (:class:`bmesh.types.BMFace`)\n"
554  "\n"
555  " .. note::\n"
556  "\n"
557  " Regions defined by edges need to connect to the face, otherwise they're "
558  "ignored as loose edges.\n");
559 static PyObject *bpy_bm_utils_face_split_edgenet(PyObject *UNUSED(self),
560  PyObject *args,
561  PyObject *kw)
562 {
563  static const char *kwlist[] = {"face", "edgenet", NULL};
564 
565  BPy_BMFace *py_face;
566  PyObject *edge_seq;
567 
568  BMEdge **edge_array;
569  Py_ssize_t edge_array_len;
570 
571  BMesh *bm;
572 
573  BMFace **face_arr;
574  int face_arr_len;
575  bool ok;
576 
577  if (!PyArg_ParseTupleAndKeywords(args,
578  kw,
579  "O!O:face_split_edgenet",
580  (char **)kwlist,
582  &py_face,
583  &edge_seq)) {
584  return NULL;
585  }
586 
587  BPY_BM_CHECK_OBJ(py_face);
588 
589  bm = py_face->bm;
590 
591  edge_array = BPy_BMElem_PySeq_As_Array(&bm,
592  edge_seq,
593  1,
594  PY_SSIZE_T_MAX,
595  &edge_array_len,
596  BM_EDGE,
597  true,
598  true,
599  "face_split_edgenet(...)");
600 
601  if (edge_array == NULL) {
602  return NULL;
603  }
604 
605  /* --- main function body --- */
606 
607  ok = BM_face_split_edgenet(bm, py_face->f, edge_array, edge_array_len, &face_arr, &face_arr_len);
608 
609  PyMem_FREE(edge_array);
610 
611  if (ok) {
612  PyObject *ret = BPy_BMFace_Array_As_Tuple(bm, face_arr, face_arr_len);
613  if (face_arr) {
614  MEM_freeN(face_arr);
615  }
616  return ret;
617  }
618 
619  PyErr_SetString(PyExc_ValueError,
620  "face_split_edgenet(...): couldn't split the face, internal error");
621  return NULL;
622 }
623 
624 PyDoc_STRVAR(bpy_bm_utils_face_join_doc,
625  ".. method:: face_join(faces, remove=True)\n"
626  "\n"
627  " Joins a sequence of faces.\n"
628  "\n"
629  " :arg faces: Sequence of faces.\n"
630  " :type faces: :class:`bmesh.types.BMFace`\n"
631  " :arg remove: Remove the edges and vertices between the faces.\n"
632  " :type remove: boolean\n"
633  " :return: The newly created face or None on failure.\n"
634  " :rtype: :class:`bmesh.types.BMFace`\n");
635 static PyObject *bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args)
636 {
637  BMesh *bm = NULL;
638  PyObject *py_face_array;
639  BMFace **face_array;
640  Py_ssize_t face_seq_len = 0;
641  BMFace *f_new;
642  bool do_remove = true;
643 
644  if (!PyArg_ParseTuple(args, "O|O&:face_join", &py_face_array, PyC_ParseBool, &do_remove)) {
645  return NULL;
646  }
647 
648  face_array = BPy_BMElem_PySeq_As_Array(
649  &bm, py_face_array, 2, PY_SSIZE_T_MAX, &face_seq_len, BM_FACE, true, true, "face_join(...)");
650 
651  if (face_array == NULL) {
652  return NULL; /* error will be set */
653  }
654 
655  /* Go ahead and join the face!
656  * --------------------------- */
657  f_new = BM_faces_join(bm, face_array, (int)face_seq_len, do_remove);
658 
659  PyMem_FREE(face_array);
660 
661  if (f_new) {
662  return BPy_BMFace_CreatePyObject(bm, f_new);
663  }
664 
665  Py_RETURN_NONE;
666 }
667 
669  bpy_bm_utils_face_vert_separate_doc,
670  ".. method:: face_vert_separate(face, vert)\n"
671  "\n"
672  " Rip a vertex in a face away and add a new vertex.\n"
673  "\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"
680  "\n"
681  " .. note::\n"
682  "\n"
683  " This is the same as loop_separate, and has only been added for convenience.\n");
684 static PyObject *bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObject *args)
685 {
686  BPy_BMFace *py_face;
687  BPy_BMVert *py_vert;
688 
689  BMesh *bm;
690  BMLoop *l;
691  BMVert *v_old, *v_new;
692 
693  if (!PyArg_ParseTuple(args,
694  "O!O!:face_vert_separate",
696  &py_face,
698  &py_vert)) {
699  return NULL;
700  }
701 
702  bm = py_face->bm;
703 
704  BPY_BM_CHECK_OBJ(py_face);
705  BPY_BM_CHECK_SOURCE_OBJ(bm, "face_vert_separate()", py_vert);
706 
707  l = BM_face_vert_share_loop(py_face->f, py_vert->v);
708 
709  if (l == NULL) {
710  PyErr_SetString(PyExc_ValueError, "vertex not found in face");
711  return NULL;
712  }
713 
714  v_old = l->v;
715  v_new = BM_face_loop_separate(bm, l);
716 
717  if (v_new != v_old) {
718  return BPy_BMVert_CreatePyObject(bm, v_new);
719  }
720 
721  Py_RETURN_NONE;
722 }
723 
724 PyDoc_STRVAR(bpy_bm_utils_face_flip_doc,
725  ".. method:: face_flip(faces)\n"
726  "\n"
727  " Flip the faces direction.\n"
728  "\n"
729  " :arg face: Face to flip.\n"
730  " :type face: :class:`bmesh.types.BMFace`\n");
731 static PyObject *bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *value)
732 {
733  if (!BPy_BMFace_Check(value)) {
734  PyErr_Format(PyExc_TypeError,
735  "face_flip(face): BMFace expected, not '%.200s'",
736  Py_TYPE(value)->tp_name);
737  return NULL;
738  }
739 
740  BPY_BM_CHECK_OBJ(value);
741 
742  BM_face_normal_flip(value->bm, value->f);
743 
744  Py_RETURN_NONE;
745 }
746 
747 PyDoc_STRVAR(bpy_bm_utils_loop_separate_doc,
748  ".. method:: loop_separate(loop)\n"
749  "\n"
750  " Rip a vertex in a face away and add a new vertex.\n"
751  "\n"
752  " :arg loop: The loop to separate.\n"
753  " :type loop: :class:`bmesh.types.BMLoop`\n"
754  " :return vert: The newly created vertex or None on failure.\n"
755  " :rtype vert: :class:`bmesh.types.BMVert`\n");
756 static PyObject *bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value)
757 {
758  BMesh *bm;
759  BMLoop *l;
760  BMVert *v_old, *v_new;
761 
762  if (!BPy_BMLoop_Check(value)) {
763  PyErr_Format(PyExc_TypeError,
764  "loop_separate(loop): BMLoop expected, not '%.200s'",
765  Py_TYPE(value)->tp_name);
766  return NULL;
767  }
768 
769  BPY_BM_CHECK_OBJ(value);
770 
771  bm = value->bm;
772  l = value->l;
773 
774  v_old = l->v;
775  v_new = BM_face_loop_separate(bm, l);
776 
777  if (v_new != v_old) {
778  return BPy_BMVert_CreatePyObject(bm, v_new);
779  }
780 
781  Py_RETURN_NONE;
782 }
783 
784 static struct PyMethodDef BPy_BM_utils_methods[] = {
785  {"vert_collapse_edge",
786  (PyCFunction)bpy_bm_utils_vert_collapse_edge,
787  METH_VARARGS,
788  bpy_bm_utils_vert_collapse_edge_doc},
789  {"vert_collapse_faces",
791  METH_VARARGS,
792  bpy_bm_utils_vert_collapse_faces_doc},
793  {"vert_dissolve",
794  (PyCFunction)bpy_bm_utils_vert_dissolve,
795  METH_VARARGS,
796  bpy_bm_utils_vert_dissolve_doc}, /* could use METH_O */
797  {"vert_splice",
798  (PyCFunction)bpy_bm_utils_vert_splice,
799  METH_VARARGS,
800  bpy_bm_utils_vert_splice_doc},
801  {"vert_separate",
802  (PyCFunction)bpy_bm_utils_vert_separate,
803  METH_VARARGS,
804  bpy_bm_utils_vert_separate_doc},
805  {"edge_split",
806  (PyCFunction)bpy_bm_utils_edge_split,
807  METH_VARARGS,
808  bpy_bm_utils_edge_split_doc},
809  {"edge_rotate",
810  (PyCFunction)bpy_bm_utils_edge_rotate,
811  METH_VARARGS,
812  bpy_bm_utils_edge_rotate_doc},
813  {"face_split",
814  (PyCFunction)bpy_bm_utils_face_split,
815  METH_VARARGS | METH_KEYWORDS,
816  bpy_bm_utils_face_split_doc},
817  {"face_split_edgenet",
818  (PyCFunction)bpy_bm_utils_face_split_edgenet,
819  METH_VARARGS | METH_KEYWORDS,
820  bpy_bm_utils_face_split_edgenet_doc},
821  {"face_join", (PyCFunction)bpy_bm_utils_face_join, METH_VARARGS, bpy_bm_utils_face_join_doc},
822  {"face_vert_separate",
823  (PyCFunction)bpy_bm_utils_face_vert_separate,
824  METH_VARARGS,
825  bpy_bm_utils_face_vert_separate_doc},
826  {"face_flip", (PyCFunction)bpy_bm_utils_face_flip, METH_O, bpy_bm_utils_face_flip_doc},
827  {"loop_separate",
828  (PyCFunction)bpy_bm_utils_loop_separate,
829  METH_O,
830  bpy_bm_utils_loop_separate_doc},
831  {NULL, NULL, 0, NULL},
832 };
833 
834 PyDoc_STRVAR(BPy_BM_utils_doc, "This module provides access to blenders bmesh data structures.");
835 static struct PyModuleDef BPy_BM_utils_module_def = {
836  PyModuleDef_HEAD_INIT,
837  "bmesh.utils", /* m_name */
838  BPy_BM_utils_doc, /* m_doc */
839  0, /* m_size */
840  BPy_BM_utils_methods, /* m_methods */
841  NULL, /* m_reload */
842  NULL, /* m_traverse */
843  NULL, /* m_clear */
844  NULL, /* m_free */
845 };
846 
847 PyObject *BPyInit_bmesh_utils(void)
848 {
849  PyObject *submodule;
850 
851  submodule = PyModule_Create(&BPy_BM_utils_module_def);
852 
853  return submodule;
854 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE float clamp_f(float value, float min, float max)
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
Read Guarded memory(de)allocation.
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_EDGE
Definition: bmesh_class.h:384
BMFace * BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del)
Join Connected Faces.
Definition: bmesh_core.c:1209
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)
Definition: bmesh_core.c:2486
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
Splice Vert.
Definition: bmesh_core.c:2284
ATTR_WARN_UNUSED_RESULT BMesh * bm
BMVert * BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
Edge Split.
Definition: bmesh_mods.c:591
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.
Definition: bmesh_mods.c:430
bool BM_vert_dissolve(BMesh *bm, BMVert *v)
Dissolve Vert.
Definition: bmesh_mods.c:59
BMVert * BM_face_loop_separate(BMesh *bm, BMLoop *l_sep)
Rip a single face from a vertex fan.
Definition: bmesh_mods.c:1097
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.
Definition: bmesh_mods.c:523
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.
Definition: bmesh_mods.c:252
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.
Definition: bmesh_mods.c:334
BMEdge * BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_flag)
Rotate Edge.
Definition: bmesh_mods.c:983
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, BMFace ***r_face_arr, int *r_face_arr_len)
PyObject * BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
PyObject * BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
PyObject * BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len)
PyObject * BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len)
PyObject * BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
PyTypeObject BPy_BMEdge_Type
PyTypeObject BPy_BMVert_Type
PyTypeObject BPy_BMFace_Type
PyObject * BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
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)
#define BPy_BMFace_Check(v)
#define BPY_BM_CHECK_OBJ(obj)
#define BPy_BMLoop_Check(v)
#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg,...)
static PyObject * bpy_bm_utils_vert_splice(PyObject *UNUSED(self), PyObject *args)
static struct PyModuleDef BPy_BM_utils_module_def
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 struct PyMethodDef BPy_BM_utils_methods[]
static PyObject * bpy_bm_utils_face_split(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
static PyObject * bpy_bm_utils_edge_split(PyObject *UNUSED(self), PyObject *args)
PyObject * BPyInit_bmesh_utils(void)
static PyObject * bpy_bm_utils_face_vert_separate(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_loop_separate(PyObject *UNUSED(self), BPy_BMLoop *value)
static PyObject * bpy_bm_utils_vert_collapse_edge(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_vert_collapse_faces(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_face_split_edgenet(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
static PyObject * bpy_bm_utils_vert_dissolve(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_vert_separate(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_face_flip(PyObject *UNUSED(self), BPy_BMFace *value)
static PyObject * bpy_bm_utils_edge_rotate(PyObject *UNUSED(self), PyObject *args)
static PyObject * bpy_bm_utils_face_join(PyObject *UNUSED(self), PyObject *args)
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1995
bool BM_vert_pair_share_face_check(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:193
BMLoop * BM_face_vert_share_loop(BMFace *f, BMVert *v)
Return the Loop Shared by Face and Vertex.
Definition: bmesh_query.c:1403
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)
Definition: bmesh_query.h:92
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMLoop * l_b
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix)
Definition: mathutils.c:283
int PyC_ParseBool(PyObject *o, void *p)
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
BMVert * v1
Definition: bmesh_class.h:134
BMVert * v2
Definition: bmesh_class.h:134
struct BMVert * v
Definition: bmesh_class.h:165
PyObject_VAR_HEAD struct BMesh * bm
struct BMEdge * e
struct BMFace * f
PyObject_VAR_HEAD struct BMesh * bm
struct BMLoop * l
PyObject_VAR_HEAD struct BMesh * bm
PyObject_VAR_HEAD struct BMesh * bm
struct BMVert * v