diff options
-rw-r--r-- | source/blender/bmesh/intern/bmesh_construct.c | 12 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_iterators.c | 25 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_iterators.h | 15 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_dissolve.c | 7 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_join_triangles.c | 4 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 4 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c | 4 |
7 files changed, 56 insertions, 15 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 930964667e9..1a7464ce340 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -500,10 +500,10 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, */ void BMO_remove_tagged_faces(BMesh *bm, const short oflag) { - BMFace *f; + BMFace *f, *f_next; BMIter iter; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BM_ITER_MESH_MUTABLE (f, f_next, &iter, bm, BM_FACES_OF_MESH) { if (BMO_elem_flag_test(bm, f, oflag)) { BM_face_kill(bm, f); } @@ -512,10 +512,10 @@ void BMO_remove_tagged_faces(BMesh *bm, const short oflag) void BMO_remove_tagged_edges(BMesh *bm, const short oflag) { - BMEdge *e; + BMEdge *e, *e_next; BMIter iter; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { if (BMO_elem_flag_test(bm, e, oflag)) { BM_edge_kill(bm, e); } @@ -524,10 +524,10 @@ void BMO_remove_tagged_edges(BMesh *bm, const short oflag) void BMO_remove_tagged_verts(BMesh *bm, const short oflag) { - BMVert *v; + BMVert *v, *v_next; BMIter iter; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, oflag)) { BM_vert_kill(bm, v); } diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index cc5e4933d39..6449a6e6d35 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -54,6 +54,31 @@ const char bm_iter_itype_htype_map[BM_ITYPE_MAX] = { }; /** + * Utility function. + */ +int BM_iter_mesh_count(BMesh *bm, const char itype) +{ + int count; + + switch (itype) { + case BM_VERTS_OF_MESH: + count = bm->totvert; + break; + case BM_EDGES_OF_MESH: + count = bm->totedge; + break; + case BM_FACES_OF_MESH: + count = bm->totface; + break; + default: + count = 0; + BLI_assert(0); + } + + return count; +} + +/** * \note Use #BM_vert_at_index / #BM_edge_at_index / #BM_face_at_index for mesh arrays. */ void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index bb25d3fabd1..fdf0f27f05f 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -89,6 +89,20 @@ extern const char bm_iter_itype_htype_map[BM_ITYPE_MAX]; #define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar) \ for (ele = BM_iter_new(iter, bm, itype, NULL), indexvar = 0; ele; ele = BM_iter_step(iter), (indexvar)++) +/* a version of BM_ITER_MESH which keeps the next item in storage + * so we can delete the current item, see bug [#36923] */ +#ifdef DEBUG +# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ + for (ele = BM_iter_new(iter, bm, itype, NULL); \ + ele ? ((void)((iter)->count = BM_iter_mesh_count(bm, itype)), \ + (void)(ele_next = BM_iter_step(iter)), 1) : 0; \ + ele = ele_next) +#else +# define BM_ITER_MESH_MUTABLE(ele, ele_next, iter, bm, itype) \ + for (ele = BM_iter_new(iter, bm, itype, NULL); ele ? ((ele_next = BM_iter_step(iter)), 1) : 0; ele = ele_next) +#endif + + #define BM_ITER_ELEM(ele, iter, data, itype) \ for (ele = BM_iter_new(iter, NULL, itype, data); ele; ele = BM_iter_step(iter)) @@ -182,6 +196,7 @@ typedef struct BMIter { char itype; } BMIter; +int BM_iter_mesh_count(BMesh *bm, const char itype); void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index d3c7a6864c3..e85a9c081b9 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -293,7 +293,8 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) } if (use_verts) { - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BMVert *v_next; + BM_ITER_MESH_MUTABLE (v, v_next, &viter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (BM_vert_edge_count(v) == 2) { BM_vert_collapse_edge(bm, v->e, v, true); @@ -349,7 +350,7 @@ static bool test_extra_verts(BMesh *bm, BMVert *v) void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) { BMIter iter, fiter; - BMVert *v; + BMVert *v, *v_next; BMFace *f; const bool use_face_split = BMO_slot_bool_get(op->slots_in, "use_face_split"); @@ -409,7 +410,7 @@ void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op) } /* clean up any remainin */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_elem_flag_test(bm, v, VERT_MARK)) { if (!BM_vert_dissolve(bm, v)) { BMO_error_raise(bm, op, BMERR_DISSOLVEVERTS_FAILED, NULL); diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 6d4f257909c..76678bfa4f7 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -203,7 +203,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMIter iter; BMOIter siter; BMFace *f; - BMEdge *e; + BMEdge *e, *e_next; /* data: edge-to-join, sort_value: error weight */ struct SortPointerByFloat *jedges; unsigned i, totedge; @@ -291,7 +291,7 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) MEM_freeN(jedges); /* join best weighted */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_MUTABLE (e, e_next, &iter, bm, BM_EDGES_OF_MESH) { BMFace *f_new; BMFace *f_a, *f_b; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 9db751ad1b7..8c3edfa23c4 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -2375,7 +2375,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, const struct MDeformVert *dvert, const int vertex_group) { BMIter iter; - BMVert *v; + BMVert *v, *v_next; BMEdge *e; BevelParams bp = {NULL}; @@ -2418,7 +2418,7 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, } } - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { BLI_assert(find_bevvert(&bp, v) != NULL); BM_vert_kill(bm, v); diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index bc9288f98f6..868caa49ec7 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -197,7 +197,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool } for (iter_step = 0; iter_step < iterations; iter_step++) { - BMVert *v; + BMVert *v, *v_next; bool iter_done; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -318,7 +318,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */ iter_done = false; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH_MUTABLE (v, v_next, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) { if (bm_vert_dissolve_fan(bm, v)) { iter_done = true; |