Blender  V3.3
bmesh_py_types.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2012 Blender Foundation. All rights reserved. */
3 
8 #include "BLI_math.h"
9 #include "BLI_sort.h"
10 
11 #include "DNA_material_types.h"
12 #include "DNA_mesh_types.h"
13 #include "DNA_object_types.h"
14 
15 #include "BKE_customdata.h"
16 #include "BKE_global.h"
17 #include "BKE_lib_id.h"
18 #include "BKE_mesh.h"
19 #include "BKE_mesh_runtime.h"
20 
21 #include "DEG_depsgraph.h"
22 #include "DEG_depsgraph_query.h"
23 
24 #include "bmesh.h"
25 
26 #include <Python.h>
27 
28 #include "../mathutils/mathutils.h"
29 
30 #include "../generic/py_capi_utils.h"
31 #include "../generic/python_utildefines.h"
32 
33 #include "bmesh_py_types.h" /* own include */
36 #include "bmesh_py_types_select.h"
37 
38 static void bm_dealloc_editmode_warn(BPy_BMesh *self);
39 
40 /* Common Flags
41  * ************ */
42 
43 /* scene does not use BM_* flags. */
45  {1, "VERT"},
46  {2, "EDGE"},
47  {4, "FACE"},
48  {0, NULL},
49 };
50 
52  {BM_VERT, "VERT"},
53  {BM_EDGE, "EDGE"},
54  {BM_FACE, "FACE"},
55  {0, NULL},
56 };
57 
59  {BM_VERT, "VERT"},
60  {BM_LOOP, "EDGE"},
61  {BM_FACE, "FACE"},
62  {BM_LOOP, "LOOP"},
63  {0, NULL},
64 };
65 
66 #define BPY_BM_HFLAG_ALL_STR "('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG')"
67 
69  {BM_ELEM_SELECT, "SELECT"},
70  {BM_ELEM_HIDDEN, "HIDE"},
71  {BM_ELEM_SEAM, "SEAM"},
72  {BM_ELEM_SMOOTH, "SMOOTH"},
73  {BM_ELEM_TAG, "TAG"},
74  {0, NULL},
75 };
76 
77 /* py-type definitions
78  * ******************* */
79 
80 /* getseters
81  * ========= */
82 
83 /* bmesh elems
84  * ----------- */
85 
86 PyDoc_STRVAR(bpy_bm_elem_select_doc, "Selected state of this element.\n\n:type: boolean");
87 PyDoc_STRVAR(bpy_bm_elem_hide_doc, "Hidden state of this element.\n\n:type: boolean");
88 PyDoc_STRVAR(bpy_bm_elem_tag_doc,
89  "Generic attribute scripts can use for own logic\n\n:type: boolean");
90 PyDoc_STRVAR(bpy_bm_elem_smooth_doc, "Smooth state of this element.\n\n:type: boolean");
91 PyDoc_STRVAR(bpy_bm_elem_seam_doc, "Seam for UV unwrapping.\n\n:type: boolean");
92 
93 static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
94 {
95  const char hflag = (char)POINTER_AS_INT(flag);
96 
97  BPY_BM_CHECK_OBJ(self);
98 
99  return PyBool_FromLong(BM_elem_flag_test(self->ele, hflag));
100 }
101 
102 static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
103 {
104  const char hflag = (char)POINTER_AS_INT(flag);
105  int param;
106 
107  BPY_BM_CHECK_INT(self);
108 
109  if ((param = PyC_Long_AsBool(value)) == -1) {
110  return -1;
111  }
112 
113  if (hflag == BM_ELEM_SELECT) {
114  BM_elem_select_set(self->bm, self->ele, param);
115  }
116  else {
117  BM_elem_flag_set(self->ele, hflag, param);
118  }
119  return 0;
120 }
121 
123  bpy_bm_elem_index_doc,
124  "Index of this element.\n"
125  "\n"
126  ":type: int\n"
127  "\n"
128  ".. note::\n"
129  "\n"
130  " This value is not necessarily valid, while editing the mesh it can become *dirty*.\n"
131  "\n"
132  " It's also possible to assign any number to this attribute for a scripts internal logic.\n"
133  "\n"
134  " To ensure the value is up to date - see :class:`BMElemSeq.index_update`.\n");
135 static PyObject *bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
136 {
137  BPY_BM_CHECK_OBJ(self);
138 
139  return PyLong_FromLong(BM_elem_index_get(self->ele));
140 }
141 
142 static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
143 {
144  int param;
145 
146  BPY_BM_CHECK_INT(self);
147 
148  if (((param = PyC_Long_AsI32(value)) == -1) && PyErr_Occurred()) {
149  /* error is set */
150  return -1;
151  }
152 
153  BM_elem_index_set(self->ele, param); /* set_dirty! */
154 
155  /* when setting the index assume its set invalid */
156  self->bm->elem_index_dirty |= self->ele->head.htype;
157 
158  return 0;
159 }
160 
161 /* type specific get/sets
162  * ---------------------- */
163 
164 /* Mesh
165  * ^^^^ */
166 
167 /* doc-strings for all uses of this function */
168 
169 PyDoc_STRVAR(bpy_bmvertseq_doc,
170  "This meshes vert sequence (read-only).\n\n:type: :class:`BMVertSeq`");
171 static PyObject *bpy_bmvertseq_get(BPy_BMesh *self, void *UNUSED(closure))
172 {
173  BPY_BM_CHECK_OBJ(self);
175 }
176 
177 PyDoc_STRVAR(bpy_bmedgeseq_doc,
178  "This meshes edge sequence (read-only).\n\n:type: :class:`BMEdgeSeq`");
179 static PyObject *bpy_bmedgeseq_get(BPy_BMesh *self, void *UNUSED(closure))
180 {
181  BPY_BM_CHECK_OBJ(self);
183 }
184 
185 PyDoc_STRVAR(bpy_bmfaceseq_doc,
186  "This meshes face sequence (read-only).\n\n:type: :class:`BMFaceSeq`");
187 static PyObject *bpy_bmfaceseq_get(BPy_BMesh *self, void *UNUSED(closure))
188 {
189  BPY_BM_CHECK_OBJ(self);
191 }
192 
193 PyDoc_STRVAR(bpy_bmloopseq_doc,
194  "This meshes loops (read-only).\n\n:type: :class:`BMLoopSeq`\n"
195  "\n"
196  ".. note::\n"
197  "\n"
198  " Loops must be accessed via faces, this is only exposed for layer access.\n");
199 static PyObject *bpy_bmloopseq_get(BPy_BMesh *self, void *UNUSED(closure))
200 {
201  BPY_BM_CHECK_OBJ(self);
203 }
204 
205 /* vert */
207  bpy_bmvert_link_edges_doc,
208  "Edges connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMEdge`");
210  bpy_bmvert_link_faces_doc,
211  "Faces connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`");
213  bpy_bmvert_link_loops_doc,
214  "Loops that use this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`");
215 /* edge */
216 PyDoc_STRVAR(bpy_bmedge_verts_doc,
217  "Verts this edge uses (always 2), (read-only).\n\n:type: :class:`BMElemSeq` of "
218  ":class:`BMVert`");
220  bpy_bmedge_link_faces_doc,
221  "Faces connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`");
223  bpy_bmedge_link_loops_doc,
224  "Loops connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`");
225 /* face */
226 PyDoc_STRVAR(bpy_bmface_verts_doc,
227  "Verts of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`");
228 PyDoc_STRVAR(bpy_bmface_edges_doc,
229  "Edges of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMEdge`");
230 PyDoc_STRVAR(bpy_bmface_loops_doc,
231  "Loops of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`");
232 /* loop */
234  bpy_bmloops_link_loops_doc,
235  "Loops connected to this loop, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`");
236 
237 static PyObject *bpy_bmelemseq_elem_get(BPy_BMElem *self, void *itype)
238 {
239  BPY_BM_CHECK_OBJ(self);
241 }
242 
243 PyDoc_STRVAR(bpy_bm_is_valid_doc,
244  "True when this element is valid (hasn't been removed).\n\n:type: boolean");
245 static PyObject *bpy_bm_is_valid_get(BPy_BMGeneric *self)
246 {
247  return PyBool_FromLong(BPY_BM_IS_VALID(self));
248 }
249 
251  bpy_bmesh_is_wrapped_doc,
252  "True when this mesh is owned by blender (typically the editmode BMesh).\n\n:type: boolean");
253 static PyObject *bpy_bmesh_is_wrapped_get(BPy_BMesh *self)
254 {
255  BPY_BM_CHECK_OBJ(self);
256 
257  return PyBool_FromLong(self->flag & BPY_BMFLAG_IS_WRAPPED);
258 }
259 
260 PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
261  "The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an "
262  "empty set.\n\n:type: set");
263 static PyObject *bpy_bmesh_select_mode_get(BPy_BMesh *self)
264 {
265  BPY_BM_CHECK_OBJ(self);
266 
268 }
269 
270 static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
271 {
272  int flag = 0;
273  BPY_BM_CHECK_INT(self);
274 
275  if (PyC_FlagSet_ToBitfield(bpy_bm_scene_vert_edge_face_flags, value, &flag, "bm.select_mode") ==
276  -1) {
277  return -1;
278  }
279  if (flag == 0) {
280  PyErr_SetString(PyExc_TypeError, "bm.select_mode: can't assign an empty value");
281  return -1;
282  }
283 
284  self->bm->selectmode = flag;
285  return 0;
286 }
287 
288 PyDoc_STRVAR(bpy_bmesh_select_history_doc,
289  "Sequence of selected items (the last is displayed as active).\n\n:type: "
290  ":class:`BMEditSelSeq`");
292 {
293  BPY_BM_CHECK_OBJ(self);
294 
296 }
297 
298 static int bpy_bmesh_select_history_set(BPy_BMesh *self, PyObject *value)
299 {
300  BPY_BM_CHECK_INT(self);
301 
302  return BPy_BMEditSel_Assign(self, value);
303 }
304 
305 /* Vert
306  * ^^^^ */
307 
308 PyDoc_STRVAR(bpy_bmvert_co_doc,
309  "The coordinates for this vertex as a 3D, wrapped vector.\n\n:type: "
310  ":class:`mathutils.Vector`");
311 static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
312 {
313  BPY_BM_CHECK_OBJ(self);
314  return Vector_CreatePyObject_wrap(self->v->co, 3, NULL);
315 }
316 
317 static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
318 {
319  BPY_BM_CHECK_INT(self);
320 
321  if (mathutils_array_parse(self->v->co, 3, 3, value, "BMVert.co") != -1) {
322  return 0;
323  }
324 
325  return -1;
326 }
327 
329  bpy_bmvert_normal_doc,
330  "The normal for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`");
331 static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
332 {
333  BPY_BM_CHECK_OBJ(self);
334  return Vector_CreatePyObject_wrap(self->v->no, 3, NULL);
335 }
336 
337 static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
338 {
339  BPY_BM_CHECK_INT(self);
340 
341  if (mathutils_array_parse(self->v->no, 3, 3, value, "BMVert.normal") != -1) {
342  return 0;
343  }
344 
345  return -1;
346 }
347 
348 PyDoc_STRVAR(bpy_bmvert_is_manifold_doc,
349  "True when this vertex is manifold (read-only).\n\n:type: boolean");
350 static PyObject *bpy_bmvert_is_manifold_get(BPy_BMVert *self)
351 {
352  BPY_BM_CHECK_OBJ(self);
353  return PyBool_FromLong(BM_vert_is_manifold(self->v));
354 }
355 
356 PyDoc_STRVAR(bpy_bmvert_is_wire_doc,
357  "True when this vertex is not connected to any faces (read-only).\n\n:type: boolean");
358 static PyObject *bpy_bmvert_is_wire_get(BPy_BMVert *self)
359 {
360  BPY_BM_CHECK_OBJ(self);
361  return PyBool_FromLong(BM_vert_is_wire(self->v));
362 }
363 
365  bpy_bmvert_is_boundary_doc,
366  "True when this vertex is connected to boundary edges (read-only).\n\n:type: boolean");
367 static PyObject *bpy_bmvert_is_boundary_get(BPy_BMVert *self)
368 {
369  BPY_BM_CHECK_OBJ(self);
370  return PyBool_FromLong(BM_vert_is_boundary(self->v));
371 }
372 
373 /* Edge
374  * ^^^^ */
375 
376 PyDoc_STRVAR(bpy_bmedge_is_manifold_doc,
377  "True when this edge is manifold (read-only).\n\n:type: boolean");
378 static PyObject *bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
379 {
380  BPY_BM_CHECK_OBJ(self);
381  return PyBool_FromLong(BM_edge_is_manifold(self->e));
382 }
383 
384 PyDoc_STRVAR(bpy_bmedge_is_contiguous_doc,
385  "True when this edge is manifold, between two faces with the same winding "
386  "(read-only).\n\n:type: boolean");
388 {
389  BPY_BM_CHECK_OBJ(self);
390  return PyBool_FromLong(BM_edge_is_contiguous(self->e));
391 }
392 
393 PyDoc_STRVAR(bpy_bmedge_is_convex_doc,
394  "True when this edge joins two convex faces, depends on a valid face normal "
395  "(read-only).\n\n:type: boolean");
396 static PyObject *bpy_bmedge_is_convex_get(BPy_BMEdge *self)
397 {
398  BPY_BM_CHECK_OBJ(self);
399  return PyBool_FromLong(BM_edge_is_convex(self->e));
400 }
401 
402 PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
403  "True when this edge is not connected to any faces (read-only).\n\n:type: boolean");
404 static PyObject *bpy_bmedge_is_wire_get(BPy_BMEdge *self)
405 {
406  BPY_BM_CHECK_OBJ(self);
407  return PyBool_FromLong(BM_edge_is_wire(self->e));
408 }
409 
410 PyDoc_STRVAR(bpy_bmedge_is_boundary_doc,
411  "True when this edge is at the boundary of a face (read-only).\n\n:type: boolean");
412 static PyObject *bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
413 {
414  BPY_BM_CHECK_OBJ(self);
415  return PyBool_FromLong(BM_edge_is_boundary(self->e));
416 }
417 
418 /* Face
419  * ^^^^ */
420 
422  bpy_bmface_normal_doc,
423  "The normal for this face as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`");
424 static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
425 {
426  BPY_BM_CHECK_OBJ(self);
427  return Vector_CreatePyObject_wrap(self->f->no, 3, NULL);
428 }
429 
430 static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
431 {
432  BPY_BM_CHECK_INT(self);
433 
434  if (mathutils_array_parse(self->f->no, 3, 3, value, "BMFace.normal") != -1) {
435  return 0;
436  }
437 
438  return -1;
439 }
440 
441 PyDoc_STRVAR(bpy_bmface_material_index_doc, "The face's material index.\n\n:type: int");
443 {
444  BPY_BM_CHECK_OBJ(self);
445  return PyLong_FromLong(self->f->mat_nr);
446 }
447 
448 static int bpy_bmface_material_index_set(BPy_BMFace *self, PyObject *value)
449 {
450  int param;
451 
452  BPY_BM_CHECK_INT(self);
453 
454  if (((param = PyC_Long_AsI32(value)) == -1) && PyErr_Occurred()) {
455  /* error is set */
456  return -1;
457  }
458 
459  if ((param < 0) || (param > MAXMAT)) {
460  /* normally we clamp but in this case raise an error */
461  PyErr_SetString(PyExc_ValueError, "material index outside of usable range (0 - 32766)");
462  return -1;
463  }
464 
465  self->f->mat_nr = (short)param;
466  return 0;
467 }
468 
469 /* Loop
470  * ^^^^ */
471 
472 PyDoc_STRVAR(bpy_bmloop_vert_doc, "The loop's vertex (read-only).\n\n:type: :class:`BMVert`");
473 static PyObject *bpy_bmloop_vert_get(BPy_BMLoop *self)
474 {
475  BPY_BM_CHECK_OBJ(self);
476  return BPy_BMVert_CreatePyObject(self->bm, self->l->v);
477 }
478 
480  bpy_bmloop_edge_doc,
481  "The loop's edge (between this loop and the next), (read-only).\n\n:type: :class:`BMEdge`");
482 static PyObject *bpy_bmloop_edge_get(BPy_BMLoop *self)
483 {
484  BPY_BM_CHECK_OBJ(self);
485  return BPy_BMEdge_CreatePyObject(self->bm, self->l->e);
486 }
487 
488 PyDoc_STRVAR(bpy_bmloop_face_doc,
489  "The face this loop makes (read-only).\n\n:type: :class:`BMFace`");
490 static PyObject *bpy_bmloop_face_get(BPy_BMLoop *self)
491 {
492  BPY_BM_CHECK_OBJ(self);
493  return BPy_BMFace_CreatePyObject(self->bm, self->l->f);
494 }
495 
496 PyDoc_STRVAR(bpy_bmloop_link_loop_next_doc,
497  "The next face corner (read-only).\n\n:type: :class:`BMLoop`");
499 {
500  BPY_BM_CHECK_OBJ(self);
501  return BPy_BMLoop_CreatePyObject(self->bm, self->l->next);
502 }
503 
504 PyDoc_STRVAR(bpy_bmloop_link_loop_prev_doc,
505  "The previous face corner (read-only).\n\n:type: :class:`BMLoop`");
507 {
508  BPY_BM_CHECK_OBJ(self);
509  return BPy_BMLoop_CreatePyObject(self->bm, self->l->prev);
510 }
511 
512 PyDoc_STRVAR(bpy_bmloop_link_loop_radial_next_doc,
513  "The next loop around the edge (read-only).\n\n:type: :class:`BMLoop`");
515 {
516  BPY_BM_CHECK_OBJ(self);
517  return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_next);
518 }
519 
520 PyDoc_STRVAR(bpy_bmloop_link_loop_radial_prev_doc,
521  "The previous loop around the edge (read-only).\n\n:type: :class:`BMLoop`");
523 {
524  BPY_BM_CHECK_OBJ(self);
525  return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_prev);
526 }
527 
528 PyDoc_STRVAR(bpy_bmloop_is_convex_doc,
529  "True when this loop is at the convex corner of a face, depends on a valid face "
530  "normal (read-only).\n\n:type: boolean");
531 static PyObject *bpy_bmloop_is_convex_get(BPy_BMLoop *self)
532 {
533  BPY_BM_CHECK_OBJ(self);
534  return PyBool_FromLong(BM_loop_is_convex(self->l));
535 }
536 
537 /* ElemSeq
538  * ^^^^^^^ */
539 
540 /* NOTE: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly. */
541 PyDoc_STRVAR(bpy_bmelemseq_layers_vert_doc,
542  "custom-data layers (read-only).\n\n:type: :class:`BMLayerAccessVert`");
543 PyDoc_STRVAR(bpy_bmelemseq_layers_edge_doc,
544  "custom-data layers (read-only).\n\n:type: :class:`BMLayerAccessEdge`");
545 PyDoc_STRVAR(bpy_bmelemseq_layers_face_doc,
546  "custom-data layers (read-only).\n\n:type: :class:`BMLayerAccessFace`");
547 PyDoc_STRVAR(bpy_bmelemseq_layers_loop_doc,
548  "custom-data layers (read-only).\n\n:type: :class:`BMLayerAccessLoop`");
549 static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype)
550 {
551  BPY_BM_CHECK_OBJ(self);
552 
554 }
555 
556 /* FaceSeq
557  * ^^^^^^^ */
558 
559 PyDoc_STRVAR(bpy_bmfaceseq_active_doc, "active face.\n\n:type: :class:`BMFace` or None");
560 static PyObject *bpy_bmfaceseq_active_get(BPy_BMElemSeq *self, void *UNUSED(closure))
561 {
562  BMesh *bm = self->bm;
563  BPY_BM_CHECK_OBJ(self);
564 
565  if (bm->act_face) {
567  }
568 
569  Py_RETURN_NONE;
570 }
571 
572 static int bpy_bmfaceseq_active_set(BPy_BMElem *self, PyObject *value, void *UNUSED(closure))
573 {
574  BMesh *bm = self->bm;
575  if (value == Py_None) {
576  bm->act_face = NULL;
577  return 0;
578  }
579  if (BPy_BMFace_Check(value)) {
580  BPY_BM_CHECK_SOURCE_INT(bm, "faces.active = f", value);
581 
582  bm->act_face = ((BPy_BMFace *)value)->f;
583  return 0;
584  }
585 
586  PyErr_Format(PyExc_TypeError,
587  "faces.active = f: expected BMFace or None, not %.200s",
588  Py_TYPE(value)->tp_name);
589  return -1;
590 }
591 
592 static PyGetSetDef bpy_bmesh_getseters[] = {
593  {"verts", (getter)bpy_bmvertseq_get, (setter)NULL, bpy_bmvertseq_doc, NULL},
594  {"edges", (getter)bpy_bmedgeseq_get, (setter)NULL, bpy_bmedgeseq_doc, NULL},
595  {"faces", (getter)bpy_bmfaceseq_get, (setter)NULL, bpy_bmfaceseq_doc, NULL},
596  {"loops", (getter)bpy_bmloopseq_get, (setter)NULL, bpy_bmloopseq_doc, NULL},
597  {"select_mode",
600  bpy_bmesh_select_mode_doc,
601  NULL},
602 
603  {"select_history",
606  bpy_bmesh_select_history_doc,
607  NULL},
608 
609  /* readonly checks */
610  {"is_wrapped",
611  (getter)bpy_bmesh_is_wrapped_get,
612  (setter)NULL,
613  bpy_bmesh_is_wrapped_doc,
614  NULL}, /* as with mathutils */
615  {"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, bpy_bm_is_valid_doc, NULL},
616 
617  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
618 };
619 
620 static PyGetSetDef bpy_bmvert_getseters[] = {
621  /* generic */
622  {"select",
623  (getter)bpy_bm_elem_hflag_get,
624  (setter)bpy_bm_elem_hflag_set,
625  bpy_bm_elem_select_doc,
626  (void *)BM_ELEM_SELECT},
627  {"hide",
628  (getter)bpy_bm_elem_hflag_get,
629  (setter)bpy_bm_elem_hflag_set,
630  bpy_bm_elem_hide_doc,
631  (void *)BM_ELEM_HIDDEN},
632  {"tag",
633  (getter)bpy_bm_elem_hflag_get,
634  (setter)bpy_bm_elem_hflag_set,
635  bpy_bm_elem_tag_doc,
636  (void *)BM_ELEM_TAG},
637  {"index",
638  (getter)bpy_bm_elem_index_get,
639  (setter)bpy_bm_elem_index_set,
640  bpy_bm_elem_index_doc,
641  NULL},
642 
643  {"co", (getter)bpy_bmvert_co_get, (setter)bpy_bmvert_co_set, bpy_bmvert_co_doc, NULL},
644  {"normal",
645  (getter)bpy_bmvert_normal_get,
646  (setter)bpy_bmvert_normal_set,
647  bpy_bmvert_normal_doc,
648  NULL},
649 
650  /* connectivity data */
651  {"link_edges",
652  (getter)bpy_bmelemseq_elem_get,
653  (setter)NULL,
654  bpy_bmvert_link_edges_doc,
655  (void *)BM_EDGES_OF_VERT},
656  {"link_faces",
657  (getter)bpy_bmelemseq_elem_get,
658  (setter)NULL,
659  bpy_bmvert_link_faces_doc,
660  (void *)BM_FACES_OF_VERT},
661  {"link_loops",
662  (getter)bpy_bmelemseq_elem_get,
663  (setter)NULL,
664  bpy_bmvert_link_loops_doc,
665  (void *)BM_LOOPS_OF_VERT},
666 
667  /* readonly checks */
668  {"is_manifold",
670  (setter)NULL,
671  bpy_bmvert_is_manifold_doc,
672  NULL},
673  {"is_wire", (getter)bpy_bmvert_is_wire_get, (setter)NULL, bpy_bmvert_is_wire_doc, NULL},
674  {"is_boundary",
676  (setter)NULL,
677  bpy_bmvert_is_boundary_doc,
678  NULL},
679  {"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, bpy_bm_is_valid_doc, NULL},
680 
681  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
682 };
683 
684 static PyGetSetDef bpy_bmedge_getseters[] = {
685  /* generic */
686  {"select",
687  (getter)bpy_bm_elem_hflag_get,
688  (setter)bpy_bm_elem_hflag_set,
689  bpy_bm_elem_select_doc,
690  (void *)BM_ELEM_SELECT},
691  {"hide",
692  (getter)bpy_bm_elem_hflag_get,
693  (setter)bpy_bm_elem_hflag_set,
694  bpy_bm_elem_hide_doc,
695  (void *)BM_ELEM_HIDDEN},
696  {"tag",
697  (getter)bpy_bm_elem_hflag_get,
698  (setter)bpy_bm_elem_hflag_set,
699  bpy_bm_elem_tag_doc,
700  (void *)BM_ELEM_TAG},
701  {"index",
702  (getter)bpy_bm_elem_index_get,
703  (setter)bpy_bm_elem_index_set,
704  bpy_bm_elem_index_doc,
705  NULL},
706 
707  {"smooth",
708  (getter)bpy_bm_elem_hflag_get,
709  (setter)bpy_bm_elem_hflag_set,
710  bpy_bm_elem_smooth_doc,
711  (void *)BM_ELEM_SMOOTH},
712  {"seam",
713  (getter)bpy_bm_elem_hflag_get,
714  (setter)bpy_bm_elem_hflag_set,
715  bpy_bm_elem_seam_doc,
716  (void *)BM_ELEM_SEAM},
717 
718  /* connectivity data */
719  {"verts",
720  (getter)bpy_bmelemseq_elem_get,
721  (setter)NULL,
722  bpy_bmedge_verts_doc,
723  (void *)BM_VERTS_OF_EDGE},
724 
725  {"link_faces",
726  (getter)bpy_bmelemseq_elem_get,
727  (setter)NULL,
728  bpy_bmedge_link_faces_doc,
729  (void *)BM_FACES_OF_EDGE},
730  {"link_loops",
731  (getter)bpy_bmelemseq_elem_get,
732  (setter)NULL,
733  bpy_bmedge_link_loops_doc,
734  (void *)BM_LOOPS_OF_EDGE},
735 
736  /* readonly checks */
737  {"is_manifold",
739  (setter)NULL,
740  bpy_bmedge_is_manifold_doc,
741  NULL},
742  {"is_contiguous",
744  (setter)NULL,
745  bpy_bmedge_is_contiguous_doc,
746  NULL},
747  {"is_convex", (getter)bpy_bmedge_is_convex_get, (setter)NULL, bpy_bmedge_is_convex_doc, NULL},
748  {"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, bpy_bmedge_is_wire_doc, NULL},
749  {"is_boundary",
751  (setter)NULL,
752  bpy_bmedge_is_boundary_doc,
753  NULL},
754  {"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, bpy_bm_is_valid_doc, NULL},
755 
756  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
757 };
758 
759 static PyGetSetDef bpy_bmface_getseters[] = {
760  /* generic */
761  {"select",
762  (getter)bpy_bm_elem_hflag_get,
763  (setter)bpy_bm_elem_hflag_set,
764  bpy_bm_elem_select_doc,
765  (void *)BM_ELEM_SELECT},
766  {"hide",
767  (getter)bpy_bm_elem_hflag_get,
768  (setter)bpy_bm_elem_hflag_set,
769  bpy_bm_elem_hide_doc,
770  (void *)BM_ELEM_HIDDEN},
771  {"tag",
772  (getter)bpy_bm_elem_hflag_get,
773  (setter)bpy_bm_elem_hflag_set,
774  bpy_bm_elem_tag_doc,
775  (void *)BM_ELEM_TAG},
776  {"index",
777  (getter)bpy_bm_elem_index_get,
778  (setter)bpy_bm_elem_index_set,
779  bpy_bm_elem_index_doc,
780  NULL},
781 
782  {"smooth",
783  (getter)bpy_bm_elem_hflag_get,
784  (setter)bpy_bm_elem_hflag_set,
785  bpy_bm_elem_smooth_doc,
786  (void *)BM_ELEM_SMOOTH},
787 
788  {"normal",
789  (getter)bpy_bmface_normal_get,
790  (setter)bpy_bmface_normal_set,
791  bpy_bmface_normal_doc,
792  NULL},
793 
794  {"material_index",
797  bpy_bmface_material_index_doc,
798  NULL},
799 
800  /* connectivity data */
801  {"verts",
802  (getter)bpy_bmelemseq_elem_get,
803  (setter)NULL,
804  bpy_bmface_verts_doc,
805  (void *)BM_VERTS_OF_FACE},
806  {"edges",
807  (getter)bpy_bmelemseq_elem_get,
808  (setter)NULL,
809  bpy_bmface_edges_doc,
810  (void *)BM_EDGES_OF_FACE},
811  {"loops",
812  (getter)bpy_bmelemseq_elem_get,
813  (setter)NULL,
814  bpy_bmface_loops_doc,
815  (void *)BM_LOOPS_OF_FACE},
816 
817  /* readonly checks */
818  {"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, bpy_bm_is_valid_doc, NULL},
819 
820  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
821 };
822 
823 static PyGetSetDef bpy_bmloop_getseters[] = {
824 /* generic */
825 /* flags are available but not used for loops. */
826 #if 0
827  {"select",
828  (getter)bpy_bm_elem_hflag_get,
829  (setter)bpy_bm_elem_hflag_set,
830  bpy_bm_elem_select_doc,
831  (void *)BM_ELEM_SELECT},
832  {"hide",
833  (getter)bpy_bm_elem_hflag_get,
834  (setter)bpy_bm_elem_hflag_set,
835  bpy_bm_elem_hide_doc,
836  (void *)BM_ELEM_HIDDEN},
837 #endif
838  {"tag",
839  (getter)bpy_bm_elem_hflag_get,
840  (setter)bpy_bm_elem_hflag_set,
841  bpy_bm_elem_tag_doc,
842  (void *)BM_ELEM_TAG},
843  {"index",
844  (getter)bpy_bm_elem_index_get,
845  (setter)bpy_bm_elem_index_set,
846  bpy_bm_elem_index_doc,
847  NULL},
848 
849  {"vert", (getter)bpy_bmloop_vert_get, (setter)NULL, bpy_bmloop_vert_doc, NULL},
850  {"edge", (getter)bpy_bmloop_edge_get, (setter)NULL, bpy_bmloop_edge_doc, NULL},
851  {"face", (getter)bpy_bmloop_face_get, (setter)NULL, bpy_bmloop_face_doc, NULL},
852 
853  /* connectivity data */
854  {"link_loops",
855  (getter)bpy_bmelemseq_elem_get,
856  (setter)NULL,
857  bpy_bmloops_link_loops_doc,
858  (void *)BM_LOOPS_OF_LOOP},
859  {"link_loop_next",
861  (setter)NULL,
862  bpy_bmloop_link_loop_next_doc,
863  NULL},
864  {"link_loop_prev",
866  (setter)NULL,
867  bpy_bmloop_link_loop_prev_doc,
868  NULL},
869  {"link_loop_radial_next",
871  (setter)NULL,
872  bpy_bmloop_link_loop_radial_next_doc,
873  NULL},
874  {"link_loop_radial_prev",
876  (setter)NULL,
877  bpy_bmloop_link_loop_radial_prev_doc,
878  NULL},
879 
880  /* readonly checks */
881  {"is_convex", (getter)bpy_bmloop_is_convex_get, (setter)NULL, bpy_bmloop_is_convex_doc, NULL},
882  {"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, bpy_bm_is_valid_doc, NULL},
883 
884  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
885 };
886 
887 static PyGetSetDef bpy_bmvertseq_getseters[] = {
888  {"layers",
889  (getter)bpy_bmelemseq_layers_get,
890  (setter)NULL,
891  bpy_bmelemseq_layers_vert_doc,
892  (void *)BM_VERT},
893  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
894 };
895 static PyGetSetDef bpy_bmedgeseq_getseters[] = {
896  {"layers",
897  (getter)bpy_bmelemseq_layers_get,
898  (setter)NULL,
899  bpy_bmelemseq_layers_edge_doc,
900  (void *)BM_EDGE},
901  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
902 };
903 static PyGetSetDef bpy_bmfaceseq_getseters[] = {
904  {"layers",
905  (getter)bpy_bmelemseq_layers_get,
906  (setter)NULL,
907  bpy_bmelemseq_layers_face_doc,
908  (void *)BM_FACE},
909  /* face only */
910  {"active",
911  (getter)bpy_bmfaceseq_active_get,
912  (setter)bpy_bmfaceseq_active_set,
913  bpy_bmfaceseq_active_doc,
914  NULL},
915  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
916 };
917 static PyGetSetDef bpy_bmloopseq_getseters[] = {
918  {"layers",
919  (getter)bpy_bmelemseq_layers_get,
920  (setter)NULL,
921  bpy_bmelemseq_layers_loop_doc,
922  (void *)BM_LOOP},
923  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
924 };
925 
926 /* Methods
927  * ======= */
928 
929 /* Mesh
930  * ---- */
931 
932 PyDoc_STRVAR(bpy_bmesh_copy_doc,
933  ".. method:: copy()\n"
934  "\n"
935  " :return: A copy of this BMesh.\n"
936  " :rtype: :class:`BMesh`\n");
937 static PyObject *bpy_bmesh_copy(BPy_BMesh *self)
938 {
939  BMesh *bm;
940  BMesh *bm_copy;
941 
942  BPY_BM_CHECK_OBJ(self);
943 
944  bm = self->bm;
945 
946  bm_copy = BM_mesh_copy(bm);
947 
948  if (bm_copy) {
949  return BPy_BMesh_CreatePyObject(bm_copy, BPY_BMFLAG_NOP);
950  }
951 
952  PyErr_SetString(PyExc_SystemError, "Unable to copy BMesh, internal error");
953  return NULL;
954 }
955 
956 PyDoc_STRVAR(bpy_bmesh_clear_doc,
957  ".. method:: clear()\n"
958  "\n"
959  " Clear all mesh data.\n");
960 static PyObject *bpy_bmesh_clear(BPy_BMesh *self)
961 {
962  BMesh *bm;
963 
964  BPY_BM_CHECK_OBJ(self);
965 
966  bm = self->bm;
967 
968  BM_mesh_clear(bm);
969 
970  Py_RETURN_NONE;
971 }
972 
974  bpy_bmesh_free_doc,
975  ".. method:: free()\n"
976  "\n"
977  " Explicitly free the BMesh data from memory, causing exceptions on further access.\n"
978  "\n"
979  " .. note::\n"
980  "\n"
981  " The BMesh is freed automatically, typically when the script finishes executing.\n"
982  " However in some cases its hard to predict when this will be and its useful to\n"
983  " explicitly free the data.\n");
984 static PyObject *bpy_bmesh_free(BPy_BMesh *self)
985 {
986  if (self->bm) {
987  BMesh *bm = self->bm;
988 
990 
991  if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
992  BM_mesh_free(bm);
993  }
994 
996  }
997 
998  Py_RETURN_NONE;
999 }
1000 
1001 PyDoc_STRVAR(bpy_bmesh_to_mesh_doc,
1002  ".. method:: to_mesh(mesh)\n"
1003  "\n"
1004  " Writes this BMesh data into an existing Mesh datablock.\n"
1005  "\n"
1006  " :arg mesh: The mesh data to write into.\n"
1007  " :type mesh: :class:`Mesh`\n");
1008 static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
1009 {
1010  PyObject *py_mesh;
1011  Mesh *me;
1012  BMesh *bm;
1013 
1014  BPY_BM_CHECK_OBJ(self);
1015 
1016  if (!PyArg_ParseTuple(args, "O:to_mesh", &py_mesh) ||
1017  !(me = PyC_RNA_AsPointer(py_mesh, "Mesh"))) {
1018  return NULL;
1019  }
1020 
1021  /* we could allow this but its almost certainly _not_ what script authors want */
1022  if (me->edit_mesh) {
1023  PyErr_Format(PyExc_ValueError, "to_mesh(): Mesh '%s' is in editmode", me->id.name + 2);
1024  return NULL;
1025  }
1026 
1027  bm = self->bm;
1028 
1029  struct Main *bmain = NULL;
1030  struct BMeshToMeshParams params = {
1031  .update_shapekey_indices = true,
1032  };
1033  if (me->id.tag & LIB_TAG_NO_MAIN) {
1034  /* Mesh might be coming from a self-contained source like object.to_mesh(). No need to remap
1035  * anything in this case. */
1036  }
1037  else {
1039  bmain = G_MAIN; /* XXX UGLY! */
1040  params.calc_object_remap = true;
1041  }
1042 
1043  BM_mesh_bm_to_me(bmain, bm, me, &params);
1044 
1045  /* we could have the user do this but if they forget blender can easy crash
1046  * since the references arrays for the objects derived meshes are now invalid */
1048 
1049  Py_RETURN_NONE;
1050 }
1051 
1052 PyDoc_STRVAR(bpy_bmesh_from_object_doc,
1053  ".. method:: from_object(object, depsgraph, cage=False, face_normals=True, "
1054  "vertex_normals=True)\n"
1055  "\n"
1056  " Initialize this bmesh from existing object data-block (only meshes are currently "
1057  "supported).\n"
1058  "\n"
1059  " :arg object: The object data to load.\n"
1060  " :type object: :class:`Object`\n"
1061  " :arg cage: Get the mesh as a deformed cage.\n"
1062  " :type cage: boolean\n"
1063  " :arg face_normals: Calculate face normals.\n"
1064  " :type face_normals: boolean\n"
1065  " :arg vertex_normals: Calculate vertex normals.\n"
1066  " :type vertex_normals: boolean\n");
1067 static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject *kw)
1068 {
1069  static const char *kwlist[] = {
1070  "object", "depsgraph", "cage", "face_normals", "vertex_normals", NULL};
1071  PyObject *py_object;
1072  PyObject *py_depsgraph;
1073  Object *ob, *ob_eval;
1074  struct Depsgraph *depsgraph;
1075  struct Scene *scene_eval;
1076  Mesh *me_eval;
1077  BMesh *bm;
1078  bool use_cage = false;
1079  bool use_fnorm = true;
1080  bool use_vert_normal = true;
1081  const CustomData_MeshMasks data_masks = CD_MASK_BMESH;
1082 
1083  BPY_BM_CHECK_OBJ(self);
1084 
1085  if (!PyArg_ParseTupleAndKeywords(args,
1086  kw,
1087  "OO|$O&O&O&:from_object",
1088  (char **)kwlist,
1089  &py_object,
1090  &py_depsgraph,
1091  PyC_ParseBool,
1092  &use_cage,
1093  PyC_ParseBool,
1094  &use_fnorm,
1095  PyC_ParseBool,
1096  &use_vert_normal) ||
1097  !(ob = PyC_RNA_AsPointer(py_object, "Object")) ||
1098  !(depsgraph = PyC_RNA_AsPointer(py_depsgraph, "Depsgraph"))) {
1099  return NULL;
1100  }
1101 
1102  if (ob->type != OB_MESH) {
1103  PyErr_SetString(PyExc_ValueError,
1104  "from_object(...): currently only mesh objects are supported");
1105  return NULL;
1106  }
1107 
1108  const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
1109  scene_eval = DEG_get_evaluated_scene(depsgraph);
1110  ob_eval = DEG_get_evaluated_object(depsgraph, ob);
1111  bool need_free = false;
1112 
1113  /* Write the display mesh into the dummy mesh */
1114  if (use_render) {
1115  if (use_cage) {
1116  PyErr_SetString(PyExc_ValueError,
1117  "from_object(...): cage arg is unsupported when dependency graph "
1118  "evaluation mode is RENDER");
1119  return NULL;
1120  }
1121 
1122  me_eval = BKE_mesh_new_from_object(depsgraph, ob_eval, true, false);
1123  need_free = true;
1124  }
1125  else {
1126  if (use_cage) {
1127  me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &data_masks);
1128  }
1129  else {
1130  me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &data_masks);
1131  }
1132  }
1133 
1134  if (me_eval == NULL) {
1135  PyErr_Format(PyExc_ValueError,
1136  "from_object(...): Object '%s' has no usable mesh data",
1137  ob->id.name + 2);
1138  return NULL;
1139  }
1140 
1141  bm = self->bm;
1142 
1144  me_eval,
1145  (&(struct BMeshFromMeshParams){
1146  .calc_face_normal = use_fnorm,
1147  .calc_vert_normal = use_vert_normal,
1148  }));
1149 
1150  if (need_free) {
1151  BKE_id_free(NULL, me_eval);
1152  }
1153 
1154  Py_RETURN_NONE;
1155 }
1156 
1158  bpy_bmesh_from_mesh_doc,
1159  ".. method:: from_mesh(mesh, face_normals=True, vertex_normals=True, use_shape_key=False, "
1160  "shape_key_index=0)\n"
1161  "\n"
1162  " Initialize this bmesh from existing mesh datablock.\n"
1163  "\n"
1164  " :arg mesh: The mesh data to load.\n"
1165  " :type mesh: :class:`Mesh`\n"
1166  " :arg use_shape_key: Use the locations from a shape key.\n"
1167  " :type use_shape_key: boolean\n"
1168  " :arg shape_key_index: The shape key index to use.\n"
1169  " :type shape_key_index: int\n"
1170  "\n"
1171  " .. note::\n"
1172  "\n"
1173  " Multiple calls can be used to join multiple meshes.\n"
1174  "\n"
1175  " Custom-data layers are only copied from ``mesh`` on initialization.\n"
1176  " Further calls will copy custom-data to matching layers, layers missing on the target "
1177  "mesh won't be added.\n");
1178 static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *kw)
1179 {
1180  static const char *kwlist[] = {
1181  "mesh", "face_normals", "vertex_normals", "use_shape_key", "shape_key_index", NULL};
1182  BMesh *bm;
1183  PyObject *py_mesh;
1184  Mesh *me;
1185  bool use_fnorm = true;
1186  bool use_vert_normal = true;
1187  bool use_shape_key = false;
1188  int shape_key_index = 0;
1189 
1190  BPY_BM_CHECK_OBJ(self);
1191 
1192  if (!PyArg_ParseTupleAndKeywords(args,
1193  kw,
1194  "O|$O&O&O&i:from_mesh",
1195  (char **)kwlist,
1196  &py_mesh,
1197  PyC_ParseBool,
1198  &use_fnorm,
1199  PyC_ParseBool,
1200  &use_vert_normal,
1201  PyC_ParseBool,
1202  &use_shape_key,
1203  &shape_key_index) ||
1204  !(me = PyC_RNA_AsPointer(py_mesh, "Mesh"))) {
1205  return NULL;
1206  }
1207 
1208  bm = self->bm;
1209 
1211  me,
1212  (&(struct BMeshFromMeshParams){
1213  .calc_face_normal = use_fnorm,
1214  .calc_vert_normal = use_vert_normal,
1215  .use_shapekey = use_shape_key,
1216  .active_shapekey = shape_key_index + 1,
1217  }));
1218 
1219  Py_RETURN_NONE;
1220 }
1221 
1222 PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc,
1223  ".. method:: select_flush_mode()\n"
1224  "\n"
1225  " flush selection based on the current mode current :class:`BMesh.select_mode`.\n");
1227 {
1228  BPY_BM_CHECK_OBJ(self);
1229 
1231 
1232  Py_RETURN_NONE;
1233 }
1234 
1235 PyDoc_STRVAR(bpy_bmesh_select_flush_doc,
1236  ".. method:: select_flush(select)\n"
1237  "\n"
1238  " Flush selection, independent of the current selection mode.\n"
1239  "\n"
1240  " :arg select: flush selection or de-selected elements.\n"
1241  " :type select: boolean\n");
1242 static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
1243 {
1244  int param;
1245 
1246  BPY_BM_CHECK_OBJ(self);
1247 
1248  if ((param = PyC_Long_AsBool(value)) == -1) {
1249  return NULL;
1250  }
1251 
1252  if (param) {
1254  }
1255  else {
1257  }
1258 
1259  Py_RETURN_NONE;
1260 }
1261 
1263  bpy_bmesh_normal_update_doc,
1264  ".. method:: normal_update()\n"
1265  "\n"
1266  " Update normals of mesh faces and verts.\n"
1267  "\n"
1268  " .. note::\n"
1269  "\n"
1270  " The normal of any vertex where :attr:`is_wire` is True will be a zero vector.\n");
1271 
1272 static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self)
1273 {
1274  BPY_BM_CHECK_OBJ(self);
1275 
1277 
1278  Py_RETURN_NONE;
1279 }
1280 
1281 PyDoc_STRVAR(bpy_bmesh_transform_doc,
1282  ".. method:: transform(matrix, filter=None)\n"
1283  "\n"
1284  " Transform the mesh (optionally filtering flagged data only).\n"
1285  "\n"
1286  " :arg matrix: transform matrix.\n"
1287  " :type matrix: 4x4 :class:`mathutils.Matrix`\n"
1288  " :arg filter: set of values in " BPY_BM_HFLAG_ALL_STR
1289  ".\n"
1290  " :type filter: set\n");
1291 static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
1292 {
1293  static const char *kwlist[] = {"matrix", "filter", NULL};
1294 
1295  MatrixObject *mat;
1296  PyObject *filter = NULL;
1297  int filter_flags = 0;
1298 
1299  BPY_BM_CHECK_OBJ(self);
1300 
1301  if (!PyArg_ParseTupleAndKeywords(args,
1302  kw,
1303  "O!|$O!:transform",
1304  (char **)kwlist,
1305  &matrix_Type,
1306  &mat,
1307  &PySet_Type,
1308  &filter)) {
1309  return NULL;
1310  }
1311 
1312  BMVert *eve;
1313  BMIter iter;
1314  void *mat_ptr;
1315 
1316  if (BaseMath_ReadCallback(mat) == -1) {
1317  return NULL;
1318  }
1319  if (mat->col_num != 4 || mat->row_num != 4) {
1320  PyErr_SetString(PyExc_ValueError, "expected a 4x4 matrix");
1321  return NULL;
1322  }
1323 
1325  bpy_bm_hflag_all_flags, filter, &filter_flags, "bm.transform") == -1) {
1326  return NULL;
1327  }
1328 
1329  mat_ptr = mat->matrix;
1330 
1331  if (!filter_flags) {
1332  BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1333  mul_m4_v3((float(*)[4])mat_ptr, eve->co);
1334  }
1335  }
1336  else {
1337  const char filter_flags_ch = (char)filter_flags;
1338  BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1339  if (BM_elem_flag_test(eve, filter_flags_ch)) {
1340  mul_m4_v3((float(*)[4])mat_ptr, eve->co);
1341  }
1342  }
1343  }
1344 
1345  Py_RETURN_NONE;
1346 }
1347 
1348 PyDoc_STRVAR(bpy_bmesh_calc_volume_doc,
1349  ".. method:: calc_volume(signed=False)\n"
1350  "\n"
1351  " Calculate mesh volume based on face normals.\n"
1352  "\n"
1353  " :arg signed: when signed is true, negative values may be returned.\n"
1354  " :type signed: bool\n"
1355  " :return: The volume of the mesh.\n"
1356  " :rtype: float\n");
1357 static PyObject *bpy_bmesh_calc_volume(BPy_BMElem *self, PyObject *args, PyObject *kw)
1358 {
1359  static const char *kwlist[] = {"signed", NULL};
1360  PyObject *is_signed = Py_False;
1361 
1362  BPY_BM_CHECK_OBJ(self);
1363 
1364  if (!PyArg_ParseTupleAndKeywords(
1365  args, kw, "|$O!:calc_volume", (char **)kwlist, &PyBool_Type, &is_signed)) {
1366  return NULL;
1367  }
1368 
1369  return PyFloat_FromDouble(BM_mesh_calc_volume(self->bm, is_signed != Py_False));
1370 }
1371 
1372 PyDoc_STRVAR(bpy_bmesh_calc_loop_triangles_doc,
1373  ".. method:: calc_loop_triangles()\n"
1374  "\n"
1375  " Calculate triangle tessellation from quads/ngons.\n"
1376  "\n"
1377  " :return: The triangulated faces.\n"
1378  " :rtype: list of :class:`BMLoop` tuples\n");
1380 {
1381  BMesh *bm;
1382 
1383  int looptris_tot;
1384  BMLoop *(*looptris)[3];
1385 
1386  PyObject *ret;
1387  int i;
1388 
1389  BPY_BM_CHECK_OBJ(self);
1390 
1391  bm = self->bm;
1392 
1393  looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
1394  looptris = PyMem_MALLOC(sizeof(*looptris) * looptris_tot);
1395 
1396  BM_mesh_calc_tessellation(bm, looptris);
1397 
1398  ret = PyList_New(looptris_tot);
1399  for (i = 0; i < looptris_tot; i++) {
1400  PyList_SET_ITEM(ret, i, BPy_BMLoop_Array_As_Tuple(bm, looptris[i], 3));
1401  }
1402 
1403  PyMem_FREE(looptris);
1404 
1405  return ret;
1406 }
1407 
1408 /* Elem
1409  * ---- */
1410 
1411 PyDoc_STRVAR(bpy_bm_elem_select_set_doc,
1412  ".. method:: select_set(select)\n"
1413  "\n"
1414  " Set the selection.\n"
1415  " This is different from the *select* attribute because it updates the selection "
1416  "state of associated geometry.\n"
1417  "\n"
1418  " :arg select: Select or de-select.\n"
1419  " :type select: boolean\n"
1420  "\n"
1421  " .. note::\n"
1422  "\n"
1423  " Currently this only flushes down, so selecting a face will select all its "
1424  "vertices but de-selecting a vertex "
1425  " won't de-select all the faces that use it, before finishing with a mesh "
1426  "typically flushing is still needed.\n");
1427 static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
1428 {
1429  int param;
1430 
1431  BPY_BM_CHECK_OBJ(self);
1432 
1433  if ((param = PyC_Long_AsBool(value)) == -1) {
1434  return NULL;
1435  }
1436 
1437  BM_elem_select_set(self->bm, self->ele, param);
1438 
1439  Py_RETURN_NONE;
1440 }
1441 
1442 PyDoc_STRVAR(bpy_bm_elem_hide_set_doc,
1443  ".. method:: hide_set(hide)\n"
1444  "\n"
1445  " Set the hide state.\n"
1446  " This is different from the *hide* attribute because it updates the selection and "
1447  "hide state of associated geometry.\n"
1448  "\n"
1449  " :arg hide: Hidden or visible.\n"
1450  " :type hide: boolean\n");
1451 static PyObject *bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value)
1452 {
1453  int param;
1454 
1455  BPY_BM_CHECK_OBJ(self);
1456 
1457  if ((param = PyC_Long_AsBool(value)) == -1) {
1458  return NULL;
1459  }
1460 
1461  BM_elem_hide_set(self->bm, self->ele, param);
1462 
1463  Py_RETURN_NONE;
1464 }
1465 
1466 PyDoc_STRVAR(bpy_bm_elem_copy_from_doc,
1467  ".. method:: copy_from(other)\n"
1468  "\n"
1469  " Copy values from another element of matching type.\n");
1470 static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
1471 {
1472  BPY_BM_CHECK_OBJ(self);
1473 
1474  if (Py_TYPE(self) != Py_TYPE(value)) {
1475  PyErr_Format(PyExc_TypeError,
1476  "expected element of type '%.200s' not '%.200s'",
1477  Py_TYPE(self)->tp_name,
1478  Py_TYPE(value)->tp_name);
1479  return NULL;
1480  }
1481 
1482  if (value->ele != self->ele) {
1483  BM_elem_attrs_copy_ex(value->bm, self->bm, value->ele, self->ele, 0xff, CD_MASK_BM_ELEM_PYPTR);
1484  }
1485 
1486  Py_RETURN_NONE;
1487 }
1488 
1489 /* Vert
1490  * ---- */
1491 
1492 PyDoc_STRVAR(bpy_bmvert_copy_from_vert_interp_doc,
1493  ".. method:: copy_from_vert_interp(vert_pair, fac)\n"
1494  "\n"
1495  " Interpolate the customdata from a vert between 2 other verts.\n"
1496  "\n"
1497  " :arg vert_pair: The vert to interpolate data from.\n"
1498  " :type vert_pair: :class:`BMVert`\n");
1499 static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *args)
1500 {
1501  PyObject *vert_seq;
1502  float fac;
1503 
1504  BPY_BM_CHECK_OBJ(self);
1505 
1506  if (!PyArg_ParseTuple(args, "Of:BMVert.copy_from_vert_interp", &vert_seq, &fac)) {
1507  return NULL;
1508  }
1509 
1510  BMesh *bm = self->bm;
1511  BMVert **vert_array = NULL;
1512  Py_ssize_t vert_seq_len; /* always 2 */
1513 
1514  vert_array = BPy_BMElem_PySeq_As_Array(&bm,
1515  vert_seq,
1516  2,
1517  2,
1518  &vert_seq_len,
1519  BM_VERT,
1520  true,
1521  true,
1522  "BMVert.copy_from_vert_interp(...)");
1523 
1524  if (vert_array == NULL) {
1525  return NULL;
1526  }
1527 
1528  BM_data_interp_from_verts(bm, vert_array[0], vert_array[1], self->v, clamp_f(fac, 0.0f, 1.0f));
1529 
1530  PyMem_FREE(vert_array);
1531  Py_RETURN_NONE;
1532 }
1533 
1534 PyDoc_STRVAR(bpy_bmvert_copy_from_face_interp_doc,
1535  ".. method:: copy_from_face_interp(face)\n"
1536  "\n"
1537  " Interpolate the customdata from a face onto this loop (the loops vert should "
1538  "overlap the face).\n"
1539  "\n"
1540  " :arg face: The face to interpolate data from.\n"
1541  " :type face: :class:`BMFace`\n");
1542 static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *args)
1543 {
1544  BPy_BMFace *py_face = NULL;
1545 
1546  BPY_BM_CHECK_OBJ(self);
1547 
1548  if (!PyArg_ParseTuple(args, "O!:BMVert.copy_from_face_interp", &BPy_BMFace_Type, &py_face)) {
1549  return NULL;
1550  }
1551 
1552  BMesh *bm = self->bm;
1553 
1554  BPY_BM_CHECK_SOURCE_OBJ(bm, "copy_from_face_interp()", py_face);
1555 
1556  BM_vert_interp_from_face(bm, self->v, py_face->f);
1557 
1558  Py_RETURN_NONE;
1559 }
1560 
1561 PyDoc_STRVAR(bpy_bmvert_calc_edge_angle_doc,
1562  ".. method:: calc_edge_angle(fallback=None)\n"
1563  "\n"
1564  " Return the angle between this vert's two connected edges.\n"
1565  "\n"
1566  " :arg fallback: return this when the vert doesn't have 2 edges\n"
1567  " (instead of raising a :exc:`ValueError`).\n"
1568  " :type fallback: any\n"
1569  " :return: Angle between edges in radians.\n"
1570  " :rtype: float\n");
1571 static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self, PyObject *args)
1572 {
1573  const float angle_invalid = -1.0f;
1574  float angle;
1575  PyObject *fallback = NULL;
1576 
1577  BPY_BM_CHECK_OBJ(self);
1578 
1579  if (!PyArg_ParseTuple(args, "|O:calc_edge_angle", &fallback)) {
1580  return NULL;
1581  }
1582 
1583  angle = BM_vert_calc_edge_angle_ex(self->v, angle_invalid);
1584 
1585  if (angle == angle_invalid) {
1586  /* avoid exception */
1587  if (fallback) {
1588  Py_INCREF(fallback);
1589  return fallback;
1590  }
1591 
1592  PyErr_SetString(PyExc_ValueError,
1593  "BMVert.calc_edge_angle(): "
1594  "vert must connect to exactly 2 edges");
1595  return NULL;
1596  }
1597 
1598  return PyFloat_FromDouble(angle);
1599 }
1600 
1602  bpy_bmvert_calc_shell_factor_doc,
1603  ".. method:: calc_shell_factor()\n"
1604  "\n"
1605  " Return a multiplier calculated based on the sharpness of the vertex.\n"
1606  " Where a flat surface gives 1.0, and higher values sharper edges.\n"
1607  " This is used to maintain shell thickness when offsetting verts along their normals.\n"
1608  "\n"
1609  " :return: offset multiplier\n"
1610  " :rtype: float\n");
1612 {
1613  BPY_BM_CHECK_OBJ(self);
1614  return PyFloat_FromDouble(BM_vert_calc_shell_factor(self->v));
1615 }
1616 
1617 PyDoc_STRVAR(bpy_bmvert_normal_update_doc,
1618  ".. method:: normal_update()\n"
1619  "\n"
1620  " Update vertex normal.\n"
1621  " This does not update the normals of adjoining faces.\n"
1622  "\n"
1623  " .. note::\n"
1624  "\n"
1625  " The vertex normal will be a zero vector if vertex :attr:`is_wire` is True.\n");
1626 static PyObject *bpy_bmvert_normal_update(BPy_BMVert *self)
1627 {
1628  BPY_BM_CHECK_OBJ(self);
1629 
1631 
1632  Py_RETURN_NONE;
1633 }
1634 
1635 /* Edge
1636  * ---- */
1637 
1638 PyDoc_STRVAR(bpy_bmedge_calc_length_doc,
1639  ".. method:: calc_length()\n"
1640  "\n"
1641  " :return: The length between both verts.\n"
1642  " :rtype: float\n");
1643 static PyObject *bpy_bmedge_calc_length(BPy_BMEdge *self)
1644 {
1645  BPY_BM_CHECK_OBJ(self);
1646  return PyFloat_FromDouble(len_v3v3(self->e->v1->co, self->e->v2->co));
1647 }
1648 
1649 PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
1650  ".. method:: calc_face_angle(fallback=None)\n"
1651  "\n"
1652  " :arg fallback: return this when the edge doesn't have 2 faces\n"
1653  " (instead of raising a :exc:`ValueError`).\n"
1654  " :type fallback: any\n"
1655  " :return: The angle between 2 connected faces in radians.\n"
1656  " :rtype: float\n");
1657 static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self, PyObject *args)
1658 {
1659  const float angle_invalid = -1.0f;
1660  float angle;
1661  PyObject *fallback = NULL;
1662 
1663  BPY_BM_CHECK_OBJ(self);
1664 
1665  if (!PyArg_ParseTuple(args, "|O:calc_face_angle", &fallback)) {
1666  return NULL;
1667  }
1668 
1669  angle = BM_edge_calc_face_angle_ex(self->e, angle_invalid);
1670 
1671  if (angle == angle_invalid) {
1672  /* avoid exception */
1673  if (fallback) {
1674  Py_INCREF(fallback);
1675  return fallback;
1676  }
1677 
1678  PyErr_SetString(PyExc_ValueError,
1679  "BMEdge.calc_face_angle(): "
1680  "edge doesn't use 2 faces");
1681  return NULL;
1682  }
1683 
1684  return PyFloat_FromDouble(angle);
1685 }
1686 
1688  bpy_bmedge_calc_face_angle_signed_doc,
1689  ".. method:: calc_face_angle_signed(fallback=None)\n"
1690  "\n"
1691  " :arg fallback: return this when the edge doesn't have 2 faces\n"
1692  " (instead of raising a :exc:`ValueError`).\n"
1693  " :type fallback: any\n"
1694  " :return: The angle between 2 connected faces in radians (negative for concave join).\n"
1695  " :rtype: float\n");
1696 static PyObject *bpy_bmedge_calc_face_angle_signed(BPy_BMEdge *self, PyObject *args)
1697 {
1698  const float angle_invalid = -FLT_MAX;
1699  float angle;
1700  PyObject *fallback = NULL;
1701 
1702  BPY_BM_CHECK_OBJ(self);
1703 
1704  if (!PyArg_ParseTuple(args, "|O:calc_face_angle_signed", &fallback)) {
1705  return NULL;
1706  }
1707 
1708  angle = BM_edge_calc_face_angle_signed_ex(self->e, angle_invalid);
1709 
1710  if (angle == angle_invalid) {
1711  /* avoid exception */
1712  if (fallback) {
1713  Py_INCREF(fallback);
1714  return fallback;
1715  }
1716 
1717  PyErr_SetString(PyExc_ValueError,
1718  "BMEdge.calc_face_angle_signed(): "
1719  "edge doesn't use 2 faces");
1720  return NULL;
1721  }
1722 
1723  return PyFloat_FromDouble(angle);
1724 }
1725 
1727  bpy_bmedge_calc_tangent_doc,
1728  ".. method:: calc_tangent(loop)\n"
1729  "\n"
1730  " Return the tangent at this edge relative to a face (pointing inward into the face).\n"
1731  " This uses the face normal for calculation.\n"
1732  "\n"
1733  " :arg loop: The loop used for tangent calculation.\n"
1734  " :type loop: :class:`BMLoop`\n"
1735  " :return: a normalized vector.\n"
1736  " :rtype: :class:`mathutils.Vector`\n");
1737 static PyObject *bpy_bmedge_calc_tangent(BPy_BMEdge *self, PyObject *args)
1738 {
1739  BPy_BMLoop *py_loop;
1740  BPY_BM_CHECK_OBJ(self);
1741 
1742  if (!PyArg_ParseTuple(args, "O!:BMEdge.calc_face_tangent", &BPy_BMLoop_Type, &py_loop)) {
1743  return NULL;
1744  }
1745 
1746  float vec[3];
1747  BPY_BM_CHECK_OBJ(py_loop);
1748  /* no need to check if they are from the same mesh or even connected */
1749  BM_edge_calc_face_tangent(self->e, py_loop->l, vec);
1750  return Vector_CreatePyObject(vec, 3, NULL);
1751 }
1752 
1754  bpy_bmedge_other_vert_doc,
1755  ".. method:: other_vert(vert)\n"
1756  "\n"
1757  " Return the other vertex on this edge or None if the vertex is not used by this edge.\n"
1758  "\n"
1759  " :arg vert: a vert in this edge.\n"
1760  " :type vert: :class:`BMVert`\n"
1761  " :return: The edges other vert.\n"
1762  " :rtype: :class:`BMVert` or None\n");
1763 static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
1764 {
1765  BMVert *other;
1766  BPY_BM_CHECK_OBJ(self);
1767 
1768  if (!BPy_BMVert_Check(value)) {
1769  PyErr_Format(PyExc_TypeError,
1770  "BMEdge.other_vert(vert): BMVert expected, not '%.200s'",
1771  Py_TYPE(value)->tp_name);
1772  return NULL;
1773  }
1774 
1775  BPY_BM_CHECK_SOURCE_OBJ(self->bm, "BMEdge.other_vert(vert)", value);
1776 
1777  other = BM_edge_other_vert(self->e, value->v);
1778 
1779  if (other) {
1780  return BPy_BMVert_CreatePyObject(self->bm, other);
1781  }
1782 
1783  /* could raise an exception here */
1784  Py_RETURN_NONE;
1785 }
1786 
1788  bpy_bmedge_normal_update_doc,
1789  ".. method:: normal_update()\n"
1790  "\n"
1791  " Update normals of all connected faces and the edge verts.\n"
1792  "\n"
1793  " .. note::\n"
1794  "\n"
1795  " The normal of edge vertex will be a zero vector if vertex :attr:`is_wire` is True.\n");
1796 static PyObject *bpy_bmedge_normal_update(BPy_BMEdge *self)
1797 {
1798  BPY_BM_CHECK_OBJ(self);
1799 
1801 
1802  Py_RETURN_NONE;
1803 }
1804 
1805 /* Face
1806  * ---- */
1807 
1809  bpy_bmface_copy_from_face_interp_doc,
1810  ".. method:: copy_from_face_interp(face, vert=True)\n"
1811  "\n"
1812  " Interpolate the customdata from another face onto this one (faces should overlap).\n"
1813  "\n"
1814  " :arg face: The face to interpolate data from.\n"
1815  " :type face: :class:`BMFace`\n"
1816  " :arg vert: When True, also copy vertex data.\n"
1817  " :type vert: boolean\n");
1818 static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
1819 {
1820  BPy_BMFace *py_face = NULL;
1821  bool do_vertex = true;
1822 
1823  BPY_BM_CHECK_OBJ(self);
1824 
1825  if (!PyArg_ParseTuple(args,
1826  "O!|O&:BMFace.copy_from_face_interp",
1827  &BPy_BMFace_Type,
1828  &py_face,
1829  PyC_ParseBool,
1830  &do_vertex)) {
1831  return NULL;
1832  }
1833 
1834  BMesh *bm = self->bm;
1835 
1836  BPY_BM_CHECK_SOURCE_OBJ(bm, "BMFace.copy_from_face_interp(face)", py_face);
1837 
1838  BM_face_interp_from_face(bm, self->f, py_face->f, do_vertex);
1839 
1840  Py_RETURN_NONE;
1841 }
1842 
1843 PyDoc_STRVAR(bpy_bmface_copy_doc,
1844  ".. method:: copy(verts=True, edges=True)\n"
1845  "\n"
1846  " Make a copy of this face.\n"
1847  "\n"
1848  " :arg verts: When set, the faces verts will be duplicated too.\n"
1849  " :type verts: boolean\n"
1850  " :arg edges: When set, the faces edges will be duplicated too.\n"
1851  " :type edges: boolean\n"
1852  " :return: The newly created face.\n"
1853  " :rtype: :class:`BMFace`\n");
1854 static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
1855 {
1856  static const char *kwlist[] = {"verts", "edges", NULL};
1857 
1858  BMesh *bm = self->bm;
1859  bool do_verts = true;
1860  bool do_edges = true;
1861 
1862  BMFace *f_cpy;
1863  BPY_BM_CHECK_OBJ(self);
1864 
1865  if (!PyArg_ParseTupleAndKeywords(args,
1866  kw,
1867  "|$O&O&:BMFace.copy",
1868  (char **)kwlist,
1869  PyC_ParseBool,
1870  &do_verts,
1871  PyC_ParseBool,
1872  &do_edges)) {
1873  return NULL;
1874  }
1875 
1876  f_cpy = BM_face_copy(bm, bm, self->f, do_verts, do_edges);
1877 
1878  if (f_cpy) {
1879  return BPy_BMFace_CreatePyObject(bm, f_cpy);
1880  }
1881 
1882  PyErr_SetString(PyExc_ValueError, "BMFace.copy(): couldn't create the new face, internal error");
1883  return NULL;
1884 }
1885 
1886 PyDoc_STRVAR(bpy_bmface_calc_area_doc,
1887  ".. method:: calc_area()\n"
1888  "\n"
1889  " Return the area of the face.\n"
1890  "\n"
1891  " :return: Return the area of the face.\n"
1892  " :rtype: float\n");
1893 static PyObject *bpy_bmface_calc_area(BPy_BMFace *self)
1894 {
1895  BPY_BM_CHECK_OBJ(self);
1896  return PyFloat_FromDouble(BM_face_calc_area(self->f));
1897 }
1898 
1899 PyDoc_STRVAR(bpy_bmface_calc_perimeter_doc,
1900  ".. method:: calc_perimeter()\n"
1901  "\n"
1902  " Return the perimeter of the face.\n"
1903  "\n"
1904  " :return: Return the perimeter of the face.\n"
1905  " :rtype: float\n");
1906 static PyObject *bpy_bmface_calc_perimeter(BPy_BMFace *self)
1907 {
1908  BPY_BM_CHECK_OBJ(self);
1909  return PyFloat_FromDouble(BM_face_calc_perimeter(self->f));
1910 }
1911 
1912 PyDoc_STRVAR(bpy_bmface_calc_tangent_edge_doc,
1913  ".. method:: calc_tangent_edge()\n"
1914  "\n"
1915  " Return face tangent based on longest edge.\n"
1916  "\n"
1917  " :return: a normalized vector.\n"
1918  " :rtype: :class:`mathutils.Vector`\n");
1920 {
1921  float tangent[3];
1922 
1923  BPY_BM_CHECK_OBJ(self);
1924  BM_face_calc_tangent_edge(self->f, tangent);
1925  return Vector_CreatePyObject(tangent, 3, NULL);
1926 }
1927 
1928 PyDoc_STRVAR(bpy_bmface_calc_tangent_edge_pair_doc,
1929  ".. method:: calc_tangent_edge_pair()\n"
1930  "\n"
1931  " Return face tangent based on the two longest disconnected edges.\n"
1932  "\n"
1933  " - Tris: Use the edge pair with the most similar lengths.\n"
1934  " - Quads: Use the longest edge pair.\n"
1935  " - NGons: Use the two longest disconnected edges.\n"
1936  "\n"
1937  " :return: a normalized vector.\n"
1938  " :rtype: :class:`mathutils.Vector`\n");
1940 {
1941  float tangent[3];
1942 
1943  BPY_BM_CHECK_OBJ(self);
1944  BM_face_calc_tangent_edge_pair(self->f, tangent);
1945  return Vector_CreatePyObject(tangent, 3, NULL);
1946 }
1947 
1948 PyDoc_STRVAR(bpy_bmface_calc_tangent_edge_diagonal_doc,
1949  ".. method:: calc_tangent_edge_diagonal()\n"
1950  "\n"
1951  " Return face tangent based on the edge farthest from any vertex.\n"
1952  "\n"
1953  " :return: a normalized vector.\n"
1954  " :rtype: :class:`mathutils.Vector`\n");
1956 {
1957  float tangent[3];
1958 
1959  BPY_BM_CHECK_OBJ(self);
1961  return Vector_CreatePyObject(tangent, 3, NULL);
1962 }
1963 
1964 PyDoc_STRVAR(bpy_bmface_calc_tangent_vert_diagonal_doc,
1965  ".. method:: calc_tangent_vert_diagonal()\n"
1966  "\n"
1967  " Return face tangent based on the two most distant vertices.\n"
1968  "\n"
1969  " :return: a normalized vector.\n"
1970  " :rtype: :class:`mathutils.Vector`\n");
1972 {
1973  float tangent[3];
1974 
1975  BPY_BM_CHECK_OBJ(self);
1977  return Vector_CreatePyObject(tangent, 3, NULL);
1978 }
1979 
1980 PyDoc_STRVAR(bpy_bmface_calc_center_median_doc,
1981  ".. method:: calc_center_median()\n"
1982  "\n"
1983  " Return median center of the face.\n"
1984  "\n"
1985  " :return: a 3D vector.\n"
1986  " :rtype: :class:`mathutils.Vector`\n");
1988 {
1989  float cent[3];
1990 
1991  BPY_BM_CHECK_OBJ(self);
1992  BM_face_calc_center_median(self->f, cent);
1993  return Vector_CreatePyObject(cent, 3, NULL);
1994 }
1995 
1996 PyDoc_STRVAR(bpy_bmface_calc_center_median_weighted_doc,
1997  ".. method:: calc_center_median_weighted()\n"
1998  "\n"
1999  " Return median center of the face weighted by edge lengths.\n"
2000  "\n"
2001  " :return: a 3D vector.\n"
2002  " :rtype: :class:`mathutils.Vector`\n");
2004 {
2005  float cent[3];
2006 
2007  BPY_BM_CHECK_OBJ(self);
2009  return Vector_CreatePyObject(cent, 3, NULL);
2010 }
2011 
2012 PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
2013  ".. method:: calc_center_bounds()\n"
2014  "\n"
2015  " Return bounds center of the face.\n"
2016  "\n"
2017  " :return: a 3D vector.\n"
2018  " :rtype: :class:`mathutils.Vector`\n");
2020 {
2021  float cent[3];
2022 
2023  BPY_BM_CHECK_OBJ(self);
2024  BM_face_calc_center_bounds(self->f, cent);
2025  return Vector_CreatePyObject(cent, 3, NULL);
2026 }
2027 
2028 PyDoc_STRVAR(bpy_bmface_normal_update_doc,
2029  ".. method:: normal_update()\n"
2030  "\n"
2031  " Update face normal based on the positions of the face verts.\n"
2032  " This does not update the normals of face verts.\n");
2033 static PyObject *bpy_bmface_normal_update(BPy_BMFace *self)
2034 {
2035  BPY_BM_CHECK_OBJ(self);
2036 
2038 
2039  Py_RETURN_NONE;
2040 }
2041 
2042 PyDoc_STRVAR(bpy_bmface_normal_flip_doc,
2043  ".. method:: normal_flip()\n"
2044  "\n"
2045  " Reverses winding of a face, which flips its normal.\n");
2046 static PyObject *bpy_bmface_normal_flip(BPy_BMFace *self)
2047 {
2048  BPY_BM_CHECK_OBJ(self);
2049 
2050  BM_face_normal_flip(self->bm, self->f);
2051 
2052  Py_RETURN_NONE;
2053 }
2054 
2055 /* Loop
2056  * ---- */
2057 
2058 PyDoc_STRVAR(bpy_bmloop_copy_from_face_interp_doc,
2059  ".. method:: copy_from_face_interp(face, vert=True, multires=True)\n"
2060  "\n"
2061  " Interpolate the customdata from a face onto this loop (the loops vert should "
2062  "overlap the face).\n"
2063  "\n"
2064  " :arg face: The face to interpolate data from.\n"
2065  " :type face: :class:`BMFace`\n"
2066  " :arg vert: When enabled, interpolate the loops vertex data (optional).\n"
2067  " :type vert: boolean\n"
2068  " :arg multires: When enabled, interpolate the loops multires data (optional).\n"
2069  " :type multires: boolean\n");
2070 static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
2071 {
2072  BPy_BMFace *py_face = NULL;
2073  bool do_vertex = true;
2074  bool do_multires = true;
2075 
2076  BPY_BM_CHECK_OBJ(self);
2077 
2078  if (!PyArg_ParseTuple(args,
2079  "O!|O&O&:BMLoop.copy_from_face_interp",
2080  &BPy_BMFace_Type,
2081  &py_face,
2082  PyC_ParseBool,
2083  &do_vertex,
2084  PyC_ParseBool,
2085  &do_multires)) {
2086  return NULL;
2087  }
2088 
2089  BMesh *bm = self->bm;
2090 
2091  BPY_BM_CHECK_SOURCE_OBJ(bm, "BMLoop.copy_from_face_interp(face)", py_face);
2092 
2093  BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires);
2094 
2095  Py_RETURN_NONE;
2096 }
2097 
2098 PyDoc_STRVAR(bpy_bmloop_calc_angle_doc,
2099  ".. method:: calc_angle()\n"
2100  "\n"
2101  " Return the angle at this loops corner of the face.\n"
2102  " This is calculated so sharper corners give lower angles.\n"
2103  "\n"
2104  " :return: The angle in radians.\n"
2105  " :rtype: float\n");
2106 static PyObject *bpy_bmloop_calc_angle(BPy_BMLoop *self)
2107 {
2108  BPY_BM_CHECK_OBJ(self);
2109  return PyFloat_FromDouble(BM_loop_calc_face_angle(self->l));
2110 }
2111 
2112 PyDoc_STRVAR(bpy_bmloop_calc_normal_doc,
2113  ".. method:: calc_normal()\n"
2114  "\n"
2115  " Return normal at this loops corner of the face.\n"
2116  " Falls back to the face normal for straight lines.\n"
2117  "\n"
2118  " :return: a normalized vector.\n"
2119  " :rtype: :class:`mathutils.Vector`\n");
2120 static PyObject *bpy_bmloop_calc_normal(BPy_BMLoop *self)
2121 {
2122  float vec[3];
2123  BPY_BM_CHECK_OBJ(self);
2124  BM_loop_calc_face_normal(self->l, vec);
2125  return Vector_CreatePyObject(vec, 3, NULL);
2126 }
2127 
2129  bpy_bmloop_calc_tangent_doc,
2130  ".. method:: calc_tangent()\n"
2131  "\n"
2132  " Return the tangent at this loops corner of the face (pointing inward into the face).\n"
2133  " Falls back to the face normal for straight lines.\n"
2134  "\n"
2135  " :return: a normalized vector.\n"
2136  " :rtype: :class:`mathutils.Vector`\n");
2137 static PyObject *bpy_bmloop_calc_tangent(BPy_BMLoop *self)
2138 {
2139  float vec[3];
2140  BPY_BM_CHECK_OBJ(self);
2142  return Vector_CreatePyObject(vec, 3, NULL);
2143 }
2144 
2145 /* Vert Seq
2146  * -------- */
2147 PyDoc_STRVAR(bpy_bmvertseq_new_doc,
2148  ".. method:: new(co=(0.0, 0.0, 0.0), example=None)\n"
2149  "\n"
2150  " Create a new vertex.\n"
2151  "\n"
2152  " :arg co: The initial location of the vertex (optional argument).\n"
2153  " :type co: float triplet\n"
2154  " :arg example: Existing vert to initialize settings.\n"
2155  " :type example: :class:`BMVert`\n"
2156  " :return: The newly created edge.\n"
2157  " :rtype: :class:`BMVert`\n");
2158 static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
2159 {
2160  PyObject *py_co = NULL;
2161  BPy_BMVert *py_vert_example = NULL; /* optional */
2162 
2163  BPY_BM_CHECK_OBJ(self);
2164 
2165  if (!PyArg_ParseTuple(args, "|OO!:verts.new", &py_co, &BPy_BMVert_Type, &py_vert_example)) {
2166  return NULL;
2167  }
2168 
2169  BMesh *bm = self->bm;
2170  BMVert *v;
2171  float co[3] = {0.0f, 0.0f, 0.0f};
2172 
2173  if (py_vert_example) {
2174  BPY_BM_CHECK_OBJ(py_vert_example);
2175  }
2176 
2177  if (py_co && mathutils_array_parse(co, 3, 3, py_co, "verts.new(co)") == -1) {
2178  return NULL;
2179  }
2180 
2182 
2183  if (v == NULL) {
2184  PyErr_SetString(PyExc_ValueError,
2185  "faces.new(verts): couldn't create the new face, internal error");
2186  return NULL;
2187  }
2188 
2189  if (py_vert_example) {
2190  BM_elem_attrs_copy(py_vert_example->bm, bm, py_vert_example->v, v);
2191  }
2192 
2193  return BPy_BMVert_CreatePyObject(bm, v);
2194 }
2195 
2196 /* Edge Seq
2197  * -------- */
2198 PyDoc_STRVAR(bpy_bmedgeseq_new_doc,
2199  ".. method:: new(verts, example=None)\n"
2200  "\n"
2201  " Create a new edge from a given pair of verts.\n"
2202  "\n"
2203  " :arg verts: Vertex pair.\n"
2204  " :type verts: pair of :class:`BMVert`\n"
2205  " :arg example: Existing edge to initialize settings (optional argument).\n"
2206  " :type example: :class:`BMEdge`\n"
2207  " :return: The newly created edge.\n"
2208  " :rtype: :class:`BMEdge`\n");
2209 static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
2210 {
2211  PyObject *vert_seq;
2212  BPy_BMEdge *py_edge_example = NULL; /* optional */
2213 
2214  BPY_BM_CHECK_OBJ(self);
2215 
2216  if (!PyArg_ParseTuple(args, "O|O!:edges.new", &vert_seq, &BPy_BMEdge_Type, &py_edge_example)) {
2217  return NULL;
2218  }
2219 
2220  BMesh *bm = self->bm;
2221  BMEdge *e;
2222  BMVert **vert_array = NULL;
2223  Py_ssize_t vert_seq_len; /* always 2 */
2224  PyObject *ret = NULL;
2225 
2226  if (py_edge_example) {
2227  BPY_BM_CHECK_OBJ(py_edge_example);
2228  }
2229 
2230  vert_array = BPy_BMElem_PySeq_As_Array(
2231  &bm, vert_seq, 2, 2, &vert_seq_len, BM_VERT, true, true, "edges.new(...)");
2232 
2233  if (vert_array == NULL) {
2234  return NULL;
2235  }
2236 
2237  if (BM_edge_exists(vert_array[0], vert_array[1])) {
2238  PyErr_SetString(PyExc_ValueError, "edges.new(): this edge exists");
2239  goto cleanup;
2240  }
2241 
2242  e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, BM_CREATE_NOP);
2243 
2244  if (e == NULL) {
2245  PyErr_SetString(PyExc_ValueError,
2246  "faces.new(verts): couldn't create the new face, internal error");
2247  goto cleanup;
2248  }
2249 
2250  if (py_edge_example) {
2251  BM_elem_attrs_copy(py_edge_example->bm, bm, py_edge_example->e, e);
2252  }
2253 
2255 
2256 cleanup:
2257  if (vert_array) {
2258  PyMem_FREE(vert_array);
2259  }
2260  return ret;
2261 }
2262 
2263 /* Face Seq
2264  * -------- */
2265 PyDoc_STRVAR(bpy_bmfaceseq_new_doc,
2266  ".. method:: new(verts, example=None)\n"
2267  "\n"
2268  " Create a new face from a given set of verts.\n"
2269  "\n"
2270  " :arg verts: Sequence of 3 or more verts.\n"
2271  " :type verts: :class:`BMVert`\n"
2272  " :arg example: Existing face to initialize settings (optional argument).\n"
2273  " :type example: :class:`BMFace`\n"
2274  " :return: The newly created face.\n"
2275  " :rtype: :class:`BMFace`\n");
2276 static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
2277 {
2278  PyObject *vert_seq;
2279  BPy_BMFace *py_face_example = NULL; /* optional */
2280 
2281  BPY_BM_CHECK_OBJ(self);
2282 
2283  if (!PyArg_ParseTuple(args, "O|O!:faces.new", &vert_seq, &BPy_BMFace_Type, &py_face_example)) {
2284  return NULL;
2285  }
2286 
2287  BMesh *bm = self->bm;
2288  Py_ssize_t vert_seq_len;
2289 
2290  BMVert **vert_array = NULL;
2291 
2292  PyObject *ret = NULL;
2293 
2294  BMFace *f_new;
2295 
2296  if (py_face_example) {
2297  BPY_BM_CHECK_OBJ(py_face_example);
2298  }
2299 
2300  vert_array = BPy_BMElem_PySeq_As_Array(
2301  &bm, vert_seq, 3, PY_SSIZE_T_MAX, &vert_seq_len, BM_VERT, true, true, "faces.new(...)");
2302 
2303  if (vert_array == NULL) {
2304  return NULL;
2305  }
2306 
2307  /* check if the face exists */
2308  if (BM_face_exists(vert_array, vert_seq_len) != NULL) {
2309  PyErr_SetString(PyExc_ValueError, "faces.new(verts): face already exists");
2310  goto cleanup;
2311  }
2312 
2313  /* Go ahead and make the face!
2314  * --------------------------- */
2315 
2316  f_new = BM_face_create_verts(bm,
2317  vert_array,
2318  vert_seq_len,
2319  py_face_example ? py_face_example->f : NULL,
2320  BM_CREATE_NOP,
2321  true);
2322 
2323  if (UNLIKELY(f_new == NULL)) {
2324  PyErr_SetString(PyExc_ValueError,
2325  "faces.new(verts): couldn't create the new face, internal error");
2326  goto cleanup;
2327  }
2328 
2329  ret = BPy_BMFace_CreatePyObject(bm, f_new);
2330 
2331  /* pass through */
2332 cleanup:
2333  if (vert_array) {
2334  PyMem_FREE(vert_array);
2335  }
2336  return ret;
2337 }
2338 
2339 /* Elem Seq
2340  * -------- */
2341 
2342 PyDoc_STRVAR(bpy_bmvertseq_remove_doc,
2343  ".. method:: remove(vert)\n"
2344  "\n"
2345  " Remove a vert.\n");
2346 static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
2347 {
2348  BPY_BM_CHECK_OBJ(self);
2349 
2350  if (!BPy_BMVert_Check(value)) {
2351  return NULL;
2352  }
2353 
2354  BMesh *bm = self->bm;
2355 
2356  BPY_BM_CHECK_SOURCE_OBJ(bm, "verts.remove(vert)", value);
2357 
2358  BM_vert_kill(bm, value->v);
2360 
2361  Py_RETURN_NONE;
2362 }
2363 
2364 PyDoc_STRVAR(bpy_bmedgeseq_remove_doc,
2365  ".. method:: remove(edge)\n"
2366  "\n"
2367  " Remove an edge.\n");
2368 static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
2369 {
2370  BPY_BM_CHECK_OBJ(self);
2371 
2372  if (!BPy_BMEdge_Check(value)) {
2373  return NULL;
2374  }
2375 
2376  BMesh *bm = self->bm;
2377 
2378  BPY_BM_CHECK_SOURCE_OBJ(bm, "edges.remove(edges)", value);
2379 
2380  BM_edge_kill(bm, value->e);
2382 
2383  Py_RETURN_NONE;
2384 }
2385 
2386 PyDoc_STRVAR(bpy_bmfaceseq_remove_doc,
2387  ".. method:: remove(face)\n"
2388  "\n"
2389  " Remove a face.\n");
2390 static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
2391 {
2392  BPY_BM_CHECK_OBJ(self);
2393 
2394  if (!BPy_BMFace_Check(value)) {
2395  return NULL;
2396  }
2397 
2398  BMesh *bm = self->bm;
2399 
2400  BPY_BM_CHECK_SOURCE_OBJ(bm, "faces.remove(face)", value);
2401 
2402  BM_face_kill(bm, value->f);
2404 
2405  Py_RETURN_NONE;
2406 }
2407 
2408 PyDoc_STRVAR(bpy_bmedgeseq_get__method_doc,
2409  ".. method:: get(verts, fallback=None)\n"
2410  "\n"
2411  " Return an edge which uses the **verts** passed.\n"
2412  "\n"
2413  " :arg verts: Sequence of verts.\n"
2414  " :type verts: :class:`BMVert`\n"
2415  " :arg fallback: Return this value if nothing is found.\n"
2416  " :return: The edge found or None\n"
2417  " :rtype: :class:`BMEdge`\n");
2418 static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
2419 {
2420  PyObject *vert_seq;
2421  PyObject *fallback = Py_None; /* optional */
2422 
2423  BPY_BM_CHECK_OBJ(self);
2424 
2425  if (!PyArg_ParseTuple(args, "O|O:edges.get", &vert_seq, &fallback)) {
2426  return NULL;
2427  }
2428 
2429  BMesh *bm = self->bm;
2430  BMEdge *e;
2431  BMVert **vert_array = NULL;
2432  Py_ssize_t vert_seq_len; /* always 2 */
2433  PyObject *ret = NULL;
2434 
2435  vert_array = BPy_BMElem_PySeq_As_Array(
2436  &bm, vert_seq, 2, 2, &vert_seq_len, BM_VERT, true, true, "edges.get(...)");
2437 
2438  if (vert_array == NULL) {
2439  return NULL;
2440  }
2441 
2442  if ((e = BM_edge_exists(vert_array[0], vert_array[1]))) {
2444  }
2445  else {
2446  ret = fallback;
2447  Py_INCREF(ret);
2448  }
2449 
2450  PyMem_FREE(vert_array);
2451  return ret;
2452 }
2453 
2454 PyDoc_STRVAR(bpy_bmfaceseq_get__method_doc,
2455  ".. method:: get(verts, fallback=None)\n"
2456  "\n"
2457  " Return a face which uses the **verts** passed.\n"
2458  "\n"
2459  " :arg verts: Sequence of verts.\n"
2460  " :type verts: :class:`BMVert`\n"
2461  " :arg fallback: Return this value if nothing is found.\n"
2462  " :return: The face found or None\n"
2463  " :rtype: :class:`BMFace`\n");
2464 static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
2465 {
2466  PyObject *vert_seq;
2467  PyObject *fallback = Py_None; /* optional */
2468 
2469  BPY_BM_CHECK_OBJ(self);
2470 
2471  if (!PyArg_ParseTuple(args, "O|O:faces.get", &vert_seq, &fallback)) {
2472  return NULL;
2473  }
2474 
2475  BMesh *bm = self->bm;
2476  BMFace *f = NULL;
2477  BMVert **vert_array = NULL;
2478  Py_ssize_t vert_seq_len;
2479  PyObject *ret = NULL;
2480 
2481  vert_array = BPy_BMElem_PySeq_As_Array(
2482  &bm, vert_seq, 1, PY_SSIZE_T_MAX, &vert_seq_len, BM_VERT, true, true, "faces.get(...)");
2483 
2484  if (vert_array == NULL) {
2485  return NULL;
2486  }
2487 
2488  f = BM_face_exists(vert_array, vert_seq_len);
2489  if (f != NULL) {
2491  }
2492  else {
2493  ret = fallback;
2494  Py_INCREF(ret);
2495  }
2496 
2497  PyMem_FREE(vert_array);
2498  return ret;
2499 }
2500 
2502  bpy_bmelemseq_index_update_doc,
2503  ".. method:: index_update()\n"
2504  "\n"
2505  " Initialize the index values of this sequence.\n"
2506  "\n"
2507  " This is the equivalent of looping over all elements and assigning the index values.\n"
2508  "\n"
2509  " .. code-block:: python\n"
2510  "\n"
2511  " for index, ele in enumerate(sequence):\n"
2512  " ele.index = index\n"
2513  "\n"
2514  " .. note::\n"
2515  "\n"
2516  " Running this on sequences besides :class:`BMesh.verts`, :class:`BMesh.edges`, "
2517  ":class:`BMesh.faces`\n"
2518  " works but won't result in each element having a valid index, instead its order in the "
2519  "sequence will be set.\n");
2521 {
2522  BMesh *bm = self->bm;
2523 
2524  BPY_BM_CHECK_OBJ(self);
2525 
2526  switch ((BMIterType)self->itype) {
2527  case BM_VERTS_OF_MESH:
2529  break;
2530  case BM_EDGES_OF_MESH:
2532  break;
2533  case BM_FACES_OF_MESH:
2535  break;
2536  default: {
2537  BMIter iter;
2538  BMElem *ele;
2539  int index = 0;
2540  const char htype = bm_iter_itype_htype_map[self->itype];
2541 
2542  BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
2543  BM_elem_index_set(ele, index); /* set_dirty! */
2544  index++;
2545  }
2546 
2547  /* since this isn't the normal vert/edge/face loops,
2548  * we're setting dirty values here. so tag as dirty. */
2549  bm->elem_index_dirty |= htype;
2550 
2551  break;
2552  }
2553  }
2554 
2555  Py_RETURN_NONE;
2556 }
2557 
2558 PyDoc_STRVAR(bpy_bmelemseq_ensure_lookup_table_doc,
2559  ".. method:: ensure_lookup_table()\n"
2560  "\n"
2561  " Ensure internal data needed for int subscription is initialized with "
2562  "verts/edges/faces, eg ``bm.verts[index]``.\n"
2563  "\n"
2564  " This needs to be called again after adding/removing data in this sequence.");
2566 {
2567  BPY_BM_CHECK_OBJ(self);
2568 
2570 
2571  Py_RETURN_NONE;
2572 }
2573 
2575  bpy_bmelemseq_sort_doc,
2576  ".. method:: sort(key=None, reverse=False)\n"
2577  "\n"
2578  " Sort the elements of this sequence, using an optional custom sort key.\n"
2579  " Indices of elements are not changed, BMElemeSeq.index_update() can be used for that.\n"
2580  "\n"
2581  " :arg key: The key that sets the ordering of the elements.\n"
2582  " :type key: :function: returning a number\n"
2583  " :arg reverse: Reverse the order of the elements\n"
2584  " :type reverse: :boolean:\n"
2585  "\n"
2586  " .. note::\n"
2587  "\n"
2588  " When the 'key' argument is not provided, the elements are reordered following their "
2589  "current index value.\n"
2590  " In particular this can be used by setting indices manually before calling this "
2591  "method.\n"
2592  "\n"
2593  " .. warning::\n"
2594  "\n"
2595  " Existing references to the N'th element, will continue to point the data at that "
2596  "index.\n");
2597 
2598 /* Use a static variable here because there is the need to sort some array
2599  * doing comparisons on elements of another array, qsort_r would have been
2600  * wonderful to use here, but unfortunately it is not standard and it's not
2601  * portable across different platforms.
2602  *
2603  * If a portable alternative to qsort_r becomes available, remove this static
2604  * var hack!
2605  *
2606  * NOTE: the functions below assumes the keys array has been allocated and it
2607  * has enough elements to complete the task.
2608  */
2609 
2610 static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v,
2611  const void *index2_v,
2612  void *keys_v)
2613 {
2614  const double *keys = keys_v;
2615  const int *index1 = (int *)index1_v;
2616  const int *index2 = (int *)index2_v;
2617 
2618  if (keys[*index1] < keys[*index2]) {
2619  return -1;
2620  }
2621  if (keys[*index1] > keys[*index2]) {
2622  return 1;
2623  }
2624 
2625  return 0;
2626 }
2627 
2628 static int bpy_bmelemseq_sort_cmp_by_keys_descending(const void *index1_v,
2629  const void *index2_v,
2630  void *keys_v)
2631 {
2632  return -bpy_bmelemseq_sort_cmp_by_keys_ascending(index1_v, index2_v, keys_v);
2633 }
2634 
2635 static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObject *kw)
2636 {
2637  static const char *kwlist[] = {"key", "reverse", NULL};
2638  PyObject *keyfunc = NULL; /* optional */
2639  bool do_reverse = false; /* optional */
2640 
2641  const char htype = bm_iter_itype_htype_map[self->itype];
2642  int n_elem;
2643 
2644  BMIter iter;
2645  BMElem *ele;
2646 
2647  double *keys;
2648  int *elem_idx;
2649  uint *elem_map_idx;
2650  int (*elem_idx_compare_by_keys)(const void *, const void *, void *);
2651 
2652  uint *vert_idx = NULL;
2653  uint *edge_idx = NULL;
2654  uint *face_idx = NULL;
2655  int i;
2656 
2657  BMesh *bm = self->bm;
2658 
2659  BPY_BM_CHECK_OBJ(self);
2660 
2661  if (args != NULL) {
2662  if (!PyArg_ParseTupleAndKeywords(args,
2663  kw,
2664  "|$OO&:BMElemSeq.sort",
2665  (char **)kwlist,
2666  &keyfunc,
2667  PyC_ParseBool,
2668  &do_reverse)) {
2669  return NULL;
2670  }
2671  }
2672 
2673  if (keyfunc != NULL && !PyCallable_Check(keyfunc)) {
2674  PyErr_SetString(PyExc_TypeError, "the 'key' argument is not a callable object");
2675  return NULL;
2676  }
2677 
2678  n_elem = BM_mesh_elem_count(bm, htype);
2679  if (n_elem <= 1) {
2680  /* 0 or 1 elements: sorted already */
2681  Py_RETURN_NONE;
2682  }
2683 
2684  keys = PyMem_MALLOC(sizeof(*keys) * n_elem);
2685  if (keys == NULL) {
2686  PyErr_NoMemory();
2687  return NULL;
2688  }
2689 
2690  i = 0;
2691  BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
2692  if (keyfunc != NULL) {
2693  PyObject *py_elem;
2694  PyObject *index;
2695 
2696  py_elem = BPy_BMElem_CreatePyObject(self->bm, (BMHeader *)ele);
2697  index = PyObject_CallFunctionObjArgs(keyfunc, py_elem, NULL);
2698  Py_DECREF(py_elem);
2699  if (index == NULL) {
2700  /* No need to set the exception here,
2701  * PyObject_CallFunctionObjArgs() does that */
2702  PyMem_FREE(keys);
2703  return NULL;
2704  }
2705 
2706  if ((keys[i] = PyFloat_AsDouble(index)) == -1 && PyErr_Occurred()) {
2707  PyErr_SetString(PyExc_ValueError,
2708  "the value returned by the 'key' function is not a number");
2709  Py_DECREF(index);
2710  PyMem_FREE(keys);
2711  return NULL;
2712  }
2713 
2714  Py_DECREF(index);
2715  }
2716  else {
2717  /* If the 'key' function is not provided we sort
2718  * according to the current index values */
2719  keys[i] = ele->head.index;
2720  }
2721 
2722  i++;
2723  }
2724 
2725  elem_idx = PyMem_MALLOC(sizeof(*elem_idx) * n_elem);
2726  if (elem_idx == NULL) {
2727  PyErr_NoMemory();
2728  PyMem_FREE(keys);
2729  return NULL;
2730  }
2731 
2732  /* Initialize the element index array */
2733  range_vn_i(elem_idx, n_elem, 0);
2734 
2735  /* Sort the index array according to the order of the 'keys' array */
2736  if (do_reverse) {
2737  elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_descending;
2738  }
2739  else {
2740  elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_ascending;
2741  }
2742 
2743  BLI_qsort_r(elem_idx, n_elem, sizeof(*elem_idx), elem_idx_compare_by_keys, keys);
2744 
2745  elem_map_idx = PyMem_MALLOC(sizeof(*elem_map_idx) * n_elem);
2746  if (elem_map_idx == NULL) {
2747  PyErr_NoMemory();
2748  PyMem_FREE(elem_idx);
2749  PyMem_FREE(keys);
2750  return NULL;
2751  }
2752 
2753  /* Initialize the map array
2754  *
2755  * We need to know the index such that if used as the new_index in
2756  * BM_mesh_remap() will give the order of the sorted keys like in
2757  * elem_idx */
2758  for (i = 0; i < n_elem; i++) {
2759  elem_map_idx[elem_idx[i]] = i;
2760  }
2761 
2762  switch ((BMIterType)self->itype) {
2763  case BM_VERTS_OF_MESH:
2764  vert_idx = elem_map_idx;
2765  break;
2766  case BM_EDGES_OF_MESH:
2767  edge_idx = elem_map_idx;
2768  break;
2769  case BM_FACES_OF_MESH:
2770  face_idx = elem_map_idx;
2771  break;
2772  default:
2773  PyErr_Format(PyExc_TypeError, "element type %d not supported", self->itype);
2774  PyMem_FREE(elem_map_idx);
2775  PyMem_FREE(elem_idx);
2776  PyMem_FREE(keys);
2777  return NULL;
2778  }
2779 
2780  BM_mesh_remap(bm, vert_idx, edge_idx, face_idx);
2781 
2782  PyMem_FREE(elem_map_idx);
2783  PyMem_FREE(elem_idx);
2784  PyMem_FREE(keys);
2785 
2786  Py_RETURN_NONE;
2787 }
2788 
2789 static struct PyMethodDef bpy_bmesh_methods[] = {
2790  /* utility */
2791  {"copy", (PyCFunction)bpy_bmesh_copy, METH_NOARGS, bpy_bmesh_copy_doc},
2792  {"clear", (PyCFunction)bpy_bmesh_clear, METH_NOARGS, bpy_bmesh_clear_doc},
2793  {"free", (PyCFunction)bpy_bmesh_free, METH_NOARGS, bpy_bmesh_free_doc},
2794 
2795  /* conversion */
2796  {"from_object",
2797  (PyCFunction)bpy_bmesh_from_object,
2798  METH_VARARGS | METH_KEYWORDS,
2799  bpy_bmesh_from_object_doc},
2800  {"from_mesh",
2801  (PyCFunction)bpy_bmesh_from_mesh,
2802  METH_VARARGS | METH_KEYWORDS,
2803  bpy_bmesh_from_mesh_doc},
2804  {"to_mesh", (PyCFunction)bpy_bmesh_to_mesh, METH_VARARGS, bpy_bmesh_to_mesh_doc},
2805 
2806  /* meshdata */
2807  {"select_flush_mode",
2808  (PyCFunction)bpy_bmesh_select_flush_mode,
2809  METH_NOARGS,
2810  bpy_bmesh_select_flush_mode_doc},
2811  {"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
2812  {"normal_update",
2813  (PyCFunction)bpy_bmesh_normal_update,
2814  METH_NOARGS,
2815  bpy_bmesh_normal_update_doc},
2816  {"transform",
2817  (PyCFunction)bpy_bmesh_transform,
2818  METH_VARARGS | METH_KEYWORDS,
2819  bpy_bmesh_transform_doc},
2820 
2821  /* calculations */
2822  {"calc_volume",
2823  (PyCFunction)bpy_bmesh_calc_volume,
2824  METH_VARARGS | METH_KEYWORDS,
2825  bpy_bmesh_calc_volume_doc},
2826  {"calc_loop_triangles",
2827  (PyCFunction)bpy_bmesh_calc_loop_triangles,
2828  METH_NOARGS,
2829  bpy_bmesh_calc_loop_triangles_doc},
2830  {NULL, NULL, 0, NULL},
2831 };
2832 
2833 static struct PyMethodDef bpy_bmvert_methods[] = {
2834  {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2835  {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2836  {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2837  {"copy_from_face_interp",
2838  (PyCFunction)bpy_bmvert_copy_from_face_interp,
2839  METH_VARARGS,
2840  bpy_bmvert_copy_from_face_interp_doc},
2841  {"copy_from_vert_interp",
2842  (PyCFunction)bpy_bmvert_copy_from_vert_interp,
2843  METH_VARARGS,
2844  bpy_bmvert_copy_from_vert_interp_doc},
2845 
2846  {"calc_edge_angle",
2847  (PyCFunction)bpy_bmvert_calc_edge_angle,
2848  METH_VARARGS,
2849  bpy_bmvert_calc_edge_angle_doc},
2850  {"calc_shell_factor",
2851  (PyCFunction)bpy_bmvert_calc_shell_factor,
2852  METH_NOARGS,
2853  bpy_bmvert_calc_shell_factor_doc},
2854 
2855  {"normal_update",
2856  (PyCFunction)bpy_bmvert_normal_update,
2857  METH_NOARGS,
2858  bpy_bmvert_normal_update_doc},
2859 
2860  {NULL, NULL, 0, NULL},
2861 };
2862 
2863 static struct PyMethodDef bpy_bmedge_methods[] = {
2864  {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2865  {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2866  {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2867 
2868  {"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
2869 
2870  {"calc_length", (PyCFunction)bpy_bmedge_calc_length, METH_NOARGS, bpy_bmedge_calc_length_doc},
2871  {"calc_face_angle",
2872  (PyCFunction)bpy_bmedge_calc_face_angle,
2873  METH_VARARGS,
2874  bpy_bmedge_calc_face_angle_doc},
2875  {"calc_face_angle_signed",
2876  (PyCFunction)bpy_bmedge_calc_face_angle_signed,
2877  METH_VARARGS,
2878  bpy_bmedge_calc_face_angle_signed_doc},
2879  {"calc_tangent",
2880  (PyCFunction)bpy_bmedge_calc_tangent,
2881  METH_VARARGS,
2882  bpy_bmedge_calc_tangent_doc},
2883 
2884  {"normal_update",
2885  (PyCFunction)bpy_bmedge_normal_update,
2886  METH_NOARGS,
2887  bpy_bmedge_normal_update_doc},
2888 
2889  {NULL, NULL, 0, NULL},
2890 };
2891 
2892 static struct PyMethodDef bpy_bmface_methods[] = {
2893  {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2894  {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2895 
2896  {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2897  {"copy_from_face_interp",
2898  (PyCFunction)bpy_bmface_copy_from_face_interp,
2899  METH_O,
2900  bpy_bmface_copy_from_face_interp_doc},
2901 
2902  {"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS | METH_KEYWORDS, bpy_bmface_copy_doc},
2903 
2904  {"calc_area", (PyCFunction)bpy_bmface_calc_area, METH_NOARGS, bpy_bmface_calc_area_doc},
2905  {"calc_perimeter",
2906  (PyCFunction)bpy_bmface_calc_perimeter,
2907  METH_NOARGS,
2908  bpy_bmface_calc_perimeter_doc},
2909  {"calc_tangent_edge",
2910  (PyCFunction)bpy_bmface_calc_tangent_edge,
2911  METH_NOARGS,
2912  bpy_bmface_calc_tangent_edge_doc},
2913  {"calc_tangent_edge_pair",
2914  (PyCFunction)bpy_bmface_calc_tangent_edge_pair,
2915  METH_NOARGS,
2916  bpy_bmface_calc_tangent_edge_pair_doc},
2917  {"calc_tangent_edge_diagonal",
2919  METH_NOARGS,
2920  bpy_bmface_calc_tangent_edge_diagonal_doc},
2921  {"calc_tangent_vert_diagonal",
2923  METH_NOARGS,
2924  bpy_bmface_calc_tangent_vert_diagonal_doc},
2925  {"calc_center_median",
2926  (PyCFunction)bpy_bmface_calc_center_mean,
2927  METH_NOARGS,
2928  bpy_bmface_calc_center_median_doc},
2929  {"calc_center_median_weighted",
2931  METH_NOARGS,
2932  bpy_bmface_calc_center_median_weighted_doc},
2933  {"calc_center_bounds",
2934  (PyCFunction)bpy_bmface_calc_center_bounds,
2935  METH_NOARGS,
2936  bpy_bmface_calc_center_bounds_doc},
2937 
2938  {"normal_update",
2939  (PyCFunction)bpy_bmface_normal_update,
2940  METH_NOARGS,
2941  bpy_bmface_normal_update_doc},
2942  {"normal_flip", (PyCFunction)bpy_bmface_normal_flip, METH_NOARGS, bpy_bmface_normal_flip_doc},
2943 
2944  {NULL, NULL, 0, NULL},
2945 };
2946 
2947 static struct PyMethodDef bpy_bmloop_methods[] = {
2948  {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2949  {"copy_from_face_interp",
2950  (PyCFunction)bpy_bmloop_copy_from_face_interp,
2951  METH_O,
2952  bpy_bmloop_copy_from_face_interp_doc},
2953 
2954  {"calc_angle", (PyCFunction)bpy_bmloop_calc_angle, METH_NOARGS, bpy_bmloop_calc_angle_doc},
2955  {"calc_normal", (PyCFunction)bpy_bmloop_calc_normal, METH_NOARGS, bpy_bmloop_calc_normal_doc},
2956  {"calc_tangent",
2957  (PyCFunction)bpy_bmloop_calc_tangent,
2958  METH_NOARGS,
2959  bpy_bmloop_calc_tangent_doc},
2960  {NULL, NULL, 0, NULL},
2961 };
2962 
2963 static struct PyMethodDef bpy_bmelemseq_methods[] = {
2964  /* odd function, initializes index values */
2965  {"index_update",
2966  (PyCFunction)bpy_bmelemseq_index_update,
2967  METH_NOARGS,
2968  bpy_bmelemseq_index_update_doc},
2969  {NULL, NULL, 0, NULL},
2970 };
2971 
2972 static struct PyMethodDef bpy_bmvertseq_methods[] = {
2973  {"new", (PyCFunction)bpy_bmvertseq_new, METH_VARARGS, bpy_bmvertseq_new_doc},
2974  {"remove", (PyCFunction)bpy_bmvertseq_remove, METH_O, bpy_bmvertseq_remove_doc},
2975 
2976  /* odd function, initializes index values */
2977  {"index_update",
2978  (PyCFunction)bpy_bmelemseq_index_update,
2979  METH_NOARGS,
2980  bpy_bmelemseq_index_update_doc},
2981  {"ensure_lookup_table",
2982  (PyCFunction)bpy_bmelemseq_ensure_lookup_table,
2983  METH_NOARGS,
2984  bpy_bmelemseq_ensure_lookup_table_doc},
2985  {"sort",
2986  (PyCFunction)bpy_bmelemseq_sort,
2987  METH_VARARGS | METH_KEYWORDS,
2988  bpy_bmelemseq_sort_doc},
2989  {NULL, NULL, 0, NULL},
2990 };
2991 
2992 static struct PyMethodDef bpy_bmedgeseq_methods[] = {
2993  {"new", (PyCFunction)bpy_bmedgeseq_new, METH_VARARGS, bpy_bmedgeseq_new_doc},
2994  {"remove", (PyCFunction)bpy_bmedgeseq_remove, METH_O, bpy_bmedgeseq_remove_doc},
2995  /* 'bpy_bmelemseq_get' for different purpose */
2996  {"get", (PyCFunction)bpy_bmedgeseq_get__method, METH_VARARGS, bpy_bmedgeseq_get__method_doc},
2997 
2998  /* odd function, initializes index values */
2999  {"index_update",
3000  (PyCFunction)bpy_bmelemseq_index_update,
3001  METH_NOARGS,
3002  bpy_bmelemseq_index_update_doc},
3003  {"ensure_lookup_table",
3004  (PyCFunction)bpy_bmelemseq_ensure_lookup_table,
3005  METH_NOARGS,
3006  bpy_bmelemseq_ensure_lookup_table_doc},
3007  {"sort",
3008  (PyCFunction)bpy_bmelemseq_sort,
3009  METH_VARARGS | METH_KEYWORDS,
3010  bpy_bmelemseq_sort_doc},
3011  {NULL, NULL, 0, NULL},
3012 };
3013 
3014 static struct PyMethodDef bpy_bmfaceseq_methods[] = {
3015  {"new", (PyCFunction)bpy_bmfaceseq_new, METH_VARARGS, bpy_bmfaceseq_new_doc},
3016  {"remove", (PyCFunction)bpy_bmfaceseq_remove, METH_O, bpy_bmfaceseq_remove_doc},
3017  /* 'bpy_bmelemseq_get' for different purpose */
3018  {"get", (PyCFunction)bpy_bmfaceseq_get__method, METH_VARARGS, bpy_bmfaceseq_get__method_doc},
3019 
3020  /* odd function, initializes index values */
3021  {"index_update",
3022  (PyCFunction)bpy_bmelemseq_index_update,
3023  METH_NOARGS,
3024  bpy_bmelemseq_index_update_doc},
3025  {"ensure_lookup_table",
3026  (PyCFunction)bpy_bmelemseq_ensure_lookup_table,
3027  METH_NOARGS,
3028  bpy_bmelemseq_ensure_lookup_table_doc},
3029  {"sort",
3030  (PyCFunction)bpy_bmelemseq_sort,
3031  METH_VARARGS | METH_KEYWORDS,
3032  bpy_bmelemseq_sort_doc},
3033  {NULL, NULL, 0, NULL},
3034 };
3035 
3036 static struct PyMethodDef bpy_bmloopseq_methods[] = {
3037  /* odd function, initializes index values */
3038  /* no: index_update() function since we can't iterate over loops */
3039  /* no: sort() function since we can't iterate over loops */
3040  {NULL, NULL, 0, NULL},
3041 };
3042 
3043 /* Sequences
3044  * ========= */
3045 
3046 /* BMElemSeq / Iter
3047  * ---------------- */
3048 
3049 static PyTypeObject *bpy_bm_itype_as_pytype(const char itype)
3050 {
3051  /* should cover all types */
3052  switch ((BMIterType)itype) {
3053  case BM_VERTS_OF_MESH:
3054  case BM_VERTS_OF_FACE:
3055  case BM_VERTS_OF_EDGE:
3056  return &BPy_BMVert_Type;
3057 
3058  case BM_EDGES_OF_MESH:
3059  case BM_EDGES_OF_FACE:
3060  case BM_EDGES_OF_VERT:
3061  return &BPy_BMEdge_Type;
3062 
3063  case BM_FACES_OF_MESH:
3064  case BM_FACES_OF_EDGE:
3065  case BM_FACES_OF_VERT:
3066  return &BPy_BMFace_Type;
3067 
3068  // case BM_ALL_LOOPS_OF_FACE:
3069  case BM_LOOPS_OF_FACE:
3070  case BM_LOOPS_OF_EDGE:
3071  case BM_LOOPS_OF_VERT:
3072  case BM_LOOPS_OF_LOOP:
3073  return &BPy_BMLoop_Type;
3074  }
3075 
3076  return NULL;
3077 }
3078 
3079 static Py_ssize_t bpy_bmelemseq_length(BPy_BMElemSeq *self)
3080 {
3081  BPY_BM_CHECK_INT(self);
3082 
3083  /* first check if the size is known */
3084  switch ((BMIterType)self->itype) {
3085  /* main-types */
3086  case BM_VERTS_OF_MESH:
3087  return self->bm->totvert;
3088  case BM_EDGES_OF_MESH:
3089  return self->bm->totedge;
3090  case BM_FACES_OF_MESH:
3091  return self->bm->totface;
3092 
3093  /* sub-types */
3094  case BM_VERTS_OF_FACE:
3095  case BM_EDGES_OF_FACE:
3096  case BM_LOOPS_OF_FACE:
3097  BPY_BM_CHECK_INT(self->py_ele);
3098  return ((BMFace *)self->py_ele->ele)->len;
3099 
3100  case BM_VERTS_OF_EDGE:
3101  return 2;
3102 
3103  default:
3104  /* quiet compiler */
3105  break;
3106  }
3107 
3108  /* loop over all items, avoid this if we can */
3109  {
3110  BMIter iter;
3111  BMHeader *ele;
3112  Py_ssize_t tot = 0;
3113 
3114  BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
3115  tot++;
3116  }
3117  return tot;
3118  }
3119 }
3120 
3121 static PyObject *bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
3122 {
3123  BPY_BM_CHECK_OBJ(self);
3124 
3125  if (keynum < 0) {
3126  /* only get length on negative value, may loop entire seq */
3127  keynum += bpy_bmelemseq_length(self);
3128  }
3129  if (keynum >= 0) {
3130  if (self->itype <= BM_FACES_OF_MESH) {
3131  if ((self->bm->elem_table_dirty & bm_iter_itype_htype_map[self->itype]) == 0) {
3132  BMHeader *ele = NULL;
3133  switch (self->itype) {
3134  case BM_VERTS_OF_MESH:
3135  if (keynum < self->bm->totvert) {
3136  ele = (BMHeader *)self->bm->vtable[keynum];
3137  }
3138  break;
3139  case BM_EDGES_OF_MESH:
3140  if (keynum < self->bm->totedge) {
3141  ele = (BMHeader *)self->bm->etable[keynum];
3142  }
3143  break;
3144  case BM_FACES_OF_MESH:
3145  if (keynum < self->bm->totface) {
3146  ele = (BMHeader *)self->bm->ftable[keynum];
3147  }
3148  break;
3149  }
3150  if (ele) {
3151  return BPy_BMElem_CreatePyObject(self->bm, ele);
3152  }
3153  /* fall through to index error below */
3154  }
3155  else {
3156  PyErr_SetString(PyExc_IndexError,
3157  "BMElemSeq[index]: outdated internal index table, "
3158  "run ensure_lookup_table() first");
3159  return NULL;
3160  }
3161  }
3162  else {
3163  BMHeader *ele = BM_iter_at_index(
3164  self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
3165  if (ele) {
3166  return BPy_BMElem_CreatePyObject(self->bm, ele);
3167  }
3168  }
3169  }
3170 
3171  PyErr_Format(PyExc_IndexError, "BMElemSeq[index]: index %d out of range", keynum);
3172  return NULL;
3173 }
3174 
3176  Py_ssize_t start,
3177  Py_ssize_t stop)
3178 {
3179  BMIter iter;
3180  int count = 0;
3181  bool ok;
3182 
3183  PyObject *list;
3184  BMHeader *ele;
3185 
3186  BPY_BM_CHECK_OBJ(self);
3187 
3188  list = PyList_New(0);
3189 
3190  ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
3191 
3192  BLI_assert(ok == true);
3193 
3194  if (UNLIKELY(ok == false)) {
3195  return list;
3196  }
3197 
3198  /* first loop up-until the start */
3199  for (ok = true; ok; ok = (BM_iter_step(&iter) != NULL)) {
3200  if (count == start) {
3201  break;
3202  }
3203  count++;
3204  }
3205 
3206  /* add items until stop */
3207  while ((ele = BM_iter_step(&iter))) {
3208  PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, ele));
3209 
3210  count++;
3211  if (count == stop) {
3212  break;
3213  }
3214  }
3215 
3216  return list;
3217 }
3218 
3219 static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key)
3220 {
3221  /* don't need error check here */
3222  if (PyIndex_Check(key)) {
3223  const Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
3224  if (i == -1 && PyErr_Occurred()) {
3225  return NULL;
3226  }
3227  return bpy_bmelemseq_subscript_int(self, i);
3228  }
3229  if (PySlice_Check(key)) {
3230  PySliceObject *key_slice = (PySliceObject *)key;
3231  Py_ssize_t step = 1;
3232 
3233  if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
3234  return NULL;
3235  }
3236  if (step != 1) {
3237  PyErr_SetString(PyExc_TypeError, "BMElemSeq[slice]: slice steps not supported");
3238  return NULL;
3239  }
3240  if (key_slice->start == Py_None && key_slice->stop == Py_None) {
3241  return bpy_bmelemseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
3242  }
3243 
3244  Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
3245 
3246  /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
3247  if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) {
3248  return NULL;
3249  }
3250  if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) {
3251  return NULL;
3252  }
3253 
3254  if (start < 0 || stop < 0) {
3255  /* only get the length for negative values */
3256  const Py_ssize_t len = bpy_bmelemseq_length(self);
3257  if (start < 0) {
3258  start += len;
3259  CLAMP_MIN(start, 0);
3260  }
3261  if (stop < 0) {
3262  stop += len;
3263  CLAMP_MIN(stop, 0);
3264  }
3265  }
3266 
3267  if (stop - start <= 0) {
3268  return PyList_New(0);
3269  }
3270 
3271  return bpy_bmelemseq_subscript_slice(self, start, stop);
3272  }
3273 
3274  PyErr_SetString(PyExc_AttributeError, "BMElemSeq[key]: invalid key, key must be an int");
3275  return NULL;
3276 }
3277 
3278 static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
3279 {
3280  BPY_BM_CHECK_INT(self);
3281 
3282  if (Py_TYPE(value) == bpy_bm_itype_as_pytype(self->itype)) {
3283  BPy_BMElem *value_bm_ele = (BPy_BMElem *)value;
3284  if (value_bm_ele->bm == self->bm) {
3285  BMElem *ele, *ele_test = value_bm_ele->ele;
3286  BMIter iter;
3287  BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
3288  if (ele == ele_test) {
3289  return 1;
3290  }
3291  }
3292  }
3293  }
3294 
3295  return 0;
3296 }
3297 
3298 /* BMElem (customdata)
3299  * ------------------- */
3300 
3301 static PyObject *bpy_bmelem_subscript(BPy_BMElem *self, BPy_BMLayerItem *key)
3302 {
3303  BPY_BM_CHECK_OBJ(self);
3304 
3305  return BPy_BMLayerItem_GetItem(self, key);
3306 }
3307 
3308 static int bpy_bmelem_ass_subscript(BPy_BMElem *self, BPy_BMLayerItem *key, PyObject *value)
3309 {
3310  BPY_BM_CHECK_INT(self);
3311 
3312  return BPy_BMLayerItem_SetItem(self, key, value);
3313 }
3314 
3315 static PySequenceMethods bpy_bmelemseq_as_sequence = {
3316  (lenfunc)bpy_bmelemseq_length, /* sq_length */
3317  NULL, /* sq_concat */
3318  NULL, /* sq_repeat */
3319  (ssizeargfunc)bpy_bmelemseq_subscript_int,
3320  /* sq_item */ /* Only set this so PySequence_Check() returns True */
3321  NULL, /* sq_slice */
3322  (ssizeobjargproc)NULL, /* sq_ass_item */
3323  NULL, /* *was* sq_ass_slice */
3324  (objobjproc)bpy_bmelemseq_contains, /* sq_contains */
3325  (binaryfunc)NULL, /* sq_inplace_concat */
3326  (ssizeargfunc)NULL, /* sq_inplace_repeat */
3327 };
3328 
3329 static PyMappingMethods bpy_bmelemseq_as_mapping = {
3330  (lenfunc)bpy_bmelemseq_length, /* mp_length */
3331  (binaryfunc)bpy_bmelemseq_subscript, /* mp_subscript */
3332  (objobjargproc)NULL, /* mp_ass_subscript */
3333 };
3334 
3335 /* for customdata access */
3336 static PyMappingMethods bpy_bm_elem_as_mapping = {
3337  (lenfunc)NULL,
3338  /* mp_length */ /* keep this empty, messes up 'if elem: ...' test */
3339  (binaryfunc)bpy_bmelem_subscript, /* mp_subscript */
3340  (objobjargproc)bpy_bmelem_ass_subscript, /* mp_ass_subscript */
3341 };
3342 
3343 /* Iterator
3344  * -------- */
3345 
3346 static PyObject *bpy_bmelemseq_iter(BPy_BMElemSeq *self)
3347 {
3348  BPy_BMIter *py_iter;
3349 
3350  BPY_BM_CHECK_OBJ(self);
3351  py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
3352  BM_iter_init(&(py_iter->iter), self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
3353  return (PyObject *)py_iter;
3354 }
3355 
3356 static PyObject *bpy_bmiter_next(BPy_BMIter *self)
3357 {
3358  BMHeader *ele = BM_iter_step(&self->iter);
3359  if (ele == NULL) {
3360  PyErr_SetNone(PyExc_StopIteration);
3361  return NULL;
3362  }
3363 
3364  return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, ele);
3365 }
3366 
3367 /* Deallocate Functions
3368  * ==================== */
3369 
3370 static void bpy_bmesh_dealloc(BPy_BMesh *self)
3371 {
3372  BMesh *bm = self->bm;
3373 
3374  /* The mesh has not been freed by #BMesh. */
3375  if (bm) {
3377 
3380  }
3383  }
3386  }
3389  }
3390 
3391  bm->py_handle = NULL;
3392 
3393  if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
3394  BM_mesh_free(bm);
3395  }
3396  }
3397 
3398  PyObject_DEL(self);
3399 }
3400 
3401 static void bpy_bmvert_dealloc(BPy_BMElem *self)
3402 {
3403  BMesh *bm = self->bm;
3404  if (bm) {
3405  void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
3406  if (ptr) {
3407  *ptr = NULL;
3408  }
3409  }
3410  PyObject_DEL(self);
3411 }
3412 
3413 static void bpy_bmedge_dealloc(BPy_BMElem *self)
3414 {
3415  BMesh *bm = self->bm;
3416  if (bm) {
3417  void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->head.data, CD_BM_ELEM_PYPTR);
3418  if (ptr) {
3419  *ptr = NULL;
3420  }
3421  }
3422  PyObject_DEL(self);
3423 }
3424 
3425 static void bpy_bmface_dealloc(BPy_BMElem *self)
3426 {
3427  BMesh *bm = self->bm;
3428  if (bm) {
3429  void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
3430  if (ptr) {
3431  *ptr = NULL;
3432  }
3433  }
3434  PyObject_DEL(self);
3435 }
3436 
3437 static void bpy_bmloop_dealloc(BPy_BMElem *self)
3438 {
3439  BMesh *bm = self->bm;
3440  if (bm) {
3441  void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->head.data, CD_BM_ELEM_PYPTR);
3442  if (ptr) {
3443  *ptr = NULL;
3444  }
3445  }
3446  PyObject_DEL(self);
3447 }
3448 
3450 {
3451  Py_XDECREF(self->py_ele);
3452 
3453  PyObject_DEL(self);
3454 }
3455 
3456 /* not sure where this should go */
3457 static Py_hash_t bpy_bm_elem_hash(PyObject *self)
3458 {
3459  return _Py_HashPointer(((BPy_BMElem *)self)->ele);
3460 }
3461 
3462 static Py_hash_t bpy_bm_hash(PyObject *self)
3463 {
3464  return _Py_HashPointer(((BPy_BMesh *)self)->bm);
3465 }
3466 
3467 /* Type Docstrings
3468  * =============== */
3469 
3470 PyDoc_STRVAR(bpy_bmesh_doc, "The BMesh data structure\n");
3471 PyDoc_STRVAR(bpy_bmvert_doc, "The BMesh vertex type\n");
3472 PyDoc_STRVAR(bpy_bmedge_doc, "The BMesh edge connecting 2 verts\n");
3473 PyDoc_STRVAR(bpy_bmface_doc, "The BMesh face with 3 or more sides\n");
3474 PyDoc_STRVAR(bpy_bmloop_doc,
3475  "This is normally accessed from :class:`BMFace.loops` where each face loop "
3476  "represents a corner of the face.\n");
3477 PyDoc_STRVAR(bpy_bmelemseq_doc,
3478  "General sequence type used for accessing any sequence of\n"
3479  ":class:`BMVert`, :class:`BMEdge`, :class:`BMFace`, :class:`BMLoop`.\n"
3480  "\n"
3481  "When accessed via :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces`\n"
3482  "there are also functions to create/remove items.\n");
3483 PyDoc_STRVAR(bpy_bmiter_doc,
3484  "Internal BMesh type for looping over verts/faces/edges,\n"
3485  "used for iterating over :class:`BMElemSeq` types.\n");
3486 
3487 static PyObject *bpy_bmesh_repr(BPy_BMesh *self)
3488 {
3489  BMesh *bm = self->bm;
3490 
3491  if (bm) {
3492  return PyUnicode_FromFormat("<BMesh(%p), totvert=%d, totedge=%d, totface=%d, totloop=%d>",
3493  bm,
3494  bm->totvert,
3495  bm->totedge,
3496  bm->totface,
3497  bm->totloop);
3498  }
3499 
3500  return PyUnicode_FromFormat("<BMesh dead at %p>", self);
3501 }
3502 
3503 static PyObject *bpy_bmvert_repr(BPy_BMVert *self)
3504 {
3505  BMesh *bm = self->bm;
3506 
3507  if (bm) {
3508  BMVert *v = self->v;
3509  return PyUnicode_FromFormat("<BMVert(%p), index=%d>", v, BM_elem_index_get(v));
3510  }
3511 
3512  return PyUnicode_FromFormat("<BMVert dead at %p>", self);
3513 }
3514 
3515 static PyObject *bpy_bmedge_repr(BPy_BMEdge *self)
3516 {
3517  BMesh *bm = self->bm;
3518 
3519  if (bm) {
3520  BMEdge *e = self->e;
3521  return PyUnicode_FromFormat("<BMEdge(%p), index=%d, verts=(%p/%d, %p/%d)>",
3522  e,
3524  e->v1,
3525  BM_elem_index_get(e->v1),
3526  e->v2,
3527  BM_elem_index_get(e->v2));
3528  }
3529 
3530  return PyUnicode_FromFormat("<BMEdge dead at %p>", self);
3531 }
3532 
3533 static PyObject *bpy_bmface_repr(BPy_BMFace *self)
3534 {
3535  BMesh *bm = self->bm;
3536 
3537  if (bm) {
3538  BMFace *f = self->f;
3539  return PyUnicode_FromFormat(
3540  "<BMFace(%p), index=%d, totverts=%d>", f, BM_elem_index_get(f), f->len);
3541  }
3542 
3543  return PyUnicode_FromFormat("<BMFace dead at %p>", self);
3544 }
3545 
3546 static PyObject *bpy_bmloop_repr(BPy_BMLoop *self)
3547 {
3548  BMesh *bm = self->bm;
3549 
3550  if (bm) {
3551  BMLoop *l = self->l;
3552  return PyUnicode_FromFormat("<BMLoop(%p), index=%d, vert=%p/%d, edge=%p/%d, face=%p/%d>",
3553  l,
3555  l->v,
3556  BM_elem_index_get(l->v),
3557  l->e,
3558  BM_elem_index_get(l->e),
3559  l->f,
3560  BM_elem_index_get(l->f));
3561  }
3562 
3563  return PyUnicode_FromFormat("<BMLoop dead at %p>", self);
3564 }
3565 
3566 /* Types
3567  * ===== */
3568 
3569 PyTypeObject BPy_BMesh_Type;
3570 PyTypeObject BPy_BMVert_Type;
3571 PyTypeObject BPy_BMEdge_Type;
3572 PyTypeObject BPy_BMFace_Type;
3573 PyTypeObject BPy_BMLoop_Type;
3574 PyTypeObject BPy_BMElemSeq_Type;
3575 PyTypeObject BPy_BMVertSeq_Type;
3576 PyTypeObject BPy_BMEdgeSeq_Type;
3577 PyTypeObject BPy_BMFaceSeq_Type;
3578 PyTypeObject BPy_BMLoopSeq_Type;
3579 PyTypeObject BPy_BMIter_Type;
3580 
3582 {
3583  BPy_BMesh_Type.tp_basicsize = sizeof(BPy_BMesh);
3584  BPy_BMVert_Type.tp_basicsize = sizeof(BPy_BMVert);
3585  BPy_BMEdge_Type.tp_basicsize = sizeof(BPy_BMEdge);
3586  BPy_BMFace_Type.tp_basicsize = sizeof(BPy_BMFace);
3587  BPy_BMLoop_Type.tp_basicsize = sizeof(BPy_BMLoop);
3588  BPy_BMElemSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
3589  BPy_BMVertSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
3590  BPy_BMEdgeSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
3591  BPy_BMFaceSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
3592  BPy_BMLoopSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
3593  BPy_BMIter_Type.tp_basicsize = sizeof(BPy_BMIter);
3594 
3595  BPy_BMesh_Type.tp_name = "BMesh";
3596  BPy_BMVert_Type.tp_name = "BMVert";
3597  BPy_BMEdge_Type.tp_name = "BMEdge";
3598  BPy_BMFace_Type.tp_name = "BMFace";
3599  BPy_BMLoop_Type.tp_name = "BMLoop";
3600  BPy_BMElemSeq_Type.tp_name = "BMElemSeq";
3601  BPy_BMVertSeq_Type.tp_name = "BMVertSeq";
3602  BPy_BMEdgeSeq_Type.tp_name = "BMEdgeSeq";
3603  BPy_BMFaceSeq_Type.tp_name = "BMFaceSeq";
3604  BPy_BMLoopSeq_Type.tp_name = "BMLoopSeq";
3605  BPy_BMIter_Type.tp_name = "BMIter";
3606 
3607  BPy_BMesh_Type.tp_doc = bpy_bmesh_doc;
3608  BPy_BMVert_Type.tp_doc = bpy_bmvert_doc;
3609  BPy_BMEdge_Type.tp_doc = bpy_bmedge_doc;
3610  BPy_BMFace_Type.tp_doc = bpy_bmface_doc;
3611  BPy_BMLoop_Type.tp_doc = bpy_bmloop_doc;
3612  BPy_BMElemSeq_Type.tp_doc = bpy_bmelemseq_doc;
3613  BPy_BMVertSeq_Type.tp_doc = NULL;
3614  BPy_BMEdgeSeq_Type.tp_doc = NULL;
3615  BPy_BMFaceSeq_Type.tp_doc = NULL;
3616  BPy_BMLoopSeq_Type.tp_doc = NULL;
3617  BPy_BMIter_Type.tp_doc = bpy_bmiter_doc;
3618 
3619  BPy_BMesh_Type.tp_repr = (reprfunc)bpy_bmesh_repr;
3620  BPy_BMVert_Type.tp_repr = (reprfunc)bpy_bmvert_repr;
3621  BPy_BMEdge_Type.tp_repr = (reprfunc)bpy_bmedge_repr;
3622  BPy_BMFace_Type.tp_repr = (reprfunc)bpy_bmface_repr;
3623  BPy_BMLoop_Type.tp_repr = (reprfunc)bpy_bmloop_repr;
3624  BPy_BMElemSeq_Type.tp_repr = NULL;
3625  BPy_BMVertSeq_Type.tp_repr = NULL;
3626  BPy_BMEdgeSeq_Type.tp_repr = NULL;
3627  BPy_BMFaceSeq_Type.tp_repr = NULL;
3628  BPy_BMLoopSeq_Type.tp_repr = NULL;
3629  BPy_BMIter_Type.tp_repr = NULL;
3630 
3631  BPy_BMesh_Type.tp_getset = bpy_bmesh_getseters;
3636  BPy_BMElemSeq_Type.tp_getset = NULL;
3641  BPy_BMIter_Type.tp_getset = NULL;
3642 
3643  BPy_BMesh_Type.tp_methods = bpy_bmesh_methods;
3644  BPy_BMVert_Type.tp_methods = bpy_bmvert_methods;
3645  BPy_BMEdge_Type.tp_methods = bpy_bmedge_methods;
3646  BPy_BMFace_Type.tp_methods = bpy_bmface_methods;
3647  BPy_BMLoop_Type.tp_methods = bpy_bmloop_methods;
3653  BPy_BMIter_Type.tp_methods = NULL;
3654 
3655  /* #BPy_BMElem_Check() uses #bpy_bm_elem_hash() to check types.
3656  * if this changes update the macro. */
3657  BPy_BMesh_Type.tp_hash = bpy_bm_hash;
3662  BPy_BMElemSeq_Type.tp_hash = NULL;
3663  BPy_BMVertSeq_Type.tp_hash = NULL;
3664  BPy_BMEdgeSeq_Type.tp_hash = NULL;
3665  BPy_BMFaceSeq_Type.tp_hash = NULL;
3666  BPy_BMLoopSeq_Type.tp_hash = NULL;
3667  BPy_BMIter_Type.tp_hash = NULL;
3668 
3673  BPy_BMLoopSeq_Type.tp_as_sequence = NULL; /* this is not a seq really, only for layer access */
3674 
3679  BPy_BMLoopSeq_Type.tp_as_mapping = NULL; /* this is not a seq really, only for layer access */
3680 
3681  /* layer access */
3682  BPy_BMVert_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3683  BPy_BMEdge_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3684  BPy_BMFace_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3685  BPy_BMLoop_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3686 
3687  BPy_BMElemSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3688  BPy_BMVertSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3689  BPy_BMEdgeSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3690  BPy_BMFaceSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3691  BPy_BMLoopSeq_Type.tp_iter = NULL; /* no mapping */
3692 
3693  /* only 1 iteratir so far */
3694  BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next;
3695  BPy_BMIter_Type.tp_iter = PyObject_SelfIter;
3696 
3697  BPy_BMesh_Type.tp_dealloc = (destructor)bpy_bmesh_dealloc;
3698  BPy_BMVert_Type.tp_dealloc = (destructor)bpy_bmvert_dealloc;
3699  BPy_BMEdge_Type.tp_dealloc = (destructor)bpy_bmedge_dealloc;
3700  BPy_BMFace_Type.tp_dealloc = (destructor)bpy_bmface_dealloc;
3701  BPy_BMLoop_Type.tp_dealloc = (destructor)bpy_bmloop_dealloc;
3702  BPy_BMElemSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3703  BPy_BMVertSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3704  BPy_BMEdgeSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3705  BPy_BMFaceSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3706  BPy_BMLoopSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3707  BPy_BMIter_Type.tp_dealloc = NULL;
3708 
3709  BPy_BMesh_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3710  BPy_BMVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3711  BPy_BMEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3712  BPy_BMFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3713  BPy_BMLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3714  BPy_BMElemSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3715  BPy_BMVertSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3716  BPy_BMEdgeSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3717  BPy_BMFaceSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3718  BPy_BMLoopSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3719  BPy_BMIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3720 
3721  PyType_Ready(&BPy_BMesh_Type);
3722  PyType_Ready(&BPy_BMVert_Type);
3723  PyType_Ready(&BPy_BMEdge_Type);
3724  PyType_Ready(&BPy_BMFace_Type);
3725  PyType_Ready(&BPy_BMLoop_Type);
3726  PyType_Ready(&BPy_BMElemSeq_Type);
3727  PyType_Ready(&BPy_BMVertSeq_Type);
3728  PyType_Ready(&BPy_BMEdgeSeq_Type);
3729  PyType_Ready(&BPy_BMFaceSeq_Type);
3730  PyType_Ready(&BPy_BMLoopSeq_Type);
3731  PyType_Ready(&BPy_BMIter_Type);
3732 }
3733 
3734 /* bmesh.types submodule
3735  * ********************* */
3736 
3737 static struct PyModuleDef BPy_BM_types_module_def = {
3738  PyModuleDef_HEAD_INIT,
3739  "bmesh.types", /* m_name */
3740  NULL, /* m_doc */
3741  0, /* m_size */
3742  NULL, /* m_methods */
3743  NULL, /* m_reload */
3744  NULL, /* m_traverse */
3745  NULL, /* m_clear */
3746  NULL, /* m_free */
3747 };
3748 
3749 PyObject *BPyInit_bmesh_types(void)
3750 {
3751  PyObject *submodule;
3752 
3753  submodule = PyModule_Create(&BPy_BM_types_module_def);
3754 
3755  /* bmesh_py_types.c */
3756  PyModule_AddType(submodule, &BPy_BMesh_Type);
3757  PyModule_AddType(submodule, &BPy_BMVert_Type);
3758  PyModule_AddType(submodule, &BPy_BMEdge_Type);
3759  PyModule_AddType(submodule, &BPy_BMFace_Type);
3760  PyModule_AddType(submodule, &BPy_BMLoop_Type);
3761  PyModule_AddType(submodule, &BPy_BMElemSeq_Type);
3762  PyModule_AddType(submodule, &BPy_BMVertSeq_Type);
3763  PyModule_AddType(submodule, &BPy_BMEdgeSeq_Type);
3764  PyModule_AddType(submodule, &BPy_BMFaceSeq_Type);
3765  PyModule_AddType(submodule, &BPy_BMLoopSeq_Type);
3766  PyModule_AddType(submodule, &BPy_BMIter_Type);
3767  /* bmesh_py_types_select.c */
3768  PyModule_AddType(submodule, &BPy_BMEditSelSeq_Type);
3769  PyModule_AddType(submodule, &BPy_BMEditSelIter_Type);
3770  /* bmesh_py_types_customdata.c */
3771  PyModule_AddType(submodule, &BPy_BMLayerAccessVert_Type);
3772  PyModule_AddType(submodule, &BPy_BMLayerAccessEdge_Type);
3773  PyModule_AddType(submodule, &BPy_BMLayerAccessFace_Type);
3774  PyModule_AddType(submodule, &BPy_BMLayerAccessLoop_Type);
3775  PyModule_AddType(submodule, &BPy_BMLayerCollection_Type);
3776  PyModule_AddType(submodule, &BPy_BMLayerItem_Type);
3777  /* bmesh_py_types_meshdata.c */
3778  PyModule_AddType(submodule, &BPy_BMLoopUV_Type);
3779  PyModule_AddType(submodule, &BPy_BMDeformVert_Type);
3780 
3781  return submodule;
3782 }
3783 
3784 /* Utility Functions
3785  * ***************** */
3786 
3787 PyObject *BPy_BMesh_CreatePyObject(BMesh *bm, int flag)
3788 {
3789  BPy_BMesh *self;
3790 
3791  if (bm->py_handle) {
3792  self = bm->py_handle;
3793  Py_INCREF(self);
3794  }
3795  else {
3796  self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
3797  self->bm = bm;
3798  self->flag = flag;
3799 
3800  bm->py_handle = self; /* point back */
3801 
3802  /* avoid allocating layers when we don't have to */
3803 #if 0
3808 #endif
3809  }
3810 
3811  return (PyObject *)self;
3812 }
3813 
3815 {
3816  BPy_BMVert *self;
3817 
3819 
3820  /* bmesh may free layers, ensure we have one to store ourself */
3821  if (UNLIKELY(ptr == NULL)) {
3824  }
3825 
3826  if (*ptr != NULL) {
3827  self = *ptr;
3828  Py_INCREF(self);
3829  }
3830  else {
3831  self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type);
3832  BLI_assert(v != NULL);
3833  self->bm = bm;
3834  self->v = v;
3835  *ptr = self;
3836  }
3837  return (PyObject *)self;
3838 }
3839 
3841 {
3842  BPy_BMEdge *self;
3843 
3845 
3846  /* bmesh may free layers, ensure we have one to store ourself */
3847  if (UNLIKELY(ptr == NULL)) {
3850  }
3851 
3852  if (*ptr != NULL) {
3853  self = *ptr;
3854  Py_INCREF(self);
3855  }
3856  else {
3857  self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type);
3858  BLI_assert(e != NULL);
3859  self->bm = bm;
3860  self->e = e;
3861  *ptr = self;
3862  }
3863  return (PyObject *)self;
3864 }
3865 
3867 {
3868  BPy_BMFace *self;
3869 
3871 
3872  /* bmesh may free layers, ensure we have one to store ourself */
3873  if (UNLIKELY(ptr == NULL)) {
3876  }
3877 
3878  if (*ptr != NULL) {
3879  self = *ptr;
3880  Py_INCREF(self);
3881  }
3882  else {
3883  self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type);
3884  BLI_assert(f != NULL);
3885  self->bm = bm;
3886  self->f = f;
3887  *ptr = self;
3888  }
3889  return (PyObject *)self;
3890 }
3891 
3893 {
3894  BPy_BMLoop *self;
3895 
3897 
3898  /* bmesh may free layers, ensure we have one to store ourself */
3899  if (UNLIKELY(ptr == NULL)) {
3902  }
3903 
3904  if (*ptr != NULL) {
3905  self = *ptr;
3906  Py_INCREF(self);
3907  }
3908  else {
3909  self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type);
3910  BLI_assert(l != NULL);
3911  self->bm = bm;
3912  self->l = l;
3913  *ptr = self;
3914  }
3915  return (PyObject *)self;
3916 }
3917 
3918 PyObject *BPy_BMElemSeq_CreatePyObject(BMesh *bm, BPy_BMElem *py_ele, const char itype)
3919 {
3920  BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMElemSeq_Type);
3921  self->bm = bm;
3922  self->py_ele = py_ele; /* can be NULL */
3923  self->itype = itype;
3924  Py_XINCREF(py_ele);
3925  return (PyObject *)self;
3926 }
3927 
3929 {
3930  BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMVertSeq_Type);
3931  self->bm = bm;
3932  self->py_ele = NULL; /* unused */
3933  self->itype = BM_VERTS_OF_MESH;
3934  return (PyObject *)self;
3935 }
3936 
3938 {
3939  BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMEdgeSeq_Type);
3940  self->bm = bm;
3941  self->py_ele = NULL; /* unused */
3942  self->itype = BM_EDGES_OF_MESH;
3943  return (PyObject *)self;
3944 }
3945 
3947 {
3948  BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMFaceSeq_Type);
3949  self->bm = bm;
3950  self->py_ele = NULL; /* unused */
3951  self->itype = BM_FACES_OF_MESH;
3952  return (PyObject *)self;
3953 }
3954 
3956 {
3957  BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMLoopSeq_Type);
3958  self->bm = bm;
3959  self->py_ele = NULL; /* unused */
3960  self->itype = 0; /* should never be passed to the iterator function */
3961  return (PyObject *)self;
3962 }
3963 
3965 {
3966  BPy_BMIter *self = PyObject_New(BPy_BMIter, &BPy_BMIter_Type);
3967  self->bm = bm;
3968  /* caller must initialize 'iter' member */
3969  return (PyObject *)self;
3970 }
3971 
3973 {
3974  switch (ele->htype) {
3975  case BM_VERT:
3976  return BPy_BMVert_CreatePyObject(bm, (BMVert *)ele);
3977  case BM_EDGE:
3978  return BPy_BMEdge_CreatePyObject(bm, (BMEdge *)ele);
3979  case BM_FACE:
3980  return BPy_BMFace_CreatePyObject(bm, (BMFace *)ele);
3981  case BM_LOOP:
3982  return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele);
3983  default:
3985  PyErr_SetString(PyExc_SystemError, "internal error");
3986  return NULL;
3987  }
3988 }
3989 
3991 {
3992  if (LIKELY(self->bm)) {
3993 
3994  /* far too slow to enable by default but handy
3995  * to uncomment for debugging tricky errors,
3996  * note that this will throw error on entering a
3997  * function where the actual error will be caused by
3998  * the previous action. */
3999 #if 0
4000  if (BM_mesh_validate(self->bm) == false) {
4001  PyErr_Format(
4002  PyExc_ReferenceError, "BMesh used by %.200s has become invalid", Py_TYPE(self)->tp_name);
4003  return -1;
4004  }
4005 #endif
4006 
4007  return 0;
4008  }
4009 
4010  PyErr_Format(
4011  PyExc_ReferenceError, "BMesh data of type %.200s has been removed", Py_TYPE(self)->tp_name);
4012  return -1;
4013 }
4014 
4016  const char *error_prefix,
4017  void **args,
4018  uint args_tot)
4019 {
4020  int ret = 0;
4021 
4022  while (args_tot--) {
4023  BPy_BMGeneric *py_bm_elem = args[args_tot];
4024  if (py_bm_elem) {
4025 
4026  BLI_assert(BPy_BMesh_Check(py_bm_elem) || BPy_BMElem_Check(py_bm_elem));
4027 
4028  ret = bpy_bm_generic_valid_check(py_bm_elem);
4029  if (UNLIKELY(ret == -1)) {
4030  break;
4031  }
4032 
4033  if (UNLIKELY(py_bm_elem->bm != bm_source)) {
4034  /* could give more info here */
4035  PyErr_Format(PyExc_ValueError,
4036  "%.200s: BMesh data of type %.200s is from another mesh",
4037  error_prefix,
4038  Py_TYPE(py_bm_elem)->tp_name);
4039  ret = -1;
4040  break;
4041  }
4042  }
4043  }
4044 
4045  return ret;
4046 }
4047 
4049 {
4050  self->bm = NULL;
4051 }
4052 
4054  PyObject *seq_fast,
4055  Py_ssize_t min,
4056  Py_ssize_t max,
4057  Py_ssize_t *r_size,
4058  const char htype,
4059  const bool do_unique_check,
4060  const bool do_bm_check,
4061  const char *error_prefix)
4062 {
4063  BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
4064  PyObject **seq_fast_items = PySequence_Fast_ITEMS(seq_fast);
4065  const Py_ssize_t seq_len = PySequence_Fast_GET_SIZE(seq_fast);
4066  Py_ssize_t i, i_last_dirty = PY_SSIZE_T_MAX;
4067 
4068  BPy_BMElem *item;
4069  BMElem **alloc;
4070 
4071  *r_size = 0;
4072 
4073  if (seq_len < min || seq_len > max) {
4074  PyErr_Format(PyExc_TypeError,
4075  "%s: sequence incorrect size, expected [%d - %d], given %d",
4076  error_prefix,
4077  min,
4078  max,
4079  seq_len);
4080  return NULL;
4081  }
4082 
4083  /* from now on, use goto */
4084  alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
4085 
4086  for (i = 0; i < seq_len; i++) {
4087  item = (BPy_BMElem *)seq_fast_items[i];
4088 
4089  if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
4090  PyErr_Format(PyExc_TypeError,
4091  "%s: expected %.200s, not '%.200s'",
4092  error_prefix,
4094  Py_TYPE(item)->tp_name);
4095  goto err_cleanup;
4096  }
4097  else if (!BPY_BM_IS_VALID(item)) {
4098  PyErr_Format(
4099  PyExc_TypeError, "%s: %d %s has been removed", error_prefix, i, Py_TYPE(item)->tp_name);
4100  goto err_cleanup;
4101  }
4102  /* trick so we can ensure all items have the same mesh,
4103  * and allows us to pass the 'bm' as NULL. */
4104  else if (do_bm_check && (bm && bm != item->bm)) {
4105  PyErr_Format(PyExc_ValueError,
4106  "%s: %d %s is from another mesh",
4107  error_prefix,
4108  i,
4110  goto err_cleanup;
4111  }
4112 
4113  if (bm == NULL) {
4114  bm = item->bm;
4115  }
4116 
4117  alloc[i] = item->ele;
4118 
4119  if (do_unique_check) {
4121  i_last_dirty = i;
4122  }
4123  }
4124 
4125  if (do_unique_check) {
4126  /* check for double verts! */
4127  bool ok = true;
4128  for (i = 0; i < seq_len; i++) {
4129  if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == false)) {
4130  ok = false;
4131  }
4132 
4133  /* ensure we don't leave this enabled */
4135  }
4136 
4137  if (ok == false) {
4138  /* Cleared above. */
4139  i_last_dirty = PY_SSIZE_T_MAX;
4140  PyErr_Format(PyExc_ValueError,
4141  "%s: found the same %.200s used multiple times",
4142  error_prefix,
4144  goto err_cleanup;
4145  }
4146  }
4147 
4148  *r_size = seq_len;
4149  if (r_bm) {
4150  *r_bm = bm;
4151  }
4152  return alloc;
4153 
4154 err_cleanup:
4155  if (do_unique_check && (i_last_dirty != PY_SSIZE_T_MAX)) {
4156  for (i = 0; i <= i_last_dirty; i++) {
4158  }
4159  }
4160  PyMem_FREE(alloc);
4161  return NULL;
4162 }
4163 
4165  PyObject *seq,
4166  Py_ssize_t min,
4167  Py_ssize_t max,
4168  Py_ssize_t *r_size,
4169  const char htype,
4170  const bool do_unique_check,
4171  const bool do_bm_check,
4172  const char *error_prefix)
4173 {
4174  PyObject *seq_fast;
4175  PyObject *ret;
4176 
4177  if (!(seq_fast = PySequence_Fast(seq, error_prefix))) {
4178  return NULL;
4179  }
4180 
4182  r_bm, seq_fast, min, max, r_size, htype, do_unique_check, do_bm_check, error_prefix);
4183 
4184  Py_DECREF(seq_fast);
4185  return ret;
4186 }
4187 
4188 PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
4189 {
4190  Py_ssize_t i;
4191  PyObject *ret = PyTuple_New(elem_len);
4192  for (i = 0; i < elem_len; i++) {
4193  PyTuple_SET_ITEM(ret, i, BPy_BMElem_CreatePyObject(bm, elem[i]));
4194  }
4195  return ret;
4196 }
4197 PyObject *BPy_BMVert_Array_As_Tuple(BMesh *bm, BMVert **elem, Py_ssize_t elem_len)
4198 {
4199  Py_ssize_t i;
4200  PyObject *ret = PyTuple_New(elem_len);
4201  for (i = 0; i < elem_len; i++) {
4202  PyTuple_SET_ITEM(ret, i, BPy_BMVert_CreatePyObject(bm, elem[i]));
4203  }
4204  return ret;
4205 }
4206 PyObject *BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_len)
4207 {
4208  Py_ssize_t i;
4209  PyObject *ret = PyTuple_New(elem_len);
4210  for (i = 0; i < elem_len; i++) {
4211  PyTuple_SET_ITEM(ret, i, BPy_BMEdge_CreatePyObject(bm, elem[i]));
4212  }
4213 
4214  return ret;
4215 }
4216 PyObject *BPy_BMFace_Array_As_Tuple(BMesh *bm, BMFace **elem, Py_ssize_t elem_len)
4217 {
4218  Py_ssize_t i;
4219  PyObject *ret = PyTuple_New(elem_len);
4220  for (i = 0; i < elem_len; i++) {
4221  PyTuple_SET_ITEM(ret, i, BPy_BMFace_CreatePyObject(bm, elem[i]));
4222  }
4223 
4224  return ret;
4225 }
4226 PyObject *BPy_BMLoop_Array_As_Tuple(BMesh *bm, BMLoop **elem, Py_ssize_t elem_len)
4227 {
4228  Py_ssize_t i;
4229  PyObject *ret = PyTuple_New(elem_len);
4230  for (i = 0; i < elem_len; i++) {
4231  PyTuple_SET_ITEM(ret, i, BPy_BMLoop_CreatePyObject(bm, elem[i]));
4232  }
4233 
4234  return ret;
4235 }
4236 
4237 int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype)
4238 {
4239  return (((htype & BM_VERT) && (type == &BPy_BMVert_Type)) ||
4240  ((htype & BM_EDGE) && (type == &BPy_BMEdge_Type)) ||
4241  ((htype & BM_FACE) && (type == &BPy_BMFace_Type)) ||
4242  ((htype & BM_LOOP) && (type == &BPy_BMLoop_Type)));
4243 }
4244 
4245 char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32])
4246 {
4247  /* zero to ensure string is always NULL terminated */
4248  char *ret_ptr = ret;
4249  if (htype & BM_VERT) {
4250  ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMVert_Type.tp_name);
4251  }
4252  if (htype & BM_EDGE) {
4253  ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMEdge_Type.tp_name);
4254  }
4255  if (htype & BM_FACE) {
4256  ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMFace_Type.tp_name);
4257  }
4258  if (htype & BM_LOOP) {
4259  ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMLoop_Type.tp_name);
4260  }
4261  ret[0] = '(';
4262  *ret_ptr++ = ')';
4263  *ret_ptr = '\0';
4264  return ret;
4265 }
4266 char *BPy_BMElem_StringFromHType(const char htype)
4267 {
4268  /* zero to ensure string is always NULL terminated */
4269  static char ret[32];
4270  return BPy_BMElem_StringFromHType_ex(htype, ret);
4271 }
4272 
4273 /* -------------------------------------------------------------------- */
4274 /* keep at bottom */
4275 
4276 /* this function is called on free, it should stay quite fast */
4278 {
4279  if (self->flag & BPY_BMFLAG_IS_WRAPPED) {
4280  /* currently nop - this works without warnings now */
4281  }
4282 }
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer(const struct CustomData *data, int type)
const CustomData_MeshMasks CD_MASK_BMESH
Definition: customdata.cc:2090
void * CustomData_bmesh_get(const struct CustomData *data, void *block, int type)
#define G_MAIN
Definition: BKE_global.h:267
void BKE_id_free(struct Main *bmain, void *idv)
bool BKE_id_is_in_global_main(struct ID *id)
Definition: lib_id.c:1902
struct Mesh * BKE_mesh_new_from_object(struct Depsgraph *depsgraph, struct Object *object, bool preserve_all_data_layers, bool preserve_origindex)
struct Mesh * mesh_get_eval_deform(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
struct Mesh * mesh_get_eval_final(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
MINLINE float clamp_f(float value, float min, float max)
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void range_vn_i(int *array_tar, int size, int start)
Definition: math_vector.c:1021
void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk)
Definition: sort.c:79
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
#define CLAMP_MIN(a, b)
#define LIKELY(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ DAG_EVAL_RENDER
Definition: DEG_depsgraph.h:46
void DEG_id_tag_update(struct ID *id, int flag)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ ID_RECALC_GEOMETRY_ALL_MODES
Definition: DNA_ID.h:884
@ LIB_TAG_NO_MAIN
Definition: DNA_ID.h:744
#define CD_MASK_BM_ELEM_PYPTR
@ CD_BM_ELEM_PYPTR
#define MAXMAT
Object is a sort of wrapper for general info.
@ OB_MESH
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_EDGE
Definition: bmesh_class.h:384
@ BM_ELEM_HIDDEN
Definition: bmesh_class.h:472
@ BM_ELEM_SEAM
Definition: bmesh_class.h:473
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
@ BM_ELEM_SMOOTH
Definition: bmesh_class.h:477
@ BM_ELEM_INTERNAL_TAG
Definition: bmesh_class.h:496
@ BM_ELEM_TAG
Definition: bmesh_class.h:484
void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v, const char hflag_mask, const uint64_t cd_mask_exclude)
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src, void *ele_dst)
BMesh * BM_mesh_copy(BMesh *bm_old)
BMVert * BM_vert_create(BMesh *bm, const float co[3], const BMVert *v_example, const eBMCreateFlag create_flag)
Main function for creating a new vertex.
Definition: bmesh_core.c:41
BMFace * BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges)
Definition: bmesh_core.c:464
void BM_vert_kill(BMesh *bm, BMVert *v)
Definition: bmesh_core.c:939
void BM_face_kill(BMesh *bm, BMFace *f)
Definition: bmesh_core.c:828
void BM_edge_kill(BMesh *bm, BMEdge *e)
Definition: bmesh_core.c:927
BMFace * BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges)
Definition: bmesh_core.c:279
BMEdge * BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *e_example, const eBMCreateFlag create_flag)
Main function for creating a new edge.
Definition: bmesh_core.c:123
@ BM_CREATE_NOP
Definition: bmesh_core.h:12
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:110
#define BM_elem_flag_disable(ele, hflag)
Definition: bmesh_inline.h:15
#define BM_elem_flag_set(ele, hflag, val)
Definition: bmesh_inline.h:16
#define BM_elem_index_set(ele, index)
Definition: bmesh_inline.h:111
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
#define BM_elem_flag_enable(ele, hflag)
Definition: bmesh_inline.h:14
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:875
void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
Definition: bmesh_interp.c:736
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:839
void BM_face_interp_from_face(BMesh *bm, BMFace *f_dst, const BMFace *f_src, const bool do_vertex)
Definition: bmesh_interp.c:169
void BM_loop_interp_from_face(BMesh *bm, BMLoop *l_dst, const BMFace *f_src, const bool do_vertex, const bool do_multires)
Definition: bmesh_interp.c:682
void BM_data_interp_from_verts(BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v_dst, const float fac)
Data, Interpolate From Verts.
Definition: bmesh_interp.c:68
const char bm_iter_itype_htype_map[BM_ITYPE_MAX]
void * BM_iter_at_index(BMesh *bm, const char itype, void *data, int index)
#define BM_ITER_MESH(ele, iter, bm, itype)
BMIterType
BMesh Iterators.
@ BM_LOOPS_OF_LOOP
@ BM_FACES_OF_EDGE
@ BM_FACES_OF_VERT
@ BM_EDGES_OF_MESH
@ BM_VERTS_OF_MESH
@ BM_VERTS_OF_EDGE
@ BM_VERTS_OF_FACE
@ BM_FACES_OF_MESH
@ BM_LOOPS_OF_VERT
@ BM_LOOPS_OF_EDGE
@ BM_EDGES_OF_VERT
@ BM_EDGES_OF_FACE
@ BM_LOOPS_OF_FACE
BLI_INLINE bool BM_iter_init(BMIter *iter, BMesh *bm, const char itype, void *data)
Iterator Init.
ATTR_WARN_UNUSED_RESULT BMesh const char itype
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_select_mode_flush(BMesh *bm)
void BM_elem_select_set(BMesh *bm, BMElem *ele, const bool select)
void BM_mesh_select_flush(BMesh *bm)
void BM_mesh_deselect_flush(BMesh *bm)
#define BM_elem_hide_set(bm, ele, hide)
Definition: bmesh_marking.h:27
void BM_mesh_remap(BMesh *bm, const uint *vert_idx, const uint *edge_idx, const uint *face_idx)
Definition: bmesh_mesh.cc:726
void BM_mesh_clear(BMesh *bm)
BMesh Clear Mesh.
Definition: bmesh_mesh.cc:237
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
Definition: bmesh_mesh.cc:258
int BM_mesh_elem_count(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:708
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:558
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.cc:446
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshParams *params)
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params)
void BM_mesh_normals_update(BMesh *bm)
void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3])
bool BM_mesh_validate(BMesh *bm)
void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3])
void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3])
void BM_vert_normal_update(BMVert *v)
void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
void BM_face_normal_update(BMFace *f)
void BM_face_normal_flip(BMesh *bm, BMFace *f)
void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3])
float BM_face_calc_area(const BMFace *f)
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3])
float BM_face_calc_perimeter(const BMFace *f)
void BM_edge_normals_update(BMEdge *e)
static Py_hash_t bpy_bm_hash(PyObject *self)
static PyObject * bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
static void bpy_bmvert_dealloc(BPy_BMElem *self)
static PyObject * bpy_bmedge_is_contiguous_get(BPy_BMEdge *self)
static PyObject * bpy_bmedge_is_wire_get(BPy_BMEdge *self)
static Py_hash_t bpy_bm_elem_hash(PyObject *self)
PyC_FlagSet bpy_bm_htype_all_flags[]
static PyMappingMethods bpy_bmelemseq_as_mapping
static PyObject * bpy_bmesh_copy(BPy_BMesh *self)
static PyObject * bpy_bmesh_select_history_get(BPy_BMesh *self)
static PyObject * bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
static PyObject * bpy_bmloop_calc_angle(BPy_BMLoop *self)
PyObject * BPy_BMIter_CreatePyObject(BMesh *bm)
static PyObject * bpy_bmface_repr(BPy_BMFace *self)
static PyObject * bpy_bmvert_normal_update(BPy_BMVert *self)
static PyObject * bpy_bmloopseq_get(BPy_BMesh *self, void *UNUSED(closure))
static PyGetSetDef bpy_bmvertseq_getseters[]
static PyObject * bpy_bmloop_link_loop_radial_next_get(BPy_BMLoop *self)
static PyObject * bpy_bmvertseq_get(BPy_BMesh *self, void *UNUSED(closure))
static PyObject * bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *args)
static PyObject * bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
static PyGetSetDef bpy_bmloopseq_getseters[]
PyObject * BPy_BMEdge_Array_As_Tuple(BMesh *bm, BMEdge **elem, Py_ssize_t elem_len)
static PyObject * bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
static PyObject * bpy_bmedge_repr(BPy_BMEdge *self)
PyTypeObject BPy_BMesh_Type
PyObject * BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
static PyObject * bpy_bmface_calc_perimeter(BPy_BMFace *self)
static PyObject * bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype)
static PyObject * bpy_bmedge_calc_face_angle(BPy_BMEdge *self, PyObject *args)
PyC_FlagSet bpy_bm_htype_vert_edge_face_flags[]
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)
static PyObject * bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value)
static PyObject * bpy_bmface_calc_tangent_edge_pair(BPy_BMFace *self)
static PyMappingMethods bpy_bm_elem_as_mapping
static PyObject * bpy_bmiter_next(BPy_BMIter *self)
static PyObject * bpy_bmface_calc_center_mean(BPy_BMFace *self)
PyObject * BPyInit_bmesh_types(void)
PyObject * BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele)
static PyObject * bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
static PyObject * bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
void BPy_BM_init_types(void)
static int bpy_bmelem_ass_subscript(BPy_BMElem *self, BPy_BMLayerItem *key, PyObject *value)
static PyObject * bpy_bmelemseq_elem_get(BPy_BMElem *self, void *itype)
static struct PyMethodDef bpy_bmedge_methods[]
void * BPy_BMElem_PySeq_As_Array_FAST(BMesh **r_bm, PyObject *seq_fast, 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)
static PyObject * bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
static void bm_dealloc_editmode_warn(BPy_BMesh *self)
PyTypeObject BPy_BMVertSeq_Type
PyTypeObject BPy_BMLoopSeq_Type
static PyObject * bpy_bmface_calc_center_bounds(BPy_BMFace *self)
static void bpy_bmedge_dealloc(BPy_BMElem *self)
static PyObject * bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *kw)
static PyObject * bpy_bmvert_repr(BPy_BMVert *self)
static PyGetSetDef bpy_bmvert_getseters[]
static PyObject * bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
static PyObject * bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
static PyObject * bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
static void bpy_bmloop_dealloc(BPy_BMElem *self)
static PyObject * bpy_bmesh_is_wrapped_get(BPy_BMesh *self)
static Py_ssize_t bpy_bmelemseq_length(BPy_BMElemSeq *self)
static PyObject * bpy_bmedge_normal_update(BPy_BMEdge *self)
PyObject * BPy_BMLoopSeq_CreatePyObject(BMesh *bm)
static struct PyMethodDef bpy_bmface_methods[]
static PyObject * bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
static PyGetSetDef bpy_bmesh_getseters[]
PyObject * BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
static PyObject * bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t start, Py_ssize_t stop)
void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
static PyObject * bpy_bmloop_link_loop_next_get(BPy_BMLoop *self)
static PyObject * bpy_bmloop_face_get(BPy_BMLoop *self)
static PyObject * bpy_bmelemseq_ensure_lookup_table(BPy_BMElemSeq *self)
static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
char * BPy_BMElem_StringFromHType_ex(const char htype, char ret[32])
static PyObject * bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key)
static PyObject * bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
static PyObject * bpy_bmesh_select_flush_mode(BPy_BMesh *self)
static PyTypeObject * bpy_bm_itype_as_pytype(const char itype)
PyTypeObject BPy_BMEdgeSeq_Type
static PyObject * bpy_bmedge_is_convex_get(BPy_BMEdge *self)
static PyObject * bpy_bmelem_subscript(BPy_BMElem *self, BPy_BMLayerItem *key)
PyTypeObject BPy_BMEdge_Type
static PyObject * bpy_bmface_calc_tangent_edge_diagonal(BPy_BMFace *self)
static PyObject * bpy_bmloop_repr(BPy_BMLoop *self)
static PyObject * bpy_bmedgeseq_get(BPy_BMesh *self, void *UNUSED(closure))
static int bpy_bmfaceseq_active_set(BPy_BMElem *self, PyObject *value, void *UNUSED(closure))
static PyObject * bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
static PyObject * bpy_bmesh_normal_update(BPy_BMesh *self)
static PyGetSetDef bpy_bmfaceseq_getseters[]
static PyObject * bpy_bmedge_calc_length(BPy_BMEdge *self)
static PyObject * bpy_bmloop_link_loop_prev_get(BPy_BMLoop *self)
static PyGetSetDef bpy_bmedge_getseters[]
static PyObject * bpy_bmedge_calc_face_angle_signed(BPy_BMEdge *self, PyObject *args)
static PyObject * bpy_bmface_calc_area(BPy_BMFace *self)
static PyObject * bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
static PyObject * bpy_bmfaceseq_active_get(BPy_BMElemSeq *self, void *UNUSED(closure))
PyObject * BPy_BMFaceSeq_CreatePyObject(BMesh *bm)
static PyObject * bpy_bmesh_calc_volume(BPy_BMElem *self, PyObject *args, PyObject *kw)
static struct PyMethodDef bpy_bmvertseq_methods[]
static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
static struct PyMethodDef bpy_bmloopseq_methods[]
static int bpy_bmelemseq_sort_cmp_by_keys_descending(const void *index1_v, const void *index2_v, void *keys_v)
int bpy_bm_generic_valid_check_source(BMesh *bm_source, const char *error_prefix, void **args, uint args_tot)
static PyObject * bpy_bmloop_calc_normal(BPy_BMLoop *self)
static PyObject * bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject *kw)
static PyObject * bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
PyObject * BPy_BMLoop_Array_As_Tuple(BMesh *bm, BMLoop **elem, Py_ssize_t elem_len)
PyObject * BPy_BMesh_CreatePyObject(BMesh *bm, int flag)
static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
static PyObject * bpy_bmvert_is_manifold_get(BPy_BMVert *self)
static PyGetSetDef bpy_bmedgeseq_getseters[]
static PyObject * bpy_bmesh_repr(BPy_BMesh *self)
static PyObject * bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
static PyObject * bpy_bmvert_co_get(BPy_BMVert *self)
static void bpy_bmelemseq_dealloc(BPy_BMElemSeq *self)
int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
static PyObject * bpy_bmedge_calc_tangent(BPy_BMEdge *self, PyObject *args)
static PyObject * bpy_bmloop_edge_get(BPy_BMLoop *self)
static PyObject * bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
static void bpy_bmface_dealloc(BPy_BMElem *self)
static PyObject * bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
static PyObject * bpy_bmface_calc_tangent_edge(BPy_BMFace *self)
PyTypeObject BPy_BMFaceSeq_Type
PyTypeObject BPy_BMVert_Type
static PyObject * bpy_bmesh_calc_loop_triangles(BPy_BMElem *self)
PyTypeObject BPy_BMIter_Type
static PyObject * bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
static PyObject * bpy_bmface_material_index_get(BPy_BMFace *self)
char * BPy_BMElem_StringFromHType(const char htype)
static struct PyMethodDef bpy_bmvert_methods[]
static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
static PyObject * bpy_bmface_normal_get(BPy_BMFace *self)
static PyObject * bpy_bmelemseq_iter(BPy_BMElemSeq *self)
static PyObject * bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
static PyObject * bpy_bmvert_is_boundary_get(BPy_BMVert *self)
#define BPY_BM_HFLAG_ALL_STR
PyObject * BPy_BMVertSeq_CreatePyObject(BMesh *bm)
static int bpy_bmesh_select_history_set(BPy_BMesh *self, PyObject *value)
static PyObject * bpy_bmface_calc_center_median_weighted(BPy_BMFace *self)
static PyObject * bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *args)
static PyObject * bpy_bmesh_clear(BPy_BMesh *self)
static PyObject * bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
static PyObject * bpy_bmvert_normal_get(BPy_BMVert *self)
PyTypeObject BPy_BMElemSeq_Type
PyObject * BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
static int bpy_bmface_material_index_set(BPy_BMFace *self, PyObject *value)
static PyGetSetDef bpy_bmface_getseters[]
PyDoc_STRVAR(bpy_bm_elem_select_doc, "Selected state of this element.\n\n:type: boolean")
static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
static struct PyMethodDef bpy_bmelemseq_methods[]
static PyObject * bpy_bmface_calc_tangent_vert_diagonal(BPy_BMFace *self)
PyTypeObject BPy_BMFace_Type
static PyObject * bpy_bmesh_select_mode_get(BPy_BMesh *self)
static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const void *index2_v, void *keys_v)
PyObject * BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
static struct PyMethodDef bpy_bmloop_methods[]
static struct PyMethodDef bpy_bmfaceseq_methods[]
static void bpy_bmesh_dealloc(BPy_BMesh *self)
static PyGetSetDef bpy_bmloop_getseters[]
static PyObject * bpy_bmfaceseq_get(BPy_BMesh *self, void *UNUSED(closure))
PyTypeObject BPy_BMLoop_Type
static PyObject * bpy_bmloop_vert_get(BPy_BMLoop *self)
static PyObject * bpy_bmface_normal_update(BPy_BMFace *self)
static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
static PyObject * bpy_bmface_normal_flip(BPy_BMFace *self)
PyObject * BPy_BMElemSeq_CreatePyObject(BMesh *bm, BPy_BMElem *py_ele, const char itype)
PyC_FlagSet bpy_bm_hflag_all_flags[]
static struct PyMethodDef bpy_bmedgeseq_methods[]
PyC_FlagSet bpy_bm_scene_vert_edge_face_flags[]
int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype)
static PyObject * bpy_bmvert_calc_edge_angle(BPy_BMVert *self, PyObject *args)
static PyObject * bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObject *kw)
static PyObject * bpy_bm_is_valid_get(BPy_BMGeneric *self)
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)
static PySequenceMethods bpy_bmelemseq_as_sequence
static PyObject * bpy_bmvert_is_wire_get(BPy_BMVert *self)
static PyObject * bpy_bmloop_link_loop_radial_prev_get(BPy_BMLoop *self)
static PyObject * bpy_bmloop_is_convex_get(BPy_BMLoop *self)
static struct PyMethodDef bpy_bmesh_methods[]
static PyObject * bpy_bmloop_calc_tangent(BPy_BMLoop *self)
static PyObject * bpy_bmesh_free(BPy_BMesh *self)
static struct PyModuleDef BPy_BM_types_module_def
PyObject * BPy_BMEdgeSeq_CreatePyObject(BMesh *bm)
static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
static PyObject * bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
static PyObject * bpy_bmvert_calc_shell_factor(BPy_BMVert *self)
static PyObject * bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
struct BPy_BMLoop BPy_BMLoop
#define BPy_BMFace_Check(v)
#define BPY_BM_CHECK_OBJ(obj)
struct BPy_BMVert BPy_BMVert
struct BPy_BMIter BPy_BMIter
#define BPY_BM_CHECK_SOURCE_INT(bm, errmsg,...)
#define BPy_BMVert_Check(v)
#define BPy_BMElem_Check(v)
struct BPy_BMEdge BPy_BMEdge
@ BPY_BMFLAG_IS_WRAPPED
@ BPY_BMFLAG_NOP
#define BPy_BMesh_Check(v)
struct BPy_BMFace BPy_BMFace
#define BPy_BMEdge_Check(v)
#define BPY_BM_CHECK_SOURCE_OBJ(bm, errmsg,...)
#define BPY_BM_IS_VALID(obj)
struct BPy_BMElemSeq BPy_BMElemSeq
#define BM_ITER_BPY_BM_SEQ(ele, iter, bpy_bmelemseq)
struct BPy_BMesh BPy_BMesh
#define BPY_BM_CHECK_INT(obj)
PyTypeObject BPy_BMLayerCollection_Type
PyTypeObject BPy_BMLayerItem_Type
PyObject * BPy_BMLayerAccess_CreatePyObject(BMesh *bm, const char htype)
PyTypeObject BPy_BMLayerAccessLoop_Type
PyTypeObject BPy_BMLayerAccessVert_Type
int BPy_BMLayerItem_SetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer, PyObject *py_value)
PyTypeObject BPy_BMLayerAccessFace_Type
PyTypeObject BPy_BMLayerAccessEdge_Type
PyObject * BPy_BMLayerItem_GetItem(BPy_BMElem *py_ele, BPy_BMLayerItem *py_layer)
BMElem.__getitem__() / setitem()
PyTypeObject BPy_BMDeformVert_Type
PyTypeObject BPy_BMLoopUV_Type
int BPy_BMEditSel_Assign(BPy_BMesh *self, PyObject *value)
PyObject * BPy_BMEditSel_CreatePyObject(BMesh *bm)
PyTypeObject BPy_BMEditSelSeq_Type
PyTypeObject BPy_BMEditSelIter_Type
BMEdge * BM_edge_exists(BMVert *v_a, BMVert *v_b)
Definition: bmesh_query.c:1553
bool BM_vert_is_wire(const BMVert *v)
Definition: bmesh_query.c:688
void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3])
BM_loop_calc_face_tangent.
Definition: bmesh_query.c:1299
bool BM_vert_is_manifold(const BMVert *v)
Definition: bmesh_query.c:705
float BM_vert_calc_shell_factor(const BMVert *v)
Definition: bmesh_query.c:1420
float BM_vert_calc_edge_angle_ex(const BMVert *v, const float fallback)
BMESH VERT/EDGE ANGLE.
Definition: bmesh_query.c:1397
BMFace * BM_face_exists(BMVert **varr, int len)
Definition: bmesh_query.c:1612
float BM_edge_calc_face_angle_ex(const BMEdge *e, const float fallback)
BMESH EDGE/FACE ANGLE.
Definition: bmesh_query.c:1329
bool BM_loop_is_convex(const BMLoop *l)
Definition: bmesh_query.c:1180
double BM_mesh_calc_volume(BMesh *bm, bool is_signed)
Definition: bmesh_query.c:2076
float BM_loop_calc_face_angle(const BMLoop *l)
Definition: bmesh_query.c:1192
float BM_edge_calc_face_angle_signed_ex(const BMEdge *e, const float fallback)
BMESH EDGE/FACE ANGLE.
Definition: bmesh_query.c:1369
void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r_tangent[3])
BMESH EDGE/FACE TANGENT.
Definition: bmesh_query.c:1384
float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
BM_loop_calc_face_normal.
Definition: bmesh_query.c:1270
bool BM_vert_is_boundary(const BMVert *v)
Definition: bmesh_query.c:916
bool BM_edge_is_convex(const BMEdge *e)
Definition: bmesh_query.c:858
BLI_INLINE bool BM_edge_is_contiguous(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_manifold(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE BMVert * BM_edge_other_vert(BMEdge *e, const BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
BLI_INLINE bool BM_edge_is_wire(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
Definition: bpy_driver.c:165
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
const Depsgraph * depsgraph
int len
Definition: draw_manager.c:108
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
int count
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition: mathutils.c:98
#define BaseMath_ReadCallback(_self)
Definition: mathutils.h:119
PyTypeObject matrix_Type
PyObject * Vector_CreatePyObject_wrap(float *vec, const int vec_num, PyTypeObject *base_type)
PyObject * Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
PyObject * PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag)
void * PyC_RNA_AsPointer(PyObject *value, const char *type_name)
int PyC_Long_AsBool(PyObject *value)
int PyC_FlagSet_ToBitfield(const PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix)
int PyC_ParseBool(PyObject *o, void *p)
return ret
#define min(a, b)
Definition: sort.c:35
BMHeader head
Definition: bmesh_class.h:243
int len
Definition: bmesh_class.h:267
BMHeader head
Definition: bmesh_class.h:255
char htype
Definition: bmesh_class.h:64
int index
Definition: bmesh_class.h:61
void * data
Definition: bmesh_class.h:51
BMHeader head
Definition: bmesh_class.h:145
struct BMVert * v
Definition: bmesh_class.h:153
struct BMEdge * e
Definition: bmesh_class.h:164
struct BMFace * f
Definition: bmesh_class.h:171
float co[3]
Definition: bmesh_class.h:87
struct BMEdge * e
Definition: bmesh_class.h:97
BMHeader head
Definition: bmesh_class.h:85
int totvert
Definition: bmesh_class.h:297
char elem_index_dirty
Definition: bmesh_class.h:305
CustomData vdata
Definition: bmesh_class.h:337
int totedge
Definition: bmesh_class.h:297
CustomData edata
Definition: bmesh_class.h:337
int totloop
Definition: bmesh_class.h:297
void * py_handle
Definition: bmesh_class.h:378
BMFace * act_face
Definition: bmesh_class.h:366
CustomData pdata
Definition: bmesh_class.h:337
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
PyObject_VAR_HEAD struct BMesh * bm
struct BMEdge * e
struct BMElem * ele
PyObject_VAR_HEAD struct BMesh * bm
struct BMFace * f
PyObject_VAR_HEAD struct BMesh * bm
struct BMLoop * l
PyObject_VAR_HEAD struct BMesh * bm
struct BMVert * v
int tag
Definition: DNA_ID.h:387
char name[66]
Definition: DNA_ID.h:378
Definition: BKE_main.h:121
struct BMEditMesh * edit_mesh
float max
PointerRNA * ptr
Definition: wm_files.c:3480