[Bf-blender-cvs] [6a10e69d270] master: UV: match 3D mesh editing behavior for edge-loop select

Campbell Barton noreply at git.blender.org
Wed Aug 26 10:42:48 CEST 2020


Commit: 6a10e69d270bc6866dd0000ffc0b81f6205ba2e9
Author: Campbell Barton
Date:   Wed Aug 26 13:13:06 2020 +1000
Branches: master
https://developer.blender.org/rB6a10e69d270bc6866dd0000ffc0b81f6205ba2e9

UV: match 3D mesh editing behavior for edge-loop select

- Cycling between part of the boundary & the entire UV boundary.
- Include pole vertices in the selection.

Edge loop selection was rewritten to use BMesh connectivity data.

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

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 cb3b32bcfee..2ea78ca5377 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -71,10 +71,14 @@
 #include "uvedit_intern.h"
 
 static void uv_select_all_perform(Scene *scene, Object *obedit, int action);
+
+static void uv_select_all_perform_multi_ex(
+    Scene *scene, Object **objects, const uint objects_len, int action, const Object *ob_exclude);
 static void uv_select_all_perform_multi(Scene *scene,
                                         Object **objects,
                                         const uint objects_len,
                                         int action);
+
 static void uv_select_flush_from_tag_face(SpaceImage *sima,
                                           Scene *scene,
                                           Object *obedit,
@@ -612,7 +616,7 @@ void uvedit_uv_select_disable(const Scene *scene,
   }
 }
 
