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]: ea5fe7abc1
This commit is contained in:
parent
ebb519652c
commit
a0706d6cf0
Notes:
blender-bot
2023-02-13 13:58:33 +01:00
Referenced by issue #102680, Pick shortest Path in UV Editor work incorrectly, if edit several objects
|
@ -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,136 +560,159 @@ 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (ele_src == NULL || ele_dst == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
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);
|
||||
if (uv_find_nearest_edge_multi(scene, objects, objects_len, co, 0.0f, &hit)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BM_mesh_elem_index_ensure(bm, BM_LOOP);
|
||||
index = BM_elem_index_get(ele_dst);
|
||||
if (uv_find_nearest_vert_multi(scene, objects, objects_len, co, 0.0f, &hit)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
RNA_int_set(op->ptr, "index", index);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
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 {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
float aspect_y;
|
||||
{
|
||||
float aspx, aspy;
|
||||
ED_uvedit_get_aspect(obedit, &aspx, &aspy);
|
||||
aspect_y = aspx / aspy;
|
||||
}
|
||||
|
||||
const int index = RNA_int_get(op->ptr, "index");
|
||||
|
||||
BMElem *ele_src, *ele_dst;
|
||||
|
||||
if (uv_selectmode & UV_SELECT_FACE) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue