diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-02-22 20:08:30 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-02-22 20:08:30 +0400 |
commit | 92c47145fde8449cd7fb0547d29dbf9491b40d97 (patch) | |
tree | 3b7077775af29a53c20c5d31a199017f4ba00d77 | |
parent | b06beb6f35a4e2842fa21eeb059bf1beba4a8e01 (diff) |
bmesh python api change in internal behavior.
* Only have 1 python object per bmesh, vertex, edge, loop, face.
* Store pointers back to the python data in a custom data layer so as not to use more memory for normal editing operations (when pythons not running).
* Currently this data is created and freed along with the BMesh PyObject.
* Incidentally - this fixes comparisons for bmesh elements which wasnt working before.
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 31 | ||||
-rw-r--r-- | source/blender/bmesh/bmesh_class.h | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_customdata_types.h | 7 | ||||
-rw-r--r-- | source/blender/python/bmesh/bmesh_py_types.c | 164 |
4 files changed, 177 insertions, 27 deletions
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index f019fb740fb..b2aaa651912 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -159,6 +159,33 @@ static void layerFree_mdeformvert(void *data, int count, int size) } } +/* copy just zeros in this case */ +static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, + int count) +{ + int i, size = sizeof(void *); + + for(i = 0; i < count; ++i) { + void **ptr = (void **)((char *)dest + i * size); + *ptr = NULL; + } +} + +static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size) +{ + extern void bpy_bm_generic_invalidate(void *self); + + int i; + + for(i = 0; i < count; ++i) { + void **ptr = (void *)((char *)data + i * size); + if (*ptr) { + bpy_bm_generic_invalidate(*ptr); + } + } +} + + static void linklist_free_simple(void *link) { MEM_freeN(link); @@ -1003,6 +1030,10 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MLoopCol), "MLoopCol", 1, "WeightLoopCol", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, + /* 33: CD_BM_ELEM_PYPTR */ + {sizeof(void *), "", 1, NULL, layerCopy_bmesh_elem_py_ptr, + layerFree_bmesh_elem_py_ptr, NULL, NULL, NULL}, + /* END BMESH ONLY */ diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 3a62eaa2eeb..6c052a402c9 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -179,6 +179,8 @@ typedef struct BMesh { ListBase errorstack; struct Object *ob; /* owner object */ + void *py_handle; + int opflag; /* current operator flag */ } BMesh; diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index f7f40e99617..d7358a4df1e 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -63,10 +63,9 @@ typedef struct CustomDataExternal { * layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */ typedef struct CustomData { CustomDataLayer *layers; /* CustomDataLayers, ordered by type */ - int typemap[33]; /* runtime only! - maps types to indices of first layer of that type, + int typemap[34]; /* runtime only! - maps types to indices of first layer of that type, * MUST be >= CD_NUMTYPES, but we cant use a define here. * Correct size is ensured in CustomData_update_typemap assert() */ - int pad1; int totlayer, maxlayer; /* number of layers, size of layers array */ int totsize, pad2; /* in editmode, total size of all data layers */ @@ -110,9 +109,10 @@ typedef struct CustomData { #define CD_CREASE 30 #define CD_ORIGSPACE_MLOOP 31 #define CD_WEIGHT_MLOOPCOL 32 +#define CD_BM_ELEM_PYPTR 33 /* BMESH ONLY END */ -#define CD_NUMTYPES 33 +#define CD_NUMTYPES 34 /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) @@ -148,6 +148,7 @@ typedef struct CustomData { #define CD_MASK_CREASE (1 << CD_CREASE) #define CD_MASK_ORIGSPACE_MLOOP (1 << CD_ORIGSPACE_MLOOP) #define CD_MASK_WEIGHT_MLOOPCOL (1LL << CD_WEIGHT_MLOOPCOL) +#define CD_MASK_BM_ELEM_PYPTR (1LL << CD_BM_ELEM_PYPTR) /* BMESH ONLY END */ /* CustomData.flag */ diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index f0189d2077b..8350166c2d0 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -31,6 +31,8 @@ #include "BLI_math.h" +#include "BKE_customdata.h" + #include "bmesh.h" #include "../mathutils/mathutils.h" @@ -1129,7 +1131,7 @@ static PyObject *bpy_bm_seq_subscript(BPy_BMElemSeq *self, PyObject *key) return NULL; } else if (step != 1) { - PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported"); + PyErr_SetString(PyExc_TypeError, "BMElemSeq[slice]: slice steps not supported"); return NULL; } else if (key_slice->start == Py_None && key_slice->stop == Py_None) { @@ -1231,6 +1233,60 @@ static PyObject *bpy_bm_iter_next(BPy_BMIter *self) /* Dealloc Functions * ================= */ +static void bpy_bmesh_dealloc(BPy_BMesh *self) +{ + BMesh *bm = self->bm; + + BM_data_layer_free(bm, &bm->vdata, CD_BM_ELEM_PYPTR); + BM_data_layer_free(bm, &bm->edata, CD_BM_ELEM_PYPTR); + BM_data_layer_free(bm, &bm->pdata, CD_BM_ELEM_PYPTR); + BM_data_layer_free(bm, &bm->ldata, CD_BM_ELEM_PYPTR); + + bm->py_handle = NULL; + + PyObject_DEL(self); +} + +static void bpy_bmvert_dealloc(BPy_BMElem *self) +{ + BMesh *bm = self->bm; + if (bm) { + void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->data, CD_BM_ELEM_PYPTR); + *ptr = NULL; + } + PyObject_DEL(self); +} + +static void bpy_bmedge_dealloc(BPy_BMElem *self) +{ + BMesh *bm = self->bm; + if (bm) { + void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->data, CD_BM_ELEM_PYPTR); + *ptr = NULL; + } + PyObject_DEL(self); +} + +static void bpy_bmface_dealloc(BPy_BMElem *self) +{ + BMesh *bm = self->bm; + if (bm) { + void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->data, CD_BM_ELEM_PYPTR); + *ptr = NULL; + } + PyObject_DEL(self); +} + +static void bpy_bmloop_dealloc(BPy_BMElem *self) +{ + BMesh *bm = self->bm; + if (bm) { + void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->data, CD_BM_ELEM_PYPTR); + *ptr = NULL; + } + PyObject_DEL(self); +} + static void bpy_bm_seq_dealloc(BPy_BMElemSeq *self) { Py_XDECREF(self->py_ele); @@ -1309,11 +1365,11 @@ void BPy_BM_init_types(void) /* only 1 iteratir so far */ BPy_BMIter_Type.tp_iternext = (iternextfunc)bpy_bm_iter_next; - BPy_BMesh_Type.tp_dealloc = NULL; - BPy_BMVert_Type.tp_dealloc = NULL; - BPy_BMEdge_Type.tp_dealloc = NULL; - BPy_BMFace_Type.tp_dealloc = NULL; - BPy_BMLoop_Type.tp_dealloc = NULL; + BPy_BMesh_Type.tp_dealloc = (destructor)bpy_bmesh_dealloc; + BPy_BMVert_Type.tp_dealloc = (destructor)bpy_bmvert_dealloc; + BPy_BMEdge_Type.tp_dealloc = (destructor)bpy_bmedge_dealloc; + BPy_BMFace_Type.tp_dealloc = (destructor)bpy_bmface_dealloc; + BPy_BMLoop_Type.tp_dealloc = (destructor)bpy_bmloop_dealloc; BPy_BMElemSeq_Type.tp_dealloc = (destructor)bpy_bm_seq_dealloc; BPy_BMIter_Type.tp_dealloc = NULL; @@ -1351,44 +1407,104 @@ void BPy_BM_init_types(void) PyObject *BPy_BMesh_CreatePyObject(BMesh *bm) { - BPy_BMesh *self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type); - self->bm = bm; + BPy_BMesh *self; + + if (bm->py_handle) { + self = bm->py_handle; + Py_INCREF(self); + } + else { + self = PyObject_New(BPy_BMesh, &BPy_BMesh_Type); + self->bm = bm; + + BM_data_layer_add(bm, &bm->vdata, CD_BM_ELEM_PYPTR); + BM_data_layer_add(bm, &bm->edata, CD_BM_ELEM_PYPTR); + BM_data_layer_add(bm, &bm->pdata, CD_BM_ELEM_PYPTR); + BM_data_layer_add(bm, &bm->ldata, CD_BM_ELEM_PYPTR); + } + 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; + BPy_BMVert *self; + + void **ptr = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_BM_ELEM_PYPTR); + + if (*ptr != NULL) { + self = *ptr; + Py_INCREF(self); + } + else { + self = PyObject_New(BPy_BMVert, &BPy_BMVert_Type); + BLI_assert(v != NULL); + self->bm = bm; + self->v = v; + *ptr = self; + } 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; + BPy_BMEdge *self; + + void **ptr = CustomData_bmesh_get(&bm->edata, e->head.data, CD_BM_ELEM_PYPTR); + + if (*ptr != NULL) { + self = *ptr; + Py_INCREF(self); + } + else { + self = PyObject_New(BPy_BMEdge, &BPy_BMEdge_Type); + BLI_assert(e != NULL); + self->bm = bm; + self->e = e; + *ptr = self; + } 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; + BPy_BMFace *self; + + void **ptr = CustomData_bmesh_get(&bm->pdata, f->head.data, CD_BM_ELEM_PYPTR); + + if (*ptr != NULL) { + self = *ptr; + Py_INCREF(self); + } + else { + self = PyObject_New(BPy_BMFace, &BPy_BMFace_Type); + BLI_assert(f != NULL); + self->bm = bm; + self->f = f; + *ptr = self; + } 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; + BPy_BMLoop *self; + + void **ptr = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_BM_ELEM_PYPTR); + + if (*ptr != NULL) { + self = *ptr; + Py_INCREF(self); + } + else { + self = PyObject_New(BPy_BMLoop, &BPy_BMLoop_Type); + BLI_assert(l != NULL); + self->bm = bm; + self->l = l; + *ptr = self; + } return (PyObject *)self; } |