Cycles: svn merge -r36352:36495 https://svn.blender.org/svnroot/bf-blender/trunk...
[blender.git] / source / blender / blenkernel / intern / node.c
index d5c53d20d072d19660d25882d216eed0c4b5ce81..16fbf38eca17e9ee4ff5a0a1568a0574fb46a977 100644 (file)
 
 #include "DNA_anim_types.h"
 #include "DNA_action_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+#include "DNA_world_types.h"
 #include "DNA_node_types.h"
 
 #include "BLI_listbase.h"
@@ -56,7 +60,6 @@
 #include "BKE_fcurve.h"
 #include "BKE_node.h"
 #include "BKE_utildefines.h"
-#include "BKE_node.h"
 
 #include "PIL_time.h"
 
@@ -518,6 +521,9 @@ void nodeGroupVerify(bNodeTree *ngroup)
        
        if(ngroup->type==NTREE_SHADER) {
                Material *ma;
+               Lamp *la;
+               World *wrld;
+
                for(ma= G.main->mat.first; ma; ma= ma->id.next) {
                        if(ma->nodetree) {
                                bNode *node;
@@ -526,6 +532,25 @@ void nodeGroupVerify(bNodeTree *ngroup)
                                                nodeVerifyType(ma->nodetree, node);
                        }
                }
+
+               for(la= G.main->lamp.first; la; la= la->id.next) {
+                       if(la->nodetree) {
+                               bNode *node;
+                               for(node= la->nodetree->nodes.first; node; node= node->next)
+                                       if(node->id == (ID *)ngroup)
+                                               nodeVerifyType(la->nodetree, node);
+                       }
+               }
+
+               for(wrld= G.main->world.first; wrld; wrld= wrld->id.next) {
+                       if(wrld->nodetree) {
+                               bNode *node;
+                               for(node= wrld->nodetree->nodes.first; node; node= node->next)
+                                       if(node->id == (ID *)ngroup)
+                                               nodeVerifyType(wrld->nodetree, node);
+                       }
+               }
+
        }
        else if(ngroup->type==NTREE_COMPOSIT) {
                Scene *sce;
@@ -551,6 +576,28 @@ void nodeGroupVerify(bNodeTree *ngroup)
        }
 }
 
+static void nodeGroupTagUseFlags(bNodeTree *ntree, bNodeTree *ngroup)
+{
+       bNode *node;
+       bNodeSocket *sock;
+
+       if(!ntree)
+               return;
+
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->id==(ID *)ngroup) {
+                       for(sock= node->inputs.first; sock; sock= sock->next)
+                               if(sock->link)
+                                       if(sock->groupsock) 
+                                               sock->groupsock->flag |= SOCK_IN_USE;
+                       for(sock= node->outputs.first; sock; sock= sock->next)
+                               if(nodeCountSocketLinks(ntree, sock))
+                                       if(sock->groupsock) 
+                                               sock->groupsock->flag |= SOCK_IN_USE;
+               }
+       }
+}
+
 /* also to check all users of groups. Now only used in editor for hide/unhide */
 /* should become callbackable? */
 void nodeGroupSocketUseFlags(bNodeTree *ngroup)
