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");
104 static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
106 const char hflag = (char)GET_INT_FROM_POINTER(flag);
108 BPY_BM_CHECK_OBJ(self);
110 return PyBool_FromLong(BM_elem_flag_test(self->ele, hflag));
113 static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
115 const char hflag = (char)GET_INT_FROM_POINTER(flag);
118 BPY_BM_CHECK_INT(self);
120 param = PyLong_AsLong(value);
123 BM_elem_flag_enable(self->ele, hflag);
126 else if (param == FALSE) {
127 BM_elem_flag_disable(self->ele, hflag);
131 PyErr_Format(PyExc_TypeError,
132 "expected True/False or 0/1, not %.200s",
133 Py_TYPE(value)->tp_name);
139 PyDoc_STRVAR(bpy_bm_elem_index_doc,
140 "Index of this element.\n"
146 " This value is not necessarily valid, while editing the mesh it can become *dirty*.\n"
148 " It's also possible to assign any number to this attribute for a scripts internal logic.\n"
150 " To ensure the value is up to date - see :class:`BMElemSeq.index_update`.\n"
152 static PyObject *bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
154 BPY_BM_CHECK_OBJ(self);
156 return PyLong_FromLong(BM_elem_index_get(self->ele));
159 static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
163 BPY_BM_CHECK_INT(self);
165 param = PyLong_AsLong(value);
167 if (param == -1 && PyErr_Occurred()) {
168 PyErr_SetString(PyExc_TypeError,
169 "expected an int type");
173 BM_elem_index_set(self->ele, param); /* set_dirty! */
175 /* when setting the index assume its set invalid */
176 if (self->ele->head.htype & (BM_VERT | BM_EDGE | BM_FACE)) {
177 self->bm->elem_index_dirty |= self->ele->head.htype;
184 /* type specific get/sets
185 * ---------------------- */
191 /* doc-strings for all uses of this funcion */
193 PyDoc_STRVAR(bpy_bmvertseq_doc,
194 "This meshes vert sequence (read-only).\n\n:type: :class:`BMVertSeq`"
196 static PyObject *bpy_bmvertseq_get(BPy_BMesh *self, void *UNUSED(closure))
198 BPY_BM_CHECK_OBJ(self);
199 return BPy_BMVertSeq_CreatePyObject(self->bm);
202 PyDoc_STRVAR(bpy_bmedgeseq_doc,
203 "This meshes edge sequence (read-only).\n\n:type: :class:`BMEdgeSeq`"
205 static PyObject *bpy_bmedgeseq_get(BPy_BMesh *self, void *UNUSED(closure))
207 BPY_BM_CHECK_OBJ(self);
208 return BPy_BMEdgeSeq_CreatePyObject(self->bm);
211 PyDoc_STRVAR(bpy_bmfaceseq_doc,
212 "This meshes face sequence (read-only).\n\n:type: :class:`BMFaceSeq`"
214 static PyObject *bpy_bmfaceseq_get(BPy_BMesh *self, void *UNUSED(closure))
216 BPY_BM_CHECK_OBJ(self);
217 return BPy_BMFaceSeq_CreatePyObject(self->bm);
220 PyDoc_STRVAR(bpy_bmloopseq_doc,
221 "This meshes face sequence (read-only).\n\n:type: :class:`BMLoopSeq`"
223 static PyObject *bpy_bmloopseq_get(BPy_BMesh *self, void *UNUSED(closure))
225 BPY_BM_CHECK_OBJ(self);
226 return BPy_BMLoopSeq_CreatePyObject(self->bm);
230 PyDoc_STRVAR(bpy_bmvert_link_edges_doc,
231 "Edges connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
233 PyDoc_STRVAR(bpy_bmvert_link_faces_doc,
234 "Faces connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
236 PyDoc_STRVAR(bpy_bmvert_link_loops_doc,
237 "Loops that use this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
240 PyDoc_STRVAR(bpy_bmedge_verts_doc,
241 "Verts this edge uses (always 2), (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
243 PyDoc_STRVAR(bpy_bmedge_link_faces_doc,
244 "Faces connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
246 PyDoc_STRVAR(bpy_bmedge_link_loops_doc,
247 "Loops connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
250 PyDoc_STRVAR(bpy_bmface_verts_doc,
251 "Verts of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
253 PyDoc_STRVAR(bpy_bmface_edges_doc,
254 "Edges of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMEdge`"
256 PyDoc_STRVAR(bpy_bmface_loops_doc,
257 "Loops of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
260 PyDoc_STRVAR(bpy_bmloops_link_loops_doc,
261 "Loops connected to this loop, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
264 static PyObject *bpy_bmelemseq_elem_get(BPy_BMElem *self, void *itype)
266 BPY_BM_CHECK_OBJ(self);
267 return BPy_BMElemSeq_CreatePyObject(self->bm, self, GET_INT_FROM_POINTER(itype));
271 PyDoc_STRVAR(bpy_bm_is_valid_doc,
272 "True when this element is valid (hasn't been removed).\n\n:type: boolean"
274 static PyObject *bpy_bm_is_valid_get(BPy_BMGeneric *self)
276 return PyBool_FromLong(BPY_BM_IS_VALID(self));
279 PyDoc_STRVAR(bpy_bmesh_is_wrapped_doc,
280 "True when this mesh is owned by blender (typically the editmode BMesh).\n\n:type: boolean"
282 static PyObject *bpy_bmesh_is_wrapped_get(BPy_BMesh *self)
284 BPY_BM_CHECK_OBJ(self);
286 return PyBool_FromLong(self->flag & BPY_BMFLAG_IS_WRAPPED);
289 PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
290 "The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an empty set.\n\n:type: set"
292 static PyObject *bpy_bmesh_select_mode_get(BPy_BMesh *self)
294 BPY_BM_CHECK_OBJ(self);
296 return PyC_FlagSet_FromBitfield(bpy_bm_scene_vert_edge_face_flags, self->bm->selectmode);
299 static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
302 BPY_BM_CHECK_INT(self);
304 if (PyC_FlagSet_ToBitfield(bpy_bm_scene_vert_edge_face_flags, value, &flag, "bm.select_mode") == -1) {
307 else if (flag == 0) {
308 PyErr_SetString(PyExc_TypeError,
309 "bm.select_mode: cant assignt an empty value");
313 self->bm->selectmode = flag;
318 PyDoc_STRVAR(bpy_bmesh_select_history_doc,
319 "Sequence of selected items (the last is displayed as active).\n\n:type: :class:`BMEditSelSeq`"
321 static PyObject *bpy_bmesh_select_history_get(BPy_BMesh *self)
323 BPY_BM_CHECK_OBJ(self);
325 return BPy_BMEditSel_CreatePyObject(self->bm);
328 static int bpy_bmesh_select_history_set(BPy_BMesh *self, PyObject *value)
330 BPY_BM_CHECK_INT(self);
332 return BPy_BMEditSel_Assign(self, value);
338 PyDoc_STRVAR(bpy_bmvert_co_doc,
339 "The coordinates for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
341 static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
343 BPY_BM_CHECK_OBJ(self);
344 return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
347 static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
349 BPY_BM_CHECK_INT(self);
351 if (mathutils_array_parse(self->v->co, 3, 3, value, "BMVert.co") != -1) {
360 PyDoc_STRVAR(bpy_bmvert_normal_doc,
361 "The normal for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
363 static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
365 BPY_BM_CHECK_OBJ(self);
366 return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
369 static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
371 BPY_BM_CHECK_INT(self);
373 if (mathutils_array_parse(self->v->no, 3, 3, value, "BMVert.normal") != -1) {
382 PyDoc_STRVAR(bpy_bmvert_is_manifold_doc,
383 "True when this vertex is manifold (read-only).\n\n:type: boolean"
385 static PyObject *bpy_bmvert_is_manifold_get(BPy_BMVert *self)
387 BPY_BM_CHECK_OBJ(self);
388 return PyBool_FromLong(BM_vert_is_manifold(self->v));
392 PyDoc_STRVAR(bpy_bmvert_is_wire_doc,
393 "True when this vertex is not connected to any faces (read-only).\n\n:type: boolean"
395 static PyObject *bpy_bmvert_is_wire_get(BPy_BMVert *self)
397 BPY_BM_CHECK_OBJ(self);
398 return PyBool_FromLong(BM_vert_is_wire(self->v));
405 PyDoc_STRVAR(bpy_bmedge_is_manifold_doc,
406 "True when this edge is manifold (read-only).\n\n:type: boolean"
408 static PyObject *bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
410 BPY_BM_CHECK_OBJ(self);
411 return PyBool_FromLong(BM_edge_is_manifold(self->e));
415 PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
416 "True when this edge is not connected to any faces (read-only).\n\n:type: boolean"
418 static PyObject *bpy_bmedge_is_wire_get(BPy_BMEdge *self)
420 BPY_BM_CHECK_OBJ(self);
421 return PyBool_FromLong(BM_edge_is_wire(self->e));
425 PyDoc_STRVAR(bpy_bmedge_is_boundary_doc,
426 "True when this edge is at the boundary of a face (read-only).\n\n:type: boolean"
428 static PyObject *bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
430 BPY_BM_CHECK_OBJ(self);
431 return PyBool_FromLong(BM_edge_is_boundary(self->e));
438 PyDoc_STRVAR(bpy_bmface_normal_doc,
439 "The normal for this face as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
441 static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
443 BPY_BM_CHECK_OBJ(self);
444 return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
447 static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
449 BPY_BM_CHECK_INT(self);
451 if (mathutils_array_parse(self->f->no, 3, 3, value, "BMFace.normal") != -1) {
459 PyDoc_STRVAR(bpy_bmface_material_index_doc,
460 "The faces material index.\n\n:type: int"
462 static PyObject *bpy_bmface_material_index_get(BPy_BMFace *self)
464 BPY_BM_CHECK_OBJ(self);
465 return PyLong_FromLong(self->f->mat_nr);
468 static int bpy_bmface_material_index_set(BPy_BMFace *self, PyObject *value)
472 BPY_BM_CHECK_INT(self);
474 param = PyLong_AsLong(value);
476 if (param == -1 && PyErr_Occurred()) {
477 PyErr_SetString(PyExc_TypeError,
478 "expected an int type");
481 else if ((param < 0) || (param > MAXMAT)) {
482 /* normally we clamp but in this case raise an error */
483 PyErr_SetString(PyExc_ValueError,
484 "material index outside of usable range (0 - 32766)");
488 self->f->mat_nr = (short)param;
496 PyDoc_STRVAR(bpy_bmloop_vert_doc,
497 "The loops vertex (read-only).\n\n:type: :class:`BMVert`"
499 static PyObject *bpy_bmloop_vert_get(BPy_BMLoop *self)
501 BPY_BM_CHECK_OBJ(self);
502 return BPy_BMVert_CreatePyObject(self->bm, self->l->v);
506 PyDoc_STRVAR(bpy_bmloop_edge_doc,
507 "The loops edge (between this loop and the next), (read-only).\n\n:type: :class:`BMEdge`"
509 static PyObject *bpy_bmloop_edge_get(BPy_BMLoop *self)
511 BPY_BM_CHECK_OBJ(self);
512 return BPy_BMEdge_CreatePyObject(self->bm, self->l->e);
516 PyDoc_STRVAR(bpy_bmloop_face_doc,
517 "The face this loop makes (read-only).\n\n:type: :class:`BMFace`"
519 static PyObject *bpy_bmloop_face_get(BPy_BMLoop *self)
521 BPY_BM_CHECK_OBJ(self);
522 return BPy_BMFace_CreatePyObject(self->bm, self->l->f);
525 PyDoc_STRVAR(bpy_bmloop_link_loop_next_doc,
526 "The next face corner (read-only).\n\n:type: :class:`BMLoop`"
528 static PyObject *bpy_bmloop_link_loop_next_get(BPy_BMLoop *self)
530 BPY_BM_CHECK_OBJ(self);
531 return BPy_BMLoop_CreatePyObject(self->bm, self->l->next);
534 PyDoc_STRVAR(bpy_bmloop_link_loop_prev_doc,
535 "The previous face corner (read-only).\n\n:type: :class:`BMLoop`"
537 static PyObject *bpy_bmloop_link_loop_prev_get(BPy_BMLoop *self)
539 BPY_BM_CHECK_OBJ(self);
540 return BPy_BMLoop_CreatePyObject(self->bm, self->l->prev);
546 /* note: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly */
547 PyDoc_STRVAR(bpy_bmelemseq_layers_doc,
548 "blah blah (read-only).\n\n:type: :class:`BMLayerAccess`"
550 static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype)
552 BPY_BM_CHECK_OBJ(self);
554 return BPy_BMLayerAccess_CreatePyObject(self->bm, GET_INT_FROM_POINTER(htype));
557 static PyGetSetDef bpy_bmesh_getseters[] = {
558 {(char *)"verts", (getter)bpy_bmvertseq_get, (setter)NULL, (char *)bpy_bmvertseq_doc, NULL},
559 {(char *)"edges", (getter)bpy_bmedgeseq_get, (setter)NULL, (char *)bpy_bmedgeseq_doc, NULL},
560 {(char *)"faces", (getter)bpy_bmfaceseq_get, (setter)NULL, (char *)bpy_bmfaceseq_doc, NULL},
561 {(char *)"loops", (getter)bpy_bmloopseq_get, (setter)NULL, (char *)bpy_bmloopseq_doc, NULL},
562 {(char *)"select_mode", (getter)bpy_bmesh_select_mode_get, (setter)bpy_bmesh_select_mode_set, (char *)bpy_bmesh_select_mode_doc, NULL},
564 {(char *)"select_history", (getter)bpy_bmesh_select_history_get, (setter)bpy_bmesh_select_history_set, (char *)bpy_bmesh_select_history_doc, NULL},
566 /* readonly checks */
567 {(char *)"is_wrapped", (getter)bpy_bmesh_is_wrapped_get, (setter)NULL, (char *)bpy_bmesh_is_wrapped_doc, NULL}, /* as with mathutils */
568 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
570 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
573 static PyGetSetDef bpy_bmvert_getseters[] = {
575 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
576 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
577 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
578 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
580 {(char *)"co", (getter)bpy_bmvert_co_get, (setter)bpy_bmvert_co_set, (char *)bpy_bmvert_co_doc, NULL},
581 {(char *)"normal", (getter)bpy_bmvert_normal_get, (setter)bpy_bmvert_normal_set, (char *)bpy_bmvert_normal_doc, NULL},
583 /* connectivity data */
584 {(char *)"link_edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_edges_doc, (void *)BM_EDGES_OF_VERT},
585 {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_faces_doc, (void *)BM_FACES_OF_VERT},
586 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_loops_doc, (void *)BM_LOOPS_OF_VERT},
588 /* readonly checks */
589 {(char *)"is_manifold", (getter)bpy_bmvert_is_manifold_get, (setter)NULL, (char *)bpy_bmvert_is_manifold_doc, NULL},
590 {(char *)"is_wire", (getter)bpy_bmvert_is_wire_get, (setter)NULL, (char *)bpy_bmvert_is_wire_doc, NULL},
591 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
593 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
596 static PyGetSetDef bpy_bmedge_getseters[] = {
598 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
599 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
600 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
601 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
603 {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
604 {(char *)"seam", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SEAM},
606 /* connectivity data */
607 {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_verts_doc, (void *)BM_VERTS_OF_EDGE},
609 {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_faces_doc, (void *)BM_FACES_OF_EDGE},
610 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_loops_doc, (void *)BM_LOOPS_OF_EDGE},
612 /* readonly checks */
613 {(char *)"is_manifold", (getter)bpy_bmedge_is_manifold_get, (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
614 {(char *)"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
615 {(char *)"is_boundary", (getter)bpy_bmedge_is_boundary_get, (setter)NULL, (char *)bpy_bmedge_is_boundary_doc, NULL},
616 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
618 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
621 static PyGetSetDef bpy_bmface_getseters[] = {
623 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
624 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
625 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
626 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
628 {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
630 {(char *)"normal", (getter)bpy_bmface_normal_get, (setter)bpy_bmface_normal_set, (char *)bpy_bmface_normal_doc, NULL},
632 {(char *)"material_index", (getter)bpy_bmface_material_index_get, (setter)bpy_bmface_material_index_set, (char *)bpy_bmface_material_index_doc, NULL},
634 /* connectivity data */
635 {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_verts_doc, (void *)BM_VERTS_OF_FACE},
636 {(char *)"edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_edges_doc, (void *)BM_EDGES_OF_FACE},
637 {(char *)"loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_loops_doc, (void *)BM_LOOPS_OF_FACE},
639 /* readonly checks */
640 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
642 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
645 static PyGetSetDef bpy_bmloop_getseters[] = {
647 // flags are available but not used for loops.
648 // {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
649 // {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
650 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
651 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
653 {(char *)"vert", (getter)bpy_bmloop_vert_get, (setter)NULL, (char *)bpy_bmloop_vert_doc, NULL},
654 {(char *)"edge", (getter)bpy_bmloop_edge_get, (setter)NULL, (char *)bpy_bmloop_edge_doc, NULL},
655 {(char *)"face", (getter)bpy_bmloop_face_get, (setter)NULL, (char *)bpy_bmloop_face_doc, NULL},
657 /* connectivity data */
658 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmloops_link_loops_doc, (void *)BM_LOOPS_OF_LOOP},
659 {(char *)"link_loop_next", (getter)bpy_bmloop_link_loop_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_next_doc, NULL},
660 {(char *)"link_loop_prev", (getter)bpy_bmloop_link_loop_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_prev_doc, NULL},
662 /* readonly checks */
663 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
665 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
668 static PyGetSetDef bpy_bmvertseq_getseters[] = {
669 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_VERT},
670 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
672 static PyGetSetDef bpy_bmedgeseq_getseters[] = {
673 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_EDGE},
674 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
676 static PyGetSetDef bpy_bmfaceseq_getseters[] = {
677 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_FACE},
678 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
680 static PyGetSetDef bpy_bmloopseq_getseters[] = {
681 {(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_LOOP},
682 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
693 PyDoc_STRVAR(bpy_bmesh_copy_doc,
694 ".. method:: copy()\n"
696 " :return: A copy of this BMesh.\n"
697 " :rtype: :class:`BMesh`\n"
699 static PyObject *bpy_bmesh_copy(BPy_BMesh *self)
704 BPY_BM_CHECK_OBJ(self);
708 bm_copy = BM_mesh_copy(bm);
711 return BPy_BMesh_CreatePyObject(bm_copy, BPY_BMFLAG_NOP);
714 PyErr_SetString(PyExc_SystemError, "Unable to copy BMesh, internal error");
719 PyDoc_STRVAR(bpy_bmesh_clear_doc,
720 ".. method:: clear()\n"
722 " Clear all mesh data.\n"
724 static PyObject *bpy_bmesh_clear(BPy_BMesh *self)
728 BPY_BM_CHECK_OBJ(self);
737 PyDoc_STRVAR(bpy_bmesh_free_doc,
738 ".. method:: free()\n"
740 " Explicitly free the BMesh data from memory, causing exceptions on further access.\n"
744 " The BMesh is freed automatically, typically when the script finishes executing.\n"
745 " However in some cases its hard to predict when this will be and its useful to\n"
746 " explicitly free the data.\n"
748 static PyObject *bpy_bmesh_free(BPy_BMesh *self)
751 BMesh *bm = self->bm;
753 if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
757 bpy_bm_generic_invalidate((BPy_BMGeneric *)self);
763 PyDoc_STRVAR(bpy_bmesh_to_mesh_doc,
764 ".. method:: to_mesh(mesh)\n"
766 " Writes this BMesh data into an existing Mesh datablock.\n"
768 " :arg mesh: The mesh data to write into.\n"
769 " :type mesh: :class:`Mesh`\n"
771 static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
777 BPY_BM_CHECK_OBJ(self);
779 if (!PyArg_ParseTuple(args, "O:to_mesh", &py_mesh) ||
780 !(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
785 /* we could allow this but its almost certainly _not_ what script authors want */
786 if (me->edit_btmesh) {
787 PyErr_Format(PyExc_ValueError,
788 "to_mesh(): Mesh '%s' is in editmode", me->id.name + 2);
794 BM_mesh_bm_to_me(bm, me, FALSE);
796 /* we could have the user do this but if they forget blender can easy crash
797 * since the references arrays for the objects derived meshes are now invalid */
798 DAG_id_tag_update(&me->id, OB_RECALC_DATA);
803 /* note: rna_Object_to_mesh() also has apply_modifiers arg that works the same way */
804 PyDoc_STRVAR(bpy_bmesh_from_object_doc,
805 ".. method:: from_object(mesh, apply_modifiers=True)\n"
807 " Initialize this bmesh from existing object datablock.\n"
809 " :arg object: The object data to load.\n"
810 " :type object: :class:`Object`\n"
811 " :arg apply_modifiers: Use the final display mesh rather then the deformed cage.\n"
812 " :type apply_modifiers: boolean\n"
814 static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args)
819 int apply_modifiers = TRUE;
822 BPY_BM_CHECK_OBJ(self);
824 if (!PyArg_ParseTuple(args, "O|i:from_object", &py_object, &apply_modifiers) ||
825 !(ob = PyC_RNA_AsPointer(py_object, "Object")))
830 dm = apply_modifiers ? ob->derivedFinal : ob->derivedDeform;
833 PyErr_Format(PyExc_ValueError,
834 "from_object(...): Object '%s' has no usable mesh data", ob->id.name + 2);
840 DM_to_bmesh_ex(dm, bm);
846 PyDoc_STRVAR(bpy_bmesh_from_mesh_doc,
847 ".. method:: from_mesh(mesh, use_shape_key=False, shape_key_index=0)\n"
849 " Initialize this bmesh from existing mesh datablock.\n"
851 " :arg mesh: The mesh data to load.\n"
852 " :type mesh: :class:`Mesh`\n"
853 " :arg use_shape_key: Use the locations from a shape key.\n"
854 " :type use_shape_key: boolean\n"
855 " :arg shape_key_index: The shape key index to use.\n"
856 " :type shape_key_index: int\n"
858 static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *kw)
860 static const char *kwlist[] = {"mesh", "use_shape_key", "shape_key_index", NULL};
864 int use_shape_key = FALSE;
865 int shape_key_index = 0;
867 if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:from_mesh", (char **)kwlist,
868 &py_mesh, &use_shape_key, &shape_key_index) ||
869 !(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
876 BM_mesh_bm_from_me(bm, me, use_shape_key, shape_key_index + 1);
882 PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc,
883 ".. method:: select_flush_mode()\n"
885 " flush selection based on the current mode current :class:`BMesh.select_mode`.\n"
887 static PyObject *bpy_bmesh_select_flush_mode(BPy_BMesh *self)
889 BPY_BM_CHECK_OBJ(self);
891 BM_mesh_select_mode_flush(self->bm);
897 PyDoc_STRVAR(bpy_bmesh_select_flush_doc,
898 ".. method:: select_flush(select)\n"
900 " Flush selection, independent of the current selection mode.\n"
902 " :arg select: flush selection or de-selected elements.\n"
903 " :type select: boolean\n"
905 static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
909 BPY_BM_CHECK_OBJ(self);
911 param = PyLong_AsLong(value);
912 if (param != FALSE && param != TRUE) {
913 PyErr_SetString(PyExc_TypeError,
914 "expected a boolean type 0/1");
918 if (param) BM_mesh_select_flush(self->bm);
919 else BM_mesh_deselect_flush(self->bm);
925 PyDoc_STRVAR(bpy_bmesh_normal_update_doc,
926 ".. method:: normal_update(skip_hidden=False)\n"
928 " Update mesh normals.\n"
930 " :arg skip_hidden: When True hidden elements are ignored.\n"
931 " :type skip_hidden: boolean\n"
933 static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self, PyObject *args)
936 int skip_hidden = FALSE;
938 BPY_BM_CHECK_OBJ(self);
940 if (!PyArg_ParseTuple(args, "|i:normal_update", &skip_hidden)) {
944 BM_mesh_normals_update(self->bm, skip_hidden);
950 PyDoc_STRVAR(bpy_bmesh_transform_doc,
951 ".. method:: transform(matrix, filter=None)\n"
953 " Transform the mesh (optionally filtering flagged data only).\n"
955 " :arg matrix: transform matrix.\n"
956 " :type matrix: 4x4 :class:`mathutils.Matrix`\n"
957 " :arg filter: set of values in ('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG').\n"
958 " :type filter: set\n"
960 static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
962 static const char *kwlist[] = {"matrix", "filter", NULL};
965 PyObject *filter = NULL;
966 int filter_flags = 0;
968 BPY_BM_CHECK_OBJ(self);
970 if (!PyArg_ParseTupleAndKeywords(args, kw,
974 &PySet_Type, &filter))
983 if (BaseMath_ReadCallback(mat) == -1) {
986 else if (mat->num_col != 4 || mat->num_row != 4) {
987 PyErr_SetString(PyExc_ValueError,
988 "expected a 4x4 matrix");
992 if (filter != NULL && PyC_FlagSet_ToBitfield(bpy_bm_hflag_all_flags, filter,
993 &filter_flags, "bm.transform") == -1)
998 mat_ptr = mat->matrix;
1000 if (!filter_flags) {
1001 BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1002 mul_m4_v3((float (*)[4])mat_ptr, eve->co);
1006 char filter_flags_ch = (char)filter_flags;
1007 BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1008 if (eve->head.hflag & filter_flags_ch) {
1009 mul_m4_v3((float (*)[4])mat_ptr, eve->co);
1022 PyDoc_STRVAR(bpy_bm_elem_select_set_doc,
1023 ".. method:: select_set(select)\n"
1025 " Set the selection.\n"
1026 " This is different from the *select* attribute because it updates the selection state of assosiated geometry.\n"
1028 " :arg select: Select or de-select.\n"
1029 " :type select: boolean\n"
1033 " Currently this only flushes down, so selecting a face will select all its vertices but de-selecting a vertex "
1034 " won't de-select all the faces that use it, before finishing with a mesh typically flushing is still needed.\n"
1036 static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
1040 BPY_BM_CHECK_OBJ(self);
1042 param = PyLong_AsLong(value);
1043 if (param != FALSE && param != TRUE) {
1044 PyErr_SetString(PyExc_TypeError,
1045 "expected a boolean type 0/1");
1049 BM_elem_select_set(self->bm, self->ele, param);
1055 PyDoc_STRVAR(bpy_bm_elem_hide_set_doc,
1056 ".. method:: hide_set(hide)\n"
1058 " Set the hide state.\n"
1059 " This is different from the *hide* attribute because it updates the selection and hide state of assosiated geometry.\n"
1061 " :arg hide: Hidden or visible.\n"
1062 " :type hide: boolean\n"
1064 static PyObject *bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value)
1068 BPY_BM_CHECK_OBJ(self);
1070 param = PyLong_AsLong(value);
1071 if (param != FALSE && param != TRUE) {
1072 PyErr_SetString(PyExc_TypeError,
1073 "expected a boolean type 0/1");
1077 BM_elem_hide_set(self->bm, self->ele, param);
1083 PyDoc_STRVAR(bpy_bm_elem_copy_from_doc,
1084 ".. method:: copy_from(other)\n"
1086 " Copy values from another element of matching type.\n"
1088 static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
1090 BPY_BM_CHECK_OBJ(self);
1092 if (Py_TYPE(self) != Py_TYPE(value)) {
1093 PyErr_Format(PyExc_TypeError,
1094 "expected element of type '%.200s' not '%.200s'",
1095 Py_TYPE(self)->tp_name, Py_TYPE(value)->tp_name);
1099 if (value->ele != self->ele) {
1100 BM_elem_attrs_copy(value->bm, self->bm, value->ele, self->ele);
1111 PyDoc_STRVAR(bpy_bmvert_copy_from_vert_interp_doc,
1112 ".. method:: copy_from_vert_interp(vert_pair, fac)\n"
1114 " Interpolate the customdata from a vert between 2 other verts.\n"
1116 " :arg vert_pair: The vert to interpolate data from.\n"
1117 " :type vert_pair: :class:`BMVert`\n"
1119 static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *args)
1124 BPY_BM_CHECK_OBJ(self);
1126 if (!PyArg_ParseTuple(args, "Of:BMVert.copy_from_vert_interp",
1132 BMesh *bm = self->bm;
1133 BMVert **vert_array = NULL;
1134 Py_ssize_t vert_seq_len; /* always 2 */
1136 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1137 &vert_seq_len, BM_VERT,
1138 TRUE, TRUE, "BMVert.copy_from_vert_interp(...)");
1140 if (vert_array == NULL) {
1144 BM_data_interp_from_verts(bm, vert_array[0], vert_array[1], self->v, CLAMPIS(fac, 0.0f, 1.0f));
1146 PyMem_FREE(vert_array);
1152 PyDoc_STRVAR(bpy_bmvert_copy_from_face_interp_doc,
1153 ".. method:: copy_from_face_interp(face)\n"
1155 " Interpolate the customdata from a face onto this loop (the loops vert should overlap the face).\n"
1157 " :arg face: The face to interpolate data from.\n"
1158 " :type face: :class:`BMFace`\n"
1160 static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *args)
1162 BPy_BMFace *py_face = NULL;
1164 BPY_BM_CHECK_OBJ(self);
1166 if (!PyArg_ParseTuple(args, "O!:BMVert.copy_from_face_interp",
1167 &BPy_BMFace_Type, &py_face))
1172 BMesh *bm = self->bm;
1174 BPY_BM_CHECK_OBJ(py_face);
1176 if (py_face->bm != bm) {
1177 PyErr_SetString(PyExc_ValueError,
1178 "BMVert.copy_from_face_interp(face): face is from another mesh");
1182 BM_vert_interp_from_face(bm, self->v, py_face->f);
1189 PyDoc_STRVAR(bpy_bmvert_calc_edge_angle_doc,
1190 ".. method:: calc_edge_angle()\n"
1192 " Return the angle between this verts 2 connected edges.\n"
1194 " :return: Angle between edges in radians.\n"
1197 static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self)
1199 BPY_BM_CHECK_OBJ(self);
1200 return PyFloat_FromDouble(BM_vert_edge_angle(self->v));
1203 PyDoc_STRVAR(bpy_bmvert_calc_shell_factor_doc,
1204 ".. method:: calc_shell_factor()\n"
1206 " Return a multiplier calculated based on the sharpness of the vertex.\n"
1207 " Where a flat surface gives 1.0, and higher values sharper edges.\n"
1208 " This is used to maintain shell thickness when offsetting verts along their normals.\n"
1210 " :return: offset multiplier\n"
1213 static PyObject *bpy_bmvert_calc_shell_factor(BPy_BMVert *self)
1215 BPY_BM_CHECK_OBJ(self);
1216 return PyFloat_FromDouble(BM_vert_shell_factor(self->v));
1219 PyDoc_STRVAR(bpy_bmvert_normal_update_doc,
1220 ".. method:: normal_update()\n"
1222 " Update vertex normal.\n"
1224 static PyObject *bpy_bmvert_normal_update(BPy_BMVert *self)
1226 BPY_BM_CHECK_OBJ(self);
1228 BM_vert_normal_update(self->v);
1237 PyDoc_STRVAR(bpy_bmedge_calc_length_doc,
1238 ".. method:: calc_length()\n"
1240 " :return: The length between both verts.\n"
1243 static PyObject *bpy_bmedge_calc_length(BPy_BMEdge *self)
1245 BPY_BM_CHECK_OBJ(self);
1246 return PyFloat_FromDouble(len_v3v3(self->e->v1->co, self->e->v2->co));
1249 PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
1250 ".. method:: calc_face_angle()\n"
1252 " :return: The angle between 2 connected faces in radians.\n"
1255 static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
1257 BPY_BM_CHECK_OBJ(self);
1258 return PyFloat_FromDouble(BM_edge_face_angle(self->e));
1261 PyDoc_STRVAR(bpy_bmedge_calc_tangent_doc,
1262 ".. method:: calc_tangent(loop)\n"
1264 " Return the tangent at this edge relative to a face (pointing inward into the face).\n"
1265 " This uses the face normal for calculation.\n"
1267 " :arg loop: The loop used for tangent calculation.\n"
1268 " :type loop: :class:`BMLoop`\n"
1269 " :return: a normalized vector.\n"
1270 " :rtype: :class:`mathutils.Vector`\n"
1272 static PyObject *bpy_bmedge_calc_tangent(BPy_BMEdge *self, PyObject *args)
1274 BPy_BMLoop *py_loop;
1275 BPY_BM_CHECK_OBJ(self);
1277 if (!PyArg_ParseTuple(args, "O!:BMEdge.calc_face_tangent",
1278 &BPy_BMLoop_Type, &py_loop))
1284 BPY_BM_CHECK_OBJ(py_loop);
1285 /* no need to check if they are from the same mesh or even connected */
1286 BM_edge_face_tangent(self->e, py_loop->l, vec);
1287 return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1292 PyDoc_STRVAR(bpy_bmedge_other_vert_doc,
1293 ".. method:: other_vert(vert)\n"
1295 " Return the other vertex on this edge or None if the vertex is not used by this edge.\n"
1297 " :arg vert: a vert in this edge.\n"
1298 " :type vert: :class:`BMVert`\n"
1299 " :return: The edges other vert.\n"
1300 " :rtype: :class:`BMVert` or None\n"
1302 static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
1305 BPY_BM_CHECK_OBJ(self);
1307 if (!BPy_BMVert_Check(value)) {
1308 PyErr_Format(PyExc_TypeError,
1309 "BMEdge.other_vert(vert): BMVert expected, not '%.200s'",
1310 Py_TYPE(value)->tp_name);
1314 BPY_BM_CHECK_OBJ(value);
1316 if (self->bm != value->bm) {
1317 PyErr_SetString(PyExc_ValueError,
1318 "BMEdge.other_vert(vert): vert is from another mesh");
1322 other = BM_edge_other_vert(self->e, value->v);
1325 return BPy_BMVert_CreatePyObject(self->bm, other);
1328 /* could raise an exception here */
1334 PyDoc_STRVAR(bpy_bmedge_normal_update_doc,
1335 ".. method:: normal_update()\n"
1337 " Update edges vertex normals.\n"
1339 static PyObject *bpy_bmedge_normal_update(BPy_BMEdge *self)
1341 BPY_BM_CHECK_OBJ(self);
1343 BM_edge_normals_update(self->e);
1352 PyDoc_STRVAR(bpy_bmface_copy_from_face_interp_doc,
1353 ".. method:: copy_from_face_interp(face)\n"
1355 " Interpolate the customdata from another face onto this one (faces should overlap).\n"
1357 " :arg face: The face to interpolate data from.\n"
1358 " :type face: :class:`BMFace`\n"
1360 static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
1362 BPy_BMFace *py_face = NULL;
1364 BPY_BM_CHECK_OBJ(self);
1366 if (!PyArg_ParseTuple(args, "O!:BMFace.copy_from_face_interp",
1367 &BPy_BMFace_Type, &py_face))
1372 BMesh *bm = self->bm;
1374 BPY_BM_CHECK_OBJ(py_face);
1376 if (py_face->bm != bm) {
1377 PyErr_SetString(PyExc_ValueError,
1378 "BMFace.copy_from_face_interp(face): face is from another mesh");
1382 BM_face_interp_from_face(bm, self->f, py_face->f);
1389 PyDoc_STRVAR(bpy_bmface_copy_doc,
1390 ".. method:: copy(verts=True, edges=True)\n"
1392 " Make a copy of this face.\n"
1394 " :arg verts: When set, the faces verts will be duplicated too.\n"
1395 " :type verts: boolean\n"
1396 " :arg edges: When set, the faces edges will be duplicated too.\n"
1397 " :type edges: boolean\n"
1398 " :return: The newly created face.\n"
1399 " :rtype: :class:`BMFace`\n"
1401 static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
1403 static const char *kwlist[] = {"verts", "edges", NULL};
1405 BMesh *bm = self->bm;
1406 int do_verts = TRUE;
1407 int do_edges = TRUE;
1410 BPY_BM_CHECK_OBJ(self);
1412 if (!PyArg_ParseTupleAndKeywords(args, kw,
1415 &do_verts, &do_edges))
1420 f_cpy = BM_face_copy(bm, self->f, do_verts, do_edges);
1423 return BPy_BMFace_CreatePyObject(bm, f_cpy);
1426 PyErr_SetString(PyExc_ValueError,
1427 "BMFace.copy(): couldn't create the new face, internal error");
1433 PyDoc_STRVAR(bpy_bmface_calc_area_doc,
1434 ".. method:: calc_area()\n"
1436 " Return the area of the face.\n"
1438 " :return: Return the area of the face.\n"
1441 static PyObject *bpy_bmface_calc_area(BPy_BMFace *self)
1443 BPY_BM_CHECK_OBJ(self);
1444 return PyFloat_FromDouble(BM_face_area_calc(self->f));
1448 PyDoc_STRVAR(bpy_bmface_calc_perimeter_doc,
1449 ".. method:: calc_perimeter()\n"
1451 " Return the perimeter of the face.\n"
1453 " :return: Return the perimeter of the face.\n"
1456 static PyObject *bpy_bmface_calc_perimeter(BPy_BMFace *self)
1458 BPY_BM_CHECK_OBJ(self);
1459 return PyFloat_FromDouble(BM_face_perimeter_calc(self->f));
1463 PyDoc_STRVAR(bpy_bmface_calc_center_mean_doc,
1464 ".. method:: calc_center_median()\n"
1466 " Return median center of the face.\n"
1468 " :return: a 3D vector.\n"
1469 " :rtype: :class:`mathutils.Vector`\n"
1471 static PyObject *bpy_bmface_calc_center_mean(BPy_BMFace *self)
1475 BPY_BM_CHECK_OBJ(self);
1476 BM_face_center_mean_calc(self->f, cent);
1477 return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
1481 PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
1482 ".. method:: calc_center_bounds()\n"
1484 " Return bounds center of the face.\n"
1486 " :return: a 3D vector.\n"
1487 " :rtype: :class:`mathutils.Vector`\n"
1489 static PyObject *bpy_bmface_calc_center_bounds(BPy_BMFace *self)
1493 BPY_BM_CHECK_OBJ(self);
1494 BM_face_center_bounds_calc(self->f, cent);
1495 return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
1499 PyDoc_STRVAR(bpy_bmface_normal_update_doc,
1500 ".. method:: normal_update()\n"
1502 " Update faces normal.\n"
1504 static PyObject *bpy_bmface_normal_update(BPy_BMFace *self)
1506 BPY_BM_CHECK_OBJ(self);
1508 BM_face_normal_update(self->f);
1517 PyDoc_STRVAR(bpy_bmloop_copy_from_face_interp_doc,
1518 ".. method:: copy_from_face_interp(face, vert=True, multires=True)\n"
1520 " Interpolate the customdata from a face onto this loop (the loops vert should overlap the face).\n"
1522 " :arg face: The face to interpolate data from.\n"
1523 " :type face: :class:`BMFace`\n"
1524 " :arg vert: When enabled, interpolate the loops vertex data (optional).\n"
1525 " :type vert: boolean\n"
1526 " :arg multires: When enabled, interpolate the loops multires data (optional).\n"
1527 " :type multires: boolean\n"
1529 static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
1531 BPy_BMFace *py_face = NULL;
1532 int do_vertex = TRUE;
1533 int do_multires = TRUE;
1535 BPY_BM_CHECK_OBJ(self);
1537 if (!PyArg_ParseTuple(args, "O!|ii:BMLoop.copy_from_face_interp",
1538 &BPy_BMFace_Type, &py_face,
1539 &do_vertex, &do_multires))
1544 BMesh *bm = self->bm;
1546 BPY_BM_CHECK_OBJ(py_face);
1548 if (py_face->bm != bm) {
1549 PyErr_SetString(PyExc_ValueError,
1550 "BMLoop.copy_from_face_interp(face): face is from another mesh");
1554 BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires);
1561 PyDoc_STRVAR(bpy_bmloop_calc_angle_doc,
1562 ".. method:: calc_angle()\n"
1564 " Return the angle at this loops corner of the face.\n"
1565 " This is calculated so sharper corners give lower angles.\n"
1567 " :return: The angle in radians.\n"
1570 static PyObject *bpy_bmloop_calc_angle(BPy_BMLoop *self)
1572 BPY_BM_CHECK_OBJ(self);
1573 return PyFloat_FromDouble(BM_loop_face_angle(self->l));
1576 PyDoc_STRVAR(bpy_bmloop_calc_normal_doc,
1577 ".. method:: calc_normal()\n"
1579 " Return normal at this loops corner of the face.\n"
1580 " Falls back to the face normal for straignt lines.\n"
1582 " :return: a normalized vector.\n"
1583 " :rtype: :class:`mathutils.Vector`\n"
1585 static PyObject *bpy_bmloop_calc_normal(BPy_BMLoop *self)
1588 BPY_BM_CHECK_OBJ(self);
1589 BM_loop_face_normal(self->l, vec);
1590 return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1593 PyDoc_STRVAR(bpy_bmloop_calc_tangent_doc,
1594 ".. method:: calc_tangent()\n"
1596 " Return the tangent at this loops corner of the face (pointing inward into the face).\n"
1597 " Falls back to the face normal for straignt lines.\n"
1599 " :return: a normalized vector.\n"
1600 " :rtype: :class:`mathutils.Vector`\n"
1602 static PyObject *bpy_bmloop_calc_tangent(BPy_BMLoop *self)
1605 BPY_BM_CHECK_OBJ(self);
1606 BM_loop_face_tangent(self->l, vec);
1607 return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1612 PyDoc_STRVAR(bpy_bmvertseq_new_doc,
1613 ".. method:: new(co=(0.0, 0.0, 0.0), example=None)\n"
1615 " Create a new vertex.\n"
1617 " :arg co: The initial location of the vertex (optional argument).\n"
1618 " :type co: float triplet\n"
1619 " :arg example: Existing vert to initialize settings.\n"
1620 " :type example: :class:`BMVert`\n"
1621 " :return: The newly created edge.\n"
1622 " :rtype: :class:`BMVert`\n"
1624 static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
1626 PyObject *py_co = NULL;
1627 BPy_BMVert *py_vert_example = NULL; /* optional */
1629 BPY_BM_CHECK_OBJ(self);
1631 if (!PyArg_ParseTuple(args, "|OO!:verts.new",
1633 &BPy_BMVert_Type, &py_vert_example))
1638 BMesh *bm = self->bm;
1640 float co[3] = {0.0f, 0.0f, 0.0f};
1642 if (py_vert_example) {
1643 BPY_BM_CHECK_OBJ(py_vert_example);
1646 if (py_co && mathutils_array_parse(co, 3, 3, py_co, "verts.new(co)") == -1) {
1650 v = BM_vert_create(bm, co, NULL);
1653 PyErr_SetString(PyExc_ValueError,
1654 "faces.new(verts): couldn't create the new face, internal error");
1658 if (py_vert_example) {
1659 BM_elem_attrs_copy(py_vert_example->bm, bm, py_vert_example->v, v);
1662 return BPy_BMVert_CreatePyObject(bm, v);
1669 PyDoc_STRVAR(bpy_bmedgeseq_new_doc,
1670 ".. method:: new(verts, example=None)\n"
1672 " Create a new edge from a given pair of verts.\n"
1674 " :arg verts: Vertex pair.\n"
1675 " :type verts: pair of :class:`BMVert`\n"
1676 " :arg example: Existing edge to initialize settings (optional argument).\n"
1677 " :type example: :class:`BMEdge`\n"
1678 " :return: The newly created edge.\n"
1679 " :rtype: :class:`BMEdge`\n"
1681 static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
1684 BPy_BMEdge *py_edge_example = NULL; /* optional */
1686 BPY_BM_CHECK_OBJ(self);
1688 if (!PyArg_ParseTuple(args, "O|O!:edges.new",
1690 &BPy_BMEdge_Type, &py_edge_example))
1695 BMesh *bm = self->bm;
1697 BMVert **vert_array = NULL;
1698 Py_ssize_t vert_seq_len; /* always 2 */
1699 PyObject *ret = NULL;
1701 if (py_edge_example) {
1702 BPY_BM_CHECK_OBJ(py_edge_example);
1705 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1706 &vert_seq_len, BM_VERT,
1707 TRUE, TRUE, "edges.new(...)");
1709 if (vert_array == NULL) {
1713 if (BM_edge_exists(vert_array[0], vert_array[1])) {
1714 PyErr_SetString(PyExc_ValueError,
1715 "edges.new(): this edge exists");
1719 e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, FALSE);
1722 PyErr_SetString(PyExc_ValueError,
1723 "faces.new(verts): couldn't create the new face, internal error");
1727 if (py_edge_example) {
1728 BM_elem_attrs_copy(py_edge_example->bm, bm, py_edge_example->e, e);
1731 ret = BPy_BMEdge_CreatePyObject(bm, e);
1734 if (vert_array) PyMem_FREE(vert_array);
1742 PyDoc_STRVAR(bpy_bmfaceseq_new_doc,
1743 ".. method:: new(verts, example=None)\n"
1745 " Create a new face from a given set of verts.\n"
1747 " :arg verts: Sequence of 3 or more verts.\n"
1748 " :type verts: :class:`BMVert`\n"
1749 " :arg example: Existing face to initialize settings (optional argument).\n"
1750 " :type example: :class:`BMFace`\n"
1751 " :return: The newly created face.\n"
1752 " :rtype: :class:`BMFace`\n"
1754 static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
1757 BPy_BMFace *py_face_example = NULL; /* optional */
1759 BPY_BM_CHECK_OBJ(self);
1761 if (!PyArg_ParseTuple(args, "O|O!:faces.new",
1763 &BPy_BMFace_Type, &py_face_example))
1768 BMesh *bm = self->bm;
1769 Py_ssize_t vert_seq_len;
1770 Py_ssize_t i, i_next;
1772 BMVert **vert_array = NULL;
1773 BMEdge **edge_array = NULL;
1775 PyObject *ret = NULL;
1779 if (py_face_example) {
1780 BPY_BM_CHECK_OBJ(py_face_example);
1783 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX,
1784 &vert_seq_len, BM_VERT,
1785 TRUE, TRUE, "faces.new(...)");
1787 if (vert_array == NULL) {
1791 /* check if the face exists */
1792 if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) {
1793 PyErr_SetString(PyExc_ValueError,
1794 "faces.new(verts): face already exists");
1798 /* Go ahead and make the face!
1799 * --------------------------- */
1801 edge_array = (BMEdge **)PyMem_MALLOC(vert_seq_len * sizeof(BMEdge **));
1804 for (i = vert_seq_len - 1, i_next = 0; i_next < vert_seq_len; (i = i_next++)) {
1805 edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, TRUE);
1808 f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE);
1810 if (f_new == NULL) {
1811 PyErr_SetString(PyExc_ValueError,
1812 "faces.new(verts): couldn't create the new face, internal error");
1816 if (py_face_example) {
1817 BM_elem_attrs_copy(py_face_example->bm, bm, py_face_example->f, f_new);
1820 ret = BPy_BMFace_CreatePyObject(bm, f_new);
1824 if (vert_array) PyMem_FREE(vert_array);
1825 if (edge_array) PyMem_FREE(edge_array);
1833 PyDoc_STRVAR(bpy_bmvertseq_remove_doc,
1834 ".. method:: remove(vert)\n"
1838 static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
1840 BPY_BM_CHECK_OBJ(self);
1842 if (!BPy_BMVert_Check(value)) {
1846 BMesh *bm = self->bm;
1848 BPY_BM_CHECK_OBJ(value);
1850 if (value->bm != bm) {
1851 PyErr_SetString(PyExc_ValueError,
1852 "verts.remove(vert): vert is from another mesh");
1856 BM_vert_kill(bm, value->v);
1857 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1863 PyDoc_STRVAR(bpy_bmedgeseq_remove_doc,
1864 ".. method:: remove(edge)\n"
1868 static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
1870 BPY_BM_CHECK_OBJ(self);
1872 if (!BPy_BMEdge_Check(value)) {
1876 BMesh *bm = self->bm;
1878 BPY_BM_CHECK_OBJ(value);
1880 if (value->bm != bm) {
1881 PyErr_SetString(PyExc_ValueError,
1882 "edges.remove(edge): edge is from another mesh");
1886 BM_edge_kill(bm, value->e);
1887 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1893 PyDoc_STRVAR(bpy_bmfaceseq_remove_doc,
1894 ".. method:: remove(face)\n"
1898 static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
1900 BPY_BM_CHECK_OBJ(self);
1902 if (!BPy_BMFace_Check(value)) {
1906 BMesh *bm = self->bm;
1908 BPY_BM_CHECK_OBJ(value);
1910 if (value->bm != bm) {
1911 PyErr_SetString(PyExc_ValueError,
1912 "faces.remove(face): face is from another mesh");
1916 BM_face_kill(bm, value->f);
1917 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1923 PyDoc_STRVAR(bpy_bmedgeseq_get__method_doc,
1924 ".. method:: get(verts, fallback=None)\n"
1926 " Return a edge which uses the **verts** passed.\n"
1928 " :arg verts: Sequence of verts.\n"
1929 " :type verts: :class:`BMVert`\n"
1930 " :arg fallback: Return this value if nothing is found.\n"
1931 " :return: The edge found or None\n"
1932 " :rtype: :class:`BMEdge`\n"
1934 static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
1937 PyObject *fallback = Py_None; /* optional */
1939 BPY_BM_CHECK_OBJ(self);
1941 if (!PyArg_ParseTuple(args, "O|O:edges.get",
1948 BMesh *bm = self->bm;
1950 BMVert **vert_array = NULL;
1951 Py_ssize_t vert_seq_len; /* always 2 */
1952 PyObject *ret = NULL;
1954 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1955 &vert_seq_len, BM_VERT,
1956 TRUE, TRUE, "edges.get(...)");
1958 if (vert_array == NULL) {
1962 if ((e = BM_edge_exists(vert_array[0], vert_array[1]))) {
1963 ret = BPy_BMEdge_CreatePyObject(bm, e);
1970 PyMem_FREE(vert_array);
1975 PyDoc_STRVAR(bpy_bmfaceseq_get__method_doc,
1976 ".. method:: get(verts, fallback=None)\n"
1978 " Return a face which uses the **verts** passed.\n"
1980 " :arg verts: Sequence of verts.\n"
1981 " :type verts: :class:`BMVert`\n"
1982 " :arg fallback: Return this value if nothing is found.\n"
1983 " :return: The face found or None\n"
1984 " :rtype: :class:`BMFace`\n"
1986 static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
1989 PyObject *fallback = Py_None; /* optional */
1991 BPY_BM_CHECK_OBJ(self);
1993 if (!PyArg_ParseTuple(args, "O|O:faces.get",
2000 BMesh *bm = self->bm;
2002 BMVert **vert_array = NULL;
2003 Py_ssize_t vert_seq_len;
2004 PyObject *ret = NULL;
2006 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 1, PY_SSIZE_T_MAX,
2007 &vert_seq_len, BM_VERT,
2008 TRUE, TRUE, "faces.get(...)");
2010 if (vert_array == NULL) {
2014 if (BM_face_exists(bm, vert_array, vert_seq_len, &f)) {
2015 ret = BPy_BMFace_CreatePyObject(bm, f);
2022 PyMem_FREE(vert_array);
2027 PyDoc_STRVAR(bpy_bmelemseq_index_update_doc,
2028 ".. method:: index_update()\n"
2030 " Initialize the index values of this sequence.\n"
2032 " This is the equivalent of looping over all elements and assigning the index values.\n"
2034 " .. code-block:: python\n"
2036 " for index, ele in enumerate(sequence):\n"
2037 " ele.index = index\n"
2041 " Running this on sequences besides :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces`\n"
2042 " works but wont result in each element having a valid index, insted its order in the sequence will be set.\n"
2044 static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
2046 BMesh *bm = self->bm;
2048 BPY_BM_CHECK_OBJ(self);
2050 switch ((BMIterType)self->itype) {
2051 case BM_VERTS_OF_MESH:
2052 BM_mesh_elem_index_ensure(self->bm, BM_VERT);
2054 case BM_EDGES_OF_MESH:
2055 BM_mesh_elem_index_ensure(self->bm, BM_EDGE);
2057 case BM_FACES_OF_MESH:
2058 BM_mesh_elem_index_ensure(self->bm, BM_FACE);
2065 const char htype = bm_iter_itype_htype_map[self->itype];
2067 BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
2068 BM_elem_index_set(ele, index); /* set_dirty! */
2072 if (htype & (BM_VERT | BM_EDGE | BM_FACE)) {
2073 /* since this isn't the normal vert/edge/face loops,
2074 * we're setting dirty values here. so tag as dirty. */
2075 bm->elem_index_dirty |= htype;
2086 static struct PyMethodDef bpy_bmesh_methods[] = {
2088 {"copy", (PyCFunction)bpy_bmesh_copy, METH_NOARGS, bpy_bmesh_copy_doc},
2089 {"clear", (PyCFunction)bpy_bmesh_clear, METH_NOARGS, bpy_bmesh_clear_doc},
2090 {"free", (PyCFunction)bpy_bmesh_free, METH_NOARGS, bpy_bmesh_free_doc},
2093 {"from_object", (PyCFunction)bpy_bmesh_from_object, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_object_doc},
2094 {"from_mesh", (PyCFunction)bpy_bmesh_from_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_mesh_doc},
2095 {"to_mesh", (PyCFunction)bpy_bmesh_to_mesh, METH_VARARGS, bpy_bmesh_to_mesh_doc},
2098 {"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
2099 {"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
2100 {"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
2101 {"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS|METH_KEYWORDS, bpy_bmesh_transform_doc},
2102 {NULL, NULL, 0, NULL}
2105 static struct PyMethodDef bpy_bmvert_methods[] = {
2106 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2107 {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2108 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2109 {"copy_from_face_interp", (PyCFunction)bpy_bmvert_copy_from_face_interp, METH_VARARGS, bpy_bmvert_copy_from_face_interp_doc},
2110 {"copy_from_vert_interp", (PyCFunction)bpy_bmvert_copy_from_vert_interp, METH_VARARGS, bpy_bmvert_copy_from_vert_interp_doc},
2112 {"calc_vert_angle", (PyCFunction)bpy_bmvert_calc_edge_angle, METH_NOARGS, bpy_bmvert_calc_edge_angle_doc},
2113 {"calc_shell_factor", (PyCFunction)bpy_bmvert_calc_shell_factor, METH_NOARGS, bpy_bmvert_calc_shell_factor_doc},
2115 {"normal_update", (PyCFunction)bpy_bmvert_normal_update, METH_NOARGS, bpy_bmvert_normal_update_doc},
2117 {NULL, NULL, 0, NULL}
2120 static struct PyMethodDef bpy_bmedge_methods[] = {
2121 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2122 {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2123 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2125 {"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
2127 {"calc_length", (PyCFunction)bpy_bmedge_calc_length, METH_NOARGS, bpy_bmedge_calc_length_doc},
2128 {"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
2129 {"calc_tangent", (PyCFunction)bpy_bmedge_calc_tangent, METH_VARARGS, bpy_bmedge_calc_tangent_doc},
2131 {"normal_update", (PyCFunction)bpy_bmedge_normal_update, METH_NOARGS, bpy_bmedge_normal_update_doc},
2133 {NULL, NULL, 0, NULL}
2136 static struct PyMethodDef bpy_bmface_methods[] = {
2137 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2138 {"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2140 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2141 {"copy_from_face_interp", (PyCFunction)bpy_bmface_copy_from_face_interp, METH_O, bpy_bmface_copy_from_face_interp_doc},
2143 {"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS|METH_KEYWORDS, bpy_bmface_copy_doc},
2145 {"calc_area", (PyCFunction)bpy_bmface_calc_area, METH_NOARGS, bpy_bmface_calc_area_doc},
2146 {"calc_perimeter", (PyCFunction)bpy_bmface_calc_perimeter, METH_NOARGS, bpy_bmface_calc_perimeter_doc},
2147 {"calc_center_median", (PyCFunction)bpy_bmface_calc_center_mean, METH_NOARGS, bpy_bmface_calc_center_mean_doc},
2148 {"calc_center_bounds", (PyCFunction)bpy_bmface_calc_center_bounds, METH_NOARGS, bpy_bmface_calc_center_bounds_doc},
2150 {"normal_update", (PyCFunction)bpy_bmface_normal_update, METH_NOARGS, bpy_bmface_normal_update_doc},
2152 {NULL, NULL, 0, NULL}
2155 static struct PyMethodDef bpy_bmloop_methods[] = {
2156 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2157 {"copy_from_face_interp", (PyCFunction)bpy_bmloop_copy_from_face_interp, METH_O, bpy_bmloop_copy_from_face_interp_doc},
2159 {"calc_angle", (PyCFunction)bpy_bmloop_calc_angle, METH_NOARGS, bpy_bmloop_calc_angle_doc},
2160 {"calc_normal", (PyCFunction)bpy_bmloop_calc_normal, METH_NOARGS, bpy_bmloop_calc_normal_doc},
2161 {"calc_tangent", (PyCFunction)bpy_bmloop_calc_tangent, METH_NOARGS, bpy_bmloop_calc_tangent_doc},
2162 {NULL, NULL, 0, NULL}
2165 static struct PyMethodDef bpy_bmelemseq_methods[] = {
2166 /* odd function, initializes index values */
2167 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2168 {NULL, NULL, 0, NULL}
2171 static struct PyMethodDef bpy_bmvertseq_methods[] = {
2172 {"new", (PyCFunction)bpy_bmvertseq_new, METH_VARARGS, bpy_bmvertseq_new_doc},
2173 {"remove", (PyCFunction)bpy_bmvertseq_remove, METH_O, bpy_bmvertseq_remove_doc},
2175 /* odd function, initializes index values */
2176 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2177 {NULL, NULL, 0, NULL}
2180 static struct PyMethodDef bpy_bmedgeseq_methods[] = {
2181 {"new", (PyCFunction)bpy_bmedgeseq_new, METH_VARARGS, bpy_bmedgeseq_new_doc},
2182 {"remove", (PyCFunction)bpy_bmedgeseq_remove, METH_O, bpy_bmedgeseq_remove_doc},
2183 /* 'bpy_bmelemseq_get' for different purpose */
2184 {"get", (PyCFunction)bpy_bmedgeseq_get__method, METH_VARARGS, bpy_bmedgeseq_get__method_doc},
2186 /* odd function, initializes index values */
2187 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2188 {NULL, NULL, 0, NULL}
2191 static struct PyMethodDef bpy_bmfaceseq_methods[] = {
2192 {"new", (PyCFunction)bpy_bmfaceseq_new, METH_VARARGS, bpy_bmfaceseq_new_doc},
2193 {"remove", (PyCFunction)bpy_bmfaceseq_remove, METH_O, bpy_bmfaceseq_remove_doc},
2194 /* 'bpy_bmelemseq_get' for different purpose */
2195 {"get", (PyCFunction)bpy_bmfaceseq_get__method, METH_VARARGS, bpy_bmfaceseq_get__method_doc},
2197 /* odd function, initializes index values */
2198 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2199 {NULL, NULL, 0, NULL}
2202 static struct PyMethodDef bpy_bmloopseq_methods[] = {
2203 /* odd function, initializes index values */
2204 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2205 {NULL, NULL, 0, NULL}
2212 * ---------------- */
2214 static PyTypeObject *bpy_bm_itype_as_pytype(const char itype)
2216 /* should cover all types */
2217 switch ((BMIterType)itype) {
2218 case BM_VERTS_OF_MESH:
2219 case BM_VERTS_OF_FACE:
2220 case BM_VERTS_OF_EDGE:
2221 return &BPy_BMVert_Type;
2223 case BM_EDGES_OF_MESH:
2224 case BM_EDGES_OF_FACE:
2225 case BM_EDGES_OF_VERT:
2226 return &BPy_BMEdge_Type;
2228 case BM_FACES_OF_MESH:
2229 case BM_FACES_OF_EDGE:
2230 case BM_FACES_OF_VERT:
2231 return &BPy_BMFace_Type;
2233 case BM_ALL_LOOPS_OF_FACE:
2234 case BM_LOOPS_OF_FACE:
2235 case BM_LOOPS_OF_EDGE:
2236 case BM_LOOPS_OF_VERT:
2237 case BM_LOOPS_OF_LOOP:
2238 return &BPy_BMLoop_Type;
2244 static Py_ssize_t bpy_bmelemseq_length(BPy_BMElemSeq *self)
2246 BPY_BM_CHECK_INT(self);
2248 /* first check if the size is known */
2249 switch ((BMIterType)self->itype) {
2251 case BM_VERTS_OF_MESH:
2252 return self->bm->totvert;
2253 case BM_EDGES_OF_MESH:
2254 return self->bm->totedge;
2255 case BM_FACES_OF_MESH:
2256 return self->bm->totface;
2259 case BM_VERTS_OF_FACE:
2260 case BM_EDGES_OF_FACE:
2261 case BM_LOOPS_OF_FACE:
2262 BPY_BM_CHECK_INT(self->py_ele);
2263 return ((BMFace *)self->py_ele->ele)->len;
2265 case BM_VERTS_OF_EDGE:
2269 /* quiet compiler */
2274 /* loop over all items, avoid this if we can */
2280 BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
2287 static PyObject *bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
2289 BPY_BM_CHECK_OBJ(self);
2291 if (keynum < 0) keynum += bpy_bmelemseq_length(self); /* only get length on negative value, may loop entire seq */
2293 BMHeader *ele = BM_iter_at_index(self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
2295 return BPy_BMElem_CreatePyObject(self->bm, ele);
2299 PyErr_Format(PyExc_IndexError,
2300 "BMElemSeq[index]: index %d out of range", keynum);
2304 static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t start, Py_ssize_t stop)
2314 BPY_BM_CHECK_OBJ(self);
2316 list = PyList_New(0);
2318 ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
2320 BLI_assert(ok == TRUE);
2322 if (UNLIKELY(ok == FALSE)) {
2326 /* first loop up-until the start */
2327 for (ok = TRUE; ok; ok = (BM_iter_step(&iter) != NULL)) {
2328 if (count == start) {
2334 /* add items until stop */
2335 while ((ele = BM_iter_step(&iter))) {
2336 item = BPy_BMElem_CreatePyObject(self->bm, ele);
2337 PyList_Append(list, item);
2341 if (count == stop) {
2349 static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key)
2351 /* don't need error check here */
2352 if (PyIndex_Check(key)) {
2353 Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2354 if (i == -1 && PyErr_Occurred())
2356 return bpy_bmelemseq_subscript_int(self, i);
2358 else if (PySlice_Check(key)) {
2359 PySliceObject *key_slice = (PySliceObject *)key;
2360 Py_ssize_t step = 1;
2362 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2365 else if (step != 1) {
2366 PyErr_SetString(PyExc_TypeError,
2367 "BMElemSeq[slice]: slice steps not supported");
2370 else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2371 return bpy_bmelemseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
2374 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
2376 /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
2377 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
2378 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL;
2380 if (start < 0 || stop < 0) {
2381 /* only get the length for negative values */
2382 Py_ssize_t len = bpy_bmelemseq_length(self);
2383 if (start < 0) start += len;
2384 if (stop < 0) start += len;
2387 if (stop - start <= 0) {
2388 return PyList_New(0);
2391 return bpy_bmelemseq_subscript_slice(self, start, stop);
2396 PyErr_SetString(PyExc_AttributeError,
2397 "BMElemSeq[key]: invalid key, key must be an int");
2402 static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
2404 BPY_BM_CHECK_INT(self);
2406 if (Py_TYPE(value) == bpy_bm_itype_as_pytype(self->itype)) {
2407 BPy_BMElem *value_bm_ele = (BPy_BMElem *)value;
2408 if (value_bm_ele->bm == self->bm) {
2409 BMElem *ele, *ele_test = value_bm_ele->ele;
2411 BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
2412 if (ele == ele_test) {
2422 /* BMElem (customdata)
2423 * ------------------- */
2425 static PyObject *bpy_bmelem_subscript(BPy_BMElem *self, BPy_BMLayerItem *key)
2427 BPY_BM_CHECK_OBJ(self);
2429 return BPy_BMLayerItem_GetItem(self, key);
2432 static int bpy_bmelem_ass_subscript(BPy_BMElem *self, BPy_BMLayerItem *key, PyObject *value)
2434 BPY_BM_CHECK_INT(self);
2436 return BPy_BMLayerItem_SetItem(self, key, value);
2439 static PySequenceMethods bpy_bmelemseq_as_sequence = {
2440 (lenfunc)bpy_bmelemseq_length, /* sq_length */
2441 NULL, /* sq_concat */
2442 NULL, /* sq_repeat */
2443 (ssizeargfunc)bpy_bmelemseq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
2444 NULL, /* sq_slice */
2445 (ssizeobjargproc)NULL, /* sq_ass_item */
2446 NULL, /* *was* sq_ass_slice */
2447 (objobjproc)bpy_bmelemseq_contains, /* sq_contains */
2448 (binaryfunc) NULL, /* sq_inplace_concat */
2449 (ssizeargfunc) NULL, /* sq_inplace_repeat */
2452 static PyMappingMethods bpy_bmelemseq_as_mapping = {
2453 (lenfunc)bpy_bmelemseq_length, /* mp_length */
2454 (binaryfunc)bpy_bmelemseq_subscript, /* mp_subscript */
2455 (objobjargproc)NULL, /* mp_ass_subscript */
2458 /* for customdata access */
2459 static PyMappingMethods bpy_bm_elem_as_mapping = {
2460 (lenfunc)NULL, /* mp_length */ /* keep this empty, messes up 'if elem: ...' test */
2461 (binaryfunc)bpy_bmelem_subscript, /* mp_subscript */
2462 (objobjargproc)bpy_bmelem_ass_subscript, /* mp_ass_subscript */
2468 static PyObject *bpy_bmelemseq_iter(BPy_BMElemSeq *self)
2470 BPy_BMIter *py_iter;
2472 BPY_BM_CHECK_OBJ(self);
2473 py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
2474 BM_iter_init(&(py_iter->iter), self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
2475 return (PyObject *)py_iter;
2478 static PyObject *bpy_bmiter_next(BPy_BMIter *self)
2480 BMHeader *ele = BM_iter_step(&self->iter);
2482 PyErr_SetString(PyExc_StopIteration,
2483 "bpy_bmiter_next stop");
2487 return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, ele);
2492 /* Dealloc Functions
2493 * ================= */
2495 static void bpy_bmesh_dealloc(BPy_BMesh *self)
2497 BMesh *bm = self->bm;
2499 /* have have been freed by bmesh */
2501 BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2502 BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2503 BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2504 BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
2506 bm->py_handle = NULL;
2508 if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
2516 static void bpy_bmvert_dealloc(BPy_BMElem *self)
2518 BMesh *bm = self->bm;
2520 void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2526 static void bpy_bmedge_dealloc(BPy_BMElem *self)
2528 BMesh *bm = self->bm;
2530 void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2536 static void bpy_bmface_dealloc(BPy_BMElem *self)
2538 BMesh *bm = self->bm;
2540 void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2546 static void bpy_bmloop_dealloc(BPy_BMElem *self)
2548 BMesh *bm = self->bm;
2550 void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2556 static void bpy_bmelemseq_dealloc(BPy_BMElemSeq *self)
2558 Py_XDECREF(self->py_ele);
2563 /* not sure where this should go */
2564 static Py_hash_t bpy_bm_elem_hash(PyObject *self)
2566 return _Py_HashPointer(((BPy_BMElem *)self)->ele);
2569 static Py_hash_t bpy_bm_hash(PyObject *self)
2571 return _Py_HashPointer(((BPy_BMesh *)self)->bm);
2575 * =============== */
2577 PyDoc_STRVAR(bpy_bmesh_doc,
2578 "The BMesh data structure\n"
2580 PyDoc_STRVAR(bpy_bmvert_doc,
2581 "The BMesh vertex type\n"
2583 PyDoc_STRVAR(bpy_bmedge_doc,
2584 "The BMesh edge connecting 2 verts\n"
2586 PyDoc_STRVAR(bpy_bmface_doc,
2587 "The BMesh face with 3 or more sides\n"
2589 PyDoc_STRVAR(bpy_bmloop_doc,
2590 "This is normally accessed from :class:`BMFace.loops` where each face corner represents a corner of a face.\n"
2592 PyDoc_STRVAR(bpy_bmelemseq_doc,
2593 "General sequence type used for accessing any sequence of \n"
2594 ":class:`BMVert`, :class:`BMEdge`, :class:`BMFace`, :class:`BMLoop`.\n"
2596 "When accessed via :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces` \n"
2597 "there are also functions to create/remomove items.\n"
2599 PyDoc_STRVAR(bpy_bmiter_doc,
2600 "Internal BMesh type for looping over verts/faces/edges,\n"
2601 "used for iterating over :class:`BMElemSeq` types.\n"
2604 static PyObject *bpy_bmesh_repr(BPy_BMesh *self)
2606 BMesh *bm = self->bm;
2609 return PyUnicode_FromFormat("<BMesh(%p), totvert=%d, totedge=%d, totface=%d, totloop=%d>",
2610 bm, bm->totvert, bm->totedge, bm->totface, bm->totloop);
2613 return PyUnicode_FromFormat("<BMesh dead at %p>", self);
2617 static PyObject *bpy_bmvert_repr(BPy_BMVert *self)
2619 BMesh *bm = self->bm;
2622 BMVert *v = self->v;
2623 return PyUnicode_FromFormat("<BMVert(%p), index=%d>",
2624 v, BM_elem_index_get(v));
2627 return PyUnicode_FromFormat("<BMVert dead at %p>", self);
2631 static PyObject *bpy_bmedge_repr(BPy_BMEdge *self)
2633 BMesh *bm = self->bm;
2636 BMEdge *e = self->e;
2637 return PyUnicode_FromFormat("<BMEdge(%p), index=%d, verts=(%p/%d, %p/%d)>",
2638 e, BM_elem_index_get(e),
2639 e->v1, BM_elem_index_get(e->v1),
2640 e->v2, BM_elem_index_get(e->v2));
2643 return PyUnicode_FromFormat("<BMEdge dead at %p>", self);
2647 static PyObject *bpy_bmface_repr(BPy_BMFace *self)
2649 BMesh *bm = self->bm;
2652 BMFace *f = self->f;
2653 return PyUnicode_FromFormat("<BMFace(%p), index=%d, totverts=%d>",
2654 f, BM_elem_index_get(f),
2658 return PyUnicode_FromFormat("<BMFace dead at %p>", self);
2662 static PyObject *bpy_bmloop_repr(BPy_BMLoop *self)
2664 BMesh *bm = self->bm;
2667 BMLoop *l = self->l;
2668 return PyUnicode_FromFormat("<BMLoop(%p), index=%d, vert=%p/%d, edge=%p/%d, face=%p/%d>",
2669 l, BM_elem_index_get(l),
2670 l->v, BM_elem_index_get(l->v),
2671 l->e, BM_elem_index_get(l->e),
2672 l->f, BM_elem_index_get(l->f));
2675 return PyUnicode_FromFormat("<BMLoop dead at %p>", self);
2682 PyTypeObject BPy_BMesh_Type = {{{0}}};
2683 PyTypeObject BPy_BMVert_Type = {{{0}}};
2684 PyTypeObject BPy_BMEdge_Type = {{{0}}};
2685 PyTypeObject BPy_BMFace_Type = {{{0}}};
2686 PyTypeObject BPy_BMLoop_Type = {{{0}}};
2687 PyTypeObject BPy_BMElemSeq_Type = {{{0}}};
2688 PyTypeObject BPy_BMVertSeq_Type = {{{0}}};
2689 PyTypeObject BPy_BMEdgeSeq_Type = {{{0}}};
2690 PyTypeObject BPy_BMFaceSeq_Type = {{{0}}};
2691 PyTypeObject BPy_BMLoopSeq_Type = {{{0}}};
2692 PyTypeObject BPy_BMIter_Type = {{{0}}};
2696 void BPy_BM_init_types(void)
2698 BPy_BMesh_Type.tp_basicsize = sizeof(BPy_BMesh);
2699 BPy_BMVert_Type.tp_basicsize = sizeof(BPy_BMVert);
2700 BPy_BMEdge_Type.tp_basicsize = sizeof(BPy_BMEdge);
2701 BPy_BMFace_Type.tp_basicsize = sizeof(BPy_BMFace);
2702 BPy_BMLoop_Type.tp_basicsize = sizeof(BPy_BMLoop);
2703 BPy_BMElemSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2704 BPy_BMVertSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2705 BPy_BMEdgeSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2706 BPy_BMFaceSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2707 BPy_BMLoopSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2708 BPy_BMIter_Type.tp_basicsize = sizeof(BPy_BMIter);
2711 BPy_BMesh_Type.tp_name = "BMesh";
2712 BPy_BMVert_Type.tp_name = "BMVert";
2713 BPy_BMEdge_Type.tp_name = "BMEdge";
2714 BPy_BMFace_Type.tp_name = "BMFace";
2715 BPy_BMLoop_Type.tp_name = "BMLoop";
2716 BPy_BMElemSeq_Type.tp_name = "BMElemSeq";
2717 BPy_BMVertSeq_Type.tp_name = "BMVertSeq";
2718 BPy_BMEdgeSeq_Type.tp_name = "BMEdgeSeq";
2719 BPy_BMFaceSeq_Type.tp_name = "BMFaceSeq";
2720 BPy_BMLoopSeq_Type.tp_name = "BMLoopSeq";
2721 BPy_BMIter_Type.tp_name = "BMIter";
2724 BPy_BMesh_Type.tp_doc = bpy_bmesh_doc;
2725 BPy_BMVert_Type.tp_doc = bpy_bmvert_doc;
2726 BPy_BMEdge_Type.tp_doc = bpy_bmedge_doc;
2727 BPy_BMFace_Type.tp_doc = bpy_bmface_doc;
2728 BPy_BMLoop_Type.tp_doc = bpy_bmloop_doc;
2729 BPy_BMElemSeq_Type.tp_doc = bpy_bmelemseq_doc;
2730 BPy_BMVertSeq_Type.tp_doc = NULL;
2731 BPy_BMEdgeSeq_Type.tp_doc = NULL;
2732 BPy_BMFaceSeq_Type.tp_doc = NULL;
2733 BPy_BMLoopSeq_Type.tp_doc = NULL;
2734 BPy_BMIter_Type.tp_doc = bpy_bmiter_doc;
2737 BPy_BMesh_Type.tp_repr = (reprfunc)bpy_bmesh_repr;
2738 BPy_BMVert_Type.tp_repr = (reprfunc)bpy_bmvert_repr;
2739 BPy_BMEdge_Type.tp_repr = (reprfunc)bpy_bmedge_repr;
2740 BPy_BMFace_Type.tp_repr = (reprfunc)bpy_bmface_repr;
2741 BPy_BMLoop_Type.tp_repr = (reprfunc)bpy_bmloop_repr;
2742 BPy_BMElemSeq_Type.tp_repr = NULL;
2743 BPy_BMVertSeq_Type.tp_repr = NULL;
2744 BPy_BMEdgeSeq_Type.tp_repr = NULL;
2745 BPy_BMFaceSeq_Type.tp_repr = NULL;
2746 BPy_BMLoopSeq_Type.tp_repr = NULL;
2747 BPy_BMIter_Type.tp_repr = NULL;
2750 BPy_BMesh_Type.tp_getset = bpy_bmesh_getseters;
2751 BPy_BMVert_Type.tp_getset = bpy_bmvert_getseters;
2752 BPy_BMEdge_Type.tp_getset = bpy_bmedge_getseters;
2753 BPy_BMFace_Type.tp_getset = bpy_bmface_getseters;
2754 BPy_BMLoop_Type.tp_getset = bpy_bmloop_getseters;
2755 BPy_BMElemSeq_Type.tp_getset = NULL;
2756 BPy_BMVertSeq_Type.tp_getset = bpy_bmvertseq_getseters;
2757 BPy_BMEdgeSeq_Type.tp_getset = bpy_bmedgeseq_getseters;
2758 BPy_BMFaceSeq_Type.tp_getset = bpy_bmfaceseq_getseters;
2759 BPy_BMLoopSeq_Type.tp_getset = bpy_bmloopseq_getseters;
2760 BPy_BMIter_Type.tp_getset = NULL;
2763 BPy_BMesh_Type.tp_methods = bpy_bmesh_methods;
2764 BPy_BMVert_Type.tp_methods = bpy_bmvert_methods;
2765 BPy_BMEdge_Type.tp_methods = bpy_bmedge_methods;
2766 BPy_BMFace_Type.tp_methods = bpy_bmface_methods;
2767 BPy_BMLoop_Type.tp_methods = bpy_bmloop_methods;
2768 BPy_BMElemSeq_Type.tp_methods = bpy_bmelemseq_methods;
2769 BPy_BMVertSeq_Type.tp_methods = bpy_bmvertseq_methods;
2770 BPy_BMEdgeSeq_Type.tp_methods = bpy_bmedgeseq_methods;
2771 BPy_BMFaceSeq_Type.tp_methods = bpy_bmfaceseq_methods;
2772 BPy_BMLoopSeq_Type.tp_methods = bpy_bmloopseq_methods;
2773 BPy_BMIter_Type.tp_methods = NULL;
2776 BPy_BMesh_Type.tp_hash = bpy_bm_hash;
2777 BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash;
2778 BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash;
2779 BPy_BMFace_Type.tp_hash = bpy_bm_elem_hash;
2780 BPy_BMLoop_Type.tp_hash = bpy_bm_elem_hash;
2781 BPy_BMElemSeq_Type.tp_hash = NULL;
2782 BPy_BMVertSeq_Type.tp_hash = NULL;
2783 BPy_BMEdgeSeq_Type.tp_hash = NULL;
2784 BPy_BMFaceSeq_Type.tp_hash = NULL;
2785 BPy_BMLoopSeq_Type.tp_hash = NULL;
2786 BPy_BMIter_Type.tp_hash = NULL;
2788 BPy_BMElemSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2789 BPy_BMVertSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2790 BPy_BMEdgeSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2791 BPy_BMFaceSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2792 BPy_BMLoopSeq_Type.tp_as_sequence = NULL; /* this is not a seq really, only for layer access */
2794 BPy_BMElemSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2795 BPy_BMVertSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2796 BPy_BMEdgeSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2797 BPy_BMFaceSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2798 BPy_BMLoopSeq_Type.tp_as_mapping = NULL; /* this is not a seq really, only for layer access */
2801 BPy_BMVert_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2802 BPy_BMEdge_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2803 BPy_BMFace_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2804 BPy_BMLoop_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2806 BPy_BMElemSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2807 BPy_BMVertSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2808 BPy_BMEdgeSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2809 BPy_BMFaceSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2810 BPy_BMLoopSeq_Type.tp_iter = NULL; /* no mapping */
2812 /* only 1 iteratir so far */
2813 BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next;
2814 BPy_BMIter_Type.tp_iter = PyObject_SelfIter;
2816 BPy_BMesh_Type.tp_dealloc = (destructor)bpy_bmesh_dealloc;
2817 BPy_BMVert_Type.tp_dealloc = (destructor)bpy_bmvert_dealloc;
2818 BPy_BMEdge_Type.tp_dealloc = (destructor)bpy_bmedge_dealloc;
2819 BPy_BMFace_Type.tp_dealloc = (destructor)bpy_bmface_dealloc;
2820 BPy_BMLoop_Type.tp_dealloc = (destructor)bpy_bmloop_dealloc;
2821 BPy_BMElemSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2822 BPy_BMVertSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2823 BPy_BMEdgeSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2824 BPy_BMFaceSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2825 BPy_BMLoopSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2826 BPy_BMIter_Type.tp_dealloc = NULL;
2828 BPy_BMesh_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2829 BPy_BMVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2830 BPy_BMEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2831 BPy_BMFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2832 BPy_BMLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2833 BPy_BMElemSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2834 BPy_BMVertSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2835 BPy_BMEdgeSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2836 BPy_BMFaceSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2837 BPy_BMLoopSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2838 BPy_BMIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2841 PyType_Ready(&BPy_BMesh_Type);
2842 PyType_Ready(&BPy_BMVert_Type);
2843 PyType_Ready(&BPy_BMEdge_Type);
2844 PyType_Ready(&BPy_BMFace_Type);
2845 PyType_Ready(&BPy_BMLoop_Type);
2846 PyType_Ready(&BPy_BMElemSeq_Type);
2847 PyType_Ready(&BPy_BMVertSeq_Type);
2848 PyType_Ready(&BPy_BMEdgeSeq_Type);
2849 PyType_Ready(&BPy_BMFaceSeq_Type);
2850 PyType_Ready(&BPy_BMLoopSeq_Type);
2851 PyType_Ready(&BPy_BMIter_Type);
2854 /* bmesh.types submodule
2855 * ********************* */
2857 static struct PyModuleDef BPy_BM_types_module_def = {
2858 PyModuleDef_HEAD_INIT,
2859 "bmesh.types", /* m_name */
2862 NULL, /* m_methods */
2863 NULL, /* m_reload */
2864 NULL, /* m_traverse */
2869 PyObject *BPyInit_bmesh_types(void)
2871 PyObject *submodule;
2873 submodule = PyModule_Create(&BPy_BM_types_module_def);
2875 #define MODULE_TYPE_ADD(s, t) \
2876 PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
2878 /* bmesh_py_types.c */
2879 MODULE_TYPE_ADD(submodule, BPy_BMesh_Type);
2880 MODULE_TYPE_ADD(submodule, BPy_BMVert_Type);
2881 MODULE_TYPE_ADD(submodule, BPy_BMEdge_Type);
2882 MODULE_TYPE_ADD(submodule, BPy_BMFace_Type);
2883 MODULE_TYPE_ADD(submodule, BPy_BMLoop_Type);
2884 MODULE_TYPE_ADD(submodule, BPy_BMElemSeq_Type);
2885 MODULE_TYPE_ADD(submodule, BPy_BMVertSeq_Type);
2886 MODULE_TYPE_ADD(submodule, BPy_BMEdgeSeq_Type);
2887 MODULE_TYPE_ADD(submodule, BPy_BMFaceSeq_Type);
2888 MODULE_TYPE_ADD(submodule, BPy_BMLoopSeq_Type);
2889 MODULE_TYPE_ADD(submodule, BPy_BMIter_Type);
2890 /* bmesh_py_types_select.c */
2891 MODULE_TYPE_ADD(submodule, BPy_BMEditSelSeq_Type);
2892 MODULE_TYPE_ADD(submodule, BPy_BMEditSelIter_Type);
2893 /* bmesh_py_types_customdata.c */
2894 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessVert_Type);
2895 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessEdge_Type);
2896 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessFace_Type);
2897 MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessLoop_Type);
2898 MODULE_TYPE_ADD(submodule, BPy_BMLayerCollection_Type);
2899 MODULE_TYPE_ADD(submodule, BPy_BMLayerItem_Type);
2900 /* bmesh_py_types_meshdata.c */
2901 MODULE_TYPE_ADD(submodule, BPy_BMLoopUV_Type);
2902 MODULE_TYPE_ADD(submodule, BPy_BMDeformVert_Type);
2904 #undef MODULE_TYPE_ADD
2909 /* Utility Functions
2910 * ***************** */
2912 PyObject *BPy_BMesh_CreatePyObject(BMesh *bm, int flag)
2916 if (bm->py_handle) {
2917 self = bm->py_handle;
2921 self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
2925 bm->py_handle = self; /* point back */
2927 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2928 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2929 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2930 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
2933 return (PyObject *)self;
2938 PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
2942 void **ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
2944 /* bmesh may free layers, ensure we have one to store ourself */
2945 if (UNLIKELY(ptr == NULL)) {
2946 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2947 ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
2955 self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type);
2956 BLI_assert(v != NULL);
2961 return (PyObject *)self;
2964 PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
2968 void **ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
2970 /* bmesh may free layers, ensure we have one to store ourself */
2971 if (UNLIKELY(ptr == NULL)) {
2972 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2973 ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
2981 self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type);
2982 BLI_assert(e != NULL);
2987 return (PyObject *)self;
2990 PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
2994 void **ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
2996 /* bmesh may free layers, ensure we have one to store ourself */
2997 if (UNLIKELY(ptr == NULL)) {
2998 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2999 ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
3007 self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type);
3008 BLI_assert(f != NULL);
3013 return (PyObject *)self;
3016 PyObject *BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
3020 void **ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
3022 /* bmesh may free layers, ensure we have one to store ourself */
3023 if (UNLIKELY(ptr == NULL)) {
3024 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
3025 ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
3033 self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type);
3034 BLI_assert(l != NULL);
3039 return (PyObject *)self;
3042 PyObject *BPy_BMElemSeq_CreatePyObject(BMesh *bm, BPy_BMElem *py_ele, const char itype)
3044 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMElemSeq_Type);
3046 self->py_ele = py_ele; /* can be NULL */
3047 self->itype = itype;
3049 return (PyObject *)self;
3052 PyObject *BPy_BMVertSeq_CreatePyObject(BMesh *bm)
3054 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMVertSeq_Type);
3056 self->py_ele = NULL; /* unused */
3057 self->itype = BM_VERTS_OF_MESH;
3058 return (PyObject *)self;
3061 PyObject *BPy_BMEdgeSeq_CreatePyObject(BMesh *bm)
3063 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMEdgeSeq_Type);
3065 self->py_ele = NULL; /* unused */
3066 self->itype = BM_EDGES_OF_MESH;
3067 return (PyObject *)self;
3070 PyObject *BPy_BMFaceSeq_CreatePyObject(BMesh *bm)
3072 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMFaceSeq_Type);
3074 self->py_ele = NULL; /* unused */
3075 self->itype = BM_FACES_OF_MESH;
3076 return (PyObject *)self;
3079 PyObject *BPy_BMLoopSeq_CreatePyObject(BMesh *bm)
3081 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMLoopSeq_Type);
3083 self->py_ele = NULL; /* unused */
3084 self->itype = 0; /* should never be passed to the iterator function */
3085 return (PyObject *)self;
3088 PyObject *BPy_BMIter_CreatePyObject(BMesh *bm)
3090 BPy_BMIter *self = PyObject_New(BPy_BMIter, &BPy_BMIter_Type);
3092 /* caller must initialize 'iter' member */
3093 return (PyObject *)self;
3096 /* this is just a helper func */
3097 PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele)
3099 switch (ele->htype) {
3101 return BPy_BMVert_CreatePyObject(bm, (BMVert *)ele);
3103 return BPy_BMEdge_CreatePyObject(bm, (BMEdge *)ele);
3105 return BPy_BMFace_CreatePyObject(bm, (BMFace *)ele);
3107 return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele);
3109 PyErr_SetString(PyExc_SystemError, "internal error");
3114 int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
3116 if (LIKELY(self->bm)) {
3120 PyErr_Format(PyExc_ReferenceError,
3121 "BMesh data of type %.200s has been removed",
3122 Py_TYPE(self)->tp_name);
3127 void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
3132 /* generic python seq as BMVert/Edge/Face array,
3133 * return value must be freed with PyMem_FREE(...);
3135 * The 'bm_r' value is assigned when empty, and used when set.
3137 void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
3139 const char do_unique_check, const char do_bm_check,
3140 const char *error_prefix)
3142 BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
3146 if (!(seq_fast = PySequence_Fast(seq, error_prefix))) {
3156 seq_len = PySequence_Fast_GET_SIZE(seq_fast);
3158 if (seq_len < min || seq_len > max) {
3159 PyErr_Format(PyExc_TypeError,
3160 "%s: sequence incorrect size, expected [%d - %d], given %d",
3161 error_prefix, min, max, seq_len);
3166 /* from now on, use goto */
3167 alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
3169 for (i = 0; i < seq_len; i++) {
3170 item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i);
3172 if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
3173 PyErr_Format(PyExc_TypeError,
3174 "%s: expected %.200s, not '%.200s'",
3175 error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name);
3178 else if (!BPY_BM_IS_VALID(item)) {
3179 PyErr_Format(PyExc_TypeError,
3180 "%s: %d %s has been removed",
3181 error_prefix, i, Py_TYPE(item)->tp_name);
3184 /* trick so we can ensure all items have the same mesh,
3185 * and allows us to pass the 'bm' as NULL. */
3186 else if (do_bm_check && (bm && bm != item->bm)) {
3187 PyErr_Format(PyExc_ValueError,
3188 "%s: %d %s is from another mesh",
3189 error_prefix, i, BPy_BMElem_StringFromHType(htype));
3197 alloc[i] = item->ele;
3199 if (do_unique_check) {
3200 BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG);
3204 if (do_unique_check) {
3205 /* check for double verts! */
3207 for (i = 0; i < seq_len; i++) {
3208 if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == FALSE)) {
3212 /* ensure we don't leave this enabled */
3213 BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG);
3217 PyErr_Format(PyExc_ValueError,
3218 "%s: found the same %.200s used multiple times",
3219 error_prefix, BPy_BMElem_StringFromHType(htype));
3224 Py_DECREF(seq_fast);
3226 if (r_bm) *r_bm = bm;
3230 Py_DECREF(seq_fast);
3237 PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
3240 PyObject *ret = PyTuple_New(elem_len);
3241 for (i = 0; i < elem_len; i++) {
3242 PyTuple_SET_ITEM(ret, i, BPy_BMElem_CreatePyObject(bm, elem[i]));
3248 int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype)
3250 return (((htype & BM_VERT) && (type == &BPy_BMVert_Type)) ||
3251 ((htype & BM_EDGE) && (type == &BPy_BMEdge_Type)) ||
3252 ((htype & BM_FACE) && (type == &BPy_BMFace_Type)) ||
3253 ((htype & BM_LOOP) && (type == &BPy_BMLoop_Type)));
3257 * Use for error strings only, not thread safe,
3259 * \return a sting like '(BMVert/BMEdge/BMFace/BMLoop)'
3261 char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32])
3263 /* zero to ensure string is always NULL terminated */
3264 char *ret_ptr = ret;
3265 if (htype & BM_VERT) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMVert_Type.tp_name);
3266 if (htype & BM_EDGE) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMEdge_Type.tp_name);
3267 if (htype & BM_FACE) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMFace_Type.tp_name);
3268 if (htype & BM_LOOP) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMLoop_Type.tp_name);
3273 char *BPy_BMElem_StringFromHType(const char htype)
3275 /* zero to ensure string is always NULL terminated */
3276 static char ret[32];
3277 return BPy_BMElem_StringFromHType_ex(htype, ret);