Patch #34204: [Render Animation] Fails with "Error: Specified sample_fmt is not suppo...
[blender.git] / source / blender / blenkernel / intern / node.c
index 8cede4f..974a564 100644 (file)
 
 #include "DNA_action_types.h"
 #include "DNA_anim_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
 #include "DNA_node_types.h"
 #include "DNA_node_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_world_types.h"
 
 #include "BLI_string.h"
 #include "BLI_math.h"
@@ -147,6 +151,7 @@ static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char
        sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
        sock->type = type;
        sock->storage = NULL;
+       sock->flag |= SOCK_COLLAPSED;
        
        sock->default_value = node_socket_make_default_value(type);
        node_socket_init_default_value(type, sock->default_value);
@@ -326,10 +331,13 @@ bNode *nodeAddNode(bNodeTree *ntree, struct bNodeTemplate *ntemp)
                ntype->initfunc(ntree, node, ntemp);
 
        /* initialize the node name with the node label.
-        * note: do this after the initfunc so nodes get
-        * their data set which may be used in naming
+        * note: do this after the initfunc so nodes get their data set which may be used in naming
         * (node groups for example) */
-       BLI_strncpy(node->name, nodeLabel(node), NODE_MAXSTR);
+       /* XXX Do not use nodeLabel() here, it returns translated content, which should *only* be used
+        *     in UI, *never* in data...
+        *     This solution may be a bit rougher than nodeLabel()'s returned string, but it's simpler
+        *     than adding a "no translate" flag to this func (and labelfunc() as well). */
+       BLI_strncpy(node->name, node->typeinfo->name, NODE_MAXSTR);
        nodeUniqueName(ntree, node);
        
        ntree->update |= NTREE_UPDATE_NODES;
@@ -343,6 +351,7 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
 {
        bNode *nnode = MEM_callocN(sizeof(bNode), "dupli node");
        bNodeSocket *sock, *oldsock;
+       bNodeLink *link, *oldlink;
 
        *nnode = *node;
        /* can be called for nodes outside a node tree (e.g. clipboard) */
@@ -382,6 +391,15 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
                sock->cache = NULL;
        }
        
+       BLI_duplicatelist(&nnode->internal_links, &node->internal_links);
+       oldlink = node->internal_links.first;
+       for (link = nnode->internal_links.first; link; link = link->next, oldlink = oldlink->next) {
+               link->fromnode = nnode;
+               link->tonode = nnode;
+               link->fromsock = link->fromsock->new_sock;
+               link->tosock = link->tosock->new_sock;
+       }
+       
        /* don't increase node->id users, freenode doesn't decrement either */
        
        if (node->typeinfo->copystoragefunc)
@@ -389,7 +407,18 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
        
        node->new_node = nnode;
        nnode->new_node = NULL;
-       nnode->preview = NULL;
+       
+       /* only shader nodes get pleasant preview updating this way, compo uses own system */
+       if (node->preview) {
+               if (ntree && (ntree->type == NTREE_SHADER)) {
+                       nnode->preview = MEM_dupallocN(node->preview);
+                       if (node->preview->rect)
+                               nnode->preview->rect = MEM_dupallocN(node->preview->rect);
+               }
+               else {
+                       nnode->preview = NULL;
+               }
+       }
        
        if (ntree)
                ntree->update |= NTREE_UPDATE_NODES;
@@ -520,15 +549,12 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
 void nodeInternalRelink(bNodeTree *ntree, bNode *node)
 {
        bNodeLink *link, *link_next;
-       ListBase intlinks;
        
-       if (!node->typeinfo->internal_connect)
+       if (node->internal_links.first == NULL)
                return;
        
-       intlinks = node->typeinfo->internal_connect(ntree, node);
-       
        /* store link pointers in output sockets, for efficient lookup */
-       for (link = intlinks.first; link; link = link->next)
+       for (link = node->internal_links.first; link; link = link->next)
                link->tosock->link = link;
        
        /* redirect downstream links */
@@ -545,6 +571,12 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
                                        link->fromnode = fromlink->fromnode;
                                        link->fromsock = fromlink->fromsock;
                                        
+                                       /* if the up- or downstream link is invalid,
+                                        * the replacement link will be invalid too.
+                                        */
+                                       if (!(fromlink->flag & NODE_LINK_VALID))
+                                               link->flag &= ~NODE_LINK_VALID;
+                                       
                                        ntree->update |= NTREE_UPDATE_LINKS;
                                }
                                else
