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:
@@ -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 */
|
||||
|
||||
|
||||
|
||||
@@ -179,6 +179,8 @@ typedef struct BMesh {
|
||||
ListBase errorstack;
|
||||
struct Object *ob; /* owner object */
|
||||
|
||||
void *py_handle;
|
||||
|
||||
int opflag; /* current operator flag */
|
||||
} BMesh;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user