2
* ***** BEGIN GPL LICENSE BLOCK *****
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
* The Original Code is Copyright (C) 2012 Blender Foundation.
19
* All rights reserved.
21
* Contributor(s): Campbell Barton
23
* ***** END GPL LICENSE BLOCK *****
26
/** \file blender/python/bmesh/bmesh_py_types.c
34
#include "DNA_mesh_types.h"
35
#include "DNA_object_types.h"
36
#include "DNA_material_types.h"
38
#include "BKE_depsgraph.h"
39
#include "BKE_customdata.h"
40
#include "BKE_DerivedMesh.h"
44
#include "../mathutils/mathutils.h"
46
#include "../generic/py_capi_utils.h"
48
#include "bmesh_py_types.h" /* own include */
49
#include "bmesh_py_types_select.h"
50
#include "bmesh_py_types_customdata.h"
51
#include "bmesh_py_types_meshdata.h"
56
/* scene does not use BM_* flags. */
57
PyC_FlagSet bpy_bm_scene_vert_edge_face_flags[] = {
64
PyC_FlagSet bpy_bm_htype_vert_edge_face_flags[] = {
71
PyC_FlagSet bpy_bm_htype_all_flags[] = {
79
PyC_FlagSet bpy_bm_hflag_all_flags[] = {
80
{BM_ELEM_SELECT, "SELECT"},
81
{BM_ELEM_HIDDEN, "HIDE"},
82
{BM_ELEM_SEAM, "SEAM"},
83
{BM_ELEM_SMOOTH, "SMOOTH"},
88
/* py-type definitions
89
* ******************* */
98
PyDoc_STRVAR(bpy_bm_elem_select_doc, "Selected state of this element.\n\n:type: boolean");
99
PyDoc_STRVAR(bpy_bm_elem_hide_doc, "Hidden state of this element.\n\n:type: boolean");
100
PyDoc_STRVAR(bpy_bm_elem_tag_doc, "Generic attribute scripts can use for own logic\n\n:type: boolean");
101
PyDoc_STRVAR(bpy_bm_elem_smooth_doc, "Smooth state of this element.\n\n:type: boolean");
102
PyDoc_STRVAR(bpy_bm_elem_seam_doc, "Seam for UV unwrapping.\n\n:type: boolean");
105
static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
107
const char hflag = (char)GET_INT_FROM_POINTER(flag);
109
BPY_BM_CHECK_OBJ(self);
111
return PyBool_FromLong(BM_elem_flag_test(self->ele, hflag));
114
static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
116
const char hflag = (char)GET_INT_FROM_POINTER(flag);
119
BPY_BM_CHECK_INT(self);
121
param = PyLong_AsLong(value);
124
BM_elem_flag_enable(self->ele, hflag);
127
else if (param == FALSE) {
128
BM_elem_flag_disable(self->ele, hflag);
132
PyErr_Format(PyExc_TypeError,
133
"expected True/False or 0/1, not %.200s",
134
Py_TYPE(value)->tp_name);
140
PyDoc_STRVAR(bpy_bm_elem_index_doc,
141
"Index of this element.\n"
147
" This value is not necessarily valid, while editing the mesh it can become *dirty*.\n"
149
" It's also possible to assign any number to this attribute for a scripts internal logic.\n"
151
" To ensure the value is up to date - see :class:`BMElemSeq.index_update`.\n"
153
static PyObject *bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
155
BPY_BM_CHECK_OBJ(self);
157
return PyLong_FromLong(BM_elem_index_get(self->ele));
160
static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
164
BPY_BM_CHECK_INT(self);
166
param = PyLong_AsLong(value);
168
if (param == -1 && PyErr_Occurred()) {
169
PyErr_SetString(PyExc_TypeError,
170
"expected an int type");
174
BM_elem_index_set(self->ele, param); /* set_dirty! */
176
/* when setting the index assume its set invalid */
177
if (self->ele->head.htype & (BM_VERT | BM_EDGE | BM_FACE)) {
178
self->bm->elem_index_dirty |= self->ele->head.htype;
185
/* type specific get/sets
186
* ---------------------- */
192
/* doc-strings for all uses of this funcion */
194
PyDoc_STRVAR(bpy_bmvertseq_doc,
195
"This meshes vert sequence (read-only).\n\n:type: :class:`BMVertSeq`"
197
static PyObject *bpy_bmvertseq_get(BPy_BMesh *self, void *UNUSED(closure))
199
BPY_BM_CHECK_OBJ(self);
200
return BPy_BMVertSeq_CreatePyObject(self->bm);
203
PyDoc_STRVAR(bpy_bmedgeseq_doc,
204
"This meshes edge sequence (read-only).\n\n:type: :class:`BMEdgeSeq`"
206
static PyObject *bpy_bmedgeseq_get(BPy_BMesh *self, void *UNUSED(closure))
208
BPY_BM_CHECK_OBJ(self);
209
return BPy_BMEdgeSeq_CreatePyObject(self->bm);
212
PyDoc_STRVAR(bpy_bmfaceseq_doc,
213
"This meshes face sequence (read-only).\n\n:type: :class:`BMFaceSeq`"
215
static PyObject *bpy_bmfaceseq_get(BPy_BMesh *self, void *UNUSED(closure))
217
BPY_BM_CHECK_OBJ(self);
218
return BPy_BMFaceSeq_CreatePyObject(self->bm);
221
PyDoc_STRVAR(bpy_bmloopseq_doc,
222
"This meshes face sequence (read-only).\n\n:type: :class:`BMLoopSeq`"
224
static PyObject *bpy_bmloopseq_get(BPy_BMesh *self, void *UNUSED(closure))
226
BPY_BM_CHECK_OBJ(self);
227
return BPy_BMLoopSeq_CreatePyObject(self->bm);
231
PyDoc_STRVAR(bpy_bmvert_link_edges_doc,
232
"Edges connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
234
PyDoc_STRVAR(bpy_bmvert_link_faces_doc,
235
"Faces connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
237
PyDoc_STRVAR(bpy_bmvert_link_loops_doc,
238
"Loops that use this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
241
PyDoc_STRVAR(bpy_bmedge_verts_doc,
242
"Verts this edge uses (always 2), (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
244
PyDoc_STRVAR(bpy_bmedge_link_faces_doc,
245
"Faces connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
247
PyDoc_STRVAR(bpy_bmedge_link_loops_doc,
248
"Loops connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
251
PyDoc_STRVAR(bpy_bmface_verts_doc,
252
"Verts of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
254
PyDoc_STRVAR(bpy_bmface_edges_doc,
255
"Edges of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMEdge`"
257
PyDoc_STRVAR(bpy_bmface_loops_doc,
258
"Loops of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
261
PyDoc_STRVAR(bpy_bmloops_link_loops_doc,
262
"Loops connected to this loop, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
265
static PyObject *bpy_bmelemseq_elem_get(BPy_BMElem *self, void *itype)
267
BPY_BM_CHECK_OBJ(self);
268
return BPy_BMElemSeq_CreatePyObject(self->bm, self, GET_INT_FROM_POINTER(itype));
272
PyDoc_STRVAR(bpy_bm_is_valid_doc,
273
"True when this element is valid (hasn't been removed).\n\n:type: boolean"
275
static PyObject *bpy_bm_is_valid_get(BPy_BMGeneric *self)
277
return PyBool_FromLong(BPY_BM_IS_VALID(self));
280
PyDoc_STRVAR(bpy_bmesh_is_wrapped_doc,
281
"True when this mesh is owned by blender (typically the editmode BMesh).\n\n:type: boolean"
283
static PyObject *bpy_bmesh_is_wrapped_get(BPy_BMesh *self)
285
BPY_BM_CHECK_OBJ(self);
287
return PyBool_FromLong(self->flag & BPY_BMFLAG_IS_WRAPPED);
290
PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
291
"The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an empty set.\n\n:type: set"
293
static PyObject *bpy_bmesh_select_mode_get(BPy_BMesh *self)
295
BPY_BM_CHECK_OBJ(self);
297
return PyC_FlagSet_FromBitfield(bpy_bm_scene_vert_edge_face_flags, self->bm->selectmode);
300
static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
303
BPY_BM_CHECK_INT(self);
305
if (PyC_FlagSet_ToBitfield(bpy_bm_scene_vert_edge_face_flags, value, &flag, "bm.select_mode") == -1) {
308
else if (flag == 0) {
309
PyErr_SetString(PyExc_TypeError,
310
"bm.select_mode: cant assignt an empty value");
314
self->bm->selectmode = flag;
319
PyDoc_STRVAR(bpy_bmesh_select_history_doc,
320
"Sequence of selected items (the last is displayed as active).\n\n:type: :class:`BMEditSelSeq`"
322
static PyObject *bpy_bmesh_select_history_get(BPy_BMesh *self)
324
BPY_BM_CHECK_OBJ(self);
326
return BPy_BMEditSel_CreatePyObject(self->bm);
329
static int bpy_bmesh_select_history_set(BPy_BMesh *self, PyObject *value)
331
BPY_BM_CHECK_INT(self);
333
return BPy_BMEditSel_Assign(self, value);
339
PyDoc_STRVAR(bpy_bmvert_co_doc,
340
"The coordinates for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
342
static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
344
BPY_BM_CHECK_OBJ(self);
345
return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
348
static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
350
BPY_BM_CHECK_INT(self);
352
if (mathutils_array_parse(self->v->co, 3, 3, value, "BMVert.co") != -1) {
361
PyDoc_STRVAR(bpy_bmvert_normal_doc,
362
"The normal for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
364
static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
366
BPY_BM_CHECK_OBJ(self);
367
return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
370
static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
372
BPY_BM_CHECK_INT(self);
374
if (mathutils_array_parse(self->v->no, 3, 3, value, "BMVert.normal") != -1) {
383
PyDoc_STRVAR(bpy_bmvert_is_manifold_doc,
384
"True when this vertex is manifold (read-only).\n\n:type: boolean"
386
static PyObject *bpy_bmvert_is_manifold_get(BPy_BMVert *self)
388
BPY_BM_CHECK_OBJ(self);
389
return PyBool_FromLong(BM_vert_is_manifold(self->v));
393
PyDoc_STRVAR(bpy_bmvert_is_wire_doc,
394
"True when this vertex is not connected to any faces (read-only).\n\n:type: boolean"
396
static PyObject *bpy_bmvert_is_wire_get(BPy_BMVert *self)
398
BPY_BM_CHECK_OBJ(self);
399
return PyBool_FromLong(BM_vert_is_wire(self->v));
406
PyDoc_STRVAR(bpy_bmedge_is_manifold_doc,
407
"True when this edge is manifold (read-only).\n\n:type: boolean"
409
static PyObject *bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
411
BPY_BM_CHECK_OBJ(self);
412
return PyBool_FromLong(BM_edge_is_manifold(self->e));
416
PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
417
"True when this edge is not connected to any faces (read-only).\n\n:type: boolean"
419
static PyObject *bpy_bmedge_is_wire_get(BPy_BMEdge *self)
421
BPY_BM_CHECK_OBJ(self);
422
return PyBool_FromLong(BM_edge_is_wire(self->e));
426
PyDoc_STRVAR(bpy_bmedge_is_boundary_doc,
427
"True when this edge is at the boundary of a face (read-only).\n\n:type: boolean"
429
static PyObject *bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
431
BPY_BM_CHECK_OBJ(self);
432
return PyBool_FromLong(BM_edge_is_boundary(self->e));
439
PyDoc_STRVAR(bpy_bmface_normal_doc,
440
"The normal for this face as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
442
static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
444
BPY_BM_CHECK_OBJ(self);
445
return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
448
static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
450
BPY_BM_CHECK_INT(self);
452
if (mathutils_array_parse(self->f->no, 3, 3, value, "BMFace.normal") != -1) {
460
PyDoc_STRVAR(bpy_bmface_material_index_doc,
461
"The faces material index.\n\n:type: int"
463
static PyObject *bpy_bmface_material_index_get(BPy_BMFace *self)
465
BPY_BM_CHECK_OBJ(self);
466
return PyLong_FromLong(self->f->mat_nr);
469
static int bpy_bmface_material_index_set(BPy_BMFace *self, PyObject *value)
473
BPY_BM_CHECK_INT(self);
475
param = PyLong_AsLong(value);
477
if (param == -1 && PyErr_Occurred()) {
478
PyErr_SetString(PyExc_TypeError,
479
"expected an int type");
482
else if ((param < 0) || (param > MAXMAT)) {
483
/* normally we clamp but in this case raise an error */
484
PyErr_SetString(PyExc_ValueError,
485
"material index outside of usable range (0 - 32766)");
489
self->f->mat_nr = (short)param;
497
PyDoc_STRVAR(bpy_bmloop_vert_doc,
498
"The loops vertex (read-only).\n\n:type: :class:`BMVert`"
500
static PyObject *bpy_bmloop_vert_get(BPy_BMLoop *self)
502
BPY_BM_CHECK_OBJ(self);
503
return BPy_BMVert_CreatePyObject(self->bm, self->l->v);
507
PyDoc_STRVAR(bpy_bmloop_edge_doc,
508
"The loops edge (between this loop and the next), (read-only).\n\n:type: :class:`BMEdge`"
510
static PyObject *bpy_bmloop_edge_get(BPy_BMLoop *self)
512
BPY_BM_CHECK_OBJ(self);
513
return BPy_BMEdge_CreatePyObject(self->bm, self->l->e);
517
PyDoc_STRVAR(bpy_bmloop_face_doc,
518
"The face this loop makes (read-only).\n\n:type: :class:`BMFace`"
520
static PyObject *bpy_bmloop_face_get(BPy_BMLoop *self)
522
BPY_BM_CHECK_OBJ(self);
523
return BPy_BMFace_CreatePyObject(self->bm, self->l->f);
526
PyDoc_STRVAR(bpy_bmloop_link_loop_next_doc,
527
"The next face corner (read-only).\n\n:type: :class:`BMLoop`"
529
static PyObject *bpy_bmloop_link_loop_next_get(BPy_BMLoop *self)
531
BPY_BM_CHECK_OBJ(self);
532
return BPy_BMLoop_CreatePyObject(self->bm, self->l->next);
535
PyDoc_STRVAR(bpy_bmloop_link_loop_prev_doc,
536
"The previous face corner (read-only).\n\n:type: :class:`BMLoop`"
538
static PyObject *bpy_bmloop_link_loop_prev_get(BPy_BMLoop *self)
540
BPY_BM_CHECK_OBJ(self);
541
return BPy_BMLoop_CreatePyObject(self->bm, self->l->prev);
547
/* note: use for bmvert/edge/face/loop seq's use these, not bmelemseq directly */
548
PyDoc_STRVAR(bpy_bmelemseq_layers_doc,
549
"blah blah (read-only).\n\n:type: :class:`BMLayerAccess`"
551
static PyObject *bpy_bmelemseq_layers_get(BPy_BMElemSeq *self, void *htype)
553
BPY_BM_CHECK_OBJ(self);
555
return BPy_BMLayerAccess_CreatePyObject(self->bm, GET_INT_FROM_POINTER(htype));
558
static PyGetSetDef bpy_bmesh_getseters[] = {
559
{(char *)"verts", (getter)bpy_bmvertseq_get, (setter)NULL, (char *)bpy_bmvertseq_doc, NULL},
560
{(char *)"edges", (getter)bpy_bmedgeseq_get, (setter)NULL, (char *)bpy_bmedgeseq_doc, NULL},
561
{(char *)"faces", (getter)bpy_bmfaceseq_get, (setter)NULL, (char *)bpy_bmfaceseq_doc, NULL},
562
{(char *)"loops", (getter)bpy_bmloopseq_get, (setter)NULL, (char *)bpy_bmloopseq_doc, NULL},
563
{(char *)"select_mode", (getter)bpy_bmesh_select_mode_get, (setter)bpy_bmesh_select_mode_set, (char *)bpy_bmesh_select_mode_doc, NULL},
565
{(char *)"select_history", (getter)bpy_bmesh_select_history_get, (setter)bpy_bmesh_select_history_set, (char *)bpy_bmesh_select_history_doc, NULL},
567
/* readonly checks */
568
{(char *)"is_wrapped", (getter)bpy_bmesh_is_wrapped_get, (setter)NULL, (char *)bpy_bmesh_is_wrapped_doc, NULL}, /* as with mathutils */
569
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
571
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
574
static PyGetSetDef bpy_bmvert_getseters[] = {
576
{(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
577
{(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
578
{(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
579
{(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
581
{(char *)"co", (getter)bpy_bmvert_co_get, (setter)bpy_bmvert_co_set, (char *)bpy_bmvert_co_doc, NULL},
582
{(char *)"normal", (getter)bpy_bmvert_normal_get, (setter)bpy_bmvert_normal_set, (char *)bpy_bmvert_normal_doc, NULL},
584
/* connectivity data */
585
{(char *)"link_edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_edges_doc, (void *)BM_EDGES_OF_VERT},
586
{(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_faces_doc, (void *)BM_FACES_OF_VERT},
587
{(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_loops_doc, (void *)BM_LOOPS_OF_VERT},
589
/* readonly checks */
590
{(char *)"is_manifold", (getter)bpy_bmvert_is_manifold_get, (setter)NULL, (char *)bpy_bmvert_is_manifold_doc, NULL},
591
{(char *)"is_wire", (getter)bpy_bmvert_is_wire_get, (setter)NULL, (char *)bpy_bmvert_is_wire_doc, NULL},
592
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
594
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
597
static PyGetSetDef bpy_bmedge_getseters[] = {
599
{(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
600
{(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
601
{(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
602
{(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
604
{(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
605
{(char *)"seam", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_seam_doc, (void *)BM_ELEM_SEAM},
607
/* connectivity data */
608
{(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_verts_doc, (void *)BM_VERTS_OF_EDGE},
610
{(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_faces_doc, (void *)BM_FACES_OF_EDGE},
611
{(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_loops_doc, (void *)BM_LOOPS_OF_EDGE},
613
/* readonly checks */
614
{(char *)"is_manifold", (getter)bpy_bmedge_is_manifold_get, (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
615
{(char *)"is_wire", (getter)bpy_bmedge_is_wire_get, (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
616
{(char *)"is_boundary", (getter)bpy_bmedge_is_boundary_get, (setter)NULL, (char *)bpy_bmedge_is_boundary_doc, NULL},
617
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
619
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
622
static PyGetSetDef bpy_bmface_getseters[] = {
624
{(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
625
{(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
626
{(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
627
{(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
629
{(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
631
{(char *)"normal", (getter)bpy_bmface_normal_get, (setter)bpy_bmface_normal_set, (char *)bpy_bmface_normal_doc, NULL},
633
{(char *)"material_index", (getter)bpy_bmface_material_index_get, (setter)bpy_bmface_material_index_set, (char *)bpy_bmface_material_index_doc, NULL},
635
/* connectivity data */
636
{(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_verts_doc, (void *)BM_VERTS_OF_FACE},
637
{(char *)"edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_edges_doc, (void *)BM_EDGES_OF_FACE},
638
{(char *)"loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_loops_doc, (void *)BM_LOOPS_OF_FACE},
640
/* readonly checks */
641
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
643
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
646
static PyGetSetDef bpy_bmloop_getseters[] = {
648
// flags are available but not used for loops.
649
// {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
650
// {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
651
{(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
652
{(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
654
{(char *)"vert", (getter)bpy_bmloop_vert_get, (setter)NULL, (char *)bpy_bmloop_vert_doc, NULL},
655
{(char *)"edge", (getter)bpy_bmloop_edge_get, (setter)NULL, (char *)bpy_bmloop_edge_doc, NULL},
656
{(char *)"face", (getter)bpy_bmloop_face_get, (setter)NULL, (char *)bpy_bmloop_face_doc, NULL},
658
/* connectivity data */
659
{(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmloops_link_loops_doc, (void *)BM_LOOPS_OF_LOOP},
660
{(char *)"link_loop_next", (getter)bpy_bmloop_link_loop_next_get, (setter)NULL, (char *)bpy_bmloop_link_loop_next_doc, NULL},
661
{(char *)"link_loop_prev", (getter)bpy_bmloop_link_loop_prev_get, (setter)NULL, (char *)bpy_bmloop_link_loop_prev_doc, NULL},
663
/* readonly checks */
664
{(char *)"is_valid", (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
666
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
669
static PyGetSetDef bpy_bmvertseq_getseters[] = {
670
{(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_VERT},
671
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
673
static PyGetSetDef bpy_bmedgeseq_getseters[] = {
674
{(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_EDGE},
675
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
677
static PyGetSetDef bpy_bmfaceseq_getseters[] = {
678
{(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_FACE},
679
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
681
static PyGetSetDef bpy_bmloopseq_getseters[] = {
682
{(char *)"layers", (getter)bpy_bmelemseq_layers_get, (setter)NULL, (char *)bpy_bmelemseq_layers_doc, (void *)BM_LOOP},
683
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
694
PyDoc_STRVAR(bpy_bmesh_copy_doc,
695
".. method:: copy()\n"
697
" :return: A copy of this BMesh.\n"
698
" :rtype: :class:`BMesh`\n"
700
static PyObject *bpy_bmesh_copy(BPy_BMesh *self)
705
BPY_BM_CHECK_OBJ(self);
709
bm_copy = BM_mesh_copy(bm);
712
return BPy_BMesh_CreatePyObject(bm_copy, BPY_BMFLAG_NOP);
715
PyErr_SetString(PyExc_SystemError, "Unable to copy BMesh, internal error");
720
PyDoc_STRVAR(bpy_bmesh_clear_doc,
721
".. method:: clear()\n"
723
" Clear all mesh data.\n"
725
static PyObject *bpy_bmesh_clear(BPy_BMesh *self)
729
BPY_BM_CHECK_OBJ(self);
738
PyDoc_STRVAR(bpy_bmesh_free_doc,
739
".. method:: free()\n"
741
" Explicitly free the BMesh data from memory, causing exceptions on further access.\n"
745
" The BMesh is freed automatically, typically when the script finishes executing.\n"
746
" However in some cases its hard to predict when this will be and its useful to\n"
747
" explicitly free the data.\n"
749
static PyObject *bpy_bmesh_free(BPy_BMesh *self)
752
BMesh *bm = self->bm;
754
if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
758
bpy_bm_generic_invalidate((BPy_BMGeneric *)self);
764
PyDoc_STRVAR(bpy_bmesh_to_mesh_doc,
765
".. method:: to_mesh(mesh)\n"
767
" Writes this BMesh data into an existing Mesh datablock.\n"
769
" :arg mesh: The mesh data to write into.\n"
770
" :type mesh: :class:`Mesh`\n"
772
static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args)
778
BPY_BM_CHECK_OBJ(self);
780
if (!PyArg_ParseTuple(args, "O:to_mesh", &py_mesh) ||
781
!(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
786
/* we could allow this but its almost certainly _not_ what script authors want */
787
if (me->edit_btmesh) {
788
PyErr_Format(PyExc_ValueError,
789
"to_mesh(): Mesh '%s' is in editmode", me->id.name + 2);
795
BM_mesh_bm_to_me(bm, me, FALSE);
797
/* we could have the user do this but if they forget blender can easy crash
798
* since the references arrays for the objects derived meshes are now invalid */
799
DAG_id_tag_update(&me->id, OB_RECALC_DATA);
804
/* note: rna_Object_to_mesh() also has apply_modifiers arg that works the same way */
805
PyDoc_STRVAR(bpy_bmesh_from_object_doc,
806
".. method:: from_object(mesh, apply_modifiers=True)\n"
808
" Initialize this bmesh from existing object datablock.\n"
810
" :arg object: The object data to load.\n"
811
" :type object: :class:`Object`\n"
812
" :arg apply_modifiers: Use the final display mesh rather then the deformed cage.\n"
813
" :type apply_modifiers: boolean\n"
815
static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args)
820
int apply_modifiers = TRUE;
823
BPY_BM_CHECK_OBJ(self);
825
if (!PyArg_ParseTuple(args, "O|i:from_object", &py_object, &apply_modifiers) ||
826
!(ob = PyC_RNA_AsPointer(py_object, "Object")))
831
dm = apply_modifiers ? ob->derivedFinal : ob->derivedDeform;
834
PyErr_Format(PyExc_ValueError,
835
"from_object(...): Object '%s' has no usable mesh data", ob->id.name + 2);
841
DM_to_bmesh_ex(dm, bm);
847
PyDoc_STRVAR(bpy_bmesh_from_mesh_doc,
848
".. method:: from_mesh(mesh, use_shape_key=False, shape_key_index=0)\n"
850
" Initialize this bmesh from existing mesh datablock.\n"
852
" :arg mesh: The mesh data to load.\n"
853
" :type mesh: :class:`Mesh`\n"
854
" :arg use_shape_key: Use the locations from a shape key.\n"
855
" :type use_shape_key: boolean\n"
856
" :arg shape_key_index: The shape key index to use.\n"
857
" :type shape_key_index: int\n"
859
static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *kw)
861
static const char *kwlist[] = {"mesh", "use_shape_key", "shape_key_index", NULL};
865
int use_shape_key = FALSE;
866
int shape_key_index = 0;
868
if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:from_mesh", (char **)kwlist,
869
&py_mesh, &use_shape_key, &shape_key_index) ||
870
!(me = PyC_RNA_AsPointer(py_mesh, "Mesh")))
877
BM_mesh_bm_from_me(bm, me, use_shape_key, shape_key_index + 1);
883
PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc,
884
".. method:: select_flush_mode()\n"
886
" flush selection based on the current mode current :class:`BMesh.select_mode`.\n"
888
static PyObject *bpy_bmesh_select_flush_mode(BPy_BMesh *self)
890
BPY_BM_CHECK_OBJ(self);
892
BM_mesh_select_mode_flush(self->bm);
898
PyDoc_STRVAR(bpy_bmesh_select_flush_doc,
899
".. method:: select_flush(select)\n"
901
" Flush selection, independent of the current selection mode.\n"
903
" :arg select: flush selection or de-selected elements.\n"
904
" :type select: boolean\n"
906
static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
910
BPY_BM_CHECK_OBJ(self);
912
param = PyLong_AsLong(value);
913
if (param != FALSE && param != TRUE) {
914
PyErr_SetString(PyExc_TypeError,
915
"expected a boolean type 0/1");
919
if (param) BM_mesh_select_flush(self->bm);
920
else BM_mesh_deselect_flush(self->bm);
926
PyDoc_STRVAR(bpy_bmesh_normal_update_doc,
927
".. method:: normal_update(skip_hidden=False)\n"
929
" Update mesh normals.\n"
931
" :arg skip_hidden: When True hidden elements are ignored.\n"
932
" :type skip_hidden: boolean\n"
934
static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self, PyObject *args)
937
int skip_hidden = FALSE;
939
BPY_BM_CHECK_OBJ(self);
941
if (!PyArg_ParseTuple(args, "|i:normal_update", &skip_hidden)) {
945
BM_mesh_normals_update(self->bm, skip_hidden);
951
PyDoc_STRVAR(bpy_bmesh_transform_doc,
952
".. method:: transform(matrix, filter=None)\n"
954
" Transform the mesh (optionally filtering flagged data only).\n"
956
" :arg matrix: transform matrix.\n"
957
" :type matrix: 4x4 :class:`mathutils.Matrix`\n"
958
" :arg filter: set of values in ('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG').\n"
959
" :type filter: set\n"
961
static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
963
static const char *kwlist[] = {"matrix", "filter", NULL};
966
PyObject *filter = NULL;
967
int filter_flags = 0;
969
BPY_BM_CHECK_OBJ(self);
971
if (!PyArg_ParseTupleAndKeywords(args, kw,
975
&PySet_Type, &filter))
984
if (BaseMath_ReadCallback(mat) == -1) {
987
else if (mat->num_col != 4 || mat->num_row != 4) {
988
PyErr_SetString(PyExc_ValueError,
989
"expected a 4x4 matrix");
993
if (filter != NULL && PyC_FlagSet_ToBitfield(bpy_bm_hflag_all_flags, filter,
994
&filter_flags, "bm.transform") == -1)
999
mat_ptr = mat->matrix;
1001
if (!filter_flags) {
1002
BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1003
mul_m4_v3((float (*)[4])mat_ptr, eve->co);
1007
char filter_flags_ch = (char)filter_flags;
1008
BM_ITER_MESH (eve, &iter, self->bm, BM_VERTS_OF_MESH) {
1009
if (eve->head.hflag & filter_flags_ch) {
1010
mul_m4_v3((float (*)[4])mat_ptr, eve->co);
1023
PyDoc_STRVAR(bpy_bm_elem_select_set_doc,
1024
".. method:: select_set(select)\n"
1026
" Set the selection.\n"
1027
" This is different from the *select* attribute because it updates the selection state of assosiated geometry.\n"
1029
" :arg select: Select or de-select.\n"
1030
" :type select: boolean\n"
1034
" Currently this only flushes down, so selecting a face will select all its vertices but de-selecting a vertex "
1035
" won't de-select all the faces that use it, before finishing with a mesh typically flushing is still needed.\n"
1037
static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
1041
BPY_BM_CHECK_OBJ(self);
1043
param = PyLong_AsLong(value);
1044
if (param != FALSE && param != TRUE) {
1045
PyErr_SetString(PyExc_TypeError,
1046
"expected a boolean type 0/1");
1050
BM_elem_select_set(self->bm, self->ele, param);
1056
PyDoc_STRVAR(bpy_bm_elem_hide_set_doc,
1057
".. method:: hide_set(hide)\n"
1059
" Set the hide state.\n"
1060
" This is different from the *hide* attribute because it updates the selection and hide state of assosiated geometry.\n"
1062
" :arg hide: Hidden or visible.\n"
1063
" :type hide: boolean\n"
1065
static PyObject *bpy_bm_elem_hide_set(BPy_BMElem *self, PyObject *value)
1069
BPY_BM_CHECK_OBJ(self);
1071
param = PyLong_AsLong(value);
1072
if (param != FALSE && param != TRUE) {
1073
PyErr_SetString(PyExc_TypeError,
1074
"expected a boolean type 0/1");
1078
BM_elem_hide_set(self->bm, self->ele, param);
1084
PyDoc_STRVAR(bpy_bm_elem_copy_from_doc,
1085
".. method:: copy_from(other)\n"
1087
" Copy values from another element of matching type.\n"
1089
static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
1091
BPY_BM_CHECK_OBJ(self);
1093
if (Py_TYPE(self) != Py_TYPE(value)) {
1094
PyErr_Format(PyExc_TypeError,
1095
"expected element of type '%.200s' not '%.200s'",
1096
Py_TYPE(self)->tp_name, Py_TYPE(value)->tp_name);
1100
if (value->ele != self->ele) {
1101
BM_elem_attrs_copy(value->bm, self->bm, value->ele, self->ele);
1112
PyDoc_STRVAR(bpy_bmvert_copy_from_vert_interp_doc,
1113
".. method:: copy_from_vert_interp(vert_pair, fac)\n"
1115
" Interpolate the customdata from a vert between 2 other verts.\n"
1117
" :arg vert_pair: The vert to interpolate data from.\n"
1118
" :type vert_pair: :class:`BMVert`\n"
1120
static PyObject *bpy_bmvert_copy_from_vert_interp(BPy_BMVert *self, PyObject *args)
1125
BPY_BM_CHECK_OBJ(self);
1127
if (!PyArg_ParseTuple(args, "Of:BMVert.copy_from_vert_interp",
1133
BMesh *bm = self->bm;
1134
BMVert **vert_array = NULL;
1135
Py_ssize_t vert_seq_len; /* always 2 */
1137
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1138
&vert_seq_len, BM_VERT,
1139
TRUE, TRUE, "BMVert.copy_from_vert_interp(...)");
1141
if (vert_array == NULL) {
1145
BM_data_interp_from_verts(bm, vert_array[0], vert_array[1], self->v, CLAMPIS(fac, 0.0f, 1.0f));
1147
PyMem_FREE(vert_array);
1153
PyDoc_STRVAR(bpy_bmvert_copy_from_face_interp_doc,
1154
".. method:: copy_from_face_interp(face)\n"
1156
" Interpolate the customdata from a face onto this loop (the loops vert should overlap the face).\n"
1158
" :arg face: The face to interpolate data from.\n"
1159
" :type face: :class:`BMFace`\n"
1161
static PyObject *bpy_bmvert_copy_from_face_interp(BPy_BMVert *self, PyObject *args)
1163
BPy_BMFace *py_face = NULL;
1165
BPY_BM_CHECK_OBJ(self);
1167
if (!PyArg_ParseTuple(args, "O!:BMVert.copy_from_face_interp",
1168
&BPy_BMFace_Type, &py_face))
1173
BMesh *bm = self->bm;
1175
BPY_BM_CHECK_OBJ(py_face);
1177
if (py_face->bm != bm) {
1178
PyErr_SetString(PyExc_ValueError,
1179
"BMVert.copy_from_face_interp(face): face is from another mesh");
1183
BM_vert_interp_from_face(bm, self->v, py_face->f);
1190
PyDoc_STRVAR(bpy_bmvert_calc_edge_angle_doc,
1191
".. method:: calc_edge_angle()\n"
1193
" Return the angle between this verts 2 connected edges.\n"
1195
" :return: Angle between edges in radians.\n"
1198
static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self)
1200
BPY_BM_CHECK_OBJ(self);
1201
return PyFloat_FromDouble(BM_vert_calc_edge_angle(self->v));
1204
PyDoc_STRVAR(bpy_bmvert_calc_shell_factor_doc,
1205
".. method:: calc_shell_factor()\n"
1207
" Return a multiplier calculated based on the sharpness of the vertex.\n"
1208
" Where a flat surface gives 1.0, and higher values sharper edges.\n"
1209
" This is used to maintain shell thickness when offsetting verts along their normals.\n"
1211
" :return: offset multiplier\n"
1214
static PyObject *bpy_bmvert_calc_shell_factor(BPy_BMVert *self)
1216
BPY_BM_CHECK_OBJ(self);
1217
return PyFloat_FromDouble(BM_vert_calc_shell_factor(self->v));
1220
PyDoc_STRVAR(bpy_bmvert_normal_update_doc,
1221
".. method:: normal_update()\n"
1223
" Update vertex normal.\n"
1225
static PyObject *bpy_bmvert_normal_update(BPy_BMVert *self)
1227
BPY_BM_CHECK_OBJ(self);
1229
BM_vert_normal_update(self->v);
1238
PyDoc_STRVAR(bpy_bmedge_calc_length_doc,
1239
".. method:: calc_length()\n"
1241
" :return: The length between both verts.\n"
1244
static PyObject *bpy_bmedge_calc_length(BPy_BMEdge *self)
1246
BPY_BM_CHECK_OBJ(self);
1247
return PyFloat_FromDouble(len_v3v3(self->e->v1->co, self->e->v2->co));
1250
PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
1251
".. method:: calc_face_angle()\n"
1253
" :return: The angle between 2 connected faces in radians.\n"
1256
static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
1258
BPY_BM_CHECK_OBJ(self);
1259
return PyFloat_FromDouble(BM_edge_calc_face_angle(self->e));
1262
PyDoc_STRVAR(bpy_bmedge_calc_tangent_doc,
1263
".. method:: calc_tangent(loop)\n"
1265
" Return the tangent at this edge relative to a face (pointing inward into the face).\n"
1266
" This uses the face normal for calculation.\n"
1268
" :arg loop: The loop used for tangent calculation.\n"
1269
" :type loop: :class:`BMLoop`\n"
1270
" :return: a normalized vector.\n"
1271
" :rtype: :class:`mathutils.Vector`\n"
1273
static PyObject *bpy_bmedge_calc_tangent(BPy_BMEdge *self, PyObject *args)
1275
BPy_BMLoop *py_loop;
1276
BPY_BM_CHECK_OBJ(self);
1278
if (!PyArg_ParseTuple(args, "O!:BMEdge.calc_face_tangent",
1279
&BPy_BMLoop_Type, &py_loop))
1285
BPY_BM_CHECK_OBJ(py_loop);
1286
/* no need to check if they are from the same mesh or even connected */
1287
BM_edge_calc_face_tangent(self->e, py_loop->l, vec);
1288
return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1293
PyDoc_STRVAR(bpy_bmedge_other_vert_doc,
1294
".. method:: other_vert(vert)\n"
1296
" Return the other vertex on this edge or None if the vertex is not used by this edge.\n"
1298
" :arg vert: a vert in this edge.\n"
1299
" :type vert: :class:`BMVert`\n"
1300
" :return: The edges other vert.\n"
1301
" :rtype: :class:`BMVert` or None\n"
1303
static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
1306
BPY_BM_CHECK_OBJ(self);
1308
if (!BPy_BMVert_Check(value)) {
1309
PyErr_Format(PyExc_TypeError,
1310
"BMEdge.other_vert(vert): BMVert expected, not '%.200s'",
1311
Py_TYPE(value)->tp_name);
1315
BPY_BM_CHECK_OBJ(value);
1317
if (self->bm != value->bm) {
1318
PyErr_SetString(PyExc_ValueError,
1319
"BMEdge.other_vert(vert): vert is from another mesh");
1323
other = BM_edge_other_vert(self->e, value->v);
1326
return BPy_BMVert_CreatePyObject(self->bm, other);
1329
/* could raise an exception here */
1335
PyDoc_STRVAR(bpy_bmedge_normal_update_doc,
1336
".. method:: normal_update()\n"
1338
" Update edges vertex normals.\n"
1340
static PyObject *bpy_bmedge_normal_update(BPy_BMEdge *self)
1342
BPY_BM_CHECK_OBJ(self);
1344
BM_edge_normals_update(self->e);
1353
PyDoc_STRVAR(bpy_bmface_copy_from_face_interp_doc,
1354
".. method:: copy_from_face_interp(face)\n"
1356
" Interpolate the customdata from another face onto this one (faces should overlap).\n"
1358
" :arg face: The face to interpolate data from.\n"
1359
" :type face: :class:`BMFace`\n"
1361
static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
1363
BPy_BMFace *py_face = NULL;
1365
BPY_BM_CHECK_OBJ(self);
1367
if (!PyArg_ParseTuple(args, "O!:BMFace.copy_from_face_interp",
1368
&BPy_BMFace_Type, &py_face))
1373
BMesh *bm = self->bm;
1375
BPY_BM_CHECK_OBJ(py_face);
1377
if (py_face->bm != bm) {
1378
PyErr_SetString(PyExc_ValueError,
1379
"BMFace.copy_from_face_interp(face): face is from another mesh");
1383
BM_face_interp_from_face(bm, self->f, py_face->f);
1390
PyDoc_STRVAR(bpy_bmface_copy_doc,
1391
".. method:: copy(verts=True, edges=True)\n"
1393
" Make a copy of this face.\n"
1395
" :arg verts: When set, the faces verts will be duplicated too.\n"
1396
" :type verts: boolean\n"
1397
" :arg edges: When set, the faces edges will be duplicated too.\n"
1398
" :type edges: boolean\n"
1399
" :return: The newly created face.\n"
1400
" :rtype: :class:`BMFace`\n"
1402
static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
1404
static const char *kwlist[] = {"verts", "edges", NULL};
1406
BMesh *bm = self->bm;
1407
int do_verts = TRUE;
1408
int do_edges = TRUE;
1411
BPY_BM_CHECK_OBJ(self);
1413
if (!PyArg_ParseTupleAndKeywords(args, kw,
1416
&do_verts, &do_edges))
1421
f_cpy = BM_face_copy(bm, self->f, do_verts, do_edges);
1424
return BPy_BMFace_CreatePyObject(bm, f_cpy);
1427
PyErr_SetString(PyExc_ValueError,
1428
"BMFace.copy(): couldn't create the new face, internal error");
1434
PyDoc_STRVAR(bpy_bmface_calc_area_doc,
1435
".. method:: calc_area()\n"
1437
" Return the area of the face.\n"
1439
" :return: Return the area of the face.\n"
1442
static PyObject *bpy_bmface_calc_area(BPy_BMFace *self)
1444
BPY_BM_CHECK_OBJ(self);
1445
return PyFloat_FromDouble(BM_face_calc_area(self->f));
1449
PyDoc_STRVAR(bpy_bmface_calc_perimeter_doc,
1450
".. method:: calc_perimeter()\n"
1452
" Return the perimeter of the face.\n"
1454
" :return: Return the perimeter of the face.\n"
1457
static PyObject *bpy_bmface_calc_perimeter(BPy_BMFace *self)
1459
BPY_BM_CHECK_OBJ(self);
1460
return PyFloat_FromDouble(BM_face_calc_perimeter(self->f));
1464
PyDoc_STRVAR(bpy_bmface_calc_center_mean_doc,
1465
".. method:: calc_center_median()\n"
1467
" Return median center of the face.\n"
1469
" :return: a 3D vector.\n"
1470
" :rtype: :class:`mathutils.Vector`\n"
1472
static PyObject *bpy_bmface_calc_center_mean(BPy_BMFace *self)
1476
BPY_BM_CHECK_OBJ(self);
1477
BM_face_calc_center_mean(self->f, cent);
1478
return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
1482
PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
1483
".. method:: calc_center_bounds()\n"
1485
" Return bounds center of the face.\n"
1487
" :return: a 3D vector.\n"
1488
" :rtype: :class:`mathutils.Vector`\n"
1490
static PyObject *bpy_bmface_calc_center_bounds(BPy_BMFace *self)
1494
BPY_BM_CHECK_OBJ(self);
1495
BM_face_calc_center_bounds(self->f, cent);
1496
return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
1500
PyDoc_STRVAR(bpy_bmface_normal_update_doc,
1501
".. method:: normal_update()\n"
1503
" Update faces normal.\n"
1505
static PyObject *bpy_bmface_normal_update(BPy_BMFace *self)
1507
BPY_BM_CHECK_OBJ(self);
1509
BM_face_normal_update(self->f);
1518
PyDoc_STRVAR(bpy_bmloop_copy_from_face_interp_doc,
1519
".. method:: copy_from_face_interp(face, vert=True, multires=True)\n"
1521
" Interpolate the customdata from a face onto this loop (the loops vert should overlap the face).\n"
1523
" :arg face: The face to interpolate data from.\n"
1524
" :type face: :class:`BMFace`\n"
1525
" :arg vert: When enabled, interpolate the loops vertex data (optional).\n"
1526
" :type vert: boolean\n"
1527
" :arg multires: When enabled, interpolate the loops multires data (optional).\n"
1528
" :type multires: boolean\n"
1530
static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
1532
BPy_BMFace *py_face = NULL;
1533
int do_vertex = TRUE;
1534
int do_multires = TRUE;
1536
BPY_BM_CHECK_OBJ(self);
1538
if (!PyArg_ParseTuple(args, "O!|ii:BMLoop.copy_from_face_interp",
1539
&BPy_BMFace_Type, &py_face,
1540
&do_vertex, &do_multires))
1545
BMesh *bm = self->bm;
1547
BPY_BM_CHECK_OBJ(py_face);
1549
if (py_face->bm != bm) {
1550
PyErr_SetString(PyExc_ValueError,
1551
"BMLoop.copy_from_face_interp(face): face is from another mesh");
1555
BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires);
1562
PyDoc_STRVAR(bpy_bmloop_calc_angle_doc,
1563
".. method:: calc_angle()\n"
1565
" Return the angle at this loops corner of the face.\n"
1566
" This is calculated so sharper corners give lower angles.\n"
1568
" :return: The angle in radians.\n"
1571
static PyObject *bpy_bmloop_calc_angle(BPy_BMLoop *self)
1573
BPY_BM_CHECK_OBJ(self);
1574
return PyFloat_FromDouble(BM_loop_calc_face_angle(self->l));
1577
PyDoc_STRVAR(bpy_bmloop_calc_normal_doc,
1578
".. method:: calc_normal()\n"
1580
" Return normal at this loops corner of the face.\n"
1581
" Falls back to the face normal for straignt lines.\n"
1583
" :return: a normalized vector.\n"
1584
" :rtype: :class:`mathutils.Vector`\n"
1586
static PyObject *bpy_bmloop_calc_normal(BPy_BMLoop *self)
1589
BPY_BM_CHECK_OBJ(self);
1590
BM_loop_calc_face_normal(self->l, vec);
1591
return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1594
PyDoc_STRVAR(bpy_bmloop_calc_tangent_doc,
1595
".. method:: calc_tangent()\n"
1597
" Return the tangent at this loops corner of the face (pointing inward into the face).\n"
1598
" Falls back to the face normal for straignt lines.\n"
1600
" :return: a normalized vector.\n"
1601
" :rtype: :class:`mathutils.Vector`\n"
1603
static PyObject *bpy_bmloop_calc_tangent(BPy_BMLoop *self)
1606
BPY_BM_CHECK_OBJ(self);
1607
BM_loop_calc_face_tangent(self->l, vec);
1608
return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
1613
PyDoc_STRVAR(bpy_bmvertseq_new_doc,
1614
".. method:: new(co=(0.0, 0.0, 0.0), example=None)\n"
1616
" Create a new vertex.\n"
1618
" :arg co: The initial location of the vertex (optional argument).\n"
1619
" :type co: float triplet\n"
1620
" :arg example: Existing vert to initialize settings.\n"
1621
" :type example: :class:`BMVert`\n"
1622
" :return: The newly created edge.\n"
1623
" :rtype: :class:`BMVert`\n"
1625
static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
1627
PyObject *py_co = NULL;
1628
BPy_BMVert *py_vert_example = NULL; /* optional */
1630
BPY_BM_CHECK_OBJ(self);
1632
if (!PyArg_ParseTuple(args, "|OO!:verts.new",
1634
&BPy_BMVert_Type, &py_vert_example))
1639
BMesh *bm = self->bm;
1641
float co[3] = {0.0f, 0.0f, 0.0f};
1643
if (py_vert_example) {
1644
BPY_BM_CHECK_OBJ(py_vert_example);
1647
if (py_co && mathutils_array_parse(co, 3, 3, py_co, "verts.new(co)") == -1) {
1651
v = BM_vert_create(bm, co, NULL);
1654
PyErr_SetString(PyExc_ValueError,
1655
"faces.new(verts): couldn't create the new face, internal error");
1659
if (py_vert_example) {
1660
BM_elem_attrs_copy(py_vert_example->bm, bm, py_vert_example->v, v);
1663
return BPy_BMVert_CreatePyObject(bm, v);
1670
PyDoc_STRVAR(bpy_bmedgeseq_new_doc,
1671
".. method:: new(verts, example=None)\n"
1673
" Create a new edge from a given pair of verts.\n"
1675
" :arg verts: Vertex pair.\n"
1676
" :type verts: pair of :class:`BMVert`\n"
1677
" :arg example: Existing edge to initialize settings (optional argument).\n"
1678
" :type example: :class:`BMEdge`\n"
1679
" :return: The newly created edge.\n"
1680
" :rtype: :class:`BMEdge`\n"
1682
static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
1685
BPy_BMEdge *py_edge_example = NULL; /* optional */
1687
BPY_BM_CHECK_OBJ(self);
1689
if (!PyArg_ParseTuple(args, "O|O!:edges.new",
1691
&BPy_BMEdge_Type, &py_edge_example))
1696
BMesh *bm = self->bm;
1698
BMVert **vert_array = NULL;
1699
Py_ssize_t vert_seq_len; /* always 2 */
1700
PyObject *ret = NULL;
1702
if (py_edge_example) {
1703
BPY_BM_CHECK_OBJ(py_edge_example);
1706
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1707
&vert_seq_len, BM_VERT,
1708
TRUE, TRUE, "edges.new(...)");
1710
if (vert_array == NULL) {
1714
if (BM_edge_exists(vert_array[0], vert_array[1])) {
1715
PyErr_SetString(PyExc_ValueError,
1716
"edges.new(): this edge exists");
1720
e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, FALSE);
1723
PyErr_SetString(PyExc_ValueError,
1724
"faces.new(verts): couldn't create the new face, internal error");
1728
if (py_edge_example) {
1729
BM_elem_attrs_copy(py_edge_example->bm, bm, py_edge_example->e, e);
1732
ret = BPy_BMEdge_CreatePyObject(bm, e);
1735
if (vert_array) PyMem_FREE(vert_array);
1743
PyDoc_STRVAR(bpy_bmfaceseq_new_doc,
1744
".. method:: new(verts, example=None)\n"
1746
" Create a new face from a given set of verts.\n"
1748
" :arg verts: Sequence of 3 or more verts.\n"
1749
" :type verts: :class:`BMVert`\n"
1750
" :arg example: Existing face to initialize settings (optional argument).\n"
1751
" :type example: :class:`BMFace`\n"
1752
" :return: The newly created face.\n"
1753
" :rtype: :class:`BMFace`\n"
1755
static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
1758
BPy_BMFace *py_face_example = NULL; /* optional */
1760
BPY_BM_CHECK_OBJ(self);
1762
if (!PyArg_ParseTuple(args, "O|O!:faces.new",
1764
&BPy_BMFace_Type, &py_face_example))
1769
BMesh *bm = self->bm;
1770
Py_ssize_t vert_seq_len;
1771
Py_ssize_t i, i_next;
1773
BMVert **vert_array = NULL;
1774
BMEdge **edge_array = NULL;
1776
PyObject *ret = NULL;
1780
if (py_face_example) {
1781
BPY_BM_CHECK_OBJ(py_face_example);
1784
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX,
1785
&vert_seq_len, BM_VERT,
1786
TRUE, TRUE, "faces.new(...)");
1788
if (vert_array == NULL) {
1792
/* check if the face exists */
1793
if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) {
1794
PyErr_SetString(PyExc_ValueError,
1795
"faces.new(verts): face already exists");
1799
/* Go ahead and make the face!
1800
* --------------------------- */
1802
edge_array = (BMEdge **)PyMem_MALLOC(vert_seq_len * sizeof(BMEdge **));
1805
for (i = vert_seq_len - 1, i_next = 0; i_next < vert_seq_len; (i = i_next++)) {
1806
edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, TRUE);
1809
f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE);
1811
if (f_new == NULL) {
1812
PyErr_SetString(PyExc_ValueError,
1813
"faces.new(verts): couldn't create the new face, internal error");
1817
if (py_face_example) {
1818
BM_elem_attrs_copy(py_face_example->bm, bm, py_face_example->f, f_new);
1821
ret = BPy_BMFace_CreatePyObject(bm, f_new);
1825
if (vert_array) PyMem_FREE(vert_array);
1826
if (edge_array) PyMem_FREE(edge_array);
1834
PyDoc_STRVAR(bpy_bmvertseq_remove_doc,
1835
".. method:: remove(vert)\n"
1839
static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
1841
BPY_BM_CHECK_OBJ(self);
1843
if (!BPy_BMVert_Check(value)) {
1847
BMesh *bm = self->bm;
1849
BPY_BM_CHECK_OBJ(value);
1851
if (value->bm != bm) {
1852
PyErr_SetString(PyExc_ValueError,
1853
"verts.remove(vert): vert is from another mesh");
1857
BM_vert_kill(bm, value->v);
1858
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1864
PyDoc_STRVAR(bpy_bmedgeseq_remove_doc,
1865
".. method:: remove(edge)\n"
1869
static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
1871
BPY_BM_CHECK_OBJ(self);
1873
if (!BPy_BMEdge_Check(value)) {
1877
BMesh *bm = self->bm;
1879
BPY_BM_CHECK_OBJ(value);
1881
if (value->bm != bm) {
1882
PyErr_SetString(PyExc_ValueError,
1883
"edges.remove(edge): edge is from another mesh");
1887
BM_edge_kill(bm, value->e);
1888
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1894
PyDoc_STRVAR(bpy_bmfaceseq_remove_doc,
1895
".. method:: remove(face)\n"
1899
static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
1901
BPY_BM_CHECK_OBJ(self);
1903
if (!BPy_BMFace_Check(value)) {
1907
BMesh *bm = self->bm;
1909
BPY_BM_CHECK_OBJ(value);
1911
if (value->bm != bm) {
1912
PyErr_SetString(PyExc_ValueError,
1913
"faces.remove(face): face is from another mesh");
1917
BM_face_kill(bm, value->f);
1918
bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1924
PyDoc_STRVAR(bpy_bmedgeseq_get__method_doc,
1925
".. method:: get(verts, fallback=None)\n"
1927
" Return a edge which uses the **verts** passed.\n"
1929
" :arg verts: Sequence of verts.\n"
1930
" :type verts: :class:`BMVert`\n"
1931
" :arg fallback: Return this value if nothing is found.\n"
1932
" :return: The edge found or None\n"
1933
" :rtype: :class:`BMEdge`\n"
1935
static PyObject *bpy_bmedgeseq_get__method(BPy_BMElemSeq *self, PyObject *args)
1938
PyObject *fallback = Py_None; /* optional */
1940
BPY_BM_CHECK_OBJ(self);
1942
if (!PyArg_ParseTuple(args, "O|O:edges.get",
1949
BMesh *bm = self->bm;
1951
BMVert **vert_array = NULL;
1952
Py_ssize_t vert_seq_len; /* always 2 */
1953
PyObject *ret = NULL;
1955
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1956
&vert_seq_len, BM_VERT,
1957
TRUE, TRUE, "edges.get(...)");
1959
if (vert_array == NULL) {
1963
if ((e = BM_edge_exists(vert_array[0], vert_array[1]))) {
1964
ret = BPy_BMEdge_CreatePyObject(bm, e);
1971
PyMem_FREE(vert_array);
1976
PyDoc_STRVAR(bpy_bmfaceseq_get__method_doc,
1977
".. method:: get(verts, fallback=None)\n"
1979
" Return a face which uses the **verts** passed.\n"
1981
" :arg verts: Sequence of verts.\n"
1982
" :type verts: :class:`BMVert`\n"
1983
" :arg fallback: Return this value if nothing is found.\n"
1984
" :return: The face found or None\n"
1985
" :rtype: :class:`BMFace`\n"
1987
static PyObject *bpy_bmfaceseq_get__method(BPy_BMElemSeq *self, PyObject *args)
1990
PyObject *fallback = Py_None; /* optional */
1992
BPY_BM_CHECK_OBJ(self);
1994
if (!PyArg_ParseTuple(args, "O|O:faces.get",
2001
BMesh *bm = self->bm;
2003
BMVert **vert_array = NULL;
2004
Py_ssize_t vert_seq_len;
2005
PyObject *ret = NULL;
2007
vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 1, PY_SSIZE_T_MAX,
2008
&vert_seq_len, BM_VERT,
2009
TRUE, TRUE, "faces.get(...)");
2011
if (vert_array == NULL) {
2015
if (BM_face_exists(bm, vert_array, vert_seq_len, &f)) {
2016
ret = BPy_BMFace_CreatePyObject(bm, f);
2023
PyMem_FREE(vert_array);
2028
PyDoc_STRVAR(bpy_bmelemseq_index_update_doc,
2029
".. method:: index_update()\n"
2031
" Initialize the index values of this sequence.\n"
2033
" This is the equivalent of looping over all elements and assigning the index values.\n"
2035
" .. code-block:: python\n"
2037
" for index, ele in enumerate(sequence):\n"
2038
" ele.index = index\n"
2042
" Running this on sequences besides :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces`\n"
2043
" works but wont result in each element having a valid index, insted its order in the sequence will be set.\n"
2045
static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
2047
BMesh *bm = self->bm;
2049
BPY_BM_CHECK_OBJ(self);
2051
switch ((BMIterType)self->itype) {
2052
case BM_VERTS_OF_MESH:
2053
BM_mesh_elem_index_ensure(self->bm, BM_VERT);
2055
case BM_EDGES_OF_MESH:
2056
BM_mesh_elem_index_ensure(self->bm, BM_EDGE);
2058
case BM_FACES_OF_MESH:
2059
BM_mesh_elem_index_ensure(self->bm, BM_FACE);
2066
const char htype = bm_iter_itype_htype_map[self->itype];
2068
BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
2069
BM_elem_index_set(ele, index); /* set_dirty! */
2073
if (htype & (BM_VERT | BM_EDGE | BM_FACE)) {
2074
/* since this isn't the normal vert/edge/face loops,
2075
* we're setting dirty values here. so tag as dirty. */
2076
bm->elem_index_dirty |= htype;
2087
static struct PyMethodDef bpy_bmesh_methods[] = {
2089
{"copy", (PyCFunction)bpy_bmesh_copy, METH_NOARGS, bpy_bmesh_copy_doc},
2090
{"clear", (PyCFunction)bpy_bmesh_clear, METH_NOARGS, bpy_bmesh_clear_doc},
2091
{"free", (PyCFunction)bpy_bmesh_free, METH_NOARGS, bpy_bmesh_free_doc},
2094
{"from_object", (PyCFunction)bpy_bmesh_from_object, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_object_doc},
2095
{"from_mesh", (PyCFunction)bpy_bmesh_from_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_mesh_doc},
2096
{"to_mesh", (PyCFunction)bpy_bmesh_to_mesh, METH_VARARGS, bpy_bmesh_to_mesh_doc},
2099
{"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
2100
{"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
2101
{"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
2102
{"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS|METH_KEYWORDS, bpy_bmesh_transform_doc},
2103
{NULL, NULL, 0, NULL}
2106
static struct PyMethodDef bpy_bmvert_methods[] = {
2107
{"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2108
{"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2109
{"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2110
{"copy_from_face_interp", (PyCFunction)bpy_bmvert_copy_from_face_interp, METH_VARARGS, bpy_bmvert_copy_from_face_interp_doc},
2111
{"copy_from_vert_interp", (PyCFunction)bpy_bmvert_copy_from_vert_interp, METH_VARARGS, bpy_bmvert_copy_from_vert_interp_doc},
2113
{"calc_vert_angle", (PyCFunction)bpy_bmvert_calc_edge_angle, METH_NOARGS, bpy_bmvert_calc_edge_angle_doc},
2114
{"calc_shell_factor", (PyCFunction)bpy_bmvert_calc_shell_factor, METH_NOARGS, bpy_bmvert_calc_shell_factor_doc},
2116
{"normal_update", (PyCFunction)bpy_bmvert_normal_update, METH_NOARGS, bpy_bmvert_normal_update_doc},
2118
{NULL, NULL, 0, NULL}
2121
static struct PyMethodDef bpy_bmedge_methods[] = {
2122
{"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2123
{"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2124
{"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2126
{"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
2128
{"calc_length", (PyCFunction)bpy_bmedge_calc_length, METH_NOARGS, bpy_bmedge_calc_length_doc},
2129
{"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
2130
{"calc_tangent", (PyCFunction)bpy_bmedge_calc_tangent, METH_VARARGS, bpy_bmedge_calc_tangent_doc},
2132
{"normal_update", (PyCFunction)bpy_bmedge_normal_update, METH_NOARGS, bpy_bmedge_normal_update_doc},
2134
{NULL, NULL, 0, NULL}
2137
static struct PyMethodDef bpy_bmface_methods[] = {
2138
{"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
2139
{"hide_set", (PyCFunction)bpy_bm_elem_hide_set, METH_O, bpy_bm_elem_hide_set_doc},
2141
{"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2142
{"copy_from_face_interp", (PyCFunction)bpy_bmface_copy_from_face_interp, METH_O, bpy_bmface_copy_from_face_interp_doc},
2144
{"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS|METH_KEYWORDS, bpy_bmface_copy_doc},
2146
{"calc_area", (PyCFunction)bpy_bmface_calc_area, METH_NOARGS, bpy_bmface_calc_area_doc},
2147
{"calc_perimeter", (PyCFunction)bpy_bmface_calc_perimeter, METH_NOARGS, bpy_bmface_calc_perimeter_doc},
2148
{"calc_center_median", (PyCFunction)bpy_bmface_calc_center_mean, METH_NOARGS, bpy_bmface_calc_center_mean_doc},
2149
{"calc_center_bounds", (PyCFunction)bpy_bmface_calc_center_bounds, METH_NOARGS, bpy_bmface_calc_center_bounds_doc},
2151
{"normal_update", (PyCFunction)bpy_bmface_normal_update, METH_NOARGS, bpy_bmface_normal_update_doc},
2153
{NULL, NULL, 0, NULL}
2156
static struct PyMethodDef bpy_bmloop_methods[] = {
2157
{"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
2158
{"copy_from_face_interp", (PyCFunction)bpy_bmloop_copy_from_face_interp, METH_O, bpy_bmloop_copy_from_face_interp_doc},
2160
{"calc_angle", (PyCFunction)bpy_bmloop_calc_angle, METH_NOARGS, bpy_bmloop_calc_angle_doc},
2161
{"calc_normal", (PyCFunction)bpy_bmloop_calc_normal, METH_NOARGS, bpy_bmloop_calc_normal_doc},
2162
{"calc_tangent", (PyCFunction)bpy_bmloop_calc_tangent, METH_NOARGS, bpy_bmloop_calc_tangent_doc},
2163
{NULL, NULL, 0, NULL}
2166
static struct PyMethodDef bpy_bmelemseq_methods[] = {
2167
/* odd function, initializes index values */
2168
{"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2169
{NULL, NULL, 0, NULL}
2172
static struct PyMethodDef bpy_bmvertseq_methods[] = {
2173
{"new", (PyCFunction)bpy_bmvertseq_new, METH_VARARGS, bpy_bmvertseq_new_doc},
2174
{"remove", (PyCFunction)bpy_bmvertseq_remove, METH_O, bpy_bmvertseq_remove_doc},
2176
/* odd function, initializes index values */
2177
{"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2178
{NULL, NULL, 0, NULL}
2181
static struct PyMethodDef bpy_bmedgeseq_methods[] = {
2182
{"new", (PyCFunction)bpy_bmedgeseq_new, METH_VARARGS, bpy_bmedgeseq_new_doc},
2183
{"remove", (PyCFunction)bpy_bmedgeseq_remove, METH_O, bpy_bmedgeseq_remove_doc},
2184
/* 'bpy_bmelemseq_get' for different purpose */
2185
{"get", (PyCFunction)bpy_bmedgeseq_get__method, METH_VARARGS, bpy_bmedgeseq_get__method_doc},
2187
/* odd function, initializes index values */
2188
{"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2189
{NULL, NULL, 0, NULL}
2192
static struct PyMethodDef bpy_bmfaceseq_methods[] = {
2193
{"new", (PyCFunction)bpy_bmfaceseq_new, METH_VARARGS, bpy_bmfaceseq_new_doc},
2194
{"remove", (PyCFunction)bpy_bmfaceseq_remove, METH_O, bpy_bmfaceseq_remove_doc},
2195
/* 'bpy_bmelemseq_get' for different purpose */
2196
{"get", (PyCFunction)bpy_bmfaceseq_get__method, METH_VARARGS, bpy_bmfaceseq_get__method_doc},
2198
/* odd function, initializes index values */
2199
{"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
2200
{NULL, NULL, 0, NULL}
2203
static struct PyMethodDef bpy_bmloopseq_methods[] = {
2204
/* odd function, initializes index values */
2205
/* no: index_update() function since we cant iterate over loops */
2206
{NULL, NULL, 0, NULL}
2213
* ---------------- */
2215
static PyTypeObject *bpy_bm_itype_as_pytype(const char itype)
2217
/* should cover all types */
2218
switch ((BMIterType)itype) {
2219
case BM_VERTS_OF_MESH:
2220
case BM_VERTS_OF_FACE:
2221
case BM_VERTS_OF_EDGE:
2222
return &BPy_BMVert_Type;
2224
case BM_EDGES_OF_MESH:
2225
case BM_EDGES_OF_FACE:
2226
case BM_EDGES_OF_VERT:
2227
return &BPy_BMEdge_Type;
2229
case BM_FACES_OF_MESH:
2230
case BM_FACES_OF_EDGE:
2231
case BM_FACES_OF_VERT:
2232
return &BPy_BMFace_Type;
2234
case BM_ALL_LOOPS_OF_FACE:
2235
case BM_LOOPS_OF_FACE:
2236
case BM_LOOPS_OF_EDGE:
2237
case BM_LOOPS_OF_VERT:
2238
case BM_LOOPS_OF_LOOP:
2239
return &BPy_BMLoop_Type;
2245
static Py_ssize_t bpy_bmelemseq_length(BPy_BMElemSeq *self)
2247
BPY_BM_CHECK_INT(self);
2249
/* first check if the size is known */
2250
switch ((BMIterType)self->itype) {
2252
case BM_VERTS_OF_MESH:
2253
return self->bm->totvert;
2254
case BM_EDGES_OF_MESH:
2255
return self->bm->totedge;
2256
case BM_FACES_OF_MESH:
2257
return self->bm->totface;
2260
case BM_VERTS_OF_FACE:
2261
case BM_EDGES_OF_FACE:
2262
case BM_LOOPS_OF_FACE:
2263
BPY_BM_CHECK_INT(self->py_ele);
2264
return ((BMFace *)self->py_ele->ele)->len;
2266
case BM_VERTS_OF_EDGE:
2270
/* quiet compiler */
2275
/* loop over all items, avoid this if we can */
2281
BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
2288
static PyObject *bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
2290
BPY_BM_CHECK_OBJ(self);
2292
if (keynum < 0) keynum += bpy_bmelemseq_length(self); /* only get length on negative value, may loop entire seq */
2294
BMHeader *ele = BM_iter_at_index(self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
2296
return BPy_BMElem_CreatePyObject(self->bm, ele);
2300
PyErr_Format(PyExc_IndexError,
2301
"BMElemSeq[index]: index %d out of range", keynum);
2305
static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t start, Py_ssize_t stop)
2315
BPY_BM_CHECK_OBJ(self);
2317
list = PyList_New(0);
2319
ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
2321
BLI_assert(ok == TRUE);
2323
if (UNLIKELY(ok == FALSE)) {
2327
/* first loop up-until the start */
2328
for (ok = TRUE; ok; ok = (BM_iter_step(&iter) != NULL)) {
2329
if (count == start) {
2335
/* add items until stop */
2336
while ((ele = BM_iter_step(&iter))) {
2337
item = BPy_BMElem_CreatePyObject(self->bm, ele);
2338
PyList_Append(list, item);
2342
if (count == stop) {
2350
static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key)
2352
/* don't need error check here */
2353
if (PyIndex_Check(key)) {
2354
Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
2355
if (i == -1 && PyErr_Occurred())
2357
return bpy_bmelemseq_subscript_int(self, i);
2359
else if (PySlice_Check(key)) {
2360
PySliceObject *key_slice = (PySliceObject *)key;
2361
Py_ssize_t step = 1;
2363
if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
2366
else if (step != 1) {
2367
PyErr_SetString(PyExc_TypeError,
2368
"BMElemSeq[slice]: slice steps not supported");
2371
else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
2372
return bpy_bmelemseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
2375
Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
2377
/* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
2378
if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
2379
if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL;
2381
if (start < 0 || stop < 0) {
2382
/* only get the length for negative values */
2383
Py_ssize_t len = bpy_bmelemseq_length(self);
2384
if (start < 0) start += len;
2385
if (stop < 0) start += len;
2388
if (stop - start <= 0) {
2389
return PyList_New(0);
2392
return bpy_bmelemseq_subscript_slice(self, start, stop);
2397
PyErr_SetString(PyExc_AttributeError,
2398
"BMElemSeq[key]: invalid key, key must be an int");
2403
static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
2405
BPY_BM_CHECK_INT(self);
2407
if (Py_TYPE(value) == bpy_bm_itype_as_pytype(self->itype)) {
2408
BPy_BMElem *value_bm_ele = (BPy_BMElem *)value;
2409
if (value_bm_ele->bm == self->bm) {
2410
BMElem *ele, *ele_test = value_bm_ele->ele;
2412
BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
2413
if (ele == ele_test) {
2423
/* BMElem (customdata)
2424
* ------------------- */
2426
static PyObject *bpy_bmelem_subscript(BPy_BMElem *self, BPy_BMLayerItem *key)
2428
BPY_BM_CHECK_OBJ(self);
2430
return BPy_BMLayerItem_GetItem(self, key);
2433
static int bpy_bmelem_ass_subscript(BPy_BMElem *self, BPy_BMLayerItem *key, PyObject *value)
2435
BPY_BM_CHECK_INT(self);
2437
return BPy_BMLayerItem_SetItem(self, key, value);
2440
static PySequenceMethods bpy_bmelemseq_as_sequence = {
2441
(lenfunc)bpy_bmelemseq_length, /* sq_length */
2442
NULL, /* sq_concat */
2443
NULL, /* sq_repeat */
2444
(ssizeargfunc)bpy_bmelemseq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
2445
NULL, /* sq_slice */
2446
(ssizeobjargproc)NULL, /* sq_ass_item */
2447
NULL, /* *was* sq_ass_slice */
2448
(objobjproc)bpy_bmelemseq_contains, /* sq_contains */
2449
(binaryfunc) NULL, /* sq_inplace_concat */
2450
(ssizeargfunc) NULL, /* sq_inplace_repeat */
2453
static PyMappingMethods bpy_bmelemseq_as_mapping = {
2454
(lenfunc)bpy_bmelemseq_length, /* mp_length */
2455
(binaryfunc)bpy_bmelemseq_subscript, /* mp_subscript */
2456
(objobjargproc)NULL, /* mp_ass_subscript */
2459
/* for customdata access */
2460
static PyMappingMethods bpy_bm_elem_as_mapping = {
2461
(lenfunc)NULL, /* mp_length */ /* keep this empty, messes up 'if elem: ...' test */
2462
(binaryfunc)bpy_bmelem_subscript, /* mp_subscript */
2463
(objobjargproc)bpy_bmelem_ass_subscript, /* mp_ass_subscript */
2469
static PyObject *bpy_bmelemseq_iter(BPy_BMElemSeq *self)
2471
BPy_BMIter *py_iter;
2473
BPY_BM_CHECK_OBJ(self);
2474
py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
2475
BM_iter_init(&(py_iter->iter), self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
2476
return (PyObject *)py_iter;
2479
static PyObject *bpy_bmiter_next(BPy_BMIter *self)
2481
BMHeader *ele = BM_iter_step(&self->iter);
2483
PyErr_SetString(PyExc_StopIteration,
2484
"bpy_bmiter_next stop");
2488
return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, ele);
2493
/* Dealloc Functions
2494
* ================= */
2496
static void bpy_bmesh_dealloc(BPy_BMesh *self)
2498
BMesh *bm = self->bm;
2500
/* have have been freed by bmesh */
2502
BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2503
BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2504
BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2505
BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
2507
bm->py_handle = NULL;
2509
if ((self->flag & BPY_BMFLAG_IS_WRAPPED) == 0) {
2517
static void bpy_bmvert_dealloc(BPy_BMElem *self)
2519
BMesh *bm = self->bm;
2521
void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2527
static void bpy_bmedge_dealloc(BPy_BMElem *self)
2529
BMesh *bm = self->bm;
2531
void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2537
static void bpy_bmface_dealloc(BPy_BMElem *self)
2539
BMesh *bm = self->bm;
2541
void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2547
static void bpy_bmloop_dealloc(BPy_BMElem *self)
2549
BMesh *bm = self->bm;
2551
void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->head.data, CD_BM_ELEM_PYPTR);
2557
static void bpy_bmelemseq_dealloc(BPy_BMElemSeq *self)
2559
Py_XDECREF(self->py_ele);
2564
/* not sure where this should go */
2565
static Py_hash_t bpy_bm_elem_hash(PyObject *self)
2567
return _Py_HashPointer(((BPy_BMElem *)self)->ele);
2570
static Py_hash_t bpy_bm_hash(PyObject *self)
2572
return _Py_HashPointer(((BPy_BMesh *)self)->bm);
2576
* =============== */
2578
PyDoc_STRVAR(bpy_bmesh_doc,
2579
"The BMesh data structure\n"
2581
PyDoc_STRVAR(bpy_bmvert_doc,
2582
"The BMesh vertex type\n"
2584
PyDoc_STRVAR(bpy_bmedge_doc,
2585
"The BMesh edge connecting 2 verts\n"
2587
PyDoc_STRVAR(bpy_bmface_doc,
2588
"The BMesh face with 3 or more sides\n"
2590
PyDoc_STRVAR(bpy_bmloop_doc,
2591
"This is normally accessed from :class:`BMFace.loops` where each face corner represents a corner of a face.\n"
2593
PyDoc_STRVAR(bpy_bmelemseq_doc,
2594
"General sequence type used for accessing any sequence of \n"
2595
":class:`BMVert`, :class:`BMEdge`, :class:`BMFace`, :class:`BMLoop`.\n"
2597
"When accessed via :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces` \n"
2598
"there are also functions to create/remomove items.\n"
2600
PyDoc_STRVAR(bpy_bmiter_doc,
2601
"Internal BMesh type for looping over verts/faces/edges,\n"
2602
"used for iterating over :class:`BMElemSeq` types.\n"
2605
static PyObject *bpy_bmesh_repr(BPy_BMesh *self)
2607
BMesh *bm = self->bm;
2610
return PyUnicode_FromFormat("<BMesh(%p), totvert=%d, totedge=%d, totface=%d, totloop=%d>",
2611
bm, bm->totvert, bm->totedge, bm->totface, bm->totloop);
2614
return PyUnicode_FromFormat("<BMesh dead at %p>", self);
2618
static PyObject *bpy_bmvert_repr(BPy_BMVert *self)
2620
BMesh *bm = self->bm;
2623
BMVert *v = self->v;
2624
return PyUnicode_FromFormat("<BMVert(%p), index=%d>",
2625
v, BM_elem_index_get(v));
2628
return PyUnicode_FromFormat("<BMVert dead at %p>", self);
2632
static PyObject *bpy_bmedge_repr(BPy_BMEdge *self)
2634
BMesh *bm = self->bm;
2637
BMEdge *e = self->e;
2638
return PyUnicode_FromFormat("<BMEdge(%p), index=%d, verts=(%p/%d, %p/%d)>",
2639
e, BM_elem_index_get(e),
2640
e->v1, BM_elem_index_get(e->v1),
2641
e->v2, BM_elem_index_get(e->v2));
2644
return PyUnicode_FromFormat("<BMEdge dead at %p>", self);
2648
static PyObject *bpy_bmface_repr(BPy_BMFace *self)
2650
BMesh *bm = self->bm;
2653
BMFace *f = self->f;
2654
return PyUnicode_FromFormat("<BMFace(%p), index=%d, totverts=%d>",
2655
f, BM_elem_index_get(f),
2659
return PyUnicode_FromFormat("<BMFace dead at %p>", self);
2663
static PyObject *bpy_bmloop_repr(BPy_BMLoop *self)
2665
BMesh *bm = self->bm;
2668
BMLoop *l = self->l;
2669
return PyUnicode_FromFormat("<BMLoop(%p), index=%d, vert=%p/%d, edge=%p/%d, face=%p/%d>",
2670
l, BM_elem_index_get(l),
2671
l->v, BM_elem_index_get(l->v),
2672
l->e, BM_elem_index_get(l->e),
2673
l->f, BM_elem_index_get(l->f));
2676
return PyUnicode_FromFormat("<BMLoop dead at %p>", self);
2683
PyTypeObject BPy_BMesh_Type = {{{0}}};
2684
PyTypeObject BPy_BMVert_Type = {{{0}}};
2685
PyTypeObject BPy_BMEdge_Type = {{{0}}};
2686
PyTypeObject BPy_BMFace_Type = {{{0}}};
2687
PyTypeObject BPy_BMLoop_Type = {{{0}}};
2688
PyTypeObject BPy_BMElemSeq_Type = {{{0}}};
2689
PyTypeObject BPy_BMVertSeq_Type = {{{0}}};
2690
PyTypeObject BPy_BMEdgeSeq_Type = {{{0}}};
2691
PyTypeObject BPy_BMFaceSeq_Type = {{{0}}};
2692
PyTypeObject BPy_BMLoopSeq_Type = {{{0}}};
2693
PyTypeObject BPy_BMIter_Type = {{{0}}};
2697
void BPy_BM_init_types(void)
2699
BPy_BMesh_Type.tp_basicsize = sizeof(BPy_BMesh);
2700
BPy_BMVert_Type.tp_basicsize = sizeof(BPy_BMVert);
2701
BPy_BMEdge_Type.tp_basicsize = sizeof(BPy_BMEdge);
2702
BPy_BMFace_Type.tp_basicsize = sizeof(BPy_BMFace);
2703
BPy_BMLoop_Type.tp_basicsize = sizeof(BPy_BMLoop);
2704
BPy_BMElemSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2705
BPy_BMVertSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2706
BPy_BMEdgeSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2707
BPy_BMFaceSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2708
BPy_BMLoopSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
2709
BPy_BMIter_Type.tp_basicsize = sizeof(BPy_BMIter);
2712
BPy_BMesh_Type.tp_name = "BMesh";
2713
BPy_BMVert_Type.tp_name = "BMVert";
2714
BPy_BMEdge_Type.tp_name = "BMEdge";
2715
BPy_BMFace_Type.tp_name = "BMFace";
2716
BPy_BMLoop_Type.tp_name = "BMLoop";
2717
BPy_BMElemSeq_Type.tp_name = "BMElemSeq";
2718
BPy_BMVertSeq_Type.tp_name = "BMVertSeq";
2719
BPy_BMEdgeSeq_Type.tp_name = "BMEdgeSeq";
2720
BPy_BMFaceSeq_Type.tp_name = "BMFaceSeq";
2721
BPy_BMLoopSeq_Type.tp_name = "BMLoopSeq";
2722
BPy_BMIter_Type.tp_name = "BMIter";
2725
BPy_BMesh_Type.tp_doc = bpy_bmesh_doc;
2726
BPy_BMVert_Type.tp_doc = bpy_bmvert_doc;
2727
BPy_BMEdge_Type.tp_doc = bpy_bmedge_doc;
2728
BPy_BMFace_Type.tp_doc = bpy_bmface_doc;
2729
BPy_BMLoop_Type.tp_doc = bpy_bmloop_doc;
2730
BPy_BMElemSeq_Type.tp_doc = bpy_bmelemseq_doc;
2731
BPy_BMVertSeq_Type.tp_doc = NULL;
2732
BPy_BMEdgeSeq_Type.tp_doc = NULL;
2733
BPy_BMFaceSeq_Type.tp_doc = NULL;
2734
BPy_BMLoopSeq_Type.tp_doc = NULL;
2735
BPy_BMIter_Type.tp_doc = bpy_bmiter_doc;
2738
BPy_BMesh_Type.tp_repr = (reprfunc)bpy_bmesh_repr;
2739
BPy_BMVert_Type.tp_repr = (reprfunc)bpy_bmvert_repr;
2740
BPy_BMEdge_Type.tp_repr = (reprfunc)bpy_bmedge_repr;
2741
BPy_BMFace_Type.tp_repr = (reprfunc)bpy_bmface_repr;
2742
BPy_BMLoop_Type.tp_repr = (reprfunc)bpy_bmloop_repr;
2743
BPy_BMElemSeq_Type.tp_repr = NULL;
2744
BPy_BMVertSeq_Type.tp_repr = NULL;
2745
BPy_BMEdgeSeq_Type.tp_repr = NULL;
2746
BPy_BMFaceSeq_Type.tp_repr = NULL;
2747
BPy_BMLoopSeq_Type.tp_repr = NULL;
2748
BPy_BMIter_Type.tp_repr = NULL;
2751
BPy_BMesh_Type.tp_getset = bpy_bmesh_getseters;
2752
BPy_BMVert_Type.tp_getset = bpy_bmvert_getseters;
2753
BPy_BMEdge_Type.tp_getset = bpy_bmedge_getseters;
2754
BPy_BMFace_Type.tp_getset = bpy_bmface_getseters;
2755
BPy_BMLoop_Type.tp_getset = bpy_bmloop_getseters;
2756
BPy_BMElemSeq_Type.tp_getset = NULL;
2757
BPy_BMVertSeq_Type.tp_getset = bpy_bmvertseq_getseters;
2758
BPy_BMEdgeSeq_Type.tp_getset = bpy_bmedgeseq_getseters;
2759
BPy_BMFaceSeq_Type.tp_getset = bpy_bmfaceseq_getseters;
2760
BPy_BMLoopSeq_Type.tp_getset = bpy_bmloopseq_getseters;
2761
BPy_BMIter_Type.tp_getset = NULL;
2764
BPy_BMesh_Type.tp_methods = bpy_bmesh_methods;
2765
BPy_BMVert_Type.tp_methods = bpy_bmvert_methods;
2766
BPy_BMEdge_Type.tp_methods = bpy_bmedge_methods;
2767
BPy_BMFace_Type.tp_methods = bpy_bmface_methods;
2768
BPy_BMLoop_Type.tp_methods = bpy_bmloop_methods;
2769
BPy_BMElemSeq_Type.tp_methods = bpy_bmelemseq_methods;
2770
BPy_BMVertSeq_Type.tp_methods = bpy_bmvertseq_methods;
2771
BPy_BMEdgeSeq_Type.tp_methods = bpy_bmedgeseq_methods;
2772
BPy_BMFaceSeq_Type.tp_methods = bpy_bmfaceseq_methods;
2773
BPy_BMLoopSeq_Type.tp_methods = bpy_bmloopseq_methods;
2774
BPy_BMIter_Type.tp_methods = NULL;
2777
BPy_BMesh_Type.tp_hash = bpy_bm_hash;
2778
BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash;
2779
BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash;
2780
BPy_BMFace_Type.tp_hash = bpy_bm_elem_hash;
2781
BPy_BMLoop_Type.tp_hash = bpy_bm_elem_hash;
2782
BPy_BMElemSeq_Type.tp_hash = NULL;
2783
BPy_BMVertSeq_Type.tp_hash = NULL;
2784
BPy_BMEdgeSeq_Type.tp_hash = NULL;
2785
BPy_BMFaceSeq_Type.tp_hash = NULL;
2786
BPy_BMLoopSeq_Type.tp_hash = NULL;
2787
BPy_BMIter_Type.tp_hash = NULL;
2789
BPy_BMElemSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2790
BPy_BMVertSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2791
BPy_BMEdgeSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2792
BPy_BMFaceSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2793
BPy_BMLoopSeq_Type.tp_as_sequence = NULL; /* this is not a seq really, only for layer access */
2795
BPy_BMElemSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2796
BPy_BMVertSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2797
BPy_BMEdgeSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2798
BPy_BMFaceSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2799
BPy_BMLoopSeq_Type.tp_as_mapping = NULL; /* this is not a seq really, only for layer access */
2802
BPy_BMVert_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2803
BPy_BMEdge_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2804
BPy_BMFace_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2805
BPy_BMLoop_Type.tp_as_mapping = &bpy_bm_elem_as_mapping;
2807
BPy_BMElemSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2808
BPy_BMVertSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2809
BPy_BMEdgeSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2810
BPy_BMFaceSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2811
BPy_BMLoopSeq_Type.tp_iter = NULL; /* no mapping */
2813
/* only 1 iteratir so far */
2814
BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next;
2815
BPy_BMIter_Type.tp_iter = PyObject_SelfIter;
2817
BPy_BMesh_Type.tp_dealloc = (destructor)bpy_bmesh_dealloc;
2818
BPy_BMVert_Type.tp_dealloc = (destructor)bpy_bmvert_dealloc;
2819
BPy_BMEdge_Type.tp_dealloc = (destructor)bpy_bmedge_dealloc;
2820
BPy_BMFace_Type.tp_dealloc = (destructor)bpy_bmface_dealloc;
2821
BPy_BMLoop_Type.tp_dealloc = (destructor)bpy_bmloop_dealloc;
2822
BPy_BMElemSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2823
BPy_BMVertSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2824
BPy_BMEdgeSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2825
BPy_BMFaceSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2826
BPy_BMLoopSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2827
BPy_BMIter_Type.tp_dealloc = NULL;
2829
BPy_BMesh_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2830
BPy_BMVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2831
BPy_BMEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2832
BPy_BMFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2833
BPy_BMLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2834
BPy_BMElemSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2835
BPy_BMVertSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2836
BPy_BMEdgeSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2837
BPy_BMFaceSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2838
BPy_BMLoopSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2839
BPy_BMIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2842
PyType_Ready(&BPy_BMesh_Type);
2843
PyType_Ready(&BPy_BMVert_Type);
2844
PyType_Ready(&BPy_BMEdge_Type);
2845
PyType_Ready(&BPy_BMFace_Type);
2846
PyType_Ready(&BPy_BMLoop_Type);
2847
PyType_Ready(&BPy_BMElemSeq_Type);
2848
PyType_Ready(&BPy_BMVertSeq_Type);
2849
PyType_Ready(&BPy_BMEdgeSeq_Type);
2850
PyType_Ready(&BPy_BMFaceSeq_Type);
2851
PyType_Ready(&BPy_BMLoopSeq_Type);
2852
PyType_Ready(&BPy_BMIter_Type);
2855
/* bmesh.types submodule
2856
* ********************* */
2858
static struct PyModuleDef BPy_BM_types_module_def = {
2859
PyModuleDef_HEAD_INIT,
2860
"bmesh.types", /* m_name */
2863
NULL, /* m_methods */
2864
NULL, /* m_reload */
2865
NULL, /* m_traverse */
2870
PyObject *BPyInit_bmesh_types(void)
2872
PyObject *submodule;
2874
submodule = PyModule_Create(&BPy_BM_types_module_def);
2876
#define MODULE_TYPE_ADD(s, t) \
2877
PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
2879
/* bmesh_py_types.c */
2880
MODULE_TYPE_ADD(submodule, BPy_BMesh_Type);
2881
MODULE_TYPE_ADD(submodule, BPy_BMVert_Type);
2882
MODULE_TYPE_ADD(submodule, BPy_BMEdge_Type);
2883
MODULE_TYPE_ADD(submodule, BPy_BMFace_Type);
2884
MODULE_TYPE_ADD(submodule, BPy_BMLoop_Type);
2885
MODULE_TYPE_ADD(submodule, BPy_BMElemSeq_Type);
2886
MODULE_TYPE_ADD(submodule, BPy_BMVertSeq_Type);
2887
MODULE_TYPE_ADD(submodule, BPy_BMEdgeSeq_Type);
2888
MODULE_TYPE_ADD(submodule, BPy_BMFaceSeq_Type);
2889
MODULE_TYPE_ADD(submodule, BPy_BMLoopSeq_Type);
2890
MODULE_TYPE_ADD(submodule, BPy_BMIter_Type);
2891
/* bmesh_py_types_select.c */
2892
MODULE_TYPE_ADD(submodule, BPy_BMEditSelSeq_Type);
2893
MODULE_TYPE_ADD(submodule, BPy_BMEditSelIter_Type);
2894
/* bmesh_py_types_customdata.c */
2895
MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessVert_Type);
2896
MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessEdge_Type);
2897
MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessFace_Type);
2898
MODULE_TYPE_ADD(submodule, BPy_BMLayerAccessLoop_Type);
2899
MODULE_TYPE_ADD(submodule, BPy_BMLayerCollection_Type);
2900
MODULE_TYPE_ADD(submodule, BPy_BMLayerItem_Type);
2901
/* bmesh_py_types_meshdata.c */
2902
MODULE_TYPE_ADD(submodule, BPy_BMLoopUV_Type);
2903
MODULE_TYPE_ADD(submodule, BPy_BMDeformVert_Type);
2905
#undef MODULE_TYPE_ADD
2910
/* Utility Functions
2911
* ***************** */
2913
PyObject *BPy_BMesh_CreatePyObject(BMesh *bm, int flag)
2917
if (bm->py_handle) {
2918
self = bm->py_handle;
2922
self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
2926
bm->py_handle = self; /* point back */
2928
BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2929
BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2930
BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2931
BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
2934
return (PyObject *)self;
2939
PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
2943
void **ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
2945
/* bmesh may free layers, ensure we have one to store ourself */
2946
if (UNLIKELY(ptr == NULL)) {
2947
BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2948
ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
2956
self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type);
2957
BLI_assert(v != NULL);
2962
return (PyObject *)self;
2965
PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
2969
void **ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
2971
/* bmesh may free layers, ensure we have one to store ourself */
2972
if (UNLIKELY(ptr == NULL)) {
2973
BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2974
ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
2982
self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type);
2983
BLI_assert(e != NULL);
2988
return (PyObject *)self;
2991
PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
2995
void **ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
2997
/* bmesh may free layers, ensure we have one to store ourself */
2998
if (UNLIKELY(ptr == NULL)) {
2999
BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
3000
ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
3008
self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type);
3009
BLI_assert(f != NULL);
3014
return (PyObject *)self;
3017
PyObject *BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
3021
void **ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
3023
/* bmesh may free layers, ensure we have one to store ourself */
3024
if (UNLIKELY(ptr == NULL)) {
3025
BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
3026
ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
3034
self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type);
3035
BLI_assert(l != NULL);
3040
return (PyObject *)self;
3043
PyObject *BPy_BMElemSeq_CreatePyObject(BMesh *bm, BPy_BMElem *py_ele, const char itype)
3045
BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMElemSeq_Type);
3047
self->py_ele = py_ele; /* can be NULL */
3048
self->itype = itype;
3050
return (PyObject *)self;
3053
PyObject *BPy_BMVertSeq_CreatePyObject(BMesh *bm)
3055
BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMVertSeq_Type);
3057
self->py_ele = NULL; /* unused */
3058
self->itype = BM_VERTS_OF_MESH;
3059
return (PyObject *)self;
3062
PyObject *BPy_BMEdgeSeq_CreatePyObject(BMesh *bm)
3064
BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMEdgeSeq_Type);
3066
self->py_ele = NULL; /* unused */
3067
self->itype = BM_EDGES_OF_MESH;
3068
return (PyObject *)self;
3071
PyObject *BPy_BMFaceSeq_CreatePyObject(BMesh *bm)
3073
BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMFaceSeq_Type);
3075
self->py_ele = NULL; /* unused */
3076
self->itype = BM_FACES_OF_MESH;
3077
return (PyObject *)self;
3080
PyObject *BPy_BMLoopSeq_CreatePyObject(BMesh *bm)
3082
BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMLoopSeq_Type);
3084
self->py_ele = NULL; /* unused */
3085
self->itype = 0; /* should never be passed to the iterator function */
3086
return (PyObject *)self;
3089
PyObject *BPy_BMIter_CreatePyObject(BMesh *bm)
3091
BPy_BMIter *self = PyObject_New(BPy_BMIter, &BPy_BMIter_Type);
3093
/* caller must initialize 'iter' member */
3094
return (PyObject *)self;
3097
/* this is just a helper func */
3098
PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele)
3100
switch (ele->htype) {
3102
return BPy_BMVert_CreatePyObject(bm, (BMVert *)ele);
3104
return BPy_BMEdge_CreatePyObject(bm, (BMEdge *)ele);
3106
return BPy_BMFace_CreatePyObject(bm, (BMFace *)ele);
3108
return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele);
3110
PyErr_SetString(PyExc_SystemError, "internal error");
3115
int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
3117
if (LIKELY(self->bm)) {
3121
PyErr_Format(PyExc_ReferenceError,
3122
"BMesh data of type %.200s has been removed",
3123
Py_TYPE(self)->tp_name);
3128
void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
3133
/* generic python seq as BMVert/Edge/Face array,
3134
* return value must be freed with PyMem_FREE(...);
3136
* The 'bm_r' value is assigned when empty, and used when set.
3138
void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
3140
const char do_unique_check, const char do_bm_check,
3141
const char *error_prefix)
3143
BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
3147
if (!(seq_fast = PySequence_Fast(seq, error_prefix))) {
3157
seq_len = PySequence_Fast_GET_SIZE(seq_fast);
3159
if (seq_len < min || seq_len > max) {
3160
PyErr_Format(PyExc_TypeError,
3161
"%s: sequence incorrect size, expected [%d - %d], given %d",
3162
error_prefix, min, max, seq_len);
3167
/* from now on, use goto */
3168
alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
3170
for (i = 0; i < seq_len; i++) {
3171
item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i);
3173
if (!BPy_BMElem_CheckHType(Py_TYPE(item), htype)) {
3174
PyErr_Format(PyExc_TypeError,
3175
"%s: expected %.200s, not '%.200s'",
3176
error_prefix, BPy_BMElem_StringFromHType(htype), Py_TYPE(item)->tp_name);
3179
else if (!BPY_BM_IS_VALID(item)) {
3180
PyErr_Format(PyExc_TypeError,
3181
"%s: %d %s has been removed",
3182
error_prefix, i, Py_TYPE(item)->tp_name);
3185
/* trick so we can ensure all items have the same mesh,
3186
* and allows us to pass the 'bm' as NULL. */
3187
else if (do_bm_check && (bm && bm != item->bm)) {
3188
PyErr_Format(PyExc_ValueError,
3189
"%s: %d %s is from another mesh",
3190
error_prefix, i, BPy_BMElem_StringFromHType(htype));
3198
alloc[i] = item->ele;
3200
if (do_unique_check) {
3201
BM_elem_flag_enable(item->ele, BM_ELEM_INTERNAL_TAG);
3205
if (do_unique_check) {
3206
/* check for double verts! */
3208
for (i = 0; i < seq_len; i++) {
3209
if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_INTERNAL_TAG) == FALSE)) {
3213
/* ensure we don't leave this enabled */
3214
BM_elem_flag_disable(alloc[i], BM_ELEM_INTERNAL_TAG);
3218
PyErr_Format(PyExc_ValueError,
3219
"%s: found the same %.200s used multiple times",
3220
error_prefix, BPy_BMElem_StringFromHType(htype));
3225
Py_DECREF(seq_fast);
3227
if (r_bm) *r_bm = bm;
3231
Py_DECREF(seq_fast);
3238
PyObject *BPy_BMElem_Array_As_Tuple(BMesh *bm, BMHeader **elem, Py_ssize_t elem_len)
3241
PyObject *ret = PyTuple_New(elem_len);
3242
for (i = 0; i < elem_len; i++) {
3243
PyTuple_SET_ITEM(ret, i, BPy_BMElem_CreatePyObject(bm, elem[i]));
3249
int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype)
3251
return (((htype & BM_VERT) && (type == &BPy_BMVert_Type)) ||
3252
((htype & BM_EDGE) && (type == &BPy_BMEdge_Type)) ||
3253
((htype & BM_FACE) && (type == &BPy_BMFace_Type)) ||
3254
((htype & BM_LOOP) && (type == &BPy_BMLoop_Type)));
3258
* Use for error strings only, not thread safe,
3260
* \return a sting like '(BMVert/BMEdge/BMFace/BMLoop)'
3262
char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32])
3264
/* zero to ensure string is always NULL terminated */
3265
char *ret_ptr = ret;
3266
if (htype & BM_VERT) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMVert_Type.tp_name);
3267
if (htype & BM_EDGE) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMEdge_Type.tp_name);
3268
if (htype & BM_FACE) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMFace_Type.tp_name);
3269
if (htype & BM_LOOP) ret_ptr += sprintf(ret_ptr, "/%s", BPy_BMLoop_Type.tp_name);
3274
char *BPy_BMElem_StringFromHType(const char htype)
3276
/* zero to ensure string is always NULL terminated */
3277
static char ret[32];
3278
return BPy_BMElem_StringFromHType_ex(htype, ret);