Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/space_node/node_select.c')
-rw-r--r--source/blender/editors/space_node/node_select.c136
1 files changed, 105 insertions, 31 deletions
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 944a54b088d..aab328249fe 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -429,19 +429,24 @@ void node_select_single(bContext *C, bNode *node)
WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
-static int node_mouse_select(Main *bmain,
- SpaceNode *snode,
- ARegion *ar,
+static int node_mouse_select(bContext *C,
const int mval[2],
const bool extend,
const bool socket_select,
- const bool deselect_all)
+ const bool deselect_all,
+ const bool wait_to_deselect_others)
{
+ Main *bmain = CTX_data_main(C);
+ SpaceNode *snode = CTX_wm_space_node(C);
+ ARegion *ar = CTX_wm_region(C);
bNode *node, *tnode;
bNodeSocket *sock = NULL;
bNodeSocket *tsock;
float cursor[2];
- bool selected = false;
+ int ret_value = OPERATOR_CANCELLED;
+
+ /* Waiting to deselect others is only allowed for basic selection. */
+ BLI_assert(!(extend || socket_select) || !wait_to_deselect_others);
/* get mouse coordinates in view2d space */
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]);
@@ -452,7 +457,7 @@ static int node_mouse_select(Main *bmain,
/* 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);
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) {
if (sock->flag & SELECT) {
@@ -460,7 +465,7 @@ static int node_mouse_select(Main *bmain,
node_socket_deselect(node, sock, true);
}
else {
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
else {
@@ -485,7 +490,7 @@ static int node_mouse_select(Main *bmain,
}
}
node_socket_select(node, sock);
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
}
@@ -501,39 +506,52 @@ static int node_mouse_select(Main *bmain,
if (!((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0)) {
node_toggle(node);
}
- selected = true;
+ ret_value = OPERATOR_FINISHED;
}
}
- else {
- if (node != NULL || deselect_all) {
+ else if (deselect_all && node == NULL) {
+ /* Deselect in empty space. */
+ for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
+ nodeSetSelected(tnode, false);
+ }
+ ret_value = OPERATOR_FINISHED;
+ }
+ else if (node != NULL) {
+ /* 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 = snode->edittree->nodes.first; tnode; tnode = tnode->next) {
- nodeSetSelected(tnode, false);
- }
- selected = true;
- if (node != NULL) {
- nodeSetSelected(node, true);
+ if (tnode != node) {
+ nodeSetSelected(tnode, false);
+ }
}
+
+ ret_value = OPERATOR_FINISHED;
}
}
}
/* update node order */
- if (selected) {
- if (node != NULL) {
+ if (ret_value != OPERATOR_CANCELLED) {
+ if (node != NULL && ret_value != OPERATOR_RUNNING_MODAL) {
ED_node_set_active(bmain, snode->edittree, node);
}
ED_node_set_active_viewer_key(snode);
ED_node_sort(snode->edittree);
+
+ WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
}
- return selected;
+ return ret_value;
}
static int node_select_exec(bContext *C, wmOperator *op)
{
- Main *bmain = CTX_data_main(C);
- SpaceNode *snode = CTX_wm_space_node(C);
- ARegion *ar = CTX_wm_region(C);
int mval[2];
/* get settings from RNA properties for operator */
@@ -546,17 +564,70 @@ static int node_select_exec(bContext *C, wmOperator *op)
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
/* perform the select */
- if (node_mouse_select(bmain, snode, ar, mval, extend, socket_select, deselect_all)) {
- /* send notifiers */
- WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL);
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false);
+
+ /* allow tweak event to work too */
+ return ret_value | OPERATOR_PASS_THROUGH;
+}
- /* allow tweak event to work too */
- return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+static int node_select_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ const short init_event_type = (short)POINTER_AS_INT(op->customdata);
+
+ /* 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");
+
+ 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) {
+ return node_select_exec(C, op);
}
- else {
- /* allow tweak event to work too */
- return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+
+ if (init_event_type == 0) {
+ if (event->val == KM_PRESS) {
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, true);
+
+ op->customdata = POINTER_FROM_INT((int)event->type);
+ if (ret_value & OPERATOR_RUNNING_MODAL) {
+ WM_event_add_modal_handler(C, op);
+ }
+ return ret_value | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* If we are in init phase, and cannot validate init of modal operations,
+ * just fall back to basic exec.
+ */
+ return node_select_exec(C, op);
+ }
+ }
+ else if (event->type == init_event_type && event->val == KM_RELEASE) {
+ const int ret_value = node_mouse_select(C, mval, extend, socket_select, deselect_all, false);
+ return ret_value | OPERATOR_PASS_THROUGH;
}
+ else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {
+ const int dx = mval[0] - event->mval[0];
+ const int dy = mval[1] - event->mval[1];
+ const float tweak_threshold = U.tweak_threshold * U.dpi_fac;
+ /* If user moves mouse more than defined threshold, we consider select operator as
+ * finished. Otherwise, it is still running until we get an 'release' event. In any
+ * case, we pass through event, but select op is not finished yet. */
+ if (abs(dx) + abs(dy) > tweak_threshold) {
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* Important not to return anything other than PASS_THROUGH here,
+ * otherwise it prevents underlying tweak detection code to work properly. */
+ return OPERATOR_PASS_THROUGH;
+ }
+ }
+
+ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH;
}
static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
@@ -564,7 +635,9 @@ static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
RNA_int_set(op->ptr, "mouse_x", event->mval[0]);
RNA_int_set(op->ptr, "mouse_y", event->mval[1]);
- return node_select_exec(C, op);
+ op->customdata = POINTER_FROM_INT(0);
+
+ return node_select_modal(C, op, event);
}
void NODE_OT_select(wmOperatorType *ot)
@@ -577,6 +650,7 @@ void NODE_OT_select(wmOperatorType *ot)
/* api callbacks */
ot->invoke = node_select_invoke;
ot->exec = node_select_exec;
+ ot->modal = node_select_modal;
ot->poll = ED_operator_node_active;
/* flags */