[Bf-blender-cvs] [a0706d6cf00] master: Fix T102680: UV Pick shortest Path wrong for multi-object editing

Campbell Barton noreply at git.blender.org
Fri Jan 20 04:04:57 CET 2023


Commit: a0706d6cf0000813568c05ebae1dfabf9c721002
Author: Campbell Barton
Date:   Fri Jan 20 12:51:50 2023 +1100
Branches: master
https://developer.blender.org/rBa0706d6cf0000813568c05ebae1dfabf9c721002

Fix T102680: UV Pick shortest Path wrong for multi-object editing

Path selection support from [0] didn't account for multiple objects in
edit-mode. Now picking the UV also picks the object to operate on.

[0]: ea5fe7abc183c1e53d327f97280f589499fe60bb

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

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

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

diff --git a/source/blender/editors/uvedit/uvedit_path.c b/source/blender/editors/uvedit/uvedit_path.c
index 82d8c536fba..1e50ddba3a3 100644
--- a/source/blender/editors/uvedit/uvedit_path.c
+++ b/source/blender/editors/uvedit/uvedit_path.c
@@ -38,6 +38,7 @@
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_query.h"
 
+#include "ED_object.h"
 #include "ED_screen.h"
 #include "ED_transform.h"
 #include "ED_uvedit.h"
@@ -559,135 +560,158 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
   op_params.track_active = true;
 
   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+  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(
+      scene, view_layer, CTX_wm_view3d(C), &objects_len);
 
   float co[2];
 
   const ARegion *region = CTX_wm_region(C);
 
-  Object *obedit = CTX_data_edit_object(C);
-  BMEditMesh *em = BKE_editmesh_from_object(obedit);
-  BMesh *bm = em->bm;
-  const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
-
-  float aspect_y;
-  {
-    float aspx, aspy;
-    ED_uvedit_get_aspect(obedit, &aspx, &aspy);
-    aspect_y = aspx / aspy;
-  }
-
   UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
 
   BMElem *ele_src = NULL, *ele_dst = NULL;
 
