diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/space_node/node_select.cc | 170 |
1 files changed, 93 insertions, 77 deletions
diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 1d0097068f1..147cbc5a05c 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -193,11 +193,6 @@ static bool is_event_over_node_or_socket(bContext *C, const wmEvent *event) return is_position_over_node_or_socket(*snode, mouse); } -static void node_toggle(bNode *node) -{ - nodeSetSelected(node, !(node->flag & SELECT)); -} - void node_socket_select(bNode *node, bNodeSocket &sock) { sock.flag |= SELECT; @@ -510,10 +505,10 @@ void node_select_single(bContext &C, bNode &node) WM_event_add_notifier(&C, NC_NODE | NA_SELECTED, nullptr); } -static int node_mouse_select(bContext *C, - wmOperator *op, - const int mval[2], - bool wait_to_deselect_others) +static bool node_mouse_select(bContext *C, + wmOperator *op, + const int mval[2], + struct SelectPick_Params *params) { Main &bmain = *CTX_data_main(C); SpaceNode &snode = *CTX_wm_space_node(C); @@ -525,36 +520,38 @@ static int node_mouse_select(bContext *C, bNodeSocket *sock = nullptr; bNodeSocket *tsock; float cursor[2]; - int ret_value = OPERATOR_CANCELLED; - const bool extend = RNA_boolean_get(op->ptr, "extend"); /* always do socket_select when extending selection. */ - const bool socket_select = extend || RNA_boolean_get(op->ptr, "socket_select"); - const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); - - /* These cases are never modal. */ - if (extend || socket_select) { - wait_to_deselect_others = false; - } + const bool socket_select = (params->sel_op == SEL_OP_XOR) || + RNA_boolean_get(op->ptr, "socket_select"); + bool changed = false; + bool found = false; + bool node_was_selected = false; /* get mouse coordinates in view2d space */ UI_view2d_region_to_view(®ion.v2d, mval[0], mval[1], &cursor[0], &cursor[1]); /* first do socket selection, these generally overlap with nodes. */ if (socket_select) { + /* NOTE: unlike nodes #SelectPick_Params isn't fully supported. */ + const bool extend = (params->sel_op == SEL_OP_XOR); if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) { + found = true; + node_was_selected = node->flag & SELECT; + /* NOTE: SOCK_IN does not take into account the extend case... * This feature is not really used anyway currently? */ node_socket_toggle(node, *sock, true); - ret_value = OPERATOR_FINISHED; + changed = true; } else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { + found = true; + node_was_selected = node->flag & SELECT; + if (sock->flag & SELECT) { if (extend) { node_socket_deselect(node, *sock, true); - } - else { - ret_value = OPERATOR_FINISHED; + changed = true; } } else { @@ -566,6 +563,7 @@ static int node_mouse_select(bContext *C, continue; } node_socket_deselect(node, *tsock, true); + changed = true; } } if (!extend) { @@ -575,69 +573,71 @@ static int node_mouse_select(bContext *C, } for (tsock = (bNodeSocket *)tnode->outputs.first; tsock; tsock = tsock->next) { node_socket_deselect(tnode, *tsock, true); + changed = true; } } } node_socket_select(node, *sock); - ret_value = OPERATOR_FINISHED; + changed = true; } } } if (!sock) { + /* find the closest visible node */ node = node_under_mouse_select(*snode.edittree, (int)cursor[0], (int)cursor[1]); + found = (node != nullptr); + node_was_selected = node && (node->flag & SELECT); - if (extend) { - if (node != nullptr) { - /* If node is selected but not active, we want to make it active, - * but not toggle (deselect) it. */ - if (!((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0)) { - node_toggle(node); - } - ret_value = OPERATOR_FINISHED; + if (params->sel_op == SEL_OP_SET) { + if ((found && params->select_passthrough) && (node->flag & SELECT)) { + found = false; } - } - else if (deselect_all && node == nullptr) { - /* Rather than deselecting others, users may want to drag to box-select (drag from empty - * space) or tweak-translate an already selected item. If these cases may apply, delay - * deselection. */ - if (wait_to_deselect_others) { - ret_value = OPERATOR_RUNNING_MODAL; - } - else { - /* Deselect in empty space. */ + else if (found || params->deselect_all) { + /* Deselect everything. */ for (tnode = (bNode *)snode.edittree->nodes.first; tnode; tnode = tnode->next) { nodeSetSelected(tnode, false); } - ret_value = OPERATOR_FINISHED; + changed = true; } } - else if (node != nullptr) { - /* When clicking on an already selected node, we want to wait to deselect - * others and allow the user to start moving the node without that. */ - if (wait_to_deselect_others && (node->flag & SELECT)) { - ret_value = OPERATOR_RUNNING_MODAL; - } - else { - nodeSetSelected(node, true); - for (tnode = (bNode *)snode.edittree->nodes.first; tnode; tnode = tnode->next) { - if (tnode != node) { - nodeSetSelected(tnode, false); - } + if (found) { + switch (params->sel_op) { + case SEL_OP_ADD: { + nodeSetSelected(node, true); + break; + } + case SEL_OP_SUB: { + nodeSetSelected(node, false); + break; + } + case SEL_OP_XOR: { + /* Check active so clicking on an inactive node activates it. */ + bool is_selected = (node->flag & NODE_SELECT) && (node->flag & NODE_ACTIVE); + nodeSetSelected(node, !is_selected); + break; + } + case SEL_OP_SET: { + nodeSetSelected(node, true); + break; + } + case SEL_OP_AND: { + BLI_assert_unreachable(); /* Doesn't make sense for picking. */ + break; } - - ret_value = OPERATOR_FINISHED; } + + changed = true; } } /* update node order */ - if (ret_value != OPERATOR_CANCELLED) { + if (changed || found) { bool active_texture_changed = false; bool viewer_node_changed = false; - if (node != nullptr && ret_value != OPERATOR_RUNNING_MODAL) { + if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) { viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed); } @@ -654,23 +654,35 @@ static int node_mouse_select(bContext *C, WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); } - return ret_value; + return changed || found; } static int node_select_exec(bContext *C, wmOperator *op) { - const bool wait_to_deselect_others = RNA_boolean_get(op->ptr, "wait_to_deselect_others"); - /* get settings from RNA properties for operator */ int mval[2]; - mval[0] = RNA_int_get(op->ptr, "mouse_x"); - mval[1] = RNA_int_get(op->ptr, "mouse_y"); + RNA_int_get_array(op->ptr, "location", mval); + + struct SelectPick_Params params = {}; + ED_select_pick_params_from_operator(op, ¶ms); /* perform the select */ - const int ret_value = node_mouse_select(C, op, mval, wait_to_deselect_others); + const bool changed = node_mouse_select(C, op, mval, ¶ms); - /* allow tweak event to work too */ - return ret_value | OPERATOR_PASS_THROUGH; + if (changed) { + return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; + } + /* Nothing selected, just passthrough. */ + return OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED; +} + +static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + RNA_int_set_array(op->ptr, "location", event->mval); + + const int retval = node_select_exec(C, op); + + return WM_operator_flag_only_pass_through_on_press(retval, event); } void NODE_OT_select(wmOperatorType *ot) @@ -684,24 +696,28 @@ void NODE_OT_select(wmOperatorType *ot) /* api callbacks */ ot->exec = node_select_exec; - ot->invoke = WM_generic_select_invoke; - ot->modal = WM_generic_select_modal; + ot->invoke = node_select_invoke; ot->poll = ED_operator_node_active; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - WM_operator_properties_generic_select(ot); - prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", ""); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); + WM_operator_properties_mouse_select(ot); + + prop = RNA_def_int_vector(ot->srna, + "location", + 2, + NULL, + INT_MIN, + INT_MAX, + "Location", + "Mouse location", + INT_MIN, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_boolean(ot->srna, "socket_select", false, "Socket Select", ""); - 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); } /** \} */ |