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:
authorLukas Toenne <lukas.toenne@googlemail.com>2012-03-09 14:16:41 +0400
committerLukas Toenne <lukas.toenne@googlemail.com>2012-03-09 14:16:41 +0400
commit455d1be696da48d319edae53119ef234ec237b23 (patch)
tree3a05c96d22870786689d429c6c4ba00eb3ad663b /source/blender/editors/space_node/node_select.c
parenteb1b38f31a96d029caa4672c66608adcdc646048 (diff)
Node socket selection feature reimplemented from 2.49. Sockets can be selected as a sub-selection of nodes and are then preferred by the auto-connect operator. This makes it easier to create precise links over long distances as an alternative to the click & hold operator.
Socket selection is indicated by a simple white highlight circle. Multiple inputs can be selected by holding SHIFTKEY (just like regular node select). Only one output socket can be selected at a time for each node, but several outputs in different nodes are allowed. The auto-connect operator will prefer selected sockets on nodes for creating links. If either the output or input side have no selected sockets it will fall back to the previous behavior of chosing 'best' sockets first (colors, then vectors, then values). This could be improved in the future, but is out of scope here.
Diffstat (limited to 'source/blender/editors/space_node/node_select.c')
-rw-r--r--source/blender/editors/space_node/node_select.c270
1 files changed, 228 insertions, 42 deletions
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 15efd65450c..e2f3e7b51f2 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -173,13 +173,150 @@ static void node_sort(bNodeTree *ntree)
}
}
+static void node_select(bNode *node)
+{
+ node->flag |= SELECT;
+}
+
+static void node_deselect(bNode *node)
+{
+ bNodeSocket *sock;
+
+ node->flag &= ~SELECT;
+
+ /* deselect sockets too */
+ for (sock=node->inputs.first; sock; sock=sock->next)
+ sock->flag &= ~SELECT;
+ for (sock=node->outputs.first; sock; sock=sock->next)
+ sock->flag &= ~SELECT;
+}
+
+static void node_toggle(bNode *node)
+{
+ if (node->flag & SELECT)
+ node_deselect(node);
+ else
+ node_select(node);
+}
+
+static void node_socket_select(bNode *node, bNodeSocket *sock)
+{
+ sock->flag |= SELECT;
+
+ /* select node too */
+ if (node)
+ node->flag |= SELECT;
+}
+
+static void node_socket_deselect(bNode *node, bNodeSocket *sock, int deselect_node)
+{
+ sock->flag &= ~SELECT;
+
+ if (node && deselect_node) {
+ int sel=0;
+
+ /* if no selected sockets remain, also deselect the node */
+ for (sock=node->inputs.first; sock; sock=sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+ for (sock=node->outputs.first; sock; sock=sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+
+ if (!sel)
+ node->flag &= ~SELECT;
+ }
+}
+
+static void node_socket_toggle(bNode *node, bNodeSocket *sock, int deselect_node)
+{
+ if (sock->flag & SELECT)
+ node_socket_deselect(node, sock, deselect_node);
+ else
+ node_socket_select(node, sock);
+}
+
/* no undo here! */
void node_deselect_all(SpaceNode *snode)
{
bNode *node;
for(node= snode->edittree->nodes.first; node; node= node->next)
- node->flag &= ~SELECT;
+ node_deselect(node);
+}
+
+void node_deselect_all_input_sockets(SpaceNode *snode, int deselect_nodes)
+{
+ bNode *node;
+ bNodeSocket *sock;
+
+ /* XXX not calling node_socket_deselect here each time, because this does iteration
+ * over all node sockets internally to check if the node stays selected.
+ * We can do that more efficiently here.
+ */
+
+ for (node= snode->edittree->nodes.first; node; node= node->next) {
+ int sel=0;
+
+ for (sock= node->inputs.first; sock; sock=sock->next)
+ sock->flag &= ~SELECT;
+
+ /* if no selected sockets remain, also deselect the node */
+ if (deselect_nodes) {
+ for (sock= node->outputs.first; sock; sock=sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+
+ if (!sel)
+ node->flag &= ~SELECT;
+ }
+ }
+
+ for (sock= snode->edittree->outputs.first; sock; sock=sock->next)
+ sock->flag &= ~SELECT;
+}
+
+void node_deselect_all_output_sockets(SpaceNode *snode, int deselect_nodes)
+{
+ bNode *node;
+ bNodeSocket *sock;
+
+ /* XXX not calling node_socket_deselect here each time, because this does iteration
+ * over all node sockets internally to check if the node stays selected.
+ * We can do that more efficiently here.
+ */
+
+ for (node= snode->edittree->nodes.first; node; node= node->next) {
+ int sel=0;
+
+ for (sock= node->outputs.first; sock; sock=sock->next)
+ sock->flag &= ~SELECT;
+
+ /* if no selected sockets remain, also deselect the node */
+ if (deselect_nodes) {
+ for (sock= node->inputs.first; sock; sock=sock->next) {
+ if (sock->flag & SELECT) {
+ sel = 1;
+ break;
+ }
+ }
+
+ if (!sel)
+ node->flag &= ~SELECT;
+ }
+ }
+
+ for (sock= snode->edittree->inputs.first; sock; sock=sock->next)
+ sock->flag &= ~SELECT;
}
/* return 1 if we need redraw otherwise zero. */
@@ -203,12 +340,12 @@ int node_select_same_type(SpaceNode *snode)
if (p->type != nac->type && p->flag & SELECT) {
/* if it's selected but different type, unselect */
redraw= 1;
- p->flag &= ~SELECT;
+ node_deselect(p);
}
else if (p->type == nac->type && (!(p->flag & SELECT))) {
/* if it's the same type and is not selected, select! */
redraw= 1;
- p->flag |= SELECT;
+ node_select(p);
}
}
return(redraw);
@@ -219,7 +356,7 @@ int node_select_same_type(SpaceNode *snode)
*/
int node_select_same_type_np(SpaceNode *snode, int dir)
{
- bNode *nac, *p;
+ bNode *nac, *p, *tnode;
/* search the active one. */
for (nac= snode->edittree->nodes.first; nac; nac= nac->next) {
@@ -248,8 +385,10 @@ int node_select_same_type_np(SpaceNode *snode, int dir)
}
if (p) {
- node_deselect_all(snode);
- p->flag |= SELECT;
+ for (tnode=snode->edittree->nodes.first; tnode; tnode=tnode->next)
+ if (tnode!=p)
+ node_deselect(tnode);
+ node_select(p);
return(1);
}
return(0);
@@ -259,9 +398,12 @@ void node_select_single(bContext *C, bNode *node)
{
Main *bmain= CTX_data_main(C);
SpaceNode *snode= CTX_wm_space_node(C);
+ bNode *tnode;
- node_deselect_all(snode);
- node->flag |= SELECT;
+ for (tnode=snode->edittree->nodes.first; tnode; tnode=tnode->next)
+ if (tnode!=node)
+ node_deselect(tnode);
+ node_select(node);
ED_node_set_active(bmain, snode->edittree, node);
@@ -272,34 +414,75 @@ void node_select_single(bContext *C, bNode *node)
/* ****** Click Select ****** */
-static bNode *node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], short extend)
+static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const int mval[2], short extend)
{
- bNode *node;
+ bNode *node, *tnode;
+ bNodeSocket *sock, *tsock;
float mx, my;
/* get mouse coordinates in view2d space */
- mx= (float)mval[0];
- my= (float)mval[1];
-
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my);
-
- /* find the closest visible node */
- node = node_under_mouse(snode->edittree, mx, my);
-
- if (node) {
- if (extend == 0) {
- node_deselect_all(snode);
- node->flag |= SELECT;
+ /* node_find_indicated_socket uses snode->mx/my */
+ snode->mx = mx;
+ snode->my = my;
+
+ /* first do socket selection, these generally overlap with nodes */
+ if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
+ if (extend) {
+ node_socket_toggle(node, sock, 1);
+ }
+ else {
+ node_deselect_all_input_sockets(snode, 1);
+ node_socket_select(node, sock);
+ }
+
+ return 1;
+ }
+ else if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
+ if (extend) {
+ if (sock->flag & SELECT) {
+ node_socket_deselect(node, sock, 1);
+ }
+ else {
+ /* still only allow one selected output per node when extending, for sensible linking.
+ * extend allows selecting outputs from different nodes though.
+ */
+ if (node) {
+ for (tsock=node->outputs.first; tsock; tsock=tsock->next)
+ node_socket_deselect(node, tsock, 1);
+ }
+ node_socket_select(node, sock);
+ }
+ }
+ else {
+ node_deselect_all_output_sockets(snode, 1);
+ node_socket_select(node, sock);
}
- else
- node->flag ^= SELECT;
- ED_node_set_active(bmain, snode->edittree, node);
+ return 1;
+ }
+ else {
+ /* find the closest visible node */
+ node = node_under_mouse(snode->edittree, mx, my);
+
+ if (node) {
+ if (extend == 0) {
+ for (tnode=snode->edittree->nodes.first; tnode; tnode=tnode->next)
+ if (tnode!=node)
+ node_deselect(tnode);
+ node_select(node);
+ }
+ else {
+ node_toggle(node);
+ }
+
+ ED_node_set_active(bmain, snode->edittree, node);
+ node_sort(snode->edittree);
+ return 1;
+ }
- node_sort(snode->edittree);
+ return 0;
}
-
- return node;
}
static int node_select_exec(bContext *C, wmOperator *op)
@@ -309,7 +492,6 @@ static int node_select_exec(bContext *C, wmOperator *op)
ARegion *ar= CTX_wm_region(C);
int mval[2];
short extend;
- /* bNode *node= NULL; */ /* UNUSED */
/* get settings from RNA properties for operator */
mval[0] = RNA_int_get(op->ptr, "mouse_x");
@@ -318,13 +500,17 @@ static int node_select_exec(bContext *C, wmOperator *op)
extend = RNA_boolean_get(op->ptr, "extend");
/* perform the select */
- /* node= */ /* UNUSED*/ node_mouse_select(bmain, snode, ar, mval, extend);
-
- /* send notifiers */
- WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
-
- /* allow tweak event to work too */
- return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+ if (node_mouse_select(bmain, snode, ar, mval, extend)) {
+ /* send notifiers */
+ WM_event_add_notifier(C, NC_NODE|NA_SELECTED, NULL);
+
+ /* allow tweak event to work too */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
+ }
+ else {
+ /* allow tweak event to work too */
+ return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
+ }
}
static int node_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
@@ -379,12 +565,12 @@ static int node_borderselect_exec(bContext *C, wmOperator *op)
for(node= snode->edittree->nodes.first; node; node= node->next) {
if(BLI_isect_rctf(&rectf, &node->totr, NULL)) {
if(gesture_mode==GESTURE_MODAL_SELECT)
- node->flag |= SELECT;
+ node_select(node);
else
- node->flag &= ~SELECT;
+ node_deselect(node);
}
else if(!extend) {
- node->flag &= ~SELECT;
+ node_deselect(node);
}
}
@@ -453,11 +639,11 @@ static int node_select_all_exec(bContext *C, wmOperator *UNUSED(op))
if(count) {
for(node=first; node; node=node->next)
- node->flag &= ~NODE_SELECT;
+ node_deselect(node);
}
else {
for(node=first; node; node=node->next)
- node->flag |= NODE_SELECT;
+ node_select(node);
}
node_sort(snode->edittree);
@@ -499,7 +685,7 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
for (node=snode->edittree->nodes.first; node; node=node->next) {
if (node->flag & NODE_TEST)
- node->flag |= NODE_SELECT;
+ node_select(node);
}
node_sort(snode->edittree);
@@ -541,7 +727,7 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
for(node=snode->edittree->nodes.first; node; node=node->next) {
if(node->flag & NODE_TEST)
- node->flag |= NODE_SELECT;
+ node_select(node);
}
node_sort(snode->edittree);