bmesh api cleanup
[blender-staging.git] / source / blender / python / bmesh / bmesh_py_types.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Campbell Barton
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/python/bmesh/bmesh_py_types.c
27  *  \ingroup pybmesh
28  */
29
30 #include <Python.h>
31
32 #include "BLI_math.h"
33
34 #include "BKE_customdata.h"
35
36 #include "bmesh.h"
37
38 #include "../mathutils/mathutils.h"
39
40 #include "../generic/py_capi_utils.h"
41
42 #include "bmesh_py_types.h" /* own include */
43
44 /* Common Flags
45  * ************ */
46
47 /* scene does not use BM_* flags. */
48 PyC_FlagSet bpy_bm_scene_vert_edge_face_flags[] = {
49     {1, "VERT"},
50     {2, "EDGE"},
51     {4, "FACE"},
52     {0, NULL}
53 };
54
55 PyC_FlagSet bpy_bm_htype_vert_edge_face_flags[] = {
56     {BM_VERT, "VERT"},
57     {BM_EDGE, "EDGE"},
58     {BM_FACE, "FACE"},
59     {0, NULL}
60 };
61
62 PyC_FlagSet bpy_bm_htype_all_flags[] = {
63     {BM_VERT, "VERT"},
64     {BM_LOOP, "EDGE"},
65     {BM_FACE, "FACE"},
66     {BM_LOOP, "LOOP"},
67     {0, NULL}
68 };
69
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"},
75     {BM_ELEM_TAG,     "TAG"},
76     {0, NULL}
77 };
78
79 /* py-type definitions
80  * ******************* */
81
82 /* getseters
83  * ========= */
84
85
86 /* bmesh elems
87  * ----------- */
88
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");
93
94
95 static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
96 {
97         const char hflag = (char)GET_INT_FROM_POINTER(flag);
98
99         BPY_BM_CHECK_OBJ(self);
100
101         return PyBool_FromLong(BM_elem_flag_test(self->ele, hflag));
102 }
103
104 static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
105 {
106         const char hflag = (char)GET_INT_FROM_POINTER(flag);
107         int param;
108
109         BPY_BM_CHECK_INT(self);
110
111         param = PyLong_AsLong(value);
112
113         if (param == TRUE) {
114                 BM_elem_flag_enable(self->ele, hflag);
115                 return 0;
116         }
117         else if (param == FALSE) {
118                 BM_elem_flag_disable(self->ele, hflag);
119                 return 0;
120         }
121         else {
122                 PyErr_Format(PyExc_TypeError,
123                              "expected True/False or 0/1, not %.200s",
124                              Py_TYPE(value)->tp_name);
125                 return -1;
126         }
127 }
128
129
130 PyDoc_STRVAR(bpy_bm_elem_index_doc,
131 "Index of this element.\n"
132 "\n"
133 ":type: int\n"
134 "\n"
135 ".. note::\n"
136 "\n"
137 "   This value is not necessarily valid, while editing the mesh it can become *dirty*.\n"
138 "\n"
139 "   It's also possible to assign any number to this attribute for a scripts internal logic.\n"
140 "\n"
141 "   To ensure the value is up to date - see :class:`BMElemSeq.index_update`.\n"
142 );
143 static PyObject *bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
144 {
145         BPY_BM_CHECK_OBJ(self);
146
147         return PyLong_FromLong(BM_elem_index_get(self->ele));
148 }
149
150 static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
151 {
152         int param;
153
154         BPY_BM_CHECK_INT(self);
155
156         param = PyLong_AsLong(value);
157
158         if (param == -1 && PyErr_Occurred()) {
159                 PyErr_SetString(PyExc_TypeError,
160                                 "expected an int type");
161                 return -1;
162         }
163         else {
164                 BM_elem_index_set(self->ele, param); /* set_dirty! */
165
166                 /* when setting the index assume its set invalid */
167                 if (self->ele->head.htype & (BM_VERT | BM_EDGE | BM_FACE)) {
168                         self->bm->elem_index_dirty |= self->ele->head.htype;
169                 }
170
171                 return 0;
172         }
173 }
174
175 /* type spesific get/sets
176  * ---------------------- */
177
178
179 /* Mesh
180  * ^^^^ */
181
182 /* doc-strings for all uses of this funcion */
183 PyDoc_STRVAR(bpy_bmesh_verts_doc,
184 "This meshes vert sequence (read-only).\n\n:type: :class:`BMElemSeq`"
185 );
186 PyDoc_STRVAR(bpy_bmesh_edges_doc,
187 "This meshes edge sequence (read-only).\n\n:type: :class:`BMElemSeq`"
188 );
189 PyDoc_STRVAR(bpy_bmesh_faces_doc,
190 "This meshes face sequence (read-only).\n\n:type: :class:`BMElemSeq`"
191 );
192
193 static PyObject *bpy_bmelemseq_get(BPy_BMesh *self, void *itype)
194 {
195         BPY_BM_CHECK_OBJ(self);
196         return BPy_BMElemSeq_CreatePyObject(self->bm, NULL, GET_INT_FROM_POINTER(itype));
197 }
198
199
200 /* vert */
201 PyDoc_STRVAR(bpy_bmvert_link_edges_doc,
202 "Edges connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
203 );
204 PyDoc_STRVAR(bpy_bmvert_link_faces_doc,
205 "Faces connected to this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
206 );
207 PyDoc_STRVAR(bpy_bmvert_link_loops_doc,
208 "Loops that use this vertex (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
209 );
210 /* edge */
211 PyDoc_STRVAR(bpy_bmedge_verts_doc,
212 "Verts this edge uses (always 2), (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
213 );
214 PyDoc_STRVAR(bpy_bmedge_link_faces_doc,
215 "Faces connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMFace`"
216 );
217 PyDoc_STRVAR(bpy_bmedge_link_loops_doc,
218 "Loops connected to this edge, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
219 );
220 /* face */
221 PyDoc_STRVAR(bpy_bmface_verts_doc,
222 "Verts of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMVert`"
223 );
224 PyDoc_STRVAR(bpy_bmface_edges_doc,
225 "Edges of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMEdge`"
226 );
227 PyDoc_STRVAR(bpy_bmface_loops_doc,
228 "Loops of this face, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
229 );
230 /* loop */
231 PyDoc_STRVAR(bpy_bmloops_link_loops_doc,
232 "Loops connected to this loop, (read-only).\n\n:type: :class:`BMElemSeq` of :class:`BMLoop`"
233 );
234
235 static PyObject *bpy_bmelemseq_elem_get(BPy_BMElem *self, void *itype)
236 {
237         BPY_BM_CHECK_OBJ(self);
238         return BPy_BMElemSeq_CreatePyObject(self->bm, self, GET_INT_FROM_POINTER(itype));
239 }
240
241
242 PyDoc_STRVAR(bpy_bm_is_valid_doc,
243 "True when this element is valid (hasn't been removed).\n\n:type: boolean"
244 );
245 static PyObject *bpy_bm_is_valid_get(BPy_BMGeneric *self)
246 {
247         return PyBool_FromLong(self->bm != NULL);
248 }
249
250
251 PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
252 "The selection mode, values can be {'VERT', 'EDGE', 'FACE'}, can't be assigned an empty set.\n\n:type: set"
253 );
254 static PyObject *bpy_bmesh_select_mode_get(BPy_BMesh *self)
255 {
256         BPY_BM_CHECK_OBJ(self);
257
258         return PyC_FlagSet_FromBitfield(bpy_bm_scene_vert_edge_face_flags, self->bm->selectmode);
259 }
260
261 static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
262 {
263         int flag = 0;
264         BPY_BM_CHECK_INT(self);
265
266         if (PyC_FlagSet_ToBitfield(bpy_bm_scene_vert_edge_face_flags, value, &flag, "bm.select_mode") == -1) {
267                 return -1;
268         }
269         else if (flag == 0) {
270                 PyErr_SetString(PyExc_TypeError,
271                                 "bm.select_mode: cant assignt an empty value");
272                 return -1;
273         }
274         else {
275                 self->bm->selectmode = flag;
276                 return 0;
277         }
278 }
279
280
281 /* Vert
282  * ^^^^ */
283
284 PyDoc_STRVAR(bpy_bmvert_co_doc,
285 "The coordinates for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
286 );
287 static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
288 {
289         BPY_BM_CHECK_OBJ(self);
290         return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
291 }
292
293 static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
294 {
295         BPY_BM_CHECK_INT(self);
296
297         if (mathutils_array_parse(self->v->co, 3, 3, value, "BMVert.co") != -1) {
298                 return 0;
299         }
300         else {
301                 return -1;
302         }
303 }
304
305
306 PyDoc_STRVAR(bpy_bmvert_normal_doc,
307 "The normal for this vertex as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
308 );
309 static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
310 {
311         BPY_BM_CHECK_OBJ(self);
312         return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
313 }
314
315 static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
316 {
317         BPY_BM_CHECK_INT(self);
318
319         if (mathutils_array_parse(self->v->no, 3, 3, value, "BMVert.normal") != -1) {
320                 return 0;
321         }
322         else {
323                 return -1;
324         }
325 }
326
327
328 PyDoc_STRVAR(bpy_bmvert_is_manifold_doc,
329 "True when this vertex is manifold (read-only).\n\n:type: boolean"
330 );
331 static PyObject *bpy_bmvert_is_manifold_get(BPy_BMVert *self)
332 {
333         BPY_BM_CHECK_OBJ(self);
334         return PyBool_FromLong(BM_vert_is_manifold(self->bm, self->v));
335 }
336
337
338 PyDoc_STRVAR(bpy_bmvert_is_wire_doc,
339 "True when this vertex is not connected to any faces (read-only).\n\n:type: boolean"
340 );
341 static PyObject *bpy_bmvert_is_wire_get(BPy_BMVert *self)
342 {
343         BPY_BM_CHECK_OBJ(self);
344         return PyBool_FromLong(BM_vert_is_wire(self->bm, self->v));
345 }
346
347
348 /* Edge
349  * ^^^^ */
350
351 PyDoc_STRVAR(bpy_bmedge_is_manifold_doc,
352 "True when this edge is manifold (read-only).\n\n:type: boolean"
353 );
354 static PyObject *bpy_bmedge_is_manifold_get(BPy_BMEdge *self)
355 {
356         BPY_BM_CHECK_OBJ(self);
357         return PyBool_FromLong(BM_edge_is_manifold(self->bm, self->e));
358 }
359
360
361 PyDoc_STRVAR(bpy_bmedge_is_wire_doc,
362 "True when this edge is not connected to any faces (read-only).\n\n:type: boolean"
363 );
364 static PyObject *bpy_bmedge_is_wire_get(BPy_BMEdge *self)
365 {
366         BPY_BM_CHECK_OBJ(self);
367         return PyBool_FromLong(BM_edge_is_wire(self->bm, self->e));
368 }
369
370
371 PyDoc_STRVAR(bpy_bmedge_is_boundary_doc,
372 "True when this edge is at the boundary of a face (read-only).\n\n:type: boolean"
373 );
374 static PyObject *bpy_bmedge_is_boundary_get(BPy_BMEdge *self)
375 {
376         BPY_BM_CHECK_OBJ(self);
377         return PyBool_FromLong(BM_edge_is_boundary(self->e));
378 }
379
380
381 /* Face
382  * ^^^^ */
383
384 PyDoc_STRVAR(bpy_bmface_normal_doc,
385 "The normal for this face as a 3D, wrapped vector.\n\n:type: :class:`mathutils.Vector`"
386 );
387 static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
388 {
389         BPY_BM_CHECK_OBJ(self);
390         return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
391 }
392
393 static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
394 {
395         BPY_BM_CHECK_INT(self);
396
397         if (mathutils_array_parse(self->f->no, 3, 3, value, "BMFace.normal") != -1) {
398                 return 0;
399         }
400         else {
401                 return -1;
402         }
403 }
404
405 static PyGetSetDef bpy_bmesh_getseters[] = {
406     {(char *)"verts", (getter)bpy_bmelemseq_get, (setter)NULL, (char *)bpy_bmesh_verts_doc, (void *)BM_VERTS_OF_MESH},
407     {(char *)"edges", (getter)bpy_bmelemseq_get, (setter)NULL, (char *)bpy_bmesh_edges_doc, (void *)BM_EDGES_OF_MESH},
408     {(char *)"faces", (getter)bpy_bmelemseq_get, (setter)NULL, (char *)bpy_bmesh_faces_doc, (void *)BM_FACES_OF_MESH},
409     {(char *)"select_mode", (getter)bpy_bmesh_select_mode_get, (setter)bpy_bmesh_select_mode_set, (char *)bpy_bmesh_select_mode_doc, NULL},
410
411     /* readonly checks */
412     {(char *)"is_valid",   (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
413
414     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
415 };
416
417 static PyGetSetDef bpy_bmvert_getseters[] = {
418     /* generic */
419     {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
420     {(char *)"hide",   (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc,   (void *)BM_ELEM_SELECT},
421     {(char *)"tag",    (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc,    (void *)BM_ELEM_TAG},
422     {(char *)"index",  (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc,  NULL},
423
424     {(char *)"co",     (getter)bpy_bmvert_co_get,     (setter)bpy_bmvert_co_set,     (char *)bpy_bmvert_co_doc, NULL},
425     {(char *)"normal", (getter)bpy_bmvert_normal_get, (setter)bpy_bmvert_normal_set, (char *)bpy_bmvert_normal_doc, NULL},
426
427     /* connectivity data */
428     {(char *)"link_edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_edges_doc, (void *)BM_EDGES_OF_VERT},
429     {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_faces_doc, (void *)BM_FACES_OF_VERT},
430     {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmvert_link_loops_doc, (void *)BM_LOOPS_OF_VERT},
431
432     /* readonly checks */
433     {(char *)"is_manifold",  (getter)bpy_bmvert_is_manifold_get,  (setter)NULL, (char *)bpy_bmvert_is_manifold_doc, NULL},
434     {(char *)"is_wire",      (getter)bpy_bmvert_is_wire_get,      (setter)NULL, (char *)bpy_bmvert_is_wire_doc, NULL},
435     {(char *)"is_valid",     (getter)bpy_bm_is_valid_get,         (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
436
437     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
438 };
439
440 static PyGetSetDef bpy_bmedge_getseters[] = {
441     /* generic */
442     {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
443     {(char *)"hide",   (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc,   (void *)BM_ELEM_SELECT},
444     {(char *)"tag",    (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc,    (void *)BM_ELEM_TAG},
445     {(char *)"index",  (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc,  NULL},
446
447     {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
448     {(char *)"seam",   (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SEAM},
449
450     /* connectivity data */
451     {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_verts_doc, (void *)BM_VERTS_OF_EDGE},
452
453     {(char *)"link_faces", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_faces_doc, (void *)BM_FACES_OF_EDGE},
454     {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmedge_link_loops_doc, (void *)BM_LOOPS_OF_EDGE},
455
456     /* readonly checks */
457     {(char *)"is_manifold",  (getter)bpy_bmedge_is_manifold_get,  (setter)NULL, (char *)bpy_bmedge_is_manifold_doc, NULL},
458     {(char *)"is_wire",      (getter)bpy_bmedge_is_wire_get,      (setter)NULL, (char *)bpy_bmedge_is_wire_doc, NULL},
459     {(char *)"is_boundary",   (getter)bpy_bmedge_is_boundary_get,   (setter)NULL, (char *)bpy_bmedge_is_boundary_doc, NULL},
460     {(char *)"is_valid",     (getter)bpy_bm_is_valid_get,         (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
461
462     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
463 };
464
465 static PyGetSetDef bpy_bmface_getseters[] = {
466     /* generic */
467     {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
468     {(char *)"hide",   (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc,   (void *)BM_ELEM_SELECT},
469     {(char *)"tag",    (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc,    (void *)BM_ELEM_TAG},
470     {(char *)"index",  (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc,  NULL},
471
472     {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
473
474     {(char *)"normal", (getter)bpy_bmface_normal_get, (setter)bpy_bmface_normal_set, (char *)bpy_bmface_normal_doc, NULL},
475
476     /* connectivity data */
477     {(char *)"verts", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_verts_doc, (void *)BM_VERTS_OF_FACE},
478     {(char *)"edges", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_edges_doc, (void *)BM_EDGES_OF_FACE},
479     {(char *)"loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmface_loops_doc, (void *)BM_LOOPS_OF_FACE},
480
481     /* readonly checks */
482     {(char *)"is_valid",   (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
483
484     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
485 };
486
487 static PyGetSetDef bpy_bmloop_getseters[] = {
488     /* generic */
489     // flags are available but not used for loops.
490     // {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
491     // {(char *)"hide",   (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc,   (void *)BM_ELEM_SELECT},
492     {(char *)"tag",    (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc,    (void *)BM_ELEM_TAG},
493     {(char *)"index",  (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc,  NULL},
494
495     /* connectivity data */
496     {(char *)"link_loops", (getter)bpy_bmelemseq_elem_get, (setter)NULL, (char *)bpy_bmloops_link_loops_doc, (void *)BM_LOOPS_OF_LOOP},
497
498     /* readonly checks */
499     {(char *)"is_valid",   (getter)bpy_bm_is_valid_get, (setter)NULL, (char *)bpy_bm_is_valid_doc, NULL},
500
501     {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
502 };
503
504
505 /* Methods
506  * ======= */
507
508
509 /* Mesh
510  * ---- */
511
512 PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc,
513 ".. method:: select_flush_mode()\n"
514 "\n"
515 "   flush selection based on the current mode current :class:`BMesh.select_mode`.\n"
516 );
517 static PyObject *bpy_bmesh_select_flush_mode(BPy_BMesh *self)
518 {
519         BPY_BM_CHECK_OBJ(self);
520
521         BM_mesh_select_mode_flush(self->bm);
522
523         Py_RETURN_NONE;
524 }
525
526
527 PyDoc_STRVAR(bpy_bmesh_select_flush_doc,
528 ".. method:: select_flush(select)\n"
529 "\n"
530 "   Flush selection, independent of the current selection mode.\n"
531 "\n"
532 "   :arg select: flush selection or de-selected elements.\n"
533 "   :type select: boolean\n"
534 );
535 static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
536 {
537         int param;
538
539         BPY_BM_CHECK_OBJ(self);
540
541         param = PyLong_AsLong(value);
542         if (param != FALSE && param != TRUE) {
543                 PyErr_SetString(PyExc_TypeError,
544                                 "expected a boolean type 0/1");
545                 return NULL;
546         }
547
548         if (param)  BM_mesh_select_flush(self->bm);
549         else        BM_mesh_deselect_flush(self->bm);
550
551         Py_RETURN_NONE;
552 }
553
554
555 PyDoc_STRVAR(bpy_bmesh_normal_update_doc,
556 ".. method:: normal_update(skip_hidden=False)\n"
557 "\n"
558 "   Update mesh normals.\n"
559 "\n"
560 "   :arg skip_hidden: When True hidden elements are ignored.\n"
561 "   :type skip_hidden: boolean\n"
562 );
563 static PyObject *bpy_bmesh_normal_update(BPy_BMesh *self, PyObject *args)
564 {
565
566         int skip_hidden = FALSE;
567
568         BPY_BM_CHECK_OBJ(self);
569
570         if (!PyArg_ParseTuple(args, "|i:normal_update", &skip_hidden)) {
571                 return NULL;
572         }
573
574         BM_mesh_normals_update(self->bm, skip_hidden);
575
576         Py_RETURN_NONE;
577 }
578
579
580 PyDoc_STRVAR(bpy_bmesh_transform_doc,
581 ".. method:: transform(matrix, filter=None)\n"
582 "\n"
583 "   Transform the mesh (optionally filtering flagged data only).\n"
584 "\n"
585 "   :arg matrix: transform matrix.\n"
586 "   :type matrix: 4x4 :class:`mathutils.Matrix`\n"
587 "   :arg filter: set of values in ('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG').\n"
588 "   :type filter: set\n"
589 );
590 static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
591 {
592         static const char *kwlist[] = {"matrix", "filter", NULL};
593
594         MatrixObject *mat;
595         PyObject *filter = NULL;
596         int filter_flags = 0;
597
598         BPY_BM_CHECK_OBJ(self);
599
600         if (!PyArg_ParseTupleAndKeywords(args, kw,
601                                          "O!|O!:transform",
602                                          (char **)kwlist,
603                                          &matrix_Type, &mat,
604                                          &PySet_Type,  &filter))
605         {
606                 return NULL;
607         }
608         else {
609                 BMVert *eve;
610                 BMIter iter;
611                 void *mat_ptr;
612
613                 if (BaseMath_ReadCallback(mat) == -1) {
614                         return NULL;
615                 }
616                 else if (mat->num_col != 4 || mat->num_row != 4) {
617                         PyErr_SetString(PyExc_ValueError,
618                                         "expected a 4x4 matrix");
619                         return NULL;
620                 }
621
622                 if (filter != NULL && PyC_FlagSet_ToBitfield(bpy_bm_hflag_all_flags, filter,
623                                                              &filter_flags, "bm.transform") == -1)
624                 {
625                         return NULL;
626                 }
627
628                 mat_ptr = mat->matrix;
629
630                 if (!filter_flags) {
631                         BM_ITER(eve, &iter, self->bm, BM_VERTS_OF_MESH, NULL) {
632                                 mul_m4_v3((float (*)[4])mat_ptr, eve->co);
633                         }
634                 }
635                 else {
636                         char filter_flags_ch = (char)filter_flags;
637                         BM_ITER(eve, &iter, self->bm, BM_VERTS_OF_MESH, NULL) {
638                                 if (eve->head.hflag & filter_flags_ch) {
639                                         mul_m4_v3((float (*)[4])mat_ptr, eve->co);
640                                 }
641                         }
642                 }
643         }
644
645         Py_RETURN_NONE;
646 }
647
648
649 /* Elem
650  * ---- */
651
652 PyDoc_STRVAR(bpy_bm_elem_select_set_doc,
653 ".. method:: select_set(select)\n"
654 "\n"
655 "   Set the selection.\n"
656 "   This is different from the *select* attribute because it updates the selection state of assosiated geometry.\n"
657 "\n"
658 "   :arg select: Select or de-select.\n"
659 "   :type select: boolean\n"
660 );
661 static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
662 {
663         int param;
664
665         BPY_BM_CHECK_OBJ(self);
666
667         param = PyLong_AsLong(value);
668         if (param != FALSE && param != TRUE) {
669                 PyErr_SetString(PyExc_TypeError,
670                                 "expected a boolean type 0/1");
671                 return NULL;
672         }
673
674         BM_elem_select_set(self->bm, self->ele, param);
675
676         Py_RETURN_NONE;
677 }
678
679
680 PyDoc_STRVAR(bpy_bm_elem_copy_from_doc,
681 ".. method:: copy_from(other)\n"
682 "\n"
683 "   Copy values from another element of matching type.\n"
684 );
685 static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
686 {
687         BPY_BM_CHECK_OBJ(self);
688
689         if (Py_TYPE(self) != Py_TYPE(value)) {
690                 PyErr_Format(PyExc_TypeError,
691                              "expected element of type '%.200s' not '%.200s'",
692                              Py_TYPE(self)->tp_name, Py_TYPE(value)->tp_name);
693                 return NULL;
694         }
695
696         if (value->ele != self->ele) {
697                 BM_elem_attrs_copy(value->bm, self->bm, value->ele, self->ele);
698         }
699
700         Py_RETURN_NONE;
701 }
702
703
704 /* Vert
705  * ---- */
706
707 PyDoc_STRVAR(bpy_bmvert_calc_edge_angle_doc,
708 ".. method:: calc_edge_angle()\n"
709 "\n"
710 "   Return the angle between 2 connected edges.\n"
711 "\n"
712 "   :return: The angle between both edges in radians.\n"
713 "   :rtype: float\n"
714 );
715 static PyObject *bpy_bmvert_calc_edge_angle(BPy_BMVert *self)
716 {
717         BPY_BM_CHECK_OBJ(self);
718         return PyFloat_FromDouble(BM_vert_edge_angle(self->bm, self->v));
719 }
720
721
722 PyDoc_STRVAR(bpy_bmvert_normal_update_doc,
723 ".. method:: normal_update()\n"
724 "\n"
725 "   Update vertex normal.\n"
726 );
727 static PyObject *bpy_bmvert_normal_update(BPy_BMVert *self)
728 {
729         BPY_BM_CHECK_OBJ(self);
730
731         BM_vert_normal_update(self->bm, self->v);
732
733         Py_RETURN_NONE;
734 }
735
736
737 /* Edge
738  * ---- */
739
740 PyDoc_STRVAR(bpy_bmedge_calc_face_angle_doc,
741 ".. method:: calc_face_angle()\n"
742 "\n"
743 "   Return the angle between 2 connected faces.\n"
744 "\n"
745 "   :return: The angle between both faces in radians.\n"
746 "   :rtype: float\n"
747 );
748 static PyObject *bpy_bmedge_calc_face_angle(BPy_BMEdge *self)
749 {
750         BPY_BM_CHECK_OBJ(self);
751         return PyFloat_FromDouble(BM_edge_face_angle(self->bm, self->e));
752 }
753
754
755 PyDoc_STRVAR(bpy_bmedge_other_vert_doc,
756 ".. method:: other_vert(vert)\n"
757 "\n"
758 "   Return the other vertex on this edge or None if the vertex is not used by this edge.\n"
759 "\n"
760 "   :arg vert: a vert in this edge.\n"
761 "   :type vert: :class:`BMVert`\n"
762 "   :return: The edges other vert.\n"
763 "   :rtype: :class:`BMVert` or None\n"
764 );
765 static PyObject *bpy_bmedge_other_vert(BPy_BMEdge *self, BPy_BMVert *value)
766 {
767         BMVert *other;
768         BPY_BM_CHECK_OBJ(self);
769
770         if (!BPy_BMVert_Check(value)) {
771                 PyErr_Format(PyExc_TypeError,
772                              "BMEdge.other_vert(vert): BMVert expected, not '%.200s'",
773                              Py_TYPE(value)->tp_name);
774                 return NULL;
775         }
776
777         BPY_BM_CHECK_OBJ(value);
778
779         if (self->bm != value->bm) {
780                 PyErr_SetString(PyExc_TypeError,
781                                 "BMEdge.other_vert(vert): vert is from another mesh");
782                 return NULL;
783         }
784
785         other = BM_edge_other_vert(self->e, value->v);
786
787         if (other) {
788                 return BPy_BMVert_CreatePyObject(self->bm, other);
789         }
790         else {
791                 /* could raise an exception here */
792                 Py_RETURN_NONE;
793         }
794 }
795
796
797 PyDoc_STRVAR(bpy_bmedge_normal_update_doc,
798 ".. method:: normal_update()\n"
799 "\n"
800 "   Update edges vertex normals.\n"
801 );
802 static PyObject *bpy_bmedge_normal_update(BPy_BMEdge *self)
803 {
804         BPY_BM_CHECK_OBJ(self);
805
806         BM_edge_normals_update(self->bm, self->e);
807
808         Py_RETURN_NONE;
809 }
810
811
812 /* Face
813  * ---- */
814
815 PyDoc_STRVAR(bpy_bmface_copy_from_face_interp_doc,
816 ".. method:: copy_from_face_interp(face)\n"
817 "\n"
818 "   Interpolate the customdata from another face onto this one (faces should overlap).\n"
819 "\n"
820 "   :arg face: The face to interpolate data from.\n"
821 "   :type face: :class:`BMFace`\n"
822 );
823 static PyObject *bpy_bmface_copy_from_face_interp(BPy_BMFace *self, PyObject *args)
824 {
825         BPy_BMFace *py_face = NULL;
826
827         BPY_BM_CHECK_OBJ(self);
828
829         if (!PyArg_ParseTuple(args, "O!:BMFace.copy_from_face_interp",
830                               &BPy_BMFace_Type, &py_face))
831         {
832                 return NULL;
833         }
834         else {
835                 BMesh *bm = self->bm;
836
837                 BPY_BM_CHECK_OBJ(py_face);
838
839                 if (py_face->bm != bm) {
840                         PyErr_SetString(PyExc_ValueError,
841                                         "BMFace.copy_from_face_interp(face): face is from another mesh");
842                         return NULL;
843                 }
844
845                 BM_face_interp_from_face(bm, self->f, py_face->f);
846
847                 Py_RETURN_NONE;
848         }
849 }
850
851
852 PyDoc_STRVAR(bpy_bmface_copy_doc,
853 ".. method:: copy(verts=True, edges=True)\n"
854 "\n"
855 "   Make a copy of this face.\n"
856 "\n"
857 "   :arg verts: When set, the faces verts will be duplicated too.\n"
858 "   :type verts: boolean\n"
859 "   :arg edges: When set, the faces edges will be duplicated too.\n"
860 "   :type edges: boolean\n"
861 "   :return: The newly created face.\n"
862 "   :rtype: :class:`BMFace`\n"
863 );
864 static PyObject *bpy_bmface_copy(BPy_BMFace *self, PyObject *args, PyObject *kw)
865 {
866         static const char *kwlist[] = {"verts", "edges", NULL};
867
868         BMesh *bm = self->bm;
869         int do_verts = TRUE;
870         int do_edges = TRUE;
871
872         BMFace *f_cpy;
873         BPY_BM_CHECK_OBJ(self);
874
875         if (!PyArg_ParseTupleAndKeywords(args, kw,
876                                          "|ii:BMFace.copy",
877                                          (char **)kwlist,
878                                          &do_verts, &do_edges))
879         {
880                 return NULL;
881         }
882
883         f_cpy = BM_face_copy(bm, self->f, do_verts, do_edges);
884
885         if (f_cpy) {
886                 return BPy_BMFace_CreatePyObject(bm, f_cpy);
887         }
888         else {
889                 PyErr_SetString(PyExc_ValueError,
890                                 "BMFace.copy(): couldn't create the new face, internal error");
891                 return NULL;
892         }
893 }
894
895
896 PyDoc_STRVAR(bpy_bmface_calc_area_doc,
897 ".. method:: calc_area()\n"
898 "\n"
899 "   Return the area of the face.\n"
900 "\n"
901 "   :return: Return the area of the face.\n"
902 "   :rtype: float\n"
903 );
904 static PyObject *bpy_bmface_calc_area(BPy_BMFace *self)
905 {
906         BPY_BM_CHECK_OBJ(self);
907         return PyFloat_FromDouble(BM_face_area_calc(self->bm, self->f));
908 }
909
910
911 PyDoc_STRVAR(bpy_bmface_calc_center_mean_doc,
912 ".. method:: calc_center_median()\n"
913 "\n"
914 "   Return median center of the face.\n"
915 "\n"
916 "   :return: a 3D vector.\n"
917 "   :rtype: :class:`mathutils.Vector`\n"
918 );
919 static PyObject *bpy_bmface_calc_center_mean(BPy_BMFace *self)
920 {
921         float cent[3];
922
923         BPY_BM_CHECK_OBJ(self);
924         BM_face_center_mean_calc(self->bm, self->f, cent);
925         return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
926 }
927
928
929 PyDoc_STRVAR(bpy_bmface_calc_center_bounds_doc,
930 ".. method:: calc_center_bounds()\n"
931 "\n"
932 "   Return bounds center of the face.\n"
933 "\n"
934 "   :return: a 3D vector.\n"
935 "   :rtype: :class:`mathutils.Vector`\n"
936 );
937 static PyObject *bpy_bmface_calc_center_bounds(BPy_BMFace *self)
938 {
939         float cent[3];
940
941         BPY_BM_CHECK_OBJ(self);
942         BM_face_center_bounds_calc(self->bm, self->f, cent);
943         return Vector_CreatePyObject(cent, 3, Py_NEW, NULL);
944 }
945
946
947 PyDoc_STRVAR(bpy_bmface_normal_update_doc,
948 ".. method:: normal_update()\n"
949 "\n"
950 "   Update faces normal.\n"
951 );
952 static PyObject *bpy_bmface_normal_update(BPy_BMFace *self)
953 {
954         BPY_BM_CHECK_OBJ(self);
955
956         BM_face_normal_update(self->bm, self->f);
957
958         Py_RETURN_NONE;
959 }
960
961
962 /* Loop
963  * ---- */
964
965 PyDoc_STRVAR(bpy_bmloop_copy_from_face_interp_doc,
966 ".. method:: copy_from_face_interp(face, vert=True, multires=True)\n"
967 "\n"
968 "   Interpolate the customdata from a face onto this loop (the loops vert should overlap the face).\n"
969 "\n"
970 "   :arg face: The face to interpolate data from.\n"
971 "   :type face: :class:`BMFace`\n"
972 "   :arg vert: When enabled, interpolate the loops vertex data.\n"
973 "   :type vert: boolean\n"
974 "   :arg multires: When enabled, interpolate the loops multires data.\n"
975 "   :type multires: boolean\n"
976 );
977 static PyObject *bpy_bmloop_copy_from_face_interp(BPy_BMLoop *self, PyObject *args)
978 {
979         BPy_BMFace *py_face = NULL;
980         int do_vertex   = TRUE;
981         int do_multires = TRUE;
982
983         BPY_BM_CHECK_OBJ(self);
984
985         if (!PyArg_ParseTuple(args, "O!|ii:BMLoop.copy_from_face_interp",
986                               &BPy_BMFace_Type, &py_face,
987                               &do_vertex, &do_multires))
988         {
989                 return NULL;
990         }
991         else {
992                 BMesh *bm = self->bm;
993
994                 BPY_BM_CHECK_OBJ(py_face);
995
996                 if (py_face->bm != bm) {
997                         PyErr_SetString(PyExc_ValueError,
998                                         "BMLoop.copy_from_face_interp(face): face is from another mesh");
999                         return NULL;
1000                 }
1001
1002                 BM_loop_interp_from_face(bm, self->l, py_face->f, do_vertex, do_multires);
1003
1004                 Py_RETURN_NONE;
1005         }
1006 }
1007
1008
1009 PyDoc_STRVAR(bpy_bmloop_calc_face_angle_doc,
1010 ".. method:: calc_face_angle()\n"
1011 "\n"
1012 "   Return angle at this loops corner of the face.\n"
1013 "   This is calculated so sharper corners give lower angles.\n"
1014 "\n"
1015 "   :return: The angle in radians.\n"
1016 "   :rtype: float\n"
1017 );
1018 static PyObject *bpy_bmloop_calc_face_angle(BPy_BMLoop *self)
1019 {
1020         BPY_BM_CHECK_OBJ(self);
1021         return PyFloat_FromDouble(BM_loop_face_angle(self->bm, self->l));
1022 }
1023
1024
1025 /* Vert Seq
1026  * -------- */
1027
1028 static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args)
1029 {
1030         PyObject *py_co = NULL;
1031         BPy_BMVert *py_vert_example = NULL; /* optional */
1032
1033         BPY_BM_CHECK_OBJ(self);
1034
1035         if (!PyArg_ParseTuple(args, "|OO!:verts.new",
1036                               py_co,
1037                               &BPy_BMVert_Type, &py_vert_example))
1038         {
1039                 return NULL;
1040         }
1041         else {
1042                 BMesh *bm = self->bm;
1043                 BMVert *v;
1044                 float co[3] = {0.0f, 0.0f, 0.0f};
1045
1046                 if (py_vert_example) {
1047                         BPY_BM_CHECK_OBJ(py_vert_example);
1048                 }
1049
1050                 if (py_co && mathutils_array_parse(co, 3, 3, py_co, "verts.new(co)") != -1) {
1051                         return NULL;
1052                 }
1053
1054                 v = BM_vert_create(bm, co, NULL);
1055
1056                 if (v == NULL) {
1057                         PyErr_SetString(PyExc_ValueError,
1058                                         "faces.new(verts): couldn't create the new face, internal error");
1059                         return NULL;
1060                 }
1061
1062                 if (py_vert_example) {
1063                         BM_elem_attrs_copy(py_vert_example->bm, bm, py_vert_example->v, v);
1064                 }
1065
1066                 return BPy_BMVert_CreatePyObject(bm, v);
1067         }
1068 }
1069
1070
1071 /* Edge Seq
1072  * -------- */
1073
1074 static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args)
1075 {
1076         PyObject *vert_seq;
1077         BPy_BMEdge *py_edge_example = NULL; /* optional */
1078
1079         BPY_BM_CHECK_OBJ(self);
1080
1081         if (!PyArg_ParseTuple(args, "O|O!:edges.new",
1082                               &vert_seq,
1083                               &BPy_BMEdge_Type, &py_edge_example))
1084         {
1085                 return NULL;
1086         }
1087         else {
1088                 BMesh *bm = self->bm;
1089                 BMEdge *e;
1090                 BMVert **vert_array = NULL;
1091                 Py_ssize_t vert_seq_len; /* always 2 */
1092                 PyObject *ret = NULL;
1093
1094                 if (py_edge_example) {
1095                         BPY_BM_CHECK_OBJ(py_edge_example);
1096                 }
1097
1098                 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1099                                                        &vert_seq_len, &BPy_BMVert_Type,
1100                                                        TRUE, TRUE, "edges.new(...)");
1101
1102                 if (BM_edge_exists(vert_array[0], vert_array[1])) {
1103                         PyErr_SetString(PyExc_ValueError,
1104                                         "edges.new(): this edge exists");
1105                         goto cleanup;
1106                 }
1107
1108                 e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, FALSE);
1109
1110                 if (e == NULL) {
1111                         PyErr_SetString(PyExc_ValueError,
1112                                         "faces.new(verts): couldn't create the new face, internal error");
1113                         goto cleanup;
1114                 }
1115
1116                 if (py_edge_example) {
1117                         BM_elem_attrs_copy(py_edge_example->bm, bm, py_edge_example->e, e);
1118                 }
1119
1120                 ret = BPy_BMEdge_CreatePyObject(bm, e);
1121
1122 cleanup:
1123                 if (vert_array) PyMem_FREE(vert_array);
1124                 return ret;
1125         }
1126 }
1127
1128
1129 /* Face Seq
1130  * -------- */
1131
1132 static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args)
1133 {
1134         PyObject *vert_seq;
1135         BPy_BMFace *py_face_example = NULL; /* optional */
1136
1137         BPY_BM_CHECK_OBJ(self);
1138
1139         if (!PyArg_ParseTuple(args, "O|O!:faces.new",
1140                               &vert_seq,
1141                               &BPy_BMFace_Type, &py_face_example))
1142         {
1143                 return NULL;
1144         }
1145         else {
1146                 BMesh *bm = self->bm;
1147                 Py_ssize_t vert_seq_len;
1148                 Py_ssize_t i, i_next;
1149
1150                 BMVert **vert_array = NULL;
1151                 BMEdge **edge_array = NULL;
1152
1153                 PyObject *ret = NULL;
1154
1155                 BMFace *f_new;
1156
1157                 if (py_face_example) {
1158                         BPY_BM_CHECK_OBJ(py_face_example);
1159                 }
1160
1161                 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 3, PY_SSIZE_T_MAX,
1162                                                        &vert_seq_len, &BPy_BMVert_Type,
1163                                                        TRUE, TRUE, "faces.new(...)");
1164
1165                 /* check if the face exists */
1166                 if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) {
1167                         PyErr_SetString(PyExc_ValueError,
1168                                         "faces.new(verts): face already exists");
1169                         goto cleanup;
1170                 }
1171
1172                 /* Go ahead and make the face!
1173                  * --------------------------- */
1174
1175                 edge_array = (BMEdge **)PyMem_MALLOC(vert_seq_len * sizeof(BMEdge **));
1176
1177                 /* ensure edges */
1178                 for (i_next = 0, i = vert_seq_len - 1; i_next < vert_seq_len; (i=i_next++)) {
1179                         edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_next], NULL, TRUE);
1180                 }
1181
1182                 f_new = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE);
1183
1184                 if (f_new == NULL) {
1185                         PyErr_SetString(PyExc_ValueError,
1186                                         "faces.new(verts): couldn't create the new face, internal error");
1187                         goto cleanup;
1188                 }
1189
1190                 if (py_face_example) {
1191                         BM_elem_attrs_copy(py_face_example->bm, bm, py_face_example->f, f_new);
1192                 }
1193
1194                 ret = BPy_BMFace_CreatePyObject(bm, f_new);
1195
1196                 /* pass through */
1197 cleanup:
1198                 if (vert_array) PyMem_FREE(vert_array);
1199                 if (edge_array) PyMem_FREE(edge_array);
1200                 return ret;
1201         }
1202 }
1203
1204 /* Elem Seq
1205  * -------- */
1206
1207 /* eek - 3 docstrings in 1!, we might need to split up this seq at some point */
1208 PyDoc_STRVAR(bpy_bmelemseq_new_doc,
1209 ".. method:: new(co=(0.0, 0.0, 0.0), example=None)\n"
1210 "\n"
1211 "   *Vertex Sequence*\n"
1212 "\n"
1213 "   :arg co: The initial location of the vertex (optional argument).\n"
1214 "   :type co: float triplet\n"
1215 "   :arg example: Existing vert to initialize settings.\n"
1216 "   :type example: :class:`BMVert`\n"
1217 "   :return: The newly created edge.\n"
1218 "   :rtype: :class:`BMVert`\n"
1219 "\n"
1220 "\n"
1221 ".. method:: new(verts, example=None)\n"
1222 "\n"
1223 "   *Edge Sequence*\n"
1224 "\n"
1225 "   :arg verts: Vertex pair.\n"
1226 "   :type verts: pair of :class:`BMVert`\n"
1227 "   :arg example: Existing edge to initialize settings (optional argument).\n"
1228 "   :type example: :class:`BMEdge`\n"
1229 "   :return: The newly created edge.\n"
1230 "   :rtype: :class:`BMEdge`\n"
1231 "\n"
1232 ".. method:: new(verts, example=None)\n"
1233 "\n"
1234 "   *Face Sequence*\n"
1235 "\n"
1236 "   Create a new vert/edge/face.\n"
1237 "\n"
1238 "   :arg verts: Sequence of 3 or more verts.\n"
1239 "   :type verts: :class:`BMVert`\n"
1240 "   :arg example: Existing face to initialize settings (optional argument).\n"
1241 "   :type example: :class:`BMFace`\n"
1242 "   :return: The newly created face.\n"
1243 "   :rtype: :class:`BMFace`\n"
1244 );
1245 static PyObject *bpy_bmelemseq_new(BPy_BMElemSeq *self, PyObject *args)
1246 {
1247         switch ((BMIterType)self->itype) {
1248                 case BM_VERTS_OF_MESH:
1249                         return bpy_bmvertseq_new(self, args);
1250                 case BM_EDGES_OF_MESH:
1251                         return bpy_bmedgeseq_new(self, args);
1252                 case BM_FACES_OF_MESH:
1253                         return bpy_bmfaceseq_new(self, args);
1254                 default:
1255                         PyErr_SetString(PyExc_TypeError,
1256                                         ".new(...): function is not valid for this sequence");
1257                         return NULL;
1258         }
1259 }
1260
1261 static PyObject *bpy_bmvertseq_remove(BPy_BMElemSeq *self, BPy_BMVert *value)
1262 {
1263         BPY_BM_CHECK_OBJ(self);
1264
1265         if (!BPy_BMVert_Check(value)) {
1266                 return NULL;
1267         }
1268         else {
1269                 BMesh *bm = self->bm;
1270
1271                 BPY_BM_CHECK_OBJ(value);
1272
1273                 if (value->bm != bm) {
1274                         PyErr_SetString(PyExc_ValueError,
1275                                         "faces.remove(vert): vertex is from another mesh");
1276                         return NULL;
1277                 }
1278
1279                 BM_vert_kill(bm, value->v);
1280                 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1281
1282                 Py_RETURN_NONE;
1283         }
1284 }
1285
1286 static PyObject *bpy_bmedgeseq_remove(BPy_BMElemSeq *self, BPy_BMEdge *value)
1287 {
1288         BPY_BM_CHECK_OBJ(self);
1289
1290         if (!BPy_BMEdge_Check(value)) {
1291                 return NULL;
1292         }
1293         else {
1294                 BMesh *bm = self->bm;
1295
1296                 BPY_BM_CHECK_OBJ(value);
1297
1298                 if (value->bm != bm) {
1299                         PyErr_SetString(PyExc_ValueError,
1300                                         "faces.remove(vert): vertex is from another mesh");
1301                         return NULL;
1302                 }
1303
1304                 BM_edge_kill(bm, value->e);
1305                 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1306
1307                 Py_RETURN_NONE;
1308         }
1309 }
1310
1311 static PyObject *bpy_bmfaceseq_remove(BPy_BMElemSeq *self, BPy_BMFace *value)
1312 {
1313         BPY_BM_CHECK_OBJ(self);
1314
1315         if (!BPy_BMFace_Check(value)) {
1316                 return NULL;
1317         }
1318         else {
1319                 BMesh *bm = self->bm;
1320
1321                 BPY_BM_CHECK_OBJ(value);
1322
1323                 if (value->bm != bm) {
1324                         PyErr_SetString(PyExc_ValueError,
1325                                         "faces.remove(vert): vertex is from another mesh");
1326                         return NULL;
1327                 }
1328
1329                 BM_face_kill(bm, value->f);
1330                 bpy_bm_generic_invalidate((BPy_BMGeneric *)value);
1331
1332                 Py_RETURN_NONE;
1333         }
1334 }
1335
1336
1337 PyDoc_STRVAR(bpy_bmelemseq_remove_doc,
1338 ".. method:: remove(elem)\n"
1339 "\n"
1340 "   Remove a vert/edge/face.\n"
1341 );
1342 static PyObject *bpy_bmelemseq_remove(BPy_BMElemSeq *self, PyObject *value)
1343 {
1344         switch ((BMIterType)self->itype) {
1345                 case BM_VERTS_OF_MESH:
1346                         return bpy_bmvertseq_remove(self, (BPy_BMVert *)value);
1347                 case BM_EDGES_OF_MESH:
1348                         return bpy_bmedgeseq_remove(self, (BPy_BMEdge *)value);
1349                 case BM_FACES_OF_MESH:
1350                         return bpy_bmfaceseq_remove(self, (BPy_BMFace *)value);
1351                 default:
1352                         PyErr_SetString(PyExc_TypeError,
1353                                         ".remove(item): function is not valid for this sequence");
1354                         return NULL;
1355         }
1356 }
1357
1358
1359 static PyObject *bpy_bmedgeseq_get(BPy_BMElemSeq *self, PyObject *args)
1360 {
1361         PyObject *vert_seq;
1362         PyObject *fallback = Py_None; /* optional */
1363
1364         BPY_BM_CHECK_OBJ(self);
1365
1366         if (!PyArg_ParseTuple(args, "O|O:edges.get",
1367                               &vert_seq,
1368                               &fallback))
1369         {
1370                 return NULL;
1371         }
1372         else {
1373                 BMesh *bm = self->bm;
1374                 BMEdge *e;
1375                 BMVert **vert_array = NULL;
1376                 Py_ssize_t vert_seq_len; /* always 2 */
1377                 PyObject *ret = NULL;
1378
1379                 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 2, 2,
1380                                                        &vert_seq_len, &BPy_BMVert_Type,
1381                                                        TRUE, TRUE, "edges.get(...)");
1382
1383                 if (vert_array == NULL) {
1384                         return NULL;
1385                 }
1386
1387                 if ((e=BM_edge_exists(vert_array[0], vert_array[1]))) {
1388                         ret = BPy_BMEdge_CreatePyObject(bm, e);
1389                 }
1390                 else {
1391                         ret = fallback;
1392                         Py_INCREF(ret);
1393                 }
1394
1395                 PyMem_FREE(vert_array);
1396                 return ret;
1397         }
1398 }
1399
1400
1401 static PyObject *bpy_bmfaceseq_get(BPy_BMElemSeq *self, PyObject *args)
1402 {
1403         PyObject *vert_seq;
1404         PyObject *fallback = Py_None; /* optional */
1405
1406         BPY_BM_CHECK_OBJ(self);
1407
1408         if (!PyArg_ParseTuple(args, "O|O:faces.get",
1409                               &vert_seq,
1410                               &fallback))
1411         {
1412                 return NULL;
1413         }
1414         else {
1415                 BMesh *bm = self->bm;
1416                 BMFace *f = NULL;
1417                 BMVert **vert_array = NULL;
1418                 Py_ssize_t vert_seq_len;
1419                 PyObject *ret = NULL;
1420
1421                 vert_array = BPy_BMElem_PySeq_As_Array(&bm, vert_seq, 1, PY_SSIZE_T_MAX,
1422                                                        &vert_seq_len, &BPy_BMVert_Type,
1423                                                        TRUE, TRUE, "faces.get(...)");
1424
1425                 if (vert_array == NULL) {
1426                         return NULL;
1427                 }
1428
1429                 if (BM_face_exists(bm, vert_array, vert_seq_len, &f)) {
1430                         ret = BPy_BMFace_CreatePyObject(bm, f);
1431                 }
1432                 else {
1433                         ret = fallback;
1434                         Py_INCREF(ret);
1435                 }
1436
1437                 PyMem_FREE(vert_array);
1438                 return ret;
1439         }
1440 }
1441
1442
1443 PyDoc_STRVAR(bpy_bmelemseq_get__method_doc,
1444 ".. method:: get(verts, fallback=None)\n"
1445 "\n"
1446 "   Return a face/edge which uses the **verts** passed.\n"
1447 "\n"
1448 "   :arg verts: Sequence of verts.\n"
1449 "   :type verts: :class:`BMVert`\n"
1450 "   :arg fallback: Return this value if nothing is found.\n"
1451 );
1452 static PyObject *bpy_bmelemseq_get__method(BPy_BMElemSeq *self, PyObject *args)
1453 {
1454         switch ((BMIterType)self->itype) {
1455                 case BM_EDGES_OF_MESH:
1456                         return bpy_bmedgeseq_get(self, args);
1457                 case BM_FACES_OF_MESH:
1458                         return bpy_bmfaceseq_get(self, args);
1459                 default:
1460                         PyErr_SetString(PyExc_TypeError,
1461                                         ".get(item): function is not valid for this sequence");
1462                         return NULL;
1463         }
1464 }
1465
1466
1467 PyDoc_STRVAR(bpy_bmelemseq_index_update_doc,
1468 ".. method:: index_update()\n"
1469 "\n"
1470 "   Initialize the index values of this sequence.\n"
1471 "\n"
1472 "   This is the equivalent of looping over all elements and assigning the index values.\n"
1473 "\n"
1474 "   .. code-block:: python\n"
1475 "\n"
1476 "      for index, ele in enumerate(sequence):\n"
1477 "          ele.index = index\n"
1478 "\n"
1479 "   .. note::\n"
1480 "\n"
1481 "      Running this on sequences besides :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces`\n"
1482 "      works but wont result in each element having a valid index, insted its order in the sequence will be set.\n"
1483 );
1484 static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self)
1485 {
1486         BMesh *bm = self->bm;
1487
1488         BPY_BM_CHECK_OBJ(self);
1489
1490         switch ((BMIterType)self->itype) {
1491                 case BM_VERTS_OF_MESH:
1492                         BM_mesh_elem_index_ensure(self->bm, BM_VERT);
1493                         break;
1494                 case BM_EDGES_OF_MESH:
1495                         BM_mesh_elem_index_ensure(self->bm, BM_EDGE);
1496                         break;
1497                 case BM_FACES_OF_MESH:
1498                         BM_mesh_elem_index_ensure(self->bm, BM_FACE);
1499                         break;
1500                 default:
1501                 {
1502                         BMIter iter;
1503                         BMElem *ele;
1504                         int index = 0;
1505                         const char htype = bm_iter_itype_htype_map[self->itype];
1506
1507                         BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
1508                                 BM_elem_index_set(ele, index); /* set_dirty! */
1509                                 index++;
1510                         }
1511
1512                         if (htype & (BM_VERT | BM_EDGE | BM_FACE)) {
1513                                 /* since this isnt the normal vert/edge/face loops,
1514                                  * we're setting dirty values here. so tag as dirty. */
1515                                 bm->elem_index_dirty |= htype;
1516                         }
1517
1518                         break;
1519                 }
1520         }
1521
1522         Py_RETURN_NONE;
1523 }
1524
1525
1526 static struct PyMethodDef bpy_bmesh_methods[] = {
1527     {"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
1528     {"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
1529     {"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc},
1530     {"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS|METH_KEYWORDS, bpy_bmesh_transform_doc},
1531     {NULL, NULL, 0, NULL}
1532 };
1533
1534 static struct PyMethodDef bpy_bmvert_methods[] = {
1535     {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
1536     {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1537
1538     {"calc_vert_angle", (PyCFunction)bpy_bmvert_calc_edge_angle, METH_NOARGS, bpy_bmvert_calc_edge_angle_doc},
1539
1540     {"normal_update",  (PyCFunction)bpy_bmvert_normal_update,  METH_NOARGS,  bpy_bmvert_normal_update_doc},
1541
1542     {NULL, NULL, 0, NULL}
1543 };
1544
1545 static struct PyMethodDef bpy_bmedge_methods[] = {
1546     {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
1547     {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1548
1549     {"other_vert", (PyCFunction)bpy_bmedge_other_vert, METH_O, bpy_bmedge_other_vert_doc},
1550
1551     {"calc_face_angle", (PyCFunction)bpy_bmedge_calc_face_angle, METH_NOARGS, bpy_bmedge_calc_face_angle_doc},
1552
1553     {"normal_update",  (PyCFunction)bpy_bmedge_normal_update,  METH_NOARGS,  bpy_bmedge_normal_update_doc},
1554
1555     {NULL, NULL, 0, NULL}
1556 };
1557
1558 static struct PyMethodDef bpy_bmface_methods[] = {
1559     {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
1560
1561     {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1562     {"copy_from_face_interp", (PyCFunction)bpy_bmface_copy_from_face_interp, METH_O, bpy_bmface_copy_from_face_interp_doc},
1563
1564     {"copy", (PyCFunction)bpy_bmface_copy, METH_VARARGS|METH_KEYWORDS, bpy_bmface_copy_doc},
1565
1566     {"calc_area",          (PyCFunction)bpy_bmface_calc_area,          METH_NOARGS, bpy_bmface_calc_area_doc},
1567     {"calc_center_median", (PyCFunction)bpy_bmface_calc_center_mean,   METH_NOARGS, bpy_bmface_calc_center_mean_doc},
1568     {"calc_center_bounds", (PyCFunction)bpy_bmface_calc_center_bounds, METH_NOARGS, bpy_bmface_calc_center_bounds_doc},
1569
1570     {"normal_update",  (PyCFunction)bpy_bmface_normal_update,  METH_NOARGS,  bpy_bmface_normal_update_doc},
1571
1572     {NULL, NULL, 0, NULL}
1573 };
1574
1575 static struct PyMethodDef bpy_bmloop_methods[] = {
1576     {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
1577     {"copy_from_face_interp", (PyCFunction)bpy_bmloop_copy_from_face_interp, METH_O, bpy_bmloop_copy_from_face_interp_doc},
1578
1579     {"calc_angle", (PyCFunction)bpy_bmloop_calc_face_angle, METH_NOARGS, bpy_bmloop_calc_face_angle_doc},
1580     {NULL, NULL, 0, NULL}
1581 };
1582
1583 static struct PyMethodDef bpy_bmelemseq_methods[] = {
1584     {"new",     (PyCFunction)bpy_bmelemseq_new,         METH_VARARGS, bpy_bmelemseq_new_doc},
1585     {"remove",  (PyCFunction)bpy_bmelemseq_remove,      METH_O,       bpy_bmelemseq_remove_doc},
1586     /* 'bpy_bmelemseq_get' for different purpose */
1587     {"get",     (PyCFunction)bpy_bmelemseq_get__method, METH_VARARGS, bpy_bmelemseq_get__method_doc},
1588
1589     /* odd function, initializes index values */
1590     {"index_update", (PyCFunction)bpy_bmelemseq_index_update, METH_NOARGS, bpy_bmelemseq_index_update_doc},
1591     {NULL, NULL, 0, NULL}
1592 };
1593
1594 /* Sequences
1595  * ========= */
1596
1597 static PyTypeObject *bpy_bm_itype_as_pytype(const char itype)
1598 {
1599         /* should cover all types */
1600         switch ((BMIterType)itype) {
1601                 case BM_VERTS_OF_MESH:
1602                 case BM_VERTS_OF_FACE:
1603                 case BM_VERTS_OF_EDGE:
1604                         return &BPy_BMVert_Type;
1605
1606                 case BM_EDGES_OF_MESH:
1607                 case BM_EDGES_OF_FACE:
1608                 case BM_EDGES_OF_VERT:
1609                         return &BPy_BMEdge_Type;
1610
1611                 case BM_FACES_OF_MESH:
1612                 case BM_FACES_OF_EDGE:
1613                 case BM_FACES_OF_VERT:
1614                         return &BPy_BMFace_Type;
1615
1616                 case BM_ALL_LOOPS_OF_FACE:
1617                 case BM_LOOPS_OF_FACE:
1618                 case BM_LOOPS_OF_EDGE:
1619                 case BM_LOOPS_OF_VERT:
1620                 case BM_LOOPS_OF_LOOP:
1621                         return &BPy_BMLoop_Type;
1622         }
1623
1624         return NULL;
1625 }
1626
1627 static Py_ssize_t bpy_bmelemseq_length(BPy_BMElemSeq *self)
1628 {
1629         BPY_BM_CHECK_INT(self);
1630
1631         /* first check if the size is known */
1632         switch ((BMIterType)self->itype) {
1633                 /* main-types */
1634                 case BM_VERTS_OF_MESH:
1635                         return self->bm->totvert;
1636                 case BM_EDGES_OF_MESH:
1637                         return self->bm->totedge;
1638                 case BM_FACES_OF_MESH:
1639                         return self->bm->totface;
1640
1641                         /* sub-types */
1642                 case BM_VERTS_OF_FACE:
1643                 case BM_EDGES_OF_FACE:
1644                 case BM_LOOPS_OF_FACE:
1645                         BPY_BM_CHECK_INT(self->py_ele);
1646                         return ((BMFace *)self->py_ele->ele)->len;
1647
1648                 case BM_VERTS_OF_EDGE:
1649                         return 2;
1650
1651                 default:
1652                         /* quiet compiler */
1653                         break;
1654         }
1655
1656
1657         /* loop over all items, avoid this if we can */
1658         {
1659                 BMIter iter;
1660                 BMHeader *ele;
1661                 Py_ssize_t tot = 0;
1662
1663                 BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
1664                         tot++;
1665                 }
1666                 return tot;
1667         }
1668 }
1669
1670 static PyObject *bpy_bmelemseq_subscript_int(BPy_BMElemSeq *self, int keynum)
1671 {
1672         BPY_BM_CHECK_OBJ(self);
1673
1674         if (keynum < 0) keynum += bpy_bmelemseq_length(self); /* only get length on negative value, may loop entire seq */
1675         if (keynum >= 0) {
1676                 BMHeader *ele = BM_iter_at_index(self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL, keynum);
1677                 if (ele) {
1678                         return BPy_BMElem_CreatePyObject(self->bm, ele);
1679                 }
1680         }
1681
1682         PyErr_Format(PyExc_IndexError,
1683                      "BMElemSeq[index]: index %d out of range", keynum);
1684         return NULL;
1685 }
1686
1687 static PyObject *bpy_bmelemseq_subscript_slice(BPy_BMElemSeq *self, Py_ssize_t start, Py_ssize_t stop)
1688 {
1689         BMIter iter;
1690         int count = 0;
1691         int ok;
1692
1693         PyObject *list;
1694         PyObject *item;
1695         BMHeader *ele;
1696
1697         BPY_BM_CHECK_OBJ(self);
1698
1699         list = PyList_New(0);
1700
1701         ok = BM_iter_init(&iter, self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
1702
1703         BLI_assert(ok == TRUE);
1704
1705         if (UNLIKELY(ok == FALSE)) {
1706                 return list;
1707         }
1708
1709         /* first loop up-until the start */
1710         for (ok = TRUE; ok; ok = (BM_iter_step(&iter) != NULL)) {
1711                 /* PointerRNA itemptr = rna_macro_iter.ptr; */
1712                 if (count == start) {
1713                         break;
1714                 }
1715                 count++;
1716         }
1717
1718         /* add items until stop */
1719         while ((ele = BM_iter_step(&iter))) {
1720                 item = BPy_BMElem_CreatePyObject(self->bm, ele);
1721                 PyList_Append(list, item);
1722                 Py_DECREF(item);
1723
1724                 count++;
1725                 if (count == stop) {
1726                         break;
1727                 }
1728         }
1729
1730         return list;
1731 }
1732
1733 static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key)
1734 {
1735         /* dont need error check here */
1736         if (PyIndex_Check(key)) {
1737                 Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
1738                 if (i == -1 && PyErr_Occurred())
1739                         return NULL;
1740                 return bpy_bmelemseq_subscript_int(self, i);
1741         }
1742         else if (PySlice_Check(key)) {
1743                 PySliceObject *key_slice = (PySliceObject *)key;
1744                 Py_ssize_t step = 1;
1745
1746                 if (key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
1747                         return NULL;
1748                 }
1749                 else if (step != 1) {
1750                         PyErr_SetString(PyExc_TypeError,
1751                                         "BMElemSeq[slice]: slice steps not supported");
1752                         return NULL;
1753                 }
1754                 else if (key_slice->start == Py_None && key_slice->stop == Py_None) {
1755                         return bpy_bmelemseq_subscript_slice(self, 0, PY_SSIZE_T_MAX);
1756                 }
1757                 else {
1758                         Py_ssize_t start = 0, stop = PY_SSIZE_T_MAX;
1759
1760                         /* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
1761                         if (key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
1762                         if (key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop))    return NULL;
1763
1764                         if (start < 0 || stop < 0) {
1765                                 /* only get the length for negative values */
1766                                 Py_ssize_t len = bpy_bmelemseq_length(self);
1767                                 if (start < 0) start += len;
1768                                 if (stop < 0) start += len;
1769                         }
1770
1771                         if (stop - start <= 0) {
1772                                 return PyList_New(0);
1773                         }
1774                         else {
1775                                 return bpy_bmelemseq_subscript_slice(self, start, stop);
1776                         }
1777                 }
1778         }
1779         else {
1780                 PyErr_SetString(PyExc_AttributeError,
1781                                 "BMElemSeq[key]: invalid key, key must be an int");
1782                 return NULL;
1783         }
1784 }
1785
1786 static int bpy_bmelemseq_contains(BPy_BMElemSeq *self, PyObject *value)
1787 {
1788         BPY_BM_CHECK_INT(self);
1789
1790         if (Py_TYPE(value) == bpy_bm_itype_as_pytype(self->itype)) {
1791                 BPy_BMElem *value_bm_ele = (BPy_BMElem *)value;
1792                 if (value_bm_ele->bm == self->bm) {
1793                         BMElem *ele, *ele_test = value_bm_ele->ele;
1794                         BMIter iter;
1795                         BM_ITER_BPY_BM_SEQ(ele, &iter, self) {
1796                                 if (ele == ele_test) {
1797                                         return 1;
1798                                 }
1799                         }
1800                 }
1801         }
1802
1803         return 0;
1804 }
1805
1806 static PySequenceMethods bpy_bmelemseq_as_sequence = {
1807     (lenfunc)bpy_bmelemseq_length,                  /* sq_length */
1808     NULL,                                        /* sq_concat */
1809     NULL,                                        /* sq_repeat */
1810     (ssizeargfunc)bpy_bmelemseq_subscript_int,      /* sq_item */ /* Only set this so PySequence_Check() returns True */
1811     NULL,                                        /* sq_slice */
1812     (ssizeobjargproc)NULL,                       /* sq_ass_item */
1813     NULL,                                        /* *was* sq_ass_slice */
1814     (objobjproc)bpy_bmelemseq_contains,             /* sq_contains */
1815     (binaryfunc) NULL,                           /* sq_inplace_concat */
1816     (ssizeargfunc) NULL,                         /* sq_inplace_repeat */
1817 };
1818
1819 static PyMappingMethods bpy_bmelemseq_as_mapping = {
1820     (lenfunc)bpy_bmelemseq_length,                  /* mp_length */
1821     (binaryfunc)bpy_bmelemseq_subscript,            /* mp_subscript */
1822     (objobjargproc)NULL,                         /* mp_ass_subscript */
1823 };
1824
1825 /* Iterator
1826  * -------- */
1827
1828 static PyObject *bpy_bmelemseq_iter(BPy_BMElemSeq *self)
1829 {
1830         BPy_BMIter *py_iter;
1831
1832         BPY_BM_CHECK_OBJ(self);
1833         py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
1834         BM_iter_init(&(py_iter->iter), self->bm, self->itype, self->py_ele ? self->py_ele->ele : NULL);
1835         return (PyObject *)py_iter;
1836 }
1837
1838 static PyObject *bpy_bmiter_next(BPy_BMIter *self)
1839 {
1840         BMHeader *ele = BM_iter_step(&self->iter);
1841         if (ele == NULL) {
1842                 PyErr_SetString(PyExc_StopIteration,
1843                                 "bpy_bmiter_next stop");
1844                 return NULL;
1845         }
1846         else {
1847                 return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, ele);
1848         }
1849 }
1850
1851
1852 /* Dealloc Functions
1853  * ================= */
1854
1855 static void bpy_bmesh_dealloc(BPy_BMesh *self)
1856 {
1857         BMesh *bm = self->bm;
1858
1859         BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
1860         BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR);
1861         BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
1862         BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
1863
1864         bm->py_handle = NULL;
1865
1866         PyObject_DEL(self);
1867 }
1868
1869 static void bpy_bmvert_dealloc(BPy_BMElem *self)
1870 {
1871         BMesh *bm = self->bm;
1872         if (bm) {
1873                 void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
1874                 *ptr = NULL;
1875         }
1876         PyObject_DEL(self);
1877 }
1878
1879 static void bpy_bmedge_dealloc(BPy_BMElem *self)
1880 {
1881         BMesh *bm = self->bm;
1882         if (bm) {
1883                 void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->head.data, CD_BM_ELEM_PYPTR);
1884                 *ptr = NULL;
1885         }
1886         PyObject_DEL(self);
1887 }
1888
1889 static void bpy_bmface_dealloc(BPy_BMElem *self)
1890 {
1891         BMesh *bm = self->bm;
1892         if (bm) {
1893                 void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->head.data, CD_BM_ELEM_PYPTR);
1894                 *ptr = NULL;
1895         }
1896         PyObject_DEL(self);
1897 }
1898
1899 static void bpy_bmloop_dealloc(BPy_BMElem *self)
1900 {
1901         BMesh *bm = self->bm;
1902         if (bm) {
1903                 void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->head.data, CD_BM_ELEM_PYPTR);
1904                 *ptr = NULL;
1905         }
1906         PyObject_DEL(self);
1907 }
1908
1909 static void bpy_bmelemseq_dealloc(BPy_BMElemSeq *self)
1910 {
1911         Py_XDECREF(self->py_ele);
1912
1913         PyObject_DEL(self);
1914 }
1915
1916 /* not sure where this should go */
1917 static long bpy_bm_elem_hash(PyObject *self)
1918 {
1919         return _Py_HashPointer(((BPy_BMElem *)self)->ele);
1920 }
1921
1922
1923 /* Type Docstrings
1924  * =============== */
1925
1926 PyDoc_STRVAR(bpy_bmesh_doc,
1927 "The BMesh data structure\n"
1928 );
1929 PyDoc_STRVAR(bpy_bmvert_doc,
1930 "The BMesh vertex type\n"
1931 );
1932 PyDoc_STRVAR(bpy_bmedge_doc,
1933 "The BMesh edge connecting 2 verts\n"
1934 );
1935 PyDoc_STRVAR(bpy_bmface_doc,
1936 "The BMesh face with 3 or more sides\n"
1937 );
1938 PyDoc_STRVAR(bpy_bmloop_doc,
1939 "This is normally accessed from :class:`BMFace.loops` where each face corner represents a corner of a face.\n"
1940 );
1941 PyDoc_STRVAR(bpy_bmelemseq_doc,
1942 "General sequence type used for accessing any sequence of \n"
1943 ":class:`BMVert`, :class:`BMEdge`, :class:`BMFace`, :class:`BMLoop`.\n"
1944 "\n"
1945 "When accessed via :class:`BMesh.verts`, :class:`BMesh.edges`, :class:`BMesh.faces` \n"
1946 "there are also functions to create/remomove items.\n"
1947 );
1948 PyDoc_STRVAR(bpy_bmiter_doc,
1949 "Internal BMesh type for looping over verts/faces/edges,\n"
1950 "used for iterating over :class:`BMElemSeq` types.\n"
1951 );
1952
1953 /* Types
1954  * ===== */
1955
1956 PyTypeObject BPy_BMesh_Type     = {{{0}}};
1957 PyTypeObject BPy_BMVert_Type    = {{{0}}};
1958 PyTypeObject BPy_BMEdge_Type    = {{{0}}};
1959 PyTypeObject BPy_BMFace_Type    = {{{0}}};
1960 PyTypeObject BPy_BMLoop_Type    = {{{0}}};
1961 PyTypeObject BPy_BMElemSeq_Type = {{{0}}};
1962 PyTypeObject BPy_BMIter_Type    = {{{0}}};
1963
1964
1965
1966 void BPy_BM_init_types(void)
1967 {
1968         BPy_BMesh_Type.tp_basicsize     = sizeof(BPy_BMesh);
1969         BPy_BMVert_Type.tp_basicsize    = sizeof(BPy_BMVert);
1970         BPy_BMEdge_Type.tp_basicsize    = sizeof(BPy_BMEdge);
1971         BPy_BMFace_Type.tp_basicsize    = sizeof(BPy_BMFace);
1972         BPy_BMLoop_Type.tp_basicsize    = sizeof(BPy_BMLoop);
1973         BPy_BMElemSeq_Type.tp_basicsize = sizeof(BPy_BMElemSeq);
1974         BPy_BMIter_Type.tp_basicsize    = sizeof(BPy_BMIter);
1975
1976
1977         BPy_BMesh_Type.tp_name     = "BMesh";
1978         BPy_BMVert_Type.tp_name    = "BMVert";
1979         BPy_BMEdge_Type.tp_name    = "BMEdge";
1980         BPy_BMFace_Type.tp_name    = "BMFace";
1981         BPy_BMLoop_Type.tp_name    = "BMLoop";
1982         BPy_BMElemSeq_Type.tp_name = "BMElemSeq";
1983         BPy_BMIter_Type.tp_name    = "BMIter";
1984
1985
1986         BPy_BMesh_Type.tp_doc     = bpy_bmesh_doc;
1987         BPy_BMVert_Type.tp_doc    = bpy_bmvert_doc;
1988         BPy_BMEdge_Type.tp_doc    = bpy_bmedge_doc;
1989         BPy_BMFace_Type.tp_doc    = bpy_bmface_doc;
1990         BPy_BMLoop_Type.tp_doc    = bpy_bmloop_doc;
1991         BPy_BMElemSeq_Type.tp_doc = bpy_bmelemseq_doc;
1992         BPy_BMIter_Type.tp_doc    = bpy_bmiter_doc;
1993
1994
1995         BPy_BMesh_Type.tp_getset     = bpy_bmesh_getseters;
1996         BPy_BMVert_Type.tp_getset    = bpy_bmvert_getseters;
1997         BPy_BMEdge_Type.tp_getset    = bpy_bmedge_getseters;
1998         BPy_BMFace_Type.tp_getset    = bpy_bmface_getseters;
1999         BPy_BMLoop_Type.tp_getset    = bpy_bmloop_getseters;
2000         BPy_BMElemSeq_Type.tp_getset = NULL;
2001         BPy_BMIter_Type.tp_getset    = NULL;
2002
2003
2004         BPy_BMesh_Type.tp_methods     = bpy_bmesh_methods;
2005         BPy_BMVert_Type.tp_methods    = bpy_bmvert_methods;
2006         BPy_BMEdge_Type.tp_methods    = bpy_bmedge_methods;
2007         BPy_BMFace_Type.tp_methods    = bpy_bmface_methods;
2008         BPy_BMLoop_Type.tp_methods    = bpy_bmloop_methods;
2009         BPy_BMElemSeq_Type.tp_methods = bpy_bmelemseq_methods;
2010         BPy_BMIter_Type.tp_methods    = NULL;
2011
2012
2013         BPy_BMesh_Type.tp_hash     = NULL;
2014         BPy_BMVert_Type.tp_hash    = bpy_bm_elem_hash;
2015         BPy_BMEdge_Type.tp_hash    = bpy_bm_elem_hash;
2016         BPy_BMFace_Type.tp_hash    = bpy_bm_elem_hash;
2017         BPy_BMLoop_Type.tp_hash    = bpy_bm_elem_hash;
2018         BPy_BMElemSeq_Type.tp_hash = NULL;
2019         BPy_BMIter_Type.tp_hash    = NULL;
2020
2021         BPy_BMElemSeq_Type.tp_as_sequence = &bpy_bmelemseq_as_sequence;
2022
2023         BPy_BMElemSeq_Type.tp_as_mapping = &bpy_bmelemseq_as_mapping;
2024
2025         BPy_BMElemSeq_Type.tp_iter = (getiterfunc)bpy_bmelemseq_iter;
2026
2027         /* only 1 iteratir so far */
2028         BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bmiter_next;
2029
2030         BPy_BMesh_Type.tp_dealloc     = (destructor)bpy_bmesh_dealloc;
2031         BPy_BMVert_Type.tp_dealloc    = (destructor)bpy_bmvert_dealloc;
2032         BPy_BMEdge_Type.tp_dealloc    = (destructor)bpy_bmedge_dealloc;
2033         BPy_BMFace_Type.tp_dealloc    = (destructor)bpy_bmface_dealloc;
2034         BPy_BMLoop_Type.tp_dealloc    = (destructor)bpy_bmloop_dealloc;
2035         BPy_BMElemSeq_Type.tp_dealloc = (destructor)bpy_bmelemseq_dealloc;
2036         BPy_BMIter_Type.tp_dealloc    = NULL;
2037
2038         /*
2039         BPy_BMesh_Type.
2040         BPy_BMVert_Type.
2041         BPy_BMEdge_Type.
2042         BPy_BMFace_Type.
2043         BPy_BMLoop_Type.
2044         BPy_BMElemSeq_Type.
2045         BPy_BMIter_Type.
2046         */
2047
2048         BPy_BMesh_Type.tp_flags     = Py_TPFLAGS_DEFAULT;
2049         BPy_BMVert_Type.tp_flags    = Py_TPFLAGS_DEFAULT;
2050         BPy_BMEdge_Type.tp_flags    = Py_TPFLAGS_DEFAULT;
2051         BPy_BMFace_Type.tp_flags    = Py_TPFLAGS_DEFAULT;
2052         BPy_BMLoop_Type.tp_flags    = Py_TPFLAGS_DEFAULT;
2053         BPy_BMElemSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2054         BPy_BMIter_Type.tp_flags    = Py_TPFLAGS_DEFAULT;
2055
2056
2057         PyType_Ready(&BPy_BMesh_Type);
2058         PyType_Ready(&BPy_BMVert_Type);
2059         PyType_Ready(&BPy_BMEdge_Type);
2060         PyType_Ready(&BPy_BMFace_Type);
2061         PyType_Ready(&BPy_BMLoop_Type);
2062         PyType_Ready(&BPy_BMElemSeq_Type);
2063         PyType_Ready(&BPy_BMIter_Type);
2064 }
2065
2066 /* bmesh.types submodule
2067  * ********************* */
2068
2069 static struct PyModuleDef BPy_BM_types_module_def = {
2070     PyModuleDef_HEAD_INIT,
2071     "bmesh.types",  /* m_name */
2072     NULL,  /* m_doc */
2073     0,  /* m_size */
2074     NULL,  /* m_methods */
2075     NULL,  /* m_reload */
2076     NULL,  /* m_traverse */
2077     NULL,  /* m_clear */
2078     NULL,  /* m_free */
2079 };
2080
2081 PyObject *BPyInit_bmesh_types(void)
2082 {
2083         PyObject *submodule;
2084
2085         submodule = PyModule_Create(&BPy_BM_types_module_def);
2086
2087 #define mod_type_add(s, t) \
2088         PyModule_AddObject(s, t.tp_name, (PyObject *)&t); Py_INCREF((PyObject *)&t)
2089
2090         mod_type_add(submodule, BPy_BMesh_Type);
2091         mod_type_add(submodule, BPy_BMVert_Type);
2092         mod_type_add(submodule, BPy_BMEdge_Type);
2093         mod_type_add(submodule, BPy_BMFace_Type);
2094         mod_type_add(submodule, BPy_BMLoop_Type);
2095         mod_type_add(submodule, BPy_BMElemSeq_Type);
2096         mod_type_add(submodule, BPy_BMIter_Type);
2097
2098 #undef mod_type_add
2099
2100         return submodule;
2101 }
2102
2103 /* Utility Functions
2104  * ***************** */
2105
2106 PyObject *BPy_BMesh_CreatePyObject(BMesh *bm)
2107 {
2108         BPy_BMesh *self;
2109
2110         if (bm->py_handle) {
2111                 self = bm->py_handle;
2112                 Py_INCREF(self);
2113         }
2114         else {
2115                 self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
2116                 self->bm = bm;
2117
2118                 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2119                 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2120                 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2121                 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
2122         }
2123
2124         return (PyObject *)self;
2125 }
2126
2127
2128
2129 PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
2130 {
2131         BPy_BMVert *self;
2132
2133         void **ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
2134
2135         /* bmesh may free layers, ensure we have one to store ourself */
2136         if (UNLIKELY(ptr == NULL)) {
2137                 BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR);
2138                 ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR);
2139         }
2140
2141         if (*ptr != NULL) {
2142                 self = *ptr;
2143                 Py_INCREF(self);
2144         }
2145         else {
2146                 self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type);
2147                 BLI_assert(v != NULL);
2148                 self->bm = bm;
2149                 self->v  = v;
2150                 *ptr = self;
2151         }
2152         return (PyObject *)self;
2153 }
2154
2155 PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
2156 {
2157         BPy_BMEdge *self;
2158
2159         void **ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
2160
2161         /* bmesh may free layers, ensure we have one to store ourself */
2162         if (UNLIKELY(ptr == NULL)) {
2163                 BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR);
2164                 ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR);
2165         }
2166
2167         if (*ptr != NULL) {
2168                 self = *ptr;
2169                 Py_INCREF(self);
2170         }
2171         else {
2172                 self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type);
2173                 BLI_assert(e != NULL);
2174                 self->bm = bm;
2175                 self->e  = e;
2176                 *ptr = self;
2177         }
2178         return (PyObject *)self;
2179 }
2180
2181 PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
2182 {
2183         BPy_BMFace *self;
2184
2185         void **ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
2186
2187         /* bmesh may free layers, ensure we have one to store ourself */
2188         if (UNLIKELY(ptr == NULL)) {
2189                 BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR);
2190                 ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR);
2191         }
2192
2193         if (*ptr != NULL) {
2194                 self = *ptr;
2195                 Py_INCREF(self);
2196         }
2197         else {
2198                 self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type);
2199                 BLI_assert(f != NULL);
2200                 self->bm = bm;
2201                 self->f  = f;
2202                 *ptr = self;
2203         }
2204         return (PyObject *)self;
2205 }
2206
2207 PyObject *BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
2208 {
2209         BPy_BMLoop *self;
2210
2211         void **ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
2212
2213         /* bmesh may free layers, ensure we have one to store ourself */
2214         if (UNLIKELY(ptr == NULL)) {
2215                 BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR);
2216                 ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR);
2217         }
2218
2219         if (*ptr != NULL) {
2220                 self = *ptr;
2221                 Py_INCREF(self);
2222         }
2223         else {
2224                 self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type);
2225                 BLI_assert(l != NULL);
2226                 self->bm = bm;
2227                 self->l  = l;
2228                 *ptr = self;
2229         }
2230         return (PyObject *)self;
2231 }
2232
2233 PyObject *BPy_BMElemSeq_CreatePyObject(BMesh *bm, BPy_BMElem *py_ele, const char itype)
2234 {
2235         BPy_BMElemSeq *self = PyObject_New(BPy_BMElemSeq, &BPy_BMElemSeq_Type);
2236         self->bm = bm;
2237         self->py_ele = py_ele; /* can be NULL */
2238         self->itype = itype;
2239         Py_XINCREF(py_ele);
2240         return (PyObject *)self;
2241 }
2242
2243 PyObject *BPy_BMIter_CreatePyObject(BMesh *bm)
2244 {
2245         BPy_BMIter *self = PyObject_New(BPy_BMIter, &BPy_BMIter_Type);
2246         self->bm = bm;
2247         /* caller must initialize 'iter' member */
2248         return (PyObject *)self;
2249 }
2250
2251 /* this is just a helper func */
2252 PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele)
2253 {
2254         switch (ele->htype) {
2255                 case BM_VERT:
2256                         return BPy_BMVert_CreatePyObject(bm, (BMVert *)ele);
2257                 case BM_EDGE:
2258                         return BPy_BMEdge_CreatePyObject(bm, (BMEdge *)ele);
2259                 case BM_FACE:
2260                         return BPy_BMFace_CreatePyObject(bm, (BMFace *)ele);
2261                 case BM_LOOP:
2262                         return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele);
2263                 default:
2264                         PyErr_SetString(PyExc_SystemError, "internal error");
2265                         return NULL;
2266         }
2267 }
2268
2269 int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
2270 {
2271         if (self->bm) {
2272                 return 0;
2273         }
2274         PyErr_Format(PyExc_ReferenceError,
2275                      "BMesh data of type %.200s has been removed",
2276                      Py_TYPE(self)->tp_name);
2277         return -1;
2278 }
2279
2280 void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
2281 {
2282         self->bm = NULL;
2283 }
2284
2285 /* generic python seq as BMVert/Edge/Face array,
2286  * return value must be freed with PyMem_FREE(...);
2287  *
2288  * The 'bm_r' value is assigned when empty, and used when set.
2289  */
2290 void *BPy_BMElem_PySeq_As_Array(BMesh **r_bm, PyObject *seq, Py_ssize_t min, Py_ssize_t max, Py_ssize_t *r_size,
2291                                 PyTypeObject *type,
2292                                 const char do_unique_check, const char do_bm_check,
2293                                 const char *error_prefix)
2294 {
2295         BMesh *bm = (r_bm && *r_bm) ? *r_bm : NULL;
2296         PyObject *seq_fast;
2297         *r_size = 0;
2298
2299         if (!(seq_fast=PySequence_Fast(seq, error_prefix))) {
2300                 return NULL;
2301         }
2302         else {
2303                 Py_ssize_t seq_len;
2304                 Py_ssize_t i;
2305
2306                 BPy_BMElem *item;
2307                 BMElem **alloc;
2308
2309                 seq_len = PySequence_Fast_GET_SIZE(seq_fast);
2310
2311                 if (seq_len < min || seq_len > max) {
2312                         PyErr_Format(PyExc_TypeError,
2313                                      "%s: sequence incorrect size, expected [%d - %d], given %d",
2314                                      error_prefix, min, max, seq_len);
2315                         return NULL;
2316                 }
2317
2318
2319                 /* from now on, use goto */
2320                 alloc = PyMem_MALLOC(seq_len * sizeof(BPy_BMElem **));
2321
2322                 for (i = 0; i < seq_len; i++) {
2323                         item = (BPy_BMElem *)PySequence_Fast_GET_ITEM(seq_fast, i);
2324
2325                         if (Py_TYPE(item) != type) {
2326                                 PyErr_Format(PyExc_TypeError,
2327                                              "%s: expected '%.200', not '%.200s'",
2328                                              error_prefix, type->tp_name, Py_TYPE(item)->tp_name);
2329                                 goto err_cleanup;
2330                         }
2331                         else if (item->bm == NULL) {
2332                                 PyErr_Format(PyExc_TypeError,
2333                                              "%s: %d %s has been removed",
2334                                              error_prefix, i, type->tp_name);
2335                                 goto err_cleanup;
2336                         }
2337                         /* trick so we can ensure all items have the same mesh,
2338                          * and allows us to pass the 'bm' as NULL. */
2339                         else if (do_bm_check && (bm  && bm != item->bm)) {
2340                                 PyErr_Format(PyExc_TypeError,
2341                                              "%s: %d %s is from another mesh",
2342                                              error_prefix, i, type->tp_name);
2343                                 goto err_cleanup;
2344                         }
2345
2346                         if (bm == NULL) {
2347                                 bm = item->bm;
2348                         }
2349
2350                         alloc[i] = item->ele;
2351
2352                         if (do_unique_check) {
2353                                 BM_elem_flag_enable(item->ele, BM_ELEM_TAG);
2354                         }
2355                 }
2356
2357                 if (do_unique_check) {
2358                         /* check for double verts! */
2359                         int ok = TRUE;
2360                         for (i = 0; i < seq_len; i++) {
2361                                 if (UNLIKELY(BM_elem_flag_test(alloc[i], BM_ELEM_TAG) == FALSE)) {
2362                                         ok = FALSE;
2363                                 }
2364
2365                                 /* ensure we dont leave this enabled */
2366                                 BM_elem_flag_disable(alloc[i], BM_ELEM_TAG);
2367                         }
2368
2369                         if (ok == FALSE) {
2370                                 PyErr_Format(PyExc_ValueError,
2371                                              "%s: found the same %s used multiple times",
2372                                              error_prefix, type->tp_name);
2373                                 goto err_cleanup;
2374                         }
2375                 }
2376
2377                 Py_DECREF(seq_fast);
2378                 *r_size = seq_len;
2379                 if (r_bm) *r_bm = bm;
2380                 return alloc;
2381
2382 err_cleanup:
2383                 Py_DECREF(seq_fast);
2384                 PyMem_FREE(alloc);
2385                 return NULL;
2386         }
2387 }