[Bf-blender-cvs] [cb261c96f56] temp-uv-face-select-no-thresh-when-inside: UV: tweak face select behavior

Campbell Barton noreply at git.blender.org
Mon Jan 18 08:28:59 CET 2021


Commit: cb261c96f56b0b6d42caec77a6be2e7a94f75e6d
Author: Campbell Barton
Date:   Mon Jan 18 18:24:56 2021 +1100
Branches: temp-uv-face-select-no-thresh-when-inside
https://developer.blender.org/rBcb261c96f56b0b6d42caec77a6be2e7a94f75e6d

UV: tweak face select behavior

When the mouse cursor is inside the UV face,
extend the selection threshold.

This means when zoomed in, a face can always be selected when the cursor
is inside it.
In the case of multiple overlapping faces - the face with the closest
center is used.

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

M	source/blender/bmesh/intern/bmesh_query_uv.c
M	source/blender/bmesh/intern/bmesh_query_uv.h
M	source/blender/editors/uvedit/uvedit_intern.h
M	source/blender/editors/uvedit/uvedit_select.c

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

diff --git a/source/blender/bmesh/intern/bmesh_query_uv.c b/source/blender/bmesh/intern/bmesh_query_uv.c
index d3067109d4e..f9b87e4e71c 100644
--- a/source/blender/bmesh/intern/bmesh_query_uv.c
+++ b/source/blender/bmesh/intern/bmesh_query_uv.c
@@ -203,3 +203,22 @@ bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int
 
   return true;
 }
+
+/**
+ * Check if the point is inside the UV face.
+ */
+bool BM_face_uv_point_inside_test(const BMFace *f, const float co[2], const int cd_loop_uv_offset)
+{
+  float(*projverts)[2] = BLI_array_alloca(projverts, f->len);
+
+  BMLoop *l_iter;
+  int i;
+
+  BLI_assert(BM_face_is_normal_valid(f));
+
+  for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
+    copy_v2_v2(projverts[i], BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset));
+  }
+
+  return isect_point_poly_v2(co, projverts, f->len, false);
+}
diff --git a/source/blender/bmesh/intern/bmesh_query_uv.h b/source/blender/bmesh/intern/bmesh_query_uv.h
index fe62c5a8809..850b27d3894 100644
--- a/source/blender/bmesh/intern/bmesh_query_uv.h
+++ b/source/blender/bmesh/intern/bmesh_query_uv.h
@@ -58,3 +58,8 @@ bool BM_loop_uv_share_vert_check(BMLoop *l_a,
                                  BMLoop *l_b,
                                  const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL();
+
+bool BM_face_uv_point_inside_test(const BMFace *f,
+                                  const float co[2],
+                                  const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
+    ATTR_NONNULL();
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 45d65e7070e..3785f7819e3 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -93,10 +93,21 @@ bool uv_find_nearest_edge_multi(struct Scene *scene,
                                 const float co[2],
                                 struct UvNearestHit *hit);
 
+bool uv_find_nearest_face_ex(struct Scene *scene,
+                             struct Object *obedit,
+                             const float co[2],
+                             struct UvNearestHit *hit,
+                             struct UvNearestHit *hit_in_face);
 bool uv_find_nearest_face(struct Scene *scene,
                           struct Object *obedit,
                           const float co[2],
                           struct UvNearestHit *hit);
+bool uv_find_nearest_face_multi_ex(struct Scene *scene,
+                                   struct Object **objects,
+                                   const uint objects_len,
+                                   const float co[2],
+                                   struct UvNearestHit *hit,
+                                   struct UvNearestHit *hit_in_face);
 bool uv_find_nearest_face_multi(struct Scene *scene,
                                 struct Object **objects,
                                 const uint objects_len,
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index 1cbd2553879..e228011bc57 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -721,7 +721,8 @@ bool uv_find_nearest_edge_multi(
   return found;
 }
 
-bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit)
+bool uv_find_nearest_face_ex(
+    Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit, UvNearestHit *hit_in_face)
 {
   BLI_assert((hit->scale[0] > 0.0f) && (hit->scale[1] > 0.0f));
   BMEditMesh *em = BKE_editmesh_from_object(obedit);
@@ -752,23 +753,49 @@ bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNea
       hit->dist_sq = dist_test_sq;
       found = true;
     }
+
+    if (hit_in_face != NULL) {
+      if (dist_test_sq < hit_in_face->dist_sq) {
+        if (BM_face_uv_point_inside_test(efa, co, cd_loop_uv_offset)) {
+          hit_in_face->ob = obedit;
+          hit_in_face->efa = efa;
+          hit_in_face->dist_sq = dist_test_sq;
+          found = true;
+        }
+      }
+    }
   }
   return found;
 }
 
-bool uv_find_nearest_face_multi(
-    Scene *scene, Object **objects, const uint objects_len, const float co[2], UvNearestHit *hit)
+bool uv_find_nearest_face(Scene *scene, Object *obedit, const float co[2], UvNearestHit *hit)
+{
+  return uv_find_nearest_face_ex(scene, obedit, co, hit, NULL);
+}
+
+bool uv_find_nearest_face_multi_ex(Scene *scene,
+                                   Object **objects,
+                                   const uint objects_len,
+                                   const float co[2],
+                                   UvNearestHit *hit,
+                                   UvNearestHit *hit_in_face)
 {
   bool found = false;
   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
     Object *obedit = objects[ob_index];
-    if (uv_find_nearest_face(scene, obedit, co, hit)) {
+    if (uv_find_nearest_face_ex(scene, obedit, co, hit, hit_in_face)) {
       found = true;
     }
   }
   return found;
 }
 
+bool uv_find_nearest_face_multi(
+    Scene *scene, Object **objects, const uint objects_len, const float co[2], UvNearestHit *hit)
+{
+  return uv_find_nearest_face_multi_ex(scene, objects, objects_len, co, hit, NULL);
+}
+
 static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset)
 {
   const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv;
@@ -1935,8 +1962,14 @@ static int uv_mouse_select_multi(bContext *C,
   }
   else if (selectmode == UV_SELECT_FACE) {
     /* find face */
-    found_item = uv_find_nearest_face_multi(scene, objects, objects_len, co, &hit);
+    UvNearestHit hit_in_face = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
+    found_item = uv_find_nearest_face_multi_ex(
+        scene, objects, objects_len, co, &hit, &hit_in_face);
     if (found_item) {
+      if (hit.ob == NULL) {
+        hit = hit_in_face;
+        printf("Using hit in face\n");
+      }
       BMesh *bm = BKE_editmesh_from_object(hit.ob)->bm;
       BM_mesh_active_face_set(bm, hit.efa);
     }



More information about the Bf-blender-cvs mailing list