[Bf-blender-cvs] [415d3ee05bf] master: UV: add path select operator that uses the selection

Campbell Barton noreply at git.blender.org
Sat Jul 11 14:12:11 CEST 2020


Commit: 415d3ee05bfa51d7a71fa8417682e38186915776
Author: Campbell Barton
Date:   Sat Jul 11 22:03:27 2020 +1000
Branches: master
https://developer.blender.org/rB415d3ee05bfa51d7a71fa8417682e38186915776

UV: add path select operator that uses the selection

Instead of using the mouse cursor position,
this selects between existing selected elements.

Access this since picking a selection path doesn't
work from the menu.

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

M	release/scripts/startup/bl_ui/space_image.py
M	source/blender/editors/include/ED_uvedit.h
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

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

diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index e272a1dbd68..651866cf316 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -191,7 +191,7 @@ class IMAGE_MT_select_linked(Menu):
         layout = self.layout
 
         layout.operator("uv.select_linked", text="Linked")
-        layout.operator("uv.shortest_path_pick", text="Shortest Path")
+        layout.operator("uv.shortest_path_select", text="Shortest Path")
 
 
 class IMAGE_MT_image(Menu):
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index cce788efa58..ec41e785714 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -175,6 +175,19 @@ bool ED_uvedit_nearest_uv_multi(const struct Scene *scene,
                                 float *dist_sq,
                                 float r_uv[2]);
 
+struct BMFace **ED_uvedit_selected_faces(struct Scene *scene,
+                                         struct BMesh *bm,
+                                         int len_max,
+                                         int *r_faces_len);
+struct BMLoop **ED_uvedit_selected_edges(struct Scene *scene,
+                                         struct BMesh *bm,
+                                         int len_max,
+                                         int *r_edges_len);
+struct BMLoop **ED_uvedit_selected_verts(struct Scene *scene,
+                                         struct BMesh *bm,
+                                         int len_max,
+                                         int *r_verts_len);
+
 void ED_uvedit_get_aspect(struct Object *obedit, float *r_aspx, float *r_aspy);
 
 void ED_uvedit_active_vert_loop_set(struct BMesh *bm, struct BMLoop *l);
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 8b99292029e..6a5f5162dff 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -111,6 +111,7 @@ void UV_OT_stitch(struct wmOperatorType *ot);
 
 /* uvedit_path.c */
 void UV_OT_shortest_path_pick(struct wmOperatorType *ot);
+void UV_OT_shortest_path_select(struct wmOperatorType *ot);
 
 /* uvedit_select.c */
 
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 18278cf2541..6003d4d5d95 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -2090,6 +2090,7 @@ void ED_operatortypes_uvedit(void)
   WM_operatortype_append(UV_OT_rip);
   WM_operatortype_append(UV_OT_stitch);
   WM_operatortype_append(UV_OT_shortest_path_pick);
+  WM_operatortype_append(UV_OT_shortest_path_select);
 
   WM_operatortype_append(UV_OT_seams_from_islands);
   WM_operatortype_append(UV_OT_mark_seam);
