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 "BKE_customdata.h"
38 #include "../mathutils/mathutils.h"
40 #include "../generic/py_capi_utils.h"
42 #include "bmesh_py_types.h" /* own include */
47 /* scene does not use BM_* flags. */
48 PyC_FlagSet bpy_bm_scene_vert_edge_face_flags[] = {
55 PyC_FlagSet bpy_bm_htype_vert_edge_face_flags[] = {
62 PyC_FlagSet bpy_bm_htype_all_flags[] = {
70 PyC_FlagSet bpy_bm_hflag_all_flags[] = {
71 {BM_ELEM_SELECT, "SELECT"},
72 {BM_ELEM_HIDDEN, "HIDE"},
73 {BM_ELEM_SEAM, "SEAM"},
74 {BM_ELEM_SMOOTH, "SMOOTH"},
79 /* py-type definitions
80 * ******************* */
89 PyDoc_STRVAR(bpy_bm_elem_select_doc, "Selected state of this element.\n\n:type: boolean");
90 PyDoc_STRVAR(bpy_bm_elem_hide_doc, "Hidden state of this element.\n\n:type: boolean");
91 PyDoc_STRVAR(bpy_bm_elem_tag_doc, "Generic attribute scripts can use for own logic\n\n:type: boolean");
92 PyDoc_STRVAR(bpy_bm_elem_smooth_doc, "Smooth state of this element.\n\n:type: boolean");
95 static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
97 const char hflag = (char)GET_INT_FROM_POINTER(flag);
99 BPY_BM_CHECK_OBJ(self);
101 return PyBool_FromLong(BM_elem_flag_test(self->ele, hflag));
104 static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
106 const char hflag = (char)GET_INT_FROM_POINTER(flag);
109 BPY_BM_CHECK_INT(self);
111 param = PyLong_AsLong(value);
114 BM_elem_flag_enable(self->ele, hflag);
117 else if (param == FALSE) {
118 BM_elem_flag_disable(self->ele, hflag);
122 PyErr_Format(PyExc_TypeError,
123 "expected True/False or 0/1, not %.200s",
124 Py_TYPE(value)->tp_name);
129 PyDoc_STRVAR(bpy_bm_elem_index_doc,
130 "Index of this element.\n"
136 " This value is not necessarily valid, while editing the mesh it can become *dirty*.\n"
138 " It's also possible to assign any number to this attribute for a scripts internal logic.\n"
140 " To ensure the value is up to date - see :class:`BMesh.update` **index** argument.\n"
142 static PyObject *bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
144 BPY_BM_CHECK_OBJ(self);
146 return PyLong_FromLong(BM_elem_index_get(self->ele));
149 static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
153 BPY_BM_CHECK_INT(self);
155 param = PyLong_AsLong(value);
157 if (param == -1 && PyErr_Occurred()) {
158 PyErr_SetString(PyExc_TypeError, "expected an int type");
162 BM_elem_index_set(self->ele, param); /* set_dirty! */
164 /* when setting the index assume its set invalid */
165 if (self->ele->htype & (BM_VERT | BM_EDGE | BM_FACE)) {
166 self->bm->elem_index_dirty |= self->ele->htype;
173 /* type spesific get/sets
174 * ---------------------- */
180 /* doc-strings for all uses of this funcion */
181 PyDoc_STRVAR(bpy_bmesh_verts_doc,
182 "This meshes vert sequence (read-only).\n\n:type: :class:`BMElemSeq`"
184 PyDoc_STRVAR(bpy_bmesh_edges_doc,
185 "This meshes edge sequence (read-only).\n\n:type: :class:`BMElemSeq`"
187 PyDoc_STRVAR(bpy_bmesh_faces_doc,
188 "This meshes face sequence (read-only).\n\n:type: :class:`BMElemSeq`"
191 static PyObject *bpy_bmelemseq_get(BPy_BMesh *self, void *itype)
193 BPY_BM_CHECK_OBJ(self);
194 return BPy_BMElemSeq_CreatePyObject(self->bm, NULL, GET_INT_FROM_POINTER(itype));
198 PyDoc_STRVAR(bpy_bmvert_link_edges_doc,
199 "Edges connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
201 PyDoc_STRVAR(bpy_bmvert_link_faces_doc,
202 "Faces connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
204 PyDoc_STRVAR(bpy_bmvert_link_loops_doc,
205 "Loops that use this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
208 PyDoc_STRVAR(bpy_bmedge_verts_doc,
209 "Verts this edge uses (always 2), (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
211 PyDoc_STRVAR(bpy_bmedge_link_faces_doc,
212 "Faces connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
214 PyDoc_STRVAR(bpy_bmedge_link_loops_doc,
215 "Loops connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
218 PyDoc_STRVAR(bpy_bmface_verts_doc,
219 "Verts of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
221 PyDoc_STRVAR(bpy_bmface_edges_doc,
222 "Edges of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMEdge`"
224 PyDoc_STRVAR(bpy_bmface_loops_doc,
225 "Loops of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
228 PyDoc_STRVAR(bpy_bmloops_link_loops_doc,
229 "Loops connected to this loop, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
232 static PyObject *bpy_bmelemseq_elem_get(BPy_BMElem *self, void *itype)
234 BPY_BM_CHECK_OBJ(self);
235 return BPy_BMElemSeq_CreatePyObject(self->bm, self, GET_INT_FROM_POINTER(itype));
238 PyDoc_STRVAR(bpy_bm_is_valid_doc,
239 "True when this element is valid (hasn't been removed).\n\n:type: boolean"
241 static PyObject *bpy_bm_is_valid_get(BPy_BMGeneric *self)
243 return PyBool_FromLong(self->bm != NULL);
247 PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
248 "The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an empty set.\n\n:type: set"
250 static PyObject *bpy_bmesh_select_mode_get(BPy_BMesh *self)
252 BPY_BM_CHECK_OBJ(self);
254 return PyC_FlagSet_FromBitfield(bpy_bm_scene_vert_edge_face_flags, self->bm->selectmode);
257 static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
260 BPY_BM_CHECK_INT(self);
262 if (PyC_FlagSet_ToBitfield(bpy_bm_scene_vert_edge_face_flags, value, &flag, "bm.select_mode") == -1) {
265 else if (flag == 0) {
266 PyErr_SetString(PyExc_TypeError, "bm.select_mode: cant assignt an empty value");
270 self->bm->selectmode = flag;
279 PyDoc_STRVAR(bpy_bmvert_co_doc,
280 "The coordinates for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
282 static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
284 BPY_BM_CHECK_OBJ(self);
285 return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
288 static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
290 BPY_BM_CHECK_INT(self);
292 if (mathutils_array_parse(self->v->co, 3, 3, value, "BMVert.co") != -1) {
300 PyDoc_STRVAR(bpy_bmvert_normal_doc,
301 "The normal for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
303 static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
305 BPY_BM_CHECK_OBJ(self);
306 return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
309 static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
311 BPY_BM_CHECK_INT(self);
313 if (mathutils_array_parse(self->v->no, 3, 3, value, "BMVert.normal") != -1) {
321 PyDoc_STRVAR(bpy_bmvert_is_manifold_doc,
322 "True when this vertex is manifold (read-only).\n\n:type: boolean"
324 static PyObject *bpy_bmvert_is_manifold_get(BPy_BMVert *self)
326 BPY_BM_CHECK_OBJ(self);
327 return PyBool_FromLong(BM_vert_is_manifold(self->bm, self->v));
330 PyDoc_STRVAR(bpy_bmvert_is_wire_doc,
331 "True when this vertex is not connected to any faces (read-only).\n\n:type: boolean"
333 static PyObject *bpy_bmvert_is_wire_get(BPy_BMVert *self)
335 BPY_BM_CHECK_OBJ(self);
336 return PyBool_FromLong(BM_vert_is_wire(self->bm, self->v));
342 PyDoc_STRVAR(bpy_bmedge_is_manifold_doc,
343 "True when this edge is manifold (read-only).\n\n:type: boolean"
345 static PyObject *bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
347 BPY_BM_CHECK_OBJ(self);
348 return PyBool_FromLong(BM_edge_is_manifold(self->bm, self->e));
351 PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
352 "True when this edge is not connected to any faces (read-only).\n\n:type: boolean"
354 static PyObject *bpy_bmedge_is_wire_get(BPy_BMEdge *self)
356 BPY_BM_CHECK_OBJ(self);
357 return PyBool_FromLong(BM_edge_is_wire(self->bm, self->e));
360 PyDoc_STRVAR(bpy_bmedge_is_boundary_doc,
361 "True when this edge is at the boundary of a face (read-only).\n\n:type: boolean"
363 static PyObject *bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
365 BPY_BM_CHECK_OBJ(self);
366 return PyBool_FromLong(BM_edge_is_boundary(self->e));
372 PyDoc_STRVAR(bpy_bmface_normal_doc,
373 "The normal for this face as a 3D, wrapped vector.\n\n:type: boolean"
375 static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
377 BPY_BM_CHECK_OBJ(self);
378 return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
381 static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
383 BPY_BM_CHECK_INT(self);
385 if (mathutils_array_parse(self->f->no, 3, 3, value, "BMFace.normal") != -1) {
393 static PyGetSetDef bpy_bmesh_getseters[] = {
394 {(char *)"verts", (getter)bpy_bmelemseq_get, (setter)NULL, (char *)bpy_bmesh_verts_doc, (void *)BM_VERTS_OF_MESH},
395 {(char *)"edges", (getter)bpy_bmelemseq_get, (setter)NULL, (char *)bpy_bmesh_edges_doc, (void *)BM_EDGES_OF_MESH},
396 {(char *)"faces", (getter)bpy_bmelemseq_get, (setter)NULL, (char *)bpy_bmesh_faces_doc, (void *)BM_FACES_OF_MESH},
397 {(char *)"select_mode", (getter)bpy_bmesh_select_mode_get, (setter)bpy_bmesh_select_mode_set, (char *)bpy_bmesh_select_mode_doc, NULL},
399 /* readonly checks */
400 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
402 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
405 static PyGetSetDef bpy_bmvert_getseters[] = {
407 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
408 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
409 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
410 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
412 {(char *)"co", (getter)bpy_bmvert_co_get, (setter)bpy_bmvert_co_set, (char *)bpy_bmvert_co_doc, NULL},
413 {(char *)"normal", (getter)bpy_bmvert_normal_get, (setter)bpy_bmvert_normal_set, (char *)bpy_bmvert_normal_doc, NULL},
415 /* connectivity data */
416 {(char *)"link_edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_edges_doc, (void *)BM_EDGES_OF_VERT},
417 {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_faces_doc, (void *)BM_FACES_OF_VERT},
418 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_loops_doc, (void *)BM_LOOPS_OF_VERT},
420 /* readonly checks */
421 {(char *)"is_manifold", (getter)bpy_bmvert_is_manifold_get, (setter)NULL, (char *)bpy_bmvert_is_manifold_doc, NULL},
422 {(char *)"is_wire", (getter)bpy_bmvert_is_wire_get, (setter)NULL, (char *)bpy_bmvert_is_wire_doc, NULL},
423 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
425 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
428 static PyGetSetDef bpy_bmedge_getseters[] = {
430 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
431 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
432 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
433 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
435 {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
436 {(char *)"seam", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SEAM},
438 /* connectivity data */
439 {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_verts_doc, (void *)BM_VERTS_OF_EDGE},
441 {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_faces_doc, (void *)BM_FACES_OF_EDGE},
442 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_loops_doc, (void *)BM_LOOPS_OF_EDGE},
444 /* readonly checks */
445 {(char *)"is_manifold", (getter)bpy_bmedge_is_manifold_get, (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
446 {(char *)"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
447 {(char *)"is_boundary", (getter)bpy_bmedge_is_boundary_get, (setter)NULL, (char *)bpy_bmedge_is_boundary_doc, NULL},
448 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
450 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
453 static PyGetSetDef bpy_bmface_getseters[] = {
455 {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
456 {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
457 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
458 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
460 {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
462 {(char *)"normal", (getter)bpy_bmface_normal_get, (setter)bpy_bmface_normal_set, (char *)bpy_bmface_normal_doc, NULL},
464 /* connectivity data */
465 {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_verts_doc, (void *)BM_VERTS_OF_FACE},
466 {(char *)"edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_edges_doc, (void *)BM_EDGES_OF_FACE},
467 {(char *)"loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_loops_doc, (void *)BM_LOOPS_OF_FACE},
469 /* readonly checks */
470 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
472 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
475 static PyGetSetDef bpy_bmloop_getseters[] = {
477 // flags are available but not used for loops.
478 // {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
479 // {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
480 {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
481 {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
483 /* connectivity data */
484 {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmloops_link_loops_doc, (void *)BM_LOOPS_OF_LOOP},
486 /* readonly checks */
487 {(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
489 {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
499 PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc,
500 ".. method:: select_flush_mode()\n"
502 " flush selection based on the current mode current :class:`BMesh.select_mode`.\n"
504 static PyObject *bpy_bmesh_select_flush_mode(BPy_BMesh *self)
506 BPY_BM_CHECK_OBJ(self);
508 BM_mesh_select_mode_flush(self->bm);
513 PyDoc_STRVAR(bpy_bmesh_select_flush_doc,
514 ".. method:: select_flush(select)\n"
516 " Flush selection, independent of the current selection mode.\n"
518 " :arg select: flush selection or de-selected elements.\n"
519 " :type select: boolean\n"
521 static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
525 BPY_BM_CHECK_OBJ(self);
527 param = PyLong_AsLong(value);
528 if (param != FALSE && param != TRUE) {
529 PyErr_SetString(PyExc_TypeError, "expected a boolean type 0/1");
533 if (param) BM_mesh_select_flush(self->bm);
534 else BM_mesh_deselect_flush(self->bm);
539 PyDoc_STRVAR(bpy_bmesh_normal_update_doc,
540 ".. method:: normal_update(skip_hidden=False)\n"
542 " Update mesh normals.\n"
544 " :arg skip_hidden: When True hidden elements are ignored.\n"
545 " :type skip_hidden: boolean\n"
547 static PyObject *bpy_bmesh_normal_update(BPy_BMElem *self, PyObject *args)
550 int skip_hidden = FALSE;
552 BPY_BM_CHECK_OBJ(self);
554 if (!PyArg_ParseTuple(args, "|i:normal_update", &skip_hidden)) {
558 BM_mesh_normals_update(self->bm, skip_hidden);
564 PyDoc_STRVAR(bpy_bmesh_transform_doc,
565 ".. method:: transform(matrix, filter=None)\n"
567 " Transform the mesh (optionally filtering flagged data only).\n"
569 " :arg matrix: transform matrix.\n"
570 " :type matrix: 4x4 :class:`mathutils.Matrix`\n"
571 " :arg filter: set of values in ('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG').\n"
572 " :type filter: set\n"
574 static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
576 static const char *kwlist[] = {"matrix", "filter", NULL};
579 PyObject *filter = NULL;
580 int filter_flags = 0;
582 BPY_BM_CHECK_OBJ(self);
584 if (!PyArg_ParseTupleAndKeywords(args, kw,
588 &PySet_Type, &filter))
597 if (BaseMath_ReadCallback(mat) == -1) {
600 else if (mat->num_col != 4 || mat->num_row != 4) {
601 PyErr_SetString(PyExc_ValueError, "expected a 4x4 matrix");
605 if (filter != NULL && PyC_FlagSet_ToBitfield(bpy_bm_hflag_all_flags, filter,
606 &filter_flags, "bm.transform") == -1)
611 mat_ptr = mat->matrix;
614 BM_ITER(eve, &iter, self->bm, BM_VERTS_OF_MESH, NULL) {
615 mul_m4_v3((float (*)[4])mat_ptr, eve->co);
619 char filter_flags_ch = (char)filter_flags;
620 BM_ITER(eve, &iter, self->bm, BM_VERTS_OF_MESH, NULL) {
621 if (eve->head.hflag & filter_flags_ch) {
622 mul_m4_v3((float (*)[4])mat_ptr, eve->co);
634 PyDoc_STRVAR(bpy_bm_elem_select_set_doc,
635 ".. method:: select_set(select)\n"
637 " Set the selection.\n"
638 " This is different from the *select* attribute because it updates the selection state of assosiated geometry.\n"
640 " :arg select: Select or de-select.\n"
641 " :type select: boolean\n"
643 static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
647 BPY_BM_CHECK_OBJ(self);
649 param = PyLong_AsLong(value);
650 if (param != FALSE && param != TRUE) {
651 PyErr_SetString(PyExc_TypeError, "expected a boolean type 0/1");
655 BM_elem_select_set(self->bm, self->ele, param);
660 PyDoc_STRVAR(bpy_bm_elem_copy_from_doc,
661 ".. method:: copy_from(select)\n"
663 " Copy values from another element.\n"
665 static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
667 BPY_BM_CHECK_OBJ(self);
669 if (Py_TYPE(self) != Py_TYPE(value)) {
670 PyErr_Format(PyExc_TypeError,
671 "expected element of type '%.200s' not '%.200s'",
672 Py_TYPE(self)->tp_name, Py_TYPE(value)->tp_name);
676 BM_elem_attrs_copy(value->bm, self->bm, value->ele, self->ele);
685 PyDoc_STRVAR(bpy_bmvert_calc_edge_angle_doc,
686 ".. method:: calc_edge_angle()\n"
688 " Return the angle between 2 connected edges.\n"
690 static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self)
692 BPY_BM_CHECK_OBJ(self);
693 return PyFloat_FromDouble(BM_vert_edge_angle(self->bm, self->v));
699 PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
700 ".. method:: calc_face_angle()\n"
702 " Return the angle between 2 connected faces.\n"
704 " :return: The angle between both faces in radians.\n"
707 static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
709 BPY_BM_CHECK_OBJ(self);
710 return PyFloat_FromDouble(BM_edge_face_angle(self->bm, self->e));
713 PyDoc_STRVAR(bpy_bmedge_other_vert_doc,
714 ".. method:: other_vert(vert)\n"
716 " Return the other vertex on this edge or None if the vertex is not used by this edge.\n"
718 " :arg vert: a vert in this edge.\n"
719 " :type vert: :class:`BMVert`\n"
720 " :return: The edges other vert.\n"
721 " :rtype: :class:`BMVert` or None\n"
723 static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
726 BPY_BM_CHECK_OBJ(self);
728 if (!BPy_BMVert_Check(value)) {
729 PyErr_Format(PyExc_TypeError,
730 "BMEdge.other_vert(vert): BMVert expected, not '%.200s'",
731 Py_TYPE(value)->tp_name);
735 BPY_BM_CHECK_OBJ(value);
737 if (self->bm != value->bm) {
738 PyErr_SetString(PyExc_TypeError,
739 "BMEdge.other_vert(vert): vert is from another mesh");
743 other = BM_edge_other_vert(self->e, value->v);
746 return BPy_BMVert_CreatePyObject(self->bm, other);
749 /* could raise an exception here */
757 PyDoc_STRVAR(bpy_bmface_copy_doc,
758 ".. method:: copy(verts=True, edges=True)\n"
760 " Make a copy of this face.\n"
762 " :arg verts: When set, the faces verts will be duplicated too.\n"
763 " :type verts: boolean\n"
764 " :arg edges: When set, the faces edges will be duplicated too.\n"
765 " :type edges: boolean\n"
766 " :return: The newly created face.\n"
767 " :rtype: :class:`BMFace`\n"
769 static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
771 static const char *kwlist[] = {"verts", "edges", NULL};
773 BMesh *bm = self->bm;
778 BPY_BM_CHECK_OBJ(self);
780 if (!PyArg_ParseTupleAndKeywords(args, kw,
783 &do_verts, &do_edges))
788 f_cpy = BM_face_copy(bm, self->f, do_verts, do_edges);
791 return BPy_BMFace_CreatePyObject(bm, f_cpy);
794 PyErr_SetString(PyExc_ValueError,
795 "BMFace.copy(): couldn't create the new face, internal error");
800 PyDoc_STRVAR(bpy_bmface_calc_area_doc,
801 ".. method:: calc_area()\n"
803 " Return the area of the face.\n"
805 " :return: Return the area of the face.\n"
808 static PyObject *bpy_bmface_calc_area(BPy_BMFace *self)
810 BPY_BM_CHECK_OBJ(self);
811 return PyFloat_FromDouble(BM_face_area_calc(self->bm, self->f));
814 PyDoc_STRVAR(bpy_bmface_calc_center_mean_doc,
815 ".. method:: calc_center_median()\n"
817 " Return median center of the face.\n"
819 " :return: a 3D vector.\n"
820 " :rtype: :class:`mathutils.Vector`\n"
822 static PyObject *bpy_bmface_calc_center_mean(BPy_BMFace *self)
826 BPY_BM_CHECK_OBJ(self);
827 BM_face_center_mean_calc(self->bm, self->f, cent);
828 return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
831 PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
832 ".. method:: calc_center_bounds()\n"
834 " Return bounds center of the face.\n"
836 " :return: a 3D vector.\n"
837 " :rtype: :class:`mathutils.Vector`\n"
839 static PyObject *bpy_bmface_calc_center_bounds(BPy_BMFace *self)
843 BPY_BM_CHECK_OBJ(self);
844 BM_face_center_bounds_calc(self->bm, self->f, cent);
845 return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
851 PyDoc_STRVAR(bpy_bmloop_calc_face_angle_doc,
852 ".. method:: calc_face_angle()\n"
854 " Return angle at this loops corner of the face.\n"
855 " This is calculated so sharper corners give lower angles.\n"
857 " :return: The angle in radians.\n"
860 static PyObject *bpy_bmloop_calc_face_angle(BPy_BMLoop *self)
862 BPY_BM_CHECK_OBJ(self);
863 return PyFloat_FromDouble(BM_loop_face_angle(self->bm, self->l));
869 static PyObject *bpy_bmvert_seq_new(BPy_BMElemSeq *self, PyObject *args)
871 PyObject *py_co = NULL;
872 BPy_BMVert *py_vert_example = NULL; /* optional */
874 BPY_BM_CHECK_OBJ(self);
876 if (!PyArg_ParseTuple(args, "|OO!:verts.new",
878 &BPy_BMVert_Type, &py_vert_example)) {
882 BMesh *bm = self->bm;
884 float co[3] = {0.0f, 0.0f, 0.0f};
886 if (py_vert_example) {
887 BPY_BM_CHECK_OBJ(py_vert_example);
890 if (py_co && mathutils_array_parse(co, 3, 3, py_co, "verts.new(co)") != -1) {
894 v = BM_vert_create(bm, co, NULL);
897 PyErr_SetString(PyExc_ValueError,
898 "faces.new(verts): couldn't create the new face, internal error");
902 if (py_vert_example) {
903 BM_elem_attrs_copy(py_vert_example->bm, bm, py_vert_example->v, v);
906 return BPy_BMVert_CreatePyObject(bm, v);
914 static PyObject *bpy_bmedge_seq_new(BPy_BMElemSeq *self, PyObject *args)
918 BPy_BMEdge *py_edge_example = NULL; /* optional */
920 BPY_BM_CHECK_OBJ(self);
922 if (!PyArg_ParseTuple(args, "O!O!|O!:edges.new",
923 &BPy_BMVert_Type, &v1,
924 &BPy_BMVert_Type, &v2,
925 &BPy_BMEdge_Type, &py_edge_example))
930 BMesh *bm = self->bm;
933 if (py_edge_example) {
934 BPY_BM_CHECK_OBJ(py_edge_example);
937 if (v1->v == v2->v) {
938 PyErr_SetString(PyExc_ValueError,
939 "edges.new(): both verts are the same");
942 if (!(bm == v1->bm && bm == v2->bm)) {
943 PyErr_SetString(PyExc_ValueError,
944 "edges.new(): both verts must be from this mesh");
947 if (BM_edge_exists(v1->v, v2->v)) {
948 PyErr_SetString(PyExc_ValueError,
949 "edges.new(): this edge exists");
952 e = BM_edge_create(bm, v1->v, v2->v, NULL, FALSE);
955 PyErr_SetString(PyExc_ValueError,
956 "faces.new(verts): couldn't create the new face, internal error");
960 if (py_edge_example) {
961 BM_elem_attrs_copy(py_edge_example->bm, bm, py_edge_example->e, e);
964 return BPy_BMEdge_CreatePyObject(bm, e);
972 static PyObject *bpy_bmface_seq_new(BPy_BMElemSeq *self, PyObject *args)
975 BPy_BMFace *py_face_example = NULL; /* optional */
977 BPY_BM_CHECK_OBJ(self);
979 if (!PyArg_ParseTuple(args, "O|O!:faces.new",
981 &BPy_BMFace_Type, &py_face_example)) {
985 BMesh *bm = self->bm;
986 Py_ssize_t vert_seq_len;
987 Py_ssize_t i, i_prev;
989 BMVert **vert_array = NULL;
990 BMEdge **edge_array = NULL;
992 PyObject *ret = NULL;
996 if (py_face_example) {
997 BPY_BM_CHECK_OBJ(py_face_example);
1000 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX,
1001 &vert_seq_len, &BPy_BMVert_Type,
1002 TRUE, TRUE, "faces.new(...)");
1004 /* check if the face exists */
1005 if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) {
1006 PyErr_SetString(PyExc_ValueError,
1007 "faces.new(verts): face already exists");
1011 /* Go ahead and make the face!
1012 * --------------------------- */
1014 edge_array = (BMEdge **)PyMem_MALLOC(vert_seq_len * sizeof(BMEdge **));
1017 for (i = 0, i_prev = vert_seq_len - 1; i < vert_seq_len; (i_prev=i++)) {
1018 edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_prev], NULL, TRUE);
1021 f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE);
1023 if (f_new == NULL) {
1024 PyErr_SetString(PyExc_ValueError,
1025 "faces.new(verts): couldn't create the new face, internal error");
1029 if (py_face_example) {
1030 BM_elem_attrs_copy(py_face_example->bm, bm, py_face_example->f, f_new);
1033 ret = BPy_BMFace_CreatePyObject(bm, f_new);
1037 if (vert_array) PyMem_FREE(vert_array);
1038 if (edge_array) PyMem_FREE(edge_array);
1046 /* eek - 3 docstrings in 1!, we might need to split up this seq at some point */
1047 PyDoc_STRVAR(bpy_bmelemseq_new_doc,
1048 ".. method:: new(co=(0.0, 0.0, 0.0), example=None)\n"
1050 " *Vertex Sequence*\n"
1052 " :arg co: The initial location of the vertex (optional argument).\n"
1053 " :type co: float triplet\n"
1054 " :arg example: Existing vert to initialize settings.\n"
1055 " :type example: :class:`BMVert`\n"
1056 " :return: The newly created edge.\n"
1057 " :rtype: :class:`BMVert`\n"
1060 ".. method:: new(v_a, v_b, example=None)\n"
1062 " *Edge Sequence*\n"
1064 " :arg v_a: Edge vertex.\n"
1065 " :type v_a: :class:`BMEdge`\n"
1066 " :arg v_b: Edge vertex.\n"
1067 " :type v_b: :class:`BMEdge`\n"
1068 " :arg example: Existing edge to initialize settings (optional argument).\n"
1069 " :type example: :class:`BMEdge`\n"
1070 " :return: The newly created edge.\n"
1071 " :rtype: :class:`BMEdge`\n"
1073 ".. method:: new(verts, example=None)\n"
1075 " *Face Sequence*\n"
1077 " Create a new vert/edge/face.\n"
1079 " :arg verts: Sequence of 3 or more verts.\n"
1080 " :type verts: :class:`BMVert`\n"
1081 " :arg example: Existing face to initialize settings (optional argument).\n"
1082 " :type example: :class:`BMFace`\n"
1083 " :return: The newly created face.\n"
1084 " :rtype: :class:`BMFace`\n"
1086 static PyObject *bpy_bmelemseq_new(BPy_BMElemSeq *self, PyObject *args)
1088 switch ((BMIterType)self->itype) {
1089 case BM_VERTS_OF_MESH:
1090 return bpy_bmvert_seq_new(self, args);
1091 case BM_EDGES_OF_MESH:
1092 return bpy_bmedge_seq_new(self, args);
1093 case BM_FACES_OF_MESH:
1094 return bpy_bmface_seq_new(self, args);
1096 PyErr_SetString(PyExc_TypeError,
1097 ".new(...): function is not valid for this sequence");
1102 static PyObject *bpy_bmvert_seq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
1104 BPY_BM_CHECK_OBJ(self);
1106 if (!BPy_BMVert_Check(value)) {
1110 BMesh *bm = self->bm;
1112 BPY_BM_CHECK_OBJ(value);
1114 if (value->bm != bm) {
1115 PyErr_SetString(PyExc_TypeError,
1116 "faces.remove(vert): vertex is from another mesh");
1119 BM_vert_kill(bm, value->v);
1120 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1126 static PyObject *bpy_bmedge_seq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
1128 BPY_BM_CHECK_OBJ(self);
1130 if (!BPy_BMEdge_Check(value)) {
1134 BMesh *bm = self->bm;
1136 BPY_BM_CHECK_OBJ(value);
1138 if (value->bm != bm) {
1139 PyErr_SetString(PyExc_TypeError,
1140 "faces.remove(vert): vertex is from another mesh");
1143 BM_edge_kill(bm, value->e);
1144 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1150 static PyObject *bpy_bmface_seq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
1152 BPY_BM_CHECK_OBJ(self);
1154 if (!BPy_BMFace_Check(value)) {
1158 BMesh *bm = self->bm;
1160 BPY_BM_CHECK_OBJ(value);
1162 if (value->bm != bm) {
1163 PyErr_SetString(PyExc_TypeError,
1164 "faces.remove(vert): vertex is from another mesh");
1167 BM_face_kill(bm, value->f);
1168 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1175 PyDoc_STRVAR(bpy_bmelemseq_remove_doc,
1176 ".. method:: remove(elem)\n"
1178 " Remove a vert/edge/face.\n"
1180 static PyObject *bpy_bmelemseq_remove(BPy_BMElemSeq *self, PyObject *value)
1182 switch ((BMIterType)self->itype) {
1183 case BM_VERTS_OF_MESH:
1184 return bpy_bmvert_seq_remove(self, (BPy_BMVert *)value);
1185 case BM_EDGES_OF_MESH:
1186 return bpy_bmedge_seq_remove(self, (BPy_BMEdge *)value);
1187 case BM_FACES_OF_MESH:
1188 return bpy_bmface_seq_remove(self, (BPy_BMFace *)value);
1190 PyErr_SetString(PyExc_TypeError,
1191 ".remove(item): function is not valid for this sequence");
1196 PyDoc_STRVAR(bpy_bmelemseq_index_update_doc,
1197 ".. method:: index_update()\n"
1199 " Initialize the index values of this sequence.\n"
1201 " This is the equivalent of looping over all elements and assigning the index values.\n"
1203 " .. code-block:: python\n"
1205 " for index, ele in enumerate(sequence):\n"
1206 " ele.index = index\n"
1210 " Running this on sequences besides :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces`\n"
1211 " works but wont result in each element having a valid index, insted its order in the sequence will be set.\n"
1213 static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
1215 BMesh *bm = self->bm;
1217 BPY_BM_CHECK_OBJ(self);
1219 switch ((BMIterType)self->itype) {
1220 case BM_VERTS_OF_MESH:
1221 BM_mesh_elem_index_ensure(self->bm, BM_VERT);
1223 case BM_EDGES_OF_MESH:
1224 BM_mesh_elem_index_ensure(self->bm, BM_EDGE);
1226 case BM_FACES_OF_MESH:
1227 BM_mesh_elem_index_ensure(self->bm, BM_FACE);
1234 const char htype = bm_iter_itype_htype_map[self->itype];
1236 BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
1237 BM_elem_index_set(ele, index); /* set_dirty! */
1241 if (htype & (BM_VERT | BM_EDGE | BM_FACE)) {
1242 /* since this isnt the normal vert/edge/face loops,
1243 * we're setting dirty values here. so tag as dirty. */
1244 bm->elem_index_dirty |= htype;
1255 static struct PyMethodDef bpy_bmesh_methods[] = {
1256 {"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
1257 {"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
1258 {"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
1259 {"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS|METH_KEYWORDS, bpy_bmesh_transform_doc},
1260 {NULL, NULL, 0, NULL}
1263 static struct PyMethodDef bpy_bmvert_methods[] = {
1264 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
1265 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1267 {"calc_vert_angle", (PyCFunction)bpy_bmvert_calc_edge_angle, METH_NOARGS, bpy_bmvert_calc_edge_angle_doc},
1268 {NULL, NULL, 0, NULL}
1271 static struct PyMethodDef bpy_bmedge_methods[] = {
1272 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
1273 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1275 {"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
1277 {"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
1278 {NULL, NULL, 0, NULL}
1281 static struct PyMethodDef bpy_bmface_methods[] = {
1282 {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
1283 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1285 {"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS|METH_KEYWORDS, bpy_bmface_copy_doc},
1287 {"calc_area", (PyCFunction)bpy_bmface_calc_area, METH_NOARGS, bpy_bmface_calc_area_doc},
1288 {"calc_center_median", (PyCFunction)bpy_bmface_calc_center_mean, METH_NOARGS, bpy_bmface_calc_center_mean_doc},
1289 {"calc_center_bounds", (PyCFunction)bpy_bmface_calc_center_bounds, METH_NOARGS, bpy_bmface_calc_center_bounds_doc},
1290 {NULL, NULL, 0, NULL}
1293 static struct PyMethodDef bpy_bmloop_methods[] = {
1294 {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1296 {"calc_angle", (PyCFunction)bpy_bmloop_calc_face_angle, METH_NOARGS, bpy_bmloop_calc_face_angle_doc},
1297 {NULL, NULL, 0, NULL}
1300 static struct PyMethodDef bpy_bmelemseq_methods[] = {
1301 {"new", (PyCFunction)bpy_bmelemseq_new, METH_VARARGS, bpy_bmelemseq_new_doc},
1302 {"remove", (PyCFunction)bpy_bmelemseq_remove, METH_O, bpy_bmelemseq_remove_doc},
1304 /* odd function, initializes index values */
1305 {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
1306 {NULL, NULL, 0, NULL}
1312 static PyTypeObject *bpy_bm_itype_as_pytype(const char itype)
1314 /* should cover all types */
1315 switch ((BMIterType)itype) {
1316 case BM_VERTS_OF_MESH:
1317 case BM_VERTS_OF_FACE:
1318 case BM_VERTS_OF_EDGE:
1319 return &BPy_BMVert_Type;
1321 case BM_EDGES_OF_MESH:
1322 case BM_EDGES_OF_FACE:
1323 case BM_EDGES_OF_VERT:
1324 return &BPy_BMEdge_Type;
1326 case BM_FACES_OF_MESH:
1327 case BM_FACES_OF_EDGE:
1328 case BM_FACES_OF_VERT:
1329 return &BPy_BMFace_Type;
1331 case BM_ALL_LOOPS_OF_FACE:
1332 case BM_LOOPS_OF_FACE:
1333 case BM_LOOPS_OF_EDGE:
1334 case BM_LOOPS_OF_VERT:
1335 case BM_LOOPS_OF_LOOP:
1336 return &BPy_BMLoop_Type;
1342 static Py_ssize_t bpy_bmelemseq_length(BPy_BMElemSeq *self)
1344 BPY_BM_CHECK_INT(self);
1346 /* first check if the size is known */
1347 switch ((BMIterType)self->itype) {
1349 case BM_VERTS_OF_MESH:
1350 return self->bm->totvert;
1351 case BM_EDGES_OF_MESH:
1352 return self->bm->totedge;
1353 case BM_FACES_OF_MESH:
1354 return self->bm->totface;
1357 case BM_VERTS_OF_FACE:
1358 case BM_EDGES_OF_FACE:
1359 case BM_LOOPS_OF_FACE:
1360 BPY_BM_CHECK_INT(self->py_ele);
1361 return ((BMFace *)self->py_ele->ele)->len;
1363 case BM_VERTS_OF_EDGE:
1367 /* quiet compiler */
1372 /* loop over all items, avoid this if we can */
1378 BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
1385 static PyObject *bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
1387 BPY_BM_CHECK_OBJ(self);
1389 if (keynum < 0) keynum += bpy_bmelemseq_length(self); /* only get length on negative value, may loop entire seq */
1391 BMHeader *ele = BM_iter_at_index(self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
1393 return BPy_BMElem_CreatePyObject(self->bm, ele);
1397 PyErr_Format(PyExc_IndexError,
1398 "BMElemSeq[index]: index %d out of range", keynum);
1402 static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t start, Py_ssize_t stop)
1412 BPY_BM_CHECK_OBJ(self);
1414 list = PyList_New(0);
1416 ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
1418 BLI_assert(ok == TRUE);
1420 if (UNLIKELY(ok == FALSE)) {
1424 /* first loop up-until the start */
1425 for (ok = TRUE; ok; ok = (BM_iter_step(&iter) != NULL)) {
1426 /* PointerRNA itemptr = rna_macro_iter.ptr; */
1427 if (count == start) {
1433 /* add items until stop */
1434 while ((ele = BM_iter_step(&iter))) {
1435 item = BPy_BMElem_CreatePyObject(self->bm, ele);
1436 PyList_Append(list, item);
1440 if (count == stop) {
1448 static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key)
1450 /* dont need error check here */
1451 if (PyIndex_Check(key)) {
1452 Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
1453 if (i == -1 && PyErr_Occurred())
1455 return bpy_bmelemseq_subscript_int(self, i);
1457 else if (PySlice_Check(key)) {
1458 PySliceObject *key_slice = (PySliceObject *)key;
1459 Py_ssize_t step = 1;
1461 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
1464 else if (step != 1) {
1465 PyErr_SetString(PyExc_TypeError, "BMElemSeq[slice]: slice steps not supported");
1468 else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
1469 return bpy_bmelemseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
1472 Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
1474 /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
1475 if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
1476 if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL;
1478 if (start < 0 || stop < 0) {
1479 /* only get the length for negative values */
1480 Py_ssize_t len = bpy_bmelemseq_length(self);
1481 if (start < 0) start += len;
1482 if (stop < 0) start += len;
1485 if (stop - start <= 0) {
1486 return PyList_New(0);
1489 return bpy_bmelemseq_subscript_slice(self, start, stop);
1494 PyErr_SetString(PyExc_AttributeError, "BMElemSeq[key]: invalid key, key must be an int");
1499 static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
1501 BPY_BM_CHECK_INT(self);
1503 if (Py_TYPE(value) == bpy_bm_itype_as_pytype(self->itype)) {
1504 BPy_BMElem *value_bm_ele = (BPy_BMElem *)value;
1505 if (value_bm_ele->bm == self->bm) {
1506 BMHeader *ele, *ele_test = value_bm_ele->ele;
1508 BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
1509 if (ele == ele_test) {
1519 static PySequenceMethods bpy_bmelemseq_as_sequence = {
1520 (lenfunc)bpy_bmelemseq_length, /* sq_length */
1521 NULL, /* sq_concat */
1522 NULL, /* sq_repeat */
1523 (ssizeargfunc)bpy_bmelemseq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
1524 NULL, /* sq_slice */
1525 (ssizeobjargproc)NULL, /* sq_ass_item */
1526 NULL, /* *was* sq_ass_slice */
1527 (objobjproc)bpy_bmelemseq_contains, /* sq_contains */
1528 (binaryfunc) NULL, /* sq_inplace_concat */
1529 (ssizeargfunc) NULL, /* sq_inplace_repeat */
1532 static PyMappingMethods bpy_bmelemseq_as_mapping = {
1533 (lenfunc)bpy_bmelemseq_length, /* mp_length */
1534 (binaryfunc)bpy_bmelemseq_subscript, /* mp_subscript */
1535 (objobjargproc)NULL, /* mp_ass_subscript */
1541 static PyObject *bpy_bmelemseq_iter(BPy_BMElemSeq *self)
1543 BPy_BMIter *py_iter;
1545 BPY_BM_CHECK_OBJ(self);
1546 py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
1547 BM_iter_init(&(py_iter->iter), self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
1548 return (PyObject *)py_iter;
1551 static PyObject *bpy_bmiter_next(BPy_BMIter *self)
1553 BMHeader *ele = BM_iter_step(&self->iter);
1555 PyErr_SetString(PyExc_StopIteration, "bpy_bmiter_next stop");
1559 return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, ele);
1564 /* Dealloc Functions
1565 * ================= */
1567 static void bpy_bmesh_dealloc(BPy_BMesh *self)
1569 BMesh *bm = self->bm;
1571 BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
1572 BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR);
1573 BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
1574 BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
1576 bm->py_handle = NULL;
1581 static void bpy_bmvert_dealloc(BPy_BMElem *self)
1583 BMesh *bm = self->bm;
1585 void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->data, CD_BM_ELEM_PYPTR);
1591 static void bpy_bmedge_dealloc(BPy_BMElem *self)
1593 BMesh *bm = self->bm;
1595 void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->data, CD_BM_ELEM_PYPTR);
1601 static void bpy_bmface_dealloc(BPy_BMElem *self)
1603 BMesh *bm = self->bm;
1605 void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->data, CD_BM_ELEM_PYPTR);
1611 static void bpy_bmloop_dealloc(BPy_BMElem *self)
1613 BMesh *bm = self->bm;
1615 void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->data, CD_BM_ELEM_PYPTR);
1621 static void bpy_bmelemseq_dealloc(BPy_BMElemSeq *self)
1623 Py_XDECREF(self->py_ele);
1628 /* not sure where this should go */
1629 static long bpy_bm_elem_hash(PyObject *self)
1631 return _Py_HashPointer(((BPy_BMElem *)self)->ele);
1636 * =============== */
1638 PyDoc_STRVAR(bpy_bmesh_doc,
1639 "The BMesh data structure\n"
1641 PyDoc_STRVAR(bpy_bmvert_doc,
1642 "The BMesh vertex type\n"
1644 PyDoc_STRVAR(bpy_bmedge_doc,
1645 "The BMesh edge connecting 2 verts\n"
1647 PyDoc_STRVAR(bpy_bmface_doc,
1648 "The BMesh face with 3 or more sides\n"
1650 PyDoc_STRVAR(bpy_bmloop_doc,
1651 "This is normally accessed from :class:`BMFace.loops` where each face corner represents a corner of a face.\n"
1653 PyDoc_STRVAR(bpy_bmelemseq_doc,
1654 "General sequence type used for accessing any sequence of \n"
1655 ":class:`BMVert`, :class:`BMEdge`, :class:`BMFace`, :class:`BMLoop`.\n"
1657 "When accessed via :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces` \n"
1658 "there are also functions to create/remomove items.\n"
1660 PyDoc_STRVAR(bpy_bmiter_doc,
1661 "Internal BMesh type for looping over verts/faces/edges,\n"
1662 "used for iterating over :class:`BMElemSeq` types.\n"
1668 PyTypeObject BPy_BMesh_Type = {{{0}}};
1669 PyTypeObject BPy_BMVert_Type = {{{0}}};
1670 PyTypeObject BPy_BMEdge_Type = {{{0}}};
1671 PyTypeObject BPy_BMFace_Type = {{{0}}};
1672 PyTypeObject BPy_BMLoop_Type = {{{0}}};
1673 PyTypeObject BPy_BMElemSeq_Type = {{{0}}};
1674 PyTypeObject BPy_BMIter_Type = {{{0}}};
1678 void BPy_BM_init_types(void)
1680 BPy_BMesh_Type.tp_basicsize = sizeof(BPy_BMesh);
1681 BPy_BMVert_Type.tp_basicsize = sizeof(BPy_BMVert);
1682 BPy_BMEdge_Type.tp_basicsize = sizeof(BPy_BMEdge);
1683 BPy_BMFace_Type.tp_basicsize = sizeof(BPy_BMFace);
1684 BPy_BMLoop_Type.tp_basicsize = sizeof(BPy_BMLoop);
1685 BPy_BMElemSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
1686 BPy_BMIter_Type.tp_basicsize = sizeof(BPy_BMIter);
1689 BPy_BMesh_Type.tp_name = "BMesh";
1690 BPy_BMVert_Type.tp_name = "BMVert";
1691 BPy_BMEdge_Type.tp_name = "BMEdge";
1692 BPy_BMFace_Type.tp_name = "BMFace";
1693 BPy_BMLoop_Type.tp_name = "BMLoop";
1694 BPy_BMElemSeq_Type.tp_name = "BMElemSeq";
1695 BPy_BMIter_Type.tp_name = "BMIter";
1698 BPy_BMesh_Type.tp_doc = bpy_bmesh_doc;
1699 BPy_BMVert_Type.tp_doc = bpy_bmvert_doc;
1700 BPy_BMEdge_Type.tp_doc = bpy_bmedge_doc;
1701 BPy_BMFace_Type.tp_doc = bpy_bmface_doc;
1702 BPy_BMLoop_Type.tp_doc = bpy_bmloop_doc;
1703 BPy_BMElemSeq_Type.tp_doc = bpy_bmelemseq_doc;
1704 BPy_BMIter_Type.tp_doc = bpy_bmiter_doc;
1707 BPy_BMesh_Type.tp_getset = bpy_bmesh_getseters;
1708 BPy_BMVert_Type.tp_getset = bpy_bmvert_getseters;
1709 BPy_BMEdge_Type.tp_getset = bpy_bmedge_getseters;
1710 BPy_BMFace_Type.tp_getset = bpy_bmface_getseters;
1711 BPy_BMLoop_Type.tp_getset = bpy_bmloop_getseters;
1712 BPy_BMElemSeq_Type.tp_getset = NULL;
1713 BPy_BMIter_Type.tp_getset = NULL;
1716 BPy_BMesh_Type.tp_methods = bpy_bmesh_methods;
1717 BPy_BMVert_Type.tp_methods = bpy_bmvert_methods;
1718 BPy_BMEdge_Type.tp_methods = bpy_bmedge_methods;
1719 BPy_BMFace_Type.tp_methods = bpy_bmface_methods;
1720 BPy_BMLoop_Type.tp_methods = bpy_bmloop_methods;
1721 BPy_BMElemSeq_Type.tp_methods = bpy_bmelemseq_methods;
1722 BPy_BMIter_Type.tp_methods = NULL;
1725 BPy_BMesh_Type.tp_hash = NULL;
1726 BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash;
1727 BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash;
1728 BPy_BMFace_Type.tp_hash = bpy_bm_elem_hash;
1729 BPy_BMLoop_Type.tp_hash = bpy_bm_elem_hash;
1730 BPy_BMElemSeq_Type.tp_hash = NULL;
1731 BPy_BMIter_Type.tp_hash = NULL;
1733 BPy_BMElemSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
1735 BPy_BMElemSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
1737 BPy_BMElemSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
1739 /* only 1 iteratir so far */
1740 BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next;
1742 BPy_BMesh_Type.tp_dealloc = (destructor)bpy_bmesh_dealloc;
1743 BPy_BMVert_Type.tp_dealloc = (destructor)bpy_bmvert_dealloc;
1744 BPy_BMEdge_Type.tp_dealloc = (destructor)bpy_bmedge_dealloc;
1745 BPy_BMFace_Type.tp_dealloc = (destructor)bpy_bmface_dealloc;
1746 BPy_BMLoop_Type.tp_dealloc = (destructor)bpy_bmloop_dealloc;
1747 BPy_BMElemSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
1748 BPy_BMIter_Type.tp_dealloc = NULL;
1760 BPy_BMesh_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1761 BPy_BMVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1762 BPy_BMEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1763 BPy_BMFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1764 BPy_BMLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1765 BPy_BMElemSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1766 BPy_BMIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1769 PyType_Ready(&BPy_BMesh_Type);
1770 PyType_Ready(&BPy_BMVert_Type);
1771 PyType_Ready(&BPy_BMEdge_Type);
1772 PyType_Ready(&BPy_BMFace_Type);
1773 PyType_Ready(&BPy_BMLoop_Type);
1774 PyType_Ready(&BPy_BMElemSeq_Type);
1775 PyType_Ready(&BPy_BMIter_Type);
1778 /* bmesh.types submodule
1779 * ********************* */
1781 static struct PyModuleDef BPy_BM_types_module_def = {
1782 PyModuleDef_HEAD_INIT,
1783 "bmesh.types", /* m_name */
1786 NULL, /* m_methods */
1787 NULL, /* m_reload */
1788 NULL, /* m_traverse */
1793 PyObject *BPyInit_bmesh_types(void)
1795 PyObject *submodule;
1797 submodule = PyModule_Create(&BPy_BM_types_module_def);
1799 #define mod_type_add(s, t) \
1800 PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
1802 mod_type_add(submodule, BPy_BMesh_Type);
1803 mod_type_add(submodule, BPy_BMVert_Type);
1804 mod_type_add(submodule, BPy_BMEdge_Type);
1805 mod_type_add(submodule, BPy_BMFace_Type);
1806 mod_type_add(submodule, BPy_BMLoop_Type);
1807 mod_type_add(submodule, BPy_BMElemSeq_Type);
1808 mod_type_add(submodule, BPy_BMIter_Type);
1815 /* Utility Functions
1816 * ***************** */
1818 PyObject *BPy_BMesh_CreatePyObject(BMesh *bm)
1822 if (bm->py_handle) {
1823 self = bm->py_handle;
1827 self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
1830 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
1831 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
1832 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
1833 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
1836 return (PyObject *)self;
1841 PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
1845 void **ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
1847 /* bmesh may free layers, ensure we have one to store ourself */
1848 if (UNLIKELY(ptr == NULL)) {
1849 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
1850 ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
1858 self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type);
1859 BLI_assert(v != NULL);
1864 return (PyObject *)self;
1867 PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
1871 void **ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
1873 /* bmesh may free layers, ensure we have one to store ourself */
1874 if (UNLIKELY(ptr == NULL)) {
1875 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
1876 ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
1884 self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type);
1885 BLI_assert(e != NULL);
1890 return (PyObject *)self;
1893 PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
1897 void **ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
1899 /* bmesh may free layers, ensure we have one to store ourself */
1900 if (UNLIKELY(ptr == NULL)) {
1901 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
1902 ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
1910 self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type);
1911 BLI_assert(f != NULL);
1916 return (PyObject *)self;
1919 PyObject *BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
1923 void **ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
1925 /* bmesh may free layers, ensure we have one to store ourself */
1926 if (UNLIKELY(ptr == NULL)) {
1927 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
1928 ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
1936 self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type);
1937 BLI_assert(l != NULL);
1942 return (PyObject *)self;
1945 PyObject *BPy_BMElemSeq_CreatePyObject(BMesh *bm, BPy_BMElem *py_ele, const char itype)
1947 BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMElemSeq_Type);
1949 self->py_ele = py_ele; /* can be NULL */
1950 self->itype = itype;
1952 return (PyObject *)self;
1955 PyObject *BPy_BMIter_CreatePyObject(BMesh *bm)
1957 BPy_BMIter *self = PyObject_New(BPy_BMIter, &BPy_BMIter_Type);
1959 /* caller must initialize 'iter' member */
1960 return (PyObject *)self;
1963 /* this is just a helper func */
1964 PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele)
1966 switch (ele->htype) {
1968 return BPy_BMVert_CreatePyObject(bm, (BMVert *)ele);
1970 return BPy_BMEdge_CreatePyObject(bm, (BMEdge *)ele);
1972 return BPy_BMFace_CreatePyObject(bm, (BMFace *)ele);
1974 return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele);
1976 PyErr_SetString(PyExc_SystemError, "internal error");
1981 int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
1986 PyErr_Format(PyExc_ReferenceError,
1987 "BMesh data of type %.200s has been removed",
1988 Py_TYPE(self)->tp_name);
1992 void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
1997 /* generic python seq as BMVert/Edge/Face array,
1998 * return value must be freed with PyMem_FREE(...);
2000 * The 'bm_r' value is assigned when empty, and used when set.
2002 void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
2004 const char do_unique_check, const char do_bm_check,
2005 const char *error_prefix)
2007 BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
2011 if (!(seq_fast=PySequence_Fast(seq, error_prefix))) {
2021 seq_len = PySequence_Fast_GET_SIZE(seq_fast);
2023 if (seq_len < min || seq_len > max) {
2024 PyErr_Format(PyExc_TypeError,
2025 "%s: sequence incorrect size, expected [%d - %d], given %d",
2026 error_prefix, min, max, seq_len);
2031 /* from now on, use goto */
2032 alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
2034 for (i = 0; i < seq_len; i++) {
2035 item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i);
2037 if (Py_TYPE(item) != type) {
2038 PyErr_Format(PyExc_TypeError,
2039 "%s: expected '%.200', not '%.200s'",
2040 error_prefix, type->tp_name, Py_TYPE(item)->tp_name);
2043 else if (item->bm == NULL) {
2044 PyErr_Format(PyExc_TypeError,
2045 "%s: %d %s has been removed",
2046 error_prefix, i, type->tp_name);
2049 /* trick so we can ensure all items have the same mesh,
2050 * and allows us to pass the 'bm' as NULL. */
2051 else if (do_bm_check && (bm && bm != item->bm)) {
2052 PyErr_Format(PyExc_TypeError,
2053 "%s: %d %s is from another mesh",
2054 error_prefix, i, type->tp_name);
2062 alloc[i] = item->ele;
2064 if (do_unique_check) {
2065 BM_elem_flag_enable(item->ele, BM_ELEM_TAG);
2069 if (do_unique_check) {
2070 /* check for double verts! */
2072 for (i = 0; i < seq_len; i++) {
2073 if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_TAG) == FALSE)) {
2077 /* ensure we dont leave this enabled */
2078 BM_elem_flag_disable(alloc[i], BM_ELEM_TAG);
2082 PyErr_Format(PyExc_ValueError,
2083 "%s: found the same %s used multiple times",
2084 error_prefix, type->tp_name);
2089 Py_DECREF(seq_fast);
2091 if (r_bm) *r_bm = bm;
2095 Py_DECREF(seq_fast);