Cycles: svn merge -r41613:41627 ^/trunk/blender
[blender.git] / source / blender / editors / interface / interface_node.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * Contributor(s): Blender Foundation 2009.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/editors/interface/interface_node.c
26  *  \ingroup edinterface
27  */
28
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include <string.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_node_types.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_screen_types.h"
38
39 #include "BLI_listbase.h"
40 #include "BLI_string.h"
41 #include "BLI_utildefines.h"
42
43 #include "BKE_context.h"
44 #include "BKE_depsgraph.h"
45 #include "BKE_library.h"
46 #include "BKE_main.h"
47 #include "BKE_node.h"
48 #include "BKE_scene.h"
49
50 #include "RNA_access.h"
51
52 #include "WM_api.h"
53 #include "WM_types.h"
54
55 #include "UI_interface.h"
56 #include "interface_intern.h"
57
58 #include "ED_node.h"
59
60 /************************* Node Link Menu **************************/
61
62 #define UI_NODE_LINK_ADD                0
63 #define UI_NODE_LINK_DISCONNECT -1
64 #define UI_NODE_LINK_REMOVE             -2
65
66 typedef struct NodeLinkArg {
67         bNodeTree *ntree;
68         bNode *node;
69         bNodeSocket *sock;
70
71         bNodeTree *ngroup;
72         int type;
73         int output;
74 } NodeLinkArg;
75
76 static void ui_node_tag_recursive(bNode *node)
77 {
78         bNodeSocket *input;
79
80         if(!node || (node->flag & NODE_TEST))
81                 return; /* in case of cycles */
82         
83         node->flag |= NODE_TEST;
84
85         for(input=node->inputs.first; input; input=input->next)
86                 if(input->link)
87                         ui_node_tag_recursive(input->link->fromnode);
88 }
89
90 static void ui_node_clear_recursive(bNode *node)
91 {
92         bNodeSocket *input;
93
94         if(!node || !(node->flag & NODE_TEST))
95                 return; /* in case of cycles */
96         
97         node->flag &= ~NODE_TEST;
98
99         for(input=node->inputs.first; input; input=input->next)
100                 if(input->link)
101                         ui_node_clear_recursive(input->link->fromnode);
102 }
103
104 static void ui_node_remove_linked(bNodeTree *ntree, bNode *rem_node)
105 {
106         bNode *node, *next;
107         bNodeSocket *sock;
108
109         if(!rem_node)
110                 return;
111
112         /* tag linked nodes to be removed */
113         for(node=ntree->nodes.first; node; node=node->next)
114                 node->flag &= ~NODE_TEST;
115         
116         ui_node_tag_recursive(rem_node);
117
118         /* clear tags on nodes that are still used by other nodes */
119         for(node=ntree->nodes.first; node; node=node->next)
120                 if(!(node->flag & NODE_TEST))
121                         for(sock=node->inputs.first; sock; sock=sock->next)
122                                 if(sock->link && sock->link->fromnode != rem_node)
123                                         ui_node_clear_recursive(sock->link->fromnode);
124
125         /* remove nodes */
126         for(node=ntree->nodes.first; node; node=next) {
127                 next = node->next;
128
129                 if(node->flag & NODE_TEST) {
130                         if(node->id)
131                                 node->id->us--;
132                         nodeFreeNode(ntree, node);
133                 }
134         }
135         
136         //node_tree_verify_groups(ntree);
137 }
138
139 static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
140 {
141         if(sock->link && sock->link->fromnode) {
142                 bNode *node = sock->link->fromnode;
143                 char node_name[UI_MAX_NAME_STR];
144
145                 if(node->type == NODE_GROUP)
146                         BLI_strncpy(node_name, node->id->name+2, UI_MAX_NAME_STR);
147                 else
148                         BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
149
150                 if(node->inputs.first == NULL &&
151                    node->outputs.first != node->outputs.last &&
152                    !(node->typeinfo->flag & NODE_OPTIONS))
153                         BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", node_name, sock->link->fromsock->name);
154                 else
155                         BLI_strncpy(name, node_name, UI_MAX_NAME_STR);
156         }
157         else if(sock->type == SOCK_SHADER)
158                 BLI_strncpy(name, "None", UI_MAX_NAME_STR);
159         else
160                 BLI_strncpy(name, "Default", UI_MAX_NAME_STR);
161 }
162
163 static void ui_node_link(bContext *C, void *arg_p, void *event_p)
164 {
165         NodeLinkArg *arg = (NodeLinkArg*)arg_p;
166         bNode *node_to = arg->node;
167         bNodeSocket *sock_to = arg->sock;
168         bNodeTree *ntree = arg->ntree;
169         bNode *node_from;
170         bNodeSocket *sock_from;
171         int event = GET_INT_FROM_POINTER(event_p);
172
173         if(event == UI_NODE_LINK_DISCONNECT) {
174                 /* disconnect */
175                 if(sock_to->link)
176                         nodeRemLink(ntree, sock_to->link);
177         }
178         else if(event == UI_NODE_LINK_REMOVE) {
179                 /* remove */
180                 if(sock_to->link)
181                         ui_node_remove_linked(ntree, sock_to->link->fromnode);
182         }
183         else {
184                 bNode *node_prev = NULL;
185
186                 /* unlink existing node */
187                 if(sock_to->link) {
188                         node_prev = sock_to->link->fromnode;
189                         nodeRemLink(ntree, sock_to->link);
190                 }
191
192                 /* find existing node that we can use */
193                 for(node_from=ntree->nodes.first; node_from; node_from=node_from->next)
194                         if(node_from->type == arg->type)
195                                 break;
196
197                 if(node_from)
198                         if(!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
199                                 node_from = NULL;
200
201                 if(node_prev && node_prev->type == arg->type &&
202                         (arg->type != NODE_GROUP || node_prev->id == &arg->ngroup->id)) {
203                         /* keep the previous node if it's the same type */
204                         node_from = node_prev;
205                 }
206                 else if(!node_from) {
207                         bNodeTemplate ntemp;
208
209                         /* add new node */
210                         if(arg->ngroup) {
211                                 ntemp.type = NODE_GROUP;
212                                 ntemp.ngroup = arg->ngroup;
213                         }
214                         else
215                                 ntemp.type = arg->type;
216
217                         node_from= nodeAddNode(ntree, &ntemp);
218                         node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
219                         node_from->locy = node_to->locy;
220
221                         if(node_from->id)
222                                 id_us_plus(node_from->id);
223                 }
224
225                 nodeSetActive(ntree, node_from);
226
227                 /* add link */
228                 sock_from = BLI_findlink(&node_from->outputs, arg->output);
229                 nodeAddLink(ntree, node_from, sock_from, node_to, sock_to);
230
231                 /* copy input sockets from previous node */
232                 if(node_prev && node_from != node_prev) {
233                         bNodeSocket *sock_prev, *sock_from;
234
235                         for(sock_prev=node_prev->inputs.first; sock_prev; sock_prev=sock_prev->next) {
236                                 for(sock_from=node_from->inputs.first; sock_from; sock_from=sock_from->next) {
237                                         if(strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
238                                                 bNodeLink *link = sock_prev->link;
239
240                                                 if(link && link->fromnode) {
241                                                         nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from);
242                                                         nodeRemLink(ntree, link);
243                                                 }
244
245                                                 if(sock_prev->default_value) {
246                                                         if(sock_from->default_value)
247                                                                 MEM_freeN(sock_from->default_value);
248
249                                                         sock_from->default_value = MEM_dupallocN(sock_prev->default_value);
250                                                 }
251                                         }
252                                 }
253                         }
254
255                         /* also preserve mapping for texture nodes */
256                         if(node_from->typeinfo->nclass == NODE_CLASS_TEXTURE &&
257                            node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE)
258                                 memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase));
259
260                         /* remove node */
261                         ui_node_remove_linked(ntree, node_prev);
262                 }
263
264                 nodeUpdate(ntree, node_from);
265         }
266
267         nodeUpdate(ntree, node_to);
268         ntreeUpdateTree(ntree);
269
270         ED_node_generic_update(CTX_data_main(C), ntree, node_to);
271 }
272
273 static int ui_compatible_sockets(int typeA, int typeB)
274 {
275         if(typeA == SOCK_SHADER || typeB == SOCK_SHADER)
276                 return (typeA == typeB);
277         
278         return (typeA == typeB);
279 }
280
281 static void ui_node_menu_column(Main *bmain, NodeLinkArg *arg, uiLayout *layout, const char *cname, int nclass, int compatibility)
282 {
283         bNodeTree *ntree = arg->ntree;
284         bNodeSocket *sock = arg->sock;
285         uiLayout *column = NULL;
286         uiBlock *block = uiLayoutGetBlock(layout);
287         uiBut *but;
288         bNodeType *ntype;
289         bNodeTree *ngroup;
290         NodeLinkArg *argN;
291         int first = 1;
292
293         if(nclass == NODE_CLASS_GROUP) {
294                 for(ngroup=bmain->nodetree.first; ngroup; ngroup=ngroup->id.next) {
295                         bNodeSocket *gsock;
296                         char name[UI_MAX_NAME_STR];
297                         int i, j, num = 0;
298
299                         if(ngroup->type != ntree->type)
300                                 continue;
301
302                         for(gsock=ngroup->inputs.first; gsock; gsock=gsock->next)
303                                 if(ui_compatible_sockets(gsock->type, sock->type))
304                                         num++;
305
306                         for(i=0, j=0, gsock=ngroup->outputs.first; gsock; gsock=gsock->next, i++) {
307                                 if(!ui_compatible_sockets(gsock->type, sock->type))
308                                         continue;
309
310                                 if(first) {
311                                         column= uiLayoutColumn(layout, 0);
312                                         uiBlockSetCurLayout(block, column);
313
314                                         uiItemL(column, cname, ICON_NONE);
315                                         but= block->buttons.last;
316                                         but->flag= UI_TEXT_LEFT;
317
318                                         first = 0;
319                                 }
320
321                                 if(num > 1) {
322                                         if(j == 0) {
323                                                 uiItemL(column, ngroup->id.name+2, ICON_NONE);
324                                                 but= block->buttons.last;
325                                                 but->flag= UI_TEXT_LEFT;
326                                         }
327
328                                         BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", gsock->name);
329                                         j++;
330                                 }
331                                 else
332                                         BLI_strncpy(name, ngroup->id.name+2, UI_MAX_NAME_STR);
333
334                                 but = uiDefBut(block, BUT, 0, ngroup->id.name+2, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
335                                         NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input");
336
337                                 argN = MEM_dupallocN(arg);
338                                 argN->ngroup = ngroup;
339                                 argN->output = i;
340                                 uiButSetNFunc(but, ui_node_link, argN, NULL);
341                         }
342                 }
343         }
344         else {
345                 bNodeTreeType *ttype= ntreeGetType(ntree->type);
346
347                 for(ntype=ttype->node_types.first; ntype; ntype=ntype->next) {
348                         bNodeSocketTemplate *stemp;
349                         char name[UI_MAX_NAME_STR];
350                         int i, j, num = 0;
351
352                         if(compatibility && !(ntype->compatibility & compatibility))
353                                 continue;
354
355                         if(ntype->nclass != nclass)
356                                 continue;
357
358                         for(i=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
359                                 if(ui_compatible_sockets(stemp->type, sock->type))
360                                         num++;
361
362                         for(i=0, j=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
363                                 if(!ui_compatible_sockets(stemp->type, sock->type))
364                                         continue;
365
366                                 if(first) {
367                                         column= uiLayoutColumn(layout, 0);
368                                         uiBlockSetCurLayout(block, column);
369
370                                         uiItemL(column, cname, ICON_NONE);
371                                         but= block->buttons.last;
372                                         but->flag= UI_TEXT_LEFT;
373
374                                         first = 0;
375                                 }
376
377                                 if(num > 1) {
378                                         if(j == 0) {
379                                                 uiItemL(column, ntype->name, ICON_NONE);
380                                                 but= block->buttons.last;
381                                                 but->flag= UI_TEXT_LEFT;
382                                         }
383
384                                         BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", stemp->name);
385                                         j++;
386                                 }
387                                 else
388                                         BLI_strncpy(name, ntype->name, UI_MAX_NAME_STR);
389
390                                 but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
391                                         NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input");
392
393                                 argN = MEM_dupallocN(arg);
394                                 argN->type = ntype->type;
395                                 argN->output = i;
396                                 uiButSetNFunc(but, ui_node_link, argN, NULL);
397                         }
398                 }
399         }
400 }
401
402 static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_p)
403 {
404         Main *bmain= CTX_data_main(C);
405         Scene *scene= CTX_data_scene(C);
406         uiBlock *block = uiLayoutGetBlock(layout);
407         uiBut *but = (uiBut*)but_p;
408         uiLayout *split, *column;
409         NodeLinkArg *arg = (NodeLinkArg*)but->func_argN;
410         bNodeSocket *sock = arg->sock;
411         int compatibility= 0;
412
413         if(arg->ntree->type == NTREE_SHADER) {
414                 if(scene_use_new_shading_nodes(scene))
415                         compatibility= NODE_NEW_SHADING;
416                 else
417                         compatibility= NODE_OLD_SHADING;
418         }
419         
420         uiBlockSetCurLayout(block, layout);
421         split= uiLayoutSplit(layout, 0, 0);
422
423         ui_node_menu_column(bmain, arg, split, "Input", NODE_CLASS_INPUT, compatibility);
424         ui_node_menu_column(bmain, arg, split, "Output", NODE_CLASS_OUTPUT, compatibility);
425         ui_node_menu_column(bmain, arg, split, "Shader", NODE_CLASS_SHADER, compatibility);
426         ui_node_menu_column(bmain, arg, split, "Texture", NODE_CLASS_TEXTURE, compatibility);
427         ui_node_menu_column(bmain, arg, split, "Color", NODE_CLASS_OP_COLOR, compatibility);
428         ui_node_menu_column(bmain, arg, split, "Vector", NODE_CLASS_OP_VECTOR, compatibility);
429         ui_node_menu_column(bmain, arg, split, "Convertor", NODE_CLASS_CONVERTOR, compatibility);
430
431         column= uiLayoutColumn(split, 0);
432         uiBlockSetCurLayout(block, column);
433
434         if(sock->link) {
435                 uiItemL(column, "Link", ICON_NONE);
436                 but= block->buttons.last;
437                 but->flag= UI_TEXT_LEFT;
438
439                 but = uiDefBut(block, BUT, 0, "Remove", 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
440                         NULL, 0.0, 0.0, 0.0, 0.0, "Remove nodes connected to the input");
441                 uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE));
442
443                 but = uiDefBut(block, BUT, 0, "Disconnect", 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
444                         NULL, 0.0, 0.0, 0.0, 0.0, "Disconnect nodes connected to the input");
445                 uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT));
446         }
447
448         ui_node_menu_column(bmain, arg, column, "Group", NODE_CLASS_GROUP, compatibility);
449 }
450
451 void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
452 {
453         uiBlock *block = uiLayoutGetBlock(layout);
454         NodeLinkArg *arg;
455         uiBut *but;
456
457         arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg");
458         arg->ntree = ntree;
459         arg->node = node;
460         arg->sock = sock;
461         arg->type = 0;
462         arg->output = 0;
463
464         uiBlockSetCurLayout(block, layout);
465
466         if(sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
467                 char name[UI_MAX_NAME_STR];
468                 ui_node_sock_name(sock, name);
469                 but= uiDefMenuBut(block, ui_template_node_link_menu, NULL, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, "");
470         }
471         else
472                 but= uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
473
474         but->type= MENU;
475         but->flag |= UI_TEXT_LEFT|UI_BUT_NODE_LINK;
476         but->poin= (char*)but;
477         but->func_argN = arg;
478
479         if(sock->link && sock->link->fromnode)
480                 if(sock->link->fromnode->flag & NODE_ACTIVE_TEXTURE)
481                         but->flag |= UI_BUT_NODE_ACTIVE;
482 }
483
484 /************************* Node Tree Layout **************************/
485
486 static void ui_node_draw_input(uiLayout *layout, bContext *C,
487         bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth);
488
489 static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth)
490 {
491         bNodeSocket *input;
492         uiLayout *col, *split;
493         PointerRNA nodeptr;
494
495         RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
496
497         if(node->typeinfo->uifunc) {
498                 if(node->type != NODE_GROUP) {
499                         split = uiLayoutSplit(layout, 0.35f, 0);
500                         col = uiLayoutColumn(split, 0);
501                         col = uiLayoutColumn(split, 0);
502
503                         node->typeinfo->uifunc(col, C, &nodeptr);
504                 }
505         }
506
507         for(input=node->inputs.first; input; input=input->next)
508                 ui_node_draw_input(layout, C, ntree, node, input, depth+1);
509 }
510
511 static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
512 {
513         PointerRNA inputptr;
514         uiBlock *block = uiLayoutGetBlock(layout);
515         uiBut *bt;
516         uiLayout *split, *row, *col;
517         bNode *lnode;
518         char label[UI_MAX_NAME_STR];
519         int indent = (depth > 1)? 2*(depth - 1): 0;
520
521         /* to avoid eternal loops on cyclic dependencies */
522         node->flag |= NODE_TEST;
523         lnode = (input->link)? input->link->fromnode: NULL;
524
525         /* socket RNA pointer */
526         RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
527
528         /* indented label */
529         memset(label, ' ', indent);
530         label[indent] = '\0';
531         BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, input->name);
532
533         /* split in label and value */
534         split = uiLayoutSplit(layout, 0.35f, 0);
535
536         row = uiLayoutRow(split, 1);
537
538         if(depth > 0) {
539                 uiBlockSetEmboss(block, UI_EMBOSSN);
540
541                 if(lnode && (lnode->inputs.first || (lnode->typeinfo->uifunc && lnode->type != NODE_GROUP))) {
542                         int icon = (input->flag & SOCK_COLLAPSED)? ICON_DISCLOSURE_TRI_RIGHT: ICON_DISCLOSURE_TRI_DOWN;
543                         uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
544                 }
545                 else
546                         uiItemL(row, "", ICON_BLANK1);
547
548                 bt = block->buttons.last;
549                 bt->x2 = UI_UNIT_X/2;
550
551                 uiBlockSetEmboss(block, UI_EMBOSS);
552         }
553
554         uiItemL(row, label, ICON_NONE);
555
556         if(lnode) {
557                 /* input linked to a node */
558                 uiTemplateNodeLink(split, ntree, node, input);
559
560                 if(!(input->flag & SOCK_COLLAPSED)) {
561                         if(depth == 0)
562                                 uiItemS(layout);
563
564                         ui_node_draw_node(layout, C, ntree, lnode, depth);
565                 }
566         }
567         else {
568                 /* input not linked, show value */
569                 if(input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) {
570                         if(input->type == SOCK_VECTOR) {
571                                 row = uiLayoutRow(split, 0);
572                                 col = uiLayoutColumn(row, 0);
573
574                                 uiItemR(col, &inputptr, "default_value", 0, "", 0);
575                         }
576                         else {
577                                 row = uiLayoutRow(split, 1);
578                                 uiItemR(row, &inputptr, "default_value", 0, "", 0);
579                         }
580                 }
581                 else
582                         row = uiLayoutRow(split, 0);
583
584                 uiTemplateNodeLink(row, ntree, node, input);
585         }
586
587         /* clear */
588         node->flag &= ~NODE_TEST;
589 }
590
591 void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input)
592 {
593         bNode *tnode;
594
595         if(!ntree)
596                 return;
597
598         /* clear for cycle check */
599         for(tnode=ntree->nodes.first; tnode; tnode=tnode->next)
600                 tnode->flag &= ~NODE_TEST;
601
602         if(input)
603                 ui_node_draw_input(layout, C, ntree, node, input, 0);
604         else
605                 ui_node_draw_node(layout, C, ntree, node, 0);
606 }
607