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 * The Original Code is Copyright (C) 2005 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Bob Holcomb. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #if 0 /* pynodes commented for now */ 00034 # ifdef WITH_PYTHON 00035 # include <Python.h> 00036 # endif 00037 #endif 00038 00039 #include "MEM_guardedalloc.h" 00040 00041 #include <stdlib.h> 00042 #include <stddef.h> 00043 #include <string.h> 00044 #include <limits.h> 00045 00046 #include "DNA_action_types.h" 00047 #include "DNA_anim_types.h" 00048 #include "DNA_node_types.h" 00049 #include "DNA_node_types.h" 00050 #include "DNA_scene_types.h" 00051 00052 #include "BLI_string.h" 00053 #include "BLI_math.h" 00054 #include "BLI_listbase.h" 00055 #include "BLI_path_util.h" 00056 #include "BLI_utildefines.h" 00057 00058 #include "BKE_animsys.h" 00059 #include "BKE_action.h" 00060 #include "BKE_fcurve.h" 00061 #include "BKE_global.h" 00062 #include "BKE_image.h" 00063 #include "BKE_library.h" 00064 #include "BKE_main.h" 00065 #include "BKE_node.h" 00066 #include "BKE_utildefines.h" 00067 #include "BKE_utildefines.h" 00068 00069 #include "BLI_listbase.h" 00070 00071 #include "RNA_access.h" 00072 00073 #include "NOD_socket.h" 00074 #include "NOD_composite.h" 00075 #include "NOD_shader.h" 00076 #include "NOD_texture.h" 00077 00078 00079 bNodeTreeType *ntreeGetType(int type) 00080 { 00081 static bNodeTreeType *types[NUM_NTREE_TYPES]; 00082 static int types_init = 1; 00083 if (types_init) { 00084 types[NTREE_SHADER] = &ntreeType_Shader; 00085 types[NTREE_COMPOSIT] = &ntreeType_Composite; 00086 types[NTREE_TEXTURE] = &ntreeType_Texture; 00087 types_init = 0; 00088 } 00089 00090 if(type >= 0 && type < NUM_NTREE_TYPES) { 00091 return types[type]; 00092 } 00093 else { 00094 return NULL; 00095 } 00096 } 00097 00098 static bNodeType *node_get_type(bNodeTree *ntree, int type) 00099 { 00100 bNodeType *ntype = ntreeGetType(ntree->type)->node_types.first; 00101 for(; ntype; ntype= ntype->next) 00102 if(ntype->type==type) 00103 return ntype; 00104 00105 return NULL; 00106 } 00107 00108 bNodeType *ntreeGetNodeType(bNodeTree *ntree) 00109 { 00110 return node_get_type(ntree, ntree->nodetype); 00111 } 00112 00113 bNodeSocketType *ntreeGetSocketType(int type) 00114 { 00115 static bNodeSocketType *types[NUM_SOCKET_TYPES]= {NULL}; 00116 static int types_init = 1; 00117 00118 if (types_init) { 00119 node_socket_type_init(types); 00120 types_init= 0; 00121 } 00122 00123 if(type < NUM_SOCKET_TYPES) { 00124 return types[type]; 00125 } 00126 else { 00127 return NULL; 00128 } 00129 } 00130 00131 void ntreeInitTypes(bNodeTree *ntree) 00132 { 00133 bNode *node, *next; 00134 00135 for(node= ntree->nodes.first; node; node= next) { 00136 next= node->next; 00137 00138 node->typeinfo= node_get_type(ntree, node->type); 00139 00140 if(node->type==NODE_DYNAMIC) { 00141 /* needed info if the pynode script fails now: */ 00142 node->storage= ntree; 00143 if(node->id!=NULL) { /* not an empty script node */ 00144 node->custom1= 0; 00145 node->custom1= BSET(node->custom1,NODE_DYNAMIC_ADDEXIST); 00146 } 00147 // if(node->typeinfo) 00148 // node->typeinfo->initfunc(node); 00149 } 00150 00151 if(node->typeinfo==NULL) { 00152 printf("Error: Node type %s doesn't exist anymore, removed\n", node->name); 00153 nodeFreeNode(ntree, node); 00154 } 00155 } 00156 00157 ntree->init |= NTREE_TYPE_INIT; 00158 } 00159 00160 static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char *name, int type) 00161 { 00162 bNodeSocketType *stype= ntreeGetSocketType(type); 00163 bNodeSocket *sock; 00164 00165 sock= MEM_callocN(sizeof(bNodeSocket), "sock"); 00166 00167 BLI_strncpy(sock->name, name, NODE_MAXSTR); 00168 sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF); 00169 sock->type= type; 00170 sock->storage = NULL; 00171 00172 if (stype->value_structsize > 0) 00173 sock->default_value = MEM_callocN(stype->value_structsize, "default socket value"); 00174 00175 return sock; 00176 } 00177 00178 bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *name, int type) 00179 { 00180 bNodeSocket *sock = make_socket(ntree, in_out, name, type); 00181 if (in_out==SOCK_IN) 00182 BLI_addtail(&node->inputs, sock); 00183 else if (in_out==SOCK_OUT) 00184 BLI_addtail(&node->outputs, sock); 00185 00186 node->update |= NODE_UPDATE; 00187 00188 return sock; 00189 } 00190 00191 bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, bNodeSocket *next_sock, const char *name, int type) 00192 { 00193 bNodeSocket *sock = make_socket(ntree, in_out, name, type); 00194 if (in_out==SOCK_IN) 00195 BLI_insertlinkbefore(&node->inputs, next_sock, sock); 00196 else if (in_out==SOCK_OUT) 00197 BLI_insertlinkbefore(&node->outputs, next_sock, sock); 00198 00199 node->update |= NODE_UPDATE; 00200 00201 return sock; 00202 } 00203 00204 void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock) 00205 { 00206 bNodeLink *link, *next; 00207 00208 for(link= ntree->links.first; link; link= next) { 00209 next= link->next; 00210 if(link->fromsock==sock || link->tosock==sock) { 00211 nodeRemLink(ntree, link); 00212 } 00213 } 00214 00215 /* this is fast, this way we don't need an in_out argument */ 00216 BLI_remlink(&node->inputs, sock); 00217 BLI_remlink(&node->outputs, sock); 00218 00219 if (sock->default_value) 00220 MEM_freeN(sock->default_value); 00221 MEM_freeN(sock); 00222 00223 node->update |= NODE_UPDATE; 00224 } 00225 00226 void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node) 00227 { 00228 bNodeSocket *sock; 00229 bNodeLink *link, *next; 00230 00231 for(link= ntree->links.first; link; link= next) { 00232 next= link->next; 00233 if(link->fromnode==node || link->tonode==node) { 00234 nodeRemLink(ntree, link); 00235 } 00236 } 00237 00238 for (sock=node->inputs.first; sock; sock=sock->next) 00239 if (sock->default_value) 00240 MEM_freeN(sock->default_value); 00241 BLI_freelistN(&node->inputs); 00242 for (sock=node->outputs.first; sock; sock=sock->next) 00243 if (sock->default_value) 00244 MEM_freeN(sock->default_value); 00245 00246 BLI_freelistN(&node->outputs); 00247 00248 node->update |= NODE_UPDATE; 00249 } 00250 00251 /* finds a node based on its name */ 00252 bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name) 00253 { 00254 return BLI_findstring(&ntree->nodes, name, offsetof(bNode, name)); 00255 } 00256 00257 /* finds a node based on given socket */ 00258 int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex, int *in_out) 00259 { 00260 bNode *node; 00261 bNodeSocket *tsock; 00262 int index= 0; 00263 00264 for(node= ntree->nodes.first; node; node= node->next) { 00265 for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++) { 00266 if(tsock==sock) { 00267 if (in_out) *in_out= SOCK_IN; 00268 break; 00269 } 00270 } 00271 if(tsock) 00272 break; 00273 for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++) { 00274 if(tsock==sock) { 00275 if (in_out) *in_out= SOCK_OUT; 00276 break; 00277 } 00278 } 00279 if(tsock) 00280 break; 00281 } 00282 00283 if(node) { 00284 *nodep= node; 00285 if(sockindex) *sockindex= index; 00286 return 1; 00287 } 00288 00289 *nodep= NULL; 00290 return 0; 00291 } 00292 00293 /* ************** Add stuff ********** */ 00294 static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) 00295 { 00296 bNodeSocketTemplate *sockdef; 00297 /* bNodeSocket *sock; */ /* UNUSED */ 00298 00299 if(ntype->inputs) { 00300 sockdef= ntype->inputs; 00301 while(sockdef->type != -1) { 00302 /* sock = */ node_add_input_from_template(ntree, node, sockdef); 00303 00304 sockdef++; 00305 } 00306 } 00307 if(ntype->outputs) { 00308 sockdef= ntype->outputs; 00309 while(sockdef->type != -1) { 00310 /* sock = */ node_add_output_from_template(ntree, node, sockdef); 00311 00312 sockdef++; 00313 } 00314 } 00315 } 00316 00317 /* Find the first available, non-duplicate name for a given node */ 00318 void nodeUniqueName(bNodeTree *ntree, bNode *node) 00319 { 00320 BLI_uniquename(&ntree->nodes, node, "Node", '.', offsetof(bNode, name), sizeof(node->name)); 00321 } 00322 00323 bNode *nodeAddNode(bNodeTree *ntree, struct bNodeTemplate *ntemp) 00324 { 00325 bNode *node; 00326 bNodeType *ntype; 00327 00328 ntype= node_get_type(ntree, ntemp->type); 00329 if(ntype == NULL) { 00330 printf("nodeAddNodeType() error: '%d' type invalid\n", ntemp->type); 00331 return NULL; 00332 } 00333 /* validity check */ 00334 if (!nodeValid(ntree, ntemp)) 00335 return NULL; 00336 00337 node= MEM_callocN(sizeof(bNode), "new node"); 00338 node->type= ntype->type; 00339 node->typeinfo= ntype; 00340 node->flag= NODE_SELECT|ntype->flag; 00341 node->width= ntype->width; 00342 node->miniwidth= 42.0f; 00343 node->height= ntype->height; 00344 00345 node_add_sockets_from_type(ntree, node, ntype); 00346 00347 if(ntype->initfunc!=NULL) 00348 ntype->initfunc(ntree, node, ntemp); 00349 00350 /* initialize the node name with the node label */ 00351 BLI_strncpy(node->name, nodeLabel(node), NODE_MAXSTR); 00352 nodeUniqueName(ntree, node); 00353 00354 BLI_addtail(&ntree->nodes, node); 00355 00356 ntree->update |= NTREE_UPDATE_NODES; 00357 00358 return node; 00359 } 00360 00361 void nodeMakeDynamicType(bNode *node) 00362 { 00363 /* find SH_DYNAMIC_NODE ntype */ 00364 bNodeType *ntype= ntreeGetType(NTREE_SHADER)->node_types.first; 00365 while(ntype) { 00366 if(ntype->type==NODE_DYNAMIC) 00367 break; 00368 ntype= ntype->next; 00369 } 00370 00371 /* make own type struct to fill */ 00372 if(ntype) { 00373 /*node->typeinfo= MEM_dupallocN(ntype);*/ 00374 bNodeType *newtype= MEM_callocN(sizeof(bNodeType), "dynamic bNodeType"); 00375 *newtype= *ntype; 00376 BLI_strncpy(newtype->name, ntype->name, sizeof(newtype->name)); 00377 node->typeinfo= newtype; 00378 } 00379 } 00380 00381 /* keep socket listorder identical, for copying links */ 00382 /* ntree is the target tree */ 00383 bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) 00384 { 00385 bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node"); 00386 bNodeSocket *sock, *oldsock; 00387 00388 *nnode= *node; 00389 nodeUniqueName(ntree, nnode); 00390 00391 BLI_addtail(&ntree->nodes, nnode); 00392 00393 BLI_duplicatelist(&nnode->inputs, &node->inputs); 00394 oldsock= node->inputs.first; 00395 for(sock= nnode->inputs.first; sock; sock= sock->next, oldsock= oldsock->next) { 00396 oldsock->new_sock= sock; 00397 sock->stack_index= 0; 00398 00399 sock->default_value = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL); 00400 00401 /* XXX some compositor node (e.g. image, render layers) still store 00402 * some persistent buffer data here, need to clear this to avoid dangling pointers. 00403 */ 00404 sock->cache = NULL; 00405 } 00406 00407 BLI_duplicatelist(&nnode->outputs, &node->outputs); 00408 oldsock= node->outputs.first; 00409 for(sock= nnode->outputs.first; sock; sock= sock->next, oldsock= oldsock->next) { 00410 oldsock->new_sock= sock; 00411 sock->stack_index= 0; 00412 00413 sock->default_value = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL); 00414 00415 /* XXX some compositor node (e.g. image, render layers) still store 00416 * some persistent buffer data here, need to clear this to avoid dangling pointers. 00417 */ 00418 sock->cache = NULL; 00419 } 00420 00421 /* don't increase node->id users, freenode doesn't decrement either */ 00422 00423 if(node->typeinfo->copystoragefunc) 00424 node->typeinfo->copystoragefunc(node, nnode); 00425 00426 node->new_node= nnode; 00427 nnode->new_node= NULL; 00428 nnode->preview= NULL; 00429 00430 ntree->update |= NTREE_UPDATE_NODES; 00431 00432 return nnode; 00433 } 00434 00435 /* also used via rna api, so we check for proper input output direction */ 00436 bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock) 00437 { 00438 bNodeSocket *sock; 00439 bNodeLink *link= NULL; 00440 int from= 0, to= 0; 00441 00442 if(fromnode) { 00443 /* test valid input */ 00444 for(sock= fromnode->outputs.first; sock; sock= sock->next) 00445 if(sock==fromsock) 00446 break; 00447 if(sock) 00448 from= 1; /* OK */ 00449 else { 00450 for(sock= fromnode->inputs.first; sock; sock= sock->next) 00451 if(sock==fromsock) 00452 break; 00453 if(sock) 00454 from= -1; /* OK but flip */ 00455 } 00456 } 00457 else { 00458 /* check tree sockets */ 00459 for(sock= ntree->inputs.first; sock; sock= sock->next) 00460 if(sock==fromsock) 00461 break; 00462 if(sock) 00463 from= 1; /* OK */ 00464 else { 00465 for(sock= ntree->outputs.first; sock; sock= sock->next) 00466 if(sock==fromsock) 00467 break; 00468 if(sock) 00469 from= -1; /* OK but flip */ 00470 } 00471 } 00472 if(tonode) { 00473 for(sock= tonode->inputs.first; sock; sock= sock->next) 00474 if(sock==tosock) 00475 break; 00476 if(sock) 00477 to= 1; /* OK */ 00478 else { 00479 for(sock= tonode->outputs.first; sock; sock= sock->next) 00480 if(sock==tosock) 00481 break; 00482 if(sock) 00483 to= -1; /* OK but flip */ 00484 } 00485 } 00486 else { 00487 /* check tree sockets */ 00488 for(sock= ntree->outputs.first; sock; sock= sock->next) 00489 if(sock==tosock) 00490 break; 00491 if(sock) 00492 to= 1; /* OK */ 00493 else { 00494 for(sock= ntree->inputs.first; sock; sock= sock->next) 00495 if(sock==tosock) 00496 break; 00497 if(sock) 00498 to= -1; /* OK but flip */ 00499 } 00500 } 00501 00502 if(from >= 0 && to >= 0) { 00503 link= MEM_callocN(sizeof(bNodeLink), "link"); 00504 BLI_addtail(&ntree->links, link); 00505 link->fromnode= fromnode; 00506 link->fromsock= fromsock; 00507 link->tonode= tonode; 00508 link->tosock= tosock; 00509 } 00510 else if(from <= 0 && to <= 0) { 00511 link= MEM_callocN(sizeof(bNodeLink), "link"); 00512 BLI_addtail(&ntree->links, link); 00513 link->fromnode= tonode; 00514 link->fromsock= tosock; 00515 link->tonode= fromnode; 00516 link->tosock= fromsock; 00517 } 00518 00519 ntree->update |= NTREE_UPDATE_LINKS; 00520 00521 return link; 00522 } 00523 00524 void nodeRemLink(bNodeTree *ntree, bNodeLink *link) 00525 { 00526 BLI_remlink(&ntree->links, link); 00527 if(link->tosock) 00528 link->tosock->link= NULL; 00529 MEM_freeN(link); 00530 00531 ntree->update |= NTREE_UPDATE_LINKS; 00532 } 00533 00534 void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) 00535 { 00536 bNodeLink *link, *next; 00537 00538 for(link= ntree->links.first; link; link= next) { 00539 next= link->next; 00540 if(link->fromsock==sock || link->tosock==sock) { 00541 nodeRemLink(ntree, link); 00542 } 00543 } 00544 00545 ntree->update |= NTREE_UPDATE_LINKS; 00546 } 00547 00548 /* transforms node location to area coords */ 00549 void nodeSpaceCoords(bNode *node, float *locx, float *locy) 00550 { 00551 if (node->parent) { 00552 nodeSpaceCoords(node->parent, locx, locy); 00553 *locx += node->locx; 00554 *locy += node->locy; 00555 } 00556 else { 00557 *locx = node->locx; 00558 *locy = node->locy; 00559 } 00560 } 00561 00562 void nodeAttachNode(bNode *node, bNode *parent) 00563 { 00564 float parentx, parenty; 00565 00566 node->parent = parent; 00567 /* transform to parent space */ 00568 nodeSpaceCoords(parent, &parentx, &parenty); 00569 node->locx -= parentx; 00570 node->locy -= parenty; 00571 } 00572 00573 void nodeDetachNode(struct bNode *node) 00574 { 00575 float parentx, parenty; 00576 00577 if (node->parent) { 00578 /* transform to "global" (area) space */ 00579 nodeSpaceCoords(node->parent, &parentx, &parenty); 00580 node->locx += parentx; 00581 node->locy += parenty; 00582 node->parent = NULL; 00583 } 00584 } 00585 00586 bNodeTree *ntreeAddTree(const char *name, int type, int nodetype) 00587 { 00588 bNodeTree *ntree; 00589 bNodeType *ntype; 00590 00591 /* trees are created as local trees if they of compositor, material or texture type, 00592 * node groups and other tree types are created as library data. 00593 */ 00594 if (ELEM3(type, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE) && nodetype==0) { 00595 ntree= MEM_callocN(sizeof(bNodeTree), "new node tree"); 00596 *( (short *)ntree->id.name )= ID_NT; /* not "type", as that is ntree->type */ 00597 BLI_strncpy(ntree->id.name+2, name, sizeof(ntree->id.name)); 00598 } 00599 else 00600 ntree= alloc_libblock(&G.main->nodetree, ID_NT, name); 00601 00602 ntree->type= type; 00603 ntree->nodetype = nodetype; 00604 00605 ntreeInitTypes(ntree); 00606 00607 ntype = node_get_type(ntree, ntree->nodetype); 00608 if (ntype && ntype->inittreefunc) 00609 ntype->inittreefunc(ntree); 00610 00611 return ntree; 00612 } 00613 00614 /* Warning: this function gets called during some rather unexpected times 00615 * - this gets called when executing compositing updates (for threaded previews) 00616 * - when the nodetree datablock needs to be copied (i.e. when users get copied) 00617 * - for scene duplication use ntreeSwapID() after so we dont have stale pointers. 00618 */ 00619 bNodeTree *ntreeCopyTree(bNodeTree *ntree) 00620 { 00621 bNodeTree *newtree; 00622 bNode *node /*, *nnode */ /* UNUSED */, *last; 00623 bNodeLink *link; 00624 bNodeSocket *gsock, *oldgsock; 00625 00626 if(ntree==NULL) return NULL; 00627 00628 /* is ntree part of library? */ 00629 for(newtree=G.main->nodetree.first; newtree; newtree= newtree->id.next) 00630 if(newtree==ntree) break; 00631 if(newtree) { 00632 newtree= copy_libblock(&ntree->id); 00633 } else { 00634 newtree= MEM_dupallocN(ntree); 00635 copy_libblock_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */ 00636 } 00637 00638 id_us_plus((ID *)newtree->gpd); 00639 00640 /* in case a running nodetree is copied */ 00641 newtree->execdata= NULL; 00642 00643 newtree->nodes.first= newtree->nodes.last= NULL; 00644 newtree->links.first= newtree->links.last= NULL; 00645 00646 last = ntree->nodes.last; 00647 for(node= ntree->nodes.first; node; node= node->next) { 00648 node->new_node= NULL; 00649 /* nnode= */ nodeCopyNode(newtree, node); /* sets node->new */ 00650 00651 /* make sure we don't copy new nodes again! */ 00652 if (node==last) 00653 break; 00654 } 00655 00656 /* socket definition for group usage */ 00657 BLI_duplicatelist(&newtree->inputs, &ntree->inputs); 00658 for(gsock= newtree->inputs.first, oldgsock= ntree->inputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { 00659 oldgsock->new_sock= gsock; 00660 gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); 00661 gsock->default_value = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL); 00662 } 00663 BLI_duplicatelist(&newtree->outputs, &ntree->outputs); 00664 for(gsock= newtree->outputs.first, oldgsock= ntree->outputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { 00665 oldgsock->new_sock= gsock; 00666 gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); 00667 gsock->default_value = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL); 00668 } 00669 00670 /* copy links */ 00671 BLI_duplicatelist(&newtree->links, &ntree->links); 00672 for(link= newtree->links.first; link; link= link->next) { 00673 link->fromnode = (link->fromnode ? link->fromnode->new_node : NULL); 00674 link->fromsock = (link->fromsock ? link->fromsock->new_sock : NULL); 00675 link->tonode = (link->tonode ? link->tonode->new_node : NULL); 00676 link->tosock = (link->tosock ? link->tosock->new_sock : NULL); 00677 /* update the link socket's pointer */ 00678 if (link->tosock) 00679 link->tosock->link = link; 00680 } 00681 00682 /* update node->parent pointers */ 00683 for (node=newtree->nodes.first; node; node=node->next) { 00684 if (node->parent) 00685 node->parent = node->parent->new_node; 00686 } 00687 00688 return newtree; 00689 } 00690 00691 /* use when duplicating scenes */ 00692 void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) 00693 { 00694 bNode *node; 00695 /* for scene duplication only */ 00696 for(node= ntree->nodes.first; node; node= node->next) { 00697 if(node->id==id_from) { 00698 node->id= id_to; 00699 } 00700 } 00701 } 00702 00703 /* *************** preview *********** */ 00704 /* if node->preview, then we assume the rect to exist */ 00705 00706 void nodeFreePreview(bNode *node) 00707 { 00708 if(node->preview) { 00709 if(node->preview->rect) 00710 MEM_freeN(node->preview->rect); 00711 MEM_freeN(node->preview); 00712 node->preview= NULL; 00713 } 00714 } 00715 00716 static void node_init_preview(bNode *node, int xsize, int ysize) 00717 { 00718 00719 if(node->preview==NULL) { 00720 node->preview= MEM_callocN(sizeof(bNodePreview), "node preview"); 00721 // printf("added preview %s\n", node->name); 00722 } 00723 00724 /* node previews can get added with variable size this way */ 00725 if(xsize==0 || ysize==0) 00726 return; 00727 00728 /* sanity checks & initialize */ 00729 if(node->preview->rect) { 00730 if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) { 00731 MEM_freeN(node->preview->rect); 00732 node->preview->rect= NULL; 00733 } 00734 } 00735 00736 if(node->preview->rect==NULL) { 00737 node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(char)*4, "node preview rect"); 00738 node->preview->xsize= xsize; 00739 node->preview->ysize= ysize; 00740 } 00741 /* no clear, makes nicer previews */ 00742 } 00743 00744 void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize) 00745 { 00746 bNode *node; 00747 00748 if(ntree==NULL) 00749 return; 00750 00751 for(node= ntree->nodes.first; node; node= node->next) { 00752 if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */ 00753 node_init_preview(node, xsize, ysize); 00754 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) 00755 ntreeInitPreview((bNodeTree *)node->id, xsize, ysize); 00756 } 00757 } 00758 00759 static void nodeClearPreview(bNode *node) 00760 { 00761 if(node->preview && node->preview->rect) 00762 memset(node->preview->rect, 0, MEM_allocN_len(node->preview->rect)); 00763 } 00764 00765 /* use it to enforce clear */ 00766 void ntreeClearPreview(bNodeTree *ntree) 00767 { 00768 bNode *node; 00769 00770 if(ntree==NULL) 00771 return; 00772 00773 for(node= ntree->nodes.first; node; node= node->next) { 00774 if(node->typeinfo->flag & NODE_PREVIEW) 00775 nodeClearPreview(node); 00776 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) 00777 ntreeClearPreview((bNodeTree *)node->id); 00778 } 00779 } 00780 00781 /* hack warning! this function is only used for shader previews, and 00782 since it gets called multiple times per pixel for Ztransp we only 00783 add the color once. Preview gets cleared before it starts render though */ 00784 void nodeAddToPreview(bNode *node, float *col, int x, int y, int do_manage) 00785 { 00786 bNodePreview *preview= node->preview; 00787 if(preview) { 00788 if(x>=0 && y>=0) { 00789 if(x<preview->xsize && y<preview->ysize) { 00790 unsigned char *tar= preview->rect+ 4*((preview->xsize*y) + x); 00791 00792 if(do_manage) { 00793 tar[0]= FTOCHAR(linearrgb_to_srgb(col[0])); 00794 tar[1]= FTOCHAR(linearrgb_to_srgb(col[1])); 00795 tar[2]= FTOCHAR(linearrgb_to_srgb(col[2])); 00796 } 00797 else { 00798 tar[0]= FTOCHAR(col[0]); 00799 tar[1]= FTOCHAR(col[1]); 00800 tar[2]= FTOCHAR(col[2]); 00801 } 00802 tar[3]= FTOCHAR(col[3]); 00803 } 00804 //else printf("prv out bound x y %d %d\n", x, y); 00805 } 00806 //else printf("prv out bound x y %d %d\n", x, y); 00807 } 00808 } 00809 00810 /* ************** Free stuff ********** */ 00811 00812 /* goes over entire tree */ 00813 void nodeUnlinkNode(bNodeTree *ntree, bNode *node) 00814 { 00815 bNodeLink *link, *next; 00816 bNodeSocket *sock; 00817 ListBase *lb; 00818 00819 for(link= ntree->links.first; link; link= next) { 00820 next= link->next; 00821 00822 if(link->fromnode==node) { 00823 lb= &node->outputs; 00824 if (link->tonode) 00825 link->tonode->update |= NODE_UPDATE; 00826 } 00827 else if(link->tonode==node) 00828 lb= &node->inputs; 00829 else 00830 lb= NULL; 00831 00832 if(lb) { 00833 for(sock= lb->first; sock; sock= sock->next) { 00834 if(link->fromsock==sock || link->tosock==sock) 00835 break; 00836 } 00837 if(sock) { 00838 nodeRemLink(ntree, link); 00839 } 00840 } 00841 } 00842 } 00843 00844 static void node_unlink_attached(bNodeTree *ntree, bNode *parent) 00845 { 00846 bNode *node; 00847 for (node=ntree->nodes.first; node; node=node->next) { 00848 if (node->parent == parent) 00849 nodeDetachNode(node); 00850 } 00851 } 00852 00853 void nodeFreeNode(bNodeTree *ntree, bNode *node) 00854 { 00855 bNodeTreeType *treetype= ntreeGetType(ntree->type); 00856 bNodeSocket *sock, *nextsock; 00857 00858 /* remove all references to this node */ 00859 nodeUnlinkNode(ntree, node); 00860 node_unlink_attached(ntree, node); 00861 00862 BLI_remlink(&ntree->nodes, node); 00863 00864 /* since it is called while free database, node->id is undefined */ 00865 00866 if (treetype->free_node_cache) 00867 treetype->free_node_cache(ntree, node); 00868 00869 for (sock=node->inputs.first; sock; sock = nextsock) { 00870 nextsock = sock->next; 00871 if (sock->default_value) 00872 MEM_freeN(sock->default_value); 00873 MEM_freeN(sock); 00874 } 00875 for (sock=node->outputs.first; sock; sock = nextsock) { 00876 nextsock = sock->next; 00877 if (sock->default_value) 00878 MEM_freeN(sock->default_value); 00879 MEM_freeN(sock); 00880 } 00881 00882 nodeFreePreview(node); 00883 00884 if(node->typeinfo && node->typeinfo->freestoragefunc) { 00885 node->typeinfo->freestoragefunc(node); 00886 } 00887 00888 MEM_freeN(node); 00889 00890 ntree->update |= NTREE_UPDATE_NODES; 00891 } 00892 00893 /* do not free ntree itself here, free_libblock calls this function too */ 00894 void ntreeFreeTree(bNodeTree *ntree) 00895 { 00896 bNode *node, *next; 00897 bNodeSocket *sock; 00898 00899 if(ntree==NULL) return; 00900 00901 /* XXX hack! node trees should not store execution graphs at all. 00902 * This should be removed when old tree types no longer require it. 00903 * Currently the execution data for texture nodes remains in the tree 00904 * after execution, until the node tree is updated or freed. 00905 */ 00906 if (ntree->execdata) { 00907 switch (ntree->type) { 00908 case NTREE_COMPOSIT: 00909 ntreeCompositEndExecTree(ntree->execdata, 1); 00910 break; 00911 case NTREE_SHADER: 00912 ntreeShaderEndExecTree(ntree->execdata, 1); 00913 break; 00914 case NTREE_TEXTURE: 00915 ntreeTexEndExecTree(ntree->execdata, 1); 00916 break; 00917 } 00918 } 00919 00920 BKE_free_animdata((ID *)ntree); 00921 00922 id_us_min((ID *)ntree->gpd); 00923 00924 BLI_freelistN(&ntree->links); /* do first, then unlink_node goes fast */ 00925 00926 for(node= ntree->nodes.first; node; node= next) { 00927 next= node->next; 00928 nodeFreeNode(ntree, node); 00929 } 00930 00931 for (sock=ntree->inputs.first; sock; sock=sock->next) 00932 if (sock->default_value) 00933 MEM_freeN(sock->default_value); 00934 BLI_freelistN(&ntree->inputs); 00935 for (sock=ntree->outputs.first; sock; sock=sock->next) 00936 if (sock->default_value) 00937 MEM_freeN(sock->default_value); 00938 BLI_freelistN(&ntree->outputs); 00939 } 00940 00941 void ntreeFreeCache(bNodeTree *ntree) 00942 { 00943 bNodeTreeType *treetype; 00944 00945 if(ntree==NULL) return; 00946 00947 treetype= ntreeGetType(ntree->type); 00948 if (treetype->free_cache) 00949 treetype->free_cache(ntree); 00950 } 00951 00952 void ntreeSetOutput(bNodeTree *ntree) 00953 { 00954 bNode *node; 00955 00956 /* find the active outputs, might become tree type dependant handler */ 00957 for(node= ntree->nodes.first; node; node= node->next) { 00958 if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { 00959 bNode *tnode; 00960 int output= 0; 00961 00962 /* we need a check for which output node should be tagged like this, below an exception */ 00963 if(node->type==CMP_NODE_OUTPUT_FILE) 00964 continue; 00965 00966 /* there is more types having output class, each one is checked */ 00967 for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { 00968 if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) { 00969 00970 if(ntree->type==NTREE_COMPOSIT) { 00971 00972 /* same type, exception for viewer */ 00973 if(tnode->type==node->type || 00974 (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && 00975 ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) { 00976 if(tnode->flag & NODE_DO_OUTPUT) { 00977 output++; 00978 if(output>1) 00979 tnode->flag &= ~NODE_DO_OUTPUT; 00980 } 00981 } 00982 } 00983 else { 00984 /* same type */ 00985 if(tnode->type==node->type) { 00986 if(tnode->flag & NODE_DO_OUTPUT) { 00987 output++; 00988 if(output>1) 00989 tnode->flag &= ~NODE_DO_OUTPUT; 00990 } 00991 } 00992 } 00993 } 00994 } 00995 if(output==0) 00996 node->flag |= NODE_DO_OUTPUT; 00997 } 00998 } 00999 01000 /* here we could recursively set which nodes have to be done, 01001 might be different for editor or for "real" use... */ 01002 } 01003 01004 typedef struct MakeLocalCallData { 01005 ID *group_id; 01006 ID *new_id; 01007 int lib, local; 01008 } MakeLocalCallData; 01009 01010 static void ntreeMakeLocal_CheckLocal(void *calldata, ID *owner_id, bNodeTree *ntree) 01011 { 01012 MakeLocalCallData *cd= (MakeLocalCallData*)calldata; 01013 bNode *node; 01014 01015 /* find if group is in tree */ 01016 for(node= ntree->nodes.first; node; node= node->next) { 01017 if(node->id == cd->group_id) { 01018 if(owner_id->lib) cd->lib= 1; 01019 else cd->local= 1; 01020 } 01021 } 01022 } 01023 01024 static void ntreeMakeLocal_LinkNew(void *calldata, ID *owner_id, bNodeTree *ntree) 01025 { 01026 MakeLocalCallData *cd= (MakeLocalCallData*)calldata; 01027 bNode *node; 01028 01029 /* find if group is in tree */ 01030 for(node= ntree->nodes.first; node; node= node->next) { 01031 if(node->id == cd->group_id) { 01032 if(owner_id->lib==NULL) { 01033 node->id= cd->new_id; 01034 cd->new_id->us++; 01035 cd->group_id->us--; 01036 } 01037 } 01038 } 01039 } 01040 01041 void ntreeMakeLocal(bNodeTree *ntree) 01042 { 01043 Main *bmain= G.main; 01044 bNodeTreeType *treetype= ntreeGetType(ntree->type); 01045 MakeLocalCallData cd; 01046 01047 /* - only lib users: do nothing 01048 * - only local users: set flag 01049 * - mixed: make copy 01050 */ 01051 01052 if(ntree->id.lib==NULL) return; 01053 if(ntree->id.us==1) { 01054 id_clear_lib_data(bmain, (ID *)ntree); 01055 return; 01056 } 01057 01058 /* now check users of groups... again typedepending, callback... */ 01059 cd.group_id = &ntree->id; 01060 cd.new_id = NULL; 01061 cd.local = 0; 01062 cd.lib = 0; 01063 01064 treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_CheckLocal); 01065 01066 /* if all users are local, we simply make tree local */ 01067 if(cd.local && cd.lib==0) { 01068 id_clear_lib_data(bmain, (ID *)ntree); 01069 } 01070 else if(cd.local && cd.lib) { 01071 /* this is the mixed case, we copy the tree and assign it to local users */ 01072 bNodeTree *newtree= ntreeCopyTree(ntree); 01073 01074 newtree->id.us= 0; 01075 01076 01077 cd.new_id = &newtree->id; 01078 treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_LinkNew); 01079 } 01080 } 01081 01082 int ntreeNodeExists(bNodeTree *ntree, bNode *testnode) 01083 { 01084 bNode *node= ntree->nodes.first; 01085 for(; node; node= node->next) 01086 if(node==testnode) 01087 return 1; 01088 return 0; 01089 } 01090 01091 int ntreeOutputExists(bNode *node, bNodeSocket *testsock) 01092 { 01093 bNodeSocket *sock= node->outputs.first; 01094 for(; sock; sock= sock->next) 01095 if(sock==testsock) 01096 return 1; 01097 return 0; 01098 } 01099 01100 /* returns localized tree for execution in threads */ 01101 bNodeTree *ntreeLocalize(bNodeTree *ntree) 01102 { 01103 bNodeTreeType *ntreetype= ntreeGetType(ntree->type); 01104 01105 bNodeTree *ltree; 01106 bNode *node; 01107 01108 bAction *action_backup= NULL, *tmpact_backup= NULL; 01109 01110 /* Workaround for copying an action on each render! 01111 * set action to NULL so animdata actions dont get copied */ 01112 AnimData *adt= BKE_animdata_from_id(&ntree->id); 01113 01114 if(adt) { 01115 action_backup= adt->action; 01116 tmpact_backup= adt->tmpact; 01117 01118 adt->action= NULL; 01119 adt->tmpact= NULL; 01120 } 01121 01122 /* node copy func */ 01123 ltree= ntreeCopyTree(ntree); 01124 01125 if(adt) { 01126 AnimData *ladt= BKE_animdata_from_id(<ree->id); 01127 01128 adt->action= ladt->action= action_backup; 01129 adt->tmpact= ladt->tmpact= tmpact_backup; 01130 01131 if(action_backup) action_backup->id.us++; 01132 if(tmpact_backup) tmpact_backup->id.us++; 01133 01134 } 01135 /* end animdata uglyness */ 01136 01137 /* ensures only a single output node is enabled */ 01138 ntreeSetOutput(ntree); 01139 01140 for(node= ntree->nodes.first; node; node= node->next) { 01141 /* store new_node pointer to original */ 01142 node->new_node->new_node= node; 01143 } 01144 01145 if (ntreetype->localize) 01146 ntreetype->localize(ltree, ntree); 01147 01148 return ltree; 01149 } 01150 01151 /* sync local composite with real tree */ 01152 /* local tree is supposed to be running, be careful moving previews! */ 01153 /* is called by jobs manager, outside threads, so it doesnt happen during draw */ 01154 void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) 01155 { 01156 bNodeTreeType *ntreetype= ntreeGetType(ntree->type); 01157 01158 if (ntreetype->local_sync) 01159 ntreetype->local_sync(localtree, ntree); 01160 } 01161 01162 /* merge local tree results back, and free local tree */ 01163 /* we have to assume the editor already changed completely */ 01164 void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) 01165 { 01166 bNodeTreeType *ntreetype= ntreeGetType(ntree->type); 01167 bNode *lnode; 01168 01169 /* move over the compbufs and previews */ 01170 for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { 01171 if(ntreeNodeExists(ntree, lnode->new_node)) { 01172 if(lnode->preview && lnode->preview->rect) { 01173 nodeFreePreview(lnode->new_node); 01174 lnode->new_node->preview= lnode->preview; 01175 lnode->preview= NULL; 01176 } 01177 } 01178 } 01179 01180 if (ntreetype->local_merge) 01181 ntreetype->local_merge(localtree, ntree); 01182 01183 ntreeFreeTree(localtree); 01184 MEM_freeN(localtree); 01185 } 01186 01187 /* ************ find stuff *************** */ 01188 01189 int ntreeHasType(bNodeTree *ntree, int type) 01190 { 01191 bNode *node; 01192 01193 if(ntree) 01194 for(node= ntree->nodes.first; node; node= node->next) 01195 if(node->type == type) 01196 return 1; 01197 return 0; 01198 } 01199 01200 bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to) 01201 { 01202 bNodeLink *link; 01203 01204 for(link= ntree->links.first; link; link= link->next) { 01205 if(link->fromsock==from && link->tosock==to) 01206 return link; 01207 if(link->fromsock==to && link->tosock==from) /* hrms? */ 01208 return link; 01209 } 01210 return NULL; 01211 } 01212 01213 int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock) 01214 { 01215 bNodeLink *link; 01216 int tot= 0; 01217 01218 for(link= ntree->links.first; link; link= link->next) { 01219 if(link->fromsock==sock || link->tosock==sock) 01220 tot++; 01221 } 01222 return tot; 01223 } 01224 01225 bNode *nodeGetActive(bNodeTree *ntree) 01226 { 01227 bNode *node; 01228 01229 if(ntree==NULL) return NULL; 01230 01231 for(node= ntree->nodes.first; node; node= node->next) 01232 if(node->flag & NODE_ACTIVE) 01233 break; 01234 return node; 01235 } 01236 01237 /* two active flags, ID nodes have special flag for buttons display */ 01238 bNode *nodeGetActiveID(bNodeTree *ntree, short idtype) 01239 { 01240 bNode *node; 01241 01242 if(ntree==NULL) return NULL; 01243 01244 /* check for group edit */ 01245 for(node= ntree->nodes.first; node; node= node->next) 01246 if(node->flag & NODE_GROUP_EDIT) 01247 break; 01248 01249 if(node) 01250 ntree= (bNodeTree*)node->id; 01251 01252 /* now find active node with this id */ 01253 for(node= ntree->nodes.first; node; node= node->next) 01254 if(node->id && GS(node->id->name)==idtype) 01255 if(node->flag & NODE_ACTIVE_ID) 01256 break; 01257 01258 return node; 01259 } 01260 01261 int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) 01262 { 01263 bNode *node; 01264 int ok= FALSE; 01265 01266 if(ntree==NULL) return ok; 01267 01268 /* check for group edit */ 01269 for(node= ntree->nodes.first; node; node= node->next) 01270 if(node->flag & NODE_GROUP_EDIT) 01271 break; 01272 01273 if(node) 01274 ntree= (bNodeTree*)node->id; 01275 01276 /* now find active node with this id */ 01277 for(node= ntree->nodes.first; node; node= node->next) { 01278 if(node->id && GS(node->id->name)==idtype) { 01279 if(id && ok==FALSE && node->id==id) { 01280 node->flag |= NODE_ACTIVE_ID; 01281 ok= TRUE; 01282 } else { 01283 node->flag &= ~NODE_ACTIVE_ID; 01284 } 01285 } 01286 } 01287 01288 return ok; 01289 } 01290 01291 01292 /* two active flags, ID nodes have special flag for buttons display */ 01293 void nodeClearActiveID(bNodeTree *ntree, short idtype) 01294 { 01295 bNode *node; 01296 01297 if(ntree==NULL) return; 01298 01299 for(node= ntree->nodes.first; node; node= node->next) 01300 if(node->id && GS(node->id->name)==idtype) 01301 node->flag &= ~NODE_ACTIVE_ID; 01302 } 01303 01304 /* two active flags, ID nodes have special flag for buttons display */ 01305 void nodeSetActive(bNodeTree *ntree, bNode *node) 01306 { 01307 bNode *tnode; 01308 01309 /* make sure only one node is active, and only one per ID type */ 01310 for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { 01311 tnode->flag &= ~NODE_ACTIVE; 01312 01313 if(node->id && tnode->id) { 01314 if(GS(node->id->name) == GS(tnode->id->name)) 01315 tnode->flag &= ~NODE_ACTIVE_ID; 01316 } 01317 if(node->typeinfo->nclass == NODE_CLASS_TEXTURE) 01318 tnode->flag &= ~NODE_ACTIVE_TEXTURE; 01319 } 01320 01321 node->flag |= NODE_ACTIVE; 01322 if(node->id) 01323 node->flag |= NODE_ACTIVE_ID; 01324 if(node->typeinfo->nclass == NODE_CLASS_TEXTURE) 01325 node->flag |= NODE_ACTIVE_TEXTURE; 01326 } 01327 01328 int nodeSocketIsHidden(bNodeSocket *sock) 01329 { 01330 return ((sock->flag & (SOCK_HIDDEN | SOCK_AUTO_HIDDEN | SOCK_UNAVAIL)) != 0); 01331 } 01332 01333 /* ************** dependency stuff *********** */ 01334 01335 /* node is guaranteed to be not checked before */ 01336 static int node_get_deplist_recurs(bNode *node, bNode ***nsort) 01337 { 01338 bNode *fromnode; 01339 bNodeSocket *sock; 01340 int level = 0xFFF; 01341 01342 node->done= 1; 01343 01344 /* check linked nodes */ 01345 for(sock= node->inputs.first; sock; sock= sock->next) { 01346 if(sock->link) { 01347 fromnode= sock->link->fromnode; 01348 if(fromnode) { 01349 if (fromnode->done==0) 01350 fromnode->level= node_get_deplist_recurs(fromnode, nsort); 01351 if (fromnode->level <= level) 01352 level = fromnode->level - 1; 01353 } 01354 } 01355 } 01356 01357 /* check parent node */ 01358 if (node->parent) { 01359 if (node->parent->done==0) 01360 node->parent->level= node_get_deplist_recurs(node->parent, nsort); 01361 if (node->parent->level <= level) 01362 level = node->parent->level - 1; 01363 } 01364 01365 if (nsort) { 01366 **nsort= node; 01367 (*nsort)++; 01368 } 01369 01370 return level; 01371 } 01372 01373 void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes) 01374 { 01375 bNode *node, **nsort; 01376 01377 *totnodes=0; 01378 01379 /* first clear data */ 01380 for(node= ntree->nodes.first; node; node= node->next) { 01381 node->done= 0; 01382 (*totnodes)++; 01383 } 01384 if(*totnodes==0) { 01385 *deplist = NULL; 01386 return; 01387 } 01388 01389 nsort= *deplist= MEM_callocN((*totnodes)*sizeof(bNode*), "sorted node array"); 01390 01391 /* recursive check */ 01392 for(node= ntree->nodes.first; node; node= node->next) { 01393 if(node->done==0) { 01394 node->level= node_get_deplist_recurs(node, &nsort); 01395 } 01396 } 01397 } 01398 01399 static void ntree_update_link_pointers(bNodeTree *ntree) 01400 { 01401 bNode *node; 01402 bNodeSocket *sock; 01403 bNodeLink *link; 01404 01405 /* first clear data */ 01406 for(node= ntree->nodes.first; node; node= node->next) { 01407 for(sock= node->inputs.first; sock; sock= sock->next) { 01408 sock->link= NULL; 01409 sock->flag &= ~SOCK_IN_USE; 01410 } 01411 for(sock= node->outputs.first; sock; sock= sock->next) { 01412 sock->flag &= ~SOCK_IN_USE; 01413 } 01414 } 01415 for(sock= ntree->inputs.first; sock; sock= sock->next) { 01416 sock->flag &= ~SOCK_IN_USE; 01417 } 01418 for(sock= ntree->outputs.first; sock; sock= sock->next) { 01419 sock->link= NULL; 01420 sock->flag &= ~SOCK_IN_USE; 01421 } 01422 01423 for(link= ntree->links.first; link; link= link->next) { 01424 link->tosock->link= link; 01425 01426 link->fromsock->flag |= SOCK_IN_USE; 01427 link->tosock->flag |= SOCK_IN_USE; 01428 } 01429 } 01430 01431 static void ntree_validate_links(bNodeTree *ntree) 01432 { 01433 bNodeTreeType *ntreetype = ntreeGetType(ntree->type); 01434 bNodeLink *link; 01435 01436 for (link = ntree->links.first; link; link = link->next) { 01437 link->flag |= NODE_LINK_VALID; 01438 if (link->fromnode && link->tonode && link->fromnode->level <= link->tonode->level) 01439 link->flag &= ~NODE_LINK_VALID; 01440 else if (ntreetype->validate_link) { 01441 if (!ntreetype->validate_link(ntree, link)) 01442 link->flag &= ~NODE_LINK_VALID; 01443 } 01444 } 01445 } 01446 01447 static void ntree_verify_nodes_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree) 01448 { 01449 ID *id= (ID*)calldata; 01450 bNode *node; 01451 01452 for (node=ntree->nodes.first; node; node=node->next) 01453 if (node->typeinfo->verifyfunc) 01454 node->typeinfo->verifyfunc(ntree, node, id); 01455 } 01456 01457 void ntreeVerifyNodes(struct Main *main, struct ID *id) 01458 { 01459 bNodeTreeType *ntreetype; 01460 bNodeTree *ntree; 01461 int n; 01462 01463 for (n=0; n < NUM_NTREE_TYPES; ++n) { 01464 ntreetype= ntreeGetType(n); 01465 if (ntreetype && ntreetype->foreach_nodetree) 01466 ntreetype->foreach_nodetree(main, id, ntree_verify_nodes_cb); 01467 } 01468 for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) 01469 ntree_verify_nodes_cb(id, NULL, ntree); 01470 } 01471 01472 void ntreeUpdateTree(bNodeTree *ntree) 01473 { 01474 bNodeTreeType *ntreetype= ntreeGetType(ntree->type); 01475 bNode *node; 01476 bNode **deplist; 01477 int totnodes, n; 01478 01479 ntree_update_link_pointers(ntree); 01480 01481 /* also updates the node level! */ 01482 ntreeGetDependencyList(ntree, &deplist, &totnodes); 01483 01484 if (deplist) { 01485 /* update individual nodes */ 01486 for (n=0; n < totnodes; ++n) { 01487 node = deplist[n]; 01488 01489 /* node tree update tags override individual node update flags */ 01490 if ((node->update & NODE_UPDATE) || (ntree->update & NTREE_UPDATE)) { 01491 if (ntreetype->update_node) 01492 ntreetype->update_node(ntree, node); 01493 else if (node->typeinfo->updatefunc) 01494 node->typeinfo->updatefunc(ntree, node); 01495 } 01496 /* clear update flag */ 01497 node->update = 0; 01498 } 01499 01500 MEM_freeN(deplist); 01501 } 01502 01503 /* general tree updates */ 01504 if (ntree->update & (NTREE_UPDATE_LINKS|NTREE_UPDATE_NODES)) { 01505 ntree_validate_links(ntree); 01506 } 01507 01508 /* update tree */ 01509 if (ntreetype->update) 01510 ntreetype->update(ntree); 01511 else { 01512 /* Trees can be associated with a specific node type (i.e. group nodes), 01513 * in that case a tree update function may be defined by that node type. 01514 */ 01515 bNodeType *ntype= node_get_type(ntree, ntree->nodetype); 01516 if (ntype && ntype->updatetreefunc) 01517 ntype->updatetreefunc(ntree); 01518 } 01519 01520 /* XXX hack, should be done by depsgraph!! */ 01521 ntreeVerifyNodes(G.main, &ntree->id); 01522 01523 /* clear the update flag */ 01524 ntree->update = 0; 01525 } 01526 01527 void nodeUpdate(bNodeTree *ntree, bNode *node) 01528 { 01529 bNodeTreeType *ntreetype= ntreeGetType(ntree->type); 01530 01531 if (ntreetype->update_node) 01532 ntreetype->update_node(ntree, node); 01533 else if (node->typeinfo->updatefunc) 01534 node->typeinfo->updatefunc(ntree, node); 01535 /* clear update flag */ 01536 node->update = 0; 01537 } 01538 01539 int nodeUpdateID(bNodeTree *ntree, ID *id) 01540 { 01541 bNodeTreeType *ntreetype; 01542 bNode *node; 01543 int change = FALSE; 01544 01545 if(ELEM(NULL, id, ntree)) 01546 return change; 01547 01548 ntreetype = ntreeGetType(ntree->type); 01549 01550 if (ntreetype->update_node) { 01551 for(node= ntree->nodes.first; node; node= node->next) { 01552 if(node->id==id) { 01553 change = TRUE; 01554 ntreetype->update_node(ntree, node); 01555 /* clear update flag */ 01556 node->update = 0; 01557 } 01558 } 01559 } 01560 else { 01561 for(node= ntree->nodes.first; node; node= node->next) { 01562 if(node->id==id) { 01563 change = TRUE; 01564 if (node->typeinfo->updatefunc) 01565 node->typeinfo->updatefunc(ntree, node); 01566 /* clear update flag */ 01567 node->update = 0; 01568 } 01569 } 01570 } 01571 01572 return change; 01573 } 01574 01575 01576 /* ************* node type access ********** */ 01577 01578 int nodeValid(bNodeTree *ntree, bNodeTemplate *ntemp) 01579 { 01580 bNodeType *ntype= node_get_type(ntree, ntemp->type); 01581 if (ntype) { 01582 if (ntype->validfunc) 01583 return ntype->validfunc(ntree, ntemp); 01584 else 01585 return 1; 01586 } 01587 else 01588 return 0; 01589 } 01590 01591 const char* nodeLabel(bNode *node) 01592 { 01593 if (node->label[0]!='\0') 01594 return node->label; 01595 else if (node->typeinfo->labelfunc) 01596 return node->typeinfo->labelfunc(node); 01597 else 01598 return node->typeinfo->name; 01599 } 01600 01601 struct bNodeTree *nodeGroupEditGet(struct bNode *node) 01602 { 01603 if (node->typeinfo->group_edit_get) 01604 return node->typeinfo->group_edit_get(node); 01605 else 01606 return NULL; 01607 } 01608 01609 struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit) 01610 { 01611 if (node->typeinfo->group_edit_set) 01612 return node->typeinfo->group_edit_set(node, edit); 01613 else if (node->typeinfo->group_edit_get) 01614 return node->typeinfo->group_edit_get(node); 01615 else 01616 return NULL; 01617 } 01618 01619 void nodeGroupEditClear(struct bNode *node) 01620 { 01621 if (node->typeinfo->group_edit_clear) 01622 node->typeinfo->group_edit_clear(node); 01623 } 01624 01625 struct bNodeTemplate nodeMakeTemplate(struct bNode *node) 01626 { 01627 bNodeTemplate ntemp; 01628 if (node->typeinfo->templatefunc) 01629 return node->typeinfo->templatefunc(node); 01630 else { 01631 ntemp.type = node->type; 01632 return ntemp; 01633 } 01634 } 01635 01636 void node_type_base(bNodeTreeType *ttype, bNodeType *ntype, int type, const char *name, short nclass, short flag) 01637 { 01638 memset(ntype, 0, sizeof(bNodeType)); 01639 01640 ntype->type = type; 01641 BLI_strncpy(ntype->name, name, sizeof(ntype->name)); 01642 ntype->nclass = nclass; 01643 ntype->flag = flag; 01644 01645 /* Default muting stuff. */ 01646 if(ttype) { 01647 ntype->mutefunc = ttype->mutefunc; 01648 ntype->mutelinksfunc = ttype->mutelinksfunc; 01649 ntype->gpumutefunc = ttype->gpumutefunc; 01650 } 01651 01652 /* default size values */ 01653 ntype->width = 140; 01654 ntype->minwidth = 100; 01655 ntype->maxwidth = 320; 01656 ntype->height = 100; 01657 ntype->minheight = 30; 01658 ntype->maxheight = FLT_MAX; 01659 } 01660 01661 void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs) 01662 { 01663 ntype->inputs = inputs; 01664 ntype->outputs = outputs; 01665 } 01666 01667 void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp)) 01668 { 01669 ntype->initfunc = initfunc; 01670 } 01671 01672 void node_type_valid(struct bNodeType *ntype, int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp)) 01673 { 01674 ntype->validfunc = validfunc; 01675 } 01676 01677 void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth) 01678 { 01679 ntype->width = width; 01680 ntype->minwidth = minwidth; 01681 if (maxwidth <= minwidth) 01682 ntype->maxwidth = FLT_MAX; 01683 else 01684 ntype->maxwidth = maxwidth; 01685 } 01686 01687 void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *)) 01688 { 01689 if (storagename) 01690 BLI_strncpy(ntype->storagename, storagename, sizeof(ntype->storagename)); 01691 else 01692 ntype->storagename[0] = '\0'; 01693 ntype->copystoragefunc = copystoragefunc; 01694 ntype->freestoragefunc = freestoragefunc; 01695 } 01696 01697 void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *)) 01698 { 01699 ntype->labelfunc = labelfunc; 01700 } 01701 01702 void node_type_template(struct bNodeType *ntype, struct bNodeTemplate (*templatefunc)(struct bNode *)) 01703 { 01704 ntype->templatefunc = templatefunc; 01705 } 01706 01707 void node_type_update(struct bNodeType *ntype, 01708 void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node), 01709 void (*verifyfunc)(struct bNodeTree *ntree, struct bNode *node, struct ID *id)) 01710 { 01711 ntype->updatefunc = updatefunc; 01712 ntype->verifyfunc = verifyfunc; 01713 } 01714 01715 void node_type_tree(struct bNodeType *ntype, void (*inittreefunc)(struct bNodeTree *), void (*updatetreefunc)(struct bNodeTree *)) 01716 { 01717 ntype->inittreefunc = inittreefunc; 01718 ntype->updatetreefunc = updatetreefunc; 01719 } 01720 01721 void node_type_group_edit(struct bNodeType *ntype, 01722 struct bNodeTree *(*group_edit_get)(struct bNode *node), 01723 struct bNodeTree *(*group_edit_set)(struct bNode *node, int edit), 01724 void (*group_edit_clear)(struct bNode *node)) 01725 { 01726 ntype->group_edit_get = group_edit_get; 01727 ntype->group_edit_set = group_edit_set; 01728 ntype->group_edit_clear = group_edit_clear; 01729 } 01730 01731 void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **)) 01732 { 01733 ntype->execfunc = execfunc; 01734 } 01735 01736 void node_type_exec_new(struct bNodeType *ntype, 01737 void *(*initexecfunc)(struct bNode *node), 01738 void (*freeexecfunc)(struct bNode *node, void *nodedata), 01739 void (*newexecfunc)(void *data, int thread, struct bNode *, void *nodedata, struct bNodeStack **, struct bNodeStack **)) 01740 { 01741 ntype->initexecfunc = initexecfunc; 01742 ntype->freeexecfunc = freeexecfunc; 01743 ntype->newexecfunc = newexecfunc; 01744 } 01745 01746 void node_type_mute(struct bNodeType *ntype, 01747 void (*mutefunc)(void *data, int thread, struct bNode *, void *nodedata, 01748 struct bNodeStack **, struct bNodeStack **), 01749 ListBase (*mutelinksfunc)(struct bNodeTree *, struct bNode *, struct bNodeStack **, struct bNodeStack **, 01750 struct GPUNodeStack *, struct GPUNodeStack *)) 01751 { 01752 ntype->mutefunc = mutefunc; 01753 ntype->mutelinksfunc = mutelinksfunc; 01754 } 01755 01756 void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)) 01757 { 01758 ntype->gpufunc = gpufunc; 01759 } 01760 01761 void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out)) 01762 { 01763 ntype->gpuextfunc = gpuextfunc; 01764 } 01765 01766 void node_type_gpu_mute(struct bNodeType *ntype, int (*gpumutefunc)(struct GPUMaterial *, struct bNode *, void *, 01767 struct GPUNodeStack *, struct GPUNodeStack *)) 01768 { 01769 ntype->gpumutefunc = gpumutefunc; 01770 } 01771 01772 void node_type_compatibility(struct bNodeType *ntype, short compatibility) 01773 { 01774 ntype->compatibility = compatibility; 01775 } 01776 01777 static bNodeType *is_nodetype_registered(ListBase *typelist, int type) 01778 { 01779 bNodeType *ntype= typelist->first; 01780 01781 for(;ntype; ntype= ntype->next ) 01782 if(ntype->type==type) 01783 return ntype; 01784 01785 return NULL; 01786 } 01787 01788 void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype) 01789 { 01790 ListBase *typelist = &(ttype->node_types); 01791 bNodeType *found= is_nodetype_registered(typelist, ntype->type); 01792 01793 if(found==NULL) 01794 BLI_addtail(typelist, ntype); 01795 } 01796 01797 static void registerCompositNodes(bNodeTreeType *ttype) 01798 { 01799 register_node_type_frame(ttype); 01800 01801 register_node_type_cmp_group(ttype); 01802 // register_node_type_cmp_forloop(ttype); 01803 // register_node_type_cmp_whileloop(ttype); 01804 01805 register_node_type_cmp_rlayers(ttype); 01806 register_node_type_cmp_image(ttype); 01807 register_node_type_cmp_texture(ttype); 01808 register_node_type_cmp_value(ttype); 01809 register_node_type_cmp_rgb(ttype); 01810 register_node_type_cmp_curve_time(ttype); 01811 register_node_type_cmp_movieclip(ttype); 01812 01813 register_node_type_cmp_composite(ttype); 01814 register_node_type_cmp_viewer(ttype); 01815 register_node_type_cmp_splitviewer(ttype); 01816 register_node_type_cmp_output_file(ttype); 01817 register_node_type_cmp_view_levels(ttype); 01818 01819 register_node_type_cmp_curve_rgb(ttype); 01820 register_node_type_cmp_mix_rgb(ttype); 01821 register_node_type_cmp_hue_sat(ttype); 01822 register_node_type_cmp_brightcontrast(ttype); 01823 register_node_type_cmp_gamma(ttype); 01824 register_node_type_cmp_invert(ttype); 01825 register_node_type_cmp_alphaover(ttype); 01826 register_node_type_cmp_zcombine(ttype); 01827 register_node_type_cmp_colorbalance(ttype); 01828 register_node_type_cmp_huecorrect(ttype); 01829 01830 register_node_type_cmp_normal(ttype); 01831 register_node_type_cmp_curve_vec(ttype); 01832 register_node_type_cmp_map_value(ttype); 01833 register_node_type_cmp_normalize(ttype); 01834 01835 register_node_type_cmp_filter(ttype); 01836 register_node_type_cmp_blur(ttype); 01837 register_node_type_cmp_dblur(ttype); 01838 register_node_type_cmp_bilateralblur(ttype); 01839 register_node_type_cmp_vecblur(ttype); 01840 register_node_type_cmp_dilateerode(ttype); 01841 register_node_type_cmp_defocus(ttype); 01842 01843 register_node_type_cmp_valtorgb(ttype); 01844 register_node_type_cmp_rgbtobw(ttype); 01845 register_node_type_cmp_setalpha(ttype); 01846 register_node_type_cmp_idmask(ttype); 01847 register_node_type_cmp_math(ttype); 01848 register_node_type_cmp_seprgba(ttype); 01849 register_node_type_cmp_combrgba(ttype); 01850 register_node_type_cmp_sephsva(ttype); 01851 register_node_type_cmp_combhsva(ttype); 01852 register_node_type_cmp_sepyuva(ttype); 01853 register_node_type_cmp_combyuva(ttype); 01854 register_node_type_cmp_sepycca(ttype); 01855 register_node_type_cmp_combycca(ttype); 01856 register_node_type_cmp_premulkey(ttype); 01857 01858 register_node_type_cmp_diff_matte(ttype); 01859 register_node_type_cmp_distance_matte(ttype); 01860 register_node_type_cmp_chroma_matte(ttype); 01861 register_node_type_cmp_color_matte(ttype); 01862 register_node_type_cmp_channel_matte(ttype); 01863 register_node_type_cmp_color_spill(ttype); 01864 register_node_type_cmp_luma_matte(ttype); 01865 register_node_type_cmp_doubleedgemask(ttype); 01866 01867 register_node_type_cmp_translate(ttype); 01868 register_node_type_cmp_rotate(ttype); 01869 register_node_type_cmp_scale(ttype); 01870 register_node_type_cmp_flip(ttype); 01871 register_node_type_cmp_crop(ttype); 01872 register_node_type_cmp_displace(ttype); 01873 register_node_type_cmp_mapuv(ttype); 01874 register_node_type_cmp_glare(ttype); 01875 register_node_type_cmp_tonemap(ttype); 01876 register_node_type_cmp_lensdist(ttype); 01877 register_node_type_cmp_transform(ttype); 01878 register_node_type_cmp_stabilize2d(ttype); 01879 register_node_type_cmp_moviedistortion(ttype); 01880 } 01881 01882 static void registerShaderNodes(bNodeTreeType *ttype) 01883 { 01884 register_node_type_frame(ttype); 01885 01886 register_node_type_sh_group(ttype); 01887 //register_node_type_sh_forloop(ttype); 01888 //register_node_type_sh_whileloop(ttype); 01889 01890 register_node_type_sh_output(ttype); 01891 register_node_type_sh_material(ttype); 01892 register_node_type_sh_camera(ttype); 01893 register_node_type_sh_gamma(ttype); 01894 register_node_type_sh_value(ttype); 01895 register_node_type_sh_rgb(ttype); 01896 register_node_type_sh_mix_rgb(ttype); 01897 register_node_type_sh_valtorgb(ttype); 01898 register_node_type_sh_rgbtobw(ttype); 01899 register_node_type_sh_texture(ttype); 01900 register_node_type_sh_normal(ttype); 01901 register_node_type_sh_geom(ttype); 01902 register_node_type_sh_mapping(ttype); 01903 register_node_type_sh_curve_vec(ttype); 01904 register_node_type_sh_curve_rgb(ttype); 01905 register_node_type_sh_math(ttype); 01906 register_node_type_sh_vect_math(ttype); 01907 register_node_type_sh_squeeze(ttype); 01908 //register_node_type_sh_dynamic(ttype); 01909 register_node_type_sh_material_ext(ttype); 01910 register_node_type_sh_invert(ttype); 01911 register_node_type_sh_seprgb(ttype); 01912 register_node_type_sh_combrgb(ttype); 01913 register_node_type_sh_hue_sat(ttype); 01914 01915 register_node_type_sh_attribute(ttype); 01916 register_node_type_sh_geometry(ttype); 01917 register_node_type_sh_light_path(ttype); 01918 register_node_type_sh_fresnel(ttype); 01919 register_node_type_sh_layer_weight(ttype); 01920 register_node_type_sh_tex_coord(ttype); 01921 01922 register_node_type_sh_background(ttype); 01923 register_node_type_sh_bsdf_diffuse(ttype); 01924 register_node_type_sh_bsdf_glossy(ttype); 01925 register_node_type_sh_bsdf_glass(ttype); 01926 register_node_type_sh_bsdf_translucent(ttype); 01927 register_node_type_sh_bsdf_transparent(ttype); 01928 register_node_type_sh_bsdf_velvet(ttype); 01929 register_node_type_sh_emission(ttype); 01930 register_node_type_sh_holdout(ttype); 01931 //register_node_type_sh_volume_transparent(ttype); 01932 //register_node_type_sh_volume_isotropic(ttype); 01933 register_node_type_sh_mix_shader(ttype); 01934 register_node_type_sh_add_shader(ttype); 01935 01936 register_node_type_sh_output_lamp(ttype); 01937 register_node_type_sh_output_material(ttype); 01938 register_node_type_sh_output_world(ttype); 01939 01940 register_node_type_sh_tex_image(ttype); 01941 register_node_type_sh_tex_environment(ttype); 01942 register_node_type_sh_tex_sky(ttype); 01943 register_node_type_sh_tex_noise(ttype); 01944 register_node_type_sh_tex_wave(ttype); 01945 register_node_type_sh_tex_voronoi(ttype); 01946 register_node_type_sh_tex_musgrave(ttype); 01947 register_node_type_sh_tex_gradient(ttype); 01948 register_node_type_sh_tex_magic(ttype); 01949 register_node_type_sh_tex_checker(ttype); 01950 } 01951 01952 static void registerTextureNodes(bNodeTreeType *ttype) 01953 { 01954 register_node_type_frame(ttype); 01955 01956 register_node_type_tex_group(ttype); 01957 // register_node_type_tex_forloop(ttype); 01958 // register_node_type_tex_whileloop(ttype); 01959 01960 register_node_type_tex_math(ttype); 01961 register_node_type_tex_mix_rgb(ttype); 01962 register_node_type_tex_valtorgb(ttype); 01963 register_node_type_tex_rgbtobw(ttype); 01964 register_node_type_tex_valtonor(ttype); 01965 register_node_type_tex_curve_rgb(ttype); 01966 register_node_type_tex_curve_time(ttype); 01967 register_node_type_tex_invert(ttype); 01968 register_node_type_tex_hue_sat(ttype); 01969 register_node_type_tex_coord(ttype); 01970 register_node_type_tex_distance(ttype); 01971 register_node_type_tex_compose(ttype); 01972 register_node_type_tex_decompose(ttype); 01973 01974 register_node_type_tex_output(ttype); 01975 register_node_type_tex_viewer(ttype); 01976 01977 register_node_type_tex_checker(ttype); 01978 register_node_type_tex_texture(ttype); 01979 register_node_type_tex_bricks(ttype); 01980 register_node_type_tex_image(ttype); 01981 01982 register_node_type_tex_rotate(ttype); 01983 register_node_type_tex_translate(ttype); 01984 register_node_type_tex_scale(ttype); 01985 register_node_type_tex_at(ttype); 01986 01987 register_node_type_tex_proc_voronoi(ttype); 01988 register_node_type_tex_proc_blend(ttype); 01989 register_node_type_tex_proc_magic(ttype); 01990 register_node_type_tex_proc_marble(ttype); 01991 register_node_type_tex_proc_clouds(ttype); 01992 register_node_type_tex_proc_wood(ttype); 01993 register_node_type_tex_proc_musgrave(ttype); 01994 register_node_type_tex_proc_noise(ttype); 01995 register_node_type_tex_proc_stucci(ttype); 01996 register_node_type_tex_proc_distnoise(ttype); 01997 } 01998 01999 static void free_dynamic_typeinfo(bNodeType *ntype) 02000 { 02001 if(ntype->type==NODE_DYNAMIC) { 02002 if(ntype->inputs) { 02003 MEM_freeN(ntype->inputs); 02004 } 02005 if(ntype->outputs) { 02006 MEM_freeN(ntype->outputs); 02007 } 02008 if(ntype->name) { 02009 MEM_freeN((void *)ntype->name); 02010 } 02011 } 02012 } 02013 02014 static void free_typeinfos(ListBase *list) 02015 { 02016 bNodeType *ntype, *next; 02017 for(ntype=list->first; ntype; ntype=next) { 02018 next = ntype->next; 02019 02020 if(ntype->type==NODE_DYNAMIC) 02021 free_dynamic_typeinfo(ntype); 02022 02023 if(ntype->needs_free) 02024 MEM_freeN(ntype); 02025 } 02026 } 02027 02028 void init_nodesystem(void) 02029 { 02030 registerCompositNodes(ntreeGetType(NTREE_COMPOSIT)); 02031 registerShaderNodes(ntreeGetType(NTREE_SHADER)); 02032 registerTextureNodes(ntreeGetType(NTREE_TEXTURE)); 02033 } 02034 02035 void free_nodesystem(void) 02036 { 02037 free_typeinfos(&ntreeGetType(NTREE_COMPOSIT)->node_types); 02038 free_typeinfos(&ntreeGetType(NTREE_SHADER)->node_types); 02039 free_typeinfos(&ntreeGetType(NTREE_TEXTURE)->node_types); 02040 } 02041 02042 /* called from unlink_scene, when deleting a scene goes over all scenes 02043 * other than the input, checks if they have render layer nodes referencing 02044 * the to-be-deleted scene, and resets them to NULL. */ 02045 02046 /* XXX needs to get current scene then! */ 02047 void clear_scene_in_nodes(Main *bmain, Scene *sce) 02048 { 02049 Scene *sce1; 02050 bNode *node; 02051 02052 for(sce1= bmain->scene.first; sce1; sce1=sce1->id.next) { 02053 if(sce1!=sce) { 02054 if(sce1->nodetree) { 02055 for(node= sce1->nodetree->nodes.first; node; node= node->next) { 02056 if(node->type==CMP_NODE_R_LAYERS) { 02057 Scene *nodesce= (Scene *)node->id; 02058 02059 if (nodesce==sce) node->id = NULL; 02060 } 02061 } 02062 } 02063 } 02064 } 02065 } 02066