diff --git a/source/blender/bmesh/bmesh_walkers.h b/source/blender/bmesh/bmesh_walkers.h index 9ed17121920..b33e9935bf7 100644 --- a/source/blender/bmesh/bmesh_walkers.h +++ b/source/blender/bmesh/bmesh_walkers.h @@ -19,19 +19,29 @@ typedef struct BMWalker { void *(*yield)(struct BMWalker *walker); int structsize; BMWOrder order; + int valid_mask; + + /* runtime */ int layer; BMesh *bm; BLI_mempool *worklist; ListBase states; - short restrictflag; + + short mask_vert; + short mask_edge; + short mask_loop; + short mask_face; + GHash *visithash; int depth; } BMWalker; /*initialize a walker. searchmask restricts some (not all) walkers to elements with a specific tool flag set. flags is specific to each walker.*/ -void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, short searchmask, int layer); +void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, + short mask_vert, short mask_edge, short mask_loop, short mask_face, + int layer); void *BMW_Begin(BMWalker *walker, void *start); void *BMW_Step(struct BMWalker *walker); void BMW_End(struct BMWalker *walker); @@ -86,6 +96,8 @@ enum { BMW_ISLAND, /*walk from a vertex to all connected vertices.*/ BMW_CONNECTED_VERTEX, + /* end of array index enum vals */ + /*do not intitialze function pointers and struct size in BMW_Init*/ BMW_CUSTOM, BMW_MAXWALKERS diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c index adfe64c6dd9..a4f5f53fd68 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.c +++ b/source/blender/bmesh/intern/bmesh_walkers.c @@ -83,18 +83,28 @@ void *BMW_Begin(BMWalker *walker, void *start) * */ -void BMW_Init(BMWalker *walker, BMesh *bm, int type, short searchmask, int layer) +void BMW_Init(BMWalker *walker, BMesh *bm, int type, + short mask_vert, short mask_edge, short mask_loop, short mask_face, + int layer) { memset(walker, 0, sizeof(BMWalker)); walker->layer = layer; walker->bm = bm; - walker->restrictflag = searchmask; + + walker->mask_vert = mask_vert; + walker->mask_edge = mask_edge; + walker->mask_loop = mask_loop; + walker->mask_face = mask_face; + walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 1"); if (type >= BMW_MAXWALKERS || type < 0) { bmesh_error(); - fprintf(stderr, "Invalid walker type in BMW_Init; type: %d, searchmask: %d, flag: %d\n", type, searchmask, layer); + fprintf(stderr, + "Invalid walker type in BMW_Init; type: %d, " + "searchmask: (v:%d,e:%d,l:%d,f:%d), flag: %d\n", + type, mask_vert, mask_edge, mask_loop, mask_face, layer); } if (type != BMW_CUSTOM) { @@ -103,6 +113,15 @@ void BMW_Init(BMWalker *walker, BMesh *bm, int type, short searchmask, int layer walker->step = bm_walker_types[type]->step; walker->structsize = bm_walker_types[type]->structsize; walker->order = bm_walker_types[type]->order; + walker->valid_mask = bm_walker_types[type]->valid_mask; + + /* safety checks */ + /* if this raises an error either the caller is wrong or + * 'bm_walker_types' needs updating */ + BLI_assert(mask_vert==0 || (walker->valid_mask & BM_VERT)); + BLI_assert(mask_edge==0 || (walker->valid_mask & BM_EDGE)); + BLI_assert(mask_loop==0 || (walker->valid_mask & BM_LOOP)); + BLI_assert(mask_face==0 || (walker->valid_mask & BM_FACE)); } walker->worklist = BLI_mempool_create(walker->structsize, 100, 100, TRUE, FALSE); diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 45b4e8c5ffd..69a2a3a794c 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -61,7 +61,7 @@ static void shellWalker_visitEdge(BMWalker *walker, BMEdge *e) return; } - if (walker->restrictflag && !BMO_TestFlag(walker->bm, e, walker->restrictflag)) { + if (walker->mask_edge && !BMO_TestFlag(walker->bm, e, walker->mask_edge)) { return; } @@ -188,7 +188,7 @@ static void connectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v) /* already visited */ return; } - if (walker->restrictflag && !BMO_TestFlag(walker->bm, v, walker->restrictflag)) { + if (walker->mask_vert && !BMO_TestFlag(walker->bm, v, walker->mask_vert)) { /* not flagged for walk */ return; } @@ -296,7 +296,7 @@ static void *islandboundWalker_step(BMWalker *walker) l = bmesh_radial_nextloop(l); f = l->f; e = l->e; - if(walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag)){ + if(walker->mask_face && !BMO_TestFlag(walker->bm, f, walker->mask_face)){ l = l->radial_next; break; } @@ -337,7 +337,7 @@ static void islandWalker_begin(BMWalker *walker, void *data) { islandWalker *iwalk = NULL; - if (walker->restrictflag && !BMO_TestFlag(walker->bm, data, walker->restrictflag)) { + if (walker->mask_face && !BMO_TestFlag(walker->bm, data, walker->mask_face)) { return; } @@ -368,7 +368,7 @@ static void *islandWalker_step(BMWalker *walker) for (; l; l=BMIter_Step(&liter)) { f = BMIter_New(&iter, walker->bm, BM_FACES_OF_EDGE, l->e); for (; f; f=BMIter_Step(&iter)) { - if (walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag)) { + if (walker->mask_face && !BMO_TestFlag(walker->bm, f, walker->mask_face)) { continue; } if (BLI_ghash_haskey(walker->visithash, f)) continue; @@ -765,7 +765,7 @@ static void *uvedgeWalker_step(BMWalker *walker) BMW_removestate(walker); - if (walker->restrictflag && !BMO_TestFlag(walker->bm, l->e, walker->restrictflag)) + if (walker->mask_edge && !BMO_TestFlag(walker->bm, l->e, walker->mask_edge)) return l; /*go over loops around l->v and nl->v and see which ones share l and nl's @@ -780,7 +780,7 @@ static void *uvedgeWalker_step(BMWalker *walker) for (j=0; jvisithash, l2)) continue; - if (walker->restrictflag && !(BMO_TestFlag(walker->bm, l2->e, walker->restrictflag))) + if (walker->mask_edge && !(BMO_TestFlag(walker->bm, l2->e, walker->mask_edge))) { if (l2->v != cl->v) continue; @@ -812,6 +812,7 @@ static BMWalker shell_walker_type = { shellWalker_yield, sizeof(shellWalker), BMW_BREADTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker islandbound_walker_type = { @@ -820,6 +821,7 @@ static BMWalker islandbound_walker_type = { islandboundWalker_yield, sizeof(islandboundWalker), BMW_DEPTH_FIRST, + BM_FACE, /* valid restrict masks */ }; static BMWalker island_walker_type = { @@ -828,6 +830,7 @@ static BMWalker island_walker_type = { islandWalker_yield, sizeof(islandWalker), BMW_BREADTH_FIRST, + BM_FACE, /* valid restrict masks */ }; static BMWalker loop_walker_type = { @@ -836,6 +839,7 @@ static BMWalker loop_walker_type = { loopWalker_yield, sizeof(loopWalker), BMW_DEPTH_FIRST, + 0, /* valid restrict masks */ /* could add flags here but so far none are used */ }; static BMWalker faceloop_walker_type = { @@ -844,6 +848,7 @@ static BMWalker faceloop_walker_type = { faceloopWalker_yield, sizeof(faceloopWalker), BMW_DEPTH_FIRST, + 0, /* valid restrict masks */ /* could add flags here but so far none are used */ }; static BMWalker edgering_walker_type = { @@ -852,6 +857,7 @@ static BMWalker edgering_walker_type = { edgeringWalker_yield, sizeof(edgeringWalker), BMW_DEPTH_FIRST, + 0, /* valid restrict masks */ /* could add flags here but so far none are used */ }; static BMWalker loopdata_region_walker_type = { @@ -860,6 +866,7 @@ static BMWalker loopdata_region_walker_type = { uvedgeWalker_yield, sizeof(uvedgeWalker), BMW_DEPTH_FIRST, + BM_EDGE, /* valid restrict masks */ }; static BMWalker connected_vertex_walker_type = { @@ -868,17 +875,18 @@ static BMWalker connected_vertex_walker_type = { connectedVertexWalker_yield, sizeof(connectedVertexWalker), BMW_BREADTH_FIRST, + BM_VERT, /* valid restrict masks */ }; BMWalker *bm_walker_types[] = { - &shell_walker_type, - &loop_walker_type, - &faceloop_walker_type, - &edgering_walker_type, - &loopdata_region_walker_type, - &islandbound_walker_type, - &island_walker_type, - &connected_vertex_walker_type, + &shell_walker_type, /* BMW_SHELL */ + &loop_walker_type, /* BMW_LOOP */ + &faceloop_walker_type, /* BMW_FACELOOP */ + &edgering_walker_type, /* BMW_EDGERING */ + &loopdata_region_walker_type, /* BMW_LOOPDATA_ISLAND */ + &islandbound_walker_type, /* BMW_ISLANDBOUND */ + &island_walker_type, /* BMW_ISLAND */ + &connected_vertex_walker_type, /* BMW_CONNECTED_VERTEX */ }; int bm_totwalkers = sizeof(bm_walker_types) / sizeof(*bm_walker_types); diff --git a/source/blender/bmesh/operators/dissolveops.c b/source/blender/bmesh/operators/dissolveops.c index 6e61956f6ef..a8f73da2d84 100644 --- a/source/blender/bmesh/operators/dissolveops.c +++ b/source/blender/bmesh/operators/dissolveops.c @@ -28,7 +28,7 @@ static int UNUSED_FUNCTION(check_hole_in_region)(BMesh *bm, BMFace *f) /*checks if there are any unmarked boundary edges in the face region*/ - BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK, BMW_NIL_LAY); + BMW_Init(®walker, bm, BMW_ISLAND, 0,0,0,FACE_MARK, BMW_NIL_LAY); f2 = BMW_Begin(®walker, f); for (; f2; f2=BMW_Step(®walker)) { l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2); @@ -69,7 +69,7 @@ void dissolvefaces_exec(BMesh *bm, BMOperator *op) faces = NULL; /*forces different allocation*/ /*yay, walk!*/ - BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK, BMW_NIL_LAY); + BMW_Init(®walker, bm, BMW_ISLAND, 0,0,0,FACE_MARK, BMW_NIL_LAY); f2 = BMW_Begin(®walker, f); for (; f2; f2=BMW_Step(®walker)) { BLI_array_append(faces, f2); diff --git a/source/blender/bmesh/operators/removedoubles.c b/source/blender/bmesh/operators/removedoubles.c index c7a38c94c45..14d74a61e4c 100644 --- a/source/blender/bmesh/operators/removedoubles.c +++ b/source/blender/bmesh/operators/removedoubles.c @@ -347,7 +347,7 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op) BMO_Init_Op(bm, &weldop, "weldverts"); BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE); - BMW_Init(&walker, bm, BMW_SHELL, EDGE_MARK, BMW_NIL_LAY); + BMW_Init(&walker, bm, BMW_SHELL, 0,EDGE_MARK,0,0, BMW_NIL_LAY); BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) { if (!BMO_TestFlag(bm, e, EDGE_MARK)) @@ -402,7 +402,7 @@ static void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer) BMO_Clear_Flag_All(bm, op, BM_ALL, 65535); BMO_Flag_Buffer(bm, op, "edges", EDGE_MARK, BM_EDGE); - BMW_Init(&walker, bm, BMW_LOOPDATA_ISLAND, EDGE_MARK, layer); + BMW_Init(&walker, bm, BMW_LOOPDATA_ISLAND, 0,EDGE_MARK,0,0, layer); BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) { BM_ITER(l, &liter, bm, BM_LOOPS_OF_FACE, f) { diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c index d583f505a46..055c08ea6f3 100644 --- a/source/blender/editors/mesh/bmesh_select.c +++ b/source/blender/editors/mesh/bmesh_select.c @@ -885,7 +885,7 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, int selec BMHeader *h; BMWalker walker; - BMW_Init(&walker, bm, walkercode, 0, BMW_NIL_LAY); + BMW_Init(&walker, bm, walkercode, 0,0,0,0, BMW_NIL_LAY); h = BMW_Begin(&walker, start); for (; h; h=BMW_Step(&walker)) { if (!select) @@ -1770,7 +1770,7 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event eed = eve->e; } - BMW_Init(&walker, em->bm, BMW_SHELL, 0, BMW_NIL_LAY); + BMW_Init(&walker, em->bm, BMW_SHELL, 0,0,0,0, BMW_NIL_LAY); e = BMW_Begin(&walker, eed->v1); for (; e; e=BMW_Step(&walker)) { BM_Select(em->bm, e->v1, sel); @@ -1822,7 +1822,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) } } - BMW_Init(&walker, em->bm, BMW_SHELL, 0, BMW_NIL_LAY); + BMW_Init(&walker, em->bm, BMW_SHELL, 0,0,0,0, BMW_NIL_LAY); for (i=0; iv1, 1); diff --git a/source/blender/editors/mesh/loopcut.c b/source/blender/editors/mesh/loopcut.c index c3797962f0b..313ebb310de 100644 --- a/source/blender/editors/mesh/loopcut.c +++ b/source/blender/editors/mesh/loopcut.c @@ -204,7 +204,7 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select) } if (select) { - BMW_Init(&walker, em->bm, BMW_EDGERING, 0, BMW_NIL_LAY); + BMW_Init(&walker, em->bm, BMW_EDGERING, 0,0,0,0, BMW_NIL_LAY); eed = BMW_Begin(&walker, startedge); for (; eed; eed=BMW_Step(&walker)) { BM_Select(em->bm, eed, 1); @@ -214,7 +214,7 @@ static void edgering_sel(tringselOpData *lcd, int previewlines, int select) return; } - BMW_Init(&walker, em->bm, BMW_EDGERING, 0, BMW_NIL_LAY); + BMW_Init(&walker, em->bm, BMW_EDGERING, 0,0,0,0, BMW_NIL_LAY); eed = startedge = BMW_Begin(&walker, startedge); lastv1 = NULL; for (lasteed=NULL; eed; eed=BMW_Step(&walker)) {