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(®ion->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(®ion->v2d); + bool hit_found = false; if (uv_selectmode == UV_SELECT_FACE) { - UvNearestHit hit = UV_NEAREST_HIT_INIT_MAX(®ion->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(®ion->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(®ion->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); } _______________________________________________ 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