@@ -562,8 +594,6 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
                if (link->tonode == node)
                        nodeRemLink(ntree, link);
        }
-       
-       BLI_freelistN(&intlinks);
 }
 
 void nodeToView(bNode *node, float x, float y, float *rx, float *ry)
@@ -632,7 +662,7 @@ void nodeDetachNode(struct bNode *node)
        }
 }
 
-bNodeTree *ntreeAddTree(const char *name, int type, int nodetype)
+bNodeTree *ntreeAddTree(Main *bmain, const char *name, int type, int nodetype)
 {
        bNodeTree *ntree;
        bNodeType *ntype;
@@ -646,7 +676,7 @@ bNodeTree *ntreeAddTree(const char *name, int type, int nodetype)
                BLI_strncpy(ntree->id.name + 2, name, sizeof(ntree->id.name));
        }
        else
-               ntree = BKE_libblock_alloc(&G.main->nodetree, ID_NT, name);
+               ntree = BKE_libblock_alloc(&bmain->nodetree, ID_NT, name);
        
        ntree->type = type;
        ntree->nodetype = nodetype;
@@ -686,7 +716,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
        }
        else {
                newtree = MEM_dupallocN(ntree);
-               BKE_libblock_copy_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */
+               BKE_libblock_copy_data(&newtree->id, &ntree->id, true); /* copy animdata and ID props */
        }
 
        id_us_plus((ID *)newtree->gpd);
@@ -710,7 +740,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use
                }
 
                node->new_node = NULL;
-               /* nnode= */ nodeCopyNode(newtree, node);   /* sets node->new */
+               /* nnode = */ nodeCopyNode(newtree, node);   /* sets node->new */
                
                /* make sure we don't copy new nodes again! */
                if (node == last)
@@ -815,7 +845,7 @@ void nodeFreePreview(bNode *node)
                        MEM_freeN(node->preview->rect);
                MEM_freeN(node->preview);
                node->preview = NULL;
-       }       
+       }
 }
 
 static void node_init_preview(bNode *node, int xsize, int ysize)
@@ -858,7 +888,7 @@ void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
                        node_init_preview(node, xsize, ysize);
                if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
                        ntreeInitPreview((bNodeTree *)node->id, xsize, ysize);
-       }               
+       }
 }
 
 static void nodeClearPreview(bNode *node)
@@ -880,13 +910,13 @@ void ntreeClearPreview(bNodeTree *ntree)
                        nodeClearPreview(node);
                if (node->type == NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
                        ntreeClearPreview((bNodeTree *)node->id);
-       }               
+       }
 }
 
 /* hack warning! this function is only used for shader previews, and 
  * since it gets called multiple times per pixel for Ztransp we only
  * add the color once. Preview gets cleared before it starts render though */
-void nodeAddToPreview(bNode *node, float col[4], int x, int y, int do_manage)
+void nodeAddToPreview(bNode *node, const float col[4], int x, int y, int do_manage)
 {
        bNodePreview *preview = node->preview;
        if (preview) {
@@ -967,6 +997,12 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
 
                if (treetype->free_node_cache)
                        treetype->free_node_cache(ntree, node);
+               
+               /* texture node has bad habit of keeping exec data around */
+               if (ntree->type == NTREE_TEXTURE && ntree->execdata) {
+                       ntreeTexEndExecTree(ntree->execdata, 1);
+                       ntree->execdata = NULL;
+               }
        }
        
        /* since it is called while free database, node->id is undefined */
@@ -985,6 +1021,8 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
                MEM_freeN(sock);
        }
 
+       BLI_freelistN(&node->internal_links);
+
        nodeFreePreview(node);
 
        MEM_freeN(node);
