Blender V2.61 - r43446

node_common.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) 2007 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Lukas Toenne.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <string.h>
00034 
00035 #include "DNA_action_types.h"
00036 #include "DNA_anim_types.h"
00037 #include "DNA_node_types.h"
00038 
00039 #include "BLI_listbase.h"
00040 #include "BLI_string.h"
00041 #include "BLI_utildefines.h"
00042 
00043 #include "BKE_action.h"
00044 #include "BKE_animsys.h"
00045 #include "BKE_global.h"
00046 #include "BKE_library.h"
00047 #include "BKE_main.h"
00048 #include "BLI_math.h"
00049 #include "BKE_node.h"
00050 #include "BKE_utildefines.h"
00051 
00052 #include "RNA_access.h"
00053 #include "RNA_types.h"
00054 
00055 #include "MEM_guardedalloc.h"
00056 
00057 #include "node_common.h"
00058 #include "node_exec.h"
00059 #include "NOD_socket.h"
00060 
00061 /**** Group ****/
00062 
00063 bNodeSocket *node_group_find_input(bNode *gnode, bNodeSocket *gsock)
00064 {
00065     bNodeSocket *sock;
00066     for (sock=gnode->inputs.first; sock; sock=sock->next)
00067         if (sock->groupsock == gsock)
00068             return sock;
00069     return NULL;
00070 }
00071 
00072 bNodeSocket *node_group_find_output(bNode *gnode, bNodeSocket *gsock)
00073 {
00074     bNodeSocket *sock;
00075     for (sock=gnode->outputs.first; sock; sock=sock->next)
00076         if (sock->groupsock == gsock)
00077             return sock;
00078     return NULL;
00079 }
00080 
00081 bNodeSocket *node_group_add_extern_socket(bNodeTree *UNUSED(ntree), ListBase *lb, int in_out, bNodeSocket *gsock)
00082 {
00083     bNodeSocket *sock;
00084     
00085     if (gsock->flag & SOCK_INTERNAL)
00086         return NULL;
00087     
00088     sock= MEM_callocN(sizeof(bNodeSocket), "sock");
00089     
00090     /* make a copy of the group socket */
00091     *sock = *gsock;
00092     sock->link = NULL;
00093     sock->next = sock->prev = NULL;
00094     sock->new_sock = NULL;
00095     
00096     /* group sockets are dynamically added */
00097     sock->flag |= SOCK_DYNAMIC;
00098     
00099     sock->own_index = gsock->own_index;
00100     sock->groupsock = gsock;
00101     sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
00102     
00103     if (gsock->default_value)
00104         sock->default_value = MEM_dupallocN(gsock->default_value);
00105     
00106     if(lb)
00107         BLI_addtail(lb, sock);
00108     
00109     return sock;
00110 }
00111 
00112 bNode *node_group_make_from_selected(bNodeTree *ntree)
00113 {
00114     bNodeLink *link, *linkn;
00115     bNode *node, *gnode, *nextn;
00116     bNodeTree *ngroup;
00117     bNodeSocket *gsock;
00118     ListBase anim_basepaths = {NULL, NULL};
00119     float min[2], max[2];
00120     int totnode=0;
00121     bNodeTemplate ntemp;
00122     
00123     INIT_MINMAX2(min, max);
00124     
00125     /* is there something to group? also do some clearing */
00126     for(node= ntree->nodes.first; node; node= node->next) {
00127         if(node->flag & NODE_SELECT) {
00128             /* no groups in groups */
00129             if(node->type==NODE_GROUP)
00130                 return NULL;
00131             DO_MINMAX2( (&node->locx), min, max);
00132             totnode++;
00133         }
00134         node->done= 0;
00135     }
00136     if(totnode==0) return NULL;
00137     
00138     /* check if all connections are OK, no unselected node has both
00139         inputs and outputs to a selection */
00140     for(link= ntree->links.first; link; link= link->next) {
00141         if(link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT)
00142             link->tonode->done |= 1;
00143         if(link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT)
00144             link->fromnode->done |= 2;
00145     }   
00146     
00147     for(node= ntree->nodes.first; node; node= node->next) {
00148         if((node->flag & NODE_SELECT)==0)
00149             if(node->done==3)
00150                 break;
00151     }
00152     if(node) 
00153         return NULL;
00154     
00155     /* OK! new nodetree */
00156     ngroup= ntreeAddTree("NodeGroup", ntree->type, NODE_GROUP);
00157     
00158     /* move nodes over */
00159     for(node= ntree->nodes.first; node; node= nextn) {
00160         nextn= node->next;
00161         if(node->flag & NODE_SELECT) {
00162             /* keep track of this node's RNA "base" path (the part of the pat identifying the node) 
00163              * if the old nodetree has animation data which potentially covers this node
00164              */
00165             if (ntree->adt) {
00166                 PointerRNA ptr;
00167                 char *path;
00168                 
00169                 RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr);
00170                 path = RNA_path_from_ID_to_struct(&ptr);
00171                 
00172                 if (path)
00173                     BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
00174             }
00175             
00176             /* change node-collection membership */
00177             BLI_remlink(&ntree->nodes, node);
00178             BLI_addtail(&ngroup->nodes, node);
00179             
00180             node->locx-= 0.5f*(min[0]+max[0]);
00181             node->locy-= 0.5f*(min[1]+max[1]);
00182         }
00183     }
00184 
00185     /* move animation data over */
00186     if (ntree->adt) {
00187         LinkData *ld, *ldn=NULL;
00188         
00189         BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths);
00190         
00191         /* paths + their wrappers need to be freed */
00192         for (ld = anim_basepaths.first; ld; ld = ldn) {
00193             ldn = ld->next;
00194             
00195             MEM_freeN(ld->data);
00196             BLI_freelinkN(&anim_basepaths, ld);
00197         }
00198     }
00199     
00200     /* node groups don't use internal cached data */
00201     ntreeFreeCache(ngroup);
00202     
00203     /* make group node */
00204     ntemp.type = NODE_GROUP;
00205     ntemp.ngroup = ngroup;
00206     gnode= nodeAddNode(ntree, &ntemp);
00207     gnode->locx= 0.5f*(min[0]+max[0]);
00208     gnode->locy= 0.5f*(min[1]+max[1]);
00209     
00210     /* relink external sockets */
00211     for(link= ntree->links.first; link; link= linkn) {
00212         linkn= link->next;
00213         
00214         if(link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) {
00215             BLI_remlink(&ntree->links, link);
00216             BLI_addtail(&ngroup->links, link);
00217         }
00218         else if(link->tonode && (link->tonode->flag & NODE_SELECT)) {
00219             gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN);
00220             link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
00221             link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock);
00222             link->tonode = gnode;
00223         }
00224         else if(link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
00225             /* search for existing group node socket */
00226             for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next)
00227                 if (gsock->link && gsock->link->fromsock==link->fromsock)
00228                     break;
00229             if (!gsock) {
00230                 gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT);
00231                 gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
00232                 link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock);
00233             }
00234             else
00235                 link->fromsock = node_group_find_output(gnode, gsock);
00236             link->fromnode = gnode;
00237         }
00238     }
00239 
00240     /* update of the group tree */
00241     ngroup->update |= NTREE_UPDATE;
00242     ntreeUpdateTree(ngroup);
00243     /* update of the tree containing the group instance node */
00244     ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
00245     ntreeUpdateTree(ntree);
00246 
00247     return gnode;
00248 }
00249 
00250 /* XXX This is a makeshift function to have useful initial group socket values.
00251  * In the end this should be implemented by a flexible socket data conversion system,
00252  * which is yet to be implemented. The idea is that beside default standard conversions,
00253  * such as int-to-float, it should be possible to quickly select a conversion method or
00254  * a chain of conversions for each input, whenever there is more than one option.
00255  * E.g. a vector-to-float conversion could use either of the x/y/z components or
00256  * the vector length.
00257  *
00258  * In the interface this could be implemented by a pseudo-script textbox on linked inputs,
00259  * with quick selection from a predefined list of conversion options. Some Examples:
00260  * - vector component 'z' (vector->float):                      "z"
00261  * - greyscale color (float->color):                            "grey"
00262  * - color luminance (color->float):                            "lum"
00263  * - matrix column 2 length (matrix->vector->float):            "col[1].len"
00264  * - mesh vertex coordinate 'y' (mesh->vertex->vector->float):  "vertex.co.y"
00265  *
00266  * The actual conversion is then done by a series of conversion functions,
00267  * which are defined in the socket type structs.
00268  */
00269 static void convert_socket_value(bNodeSocket *from, bNodeSocket *to)
00270 {
00271     /* XXX only one of these pointers is valid! just putting them here for convenience */
00272     bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from->default_value;
00273     bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from->default_value;
00274     bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from->default_value;
00275     bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from->default_value;
00276     bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from->default_value;
00277 
00278     bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to->default_value;
00279     bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to->default_value;
00280     bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to->default_value;
00281     bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to->default_value;
00282     bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to->default_value;
00283 
00284     switch (from->type) {
00285     case SOCK_FLOAT:
00286         switch (to->type) {
00287         case SOCK_FLOAT:
00288             tofloat->value = fromfloat->value;
00289             break;
00290         case SOCK_INT:
00291             toint->value = (int)fromfloat->value;
00292             break;
00293         case SOCK_BOOLEAN:
00294             tobool->value = (fromfloat->value > 0.0f);
00295             break;
00296         case SOCK_VECTOR:
00297             tovector->value[0] = tovector->value[1] = tovector->value[2] = fromfloat->value;
00298             break;
00299         case SOCK_RGBA:
00300             torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = fromfloat->value;
00301             break;
00302         }
00303         break;
00304     case SOCK_INT:
00305         switch (to->type) {
00306         case SOCK_FLOAT:
00307             tofloat->value = (float)fromint->value;
00308             break;
00309         case SOCK_INT:
00310             toint->value = fromint->value;
00311             break;
00312         case SOCK_BOOLEAN:
00313             tobool->value = (fromint->value > 0);
00314             break;
00315         case SOCK_VECTOR:
00316             tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)fromint->value;
00317             break;
00318         case SOCK_RGBA:
00319             torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)fromint->value;
00320             break;
00321         }
00322         break;
00323     case SOCK_BOOLEAN:
00324         switch (to->type) {
00325         case SOCK_FLOAT:
00326             tofloat->value = (float)frombool->value;
00327             break;
00328         case SOCK_INT:
00329             toint->value = (int)frombool->value;
00330             break;
00331         case SOCK_BOOLEAN:
00332             tobool->value = frombool->value;
00333             break;
00334         case SOCK_VECTOR:
00335             tovector->value[0] = tovector->value[1] = tovector->value[2] = (float)frombool->value;
00336             break;
00337         case SOCK_RGBA:
00338             torgba->value[0] = torgba->value[1] = torgba->value[2] = torgba->value[3] = (float)frombool->value;
00339             break;
00340         }
00341         break;
00342     case SOCK_VECTOR:
00343         switch (to->type) {
00344         case SOCK_FLOAT:
00345             tofloat->value = fromvector->value[0];
00346             break;
00347         case SOCK_INT:
00348             toint->value = (int)fromvector->value[0];
00349             break;
00350         case SOCK_BOOLEAN:
00351             tobool->value = (fromvector->value[0] > 0.0f);
00352             break;
00353         case SOCK_VECTOR:
00354             copy_v3_v3(tovector->value, fromvector->value);
00355             break;
00356         case SOCK_RGBA:
00357             copy_v3_v3(torgba->value, fromvector->value);
00358             torgba->value[3] = 1.0f;
00359             break;
00360         }
00361         break;
00362     case SOCK_RGBA:
00363         switch (to->type) {
00364         case SOCK_FLOAT:
00365             tofloat->value = fromrgba->value[0];
00366             break;
00367         case SOCK_INT:
00368             toint->value = (int)fromrgba->value[0];
00369             break;
00370         case SOCK_BOOLEAN:
00371             tobool->value = (fromrgba->value[0] > 0.0f);
00372             break;
00373         case SOCK_VECTOR:
00374             copy_v3_v3(tovector->value, fromrgba->value);
00375             break;
00376         case SOCK_RGBA:
00377             copy_v4_v4(torgba->value, fromrgba->value);
00378             break;
00379         }
00380         break;
00381     }
00382 }
00383 
00384 static void copy_socket_value(bNodeSocket *from, bNodeSocket *to)
00385 {
00386     /* XXX only one of these pointers is valid! just putting them here for convenience */
00387     bNodeSocketValueFloat *fromfloat= (bNodeSocketValueFloat*)from->default_value;
00388     bNodeSocketValueInt *fromint= (bNodeSocketValueInt*)from->default_value;
00389     bNodeSocketValueBoolean *frombool= (bNodeSocketValueBoolean*)from->default_value;
00390     bNodeSocketValueVector *fromvector= (bNodeSocketValueVector*)from->default_value;
00391     bNodeSocketValueRGBA *fromrgba= (bNodeSocketValueRGBA*)from->default_value;
00392 
00393     bNodeSocketValueFloat *tofloat= (bNodeSocketValueFloat*)to->default_value;
00394     bNodeSocketValueInt *toint= (bNodeSocketValueInt*)to->default_value;
00395     bNodeSocketValueBoolean *tobool= (bNodeSocketValueBoolean*)to->default_value;
00396     bNodeSocketValueVector *tovector= (bNodeSocketValueVector*)to->default_value;
00397     bNodeSocketValueRGBA *torgba= (bNodeSocketValueRGBA*)to->default_value;
00398 
00399     if (from->type != to->type)
00400         return;
00401 
00402     switch (from->type) {
00403     case SOCK_FLOAT:
00404         *tofloat = *fromfloat;
00405         break;
00406     case SOCK_INT:
00407         *toint = *fromint;
00408         break;
00409     case SOCK_BOOLEAN:
00410         *tobool = *frombool;
00411         break;
00412     case SOCK_VECTOR:
00413         *tovector = *fromvector;
00414         break;
00415     case SOCK_RGBA:
00416         *torgba = *fromrgba;
00417         break;
00418     }
00419 }
00420 
00421 /* returns 1 if its OK */
00422 int node_group_ungroup(bNodeTree *ntree, bNode *gnode)
00423 {
00424     bNodeLink *link, *linkn;
00425     bNode *node, *nextn;
00426     bNodeTree *ngroup, *wgroup;
00427     ListBase anim_basepaths = {NULL, NULL};
00428     
00429     ngroup= (bNodeTree *)gnode->id;
00430     if(ngroup==NULL) return 0;
00431     
00432     /* clear new pointers, set in copytree */
00433     for(node= ntree->nodes.first; node; node= node->next)
00434         node->new_node= NULL;
00435     
00436     /* wgroup is a temporary copy of the NodeTree we're merging in
00437      *  - all of wgroup's nodes are transferred across to their new home
00438      *  - ngroup (i.e. the source NodeTree) is left unscathed
00439      */
00440     wgroup= ntreeCopyTree(ngroup);
00441     
00442     /* add the nodes into the ntree */
00443     for(node= wgroup->nodes.first; node; node= nextn) {
00444         nextn= node->next;
00445         
00446         /* keep track of this node's RNA "base" path (the part of the pat identifying the node) 
00447          * if the old nodetree has animation data which potentially covers this node
00448          */
00449         if (wgroup->adt) {
00450             PointerRNA ptr;
00451             char *path;
00452             
00453             RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr);
00454             path = RNA_path_from_ID_to_struct(&ptr);
00455             
00456             if (path)
00457                 BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
00458         }
00459         
00460         /* migrate node */
00461         BLI_remlink(&wgroup->nodes, node);
00462         BLI_addtail(&ntree->nodes, node);
00463         
00464         node->locx+= gnode->locx;
00465         node->locy+= gnode->locy;
00466         
00467         node->flag |= NODE_SELECT;
00468     }
00469     
00470     /* restore external links to and from the gnode */
00471     for(link= ntree->links.first; link; link= link->next) {
00472         if (link->fromnode==gnode) {
00473             if (link->fromsock->groupsock) {
00474                 bNodeSocket *gsock= link->fromsock->groupsock;
00475                 if (gsock->link) {
00476                     if (gsock->link->fromnode) {
00477                         /* NB: using the new internal copies here! the groupsock pointer still maps to the old tree */
00478                         link->fromnode = (gsock->link->fromnode ? gsock->link->fromnode->new_node : NULL);
00479                         link->fromsock = gsock->link->fromsock->new_sock;
00480                     }
00481                     else {
00482                         /* group output directly maps to group input */
00483                         bNodeSocket *insock= node_group_find_input(gnode, gsock->link->fromsock);
00484                         if (insock->link) {
00485                             link->fromnode = insock->link->fromnode;
00486                             link->fromsock = insock->link->fromsock;
00487                         }
00488                     }
00489                 }
00490                 else {
00491                     /* copy the default input value from the group socket default to the external socket */
00492                     convert_socket_value(gsock, link->tosock);
00493                 }
00494             }
00495         }
00496     }
00497     /* remove internal output links, these are not used anymore */
00498     for(link=wgroup->links.first; link; link= linkn) {
00499         linkn = link->next;
00500         if (!link->tonode)
00501             nodeRemLink(wgroup, link);
00502     }
00503     /* restore links from internal nodes */
00504     for(link= wgroup->links.first; link; link= link->next) {
00505         /* indicates link to group input */
00506         if (!link->fromnode) {
00507             /* NB: can't use find_group_node_input here,
00508              * because gnode sockets still point to the old tree!
00509              */
00510             bNodeSocket *insock;
00511             for (insock= gnode->inputs.first; insock; insock= insock->next)
00512                 if (insock->groupsock->new_sock == link->fromsock)
00513                     break;
00514             if (insock->link) {
00515                 link->fromnode = insock->link->fromnode;
00516                 link->fromsock = insock->link->fromsock;
00517             }
00518             else {
00519                 /* copy the default input value from the group node socket default to the internal socket */
00520                 convert_socket_value(insock, link->tosock);
00521                 nodeRemLink(wgroup, link);
00522             }
00523         }
00524     }
00525     
00526     /* add internal links to the ntree */
00527     for(link= wgroup->links.first; link; link= linkn) {
00528         linkn= link->next;
00529         BLI_remlink(&wgroup->links, link);
00530         BLI_addtail(&ntree->links, link);
00531     }
00532     
00533     /* and copy across the animation,
00534      * note that the animation data's action can be NULL here */
00535     if (wgroup->adt) {
00536         LinkData *ld, *ldn=NULL;
00537         bAction *waction;
00538         
00539         /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */
00540         waction = wgroup->adt->action = copy_action(wgroup->adt->action);
00541         
00542         /* now perform the moving */
00543         BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths);
00544         
00545         /* paths + their wrappers need to be freed */
00546         for (ld = anim_basepaths.first; ld; ld = ldn) {
00547             ldn = ld->next;
00548             
00549             MEM_freeN(ld->data);
00550             BLI_freelinkN(&anim_basepaths, ld);
00551         }
00552         
00553         /* free temp action too */
00554         if (waction) {
00555             free_libblock(&G.main->action, waction);
00556         }
00557     }
00558     
00559     /* delete the group instance. this also removes old input links! */
00560     nodeFreeNode(ntree, gnode);
00561 
00562     /* free the group tree (takes care of user count) */
00563     free_libblock(&G.main->nodetree, wgroup);
00564     
00565     ntree->update |= NTREE_UPDATE_NODES | NTREE_UPDATE_LINKS;
00566     ntreeUpdateTree(ntree);
00567     
00568     return 1;
00569 }
00570 
00571 bNodeSocket *node_group_add_socket(bNodeTree *ngroup, const char *name, int type, int in_out)
00572 {
00573     bNodeSocketType *stype = ntreeGetSocketType(type);
00574     bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
00575     
00576     BLI_strncpy(gsock->name, name, sizeof(gsock->name));
00577     gsock->type = type;
00578     /* group sockets are dynamically added */
00579     gsock->flag |= SOCK_DYNAMIC;
00580 
00581     gsock->next = gsock->prev = NULL;
00582     gsock->new_sock = NULL;
00583     gsock->link = NULL;
00584     /* assign new unique index */
00585     gsock->own_index = ngroup->cur_index++;
00586     gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
00587     
00588     if (stype->value_structsize > 0)
00589         gsock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
00590     
00591     BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
00592     
00593     ngroup->update |= (in_out==SOCK_IN ? NTREE_UPDATE_GROUP_IN : NTREE_UPDATE_GROUP_OUT);
00594     
00595     return gsock;
00596 }
00597 
00598 bNodeSocket *node_group_expose_socket(bNodeTree *ngroup, bNodeSocket *sock, int in_out)
00599 {
00600     bNodeSocket *gsock= node_group_add_socket(ngroup, sock->name, sock->type, in_out);
00601     
00602     /* initialize the default value. */
00603     copy_socket_value(sock, gsock);
00604     
00605     return gsock;
00606 }
00607 
00608 void node_group_expose_all_sockets(bNodeTree *ngroup)
00609 {
00610     bNode *node;
00611     bNodeSocket *sock, *gsock;
00612     
00613     for (node=ngroup->nodes.first; node; node=node->next) {
00614         for (sock=node->inputs.first; sock; sock=sock->next) {
00615             if (!sock->link && !nodeSocketIsHidden(sock)) {
00616                 gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_IN);
00617                 
00618                 /* initialize the default value. */
00619                 copy_socket_value(sock, gsock);
00620                 
00621                 sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
00622             }
00623         }
00624         for (sock=node->outputs.first; sock; sock=sock->next) {
00625             if (nodeCountSocketLinks(ngroup, sock)==0 && !nodeSocketIsHidden(sock)) {
00626                 gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_OUT);
00627                 
00628                 /* initialize the default value. */
00629                 copy_socket_value(sock, gsock);
00630                 
00631                 gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
00632             }
00633         }
00634     }
00635 }
00636 
00637 void node_group_remove_socket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out)
00638 {
00639     nodeRemSocketLinks(ngroup, gsock);
00640     
00641     switch (in_out) {
00642     case SOCK_IN:
00643         BLI_remlink(&ngroup->inputs, gsock);
00644         ngroup->update |= NTREE_UPDATE_GROUP_IN;
00645         break;
00646     case SOCK_OUT:
00647         BLI_remlink(&ngroup->outputs, gsock);
00648         ngroup->update |= NTREE_UPDATE_GROUP_OUT;
00649         break;
00650     }
00651     
00652     if (gsock->default_value)
00653         MEM_freeN(gsock->default_value);
00654     
00655     MEM_freeN(gsock);
00656 }
00657 
00658 /* groups display their internal tree name as label */
00659 const char *node_group_label(bNode *node)
00660 {
00661     return (node->id)? node->id->name+2: "Missing Datablock";
00662 }
00663 
00664 int node_group_valid(bNodeTree *ntree, bNodeTemplate *ntemp)
00665 {
00666     bNodeTemplate childtemp;
00667     bNode *node;
00668     
00669     /* regular groups cannot be recursive */
00670     if (ntree == ntemp->ngroup)
00671         return 0;
00672     
00673     /* make sure all children are valid */
00674     for (node=ntemp->ngroup->nodes.first; node; node=node->next) {
00675         childtemp = nodeMakeTemplate(node);
00676         if (!nodeValid(ntree, &childtemp))
00677             return 0;
00678     }
00679     
00680     return 1;
00681 }
00682 
00683 bNodeTemplate node_group_template(bNode *node)
00684 {
00685     bNodeTemplate ntemp;
00686     ntemp.type = NODE_GROUP;
00687     ntemp.ngroup = (bNodeTree*)node->id;
00688     return ntemp;
00689 }
00690 
00691 void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
00692 {
00693     node->id = (ID*)ntemp->ngroup;
00694     
00695     /* NB: group socket input/output roles are inverted internally!
00696      * Group "inputs" work as outputs in links and vice versa.
00697      */
00698     if (ntemp->ngroup) {
00699         bNodeSocket *gsock;
00700         for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next)
00701             node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock);
00702         for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next)
00703             node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock);
00704     }
00705 }
00706 
00707 static bNodeSocket *group_verify_socket(bNodeTree *ntree, ListBase *lb, int in_out, bNodeSocket *gsock)
00708 {
00709     bNodeSocket *sock;
00710     
00711     /* group sockets tagged as internal are not exposed ever */
00712     if (gsock->flag & SOCK_INTERNAL)
00713         return NULL;
00714     
00715     for(sock= lb->first; sock; sock= sock->next) {
00716         if(sock->own_index==gsock->own_index)
00717                 break;
00718     }
00719     if(sock) {
00720         sock->groupsock = gsock;
00721         
00722         BLI_strncpy(sock->name, gsock->name, sizeof(sock->name));
00723         sock->type= gsock->type;
00724         
00725         /* XXX hack: group socket input/output roles are inverted internally,
00726          * need to change the limit value when making actual node sockets from them.
00727          */
00728         sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
00729         
00730         BLI_remlink(lb, sock);
00731         
00732         return sock;
00733     }
00734     else {
00735         return node_group_add_extern_socket(ntree, NULL, in_out, gsock);
00736     }
00737 }
00738 
00739 static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb, int in_out, ListBase *glb)
00740 {
00741     bNodeSocket *sock, *nextsock, *gsock;
00742     
00743     /* step by step compare */
00744     for (gsock= glb->first; gsock; gsock=gsock->next) {
00745         /* abusing new_sock pointer for verification here! only used inside this function */
00746         gsock->new_sock= group_verify_socket(ntree, lb, in_out, gsock);
00747     }
00748     /* leftovers are removed */
00749     for (sock=lb->first; sock; sock=nextsock) {
00750         nextsock=sock->next;
00751         if (sock->flag & SOCK_DYNAMIC)
00752             nodeRemoveSocket(ntree, node, sock);
00753     }
00754     /* and we put back the verified sockets */
00755     for (gsock= glb->first; gsock; gsock=gsock->next) {
00756         if (gsock->new_sock) {
00757             BLI_addtail(lb, gsock->new_sock);
00758             gsock->new_sock = NULL;
00759         }
00760     }
00761 }
00762 
00763 /* make sure all group node in ntree, which use ngroup, are sync'd */
00764 void node_group_verify(struct bNodeTree *ntree, struct bNode *node, struct ID *id)
00765 {
00766     /* check inputs and outputs, and remove or insert them */
00767     if (node->id==id) {
00768         bNodeTree *ngroup= (bNodeTree*)node->id;
00769         group_verify_socket_list(ntree, node, &node->inputs, SOCK_IN, &ngroup->inputs);
00770         group_verify_socket_list(ntree, node, &node->outputs, SOCK_OUT, &ngroup->outputs);
00771     }
00772 }
00773 
00774 struct bNodeTree *node_group_edit_get(bNode *node)
00775 {
00776     if (node->flag & NODE_GROUP_EDIT)
00777         return (bNodeTree*)node->id;
00778     else
00779         return NULL;
00780 }
00781 
00782 struct bNodeTree *node_group_edit_set(bNode *node, int edit)
00783 {
00784     if (edit) {
00785         bNodeTree *ngroup= (bNodeTree*)node->id;
00786         if (ngroup) {
00787             if(ngroup->id.lib)
00788                 ntreeMakeLocal(ngroup);
00789             
00790             node->flag |= NODE_GROUP_EDIT;
00791         }
00792         return ngroup;
00793     }
00794     else {
00795         node->flag &= ~NODE_GROUP_EDIT;
00796         return NULL;
00797     }
00798 }
00799 
00800 void node_group_edit_clear(bNode *node)
00801 {
00802     bNodeTree *ngroup= (bNodeTree*)node->id;
00803     bNode *inode;
00804     
00805     node->flag &= ~NODE_GROUP_EDIT;
00806     
00807     if (ngroup)
00808         for (inode=ngroup->nodes.first; inode; inode=inode->next)
00809             nodeGroupEditClear(inode);
00810 }
00811 
00812 void node_group_link(bNodeTree *ntree, bNodeSocket *sock, int in_out)
00813 {
00814     node_group_expose_socket(ntree, sock, in_out);
00815 }
00816 
00817 /**** For Loop ****/
00818 
00819 /* Essentially a group node with slightly different behavior.
00820  * The internal tree is executed several times, with each output being re-used
00821  * as an input in the next iteration. For this purpose, input and output socket
00822  * lists are kept identical!
00823  */
00824 
00825 bNodeTemplate node_forloop_template(bNode *node)
00826 {
00827     bNodeTemplate ntemp;
00828     ntemp.type = NODE_FORLOOP;
00829     ntemp.ngroup = (bNodeTree*)node->id;
00830     return ntemp;
00831 }
00832 
00833 void node_forloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
00834 {
00835     /* bNodeSocket *sock; */ /* UNUSED */
00836     
00837     node->id = (ID*)ntemp->ngroup;
00838     
00839     /* sock = */ nodeAddInputFloat(ntree, node, "Iterations", PROP_UNSIGNED, 1, 0, 10000);
00840     
00841     /* NB: group socket input/output roles are inverted internally!
00842      * Group "inputs" work as outputs in links and vice versa.
00843      */
00844     if (ntemp->ngroup) {
00845         bNodeSocket *gsock;
00846         for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next)
00847             node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock);
00848         for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next)
00849             node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock);
00850     }
00851 }
00852 
00853 void node_forloop_init_tree(bNodeTree *ntree)
00854 {
00855     bNodeSocket *sock;
00856     sock = node_group_add_socket(ntree, "Iteration", SOCK_FLOAT, SOCK_IN);
00857     sock->flag |= SOCK_INTERNAL;
00858 }
00859 
00860 static void loop_sync(bNodeTree *ntree, int sync_in_out)
00861 {
00862     bNodeSocket *sock, *sync, *nsync, *mirror;
00863     ListBase *sync_lb;
00864     
00865     if (sync_in_out==SOCK_IN) {
00866         sock = ntree->outputs.first;
00867         
00868         sync = ntree->inputs.first;
00869         sync_lb = &ntree->inputs;
00870     }
00871     else {
00872         sock = ntree->inputs.first;
00873         
00874         sync = ntree->outputs.first;
00875         sync_lb = &ntree->outputs;
00876     }
00877     
00878     /* NB: the sock->storage pointer is used here directly to store the own_index int
00879      * out the mirrored socket counterpart!
00880      */
00881     
00882     while (sock) {
00883         /* skip static and internal sockets on the sync side (preserves socket order!) */
00884         while (sync && ((sync->flag & SOCK_INTERNAL) || !(sync->flag & SOCK_DYNAMIC)))
00885             sync = sync->next;
00886         
00887         if (sync && !(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC)) {
00888             if (sock->storage==NULL) {
00889                 /* if mirror index is 0, the sockets is newly added and a new mirror must be created. */
00890                 mirror = node_group_expose_socket(ntree, sock, sync_in_out);
00891                 /* store the mirror index */
00892                 sock->storage = SET_INT_IN_POINTER(mirror->own_index);
00893                 mirror->storage = SET_INT_IN_POINTER(sock->own_index);
00894                 /* move mirror to the right place */
00895                 BLI_remlink(sync_lb, mirror);
00896                 if (sync)
00897                     BLI_insertlinkbefore(sync_lb, sync, mirror);
00898                 else
00899                     BLI_addtail(sync_lb, mirror);
00900             }
00901             else {
00902                 /* look up the mirror socket */
00903                 for (mirror=sync; mirror; mirror=mirror->next)
00904                     if (mirror->own_index == GET_INT_FROM_POINTER(sock->storage))
00905                         break;
00906                 /* make sure the name is the same (only for identification by user, no deeper meaning) */
00907                 BLI_strncpy(mirror->name, sock->name, sizeof(mirror->name));
00908                 /* fix the socket order if necessary */
00909                 if (mirror != sync) {
00910                     BLI_remlink(sync_lb, mirror);
00911                     BLI_insertlinkbefore(sync_lb, sync, mirror);
00912                 }
00913                 else
00914                     sync = sync->next;
00915             }
00916         }
00917         
00918         sock = sock->next;
00919     }
00920     
00921     /* remaining sockets in sync_lb are leftovers from deleted sockets, remove them */
00922     while (sync) {
00923         nsync = sync->next;
00924         if (!(sync->flag & SOCK_INTERNAL) && (sync->flag & SOCK_DYNAMIC))
00925             node_group_remove_socket(ntree, sync, sync_in_out);
00926         sync = nsync;
00927     }
00928 }
00929 
00930 void node_loop_update_tree(bNodeTree *ngroup)
00931 {
00932     /* make sure inputs & outputs are identical */
00933     if (ngroup->update & NTREE_UPDATE_GROUP_IN)
00934         loop_sync(ngroup, SOCK_OUT);
00935     if (ngroup->update & NTREE_UPDATE_GROUP_OUT)
00936         loop_sync(ngroup, SOCK_IN);
00937 }
00938 
00939 void node_whileloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp)
00940 {
00941     /* bNodeSocket *sock; */ /* UNUSED */
00942     
00943     node->id = (ID*)ntemp->ngroup;
00944     
00945     /* sock = */ nodeAddInputFloat(ntree, node, "Condition", PROP_NONE, 1, 0, 1);
00946     
00947     /* max iterations */
00948     node->custom1 = 10000;
00949     
00950     /* NB: group socket input/output roles are inverted internally!
00951      * Group "inputs" work as outputs in links and vice versa.
00952      */
00953     if (ntemp->ngroup) {
00954         bNodeSocket *gsock;
00955         for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next)
00956             node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock);
00957         for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next)
00958             node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock);
00959     }
00960 }
00961 
00962 void node_whileloop_init_tree(bNodeTree *ntree)
00963 {
00964     bNodeSocket *sock;
00965     sock = node_group_add_socket(ntree, "Condition", SOCK_FLOAT, SOCK_OUT);
00966     sock->flag |= SOCK_INTERNAL;
00967 }
00968 
00969 bNodeTemplate node_whileloop_template(bNode *node)
00970 {
00971     bNodeTemplate ntemp;
00972     ntemp.type = NODE_WHILELOOP;
00973     ntemp.ngroup = (bNodeTree*)node->id;
00974     return ntemp;
00975 }
00976 
00977 /**** FRAME ****/
00978 
00979 void register_node_type_frame(bNodeTreeType *ttype)
00980 {
00981     /* frame type is used for all tree types, needs dynamic allocation */
00982     bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
00983 
00984     node_type_base(ttype, ntype, NODE_FRAME, "Frame", NODE_CLASS_LAYOUT, NODE_BACKGROUND);
00985     node_type_size(ntype, 150, 100, 0);
00986     node_type_compatibility(ntype, NODE_OLD_SHADING|NODE_NEW_SHADING);
00987     
00988     ntype->needs_free = 1;
00989     nodeRegisterType(ttype, ntype);
00990 }