From 21fd09c028dce833f58cdaa8a1ff45876a5e5a2f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 11 Mar 2012 02:45:27 +0000 Subject: [PATCH] bmesh py api: change .from_mesh() / .to_mesh() to be class methods of BMesh rather than functions in the module. added example script which converts a mesh to a bmesh, edits and converts back again. --- release/scripts/templates/bmesh_simple.py | 21 +++++ ...gamelogic_basic.py => gamelogic_simple.py} | 0 source/blender/python/bmesh/bmesh_py_api.c | 82 ++++-------------- source/blender/python/bmesh/bmesh_py_types.c | 83 +++++++++++++++++++ source/blender/python/bmesh/bmesh_py_types.h | 2 +- 5 files changed, 123 insertions(+), 65 deletions(-) create mode 100644 release/scripts/templates/bmesh_simple.py rename release/scripts/templates/{gamelogic_basic.py => gamelogic_simple.py} (100%) diff --git a/release/scripts/templates/bmesh_simple.py b/release/scripts/templates/bmesh_simple.py new file mode 100644 index 00000000000..656febf4918 --- /dev/null +++ b/release/scripts/templates/bmesh_simple.py @@ -0,0 +1,21 @@ +# This example assumes we have a mesh object selected + +import bpy +import bmesh + +# Get the active mesh +me = bpy.context.object.data + + +# Get a BMesh representation +bm = bmesh.new() # create an empty BMesh +bm.from_mesh(me) # fill it in from a Mesh + + +# Modify the BMesh, can do anything here... +for v in bm.verts: + v.co.x += 1.0 + + +# Finish up, write the bmesh back to the mesh +bm.to_mesh(me) diff --git a/release/scripts/templates/gamelogic_basic.py b/release/scripts/templates/gamelogic_simple.py similarity index 100% rename from release/scripts/templates/gamelogic_basic.py rename to release/scripts/templates/gamelogic_simple.py diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index 3990005d139..280bab26c4b 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -40,17 +40,14 @@ #include "BLI_utildefines.h" #include "BKE_tessmesh.h" -#include "BKE_depsgraph.h" #include "DNA_mesh_types.h" -#include "DNA_object_types.h" #include "../generic/py_capi_utils.h" #include "bmesh_py_api.h" /* own include */ - PyDoc_STRVAR(bpy_bm_new_doc, ".. method:: new()\n" "\n" @@ -70,88 +67,40 @@ static PyObject *bpy_bm_new(PyObject *UNUSED(self)) return (PyObject *)py_bmesh; } -PyDoc_STRVAR(bpy_bm_from_mesh_doc, -".. method:: from_mesh(mesh)\n" +PyDoc_STRVAR(bpy_bm_from_edit_mesh_doc, +".. method:: from_edit_mesh(mesh)\n" "\n" " Return a BMesh from this mesh, currently the mesh must already be in editmode.\n" "\n" " :return: the BMesh assosiated with this mesh.\n" " :rtype: :class:`bmesh.types.BMesh`\n" ); - -static PyObject *bpy_bm_from_mesh(PyObject *UNUSED(self), PyObject *value) +static PyObject *bpy_bm_from_edit_mesh(PyObject *UNUSED(self), PyObject *value) { BPy_BMesh *py_bmesh; BMesh *bm; Mesh *me = PyC_RNA_AsPointer(value, "Mesh"); - int py_owns; if (me == NULL) { return NULL; } - /* temp! */ - if (!me->edit_btmesh) { - bm = BM_mesh_create(NULL, &bm_mesh_allocsize_default); - BM_mesh_to_bmesh(bm, me, 0, 0); /* BMESH_TODO add args */ - py_owns = TRUE; - } - else { - bm = me->edit_btmesh->bm; - py_owns = FALSE; + if (me->edit_btmesh == NULL) { + PyErr_SetString(PyExc_ValueError, + "The mesh must be in editmode"); + return NULL; } + bm = me->edit_btmesh->bm; + py_bmesh = (BPy_BMesh *)BPy_BMesh_CreatePyObject(bm); - py_bmesh->py_owns = py_owns; + py_bmesh->py_owns = FALSE; return (PyObject *)py_bmesh; } -PyDoc_STRVAR(bpy_bm_to_mesh_doc, -".. method:: to_mesh(mesh, bmesh)\n" -"\n" -" Return a BMesh from this mesh, currently the mesh must already be in editmode.\n" -"\n" -" :return: the BMesh assosiated with this mesh.\n" -" :rtype: :class:`bmesh.types.BMesh`\n" -); - -static PyObject *bpy_bm_to_mesh(PyObject *UNUSED(self), PyObject *args) -{ - PyObject *py_mesh; - BPy_BMesh *py_bmesh; - Mesh *me; - BMesh *bm; - - if (!PyArg_ParseTuple(args, "OO!:to_mesh", &py_mesh, &BPy_BMesh_Type, &py_bmesh) || - !(me = PyC_RNA_AsPointer(py_mesh, "Mesh"))) - { - return NULL; - } - - BPY_BM_CHECK_OBJ(py_bmesh); - - if (me->edit_btmesh) { - PyErr_Format(PyExc_ValueError, - "to_mesh(): Mesh '%s' is in editmode", me->id.name + 2); - return NULL; - } - - bm = py_bmesh->bm; - - BM_mesh_from_bmesh(bm, me, FALSE); - - /* we could have the user do this but if they forget blender can easy crash - * since the references arrays for the objects derived meshes are now invalid */ - DAG_id_tag_update(&me->id, OB_RECALC_DATA); - - Py_RETURN_NONE; -} - static struct PyMethodDef BPy_BM_methods[] = { - /* THESE NAMES MAY CHANGE! */ - {"new", (PyCFunction)bpy_bm_new, METH_NOARGS, bpy_bm_new_doc}, - {"from_mesh", (PyCFunction)bpy_bm_from_mesh, METH_O, bpy_bm_from_mesh_doc}, - {"to_mesh", (PyCFunction)bpy_bm_to_mesh, METH_VARARGS, bpy_bm_to_mesh_doc}, + {"new", (PyCFunction)bpy_bm_new, METH_NOARGS, bpy_bm_new_doc}, + {"from_edit_mesh", (PyCFunction)bpy_bm_from_edit_mesh, METH_O, bpy_bm_from_edit_mesh_doc}, {NULL, NULL, 0, NULL} }; @@ -163,6 +112,12 @@ PyDoc_STRVAR(BPy_BM_doc, "\n" "* :mod:`bmesh.utils`\n" "* :mod:`bmesh.types`\n" +"\n" +"\n" +"Example Script\n" +"--------------\n" +"\n" +".. literalinclude:: ../../../release/scripts/templates/bmesh_simple.py\n" ); static struct PyModuleDef BPy_BM_module_def = { PyModuleDef_HEAD_INIT, @@ -185,7 +140,6 @@ PyObject *BPyInit_bmesh(void) BPy_BM_init_types(); BPy_BM_init_select_types(); - mod = PyModule_Create(&BPy_BM_module_def); /* bmesh.types */ diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index c15323186ac..eefe3ccbe02 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -31,6 +31,10 @@ #include "BLI_math.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "BKE_depsgraph.h" #include "BKE_customdata.h" #include "bmesh.h" @@ -586,6 +590,82 @@ static PyGetSetDef bpy_bmloop_getseters[] = { /* Mesh * ---- */ +PyDoc_STRVAR(bpy_bmesh_to_mesh_doc, +".. method:: to_mesh(mesh)\n" +"\n" +" Writes this BMesh data into an existing Mesh datablock.\n" +"\n" +" :arg mesh: The mesh data to write into.\n" +" :type mesh: :class:`Mesh`\n" +); +static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) +{ + PyObject *py_mesh; + Mesh *me; + BMesh *bm; + + BPY_BM_CHECK_OBJ(self); + + if (!PyArg_ParseTuple(args, "O:to_mesh", &py_mesh) || + !(me = PyC_RNA_AsPointer(py_mesh, "Mesh"))) + { + return NULL; + } + + /* we could allow this but its almost certainly _not_ what script authors want */ + if (me->edit_btmesh) { + PyErr_Format(PyExc_ValueError, + "to_mesh(): Mesh '%s' is in editmode", me->id.name + 2); + return NULL; + } + + bm = self->bm; + + BM_mesh_from_bmesh(bm, me, FALSE); + + /* we could have the user do this but if they forget blender can easy crash + * since the references arrays for the objects derived meshes are now invalid */ + DAG_id_tag_update(&me->id, OB_RECALC_DATA); + + Py_RETURN_NONE; +} + +PyDoc_STRVAR(bpy_bmesh_from_mesh_doc, +".. method:: from_mesh(mesh, use_shape_key=False, shape_key_index=0)\n" +"\n" +" Initialize this bmesh from existing mesh datablock.\n" +"\n" +" :arg mesh: The mesh data to load.\n" +" :type mesh: :class:`Mesh`\n" +" :arg use_shape_key: Use the locations from a shape key.\n" +" :type use_shape_key: boolean\n" +" :arg shape_key_index: The shape key index to use.\n" +" :type shape_key_index: int\n" +); +static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject *kw) +{ + static const char *kwlist[] = {"mesh", "use_shape_key", "shape_key_index", NULL}; + BMesh *bm; + PyObject *py_mesh; + Mesh *me; + int use_shape_key = FALSE; + int shape_key_index = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kw, "O|ii:to_mesh", (char **)kwlist, + &py_mesh, &use_shape_key, &shape_key_index) || + !(me = PyC_RNA_AsPointer(py_mesh, "Mesh"))) + { + return NULL; + } + + bm = self->bm; + + BM_mesh_to_bmesh(bm, me, use_shape_key, shape_key_index + 1); + + Py_RETURN_NONE; +} + + PyDoc_STRVAR(bpy_bmesh_select_flush_mode_doc, ".. method:: select_flush_mode()\n" "\n" @@ -1716,6 +1796,9 @@ static PyObject *bpy_bmelemseq_index_update(BPy_BMElemSeq *self) static struct PyMethodDef bpy_bmesh_methods[] = { + {"from_mesh", (PyCFunction)bpy_bmesh_from_mesh, METH_VARARGS | METH_KEYWORDS, bpy_bmesh_from_mesh_doc}, + {"to_mesh", (PyCFunction)bpy_bmesh_to_mesh, METH_VARARGS, bpy_bmesh_to_mesh_doc}, + {"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}, {"normal_update", (PyCFunction)bpy_bmesh_normal_update, METH_VARARGS, bpy_bmesh_normal_update_doc}, diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index 52a82c50dd1..88569c5eeaf 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -62,7 +62,7 @@ typedef struct BPy_BMElem { typedef struct BPy_BMesh { PyObject_VAR_HEAD struct BMesh *bm; /* keep first */ - char py_owns; + char py_owns; /* when set, free along with the PyObject */ } BPy_BMesh; /* element types */