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.
This commit is contained in:
Campbell Barton
2012-02-22 16:08:30 +00:00
parent b06beb6f35
commit 92c47145fd
4 changed files with 177 additions and 27 deletions

View File

@@ -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 */

View File

@@ -179,6 +179,8 @@ typedef struct BMesh {
ListBase errorstack;
struct Object *ob; /* owner object */
void *py_handle;
int opflag; /* current operator flag */
} BMesh;

View File

@@ -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 */

View File

@@ -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;
}