[Bf-blender-cvs] [246efd7286f] master: Fix UV selection threshold which ignored image aspect and zoom level

Campbell Barton noreply at git.blender.org
Sat Jan 9 09:16:38 CET 2021


Commit: 246efd7286f6187e4dd4b3edcc79cccb1746bb1d
Author: Campbell Barton
Date:   Sat Jan 9 18:27:25 2021 +1100
Branches: master
https://developer.blender.org/rB246efd7286f6187e4dd4b3edcc79cccb1746bb1d

Fix UV selection threshold which ignored image aspect and zoom level

Selecting UVs wasn't properly scaling based on the zoom or image aspect.

This now matches vertex selection in the 3D view.

===================================================================

M	source/blender/editors/sculpt_paint/sculpt_uv.c
M	source/blender/editors/uvedit/uvedit_intern.h
M	source/blender/editors/uvedit/uvedit_ops.c
M	source/blender/editors/uvedit/uvedit_path.c
M	source/blender/editors/uvedit/uvedit_select.c
M	source/blender/editors/uvedit/uvedit_smart_stitch.c

===================================================================

diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index f77d473ae57..219a8303674 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -543,7 +543,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
     /* we need to find the active island here */
     if (do_island_optimization) {
       UvElement *element;
-      UvNearestHit hit = UV_NEAREST_HIT_INIT;
+      UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
       uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit);
 
       element = BM_uv_element_get(data->elementMap, hit.efa, hit.l);
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 28567234fab..6fef7ebcf22 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -41,13 +41,34 @@ typedef struct UvNearestHit {
   /** Always set if we have a hit. */
   struct BMFace *efa;
   struct BMLoop *l;
-  /** Needs to be set before calling nearest functions. */
+  /**
+   * Needs to be set before calling nearest functions.
+   *
+   * \note When #UV_NEAREST_HIT_INIT_DIST_PX or #UV_NEAREST_HIT_INIT_MAX are used,
+   * this value is pixels squared.
+   */
   float dist_sq;
+
+  /** Scale the UV's to account for aspect ratio from the image view. */
+  float scale[2];
 } UvNearestHit;
 
