Blender V2.61 - r43446

node.c

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