Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/python/CMakeLists.txt1
-rw-r--r--source/blender/python/SConscript8
-rw-r--r--source/blender/python/bmesh/CMakeLists.txt43
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.c97
-rw-r--r--source/blender/python/bmesh/bmesh_py_api.h35
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.c1310
-rw-r--r--source/blender/python/bmesh/bmesh_py_types.h124
-rw-r--r--source/blender/python/intern/bpy_interface.c3
-rw-r--r--source/creator/CMakeLists.txt1
9 files changed, 1620 insertions, 2 deletions
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt
index 8071edb378f..e855f3a3756 100644
--- a/source/blender/python/CMakeLists.txt
+++ b/source/blender/python/CMakeLists.txt
@@ -19,3 +19,4 @@
add_subdirectory(intern)
add_subdirectory(generic)
add_subdirectory(mathutils)
+add_subdirectory(bmesh)
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 2a47c2dcb96..996ee542769 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -5,12 +5,18 @@
Import ('env')
incs = '. ../editors/include ../makesdna ../makesrna ../blenfont ../blenlib ../blenkernel ../nodes'
-incs += ' ../imbuf ../blenloader ../gpu ../render/extern/include ../windowmanager'
+incs += ' ../imbuf ../blenloader ../bmesh ../gpu ../render/extern/include ../windowmanager'
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include #intern/cycles/blender'
incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC']
is_debug = (env['OURPLATFORM'] in ('win32-mingw', 'win32-vc','win64-vc') and env['BF_DEBUG'])
+# bmesh
+defs = []
+
+sources = env.Glob('bmesh/*.c')
+env.BlenderLib( libname = 'bf_python_bmesh', sources = Split(sources), includes = Split(incs), defines = defs, libtype = ['core','player'], priority = [362,165])
+
# generic
defs = []
diff --git a/source/blender/python/bmesh/CMakeLists.txt b/source/blender/python/bmesh/CMakeLists.txt
new file mode 100644
index 00000000000..31e108cf3ae
--- /dev/null
+++ b/source/blender/python/bmesh/CMakeLists.txt
@@ -0,0 +1,43 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Campbell Barton
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../../bmesh
+ ../../blenkernel
+ ../../blenlib
+ ../../blenloader
+ ../../makesdna
+ ../../../../intern/guardedalloc
+)
+
+set(INC_SYS
+ ${PYTHON_INCLUDE_DIRS}
+)
+
+set(SRC
+ bmesh_py_api.c
+ bmesh_py_types.c
+
+ bmesh_py_api.h
+ bmesh_py_types.h
+)
+
+blender_add_lib(bf_python_bmesh "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c
new file mode 100644
index 00000000000..8534bbefd3b
--- /dev/null
+++ b/source/blender/python/bmesh/bmesh_py_api.c
@@ -0,0 +1,97 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/generic/blf_py_api.c
+ * \ingroup pygen
+ *
+ * This file defines the 'bme' bmesh main module.
+ */
+
+#include <Python.h>
+
+#include "bmesh.h"
+
+#include "bmesh_py_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_tessmesh.h"
+
+#include "DNA_mesh_types.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "bmesh_py_api.h" /* own include */
+
+PyDoc_STRVAR(bpy_bm_from_mesh_doc,
+".. method:: from_mesh(mesh)\n"
+"\n"
+" todo.\n"
+);
+
+static PyObject *bpy_bm_from_mesh(PyObject *UNUSED(self), PyObject *value)
+{
+ Mesh *me = PyC_RNA_AsPointer(value, "Mesh");
+
+ /* temp! */
+ if (!me->edit_btmesh) {
+ PyErr_SetString(PyExc_ValueError,
+ "Mesh is not in editmode");
+ return NULL;
+ }
+
+ return BPy_BMesh_CreatePyObject(me->edit_btmesh->bm);
+}
+
+static struct PyMethodDef BPy_BM_methods[] = {
+ {"from_mesh", (PyCFunction)bpy_bm_from_mesh, METH_O, bpy_bm_from_mesh_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+PyDoc_STRVAR(BPy_BM_doc,
+"This module provides access to blenders bmesh data structures."
+);
+static struct PyModuleDef BPy_BM_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "bme", /* m_name */
+ BPy_BM_doc, /* m_doc */
+ 0, /* m_size */
+ BPy_BM_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+PyObject *BPyInit_bmesh(void)
+{
+ PyObject *submodule;
+
+ BPy_BM_init_types();
+
+ submodule = PyModule_Create(&BPy_BM_module_def);
+
+ return submodule;
+}
diff --git a/source/blender/python/bmesh/bmesh_py_api.h b/source/blender/python/bmesh/bmesh_py_api.h
new file mode 100644
index 00000000000..0923af06186
--- /dev/null
+++ b/source/blender/python/bmesh/bmesh_py_api.h
@@ -0,0 +1,35 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/bmesh/bme.h
+ * \ingroup pybmesh
+ */
+
+#ifndef __BMESH_PY_API_H__
+#define __BMESH_PY_API_H__
+
+PyObject *BPyInit_bmesh(void);
+
+#endif /* __BMESH_PY_API_H__ */
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
new file mode 100644
index 00000000000..55c5827cb44
--- /dev/null
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -0,0 +1,1310 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/bmesh/bme_types.c
+ * \ingroup pybmesh
+ */
+
+#include <Python.h>
+
+#include "BLI_math.h"
+
+#include "bmesh.h"
+
+#include "../mathutils/mathutils.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "bmesh_py_types.h" /* own include */
+
+/* Common Flags
+ * ************ */
+
+/* scene does not use BM_* flags. */
+PyC_FlagSet bpy_bm_scene_vert_edge_face_flags[] = {
+ {1, "VERT"},
+ {2, "EDGE"},
+ {4, "FACE"},
+ {0, NULL}
+};
+
+PyC_FlagSet bpy_bm_htype_vert_edge_face_flags[] = {
+ {BM_VERT, "VERT"},
+ {BM_EDGE, "EDGE"},
+ {BM_FACE, "FACE"},
+ {0, NULL}
+};
+
+PyC_FlagSet bpy_bm_htype_all_flags[] = {
+ {BM_VERT, "VERT"},
+ {BM_LOOP, "EDGE"},
+ {BM_FACE, "FACE"},
+ {BM_LOOP, "LOOP"},
+ {0, NULL}
+};
+
+PyC_FlagSet bpy_bm_hflag_all_flags[] = {
+ {BM_ELEM_SELECT, "SELECT"},
+ {BM_ELEM_HIDDEN, "HIDE"},
+ {BM_ELEM_SEAM, "SEAM"},
+ {BM_ELEM_SMOOTH, "SMOOTH"},
+ {BM_ELEM_TAG, "TAG"},
+ {0, NULL}
+};
+
+/* py-type definitions
+ * ******************* */
+
+/* getseters
+ * ========= */
+
+
+/* bmesh elems
+ * ----------- */
+
+PyDoc_STRVAR(bpy_bm_elem_select_doc, "Selected state of this element (boolean)");
+PyDoc_STRVAR(bpy_bm_elem_hide_doc, "Hidden state of this element (boolean)");
+PyDoc_STRVAR(bpy_bm_elem_tag_doc, "Tag state of this element (boolean)");
+PyDoc_STRVAR(bpy_bm_elem_smooth_doc, "Smooth state of this element (boolean)");
+PyDoc_STRVAR(bpy_bm_elem_index_doc, "Index of this element");
+
+
+static PyObject *bpy_bm_elem_hflag_get(BPy_BMElem *self, void *flag)
+{
+ const char hflag = (char)GET_INT_FROM_POINTER(flag);
+
+ BPY_BM_CHECK_OBJ(self);
+
+ return PyBool_FromLong(BM_elem_flag_test(self->ele, hflag));
+}
+
+static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag)
+{
+ const char hflag = (char)GET_INT_FROM_POINTER(flag);
+ int param;
+
+ BPY_BM_CHECK_INT(self);
+
+ param = PyLong_AsLong(value);
+
+ if (param == TRUE) {
+ BM_elem_flag_enable(self->ele, hflag);
+ return 0;
+ }
+ else if (param == FALSE) {
+ BM_elem_flag_disable(self->ele, hflag);
+ return 0;
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "expected True/False or 0/1, not %.200s",
+ Py_TYPE(value)->tp_name);
+ return -1;
+ }
+}
+
+static PyObject *bpy_bm_elem_index_get(BPy_BMElem *self, void *UNUSED(flag))
+{
+ BPY_BM_CHECK_OBJ(self);
+
+ return PyLong_FromLong(BM_elem_index_get(self->ele));
+}
+
+static int bpy_bm_elem_index_set(BPy_BMElem *self, PyObject *value, void *UNUSED(flag))
+{
+ int param;
+
+ BPY_BM_CHECK_INT(self);
+
+ param = PyLong_AsLong(value);
+
+ if (param == -1 && PyErr_Occurred()) {
+ PyErr_SetString(PyExc_TypeError, "expected an int type");
+ return -1;
+ }
+ else {
+ BM_elem_index_set(self->ele, param);
+
+ /* when setting the index assume its set invalid */
+ if (self->ele->htype & (BM_VERT | BM_EDGE | BM_FACE)) {
+ self->bm->elem_index_dirty |= self->ele->htype;
+ }
+
+ return 0;
+ }
+}
+
+/* type spesific get/sets
+ * ---------------------- */
+
+
+/* Mesh
+ * ^^^^ */
+
+PyDoc_STRVAR(bpy_bmesh_verts_doc,
+"The :class:`bme.types.BMVertSeq` object this mesh"
+);
+static PyObject *bpy_bmesh_verts_get(BPy_BMesh *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return BPy_BMVertSeq_CreatePyObject(self->bm);
+}
+
+PyDoc_STRVAR(bpy_bmesh_edges_doc,
+"The :class:`bme.types.BMEdgeSeq` object this mesh"
+);
+static PyObject *bpy_bmesh_edges_get(BPy_BMesh *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return BPy_BMEdgeSeq_CreatePyObject(self->bm);
+}
+
+PyDoc_STRVAR(bpy_bmesh_faces_doc,
+"The :class:`bme.types.BMFaceSeq` object this mesh"
+);
+static PyObject *bpy_bmesh_faces_get(BPy_BMesh *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return BPy_BMFaceSeq_CreatePyObject(self->bm);
+}
+
+PyDoc_STRVAR(bpy_bmesh_select_mode_doc,
+"The selection mode for this mesh"
+);
+static PyObject *bpy_bmesh_select_mode_get(BPy_BMesh *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+
+ return PyC_FlagSet_FromBitfield(bpy_bm_scene_vert_edge_face_flags, self->bm->selectmode);
+}
+
+static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value)
+{
+ int flag = 0;
+ BPY_BM_CHECK_INT(self);
+
+ if (PyC_FlagSet_ToBitfield(bpy_bm_scene_vert_edge_face_flags, value, &flag, "bm.select_mode") == -1) {
+ return -1;
+ }
+ else if (flag == 0) {
+ PyErr_SetString(PyExc_TypeError, "bm.select_mode: cant assignt an empty value");
+ return -1;
+ }
+ else {
+ self->bm->selectmode = flag;
+ return 0;
+ }
+}
+
+
+/* Vert
+ * ^^^^ */
+
+PyDoc_STRVAR(bpy_bmvert_co_doc,
+"The coordinates for this vertex"
+);
+static PyObject *bpy_bmvert_co_get(BPy_BMVert *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return Vector_CreatePyObject(self->v->co, 3, Py_WRAP, NULL);
+}
+
+static int bpy_bmvert_co_set(BPy_BMVert *self, PyObject *value)
+{
+ BPY_BM_CHECK_INT(self);
+
+ if (mathutils_array_parse(self->v->co, 3, 3, value, "BMVert.co") != -1) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+PyDoc_STRVAR(bpy_bmvert_normal_doc,
+"The normal for this vertex"
+);
+static PyObject *bpy_bmvert_normal_get(BPy_BMVert *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return Vector_CreatePyObject(self->v->no, 3, Py_WRAP, NULL);
+}
+
+static int bpy_bmvert_normal_set(BPy_BMVert *self, PyObject *value)
+{
+ BPY_BM_CHECK_INT(self);
+
+ if (mathutils_array_parse(self->v->no, 3, 3, value, "BMVert.normal") != -1) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+/* Face
+ * ^^^^ */
+
+PyDoc_STRVAR(bpy_bmface_normal_doc,
+"The normal for this face"
+);
+static PyObject *bpy_bmface_normal_get(BPy_BMFace *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+ return Vector_CreatePyObject(self->f->no, 3, Py_WRAP, NULL);
+}
+
+static int bpy_bmface_normal_set(BPy_BMFace *self, PyObject *value)
+{
+ BPY_BM_CHECK_INT(self);
+
+ if (mathutils_array_parse(self->f->no, 3, 3, value, "BMFace.normal") != -1) {
+ return 0;
+ }
+ else {
+ return -1;
+ }
+}
+
+static PyGetSetDef bpy_bmesh_getseters[] = {
+ {(char *)"verts", (getter)bpy_bmesh_verts_get, (setter)NULL, (char *)bpy_bmesh_verts_doc, NULL},
+ {(char *)"edges", (getter)bpy_bmesh_edges_get, (setter)NULL, (char *)bpy_bmesh_edges_doc, NULL},
+ {(char *)"faces", (getter)bpy_bmesh_faces_get, (setter)NULL, (char *)bpy_bmesh_faces_doc, NULL},
+ {(char *)"select_mode", (getter)bpy_bmesh_select_mode_get, (setter)bpy_bmesh_select_mode_set, (char *)bpy_bmesh_select_mode_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+static PyGetSetDef bpy_bmvert_getseters[] = {
+ /* generic */
+ {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
+ {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
+
+ {(char *)"co", (getter)bpy_bmvert_co_get, (setter)bpy_bmvert_co_set, (char *)bpy_bmvert_co_doc, NULL},
+ {(char *)"normal", (getter)bpy_bmvert_normal_get, (setter)bpy_bmvert_normal_set, (char *)bpy_bmvert_normal_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+static PyGetSetDef bpy_bmedge_getseters[] = {
+ /* generic */
+ {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
+ {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
+
+ {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
+ {(char *)"seam", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SEAM},
+
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+static PyGetSetDef bpy_bmface_getseters[] = {
+ /* generic */
+ {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
+ {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
+
+ {(char *)"smooth", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_smooth_doc, (void *)BM_ELEM_SMOOTH},
+
+ {(char *)"normal", (getter)bpy_bmface_normal_get, (setter)bpy_bmface_normal_set, (char *)bpy_bmface_normal_doc, NULL},
+
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+static PyGetSetDef bpy_bmloop_getseters[] = {
+ /* generic */
+ {(char *)"select", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_select_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"hide", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_hide_doc, (void *)BM_ELEM_SELECT},
+ {(char *)"tag", (getter)bpy_bm_elem_hflag_get, (setter)bpy_bm_elem_hflag_set, (char *)bpy_bm_elem_tag_doc, (void *)BM_ELEM_TAG},
+ {(char *)"index", (getter)bpy_bm_elem_index_get, (setter)bpy_bm_elem_index_set, (char *)bpy_bm_elem_index_doc, NULL},
+ {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
+};
+
+
+/* Methods
+ * ======= */
+
+/* Mesh
+ * ---- */
+
+PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc,
+".. method:: select_flush_mode()\n"
+"\n"
+" todo.\n"
+);
+static PyObject *bpy_bmesh_select_flush_mode(BPy_BMesh *self)
+{
+ BPY_BM_CHECK_OBJ(self);
+
+ BM_mesh_select_mode_flush(self->bm);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpy_bmesh_select_flush_doc,
+".. method:: select_flush(select)\n"
+"\n"
+" todo.\n"
+);
+static PyObject *bpy_bmesh_select_flush(BPy_BMesh *self, PyObject *value)
+{
+ int param;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ param = PyLong_AsLong(value);
+ if (param != FALSE && param != TRUE) {
+ PyErr_SetString(PyExc_TypeError, "expected a boolean type 0/1");
+ return NULL;
+ }
+
+ if (param) BM_mesh_select_flush(self->bm);
+ else BM_mesh_deselect_flush(self->bm);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpy_bmesh_update_doc,
+".. method:: update(index=False, normals=False)\n"
+"\n"
+" Update mesh data.\n"
+);
+static PyObject *bpy_bmesh_update(BPy_BMElem *self, PyObject *args, PyObject *kw)
+{
+ static const char *kwlist[] = {"normals", "index", NULL};
+
+ int do_normals = FALSE;
+
+ PyObject *index_flags = NULL;
+ int do_index_hflag = 0;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw,
+ "|iO:update",
+ (char **)kwlist,
+ &do_normals, &index_flags))
+ {
+ return NULL;
+ }
+
+ if (index_flags) {
+ if (PyC_FlagSet_ToBitfield(bpy_bm_htype_vert_edge_face_flags, index_flags,
+ &do_index_hflag, "bm.update(index=...)") == -1)
+ {
+ return NULL;
+ }
+ }
+
+ if (do_normals) {
+ BM_mesh_normals_update(self->bm);
+ }
+
+ if (do_index_hflag) {
+ BM_mesh_elem_index_ensure(self->bm, (char)do_index_hflag);
+ }
+
+ Py_RETURN_NONE;
+}
+
+
+PyDoc_STRVAR(bpy_bmesh_transform_doc,
+".. method:: transform(matrix, filter=None)\n"
+"\n"
+" Transform the mesh (optionally filtering flagged data only).\n"
+"\n"
+" :arg matrix: transform matrix.\n"
+" :type matrix: 4x4 :class:`mathutils.Matrix`"
+" :arg filter: set of values in ('SELECT', 'HIDE', 'SEAM', 'SMOOTH', 'TAG').\n"
+" :type filter: set\n"
+);
+static PyObject *bpy_bmesh_transform(BPy_BMElem *self, PyObject *args, PyObject *kw)
+{
+ static const char *kwlist[] = {"matrix", "filter", NULL};
+
+ MatrixObject *mat;
+ PyObject *filter = NULL;
+ int filter_flags = 0;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ if (!PyArg_ParseTupleAndKeywords(args, kw,
+ "O!|O!:transform",
+ (char **)kwlist,
+ &matrix_Type, &mat,
+ &PySet_Type, &filter))
+ {
+ return NULL;
+ }
+ else {
+ BMVert *eve;
+ BMIter iter;
+ void *mat_ptr;
+
+ if (BaseMath_ReadCallback(mat) == -1) {
+ return NULL;
+ }
+ else if (mat->num_col != 4 || mat->num_row != 4) {
+ PyErr_SetString(PyExc_ValueError, "expected a 4x4 matrix");
+ return NULL;
+ }
+
+ if (filter != NULL && PyC_FlagSet_ToBitfield(bpy_bm_hflag_all_flags, filter,
+ &filter_flags, "bm.transform") == -1)
+ {
+ return NULL;
+ }
+
+ mat_ptr = mat->matrix;
+
+ if (!filter_flags) {
+ BM_ITER(eve, &iter, self->bm, BM_VERTS_OF_MESH, NULL) {
+ mul_m4_v3((float (*)[4])mat_ptr, eve->co);
+ }
+ }
+ else {
+ char filter_flags_ch = (char)filter_flags;
+ BM_ITER(eve, &iter, self->bm, BM_VERTS_OF_MESH, NULL) {
+ if (eve->head.hflag & filter_flags_ch) {
+ mul_m4_v3((float (*)[4])mat_ptr, eve->co);
+ }
+ }
+ }
+ }
+
+ Py_RETURN_NONE;
+}
+
+/* Elem
+ * ---- */
+
+PyDoc_STRVAR(bpy_bm_elem_select_set_doc,
+".. method:: select_set(select)\n"
+"\n"
+" Set the selection and update assosiated geometry.\n"
+);
+static PyObject *bpy_bm_elem_select_set(BPy_BMElem *self, PyObject *value)
+{
+ int param;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ param = PyLong_AsLong(value);
+ if (param != FALSE && param != TRUE) {
+ PyErr_SetString(PyExc_TypeError, "expected a boolean type 0/1");
+ return NULL;
+ }
+
+ BM_elem_select_set(self->bm, self->ele, param);
+
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(bpy_bm_elem_copy_from_doc,
+".. method:: copy_from(select)\n"
+"\n"
+" Copy values from another element.\n"
+);
+static PyObject *bpy_bm_elem_copy_from(BPy_BMElem *self, BPy_BMElem *value)
+{
+ BPY_BM_CHECK_OBJ(self);
+
+ if (Py_TYPE(self) != Py_TYPE(value)) {
+ PyErr_Format(PyExc_TypeError,
+ "expected element of type '%.200s' not '%.200s'",
+ Py_TYPE(self)->tp_name, Py_TYPE(value)->tp_name);
+ return NULL;
+ }
+
+ BM_elem_attrs_copy(value->bm, self->bm, value->ele, self->ele);
+
+ Py_RETURN_NONE;
+}
+
+/* Vert Seq
+ * -------- */
+
+PyDoc_STRVAR(bpy_bmvert_seq_new_doc,
+".. method:: new()\n"
+"\n"
+" Create a new vertex.\n"
+);
+static PyObject *bpy_bmvert_seq_new(BPy_BMGeneric *self, PyObject *args)
+{
+ PyObject *py_co = NULL;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ if(!PyArg_ParseTuple(args, "|O:verts.new", py_co)) {
+ return NULL;
+ }
+ else {
+ BMesh *bm = self->bm;
+ BMVert *v;
+ float co[3] = {0.0f, 0.0f, 0.0f};
+
+ if (py_co && mathutils_array_parse(co, 3, 3, py_co, "verts.new(co)") != -1) {
+ return NULL;
+ }
+
+ v = BM_vert_create(bm, co, NULL);
+
+ if (v == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "faces.new(verts): couldn't create the new face, internal error");
+ return NULL;
+ }
+
+ return BPy_BMVert_CreatePyObject(bm, v);
+ }
+}
+
+/* Edge Seq
+ * -------- */
+
+PyDoc_STRVAR(bpy_bmedge_seq_new_doc,
+".. method:: new()\n"
+"\n"
+" Create a new edge.\n"
+);
+static PyObject *bpy_bmedge_seq_new(BPy_BMGeneric *self, PyObject *args)
+{
+ BPy_BMVert *v1;
+ BPy_BMVert *v2;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ if(!PyArg_ParseTuple(args, "O!O!:edges.new",
+ &BPy_BMVert_Type, &v1,
+ &BPy_BMVert_Type, &v2))
+ {
+ return NULL;
+ }
+ else {
+ BMesh *bm = self->bm;
+ BMEdge *e;
+
+ if (v1->v == v2->v) {
+ PyErr_SetString(PyExc_ValueError,
+ "edges.new(): both verts are the same");
+ }
+
+ if (!(bm == v1->bm && bm == v2->bm)) {
+ PyErr_SetString(PyExc_ValueError,
+ "edges.new(): both verts must be from this mesh");
+ }
+
+ if (BM_edge_exists(v1->v, v2->v)) {
+ PyErr_SetString(PyExc_ValueError,
+ "edges.new(): this edge exists");
+ }
+
+ e = BM_edge_create(bm, v1->v, v2->v, NULL, FALSE);
+
+ if (e == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "faces.new(verts): couldn't create the new face, internal error");
+ return NULL;
+ }
+
+ return BPy_BMEdge_CreatePyObject(bm, e);
+ }
+}
+
+/* Edge Seq
+ * -------- */
+
+PyDoc_STRVAR(bpy_bmface_seq_new_doc,
+".. method:: new()\n"
+"\n"
+" Create a new face.\n"
+);
+static PyObject *bpy_bmface_seq_new(BPy_BMGeneric *self, PyObject *args)
+{
+ PyObject *vert_seq;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ if(!PyArg_ParseTuple(args, "O:faces.new", &vert_seq)) {
+ return NULL;
+ }
+ else {
+ BMesh *bm = self->bm;
+ PyObject *vert_seq_fast;
+ Py_ssize_t vert_seq_len;
+ Py_ssize_t i, i_prev;
+
+ void *alloc;
+ BMVert **vert_array;
+ BMEdge **edge_array;
+
+ BPy_BMVert *item;
+ PyObject *ret = NULL;
+ int ok;
+
+ BMFace *f;
+
+ if (!(vert_seq_fast=PySequence_Fast(vert_seq, "faces.new(...)"))) {
+ return NULL;
+ }
+
+ vert_seq_len = PySequence_Fast_GET_SIZE(vert_seq_fast);
+
+ alloc = PyMem_MALLOC(vert_seq_len * sizeof(BMVert **) + vert_seq_len * sizeof(BMEdge **));
+
+ vert_array = (BMVert **) alloc;
+ edge_array = (BMEdge **) &(((BMVert **)alloc)[vert_seq_len]);
+
+ /* --- */
+ for (i = 0; i < vert_seq_len; i++) {
+ item = (BPy_BMVert *)PySequence_Fast_GET_ITEM(vert_seq_fast, i);
+
+ if (!BPy_BMVert_Check(item)) {
+ PyErr_Format(PyExc_TypeError,
+ "faces.new(verts): expected BMVert sequence, not '%.200s'",
+ Py_TYPE(item)->tp_name);
+ }
+ else if (item->bm != bm) {
+ PyErr_Format(PyExc_TypeError,
+ "faces.new(verts): %d vertex is from another mesh", i);
+ }
+
+ vert_array[i] = item->v;
+
+ BM_elem_flag_enable(item->v, BM_ELEM_TAG);
+ }
+
+ /* check for double verts! */
+ ok = TRUE;
+ for (i = 0; i < vert_seq_len; i++) {
+ if (UNLIKELY(BM_elem_flag_test(vert_array[i], BM_ELEM_TAG) == FALSE)) {
+ ok = FALSE;
+ }
+ BM_elem_flag_disable(item->v, BM_ELEM_TAG);
+ }
+
+ if (ok == FALSE) {
+ PyErr_SetString(PyExc_ValueError,
+ "faces.new(verts): found the same vertex used multiple times");
+ goto cleanup;
+ }
+
+ /* check if the face exists */
+ if (BM_face_exists(bm, vert_array, vert_seq_len, NULL)) {
+ PyErr_SetString(PyExc_ValueError,
+ "faces.new(verts): face already exists");
+ goto cleanup;
+ }
+
+
+ /* Go ahead and make the face!
+ * --------------------------- */
+
+ /* ensure edges */
+ ok = TRUE;
+ for (i = 0, i_prev = vert_seq_len - 1; i < vert_seq_len; (i_prev=i++)) {
+ edge_array[i] = BM_edge_create(bm, vert_array[i], vert_array[i_prev], NULL, TRUE);
+ }
+
+ f = BM_face_create(bm, vert_array, edge_array, vert_seq_len, FALSE);
+
+ if (f == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "faces.new(verts): couldn't create the new face, internal error");
+ goto cleanup;
+ }
+
+ ret = BPy_BMFace_CreatePyObject(bm, f);
+
+ /* pass through */
+cleanup:
+ Py_DECREF(vert_seq_fast);
+ PyMem_FREE(alloc);
+ return ret;
+ }
+}
+
+
+
+
+static struct PyMethodDef bpy_bmesh_methods[] = {
+ {"select_flush_mode", (PyCFunction)bpy_bmesh_select_flush_mode, METH_NOARGS, bpy_bmesh_select_flush_mode_doc},
+ {"select_flush", (PyCFunction)bpy_bmesh_select_flush, METH_O, bpy_bmesh_select_flush_doc},
+ {"update", (PyCFunction)bpy_bmesh_update, METH_VARARGS|METH_KEYWORDS, bpy_bmesh_update_doc},
+ {"transform", (PyCFunction)bpy_bmesh_transform, METH_VARARGS|METH_KEYWORDS, bpy_bmesh_transform_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyMethodDef bpy_bmvert_methods[] = {
+ {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
+ {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyMethodDef bpy_bmedge_methods[] = {
+ {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
+ {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyMethodDef bpy_bmface_methods[] = {
+ {"select_set", (PyCFunction)bpy_bm_elem_select_set, METH_O, bpy_bm_elem_select_set_doc},
+ {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyMethodDef bpy_bmloop_methods[] = {
+ {"copy_from", (PyCFunction)bpy_bm_elem_copy_from, METH_O, bpy_bm_elem_copy_from_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyMethodDef bpy_bmvert_seq_methods[] = {
+ {"new", (PyCFunction)bpy_bmvert_seq_new, METH_VARARGS, bpy_bmvert_seq_new_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyMethodDef bpy_bmedge_seq_methods[] = {
+ {"new", (PyCFunction)bpy_bmedge_seq_new, METH_VARARGS, bpy_bmedge_seq_new_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyMethodDef bpy_bmface_seq_methods[] = {
+ {"new", (PyCFunction)bpy_bmface_seq_new, METH_VARARGS, bpy_bmface_seq_new_doc},
+ {NULL, NULL, 0, NULL}
+};
+
+/* Sequences
+ * ========= */
+
+static Py_ssize_t bpy_bmvert_seq_length(BPy_BMGeneric *self)
+{
+ BPY_BM_CHECK_INT(self);
+ return self->bm->totvert;
+}
+static Py_ssize_t bpy_bmedge_seq_length(BPy_BMGeneric *self)
+{
+ BPY_BM_CHECK_INT(self);
+ return self->bm->totedge;
+}
+static Py_ssize_t bpy_bmface_seq_length(BPy_BMGeneric *self)
+{
+ BPY_BM_CHECK_INT(self);
+ return self->bm->totface;
+}
+
+static PyObject *bpy_bmvert_seq_subscript_int(BPy_BMGeneric *self, int keynum)
+{
+ int len;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ len = self->bm->totvert;
+ if (keynum < 0) keynum += len;
+ if (keynum >= 0 && keynum < len) {
+ return BPy_BMVert_CreatePyObject(self->bm, BM_iter_at_index(self->bm, BM_VERTS_OF_MESH, NULL, keynum));
+ }
+ PyErr_Format(PyExc_IndexError,
+ "bm.verts[index]: index %d out of range", keynum);
+ return NULL;
+}
+
+static PyObject *bpy_bmedge_seq_subscript_int(BPy_BMGeneric *self, int keynum)
+{
+ int len;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ len = self->bm->totedge;
+ if (keynum < 0) keynum += len;
+ if (keynum >= 0 && keynum < len) {
+ return BPy_BMEdge_CreatePyObject(self->bm, BM_iter_at_index(self->bm, BM_EDGES_OF_MESH, NULL, keynum));
+ }
+ PyErr_Format(PyExc_IndexError,
+ "bm.edges[index]: index %d out of range", keynum);
+ return NULL;
+}
+
+
+static PyObject *bpy_bmface_seq_subscript_int(BPy_BMGeneric *self, int keynum)
+{
+ int len;
+
+ BPY_BM_CHECK_OBJ(self);
+
+ len = self->bm->totface;
+ if (keynum < 0) keynum += len;
+ if (keynum >= 0 && keynum < len) {
+ return BPy_BMFace_CreatePyObject(self->bm, BM_iter_at_index(self->bm, BM_FACES_OF_MESH, NULL, keynum));
+ }
+ PyErr_Format(PyExc_IndexError,
+ "bm.faces[index]: index %d out of range", keynum);
+ return NULL;
+}
+
+static PyObject *bpy_bmvert_seq_subscript(BPy_BMGeneric *self, PyObject *key)
+{
+ /* dont need error check here */
+ if (PyIndex_Check(key)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ return bpy_bmvert_seq_subscript_int(self, i);
+ }
+ /* TODO, slice */
+ else {
+ PyErr_SetString(PyExc_AttributeError, "bm.verts[key]: invalid key, key must be an int");
+ return NULL;
+ }
+}
+
+static PyObject *bpy_bmedge_seq_subscript(BPy_BMGeneric *self, PyObject *key)
+{
+ /* dont need error check here */
+ if (PyIndex_Check(key)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ return bpy_bmedge_seq_subscript_int(self, i);
+ }
+ /* TODO, slice */
+ else {
+ PyErr_SetString(PyExc_AttributeError, "bm.edges[key]: invalid key, key must be an int");
+ return NULL;
+ }
+}
+
+static PyObject *bpy_bmface_seq_subscript(BPy_BMGeneric *self, PyObject *key)
+{
+ /* dont need error check here */
+ if (PyIndex_Check(key)) {
+ Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ return bpy_bmface_seq_subscript_int(self, i);
+ }
+ /* TODO, slice */
+ else {
+ PyErr_SetString(PyExc_AttributeError, "bm.faces[key]: invalid key, key must be an int");
+ return NULL;
+ }
+}
+
+static int bpy_bmvert_seq_contains(BPy_BMGeneric *self, PyObject *value)
+{
+ BPY_BM_CHECK_INT(self);
+
+ if (BPy_BMVert_Check(value)) {
+ BPy_BMVert *value_bmvert = (BPy_BMVert *)value;
+ if (value_bmvert->bm == self->bm) {
+ BMVert *v, *v_test = value_bmvert->v;
+ BMIter iter;
+ BM_ITER(v, &iter, self->bm, BM_VERTS_OF_MESH, NULL) {
+ if (v == v_test) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int bpy_bmedge_seq_contains(BPy_BMGeneric *self, PyObject *value)
+{
+ BPY_BM_CHECK_INT(self);
+
+ if (BPy_BMEdge_Check(value)) {
+ BPy_BMEdge *value_bmedge = (BPy_BMEdge *)value;
+ if (value_bmedge->bm == self->bm) {
+ BMEdge *e, *e_test = value_bmedge->e;
+ BMIter iter;
+ BM_ITER(e, &iter, self->bm, BM_EDGES_OF_MESH, NULL) {
+ if (e == e_test) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int bpy_bmface_seq_contains(BPy_BMGeneric *self, PyObject *value)
+{
+ BPY_BM_CHECK_INT(self);
+
+ if (BPy_BMFace_Check(value)) {
+ BPy_BMFace *value_bmface = (BPy_BMFace *)value;
+ if (value_bmface->bm == self->bm) {
+ BMFace *f, *f_test = value_bmface->f;
+ BMIter iter;
+ BM_ITER(f, &iter, self->bm, BM_FACES_OF_MESH, NULL) {
+ if (f == f_test) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static PySequenceMethods bpy_bmvert_seq_as_sequence = {
+ (lenfunc)bpy_bmvert_seq_length, /* sq_length */
+ NULL, /* sq_concat */
+ NULL, /* sq_repeat */
+ (ssizeargfunc)bpy_bmvert_seq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
+ NULL, /* sq_slice */
+ (ssizeobjargproc)NULL, /* sq_ass_item */
+ NULL, /* *was* sq_ass_slice */
+ (objobjproc)bpy_bmvert_seq_contains, /* sq_contains */
+ (binaryfunc) NULL, /* sq_inplace_concat */
+ (ssizeargfunc) NULL, /* sq_inplace_repeat */
+};
+
+static PySequenceMethods bpy_bmedge_seq_as_sequence = {
+ (lenfunc)bpy_bmedge_seq_length, /* sq_length */
+ NULL, /* sq_concat */
+ NULL, /* sq_repeat */
+ (ssizeargfunc)bpy_bmedge_seq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
+ NULL, /* sq_slice */
+ (ssizeobjargproc)NULL, /* sq_ass_item */
+ NULL, /* *was* sq_ass_slice */
+ (objobjproc)bpy_bmedge_seq_contains, /* sq_contains */
+ (binaryfunc) NULL, /* sq_inplace_concat */
+ (ssizeargfunc) NULL, /* sq_inplace_repeat */
+};
+
+static PySequenceMethods bpy_bmface_seq_as_sequence = {
+ (lenfunc)bpy_bmface_seq_length, /* sq_length */
+ NULL, /* sq_concat */
+ NULL, /* sq_repeat */
+ (ssizeargfunc)bpy_bmface_seq_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
+ NULL, /* sq_slice */
+ (ssizeobjargproc)NULL, /* sq_ass_item */
+ NULL, /* *was* sq_ass_slice */
+ (objobjproc)bpy_bmface_seq_contains, /* sq_contains */
+ (binaryfunc) NULL, /* sq_inplace_concat */
+ (ssizeargfunc) NULL, /* sq_inplace_repeat */
+};
+
+
+static PyMappingMethods bpy_bmvert_seq_as_mapping = {
+ (lenfunc)bpy_bmvert_seq_length, /* mp_length */
+ (binaryfunc)bpy_bmvert_seq_subscript, /* mp_subscript */
+ (objobjargproc)NULL, /* mp_ass_subscript */
+};
+
+static PyMappingMethods bpy_bmedge_seq_as_mapping = {
+ (lenfunc)bpy_bmedge_seq_length, /* mp_length */
+ (binaryfunc)bpy_bmedge_seq_subscript, /* mp_subscript */
+ (objobjargproc)NULL, /* mp_ass_subscript */
+};
+
+static PyMappingMethods bpy_bmface_seq_as_mapping = {
+ (lenfunc)bpy_bmface_seq_length, /* mp_length */
+ (binaryfunc)bpy_bmface_seq_subscript, /* mp_subscript */
+ (objobjargproc)NULL, /* mp_ass_subscript */
+};
+
+/* Iterator
+ * -------- */
+
+static PyObject *bpy_bmvert_seq_iter(BPy_BMGeneric *self)
+{
+ BPy_BMIter *py_iter;
+
+ BPY_BM_CHECK_OBJ(self);
+ py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
+ BM_iter_init(&py_iter->iter, self->bm, BM_VERTS_OF_MESH, NULL);
+ return (PyObject *)py_iter;
+}
+
+static PyObject *bpy_bmedge_seq_iter(BPy_BMGeneric *self)
+{
+ BPy_BMIter *py_iter;
+
+ BPY_BM_CHECK_OBJ(self);
+ py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
+ BM_iter_init(&py_iter->iter, self->bm, BM_EDGES_OF_MESH, NULL);
+ return (PyObject *)py_iter;
+}
+
+static PyObject *bpy_bmface_seq_iter(BPy_BMGeneric *self)
+{
+ BPy_BMIter *py_iter;
+
+ BPY_BM_CHECK_OBJ(self);
+ py_iter = (BPy_BMIter *)BPy_BMIter_CreatePyObject(self->bm);
+ BM_iter_init(&py_iter->iter, self->bm, BM_FACES_OF_MESH, NULL);
+ return (PyObject *)py_iter;
+}
+
+
+static PyObject *bpy_bm_iter_next(BPy_BMIter *self)
+{
+ BMHeader *ele = BM_iter_step(&self->iter);
+ if (ele == NULL) {
+ PyErr_SetString(PyExc_StopIteration, "bpy_bm_iter_next stop");
+ return NULL;
+ }
+ else {
+ return (PyObject *)BPy_BMElem_CreatePyObject(self->bm, ele);
+ }
+}
+
+
+/* not sure where this should go */
+static long bpy_bm_elem_hash(PyObject *self)
+{
+ return _Py_HashPointer(((BPy_BMElem *)self)->ele);
+}
+
+PyTypeObject BPy_BMesh_Type = {{{0}}};
+PyTypeObject BPy_BMVert_Type = {{{0}}};
+PyTypeObject BPy_BMEdge_Type = {{{0}}};
+PyTypeObject BPy_BMFace_Type = {{{0}}};
+PyTypeObject BPy_BMLoop_Type = {{{0}}};
+PyTypeObject BPy_BMVertSeq_Type = {{{0}}};
+PyTypeObject BPy_BMEdgeSeq_Type = {{{0}}};
+PyTypeObject BPy_BMFaceSeq_Type = {{{0}}};
+PyTypeObject BPy_BMIter_Type = {{{0}}};
+
+
+
+void BPy_BM_init_types(void)
+{
+ BPy_BMesh_Type.tp_basicsize = sizeof(BPy_BMesh);
+ BPy_BMVert_Type.tp_basicsize = sizeof(BPy_BMVert);
+ BPy_BMEdge_Type.tp_basicsize = sizeof(BPy_BMEdge);
+ BPy_BMFace_Type.tp_basicsize = sizeof(BPy_BMFace);
+ BPy_BMLoop_Type.tp_basicsize = sizeof(BPy_BMLoop);
+ BPy_BMVertSeq_Type.tp_basicsize = sizeof(BPy_BMGeneric);
+ BPy_BMEdgeSeq_Type.tp_basicsize = sizeof(BPy_BMGeneric);
+ BPy_BMFaceSeq_Type.tp_basicsize = sizeof(BPy_BMGeneric);
+ BPy_BMIter_Type.tp_basicsize = sizeof(BPy_BMIter);
+
+
+ BPy_BMesh_Type.tp_name = "BMesh";
+ BPy_BMVert_Type.tp_name = "BMVert";
+ BPy_BMEdge_Type.tp_name = "BMEdge";
+ BPy_BMFace_Type.tp_name = "BMFace";
+ BPy_BMLoop_Type.tp_name = "BMLoop";
+ BPy_BMVertSeq_Type.tp_name = "BMVertSeq";
+ BPy_BMEdgeSeq_Type.tp_name = "BMEdgeSeq";
+ BPy_BMFaceSeq_Type.tp_name = "BMFaceSeq";
+ BPy_BMIter_Type.tp_name = "BMIter";
+
+
+ BPy_BMesh_Type.tp_getset = bpy_bmesh_getseters;
+ BPy_BMVert_Type.tp_getset = bpy_bmvert_getseters;
+ BPy_BMEdge_Type.tp_getset = bpy_bmedge_getseters;
+ BPy_BMFace_Type.tp_getset = bpy_bmface_getseters;
+ BPy_BMLoop_Type.tp_getset = bpy_bmloop_getseters;
+ BPy_BMVertSeq_Type.tp_getset = NULL;
+ BPy_BMEdgeSeq_Type.tp_getset = NULL;
+ BPy_BMFaceSeq_Type.tp_getset = NULL;
+ BPy_BMIter_Type.tp_getset = NULL;
+
+
+ BPy_BMesh_Type.tp_methods = bpy_bmesh_methods;
+ BPy_BMVert_Type.tp_methods = bpy_bmvert_methods;
+ BPy_BMEdge_Type.tp_methods = bpy_bmedge_methods;
+ BPy_BMFace_Type.tp_methods = bpy_bmface_methods;
+ BPy_BMLoop_Type.tp_methods = bpy_bmloop_methods;
+ BPy_BMVertSeq_Type.tp_methods = bpy_bmvert_seq_methods;
+ BPy_BMEdgeSeq_Type.tp_methods = bpy_bmedge_seq_methods;
+ BPy_BMFaceSeq_Type.tp_methods = bpy_bmface_seq_methods;
+ BPy_BMIter_Type.tp_methods = NULL;
+
+
+ BPy_BMesh_Type.tp_hash = NULL;
+ BPy_BMVert_Type.tp_hash = bpy_bm_elem_hash;
+ BPy_BMEdge_Type.tp_hash = bpy_bm_elem_hash;
+ BPy_BMFace_Type.tp_hash = bpy_bm_elem_hash;
+ BPy_BMLoop_Type.tp_hash = bpy_bm_elem_hash;
+ BPy_BMVertSeq_Type.tp_hash = NULL;
+ BPy_BMEdgeSeq_Type.tp_hash = NULL;
+ BPy_BMFaceSeq_Type.tp_hash = NULL;
+ BPy_BMIter_Type.tp_hash = NULL;
+
+
+ BPy_BMVertSeq_Type.tp_as_sequence = &bpy_bmvert_seq_as_sequence;
+ BPy_BMEdgeSeq_Type.tp_as_sequence = &bpy_bmedge_seq_as_sequence;
+ BPy_BMFaceSeq_Type.tp_as_sequence = &bpy_bmface_seq_as_sequence;
+
+ BPy_BMVertSeq_Type.tp_as_mapping = &bpy_bmvert_seq_as_mapping;
+ BPy_BMEdgeSeq_Type.tp_as_mapping = &bpy_bmedge_seq_as_mapping;
+ BPy_BMFaceSeq_Type.tp_as_mapping = &bpy_bmface_seq_as_mapping;
+
+ BPy_BMVertSeq_Type.tp_iter = (getiterfunc)bpy_bmvert_seq_iter;
+ BPy_BMEdgeSeq_Type.tp_iter = (getiterfunc)bpy_bmedge_seq_iter;
+ BPy_BMFaceSeq_Type.tp_iter = (getiterfunc)bpy_bmface_seq_iter;
+
+ /* only 1 iteratir so far */
+ BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bm_iter_next;
+
+ /*
+ BPy_BMesh_Type.
+ BPy_BMVert_Type.
+ BPy_BMEdge_Type.
+ BPy_BMFace_Type.
+ BPy_BMLoop_Type.
+ BPy_BMVertSeq_Type.
+ BPy_BMEdgeSeq_Type.
+ BPy_BMFaceSeq_Type.
+ BPy_BMIter_Type.
+ */
+
+ BPy_BMesh_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMVert_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMEdge_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMFace_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMLoop_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMVertSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMEdgeSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMFaceSeq_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ BPy_BMIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+
+
+ PyType_Ready(&BPy_BMesh_Type);
+ PyType_Ready(&BPy_BMVert_Type);
+ PyType_Ready(&BPy_BMEdge_Type);
+ PyType_Ready(&BPy_BMFace_Type);
+ PyType_Ready(&BPy_BMLoop_Type);
+ PyType_Ready(&BPy_BMVertSeq_Type);
+ PyType_Ready(&BPy_BMEdgeSeq_Type);
+ PyType_Ready(&BPy_BMFaceSeq_Type);
+ PyType_Ready(&BPy_BMIter_Type);
+}
+
+
+/* Utility Functions
+ * ***************** */
+
+PyObject *BPy_BMesh_CreatePyObject(BMesh *bm)
+{
+ BPy_BMesh *self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type);
+ self->bm = bm;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v)
+{
+ BPy_BMVert *self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type);
+ BLI_assert(v != NULL);
+ self->bm = bm;
+ self->v = v;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e)
+{
+ BPy_BMEdge *self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type);
+ BLI_assert(e != NULL);
+ self->bm = bm;
+ self->e = e;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f)
+{
+ BPy_BMFace *self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type);
+ BLI_assert(f != NULL);
+ self->bm = bm;
+ self->f = f;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l)
+{
+ BPy_BMLoop *self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type);
+ BLI_assert(l != NULL);
+ self->bm = bm;
+ self->l = l;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMVertSeq_CreatePyObject(BMesh *bm)
+{
+ BPy_BMGeneric *self = PyObject_New(BPy_BMGeneric, &BPy_BMVertSeq_Type);
+ self->bm = bm;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMEdgeSeq_CreatePyObject(BMesh *bm)
+{
+ BPy_BMGeneric *self = PyObject_New(BPy_BMGeneric, &BPy_BMEdgeSeq_Type);
+ self->bm = bm;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMFaceSeq_CreatePyObject(BMesh *bm)
+{
+ BPy_BMGeneric *self = PyObject_New(BPy_BMGeneric, &BPy_BMFaceSeq_Type);
+ self->bm = bm;
+ return (PyObject *)self;
+}
+
+PyObject *BPy_BMIter_CreatePyObject(BMesh *bm)
+{
+ BPy_BMIter *self = PyObject_New(BPy_BMIter, &BPy_BMIter_Type);
+ self->bm = bm;
+ /* caller must initialize 'iter' member */
+ return (PyObject *)self;
+}
+
+/* this is just a helper func */
+PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele)
+{
+ switch (ele->htype) {
+ case BM_VERT:
+ return BPy_BMVert_CreatePyObject(bm, (BMVert *)ele);
+ case BM_EDGE:
+ return BPy_BMEdge_CreatePyObject(bm, (BMEdge *)ele);
+ case BM_FACE:
+ return BPy_BMFace_CreatePyObject(bm, (BMFace *)ele);
+ case BM_LOOP:
+ return BPy_BMLoop_CreatePyObject(bm, (BMLoop *)ele);
+ default:
+ PyErr_SetString(PyExc_SystemError, "internal error");
+ return NULL;
+ }
+}
+
+int bpy_bm_generic_valid_check(BPy_BMGeneric *self)
+{
+ if (self->bm) {
+ return 0;
+ }
+ PyErr_Format(PyExc_ReferenceError,
+ "BMesh data of type %.200s has been removed",
+ Py_TYPE(self)->tp_name);
+ return -1;
+}
+
+void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
+{
+ self->bm = NULL;
+}
diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h
new file mode 100644
index 00000000000..51d5e6aa5ee
--- /dev/null
+++ b/source/blender/python/bmesh/bmesh_py_types.h
@@ -0,0 +1,124 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2011 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/python/bmesh/bme_types.h
+ * \ingroup pybmesh
+ */
+
+#ifndef __BMESH_TYPES_H__
+#define __BMESH_TYPES_H__
+
+extern PyTypeObject BPy_BMesh_Type;
+extern PyTypeObject BPy_BMVert_Type;
+extern PyTypeObject BPy_BMEdge_Type;
+extern PyTypeObject BPy_BMFace_Type;
+extern PyTypeObject BPy_BMLoop_Type;
+extern PyTypeObject BPy_BMVertSeq_Type;
+extern PyTypeObject BPy_BMEdgeSeq_Type;
+extern PyTypeObject BPy_BMFaceSeq_Type;
+extern PyTypeObject BPy_BMIter_Type;
+
+#define BPy_BMesh_Check(v) (Py_TYPE(v) == &BPy_BMesh_Type)
+#define BPy_BMVert_Check(v) (Py_TYPE(v) == &BPy_BMVert_Type)
+#define BPy_BMEdge_Check(v) (Py_TYPE(v) == &BPy_BMEdge_Type)
+#define BPy_BMFace_Check(v) (Py_TYPE(v) == &BPy_BMFace_Type)
+#define BPy_BMLoop_Check(v) (Py_TYPE(v) == &BPy_BMLoop_Type)
+#define BPy_BMVertSeq_Check(v) (Py_TYPE(v) == &BPy_BMVertSeq_Type)
+#define BPy_BMEdgeSeq_Check(v) (Py_TYPE(v) == &BPy_BMEdgeSeq_Type)
+#define BPy_BMFaceSeq_Check(v) (Py_TYPE(v) == &BPy_BMFaceSeq_Type)
+#define BPy_BMIter_Check(v) (Py_TYPE(v) == &BPy_BMIter_Type)
+
+/* cast from _any_ bmesh type - they all have BMesh first */
+typedef struct BPy_BMGeneric {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+} BPy_BMGeneric;
+
+/* BPy_BMVert/BPy_BMEdge/BPy_BMFace/BPy_BMLoop can cast to this */
+typedef struct BPy_BMElem {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+ struct BMHeader *ele;
+} BPy_BMElem;
+
+typedef struct BPy_BMesh {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+} BPy_BMesh;
+
+/* element types */
+typedef struct BPy_BMVert {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+ struct BMVert *v;
+} BPy_BMVert;
+
+typedef struct BPy_BMEdge {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+ struct BMEdge *e;
+} BPy_BMEdge;
+
+typedef struct BPy_BMFace {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+ struct BMFace *f;
+} BPy_BMFace;
+
+typedef struct BPy_BMLoop {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+ struct BMLoop *l;
+} BPy_BMLoop;
+
+
+/* iterators */
+typedef struct BPy_BMIter {
+ PyObject_VAR_HEAD
+ struct BMesh *bm; /* keep first */
+ BMIter iter;
+} BPy_BMIter;
+
+void BPy_BM_init_types(void);
+
+PyObject *BPy_BMesh_CreatePyObject(BMesh *bm);
+PyObject *BPy_BMVert_CreatePyObject(BMesh *bm, BMVert *v);
+PyObject *BPy_BMEdge_CreatePyObject(BMesh *bm, BMEdge *e);
+PyObject *BPy_BMFace_CreatePyObject(BMesh *bm, BMFace *f);
+PyObject *BPy_BMLoop_CreatePyObject(BMesh *bm, BMLoop *l);
+PyObject *BPy_BMVertSeq_CreatePyObject(BMesh *bm);
+PyObject *BPy_BMEdgeSeq_CreatePyObject(BMesh *bm);
+PyObject *BPy_BMFaceSeq_CreatePyObject(BMesh *bm);
+PyObject *BPy_BMIter_CreatePyObject(BMesh *bm);
+
+PyObject *BPy_BMElem_CreatePyObject(BMesh *bm, BMHeader *ele); /* just checks type and creates v/e/f/l */
+
+int bpy_bm_generic_valid_check(BPy_BMGeneric *self);
+void bpy_bm_generic_invalidate(BPy_BMGeneric *self);
+
+#define BPY_BM_CHECK_OBJ(obj) if (bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1) { return NULL; } (void)NULL
+#define BPY_BM_CHECK_INT(obj) if (bpy_bm_generic_valid_check((BPy_BMGeneric *)obj) == -1) { return -1; } (void)NULL
+
+#endif /* __BMESH_TYPES_H__ */
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 72c072c13d5..5d05c688028 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -72,6 +72,7 @@
/* inittab initialization functions */
#include "../generic/bgl.h"
#include "../generic/blf_py_api.h"
+#include "../bmesh/bmesh_py_api.h"
#include "../mathutils/mathutils.h"
/* for internal use, when starting and ending python scripts */
@@ -192,6 +193,7 @@ static struct _inittab bpy_internal_modules[] = {
// {(char *)"mathutils.noise", PyInit_mathutils_noise},
{(char *)"bgl", BPyInit_bgl},
{(char *)"blf", BPyInit_blf},
+ {(char *)"bme", BPyInit_bmesh},
#ifdef WITH_AUDASPACE
{(char *)"aud", AUD_initPython},
#endif
@@ -699,7 +701,6 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
return done;
}
-
#ifdef WITH_PYTHON_MODULE
#include "BLI_fileops.h"
/* TODO, reloading the module isnt functional at the moment. */
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index b39d2a5b5c2..35174834a47 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -797,6 +797,7 @@ endif()
bf_python
bf_python_ext
bf_python_mathutils
+ bf_python_bmesh
bf_ikplugin
bf_bmesh
bf_modifiers