@@ -569,62 +616,26 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup)
        /* tag all thats in use */
        if(ngroup->type==NTREE_SHADER) {
                Material *ma;
-               for(ma= G.main->mat.first; ma; ma= ma->id.next) {
-                       if(ma->nodetree) {
-                               for(node= ma->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id==&ngroup->id) {
-                                               for(sock= node->inputs.first; sock; sock= sock->next)
-                                                       if(sock->link)
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                               for(sock= node->outputs.first; sock; sock= sock->next)
-                                                       if(nodeCountSocketLinks(ma->nodetree, sock))
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                       }
-                               }
-                       }
-               }
+               Lamp *la;
+               World *wrld;
+
+               for(ma= G.main->mat.first; ma; ma= ma->id.next)
+                       nodeGroupTagUseFlags(ma->nodetree, ngroup);
+               for(la= G.main->lamp.first; la; la= la->id.next)
+                       nodeGroupTagUseFlags(la->nodetree, ngroup);
+               for(wrld= G.main->world.first; wrld; wrld= wrld->id.next)
+                       nodeGroupTagUseFlags(wrld->nodetree, ngroup);
        }
        else if(ngroup->type==NTREE_COMPOSIT) {
                Scene *sce;
-               for(sce= G.main->scene.first; sce; sce= sce->id.next) {
-                       if(sce->nodetree) {
-                               for(node= sce->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id==(ID *)ngroup) {
-                                               for(sock= node->inputs.first; sock; sock= sock->next)
-                                                       if(sock->link)
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                               for(sock= node->outputs.first; sock; sock= sock->next)
-                                                       if(nodeCountSocketLinks(sce->nodetree, sock))
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                       }
-                               }
-                       }
-               }
+               for(sce= G.main->scene.first; sce; sce= sce->id.next)
+                       nodeGroupTagUseFlags(sce->nodetree, ngroup);
        }
        else if(ngroup->type==NTREE_TEXTURE) {
                Tex *tx;
-               for(tx= G.main->tex.first; tx; tx= tx->id.next) {
-                       if(tx->nodetree) {
-                               for(node= tx->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id==(ID *)ngroup) {
-                                               for(sock= node->inputs.first; sock; sock= sock->next)
-                                                       if(sock->link)
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                               for(sock= node->outputs.first; sock; sock= sock->next)
-                                                       if(nodeCountSocketLinks(tx->nodetree, sock))
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                       }
-                               }
-                       }
-               }
+               for(tx= G.main->tex.first; tx; tx= tx->id.next)
+                       nodeGroupTagUseFlags(tx->nodetree, ngroup);
        }
-       
 }
 /* finds a node based on its name */
 bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
@@ -902,6 +913,7 @@ void nodeGroupRemoveSocket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out)
        case SOCK_IN:   BLI_remlink(&ngroup->inputs, gsock);    break;
        case SOCK_OUT:  BLI_remlink(&ngroup->outputs, gsock);   break;
        }
+       MEM_freeN(gsock);
 }
 
 /* ************** Add stuff ********** */
@@ -967,6 +979,11 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
        } else
                ntype= node_get_type(ntree, type, id);
 
+       if(ntype == NULL) {
+               printf("nodeAddNodeType() error: '%d' type invalid\n", type);
+               return NULL;
+       }
+
        node= MEM_callocN(sizeof(bNode), "new node");
        BLI_addtail(&ntree->nodes, node);
        node->typeinfo= ntype;
@@ -1188,7 +1205,9 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree)
                newtree= MEM_dupallocN(ntree);
                copy_libblock_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */
        }
-       
+
+       id_us_plus((ID *)newtree->gpd);
+
        /* in case a running nodetree is copied */
        newtree->init &= ~(NTREE_EXEC_INIT);
        newtree->threadstack= NULL;
@@ -1430,6 +1449,8 @@ void ntreeFreeTree(bNodeTree *ntree)
        
        BKE_free_animdata((ID *)ntree);
 
