Cycles: svn merge -r41627:41650 ^/trunk/blender
[blender.git] / source / blender / editors / space_node / node_templates.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 "UI_resources.h"
57 #include "../interface/interface_intern.h"
58
59 #include "ED_node.h"
60
61 /************************* Node Socket Manipulation **************************/
62
63 static void node_tag_recursive(bNode *node)
64 {
65         bNodeSocket *input;
66
67         if(!node || (node->flag & NODE_TEST))
68                 return; /* in case of cycles */
69         
70         node->flag |= NODE_TEST;
71
72         for(input=node->inputs.first; input; input=input->next)
73                 if(input->link)
74                         node_tag_recursive(input->link->fromnode);
75 }
76
77 static void node_clear_recursive(bNode *node)
78 {
79         bNodeSocket *input;
80
81         if(!node || !(node->flag & NODE_TEST))
82                 return; /* in case of cycles */
83         
84         node->flag &= ~NODE_TEST;
85
86         for(input=node->inputs.first; input; input=input->next)
87                 if(input->link)
88                         node_clear_recursive(input->link->fromnode);
89 }
90
91 static void node_remove_linked(bNodeTree *ntree, bNode *rem_node)
92 {
93         bNode *node, *next;
94         bNodeSocket *sock;
95
96         if(!rem_node)
97                 return;
98
99         /* tag linked nodes to be removed */
100         for(node=ntree->nodes.first; node; node=node->next)
101                 node->flag &= ~NODE_TEST;
102         
103         node_tag_recursive(rem_node);
104
105         /* clear tags on nodes that are still used by other nodes */
106         for(node=ntree->nodes.first; node; node=node->next)
107                 if(!(node->flag & NODE_TEST))
108                         for(sock=node->inputs.first; sock; sock=sock->next)
109                                 if(sock->link && sock->link->fromnode != rem_node)
110                                         node_clear_recursive(sock->link->fromnode);
111
112         /* remove nodes */
113         for(node=ntree->nodes.first; node; node=next) {
114                 next = node->next;
115
116                 if(node->flag & NODE_TEST) {
117                         if(node->id)
118                                 node->id->us--;
119                         nodeFreeNode(ntree, node);
120                 }
121         }
122 }
123
124 /* disconnect socket from the node it is connected to */
125 static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
126 {
127         if(!sock_to->link)
128                 return;
129
130         nodeRemLink(ntree, sock_to->link);
131
132         nodeUpdate(ntree, node_to);
133         ntreeUpdateTree(ntree);
134
135         ED_node_generic_update(bmain, ntree, node_to);
136 }
137
138 /* remove all nodes connected to this socket, if they aren't connected to other nodes */
139 static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to)
140 {
141         if(!sock_to->link)
142                 return;
143
144         node_remove_linked(ntree, sock_to->link->fromnode);
145
146         nodeUpdate(ntree, node_to);
147         ntreeUpdateTree(ntree);
148
149         ED_node_generic_update(bmain, ntree, node_to);
150 }
151
152 /* add new node connected to this socket, or replace an existing one */
153 static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num)
154 {
155         bNode *node_from;
156         bNodeSocket *sock_from;
157         bNode *node_prev = NULL;
158
159         /* unlink existing node */
160         if(sock_to->link) {
161                 node_prev = sock_to->link->fromnode;
162                 nodeRemLink(ntree, sock_to->link);
163         }
164
165         /* find existing node that we can use */
166         for(node_from=ntree->nodes.first; node_from; node_from=node_from->next)
167                 if(node_from->type == ntemp->type)
168                         break;
169
170         if(node_from)
171                 if(!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS)))
172                         node_from = NULL;
173
174         if(node_prev && node_prev->type == ntemp->type &&
175                 (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id)) {
176                 /* keep the previous node if it's the same type */
177                 node_from = node_prev;
178         }
179         else if(!node_from) {
180                 node_from= nodeAddNode(ntree, ntemp);
181                 node_from->locx = node_to->locx - (node_from->typeinfo->width + 50);
182                 node_from->locy = node_to->locy;
183
184                 if(node_from->id)
185                         id_us_plus(node_from->id);
186         }
187
188         nodeSetActive(ntree, node_from);
189
190         /* add link */
191         sock_from = BLI_findlink(&node_from->outputs, sock_num);
192         nodeAddLink(ntree, node_from, sock_from, node_to, sock_to);
193
194         /* copy input sockets from previous node */
195         if(node_prev && node_from != node_prev) {
196                 bNodeSocket *sock_prev, *sock_from;
197
198                 for(sock_prev=node_prev->inputs.first; sock_prev; sock_prev=sock_prev->next) {
199                         for(sock_from=node_from->inputs.first; sock_from; sock_from=sock_from->next) {
200                                 if(strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) {
201                                         bNodeLink *link = sock_prev->link;
202
203                                         if(link && link->fromnode) {
204                                                 nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from);
205                                                 nodeRemLink(ntree, link);
206                                         }
207
208                                         if(sock_prev->default_value) {
209                                                 if(sock_from->default_value)
210                                                         MEM_freeN(sock_from->default_value);
211
212                                                 sock_from->default_value = MEM_dupallocN(sock_prev->default_value);
213                                         }
214                                 }
215                         }
216                 }
217
218                 /* also preserve mapping for texture nodes */
219                 if(node_from->typeinfo->nclass == NODE_CLASS_TEXTURE &&
220                    node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE)
221                         memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase));
222
223                 /* remove node */
224                 node_remove_linked(ntree, node_prev);
225         }
226
227         nodeUpdate(ntree, node_from);
228         nodeUpdate(ntree, node_to);
229         ntreeUpdateTree(ntree);
230
231         ED_node_generic_update(bmain, ntree, node_to);
232 }
233
234 /****************************** Node Link Menu *******************************/
235
236 #define UI_NODE_LINK_ADD                0
237 #define UI_NODE_LINK_DISCONNECT -1
238 #define UI_NODE_LINK_REMOVE             -2
239
240 typedef struct NodeLinkArg {
241         Main *bmain;
242         Scene *scene;
243         bNodeTree *ntree;
244         bNode *node;
245         bNodeSocket *sock;
246
247         bNodeTree *ngroup;
248         int type;
249         int output;
250
251         uiLayout *layout;
252 } NodeLinkArg;
253
254 static void ui_node_link(bContext *UNUSED(C), void *arg_p, void *event_p)
255 {
256         NodeLinkArg *arg = (NodeLinkArg*)arg_p;
257         Main *bmain = arg->bmain;
258         bNode *node_to = arg->node;
259         bNodeSocket *sock_to = arg->sock;
260         bNodeTree *ntree = arg->ntree;
261         int event = GET_INT_FROM_POINTER(event_p);
262         bNodeTemplate ntemp;
263
264         ntemp.type = arg->type;
265         ntemp.ngroup = arg->ngroup;
266
267         if(event == UI_NODE_LINK_DISCONNECT)
268                 node_socket_disconnect(bmain, ntree, node_to, sock_to);
269         else if(event == UI_NODE_LINK_REMOVE)
270                 node_socket_remove(bmain, ntree, node_to, sock_to);
271         else
272                 node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output);
273 }
274
275 static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR])
276 {
277         if(sock->link && sock->link->fromnode) {
278                 bNode *node = sock->link->fromnode;
279                 char node_name[UI_MAX_NAME_STR];
280
281                 if(node->type == NODE_GROUP)
282                         BLI_strncpy(node_name, node->id->name+2, UI_MAX_NAME_STR);
283                 else
284                         BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR);
285
286                 if(node->inputs.first == NULL &&
287                    node->outputs.first != node->outputs.last &&
288                    !(node->typeinfo->flag & NODE_OPTIONS))
289                         BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", node_name, sock->link->fromsock->name);
290                 else
291                         BLI_strncpy(name, node_name, UI_MAX_NAME_STR);
292         }
293         else if(sock->type == SOCK_SHADER)
294                 BLI_strncpy(name, "None", UI_MAX_NAME_STR);
295         else
296                 BLI_strncpy(name, "Default", UI_MAX_NAME_STR);
297 }
298
299 static int ui_compatible_sockets(int typeA, int typeB)
300 {
301         return (typeA == typeB);
302 }
303
304 static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname)
305 {
306         Main *bmain = arg->bmain;
307         bNodeTree *ntree = arg->ntree;
308         bNodeSocket *sock = arg->sock;
309         uiLayout *layout = arg->layout;
310         uiLayout *column = NULL;
311         uiBlock *block = uiLayoutGetBlock(layout);
312         uiBut *but;
313         bNodeType *ntype;
314         bNodeTree *ngroup;
315         NodeLinkArg *argN;
316         int first = 1;
317         int compatibility= 0;
318
319         if(ntree->type == NTREE_SHADER) {
320                 if(scene_use_new_shading_nodes(arg->scene))
321                         compatibility= NODE_NEW_SHADING;
322                 else
323                         compatibility= NODE_OLD_SHADING;
324         }
325
326         if(nclass == NODE_CLASS_GROUP) {
327                 for(ngroup=bmain->nodetree.first; ngroup; ngroup=ngroup->id.next) {
328                         bNodeSocket *gsock;
329                         char name[UI_MAX_NAME_STR];
330                         int i, j, num = 0;
331
332                         if(ngroup->type != ntree->type)
333                                 continue;
334
335                         for(gsock=ngroup->inputs.first; gsock; gsock=gsock->next)
336                                 if(ui_compatible_sockets(gsock->type, sock->type))
337                                         num++;
338
339                         for(i=0, j=0, gsock=ngroup->outputs.first; gsock; gsock=gsock->next, i++) {
340                                 if(!ui_compatible_sockets(gsock->type, sock->type))
341                                         continue;
342
343                                 if(first) {
344                                         column= uiLayoutColumn(layout, 0);
345                                         uiBlockSetCurLayout(block, column);
346
347                                         uiItemL(column, cname, ICON_NODE);
348                                         but= block->buttons.last;
349                                         but->flag= UI_TEXT_LEFT;
350
351                                         first = 0;
352                                 }
353
354                                 if(num > 1) {
355                                         if(j == 0) {
356                                                 uiItemL(column, ngroup->id.name+2, ICON_NODE);
357                                                 but= block->buttons.last;
358                                                 but->flag= UI_TEXT_LEFT;
359                                         }
360
361                                         BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", gsock->name);
362                                         j++;
363                                 }
364                                 else
365                                         BLI_strncpy(name, ngroup->id.name+2, UI_MAX_NAME_STR);
366
367                                 but = uiDefBut(block, BUT, 0, ngroup->id.name+2, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
368                                         NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input");
369
370                                 argN = MEM_dupallocN(arg);
371                                 argN->ngroup = ngroup;
372                                 argN->output = i;
373                                 uiButSetNFunc(but, ui_node_link, argN, NULL);
374                         }
375                 }
376         }
377         else {
378                 bNodeTreeType *ttype= ntreeGetType(ntree->type);
379
380                 for(ntype=ttype->node_types.first; ntype; ntype=ntype->next) {
381                         bNodeSocketTemplate *stemp;
382                         char name[UI_MAX_NAME_STR];
383                         int i, j, num = 0;
384
385                         if(compatibility && !(ntype->compatibility & compatibility))
386                                 continue;
387
388                         if(ntype->nclass != nclass)
389                                 continue;
390
391                         for(i=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++)
392                                 if(ui_compatible_sockets(stemp->type, sock->type))
393                                         num++;
394
395                         for(i=0, j=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++) {
396                                 if(!ui_compatible_sockets(stemp->type, sock->type))
397                                         continue;
398
399                                 if(first) {
400                                         column= uiLayoutColumn(layout, 0);
401                                         uiBlockSetCurLayout(block, column);
402
403                                         uiItemL(column, cname, ICON_NODE);
404                                         but= block->buttons.last;
405                                         but->flag= UI_TEXT_LEFT;
406
407                                         first = 0;
408                                 }
409
410                                 if(num > 1) {
411                                         if(j == 0) {
412                                                 uiItemL(column, ntype->name, ICON_NODE);
413                                                 but= block->buttons.last;
414                                                 but->flag= UI_TEXT_LEFT;
415                                         }
416
417                                         BLI_snprintf(name, UI_MAX_NAME_STR, "  %s", stemp->name);
418                                         j++;
419                                 }
420                                 else
421                                         BLI_strncpy(name, ntype->name, UI_MAX_NAME_STR);
422
423                                 but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
424                                         NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input");
425
426                                 argN = MEM_dupallocN(arg);
427                                 argN->type = ntype->type;
428                                 argN->output = i;
429                                 uiButSetNFunc(but, ui_node_link, argN, NULL);
430                         }
431                 }
432         }
433 }
434
435 static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name)
436 {
437         NodeLinkArg *arg = (NodeLinkArg*)calldata;
438
439         if(!ELEM(nclass, NODE_CLASS_GROUP, NODE_CLASS_LAYOUT))
440                 ui_node_menu_column(arg, nclass, name);
441 }
442
443 static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_p)
444 {
445         Main *bmain= CTX_data_main(C);
446         Scene *scene= CTX_data_scene(C);
447         uiBlock *block = uiLayoutGetBlock(layout);
448         uiBut *but = (uiBut*)but_p;
449         uiLayout *split, *column;
450         NodeLinkArg *arg = (NodeLinkArg*)but->func_argN;
451         bNodeSocket *sock = arg->sock;
452         bNodeTreeType *ntreetype= ntreeGetType(arg->ntree->type);
453
454         uiBlockSetCurLayout(block, layout);
455         split= uiLayoutSplit(layout, 0, 0);
456
457         arg->bmain= bmain;
458         arg->scene= scene;
459         arg->layout= split;
460         
461         if(ntreetype && ntreetype->foreach_nodeclass)
462                 ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb);
463
464         column= uiLayoutColumn(split, 0);
465         uiBlockSetCurLayout(block, column);
466
467         if(sock->link) {
468                 uiItemL(column, "Link", ICON_NONE);
469                 but= block->buttons.last;
470                 but->flag= UI_TEXT_LEFT;
471
472                 but = uiDefBut(block, BUT, 0, "Remove", 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
473                         NULL, 0.0, 0.0, 0.0, 0.0, "Remove nodes connected to the input");
474                 uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE));
475
476                 but = uiDefBut(block, BUT, 0, "Disconnect", 0, 0, UI_UNIT_X*4, UI_UNIT_Y,
477                         NULL, 0.0, 0.0, 0.0, 0.0, "Disconnect nodes connected to the input");
478                 uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT));
479         }
480
481         ui_node_menu_column(arg, NODE_CLASS_GROUP, IFACE_("Group"));
482 }
483
484 void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock)
485 {
486         uiBlock *block = uiLayoutGetBlock(layout);
487         NodeLinkArg *arg;
488         uiBut *but;
489
490         arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg");
491         arg->ntree = ntree;
492         arg->node = node;
493         arg->sock = sock;
494         arg->type = 0;
495         arg->output = 0;
496
497         uiBlockSetCurLayout(block, layout);
498
499         if(sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) {
500                 char name[UI_MAX_NAME_STR];
501                 ui_node_sock_name(sock, name);
502                 but= uiDefMenuBut(block, ui_template_node_link_menu, NULL, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, "");
503         }
504         else
505                 but= uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, "");
506
507         but->type= MENU;
508         but->flag |= UI_TEXT_LEFT|UI_BUT_NODE_LINK;
509         but->poin= (char*)but;
510         but->func_argN = arg;
511
512         if(sock->link && sock->link->fromnode)
513                 if(sock->link->fromnode->flag & NODE_ACTIVE_TEXTURE)
514                         but->flag |= UI_BUT_NODE_ACTIVE;
515 }
516
517 /**************************** Node Tree Layout *******************************/
518
519 static void ui_node_draw_input(uiLayout *layout, bContext *C,
520         bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth);
521
522 static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth)
523 {
524         bNodeSocket *input;
525         uiLayout *col, *split;
526         PointerRNA nodeptr;
527
528         RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
529
530         if(node->typeinfo->uifunc) {
531                 if(node->type != NODE_GROUP) {
532                         split = uiLayoutSplit(layout, 0.35f, 0);
533                         col = uiLayoutColumn(split, 0);
534                         col = uiLayoutColumn(split, 0);
535
536                         node->typeinfo->uifunc(col, C, &nodeptr);
537                 }
538         }
539
540         for(input=node->inputs.first; input; input=input->next)
541                 ui_node_draw_input(layout, C, ntree, node, input, depth+1);
542 }
543
544 static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth)
545 {
546         PointerRNA inputptr;
547         uiBlock *block = uiLayoutGetBlock(layout);
548         uiBut *bt;
549         uiLayout *split, *row, *col;
550         bNode *lnode;
551         char label[UI_MAX_NAME_STR];
552         int indent = (depth > 1)? 2*(depth - 1): 0;
553
554         if(input->flag & SOCK_UNAVAIL)
555                 return;
556
557         /* to avoid eternal loops on cyclic dependencies */
558         node->flag |= NODE_TEST;
559         lnode = (input->link)? input->link->fromnode: NULL;
560
561         /* socket RNA pointer */
562         RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr);
563
564         /* indented label */
565         memset(label, ' ', indent);
566         label[indent] = '\0';
567         BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, input->name);
568
569         /* split in label and value */
570         split = uiLayoutSplit(layout, 0.35f, 0);
571
572         row = uiLayoutRow(split, 1);
573
574         if(depth > 0) {
575                 uiBlockSetEmboss(block, UI_EMBOSSN);
576
577                 if(lnode && (lnode->inputs.first || (lnode->typeinfo->uifunc && lnode->type != NODE_GROUP))) {
578                         int icon = (input->flag & SOCK_COLLAPSED)? ICON_DISCLOSURE_TRI_RIGHT: ICON_DISCLOSURE_TRI_DOWN;
579                         uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon);
580                 }
581                 else
582                         uiItemL(row, "", ICON_BLANK1);
583
584                 bt = block->buttons.last;
585                 bt->x2 = UI_UNIT_X/2;
586
587                 uiBlockSetEmboss(block, UI_EMBOSS);
588         }
589
590         uiItemL(row, label, ICON_NONE);
591         bt= block->buttons.last;
592         bt->flag= UI_TEXT_LEFT;
593
594         if(lnode) {
595                 /* input linked to a node */
596                 uiTemplateNodeLink(split, ntree, node, input);
597
598                 if(!(input->flag & SOCK_COLLAPSED)) {
599                         if(depth == 0)
600                                 uiItemS(layout);
601
602                         ui_node_draw_node(layout, C, ntree, lnode, depth);
603                 }
604         }
605         else {
606                 /* input not linked, show value */
607                 if(input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) {
608                         if(input->type == SOCK_VECTOR) {
609                                 row = uiLayoutRow(split, 0);
610                                 col = uiLayoutColumn(row, 0);
611
612                                 uiItemR(col, &inputptr, "default_value", 0, "", 0);
613                         }
614                         else {
615                                 row = uiLayoutRow(split, 1);
616                                 uiItemR(row, &inputptr, "default_value", 0, "", 0);
617                         }
618                 }
619                 else
620                         row = uiLayoutRow(split, 0);
621
622                 uiTemplateNodeLink(row, ntree, node, input);
623         }
624
625         /* clear */
626         node->flag &= ~NODE_TEST;
627 }
628
629 void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input)
630 {
631         bNode *tnode;
632
633         if(!ntree)
634                 return;
635
636         /* clear for cycle check */
637         for(tnode=ntree->nodes.first; tnode; tnode=tnode->next)
638                 tnode->flag &= ~NODE_TEST;
639
640         if(input)
641                 ui_node_draw_input(layout, C, ntree, node, input, 0);
642         else
643                 ui_node_draw_node(layout, C, ntree, node, 0);
644 }
645