diff --git a/source/blender/editors/uvedit/uvedit_path.c b/source/blender/editors/uvedit/uvedit_path.c
index 4f0c472158a..e9615b62523 100644
--- a/source/blender/editors/uvedit/uvedit_path.c
+++ b/source/blender/editors/uvedit/uvedit_path.c
@@ -677,3 +677,95 @@ void UV_OT_shortest_path_pick(wmOperatorType *ot)
 }
 
 /** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Select Path Between Existing Selection
+ * \{ */
+
+static int uv_shortest_path_select_exec(bContext *C, wmOperator *op)
+{
+  Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+  Scene *scene = CTX_data_scene(C);
+  const ToolSettings *ts = scene->toolsettings;
+  bool found_valid_elements = false;
+
+  float aspect_y;
+  {
+    Object *obedit = CTX_data_edit_object(C);
+    float aspx, aspy;
+    ED_uvedit_get_aspect(obedit, &aspx, &aspy);
+    aspect_y = aspx / aspy;
+  }
+
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  uint objects_len = 0;
+  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
+      view_layer, CTX_wm_view3d(C), &objects_len);
+  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+    Object *obedit = objects[ob_index];
+    BMEditMesh *em = BKE_editmesh_from_object(obedit);
+    BMesh *bm = em->bm;
+    const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+    BMElem *ele_src = NULL, *ele_dst = NULL;
+
+    /* Find 2x elements. */
+    {
+      BMElem **ele_array = NULL;
+      int ele_array_len = 0;
+      if (ts->uv_selectmode & UV_SELECT_FACE) {
+        ele_array = (BMElem **)ED_uvedit_selected_faces(scene, bm, 3, &ele_array_len);
+      }
+      else if (ts->uv_selectmode & UV_SELECT_EDGE) {
+        ele_array = (BMElem **)ED_uvedit_selected_edges(scene, bm, 3, &ele_array_len);
+      }
+      else {
+        ele_array = (BMElem **)ED_uvedit_selected_verts(scene, bm, 3, &ele_array_len);
+      }
+
+      if (ele_array_len == 2) {
+        ele_src = ele_array[0];
+        ele_dst = ele_array[1];
+      }
+      MEM_freeN(ele_array);
+    }
+
+    if (ele_src && ele_dst) {
+      struct PathSelectParams op_params;
+      path_select_params_from_op(op, &op_params);
+
+      uv_shortest_path_pick_ex(
+          scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
+
+      found_valid_elements = true;
+    }
+  }
+  MEM_freeN(objects);
+
+  if (!found_valid_elements) {
+    BKE_report(
+        op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected");
+    return OPERATOR_CANCELLED;
+  }
+
+  return OPERATOR_FINISHED;
+}
+
+void UV_OT_shortest_path_select(wmOperatorType *ot)
+{
+  /* identifiers */
+  ot->name = "Select Shortest Path";
+  ot->idname = "UV_OT_shortest_path_select";
+  ot->description = "Selected shortest path between two vertices/edges/faces";
+
+  /* api callbacks */
+  ot->exec = uv_shortest_path_select_exec;
+  ot->poll = ED_operator_editmesh;
+
+  /* flags */
+  ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+  /* properties */
+  path_select_properties(ot);
+}
+
+/** \} */
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index a589114fd46..bae097a09bf 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -3419,3 +3419,154 @@ void UV_OT_select_overlap(wmOperatorType *ot)
 }
 
 /** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Selected Elements as Arrays (Vertex, Edge & Faces)
+ *
+ * These functions return single elements per connected vertex/edge.
+ * So an edge that has two connected edge loops only assigns one loop in the array.
+ * \{ */
+
+BMFace **ED_uvedit_selected_faces(Scene *scene, BMesh *bm, int len_max, int *r_faces_len)
+{
+  const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+  CLAMP_MAX(len_max, bm->totface);
+  int faces_len = 0;
+  BMFace **faces = MEM_mallocN(sizeof(*faces) * len_max, __func__);
+
+  BMIter iter;
+  BMFace *f;
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    if (uvedit_face_visible_test(scene, f)) {
+      if (uvedit_face_select_test(scene, f, cd_loop_uv_offset)) {
+        faces[faces_len++] = f;
+        if (faces_len == len_max) {
+          goto finally;
+        }
+      }
+    }
+  }
+
+finally:
+  *r_faces_len = faces_len;
+  if (faces_len != len_max) {
+    faces = MEM_reallocN(faces, sizeof(*faces) * faces_len);
+  }
+  return faces;
+}
+
+BMLoop **ED_uvedit_selected_edges(Scene *scene, BMesh *bm, int len_max, int *r_edges_len)
+{
+  const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+  CLAMP_MAX(len_max, bm->totloop);
+  int edges_len = 0;
+  BMLoop **edges = MEM_mallocN(sizeof(*edges) * len_max, __func__);
+
+  BMIter iter;
+  BMFace *f;
+
+  /* Clear tag. */
+  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);
+    }
+  }
+
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    if (uvedit_face_visible_test(scene, f)) {
+      BMIter liter;
+      BMLoop *l_iter;
+      BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) {
+        if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) {
+          const MLoopUV *luv_curr = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+          const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset);
+          if ((luv_curr->flag & MLOOPUV_VERTSEL) && (luv_next->flag & MLOOPUV_VERTSEL)) {
+            BM_elem_flag_enable(l_iter, BM_ELEM_TAG);
+
+            edges[edges_len++] = l_iter;
+            if (edges_len == len_max) {
+              goto finally;
+            }
+
+            /* Tag other connected loops so we don't consider them separate edges. */
+            if (l_iter != l_iter->radial_next) {
+              BMLoop *l_radial_iter = l_iter->radial_next;
+              do {
+                if (BM_loop_uv_share_edge_check(l_iter, l_radial_iter, cd_loop_uv_offset)) {
+                  BM_elem_flag_enable(l_radial_iter, BM_ELEM_TAG);
+                }
+              } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter);
+            }
+          }
+        }
+      }
+    }
+  }
+
+finally:
+  *r_edges_len = edges_len;
+  if (edges_len != len_max) {
+    edges = MEM_reallocN(edges, sizeof(*edges) * edges_len);
+  }
+  return edges;
+}
+
+BMLoop **ED_uvedit_selected_verts(Scene *scene, BMesh *bm, int len_max, int *r_verts_len)
+{
+  const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+  CLAMP_MAX(len_max, bm->totloop);
+  int verts_len = 0;
+  BMLoop **verts = MEM_mallocN(sizeof(*verts) * len_max, __func__);
+
+  BMIter iter;
+  BMFace *f;
+
+  /* Clear tag. */
+  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);
+    }
+  }
+
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    if (uvedit_face_visible_test(scene, f)) {
+      BMIter liter;
+      BMLoop *l_iter;
+      BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) {


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list