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