Commit: a7f24a8307ce2fedbca27495344a9d7623c094f1
Author: Siddhartha Jejurkar
Date:   Mon Aug 9 03:00:27 2021 +0530
Branches: soc-2021-uv-editor-improvements-edge-selection
https://developer.blender.org/rBa7f24a8307ce2fedbca27495344a9d7623c094f1

Edge selection support for Edge ring and loop select operator

* Adds edge selection support for edge ring and edge loop select operator
* Selecting face loops in the UV editor is now done through the loop
  select operator

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

M       source/blender/editors/uvedit/uvedit_select.c

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

diff --git a/source/blender/editors/uvedit/uvedit_select.c 
b/source/blender/editors/uvedit/uvedit_select.c
index 2ba64bb7961..d7762775296 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -844,14 +844,10 @@ void uvedit_uv_select_disable(const Scene *scene,
   }
 }
 
-/* Returns a radial loop which shares the same UV edge and has a visible UV 
face.
- * If more than one such radial loops exist then return NULL */
 static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(const 
Scene *scene,
                                                                     BMLoop 
*l_src,
                                                                     const int 
cd_loop_uv_offset)
 {
-  /* This function basically tells if the UV edge associated with this loop is 
a boundry edge or if
-   * it is shared with another UV face or not */
   BMLoop *l_other = NULL;
   BMLoop *l_iter = l_src->radial_next;
   if (l_iter != l_src) {
@@ -873,14 +869,11 @@ static BMLoop 
*uvedit_loop_find_other_radial_loop_with_visible_face(const Scene
   return l_other;
 }
 
-/* Finds the loop belonging to another face that is also a boundry loop (is at 
the boundry of UV)
- */
 static BMLoop *uvedit_loop_find_other_boundary_loop_with_visible_face(const 
Scene *scene,
                                                                       BMLoop 
*l_edge,
                                                                       BMVert 
*v_pivot,
                                                                       const 
int cd_loop_uv_offset)
 {
-  /* This function helps find another loop whose UV edge is also a boundry 
edge) */
   BLI_assert(uvedit_loop_find_other_radial_loop_with_visible_face(
                  scene, l_edge, cd_loop_uv_offset) == NULL);
 
@@ -1645,7 +1638,7 @@ static int uv_select_edgeloop(
   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, 
CD_MLOOPUV);
 
   if (extend) {
-    select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset));
+    select = !(uvedit_edge_select_test(scene, hit->l, cd_loop_uv_offset));
   }
   else {
     select = true;
@@ -1712,6 +1705,70 @@ static int uv_select_edgeloop(
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Face Loop Select
+ * \{ */
+
+static int uv_select_faceloop(
+    const SpaceImage *sima, Scene *scene, Object *obedit, UvNearestHit *hit, 
const bool extend)
+{
+  BMEditMesh *em = BKE_editmesh_from_object(obedit);
+  bool select;
+
+  const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, 
CD_MLOOPUV);
+
+  if (!extend) {
+    uv_select_all_perform(scene, NULL, obedit, SEL_DESELECT);
+  }
+
+  BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
+
+  if (extend) {
+    select = !(uvedit_face_select_test(scene, hit->l->f, cd_loop_uv_offset));
+  }
+  else {
+    select = true;
+  }
+
+  BMLoop *l_pair[2] = {
+      hit->l,
+      uvedit_loop_find_other_radial_loop_with_visible_face(scene, hit->l, 
cd_loop_uv_offset),
+  };
+
+  for (int side = 0; side < 2; side++) {
+    BMLoop *l_step = l_pair[side];
+    while (l_step) {
+      if (!uvedit_face_visible_test(scene, l_step->f)) {
+        break;
+      }
+
+      uvedit_face_select_set_with_sticky(
+          sima, scene, em, l_step->f, select, false, cd_loop_uv_offset);
+
+      BM_elem_flag_enable(l_step->f, BM_ELEM_TAG);
+      if (l_step->f->len == 4) {
+        BMLoop *l_step_opposite = l_step->next->next;
+        l_step = uvedit_loop_find_other_radial_loop_with_visible_face(
+            scene, l_step_opposite, cd_loop_uv_offset);
+      }
+      else {
+        l_step = NULL;
+      }
+
+      /* Break iteration when l_step :
+       * - is the first loop where we started from
+       * - tagged using BM_ELEM_TAG(meaning this loop has been visited in this 
iteration) */
+      if (l_step && BM_elem_flag_test(l_step->f, BM_ELEM_TAG)) {
+        break;
+      }
+    }
+  }
+
+  return (select) ? 1 : -1;
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Edge Ring Select
  * \{ */
@@ -1724,6 +1781,9 @@ static int uv_select_edgering(
   const bool use_face_select = (ts->uv_flag & UV_SYNC_SELECTION) ?
                                    (ts->selectmode & SCE_SELECT_FACE) :
                                    (ts->uv_selectmode & UV_SELECT_FACE);
+  const bool use_vertex_select = (ts->uv_flag & UV_SYNC_SELECTION) ?
+                                     (ts->selectmode & SCE_SELECT_VERTEX) :
+                                     (ts->uv_selectmode & UV_SELECT_VERTEX);
   bool select;
 
   const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, 
CD_MLOOPUV);
@@ -1735,7 +1795,7 @@ static int uv_select_edgering(
   BM_mesh_elem_hflag_disable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
 
   if (extend) {
-    select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset));
+    select = !(uvedit_edge_select_test(scene, hit->l, cd_loop_uv_offset));
   }
   else {
     select = true;
@@ -1756,10 +1816,20 @@ static int uv_select_edgering(
       }
 
       if (use_face_select) {
+        /* While selecting face loops is now done in a separate function - 
uv_select_faceloop()
+         * ,this check is still kept for edge ring selection to keep it 
consistent with how edge
+         * ring selection works in the 3D viewport */
         uvedit_face_select_set_with_sticky(
             sima, scene, em, l_step->f, select, false, cd_loop_uv_offset);
       }
+      else if (use_vertex_select) {
+        uvedit_uv_select_set_with_sticky(
+            sima, scene, em, l_step, select, false, cd_loop_uv_offset);
+        uvedit_uv_select_set_with_sticky(
+            sima, scene, em, l_step->next, select, false, cd_loop_uv_offset);
+      }
       else {
+        /* Edge select mode */
         uvedit_edge_select_set_with_sticky(
             sima, scene, em, l_step, select, false, cd_loop_uv_offset);
       }
@@ -1778,8 +1848,19 @@ static int uv_select_edgering(
         l_step = NULL;
       }
 
+      /* Break iteration when l_step :
+       * - is the first loop where we started from
+       * - tagged using BM_ELEM_TAG (meaning this loop has been visited in 
this iteration)
+       * - has its corresponding UV edge selected/unselected based on select */
       if (l_step && BM_elem_flag_test(l_step->e, BM_ELEM_TAG)) {
-        break;
+        /* Previously this check was not done and this resulted in the final 
edge in the edge ring
+         * cycle to be skipped during selection (casued by old sticky 
selection behavior) */
+        if (select && uvedit_edge_select_test(scene, l_step, 
cd_loop_uv_offset)) {
+          break;
+        }
+        else if (!select && !uvedit_edge_select_test(scene, l_step, 
cd_loop_uv_offset)) {
+          break;
+        }
       }
     }
   }
@@ -2752,7 +2833,12 @@ static int uv_mouse_select_loop_generic_multi(bContext 
*C,
   }
 
   if (loop_type == UV_LOOP_SELECT) {
-    flush = uv_select_edgeloop(sima, scene, obedit, &hit, extend);
+    if (ED_uvedit_select_mode_get(scene) == UV_SELECT_FACE) {
+      flush = uv_select_faceloop(sima, scene, obedit, &hit, extend);
+    }
+    else {
+      flush = uv_select_edgeloop(sima, scene, obedit, &hit, extend);
+    }
   }
   else if (loop_type == UV_RING_SELECT) {
     flush = uv_select_edgering(sima, scene, obedit, &hit, extend);
@@ -2804,15 +2890,7 @@ static int uv_select_loop_exec(bContext *C, wmOperator 
*op)
   RNA_float_get_array(op->ptr, "location", co);
   const bool extend = RNA_boolean_get(op->ptr, "extend");
 
-  Scene *scene = CTX_data_scene(C);
-  enum eUVLoopGenericType type = UV_LOOP_SELECT;
-  if (ED_uvedit_select_mode_get(scene) == UV_SELECT_FACE) {
-    /* For now ring-select and face-loop is the same thing,
-     * if we support real edge selection this will no longer be the case. */
-    type = UV_RING_SELECT;
-  }
-
-  return uv_mouse_select_loop_generic(C, co, extend, type);
+  return uv_mouse_select_loop_generic(C, co, extend, UV_LOOP_SELECT);
 }
 
 static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent 
*event)

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to