@@ -996,6 +1034,7 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
 /* do not free ntree itself here, BKE_libblock_free calls this function too */
 void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
 {
+       bNodeTree *tntree;
        bNode *node, *next;
        bNodeSocket *sock;
        
@@ -1008,14 +1047,12 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
         */
        if (ntree->execdata) {
                switch (ntree->type) {
-                       case NTREE_COMPOSIT:
-                               ntreeCompositEndExecTree(ntree->execdata, 1);
-                               break;
                        case NTREE_SHADER:
                                ntreeShaderEndExecTree(ntree->execdata, 1);
                                break;
                        case NTREE_TEXTURE:
                                ntreeTexEndExecTree(ntree->execdata, 1);
+                               ntree->execdata = NULL;
                                break;
                }
        }
@@ -1052,6 +1089,14 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
        for (sock = ntree->outputs.first; sock; sock = sock->next)
                node_socket_free_default_value(sock->type, sock->default_value);
        BLI_freelistN(&ntree->outputs);
+       
+       /* if ntree is not part of library, free the libblock data explicitly */
+       for (tntree = G.main->nodetree.first; tntree; tntree = tntree->id.next)
+               if (tntree == ntree)
+                       break;
+       if (tntree == NULL) {
+               BKE_libblock_free_data(&ntree->id);
+       }
 }
 /* same as ntreeFreeTree_ex but always manage users */
 void ntreeFreeTree(bNodeTree *ntree)
@@ -1123,6 +1168,18 @@ void ntreeSetOutput(bNodeTree *ntree)
         * might be different for editor or for "real" use... */
 }
 
+bNodeTree *ntreeFromID(ID *id)
+{
+       switch (GS(id->name)) {
+               case ID_MA:  return ((Material *)id)->nodetree;
+               case ID_LA:  return ((Lamp *)id)->nodetree;
+               case ID_WO:  return ((World *)id)->nodetree;
+               case ID_TE:  return ((Tex *)id)->nodetree;
+               case ID_SCE: return ((Scene *)id)->nodetree;
+               default: return NULL;
+       }
+}
+
 typedef struct MakeLocalCallData {
        ID *group_id;
        ID *new_id;
@@ -1554,11 +1611,11 @@ int BKE_node_clipboard_validate(void)
 
        /* lists must be aligned */
        BLI_assert(BLI_countlist(&node_clipboard.nodes) ==
-                          BLI_countlist(&node_clipboard.nodes_extra_info));
+                  BLI_countlist(&node_clipboard.nodes_extra_info));
 
        for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first;
-                node;
-                node = node->next, node_info = node_info->next)
+            node;
+            node = node->next, node_info = node_info->next)
        {
                /* validate the node against the stored node info */
 
@@ -1590,7 +1647,7 @@ void BKE_node_clipboard_add_node(bNode *node)
 {
 #ifdef USE_NODE_CB_VALIDATE
        /* add extra info */
-       bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), STRINGIFY(bNodeClipboardExtraInfo));
+       bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), "bNodeClipboardExtraInfo");
 
        node_info->id = node->id;
        if (node->id) {
@@ -1638,21 +1695,21 @@ int BKE_node_clipboard_get_type(void)
 /* ************** dependency stuff *********** */
 
 /* node is guaranteed to be not checked before */
-static int node_get_deplist_recurs(bNode *node, bNode ***nsort)
+static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort)
 {
        bNode *fromnode;
-       bNodeSocket *sock;
+       bNodeLink *link;
        int level = 0xFFF;
        
        node->done = TRUE;
        
        /* check linked nodes */
-       for (sock = node->inputs.first; sock; sock = sock->next) {
-               if (sock->link) {
-                       fromnode = sock->link->fromnode;
+       for (link = ntree->links.first; link; link = link->next) {
+               if (link->tonode == node) {
+                       fromnode = link->fromnode;
                        if (fromnode) {
                                if (fromnode->done == 0)
-                                       fromnode->level = node_get_deplist_recurs(fromnode, nsort);
+                                       fromnode->level = node_get_deplist_recurs(ntree, fromnode, nsort);
                                if (fromnode->level <= level)
                                        level = fromnode->level - 1;
                        }
@@ -1662,7 +1719,7 @@ static int node_get_deplist_recurs(bNode *node, bNode ***nsort)
        /* check parent node */
        if (node->parent) {
                if (node->parent->done == 0)
-                       node->parent->level = node_get_deplist_recurs(node->parent, nsort);
+                       node->parent->level = node_get_deplist_recurs(ntree, node->parent, nsort);
                if (node->parent->level <= level)
                        level = node->parent->level - 1;
        }
@@ -1696,7 +1753,7 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, in
        /* recursive check */
        for (node = ntree->nodes.first; node; node = node->next) {
                if (node->done == 0) {
-                       node->level = node_get_deplist_recurs(node, &nsort);
+                       node->level = node_get_deplist_recurs(ntree, node, &nsort);
                }
        }
 }
@@ -1714,7 +1771,7 @@ static void ntree_update_node_level(bNodeTree *ntree)
        /* recursive check */
        for (node = ntree->nodes.first; node; node = node->next) {
                if (node->done == 0) {
-                       node->level = node_get_deplist_recurs(node, NULL);
+                       node->level = node_get_deplist_recurs(ntree, node, NULL);
                }
        }
 }
@@ -1813,6 +1870,8 @@ void ntreeUpdateTree(bNodeTree *ntree)
                                ntreetype->update_node(ntree, node);
                        else if (node->typeinfo->updatefunc)
                                node->typeinfo->updatefunc(ntree, node);
+                       
+                       nodeUpdateInternalLinks(ntree, node);
                }
        }
        
@@ -1850,6 +1909,9 @@ void nodeUpdate(bNodeTree *ntree, bNode *node)
                ntreetype->update_node(ntree, node);
        else if (node->typeinfo->updatefunc)
                node->typeinfo->updatefunc(ntree, node);
+       
+       nodeUpdateInternalLinks(ntree, node);
+       
        /* clear update flag */
        node->update = 0;
 }