+       id_us_min((ID *)ntree->gpd);
+
        BLI_freelistN(&ntree->links);   /* do first, then unlink_node goes fast */
        
        for(node= ntree->nodes.first; node; node= next) {
@@ -1473,6 +1494,23 @@ void ntreeMakeLocal(bNodeTree *ntree)
        /* now check users of groups... again typedepending, callback... */
        if(ntree->type==NTREE_SHADER) {
                Material *ma;
+               Lamp *la;
+               World *wrld;
+
+               for(ma= G.main->mat.first; ma; ma= ma->id.next) {
+                       if(ma->nodetree) {
+                               bNode *node;
+                               
+                               /* find if group is in tree */
+                               for(node= ma->nodetree->nodes.first; node; node= node->next) {
+                                       if(node->id == (ID *)ntree) {
+                                               if(ma->id.lib) lib= 1;
+                                               else local= 1;
+                                       }
+                               }
+                       }
+               }
+
                for(ma= G.main->mat.first; ma; ma= ma->id.next) {
                        if(ma->nodetree) {
                                bNode *node;
@@ -1486,6 +1524,34 @@ void ntreeMakeLocal(bNodeTree *ntree)
                                }
                        }
                }
+
+               for(la= G.main->lamp.first; la; la= la->id.next) {
+                       if(la->nodetree) {
+                               bNode *node;
+                               
+                               /* find if group is in tree */
+                               for(node= la->nodetree->nodes.first; node; node= node->next) {
+                                       if(node->id == (ID *)ntree) {
+                                               if(la->id.lib) lib= 1;
+                                               else local= 1;
+                                       }
+                               }
+                       }
+               }
+
+               for(wrld= G.main->world.first; wrld; wrld= wrld->id.next) {
+                       if(wrld->nodetree) {
+                               bNode *node;
+                               
+                               /* find if group is in tree */
+                               for(node= wrld->nodetree->nodes.first; node; node= node->next) {
+                                       if(node->id == (ID *)ntree) {
+                                               if(wrld->id.lib) lib= 1;
+                                               else local= 1;
+                                       }
+                               }
+                       }
+               }
        }
        else if(ntree->type==NTREE_COMPOSIT) {
                Scene *sce;
@@ -1534,6 +1600,9 @@ void ntreeMakeLocal(bNodeTree *ntree)
                
                if(ntree->type==NTREE_SHADER) {
                        Material *ma;
+                       Lamp *la;
+                       World *wrld;
+
                        for(ma= G.main->mat.first; ma; ma= ma->id.next) {
                                if(ma->nodetree) {
                                        bNode *node;
@@ -1550,6 +1619,40 @@ void ntreeMakeLocal(bNodeTree *ntree)
                                        }
                                }
                        }
+
+                       for(la= G.main->lamp.first; la; la= la->id.next) {
+                               if(la->nodetree) {
+                                       bNode *node;
+                                       
+                                       /* find if group is in tree */
+                                       for(node= la->nodetree->nodes.first; node; node= node->next) {
+                                               if(node->id == (ID *)ntree) {
+                                                       if(la->id.lib==NULL) {
+                                                               node->id= &newtree->id;
+                                                               newtree->id.us++;
+                                                               ntree->id.us--;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       for(wrld= G.main->world.first; wrld; wrld= wrld->id.next) {
+                               if(wrld->nodetree) {
+                                       bNode *node;
+                                       
+                                       /* find if group is in tree */
+                                       for(node= wrld->nodetree->nodes.first; node; node= node->next) {
+                                               if(node->id == (ID *)ntree) {
+                                                       if(wrld->id.lib==NULL) {
+                                                               node->id= &newtree->id;
+                                                               newtree->id.us++;
+                                                               ntree->id.us--;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
                }
                else if(ntree->type==NTREE_COMPOSIT) {
                        Scene *sce;
@@ -1997,11 +2100,23 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod
        if (ntree->type==NTREE_COMPOSIT) {
                bNodeSocket *sock;
                bNodeStack *ns;
+               
+               /* clear hasoutput on all local stack data,
+                * only the group output will be used from now on
+                */
+               for (node=ntree->nodes.first; node; node=node->next) {
+                       for (sock=node->outputs.first; sock; sock=sock->next) {
+                               if (sock->stack_type==SOCK_STACK_LOCAL) {
+                                       ns= get_socket_stack(stack, sock, in);
+                                       ns->hasoutput = 0;
+                               }
+                       }
+               }
+               /* use the hasoutput flag to tag external sockets */
                for (sock=ntree->outputs.first; sock; sock=sock->next) {
-                       /* use the hasoutput flag to tag external sockets */
                        if (sock->stack_type==SOCK_STACK_LOCAL) {
                                ns= get_socket_stack(stack, sock, in);
-                               ns->hasoutput = 0;
+                               ns->hasoutput = 1;
                        }
                }
                /* now free all stacks that are not used from outside */
@@ -2009,11 +2124,9 @@ static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNod
                        for (sock=node->outputs.first; sock; sock=sock->next) {
                                if (sock->stack_type==SOCK_STACK_LOCAL ) {
                                        ns= get_socket_stack(stack, sock, in);
-                                       if (ns->hasoutput!=0 && ns->data) {
+                                       if (ns->hasoutput==0 && ns->data) {
                                                free_compbuf(ns->data);
                                                ns->data = NULL;
-                                               /* reset the flag */
-                                               ns->hasoutput = 1;
                                        }
                                }
                        }
@@ -2229,9 +2342,37 @@ static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack, bNodeStack *
                        }
                }
                
+               /* non-composite trees do all nodes by default */
+               if (ntree->type!=NTREE_COMPOSIT)
+                       node->need_exec = 1;
+               
+               for(sock= node->inputs.first; sock; sock= sock->next) {
+                       bNodeStack *ns = get_socket_stack(stack, sock, gin);
+                       if (ns) {
+                               ns->hasoutput = 1;
+                               
+                               /* sock type is needed to detect rgba or value or vector types */
+                               if(sock->link && sock->link->fromsock)
+                                       ns->sockettype= sock->link->fromsock->type;
+                               else
+                                       sock->ns.sockettype= sock->type;
+                       }
+                       
+                       if(sock->link) {
+                               bNodeLink *link= sock->link;
+                               /* this is the test for a cyclic case */
+                               if(link->fromnode && link->tonode) {
+                                       if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF);
+                                       else {
+                                               node->need_exec= 0;
+                                       }
+                               }
+                       }
+               }
+               
                /* set stack types (for local stack entries) */
                for(sock= node->outputs.first; sock; sock= sock->next) {
-                       bNodeStack *ns = get_socket_stack(stack, sock, NULL);
+                       bNodeStack *ns = get_socket_stack(stack, sock, gin);
                        if (ns)
                                ns->sockettype = sock->type;
                }
@@ -2281,13 +2422,18 @@ static void tex_end_exec(bNodeTree *ntree)
        bNodeStack *ns;
        int th, a;
        
-       if(ntree->threadstack)
-               for(th=0; th<BLENDER_MAX_THREADS; th++)
-                       for(nts=ntree->threadstack[th].first; nts; nts=nts->next)
-                               for(ns= nts->stack, a=0; a<ntree->stacksize; a++, ns++)
-                                       if(ns->data)
+       if(ntree->threadstack) {
+               for(th=0; th<BLENDER_MAX_THREADS; th++) {
+                       for(nts=ntree->threadstack[th].first; nts; nts=nts->next) {
+                               for(ns= nts->stack, a=0; a<ntree->stacksize; a++, ns++) {
+                                       if(ns->data) {
                                                MEM_freeN(ns->data);
-                                               
+                                               ns->data= NULL;
+                                       }
+                               }
+                       }
+               }
+       }
 }
 
 void ntreeBeginExecTree(bNodeTree *ntree)
@@ -2320,7 +2466,7 @@ void ntreeBeginExecTree(bNodeTree *ntree)
                for(node= ntree->nodes.first; node; node= node->next) {
                        bNodeSocket *sock;
                        
-                       /* composite has own need_exec tag handling */
+                       /* non-composite trees do all nodes by default */
                        if(ntree->type!=NTREE_COMPOSIT)
                                node->need_exec= 1;
 
@@ -2465,7 +2611,7 @@ static int node_only_value(bNode *node)
        if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
                int retval= 1;
                for(sock= node->inputs.first; sock; sock= sock->next) {
-                       if(sock->link)
+                       if(sock->link && sock->link->fromnode)
                                retval &= node_only_value(sock->link->fromnode);
                }
                return retval;
@@ -2623,7 +2769,7 @@ static void freeExecutableNode(bNodeTree *ntree)
        for(node= ntree->nodes.first; node; node= node->next) {
                if((node->exec & NODE_FINISHED)==0) {
                        for(sock= node->inputs.first; sock; sock= sock->next)
-                               if(sock->link)
+                               if(sock->link && sock->link->fromnode)
                                        sock->link->fromnode->exec &= ~NODE_FREEBUFS;
                }
        }
@@ -2724,7 +2870,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
                        node= getExecutableNode(ntree);
                        if(node) {
                                if(ntree->progress && totnode)
-                                       ntree->progress(ntree->prh, (1.0 - curnode/(float)totnode));
+                                       ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode));
                                if(ntree->stats_draw) {
                                        char str[64];
                                        sprintf(str, "Compositing %d %s", curnode, node->name);
@@ -3461,30 +3607,49 @@ static void registerCompositNodes(ListBase *ntypelist)
 static void registerShaderNodes(ListBase *ntypelist) 
 {
        register_node_type_group(ntypelist);
-       
-       register_node_type_sh_output(ntypelist);
+
+       register_node_type_sh_value(ntypelist);
+       register_node_type_sh_rgb(ntypelist);
+       register_node_type_sh_math(ntypelist);
+       register_node_type_sh_vect_math(ntypelist);
        register_node_type_sh_mix_rgb(ntypelist);
-       register_node_type_sh_valtorgb(ntypelist);
        register_node_type_sh_rgbtobw(ntypelist);
-       register_node_type_sh_normal(ntypelist);
-       register_node_type_sh_geom(ntypelist);
        register_node_type_sh_mapping(ntypelist);
-       register_node_type_sh_curve_vec(ntypelist);
-       register_node_type_sh_curve_rgb(ntypelist);
-       register_node_type_sh_math(ntypelist);
-       register_node_type_sh_vect_math(ntypelist);
-       register_node_type_sh_squeeze(ntypelist);
-       register_node_type_sh_camera(ntypelist);
-       register_node_type_sh_material(ntypelist);
-       register_node_type_sh_material_ext(ntypelist);
-       register_node_type_sh_value(ntypelist);
-       register_node_type_sh_rgb(ntypelist);
-       register_node_type_sh_texture(ntypelist);
-//     register_node_type_sh_dynamic(ntypelist);
-       register_node_type_sh_invert(ntypelist);
-       register_node_type_sh_seprgb(ntypelist);
-       register_node_type_sh_combrgb(ntypelist);
-       register_node_type_sh_hue_sat(ntypelist);
+
+       register_node_type_sh_attribute(ntypelist);
+       register_node_type_sh_geometry(ntypelist);
+       register_node_type_sh_light_path(ntypelist);
+       register_node_type_sh_fresnel(ntypelist);
+       register_node_type_sh_tex_coord(ntypelist);
+
+       register_node_type_sh_background(ntypelist);
+       register_node_type_sh_bsdf_diffuse(ntypelist);
+       register_node_type_sh_bsdf_glass(ntypelist);
+       register_node_type_sh_bsdf_glossy(ntypelist);
+       register_node_type_sh_bsdf_translucent(ntypelist);
+       register_node_type_sh_bsdf_transparent(ntypelist);
+       register_node_type_sh_bsdf_velvet(ntypelist);
+       register_node_type_sh_emission(ntypelist);
+       register_node_type_sh_mix_closure(ntypelist);
+       register_node_type_sh_add_closure(ntypelist);
+
+       register_node_type_sh_output_lamp(ntypelist);
+       register_node_type_sh_output_material(ntypelist);
+       register_node_type_sh_output_world(ntypelist);
+
+       register_node_type_sh_tex_blend(ntypelist);
+       register_node_type_sh_tex_clouds(ntypelist);
+       register_node_type_sh_tex_distnoise(ntypelist);
+       register_node_type_sh_tex_image(ntypelist);
+       register_node_type_sh_tex_environment(ntypelist);
+       register_node_type_sh_tex_magic(ntypelist);
+       register_node_type_sh_tex_marble(ntypelist);
+       register_node_type_sh_tex_musgrave(ntypelist);
+       register_node_type_sh_tex_noise(ntypelist);
+       register_node_type_sh_tex_sky(ntypelist);
+       register_node_type_sh_tex_stucci(ntypelist);
+       register_node_type_sh_tex_voronoi(ntypelist);
+       register_node_type_sh_tex_wood(ntypelist);
 }
 
 static void registerTextureNodes(ListBase *ntypelist)