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