@@ -1889,9 +1951,21 @@ int nodeUpdateID(bNodeTree *ntree, ID *id)
                }
        }
        
+       for (node = ntree->nodes.first; node; node = node->next) {
+               nodeUpdateInternalLinks(ntree, node);
+       }
+       
        return change;
 }
 
+void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node)
+{
+       BLI_freelistN(&node->internal_links);
+       
+       if (node->typeinfo && node->typeinfo->update_internal_links)
+               node->typeinfo->update_internal_links(ntree, node);
+}
+
 
 /* ************* node type access ********** */
 
@@ -1964,12 +2038,11 @@ void node_type_base(bNodeTreeType *ttype, bNodeType *ntype, int type, const char
 
        /* Default muting stuff. */
        if (ttype)
-               ntype->internal_connect = ttype->internal_connect;
+               ntype->update_internal_links = ttype->update_internal_links;
 
        /* default size values */
-       ntype->width = 140;
-       ntype->minwidth = 100;
-       ntype->maxwidth = 320;
+       node_type_size_preset(ntype, NODE_SIZE_DEFAULT);
+       
        ntype->height = 100;
        ntype->minheight = 30;
        ntype->maxheight = FLT_MAX;
@@ -2001,6 +2074,21 @@ void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwid
                ntype->maxwidth = maxwidth;
 }
 
+void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size)
+{
+       switch (size) {
+               case NODE_SIZE_DEFAULT:
+                       node_type_size(ntype, 140, 100, 320);
+                       break;
+               case NODE_SIZE_SMALL:
+                       node_type_size(ntype, 100, 80, 320);
+                       break;
+               case NODE_SIZE_LARGE:
+                       node_type_size(ntype, 140, 120, 500);
+                       break;
+       }
+}
+
 void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *))
 {
        if (storagename)
@@ -2060,9 +2148,9 @@ void node_type_exec_new(struct bNodeType *ntype,
        ntype->newexecfunc = newexecfunc;
 }
 
-void node_type_internal_connect(bNodeType *ntype, ListBase (*internal_connect)(bNodeTree *, bNode *))
+void node_type_internal_links(bNodeType *ntype, void (*update_internal_links)(bNodeTree *, bNode *))
 {
-       ntype->internal_connect = internal_connect;
+       ntype->update_internal_links = update_internal_links;
 }
 
 void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out))
@@ -2098,6 +2186,24 @@ void nodeRegisterType(bNodeTreeType *ttype, bNodeType *ntype)
        
        if (found == NULL)
                BLI_addtail(typelist, ntype);
