Blender  V2.59
node.c
Go to the documentation of this file.
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(&ltree->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