2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2012 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Campbell Barton
23 * ***** END GPL LICENSE BLOCK *****
26 /** \file blender/python/bmesh/bmesh_py_types.c
34 #include "DNA_mesh_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_material_types.h"
38 #include "BKE_depsgraph.h"
39 #include "BKE_customdata.h"
40 #include "BKE_DerivedMesh.h"
44 #include "../mathutils/mathutils.h"
46 #include "../generic/py_capi_utils.h"
48 #include "bmesh_py_types.h" /* own include */
49 #include "bmesh_py_types_select.h"
50 #include "bmesh_py_types_customdata.h"
51 #include "bmesh_py_types_meshdata.h"
56 /* scene does not use BM_* flags. */
57 PyC_FlagSet bpy_bm_scene_vert_edge_face_flags[] = {
64 PyC_FlagSet bpy_bm_htype_vert_edge_face_flags[] = {
71 PyC_FlagSet bpy_bm_htype_all_flags[] = {
79 PyC_FlagSet bpy_bm_hflag_all_flags[] = {
80 {BM_ELEM_SELECT, "SELECT"},
81 {BM_ELEM_HIDDEN, "HIDE"},
82 {BM_ELEM_SEAM, "SEAM"},
83 {BM_ELEM_SMOOTH, "SMOOTH"},
88 /* py-type definitions
89 * ******************* */
98 PyDoc_STRVAR(bpy_bm_elem_select_doc, "Selected state of this element.\n\n:type: boolean");
99 PyDoc_STRVAR(bpy_bm_elem_hide_doc, "Hidden state of this element.\n\n:type: boolean");
100 PyDoc_STRVAR(bpy_bm_elem_tag_doc, "Generic attribute scripts can use for own logic\n\n:type: boolean");
101 PyDoc_STRVAR(bpy_bm_elem_smooth_doc, "Smooth state of this element.\n\n:type: boolean");
102 PyDoc_STRVAR(bpy_bm_elem_seam_doc, "Seam for UV unwrapping.\n\n:type: boolean");
105 static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
107 const char hflag = (char)GET_INT_FROM_POINTER(flag);
109 BPY_BM_CHECK_OBJ(self);
111 return PyBool_FromLong(BM_elem_flag_test(self->ele, hflag));
114 static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
116 const char hflag = (char)GET_INT_FROM_POINTER(flag);
119 BPY_BM_CHECK_INT(self);
121 param = PyLong_AsLong(value);
124 BM_elem_flag_enable(self->ele, hflag);
127 else if (param == FALSE) {
128 BM_elem_flag_disable(self->ele, hflag);
132 PyErr_Format(PyExc_TypeError,
133 "expected True/False or 0/1, not %.200s",
134 Py_TYPE(value)->tp_name);
140 PyDoc_STRVAR(bpy_bm_elem_index_doc,
141 "Index of this element.\n"
147 " This value is not necessarily valid, while editing the mesh it can become *dirty*.\n"
149 " It's also possible to assign any number to this attribute for a scripts internal logic.\n"
151 " To ensure the value is up to date - see :class:`BMElemSeq.index_update`.\n"
153 static PyObject *bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
155 BPY_BM_CHECK_OBJ(self);
157 return PyLong_FromLong(BM_elem_index_get(self->ele));
160 static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
164 BPY_BM_CHECK_INT(self);
166 param = PyLong_AsLong(value);
168 if (param == -1 && PyErr_Occurred()) {
169 PyErr_SetString(PyExc_TypeError,
170 "expected an int type");
174 BM_elem_index_set(self->ele, param); /* set_dirty! */
176 /* when setting the index assume its set invalid */
177 if (self->ele->head.htype & (BM_VERT | BM_EDGE | BM_FACE)) {
178 self->bm->elem_index_dirty |= self->ele->head.htype;
185 /* type specific get/sets
186 * ---------------------- */
192 /* doc-strings for all uses of this function */
194 PyDoc_STRVAR(bpy_bmvertseq_doc,
195 "This meshes vert sequence (read-only).\n\n:type: :class:`BMVertSeq`"
197 static PyObject *bpy_bmvertseq_get(BPy_BMesh *self, void *UNUSED(closure))
199 BPY_BM_CHECK_OBJ(self);
200 return BPy_BMVertSeq_CreatePyObject(self->bm);
203 PyDoc_STRVAR(bpy_bmedgeseq_doc,
204 "This meshes edge sequence (read-only).\n\n:type: :class:`BMEdgeSeq`"
206 static PyObject *bpy_bmedgeseq_get(BPy_BMesh *self, void *UNUSED(closure))
208 BPY_BM_CHECK_OBJ(self);
209 return BPy_BMEdgeSeq_CreatePyObject(self->bm);
212 PyDoc_STRVAR(bpy_bmfaceseq_doc,
213 "This meshes face sequence (read-only).\n\n:type: :class:`BMFaceSeq`"
215 static PyObject *bpy_bmfaceseq_get(BPy_BMesh *self, void *UNUSED(closure))
217 BPY_BM_CHECK_OBJ(self);
218 return BPy_BMFaceSeq_CreatePyObject(self->bm);
221 PyDoc_STRVAR(bpy_bmloopseq_doc,
222 "This meshes face sequence (read-only).\n\n:type: :class:`BMLoopSeq`"
224 static PyObject *bpy_bmloopseq_get(BPy_BMesh *self, void *UNUSED(closure))
226 BPY_BM_CHECK_OBJ(self);
227 return BPy_BMLoopSeq_CreatePyObject(self->bm);
231 PyDoc_STRVAR(bpy_bmvert_link_edges_doc,
232 "Edges connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
234 PyDoc_STRVAR(bpy_bmvert_link_faces_doc,
235 "Faces connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
237 PyDoc_STRVAR(bpy_bmvert_link_loops_doc,
238 "Loops that use this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
241 PyDoc_STRVAR(bpy_bmedge_verts_doc,
242 "Verts this edge uses (always 2), (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
244 PyDoc_STRVAR(bpy_bmedge_link_faces_doc,
245 "Faces connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
247 PyDoc_STRVAR(bpy_bmedge_link_loops_doc,
248 "Loops connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
251 PyDoc_STRVAR(bpy_bmface_verts_doc,
252 "Verts of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
254 PyDoc_STRVAR(bpy_bmface_edges_doc,
255 "Edges of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMEdge`"
257 PyDoc_STRVAR(bpy_bmface_loops_doc,
258 "Loops of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
261 PyDoc_STRVAR(bpy_bmloops_link_loops_doc,
262 "Loops connected to this loop, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
265 static PyObject *bpy_bmelemseq_elem_get(BPy_BMElem *self, void *itype)
267 BPY_BM_CHECK_OBJ(self);
268 return BPy_BMElemSeq_CreatePyObject(self->bm, self, GET_INT_FROM_POINTER(itype));
272 PyDoc_STRVAR(bpy_bm_is_valid_doc,
273 "True when this element is valid (hasn't been removed).\n\n:type: boolean"
275 static PyObject *bpy_bm_is_valid_get(BPy_BMGeneric *self)
277 return PyBool_FromLong(BPY_BM_IS_VALID(self));
280 PyDoc_STRVAR(bpy_bmesh_is_wrapped_doc,
281 "True when this mesh is owned by blender (typically the editmode BMesh).\n\n:type: boolean"
283 static PyObject *bpy_bmesh_is_wrapped_get(BPy_BMesh *self)
285 BPY_BM_CHECK_OBJ(self);
287 return PyBool_FromLong(self->flag & BPY_BMFLAG_IS_WRAPPED);
290 PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
291 "The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an empty set.\n\n:type: set"
293 static PyObject *bpy_bmesh_select_mode_get(BPy_BMesh *self)
295 BPY_BM_CHECK_OBJ(self);
297 return PyC_FlagSet_FromBitfield(bpy_bm_scene_vert_edge_face_flags, self->bm->selectmode);
300 static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
303 BPY_BM_CHECK_INT(self);
305 if (PyC_FlagSet_ToBitfield(bpy_bm_scene_vert_edge_face_flags, value, &flag, "bm.select_mode") == -1) {
308 else if (flag == 0) {
309 PyErr_SetString(PyExc_TypeError,
310 "bm.select_mode: cant assignt an empty value");
314 self->bm->selectmode = flag;
319 PyDoc_STRVAR(bpy_bmesh_select_history_doc,
320 "Sequence of selected items (the last is displayed as active).\n\n:type: :class:`BMEditSelSeq`"
322 static PyObject *bpy_bmesh_select_history_get(BPy_BMesh *self)
324 BPY_BM_CHECK_OBJ(self);
326 return BPy_BMEditSel_CreatePyObject(self->bm);
329 static int bpy_bmesh_select_history_set(BPy_BMesh *self, PyObject *value)
331 BPY_BM_CHECK_INT(self);
333 return BPy_BMEditSel_Assign(self, value);
339 PyDoc_STRVAR(bpy_bmvert_co_doc,
340 "The coordinates for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
342 static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
344 BPY_BM_CHECK_OBJ(self);
345 return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
348 static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
350 BPY_BM_CHECK_INT(self);
352 if (mathutils_array_parse(self->v->co, 3, 3, value, "BMVert.co") != -1) {
361 PyDoc_STRVAR(bpy_bmvert_normal_doc,
362 "The normal for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
364 static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
366 BPY_BM_CHECK_OBJ(self);
367 return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
370 static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
372 BPY_BM_CHECK_INT(self);
374 if (mathutils_array_parse(self->v->no, 3, 3, value, "BMVert.normal") != -1) {
383 PyDoc_STRVAR(bpy_bmvert_is_manifold_doc,
384 "True when this vertex is manifold (read-only).\n\n:type: boolean"
386 static PyObject *bpy_bmvert_is_manifold_get(BPy_BMVert *self)
388 BPY_BM_CHECK_OBJ(self);
389 return PyBool_FromLong(BM_vert_is_manifold(self->v));
393 PyDoc_STRVAR(bpy_bmvert_is_wire_doc,
394 "True when this vertex is not connected to any faces (read-only).\n\n:type: boolean"
396 static PyObject *bpy_bmvert_is_wire_get(BPy_BMVert *self)
398 BPY_BM_CHECK_OBJ(self);
399 return PyBool_FromLong(BM_vert_is_wire(self->v));
406 PyDoc_STRVAR(bpy_bmedge_is_manifold_doc,
407 "True when this edge is manifold (read-only).\n\n:type: boolean"
409 static PyObject *bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
411 BPY_BM_CHECK_OBJ(self);
412 return PyBool_FromLong(BM_edge_is_manifold(self->e));
416 PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
417 "True when this edge is not connected to any faces (read-only).\n\n:type: boolean"
419 static PyObject *bpy_bmedge_is_wire_get(BPy_BMEdge *self)
421 BPY_BM_CHECK_OBJ(self);
422 return PyBool_FromLong(BM_edge_is_wire(self->e));
426 PyDoc_STRVAR(bpy_bmedge_is_boundary_doc,
427 "True when this edge is at the boundary of a face (read-only).\n\n:type: boolean"
429 static PyObject *bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
431 BPY_BM_CHECK_OBJ(self);
432 return PyBool_FromLong(BM_edge_is_boundary(self->e));
439 PyDoc_STRVAR(bpy_bmface_normal_doc,
440 "The normal for this face as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
442 static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
444 BPY_BM_CHECK_OBJ(self);
445 return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
448 static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
450 BPY_BM_CHECK_INT(self);
452 if (mathutils_array_parse(self->f->no, 3, 3, value, "BMFace.normal") != -1) {
460 PyDoc_STRVAR(bpy_bmface_material_index_doc,
461 "The faces material index.\n\n:type: int"
463 static PyObject *bpy_bmface_material_index_get(BPy_BMFace *self)
465 BPY_BM_CHECK_OBJ(self);
466 return PyLong_FromLong(self->f->mat_nr);
469 static int bpy_bmface_material_index_set(BPy_BMFace *self, PyObject *value)
473 BPY_BM_CHECK_INT(self);
475 param = PyLong_AsLong(value);
477 if (param == -1 && PyErr_Occurred()) {
478 PyErr_SetString(PyExc_TypeError,
479 "expected an int type");
482 else if ((param < 0) || (param > MAXMAT)) {
483 /* normally we clamp but in this case raise an error */
484 PyErr_SetString(PyExc_ValueError,
485 "material index outside of usable range (0 - 32766)");
489 self->f->mat_nr = (short)param;
497 PyDoc_STRVAR(bpy_bmloop_vert_doc,
498 "The loops vertex (read-only).\n\n:type: :class:`BMVert`"
500 static PyObject *bpy_bmloop_vert_get(BPy_BMLoop *self)
502 BPY_BM_CHECK_OBJ(self);
503 return BPy_BMVert_CreatePyObject(self->bm, self->l->v);
507 PyDoc_STRVAR(bpy_bmloop_edge_doc,
508 "The loops edge (between this loop and the next), (read-only).\n\n:type: :class:`BMEdge`"
510 static PyObject *bpy_bmloop_edge_get(BPy_BMLoop *self)
512 BPY_BM_CHECK_OBJ(self);
513 return BPy_BMEdge_CreatePyObject(self->bm, self->l->e);
517 PyDoc_STRVAR(bpy_bmloop_face_doc,
518 "The face this loop makes (read-only).\n\n:type: :class:`BMFace`"
520 static PyObject *bpy_bmloop_face_get(BPy_BMLoop *self)
522 BPY_BM_CHECK_OBJ(self);
523 return BPy_BMFace_CreatePyObject(self->bm, self->l->f);
526 PyDoc_STRVAR(bpy_bmloop_link_loop_next_doc,
527 "The next face corner (read-only).\n\n:type: :class:`BMLoop`"
529 static PyObject *bpy_bmloop_link_loop_next_get(BPy_BMLoop *self)
531 BPY_BM_CHECK_OBJ(self);
532 return BPy_BMLoop_CreatePyObject(self->bm, self->l->next);
535 PyDoc_STRVAR(bpy_bmloop_link_loop_prev_doc,
536 "The previous face corner (read-only).\n\n:type: :class:`BMLoop`"
538 static PyObject *bpy_bmloop_link_loop_prev_get(BPy_BMLoop *self)
540 BPY_BM_CHECK_OBJ(self);
541 return BPy_BMLoop_CreatePyObject(self->bm, self->l->prev);
544 PyDoc_STRVAR(bpy_bmloop_link_loop_radial_next_doc,
545 "The next loop around the edge (read-only).\n\n:type: :class:`BMLoop`"
547 static PyObject *bpy_bmloop_link_loop_radial_next_get(BPy_BMLoop *self)
549 BPY_BM_CHECK_OBJ(self);
550 return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_next);
553 PyDoc_STRVAR(bpy_bmloop_link_loop_radial_prev_doc,
554 "The previous loop around the edge (read-only).\n\n:type: :class:`BMLoop`"
556 static PyObject *bpy_bmloop_link_loop_radial_prev_get(BPy_BMLoop *self)
558 BPY_BM_CHECK_OBJ(self);
559 return BPy_BMLoop_CreatePyObject(self->bm, self->l->radial_prev);
565 /* note: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly */
566 PyDoc_STRVAR(bpy_bmelemseq_layers_doc,
567 "custom-data layers (read-only).\n\n:type: :class:`BMLayerAccess`"
569 static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype)
571 BPY_BM_CHECK_OBJ(self);
573 return BPy_BMLayerAccess_CreatePyObject(self->bm, GET_INT_FROM_POINTER(htype));
579 PyDoc_STRVAR(bpy_bmfaceseq_active_doc,
580 "active face.\n\n:type: :class:`BMFace` or None"
582 static PyObject *bpy_bmfaceseq_active_get(BPy_BMElemSeq *self, void *UNUSED(closure))
584 BMesh *bm = self->bm;
585 BPY_BM_CHECK_OBJ(self);
588 return BPy_BMElem_CreatePyObject(bm, (BMHeader *)bm->act_face);
595 static int bpy_bmfaceseq_active_set(BPy_BMElem *self, PyObject *value, void *UNUSED(closure))
597 BMesh *bm = self->bm;
598 if (value == Py_None) {
602 else if (BPy_BMFace_Check(value)) {
603 BPY_BM_CHECK_SOURCE_INT(value, bm, "faces.active = f");
605 bm->act_face = ((BPy_BMFace *)value)->f;
609 PyErr_Format(PyExc_TypeError,
610 "faces.active = f: expected BMFace or None, not %.200s",
611 Py_TYPE(value)->tp_name);
616 static PyGetSetDef bpy_bmesh_getseters[] = {
617 {(char *)"verts", (getter)bpy_bmvertseq_get, (setter)NULL, (char *)bpy_bmvertseq_doc, NULL},
618 {(char *)"edges", (getter)bpy_bmedgeseq_get, (setter)NULL, (char *)bpy_bmedgeseq_doc, NULL},
619 {(char *)"faces", (getter)bpy_bmfaceseq_get, (setter)NULL, (char *)bpy_bmfaceseq_doc, NULL},
620 {(char *)"loops", (getter)bpy_bmloopseq_get, (setter)NULL, (char *)bpy_bmloopseq_doc, NULL},
621 {(char *)"select_mode", (getter)bpy_bmesh_select_mode_get, (setter)bpy_bmesh_select_mode_set, (char *)bpy_bmesh_select_mode_doc, NULL},
623 {(char *)"select_history", (getter)bpy_bmesh_select_history_get, (setter)bpy_bmesh_select_history_set, (char *)bpy_bmesh_select_history_doc, NULL},
625 /* readonly checks */
626 {(char *)"is_wrapped", (getter)bpy_bmesh_is_wrapped_get, (setter)NULL, (char *)bpy_bmesh_is_wrapped_doc, NULL}, /* as with mathutils */
627 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
629 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
632 static PyGetSetDef bpy_bmvert_getseters[] = {
634 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
635 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_HIDDEN},
636 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
637 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
639 {(char *)"co", (getter)bpy_bmvert_co_get, (setter)bpy_bmvert_co_set, (char *)bpy_bmvert_co_doc, NULL},
640 {(char *)"normal", (getter)bpy_bmvert_normal_get, (setter)bpy_bmvert_normal_set, (char *)bpy_bmvert_normal_doc, NULL},
642 /* connectivity data */
643 {(char *)"link_edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_edges_doc, (void *)BM_EDGES_OF_VERT},
644 {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_faces_doc, (void *)BM_FACES_OF_VERT},
645 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_loops_doc, (void *)BM_LOOPS_OF_VERT},
647 /* readonly checks */
648 {(char *)"is_manifold", (getter)bpy_bmvert_is_manifold_get, (setter)NULL, (char *)bpy_bmvert_is_manifold_doc, NULL},
649 {(char *)"is_wire", (getter)bpy_bmvert_is_wire_get, (setter)NULL, (char *)bpy_bmvert_is_wire_doc, NULL},
650 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
652 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
655 static PyGetSetDef bpy_bmedge_getseters[] = {
657 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
658 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_HIDDEN},
659 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
660 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
662 {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
663 {(char *)"seam", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_seam_doc, (void *)BM_ELEM_SEAM},
665 /* connectivity data */
666 {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_verts_doc, (void *)BM_VERTS_OF_EDGE},
668 {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_faces_doc, (void *)BM_FACES_OF_EDGE},
669 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_loops_doc, (void *)BM_LOOPS_OF_EDGE},
671 /* readonly checks */
672 {(char *)"is_manifold", (getter)bpy_bmedge_is_manifold_get, (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
673 {(char *)"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
674 {(char *)"is_boundary", (getter)bpy_bmedge_is_boundary_get, (setter)NULL, (char *)bpy_bmedge_is_boundary_doc, NULL},
675 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
677 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
680 static PyGetSetDef bpy_bmface_getseters[] = {
682 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
683 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_HIDDEN},
684 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
685 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
687 {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
689 {(char *)"normal", (getter)bpy_bmface_normal_get, (setter)bpy_bmface_normal_set, (char *)bpy_bmface_normal_doc, NULL},
691 {(char *)"material_index", (getter)bpy_bmface_material_index_get, (setter)bpy_bmface_material_index_set, (char *)bpy_bmface_material_index_doc, NULL},
693 /* connectivity data */
694 {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_verts_doc, (void *)BM_VERTS_OF_FACE},
695 {(char *)"edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_edges_doc, (void *)BM_EDGES_OF_FACE},
696 {(char *)"loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_loops_doc, (void *)BM_LOOPS_OF_FACE},
698 /* readonly checks */
699 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
701 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
704 static PyGetSetDef bpy_bmloop_getseters[] = {
706 /* flags are available but not used for loops. */
707 // {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
708 // {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_HIDDEN},
709 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
710 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
712 {(char *)"vert", (getter)bpy_bmloop_vert_get, (setter)NULL, (char *)bpy_bmloop_vert_doc, NULL},
713 {(char *)"edge", (getter)bpy_bmloop_edge_get, (setter)NULL, (char *)bpy_bmloop_edge_doc, NULL},
714 {(char *)"face", (getter)bpy_bmloop_face_get, (setter)NULL, (char *)bpy_bmloop_face_doc, NULL},
716 /* connectivity data */
717 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmloops_link_loops_doc, (void *)BM_LOOPS_OF_LOOP},
718 {(char *)"link_loop_next", (getter)bpy_bmloop_link_loop_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_next_doc, NULL},
719 {(char *)"link_loop_prev", (getter)bpy_bmloop_link_loop_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_prev_doc, NULL},
720 {(char *)"link_loop_radial_next", (getter)bpy_bmloop_link_loop_radial_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_next_doc, NULL},
721 {(char *)"link_loop_radial_prev", (getter)bpy_bmloop_link_loop_radial_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_radial_prev_doc, NULL},
723 /* readonly checks */
724 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
726 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
729 static PyGetSetDef bpy_bmvertseq_getseters[] = {
730 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_VERT},
731 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
733 static PyGetSetDef bpy_bmedgeseq_getseters[] = {
734 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_EDGE},
735 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
737 static PyGetSetDef bpy_bmfaceseq_getseters[] = {
738 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_FACE},
740 {(char *)"active", (getter)bpy_bmfaceseq_active_get, (setter)bpy_bmfaceseq_active_set, (char *)bpy_bmfaceseq_active_doc, NULL},
741 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
743 static PyGetSetDef bpy_bmloopseq_getseters[] = {
744 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_LOOP},
745 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
756 PyDoc_STRVAR(bpy_bmesh_copy_doc,
757 ".. method:: copy()\n"
759 " :return: A copy of this BMesh.\n"
760 " :rtype: :class:`BMesh`\n"
762 static PyObject *bpy_bmesh_copy(BPy_BMesh *self)
767 BPY_BM_CHECK_OBJ(self);
771 bm_copy = BM_mesh_copy(bm);
774 return BPy_BMesh_CreatePyObject(bm_copy, BPY_BMFLAG_NOP);
777 PyErr_SetString(PyExc_SystemError, "Unable to copy BMesh, internal error");
782 PyDoc_STRVAR(bpy_bmesh_clear_doc,
783 ".. method:: clear()\n"
785 " Clear all mesh data.\n"
787 static PyObject *bpy_bmesh_clear(BPy_BMesh *self)
791 BPY_BM_CHECK_OBJ(self);
800 PyDoc_STRVAR(bpy_bmesh_free_doc,
801 ".. method:: free()\n"
803 " Explicitly free the BMesh data from memory, causing exceptions on further access.\n"
807 " The BMesh is freed automatically, typically when the script finishes executing.\n"
808 " However in some cases its hard to predict when this will be and its useful to\n"
809 " explicitly free the data.\n"
811 static PyObject *bpy_bmesh_free(BPy_BMesh *self)
814 BMesh *bm = self->bm;
816 if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
820 bpy_bm_generic_invalidate((BPy_BMGeneric *)self);
826 PyDoc_STRVAR(bpy_bmesh_to_mesh_doc,
827 ".. method:: to_mesh(mesh)\n"
829 " Writes this BMesh data into an existing Mesh datablock.\n"
831 " :arg mesh: The mesh data to write into.\n"
832 " :type mesh: :class:`Mesh`\n"
834 static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
840 BPY_BM_CHECK_OBJ(self);
842 if (!PyArg_ParseTuple(args, "O:to_mesh", &py_mesh) ||
843 !(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
848 /* we could allow this but its almost certainly _not_ what script authors want */
849 if (me->edit_btmesh) {
850 PyErr_Format(PyExc_ValueError,
851 "to_mesh(): Mesh '%s' is in editmode", me->id.name + 2);
857 BM_mesh_bm_to_me(bm, me, FALSE);
859 /* we could have the user do this but if they forget blender can easy crash
860 * since the references arrays for the objects derived meshes are now invalid */
861 DAG_id_tag_update(&me->id, OB_RECALC_DATA);
866 PyDoc_STRVAR(bpy_bmesh_from_object_doc,
867 ".. method:: from_object(object, scene, deform=True, render=False, cage=False)\n"
869 " Initialize this bmesh from existing object datablock (currently only meshes are supported).\n"
871 " :arg object: The object data to load.\n"
872 " :type object: :class:`Object`\n"
873 " :arg deform: Apply deformation modifiers.\n"
874 " :type deform: boolean\n"
875 " :arg render: Use render settings.\n"
876 " :type render: boolean\n"
877 " :arg cage: Get the mesh as a deformed cage.\n"
878 " :type cage: boolean\n"
880 static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args)
887 int use_deform = TRUE;
888 int use_render = FALSE;
889 int use_cage = FALSE;
891 const int mask = CD_MASK_BMESH;
893 BPY_BM_CHECK_OBJ(self);
895 if (!PyArg_ParseTuple(args, "OO|iii:from_object", &py_object, &py_scene, &use_render, &use_cage) ||
896 !(ob = PyC_RNA_AsPointer(py_object, "Object")) ||
897 !(scene = PyC_RNA_AsPointer(py_scene, "Scene")))
902 if (ob->type != OB_MESH) {
903 PyErr_SetString(PyExc_ValueError,
904 "from_object(...): currently only mesh objects are supported");
908 /* Write the display mesh into the dummy mesh */
912 PyErr_SetString(PyExc_ValueError,
913 "from_object(...): cage arg is unsupported when (render=True)");
917 dm = mesh_create_derived_render(scene, ob, mask);
922 dm = mesh_get_derived_deform(scene, ob, mask); /* ob->derivedDeform */
925 dm = mesh_get_derived_final(scene, ob, mask); /* ob->derivedFinal */
933 PyErr_SetString(PyExc_ValueError,
934 "from_object(...): cage arg is unsupported when (render=True)");
938 dm = mesh_create_derived_no_deform_render(scene, ob, NULL, mask);
943 PyErr_SetString(PyExc_ValueError,
944 "from_object(...): cage arg is unsupported when (deform=False, render=False)");
948 dm = mesh_create_derived_no_deform(scene, ob, NULL, mask);
954 PyErr_Format(PyExc_ValueError,
955 "from_object(...): Object '%s' has no usable mesh data", ob->id.name + 2);
961 DM_to_bmesh_ex(dm, bm);
969 PyDoc_STRVAR(bpy_bmesh_from_mesh_doc,
970 ".. method:: from_mesh(mesh, use_shape_key=False, shape_key_index=0)\n"
972 " Initialize this bmesh from existing mesh datablock.\n"
974 " :arg mesh: The mesh data to load.\n"
975 " :type mesh: :class:`Mesh`\n"
976 " :arg use_shape_key: Use the locations from a shape key.\n"
977 " :type use_shape_key: boolean\n"
978 " :arg shape_key_index: The shape key index to use.\n"
979 " :type shape_key_index: int\n"
981 static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *kw)
983 static const char *kwlist[] = {"mesh", "use_shape_key", "shape_key_index", NULL};
987 int use_shape_key = FALSE;
988 int shape_key_index = 0;
990 if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:from_mesh", (char **)kwlist,
991 &py_mesh, &use_shape_key, &shape_key_index) ||
992 !(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
999 BM_mesh_bm_from_me(bm, me, use_shape_key, shape_key_index + 1);
1005 PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc,
1006 ".. method:: select_flush_mode()\n"
1008 " flush selection based on the current mode current :class:`BMesh.select_mode`.\n"
1010 static PyObject *bpy_bmesh_select_flush_mode(BPy_BMesh *self)
1012 BPY_BM_CHECK_OBJ(self);
1014 BM_mesh_select_mode_flush(self->bm);
1020 PyDoc_STRVAR(bpy_bmesh_select_flush_doc,
1021 ".. method:: select_flush(select)\n"
1023 " Flush selection, independent of the current selection mode.\n"
1025 " :arg select: flush selection or de-selected elements.\n"
1026 " :type select: boolean\n"
1028 static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
1032 BPY_BM_CHECK_OBJ(self);
1034 param = PyLong_AsLong(value);
1035 if (param != FALSE && param != TRUE) {
1036 PyErr_SetString(PyExc_TypeError,
1037 "expected a boolean type 0/1");
1041 if (param) BM_mesh_select_flush(self->bm);
1042 else BM_mesh_deselect_flush(self->bm);
1048 PyDoc_STRVAR(bpy_bmesh_normal_update_doc,
1049 ".. method:: normal_update(skip_hidden=False)\n"
1051 " Update mesh normals.\n"
1053 " :arg skip_hidden: When True hidden elements are ignored.\n"
1054 " :type skip_hidden: boolean\n"
1056 static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self, PyObject *args)
1059 int skip_hidden = FALSE;
1061 BPY_BM_CHECK_OBJ(self);
1063 if (!PyArg_ParseTuple(args, "|i:normal_update", &skip_hidden)) {
1067 BM_mesh_normals_update(self->bm, skip_hidden);
1073 PyDoc_STRVAR(bpy_bmesh_transform_doc,
1074 ".. method:: transform(matrix, filter=None)\n"
1076 " Transform the mesh (optionally filtering flagged data only).\n"
1078 " :arg matrix: transform matrix.\n"
1079 " :type matrix: 4x4 :class:`mathutils.Matrix`\n"
1080 " :arg filter: set of values in ('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG').\n"
1081 " :type filter: set\n"
1083 static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
1085 static const char *kwlist[] = {"matrix", "filter", NULL};
1088 PyObject *filter = NULL;
1089 int filter_flags = 0;
1091 BPY_BM_CHECK_OBJ(self);
1093 if (!PyArg_ParseTupleAndKeywords(args, kw,
1097 &PySet_Type, &filter))
1106 if (BaseMath_ReadCallback(mat) == -1) {
1109 else if (mat->num_col != 4 || mat->num_row != 4) {
1110 PyErr_SetString(PyExc_ValueError,
1111 "expected a 4x4 matrix");
1115 if (filter != NULL && PyC_FlagSet_ToBitfield(bpy_bm_hflag_all_flags, filter,
1116 &filter_flags, "bm.transform") == -1)
1121 mat_ptr = mat->matrix;
1123 if (!filter_flags) {
1124 BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1125 mul_m4_v3((float (*)[4])mat_ptr, eve->co);
1129 char filter_flags_ch = (char)filter_flags;
1130 BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1131 if (eve->head.hflag & filter_flags_ch) {
1132 mul_m4_v3((float (*)[4])mat_ptr, eve->co);
1145 PyDoc_STRVAR(bpy_bm_elem_select_set_doc,
1146 ".. method:: select_set(select)\n"
1148 " Set the selection.\n"
1149 " This is different from the *select* attribute because it updates the selection state of associated geometry.\n"
1151 " :arg select: Select or de-select.\n"
1152 " :type select: boolean\n"
1156 " Currently this only flushes down, so selecting a face will select all its vertices but de-selecting a vertex "
1157 " won't de-select all the faces that use it, before finishing with a mesh typically flushing is still needed.\n"
1159 static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
1163 BPY_BM_CHECK_OBJ(self);
1165 param = PyLong_AsLong(value);
1166 if (param != FALSE && param != TRUE) {
1167 PyErr_SetString(PyExc_TypeError,
1168 "expected a boolean type 0/1");
1172 BM_elem_select_set(self->bm, self->ele, param);
1178 PyDoc_STRVAR(bpy_bm_elem_hide_set_doc,
1179 ".. method:: hide_set(hide)\n"
1181 " Set the hide state.\n"
1182 " This is different from the *hide* attribute because it updates the selection and hide state of associated geometry.\n"
1184 " :arg hide: Hidden or visible.\n"
1185 " :type hide: boolean\n"
1187 static PyObject *bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value)
1191 BPY_BM_CHECK_OBJ(self);
1193 param = PyLong_AsLong(value);
1194 if (param != FALSE && param != TRUE) {
1195 PyErr_SetString(PyExc_TypeError,
1196 "expected a boolean type 0/1");
1200 BM_elem_hide_set(self->bm, self->ele, param);
1206 PyDoc_STRVAR(bpy_bm_elem_copy_from_doc,
1207 ".. method:: copy_from(other)\n"
1209 " Copy values from another element of matching type.\n"
1211 static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
1213 BPY_BM_CHECK_OBJ(self);
1215 if (Py_TYPE(self) != Py_TYPE(value)) {
1216 PyErr_Format(PyExc_TypeError,
1217 "expected element of type '%.200s' not '%.200s'",
1218 Py_TYPE(self)->tp_name, Py_TYPE(value)->tp_name);
1222 if (value->ele != self->ele) {
1223 BM_elem_attrs_copy(value->bm, self->bm, value->ele, self->ele);
1234 PyDoc_STRVAR(bpy_bmvert_copy_from_vert_interp_doc,
1235 ".. method:: copy_from_vert_interp(vert_pair, fac)\n"
1237 " Interpolate the customdata from a vert between 2 other verts.\n"
1239 " :arg vert_pair: The vert to interpolate data from.\n"
1240 " :type vert_pair: :class:`BMVert`\n"
1242 static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *args)
1247 BPY_BM_CHECK_OBJ(self);
1249 if (!PyArg_ParseTuple(args, "Of:BMVert.copy_from_vert_interp",
1255 BMesh *bm = self->bm;
1256 BMVert **vert_array = NULL;
1257 Py_ssize_t vert_seq_len; /* always 2 */
1259 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1260 &vert_seq_len, BM_VERT,
1261 TRUE, TRUE, "BMVert.copy_from_vert_interp(...)");
1263 if (vert_array == NULL) {
1267 BM_data_interp_from_verts(bm, vert_array[0], vert_array[1], self->v, CLAMPIS(fac, 0.0f, 1.0f));
1269 PyMem_FREE(vert_array);
1275 PyDoc_STRVAR(bpy_bmvert_copy_from_face_interp_doc,
1276 ".. method:: copy_from_face_interp(face)\n"
1278 " Interpolate the customdata from a face onto this loop (the loops vert should overlap the face).\n"
1280 " :arg face: The face to interpolate data from.\n"
1281 " :type face: :class:`BMFace`\n"
1283 static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *args)
1285 BPy_BMFace *py_face = NULL;
1287 BPY_BM_CHECK_OBJ(self);
1289 if (!PyArg_ParseTuple(args, "O!:BMVert.copy_from_face_interp",
1290 &BPy_BMFace_Type, &py_face))
1295 BMesh *bm = self->bm;
1297 BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "copy_from_face_interp()");
1299 BM_vert_interp_from_face(bm, self->v, py_face->f);
1306 PyDoc_STRVAR(bpy_bmvert_calc_edge_angle_doc,
1307 ".. method:: calc_edge_angle()\n"
1309 " Return the angle between this verts 2 connected edges.\n"
1311 " :return: Angle between edges in radians.\n"
1314 static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self)
1316 BPY_BM_CHECK_OBJ(self);
1317 return PyFloat_FromDouble(BM_vert_calc_edge_angle(self->v));
1320 PyDoc_STRVAR(bpy_bmvert_calc_shell_factor_doc,
1321 ".. method:: calc_shell_factor()\n"
1323 " Return a multiplier calculated based on the sharpness of the vertex.\n"
1324 " Where a flat surface gives 1.0, and higher values sharper edges.\n"
1325 " This is used to maintain shell thickness when offsetting verts along their normals.\n"
1327 " :return: offset multiplier\n"
1330 static PyObject *bpy_bmvert_calc_shell_factor(BPy_BMVert *self)
1332 BPY_BM_CHECK_OBJ(self);
1333 return PyFloat_FromDouble(BM_vert_calc_shell_factor(self->v));
1336 PyDoc_STRVAR(bpy_bmvert_normal_update_doc,
1337 ".. method:: normal_update()\n"
1339 " Update vertex normal.\n"
1341 static PyObject *bpy_bmvert_normal_update(BPy_BMVert *self)
1343 BPY_BM_CHECK_OBJ(self);
1345 BM_vert_normal_update(self->v);
1354 PyDoc_STRVAR(bpy_bmedge_calc_length_doc,
1355 ".. method:: calc_length()\n"
1357 " :return: The length between both verts.\n"
1360 static PyObject *bpy_bmedge_calc_length(BPy_BMEdge *self)
1362 BPY_BM_CHECK_OBJ(self);
1363 return PyFloat_FromDouble(len_v3v3(self->e->v1->co, self->e->v2->co));
1366 PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
1367 ".. method:: calc_face_angle()\n"
1369 " :return: The angle between 2 connected faces in radians.\n"
1372 static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
1374 BPY_BM_CHECK_OBJ(self);
1375 return PyFloat_FromDouble(BM_edge_calc_face_angle(self->e));
1378 PyDoc_STRVAR(bpy_bmedge_calc_tangent_doc,
1379 ".. method:: calc_tangent(loop)\n"
1381 " Return the tangent at this edge relative to a face (pointing inward into the face).\n"
1382 " This uses the face normal for calculation.\n"
1384 " :arg loop: The loop used for tangent calculation.\n"
1385 " :type loop: :class:`BMLoop`\n"
1386 " :return: a normalized vector.\n"
1387 " :rtype: :class:`mathutils.Vector`\n"
1389 static PyObject *bpy_bmedge_calc_tangent(BPy_BMEdge *self, PyObject *args)
1391 BPy_BMLoop *py_loop;
1392 BPY_BM_CHECK_OBJ(self);
1394 if (!PyArg_ParseTuple(args, "O!:BMEdge.calc_face_tangent",
1395 &BPy_BMLoop_Type, &py_loop))
1401 BPY_BM_CHECK_OBJ(py_loop);
1402 /* no need to check if they are from the same mesh or even connected */
1403 BM_edge_calc_face_tangent(self->e, py_loop->l, vec);
1404 return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1409 PyDoc_STRVAR(bpy_bmedge_other_vert_doc,
1410 ".. method:: other_vert(vert)\n"
1412 " Return the other vertex on this edge or None if the vertex is not used by this edge.\n"
1414 " :arg vert: a vert in this edge.\n"
1415 " :type vert: :class:`BMVert`\n"
1416 " :return: The edges other vert.\n"
1417 " :rtype: :class:`BMVert` or None\n"
1419 static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
1422 BPY_BM_CHECK_OBJ(self);
1424 if (!BPy_BMVert_Check(value)) {
1425 PyErr_Format(PyExc_TypeError,
1426 "BMEdge.other_vert(vert): BMVert expected, not '%.200s'",
1427 Py_TYPE(value)->tp_name);
1431 BPY_BM_CHECK_SOURCE_OBJ(value, self->bm, "BMEdge.other_vert(vert)");
1433 other = BM_edge_other_vert(self->e, value->v);
1436 return BPy_BMVert_CreatePyObject(self->bm, other);
1439 /* could raise an exception here */
1445 PyDoc_STRVAR(bpy_bmedge_normal_update_doc,
1446 ".. method:: normal_update()\n"
1448 " Update edges vertex normals.\n"
1450 static PyObject *bpy_bmedge_normal_update(BPy_BMEdge *self)
1452 BPY_BM_CHECK_OBJ(self);
1454 BM_edge_normals_update(self->e);
1463 PyDoc_STRVAR(bpy_bmface_copy_from_face_interp_doc,
1464 ".. method:: copy_from_face_interp(face)\n"
1466 " Interpolate the customdata from another face onto this one (faces should overlap).\n"
1468 " :arg face: The face to interpolate data from.\n"
1469 " :type face: :class:`BMFace`\n"
1471 static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
1473 BPy_BMFace *py_face = NULL;
1475 BPY_BM_CHECK_OBJ(self);
1477 if (!PyArg_ParseTuple(args, "O!:BMFace.copy_from_face_interp",
1478 &BPy_BMFace_Type, &py_face))
1483 BMesh *bm = self->bm;
1485 BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMFace.copy_from_face_interp(face)");
1487 BM_face_interp_from_face(bm, self->f, py_face->f);
1494 PyDoc_STRVAR(bpy_bmface_copy_doc,
1495 ".. method:: copy(verts=True, edges=True)\n"
1497 " Make a copy of this face.\n"
1499 " :arg verts: When set, the faces verts will be duplicated too.\n"
1500 " :type verts: boolean\n"
1501 " :arg edges: When set, the faces edges will be duplicated too.\n"
1502 " :type edges: boolean\n"
1503 " :return: The newly created face.\n"
1504 " :rtype: :class:`BMFace`\n"
1506 static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
1508 static const char *kwlist[] = {"verts", "edges", NULL};
1510 BMesh *bm = self->bm;
1511 int do_verts = TRUE;
1512 int do_edges = TRUE;
1515 BPY_BM_CHECK_OBJ(self);
1517 if (!PyArg_ParseTupleAndKeywords(args, kw,
1520 &do_verts, &do_edges))
1525 f_cpy = BM_face_copy(bm, self->f, do_verts, do_edges);
1528 return BPy_BMFace_CreatePyObject(bm, f_cpy);
1531 PyErr_SetString(PyExc_ValueError,
1532 "BMFace.copy(): couldn't create the new face, internal error");
1538 PyDoc_STRVAR(bpy_bmface_calc_area_doc,
1539 ".. method:: calc_area()\n"
1541 " Return the area of the face.\n"
1543 " :return: Return the area of the face.\n"
1546 static PyObject *bpy_bmface_calc_area(BPy_BMFace *self)
1548 BPY_BM_CHECK_OBJ(self);
1549 return PyFloat_FromDouble(BM_face_calc_area(self->f));
1553 PyDoc_STRVAR(bpy_bmface_calc_perimeter_doc,
1554 ".. method:: calc_perimeter()\n"
1556 " Return the perimeter of the face.\n"
1558 " :return: Return the perimeter of the face.\n"
1561 static PyObject *bpy_bmface_calc_perimeter(BPy_BMFace *self)
1563 BPY_BM_CHECK_OBJ(self);
1564 return PyFloat_FromDouble(BM_face_calc_perimeter(self->f));
1568 PyDoc_STRVAR(bpy_bmface_calc_center_mean_doc,
1569 ".. method:: calc_center_median()\n"
1571 " Return median center of the face.\n"
1573 " :return: a 3D vector.\n"
1574 " :rtype: :class:`mathutils.Vector`\n"
1576 static PyObject *bpy_bmface_calc_center_mean(BPy_BMFace *self)
1580 BPY_BM_CHECK_OBJ(self);
1581 BM_face_calc_center_mean(self->f, cent);
1582 return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
1586 PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
1587 ".. method:: calc_center_bounds()\n"
1589 " Return bounds center of the face.\n"
1591 " :return: a 3D vector.\n"
1592 " :rtype: :class:`mathutils.Vector`\n"
1594 static PyObject *bpy_bmface_calc_center_bounds(BPy_BMFace *self)
1598 BPY_BM_CHECK_OBJ(self);
1599 BM_face_calc_center_bounds(self->f, cent);
1600 return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
1604 PyDoc_STRVAR(bpy_bmface_normal_update_doc,
1605 ".. method:: normal_update()\n"
1607 " Update faces normal.\n"
1609 static PyObject *bpy_bmface_normal_update(BPy_BMFace *self)
1611 BPY_BM_CHECK_OBJ(self);
1613 BM_face_normal_update(self->f);
1622 PyDoc_STRVAR(bpy_bmloop_copy_from_face_interp_doc,
1623 ".. method:: copy_from_face_interp(face, vert=True, multires=True)\n"
1625 " Interpolate the customdata from a face onto this loop (the loops vert should overlap the face).\n"
1627 " :arg face: The face to interpolate data from.\n"
1628 " :type face: :class:`BMFace`\n"
1629 " :arg vert: When enabled, interpolate the loops vertex data (optional).\n"
1630 " :type vert: boolean\n"
1631 " :arg multires: When enabled, interpolate the loops multires data (optional).\n"
1632 " :type multires: boolean\n"
1634 static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
1636 BPy_BMFace *py_face = NULL;
1637 int do_vertex = TRUE;
1638 int do_multires = TRUE;
1640 BPY_BM_CHECK_OBJ(self);
1642 if (!PyArg_ParseTuple(args, "O!|ii:BMLoop.copy_from_face_interp",
1643 &BPy_BMFace_Type, &py_face,
1644 &do_vertex, &do_multires))
1649 BMesh *bm = self->bm;
1651 BPY_BM_CHECK_SOURCE_OBJ(py_face, bm, "BMLoop.copy_from_face_interp(face)");
1653 BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires);
1660 PyDoc_STRVAR(bpy_bmloop_calc_angle_doc,
1661 ".. method:: calc_angle()\n"
1663 " Return the angle at this loops corner of the face.\n"
1664 " This is calculated so sharper corners give lower angles.\n"
1666 " :return: The angle in radians.\n"
1669 static PyObject *bpy_bmloop_calc_angle(BPy_BMLoop *self)
1671 BPY_BM_CHECK_OBJ(self);
1672 return PyFloat_FromDouble(BM_loop_calc_face_angle(self->l));
1675 PyDoc_STRVAR(bpy_bmloop_calc_normal_doc,
1676 ".. method:: calc_normal()\n"
1678 " Return normal at this loops corner of the face.\n"
1679 " Falls back to the face normal for straight lines.\n"
1681 " :return: a normalized vector.\n"
1682 " :rtype: :class:`mathutils.Vector`\n"
1684 static PyObject *bpy_bmloop_calc_normal(BPy_BMLoop *self)
1687 BPY_BM_CHECK_OBJ(self);
1688 BM_loop_calc_face_normal(self->l, vec);
1689 return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1692 PyDoc_STRVAR(bpy_bmloop_calc_tangent_doc,
1693 ".. method:: calc_tangent()\n"
1695 " Return the tangent at this loops corner of the face (pointing inward into the face).\n"
1696 " Falls back to the face normal for straight lines.\n"
1698 " :return: a normalized vector.\n"
1699 " :rtype: :class:`mathutils.Vector`\n"
1701 static PyObject *bpy_bmloop_calc_tangent(BPy_BMLoop *self)
1704 BPY_BM_CHECK_OBJ(self);
1705 BM_loop_calc_face_tangent(self->l, vec);
1706 return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1711 PyDoc_STRVAR(bpy_bmvertseq_new_doc,
1712 ".. method:: new(co=(0.0, 0.0, 0.0), example=None)\n"
1714 " Create a new vertex.\n"
1716 " :arg co: The initial location of the vertex (optional argument).\n"
1717 " :type co: float triplet\n"
1718 " :arg example: Existing vert to initialize settings.\n"
1719 " :type example: :class:`BMVert`\n"
1720 " :return: The newly created edge.\n"
1721 " :rtype: :class:`BMVert`\n"
1723 static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
1725 PyObject *py_co = NULL;
1726 BPy_BMVert *py_vert_example = NULL; /* optional */
1728 BPY_BM_CHECK_OBJ(self);
1730 if (!PyArg_ParseTuple(args, "|OO!:verts.new",
1732 &BPy_BMVert_Type, &py_vert_example))
1737 BMesh *bm = self->bm;
1739 float co[3] = {0.0f, 0.0f, 0.0f};
1741 if (py_vert_example) {
1742 BPY_BM_CHECK_OBJ(py_vert_example);
1745 if (py_co && mathutils_array_parse(co, 3, 3, py_co, "verts.new(co)") == -1) {
1749 v = BM_vert_create(bm, co, NULL);
1752 PyErr_SetString(PyExc_ValueError,
1753 "faces.new(verts): couldn't create the new face, internal error");
1757 if (py_vert_example) {
1758 BM_elem_attrs_copy(py_vert_example->bm, bm, py_vert_example->v, v);
1761 return BPy_BMVert_CreatePyObject(bm, v);
1768 PyDoc_STRVAR(bpy_bmedgeseq_new_doc,
1769 ".. method:: new(verts, example=None)\n"
1771 " Create a new edge from a given pair of verts.\n"
1773 " :arg verts: Vertex pair.\n"
1774 " :type verts: pair of :class:`BMVert`\n"
1775 " :arg example: Existing edge to initialize settings (optional argument).\n"
1776 " :type example: :class:`BMEdge`\n"
1777 " :return: The newly created edge.\n"
1778 " :rtype: :class:`BMEdge`\n"
1780 static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
1783 BPy_BMEdge *py_edge_example = NULL; /* optional */
1785 BPY_BM_CHECK_OBJ(self);
1787 if (!PyArg_ParseTuple(args, "O|O!:edges.new",
1789 &BPy_BMEdge_Type, &py_edge_example))
1794 BMesh *bm = self->bm;
1796 BMVert **vert_array = NULL;
1797 Py_ssize_t vert_seq_len; /* always 2 */
1798 PyObject *ret = NULL;
1800 if (py_edge_example) {
1801 BPY_BM_CHECK_OBJ(py_edge_example);
1804 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1805 &vert_seq_len, BM_VERT,
1806 TRUE, TRUE, "edges.new(...)");
1808 if (vert_array == NULL) {
1812 if (BM_edge_exists(vert_array[0], vert_array[1])) {
1813 PyErr_SetString(PyExc_ValueError,
1814 "edges.new(): this edge exists");
1818 e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, FALSE);
1821 PyErr_SetString(PyExc_ValueError,
1822 "faces.new(verts): couldn't create the new face, internal error");
1826 if (py_edge_example) {
1827 BM_elem_attrs_copy(py_edge_example->bm, bm, py_edge_example->e, e);
1830 ret = BPy_BMEdge_CreatePyObject(bm, e);
1833 if (vert_array) PyMem_FREE(vert_array);
1841 PyDoc_STRVAR(bpy_bmfaceseq_new_doc,
1842 ".. method:: new(verts, example=None)\n"
1844 " Create a new face from a given set of verts.\n"
1846 " :arg verts: Sequence of 3 or more verts.\n"
1847 " :type verts: :class:`BMVert`\n"
1848 " :arg example: Existing face to initialize settings (optional argument).\n"
1849 " :type example: :class:`BMFace`\n"
1850 " :return: The newly created face.\n"
1851 " :rtype: :class:`BMFace`\n"
1853 static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
1856 BPy_BMFace *py_face_example = NULL; /* optional */
1858 BPY_BM_CHECK_OBJ(self);
1860 if (!PyArg_ParseTuple(args, "O|O!:faces.new",
1862 &BPy_BMFace_Type, &py_face_example))
1867 BMesh *bm = self->bm;
1868 Py_ssize_t vert_seq_len;
1869 Py_ssize_t i, i_next;
1871 BMVert **vert_array = NULL;
1872 BMEdge **edge_array = NULL;
1874 PyObject *ret = NULL;
1878 if (py_face_example) {
1879 BPY_BM_CHECK_OBJ(py_face_example);
1882 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX,
1883 &vert_seq_len, BM_VERT,
1884 TRUE, TRUE, "faces.new(...)");
1886 if (vert_array == NULL) {
1890 /* check if the face exists */
1891 if (BM_face_exists(vert_array, vert_seq_len, NULL)) {
1892 PyErr_SetString(PyExc_ValueError,
1893 "faces.new(verts): face already exists");
1897 /* Go ahead and make the face!
1898 * --------------------------- */
1900 edge_array = (BMEdge **)PyMem_MALLOC(vert_seq_len * sizeof(BMEdge **));
1903 for (i = vert_seq_len - 1, i_next = 0; i_next < vert_seq_len; (i = i_next++)) {
1904 edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, TRUE);
1907 f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE);
1909 if (UNLIKELY(f_new == NULL)) {
1910 PyErr_SetString(PyExc_ValueError,
1911 "faces.new(verts): couldn't create the new face, internal error");
1915 if (py_face_example) {
1916 BM_elem_attrs_copy(py_face_example->bm, bm, py_face_example->f, f_new);
1919 ret = BPy_BMFace_CreatePyObject(bm, f_new);
1923 if (vert_array) PyMem_FREE(vert_array);
1924 if (edge_array) PyMem_FREE(edge_array);
1932 PyDoc_STRVAR(bpy_bmvertseq_remove_doc,
1933 ".. method:: remove(vert)\n"
1937 static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
1939 BPY_BM_CHECK_OBJ(self);
1941 if (!BPy_BMVert_Check(value)) {
1945 BMesh *bm = self->bm;
1947 BPY_BM_CHECK_SOURCE_OBJ(value, bm, "verts.remove(vert)");
1949 BM_vert_kill(bm, value->v);
1950 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1956 PyDoc_STRVAR(bpy_bmedgeseq_remove_doc,
1957 ".. method:: remove(edge)\n"
1961 static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
1963 BPY_BM_CHECK_OBJ(self);
1965 if (!BPy_BMEdge_Check(value)) {
1969 BMesh *bm = self->bm;
1971 BPY_BM_CHECK_SOURCE_OBJ(value, bm, "edges.remove(edges)");
1973 BM_edge_kill(bm, value->e);
1974 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1980 PyDoc_STRVAR(bpy_bmfaceseq_remove_doc,
1981 ".. method:: remove(face)\n"
1985 static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
1987 BPY_BM_CHECK_OBJ(self);
1989 if (!BPy_BMFace_Check(value)) {
1993 BMesh *bm = self->bm;
1995 BPY_BM_CHECK_SOURCE_OBJ(value, bm, "faces.remove(face)");
1997 BM_face_kill(bm, value->f);
1998 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
2004 PyDoc_STRVAR(bpy_bmedgeseq_get__method_doc,
2005 ".. method:: get(verts, fallback=None)\n"
2007 " Return a edge which uses the **verts** passed.\n"
2009 " :arg verts: Sequence of verts.\n"
2010 " :type verts: :class:`BMVert`\n"
2011 " :arg fallback: Return this value if nothing is found.\n"
2012 " :return: The edge found or None\n"
2013 " :rtype: :class:`BMEdge`\n"
2015 static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
2018 PyObject *fallback = Py_None; /* optional */
2020 BPY_BM_CHECK_OBJ(self);
2022 if (!PyArg_ParseTuple(args, "O|O:edges.get",
2029 BMesh *bm = self->bm;
2031 BMVert **vert_array = NULL;
2032 Py_ssize_t vert_seq_len; /* always 2 */
2033 PyObject *ret = NULL;
2035 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
2036 &vert_seq_len, BM_VERT,
2037 TRUE, TRUE, "edges.get(...)");
2039 if (vert_array == NULL) {
2043 if ((e = BM_edge_exists(vert_array[0], vert_array[1]))) {
2044 ret = BPy_BMEdge_CreatePyObject(bm, e);
2051 PyMem_FREE(vert_array);
2056 PyDoc_STRVAR(bpy_bmfaceseq_get__method_doc,
2057 ".. method:: get(verts, fallback=None)\n"
2059 " Return a face which uses the **verts** passed.\n"
2061 " :arg verts: Sequence of verts.\n"
2062 " :type verts: :class:`BMVert`\n"
2063 " :arg fallback: Return this value if nothing is found.\n"
2064 " :return: The face found or None\n"
2065 " :rtype: :class:`BMFace`\n"
2067 static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
2070 PyObject *fallback = Py_None; /* optional */
2072 BPY_BM_CHECK_OBJ(self);
2074 if (!PyArg_ParseTuple(args, "O|O:faces.get",
2081 BMesh *bm = self->bm;
2083 BMVert **vert_array = NULL;
2084 Py_ssize_t vert_seq_len;
2085 PyObject *ret = NULL;
2087 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 1, PY_SSIZE_T_MAX,
2088 &vert_seq_len, BM_VERT,
2089 TRUE, TRUE, "faces.get(...)");
2091 if (vert_array == NULL) {
2095 if (BM_face_exists(vert_array, vert_seq_len, &f)) {
2096 ret = BPy_BMFace_CreatePyObject(bm, f);
2103 PyMem_FREE(vert_array);
2108 PyDoc_STRVAR(bpy_bmelemseq_index_update_doc,
2109 ".. method:: index_update()\n"
2111 " Initialize the index values of this sequence.\n"
2113 " This is the equivalent of looping over all elements and assigning the index values.\n"
2115 " .. code-block:: python\n"
2117 " for index, ele in enumerate(sequence):\n"
2118 " ele.index = index\n"
2122 " Running this on sequences besides :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces`\n"
2123 " works but wont result in each element having a valid index, insted its order in the sequence will be set.\n"
2125 static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
2127 BMesh *bm = self->bm;
2129 BPY_BM_CHECK_OBJ(self);
2131 switch ((BMIterType)self->itype) {
2132 case BM_VERTS_OF_MESH:
2133 BM_mesh_elem_index_ensure(self->bm, BM_VERT);
2135 case BM_EDGES_OF_MESH:
2136 BM_mesh_elem_index_ensure(self->bm, BM_EDGE);
2138 case BM_FACES_OF_MESH:
2139 BM_mesh_elem_index_ensure(self->bm, BM_FACE);
2146 const char htype = bm_iter_itype_htype_map[self->itype];
2148 BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
2149 BM_elem_index_set(ele, index); /* set_dirty! */
2153 if (htype & (BM_VERT | BM_EDGE | BM_FACE)) {
2154 /* since this isn't the normal vert/edge/face loops,
2155 * we're setting dirty values here. so tag as dirty. */
2156 bm->elem_index_dirty |= htype;
2166 PyDoc_STRVAR(bpy_bmelemseq_sort_doc,
2167 ".. method:: sort(key=None, reverse=False)\n"
2169 " Sort the elements of this sequence, using an optional custom sort key.\n"
2170 " Indices of elements are not changed, BMElemeSeq.index_update() can be used for that.\n"
2172 " :arg key: The key that sets the ordering of the elements.\n"
2173 " :type key: :function: returning a number\n"
2174 " :arg reverse: Reverse the order of the elements\n"
2175 " :type reverse: :boolean:\n"
2179 " When the 'key' argument is not provided, the elements are reordered following their current index value.\n"
2180 " In particular this can be used by setting indices manually before calling this method.\n"
2184 /* Use a static variable here because there is the need to sort some array
2185 * doing comparisons on elements of another array, qsort_r would have been
2186 * wonderful to use here, but unfortunately it is not standard and it's not
2187 * portable across different platforms.
2189 * If a portable alternative to qsort_r becomes available, remove this static
2192 * Note: the functions below assumes the keys array has been allocated and it
2193 * has enough elements to complete the task.
2195 static double *keys = NULL;
2197 static int bpy_bmelemseq_sort_cmp_by_keys_ascending(const void *index1_v, const void *index2_v)
2199 const int *index1 = (int *)index1_v;
2200 const int *index2 = (int *)index2_v;
2202 if (keys[*index1] < keys[*index2]) return -1;
2203 else if (keys[*index1] > keys[*index2]) return 1;
2207 static int bpy_bmelemseq_sort_cmp_by_keys_descending(const void *index1_v, const void *index2_v)
2209 return -bpy_bmelemseq_sort_cmp_by_keys_ascending(index1_v, index2_v);
2212 static PyObject *bpy_bmelemseq_sort(BPy_BMElemSeq *self, PyObject *args, PyObject *kw)
2214 static const char *kwlist[] = {"key", "reverse", NULL};
2215 PyObject *keyfunc = NULL; /* optional */
2216 int reverse = FALSE; /* optional */
2218 const char htype = bm_iter_itype_htype_map[self->itype];
2226 int (*elem_idx_compare_by_keys)(const void *, const void *);
2228 int *vert_idx = NULL;
2229 int *edge_idx = NULL;
2230 int *face_idx = NULL;
2233 BMesh *bm = self->bm;
2235 BPY_BM_CHECK_OBJ(self);
2238 if (!PyArg_ParseTupleAndKeywords(args, kw,
2239 "|Oi:BMElemSeq.sort",
2241 &keyfunc, &reverse))
2247 if (keyfunc != NULL && !PyCallable_Check(keyfunc)) {
2248 PyErr_SetString(PyExc_TypeError,
2249 "the 'key' argument is not a callable object");
2253 n_elem = BM_mesh_elem_count(bm, htype);
2255 /* 0 or 1 elements: sorted already */
2259 keys = PyMem_MALLOC(sizeof(*keys) * n_elem);
2266 BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
2267 if (keyfunc != NULL) {
2271 py_elem = BPy_BMElem_CreatePyObject(self->bm, (BMHeader *)ele);
2272 index = PyObject_CallFunctionObjArgs(keyfunc, py_elem, NULL);
2274 if (index == NULL) {
2275 /* No need to set the exception here,
2276 * PyObject_CallFunctionObjArgs() does that */
2281 if ((keys[i] = PyFloat_AsDouble(index)) == -1 && PyErr_Occurred()) {
2282 PyErr_SetString(PyExc_ValueError,
2283 "the value returned by the 'key' function is not a number");
2292 /* If the 'key' function is not provided we sort
2293 * according to the current index values */
2294 keys[i] = ele->head.index;
2300 elem_idx = PyMem_MALLOC(sizeof(*elem_idx) * n_elem);
2301 if (elem_idx == NULL) {
2307 /* Initialize the element index array */
2308 range_vn_i(elem_idx, n_elem, 0);
2310 /* Sort the index array according to the order of the 'keys' array */
2312 elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_descending;
2314 elem_idx_compare_by_keys = bpy_bmelemseq_sort_cmp_by_keys_ascending;
2316 qsort(elem_idx, n_elem, sizeof(*elem_idx), elem_idx_compare_by_keys);
2318 elem_map_idx = PyMem_MALLOC(sizeof(*elem_map_idx) * n_elem);
2319 if (elem_map_idx == NULL) {
2321 PyMem_FREE(elem_idx);
2326 /* Initialize the map array
2328 * We need to know the index such that if used as the new_index in
2329 * BM_mesh_remap() will give the order of the sorted keys like in
2331 for (i = 0; i < n_elem; i++) {
2332 elem_map_idx[elem_idx[i]] = i;
2335 switch ((BMIterType)self->itype) {
2336 case BM_VERTS_OF_MESH:
2337 vert_idx = elem_map_idx;
2339 case BM_EDGES_OF_MESH:
2340 edge_idx = elem_map_idx;
2342 case BM_FACES_OF_MESH:
2343 face_idx = elem_map_idx;
2346 PyErr_Format(PyExc_TypeError, "element type %d not supported", self->itype);
2347 PyMem_FREE(elem_map_idx);
2348 PyMem_FREE(elem_idx);
2353 BM_mesh_remap(bm, vert_idx, edge_idx, face_idx);
2355 PyMem_FREE(elem_map_idx);
2356 PyMem_FREE(elem_idx);
2362 static struct PyMethodDef bpy_bmesh_methods[] = {
2364 {"copy", (PyCFunction)bpy_bmesh_copy, METH_NOARGS, bpy_bmesh_copy_doc},
2365 {"clear", (PyCFunction)bpy_bmesh_clear, METH_NOARGS, bpy_bmesh_clear_doc},
2366 {"free", (PyCFunction)bpy_bmesh_free, METH_NOARGS, bpy_bmesh_free_doc},
2369 {"from_object", (PyCFunction)bpy_bmesh_from_object, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_object_doc},
2370 {"from_mesh", (PyCFunction)bpy_bmesh_from_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_mesh_doc},
2371 {"to_mesh", (PyCFunction)bpy_bmesh_to_mesh, METH_VARARGS, bpy_bmesh_to_mesh_doc},
2374 {"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
2375 {"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
2376 {"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
2377 {"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_transform_doc},
2378 {NULL, NULL, 0, NULL}
2381 static struct PyMethodDef bpy_bmvert_methods[] = {
2382 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2383 {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2384 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2385 {"copy_from_face_interp", (PyCFunction)bpy_bmvert_copy_from_face_interp, METH_VARARGS, bpy_bmvert_copy_from_face_interp_doc},
2386 {"copy_from_vert_interp", (PyCFunction)bpy_bmvert_copy_from_vert_interp, METH_VARARGS, bpy_bmvert_copy_from_vert_interp_doc},
2388 {"calc_vert_angle", (PyCFunction)bpy_bmvert_calc_edge_angle, METH_NOARGS, bpy_bmvert_calc_edge_angle_doc},
2389 {"calc_shell_factor", (PyCFunction)bpy_bmvert_calc_shell_factor, METH_NOARGS, bpy_bmvert_calc_shell_factor_doc},
2391 {"normal_update", (PyCFunction)bpy_bmvert_normal_update, METH_NOARGS, bpy_bmvert_normal_update_doc},
2393 {NULL, NULL, 0, NULL}
2396 static struct PyMethodDef bpy_bmedge_methods[] = {
2397 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2398 {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2399 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2401 {"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
2403 {"calc_length", (PyCFunction)bpy_bmedge_calc_length, METH_NOARGS, bpy_bmedge_calc_length_doc},
2404 {"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
2405 {"calc_tangent", (PyCFunction)bpy_bmedge_calc_tangent, METH_VARARGS, bpy_bmedge_calc_tangent_doc},
2407 {"normal_update", (PyCFunction)bpy_bmedge_normal_update, METH_NOARGS, bpy_bmedge_normal_update_doc},
2409 {NULL, NULL, 0, NULL}
2412 static struct PyMethodDef bpy_bmface_methods[] = {
2413 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2414 {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2416 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2417 {"copy_from_face_interp", (PyCFunction)bpy_bmface_copy_from_face_interp, METH_O, bpy_bmface_copy_from_face_interp_doc},
2419 {"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS | METH_KEYWORDS, bpy_bmface_copy_doc},
2421 {"calc_area", (PyCFunction)bpy_bmface_calc_area, METH_NOARGS, bpy_bmface_calc_area_doc},
2422 {"calc_perimeter", (PyCFunction)bpy_bmface_calc_perimeter, METH_NOARGS, bpy_bmface_calc_perimeter_doc},
2423 {"calc_center_median", (PyCFunction)bpy_bmface_calc_center_mean, METH_NOARGS, bpy_bmface_calc_center_mean_doc},
2424 {"calc_center_bounds", (PyCFunction)bpy_bmface_calc_center_bounds, METH_NOARGS, bpy_bmface_calc_center_bounds_doc},
2426 {"normal_update", (PyCFunction)bpy_bmface_normal_update, METH_NOARGS, bpy_bmface_normal_update_doc},
2428 {NULL, NULL, 0, NULL}
2431 static struct PyMethodDef bpy_bmloop_methods[] = {
2432 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2433 {"copy_from_face_interp", (PyCFunction)bpy_bmloop_copy_from_face_interp, METH_O, bpy_bmloop_copy_from_face_interp_doc},
2435 {"calc_angle", (PyCFunction)bpy_bmloop_calc_angle, METH_NOARGS, bpy_bmloop_calc_angle_doc},
2436 {"calc_normal", (PyCFunction)bpy_bmloop_calc_normal, METH_NOARGS, bpy_bmloop_calc_normal_doc},
2437 {"calc_tangent", (PyCFunction)bpy_bmloop_calc_tangent, METH_NOARGS, bpy_bmloop_calc_tangent_doc},
2438 {NULL, NULL, 0, NULL}
2441 static struct PyMethodDef bpy_bmelemseq_methods[] = {
2442 /* odd function, initializes index values */
2443 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2444 {NULL, NULL, 0, NULL}
2447 static struct PyMethodDef bpy_bmvertseq_methods[] = {
2448 {"new", (PyCFunction)bpy_bmvertseq_new, METH_VARARGS, bpy_bmvertseq_new_doc},
2449 {"remove", (PyCFunction)bpy_bmvertseq_remove, METH_O, bpy_bmvertseq_remove_doc},
2451 /* odd function, initializes index values */
2452 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2453 {"sort", (PyCFunction)bpy_bmelemseq_sort, METH_VARARGS | METH_KEYWORDS, bpy_bmelemseq_sort_doc},
2454 {NULL, NULL, 0, NULL}
2457 static struct PyMethodDef bpy_bmedgeseq_methods[] = {
2458 {"new", (PyCFunction)bpy_bmedgeseq_new, METH_VARARGS, bpy_bmedgeseq_new_doc},
2459 {"remove", (PyCFunction)bpy_bmedgeseq_remove, METH_O, bpy_bmedgeseq_remove_doc},
2460 /* 'bpy_bmelemseq_get' for different purpose */
2461 {"get", (PyCFunction)bpy_bmedgeseq_get__method, METH_VARARGS, bpy_bmedgeseq_get__method_doc},
2463 /* odd function, initializes index values */
2464 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2465 {"sort", (PyCFunction)bpy_bmelemseq_sort, METH_VARARGS | METH_KEYWORDS, bpy_bmelemseq_sort_doc},
2466 {NULL, NULL, 0, NULL}
2469 static struct PyMethodDef bpy_bmfaceseq_methods[] = {
2470 {"new", (PyCFunction)bpy_bmfaceseq_new, METH_VARARGS, bpy_bmfaceseq_new_doc},
2471 {"remove", (PyCFunction)bpy_bmfaceseq_remove, METH_O, bpy_bmfaceseq_remove_doc},
2472 /* 'bpy_bmelemseq_get' for different purpose */
2473 {"get", (PyCFunction)bpy_bmfaceseq_get__method, METH_VARARGS, bpy_bmfaceseq_get__method_doc},
2475 /* odd function, initializes index values */
2476 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2477 {"sort", (PyCFunction)bpy_bmelemseq_sort, METH_VARARGS | METH_KEYWORDS, bpy_bmelemseq_sort_doc},
2478 {NULL, NULL, 0, NULL}
2481 static struct PyMethodDef bpy_bmloopseq_methods[] = {
2482 /* odd function, initializes index values */
2483 /* no: index_update() function since we cant iterate over loops */
2484 /* no: sort() function since we cant iterate over loops */
2485 {NULL, NULL, 0, NULL}
2492 * ---------------- */
2494 static PyTypeObject *bpy_bm_itype_as_pytype(const char itype)
2496 /* should cover all types */
2497 switch ((BMIterType)itype) {
2498 case BM_VERTS_OF_MESH:
2499 case BM_VERTS_OF_FACE:
2500 case BM_VERTS_OF_EDGE:
2501 return &BPy_BMVert_Type;
2503 case BM_EDGES_OF_MESH:
2504 case BM_EDGES_OF_FACE:
2505 case BM_EDGES_OF_VERT:
2506 return &BPy_BMEdge_Type;
2508 case BM_FACES_OF_MESH:
2509 case BM_FACES_OF_EDGE:
2510 case BM_FACES_OF_VERT:
2511 return &BPy_BMFace_Type;
2513 case BM_ALL_LOOPS_OF_FACE:
2514 case BM_LOOPS_OF_FACE:
2515 case BM_LOOPS_OF_EDGE:
2516 case BM_LOOPS_OF_VERT:
2517 case BM_LOOPS_OF_LOOP:
2518 return &BPy_BMLoop_Type;
2524 static Py_ssize_t bpy_bmelemseq_length(BPy_BMElemSeq *self)
2526 BPY_BM_CHECK_INT(self);
2528 /* first check if the size is known */
2529 switch ((BMIterType)self->itype) {
2531 case BM_VERTS_OF_MESH:
2532 return self->bm->totvert;
2533 case BM_EDGES_OF_MESH:
2534 return self->bm->totedge;
2535 case BM_FACES_OF_MESH:
2536 return self->bm->totface;
2539 case BM_VERTS_OF_FACE:
2540 case BM_EDGES_OF_FACE:
2541 case BM_LOOPS_OF_FACE:
2542 BPY_BM_CHECK_INT(self->py_ele);
2543 return ((BMFace *)self->py_ele->ele)->len;
2545 case BM_VERTS_OF_EDGE:
2549 /* quiet compiler */
2554 /* loop over all items, avoid this if we can */
2560 BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
2567 static PyObject *bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
2569 BPY_BM_CHECK_OBJ(self);
2571 if (keynum < 0) keynum += bpy_bmelemseq_length(self); /* only get length on negative value, may loop entire seq */
2573 BMHeader *ele = BM_iter_at_index(self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
2575 return BPy_BMElem_CreatePyObject(self->bm, ele);
2579 PyErr_Format(PyExc_IndexError,
2580 "BMElemSeq[index]: index %d out of range", keynum);
2584 static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t start, Py_ssize_t stop)
2594 BPY_BM_CHECK_OBJ(self);
2596 list = PyList_New(0);
2598 ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
2600 BLI_assert(ok == TRUE);
2602 if (UNLIKELY(ok == FALSE)) {
2606 /* first loop up-until the start */
2607 for (ok = TRUE; ok; ok = (BM_iter_step(&iter) != NULL)) {
2608 if (count == start) {
2614 /* add items until stop */
2615 while ((ele = BM_iter_step(&iter))) {
2616 item = BPy_BMElem_CreatePyObject(self->bm, ele);
2617 PyList_Append(list, item);
2621 if (count == stop) {
2629 static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key)
2631 /* don't need error check here */
2632 if (PyIndex_Check(key)) {
2633 Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2634 if (i == -1 && PyErr_Occurred())
2636 return bpy_bmelemseq_subscript_int(self, i);
2638 else if (PySlice_Check(key)) {
2639 PySliceObject *key_slice = (PySliceObject *)key;
2640 Py_ssize_t step = 1;
2642 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2645 else if (step != 1) {
2646 PyErr_SetString(PyExc_TypeError,
2647 "BMElemSeq[slice]: slice steps not supported");
2650 else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2651 return bpy_bmelemseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
2654 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
2656 /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
2657 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
2658 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL;
2660 if (start < 0 || stop < 0) {
2661 /* only get the length for negative values */
2662 Py_ssize_t len = bpy_bmelemseq_length(self);
2663 if (start < 0) start += len;
2664 if (stop < 0) stop += len;
2667 if (stop - start <= 0) {
2668 return PyList_New(0);
2671 return bpy_bmelemseq_subscript_slice(self, start, stop);
2676 PyErr_SetString(PyExc_AttributeError,
2677 "BMElemSeq[key]: invalid key, key must be an int");
2682 static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
2684 BPY_BM_CHECK_INT(self);
2686 if (Py_TYPE(value) == bpy_bm_itype_as_pytype(self->itype)) {
2687 BPy_BMElem *value_bm_ele = (BPy_BMElem *)value;
2688 if (value_bm_ele->bm == self->bm) {
2689 BMElem *ele, *ele_test = value_bm_ele->ele;
2691 BM_ITER_BPY_BM_SEQ (ele, &iter, self) {
2692 if (ele == ele_test) {
2702 /* BMElem (customdata)
2703 * ------------------- */
2705 static PyObject *bpy_bmelem_subscript(BPy_BMElem *self, BPy_BMLayerItem *key)
2707 BPY_BM_CHECK_OBJ(self);
2709 return BPy_BMLayerItem_GetItem(self, key);
2712 static int bpy_bmelem_ass_subscript(BPy_BMElem *self, BPy_BMLayerItem *key, PyObject *value)
2714 BPY_BM_CHECK_INT(self);
2716 return BPy_BMLayerItem_SetItem(self, key, value);
2719 static PySequenceMethods bpy_bmelemseq_as_sequence = {
2720 (lenfunc)bpy_bmelemseq_length, /* sq_length */
2721 NULL, /* sq_concat */
2722 NULL, /* sq_repeat */
2723 (ssizeargfunc)bpy_bmelemseq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
2724 NULL, /* sq_slice */
2725 (ssizeobjargproc)NULL, /* sq_ass_item */
2726 NULL, /* *was* sq_ass_slice */
2727 (objobjproc)bpy_bmelemseq_contains, /* sq_contains */
2728 (binaryfunc) NULL, /* sq_inplace_concat */
2729 (ssizeargfunc) NULL, /* sq_inplace_repeat */
2732 static PyMappingMethods bpy_bmelemseq_as_mapping = {
2733 (lenfunc)bpy_bmelemseq_length, /* mp_length */
2734 (binaryfunc)bpy_bmelemseq_subscript, /* mp_subscript */
2735 (objobjargproc)NULL, /* mp_ass_subscript */
2738 /* for customdata access */
2739 static PyMappingMethods bpy_bm_elem_as_mapping = {
2740 (lenfunc)NULL, /* mp_length */ /* keep this empty, messes up 'if elem: ...' test */
2741 (binaryfunc)bpy_bmelem_subscript, /* mp_subscript */
2742 (objobjargproc)bpy_bmelem_ass_subscript, /* mp_ass_subscript */
2748 static PyObject *bpy_bmelemseq_iter(BPy_BMElemSeq *self)
2750 BPy_BMIter *py_iter;
2752 BPY_BM_CHECK_OBJ(self);
2753 py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
2754 BM_iter_init(&(py_iter->iter), self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
2755 return (PyObject *)py_iter;
2758 static PyObject *bpy_bmiter_next(BPy_BMIter *self)
2760 BMHeader *ele = BM_iter_step(&self->iter);
2762 PyErr_SetString(PyExc_StopIteration,
2763 "bpy_bmiter_next stop");
2767 return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, ele);
2772 /* Dealloc Functions
2773 * ================= */
2775 static void bpy_bmesh_dealloc(BPy_BMesh *self)
2777 BMesh *bm = self->bm;
2779 /* have have been freed by bmesh */
2781 BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2782 BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2783 BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2784 BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
2786 bm->py_handle = NULL;
2788 if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
2796 static void bpy_bmvert_dealloc(BPy_BMElem *self)
2798 BMesh *bm = self->bm;
2800 void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2806 static void bpy_bmedge_dealloc(BPy_BMElem *self)
2808 BMesh *bm = self->bm;
2810 void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2816 static void bpy_bmface_dealloc(BPy_BMElem *self)
2818 BMesh *bm = self->bm;
2820 void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2826 static void bpy_bmloop_dealloc(BPy_BMElem *self)
2828 BMesh *bm = self->bm;
2830 void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2836 static void bpy_bmelemseq_dealloc(BPy_BMElemSeq *self)
2838 Py_XDECREF(self->py_ele);
2843 /* not sure where this should go */
2844 static Py_hash_t bpy_bm_elem_hash(PyObject *self)
2846 return _Py_HashPointer(((BPy_BMElem *)self)->ele);
2849 static Py_hash_t bpy_bm_hash(PyObject *self)
2851 return _Py_HashPointer(((BPy_BMesh *)self)->bm);
2855 * =============== */
2857 PyDoc_STRVAR(bpy_bmesh_doc,
2858 "The BMesh data structure\n"
2860 PyDoc_STRVAR(bpy_bmvert_doc,
2861 "The BMesh vertex type\n"
2863 PyDoc_STRVAR(bpy_bmedge_doc,
2864 "The BMesh edge connecting 2 verts\n"
2866 PyDoc_STRVAR(bpy_bmface_doc,
2867 "The BMesh face with 3 or more sides\n"
2869 PyDoc_STRVAR(bpy_bmloop_doc,
2870 "This is normally accessed from :class:`BMFace.loops` where each face corner represents a corner of a face.\n"
2872 PyDoc_STRVAR(bpy_bmelemseq_doc,
2873 "General sequence type used for accessing any sequence of \n"
2874 ":class:`BMVert`, :class:`BMEdge`, :class:`BMFace`, :class:`BMLoop`.\n"
2876 "When accessed via :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces` \n"
2877 "there are also functions to create/remomove items.\n"
2879 PyDoc_STRVAR(bpy_bmiter_doc,
2880 "Internal BMesh type for looping over verts/faces/edges,\n"
2881 "used for iterating over :class:`BMElemSeq` types.\n"
2884 static PyObject *bpy_bmesh_repr(BPy_BMesh *self)
2886 BMesh *bm = self->bm;
2889 return PyUnicode_FromFormat("<BMesh(%p), totvert=%d, totedge=%d, totface=%d, totloop=%d>",
2890 bm, bm->totvert, bm->totedge, bm->totface, bm->totloop);
2893 return PyUnicode_FromFormat("<BMesh dead at %p>", self);
2897 static PyObject *bpy_bmvert_repr(BPy_BMVert *self)
2899 BMesh *bm = self->bm;
2902 BMVert *v = self->v;
2903 return PyUnicode_FromFormat("<BMVert(%p), index=%d>",
2904 v, BM_elem_index_get(v));
2907 return PyUnicode_FromFormat("<BMVert dead at %p>", self);
2911 static PyObject *bpy_bmedge_repr(BPy_BMEdge *self)
2913 BMesh *bm = self->bm;
2916 BMEdge *e = self->e;
2917 return PyUnicode_FromFormat("<BMEdge(%p), index=%d, verts=(%p/%d, %p/%d)>",
2918 e, BM_elem_index_get(e),
2919 e->v1, BM_elem_index_get(e->v1),
2920 e->v2, BM_elem_index_get(e->v2));
2923 return PyUnicode_FromFormat("<BMEdge dead at %p>", self);
2927 static PyObject *bpy_bmface_repr(BPy_BMFace *self)
2929 BMesh *bm = self->bm;
2932 BMFace *f = self->f;
2933 return PyUnicode_FromFormat("<BMFace(%p), index=%d, totverts=%d>",
2934 f, BM_elem_index_get(f),
2938 return PyUnicode_FromFormat("<BMFace dead at %p>", self);
2942 static PyObject *bpy_bmloop_repr(BPy_BMLoop *self)
2944 BMesh *bm = self->bm;
2947 BMLoop *l = self->l;
2948 return PyUnicode_FromFormat("<BMLoop(%p), index=%d, vert=%p/%d, edge=%p/%d, face=%p/%d>",
2949 l, BM_elem_index_get(l),
2950 l->v, BM_elem_index_get(l->v),
2951 l->e, BM_elem_index_get(l->e),
2952 l->f, BM_elem_index_get(l->f));
2955 return PyUnicode_FromFormat("<BMLoop dead at %p>", self);
2962 PyTypeObject BPy_BMesh_Type = {{{0}}};
2963 PyTypeObject BPy_BMVert_Type = {{{0}}};
2964 PyTypeObject BPy_BMEdge_Type = {{{0}}};
2965 PyTypeObject BPy_BMFace_Type = {{{0}}};
2966 PyTypeObject BPy_BMLoop_Type = {{{0}}};
2967 PyTypeObject BPy_BMElemSeq_Type = {{{0}}};
2968 PyTypeObject BPy_BMVertSeq_Type = {{{0}}};
2969 PyTypeObject BPy_BMEdgeSeq_Type = {{{0}}};
2970 PyTypeObject BPy_BMFaceSeq_Type = {{{0}}};
2971 PyTypeObject BPy_BMLoopSeq_Type = {{{0}}};
2972 PyTypeObject BPy_BMIter_Type = {{{0}}};
2976 void BPy_BM_init_types(void)
2978 BPy_BMesh_Type.tp_basicsize = sizeof(BPy_BMesh);
2979 BPy_BMVert_Type.tp_basicsize = sizeof(BPy_BMVert);
2980 BPy_BMEdge_Type.tp_basicsize = sizeof(BPy_BMEdge);
2981 BPy_BMFace_Type.tp_basicsize = sizeof(BPy_BMFace);
2982 BPy_BMLoop_Type.tp_basicsize = sizeof(BPy_BMLoop);
2983 BPy_BMElemSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2984 BPy_BMVertSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2985 BPy_BMEdgeSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2986 BPy_BMFaceSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2987 BPy_BMLoopSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2988 BPy_BMIter_Type.tp_basicsize = sizeof(BPy_BMIter);
2991 BPy_BMesh_Type.tp_name = "BMesh";
2992 BPy_BMVert_Type.tp_name = "BMVert";
2993 BPy_BMEdge_Type.tp_name = "BMEdge";
2994 BPy_BMFace_Type.tp_name = "BMFace";
2995 BPy_BMLoop_Type.tp_name = "BMLoop";
2996 BPy_BMElemSeq_Type.tp_name = "BMElemSeq";
2997 BPy_BMVertSeq_Type.tp_name = "BMVertSeq";
2998 BPy_BMEdgeSeq_Type.tp_name = "BMEdgeSeq";
2999 BPy_BMFaceSeq_Type.tp_name = "BMFaceSeq";
3000 BPy_BMLoopSeq_Type.tp_name = "BMLoopSeq";
3001 BPy_BMIter_Type.tp_name = "BMIter";
3004 BPy_BMesh_Type.tp_doc = bpy_bmesh_doc;
3005 BPy_BMVert_Type.tp_doc = bpy_bmvert_doc;
3006 BPy_BMEdge_Type.tp_doc = bpy_bmedge_doc;
3007 BPy_BMFace_Type.tp_doc = bpy_bmface_doc;
3008 BPy_BMLoop_Type.tp_doc = bpy_bmloop_doc;
3009 BPy_BMElemSeq_Type.tp_doc = bpy_bmelemseq_doc;
3010 BPy_BMVertSeq_Type.tp_doc = NULL;
3011 BPy_BMEdgeSeq_Type.tp_doc = NULL;
3012 BPy_BMFaceSeq_Type.tp_doc = NULL;
3013 BPy_BMLoopSeq_Type.tp_doc = NULL;
3014 BPy_BMIter_Type.tp_doc = bpy_bmiter_doc;
3017 BPy_BMesh_Type.tp_repr = (reprfunc)bpy_bmesh_repr;
3018 BPy_BMVert_Type.tp_repr = (reprfunc)bpy_bmvert_repr;
3019 BPy_BMEdge_Type.tp_repr = (reprfunc)bpy_bmedge_repr;
3020 BPy_BMFace_Type.tp_repr = (reprfunc)bpy_bmface_repr;
3021 BPy_BMLoop_Type.tp_repr = (reprfunc)bpy_bmloop_repr;
3022 BPy_BMElemSeq_Type.tp_repr = NULL;
3023 BPy_BMVertSeq_Type.tp_repr = NULL;
3024 BPy_BMEdgeSeq_Type.tp_repr = NULL;
3025 BPy_BMFaceSeq_Type.tp_repr = NULL;
3026 BPy_BMLoopSeq_Type.tp_repr = NULL;
3027 BPy_BMIter_Type.tp_repr = NULL;
3030 BPy_BMesh_Type.tp_getset = bpy_bmesh_getseters;
3031 BPy_BMVert_Type.tp_getset = bpy_bmvert_getseters;
3032 BPy_BMEdge_Type.tp_getset = bpy_bmedge_getseters;
3033 BPy_BMFace_Type.tp_getset = bpy_bmface_getseters;
3034 BPy_BMLoop_Type.tp_getset = bpy_bmloop_getseters;
3035 BPy_BMElemSeq_Type.tp_getset = NULL;
3036 BPy_BMVertSeq_Type.tp_getset = bpy_bmvertseq_getseters;
3037 BPy_BMEdgeSeq_Type.tp_getset = bpy_bmedgeseq_getseters;
3038 BPy_BMFaceSeq_Type.tp_getset = bpy_bmfaceseq_getseters;
3039 BPy_BMLoopSeq_Type.tp_getset = bpy_bmloopseq_getseters;
3040 BPy_BMIter_Type.tp_getset = NULL;
3043 BPy_BMesh_Type.tp_methods = bpy_bmesh_methods;
3044 BPy_BMVert_Type.tp_methods = bpy_bmvert_methods;
3045 BPy_BMEdge_Type.tp_methods = bpy_bmedge_methods;
3046 BPy_BMFace_Type.tp_methods = bpy_bmface_methods;
3047 BPy_BMLoop_Type.tp_methods = bpy_bmloop_methods;
3048 BPy_BMElemSeq_Type.tp_methods = bpy_bmelemseq_methods;
3049 BPy_BMVertSeq_Type.tp_methods = bpy_bmvertseq_methods;
3050 BPy_BMEdgeSeq_Type.tp_methods = bpy_bmedgeseq_methods;
3051 BPy_BMFaceSeq_Type.tp_methods = bpy_bmfaceseq_methods;
3052 BPy_BMLoopSeq_Type.tp_methods = bpy_bmloopseq_methods;
3053 BPy_BMIter_Type.tp_methods = NULL;
3055 /*BPy_BMElem_Check() uses bpy_bm_elem_hash() to check types.
3056 * if this changes update the macro */
3057 BPy_BMesh_Type.tp_hash = bpy_bm_hash;
3058 BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash;
3059 BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash;
3060 BPy_BMFace_Type.tp_hash = bpy_bm_elem_hash;
3061 BPy_BMLoop_Type.tp_hash = bpy_bm_elem_hash;
3062 BPy_BMElemSeq_Type.tp_hash = NULL;
3063 BPy_BMVertSeq_Type.tp_hash = NULL;
3064 BPy_BMEdgeSeq_Type.tp_hash = NULL;
3065 BPy_BMFaceSeq_Type.tp_hash = NULL;
3066 BPy_BMLoopSeq_Type.tp_hash = NULL;
3067 BPy_BMIter_Type.tp_hash = NULL;
3069 BPy_BMElemSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
3070 BPy_BMVertSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
3071 BPy_BMEdgeSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
3072 BPy_BMFaceSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
3073 BPy_BMLoopSeq_Type.tp_as_sequence = NULL; /* this is not a seq really, only for layer access */
3075 BPy_BMElemSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
3076 BPy_BMVertSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
3077 BPy_BMEdgeSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
3078 BPy_BMFaceSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
3079 BPy_BMLoopSeq_Type.tp_as_mapping = NULL; /* this is not a seq really, only for layer access */
3082 BPy_BMVert_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3083 BPy_BMEdge_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3084 BPy_BMFace_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3085 BPy_BMLoop_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
3087 BPy_BMElemSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3088 BPy_BMVertSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3089 BPy_BMEdgeSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3090 BPy_BMFaceSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
3091 BPy_BMLoopSeq_Type.tp_iter = NULL; /* no mapping */
3093 /* only 1 iteratir so far */
3094 BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next;
3095 BPy_BMIter_Type.tp_iter = PyObject_SelfIter;
3097 BPy_BMesh_Type.tp_dealloc = (destructor)bpy_bmesh_dealloc;
3098 BPy_BMVert_Type.tp_dealloc = (destructor)bpy_bmvert_dealloc;
3099 BPy_BMEdge_Type.tp_dealloc = (destructor)bpy_bmedge_dealloc;
3100 BPy_BMFace_Type.tp_dealloc = (destructor)bpy_bmface_dealloc;
3101 BPy_BMLoop_Type.tp_dealloc = (destructor)bpy_bmloop_dealloc;
3102 BPy_BMElemSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3103 BPy_BMVertSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3104 BPy_BMEdgeSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3105 BPy_BMFaceSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3106 BPy_BMLoopSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
3107 BPy_BMIter_Type.tp_dealloc = NULL;
3109 BPy_BMesh_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3110 BPy_BMVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3111 BPy_BMEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3112 BPy_BMFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3113 BPy_BMLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3114 BPy_BMElemSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3115 BPy_BMVertSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3116 BPy_BMEdgeSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3117 BPy_BMFaceSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3118 BPy_BMLoopSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3119 BPy_BMIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
3122 PyType_Ready(&BPy_BMesh_Type);
3123 PyType_Ready(&BPy_BMVert_Type);
3124 PyType_Ready(&BPy_BMEdge_Type);
3125 PyType_Ready(&BPy_BMFace_Type);
3126 PyType_Ready(&BPy_BMLoop_Type);
3127 PyType_Ready(&BPy_BMElemSeq_Type);
3128 PyType_Ready(&BPy_BMVertSeq_Type);
3129 PyType_Ready(&BPy_BMEdgeSeq_Type);
3130 PyType_Ready(&BPy_BMFaceSeq_Type);
3131 PyType_Ready(&BPy_BMLoopSeq_Type);
3132 PyType_Ready(&BPy_BMIter_Type);
3135 /* bmesh.types submodule
3136 * ********************* */
3138 static struct PyModuleDef BPy_BM_types_module_def = {
3139 PyModuleDef_HEAD_INIT,
3140 "bmesh.types", /* m_name */
3143 NULL, /* m_methods */
3144 NULL, /* m_reload */
3145 NULL, /* m_traverse */
3150 PyObject *BPyInit_bmesh_types(void)
3152 PyObject *submodule;
3154 submodule = PyModule_Create(&BPy_BM_types_module_def);
3156 #define MODULE_TYPE_ADD(s, t) \
3157 PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
3159 /* bmesh_py_types.c */
3160 MODULE_TYPE_ADD(submodule, BPy_BMesh_Type);
3161 MODULE_TYPE_ADD(submodule, BPy_BMVert_Type);
3162 MODULE_TYPE_ADD(submodule, BPy_BMEdge_Type);
3163 MODULE_TYPE_ADD(submodule, BPy_BMFace_Type);
3164 MODULE_TYPE_ADD(submodule, BPy_BMLoop_Type);
3165 MODULE_TYPE_ADD(submodule, BPy_BMElemSeq_Type);
3166 MODULE_TYPE_ADD(submodule, BPy_BMVertSeq_Type);
3167 MODULE_TYPE_ADD(submodule, BPy_BMEdgeSeq_Type);
3168 MODULE_TYPE_ADD(submodule, BPy_BMFaceSeq_Type);
3169 MODULE_TYPE_ADD(submodule, BPy_BMLoopSeq_Type);
3170 MODULE_TYPE_ADD(submodule, BPy_BMIter_Type);
3171 /* bmesh_py_types_select.c */
3172 MODULE_TYPE_ADD(submodule, BPy_BMEditSelSeq_Type);
3173 MODULE_TYPE_ADD(submodule, BPy_BMEditSelIter_Type);
3174 /* bmesh_py_types_customdata.c */
3175 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessVert_Type);
3176 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessEdge_Type);
3177 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessFace_Type);
3178 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessLoop_Type);
3179 MODULE_TYPE_ADD(submodule, BPy_BMLayerCollection_Type);
3180 MODULE_TYPE_ADD(submodule, BPy_BMLayerItem_Type);
3181 /* bmesh_py_types_meshdata.c */
3182 MODULE_TYPE_ADD(submodule, BPy_BMLoopUV_Type);
3183 MODULE_TYPE_ADD(submodule, BPy_BMDeformVert_Type);
3185 #undef MODULE_TYPE_ADD
3190 /* Utility Functions
3191 * ***************** */
3193 PyObject *BPy_BMesh_CreatePyObject(BMesh *bm, int flag)
3197 if (bm->py_handle) {
3198 self = bm->py_handle;
3202 self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
3206 bm->py_handle = self; /* point back */
3208 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
3209 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
3210 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
3211 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
3214 return (PyObject *)self;
3219 PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
3223 void **ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
3225 /* bmesh may free layers, ensure we have one to store ourself */
3226 if (UNLIKELY(ptr == NULL)) {
3227 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
3228 ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
3236 self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type);
3237 BLI_assert(v != NULL);
3242 return (PyObject *)self;
3245 PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
3249 void **ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
3251 /* bmesh may free layers, ensure we have one to store ourself */
3252 if (UNLIKELY(ptr == NULL)) {
3253 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
3254 ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
3262 self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type);
3263 BLI_assert(e != NULL);
3268 return (PyObject *)self;
3271 PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
3275 void **ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
3277 /* bmesh may free layers, ensure we have one to store ourself */
3278 if (UNLIKELY(ptr == NULL)) {
3279 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
3280 ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
3288 self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type);
3289 BLI_assert(f != NULL);
3294 return (PyObject *)self;
3297 PyObject *BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
3301 void **ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
3303 /* bmesh may free layers, ensure we have one to store ourself */
3304 if (UNLIKELY(ptr == NULL)) {
3305 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
3306 ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
3314 self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type);
3315 BLI_assert(l != NULL);
3320 return (PyObject *)self;
3323 PyObject *BPy_BMElemSeq_CreatePyObject(BMesh *bm, BPy_BMElem *py_ele, const char itype)
3325 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMElemSeq_Type);
3327 self->py_ele = py_ele; /* can be NULL */
3328 self->itype = itype;
3330 return (PyObject *)self;
3333 PyObject *BPy_BMVertSeq_CreatePyObject(BMesh *bm)
3335 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMVertSeq_Type);
3337 self->py_ele = NULL; /* unused */
3338 self->itype = BM_VERTS_OF_MESH;
3339 return (PyObject *)self;
3342 PyObject *BPy_BMEdgeSeq_CreatePyObject(BMesh *bm)
3344 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMEdgeSeq_Type);
3346 self->py_ele = NULL; /* unused */
3347 self->itype = BM_EDGES_OF_MESH;
3348 return (PyObject *)self;
3351 PyObject *BPy_BMFaceSeq_CreatePyObject(BMesh *bm)
3353 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMFaceSeq_Type);
3355 self->py_ele = NULL; /* unused */
3356 self->itype = BM_FACES_OF_MESH;
3357 return (PyObject *)self;
3360 PyObject *BPy_BMLoopSeq_CreatePyObject(BMesh *bm)
3362 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMLoopSeq_Type);
3364 self->py_ele = NULL; /* unused */
3365 self->itype = 0; /* should never be passed to the iterator function */
3366 return (PyObject *)self;
3369 PyObject *BPy_BMIter_CreatePyObject(BMesh *bm)
3371 BPy_BMIter *self = PyObject_New(BPy_BMIter, &BPy_BMIter_Type);
3373 /* caller must initialize 'iter' member */
3374 return (PyObject *)self;
3377 /* this is just a helper func */
3378 PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele)
3380 switch (ele->htype) {
3382 return BPy_BMVert_CreatePyObject(bm, (BMVert *)ele);
3384 return BPy_BMEdge_CreatePyObject(bm, (BMEdge *)ele);
3386 return BPy_BMFace_CreatePyObject(bm, (BMFace *)ele);
3388 return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele);
3391 PyErr_SetString(PyExc_SystemError, "internal error");
3396 int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
3398 if (LIKELY(self->bm)) {
3400 /* far too slow to enable by default but handy
3401 * to uncomment for debugging tricky errors,
3402 * note that this will throw error on entering a
3403 * function where the actual error will be caused by
3404 * the previous action. */
3406 if (BM_mesh_validate(self->bm) == FALSE) {
3407 PyErr_Format(PyExc_ReferenceError,
3408 "BMesh used by %.200s has become invalid",
3409 Py_TYPE(self)->tp_name);
3417 PyErr_Format(PyExc_ReferenceError,
3418 "BMesh data of type %.200s has been removed",
3419 Py_TYPE(self)->tp_name);
3424 int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix)
3426 int ret = bpy_bm_generic_valid_check(self);
3427 if (LIKELY(ret == 0)) {
3428 if (UNLIKELY(self->bm != bm_source)) {
3429 /* could give more info here */
3430 PyErr_Format(PyExc_ValueError,
3431 "%.200s: BMesh data of type %.200s is from another mesh",
3432 error_prefix, Py_TYPE(self)->tp_name);
3439 void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
3444 /* generic python seq as BMVert/Edge/Face array,
3445 * return value must be freed with PyMem_FREE(...);
3447 * The 'bm_r' value is assigned when empty, and used when set.
3449 void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
3451 const char do_unique_check, const char do_bm_check,
3452 const char *error_prefix)
3454 BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
3458 if (!(seq_fast = PySequence_Fast(seq, error_prefix))) {