-static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(Scene *scene,
+static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(const Scene *scene,
                                                                     BMLoop *l_src,
                                                                     const int cd_loop_uv_offset)
 {
@@ -637,6 +641,37 @@ static BMLoop *uvedit_loop_find_other_radial_loop_with_visible_face(Scene *scene
   return l_other;
 }
 
+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)
+{
+  BLI_assert(uvedit_loop_find_other_radial_loop_with_visible_face(
+                 scene, l_edge, cd_loop_uv_offset) == NULL);
+
+  BMLoop *l_step = l_edge;
+  l_step = (l_step->v == v_pivot) ? l_step->prev : l_step->next;
+  BMLoop *l_step_last = NULL;
+  do {
+    BLI_assert(BM_vert_in_edge(l_step->e, v_pivot));
+    l_step_last = l_step;
+    l_step = uvedit_loop_find_other_radial_loop_with_visible_face(
+        scene, l_step, cd_loop_uv_offset);
+    if (l_step) {
+      l_step = (l_step->v == v_pivot) ? l_step->prev : l_step->next;
+    }
+  } while (l_step != NULL);
+
+  BM_elem_flag_set(l_step_last->e, BM_ELEM_SMOOTH, false);
+
+  if (l_step_last != NULL) {
+    BLI_assert(uvedit_loop_find_other_radial_loop_with_visible_face(
+                   scene, l_step_last, cd_loop_uv_offset) == NULL);
+  }
+
+  return l_step_last;
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -971,200 +1006,235 @@ BMLoop *uv_find_nearest_loop_from_edge(struct Scene *scene,
 /** \name Edge Loop Select
  * \{ */
 
-static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first)
-{
-  UvMapVert *iterv;
-  int count = 0;
+/** Mode for selecting edge loops at boundaries. */
+enum eUVEdgeLoopBoundaryMode {
+  /** Delimit at face corners (don't walk over multiple edges in the same face). */
+  UV_EDGE_LOOP_BOUNDARY_LOOP = 1,
+  /** Don't delimit, walk over the all connected boundary loops. */
+  UV_EDGE_LOOP_BOUNDARY_ALL = 2,
+};
 
-  for (iterv = first; iterv; iterv = iterv->next) {
-    if (iterv->separate && iterv != first) {
-      break;
+static BMLoop *bm_select_edgeloop_double_side_next(const Scene *scene,
+                                                   BMLoop *l_step,
+                                                   BMVert *v_from,
+                                                   const int cd_loop_uv_offset)
+{
+  if (l_step->f->len == 4) {
+    BMVert *v_from_next = BM_edge_other_vert(l_step->e, v_from);
+    BMLoop *l_step_over = (v_from == l_step->v) ? l_step->next : l_step->prev;
+    l_step_over = uvedit_loop_find_other_radial_loop_with_visible_face(
+        scene, l_step_over, cd_loop_uv_offset);
+    if (l_step_over) {
+      return (l_step_over->v == v_from_next) ? l_step_over->prev : l_step_over->next;
     }
-
-    count++;
-  }
-
-  if (count < 5) {
-    first->flag = 1;
   }
+  return NULL;
 }
 
-static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l)
+static BMLoop *bm_select_edgeloop_single_side_next(const Scene *scene,
+                                                   BMLoop *l_step,
+                                                   BMVert *v_from,
+                                                   const int cd_loop_uv_offset)
 {
-  UvMapVert *iterv, *first;
-  first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
+  BMVert *v_from_next = BM_edge_other_vert(l_step->e, v_from);
+  return uvedit_loop_find_other_boundary_loop_with_visible_face(
+      scene, l_step, v_from_next, cd_loop_uv_offset);
+}
 
-  for (iterv = first; iterv; iterv = iterv->next) {
-    if (iterv->separate) {
-      first = iterv;
-    }
-    if (iterv->poly_index == BM_elem_index_get(efa)) {
-      return first;
+/* TODO(campbell): support this in the BMesh API, as we have for clearing other types. */
+static void bm_loop_tags_clear(BMesh *bm)
+{
+  BMIter iter;
+  BMFace *f;
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    BMIter liter;
+    BMLoop *l_iter;
+    BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) {
+      BM_elem_flag_disable(l_iter, BM_ELEM_TAG);
     }
   }
-
-  return NULL;
 }
 
-static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em,
-                                              UvMapVert *first1,
-                                              UvMapVert *first2,
-                                              int *totface)
+/**
+ * Tag all loops which should be selected, the caller must select.
+ */
+static void uv_select_edgeloop_double_side_tag(const Scene *scene,
+                                               BMEditMesh *em,
+                                               BMLoop *l_init_pair[2],
+                                               const int cd_loop_uv_offset)
 {
-  UvMapVert *iterv1, *iterv2;
-  BMFace *efa;
-  int tot = 0;
-
-  /* count number of faces this edge has */
-  for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
-    if (iterv1->separate && iterv1 != first1) {
-      break;
-    }
+  bm_loop_tags_clear(em->bm);
 
-    for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
-      if (iterv2->separate && iterv2 != first2) {
+  for (int side = 0; side < 2; side++) {
+    BMLoop *l_step_pair[2] = {l_init_pair[0], l_init_pair[1]};
+    BMVert *v_from = side ? l_step_pair[0]->e->v1 : l_step_pair[0]->e->v2;
+    /* Disable since we start from the same edge. */
+    BM_elem_flag_disable(l_step_pair[0], BM_ELEM_TAG);
+    BM_elem_flag_disable(l_step_pair[1], BM_ELEM_TAG);
+    while ((l_step_pair[0] != NULL) && (l_step_pair[1] != NULL)) {
+      if (!uvedit_face_visible_test(scene, l_step_pair[0]->f) ||
+          !uvedit_face_visible_test(scene, l_step_pair[1]->f) ||
+          /* Check loops have not diverged. */
+          (uvedit_loop_find_other_radial_loop_with_visible_face(
+               scene, l_step_pair[0], cd_loop_uv_offset) != l_step_pair[1])) {
         break;
       }
 
-      if (iterv1->poly_index == iterv2->poly_index) {
-        /* if face already tagged, don't do this edge */
-        efa = BM_face_at_index(em->bm, iterv1->poly_index);
-        if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
-          return false;
-        }
+      BLI_assert(l_step_pair[0]->e == l_step_pair[1]->e);
+
+      BM_elem_flag_enable(l_step_pair[0], BM_ELEM_TAG);
+      BM_elem_flag_enable(l_step_pair[1], BM_ELEM_TAG);
+
+      BMVert *v_from_next = BM_edge_other_vert(l_step_pair[0]->e, v_from);
+      /* Walk over both sides, ensure they keep on the same edge. */
+      for (int i = 0; i < ARRAY_SIZE(l_step_pair); i++) {
+        l_step_pair[i] = bm_select_edgeloop_double_side_next(
+            scene, l_step_pair[i], v_from, cd_loop_uv_offset);
+      }
 
-        tot++;
+      if ((l_step_pair[0] && BM_elem_flag_test(l_step_pair[0], BM_ELEM_TAG)) ||
+          (l_step_pair[1] && BM_elem_flag_test(l_step_pair[1], BM_ELEM_TAG))) {
         break;
       }
+      v_from = v_from_next;
     }
   }
+}
 
-  if (*totface == 0) { /* start edge */
-    *totface = tot;
-  }
-  else if (tot != *totface) { /* check for same number of faces as start edge */
-    return false;
+/**
+ * Tag all loops which should be selected, the caller must select.
+ *
+ * \param r_count_by_select: Count the number of unselected and selected loops,
+ * this is needed to implement cycling between #eUVEdgeLoopBoundaryMode.
+ */
+static void uv_select_edgeloop_single_side_tag(const Scene *scene,
+                                               BMEditMesh *em,
+                                               BMLoop *l_init,
+                                               const int cd_loop_uv_offset,
+                                               enum eUVEdgeLoopBoundaryMode boundary_mode,
+                                               int r_count_by_select[2])
+{
+  if (r_count_by_select) {
+    r_count_by_select[0] = r_count_by_select[1] = 0;
   }
 
-  /* tag the faces */
-  for (iterv1 = first1; iterv1; iterv1 = iterv1->next) {
-    if (iterv1->separate && iterv1 != first1) {
-      break;
-    }
+  bm_loop_tags_clear(em->bm);
 
-    for (iterv2 = first2; iterv2; iterv2 = iterv2->next) {
-      if (iterv2->separate && iterv2 != first2) {
+  for (int side = 0; side < 2; side++) {
+    BMLoop *l_step = l_init;
+    BMVert *v_from = side ? l_step->e->v1 : l_step->e->v2;
+    /* Disable since we start from the same edge. */
+    BM_elem_flag_disable(l_step, BM_ELEM_TAG);
+    while (l_step != NULL) {
+
+      if (!uvedit_face_visible_test(scene, l_step->f) ||
+          /* Check the boundary is still a  boundary. */
+          (uvedit_loop_find_other_radial_loop_with_visible_face(
+               scene, l_step, cd_loop_uv_offset) != NULL)) {
         break;
       }
 
-      if (iterv1->poly_index == iterv2->poly_index) {
-        efa = BM_face_at_index(em->bm, iterv1->poly_index);
-        BM_elem_flag_enable

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list