Patch #34204: [Render Animation] Fails with "Error: Specified sample_fmt is not suppo...
[blender.git] / source / blender / blenkernel / intern / node.c
index 7cee962..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"
@@ -58,8 +62,6 @@
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_node.h"
-#include "BKE_utildefines.h"
-#include "BKE_utildefines.h"
 
 #include "RNA_access.h"
 
@@ -149,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);
@@ -328,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;
@@ -345,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) */
@@ -384,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)
@@ -391,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;
@@ -522,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 */
@@ -547,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
@@ -564,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)
@@ -634,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;
@@ -648,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;
@@ -671,7 +699,7 @@ bNodeTree *ntreeAddTree(const char *name, int type, int nodetype)
  * copying for internal use (threads for eg), where you wont want it to modify the
  * scene data.
  */
-static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_extern)
+static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_user, const short do_make_extern)
 {
        bNodeTree *newtree;
        bNode *node /*, *nnode */ /* UNUSED */, *last;
@@ -688,7 +716,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e
        }
        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);
@@ -702,12 +730,17 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e
        last = ntree->nodes.last;
        for (node = ntree->nodes.first; node; node = node->next) {
 
+               /* ntreeUserDecrefID inline */
+               if (do_id_user) {
+                       id_us_plus(node->id);
+               }
+
                if (do_make_extern) {
                        id_lib_extern(node->id);
                }
 
                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)
@@ -751,22 +784,56 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_make_e
        return newtree;
 }
 
+bNodeTree *ntreeCopyTree_ex(bNodeTree *ntree, const short do_id_user)
+{
+       return ntreeCopyTree_internal(ntree, do_id_user, TRUE);
+}
 bNodeTree *ntreeCopyTree(bNodeTree *ntree)
 {
-       return ntreeCopyTree_internal(ntree, TRUE);
+       return ntreeCopyTree_ex(ntree, TRUE);
 }
 
 /* use when duplicating scenes */
-void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to)
+void ntreeSwitchID_ex(bNodeTree *ntree, ID *id_from, ID *id_to, const short do_id_user)
 {
        bNode *node;
+
+       if (id_from == id_to) {
+               /* should never happen but may as well skip if it does */
+               return;
+       }
+
        /* for scene duplication only */
        for (node = ntree->nodes.first; node; node = node->next) {
                if (node->id == id_from) {
+                       if (do_id_user) {
+                               id_us_min(id_from);
+                               id_us_plus(id_to);
+                       }
+
                        node->id = id_to;
                }
        }
 }
+void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to)
+{
+       ntreeSwitchID_ex(ntree, id_from, id_to, TRUE);
+}
+
+void ntreeUserIncrefID(bNodeTree *ntree)
+{
+       bNode *node;
+       for (node = ntree->nodes.first; node; node = node->next) {
+               id_us_plus(node->id);
+       }
+}
+void ntreeUserDecrefID(bNodeTree *ntree)
+{
+       bNode *node;
+       for (node = ntree->nodes.first; node; node = node->next) {
+               id_us_min(node->id);
+       }
+}
 
 /* *************** preview *********** */
 /* if node->preview, then we assume the rect to exist */
@@ -778,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)
@@ -821,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)
@@ -843,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) {
@@ -913,6 +980,7 @@ static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
        }
 }
 
+/** \note caller needs to manage node->id user */
 void nodeFreeNode(bNodeTree *ntree, bNode *node)
 {
        bNodeSocket *sock, *nextsock;
@@ -929,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 */
@@ -947,6 +1021,8 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
                MEM_freeN(sock);
        }
 
+       BLI_freelistN(&node->internal_links);
+
        nodeFreePreview(node);
 
        MEM_freeN(node);
@@ -956,8 +1032,9 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
 }
 
 /* do not free ntree itself here, BKE_libblock_free calls this function too */
-void ntreeFreeTree(bNodeTree *ntree)
+void ntreeFreeTree_ex(bNodeTree *ntree, const short do_id_user)
 {
+       bNodeTree *tntree;
        bNode *node, *next;
        bNodeSocket *sock;
        
@@ -970,14 +1047,12 @@ void ntreeFreeTree(bNodeTree *ntree)
         */
        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;
                }
        }
@@ -990,6 +1065,21 @@ void ntreeFreeTree(bNodeTree *ntree)
        
        for (node = ntree->nodes.first; node; node = next) {
                next = node->next;
+
+               /* ntreeUserIncrefID inline */
+
+               /* XXX, this is correct, however when freeing the entire database
+                * this ends up accessing freed data which isn't properly unlinking
+                * its self from scene nodes, SO - for now prefer invalid usercounts
+                * on free rather then bad memory access - Campbell */
+#if 0
+               if (do_id_user) {
+                       id_us_min(node->id);
+               }
+#else
+               (void)do_id_user;
+#endif
+
                nodeFreeNode(ntree, node);
        }
        
@@ -999,6 +1089,19 @@ void ntreeFreeTree(bNodeTree *ntree)
        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)
+{
+       ntreeFreeTree_ex(ntree, TRUE);
 }
 
 void ntreeFreeCache(bNodeTree *ntree)
@@ -1065,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;
@@ -1188,7 +1303,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
        }
 
        /* node copy func */
