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