diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.cc b/source/blender/bmesh/intern/bmesh_mesh_normals.cc index b472caec87f..eef566e6241 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.cc @@ -2050,6 +2050,104 @@ static void bm_loop_normal_mark_indiv_do_loop(BMLoop *l, } } +static void bm_loop_normal_mark_verts_impl(BMesh *bm, + BLI_bitmap *loops, + const bool do_all_loops_of_vert, + int *totloopsel_p) +{ + /* Select all loops of selected verts. */ + BMLoop *l; + BMVert *v; + BMIter liter, viter; + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + bm_loop_normal_mark_indiv_do_loop( + l, loops, bm->lnor_spacearr, totloopsel_p, do_all_loops_of_vert); + } + } + } +} + +static void bm_loop_normal_mark_edges_impl(BMesh *bm, + BLI_bitmap *loops, + const bool do_all_loops_of_vert, + int *totloopsel_p) +{ + /* Only select all loops of selected edges. */ + BMLoop *l; + BMEdge *e; + BMIter liter, eiter; + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { + bm_loop_normal_mark_indiv_do_loop( + l, loops, bm->lnor_spacearr, totloopsel_p, do_all_loops_of_vert); + /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects + * *two* loops in each of its faces. We have to find the other one too. */ + if (BM_vert_in_edge(e, l->next->v)) { + bm_loop_normal_mark_indiv_do_loop( + l->next, loops, bm->lnor_spacearr, totloopsel_p, do_all_loops_of_vert); + } + else { + BLI_assert(BM_vert_in_edge(e, l->prev->v)); + bm_loop_normal_mark_indiv_do_loop( + l->prev, loops, bm->lnor_spacearr, totloopsel_p, do_all_loops_of_vert); + } + } + } + } +} + +static void bm_loop_normal_mark_faces_impl(BMesh *bm, + BLI_bitmap *loops, + const bool do_all_loops_of_vert, + int *totloopsel_p) +{ + /* Only select all loops of selected faces. */ + BMLoop *l; + BMFace *f; + BMIter liter, fiter; + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { + bm_loop_normal_mark_indiv_do_loop( + l, loops, bm->lnor_spacearr, totloopsel_p, do_all_loops_of_vert); + } + } + } +} + +static int bm_loop_normal_mark_verts(BMesh *bm, BLI_bitmap *loops, const bool do_all_loops_of_vert) +{ + BM_mesh_elem_index_ensure(bm, BM_LOOP); + BLI_assert(bm->lnor_spacearr != nullptr); + BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR); + int totloopsel = 0; + bm_loop_normal_mark_verts_impl(bm, loops, do_all_loops_of_vert, &totloopsel); + return totloopsel; +} + +static int bm_loop_normal_mark_edges(BMesh *bm, BLI_bitmap *loops, const bool do_all_loops_of_vert) +{ + BM_mesh_elem_index_ensure(bm, BM_LOOP); + BLI_assert(bm->lnor_spacearr != nullptr); + BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR); + int totloopsel = 0; + bm_loop_normal_mark_edges_impl(bm, loops, do_all_loops_of_vert, &totloopsel); + return totloopsel; +} + +static int bm_loop_normal_mark_faces(BMesh *bm, BLI_bitmap *loops, const bool do_all_loops_of_vert) +{ + BM_mesh_elem_index_ensure(bm, BM_LOOP); + BLI_assert(bm->lnor_spacearr != nullptr); + BLI_assert(bm->lnor_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR); + int totloopsel = 0; + bm_loop_normal_mark_faces_impl(bm, loops, do_all_loops_of_vert, &totloopsel); + return totloopsel; +} + /* Mark the individual clnors to be edited, if multiple selection methods are used. */ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops, const bool do_all_loops_of_vert) { @@ -2104,57 +2202,13 @@ static int bm_loop_normal_mark_indiv(BMesh *bm, BLI_bitmap *loops, const bool do } else { if (sel_faces) { - /* Only select all loops of selected faces. */ - BMLoop *l; - BMFace *f; - BMIter liter, fiter; - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { - bm_loop_normal_mark_indiv_do_loop( - l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); - } - } - } + bm_loop_normal_mark_faces_impl(bm, loops, do_all_loops_of_vert, &totloopsel); } if (sel_edges) { - /* Only select all loops of selected edges. */ - BMLoop *l; - BMEdge *e; - BMIter liter, eiter; - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - bm_loop_normal_mark_indiv_do_loop( - l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); - /* Loops actually 'have' two edges, or said otherwise, a selected edge actually selects - * *two* loops in each of its faces. We have to find the other one too. */ - if (BM_vert_in_edge(e, l->next->v)) { - bm_loop_normal_mark_indiv_do_loop( - l->next, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); - } - else { - BLI_assert(BM_vert_in_edge(e, l->prev->v)); - bm_loop_normal_mark_indiv_do_loop( - l->prev, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); - } - } - } - } + bm_loop_normal_mark_edges_impl(bm, loops, do_all_loops_of_vert, &totloopsel); } if (sel_verts) { - /* Select all loops of selected verts. */ - BMLoop *l; - BMVert *v; - BMIter liter, viter; - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - bm_loop_normal_mark_indiv_do_loop( - l, loops, bm->lnor_spacearr, &totloopsel, do_all_loops_of_vert); - } - } - } + bm_loop_normal_mark_verts_impl(bm, loops, do_all_loops_of_vert, &totloopsel); } } @@ -2184,8 +2238,8 @@ static void loop_normal_editdata_init( lnor_ed->loc = v->co; } -BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm, - const bool do_all_loops_of_vert) +BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init_with_htype( + BMesh *bm, const bool do_all_loops_of_vert, const char htype_override) { BMLoop *l; BMVert *v; @@ -2208,7 +2262,26 @@ BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm, BLI_bitmap *loops = BLI_BITMAP_NEW(bm->totloop, __func__); /* This function define loop normals to edit, based on selection modes and history. */ - totloopsel = bm_loop_normal_mark_indiv(bm, loops, do_all_loops_of_vert); + if (htype_override != 0) { + BLI_assert(ELEM(htype_override, BM_VERT, BM_EDGE, BM_FACE)); + switch (htype_override) { + case BM_VERT: { + totloopsel = bm_loop_normal_mark_verts(bm, loops, do_all_loops_of_vert); + break; + } + case BM_EDGE: { + totloopsel = bm_loop_normal_mark_edges(bm, loops, do_all_loops_of_vert); + break; + } + case BM_FACE: { + totloopsel = bm_loop_normal_mark_faces(bm, loops, do_all_loops_of_vert); + break; + } + } + } + else { + totloopsel = bm_loop_normal_mark_indiv(bm, loops, do_all_loops_of_vert); + } if (totloopsel) { BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata = @@ -2231,6 +2304,12 @@ BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm, return lnors_ed_arr; } +BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm, + const bool do_all_loops_of_vert) +{ + return BM_loop_normal_editdata_array_init_with_htype(bm, do_all_loops_of_vert, 0); +} + void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr) { MEM_SAFE_FREE(lnors_ed_arr->lnor_editdata); diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.hh b/source/blender/bmesh/intern/bmesh_mesh_normals.hh index f7adaacfaa0..e2f0402efad 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.hh +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.hh @@ -87,6 +87,15 @@ void BM_lnorspace_err(BMesh *bm); #endif /* Loop Generics */ + +/** + * Initialize loop data based on a type, overriding the #BMesh::selectmode of `bm`. + * This can be useful if a single types selection is preferred, + * instead of using mixed modes and the selection history. + */ +BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init_with_htype(BMesh *bm, + bool do_all_loops_of_vert, + char htype_override); BMLoopNorEditDataArray *BM_loop_normal_editdata_array_init(BMesh *bm, bool do_all_loops_of_vert); void BM_loop_normal_editdata_array_free(BMLoopNorEditDataArray *lnors_ed_arr);