Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Contributor(s): Blender Foundation 2009. 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00027 #include <stdlib.h> 00028 #include <stddef.h> 00029 #include <string.h> 00030 00031 #include "MEM_guardedalloc.h" 00032 00033 #include "DNA_node_types.h" 00034 #include "DNA_scene_types.h" 00035 #include "DNA_screen_types.h" 00036 00037 #include "BLI_listbase.h" 00038 #include "BLI_string.h" 00039 #include "BLI_utildefines.h" 00040 00041 #include "BLF_translation.h" 00042 00043 #include "BKE_context.h" 00044 #include "BKE_depsgraph.h" 00045 #include "BKE_library.h" 00046 #include "BKE_main.h" 00047 #include "BKE_node.h" 00048 #include "BKE_scene.h" 00049 00050 #include "RNA_access.h" 00051 00052 #include "WM_api.h" 00053 #include "WM_types.h" 00054 00055 #include "UI_interface.h" 00056 #include "UI_resources.h" 00057 #include "../interface/interface_intern.h" 00058 00059 #include "ED_node.h" 00060 00061 /************************* Node Socket Manipulation **************************/ 00062 00063 static void node_tag_recursive(bNode *node) 00064 { 00065 bNodeSocket *input; 00066 00067 if(!node || (node->flag & NODE_TEST)) 00068 return; /* in case of cycles */ 00069 00070 node->flag |= NODE_TEST; 00071 00072 for(input=node->inputs.first; input; input=input->next) 00073 if(input->link) 00074 node_tag_recursive(input->link->fromnode); 00075 } 00076 00077 static void node_clear_recursive(bNode *node) 00078 { 00079 bNodeSocket *input; 00080 00081 if(!node || !(node->flag & NODE_TEST)) 00082 return; /* in case of cycles */ 00083 00084 node->flag &= ~NODE_TEST; 00085 00086 for(input=node->inputs.first; input; input=input->next) 00087 if(input->link) 00088 node_clear_recursive(input->link->fromnode); 00089 } 00090 00091 static void node_remove_linked(bNodeTree *ntree, bNode *rem_node) 00092 { 00093 bNode *node, *next; 00094 bNodeSocket *sock; 00095 00096 if(!rem_node) 00097 return; 00098 00099 /* tag linked nodes to be removed */ 00100 for(node=ntree->nodes.first; node; node=node->next) 00101 node->flag &= ~NODE_TEST; 00102 00103 node_tag_recursive(rem_node); 00104 00105 /* clear tags on nodes that are still used by other nodes */ 00106 for(node=ntree->nodes.first; node; node=node->next) 00107 if(!(node->flag & NODE_TEST)) 00108 for(sock=node->inputs.first; sock; sock=sock->next) 00109 if(sock->link && sock->link->fromnode != rem_node) 00110 node_clear_recursive(sock->link->fromnode); 00111 00112 /* remove nodes */ 00113 for(node=ntree->nodes.first; node; node=next) { 00114 next = node->next; 00115 00116 if(node->flag & NODE_TEST) { 00117 if(node->id) 00118 node->id->us--; 00119 nodeFreeNode(ntree, node); 00120 } 00121 } 00122 } 00123 00124 /* disconnect socket from the node it is connected to */ 00125 static void node_socket_disconnect(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to) 00126 { 00127 if(!sock_to->link) 00128 return; 00129 00130 nodeRemLink(ntree, sock_to->link); 00131 00132 nodeUpdate(ntree, node_to); 00133 ntreeUpdateTree(ntree); 00134 00135 ED_node_generic_update(bmain, ntree, node_to); 00136 } 00137 00138 /* remove all nodes connected to this socket, if they aren't connected to other nodes */ 00139 static void node_socket_remove(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to) 00140 { 00141 if(!sock_to->link) 00142 return; 00143 00144 node_remove_linked(ntree, sock_to->link->fromnode); 00145 00146 nodeUpdate(ntree, node_to); 00147 ntreeUpdateTree(ntree); 00148 00149 ED_node_generic_update(bmain, ntree, node_to); 00150 } 00151 00152 /* add new node connected to this socket, or replace an existing one */ 00153 static void node_socket_add_replace(Main *bmain, bNodeTree *ntree, bNode *node_to, bNodeSocket *sock_to, bNodeTemplate *ntemp, int sock_num) 00154 { 00155 bNode *node_from; 00156 bNodeSocket *sock_from; 00157 bNode *node_prev = NULL; 00158 00159 /* unlink existing node */ 00160 if(sock_to->link) { 00161 node_prev = sock_to->link->fromnode; 00162 nodeRemLink(ntree, sock_to->link); 00163 } 00164 00165 /* find existing node that we can use */ 00166 for(node_from=ntree->nodes.first; node_from; node_from=node_from->next) 00167 if(node_from->type == ntemp->type) 00168 break; 00169 00170 if(node_from) 00171 if(!(node_from->inputs.first == NULL && !(node_from->typeinfo->flag & NODE_OPTIONS))) 00172 node_from = NULL; 00173 00174 if(node_prev && node_prev->type == ntemp->type && 00175 (ntemp->type != NODE_GROUP || node_prev->id == &ntemp->ngroup->id)) { 00176 /* keep the previous node if it's the same type */ 00177 node_from = node_prev; 00178 } 00179 else if(!node_from) { 00180 node_from= nodeAddNode(ntree, ntemp); 00181 node_from->locx = node_to->locx - (node_from->typeinfo->width + 50); 00182 node_from->locy = node_to->locy; 00183 00184 if(node_from->id) 00185 id_us_plus(node_from->id); 00186 } 00187 00188 nodeSetActive(ntree, node_from); 00189 00190 /* add link */ 00191 sock_from = BLI_findlink(&node_from->outputs, sock_num); 00192 nodeAddLink(ntree, node_from, sock_from, node_to, sock_to); 00193 00194 /* copy input sockets from previous node */ 00195 if(node_prev && node_from != node_prev) { 00196 bNodeSocket *sock_prev, *sock_from; 00197 00198 for(sock_prev=node_prev->inputs.first; sock_prev; sock_prev=sock_prev->next) { 00199 for(sock_from=node_from->inputs.first; sock_from; sock_from=sock_from->next) { 00200 if(strcmp(sock_prev->name, sock_from->name) == 0 && sock_prev->type == sock_from->type) { 00201 bNodeLink *link = sock_prev->link; 00202 00203 if(link && link->fromnode) { 00204 nodeAddLink(ntree, link->fromnode, link->fromsock, node_from, sock_from); 00205 nodeRemLink(ntree, link); 00206 } 00207 00208 if(sock_prev->default_value) { 00209 if(sock_from->default_value) 00210 MEM_freeN(sock_from->default_value); 00211 00212 sock_from->default_value = MEM_dupallocN(sock_prev->default_value); 00213 } 00214 } 00215 } 00216 } 00217 00218 /* also preserve mapping for texture nodes */ 00219 if(node_from->typeinfo->nclass == NODE_CLASS_TEXTURE && 00220 node_prev->typeinfo->nclass == NODE_CLASS_TEXTURE) 00221 memcpy(node_from->storage, node_prev->storage, sizeof(NodeTexBase)); 00222 00223 /* remove node */ 00224 node_remove_linked(ntree, node_prev); 00225 } 00226 00227 nodeUpdate(ntree, node_from); 00228 nodeUpdate(ntree, node_to); 00229 ntreeUpdateTree(ntree); 00230 00231 ED_node_generic_update(bmain, ntree, node_to); 00232 } 00233 00234 /****************************** Node Link Menu *******************************/ 00235 00236 #define UI_NODE_LINK_ADD 0 00237 #define UI_NODE_LINK_DISCONNECT -1 00238 #define UI_NODE_LINK_REMOVE -2 00239 00240 typedef struct NodeLinkArg { 00241 Main *bmain; 00242 Scene *scene; 00243 bNodeTree *ntree; 00244 bNode *node; 00245 bNodeSocket *sock; 00246 00247 bNodeTree *ngroup; 00248 int type; 00249 int output; 00250 00251 uiLayout *layout; 00252 } NodeLinkArg; 00253 00254 static void ui_node_link(bContext *UNUSED(C), void *arg_p, void *event_p) 00255 { 00256 NodeLinkArg *arg = (NodeLinkArg*)arg_p; 00257 Main *bmain = arg->bmain; 00258 bNode *node_to = arg->node; 00259 bNodeSocket *sock_to = arg->sock; 00260 bNodeTree *ntree = arg->ntree; 00261 int event = GET_INT_FROM_POINTER(event_p); 00262 bNodeTemplate ntemp; 00263 00264 ntemp.type = arg->type; 00265 ntemp.ngroup = arg->ngroup; 00266 00267 if(event == UI_NODE_LINK_DISCONNECT) 00268 node_socket_disconnect(bmain, ntree, node_to, sock_to); 00269 else if(event == UI_NODE_LINK_REMOVE) 00270 node_socket_remove(bmain, ntree, node_to, sock_to); 00271 else 00272 node_socket_add_replace(bmain, ntree, node_to, sock_to, &ntemp, arg->output); 00273 } 00274 00275 static void ui_node_sock_name(bNodeSocket *sock, char name[UI_MAX_NAME_STR]) 00276 { 00277 if(sock->link && sock->link->fromnode) { 00278 bNode *node = sock->link->fromnode; 00279 char node_name[UI_MAX_NAME_STR]; 00280 00281 if(node->type == NODE_GROUP) 00282 BLI_strncpy(node_name, node->id->name+2, UI_MAX_NAME_STR); 00283 else 00284 BLI_strncpy(node_name, node->typeinfo->name, UI_MAX_NAME_STR); 00285 00286 if(node->inputs.first == NULL && 00287 node->outputs.first != node->outputs.last && 00288 !(node->typeinfo->flag & NODE_OPTIONS)) 00289 BLI_snprintf(name, UI_MAX_NAME_STR, "%s | %s", node_name, sock->link->fromsock->name); 00290 else 00291 BLI_strncpy(name, node_name, UI_MAX_NAME_STR); 00292 } 00293 else if(sock->type == SOCK_SHADER) 00294 BLI_strncpy(name, "None", UI_MAX_NAME_STR); 00295 else 00296 BLI_strncpy(name, "Default", UI_MAX_NAME_STR); 00297 } 00298 00299 static int ui_compatible_sockets(int typeA, int typeB) 00300 { 00301 return (typeA == typeB); 00302 } 00303 00304 static void ui_node_menu_column(NodeLinkArg *arg, int nclass, const char *cname) 00305 { 00306 Main *bmain = arg->bmain; 00307 bNodeTree *ntree = arg->ntree; 00308 bNodeSocket *sock = arg->sock; 00309 uiLayout *layout = arg->layout; 00310 uiLayout *column = NULL; 00311 uiBlock *block = uiLayoutGetBlock(layout); 00312 uiBut *but; 00313 bNodeType *ntype; 00314 bNodeTree *ngroup; 00315 NodeLinkArg *argN; 00316 int first = 1; 00317 int compatibility= 0; 00318 00319 if(ntree->type == NTREE_SHADER) { 00320 if(scene_use_new_shading_nodes(arg->scene)) 00321 compatibility= NODE_NEW_SHADING; 00322 else 00323 compatibility= NODE_OLD_SHADING; 00324 } 00325 00326 if(nclass == NODE_CLASS_GROUP) { 00327 for(ngroup=bmain->nodetree.first; ngroup; ngroup=ngroup->id.next) { 00328 bNodeSocket *gsock; 00329 char name[UI_MAX_NAME_STR]; 00330 int i, j, num = 0; 00331 00332 if(ngroup->type != ntree->type) 00333 continue; 00334 00335 for(gsock=ngroup->inputs.first; gsock; gsock=gsock->next) 00336 if(ui_compatible_sockets(gsock->type, sock->type)) 00337 num++; 00338 00339 for(i=0, j=0, gsock=ngroup->outputs.first; gsock; gsock=gsock->next, i++) { 00340 if(!ui_compatible_sockets(gsock->type, sock->type)) 00341 continue; 00342 00343 if(first) { 00344 column= uiLayoutColumn(layout, 0); 00345 uiBlockSetCurLayout(block, column); 00346 00347 uiItemL(column, cname, ICON_NODE); 00348 but= block->buttons.last; 00349 but->flag= UI_TEXT_LEFT; 00350 00351 first = 0; 00352 } 00353 00354 if(num > 1) { 00355 if(j == 0) { 00356 uiItemL(column, ngroup->id.name+2, ICON_NODE); 00357 but= block->buttons.last; 00358 but->flag= UI_TEXT_LEFT; 00359 } 00360 00361 BLI_snprintf(name, UI_MAX_NAME_STR, " %s", gsock->name); 00362 j++; 00363 } 00364 else 00365 BLI_strncpy(name, ngroup->id.name+2, UI_MAX_NAME_STR); 00366 00367 but = uiDefBut(block, BUT, 0, ngroup->id.name+2, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, 00368 NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input"); 00369 00370 argN = MEM_dupallocN(arg); 00371 argN->type = NODE_GROUP; 00372 argN->ngroup = ngroup; 00373 argN->output = i; 00374 uiButSetNFunc(but, ui_node_link, argN, NULL); 00375 } 00376 } 00377 } 00378 else { 00379 bNodeTreeType *ttype= ntreeGetType(ntree->type); 00380 00381 for(ntype=ttype->node_types.first; ntype; ntype=ntype->next) { 00382 bNodeSocketTemplate *stemp; 00383 char name[UI_MAX_NAME_STR]; 00384 int i, j, num = 0; 00385 00386 if(compatibility && !(ntype->compatibility & compatibility)) 00387 continue; 00388 00389 if(ntype->nclass != nclass) 00390 continue; 00391 00392 for(i=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++) 00393 if(ui_compatible_sockets(stemp->type, sock->type)) 00394 num++; 00395 00396 for(i=0, j=0, stemp=ntype->outputs; stemp && stemp->type != -1; stemp++, i++) { 00397 if(!ui_compatible_sockets(stemp->type, sock->type)) 00398 continue; 00399 00400 if(first) { 00401 column= uiLayoutColumn(layout, 0); 00402 uiBlockSetCurLayout(block, column); 00403 00404 uiItemL(column, cname, ICON_NODE); 00405 but= block->buttons.last; 00406 but->flag= UI_TEXT_LEFT; 00407 00408 first = 0; 00409 } 00410 00411 if(num > 1) { 00412 if(j == 0) { 00413 uiItemL(column, ntype->name, ICON_NODE); 00414 but= block->buttons.last; 00415 but->flag= UI_TEXT_LEFT; 00416 } 00417 00418 BLI_snprintf(name, UI_MAX_NAME_STR, " %s", stemp->name); 00419 j++; 00420 } 00421 else 00422 BLI_strncpy(name, ntype->name, UI_MAX_NAME_STR); 00423 00424 but = uiDefBut(block, BUT, 0, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, 00425 NULL, 0.0, 0.0, 0.0, 0.0, "Add node to input"); 00426 00427 argN = MEM_dupallocN(arg); 00428 argN->type = ntype->type; 00429 argN->output = i; 00430 uiButSetNFunc(but, ui_node_link, argN, NULL); 00431 } 00432 } 00433 } 00434 } 00435 00436 static void node_menu_column_foreach_cb(void *calldata, int nclass, const char *name) 00437 { 00438 NodeLinkArg *arg = (NodeLinkArg*)calldata; 00439 00440 if(!ELEM(nclass, NODE_CLASS_GROUP, NODE_CLASS_LAYOUT)) 00441 ui_node_menu_column(arg, nclass, name); 00442 } 00443 00444 static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_p) 00445 { 00446 Main *bmain= CTX_data_main(C); 00447 Scene *scene= CTX_data_scene(C); 00448 uiBlock *block = uiLayoutGetBlock(layout); 00449 uiBut *but = (uiBut*)but_p; 00450 uiLayout *split, *column; 00451 NodeLinkArg *arg = (NodeLinkArg*)but->func_argN; 00452 bNodeSocket *sock = arg->sock; 00453 bNodeTreeType *ntreetype= ntreeGetType(arg->ntree->type); 00454 00455 uiBlockSetCurLayout(block, layout); 00456 split= uiLayoutSplit(layout, 0, 0); 00457 00458 arg->bmain= bmain; 00459 arg->scene= scene; 00460 arg->layout= split; 00461 00462 if(ntreetype && ntreetype->foreach_nodeclass) 00463 ntreetype->foreach_nodeclass(scene, arg, node_menu_column_foreach_cb); 00464 00465 column= uiLayoutColumn(split, 0); 00466 uiBlockSetCurLayout(block, column); 00467 00468 if(sock->link) { 00469 uiItemL(column, "Link", ICON_NONE); 00470 but= block->buttons.last; 00471 but->flag= UI_TEXT_LEFT; 00472 00473 but = uiDefBut(block, BUT, 0, "Remove", 0, 0, UI_UNIT_X*4, UI_UNIT_Y, 00474 NULL, 0.0, 0.0, 0.0, 0.0, "Remove nodes connected to the input"); 00475 uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_REMOVE)); 00476 00477 but = uiDefBut(block, BUT, 0, "Disconnect", 0, 0, UI_UNIT_X*4, UI_UNIT_Y, 00478 NULL, 0.0, 0.0, 0.0, 0.0, "Disconnect nodes connected to the input"); 00479 uiButSetNFunc(but, ui_node_link, MEM_dupallocN(arg), SET_INT_IN_POINTER(UI_NODE_LINK_DISCONNECT)); 00480 } 00481 00482 ui_node_menu_column(arg, NODE_CLASS_GROUP, IFACE_("Group")); 00483 } 00484 00485 void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock) 00486 { 00487 uiBlock *block = uiLayoutGetBlock(layout); 00488 NodeLinkArg *arg; 00489 uiBut *but; 00490 00491 arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg"); 00492 arg->ntree = ntree; 00493 arg->node = node; 00494 arg->sock = sock; 00495 arg->type = 0; 00496 arg->output = 0; 00497 00498 uiBlockSetCurLayout(block, layout); 00499 00500 if(sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) { 00501 char name[UI_MAX_NAME_STR]; 00502 ui_node_sock_name(sock, name); 00503 but= uiDefMenuBut(block, ui_template_node_link_menu, NULL, name, 0, 0, UI_UNIT_X*4, UI_UNIT_Y, ""); 00504 } 00505 else 00506 but= uiDefIconMenuBut(block, ui_template_node_link_menu, NULL, ICON_NONE, 0, 0, UI_UNIT_X, UI_UNIT_Y, ""); 00507 00508 but->type= MENU; 00509 but->flag |= UI_TEXT_LEFT|UI_BUT_NODE_LINK; 00510 but->poin= (char*)but; 00511 but->func_argN = arg; 00512 00513 if(sock->link && sock->link->fromnode) 00514 if(sock->link->fromnode->flag & NODE_ACTIVE_TEXTURE) 00515 but->flag |= UI_BUT_NODE_ACTIVE; 00516 } 00517 00518 /**************************** Node Tree Layout *******************************/ 00519 00520 static void ui_node_draw_input(uiLayout *layout, bContext *C, 00521 bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth); 00522 00523 static void ui_node_draw_node(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth) 00524 { 00525 bNodeSocket *input; 00526 uiLayout *col, *split; 00527 PointerRNA nodeptr; 00528 00529 RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); 00530 00531 if(node->typeinfo->uifunc) { 00532 if(node->type != NODE_GROUP) { 00533 split = uiLayoutSplit(layout, 0.35f, 0); 00534 col = uiLayoutColumn(split, 0); 00535 col = uiLayoutColumn(split, 0); 00536 00537 node->typeinfo->uifunc(col, C, &nodeptr); 00538 } 00539 } 00540 00541 for(input=node->inputs.first; input; input=input->next) 00542 ui_node_draw_input(layout, C, ntree, node, input, depth+1); 00543 } 00544 00545 static void ui_node_draw_input(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input, int depth) 00546 { 00547 PointerRNA inputptr; 00548 uiBlock *block = uiLayoutGetBlock(layout); 00549 uiBut *bt; 00550 uiLayout *split, *row, *col; 00551 bNode *lnode; 00552 char label[UI_MAX_NAME_STR]; 00553 int indent = (depth > 1)? 2*(depth - 1): 0; 00554 int dependency_loop; 00555 00556 if(input->flag & SOCK_UNAVAIL) 00557 return; 00558 00559 /* to avoid eternal loops on cyclic dependencies */ 00560 node->flag |= NODE_TEST; 00561 lnode = (input->link)? input->link->fromnode: NULL; 00562 00563 dependency_loop = (lnode && (lnode->flag & NODE_TEST)); 00564 if(dependency_loop) 00565 lnode = NULL; 00566 00567 /* socket RNA pointer */ 00568 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr); 00569 00570 /* indented label */ 00571 memset(label, ' ', indent); 00572 label[indent] = '\0'; 00573 BLI_snprintf(label, UI_MAX_NAME_STR, "%s%s:", label, input->name); 00574 00575 /* split in label and value */ 00576 split = uiLayoutSplit(layout, 0.35f, 0); 00577 00578 row = uiLayoutRow(split, 1); 00579 00580 if(depth > 0) { 00581 uiBlockSetEmboss(block, UI_EMBOSSN); 00582 00583 if(lnode && (lnode->inputs.first || (lnode->typeinfo->uifunc && lnode->type != NODE_GROUP))) { 00584 int icon = (input->flag & SOCK_COLLAPSED)? ICON_DISCLOSURE_TRI_RIGHT: ICON_DISCLOSURE_TRI_DOWN; 00585 uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); 00586 } 00587 else 00588 uiItemL(row, "", ICON_BLANK1); 00589 00590 bt = block->buttons.last; 00591 bt->x2 = UI_UNIT_X/2; 00592 00593 uiBlockSetEmboss(block, UI_EMBOSS); 00594 } 00595 00596 uiItemL(row, label, ICON_NONE); 00597 bt= block->buttons.last; 00598 bt->flag= UI_TEXT_LEFT; 00599 00600 if(dependency_loop) { 00601 row = uiLayoutRow(split, 0); 00602 uiItemL(row, "Dependency Loop", ICON_ERROR); 00603 } 00604 else if(lnode) { 00605 /* input linked to a node */ 00606 uiTemplateNodeLink(split, ntree, node, input); 00607 00608 if(!(input->flag & SOCK_COLLAPSED)) { 00609 if(depth == 0) 00610 uiItemS(layout); 00611 00612 ui_node_draw_node(layout, C, ntree, lnode, depth); 00613 } 00614 } 00615 else { 00616 /* input not linked, show value */ 00617 if(input->type != SOCK_SHADER && !(input->flag & SOCK_HIDE_VALUE)) { 00618 if(input->type == SOCK_VECTOR) { 00619 row = uiLayoutRow(split, 0); 00620 col = uiLayoutColumn(row, 0); 00621 00622 uiItemR(col, &inputptr, "default_value", 0, "", 0); 00623 } 00624 else { 00625 row = uiLayoutRow(split, 1); 00626 uiItemR(row, &inputptr, "default_value", 0, "", 0); 00627 } 00628 } 00629 else 00630 row = uiLayoutRow(split, 0); 00631 00632 uiTemplateNodeLink(row, ntree, node, input); 00633 } 00634 00635 /* clear */ 00636 node->flag &= ~NODE_TEST; 00637 } 00638 00639 void uiTemplateNodeView(uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *input) 00640 { 00641 bNode *tnode; 00642 00643 if(!ntree) 00644 return; 00645 00646 /* clear for cycle check */ 00647 for(tnode=ntree->nodes.first; tnode; tnode=tnode->next) 00648 tnode->flag &= ~NODE_TEST; 00649 00650 if(input) 00651 ui_node_draw_input(layout, C, ntree, node, input, 0); 00652 else 00653 ui_node_draw_node(layout, C, ntree, node, 0); 00654 } 00655