+       
+       /* Associate the RNA struct type with the bNodeType.
+        * Dynamically registered nodes will create an RNA type at runtime
+        * and call RNA_struct_blender_type_set, so this only needs to be done for old RNA types
+        * created in makesrna, which can not be associated to a bNodeType immediately,
+        * since bNodeTypes are registered afterward ...
+        */
+       #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+       if (ID == ntype->type) { \
+               StructRNA *srna = RNA_struct_find(STRINGIFY_ARG(Category##StructName)); \
+               BLI_assert(srna != NULL); \
+               RNA_struct_blender_type_set(srna, ntype); \
+       }
+       
+       /* XXX hack, this file will be moved to the nodes folder in customnodes branch,
+        * then this stupid include path is not needed any more.
+        */
+       #include "intern/rna_nodetree_types.h"
 }
 
 static void registerCompositNodes(bNodeTreeType *ttype)
@@ -2106,8 +2212,6 @@ static void registerCompositNodes(bNodeTreeType *ttype)
        register_node_type_reroute(ttype);
        
        register_node_type_cmp_group(ttype);
-//     register_node_type_cmp_forloop(ttype);
-//     register_node_type_cmp_whileloop(ttype);
        
        register_node_type_cmp_rlayers(ttype);
        register_node_type_cmp_image(ttype);
@@ -2137,6 +2241,7 @@ static void registerCompositNodes(bNodeTreeType *ttype)
        register_node_type_cmp_normal(ttype);
        register_node_type_cmp_curve_vec(ttype);
        register_node_type_cmp_map_value(ttype);
+       register_node_type_cmp_map_range(ttype);
        register_node_type_cmp_normalize(ttype);
        
        register_node_type_cmp_filter(ttype);
@@ -2195,6 +2300,7 @@ static void registerCompositNodes(bNodeTreeType *ttype)
        register_node_type_cmp_bokehimage(ttype);
        register_node_type_cmp_bokehblur(ttype);
        register_node_type_cmp_switch(ttype);
+       register_node_type_cmp_pixelate(ttype);
 
        register_node_type_cmp_mask(ttype);
        register_node_type_cmp_trackpos(ttype);
@@ -2206,8 +2312,6 @@ static void registerShaderNodes(bNodeTreeType *ttype)
        register_node_type_reroute(ttype);
        
        register_node_type_sh_group(ttype);
-       //register_node_type_sh_forloop(ttype);
-       //register_node_type_sh_whileloop(ttype);
 
        register_node_type_sh_output(ttype);
        register_node_type_sh_material(ttype);
@@ -2243,16 +2347,24 @@ static void registerShaderNodes(bNodeTreeType *ttype)
        register_node_type_sh_layer_weight(ttype);
        register_node_type_sh_tex_coord(ttype);
        register_node_type_sh_particle_info(ttype);
+       register_node_type_sh_hair_info(ttype);
+       register_node_type_sh_bump(ttype);
+       register_node_type_sh_script(ttype);
+       register_node_type_sh_tangent(ttype);
+       register_node_type_sh_normal_map(ttype);
 
        register_node_type_sh_background(ttype);
+       register_node_type_sh_bsdf_anisotropic(ttype);
        register_node_type_sh_bsdf_diffuse(ttype);
        register_node_type_sh_bsdf_glossy(ttype);
        register_node_type_sh_bsdf_glass(ttype);
+       register_node_type_sh_bsdf_refraction(ttype);
        register_node_type_sh_bsdf_translucent(ttype);
        register_node_type_sh_bsdf_transparent(ttype);
        register_node_type_sh_bsdf_velvet(ttype);
        register_node_type_sh_emission(ttype);
        register_node_type_sh_holdout(ttype);
+       register_node_type_sh_ambient_occlusion(ttype);
        //register_node_type_sh_volume_transparent(ttype);
        //register_node_type_sh_volume_isotropic(ttype);
        register_node_type_sh_mix_shader(ttype);
@@ -2281,8 +2393,6 @@ static void registerTextureNodes(bNodeTreeType *ttype)
        register_node_type_reroute(ttype);
        
        register_node_type_tex_group(ttype);
-//     register_node_type_tex_forloop(ttype);
-//     register_node_type_tex_whileloop(ttype);
        
        register_node_type_tex_math(ttype);
        register_node_type_tex_mix_rgb(ttype);