Merged changes in the trunk up to revision 51718.
[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, 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, 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                 for (link = snode->edittree->links.first; link; link = next) {
845                         next = link->next;
846
847                         if (cut_links_intersect(link, mcoords, i)) {
848
849                                 if (found == FALSE) {
850                                         ED_preview_kill_jobs(C);
851                                         found = TRUE;
852                                 }
853
854                                 snode_update(snode, link->tonode);
855                                 nodeRemLink(snode->edittree, link);
856                         }
857                 }
858
859                 if (found) {
860                         ntreeUpdateTree(snode->edittree);
861                         snode_notify(C, snode);
862                         snode_dag_update(C, snode);
863
864                         return OPERATOR_FINISHED;
865                 }
866                 else {
867                         return OPERATOR_CANCELLED;
868                 }
869
870         }
871
872         return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
873 }
874
875 void NODE_OT_links_cut(wmOperatorType *ot)
876 {
877         PropertyRNA *prop;
878
879         ot->name = "Cut links";
880         ot->idname = "NODE_OT_links_cut";
881         ot->description = "Use the mouse to cut (remove) some links";
882
883         ot->invoke = WM_gesture_lines_invoke;
884         ot->modal = WM_gesture_lines_modal;
885         ot->exec = cut_links_exec;
886         ot->cancel = WM_gesture_lines_cancel;
887
888         ot->poll = ED_operator_node_active;
889
890         /* flags */
891         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
892
893         prop = RNA_def_property(ot->srna, "path", PROP_COLLECTION, PROP_NONE);
894         RNA_def_property_struct_runtime(prop, &RNA_OperatorMousePath);
895         /* internal */
896         RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX);
897 }
898
899 /* ********************** Detach links operator ***************** */
900
901 static int detach_links_exec(bContext *C, wmOperator *UNUSED(op))
902 {
903         SpaceNode *snode = CTX_wm_space_node(C);
904         bNodeTree *ntree = snode->edittree;
905         bNode *node;
906
907         ED_preview_kill_jobs(C);
908
909         for (node = ntree->nodes.first; node; node = node->next) {
910                 if (node->flag & SELECT) {
911                         nodeInternalRelink(ntree, node);
912                 }
913         }
914
915         ntreeUpdateTree(ntree);
916
917         snode_notify(C, snode);
918         snode_dag_update(C, snode);
919
920         return OPERATOR_FINISHED;
921 }
922
923 void NODE_OT_links_detach(wmOperatorType *ot)
924 {
925         ot->name = "Detach Links";
926         ot->idname = "NODE_OT_links_detach";
927         ot->description = "Remove all links to selected nodes, and try to connect neighbor nodes together";
928
929         ot->exec = detach_links_exec;
930         ot->poll = ED_operator_node_active;
931
932         /* flags */
933         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
934 }
935
936
937 /* ****************** Show Cyclic Dependencies Operator  ******************* */
938
939 static int node_show_cycles_exec(bContext *C, wmOperator *UNUSED(op))
940 {
941         SpaceNode *snode = CTX_wm_space_node(C);
942
943         /* this is just a wrapper around this call... */
944         ntreeUpdateTree(snode->nodetree);
945         snode_notify(C, snode);
946
947         return OPERATOR_FINISHED;
948 }
949
950 void NODE_OT_show_cyclic_dependencies(wmOperatorType *ot)
951 {
952         /* identifiers */
953         ot->name = "Show Cyclic Dependencies";
954         ot->description = "Sort the nodes and show the cyclic dependencies between the nodes";
955         ot->idname = "NODE_OT_show_cyclic_dependencies";
956
957         /* callbacks */
958         ot->exec = node_show_cycles_exec;
959         ot->poll = ED_operator_node_active;
960
961         /* flags */
962         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
963 }
964
965 /* ****************** Set Parent ******************* */
966
967 static int node_parent_set_exec(bContext *C, wmOperator *UNUSED(op))
968 {
969         SpaceNode *snode = CTX_wm_space_node(C);
970         bNodeTree *ntree = snode->edittree;
971         bNode *frame = nodeGetActive(ntree), *node;
972         if (!frame || frame->type != NODE_FRAME)
973                 return OPERATOR_CANCELLED;
974
975         for (node = ntree->nodes.first; node; node = node->next) {
976                 if (node == frame)
977                         continue;
978                 if (node->flag & NODE_SELECT) {
979                         nodeDetachNode(node);
980                         nodeAttachNode(node, frame);
981                 }
982         }
983
984         ED_node_sort(ntree);
985         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
986
987         return OPERATOR_FINISHED;
988 }
989
990 void NODE_OT_parent_set(wmOperatorType *ot)
991 {
992         /* identifiers */
993         ot->name = "Make Parent";
994         ot->description = "Attach selected nodes";
995         ot->idname = "NODE_OT_parent_set";
996
997         /* api callbacks */
998         ot->exec = node_parent_set_exec;
999         ot->poll = ED_operator_node_active;
1000
1001         /* flags */
1002         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1003 }
1004
1005 /* ****************** Clear Parent ******************* */
1006
1007 static int node_parent_clear_exec(bContext *C, wmOperator *UNUSED(op))
1008 {
1009         SpaceNode *snode = CTX_wm_space_node(C);
1010         bNodeTree *ntree = snode->edittree;
1011         bNode *node;
1012
1013         for (node = ntree->nodes.first; node; node = node->next) {
1014                 if (node->flag & NODE_SELECT) {
1015                         nodeDetachNode(node);
1016                 }
1017         }
1018
1019         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1020
1021         return OPERATOR_FINISHED;
1022 }
1023
1024 void NODE_OT_parent_clear(wmOperatorType *ot)
1025 {
1026         /* identifiers */
1027         ot->name = "Clear Parent";
1028         ot->description = "Detach selected nodes";
1029         ot->idname = "NODE_OT_parent_clear";
1030
1031         /* api callbacks */
1032         ot->exec = node_parent_clear_exec;
1033         ot->poll = ED_operator_node_active;
1034
1035         /* flags */
1036         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1037 }
1038
1039 /* ****************** Join Nodes ******************* */
1040
1041 /* tags for depth-first search */
1042 #define NODE_JOIN_DONE          1
1043 #define NODE_JOIN_IS_DESCENDANT 2
1044
1045 static void node_join_attach_recursive(bNode *node, bNode *frame)
1046 {
1047         node->done |= NODE_JOIN_DONE;
1048
1049         if (node == frame) {
1050                 node->done |= NODE_JOIN_IS_DESCENDANT;
1051         }
1052         else if (node->parent) {
1053                 /* call recursively */
1054                 if (!(node->parent->done & NODE_JOIN_DONE))
1055                         node_join_attach_recursive(node->parent, frame);
1056
1057                 /* in any case: if the parent is a descendant, so is the child */
1058                 if (node->parent->done & NODE_JOIN_IS_DESCENDANT)
1059                         node->done |= NODE_JOIN_IS_DESCENDANT;
1060                 else if (node->flag & NODE_TEST) {
1061                         /* if parent is not an decendant of the frame, reattach the node */
1062                         nodeDetachNode(node);
1063                         nodeAttachNode(node, frame);
1064                         node->done |= NODE_JOIN_IS_DESCENDANT;
1065                 }
1066         }
1067         else if (node->flag & NODE_TEST) {
1068                 nodeAttachNode(node, frame);
1069                 node->done |= NODE_JOIN_IS_DESCENDANT;
1070         }
1071 }
1072
1073 static int node_join_exec(bContext *C, wmOperator *UNUSED(op))
1074 {
1075         SpaceNode *snode = CTX_wm_space_node(C);
1076         Main *bmain = CTX_data_main(C);
1077         Scene *scene = CTX_data_scene(C);
1078         bNodeTree *ntree = snode->edittree;
1079         bNode *node, *frame;
1080         bNodeTemplate ntemp;
1081
1082         /* XXX save selection: node_add_node call below sets the new frame as single active+selected node */
1083         for (node = ntree->nodes.first; node; node = node->next) {
1084                 if (node->flag & NODE_SELECT)
1085                         node->flag |= NODE_TEST;
1086                 else
1087                         node->flag &= ~NODE_TEST;
1088         }
1089
1090         ntemp.main = bmain;
1091         ntemp.scene = scene;
1092         ntemp.type = NODE_FRAME;
1093         frame = node_add_node(snode, bmain, scene, &ntemp, 0.0f, 0.0f);
1094
1095         /* reset tags */
1096         for (node = ntree->nodes.first; node; node = node->next)
1097                 node->done = 0;
1098
1099         for (node = ntree->nodes.first; node; node = node->next) {
1100                 if (!(node->done & NODE_JOIN_DONE))
1101                         node_join_attach_recursive(node, frame);
1102         }
1103
1104         /* restore selection */
1105         for (node = ntree->nodes.first; node; node = node->next) {
1106                 if (node->flag & NODE_TEST)
1107                         node->flag |= NODE_SELECT;
1108         }
1109
1110         ED_node_sort(ntree);
1111         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1112
1113         return OPERATOR_FINISHED;
1114 }
1115
1116 void NODE_OT_join(wmOperatorType *ot)
1117 {
1118         /* identifiers */
1119         ot->name = "Join Nodes";
1120         ot->description = "Attach selected nodes to a new common frame";
1121         ot->idname = "NODE_OT_join";
1122
1123         /* api callbacks */
1124         ot->exec = node_join_exec;
1125         ot->poll = ED_operator_node_active;
1126
1127         /* flags */
1128         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1129 }
1130
1131 /* ****************** Attach ******************* */
1132
1133 static int node_attach_exec(bContext *C, wmOperator *UNUSED(op))
1134 {
1135         SpaceNode *snode = CTX_wm_space_node(C);
1136         bNodeTree *ntree = snode->edittree;
1137         bNode *frame;
1138
1139         /* check nodes front to back */
1140         for (frame = ntree->nodes.last; frame; frame = frame->prev) {
1141                 /* skip selected, those are the nodes we want to attach */
1142                 if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT))
1143                         continue;
1144                 if (BLI_rctf_isect_pt(&frame->totr, snode->cursor[0], snode->cursor[1]))
1145                         break;
1146         }
1147         if (frame) {
1148                 bNode *node, *parent;
1149                 for (node = ntree->nodes.last; node; node = node->prev) {
1150                         if (node->flag & NODE_SELECT) {
1151                                 if (node->parent == NULL) {
1152                                         /* disallow moving a parent into its child */
1153                                         if (nodeAttachNodeCheck(frame, node) == FALSE) {
1154                                                 /* attach all unparented nodes */
1155                                                 nodeAttachNode(node, frame);
1156                                         }
1157                                 }
1158                                 else {
1159                                         /* attach nodes which share parent with the frame */
1160                                         for (parent = frame->parent; parent; parent = parent->parent) {
1161                                                 if (parent == node->parent) {
1162                                                         break;
1163                                                 }
1164                                         }
1165
1166                                         if (parent) {
1167                                                 /* disallow moving a parent into its child */
1168                                                 if (nodeAttachNodeCheck(frame, node) == FALSE) {
1169                                                         nodeDetachNode(node);
1170                                                         nodeAttachNode(node, frame);
1171                                                 }
1172                                         }
1173                                 }
1174                         }
1175                 }
1176         }
1177
1178         ED_node_sort(ntree);
1179         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1180
1181         return OPERATOR_FINISHED;
1182 }
1183
1184 static int node_attach_invoke(bContext *C, wmOperator *op, wmEvent *event)
1185 {
1186         ARegion *ar = CTX_wm_region(C);
1187         SpaceNode *snode = CTX_wm_space_node(C);
1188
1189         /* convert mouse coordinates to v2d space */
1190         UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]);
1191
1192         return node_attach_exec(C, op);
1193 }
1194
1195 void NODE_OT_attach(wmOperatorType *ot)
1196 {
1197         /* identifiers */
1198         ot->name = "Attach Nodes";
1199         ot->description = "Attach active node to a frame";
1200         ot->idname = "NODE_OT_attach";
1201
1202         /* api callbacks */
1203         ot->exec = node_attach_exec;
1204         ot->invoke = node_attach_invoke;
1205         ot->poll = ED_operator_node_active;
1206
1207         /* flags */
1208         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1209 }
1210
1211 /* ****************** Detach ******************* */
1212
1213 /* tags for depth-first search */
1214 #define NODE_DETACH_DONE            1
1215 #define NODE_DETACH_IS_DESCENDANT   2
1216
1217 static void node_detach_recursive(bNode *node)
1218 {
1219         node->done |= NODE_DETACH_DONE;
1220
1221         if (node->parent) {
1222                 /* call recursively */
1223                 if (!(node->parent->done & NODE_DETACH_DONE))
1224                         node_detach_recursive(node->parent);
1225
1226                 /* in any case: if the parent is a descendant, so is the child */
1227                 if (node->parent->done & NODE_DETACH_IS_DESCENDANT)
1228                         node->done |= NODE_DETACH_IS_DESCENDANT;
1229                 else if (node->flag & NODE_SELECT) {
1230                         /* if parent is not a decendant of a selected node, detach */
1231                         nodeDetachNode(node);
1232                         node->done |= NODE_DETACH_IS_DESCENDANT;
1233                 }
1234         }
1235         else if (node->flag & NODE_SELECT) {
1236                 node->done |= NODE_DETACH_IS_DESCENDANT;
1237         }
1238 }
1239
1240
1241 /* detach the root nodes in the current selection */
1242 static int node_detach_exec(bContext *C, wmOperator *UNUSED(op))
1243 {
1244         SpaceNode *snode = CTX_wm_space_node(C);
1245         bNodeTree *ntree = snode->edittree;
1246         bNode *node;
1247
1248         /* reset tags */
1249         for (node = ntree->nodes.first; node; node = node->next)
1250                 node->done = 0;
1251         /* detach nodes recursively
1252          * relative order is preserved here!
1253          */
1254         for (node = ntree->nodes.first; node; node = node->next) {
1255                 if (!(node->done & NODE_DETACH_DONE))
1256                         node_detach_recursive(node);
1257         }
1258
1259         ED_node_sort(ntree);
1260         WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
1261
1262         return OPERATOR_FINISHED;
1263 }
1264
1265 void NODE_OT_detach(wmOperatorType *ot)
1266 {
1267         /* identifiers */
1268         ot->name = "Detach Nodes";
1269         ot->description = "Detach selected nodes from parents";
1270         ot->idname = "NODE_OT_detach";
1271
1272         /* api callbacks */
1273         ot->exec = node_detach_exec;
1274         ot->poll = ED_operator_node_active;
1275
1276         /* flags */
1277         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1278 }
1279
1280 /* *********************  automatic node insert on dragging ******************* */
1281
1282
1283 /* prevent duplicate testing code below */
1284 static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select)
1285 {
1286         SpaceNode *snode = sa ? sa->spacedata.first : NULL;
1287         bNode *node;
1288         bNodeLink *link;
1289
1290         /* no unlucky accidents */
1291         if (sa == NULL || sa->spacetype != SPACE_NODE) return NULL;
1292
1293         *select = NULL;
1294
1295         for (node = snode->edittree->nodes.first; node; node = node->next) {
1296                 if (node->flag & SELECT) {
1297                         if (*select)
1298                                 break;
1299                         else
1300                                 *select = node;
1301                 }
1302         }
1303         /* only one selected */
1304         if (node || *select == NULL) return NULL;
1305
1306         /* correct node */
1307         if ((*select)->inputs.first == NULL || (*select)->outputs.first == NULL) return NULL;
1308
1309         /* test node for links */
1310         for (link = snode->edittree->links.first; link; link = link->next) {
1311                 if (link->tonode == *select || link->fromnode == *select)
1312                         return NULL;
1313         }
1314
1315         return snode;
1316 }
1317
1318 /* test == 0, clear all intersect flags */
1319 void ED_node_link_intersect_test(ScrArea *sa, int test)
1320 {
1321         bNode *select;
1322         SpaceNode *snode = ed_node_link_conditions(sa, &select);
1323         bNodeLink *link, *selink = NULL;
1324         float mcoords[6][2];
1325
1326         if (snode == NULL) return;
1327
1328         /* clear flags */
1329         for (link = snode->edittree->links.first; link; link = link->next)
1330                 link->flag &= ~NODE_LINKFLAG_HILITE;
1331
1332         if (test == 0) return;
1333
1334         /* okay, there's 1 node, without links, now intersect */
1335         mcoords[0][0] = select->totr.xmin;
1336         mcoords[0][1] = select->totr.ymin;
1337         mcoords[1][0] = select->totr.xmax;
1338         mcoords[1][1] = select->totr.ymin;
1339         mcoords[2][0] = select->totr.xmax;
1340         mcoords[2][1] = select->totr.ymax;
1341         mcoords[3][0] = select->totr.xmin;
1342         mcoords[3][1] = select->totr.ymax;
1343         mcoords[4][0] = select->totr.xmin;
1344         mcoords[4][1] = select->totr.ymin;
1345         mcoords[5][0] = select->totr.xmax;
1346         mcoords[5][1] = select->totr.ymax;
1347
1348         /* we only tag a single link for intersect now */
1349         /* idea; use header dist when more? */
1350         for (link = snode->edittree->links.first; link; link = link->next) {
1351
1352                 if (cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */
1353                         if (selink)
1354                                 break;
1355                         selink = link;
1356                 }
1357         }
1358
1359         if (link == NULL && selink)
1360                 selink->flag |= NODE_LINKFLAG_HILITE;
1361 }
1362
1363 /* assumes sockets in list */
1364 static bNodeSocket *socket_best_match(ListBase *sockets)
1365 {
1366         bNodeSocket *sock;
1367         int type, maxtype = 0;
1368
1369         /* find type range */
1370         for (sock = sockets->first; sock; sock = sock->next)
1371                 maxtype = max_ii(sock->type, maxtype);
1372
1373         /* try all types, starting from 'highest' (i.e. colors, vectors, values) */
1374         for (type = maxtype; type >= 0; --type) {
1375                 for (sock = sockets->first; sock; sock = sock->next) {
1376                         if (!nodeSocketIsHidden(sock) && type == sock->type) {
1377                                 return sock;
1378                         }
1379                 }
1380         }
1381
1382         /* no visible sockets, unhide first of highest type */
1383         for (type = maxtype; type >= 0; --type) {
1384                 for (sock = sockets->first; sock; sock = sock->next) {
1385                         if (type == sock->type) {
1386                                 sock->flag &= ~SOCK_HIDDEN;
1387                                 return sock;
1388                         }
1389                 }
1390         }
1391
1392         return NULL;
1393 }
1394
1395 /* assumes link with NODE_LINKFLAG_HILITE set */
1396 void ED_node_link_insert(ScrArea *sa)
1397 {
1398         bNode *node, *select;
1399         SpaceNode *snode = ed_node_link_conditions(sa, &select);
1400         bNodeLink *link;
1401         bNodeSocket *sockto;
1402
1403         if (snode == NULL) return;
1404
1405         /* get the link */
1406         for (link = snode->edittree->links.first; link; link = link->next)
1407                 if (link->flag & NODE_LINKFLAG_HILITE)
1408                         break;
1409
1410         if (link) {
1411                 node = link->tonode;
1412                 sockto = link->tosock;
1413
1414                 link->tonode = select;
1415                 link->tosock = socket_best_match(&select->inputs);
1416                 link->flag &= ~NODE_LINKFLAG_HILITE;
1417
1418                 nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto);
1419                 ntreeUpdateTree(snode->edittree);   /* needed for pointers */
1420                 snode_update(snode, select);
1421                 ED_node_changed_update(snode->id, select);
1422         }
1423 }