-#define UV_NEAREST_HIT_INIT \
+#define UV_NEAREST_HIT_INIT_DIST_PX(v2d, dist_px) \
+  { \
+    .dist_sq = square_f(U.pixelsize * dist_px), \
+    .scale = { \
+        UI_view2d_scale_get_x(v2d), \
+        UI_view2d_scale_get_y(v2d), \
+    }, \
+  }
+
+#define UV_NEAREST_HIT_INIT_MAX(v2d) \
   { \
     .dist_sq = FLT_MAX, \
+    .scale = { \
+        UI_view2d_scale_get_x(v2d), \
+        UI_view2d_scale_get_y(v2d), \
+    }, \
   }
 
 bool uv_find_nearest_vert(struct Scene *scene,
@@ -96,7 +117,6 @@ BMLoop *uv_find_nearest_loop_from_edge(struct Scene *scene,
 void uvedit_live_unwrap_update(struct SpaceImage *sima,
                                struct Scene *scene,
                                struct Object *obedit);
-void uvedit_pixel_to_float(struct SpaceImage *sima, float pixeldist, float r_dist[2]);
 
 /* operators */
 
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index aac5b96f737..167acf7da18 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -186,28 +186,6 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i
 
 /** \} */
 
-/* -------------------------------------------------------------------- */
-/** \name Space Conversion
- * \{ */
-
-void uvedit_pixel_to_float(SpaceImage *sima, float pixeldist, float r_dist[2])
-{
-  int width, height;
-
-  if (sima) {
-    ED_space_image_get_size(sima, &width, &height);
-  }
-  else {
-    width = IMG_SIZE_FALLBACK;
-    height = IMG_SIZE_FALLBACK;
-  }
-
-  r_dist[0] = pixeldist / width;
-  r_dist[1] = pixeldist / height;
-}
-
-/** \} */
-
 /* -------------------------------------------------------------------- */
 /** \name Live Unwrap Utilities
  * \{ */
diff --git a/source/blender/editors/uvedit/uvedit_path.c b/source/blender/editors/uvedit/uvedit_path.c
index 51de199c696..016a054cf21 100644
--- a/source/blender/editors/uvedit/uvedit_path.c
+++ b/source/blender/editors/uvedit/uvedit_path.c
@@ -574,7 +574,7 @@ static bool uv_shortest_path_pick_ex(const SpaceImage *sima,
 
 static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 {
-  const SpaceImage *sima = CTX_wm_space_image(C);
+  SpaceImage *sima = CTX_wm_space_image(C);
   Scene *scene = CTX_data_scene(C);
   const ToolSettings *ts = scene->toolsettings;
   const char uv_selectmode = ED_uvedit_select_mode_get(scene);
@@ -613,7 +613,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
   BMElem *ele_src = NULL, *ele_dst = NULL;
 
   if (uv_selectmode == UV_SELECT_FACE) {
-    UvNearestHit hit = UV_NEAREST_HIT_INIT;
+    UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
     if (!uv_find_nearest_face(scene, obedit, co, &hit)) {
       return OPERATOR_CANCELLED;
     }
@@ -626,7 +626,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
   }
 
   else if (uv_selectmode & UV_SELECT_EDGE) {
-    UvNearestHit hit = UV_NEAREST_HIT_INIT;
+    UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
     if (!uv_find_nearest_edge(scene, obedit, co, &hit)) {
       return OPERATOR_CANCELLED;
     }
@@ -652,7 +652,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
     ele_dst = (BMElem *)hit.l;
   }
   else {
-    UvNearestHit hit = UV_NEAREST_HIT_INIT;
+    UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
     if (!uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit)) {
       return OPERATOR_CANCELLED;
     }
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index bfb01cb073e..118a2263cc3 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -201,21 +201,6 @@ void ED_uvedit_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const b
   }
 }
 
-/**
- * Apply a penalty to elements that are already selected
- * so elements that aren't already selected are prioritized.
- *
- * \note This is calculated in screen-space otherwise zooming in on a uv-vert and
- * shift-selecting can consider an adjacent point close enough to add to
- * the selection rather than de-selecting the closest.
- */
-static float uv_select_penalty_default(SpaceImage *sima)
-{
-  float penalty[2];
-  uvedit_pixel_to_float(sima, 5.0f / (sima ? sima->zoom : 1.0f), penalty);
-  return len_v2(penalty);
-}
-
 static void uvedit_vertex_select_tagged(BMEditMesh *em,
                                         Scene *scene,
                                         bool select,
@@ -680,6 +665,7 @@ static BMLoop *uvedit_loop_find_other_boundary_loop_with_visible_face(const Scen
 
 bool uv_find_nearest_edge(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit)
 {
+  BLI_assert((hit->scale[0] > 0.0f) && (hit->scale[1] > 0.0f));
   BMEditMesh *em = BKE_editmesh_from_object(obedit);
   BMFace *efa;
   BMLoop *l;
@@ -700,7 +686,13 @@ bool uv_find_nearest_edge(Scene *scene, Object *obedit, const float co[2], UvNea
       luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
       luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
 
-      const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv);
+      float delta[2];
+      closest_to_line_segment_v2(delta, co, luv->uv, luv_next->uv);
+
+      sub_v2_v2(delta, co);
+      mul_v2_v2(delta, hit->scale);
+
+      const float dist_test_sq = len_squared_v2(delta);
 
       if (dist_test_sq < hit->dist_sq) {
         hit->efa = efa;
@@ -734,6 +726,7 @@ bool uv_find_nearest_edge_multi(Scene *scene,
 
 bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit_final)
 {
+  BLI_assert((hit_final->scale[0] > 0.0f) && (hit_final->scale[1] > 0.0f));
   BMEditMesh *em = BKE_editmesh_from_object(obedit);
   bool found = false;
 
@@ -757,7 +750,11 @@ bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNea
       float cent[2];
       BM_face_uv_calc_center_median(efa, cd_loop_uv_offset, cent);
 
-      const float dist_test_sq = len_squared_v2v2(co, cent);
+      float delta[2];
+      sub_v2_v2v2(delta, co, cent);
+      mul_v2_v2(delta, hit.scale);
+
+      const float dist_test_sq = len_squared_v2(delta);
 
       if (dist_test_sq < hit.dist_sq) {
         hit.efa = efa;
@@ -805,9 +802,10 @@ bool uv_find_nearest_vert(Scene *scene,
                           const float penalty_dist,
                           UvNearestHit *hit_final)
 {
+  BLI_assert((hit_final->scale[0] > 0.0f) && (hit_final->scale[1] > 0.0f));
   bool found = false;
 
-  /* this will fill in hit.vert1 and hit.vert2 */
+  /* This will fill in `hit.l`. */
   float dist_sq_init = hit_final->dist_sq;
   UvNearestHit hit = *hit_final;
   if (uv_find_nearest_edge(scene, obedit, co, &hit)) {
@@ -832,14 +830,17 @@ bool uv_find_nearest_vert(Scene *scene,
       BMLoop *l;
       int i;
       BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
-        float dist_test_sq;
         MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
-        if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
-          dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist;
-          dist_test_sq = square_f(dist_test_sq);
-        }
-        else {
-          dist_test_sq = len_squared_v2v2(co, luv->uv);
+
+        float delta[2];
+
+        sub_v2_v2v2(delta, co, luv->uv);
+        mul_v2_v2(delta, hit.scale);
+
+        float dist_test_sq = len_squared_v2(delta);
+
+        if ((penalty_dist != 0.0f) && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+          dist_test_sq = square_f(sqrtf(dist_test_sq) + penalty_dist);
         }
 
         if (dist_test_sq <= hit.dist_sq) {
@@ -1912,15 +1913,18 @@ static int uv_mouse_select_multi(bContext *C,
 {
   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
   SpaceImage *sima = CTX_wm_space_image(C);
+  const ARegion *region = CTX_wm_region(C);
   Scene *scene = CTX_data_scene(C);
   const ToolSettings *ts = scene->toolsettings;
-  UvNearestHit hit = UV_NEAREST_HIT_INIT;
+  UvNearestHit hit = UV_NEAREST_HIT_INIT_DIST_PX(&region->v2d, 75.0f);
   int selectmode, sticky;
   bool found_item = false;
   /* 0 == don't flush, 1 == sel, -1 == desel;  only use when selection sync is enabled */
   int flush = 0;
 
-  const float penalty_dist = uv_select_penalty_default(sima);
+  /* Penalty (in pixels) applied to elements that are already selected
+   * so elements that aren't already selected are prioritized. */
+  const float penalty_dist = 3.0f * U.pixelsize;
 
   /* retrieve operation mode */
   if (ts->uv_flag & UV_SYNC_SELECTION) {
@@ 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list