From d81a32dcaaaa86dc27d22520ca64b338d70eda04 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Thu, 31 Aug 2023 01:27:00 -0300 Subject: [PATCH] UV: Deduplicate code that traverses each UV The algorithm that traverses UV is a bit complex and is being iterated a lot in different areas of the code. This commit deduplicates this code by creating a foreach UV function. At the moment only the `uvedit_ops.cc` file uses this function but similar cleanups can also be done on many other files that use UVs. --- source/blender/editors/include/ED_uvedit.hh | 11 + source/blender/editors/uvedit/uvedit_ops.cc | 330 ++++++-------------- 2 files changed, 112 insertions(+), 229 deletions(-) diff --git a/source/blender/editors/include/ED_uvedit.hh b/source/blender/editors/include/ED_uvedit.hh index 14b162825e7..a020374e768 100644 --- a/source/blender/editors/include/ED_uvedit.hh +++ b/source/blender/editors/include/ED_uvedit.hh @@ -41,6 +41,17 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf); */ void ED_uvedit_select_all(BMesh *bm); +void ED_uvedit_foreach_uv(const Scene *scene, + BMesh *bm, + const bool skip_invisible, + const bool selected, + blender::FunctionRef user_fn); +void ED_uvedit_foreach_uv_multi(const Scene *scene, + Object **objects_edit, + uint objects_len, + const bool skip_invisible, + const bool skip_nonselected, + blender::FunctionRef user_fn); bool ED_uvedit_minmax_multi( const Scene *scene, Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]); bool ED_uvedit_center_multi( diff --git a/source/blender/editors/uvedit/uvedit_ops.cc b/source/blender/editors/uvedit/uvedit_ops.cc index feb6054ae0c..0887c5996e1 100644 --- a/source/blender/editors/uvedit/uvedit_ops.cc +++ b/source/blender/editors/uvedit/uvedit_ops.cc @@ -59,6 +59,8 @@ #include "uvedit_intern.h" +using namespace blender; + /* -------------------------------------------------------------------- */ /** \name State Testing * \{ */ @@ -192,37 +194,61 @@ void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit) /** \name Geometric Utilities * \{ */ +void ED_uvedit_foreach_uv(const Scene *scene, + BMesh *bm, + const bool skip_invisible, + const bool selected, + FunctionRef user_fn) +{ + /* Check selection for quick return. */ + const bool synced_selection = (scene->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0; + if (synced_selection && (bm->totvertsel == selected ? 0 : bm->totvert)) { + return; + } + + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + + const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + if (skip_invisible && !uvedit_face_visible_test(scene, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (uvedit_uv_select_test(scene, l, offsets) == selected) { + float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); + user_fn(luv); + } + } + } +} + +void ED_uvedit_foreach_uv_multi(const Scene *scene, + Object **objects_edit, + uint objects_len, + const bool skip_invisible, + const bool skip_nonselected, + FunctionRef user_fn) +{ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects_edit[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + ED_uvedit_foreach_uv(scene, em->bm, skip_invisible, skip_nonselected, user_fn); + } +} + bool ED_uvedit_minmax_multi( const Scene *scene, Object **objects_edit, uint objects_len, float r_min[2], float r_max[2]) { bool changed = false; INIT_MINMAX2(r_min, r_max); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects_edit[ob_index]; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - float *luv; - - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, offsets)) { - luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - minmax_v2v2_v2(r_min, r_max, luv); - changed = true; - } - } - } - } + ED_uvedit_foreach_uv_multi(scene, objects_edit, objects_len, true, true, [&](float luv[2]) { + minmax_v2v2_v2(r_min, r_max, luv); + changed = true; + }); return changed; } @@ -249,31 +275,10 @@ static bool ED_uvedit_median_multi(const Scene *scene, uint sel = 0; zero_v2(co); - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects_edit[ob_index]; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - float *luv; - - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - if (uvedit_uv_select_test(scene, l, offsets)) { - add_v2_v2(co, luv); - sel++; - } - } - } - } + ED_uvedit_foreach_uv_multi(scene, objects_edit, objects_len, true, true, [&](float luv[2]) { + add_v2_v2(co, luv); + sel++; + }); mul_v2_fl(co, 1.0f / float(sel)); @@ -359,36 +364,22 @@ static bool uvedit_uv_align_weld(Scene *scene, const float cent[2]) { bool changed = false; - const BMUVOffsets offsets = BM_uv_map_get_offsets(bm); - BMIter iter; - BMFace *efa; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BMIter liter; - BMLoop *l; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (!uvedit_uv_select_test(scene, l, offsets)) { - continue; - } - float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - if (ELEM(tool, UV_ALIGN_X, UV_WELD)) { - if (luv[0] != cent[0]) { - luv[0] = cent[0]; - changed = true; - } - } - if (ELEM(tool, UV_ALIGN_Y, UV_WELD)) { - if (luv[1] != cent[1]) { - luv[1] = cent[1]; - changed = true; - } + ED_uvedit_foreach_uv(scene, bm, true, true, [&](float luv[2]) { + if (ELEM(tool, UV_ALIGN_X, UV_WELD)) { + if (luv[0] != cent[0]) { + luv[0] = cent[0]; + changed = true; } } - } + if (ELEM(tool, UV_ALIGN_Y, UV_WELD)) { + if (luv[1] != cent[1]) { + luv[1] = cent[1]; + changed = true; + } + } + }); + return changed; } @@ -561,33 +552,9 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) scene, view_layer, ((View3D *)nullptr), &objects_len); if (tool == UV_ALIGN_AUTO) { - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (synced_selection && (em->bm->totvertsel == 0)) { - continue; - } - - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BMIter iter, liter; - BMFace *efa; - BMLoop *l; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, offsets)) { - float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - minmax_v2v2_v2(min, max, luv); - } - } - } - } + ED_uvedit_foreach_uv_multi(scene, objects, objects_len, true, true, [&](float luv[2]) { + minmax_v2v2_v2(min, max, luv); + }); tool = (max[0] - min[0] >= max[1] - min[1]) ? UV_ALIGN_Y : UV_ALIGN_X; } @@ -718,33 +685,14 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op) int mloopuv_count = 0; /* Also used for *duplicates count. */ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - BMIter iter, liter; - BMFace *efa; - BMLoop *l; Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (synced_selection && (em->bm->totvertsel == 0)) { - continue; - } - - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, offsets)) { - float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - BLI_kdtree_2d_insert(tree, mloopuv_count, luv); - duplicates.append(-1); - mloopuv_arr.append(luv); - mloopuv_count++; - } - } - } + ED_uvedit_foreach_uv(scene, em->bm, true, true, [&](float luv[2]) { + BLI_kdtree_2d_insert(tree, mloopuv_count, luv); + duplicates.append(-1); + mloopuv_arr.append(luv); + mloopuv_count++; + }); ob_mloopuv_max_idx[ob_index] = mloopuv_count - 1; } @@ -845,70 +793,28 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op) int mloopuv_count = 0; /* Add visible non-selected uvs to tree */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - BMIter iter, liter; - BMFace *efa; - BMLoop *l; - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - if (synced_selection && (em->bm->totvertsel == em->bm->totvert)) { - continue; - } - - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (!uvedit_uv_select_test(scene, l, offsets)) { - float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - BLI_kdtree_2d_insert(tree, mloopuv_count, luv); - mloopuv_arr.append(luv); - mloopuv_count++; - } - } - } - } + ED_uvedit_foreach_uv_multi(scene, objects, objects_len, true, false, [&](float luv[2]) { + BLI_kdtree_2d_insert(tree, mloopuv_count, luv); + mloopuv_arr.append(luv); + mloopuv_count++; + }); BLI_kdtree_2d_balance(tree); /* For each selected uv, find duplicate non selected uv. */ for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - BMIter iter, liter; - BMFace *efa; - BMLoop *l; bool changed = false; Object *obedit = objects[ob_index]; BMEditMesh *em = BKE_editmesh_from_object(obedit); + ED_uvedit_foreach_uv(scene, em->bm, true, true, [&](float luv[2]) { + KDTreeNearest_2d nearest; + const int i = BLI_kdtree_2d_find_nearest(tree, luv, &nearest); - if (synced_selection && (em->bm->totvertsel == 0)) { - continue; - } - - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; + if (i != -1 && nearest.dist < threshold) { + copy_v2_v2(luv, mloopuv_arr[i]); + changed = true; } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, offsets)) { - float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - KDTreeNearest_2d nearest; - const int i = BLI_kdtree_2d_find_nearest(tree, luv, &nearest); - - if (i != -1 && nearest.dist < threshold) { - copy_v2_v2(luv, mloopuv_arr[i]); - changed = true; - } - } - } - } + }); if (changed) { uvedit_live_unwrap_update(sima, scene, obedit); @@ -1096,21 +1002,10 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Object *obedit, const float curs float *luv; bool changed = false; - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, offsets)) { - luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - copy_v2_v2(luv, cursor); - changed = true; - } - } - } + ED_uvedit_foreach_uv(scene, em->bm, true, true, [&](float luv[2]) { + copy_v2_v2(luv, cursor); + changed = true; + }); return changed; } @@ -1124,21 +1019,10 @@ static bool uv_snap_uvs_offset(Scene *scene, Object *obedit, const float offset[ float *luv; bool changed = false; - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, offsets)) { - luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - add_v2_v2(luv, offset); - changed = true; - } - } - } + ED_uvedit_foreach_uv(scene, em->bm, true, true, [&](float luv[2]) { + add_v2_v2(luv, offset); + changed = true; + }); return changed; } @@ -1209,26 +1093,14 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit float w, h; bool changed = false; - const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm); - ED_space_image_get_size(sima, &width, &height); w = float(width); h = float(height); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (uvedit_uv_select_test(scene, l, offsets)) { - luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv); - uv_snap_to_pixel(luv, w, h); - } - } - + ED_uvedit_foreach_uv(scene, em->bm, true, true, [&](float luv[2]) { + uv_snap_to_pixel(luv, w, h); changed = true; - } + }); return changed; }