-       ltree = ntreeCopyTree_internal(ntree, FALSE);
+       ltree = ntreeCopyTree_internal(ntree, FALSE, FALSE);
 
        if (adt) {
                AnimData *ladt = BKE_animdata_from_id(&ltree->id);
@@ -1248,7 +1363,7 @@ void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
        if (ntreetype->local_merge)
                ntreetype->local_merge(localtree, ntree);
 
-       ntreeFreeTree(localtree);
+       ntreeFreeTree_ex(localtree, FALSE);
        MEM_freeN(localtree);
 }
 
@@ -1425,13 +1540,37 @@ void nodeSocketSetType(bNodeSocket *sock, int type)
 
 /* ************** Node Clipboard *********** */
 
+#define USE_NODE_CB_VALIDATE
+
+#ifdef USE_NODE_CB_VALIDATE
+/**
+ * This data structure is to validate the node on creation,
+ * otherwise we may reference missing data.
+ *
+ * Currently its only used for ID's, but nodes may one day
+ * reference other pointers which need validation.
+ */
+typedef struct bNodeClipboardExtraInfo {
+       struct bNodeClipboardExtraInfo *next, *prev;
+       ID  *id;
+       char id_name[MAX_ID_NAME];
+       char library_name[FILE_MAX];
+} bNodeClipboardExtraInfo;
+#endif  /* USE_NODE_CB_VALIDATE */
+
+
 typedef struct bNodeClipboard {
        ListBase nodes;
+
+#ifdef USE_NODE_CB_VALIDATE
+       ListBase nodes_extra_info;
+#endif
+
        ListBase links;
        int type;
 } bNodeClipboard;
 
-bNodeClipboard node_clipboard;
+bNodeClipboard node_clipboard = {{0}};
 
 void BKE_node_clipboard_init(struct bNodeTree *ntree)
 {
@@ -1454,11 +1593,83 @@ void BKE_node_clipboard_clear(void)
                nodeFreeNode(NULL, node);
        }
        node_clipboard.nodes.first = node_clipboard.nodes.last = NULL;
+
+#ifdef USE_NODE_CB_VALIDATE
+       BLI_freelistN(&node_clipboard.nodes_extra_info);
+#endif
+}
+
+/* return FALSE when one or more ID's are lost */
+int BKE_node_clipboard_validate(void)
+{
+       int ok = TRUE;
+
+#ifdef USE_NODE_CB_VALIDATE
+       bNodeClipboardExtraInfo *node_info;
+       bNode *node;
+
+
+       /* lists must be aligned */
+       BLI_assert(BLI_countlist(&node_clipboard.nodes) ==
+                  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)
+       {
+               /* validate the node against the stored node info */
+
+               /* re-assign each loop since we may clear,
+                * open a new file where the ID is valid, and paste again */
+               node->id = node_info->id;
+
+               /* currently only validate the ID */
+               if (node->id) {
+                       ListBase *lb = which_libbase(G.main, GS(node_info->id_name));
+                       BLI_assert(lb != NULL);
+
+                       if (BLI_findindex(lb, node_info->id) == -1) {
+                               /* may assign NULL */
+                               node->id = BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2);
+
+                               if (node->id == NULL) {
+                                       ok = FALSE;
+                               }
+                       }
+               }
+       }
+#endif  /* USE_NODE_CB_VALIDATE */
+
+       return ok;
 }
 
 void BKE_node_clipboard_add_node(bNode *node)
 {
+#ifdef USE_NODE_CB_VALIDATE
+       /* add extra info */
+       bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), "bNodeClipboardExtraInfo");
+
+       node_info->id = node->id;
+       if (node->id) {
+               BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name));
+               if (node->id->lib) {
+                       BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name));
+               }
+               else {
+                       node_info->library_name[0] = '\0';
+               }
+       }
+       else {
+               node_info->id_name[0] = '\0';
+               node_info->library_name[0] = '\0';
+       }
+       BLI_addtail(&node_clipboard.nodes_extra_info, node_info);
+       /* end extra info */
+#endif  /* USE_NODE_CB_VALIDATE */
+
+       /* add node */
        BLI_addtail(&node_clipboard.nodes, node);
+
 }
 
 void BKE_node_clipboard_add_link(bNodeLink *link)
@@ -1484,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;
                        }
@@ -1508,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;
        }
@@ -1542,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);
                }
        }
 }
@@ -1560,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);
                }
        }
 }
@@ -1659,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);
                }
        }
        
@@ -1696,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;
 }
@@ -1735,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 ********** */
 
@@ -1810,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;
@@ -1847,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)
@@ -1906,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))
@@ -1944,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)
@@ -1952,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);
@@ -1983,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);
@@ -1992,6 +2251,7 @@ static void registerCompositNodes(bNodeTreeType *ttype)
        register_node_type_cmp_vecblur(ttype);
        register_node_type_cmp_dilateerode(ttype);
        register_node_type_cmp_inpaint(ttype);
+       register_node_type_cmp_despeckle(ttype);
        register_node_type_cmp_defocus(ttype);
        
        register_node_type_cmp_valtorgb(ttype);
@@ -2040,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);
@@ -2051,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);
@@ -2088,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);
@@ -2117,6 +2384,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
        register_node_type_sh_tex_gradient(ttype);
        register_node_type_sh_tex_magic(ttype);
        register_node_type_sh_tex_checker(ttype);
+       register_node_type_sh_tex_brick(ttype);
 }
 
 static void registerTextureNodes(bNodeTreeType *ttype)
@@ -2125,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);