diff options
author | Campbell Barton <campbell@blender.org> | 2022-03-17 16:28:15 +0300 |
---|---|---|
committer | Campbell Barton <campbell@blender.org> | 2022-03-23 08:09:22 +0300 |
commit | d356edf420ba13b3a544dcc598a0e31a36e1d86c (patch) | |
tree | 9f2d8383e500d221bf4dd4aa8ac23a2ccba478a6 /source/blender/editors/uvedit | |
parent | cf1a0ca612f0f96c7513d5c31f3bd4d665057c28 (diff) |
UV: support "Tweak Tool: Left Mouse Select & Move"
- Follow the same conventions as the 3D viewport for UV selection
(using SelectPick_Params internally).
- Use WM_operator_properties_mouse_select for selection properties.
Diffstat (limited to 'source/blender/editors/uvedit')
-rw-r--r-- | source/blender/editors/uvedit/uvedit_select.c | 235 |
1 files changed, 131 insertions, 104 deletions
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 938b798f4b6..ed4aa6985c4 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -2388,12 +2388,11 @@ void UV_OT_select_all(wmOperatorType *ot) /** \name Mouse Select Operator * \{ */ -static int uv_mouse_select_multi(bContext *C, - Object **objects, - uint objects_len, - const float co[2], - const bool extend, - const bool deselect_all) +static bool uv_mouse_select_multi(bContext *C, + Object **objects, + uint objects_len, + const float co[2], + const struct SelectPick_Params *params) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); const ARegion *region = CTX_wm_region(C); @@ -2477,117 +2476,145 @@ static int uv_mouse_select_multi(bContext *C, } } - if (!found_item) { - if (deselect_all) { - uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); + bool found = found_item; + bool changed = false; + + bool is_selected = false; + if (found) { + Object *obedit = hit.ob; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + if (selectmode == UV_SELECT_FACE) { + is_selected = uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset); + } + else if (selectmode == UV_SELECT_EDGE) { + is_selected = uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset); + } + else { /* Vertex or island. */ + is_selected = uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset); + } + } + if (params->sel_op == SEL_OP_SET) { + if ((found && params->select_passthrough) && is_selected) { + found = false; + } + else if (found || params->deselect_all) { + /* Deselect everything. */ + uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *obedit = objects[ob_index]; uv_select_tag_update_for_object(depsgraph, ts, obedit); } - - return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; + changed = true; } - return OPERATOR_CANCELLED; } - Object *obedit = hit.ob; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + if (found) { + Object *obedit = hit.ob; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - /* do selection */ - if (selectmode == UV_SELECT_ISLAND) { - if (!extend) { - uv_select_all_perform_multi_ex(scene, objects, objects_len, SEL_DESELECT, obedit); - } - /* Current behavior of 'extend' - * is actually toggling, so pass extend flag as 'toggle' here */ - uv_select_linked_multi(scene, objects, objects_len, &hit, false, false, extend, false); - } - else if (extend) { - bool select = true; - if (selectmode == UV_SELECT_VERTEX) { - /* (de)select uv vertex */ - select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset); - uvedit_uv_select_set_with_sticky(scene, em, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_EDGE) { - /* (de)select edge */ - select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset)); - uvedit_edge_select_set_with_sticky(scene, em, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_FACE) { - /* (de)select face */ - select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset)); - uvedit_face_select_set_with_sticky(scene, em, hit.efa, select, true, cd_loop_uv_offset); - flush = -1; + if (selectmode == UV_SELECT_ISLAND) { + const bool extend = params->sel_op == SEL_OP_ADD; + const bool deselect = params->sel_op == SEL_OP_SUB; + const bool toggle = params->sel_op == SEL_OP_XOR; + /* Current behavior of 'extend' + * is actually toggling, so pass extend flag as 'toggle' here */ + uv_select_linked_multi(scene, objects, objects_len, &hit, extend, deselect, toggle, false); + /* TODO: check if this actually changed. */ + changed = true; } + else { + BLI_assert(ELEM(selectmode, UV_SELECT_VERTEX, UV_SELECT_EDGE, UV_SELECT_FACE)); + bool select_value = false; + switch (params->sel_op) { + case SEL_OP_ADD: { + select_value = true; + break; + } + case SEL_OP_SUB: { + select_value = false; + break; + } + case SEL_OP_XOR: { + select_value = !is_selected; + break; + } + case SEL_OP_SET: { + /* Deselect has already been performed. */ + select_value = true; + break; + } + case SEL_OP_AND: { + BLI_assert_unreachable(); /* Doesn't make sense for picking. */ + break; + } + } - /* de-selecting an edge may deselect a face too - validate */ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (select == false) { - BM_select_history_validate(em->bm); + if (selectmode == UV_SELECT_FACE) { + uvedit_face_select_set_with_sticky( + scene, em, hit.efa, select_value, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_EDGE) { + uvedit_edge_select_set_with_sticky( + scene, em, hit.l, select_value, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_VERTEX) { + uvedit_uv_select_set_with_sticky(scene, em, hit.l, select_value, true, cd_loop_uv_offset); + flush = 1; + } + else { + BLI_assert_unreachable(); } - } - /* (de)select sticky uv nodes */ - if (sticky != SI_STICKY_DISABLE) { - flush = select ? 1 : -1; - } - } - else { - const bool select = true; - /* deselect all */ - uv_select_all_perform_multi(scene, objects, objects_len, SEL_DESELECT); + /* De-selecting an edge may deselect a face too - validate. */ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (select_value == false) { + BM_select_history_validate(em->bm); + } + } - if (selectmode == UV_SELECT_VERTEX) { - /* select vertex */ - uvedit_uv_select_set_with_sticky(scene, em, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_EDGE) { - /* select edge */ - uvedit_edge_select_set_with_sticky(scene, em, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_FACE) { - /* select face */ - uvedit_face_select_set_with_sticky(scene, em, hit.efa, select, true, cd_loop_uv_offset); - flush = 1; + /* (de)select sticky UV nodes. */ + if (sticky != SI_STICKY_DISABLE) { + flush = select_value ? 1 : -1; + } + + changed = true; } - } - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (flush != 0) { - EDBM_selectmode_flush(em); + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (flush != 0) { + EDBM_selectmode_flush(em); + } + } + else { + /* Setting the selection implies a single element, which doesn't need to be flushed. */ + if (params->sel_op != SEL_OP_SET) { + ED_uvedit_selectmode_flush(scene, em); + } } - } - /* #extend=false implies single vertex selection, which doesn't need to be flushed. */ - else if (extend) { - ED_uvedit_selectmode_flush(scene, em); } - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obiter = objects[ob_index]; - uv_select_tag_update_for_object(depsgraph, ts, obiter); + if (changed && found) { + /* Only update the `hit` object as de-selecting all will have refreshed the others. */ + Object *obedit = hit.ob; + uv_select_tag_update_for_object(depsgraph, ts, obedit); } - return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; + return changed || found; } -static int uv_mouse_select(bContext *C, - const float co[2], - const bool extend, - const bool deselect_all) +static bool uv_mouse_select(bContext *C, const float co[2], const struct SelectPick_Params *params) { 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_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all); + bool changed = uv_mouse_select_multi(C, objects, objects_len, co, params); MEM_freeN(objects); - return ret; + return changed; } static int uv_select_exec(bContext *C, wmOperator *op) @@ -2595,10 +2622,20 @@ static int uv_select_exec(bContext *C, wmOperator *op) float co[2]; RNA_float_get_array(op->ptr, "location", co); - const bool extend = RNA_boolean_get(op->ptr, "extend"); - const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); + const struct SelectPick_Params params = { + .sel_op = ED_select_op_from_booleans(RNA_boolean_get(op->ptr, "extend"), + RNA_boolean_get(op->ptr, "deselect"), + RNA_boolean_get(op->ptr, "toggle")), + .deselect_all = RNA_boolean_get(op->ptr, "deselect_all"), + .select_passthrough = RNA_boolean_get(op->ptr, "select_passthrough"), + }; - return uv_mouse_select(C, co, extend, deselect_all); + const bool changed = uv_mouse_select(C, co, ¶ms); + + if (changed) { + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + } + return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH; } static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) @@ -2629,18 +2666,8 @@ void UV_OT_select(wmOperatorType *ot) /* properties */ PropertyRNA *prop; - prop = RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - prop = RNA_def_boolean(ot->srna, - "deselect_all", - false, - "Deselect On Nothing", - "Deselect all when nothing under the cursor"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + WM_operator_properties_mouse_select(ot); prop = RNA_def_float_vector( ot->srna, |