Refactor: move logic for creating custom-normal arrays into functions

Also add `BM_loop_normal_editdata_array_init_with_htype`
(needed to fix #146515).

Ref !147087
This commit is contained in:
Campbell Barton
2025-10-01 03:40:04 +00:00
parent cc04e0128d
commit 2fd3b557d8
2 changed files with 138 additions and 50 deletions

View File

@@ -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);

View File

@@ -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);