code cleanup: use const events for modal and invoke operators.
[blender.git] / source / blender / editors / space_node / node_relationships.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Nathan Letwory
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_node/node_relationships.c
29  *  \ingroup spnode
30  */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_node_types.h"
35 #include "DNA_object_types.h"
36
37 #include "BLI_math.h"
38 #include "BLI_blenlib.h"
39
40 #include "BKE_context.h"
41 #include "BKE_main.h"
42 #include "BKE_node.h"
43
44 #include "ED_node.h"  /* own include */
45 #include "ED_screen.h"
46 #include "ED_render.h"
47
48 #include "RNA_access.h"
49 #include "RNA_define.h"
50
51 #include "WM_api.h"
52 #include "WM_types.h"
53
54 #include "UI_view2d.h"
55
56 #include "node_intern.h"  /* own include */
57
58 /* ****************** Add *********************** */
59
60
61 typedef struct bNodeListItem {
62         struct bNodeListItem *next, *prev;
63         struct bNode *node;
64 } bNodeListItem;
65
66 static int sort_nodes_locx(void *a, void *b)
67 {
68         bNodeListItem *nli1 = (bNodeListItem *)a;
69         bNodeListItem *nli2 = (bNodeListItem *)b;
70         bNode *node1 = nli1->node;
71         bNode *node2 = nli2->node;
72
73         if (node1->locx > node2->locx)
74                 return 1;
75         else
76                 return 0;
77 }
78
79 static int socket_is_available(bNodeTree *UNUSED(ntree), bNodeSocket *sock, int allow_used)
80 {
81         if (nodeSocketIsHidden(sock))
82                 return 0;
83
84         if (!allow_used && (sock->flag & SOCK_IN_USE))
85                 return 0;
86
87         return 1;
88 }
89
90 static bNodeSocket *best_socket_output(bNodeTree *ntree, bNode *node, bNodeSocket *sock_target, int allow_multiple)
91 {
92         bNodeSocket *sock;
93
94         /* first look for selected output */
95         for (sock = node->outputs.first; sock; sock = sock->next) {
96                 if (!socket_is_available(ntree, sock, allow_multiple))
97                         continue;
98
99                 if (sock->flag & SELECT)
100                         return sock;
101         }
102
103         /* try to find a socket with a matching name */
104         for (sock = node->outputs.first; sock; sock = sock->next) {
105                 if (!socket_is_available(ntree, sock, allow_multiple))
106                         continue;
107
108                 /* check for same types */
109                 if (sock->type == sock_target->type) {
110                         if (strcmp(sock->name, sock_target->name) == 0)
111                                 return sock;
112                 }
113         }
114
115         /* otherwise settle for the first available socket of the right type */
116         for (sock = node->outputs.first; sock; sock = sock->next) {
117
118                 if (!socket_is_available(ntree, sock, allow_multiple))
119                         continue;
120
121                 /* check for same types */
122                 if (sock->type == sock_target->type) {
123                         return sock;
124                 }
125         }
126
127         return NULL;
128 }
129
130 /* this is a bit complicated, but designed to prioritize finding
131  * sockets of higher types, such as image, first */
132 static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, int replace)
133 {
134         bNodeSocket *sock;
135         int socktype, maxtype = 0;
136         int a = 0;
137
138         for (sock = node->inputs.first; sock; sock = sock->next) {
139                 maxtype = max_ii(sock->type, maxtype);
140         }
141
142         /* find sockets of higher 'types' first (i.e. image) */
143         for (socktype = maxtype; socktype >= 0; socktype--) {
144                 for (sock = node->inputs.first; sock; sock = sock->next) {
145
146                         if (!socket_is_available(ntree, sock, replace)) {
147                                 a++;
148                                 continue;
149                         }
150
151                         if (sock->type == socktype) {
152                                 /* increment to make sure we don't keep finding
153                                  * the same socket on every attempt running this function */
154                                 a++;
155                                 if (a > num)
156                                         return sock;
157                         }
158                 }
159         }
160
161         return NULL;
162 }
163
164 static int snode_autoconnect_input(SpaceNode *snode, bNode *node_fr, bNodeSocket *sock_fr, bNode *node_to, bNodeSocket *sock_to, int replace)
165 {
166         bNodeTree *ntree = snode->edittree;
167         bNodeLink *link;
168
169         /* then we can connect */
170         if (replace)
171                 nodeRemSocketLinks(ntree, sock_to);
172
173         link = nodeAddLink(ntree, node_fr, sock_fr, node_to, sock_to);
174         /* validate the new link */
175         ntreeUpdateTree(ntree);
176         if (!(link->flag & NODE_LINK_VALID)) {
177                 nodeRemLink(ntree, link);
178                 return 0;
179         }
180
181         snode_update(snode, node_to);
182         return 1;
183 }
184
185 static void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace)
186 {
187         bNodeTree *ntree = snode->edittree;
188         ListBase *nodelist = MEM_callocN(sizeof(ListBase), "items_list");
189         bNodeListItem *nli;
190         bNode *node;
191         int i, numlinks = 0;
192
193         for (node = ntree->nodes.first; node; node = node->next) {
194                 if (node->flag & NODE_SELECT) {
195                         nli = MEM_mallocN(sizeof(bNodeListItem), "temporary node list item");
196                         nli->node = node;
197                         BLI_addtail(nodelist, nli);
198                 }
199         }
200
201         /* sort nodes left to right */
202         BLI_sortlist(nodelist, sort_nodes_locx);
203
204         for (nli = nodelist->first; nli; nli = nli->next) {
205                 bNode *node_fr, *node_to;
206                 bNodeSocket *sock_fr, *sock_to;
207                 int has_selected_inputs = 0;
208
209                 if (nli->next == NULL) break;
210
211                 node_fr = nli->node;
212                 node_to = nli->next->node;
213
214                 /* if there are selected sockets, connect those */
215                 for (sock_to = node_to->inputs.first; sock_to; sock_to = sock_to->next) {
216                         if (sock_to->flag & SELECT) {
217                                 has_selected_inputs = 1;
218
219                                 if (!socket_is_available(ntree, sock_to, replace))
220                                         continue;
221
222                                 /* check for an appropriate output socket to connect from */
223                                 sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
224                                 if (!sock_fr)
225                                         continue;
226
227                                 if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
228                                         numlinks++;
229                                 }
230                         }
231                 }
232
233                 if (!has_selected_inputs) {
234                         /* no selected inputs, connect by finding suitable match */
235                         int num_inputs = BLI_countlist(&node_to->inputs);
236
237                         for (i = 0; i < num_inputs; i++) {
238
239                                 /* find the best guess input socket */
240                                 sock_to = best_socket_input(ntree, node_to, i, replace);
241                                 if (!sock_to)
242                                         continue;
243
244                                 /* check for an appropriate output socket to connect from */
245                                 sock_fr = best_socket_output(ntree, node_fr, sock_to, allow_multiple);
246                                 if (!sock_fr)
247                                         continue;
248
249                                 if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
250                                         numlinks++;
251                                         break;
252                                 }
253                         }
254                 }
255         }
256
257         if (numlinks > 0) {
258                 ntreeUpdateTree(ntree);
259         }
260
261         BLI_freelistN(nodelist);
262         MEM_freeN(nodelist);
263 }
264
265 /* *************************** link viewer op ******************** */
266
267 static int node_link_viewer(const bContext *C, bNode *tonode)
268 {
269         SpaceNode *snode = CTX_wm_space_node(C);
270         bNode *node;
271         bNodeLink *link;
272         bNodeSocket *sock;
273
274         /* context check */
275         if (tonode == NULL || tonode->outputs.first == NULL)
276                 return OPERATOR_CANCELLED;
277         if (ELEM(tonode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
278                 return OPERATOR_CANCELLED;
279
280         /* get viewer */
281         for (node = snode->edittree->nodes.first; node; node = node->next)
282                 if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
283                         if (node->flag & NODE_DO_OUTPUT)
284                                 break;
285         /* no viewer, we make one active */
286         if (node == NULL) {
287                 for (node = snode->edittree->nodes.first; node; node = node->next) {
288                         if (ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
289                                 node->flag |= NODE_DO_OUTPUT;
290                                 break;
291                         }
292                 }
293         }
294
295         sock = NULL;
296
297         /* try to find an already connected socket to cycle to the next */
298         if (node) {
299                 link = NULL;
300                 for (link = snode->edittree->links.first; link; link = link->next)
301                         if (link->tonode == node && link->fromnode == tonode)
302                                 if (link->tosock == node->inputs.first)
303                                         break;
304                 if (link) {
305                         /* unlink existing connection */
306                         sock = link->fromsock;
307                         nodeRemLink(snode->edittree, link);
308
309                         /* find a socket after the previously connected socket */
310                         for (sock = sock->next; sock; sock = sock->next)
311                                 if (!nodeSocketIsHidden(sock))
312                                         break;
313                 }
314         }
315
316         /* find a socket starting from the first socket */
317         if (!sock) {
318                 for (sock = tonode->outputs.first; sock; sock = sock->next)
319                         if (!nodeSocketIsHidden(sock))
320                                 break;
321         }
322
323         if (sock) {
324                 /* add a new viewer if none exists yet */
325                 if (!node) {
326                         Main *bmain = CTX_data_main(C);
327                         Scene *scene = CTX_data_scene(C);
328                         bNodeTemplate ntemp;
329
330                         ntemp.type = CMP_NODE_VIEWER;
331                         /* XXX location is a quick hack, just place it next to the linked socket */
332                         node = node_add_node(snode, bmain, scene, &ntemp, sock->locx + 100, sock->locy);
333                         if (!node)
334                                 return OPERATOR_CANCELLED;
335
336                         link = NULL;
337                 }
338                 else {
339                         /* get link to viewer */
340                         for (link = snode->edittree->links.first; link; link = link->next)
341                                 if (link->tonode == node && link->tosock == node->inputs.first)
342                                         break;
343                 }
344
345                 if (link == NULL) {
346                         nodeAddLink(snode->edittree, tonode, sock, node, node->inputs.first);
347                 }
348                 else {
349                         link->fromnode = tonode;
350                         link->fromsock = sock;
351                         /* make sure the dependency sorting is updated */
352                         snode->edittree->update |= NTREE_UPDATE_LINKS;
353                 }
354                 ntreeUpdateTree(snode->edittree);
355                 snode_update(snode, node);
356         }
357
358         return OPERATOR_FINISHED;
359 }
360
361
362 static int node_active_link_viewer(bContext *C, wmOperator *UNUSED(op))
363 {
364         SpaceNode *snode = CTX_wm_space_node(C);
365         bNode *node;
366
367         node = editnode_get_active(snode->edittree);
368
369         if (!node)
370                 return OPERATOR_CANCELLED;
371
372         ED_preview_kill_jobs(C);
373
374         if (node_link_viewer(C, node) == OPERATOR_CANCELLED)
375                 return OPERATOR_CANCELLED;
376
377         snode_notify(C, snode);
378
379         return OPERATOR_FINISHED;
380 }
381
382
383 void NODE_OT_link_viewer(wmOperatorType *ot)
384 {
385         /* identifiers */
386         ot->name = "Link to Viewer Node";
387         ot->description = "Link to viewer node";
388         ot->idname = "NODE_OT_link_viewer";
389
390         /* api callbacks */
391         ot->exec = node_active_link_viewer;
392         ot->poll = composite_node_active;
393
394         /* flags */
395         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
396 }
397
398
399 /* *************************** add link op ******************** */
400
401 static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeLink *link)
402 {
403         bNodeLink *tlink;
404         bNodeSocket *sock;
405
406         if (tsock && nodeCountSocketLinks(snode->edittree, link->tosock) > tsock->limit) {
407
408                 for (tlink = snode->edittree->links.first; tlink; tlink = tlink->next) {
409                         if (link != tlink && tlink->tosock == link->tosock)
410                                 break;
411                 }
412                 if (tlink) {
413                         /* try to move the existing link to the next available socket */
414                         if (tlink->tonode) {
415                                 /* is there a free input socket with the target type? */
416                                 for (sock = tlink->tonode->inputs.first; sock; sock = sock->next) {
417                                         if (sock->type == tlink->tosock->type)
418                                                 if (nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
419                                                         break;
420                                 }
421                                 if (sock) {
422                                         tlink->tosock = sock;
423                                         sock->flag &= ~SOCK_HIDDEN;
424                                 }
425                                 else {
426                                         nodeRemLink(snode->edittree, tlink);
427                                 }
428                         }
429                         else
430                                 nodeRemLink(snode->edittree, tlink);
431
432                         snode->edittree->update |= NTREE_UPDATE_LINKS;
433                 }
434         }
435 }
436
437 static int outside_group_rect(SpaceNode *snode)
438 {
439         bNode *gnode = node_tree_get_editgroup(snode->nodetree);
440         if (gnode) {
441                 return (snode->cursor[0] <  gnode->totr.xmin ||
442                         snode->cursor[0] >= gnode->totr.xmax ||
443                         snode->cursor[1] <  gnode->totr.ymin ||
444                         snode->cursor[1] >= gnode->totr.ymax);
445         }
446         return 0;
447 }
448
449 /* loop that adds a nodelink, called by function below  */
450 /* in_out = starting socket */
451 static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event)
452 {
453         SpaceNode *snode = CTX_wm_space_node(C);
454         ARegion *ar = CTX_wm_region(C);
455         bNodeLinkDrag *nldrag = op->customdata;
456         bNodeTree *ntree = snode->edittree;
457         bNode *tnode;
458         bNodeSocket *tsock = NULL;
459         bNodeLink *link;
460         LinkData *linkdata;
461         int in_out;
462
463         in_out = nldrag->in_out;
464
465         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
466                                  &snode->cursor[0], &snode->cursor[1]);
467
468         switch (event->type) {
469                 case MOUSEMOVE:
470
471                         if (in_out == SOCK_OUT) {
472                                 if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
473                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
474                                                 link = linkdata->data;
475
476                                                 /* skip if this is already the target socket */
477                                                 if (link->tosock == tsock)
478                                                         continue;
479                                                 /* skip if socket is on the same node as the fromsock */
480                                                 if (tnode && link->fromnode == tnode)
481                                                         continue;
482
483                                                 /* attach links to the socket */
484                                                 link->tonode = tnode;
485                                                 link->tosock = tsock;
486                                                 /* add it to the node tree temporarily */
487                                                 if (BLI_findindex(&ntree->links, link) < 0)
488                                                         BLI_addtail(&ntree->links, link);
489
490                                                 ntree->update |= NTREE_UPDATE_LINKS;
491                                         }
492                                         ntreeUpdateTree(ntree);
493                                 }
494                                 else {
495                                         int do_update = FALSE;
496                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
497                                                 link = linkdata->data;
498
499                                                 if (link->tonode || link->tosock) {
500                                                         BLI_remlink(&ntree->links, link);
501                                                         link->prev = link->next = NULL;
502                                                         link->tonode = NULL;
503                                                         link->tosock = NULL;
504
505                                                         ntree->update |= NTREE_UPDATE_LINKS;
506                                                         do_update = TRUE;
507                                                 }
508                                         }
509                                         if (do_update) {
510                                                 ntreeUpdateTree(ntree);
511                                         }
512                                 }
513                         }
514                         else {
515                                 if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
516                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
517                                                 link = linkdata->data;
518
519                                                 /* skip if this is already the target socket */
520                                                 if (link->fromsock == tsock)
521                                                         continue;
522                                                 /* skip if socket is on the same node as the fromsock */
523                                                 if (tnode && link->tonode == tnode)
524                                                         continue;
525
526                                                 /* attach links to the socket */
527                                                 link->fromnode = tnode;
528                                                 link->fromsock = tsock;
529                                                 /* add it to the node tree temporarily */
530                                                 if (BLI_findindex(&ntree->links, link) < 0)
531                                                         BLI_addtail(&ntree->links, link);
532
533                                                 ntree->update |= NTREE_UPDATE_LINKS;
534                                         }
535                                         ntreeUpdateTree(ntree);
536                                 }
537                                 else {
538                                         int do_update = FALSE;
539                                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
540                                                 link = linkdata->data;
541
542                                                 if (link->fromnode || link->fromsock) {
543                                                         BLI_remlink(&ntree->links, link);
544                                                         link->prev = link->next = NULL;
545                                                         link->fromnode = NULL;
546                                                         link->fromsock = NULL;
547
548                                                         ntree->update |= NTREE_UPDATE_LINKS;
549                                                         do_update = TRUE;
550                                                 }
551                                         }
552                                         if (do_update) {
553                                                 ntreeUpdateTree(ntree);
554                                         }
555                                 }
556                         }
557
558                         ED_region_tag_redraw(ar);
559                         break;
560
561                 case LEFTMOUSE:
562                 case RIGHTMOUSE:
563                 case MIDDLEMOUSE:
564                 {
565                         for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) {
566                                 link = linkdata->data;
567
568                                 if (link->tosock && link->fromsock) {
569                                         /* send changed events for original tonode and new */
570                                         if (link->tonode)
571                                                 snode_update(snode, link->tonode);
572
573                                         /* we might need to remove a link */
574                                         if (in_out == SOCK_OUT)
575                                                 node_remove_extra_links(snode, link->tosock, link);
576
577                                         /* when linking to group outputs, update the socket type */
578                                         /* XXX this should all be part of a generic update system */
579                                         if (!link->tonode) {
580                                                 if (link->tosock->type != link->fromsock->type)
581                                                         nodeSocketSetType(link->tosock, link->fromsock->type);
582                                         }
583                                 }
584                                 else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
585                                         /* automatically add new group socket */
586                                         if (link->tonode && link->tosock) {
587                                                 link->fromsock = node_group_expose_socket(ntree, link->tosock, SOCK_IN);
588                                                 link->fromnode = NULL;
589                                                 if (BLI_findindex(&ntree->links, link) < 0)
590                                                         BLI_addtail(&ntree->links, link);
591
592                                                 ntree->update |= NTREE_UPDATE_GROUP_IN | NTREE_UPDATE_LINKS;
593                                         }
594                                         else if (link->fromnode && link->fromsock) {
595                                                 link->tosock = node_group_expose_socket(ntree, link->fromsock, SOCK_OUT);
596                                                 link->tonode = NULL;
597                                                 if (BLI_findindex(&ntree->links, link) < 0)
598                                                         BLI_addtail(&ntree->links, link);
599
600                                                 ntree->update |= NTREE_UPDATE_GROUP_OUT | NTREE_UPDATE_LINKS;
601                                         }
602                                 }
603                                 else
604                                         nodeRemLink(ntree, link);
605                         }
606
607                         ntreeUpdateTree(ntree);
608                         snode_notify(C, snode);
609                         snode_dag_update(C, snode);
610
611                         BLI_remlink(&snode->linkdrag, nldrag);
612                         /* links->data pointers are either held by the tree or freed already */
613                         BLI_freelistN(&nldrag->links);
614                         MEM_freeN(nldrag);
615
616                         return OPERATOR_FINISHED;
617                 }
618         }
619
620         return OPERATOR_RUNNING_MODAL;
621 }
622
623 /* return 1 when socket clicked */
624 static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach)
625 {
626         bNode *node;
627         bNodeSocket *sock;
628         bNodeLink *link, *link_next, *oplink;
629         bNodeLinkDrag *nldrag = NULL;
630         LinkData *linkdata;
631         int num_links;
632
633         /* output indicated? */
634         if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) {
635                 nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
636
637                 num_links = nodeCountSocketLinks(snode->edittree, sock);
638                 if (num_links > 0 && (num_links >= sock->limit || detach)) {
639                         /* dragged links are fixed on input side */
640                         nldrag->in_out = SOCK_IN;
641                         /* detach current links and store them in the operator data */
642                         for (link = snode->edittree->links.first; link; link = link_next) {
643                                 link_next = link->next;
644                                 if (link->fromsock == sock) {
645                                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
646                                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
647                                         *oplink = *link;
648                                         oplink->next = oplink->prev = NULL;
649                                         BLI_addtail(&nldrag->links, linkdata);
650                                         nodeRemLink(snode->edittree, link);
651                                 }
652                         }
653                 }
654                 else {
655                         /* dragged links are fixed on output side */
656                         nldrag->in_out = SOCK_OUT;
657                         /* create a new link */
658                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
659                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
660                         oplink->fromnode = node;
661                         oplink->fromsock = sock;
662                         BLI_addtail(&nldrag->links, linkdata);
663                 }
664         }
665         /* or an input? */
666         else if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) {
667                 nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata");
668
669                 num_links = nodeCountSocketLinks(snode->edittree, sock);
670                 if (num_links > 0 && (num_links >= sock->limit || detach)) {
671                         /* dragged links are fixed on output side */
672                         nldrag->in_out = SOCK_OUT;
673                         /* detach current links and store them in the operator data */
674                         for (link = snode->edittree->links.first; link; link = link_next) {
675                                 link_next = link->next;
676                                 if (link->tosock == sock) {
677                                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
678                                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
679                                         *oplink = *link;
680                                         oplink->next = oplink->prev = NULL;
681                                         BLI_addtail(&nldrag->links, linkdata);
682                                         nodeRemLink(snode->edittree, link);
683
684                                         /* send changed event to original link->tonode */
685                                         if (node)
686                                                 snode_update(snode, node);
687                                 }
688                         }
689                 }
690                 else {
691                         /* dragged links are fixed on input side */
692                         nldrag->in_out = SOCK_IN;
693                         /* create a new link */
694                         linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data");
695                         linkdata->data = oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link");
696                         oplink->tonode = node;
697                         oplink->tosock = sock;
698                         BLI_addtail(&nldrag->links, linkdata);
699                 }
700         }
701
702         return nldrag;
703 }
704
705 static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
706 {
707         SpaceNode *snode = CTX_wm_space_node(C);
708         ARegion *ar = CTX_wm_region(C);
709         bNodeLinkDrag *nldrag;
710         int detach = RNA_boolean_get(op->ptr, "detach");
711
712         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1],
713                                  &snode->cursor[0], &snode->cursor[1]);
714
715         ED_preview_kill_jobs(C);
716
717         nldrag = node_link_init(snode, detach);
718
719         if (nldrag) {
720                 op->customdata = nldrag;
721                 BLI_addtail(&snode->linkdrag, nldrag);
722
723                 /* add modal handler */
724                 WM_event_add_modal_handler(C, op);
725
726                 return OPERATOR_RUNNING_MODAL;
727         }
728         else
729                 return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
730 }
731
732 static int node_link_cancel(bContext *C, wmOperator *op)
733 {
734         SpaceNode *snode = CTX_wm_space_node(C);
735         bNodeLinkDrag *nldrag = op->customdata;
736
737         BLI_remlink(&snode->linkdrag, nldrag);
738
739         BLI_freelistN(&nldrag->links);
740         MEM_freeN(nldrag);
741
742         return OPERATOR_CANCELLED;
743 }
744
745 void NODE_OT_link(wmOperatorType *ot)
746 {
747         /* identifiers */
748         ot->name = "Link Nodes";
749         ot->idname = "NODE_OT_link";
750         ot->description = "Use the mouse to create a link between two nodes";
751
752         /* api callbacks */
753         ot->invoke = node_link_invoke;
754         ot->modal = node_link_modal;
755 //      ot->exec = node_link_exec;
756         ot->poll = ED_operator_node_active;
757         ot->cancel = node_link_cancel;
758
759         /* flags */
760         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
761
762         RNA_def_boolean(ot->srna, "detach", FALSE, "Detach", "Detach and redirect existing links");
763 }
764
765 /* ********************** Make Link operator ***************** */
766
767 /* makes a link between selected output and input sockets */
768 static int node_make_link_exec(bContext *C, wmOperator *op)
769 {
770         SpaceNode *snode = CTX_wm_space_node(C);
771         int replace = RNA_boolean_get(op->ptr, "replace");
772
773         ED_preview_kill_jobs(C);
774
775         snode_autoconnect(snode, 1, replace);
776
777         /* deselect sockets after linking */
778         node_deselect_all_input_sockets(snode, 0);
779         node_deselect_all_output_sockets(snode, 0);
780
781         ntreeUpdateTree(snode->edittree);
782         snode_notify(C, snode);
783         snode_dag_update(C, snode);
784
785         return OPERATOR_FINISHED;
786 }
787
788 void NODE_OT_link_make(wmOperatorType *ot)
789 {
790         /* identifiers */
791         ot->name = "Make Links";
792         ot->description = "Makes a link between selected output in input sockets";
793         ot->idname = "NODE_OT_link_make";
794
795         /* callbacks */
796         ot->exec = node_make_link_exec;
797         ot->poll = ED_operator_node_active; // XXX we need a special poll which checks that there are selected input/output sockets
798
799         /* flags */
800         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
801
802         RNA_def_boolean(ot->srna, "replace", 0, "Replace", "Replace socket connections with the new links");
803 }
804
805 /* ********************** Cut Link operator ***************** */
806 static int cut_links_intersect(bNodeLink *link, float mcoords[][2], int tot)
807 {
808         float coord_array[NODE_LINK_RESOL + 1][2];
809         int i, b;
810
811         if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) {
812
813                 for (i = 0; i < tot - 1; i++)
814                         for (b = 0; b < NODE_LINK_RESOL; b++)
815                                 if (isect_line_line_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0)
816                                         return 1;
817         }
818         return 0;
819 }
820
821 static int cut_links_exec(bContext *C, wmOperator *op)
822 {
823         SpaceNode *snode = CTX_wm_space_node(C);
824         ARegion *ar = CTX_wm_region(C);
825         float mcoords[256][2];
826         int i = 0;
827
828         RNA_BEGIN(op->ptr, itemptr, "path")
829         {
830                 float loc[2];
831
832                 RNA_float_get_array(&itemptr, "loc", loc);
833                 UI_view2d_region_to_view(&ar->v2d, (int)loc[0], (int)loc[1],
834                                          &mcoords[i][0], &mcoords[i][1]);
835                 i++;
836                 if (i >= 256) break;
837         }
838         RNA_END;
839
840         if (i > 1) {
841                 int found = FALSE;
842                 bNodeLink *link, *next;
843                 
844                 ED_preview_kill_jobs(C);
845                 
846                 for (link = snode->edittree->links.first; link; link = next) {
847                         next = link->next;
848
849                         if (cut_links_intersect(link, mcoords, i)) {
850
851                                 if (found == FALSE) {
852                                         ED_preview_kill_jobs(C);
853                                         found = TRUE;
854                                 }
855
856                                 snode_update(snode, link->tonode);
857                                 nodeRemLink(snode->edittree, link);
858                         }
859                 }
860
861                 if (found) {
862                         ntreeUpdateTree(snode->edittree);
863                         snode_notify(C, snode);
864                         snode_dag_update(C, snode);
865
866                         return OPERATOR_FINISHED;
867                 }
868                 else {
869                         return OPERATOR_CANCELLED;
870                 }
871
872         }
873
874         return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
875 }
876
877 void NODE_OT_links_cut(wmOperatorType *ot)
878 {
879         PropertyRNA *prop;
880
881         ot->name = "Cut Links";
882         ot->idname = "NODE_OT_links_cut";
883         ot->description = "Use the mouse to cut (remove) some links";
884
885         ot->invoke = WM_gesture_lines_invoke;
886         ot->modal = WM_gesture_lines_modal;
887         ot->exec = cut_links_exec;
888         ot->cancel = WM_gesture_lines_cancel;
889
890         ot->poll = ED_operator_node_active;
891
892         /* flags */
893         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
894
895         prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
896         RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
897         /* internal */
898         RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
899 }
900
901 /* ********************** Detach links operator ***************** */
902
903 static int detach_links_exec(bContext *C, wmOperator *UNUSED(op))
904 {
905         SpaceNode *snode = CTX_wm_space_node(C);
906         bNodeTree *ntree = snode->edittree;
907         bNode *node;
908
909         ED_preview_kill_jobs(C);
910
911         for (node = ntree->nodes.first; node; node = node->next) {
912                 if (node->flag & SELECT) {
913                         nodeInternalRelink(ntree, node);
914                 }
915         }
916
917         ntreeUpdateTree(ntree);
918
919         snode_notify(C, snode);
920         snode_dag_update(C, snode);
921
922         return OPERATOR_FINISHED;
923 }
924
925 void NODE_OT_links_detach(wmOperatorType *ot)
926 {
927         ot->name = "Detach Links";
928         ot->idname = "NODE_OT_links_detach";
929         ot->description = "Remove all links to selected nodes, and try to connect neighbor nodes together";
930
931         ot->exec = detach_links_exec;
932         ot->poll = ED_operator_node_active;
933
934         /* flags */
935         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
936 }
937
938
939 /* ****************** Show Cyclic Dependencies Operator  ******************* */
940
941 static int node_show_cycles_exec(bContext *C, wmOperator *UNUSED(op))
942 {
943         SpaceNode *snode = CTX_wm_space_node(C);
944
945         /* this is just a wrapper around this call... */
946         ntreeUpdateTree(snode->nodetree);
947         snode_notify(C, snode);
948
949         return OPERATOR_FINISHED;
950 }
951
952 void NODE_OT_show_cyclic_dependencies(wmOperatorType *ot)
953 {
954         /* identifiers */
955         ot->name = "Show Cyclic Dependencies";
956         ot->description = "Sort the nodes and show the cyclic dependencies between the nodes";
957         ot->idname = "NODE_OT_show_cyclic_dependencies";
958
959         /* callbacks */
960         ot->exec = node_show_cycles_exec;
961         ot->poll = ED_operator_node_active;
962
963         /* flags */
964         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
965 }
966
967 /* ****************** Set Parent ******************* */
968
969 static int node_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
970 {
971         SpaceNode *snode = CTX_wm_space_node(C);
972         bNodeTree *ntree = snode->edittree;
973         bNode *frame = nodeGetActive(ntree), *node;
974         if (!frame || frame->type != NODE_FRAME)
975                 return OPERATOR_CANCELLED;
976
977         for (node = ntree->nodes.first; node; node = node->next) {
978                 if (node == frame)
979                         continue;
980                 if (node->flag & NODE_SELECT) {
981                         nodeDetachNode(node);
982                         nodeAttachNode(node, frame);
983                 }
984         }
985
986         ED_node_sort(ntree);
987         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
988
989         return OPERATOR_FINISHED;
990 }
991
992 void NODE_OT_parent_set(wmOperatorType *ot)
993 {
994         /* identifiers */
995         ot->name = "Make Parent";
996         ot->description = "Attach selected nodes";
997         ot->idname = "NODE_OT_parent_set";
998
999         /* api callbacks */
1000         ot->exec = node_parent_set_exec;
1001         ot->poll = ED_operator_node_active;
1002
1003         /* flags */
1004         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1005 }
1006
1007 /* ****************** Clear Parent ******************* */
1008
1009 static int node_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
1010 {
1011         SpaceNode *snode = CTX_wm_space_node(C);
1012         bNodeTree *ntree = snode->edittree;
1013         bNode *node;
1014
1015         for (node = ntree->nodes.first; node; node = node->next) {
1016                 if (node->flag & NODE_SELECT) {
1017                         nodeDetachNode(node);
1018                 }
1019         }
1020
1021         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1022
1023         return OPERATOR_FINISHED;
1024 }
1025
1026 void NODE_OT_parent_clear(wmOperatorType *ot)
1027 {
1028         /* identifiers */
1029         ot->name = "Clear Parent";
1030         ot->description = "Detach selected nodes";
1031         ot->idname = "NODE_OT_parent_clear";
1032
1033         /* api callbacks */
1034         ot->exec = node_parent_clear_exec;
1035         ot->poll = ED_operator_node_active;
1036
1037         /* flags */
1038         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1039 }
1040
1041 /* ****************** Join Nodes ******************* */
1042
1043 /* tags for depth-first search */
1044 #define NODE_JOIN_DONE          1
1045 #define NODE_JOIN_IS_DESCENDANT 2
1046
1047 static void node_join_attach_recursive(bNode *node, bNode *frame)
1048 {
1049         node->done |= NODE_JOIN_DONE;
1050
1051         if (node == frame) {
1052                 node->done |= NODE_JOIN_IS_DESCENDANT;
1053         }
1054         else if (node->parent) {
1055                 /* call recursively */
1056                 if (!(node->parent->done & NODE_JOIN_DONE))
1057                         node_join_attach_recursive(node->parent, frame);
1058
1059                 /* in any case: if the parent is a descendant, so is the child */
1060                 if (node->parent->done & NODE_JOIN_IS_DESCENDANT)
1061                         node->done |= NODE_JOIN_IS_DESCENDANT;
1062                 else if (node->flag & NODE_TEST) {
1063                         /* if parent is not an decendant of the frame, reattach the node */
1064                         nodeDetachNode(node);
1065                         nodeAttachNode(node, frame);
1066                         node->done |= NODE_JOIN_IS_DESCENDANT;
1067                 }
1068         }
1069         else if (node->flag & NODE_TEST) {
1070                 nodeAttachNode(node, frame);
1071                 node->done |= NODE_JOIN_IS_DESCENDANT;
1072         }
1073 }
1074
1075 static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
1076 {
1077         SpaceNode *snode = CTX_wm_space_node(C);
1078         Main *bmain = CTX_data_main(C);
1079         Scene *scene = CTX_data_scene(C);
1080         bNodeTree *ntree = snode->edittree;
1081         bNode *node, *frame;
1082         bNodeTemplate ntemp;
1083
1084         /* XXX save selection: node_add_node call below sets the new frame as single active+selected node */
1085         for (node = ntree->nodes.first; node; node = node->next) {
1086                 if (node->flag & NODE_SELECT)
1087                         node->flag |= NODE_TEST;
1088                 else
1089                         node->flag &= ~NODE_TEST;
1090         }
1091
1092         ntemp.main = bmain;
1093         ntemp.scene = scene;
1094         ntemp.type = NODE_FRAME;
1095         frame = node_add_node(snode, bmain, scene, &ntemp, 0.0f, 0.0f);
1096
1097         /* reset tags */
1098         for (node = ntree->nodes.first; node; node = node->next)
1099                 node->done = 0;
1100
1101         for (node = ntree->nodes.first; node; node = node->next) {
1102                 if (!(node->done & NODE_JOIN_DONE))
1103                         node_join_attach_recursive(node, frame);
1104         }
1105
1106         /* restore selection */
1107         for (node = ntree->nodes.first; node; node = node->next) {
1108                 if (node->flag & NODE_TEST)
1109                         node->flag |= NODE_SELECT;
1110         }
1111
1112         ED_node_sort(ntree);
1113         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1114
1115         return OPERATOR_FINISHED;
1116 }
1117
1118 void NODE_OT_join(wmOperatorType *ot)
1119 {
1120         /* identifiers */
1121         ot->name = "Join Nodes";
1122         ot->description = "Attach selected nodes to a new common frame";
1123         ot->idname = "NODE_OT_join";
1124
1125         /* api callbacks */
1126         ot->exec = node_join_exec;
1127         ot->poll = ED_operator_node_active;
1128
1129         /* flags */
1130         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1131 }
1132
1133 /* ****************** Attach ******************* */
1134
1135 static int node_attach_exec(bContext *C, wmOperator *UNUSED(op))
1136 {
1137         SpaceNode *snode = CTX_wm_space_node(C);
1138         bNodeTree *ntree = snode->edittree;
1139         bNode *frame;
1140
1141         /* check nodes front to back */
1142         for (frame = ntree->nodes.last; frame; frame = frame->prev) {
1143                 /* skip selected, those are the nodes we want to attach */
1144                 if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
1145                         continue;
1146                 if (BLI_rctf_isect_pt(&frame->totr, snode->cursor[0], snode->cursor[1]))
1147                         break;
1148         }
1149         if (frame) {
1150                 bNode *node, *parent;
1151                 for (node = ntree->nodes.last; node; node = node->prev) {
1152                         if (node->flag & NODE_SELECT) {
1153                                 if (node->parent == NULL) {
1154                                         /* disallow moving a parent into its child */
1155                                         if (nodeAttachNodeCheck(frame, node) == FALSE) {
1156                                                 /* attach all unparented nodes */
1157                                                 nodeAttachNode(node, frame);
1158                                         }
1159                                 }
1160                                 else {
1161                                         /* attach nodes which share parent with the frame */
1162                                         for (parent = frame->parent; parent; parent = parent->parent) {
1163                                                 if (parent == node->parent) {
1164                                                         break;
1165                                                 }
1166                                         }
1167
1168                                         if (parent) {
1169                                                 /* disallow moving a parent into its child */
1170                                                 if (nodeAttachNodeCheck(frame, node) == FALSE) {
1171                                                         nodeDetachNode(node);
1172                                                         nodeAttachNode(node, frame);
1173                                                 }
1174                                         }
1175                                 }
1176                         }
1177                 }
1178         }
1179
1180         ED_node_sort(ntree);
1181         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1182
1183         return OPERATOR_FINISHED;
1184 }
1185
1186 static int node_attach_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1187 {
1188         ARegion *ar = CTX_wm_region(C);
1189         SpaceNode *snode = CTX_wm_space_node(C);
1190
1191         /* convert mouse coordinates to v2d space */
1192         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
1193
1194         return node_attach_exec(C, op);
1195 }
1196
1197 void NODE_OT_attach(wmOperatorType *ot)
1198 {
1199         /* identifiers */
1200         ot->name = "Attach Nodes";
1201         ot->description = "Attach active node to a frame";
1202         ot->idname = "NODE_OT_attach";
1203
1204         /* api callbacks */
1205         ot->exec = node_attach_exec;
1206         ot->invoke = node_attach_invoke;
1207         ot->poll = ED_operator_node_active;
1208
1209         /* flags */
1210         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1211 }
1212
1213 /* ****************** Detach ******************* */
1214
1215 /* tags for depth-first search */
1216 #define NODE_DETACH_DONE            1
1217 #define NODE_DETACH_IS_DESCENDANT   2
1218
1219 static void node_detach_recursive(bNode *node)
1220 {
1221         node->done |= NODE_DETACH_DONE;
1222
1223         if (node->parent) {
1224                 /* call recursively */
1225                 if (!(node->parent->done & NODE_DETACH_DONE))
1226                         node_detach_recursive(node->parent);
1227
1228                 /* in any case: if the parent is a descendant, so is the child */
1229                 if (node->parent->done & NODE_DETACH_IS_DESCENDANT)
1230                         node->done |= NODE_DETACH_IS_DESCENDANT;
1231                 else if (node->flag & NODE_SELECT) {
1232                         /* if parent is not a decendant of a selected node, detach */
1233                         nodeDetachNode(node);
1234                         node->done |= NODE_DETACH_IS_DESCENDANT;
1235                 }
1236         }
1237         else if (node->flag & NODE_SELECT) {
1238                 node->done |= NODE_DETACH_IS_DESCENDANT;
1239         }
1240 }
1241
1242
1243 /* detach the root nodes in the current selection */
1244 static int node_detach_exec(bContext *C, wmOperator *UNUSED(op))
1245 {
1246         SpaceNode *snode = CTX_wm_space_node(C);
1247         bNodeTree *ntree = snode->edittree;
1248         bNode *node;
1249
1250         /* reset tags */
1251         for (node = ntree->nodes.first; node; node = node->next)
1252                 node->done = 0;
1253         /* detach nodes recursively
1254          * relative order is preserved here!
1255          */
1256         for (node = ntree->nodes.first; node; node = node->next) {
1257                 if (!(node->done & NODE_DETACH_DONE))
1258                         node_detach_recursive(node);
1259         }
1260
1261         ED_node_sort(ntree);
1262         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1263
1264         return OPERATOR_FINISHED;
1265 }
1266
1267 void NODE_OT_detach(wmOperatorType *ot)
1268 {
1269         /* identifiers */
1270         ot->name = "Detach Nodes";
1271         ot->description = "Detach selected nodes from parents";
1272         ot->idname = "NODE_OT_detach";
1273
1274         /* api callbacks */
1275         ot->exec = node_detach_exec;
1276         ot->poll = ED_operator_node_active;
1277
1278         /* flags */
1279         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1280 }
1281
1282 /* *********************  automatic node insert on dragging ******************* */
1283
1284
1285 /* prevent duplicate testing code below */
1286 static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select)
1287 {
1288         SpaceNode *snode = sa ? sa->spacedata.first : NULL;
1289         bNode *node;
1290         bNodeLink *link;
1291
1292         /* no unlucky accidents */
1293         if (sa == NULL || sa->spacetype != SPACE_NODE) return NULL;
1294
1295         *select = NULL;
1296
1297         for (node = snode->edittree->nodes.first; node; node = node->next) {
1298                 if (node->flag & SELECT) {
1299                         if (*select)
1300                                 break;
1301                         else
1302                                 *select = node;
1303                 }
1304         }
1305         /* only one selected */
1306         if (node || *select == NULL) return NULL;
1307
1308         /* correct node */
1309         if ((*select)->inputs.first == NULL || (*select)->outputs.first == NULL) return NULL;
1310
1311         /* test node for links */
1312         for (link = snode->edittree->links.first; link; link = link->next) {
1313                 if (link->tonode == *select || link->fromnode == *select)
1314                         return NULL;
1315         }
1316
1317         return snode;
1318 }
1319
1320 /* test == 0, clear all intersect flags */
1321 void ED_node_link_intersect_test(ScrArea *sa, int test)
1322 {
1323         bNode *select;
1324         SpaceNode *snode = ed_node_link_conditions(sa, &select);
1325         bNodeLink *link, *selink = NULL;
1326         float mcoords[6][2];
1327
1328         if (snode == NULL) return;
1329
1330         /* clear flags */
1331         for (link = snode->edittree->links.first; link; link = link->next)
1332                 link->flag &= ~NODE_LINKFLAG_HILITE;
1333
1334         if (test == 0) return;
1335
1336         /* okay, there's 1 node, without links, now intersect */
1337         mcoords[0][0] = select->totr.xmin;
1338         mcoords[0][1] = select->totr.ymin;
1339         mcoords[1][0] = select->totr.xmax;
1340         mcoords[1][1] = select->totr.ymin;
1341         mcoords[2][0] = select->totr.xmax;
1342         mcoords[2][1] = select->totr.ymax;
1343         mcoords[3][0] = select->totr.xmin;
1344         mcoords[3][1] = select->totr.ymax;
1345         mcoords[4][0] = select->totr.xmin;
1346         mcoords[4][1] = select->totr.ymin;
1347         mcoords[5][0] = select->totr.xmax;
1348         mcoords[5][1] = select->totr.ymax;
1349
1350         /* we only tag a single link for intersect now */
1351         /* idea; use header dist when more? */
1352         for (link = snode->edittree->links.first; link; link = link->next) {
1353
1354                 if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */
1355                         if (selink)
1356                                 break;
1357                         selink = link;
1358                 }
1359         }
1360
1361         if (link == NULL && selink)
1362                 selink->flag |= NODE_LINKFLAG_HILITE;
1363 }
1364
1365 /* assumes sockets in list */
1366 static bNodeSocket *socket_best_match(ListBase *sockets)
1367 {
1368         bNodeSocket *sock;
1369         int type, maxtype = 0;
1370
1371         /* find type range */
1372         for (sock = sockets->first; sock; sock = sock->next)
1373                 maxtype = max_ii(sock->type, maxtype);
1374
1375         /* try all types, starting from 'highest' (i.e. colors, vectors, values) */
1376         for (type = maxtype; type >= 0; --type) {
1377                 for (sock = sockets->first; sock; sock = sock->next) {
1378                         if (!nodeSocketIsHidden(sock) && type == sock->type) {
1379                                 return sock;
1380                         }
1381                 }
1382         }
1383
1384         /* no visible sockets, unhide first of highest type */
1385         for (type = maxtype; type >= 0; --type) {
1386                 for (sock = sockets->first; sock; sock = sock->next) {
1387                         if (type == sock->type) {
1388                                 sock->flag &= ~SOCK_HIDDEN;
1389                                 return sock;
1390                         }
1391                 }
1392         }
1393
1394         return NULL;
1395 }
1396
1397 /* assumes link with NODE_LINKFLAG_HILITE set */
1398 void ED_node_link_insert(ScrArea *sa)
1399 {
1400         bNode *node, *select;
1401         SpaceNode *snode = ed_node_link_conditions(sa, &select);
1402         bNodeLink *link;
1403         bNodeSocket *sockto;
1404
1405         if (snode == NULL) return;
1406
1407         /* get the link */
1408         for (link = snode->edittree->links.first; link; link = link->next)
1409                 if (link->flag & NODE_LINKFLAG_HILITE)
1410                         break;
1411
1412         if (link) {
1413                 node = link->tonode;
1414                 sockto = link->tosock;
1415
1416                 link->tonode = select;
1417                 link->tosock = socket_best_match(&select->inputs);
1418                 link->flag &= ~NODE_LINKFLAG_HILITE;
1419
1420                 nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto);
1421                 ntreeUpdateTree(snode->edittree);   /* needed for pointers */
1422                 snode_update(snode, select);
1423                 ED_node_changed_update(snode->id, select);
1424         }
1425 }