|
Blender
V2.59
|
00001 /* 00002 * $Id: node.c 38263 2011-07-09 17:03:35Z ton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2005 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): Bob Holcomb. 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #if 0 /* pynodes commented for now */ 00036 # ifdef WITH_PYTHON 00037 # include <Python.h> 00038 # endif 00039 #endif 00040 00041 #include "MEM_guardedalloc.h" 00042 00043 #include <stdlib.h> 00044 #include <stddef.h> 00045 #include <string.h> 00046 #include <limits.h> 00047 00048 #include "DNA_anim_types.h" 00049 #include "DNA_action_types.h" 00050 #include "DNA_node_types.h" 00051 00052 #include "BLI_listbase.h" 00053 00054 #include "RNA_access.h" 00055 00056 #include "BKE_animsys.h" 00057 #include "BKE_action.h" 00058 #include "BKE_fcurve.h" 00059 #include "BKE_node.h" 00060 #include "BKE_utildefines.h" 00061 00062 #include "PIL_time.h" 00063 00064 #include "CMP_node.h" 00065 #include "intern/CMP_util.h" /* stupid include path... */ 00066 00067 #include "SHD_node.h" 00068 #include "TEX_node.h" 00069 #include "intern/TEX_util.h" 00070 00071 #include "GPU_material.h" 00072 00073 static ListBase empty_list = {NULL, NULL}; 00074 ListBase node_all_composit = {NULL, NULL}; 00075 ListBase node_all_shaders = {NULL, NULL}; 00076 ListBase node_all_textures = {NULL, NULL}; 00077 00078 /* ************** Type stuff ********** */ 00079 00080 static bNodeType *node_get_type(bNodeTree *ntree, int type, ID *id) 00081 { 00082 bNodeType *ntype = ntree->alltypes.first; 00083 for(; ntype; ntype= ntype->next) 00084 if(ntype->type==type && id==ntype->id ) 00085 return ntype; 00086 00087 return NULL; 00088 } 00089 00090 void ntreeInitTypes(bNodeTree *ntree) 00091 { 00092 bNode *node, *next; 00093 00094 if(ntree->type==NTREE_SHADER) 00095 ntree->alltypes= node_all_shaders; 00096 else if(ntree->type==NTREE_COMPOSIT) 00097 ntree->alltypes= node_all_composit; 00098 else if(ntree->type==NTREE_TEXTURE) 00099 ntree->alltypes= node_all_textures; 00100 else { 00101 ntree->alltypes= empty_list; 00102 printf("Error: no type definitions for nodes\n"); 00103 } 00104 00105 for(node= ntree->nodes.first; node; node= next) { 00106 next= node->next; 00107 if(node->type==NODE_DYNAMIC) { 00108 bNodeType *stype= NULL; 00109 if(node->id==NULL) { /* empty script node */ 00110 stype= node_get_type(ntree, node->type, NULL); 00111 } else { /* not an empty script node */ 00112 stype= node_get_type(ntree, node->type, node->id); 00113 if(!stype) { 00114 stype= node_get_type(ntree, node->type, NULL); 00115 /* needed info if the pynode script fails now: */ 00116 if (node->id) node->storage= ntree; 00117 } else { 00118 node->custom1= 0; 00119 node->custom1= BSET(node->custom1,NODE_DYNAMIC_ADDEXIST); 00120 } 00121 } 00122 node->typeinfo= stype; 00123 if(node->typeinfo) 00124 node->typeinfo->initfunc(node); 00125 } else { 00126 node->typeinfo= node_get_type(ntree, node->type, NULL); 00127 } 00128 00129 if(node->typeinfo==NULL) { 00130 printf("Error: Node type %s doesn't exist anymore, removed\n", node->name); 00131 nodeFreeNode(ntree, node); 00132 } 00133 } 00134 00135 ntree->init |= NTREE_TYPE_INIT; 00136 } 00137 00138 /* updates node with (modified) bNodeType.. this should be done for all trees */ 00139 void ntreeUpdateType(bNodeTree *ntree, bNodeType *ntype) 00140 { 00141 bNode *node; 00142 00143 for(node= ntree->nodes.first; node; node= node->next) { 00144 if(node->typeinfo== ntype) { 00145 nodeUpdateType(ntree, node, ntype); 00146 } 00147 } 00148 } 00149 00150 /* only used internal... we depend on type definitions! */ 00151 static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype) 00152 { 00153 bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock"); 00154 00155 BLI_strncpy(sock->name, stype->name, NODE_MAXSTR); 00156 if(stype->limit==0) sock->limit= 0xFFF; 00157 else sock->limit= stype->limit; 00158 sock->type= stype->type; 00159 00160 sock->ns.vec[0]= stype->val1; 00161 sock->ns.vec[1]= stype->val2; 00162 sock->ns.vec[2]= stype->val3; 00163 sock->ns.vec[3]= stype->val4; 00164 sock->ns.min= stype->min; 00165 sock->ns.max= stype->max; 00166 00167 if(lb) 00168 BLI_addtail(lb, sock); 00169 00170 return sock; 00171 } 00172 00173 static bNodeSocket *node_add_group_socket(ListBase *lb, bNodeSocket *gsock) 00174 { 00175 bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock"); 00176 00177 /* make a copy of the group socket */ 00178 *sock = *gsock; 00179 sock->link = NULL; 00180 sock->next = sock->prev = NULL; 00181 sock->new_sock = NULL; 00182 sock->ns.data = NULL; 00183 00184 sock->own_index = gsock->own_index; 00185 sock->groupsock = gsock; 00186 /* XXX hack: group socket input/output roles are inverted internally, 00187 * need to change the limit value when making actual node sockets from them. 00188 */ 00189 sock->limit = (gsock->limit==1 ? 0xFFF : 1); 00190 00191 if(lb) 00192 BLI_addtail(lb, sock); 00193 00194 return sock; 00195 } 00196 00197 static void node_rem_socket(bNodeTree *ntree, ListBase *lb, bNodeSocket *sock) 00198 { 00199 bNodeLink *link, *next; 00200 00201 for(link= ntree->links.first; link; link= next) { 00202 next= link->next; 00203 if(link->fromsock==sock || link->tosock==sock) { 00204 nodeRemLink(ntree, link); 00205 } 00206 } 00207 00208 BLI_remlink(lb, sock); 00209 MEM_freeN(sock); 00210 } 00211 00212 static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype) 00213 { 00214 bNodeSocket *sock; 00215 00216 for(sock= lb->first; sock; sock= sock->next) { 00217 if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0) 00218 break; 00219 } 00220 if(sock) { 00221 sock->type= stype->type; /* in future, read this from tydefs! */ 00222 if(stype->limit==0) sock->limit= 0xFFF; 00223 else sock->limit= stype->limit; 00224 00225 sock->ns.min= stype->min; 00226 sock->ns.max= stype->max; 00227 00228 BLI_remlink(lb, sock); 00229 00230 return sock; 00231 } 00232 else { 00233 return node_add_socket_type(NULL, stype); 00234 } 00235 } 00236 00237 static bNodeSocket *verify_group_socket(ListBase *lb, bNodeSocket *gsock) 00238 { 00239 bNodeSocket *sock; 00240 00241 for(sock= lb->first; sock; sock= sock->next) { 00242 if(sock->own_index==gsock->own_index) 00243 break; 00244 } 00245 if(sock) { 00246 sock->groupsock = gsock; 00247 00248 strcpy(sock->name, gsock->name); 00249 sock->type= gsock->type; 00250 00251 /* XXX hack: group socket input/output roles are inverted internally, 00252 * need to change the limit value when making actual node sockets from them. 00253 */ 00254 sock->limit = (gsock->limit==1 ? 0xFFF : 1); 00255 00256 sock->ns.min= gsock->ns.min; 00257 sock->ns.max= gsock->ns.max; 00258 00259 BLI_remlink(lb, sock); 00260 00261 return sock; 00262 } 00263 else { 00264 return node_add_group_socket(NULL, gsock); 00265 } 00266 } 00267 00268 static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *stype_first) 00269 { 00270 bNodeSocketType *stype; 00271 00272 /* no inputs anymore? */ 00273 if(stype_first==NULL) { 00274 while(lb->first) 00275 node_rem_socket(ntree, lb, lb->first); 00276 } 00277 else { 00278 /* step by step compare */ 00279 stype= stype_first; 00280 while(stype->type != -1) { 00281 stype->sock= verify_socket(lb, stype); 00282 stype++; 00283 } 00284 /* leftovers are removed */ 00285 while(lb->first) 00286 node_rem_socket(ntree, lb, lb->first); 00287 /* and we put back the verified sockets */ 00288 stype= stype_first; 00289 while(stype->type != -1) { 00290 BLI_addtail(lb, stype->sock); 00291 stype++; 00292 } 00293 } 00294 } 00295 00296 static void verify_group_socket_list(bNodeTree *ntree, ListBase *lb, ListBase *glb) 00297 { 00298 bNodeSocket *gsock; 00299 00300 /* step by step compare */ 00301 for (gsock= glb->first; gsock; gsock=gsock->next) { 00302 /* abusing new_sock pointer for verification here! only used inside this function */ 00303 gsock->new_sock= verify_group_socket(lb, gsock); 00304 } 00305 /* leftovers are removed */ 00306 while(lb->first) 00307 node_rem_socket(ntree, lb, lb->first); 00308 /* and we put back the verified sockets */ 00309 for (gsock= glb->first; gsock; gsock=gsock->next) { 00310 BLI_addtail(lb, gsock->new_sock); 00311 gsock->new_sock = NULL; 00312 } 00313 } 00314 00315 void nodeVerifyType(bNodeTree *ntree, bNode *node) 00316 { 00317 /* node groups don't have static sock lists, but use external sockets from the tree instead */ 00318 if (node->type==NODE_GROUP) { 00319 bNodeTree *ngroup= (bNodeTree*)node->id; 00320 if (ngroup) { 00321 verify_group_socket_list(ntree, &node->inputs, &ngroup->inputs); 00322 verify_group_socket_list(ntree, &node->outputs, &ngroup->outputs); 00323 } 00324 } 00325 else { 00326 bNodeType *ntype= node->typeinfo; 00327 if(ntype) { 00328 verify_socket_list(ntree, &node->inputs, ntype->inputs); 00329 verify_socket_list(ntree, &node->outputs, ntype->outputs); 00330 } 00331 } 00332 } 00333 00334 void ntreeVerifyTypes(bNodeTree *ntree) 00335 { 00336 bNode *node; 00337 00338 /* if((ntree->init & NTREE_TYPE_INIT)==0) */ 00339 ntreeInitTypes(ntree); 00340 00341 /* check inputs and outputs, and remove or insert them */ 00342 for(node= ntree->nodes.first; node; node= node->next) 00343 nodeVerifyType(ntree, node); 00344 00345 } 00346 00347 /* ************** Group stuff ********** */ 00348 00349 /* XXX group typeinfo struct is used directly in ntreeMakeOwnType, needs cleanup */ 00350 static bNodeType ntype_group; 00351 00352 /* groups display their internal tree name as label */ 00353 static const char *group_label(bNode *node) 00354 { 00355 return (node->id)? node->id->name+2: "Missing Datablock"; 00356 } 00357 00358 void register_node_type_group(ListBase *lb) 00359 { 00360 node_type_base(&ntype_group, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS, NULL, NULL); 00361 node_type_size(&ntype_group, 120, 60, 200); 00362 node_type_label(&ntype_group, group_label); 00363 00364 nodeRegisterType(lb, &ntype_group); 00365 } 00366 00367 static bNodeSocket *find_group_node_input(bNode *gnode, bNodeSocket *gsock) 00368 { 00369 bNodeSocket *sock; 00370 for (sock=gnode->inputs.first; sock; sock=sock->next) 00371 if (sock->groupsock == gsock) 00372 return sock; 00373 return NULL; 00374 } 00375 00376 static bNodeSocket *find_group_node_output(bNode *gnode, bNodeSocket *gsock) 00377 { 00378 bNodeSocket *sock; 00379 for (sock=gnode->outputs.first; sock; sock=sock->next) 00380 if (sock->groupsock == gsock) 00381 return sock; 00382 return NULL; 00383 } 00384 00385 bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) 00386 { 00387 bNodeLink *link, *linkn; 00388 bNode *node, *gnode, *nextn; 00389 bNodeTree *ngroup; 00390 bNodeSocket *gsock; 00391 ListBase anim_basepaths = {NULL, NULL}; 00392 float min[2], max[2]; 00393 int totnode=0; 00394 00395 INIT_MINMAX2(min, max); 00396 00397 /* is there something to group? also do some clearing */ 00398 for(node= ntree->nodes.first; node; node= node->next) { 00399 if(node->flag & NODE_SELECT) { 00400 /* no groups in groups */ 00401 if(node->type==NODE_GROUP) 00402 return NULL; 00403 DO_MINMAX2( (&node->locx), min, max); 00404 totnode++; 00405 } 00406 node->done= 0; 00407 } 00408 if(totnode==0) return NULL; 00409 00410 /* check if all connections are OK, no unselected node has both 00411 inputs and outputs to a selection */ 00412 for(link= ntree->links.first; link; link= link->next) { 00413 if(link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT) 00414 link->tonode->done |= 1; 00415 if(link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT) 00416 link->fromnode->done |= 2; 00417 } 00418 00419 for(node= ntree->nodes.first; node; node= node->next) { 00420 if((node->flag & NODE_SELECT)==0) 00421 if(node->done==3) 00422 break; 00423 } 00424 if(node) 00425 return NULL; 00426 00427 /* OK! new nodetree */ 00428 ngroup= ntreeAddTree("NodeGroup", ntree->type, TRUE); 00429 00430 /* move nodes over */ 00431 for(node= ntree->nodes.first; node; node= nextn) { 00432 nextn= node->next; 00433 if(node->flag & NODE_SELECT) { 00434 /* keep track of this node's RNA "base" path (the part of the pat identifying the node) 00435 * if the old nodetree has animation data which potentially covers this node 00436 */ 00437 if (ntree->adt) { 00438 PointerRNA ptr; 00439 char *path; 00440 00441 RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); 00442 path = RNA_path_from_ID_to_struct(&ptr); 00443 00444 if (path) 00445 BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); 00446 } 00447 00448 /* change node-collection membership */ 00449 BLI_remlink(&ntree->nodes, node); 00450 BLI_addtail(&ngroup->nodes, node); 00451 00452 node->locx-= 0.5f*(min[0]+max[0]); 00453 node->locy-= 0.5f*(min[1]+max[1]); 00454 } 00455 } 00456 00457 /* move animation data over */ 00458 if (ntree->adt) { 00459 LinkData *ld, *ldn=NULL; 00460 00461 BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths); 00462 00463 /* paths + their wrappers need to be freed */ 00464 for (ld = anim_basepaths.first; ld; ld = ldn) { 00465 ldn = ld->next; 00466 00467 MEM_freeN(ld->data); 00468 BLI_freelinkN(&anim_basepaths, ld); 00469 } 00470 } 00471 00472 /* make group node */ 00473 gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup, NULL); 00474 gnode->locx= 0.5f*(min[0]+max[0]); 00475 gnode->locy= 0.5f*(min[1]+max[1]); 00476 00477 /* relink external sockets */ 00478 for(link= ntree->links.first; link; link= linkn) { 00479 linkn= link->next; 00480 00481 if(link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) { 00482 BLI_remlink(&ntree->links, link); 00483 BLI_addtail(&ngroup->links, link); 00484 } 00485 else if(link->tonode && (link->tonode->flag & NODE_SELECT)) { 00486 gsock = nodeGroupExposeSocket(ngroup, link->tosock, SOCK_IN); 00487 link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock); 00488 link->tosock = node_add_group_socket(&gnode->inputs, gsock); 00489 link->tonode = gnode; 00490 } 00491 else if(link->fromnode && (link->fromnode->flag & NODE_SELECT)) { 00492 /* search for existing group node socket */ 00493 for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) 00494 if (gsock->link && gsock->link->fromsock==link->fromsock) 00495 break; 00496 if (!gsock) { 00497 gsock = nodeGroupExposeSocket(ngroup, link->fromsock, SOCK_OUT); 00498 gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock); 00499 link->fromsock = node_add_group_socket(&gnode->outputs, gsock); 00500 } 00501 else 00502 link->fromsock = find_group_node_output(gnode, gsock); 00503 link->fromnode = gnode; 00504 } 00505 } 00506 00507 /* update node levels */ 00508 ntreeSolveOrder(ntree); 00509 00510 return gnode; 00511 } 00512 00513 /* here's a nasty little one, need to check users... */ 00514 /* should become callbackable... */ 00515 void nodeGroupVerify(bNodeTree *ngroup) 00516 { 00517 /* group changed, so we rebuild the type definition */ 00518 // ntreeMakeGroupSockets(ngroup); 00519 00520 if(ngroup->type==NTREE_SHADER) { 00521 Material *ma; 00522 for(ma= G.main->mat.first; ma; ma= ma->id.next) { 00523 if(ma->nodetree) { 00524 bNode *node; 00525 for(node= ma->nodetree->nodes.first; node; node= node->next) 00526 if(node->id == (ID *)ngroup) 00527 nodeVerifyType(ma->nodetree, node); 00528 } 00529 } 00530 } 00531 else if(ngroup->type==NTREE_COMPOSIT) { 00532 Scene *sce; 00533 for(sce= G.main->scene.first; sce; sce= sce->id.next) { 00534 if(sce->nodetree) { 00535 bNode *node; 00536 for(node= sce->nodetree->nodes.first; node; node= node->next) 00537 if(node->id == (ID *)ngroup) 00538 nodeVerifyType(sce->nodetree, node); 00539 } 00540 } 00541 } 00542 else if(ngroup->type==NTREE_TEXTURE) { 00543 Tex *tx; 00544 for(tx= G.main->tex.first; tx; tx= tx->id.next) { 00545 if(tx->nodetree) { 00546 bNode *node; 00547 for(node= tx->nodetree->nodes.first; node; node= node->next) 00548 if(node->id == (ID *)ngroup) 00549 nodeVerifyType(tx->nodetree, node); 00550 } 00551 } 00552 } 00553 } 00554 00555 /* also to check all users of groups. Now only used in editor for hide/unhide */ 00556 /* should become callbackable? */ 00557 void nodeGroupSocketUseFlags(bNodeTree *ngroup) 00558 { 00559 bNode *node; 00560 bNodeSocket *sock; 00561 00562 /* clear flags */ 00563 for(node= ngroup->nodes.first; node; node= node->next) { 00564 for(sock= node->inputs.first; sock; sock= sock->next) 00565 sock->flag &= ~SOCK_IN_USE; 00566 for(sock= node->outputs.first; sock; sock= sock->next) 00567 sock->flag &= ~SOCK_IN_USE; 00568 } 00569 00570 /* tag all thats in use */ 00571 if(ngroup->type==NTREE_SHADER) { 00572 Material *ma; 00573 for(ma= G.main->mat.first; ma; ma= ma->id.next) { 00574 if(ma->nodetree) { 00575 for(node= ma->nodetree->nodes.first; node; node= node->next) { 00576 if(node->id==&ngroup->id) { 00577 for(sock= node->inputs.first; sock; sock= sock->next) 00578 if(sock->link) 00579 if(sock->groupsock) 00580 sock->groupsock->flag |= SOCK_IN_USE; 00581 for(sock= node->outputs.first; sock; sock= sock->next) 00582 if(nodeCountSocketLinks(ma->nodetree, sock)) 00583 if(sock->groupsock) 00584 sock->groupsock->flag |= SOCK_IN_USE; 00585 } 00586 } 00587 } 00588 } 00589 } 00590 else if(ngroup->type==NTREE_COMPOSIT) { 00591 Scene *sce; 00592 for(sce= G.main->scene.first; sce; sce= sce->id.next) { 00593 if(sce->nodetree) { 00594 for(node= sce->nodetree->nodes.first; node; node= node->next) { 00595 if(node->id==(ID *)ngroup) { 00596 for(sock= node->inputs.first; sock; sock= sock->next) 00597 if(sock->link) 00598 if(sock->groupsock) 00599 sock->groupsock->flag |= SOCK_IN_USE; 00600 for(sock= node->outputs.first; sock; sock= sock->next) 00601 if(nodeCountSocketLinks(sce->nodetree, sock)) 00602 if(sock->groupsock) 00603 sock->groupsock->flag |= SOCK_IN_USE; 00604 } 00605 } 00606 } 00607 } 00608 } 00609 else if(ngroup->type==NTREE_TEXTURE) { 00610 Tex *tx; 00611 for(tx= G.main->tex.first; tx; tx= tx->id.next) { 00612 if(tx->nodetree) { 00613 for(node= tx->nodetree->nodes.first; node; node= node->next) { 00614 if(node->id==(ID *)ngroup) { 00615 for(sock= node->inputs.first; sock; sock= sock->next) 00616 if(sock->link) 00617 if(sock->groupsock) 00618 sock->groupsock->flag |= SOCK_IN_USE; 00619 for(sock= node->outputs.first; sock; sock= sock->next) 00620 if(nodeCountSocketLinks(tx->nodetree, sock)) 00621 if(sock->groupsock) 00622 sock->groupsock->flag |= SOCK_IN_USE; 00623 } 00624 } 00625 } 00626 } 00627 } 00628 00629 } 00630 /* finds a node based on its name */ 00631 bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name) 00632 { 00633 return BLI_findstring(&ntree->nodes, name, offsetof(bNode, name)); 00634 } 00635 00636 /* finds a node based on given socket */ 00637 int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockindex, int *in_out) 00638 { 00639 bNode *node; 00640 bNodeSocket *tsock; 00641 int index= 0; 00642 00643 for(node= ntree->nodes.first; node; node= node->next) { 00644 for(index=0, tsock= node->inputs.first; tsock; tsock= tsock->next, index++) { 00645 if(tsock==sock) { 00646 if (in_out) *in_out= SOCK_IN; 00647 break; 00648 } 00649 } 00650 if(tsock) 00651 break; 00652 for(index=0, tsock= node->outputs.first; tsock; tsock= tsock->next, index++) { 00653 if(tsock==sock) { 00654 if (in_out) *in_out= SOCK_OUT; 00655 break; 00656 } 00657 } 00658 if(tsock) 00659 break; 00660 } 00661 00662 if(node) { 00663 *nodep= node; 00664 if(sockindex) *sockindex= index; 00665 return 1; 00666 } 00667 00668 *nodep= NULL; 00669 return 0; 00670 } 00671 00672 /* returns 1 if its OK */ 00673 int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode) 00674 { 00675 bNodeLink *link, *linkn; 00676 bNode *node, *nextn; 00677 bNodeTree *ngroup, *wgroup; 00678 ListBase anim_basepaths = {NULL, NULL}; 00679 00680 ngroup= (bNodeTree *)gnode->id; 00681 if(ngroup==NULL) return 0; 00682 00683 /* clear new pointers, set in copytree */ 00684 for(node= ntree->nodes.first; node; node= node->next) 00685 node->new_node= NULL; 00686 00687 /* wgroup is a temporary copy of the NodeTree we're merging in 00688 * - all of wgroup's nodes are transferred across to their new home 00689 * - ngroup (i.e. the source NodeTree) is left unscathed 00690 */ 00691 wgroup= ntreeCopyTree(ngroup); 00692 00693 /* add the nodes into the ntree */ 00694 for(node= wgroup->nodes.first; node; node= nextn) { 00695 nextn= node->next; 00696 00697 /* keep track of this node's RNA "base" path (the part of the pat identifying the node) 00698 * if the old nodetree has animation data which potentially covers this node 00699 */ 00700 if (wgroup->adt) { 00701 PointerRNA ptr; 00702 char *path; 00703 00704 RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr); 00705 path = RNA_path_from_ID_to_struct(&ptr); 00706 00707 if (path) 00708 BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); 00709 } 00710 00711 /* migrate node */ 00712 BLI_remlink(&wgroup->nodes, node); 00713 BLI_addtail(&ntree->nodes, node); 00714 00715 node->locx+= gnode->locx; 00716 node->locy+= gnode->locy; 00717 00718 node->flag |= NODE_SELECT; 00719 } 00720 00721 /* restore external links to and from the gnode */ 00722 for(link= ntree->links.first; link; link= link->next) { 00723 if (link->fromnode==gnode) { 00724 if (link->fromsock->groupsock) { 00725 bNodeSocket *gsock= link->fromsock->groupsock; 00726 if (gsock->link) { 00727 if (gsock->link->fromnode) { 00728 /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */ 00729 link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL); 00730 link->fromsock = gsock->link->fromsock->new_sock; 00731 } 00732 else { 00733 /* group output directly maps to group input */ 00734 bNodeSocket *insock= find_group_node_input(gnode, gsock->link->fromsock); 00735 if (insock->link) { 00736 link->fromnode = insock->link->fromnode; 00737 link->fromsock = insock->link->fromsock; 00738 } 00739 } 00740 } 00741 else { 00742 /* constant group output: copy the stack value to the external socket. 00743 * the link is kept here until all possible external users have been fixed. 00744 */ 00745 QUATCOPY(link->tosock->ns.vec, gsock->ns.vec); 00746 } 00747 } 00748 } 00749 } 00750 /* remove internal output links, these are not used anymore */ 00751 for(link=wgroup->links.first; link; link= linkn) { 00752 linkn = link->next; 00753 if (!link->tonode) 00754 nodeRemLink(wgroup, link); 00755 } 00756 /* restore links from internal nodes */ 00757 for(link= wgroup->links.first; link; link= link->next) { 00758 /* indicates link to group input */ 00759 if (!link->fromnode) { 00760 /* NB: can't use find_group_node_input here, 00761 * because gnode sockets still point to the old tree! 00762 */ 00763 bNodeSocket *insock; 00764 for (insock= gnode->inputs.first; insock; insock= insock->next) 00765 if (insock->groupsock->new_sock == link->fromsock) 00766 break; 00767 if (insock->link) { 00768 link->fromnode = insock->link->fromnode; 00769 link->fromsock = insock->link->fromsock; 00770 } 00771 else { 00772 /* uses group constant input. copy the input value and remove the dead link. */ 00773 QUATCOPY(link->tosock->ns.vec, insock->ns.vec); 00774 nodeRemLink(wgroup, link); 00775 } 00776 } 00777 } 00778 00779 /* add internal links to the ntree */ 00780 for(link= wgroup->links.first; link; link= linkn) { 00781 linkn= link->next; 00782 BLI_remlink(&wgroup->links, link); 00783 BLI_addtail(&ntree->links, link); 00784 } 00785 00786 /* and copy across the animation */ 00787 if (wgroup->adt) { 00788 LinkData *ld, *ldn=NULL; 00789 bAction *waction; 00790 00791 /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */ 00792 waction = wgroup->adt->action = copy_action(wgroup->adt->action); 00793 00794 /* now perform the moving */ 00795 BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths); 00796 00797 /* paths + their wrappers need to be freed */ 00798 for (ld = anim_basepaths.first; ld; ld = ldn) { 00799 ldn = ld->next; 00800 00801 MEM_freeN(ld->data); 00802 BLI_freelinkN(&anim_basepaths, ld); 00803 } 00804 00805 /* free temp action too */ 00806 free_libblock(&G.main->action, waction); 00807 } 00808 00809 /* delete the group instance. this also removes old input links! */ 00810 nodeFreeNode(ntree, gnode); 00811 00812 /* free the group tree (takes care of user count) */ 00813 free_libblock(&G.main->nodetree, wgroup); 00814 00815 /* solve order goes fine, but the level tags not... doing it twice works for now. solve this once */ 00816 /* XXX is this still necessary with new groups? it may have been caused by non-updated sock->link pointers. lukas */ 00817 ntreeSolveOrder(ntree); 00818 ntreeSolveOrder(ntree); 00819 00820 return 1; 00821 } 00822 00823 void nodeGroupCopy(bNode *gnode) 00824 { 00825 bNodeSocket *sock; 00826 00827 gnode->id->us--; 00828 gnode->id= (ID *)ntreeCopyTree((bNodeTree *)gnode->id); 00829 00830 /* new_sock was set in nodeCopyNode */ 00831 for(sock=gnode->inputs.first; sock; sock=sock->next) 00832 if(sock->groupsock) 00833 sock->groupsock= sock->groupsock->new_sock; 00834 00835 for(sock=gnode->outputs.first; sock; sock=sock->next) 00836 if(sock->groupsock) 00837 sock->groupsock= sock->groupsock->new_sock; 00838 } 00839 00840 bNodeSocket *nodeGroupAddSocket(bNodeTree *ngroup, const char *name, int type, int in_out) 00841 { 00842 bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket"); 00843 00844 strncpy(gsock->name, name, sizeof(gsock->name)); 00845 gsock->type = type; 00846 gsock->ns.sockettype = type; 00847 gsock->ns.min = INT_MIN; 00848 gsock->ns.max = INT_MAX; 00849 zero_v4(gsock->ns.vec); 00850 gsock->ns.data = NULL; 00851 gsock->flag = 0; 00852 00853 gsock->next = gsock->prev = NULL; 00854 gsock->new_sock = NULL; 00855 gsock->link = NULL; 00856 gsock->ns.data = NULL; 00857 /* assign new unique index */ 00858 gsock->own_index = ngroup->cur_index++; 00859 gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1); 00860 00861 BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock); 00862 00863 return gsock; 00864 } 00865 00866 bNodeSocket *nodeGroupExposeSocket(bNodeTree *ngroup, bNodeSocket *sock, int in_out) 00867 { 00868 bNodeSocket *gsock= nodeGroupAddSocket(ngroup, sock->name, sock->type, in_out); 00869 /* initialize the default socket value */ 00870 QUATCOPY(gsock->ns.vec, sock->ns.vec); 00871 return gsock; 00872 } 00873 00874 void nodeGroupExposeAllSockets(bNodeTree *ngroup) 00875 { 00876 bNode *node; 00877 bNodeSocket *sock, *gsock; 00878 00879 for (node=ngroup->nodes.first; node; node=node->next) { 00880 for (sock=node->inputs.first; sock; sock=sock->next) { 00881 if (!sock->link && !(sock->flag & SOCK_HIDDEN)) { 00882 gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_IN); 00883 /* initialize the default socket value */ 00884 QUATCOPY(gsock->ns.vec, sock->ns.vec); 00885 sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock); 00886 } 00887 } 00888 for (sock=node->outputs.first; sock; sock=sock->next) { 00889 if (nodeCountSocketLinks(ngroup, sock)==0 && !(sock->flag & SOCK_HIDDEN)) { 00890 gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_OUT); 00891 /* initialize the default socket value */ 00892 QUATCOPY(gsock->ns.vec, sock->ns.vec); 00893 gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock); 00894 } 00895 } 00896 } 00897 } 00898 00899 void nodeGroupRemoveSocket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out) 00900 { 00901 nodeRemSocketLinks(ngroup, gsock); 00902 switch (in_out) { 00903 case SOCK_IN: BLI_remlink(&ngroup->inputs, gsock); break; 00904 case SOCK_OUT: BLI_remlink(&ngroup->outputs, gsock); break; 00905 } 00906 MEM_freeN(gsock); 00907 } 00908 00909 /* ************** Add stuff ********** */ 00910 void nodeAddSockets(bNode *node, bNodeType *ntype) 00911 { 00912 if (node->type==NODE_GROUP) { 00913 bNodeTree *ntree= (bNodeTree*)node->id; 00914 if (ntree) { 00915 bNodeSocket *gsock; 00916 for (gsock=ntree->inputs.first; gsock; gsock=gsock->next) 00917 node_add_group_socket(&node->inputs, gsock); 00918 for (gsock=ntree->outputs.first; gsock; gsock=gsock->next) 00919 node_add_group_socket(&node->outputs, gsock); 00920 } 00921 } 00922 else { 00923 bNodeSocketType *stype; 00924 00925 if(ntype->inputs) { 00926 stype= ntype->inputs; 00927 while(stype->type != -1) { 00928 node_add_socket_type(&node->inputs, stype); 00929 stype++; 00930 } 00931 } 00932 if(ntype->outputs) { 00933 stype= ntype->outputs; 00934 while(stype->type != -1) { 00935 node_add_socket_type(&node->outputs, stype); 00936 stype++; 00937 } 00938 } 00939 } 00940 } 00941 00942 /* Find the first available, non-duplicate name for a given node */ 00943 void nodeUniqueName(bNodeTree *ntree, bNode *node) 00944 { 00945 BLI_uniquename(&ntree->nodes, node, "Node", '.', offsetof(bNode, name), sizeof(node->name)); 00946 } 00947 00948 bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id) 00949 { 00950 bNode *node= NULL; 00951 bNodeType *ntype= NULL; 00952 00953 if (ngroup && BLI_findindex(&G.main->nodetree, ngroup)==-1) { 00954 printf("nodeAddNodeType() error: '%s' not in main->nodetree\n", ngroup->id.name); 00955 return NULL; 00956 } 00957 00958 if(type>=NODE_DYNAMIC_MENU) { 00959 int a=0, idx= type-NODE_DYNAMIC_MENU; 00960 ntype= ntree->alltypes.first; 00961 while(ntype) { 00962 if(ntype->type==NODE_DYNAMIC) { 00963 if(a==idx) 00964 break; 00965 a++; 00966 } 00967 ntype= ntype->next; 00968 } 00969 } else 00970 ntype= node_get_type(ntree, type, id); 00971 00972 if(ntype == NULL) { 00973 printf("nodeAddNodeType() error: '%d' type invalid\n", type); 00974 return NULL; 00975 } 00976 00977 node= MEM_callocN(sizeof(bNode), "new node"); 00978 BLI_addtail(&ntree->nodes, node); 00979 node->typeinfo= ntype; 00980 if(type>=NODE_DYNAMIC_MENU) 00981 node->custom2= type; /* for node_dynamic_init */ 00982 00983 if(ngroup) 00984 BLI_strncpy(node->name, ngroup->id.name+2, NODE_MAXSTR); 00985 else if(type>NODE_DYNAMIC_MENU) { 00986 BLI_strncpy(node->name, ntype->id->name+2, NODE_MAXSTR); 00987 } 00988 else 00989 BLI_strncpy(node->name, ntype->name, NODE_MAXSTR); 00990 00991 nodeUniqueName(ntree, node); 00992 00993 node->type= ntype->type; 00994 node->flag= NODE_SELECT|ntype->flag; 00995 node->width= ntype->width; 00996 node->miniwidth= 42.0f; /* small value only, allows print of first chars */ 00997 00998 if(type==NODE_GROUP) 00999 node->id= (ID *)ngroup; 01000 01001 /* need init handler later? */ 01002 /* got it-bob*/ 01003 if(ntype->initfunc!=NULL) 01004 ntype->initfunc(node); 01005 01006 nodeAddSockets(node, ntype); 01007 01008 return node; 01009 } 01010 01011 void nodeMakeDynamicType(bNode *node) 01012 { 01013 /* find SH_DYNAMIC_NODE ntype */ 01014 bNodeType *ntype= node_all_shaders.first; 01015 while(ntype) { 01016 if(ntype->type==NODE_DYNAMIC && ntype->id==NULL) 01017 break; 01018 ntype= ntype->next; 01019 } 01020 01021 /* make own type struct to fill */ 01022 if(ntype) { 01023 /*node->typeinfo= MEM_dupallocN(ntype);*/ 01024 bNodeType *newtype= MEM_callocN(sizeof(bNodeType), "dynamic bNodeType"); 01025 *newtype= *ntype; 01026 newtype->name= BLI_strdup(ntype->name); 01027 node->typeinfo= newtype; 01028 } 01029 } 01030 01031 void nodeUpdateType(bNodeTree *ntree, bNode* node, bNodeType *ntype) 01032 { 01033 verify_socket_list(ntree, &node->inputs, ntype->inputs); 01034 verify_socket_list(ntree, &node->outputs, ntype->outputs); 01035 } 01036 01037 /* keep socket listorder identical, for copying links */ 01038 /* ntree is the target tree */ 01039 bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node) 01040 { 01041 bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node"); 01042 bNodeSocket *sock, *oldsock; 01043 01044 *nnode= *node; 01045 nodeUniqueName(ntree, nnode); 01046 01047 BLI_addtail(&ntree->nodes, nnode); 01048 01049 BLI_duplicatelist(&nnode->inputs, &node->inputs); 01050 oldsock= node->inputs.first; 01051 for(sock= nnode->inputs.first; sock; sock= sock->next, oldsock= oldsock->next) { 01052 oldsock->new_sock= sock; 01053 } 01054 01055 BLI_duplicatelist(&nnode->outputs, &node->outputs); 01056 oldsock= node->outputs.first; 01057 for(sock= nnode->outputs.first; sock; sock= sock->next, oldsock= oldsock->next) { 01058 sock->stack_index= 0; 01059 sock->ns.data= NULL; 01060 oldsock->new_sock= sock; 01061 } 01062 01063 /* don't increase node->id users, freenode doesn't decrement either */ 01064 01065 if(node->typeinfo->copystoragefunc) 01066 node->typeinfo->copystoragefunc(node, nnode); 01067 01068 node->new_node= nnode; 01069 nnode->new_node= NULL; 01070 nnode->preview= NULL; 01071 01072 return nnode; 01073 } 01074 01075 /* fromsock and tosock can be NULL */ 01076 /* also used via rna api, so we check for proper input output direction */ 01077 bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock) 01078 { 01079 bNodeSocket *sock; 01080 bNodeLink *link= NULL; 01081 int from= 0, to= 0; 01082 01083 if(fromnode) { 01084 /* test valid input */ 01085 for(sock= fromnode->outputs.first; sock; sock= sock->next) 01086 if(sock==fromsock) 01087 break; 01088 if(sock) 01089 from= 1; /* OK */ 01090 else { 01091 for(sock= fromnode->inputs.first; sock; sock= sock->next) 01092 if(sock==fromsock) 01093 break; 01094 if(sock) 01095 from= -1; /* OK but flip */ 01096 } 01097 } 01098 if(tonode) { 01099 for(sock= tonode->inputs.first; sock; sock= sock->next) 01100 if(sock==tosock) 01101 break; 01102 if(sock) 01103 to= 1; /* OK */ 01104 else { 01105 for(sock= tonode->outputs.first; sock; sock= sock->next) 01106 if(sock==tosock) 01107 break; 01108 if(sock) 01109 to= -1; /* OK but flip */ 01110 } 01111 } 01112 01113 /* this allows NULL sockets to work */ 01114 if(from >= 0 && to >= 0) { 01115 link= MEM_callocN(sizeof(bNodeLink), "link"); 01116 BLI_addtail(&ntree->links, link); 01117 link->fromnode= fromnode; 01118 link->fromsock= fromsock; 01119 link->tonode= tonode; 01120 link->tosock= tosock; 01121 } 01122 else if(from <= 0 && to <= 0) { 01123 link= MEM_callocN(sizeof(bNodeLink), "link"); 01124 BLI_addtail(&ntree->links, link); 01125 link->fromnode= tonode; 01126 link->fromsock= tosock; 01127 link->tonode= fromnode; 01128 link->tosock= fromsock; 01129 } 01130 01131 return link; 01132 } 01133 01134 void nodeRemLink(bNodeTree *ntree, bNodeLink *link) 01135 { 01136 BLI_remlink(&ntree->links, link); 01137 if(link->tosock) 01138 link->tosock->link= NULL; 01139 MEM_freeN(link); 01140 } 01141 01142 void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) 01143 { 01144 bNodeLink *link, *next; 01145 01146 for(link= ntree->links.first; link; link= next) { 01147 next= link->next; 01148 if(link->fromsock==sock || link->tosock==sock) { 01149 nodeRemLink(ntree, link); 01150 } 01151 } 01152 } 01153 01154 01155 bNodeTree *ntreeAddTree(const char *name, int type, const short is_group) 01156 { 01157 bNodeTree *ntree; 01158 01159 if (is_group) 01160 ntree= alloc_libblock(&G.main->nodetree, ID_NT, name); 01161 else { 01162 ntree= MEM_callocN(sizeof(bNodeTree), "new node tree"); 01163 *( (short *)ntree->id.name )= ID_NT; /* not "type", as that is ntree->type */ 01164 BLI_strncpy(ntree->id.name+2, name, sizeof(ntree->id.name)); 01165 } 01166 01167 ntree->type= type; 01168 ntree->alltypes.first = NULL; 01169 ntree->alltypes.last = NULL; 01170 01171 ntreeInitTypes(ntree); 01172 return ntree; 01173 } 01174 01175 /* Warning: this function gets called during some rather unexpected times 01176 * - this gets called when executing compositing updates (for threaded previews) 01177 * - when the nodetree datablock needs to be copied (i.e. when users get copied) 01178 * - for scene duplication use ntreeSwapID() after so we dont have stale pointers. 01179 */ 01180 bNodeTree *ntreeCopyTree(bNodeTree *ntree) 01181 { 01182 bNodeTree *newtree; 01183 bNode *node, *nnode, *last; 01184 bNodeLink *link; 01185 bNodeSocket *gsock, *oldgsock; 01186 01187 if(ntree==NULL) return NULL; 01188 01189 /* is ntree part of library? */ 01190 for(newtree=G.main->nodetree.first; newtree; newtree= newtree->id.next) 01191 if(newtree==ntree) break; 01192 if(newtree) { 01193 newtree= copy_libblock(ntree); 01194 } else { 01195 newtree= MEM_dupallocN(ntree); 01196 copy_libblock_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */ 01197 } 01198 01199 id_us_plus((ID *)newtree->gpd); 01200 01201 /* in case a running nodetree is copied */ 01202 newtree->init &= ~(NTREE_EXEC_INIT); 01203 newtree->threadstack= NULL; 01204 newtree->stack= NULL; 01205 01206 newtree->nodes.first= newtree->nodes.last= NULL; 01207 newtree->links.first= newtree->links.last= NULL; 01208 01209 last = ntree->nodes.last; 01210 for(node= ntree->nodes.first; node; node= node->next) { 01211 node->new_node= NULL; 01212 nnode= nodeCopyNode(newtree, node); /* sets node->new */ 01213 if(node==last) break; 01214 } 01215 01216 /* socket definition for group usage */ 01217 BLI_duplicatelist(&newtree->inputs, &ntree->inputs); 01218 for(gsock= newtree->inputs.first, oldgsock= ntree->inputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { 01219 oldgsock->new_sock= gsock; 01220 gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); 01221 } 01222 01223 BLI_duplicatelist(&newtree->outputs, &ntree->outputs); 01224 for(gsock= newtree->outputs.first, oldgsock= ntree->outputs.first; gsock; gsock=gsock->next, oldgsock=oldgsock->next) { 01225 oldgsock->new_sock= gsock; 01226 gsock->groupsock = (oldgsock->groupsock ? oldgsock->groupsock->new_sock : NULL); 01227 } 01228 01229 /* copy links */ 01230 BLI_duplicatelist(&newtree->links, &ntree->links); 01231 for(link= newtree->links.first; link; link= link->next) { 01232 link->fromnode = (link->fromnode ? link->fromnode->new_node : NULL); 01233 link->fromsock = (link->fromsock ? link->fromsock->new_sock : NULL); 01234 link->tonode = (link->tonode ? link->tonode->new_node : NULL); 01235 link->tosock = (link->tosock ? link->tosock->new_sock : NULL); 01236 /* update the link socket's pointer */ 01237 if (link->tosock) 01238 link->tosock->link = link; 01239 } 01240 01241 return newtree; 01242 } 01243 01244 /* use when duplicating scenes */ 01245 void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to) 01246 { 01247 bNode *node; 01248 /* for scene duplication only */ 01249 for(node= ntree->nodes.first; node; node= node->next) { 01250 if(node->id==id_from) { 01251 node->id= id_to; 01252 } 01253 } 01254 } 01255 01256 /* *************** preview *********** */ 01257 /* if node->preview, then we assume the rect to exist */ 01258 01259 static void node_free_preview(bNode *node) 01260 { 01261 if(node->preview) { 01262 if(node->preview->rect) 01263 MEM_freeN(node->preview->rect); 01264 MEM_freeN(node->preview); 01265 node->preview= NULL; 01266 } 01267 } 01268 01269 static void node_init_preview(bNode *node, int xsize, int ysize) 01270 { 01271 01272 if(node->preview==NULL) { 01273 node->preview= MEM_callocN(sizeof(bNodePreview), "node preview"); 01274 // printf("added preview %s\n", node->name); 01275 } 01276 01277 /* node previews can get added with variable size this way */ 01278 if(xsize==0 || ysize==0) 01279 return; 01280 01281 /* sanity checks & initialize */ 01282 if(node->preview->rect) { 01283 if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) { 01284 MEM_freeN(node->preview->rect); 01285 node->preview->rect= NULL; 01286 } 01287 } 01288 01289 if(node->preview->rect==NULL) { 01290 node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(char)*4, "node preview rect"); 01291 node->preview->xsize= xsize; 01292 node->preview->ysize= ysize; 01293 } 01294 /* no clear, makes nicer previews */ 01295 } 01296 01297 void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize) 01298 { 01299 bNode *node; 01300 01301 if(ntree==NULL) 01302 return; 01303 01304 for(node= ntree->nodes.first; node; node= node->next) { 01305 if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */ 01306 node_init_preview(node, xsize, ysize); 01307 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) 01308 ntreeInitPreview((bNodeTree *)node->id, xsize, ysize); 01309 } 01310 } 01311 01312 static void nodeClearPreview(bNode *node) 01313 { 01314 if(node->preview && node->preview->rect) 01315 memset(node->preview->rect, 0, MEM_allocN_len(node->preview->rect)); 01316 } 01317 01318 /* use it to enforce clear */ 01319 void ntreeClearPreview(bNodeTree *ntree) 01320 { 01321 bNode *node; 01322 01323 if(ntree==NULL) 01324 return; 01325 01326 for(node= ntree->nodes.first; node; node= node->next) { 01327 if(node->typeinfo->flag & NODE_PREVIEW) 01328 nodeClearPreview(node); 01329 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) 01330 ntreeClearPreview((bNodeTree *)node->id); 01331 } 01332 } 01333 01334 /* hack warning! this function is only used for shader previews, and 01335 since it gets called multiple times per pixel for Ztransp we only 01336 add the color once. Preview gets cleared before it starts render though */ 01337 void nodeAddToPreview(bNode *node, float *col, int x, int y, int do_manage) 01338 { 01339 bNodePreview *preview= node->preview; 01340 if(preview) { 01341 if(x>=0 && y>=0) { 01342 if(x<preview->xsize && y<preview->ysize) { 01343 unsigned char *tar= preview->rect+ 4*((preview->xsize*y) + x); 01344 01345 if(do_manage) { 01346 tar[0]= FTOCHAR(linearrgb_to_srgb(col[0])); 01347 tar[1]= FTOCHAR(linearrgb_to_srgb(col[1])); 01348 tar[2]= FTOCHAR(linearrgb_to_srgb(col[2])); 01349 } 01350 else { 01351 tar[0]= FTOCHAR(col[0]); 01352 tar[1]= FTOCHAR(col[1]); 01353 tar[2]= FTOCHAR(col[2]); 01354 } 01355 tar[3]= FTOCHAR(col[3]); 01356 } 01357 //else printf("prv out bound x y %d %d\n", x, y); 01358 } 01359 //else printf("prv out bound x y %d %d\n", x, y); 01360 } 01361 } 01362 01363 01364 /* ************** Free stuff ********** */ 01365 01366 /* goes over entire tree */ 01367 void nodeUnlinkNode(bNodeTree *ntree, bNode *node) 01368 { 01369 bNodeLink *link, *next; 01370 bNodeSocket *sock; 01371 ListBase *lb; 01372 01373 for(link= ntree->links.first; link; link= next) { 01374 next= link->next; 01375 01376 if(link->fromnode==node) { 01377 lb= &node->outputs; 01378 if (link->tonode) 01379 NodeTagChanged(ntree, link->tonode); 01380 } 01381 else if(link->tonode==node) 01382 lb= &node->inputs; 01383 else 01384 lb= NULL; 01385 01386 if(lb) { 01387 for(sock= lb->first; sock; sock= sock->next) { 01388 if(link->fromsock==sock || link->tosock==sock) 01389 break; 01390 } 01391 if(sock) { 01392 nodeRemLink(ntree, link); 01393 } 01394 } 01395 } 01396 } 01397 01398 static void composit_free_node_cache(bNode *node) 01399 { 01400 bNodeSocket *sock; 01401 01402 for(sock= node->outputs.first; sock; sock= sock->next) { 01403 if(sock->ns.data) { 01404 free_compbuf(sock->ns.data); 01405 sock->ns.data= NULL; 01406 } 01407 } 01408 } 01409 01410 void nodeFreeNode(bNodeTree *ntree, bNode *node) 01411 { 01412 nodeUnlinkNode(ntree, node); 01413 BLI_remlink(&ntree->nodes, node); 01414 01415 /* since it is called while free database, node->id is undefined */ 01416 01417 if(ntree->type==NTREE_COMPOSIT) 01418 composit_free_node_cache(node); 01419 BLI_freelistN(&node->inputs); 01420 BLI_freelistN(&node->outputs); 01421 01422 node_free_preview(node); 01423 01424 if(node->typeinfo && node->typeinfo->freestoragefunc) { 01425 node->typeinfo->freestoragefunc(node); 01426 } 01427 01428 MEM_freeN(node); 01429 } 01430 01431 /* do not free ntree itself here, free_libblock calls this function too */ 01432 void ntreeFreeTree(bNodeTree *ntree) 01433 { 01434 bNode *node, *next; 01435 01436 if(ntree==NULL) return; 01437 01438 ntreeEndExecTree(ntree); /* checks for if it is still initialized */ 01439 01440 BKE_free_animdata((ID *)ntree); 01441 01442 id_us_min((ID *)ntree->gpd); 01443 01444 BLI_freelistN(&ntree->links); /* do first, then unlink_node goes fast */ 01445 01446 for(node= ntree->nodes.first; node; node= next) { 01447 next= node->next; 01448 nodeFreeNode(ntree, node); 01449 } 01450 01451 BLI_freelistN(&ntree->inputs); 01452 BLI_freelistN(&ntree->outputs); 01453 } 01454 01455 void ntreeFreeCache(bNodeTree *ntree) 01456 { 01457 bNode *node; 01458 01459 if(ntree==NULL) return; 01460 01461 if(ntree->type==NTREE_COMPOSIT) 01462 for(node= ntree->nodes.first; node; node= node->next) 01463 composit_free_node_cache(node); 01464 01465 } 01466 01467 void ntreeMakeLocal(bNodeTree *ntree) 01468 { 01469 int local=0, lib=0; 01470 01471 /* - only lib users: do nothing 01472 * - only local users: set flag 01473 * - mixed: make copy 01474 */ 01475 01476 if(ntree->id.lib==NULL) return; 01477 if(ntree->id.us==1) { 01478 ntree->id.lib= NULL; 01479 ntree->id.flag= LIB_LOCAL; 01480 new_id(NULL, (ID *)ntree, NULL); 01481 return; 01482 } 01483 01484 /* now check users of groups... again typedepending, callback... */ 01485 if(ntree->type==NTREE_SHADER) { 01486 Material *ma; 01487 for(ma= G.main->mat.first; ma; ma= ma->id.next) { 01488 if(ma->nodetree) { 01489 bNode *node; 01490 01491 /* find if group is in tree */ 01492 for(node= ma->nodetree->nodes.first; node; node= node->next) { 01493 if(node->id == (ID *)ntree) { 01494 if(ma->id.lib) lib= 1; 01495 else local= 1; 01496 } 01497 } 01498 } 01499 } 01500 } 01501 else if(ntree->type==NTREE_COMPOSIT) { 01502 Scene *sce; 01503 for(sce= G.main->scene.first; sce; sce= sce->id.next) { 01504 if(sce->nodetree) { 01505 bNode *node; 01506 01507 /* find if group is in tree */ 01508 for(node= sce->nodetree->nodes.first; node; node= node->next) { 01509 if(node->id == (ID *)ntree) { 01510 if(sce->id.lib) lib= 1; 01511 else local= 1; 01512 } 01513 } 01514 } 01515 } 01516 } 01517 else if(ntree->type==NTREE_TEXTURE) { 01518 Tex *tx; 01519 for(tx= G.main->tex.first; tx; tx= tx->id.next) { 01520 if(tx->nodetree) { 01521 bNode *node; 01522 01523 /* find if group is in tree */ 01524 for(node= tx->nodetree->nodes.first; node; node= node->next) { 01525 if(node->id == (ID *)ntree) { 01526 if(tx->id.lib) lib= 1; 01527 else local= 1; 01528 } 01529 } 01530 } 01531 } 01532 } 01533 01534 /* if all users are local, we simply make tree local */ 01535 if(local && lib==0) { 01536 ntree->id.lib= NULL; 01537 ntree->id.flag= LIB_LOCAL; 01538 new_id(NULL, (ID *)ntree, NULL); 01539 } 01540 else if(local && lib) { 01541 /* this is the mixed case, we copy the tree and assign it to local users */ 01542 bNodeTree *newtree= ntreeCopyTree(ntree); 01543 01544 newtree->id.us= 0; 01545 01546 if(ntree->type==NTREE_SHADER) { 01547 Material *ma; 01548 for(ma= G.main->mat.first; ma; ma= ma->id.next) { 01549 if(ma->nodetree) { 01550 bNode *node; 01551 01552 /* find if group is in tree */ 01553 for(node= ma->nodetree->nodes.first; node; node= node->next) { 01554 if(node->id == (ID *)ntree) { 01555 if(ma->id.lib==NULL) { 01556 node->id= &newtree->id; 01557 newtree->id.us++; 01558 ntree->id.us--; 01559 } 01560 } 01561 } 01562 } 01563 } 01564 } 01565 else if(ntree->type==NTREE_COMPOSIT) { 01566 Scene *sce; 01567 for(sce= G.main->scene.first; sce; sce= sce->id.next) { 01568 if(sce->nodetree) { 01569 bNode *node; 01570 01571 /* find if group is in tree */ 01572 for(node= sce->nodetree->nodes.first; node; node= node->next) { 01573 if(node->id == (ID *)ntree) { 01574 if(sce->id.lib==NULL) { 01575 node->id= &newtree->id; 01576 newtree->id.us++; 01577 ntree->id.us--; 01578 } 01579 } 01580 } 01581 } 01582 } 01583 } 01584 else if(ntree->type==NTREE_TEXTURE) { 01585 Tex *tx; 01586 for(tx= G.main->tex.first; tx; tx= tx->id.next) { 01587 if(tx->nodetree) { 01588 bNode *node; 01589 01590 /* find if group is in tree */ 01591 for(node= tx->nodetree->nodes.first; node; node= node->next) { 01592 if(node->id == (ID *)ntree) { 01593 if(tx->id.lib==NULL) { 01594 node->id= &newtree->id; 01595 newtree->id.us++; 01596 ntree->id.us--; 01597 } 01598 } 01599 } 01600 } 01601 } 01602 } 01603 } 01604 } 01605 01606 01607 /* ************ find stuff *************** */ 01608 01609 static int ntreeHasType(bNodeTree *ntree, int type) 01610 { 01611 bNode *node; 01612 01613 if(ntree) 01614 for(node= ntree->nodes.first; node; node= node->next) 01615 if(node->type == type) 01616 return 1; 01617 return 0; 01618 } 01619 01620 bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to) 01621 { 01622 bNodeLink *link; 01623 01624 for(link= ntree->links.first; link; link= link->next) { 01625 if(link->fromsock==from && link->tosock==to) 01626 return link; 01627 if(link->fromsock==to && link->tosock==from) /* hrms? */ 01628 return link; 01629 } 01630 return NULL; 01631 } 01632 01633 int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock) 01634 { 01635 bNodeLink *link; 01636 int tot= 0; 01637 01638 for(link= ntree->links.first; link; link= link->next) { 01639 if(link->fromsock==sock || link->tosock==sock) 01640 tot++; 01641 } 01642 return tot; 01643 } 01644 01645 bNode *nodeGetActive(bNodeTree *ntree) 01646 { 01647 bNode *node; 01648 01649 if(ntree==NULL) return NULL; 01650 01651 for(node= ntree->nodes.first; node; node= node->next) 01652 if(node->flag & NODE_ACTIVE) 01653 break; 01654 return node; 01655 } 01656 01657 /* two active flags, ID nodes have special flag for buttons display */ 01658 bNode *nodeGetActiveID(bNodeTree *ntree, short idtype) 01659 { 01660 bNode *node; 01661 01662 if(ntree==NULL) return NULL; 01663 01664 /* check for group edit */ 01665 for(node= ntree->nodes.first; node; node= node->next) 01666 if(node->flag & NODE_GROUP_EDIT) 01667 break; 01668 01669 if(node) 01670 ntree= (bNodeTree*)node->id; 01671 01672 /* now find active node with this id */ 01673 for(node= ntree->nodes.first; node; node= node->next) 01674 if(node->id && GS(node->id->name)==idtype) 01675 if(node->flag & NODE_ACTIVE_ID) 01676 break; 01677 01678 return node; 01679 } 01680 01681 int nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) 01682 { 01683 bNode *node; 01684 int ok= FALSE; 01685 01686 if(ntree==NULL) return ok; 01687 01688 /* check for group edit */ 01689 for(node= ntree->nodes.first; node; node= node->next) 01690 if(node->flag & NODE_GROUP_EDIT) 01691 break; 01692 01693 if(node) 01694 ntree= (bNodeTree*)node->id; 01695 01696 /* now find active node with this id */ 01697 for(node= ntree->nodes.first; node; node= node->next) { 01698 if(node->id && GS(node->id->name)==idtype) { 01699 if(id && ok==FALSE && node->id==id) { 01700 node->flag |= NODE_ACTIVE_ID; 01701 ok= TRUE; 01702 } else { 01703 node->flag &= ~NODE_ACTIVE_ID; 01704 } 01705 } 01706 } 01707 01708 return ok; 01709 } 01710 01711 01712 /* two active flags, ID nodes have special flag for buttons display */ 01713 void nodeClearActiveID(bNodeTree *ntree, short idtype) 01714 { 01715 bNode *node; 01716 01717 if(ntree==NULL) return; 01718 01719 for(node= ntree->nodes.first; node; node= node->next) 01720 if(node->id && GS(node->id->name)==idtype) 01721 node->flag &= ~NODE_ACTIVE_ID; 01722 } 01723 01724 /* two active flags, ID nodes have special flag for buttons display */ 01725 void nodeSetActive(bNodeTree *ntree, bNode *node) 01726 { 01727 bNode *tnode; 01728 01729 /* make sure only one node is active, and only one per ID type */ 01730 for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { 01731 tnode->flag &= ~NODE_ACTIVE; 01732 01733 if(node->id && tnode->id) { 01734 if(GS(node->id->name) == GS(tnode->id->name)) 01735 tnode->flag &= ~NODE_ACTIVE_ID; 01736 } 01737 } 01738 01739 node->flag |= NODE_ACTIVE; 01740 if(node->id) 01741 node->flag |= NODE_ACTIVE_ID; 01742 } 01743 01744 /* use flags are not persistant yet, groups might need different tagging, so we do it each time 01745 when we need to get this info */ 01746 void ntreeSocketUseFlags(bNodeTree *ntree) 01747 { 01748 bNode *node; 01749 bNodeSocket *sock; 01750 bNodeLink *link; 01751 01752 /* clear flags */ 01753 for(node= ntree->nodes.first; node; node= node->next) { 01754 for(sock= node->inputs.first; sock; sock= sock->next) 01755 sock->flag &= ~SOCK_IN_USE; 01756 for(sock= node->outputs.first; sock; sock= sock->next) 01757 sock->flag &= ~SOCK_IN_USE; 01758 } 01759 01760 /* tag all thats in use */ 01761 for(link= ntree->links.first; link; link= link->next) { 01762 01763 if(link->fromsock) // FIXME, see below 01764 link->fromsock->flag |= SOCK_IN_USE; 01765 if(link->tosock) // FIXME This can be NULL, when dragging a new link in the UI, should probably copy the node tree for preview render - campbell 01766 link->tosock->flag |= SOCK_IN_USE; 01767 } 01768 } 01769 01770 /* ************** dependency stuff *********** */ 01771 01772 /* node is guaranteed to be not checked before */ 01773 static int node_recurs_check(bNode *node, bNode ***nsort) 01774 { 01775 bNode *fromnode; 01776 bNodeSocket *sock; 01777 int level = 0xFFF; 01778 01779 node->done= 1; 01780 01781 for(sock= node->inputs.first; sock; sock= sock->next) { 01782 if(sock->link) { 01783 fromnode= sock->link->fromnode; 01784 if(fromnode) { 01785 if (fromnode->done==0) 01786 fromnode->level= node_recurs_check(fromnode, nsort); 01787 if (fromnode->level <= level) 01788 level = fromnode->level - 1; 01789 } 01790 } 01791 } 01792 **nsort= node; 01793 (*nsort)++; 01794 01795 return level; 01796 } 01797 01798 01799 static void ntreeSetOutput(bNodeTree *ntree) 01800 { 01801 bNode *node; 01802 01803 /* find the active outputs, might become tree type dependant handler */ 01804 for(node= ntree->nodes.first; node; node= node->next) { 01805 if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { 01806 bNode *tnode; 01807 int output= 0; 01808 01809 /* we need a check for which output node should be tagged like this, below an exception */ 01810 if(node->type==CMP_NODE_OUTPUT_FILE) 01811 continue; 01812 01813 /* there is more types having output class, each one is checked */ 01814 for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) { 01815 if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) { 01816 01817 if(ntree->type==NTREE_COMPOSIT) { 01818 01819 /* same type, exception for viewer */ 01820 if(tnode->type==node->type || 01821 (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && 01822 ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) { 01823 if(tnode->flag & NODE_DO_OUTPUT) { 01824 output++; 01825 if(output>1) 01826 tnode->flag &= ~NODE_DO_OUTPUT; 01827 } 01828 } 01829 } 01830 else { 01831 /* same type */ 01832 if(tnode->type==node->type) { 01833 if(tnode->flag & NODE_DO_OUTPUT) { 01834 output++; 01835 if(output>1) 01836 tnode->flag &= ~NODE_DO_OUTPUT; 01837 } 01838 } 01839 } 01840 } 01841 } 01842 if(output==0) 01843 node->flag |= NODE_DO_OUTPUT; 01844 } 01845 } 01846 01847 /* here we could recursively set which nodes have to be done, 01848 might be different for editor or for "real" use... */ 01849 } 01850 01851 void ntreeSolveOrder(bNodeTree *ntree) 01852 { 01853 bNode *node, **nodesort, **nsort; 01854 bNodeSocket *sock; 01855 bNodeLink *link; 01856 int a, totnode=0; 01857 01858 /* the solve-order is called on each tree change, so we should be sure no exec can be running */ 01859 ntreeEndExecTree(ntree); 01860 01861 /* set links pointers the input sockets, to find dependencies */ 01862 /* first clear data */ 01863 for(node= ntree->nodes.first; node; node= node->next) { 01864 node->done= 0; 01865 totnode++; 01866 for(sock= node->inputs.first; sock; sock= sock->next) 01867 sock->link= NULL; 01868 } 01869 /* clear group socket links */ 01870 for(sock= ntree->outputs.first; sock; sock= sock->next) 01871 sock->link= NULL; 01872 if(totnode==0) 01873 return; 01874 01875 for(link= ntree->links.first; link; link= link->next) { 01876 link->tosock->link= link; 01877 } 01878 01879 nsort= nodesort= MEM_callocN(totnode*sizeof(void *), "sorted node array"); 01880 01881 /* recursive check */ 01882 for(node= ntree->nodes.first; node; node= node->next) { 01883 if(node->done==0) { 01884 node->level= node_recurs_check(node, &nsort); 01885 } 01886 } 01887 01888 /* re-insert nodes in order, first a paranoia check */ 01889 for(a=0; a<totnode; a++) { 01890 if(nodesort[a]==NULL) 01891 break; 01892 } 01893 if(a<totnode) 01894 printf("sort error in node tree"); 01895 else { 01896 ntree->nodes.first= ntree->nodes.last= NULL; 01897 for(a=0; a<totnode; a++) 01898 BLI_addtail(&ntree->nodes, nodesort[a]); 01899 } 01900 01901 MEM_freeN(nodesort); 01902 01903 ntreeSetOutput(ntree); 01904 } 01905 01906 01907 /* Should be callback! */ 01908 /* Do not call execs here */ 01909 void NodeTagChanged(bNodeTree *ntree, bNode *node) 01910 { 01911 if(ntree->type==NTREE_COMPOSIT) { 01912 bNodeSocket *sock; 01913 01914 for(sock= node->outputs.first; sock; sock= sock->next) { 01915 if(sock->ns.data) { 01916 //free_compbuf(sock->ns.data); 01917 //sock->ns.data= NULL; 01918 } 01919 } 01920 node->need_exec= 1; 01921 } 01922 } 01923 01924 int NodeTagIDChanged(bNodeTree *ntree, ID *id) 01925 { 01926 int change = FALSE; 01927 01928 if(ELEM(NULL, id, ntree)) 01929 return change; 01930 01931 if(ntree->type==NTREE_COMPOSIT) { 01932 bNode *node; 01933 01934 for(node= ntree->nodes.first; node; node= node->next) { 01935 if(node->id==id) { 01936 change= TRUE; 01937 NodeTagChanged(ntree, node); 01938 } 01939 } 01940 } 01941 01942 return change; 01943 } 01944 01945 01946 01947 /* ******************* executing ************* */ 01948 01949 /* for a given socket, find the actual stack entry */ 01950 static bNodeStack *get_socket_stack(bNodeStack *stack, bNodeSocket *sock, bNodeStack **gin) 01951 { 01952 switch (sock->stack_type) { 01953 case SOCK_STACK_LOCAL: 01954 return stack + sock->stack_index; 01955 case SOCK_STACK_EXTERN: 01956 return (gin ? gin[sock->stack_index] : NULL); 01957 case SOCK_STACK_CONST: 01958 return sock->stack_ptr; 01959 } 01960 return NULL; 01961 } 01962 01963 /* see notes at ntreeBeginExecTree */ 01964 static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin) 01965 { 01966 bNodeSocket *sock; 01967 01968 /* build pointer stack */ 01969 if (in) { 01970 for(sock= node->inputs.first; sock; sock= sock->next) { 01971 *(in++) = get_socket_stack(stack, sock, gin); 01972 } 01973 } 01974 01975 if (out) { 01976 for(sock= node->outputs.first; sock; sock= sock->next) { 01977 *(out++) = get_socket_stack(stack, sock, gin); 01978 } 01979 } 01980 } 01981 01982 static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNodeStack **in) 01983 { 01984 bNode *node; 01985 bNodeTree *ntree= (bNodeTree *)gnode->id; 01986 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 01987 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ 01988 01989 if(ntree==NULL) return; 01990 01991 stack+= gnode->stack_index; 01992 01993 for(node= ntree->nodes.first; node; node= node->next) { 01994 if(node->typeinfo->execfunc) { 01995 node_get_stack(node, stack, nsin, nsout, in); 01996 01997 /* for groups, only execute outputs for edited group */ 01998 if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { 01999 if(node->type==CMP_NODE_OUTPUT_FILE || (gnode->flag & NODE_GROUP_EDIT)) 02000 node->typeinfo->execfunc(data, node, nsin, nsout); 02001 } 02002 else 02003 node->typeinfo->execfunc(data, node, nsin, nsout); 02004 } 02005 } 02006 02007 /* free internal buffers */ 02008 if (ntree->type==NTREE_COMPOSIT) { 02009 bNodeSocket *sock; 02010 bNodeStack *ns; 02011 02012 /* clear hasoutput on all local stack data, 02013 * only the group output will be used from now on 02014 */ 02015 for (node=ntree->nodes.first; node; node=node->next) { 02016 for (sock=node->outputs.first; sock; sock=sock->next) { 02017 if (sock->stack_type==SOCK_STACK_LOCAL) { 02018 ns= get_socket_stack(stack, sock, in); 02019 ns->hasoutput = 0; 02020 } 02021 } 02022 } 02023 /* use the hasoutput flag to tag external sockets */ 02024 for (sock=ntree->outputs.first; sock; sock=sock->next) { 02025 if (sock->stack_type==SOCK_STACK_LOCAL) { 02026 ns= get_socket_stack(stack, sock, in); 02027 ns->hasoutput = 1; 02028 } 02029 } 02030 /* now free all stacks that are not used from outside */ 02031 for (node=ntree->nodes.first; node; node=node->next) { 02032 for (sock=node->outputs.first; sock; sock=sock->next) { 02033 if (sock->stack_type==SOCK_STACK_LOCAL ) { 02034 ns= get_socket_stack(stack, sock, in); 02035 if (ns->hasoutput==0 && ns->data) { 02036 free_compbuf(ns->data); 02037 ns->data = NULL; 02038 } 02039 } 02040 } 02041 } 02042 } 02043 } 02044 02045 static int set_stack_indexes_default(bNode *node, int index) 02046 { 02047 bNodeSocket *sock; 02048 02049 for (sock=node->inputs.first; sock; sock=sock->next) { 02050 if (sock->link && sock->link->fromsock) { 02051 sock->stack_type = sock->link->fromsock->stack_type; 02052 sock->stack_index = sock->link->fromsock->stack_index; 02053 sock->stack_ptr = sock->link->fromsock->stack_ptr; 02054 } 02055 else { 02056 sock->stack_type = SOCK_STACK_CONST; 02057 sock->stack_index = -1; 02058 sock->stack_ptr = &sock->ns; 02059 } 02060 } 02061 02062 for (sock=node->outputs.first; sock; sock=sock->next) { 02063 sock->stack_type = SOCK_STACK_LOCAL; 02064 sock->stack_index = index++; 02065 sock->stack_ptr = NULL; 02066 } 02067 02068 return index; 02069 } 02070 02071 static int ntree_begin_exec_tree(bNodeTree *ntree); 02072 static int set_stack_indexes_group(bNode *node, int index) 02073 { 02074 bNodeTree *ngroup= (bNodeTree*)node->id; 02075 bNodeSocket *sock; 02076 02077 if(ngroup && (ngroup->init & NTREE_TYPE_INIT)==0) 02078 ntreeInitTypes(ngroup); 02079 02080 node->stack_index = index; 02081 if(ngroup) 02082 index += ntree_begin_exec_tree(ngroup); 02083 02084 for (sock=node->inputs.first; sock; sock=sock->next) { 02085 if (sock->link && sock->link->fromsock) { 02086 sock->stack_type = sock->link->fromsock->stack_type; 02087 sock->stack_index = sock->link->fromsock->stack_index; 02088 sock->stack_ptr = sock->link->fromsock->stack_ptr; 02089 } 02090 else { 02091 sock->stack_type = SOCK_STACK_CONST; 02092 sock->stack_index = -1; 02093 sock->stack_ptr = &sock->ns; 02094 } 02095 } 02096 02097 /* identify group node outputs from internal group sockets */ 02098 for(sock= node->outputs.first; sock; sock= sock->next) { 02099 if (sock->groupsock) { 02100 bNodeSocket *insock, *gsock = sock->groupsock; 02101 switch (gsock->stack_type) { 02102 case SOCK_STACK_EXTERN: 02103 /* extern stack is resolved for this group node instance */ 02104 insock= find_group_node_input(node, gsock->link->fromsock); 02105 sock->stack_type = insock->stack_type; 02106 sock->stack_index = insock->stack_index; 02107 sock->stack_ptr = insock->stack_ptr; 02108 break; 02109 case SOCK_STACK_LOCAL: 02110 sock->stack_type = SOCK_STACK_LOCAL; 02111 /* local stack index must be offset by group node instance */ 02112 sock->stack_index = gsock->stack_index + node->stack_index; 02113 sock->stack_ptr = NULL; 02114 break; 02115 case SOCK_STACK_CONST: 02116 sock->stack_type = SOCK_STACK_CONST; 02117 sock->stack_index = -1; 02118 sock->stack_ptr = gsock->stack_ptr; 02119 break; 02120 } 02121 } 02122 else { 02123 sock->stack_type = SOCK_STACK_LOCAL; 02124 sock->stack_index = index++; 02125 sock->stack_ptr = NULL; 02126 } 02127 } 02128 02129 return index; 02130 } 02131 02132 /* recursively called for groups */ 02133 /* we set all trees on own local indices, but put a total counter 02134 in the groups, so each instance of a group has own stack */ 02135 static int ntree_begin_exec_tree(bNodeTree *ntree) 02136 { 02137 bNode *node; 02138 bNodeSocket *gsock; 02139 int index= 0, i; 02140 02141 if((ntree->init & NTREE_TYPE_INIT)==0) 02142 ntreeInitTypes(ntree); 02143 02144 /* group inputs are numbered 0..totinputs, so external stack can easily be addressed */ 02145 i = 0; 02146 for(gsock=ntree->inputs.first; gsock; gsock = gsock->next) { 02147 gsock->stack_type = SOCK_STACK_EXTERN; 02148 gsock->stack_index = i++; 02149 gsock->stack_ptr = NULL; 02150 } 02151 02152 /* create indices for stack, check preview */ 02153 for(node= ntree->nodes.first; node; node= node->next) { 02154 /* XXX can this be done by a generic one-for-all function? 02155 * otherwise should use node-type callback. 02156 */ 02157 if(node->type==NODE_GROUP) 02158 index = set_stack_indexes_group(node, index); 02159 else 02160 index = set_stack_indexes_default(node, index); 02161 } 02162 02163 /* group outputs */ 02164 for(gsock=ntree->outputs.first; gsock; gsock = gsock->next) { 02165 if (gsock->link && gsock->link->fromsock) { 02166 gsock->stack_type = gsock->link->fromsock->stack_type; 02167 gsock->stack_index = gsock->link->fromsock->stack_index; 02168 gsock->stack_ptr = gsock->link->fromsock->stack_ptr; 02169 } 02170 else { 02171 gsock->stack_type = SOCK_STACK_CONST; 02172 gsock->stack_index = -1; 02173 gsock->stack_ptr = &gsock->ns; 02174 } 02175 } 02176 02177 return index; 02178 } 02179 02180 /* copy socket compbufs to stack, initialize usage of curve nodes */ 02181 static void composit_begin_exec(bNodeTree *ntree, bNodeStack *stack) 02182 { 02183 bNode *node; 02184 bNodeSocket *sock; 02185 02186 for(node= ntree->nodes.first; node; node= node->next) { 02187 02188 /* initialize needed for groups */ 02189 node->exec= 0; 02190 02191 for(sock= node->outputs.first; sock; sock= sock->next) { 02192 bNodeStack *ns= get_socket_stack(stack, sock, NULL); 02193 if(ns && sock->ns.data) { 02194 ns->data= sock->ns.data; 02195 sock->ns.data= NULL; 02196 } 02197 } 02198 02199 /* cannot initialize them while using in threads */ 02200 if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) { 02201 curvemapping_initialize(node->storage); 02202 if(node->type==CMP_NODE_CURVE_RGB) 02203 curvemapping_premultiply(node->storage, 0); 02204 } 02205 if(node->type==NODE_GROUP && node->id) 02206 composit_begin_exec((bNodeTree *)node->id, stack + node->stack_index); 02207 02208 } 02209 } 02210 02211 /* copy stack compbufs to sockets */ 02212 static void composit_end_exec(bNodeTree *ntree, bNodeStack *stack) 02213 { 02214 bNode *node; 02215 bNodeStack *ns; 02216 02217 for(node= ntree->nodes.first; node; node= node->next) { 02218 bNodeSocket *sock; 02219 02220 for(sock= node->outputs.first; sock; sock= sock->next) { 02221 ns = get_socket_stack(stack, sock, NULL); 02222 if(ns && ns->data) { 02223 sock->ns.data= ns->data; 02224 ns->data= NULL; 02225 } 02226 } 02227 02228 if(node->type==CMP_NODE_CURVE_RGB) 02229 curvemapping_premultiply(node->storage, 1); 02230 02231 if(node->type==NODE_GROUP && node->id) 02232 composit_end_exec((bNodeTree *)node->id, stack + node->stack_index); 02233 02234 node->need_exec= 0; 02235 } 02236 } 02237 02238 static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack, bNodeStack **gin) 02239 { 02240 bNodeTree *ntree= (bNodeTree *)gnode->id; 02241 bNode *node; 02242 bNodeSocket *sock; 02243 02244 stack+= gnode->stack_index; 02245 02246 for(node= ntree->nodes.first; node; node= node->next) { 02247 if(node->typeinfo->execfunc) { 02248 for(sock= node->inputs.first; sock; sock= sock->next) { 02249 bNodeStack *ns = get_socket_stack(stack, sock, gin); 02250 ns->hasoutput= 1; 02251 } 02252 } 02253 02254 /* non-composite trees do all nodes by default */ 02255 if (ntree->type!=NTREE_COMPOSIT) 02256 node->need_exec = 1; 02257 02258 for(sock= node->inputs.first; sock; sock= sock->next) { 02259 bNodeStack *ns = get_socket_stack(stack, sock, gin); 02260 if (ns) { 02261 ns->hasoutput = 1; 02262 02263 /* sock type is needed to detect rgba or value or vector types */ 02264 if(sock->link && sock->link->fromsock) 02265 ns->sockettype= sock->link->fromsock->type; 02266 else 02267 sock->ns.sockettype= sock->type; 02268 } 02269 02270 if(sock->link) { 02271 bNodeLink *link= sock->link; 02272 /* this is the test for a cyclic case */ 02273 if(link->fromnode && link->tonode) { 02274 if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF); 02275 else { 02276 node->need_exec= 0; 02277 } 02278 } 02279 } 02280 } 02281 02282 /* set stack types (for local stack entries) */ 02283 for(sock= node->outputs.first; sock; sock= sock->next) { 02284 bNodeStack *ns = get_socket_stack(stack, sock, gin); 02285 if (ns) 02286 ns->sockettype = sock->type; 02287 } 02288 } 02289 } 02290 02291 /* notes below are ancient! (ton) */ 02292 /* stack indices make sure all nodes only write in allocated data, for making it thread safe */ 02293 /* only root tree gets the stack, to enable instances to have own stack entries */ 02294 /* per tree (and per group) unique indices are created */ 02295 /* the index_ext we need to be able to map from groups to the group-node own stack */ 02296 02297 typedef struct bNodeThreadStack { 02298 struct bNodeThreadStack *next, *prev; 02299 bNodeStack *stack; 02300 int used; 02301 } bNodeThreadStack; 02302 02303 static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread) 02304 { 02305 ListBase *lb= &ntree->threadstack[thread]; 02306 bNodeThreadStack *nts; 02307 02308 for(nts=lb->first; nts; nts=nts->next) { 02309 if(!nts->used) { 02310 nts->used= 1; 02311 return nts; 02312 } 02313 } 02314 nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack"); 02315 nts->stack= MEM_dupallocN(ntree->stack); 02316 nts->used= 1; 02317 BLI_addtail(lb, nts); 02318 02319 return nts; 02320 } 02321 02322 static void ntreeReleaseThreadStack(bNodeThreadStack *nts) 02323 { 02324 nts->used= 0; 02325 } 02326 02327 /* free texture delegates */ 02328 static void tex_end_exec(bNodeTree *ntree) 02329 { 02330 bNodeThreadStack *nts; 02331 bNodeStack *ns; 02332 int th, a; 02333 02334 if(ntree->threadstack) { 02335 for(th=0; th<BLENDER_MAX_THREADS; th++) { 02336 for(nts=ntree->threadstack[th].first; nts; nts=nts->next) { 02337 for(ns= nts->stack, a=0; a<ntree->stacksize; a++, ns++) { 02338 if(ns->data) { 02339 MEM_freeN(ns->data); 02340 ns->data= NULL; 02341 } 02342 } 02343 } 02344 } 02345 } 02346 } 02347 02348 void ntreeBeginExecTree(bNodeTree *ntree) 02349 { 02350 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 02351 02352 /* let's make it sure */ 02353 if(ntree->init & NTREE_EXEC_INIT) 02354 return; 02355 02356 /* allocate the thread stack listbase array */ 02357 if(ntree->type!=NTREE_COMPOSIT) 02358 ntree->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array"); 02359 02360 /* goes recursive over all groups */ 02361 ntree->stacksize= ntree_begin_exec_tree(ntree); 02362 02363 if(ntree->stacksize) { 02364 bNode *node; 02365 bNodeStack *ns; 02366 int a; 02367 02368 /* allocate the base stack */ 02369 ns=ntree->stack= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack"); 02370 02371 /* tag inputs, the get_stack() gives own socket stackdata if not in use */ 02372 for(a=0; a<ntree->stacksize; a++, ns++) ns->hasinput= 1; 02373 02374 /* tag used outputs, so we know when we can skip operations */ 02375 for(node= ntree->nodes.first; node; node= node->next) { 02376 bNodeSocket *sock; 02377 02378 /* non-composite trees do all nodes by default */ 02379 if(ntree->type!=NTREE_COMPOSIT) 02380 node->need_exec= 1; 02381 02382 for(sock= node->inputs.first; sock; sock= sock->next) { 02383 ns = get_socket_stack(ntree->stack, sock, NULL); 02384 if (ns) { 02385 ns->hasoutput = 1; 02386 02387 /* sock type is needed to detect rgba or value or vector types */ 02388 if(sock->link && sock->link->fromsock) 02389 ns->sockettype= sock->link->fromsock->type; 02390 else 02391 sock->ns.sockettype= sock->type; 02392 } 02393 02394 if(sock->link) { 02395 bNodeLink *link= sock->link; 02396 /* this is the test for a cyclic case */ 02397 if(link->fromnode && link->tonode) { 02398 if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF); 02399 else { 02400 node->need_exec= 0; 02401 } 02402 } 02403 } 02404 } 02405 02406 /* set stack types (for local stack entries) */ 02407 for(sock= node->outputs.first; sock; sock= sock->next) { 02408 ns = get_socket_stack(ntree->stack, sock, NULL); 02409 if (ns) 02410 ns->sockettype = sock->type; 02411 } 02412 02413 if(node->type==NODE_GROUP && node->id) { 02414 node_get_stack(node, ntree->stack, nsin, NULL, NULL); 02415 group_tag_used_outputs(node, ntree->stack, nsin); 02416 } 02417 } 02418 02419 if(ntree->type==NTREE_COMPOSIT) 02420 composit_begin_exec(ntree, ntree->stack); 02421 02422 /* ensures only a single output node is enabled, texnode allows multiple though */ 02423 if(ntree->type!=NTREE_TEXTURE) 02424 ntreeSetOutput(ntree); 02425 02426 } 02427 02428 ntree->init |= NTREE_EXEC_INIT; 02429 } 02430 02431 void ntreeEndExecTree(bNodeTree *ntree) 02432 { 02433 bNodeStack *ns; 02434 02435 if(ntree->init & NTREE_EXEC_INIT) { 02436 bNodeThreadStack *nts; 02437 int a; 02438 02439 /* another callback candidate! */ 02440 if(ntree->type==NTREE_COMPOSIT) { 02441 composit_end_exec(ntree, ntree->stack); 02442 02443 for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) { 02444 if(ns->data) { 02445 printf("freed leftover buffer from stack\n"); 02446 free_compbuf(ns->data); 02447 ns->data= NULL; 02448 } 02449 } 02450 } 02451 else if(ntree->type==NTREE_TEXTURE) 02452 tex_end_exec(ntree); 02453 02454 if(ntree->stack) { 02455 MEM_freeN(ntree->stack); 02456 ntree->stack= NULL; 02457 } 02458 02459 if(ntree->threadstack) { 02460 for(a=0; a<BLENDER_MAX_THREADS; a++) { 02461 for(nts=ntree->threadstack[a].first; nts; nts=nts->next) 02462 if (nts->stack) MEM_freeN(nts->stack); 02463 BLI_freelistN(&ntree->threadstack[a]); 02464 } 02465 02466 MEM_freeN(ntree->threadstack); 02467 ntree->threadstack= NULL; 02468 } 02469 02470 ntree->init &= ~NTREE_EXEC_INIT; 02471 } 02472 } 02473 02474 /* nodes are presorted, so exec is in order of list */ 02475 void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread) 02476 { 02477 bNode *node; 02478 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 02479 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ 02480 bNodeStack *stack; 02481 bNodeThreadStack *nts = NULL; 02482 02483 /* only when initialized */ 02484 if((ntree->init & NTREE_EXEC_INIT)==0) 02485 ntreeBeginExecTree(ntree); 02486 02487 /* composite does 1 node per thread, so no multiple stacks needed */ 02488 if(ntree->type==NTREE_COMPOSIT) { 02489 stack= ntree->stack; 02490 } 02491 else { 02492 nts= ntreeGetThreadStack(ntree, thread); 02493 stack= nts->stack; 02494 } 02495 02496 for(node= ntree->nodes.first; node; node= node->next) { 02497 if(node->need_exec) { 02498 if(node->typeinfo->execfunc) { 02499 node_get_stack(node, stack, nsin, nsout, NULL); 02500 node->typeinfo->execfunc(callerdata, node, nsin, nsout); 02501 } 02502 else if(node->type==NODE_GROUP && node->id) { 02503 node_get_stack(node, stack, nsin, NULL, NULL); 02504 node_group_execute(stack, callerdata, node, nsin); 02505 } 02506 } 02507 } 02508 02509 if(nts) 02510 ntreeReleaseThreadStack(nts); 02511 } 02512 02513 02514 /* ***************************** threaded version for execute composite nodes ************* */ 02515 /* these are nodes without input, only giving values */ 02516 /* or nodes with only value inputs */ 02517 static int node_only_value(bNode *node) 02518 { 02519 bNodeSocket *sock; 02520 02521 if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB)) 02522 return 1; 02523 02524 /* doing this for all node types goes wrong. memory free errors */ 02525 if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) { 02526 int retval= 1; 02527 for(sock= node->inputs.first; sock; sock= sock->next) { 02528 if(sock->link && sock->link->fromnode) 02529 retval &= node_only_value(sock->link->fromnode); 02530 } 02531 return retval; 02532 } 02533 return 0; 02534 } 02535 02536 02537 /* not changing info, for thread callback */ 02538 typedef struct ThreadData { 02539 bNodeStack *stack; 02540 RenderData *rd; 02541 } ThreadData; 02542 02543 static void *exec_composite_node(void *node_v) 02544 { 02545 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 02546 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ 02547 bNode *node= node_v; 02548 ThreadData *thd= (ThreadData *)node->threaddata; 02549 02550 node_get_stack(node, thd->stack, nsin, nsout, NULL); 02551 02552 if((node->flag & NODE_MUTED) && (!node_only_value(node))) { 02553 /* viewers we execute, for feedback to user */ 02554 if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 02555 node->typeinfo->execfunc(thd->rd, node, nsin, nsout); 02556 else 02557 node_compo_pass_on(node, nsin, nsout); 02558 } 02559 else if(node->typeinfo->execfunc) { 02560 node->typeinfo->execfunc(thd->rd, node, nsin, nsout); 02561 } 02562 else if(node->type==NODE_GROUP && node->id) { 02563 node_group_execute(thd->stack, thd->rd, node, nsin); 02564 } 02565 02566 node->exec |= NODE_READY; 02567 return NULL; 02568 } 02569 02570 /* return total of executable nodes, for timecursor */ 02571 /* only compositor uses it */ 02572 static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd) 02573 { 02574 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 02575 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ 02576 bNode *node; 02577 bNodeSocket *sock; 02578 int totnode= 0, group_edit= 0; 02579 02580 /* note; do not add a dependency sort here, the stack was created already */ 02581 02582 /* if we are in group edit, viewer nodes get skipped when group has viewer */ 02583 for(node= ntree->nodes.first; node; node= node->next) 02584 if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT)) 02585 if(ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER)) 02586 group_edit= 1; 02587 02588 for(node= ntree->nodes.first; node; node= node->next) { 02589 int a; 02590 02591 node_get_stack(node, thd->stack, nsin, nsout, NULL); 02592 02593 /* test the outputs */ 02594 /* skip value-only nodes (should be in type!) */ 02595 if(!node_only_value(node)) { 02596 for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { 02597 if(nsout[a]->data==NULL && nsout[a]->hasoutput) { 02598 node->need_exec= 1; 02599 break; 02600 } 02601 } 02602 } 02603 02604 /* test the inputs */ 02605 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { 02606 /* skip viewer nodes in bg render or group edit */ 02607 if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit)) 02608 node->need_exec= 0; 02609 /* is sock in use? */ 02610 else if(sock->link) { 02611 bNodeLink *link= sock->link; 02612 02613 /* this is the test for a cyclic case */ 02614 if(link->fromnode==NULL || link->tonode==NULL); 02615 else if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { 02616 if(link->fromnode->need_exec) { 02617 node->need_exec= 1; 02618 break; 02619 } 02620 } 02621 else { 02622 node->need_exec= 0; 02623 printf("Node %s skipped, cyclic dependency\n", node->name); 02624 } 02625 } 02626 } 02627 02628 if(node->need_exec) { 02629 02630 /* free output buffers */ 02631 for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { 02632 if(nsout[a]->data) { 02633 free_compbuf(nsout[a]->data); 02634 nsout[a]->data= NULL; 02635 } 02636 } 02637 totnode++; 02638 /* printf("node needs exec %s\n", node->name); */ 02639 02640 /* tag for getExecutableNode() */ 02641 node->exec= 0; 02642 } 02643 else { 02644 /* tag for getExecutableNode() */ 02645 node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED; 02646 02647 } 02648 } 02649 02650 /* last step: set the stack values for only-value nodes */ 02651 /* just does all now, compared to a full buffer exec this is nothing */ 02652 if(totnode) { 02653 for(node= ntree->nodes.first; node; node= node->next) { 02654 if(node->need_exec==0 && node_only_value(node)) { 02655 if(node->typeinfo->execfunc) { 02656 node_get_stack(node, thd->stack, nsin, nsout, NULL); 02657 node->typeinfo->execfunc(thd->rd, node, nsin, nsout); 02658 } 02659 } 02660 } 02661 } 02662 02663 return totnode; 02664 } 02665 02666 /* while executing tree, free buffers from nodes that are not needed anymore */ 02667 static void freeExecutableNode(bNodeTree *ntree) 02668 { 02669 /* node outputs can be freed when: 02670 - not a render result or image node 02671 - when node outputs go to nodes all being set NODE_FINISHED 02672 */ 02673 bNode *node; 02674 bNodeSocket *sock; 02675 02676 /* set exec flag for finished nodes that might need freed */ 02677 for(node= ntree->nodes.first; node; node= node->next) { 02678 if(node->type!=CMP_NODE_R_LAYERS) 02679 if(node->exec & NODE_FINISHED) 02680 node->exec |= NODE_FREEBUFS; 02681 } 02682 /* clear this flag for input links that are not done yet */ 02683 for(node= ntree->nodes.first; node; node= node->next) { 02684 if((node->exec & NODE_FINISHED)==0) { 02685 for(sock= node->inputs.first; sock; sock= sock->next) 02686 if(sock->link && sock->link->fromnode) 02687 sock->link->fromnode->exec &= ~NODE_FREEBUFS; 02688 } 02689 } 02690 /* now we can free buffers */ 02691 for(node= ntree->nodes.first; node; node= node->next) { 02692 if(node->exec & NODE_FREEBUFS) { 02693 for(sock= node->outputs.first; sock; sock= sock->next) { 02694 bNodeStack *ns= get_socket_stack(ntree->stack, sock, NULL); 02695 if(ns && ns->data) { 02696 free_compbuf(ns->data); 02697 ns->data= NULL; 02698 // printf("freed buf node %s \n", node->name); 02699 } 02700 } 02701 } 02702 } 02703 } 02704 02705 static bNode *getExecutableNode(bNodeTree *ntree) 02706 { 02707 bNode *node; 02708 bNodeSocket *sock; 02709 02710 for(node= ntree->nodes.first; node; node= node->next) { 02711 if(node->exec==0) { 02712 02713 /* input sockets should be ready */ 02714 for(sock= node->inputs.first; sock; sock= sock->next) { 02715 if(sock->link && sock->link->fromnode) 02716 if((sock->link->fromnode->exec & NODE_READY)==0) 02717 break; 02718 } 02719 if(sock==NULL) 02720 return node; 02721 } 02722 } 02723 return NULL; 02724 } 02725 02726 /* check if texture nodes need exec or end */ 02727 static void ntree_composite_texnode(bNodeTree *ntree, int init) 02728 { 02729 bNode *node; 02730 02731 for(node= ntree->nodes.first; node; node= node->next) { 02732 if(node->type==CMP_NODE_TEXTURE && node->id) { 02733 Tex *tex= (Tex *)node->id; 02734 if(tex->nodetree && tex->use_nodes) { 02735 /* has internal flag to detect it only does it once */ 02736 if(init) 02737 ntreeBeginExecTree(tex->nodetree); 02738 else 02739 ntreeEndExecTree(tex->nodetree); 02740 } 02741 } 02742 } 02743 02744 } 02745 02746 /* optimized tree execute test for compositing */ 02747 void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) 02748 { 02749 bNode *node; 02750 ListBase threads; 02751 ThreadData thdata; 02752 int totnode, curnode, rendering= 1; 02753 02754 if(ntree==NULL) return; 02755 02756 if(do_preview) 02757 ntreeInitPreview(ntree, 0, 0); 02758 02759 ntreeBeginExecTree(ntree); 02760 ntree_composite_texnode(ntree, 1); 02761 02762 /* prevent unlucky accidents */ 02763 if(G.background) 02764 rd->scemode &= ~R_COMP_CROP; 02765 02766 /* setup callerdata for thread callback */ 02767 thdata.rd= rd; 02768 thdata.stack= ntree->stack; 02769 02770 /* fixed seed, for example noise texture */ 02771 BLI_srandom(rd->cfra); 02772 02773 /* sets need_exec tags in nodes */ 02774 curnode = totnode= setExecutableNodes(ntree, &thdata); 02775 02776 BLI_init_threads(&threads, exec_composite_node, rd->threads); 02777 02778 while(rendering) { 02779 02780 if(BLI_available_threads(&threads)) { 02781 node= getExecutableNode(ntree); 02782 if(node) { 02783 if(ntree->progress && totnode) 02784 ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode)); 02785 if(ntree->stats_draw) { 02786 char str[64]; 02787 sprintf(str, "Compositing %d %s", curnode, node->name); 02788 ntree->stats_draw(ntree->sdh, str); 02789 } 02790 curnode--; 02791 02792 node->threaddata = &thdata; 02793 node->exec= NODE_PROCESSING; 02794 BLI_insert_thread(&threads, node); 02795 } 02796 else 02797 PIL_sleep_ms(50); 02798 } 02799 else 02800 PIL_sleep_ms(50); 02801 02802 rendering= 0; 02803 /* test for ESC */ 02804 if(ntree->test_break && ntree->test_break(ntree->tbh)) { 02805 for(node= ntree->nodes.first; node; node= node->next) 02806 node->exec |= NODE_READY; 02807 } 02808 02809 /* check for ready ones, and if we need to continue */ 02810 for(node= ntree->nodes.first; node; node= node->next) { 02811 if(node->exec & NODE_READY) { 02812 if((node->exec & NODE_FINISHED)==0) { 02813 BLI_remove_thread(&threads, node); /* this waits for running thread to finish btw */ 02814 node->exec |= NODE_FINISHED; 02815 02816 /* freeing unused buffers */ 02817 if(rd->scemode & R_COMP_FREE) 02818 freeExecutableNode(ntree); 02819 } 02820 } 02821 else rendering= 1; 02822 } 02823 } 02824 02825 BLI_end_threads(&threads); 02826 02827 ntreeEndExecTree(ntree); 02828 } 02829 02830 02831 /* ********** copy composite tree entirely, to allow threaded exec ******************* */ 02832 /* ***************** do NOT execute this in a thread! ****************** */ 02833 02834 /* returns localized tree for execution in threads */ 02835 /* local tree then owns all compbufs (for composite) */ 02836 bNodeTree *ntreeLocalize(bNodeTree *ntree) 02837 { 02838 bNodeTree *ltree; 02839 bNode *node; 02840 bNodeSocket *sock; 02841 02842 bAction *action_backup= NULL, *tmpact_backup= NULL; 02843 02844 /* Workaround for copying an action on each render! 02845 * set action to NULL so animdata actions dont get copied */ 02846 AnimData *adt= BKE_animdata_from_id(&ntree->id); 02847 02848 if(adt) { 02849 action_backup= adt->action; 02850 tmpact_backup= adt->tmpact; 02851 02852 adt->action= NULL; 02853 adt->tmpact= NULL; 02854 } 02855 02856 /* node copy func */ 02857 ltree= ntreeCopyTree(ntree); 02858 02859 if(adt) { 02860 AnimData *ladt= BKE_animdata_from_id(<ree->id); 02861 02862 adt->action= ladt->action= action_backup; 02863 adt->tmpact= ladt->tmpact= tmpact_backup; 02864 02865 if(action_backup) action_backup->id.us++; 02866 if(tmpact_backup) tmpact_backup->id.us++; 02867 02868 } 02869 /* end animdata uglyness */ 02870 02871 /* ensures only a single output node is enabled */ 02872 ntreeSetOutput(ltree); 02873 02874 for(node= ntree->nodes.first; node; node= node->next) { 02875 02876 /* store new_node pointer to original */ 02877 node->new_node->new_node= node; 02878 02879 if(ntree->type==NTREE_COMPOSIT) { 02880 /* ensure new user input gets handled ok, only composites (texture nodes will break, for painting since it uses no tags) */ 02881 node->need_exec= 0; 02882 02883 /* move over the compbufs */ 02884 /* right after ntreeCopyTree() oldsock pointers are valid */ 02885 02886 if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { 02887 if(node->id) { 02888 if(node->flag & NODE_DO_OUTPUT) 02889 node->new_node->id= (ID *)copy_image((Image *)node->id); 02890 else 02891 node->new_node->id= NULL; 02892 } 02893 } 02894 02895 for(sock= node->outputs.first; sock; sock= sock->next) { 02896 02897 sock->new_sock->ns.data= sock->ns.data; 02898 compbuf_set_node(sock->new_sock->ns.data, node->new_node); 02899 02900 sock->ns.data= NULL; 02901 sock->new_sock->new_sock= sock; 02902 } 02903 } 02904 } 02905 02906 return ltree; 02907 } 02908 02909 static int node_exists(bNodeTree *ntree, bNode *testnode) 02910 { 02911 bNode *node= ntree->nodes.first; 02912 for(; node; node= node->next) 02913 if(node==testnode) 02914 return 1; 02915 return 0; 02916 } 02917 02918 static int outsocket_exists(bNode *node, bNodeSocket *testsock) 02919 { 02920 bNodeSocket *sock= node->outputs.first; 02921 for(; sock; sock= sock->next) 02922 if(sock==testsock) 02923 return 1; 02924 return 0; 02925 } 02926 02927 02928 /* sync local composite with real tree */ 02929 /* local composite is supposed to be running, be careful moving previews! */ 02930 /* is called by jobs manager, outside threads, so it doesnt happen during draw */ 02931 void ntreeLocalSync(bNodeTree *localtree, bNodeTree *ntree) 02932 { 02933 bNode *lnode; 02934 02935 if(ntree->type==NTREE_COMPOSIT) { 02936 /* move over the compbufs and previews */ 02937 for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { 02938 if( (lnode->exec & NODE_READY) && !(lnode->exec & NODE_SKIPPED) ) { 02939 if(node_exists(ntree, lnode->new_node)) { 02940 02941 if(lnode->preview && lnode->preview->rect) { 02942 node_free_preview(lnode->new_node); 02943 lnode->new_node->preview= lnode->preview; 02944 lnode->preview= NULL; 02945 } 02946 } 02947 } 02948 } 02949 } 02950 else if(ELEM(ntree->type, NTREE_SHADER, NTREE_TEXTURE)) { 02951 /* copy over contents of previews */ 02952 for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { 02953 if(node_exists(ntree, lnode->new_node)) { 02954 bNode *node= lnode->new_node; 02955 02956 if(node->preview && node->preview->rect) { 02957 if(lnode->preview && lnode->preview->rect) { 02958 int xsize= node->preview->xsize; 02959 int ysize= node->preview->ysize; 02960 memcpy(node->preview->rect, lnode->preview->rect, 4*xsize + xsize*ysize*sizeof(char)*4); 02961 } 02962 } 02963 } 02964 } 02965 } 02966 } 02967 02968 /* merge local tree results back, and free local tree */ 02969 /* we have to assume the editor already changed completely */ 02970 void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree) 02971 { 02972 bNode *lnode; 02973 bNodeSocket *lsock; 02974 02975 /* move over the compbufs and previews */ 02976 for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) { 02977 if(node_exists(ntree, lnode->new_node)) { 02978 02979 if(lnode->preview && lnode->preview->rect) { 02980 node_free_preview(lnode->new_node); 02981 lnode->new_node->preview= lnode->preview; 02982 lnode->preview= NULL; 02983 } 02984 02985 if(ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) { 02986 if(lnode->id && (lnode->flag & NODE_DO_OUTPUT)) { 02987 /* image_merge does sanity check for pointers */ 02988 BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id); 02989 } 02990 } 02991 02992 for(lsock= lnode->outputs.first; lsock; lsock= lsock->next) { 02993 if(outsocket_exists(lnode->new_node, lsock->new_sock)) { 02994 lsock->new_sock->ns.data= lsock->ns.data; 02995 compbuf_set_node(lsock->new_sock->ns.data, lnode->new_node); 02996 lsock->ns.data= NULL; 02997 lsock->new_sock= NULL; 02998 } 02999 } 03000 } 03001 } 03002 ntreeFreeTree(localtree); 03003 MEM_freeN(localtree); 03004 } 03005 03006 /* *********************************************** */ 03007 03008 /* GPU material from shader nodes */ 03009 03010 static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) 03011 { 03012 bNodeSocket *sock; 03013 int i; 03014 03015 for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { 03016 memset(&gs[i], 0, sizeof(gs[i])); 03017 03018 QUATCOPY(gs[i].vec, ns[i]->vec); 03019 gs[i].link= ns[i]->data; 03020 03021 if (sock->type == SOCK_VALUE) 03022 gs[i].type= GPU_FLOAT; 03023 else if (sock->type == SOCK_VECTOR) 03024 gs[i].type= GPU_VEC3; 03025 else if (sock->type == SOCK_RGBA) 03026 gs[i].type= GPU_VEC4; 03027 else 03028 gs[i].type= GPU_NONE; 03029 03030 gs[i].name = ""; 03031 gs[i].hasinput= ns[i]->hasinput && ns[i]->data; 03032 gs[i].hasoutput= ns[i]->hasoutput && ns[i]->data; 03033 gs[i].sockettype= ns[i]->sockettype; 03034 } 03035 03036 gs[i].type= GPU_NONE; 03037 } 03038 03039 static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) 03040 { 03041 bNodeSocket *sock; 03042 int i; 03043 03044 for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { 03045 ns[i]->data= gs[i].link; 03046 ns[i]->sockettype= gs[i].sockettype; 03047 } 03048 } 03049 03050 static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in) 03051 { 03052 bNode *node; 03053 bNodeTree *ntree= (bNodeTree *)gnode->id; 03054 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 03055 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ 03056 GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; 03057 int doit = 0; 03058 03059 if(ntree==NULL) return; 03060 03061 stack+= gnode->stack_index; 03062 03063 for(node= ntree->nodes.first; node; node= node->next) { 03064 if(node->typeinfo->gpufunc) { 03065 node_get_stack(node, stack, nsin, nsout, in); 03066 03067 doit = 0; 03068 03069 /* for groups, only execute outputs for edited group */ 03070 if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { 03071 if(gnode->flag & NODE_GROUP_EDIT) 03072 if(node->flag & NODE_DO_OUTPUT) 03073 doit = 1; 03074 } 03075 else 03076 doit = 1; 03077 03078 if(doit) { 03079 gpu_from_node_stack(&node->inputs, nsin, gpuin); 03080 gpu_from_node_stack(&node->outputs, nsout, gpuout); 03081 if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) 03082 data_from_gpu_stack(&node->outputs, nsout, gpuout); 03083 } 03084 } 03085 } 03086 } 03087 03088 void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) 03089 { 03090 bNode *node; 03091 bNodeStack *stack; 03092 bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ 03093 bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ 03094 GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; 03095 03096 if((ntree->init & NTREE_EXEC_INIT)==0) 03097 ntreeBeginExecTree(ntree); 03098 03099 stack= ntree->stack; 03100 03101 for(node= ntree->nodes.first; node; node= node->next) { 03102 if(node->typeinfo->gpufunc) { 03103 node_get_stack(node, stack, nsin, nsout, NULL); 03104 gpu_from_node_stack(&node->inputs, nsin, gpuin); 03105 gpu_from_node_stack(&node->outputs, nsout, gpuout); 03106 if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) 03107 data_from_gpu_stack(&node->outputs, nsout, gpuout); 03108 } 03109 else if(node->type==NODE_GROUP && node->id) { 03110 node_get_stack(node, stack, nsin, nsout, NULL); 03111 gpu_node_group_execute(stack, mat, node, nsin); 03112 } 03113 } 03114 03115 ntreeEndExecTree(ntree); 03116 } 03117 03118 /* **************** call to switch lamploop for material node ************ */ 03119 03120 void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); 03121 03122 void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *)) 03123 { 03124 node_shader_lamp_loop= lamp_loop_func; 03125 } 03126 03127 /* clumsy checking... should do dynamic outputs once */ 03128 static void force_hidden_passes(bNode *node, int passflag) 03129 { 03130 bNodeSocket *sock; 03131 03132 for(sock= node->outputs.first; sock; sock= sock->next) 03133 sock->flag &= ~SOCK_UNAVAIL; 03134 03135 sock= BLI_findlink(&node->outputs, RRES_OUT_Z); 03136 if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL; 03137 sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL); 03138 if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL; 03139 sock= BLI_findlink(&node->outputs, RRES_OUT_VEC); 03140 if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL; 03141 sock= BLI_findlink(&node->outputs, RRES_OUT_UV); 03142 if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL; 03143 sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA); 03144 if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL; 03145 sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF); 03146 if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL; 03147 sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC); 03148 if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL; 03149 sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW); 03150 if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL; 03151 sock= BLI_findlink(&node->outputs, RRES_OUT_AO); 03152 if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL; 03153 sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT); 03154 if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL; 03155 sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT); 03156 if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL; 03157 sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT); 03158 if(!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL; 03159 sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB); 03160 if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL; 03161 sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA); 03162 if(!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL; 03163 sock= BLI_findlink(&node->outputs, RRES_OUT_MIST); 03164 if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL; 03165 sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT); 03166 if(!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL; 03167 sock= BLI_findlink(&node->outputs, RRES_OUT_ENV); 03168 if(!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL; 03169 03170 } 03171 03172 /* based on rules, force sockets hidden always */ 03173 void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene) 03174 { 03175 bNode *node; 03176 03177 if(ntree==NULL) return; 03178 03179 for(node= ntree->nodes.first; node; node= node->next) { 03180 if( node->type==CMP_NODE_R_LAYERS) { 03181 Scene *sce= node->id?(Scene *)node->id:curscene; 03182 SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1); 03183 if(srl) 03184 force_hidden_passes(node, srl->passflag); 03185 } 03186 else if( node->type==CMP_NODE_IMAGE) { 03187 Image *ima= (Image *)node->id; 03188 if(ima) { 03189 if(ima->rr) { 03190 ImageUser *iuser= node->storage; 03191 RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer); 03192 if(rl) 03193 force_hidden_passes(node, rl->passflag); 03194 else 03195 force_hidden_passes(node, 0); 03196 } 03197 else if(ima->type!=IMA_TYPE_MULTILAYER) { /* if ->rr not yet read we keep inputs */ 03198 force_hidden_passes(node, RRES_OUT_Z); 03199 } 03200 else 03201 force_hidden_passes(node, 0); 03202 } 03203 else 03204 force_hidden_passes(node, 0); 03205 } 03206 } 03207 03208 } 03209 03210 /* called from render pipeline, to tag render input and output */ 03211 /* need to do all scenes, to prevent errors when you re-render 1 scene */ 03212 void ntreeCompositTagRender(Scene *curscene) 03213 { 03214 Scene *sce; 03215 03216 for(sce= G.main->scene.first; sce; sce= sce->id.next) { 03217 if(sce->nodetree) { 03218 bNode *node; 03219 03220 for(node= sce->nodetree->nodes.first; node; node= node->next) { 03221 if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE) 03222 NodeTagChanged(sce->nodetree, node); 03223 else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */ 03224 NodeTagChanged(sce->nodetree, node); 03225 } 03226 } 03227 } 03228 } 03229 03230 static int node_animation_properties(bNodeTree *ntree, bNode *node) 03231 { 03232 bNodeSocket *sock; 03233 const ListBase *lb; 03234 Link *link; 03235 PointerRNA ptr; 03236 PropertyRNA *prop; 03237 03238 /* check to see if any of the node's properties have fcurves */ 03239 RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr); 03240 lb = RNA_struct_type_properties(ptr.type); 03241 03242 for (link=lb->first; link; link=link->next) { 03243 int driven, len=1, index; 03244 prop = (PropertyRNA *)link; 03245 03246 if (RNA_property_array_check(&ptr, prop)) 03247 len = RNA_property_array_length(&ptr, prop); 03248 03249 for (index=0; index<len; index++) { 03250 if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) { 03251 NodeTagChanged(ntree, node); 03252 return 1; 03253 } 03254 } 03255 } 03256 03257 /* now check node sockets */ 03258 for (sock = node->inputs.first; sock; sock=sock->next) { 03259 int driven, len=1, index; 03260 03261 RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); 03262 prop = RNA_struct_find_property(&ptr, "default_value"); 03263 03264 if (RNA_property_array_check(&ptr, prop)) 03265 len = RNA_property_array_length(&ptr, prop); 03266 03267 for (index=0; index<len; index++) { 03268 if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) { 03269 NodeTagChanged(ntree, node); 03270 return 1; 03271 } 03272 } 03273 } 03274 03275 return 0; 03276 } 03277 03278 /* tags nodes that have animation capabilities */ 03279 int ntreeCompositTagAnimated(bNodeTree *ntree) 03280 { 03281 bNode *node; 03282 int tagged= 0; 03283 03284 if(ntree==NULL) return 0; 03285 03286 for(node= ntree->nodes.first; node; node= node->next) { 03287 03288 tagged = node_animation_properties(ntree, node); 03289 03290 /* otherwise always tag these node types */ 03291 if(node->type==CMP_NODE_IMAGE) { 03292 Image *ima= (Image *)node->id; 03293 if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { 03294 NodeTagChanged(ntree, node); 03295 tagged= 1; 03296 } 03297 } 03298 else if(node->type==CMP_NODE_TIME) { 03299 NodeTagChanged(ntree, node); 03300 tagged= 1; 03301 } 03302 /* here was tag render layer, but this is called after a render, so re-composites fail */ 03303 else if(node->type==NODE_GROUP) { 03304 if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) { 03305 NodeTagChanged(ntree, node); 03306 } 03307 } 03308 } 03309 03310 return tagged; 03311 } 03312 03313 03314 /* called from image window preview */ 03315 void ntreeCompositTagGenerators(bNodeTree *ntree) 03316 { 03317 bNode *node; 03318 03319 if(ntree==NULL) return; 03320 03321 for(node= ntree->nodes.first; node; node= node->next) { 03322 if( ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE)) 03323 NodeTagChanged(ntree, node); 03324 } 03325 } 03326 03327 /* XXX after render animation system gets a refresh, this call allows composite to end clean */ 03328 void ntreeClearTags(bNodeTree *ntree) 03329 { 03330 bNode *node; 03331 03332 if(ntree==NULL) return; 03333 03334 for(node= ntree->nodes.first; node; node= node->next) { 03335 node->need_exec= 0; 03336 if(node->type==NODE_GROUP) 03337 ntreeClearTags((bNodeTree *)node->id); 03338 } 03339 } 03340 03341 03342 int ntreeTexTagAnimated(bNodeTree *ntree) 03343 { 03344 bNode *node; 03345 03346 if(ntree==NULL) return 0; 03347 03348 for(node= ntree->nodes.first; node; node= node->next) { 03349 if(node->type==TEX_NODE_CURVE_TIME) { 03350 NodeTagChanged(ntree, node); 03351 return 1; 03352 } 03353 else if(node->type==NODE_GROUP) { 03354 if( ntreeTexTagAnimated((bNodeTree *)node->id) ) { 03355 return 1; 03356 } 03357 } 03358 } 03359 03360 return 0; 03361 } 03362 03363 /* ************* node definition init ********** */ 03364 03365 void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag, 03366 struct bNodeSocketType *inputs, struct bNodeSocketType *outputs) 03367 { 03368 memset(ntype, 0, sizeof(bNodeType)); 03369 03370 ntype->type = type; 03371 ntype->name = name; 03372 ntype->nclass = nclass; 03373 ntype->flag = flag; 03374 03375 ntype->inputs = inputs; 03376 ntype->outputs = outputs; 03377 03378 /* default size values */ 03379 ntype->width = 140; 03380 ntype->minwidth = 100; 03381 ntype->maxwidth = 320; 03382 } 03383 03384 void node_type_init(bNodeType *ntype, void (*initfunc)(struct bNode *)) 03385 { 03386 ntype->initfunc = initfunc; 03387 } 03388 03389 void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth) 03390 { 03391 ntype->width = width; 03392 ntype->minwidth = minwidth; 03393 ntype->maxwidth = maxwidth; 03394 } 03395 03396 void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *)) 03397 { 03398 if (storagename) 03399 strncpy(ntype->storagename, storagename, sizeof(ntype->storagename)); 03400 else 03401 ntype->storagename[0] = '\0'; 03402 ntype->copystoragefunc = copystoragefunc; 03403 ntype->freestoragefunc = freestoragefunc; 03404 } 03405 03406 void node_type_exec(struct bNodeType *ntype, void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **)) 03407 { 03408 ntype->execfunc = execfunc; 03409 } 03410 03411 void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out)) 03412 { 03413 ntype->gpufunc = gpufunc; 03414 } 03415 03416 void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *)) 03417 { 03418 ntype->labelfunc = labelfunc; 03419 } 03420 03421 static bNodeType *is_nodetype_registered(ListBase *typelist, int type, ID *id) 03422 { 03423 bNodeType *ntype= typelist->first; 03424 03425 for(;ntype; ntype= ntype->next ) 03426 if(ntype->type==type && ntype->id==id) 03427 return ntype; 03428 03429 return NULL; 03430 } 03431 03432 /* type can be from a static array, we make copy for duplicate types (like group) */ 03433 void nodeRegisterType(ListBase *typelist, const bNodeType *ntype) 03434 { 03435 bNodeType *found= is_nodetype_registered(typelist, ntype->type, ntype->id); 03436 03437 if(found==NULL) { 03438 bNodeType *ntypen= MEM_callocN(sizeof(bNodeType), "node type"); 03439 *ntypen= *ntype; 03440 BLI_addtail(typelist, ntypen); 03441 } 03442 } 03443 03444 static void registerCompositNodes(ListBase *ntypelist) 03445 { 03446 register_node_type_group(ntypelist); 03447 03448 register_node_type_cmp_rlayers(ntypelist); 03449 register_node_type_cmp_image(ntypelist); 03450 register_node_type_cmp_texture(ntypelist); 03451 register_node_type_cmp_value(ntypelist); 03452 register_node_type_cmp_rgb(ntypelist); 03453 register_node_type_cmp_curve_time(ntypelist); 03454 03455 register_node_type_cmp_composite(ntypelist); 03456 register_node_type_cmp_viewer(ntypelist); 03457 register_node_type_cmp_splitviewer(ntypelist); 03458 register_node_type_cmp_output_file(ntypelist); 03459 register_node_type_cmp_view_levels(ntypelist); 03460 03461 register_node_type_cmp_curve_rgb(ntypelist); 03462 register_node_type_cmp_mix_rgb(ntypelist); 03463 register_node_type_cmp_hue_sat(ntypelist); 03464 register_node_type_cmp_brightcontrast(ntypelist); 03465 register_node_type_cmp_gamma(ntypelist); 03466 register_node_type_cmp_invert(ntypelist); 03467 register_node_type_cmp_alphaover(ntypelist); 03468 register_node_type_cmp_zcombine(ntypelist); 03469 register_node_type_cmp_colorbalance(ntypelist); 03470 register_node_type_cmp_huecorrect(ntypelist); 03471 03472 register_node_type_cmp_normal(ntypelist); 03473 register_node_type_cmp_curve_vec(ntypelist); 03474 register_node_type_cmp_map_value(ntypelist); 03475 register_node_type_cmp_normalize(ntypelist); 03476 03477 register_node_type_cmp_filter(ntypelist); 03478 register_node_type_cmp_blur(ntypelist); 03479 register_node_type_cmp_dblur(ntypelist); 03480 register_node_type_cmp_bilateralblur(ntypelist); 03481 register_node_type_cmp_vecblur(ntypelist); 03482 register_node_type_cmp_dilateerode(ntypelist); 03483 register_node_type_cmp_defocus(ntypelist); 03484 03485 register_node_type_cmp_valtorgb(ntypelist); 03486 register_node_type_cmp_rgbtobw(ntypelist); 03487 register_node_type_cmp_setalpha(ntypelist); 03488 register_node_type_cmp_idmask(ntypelist); 03489 register_node_type_cmp_math(ntypelist); 03490 register_node_type_cmp_seprgba(ntypelist); 03491 register_node_type_cmp_combrgba(ntypelist); 03492 register_node_type_cmp_sephsva(ntypelist); 03493 register_node_type_cmp_combhsva(ntypelist); 03494 register_node_type_cmp_sepyuva(ntypelist); 03495 register_node_type_cmp_combyuva(ntypelist); 03496 register_node_type_cmp_sepycca(ntypelist); 03497 register_node_type_cmp_combycca(ntypelist); 03498 register_node_type_cmp_premulkey(ntypelist); 03499 03500 register_node_type_cmp_diff_matte(ntypelist); 03501 register_node_type_cmp_distance_matte(ntypelist); 03502 register_node_type_cmp_chroma_matte(ntypelist); 03503 register_node_type_cmp_color_matte(ntypelist); 03504 register_node_type_cmp_channel_matte(ntypelist); 03505 register_node_type_cmp_color_spill(ntypelist); 03506 register_node_type_cmp_luma_matte(ntypelist); 03507 03508 register_node_type_cmp_translate(ntypelist); 03509 register_node_type_cmp_rotate(ntypelist); 03510 register_node_type_cmp_scale(ntypelist); 03511 register_node_type_cmp_flip(ntypelist); 03512 register_node_type_cmp_crop(ntypelist); 03513 register_node_type_cmp_displace(ntypelist); 03514 register_node_type_cmp_mapuv(ntypelist); 03515 register_node_type_cmp_glare(ntypelist); 03516 register_node_type_cmp_tonemap(ntypelist); 03517 register_node_type_cmp_lensdist(ntypelist); 03518 } 03519 03520 static void registerShaderNodes(ListBase *ntypelist) 03521 { 03522 register_node_type_group(ntypelist); 03523 03524 register_node_type_sh_output(ntypelist); 03525 register_node_type_sh_mix_rgb(ntypelist); 03526 register_node_type_sh_valtorgb(ntypelist); 03527 register_node_type_sh_rgbtobw(ntypelist); 03528 register_node_type_sh_normal(ntypelist); 03529 register_node_type_sh_geom(ntypelist); 03530 register_node_type_sh_mapping(ntypelist); 03531 register_node_type_sh_curve_vec(ntypelist); 03532 register_node_type_sh_curve_rgb(ntypelist); 03533 register_node_type_sh_math(ntypelist); 03534 register_node_type_sh_vect_math(ntypelist); 03535 register_node_type_sh_squeeze(ntypelist); 03536 register_node_type_sh_camera(ntypelist); 03537 register_node_type_sh_material(ntypelist); 03538 register_node_type_sh_material_ext(ntypelist); 03539 register_node_type_sh_value(ntypelist); 03540 register_node_type_sh_rgb(ntypelist); 03541 register_node_type_sh_texture(ntypelist); 03542 // register_node_type_sh_dynamic(ntypelist); 03543 register_node_type_sh_invert(ntypelist); 03544 register_node_type_sh_seprgb(ntypelist); 03545 register_node_type_sh_combrgb(ntypelist); 03546 register_node_type_sh_hue_sat(ntypelist); 03547 } 03548 03549 static void registerTextureNodes(ListBase *ntypelist) 03550 { 03551 register_node_type_group(ntypelist); 03552 03553 register_node_type_tex_math(ntypelist); 03554 register_node_type_tex_mix_rgb(ntypelist); 03555 register_node_type_tex_valtorgb(ntypelist); 03556 register_node_type_tex_rgbtobw(ntypelist); 03557 register_node_type_tex_valtonor(ntypelist); 03558 register_node_type_tex_curve_rgb(ntypelist); 03559 register_node_type_tex_curve_time(ntypelist); 03560 register_node_type_tex_invert(ntypelist); 03561 register_node_type_tex_hue_sat(ntypelist); 03562 register_node_type_tex_coord(ntypelist); 03563 register_node_type_tex_distance(ntypelist); 03564 register_node_type_tex_compose(ntypelist); 03565 register_node_type_tex_decompose(ntypelist); 03566 03567 register_node_type_tex_output(ntypelist); 03568 register_node_type_tex_viewer(ntypelist); 03569 03570 register_node_type_tex_checker(ntypelist); 03571 register_node_type_tex_texture(ntypelist); 03572 register_node_type_tex_bricks(ntypelist); 03573 register_node_type_tex_image(ntypelist); 03574 03575 register_node_type_tex_rotate(ntypelist); 03576 register_node_type_tex_translate(ntypelist); 03577 register_node_type_tex_scale(ntypelist); 03578 register_node_type_tex_at(ntypelist); 03579 03580 register_node_type_tex_proc_voronoi(ntypelist); 03581 register_node_type_tex_proc_blend(ntypelist); 03582 register_node_type_tex_proc_magic(ntypelist); 03583 register_node_type_tex_proc_marble(ntypelist); 03584 register_node_type_tex_proc_clouds(ntypelist); 03585 register_node_type_tex_proc_wood(ntypelist); 03586 register_node_type_tex_proc_musgrave(ntypelist); 03587 register_node_type_tex_proc_noise(ntypelist); 03588 register_node_type_tex_proc_stucci(ntypelist); 03589 register_node_type_tex_proc_distnoise(ntypelist); 03590 } 03591 03592 static void remove_dynamic_typeinfos(ListBase *list) 03593 { 03594 bNodeType *ntype= list->first; 03595 bNodeType *next= NULL; 03596 while(ntype) { 03597 next= ntype->next; 03598 if(ntype->type==NODE_DYNAMIC && ntype->id!=NULL) { 03599 BLI_remlink(list, ntype); 03600 if(ntype->inputs) { 03601 bNodeSocketType *sock= ntype->inputs; 03602 while(sock->type!=-1) { 03603 MEM_freeN((void *)sock->name); 03604 sock++; 03605 } 03606 MEM_freeN(ntype->inputs); 03607 } 03608 if(ntype->outputs) { 03609 bNodeSocketType *sock= ntype->outputs; 03610 while(sock->type!=-1) { 03611 MEM_freeN((void *)sock->name); 03612 sock++; 03613 } 03614 MEM_freeN(ntype->outputs); 03615 } 03616 if(ntype->name) { 03617 MEM_freeN((void *)ntype->name); 03618 } 03619 MEM_freeN(ntype); 03620 } 03621 ntype= next; 03622 } 03623 } 03624 03625 void init_nodesystem(void) 03626 { 03627 registerCompositNodes(&node_all_composit); 03628 registerShaderNodes(&node_all_shaders); 03629 registerTextureNodes(&node_all_textures); 03630 } 03631 03632 void free_nodesystem(void) 03633 { 03634 /*remove_dynamic_typeinfos(&node_all_composit);*/ /* unused for now */ 03635 BLI_freelistN(&node_all_composit); 03636 remove_dynamic_typeinfos(&node_all_shaders); 03637 BLI_freelistN(&node_all_shaders); 03638 BLI_freelistN(&node_all_textures); 03639 } 03640 03641 /* called from unlink_scene, when deleting a scene goes over all scenes 03642 * other than the input, checks if they have render layer nodes referencing 03643 * the to-be-deleted scene, and resets them to NULL. */ 03644 03645 /* XXX needs to get current scene then! */ 03646 void clear_scene_in_nodes(Main *bmain, Scene *sce) 03647 { 03648 Scene *sce1; 03649 bNode *node; 03650 03651 for(sce1= bmain->scene.first; sce1; sce1=sce1->id.next) { 03652 if(sce1!=sce) { 03653 if(sce1->nodetree) { 03654 for(node= sce1->nodetree->nodes.first; node; node= node->next) { 03655 if(node->type==CMP_NODE_R_LAYERS) { 03656 Scene *nodesce= (Scene *)node->id; 03657 03658 if (nodesce==sce) node->id = NULL; 03659 } 03660 } 03661 } 03662 } 03663 } 03664 } 03665