Sculpt-dev: fix bmesh python bug
Save and restore python pointers when adding or removing customdata layers, this is needed since tool flags are a customdata layer in sculpt-dev. Reallocating tool flags shouldn't clear python pointers.
This commit is contained in:
parent
d54416506a
commit
1cd88104f0
|
@ -13,6 +13,7 @@ set(INC
|
|||
../../../intern/eigen
|
||||
../../../intern/guardedalloc
|
||||
../../../extern/rangetree
|
||||
../python/bmesh
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
|
|
@ -1238,6 +1238,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v_dst, const BMFace *f_src)
|
|||
CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, f_src->len, v_dst->head.data);
|
||||
}
|
||||
|
||||
void BPy_bm_new_customdata_layout(BMesh *bm, CustomData *cdata, void *state, char htype);
|
||||
void *BPy_bm_new_customdata_layout_pre(BMesh *bm, CustomData *cdata, char htype);
|
||||
|
||||
static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
||||
{
|
||||
BMIter iter;
|
||||
|
@ -1259,6 +1262,7 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
|||
BMVert *eve;
|
||||
|
||||
CustomData_bmesh_init_pool_ex(data, bm->totvert, BM_VERT, __func__);
|
||||
void *state = BPy_bm_new_customdata_layout_pre(bm, olddata, BM_VERT);
|
||||
|
||||
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
||||
block = NULL;
|
||||
|
@ -1267,11 +1271,15 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
|||
CustomData_bmesh_free_block(olddata, &eve->head.data);
|
||||
eve->head.data = block;
|
||||
}
|
||||
|
||||
BPy_bm_new_customdata_layout(bm, &bm->vdata, state, BM_VERT);
|
||||
MEM_SAFE_FREE(state);
|
||||
}
|
||||
else if (data == &bm->edata) {
|
||||
BMEdge *eed;
|
||||
|
||||
CustomData_bmesh_init_pool_ex(data, bm->totedge, BM_EDGE, __func__);
|
||||
void *state = BPy_bm_new_customdata_layout_pre(bm, olddata, BM_EDGE);
|
||||
|
||||
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
||||
block = NULL;
|
||||
|
@ -1280,6 +1288,9 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
|||
CustomData_bmesh_free_block(olddata, &eed->head.data);
|
||||
eed->head.data = block;
|
||||
}
|
||||
|
||||
BPy_bm_new_customdata_layout(bm, &bm->edata, state, BM_EDGE);
|
||||
MEM_SAFE_FREE(state);
|
||||
}
|
||||
else if (data == &bm->ldata) {
|
||||
BMIter liter;
|
||||
|
@ -1287,6 +1298,8 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
|||
BMLoop *l;
|
||||
|
||||
CustomData_bmesh_init_pool_ex(data, bm->totloop, BM_LOOP, __func__);
|
||||
void *state = BPy_bm_new_customdata_layout_pre(bm, olddata, BM_LOOP);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||
block = NULL;
|
||||
|
@ -1296,11 +1309,15 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
|||
l->head.data = block;
|
||||
}
|
||||
}
|
||||
|
||||
BPy_bm_new_customdata_layout(bm, &bm->ldata, state, BM_LOOP);
|
||||
MEM_SAFE_FREE(state);
|
||||
}
|
||||
else if (data == &bm->pdata) {
|
||||
BMFace *efa;
|
||||
|
||||
CustomData_bmesh_init_pool_ex(data, bm->totface, BM_FACE, __func__);
|
||||
void *state = BPy_bm_new_customdata_layout_pre(bm, olddata, BM_FACE);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
||||
block = NULL;
|
||||
|
@ -1309,6 +1326,9 @@ static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data)
|
|||
CustomData_bmesh_free_block(olddata, &efa->head.data);
|
||||
efa->head.data = block;
|
||||
}
|
||||
|
||||
BPy_bm_new_customdata_layout(bm, &bm->pdata, state, BM_FACE);
|
||||
MEM_SAFE_FREE(state);
|
||||
}
|
||||
else {
|
||||
/* should never reach this! */
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
* \ingroup pybmesh
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_sort.h"
|
||||
|
||||
|
@ -4047,6 +4049,134 @@ int bpy_bm_generic_valid_check_source(BMesh *bm_source,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void *BPy_bm_new_customdata_layout_pre(BMesh *bm, CustomData *cdata, char htype)
|
||||
{
|
||||
if (!CustomData_has_layer(cdata, CD_BM_ELEM_PYPTR)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLI_mempool *pool = NULL;
|
||||
int num = 0;
|
||||
|
||||
switch (htype) {
|
||||
case BM_VERT:
|
||||
pool = bm->vpool;
|
||||
num = bm->totvert;
|
||||
break;
|
||||
case BM_EDGE:
|
||||
pool = bm->epool;
|
||||
num = bm->totedge;
|
||||
break;
|
||||
case BM_LOOP:
|
||||
pool = bm->fpool;
|
||||
num = bm->totloop;
|
||||
break;
|
||||
case BM_FACE:
|
||||
pool = bm->fpool;
|
||||
num = bm->totface;
|
||||
break;
|
||||
}
|
||||
|
||||
void **ptrs = MEM_malloc_arrayN(num, sizeof(void *), __func__);
|
||||
|
||||
int cd_py = CustomData_get_offset(cdata, CD_BM_ELEM_PYPTR);
|
||||
|
||||
BMElem *elem;
|
||||
BLI_mempool_iter iter;
|
||||
|
||||
int i = 0;
|
||||
|
||||
if (htype != BM_LOOP) {
|
||||
BLI_mempool_iternew(pool, &iter);
|
||||
while ((elem = BLI_mempool_iterstep(&iter))) {
|
||||
ptrs[i++] = *((void **)BM_ELEM_CD_GET_VOID_P(elem, cd_py));
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMFace *f;
|
||||
|
||||
BLI_mempool_iternew(pool, &iter);
|
||||
while ((f = BLI_mempool_iterstep(&iter))) {
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
do {
|
||||
ptrs[i++] = *((void **)BM_ELEM_CD_GET_VOID_P(l, cd_py));
|
||||
} while ((l = l->next) != f->l_first);
|
||||
}
|
||||
}
|
||||
|
||||
return ptrs;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT void BPy_bm_new_customdata_layout(BMesh *bm, CustomData *cdata, void *state, char htype)
|
||||
{
|
||||
/*
|
||||
* Un-invalidate python pointers, which got invalidated when the customdata layout
|
||||
* changed.
|
||||
*/
|
||||
|
||||
if (!state || !CustomData_has_layer(cdata, CD_BM_ELEM_PYPTR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BLI_mempool *pool = NULL;
|
||||
void **ptrs = (void **)state;
|
||||
|
||||
switch (htype) {
|
||||
case BM_VERT:
|
||||
pool = bm->vpool;
|
||||
break;
|
||||
case BM_EDGE:
|
||||
pool = bm->epool;
|
||||
break;
|
||||
case BM_LOOP:
|
||||
pool = bm->fpool;
|
||||
break;
|
||||
case BM_FACE:
|
||||
pool = bm->fpool;
|
||||
break;
|
||||
}
|
||||
|
||||
int cd_py = CustomData_get_offset(cdata, CD_BM_ELEM_PYPTR);
|
||||
|
||||
BMElem *elem;
|
||||
BLI_mempool_iter iter;
|
||||
int i = 0;
|
||||
|
||||
if (htype != BM_LOOP) {
|
||||
BLI_mempool_iternew(pool, &iter);
|
||||
while ((elem = BLI_mempool_iterstep(&iter))) {
|
||||
void **ptr = BM_ELEM_CD_GET_VOID_P(elem, cd_py);
|
||||
|
||||
*ptr = ptrs[i++];
|
||||
BPy_BMGeneric *bpy_ptr = (BPy_BMGeneric *)*ptr;
|
||||
|
||||
if (bpy_ptr) {
|
||||
bpy_ptr->bm = bm;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMFace *f;
|
||||
|
||||
BLI_mempool_iternew(pool, &iter);
|
||||
while ((f = BLI_mempool_iterstep(&iter))) {
|
||||
BMLoop *l = f->l_first;
|
||||
|
||||
do {
|
||||
void **ptr = BM_ELEM_CD_GET_VOID_P(l, cd_py);
|
||||
|
||||
*ptr = ptrs[i++];
|
||||
BPy_BMGeneric *bpy_ptr = (BPy_BMGeneric *)*ptr;
|
||||
|
||||
if (bpy_ptr) {
|
||||
bpy_ptr->bm = bm;
|
||||
}
|
||||
} while ((l = l->next) != f->l_first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bpy_bm_generic_invalidate(BPy_BMGeneric *self)
|
||||
{
|
||||
self->bm = NULL;
|
||||
|
|
Loading…
Reference in New Issue