[Bf-blender-cvs] [1cd88104f09] sculpt-dev: Sculpt-dev: fix bmesh python bug

Joseph Eagar noreply at git.blender.org
Tue Jun 14 05:16:49 CEST 2022


Commit: 1cd88104f09d4b70b8c5bd49e0e0931673d5909c
Author: Joseph Eagar
Date:   Mon Jun 13 20:13:02 2022 -0700
Branches: sculpt-dev
https://developer.blender.org/rB1cd88104f09d4b70b8c5bd49e0e0931673d5909c

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.

===================================================================

M	source/blender/bmesh/CMakeLists.txt
M	source/blender/bmesh/intern/bmesh_interp.c
M	source/blender/python/bmesh/bmesh_py_types.c

===================================================================

diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 4856e57f412..96e0236e4aa 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -13,6 +13,7 @@ set(INC
   ../../../intern/eigen
   ../../../intern/guardedalloc
   ../../../extern/rangetree
+  ../python/bmesh
 )
 
 set(INC_SYS
diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c
index e3f568d47f9..a51571a9b7e 100644
--- a/source/blender/bmesh/intern/bmesh_interp.c
+++ b/source/blender/bmesh/intern/bmesh_interp.c
@@ -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! */
diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c
index 23dc7f7c0e2..6cc51366fd1 100644
--- a/source/blender/python/bmesh/bmesh_py_types.c
+++ b/source/blender/python/bmesh/bmesh_py_types.c
@@ -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;



More information about the Bf-blender-cvs mailing list