+  /* Detect the hit. */
+  UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
+  bool hit_found = false;
   if (uv_selectmode == UV_SELECT_FACE) {
-    UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
-    if (!uv_find_nearest_face(scene, obedit, co, &hit)) {
-      return OPERATOR_CANCELLED;
+    if (uv_find_nearest_face_multi(scene, objects, objects_len, co, &hit)) {
+      hit_found = true;
     }
-
-    BMFace *f_src = BM_mesh_active_face_get(bm, false, false);
-    /* Check selection? */
-
-    ele_src = (BMElem *)f_src;
-    ele_dst = (BMElem *)hit.efa;
   }
-
   else if (uv_selectmode & UV_SELECT_EDGE) {
-    UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
-    if (!uv_find_nearest_edge(scene, obedit, co, 0.0f, &hit)) {
-      return OPERATOR_CANCELLED;
-    }
-
-    BMLoop *l_src = NULL;
-    if (ts->uv_flag & UV_SYNC_SELECTION) {
-      BMEdge *e_src = BM_mesh_active_edge_get(bm);
-      if (e_src != NULL) {
-        l_src = uv_find_nearest_loop_from_edge(scene, obedit, e_src, co);
-      }
+    if (uv_find_nearest_edge_multi(scene, objects, objects_len, co, 0.0f, &hit)) {
+      hit_found = true;
     }
-    else {
-      l_src = ED_uvedit_active_edge_loop_get(bm);
-      if (l_src != NULL) {
-        if (!uvedit_uv_select_test(scene, l_src, offsets) &&
-            !uvedit_uv_select_test(scene, l_src->next, offsets)) {
-          l_src = NULL;
-        }
-        ele_src = (BMElem *)l_src;
-      }
-    }
-    ele_src = (BMElem *)l_src;
-    ele_dst = (BMElem *)hit.l;
   }
   else {
-    UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(&region->v2d);
-    if (!uv_find_nearest_vert(scene, obedit, co, 0.0f, &hit)) {
-      return OPERATOR_CANCELLED;
+    if (uv_find_nearest_vert_multi(scene, objects, objects_len, co, 0.0f, &hit)) {
+      hit_found = true;
     }
+  }
 
-    BMLoop *l_src = NULL;
-    if (ts->uv_flag & UV_SYNC_SELECTION) {
-      BMVert *v_src = BM_mesh_active_vert_get(bm);
-      if (v_src != NULL) {
-        l_src = uv_find_nearest_loop_from_vert(scene, obedit, v_src, co);
+  bool changed = false;
+  if (hit_found) {
+    /* This may not be the active object. */
+    Object *obedit = hit.ob;
+    BMEditMesh *em = BKE_editmesh_from_object(obedit);
+    BMesh *bm = em->bm;
+    const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
+
+    /* Respond to the hit. */
+    if (uv_selectmode == UV_SELECT_FACE) {
+      /* Face selection. */
+      BMFace *f_src = BM_mesh_active_face_get(bm, false, false);
+      /* Check selection? */
+      ele_src = (BMElem *)f_src;
+      ele_dst = (BMElem *)hit.efa;
+    }
+    else if (uv_selectmode & UV_SELECT_EDGE) {
+      /* Edge selection. */
+      BMLoop *l_src = NULL;
+      if (ts->uv_flag & UV_SYNC_SELECTION) {
+        BMEdge *e_src = BM_mesh_active_edge_get(bm);
+        if (e_src != NULL) {
+          l_src = uv_find_nearest_loop_from_edge(scene, obedit, e_src, co);
+        }
+      }
+      else {
+        l_src = ED_uvedit_active_edge_loop_get(bm);
+        if (l_src != NULL) {
+          if (!uvedit_uv_select_test(scene, l_src, offsets) &&
+              !uvedit_uv_select_test(scene, l_src->next, offsets)) {
+            l_src = NULL;
+          }
+          ele_src = (BMElem *)l_src;
+        }
       }
+      ele_src = (BMElem *)l_src;
+      ele_dst = (BMElem *)hit.l;
     }
     else {
-      l_src = ED_uvedit_active_vert_loop_get(bm);
-      if (l_src != NULL) {
-        if (!uvedit_uv_select_test(scene, l_src, offsets)) {
-          l_src = NULL;
+      /* Vertex selection. */
+      BMLoop *l_src = NULL;
+      if (ts->uv_flag & UV_SYNC_SELECTION) {
+        BMVert *v_src = BM_mesh_active_vert_get(bm);
+        if (v_src != NULL) {
+          l_src = uv_find_nearest_loop_from_vert(scene, obedit, v_src, co);
         }
       }
+      else {
+        l_src = ED_uvedit_active_vert_loop_get(bm);
+        if (l_src != NULL) {
+          if (!uvedit_uv_select_test(scene, l_src, offsets)) {
+            l_src = NULL;
+          }
+        }
+      }
+      ele_src = (BMElem *)l_src;
+      ele_dst = (BMElem *)hit.l;
     }
-    ele_src = (BMElem *)l_src;
-    ele_dst = (BMElem *)hit.l;
-  }
 
-  if (ele_src == NULL || ele_dst == NULL) {
-    return OPERATOR_CANCELLED;
-  }
+    if (ele_src && ele_dst) {
+      /* Always use the active object, not `obedit` as the active defines the UV display. */
+      float aspect_y;
+      {
+        float aspx, aspy;
+        ED_uvedit_get_aspect(CTX_data_edit_object(C), &aspx, &aspy);
+        aspect_y = aspx / aspy;
+      }
 
-  uv_shortest_path_pick_ex(
-      scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, offsets);
+      uv_shortest_path_pick_ex(
+          scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, offsets);
 
-  /* To support redo. */
-  int index;
-  if (uv_selectmode & UV_SELECT_FACE) {
-    BM_mesh_elem_index_ensure(bm, BM_FACE);
-    index = BM_elem_index_get(ele_dst);
-  }
-  else if (uv_selectmode & UV_SELECT_EDGE) {
-    BM_mesh_elem_index_ensure(bm, BM_LOOP);
-    index = BM_elem_index_get(ele_dst);
-  }
-  else {
-    BM_mesh_elem_index_ensure(bm, BM_LOOP);
-    index = BM_elem_index_get(ele_dst);
+      /* Store the object and it's index so redo is possible. */
+      int index;
+      if (uv_selectmode & UV_SELECT_FACE) {
+        BM_mesh_elem_index_ensure(bm, BM_FACE);
+        index = BM_elem_index_get(ele_dst);
+      }
+      else if (uv_selectmode & UV_SELECT_EDGE) {
+        BM_mesh_elem_index_ensure(bm, BM_LOOP);
+        index = BM_elem_index_get(ele_dst);
+      }
+      else {
+        BM_mesh_elem_index_ensure(bm, BM_LOOP);
+        index = BM_elem_index_get(ele_dst);
+      }
+
+      const int object_index = ED_object_in_mode_to_index(scene, view_layer, OB_MODE_EDIT, obedit);
+      BLI_assert(object_index != -1);
+      RNA_int_set(op->ptr, "object_index", object_index);
+      RNA_int_set(op->ptr, "index", index);
+      changed = true;
+    }
   }
-  RNA_int_set(op->ptr, "index", index);
 
-  return OPERATOR_FINISHED;
+  MEM_freeN(objects);
+
+  return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
 }
 
 static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op)
 {
   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
   Scene *scene = CTX_data_scene(C);
+  ViewLayer *view_layer = CTX_data_view_layer(C);
   const char uv_selectmode = ED_uvedit_select_mode_get(scene);
-  Object *obedit = CTX_data_edit_object(C);
-  BMEditMesh *em = BKE_editmesh_from_object(obedit);
-  BMesh *bm = em->bm;
-  const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
 
-  float aspect_y;
-  {
-    float aspx, aspy;
-    ED_uvedit_get_aspect(obedit, &aspx, &aspy);
-    aspect_y = aspx / aspy;
+  const int object_index = RNA_int_get(op->ptr, "object_index");
+  const int index = RNA_int_get(op->ptr, "index");
+  if (object_index == -1) {
+    return OPERATOR_CANCELLED;
   }
 
-  const int index = RNA_int_get(op->ptr, "index");
+  Object *obedit = ED_object_in_mode_from_index(scene, view_layer, OB_MODE_EDIT, object_index);
+  if (obedit == NULL) {
+    return OPERATOR_CANCELLED;
+  }
+
+  BMEditMesh *em = BKE_editmesh_from_object(obedit);
+  BMesh *bm = em->bm;
+  const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
 
   BMElem *ele_src, *ele_dst;
 
@@ -719,6 +743,14 @@ static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op)
     }
   }
 
+  /* Always use the active object, not `obedit` as the active defines the UV display. */
+  float aspect_y;
+  {
+    float aspx, aspy;
+    ED_uvedit_get_aspect(CTX_data_edit_object(C), &aspx, &aspy);
+    aspect_y = aspx / aspy;
+  }
+
   struct PathSelectParams op_params;
   path_select_params_from_op(op, &op_params);
   op_params.track_active = true;
@@ -752,6 +784,8 @@ void UV_OT_shortest_path_pick(wmOperatorType *ot)
   path_select_properties(ot);
 
   /* use for redo */
+  prop = RNA_def_int(ot->srna, "object_index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
+  RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
   prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX);
   RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
 }



More information about the Bf-blender-cvs mailing list