svn merge ^/trunk/blender -r55372:55392
[blender.git] / source / blender / blenloader / intern / readfile.c
index 4bae406fd09e24c870a65b7296f21d04e078b693..0fa01b95bb2bf5efc908cc4a02ac70f66316bdf3 100644 (file)
@@ -71,6 +71,9 @@
 #include "DNA_key_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_lamp_types.h"
+#ifdef WITH_FREESTYLE
+#  include "DNA_linestyle_types.h"
+#endif
 #include "DNA_meta_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h" // for which_libbase
 #include "BKE_idcode.h"
+#include "BKE_idprop.h"
 #include "BKE_material.h"
 #include "BKE_main.h" // for Main
 #include "BKE_mesh.h" // for ME_ defines (patching)
 
 #include "IMB_imbuf.h"  // for proxy / timecode versioning stuff
 
+#include "NOD_common.h"
 #include "NOD_socket.h"
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
 
 #include "BLO_readfile.h"
 #include "BLO_undofile.h"
@@ -378,7 +386,7 @@ static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
 
                for (i = 0, entry = onm->entries; i < nentries; i++, entry++) {
                        if (entry->old == addr) {
-                               ID *id = id = entry->newp;
+                               ID *id = entry->newp;
                                if (id && (!lib || id->lib)) {
                                        return id;
                                }
@@ -493,16 +501,6 @@ void blo_split_main(ListBase *mainlist, Main *main)
                split_libdata(lbarray[i], main->next);
 }
 
-/* removes things like /blah/blah/../../blah/ etc, then writes in *name the full path */
-static void cleanup_path(const char *relabase, char *name)
-{
-       char filename[FILE_MAXFILE];
-       
-       BLI_splitdirstring(name, filename);
-       BLI_cleanup_dir(relabase, name);
-       strcat(name, filename);
-}
-
 static void read_file_version(FileData *fd, Main *main)
 {
        BHead *bhead;
@@ -531,7 +529,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
        char name1[FILE_MAX];
        
        BLI_strncpy(name1, filepath, sizeof(name1));
-       cleanup_path(relabase, name1);
+       BLI_cleanup_path(relabase, name1);
        
 //     printf("blo_find_main: relabase  %s\n", relabase);
 //     printf("blo_find_main: original in  %s\n", filepath);
@@ -1051,7 +1049,7 @@ static int fd_read_gzip_from_memory_init(FileData *fd)
        return 1;
 }
 
-FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
+FileData *blo_openblendermemory(const void *mem, int memsize, ReportList *reports)
 {
        if (!mem || memsize<SIZEOFBLENDERHEADER) {
                BKE_report(reports, RPT_WARNING, (mem) ? TIP_("Unable to read"): TIP_("Unable to open"));
@@ -1059,7 +1057,7 @@ FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
        }
        else {
                FileData *fd = filedata_new();
-               char *cp = mem;
+               const char *cp = mem;
                
                fd->buffer = mem;
                fd->buffersize = memsize;
@@ -1072,10 +1070,10 @@ FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
                        }
                }
                else
-                       fd->read = fd_read_from_memory;
+               fd->read = fd_read_from_memory;
                        
                fd->flags |= FD_FLAGS_NOT_MY_BUFFER;
-
+               
                return blo_decode_and_check(fd, reports);
        }
 }
@@ -1116,7 +1114,7 @@ void blo_freefiledata(FileData *fd)
                }
                
                if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
-                       MEM_freeN(fd->buffer);
+                       MEM_freeN((void *)fd->buffer);
                        fd->buffer = NULL;
                }
                
@@ -1175,7 +1173,7 @@ int BLO_is_a_library(const char *path, char *dir, char *group)
        dir[len - 1] = '\0';
 
        /* Find the last slash */
-       fd = BLI_last_slash(dir);
+       fd = (char *)BLI_last_slash(dir);
 
        if (fd == NULL) return 0;
        *fd = 0;
@@ -1184,10 +1182,10 @@ int BLO_is_a_library(const char *path, char *dir, char *group)
                *fd = '/'; /* put back the removed slash separating the dir and the .blend file name */
        }
        else {
-               char *gp = fd + 1; // in case we have a .blend file, gp points to the group
+               const char * const gp = fd + 1; // in case we have a .blend file, gp points to the group
                
                /* Find the last slash */
-               fd = BLI_last_slash(dir);
+               fd = (char *)BLI_last_slash(dir);
                if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
                
                /* now we know that we are in a blend file and it is safe to 
@@ -1205,19 +1203,19 @@ static void *newdataadr(FileData *fd, void *adr)                /* only direct databocks */
        return oldnewmap_lookup_and_inc(fd->datamap, adr);
 }
 
-static void *newglobadr(FileData *fd, void *adr)           /* direct datablocks with global linking */
+static void *newglobadr(FileData *fd, void *adr)               /* direct datablocks with global linking */
 {
        return oldnewmap_lookup_and_inc(fd->globmap, adr);
 }
 
-static void *newimaadr(FileData *fd, void *adr)                    /* used to restore image data after undo */
+static void *newimaadr(FileData *fd, void *adr)                /* used to restore image data after undo */
 {
        if (fd->imamap && adr)
                return oldnewmap_lookup_and_inc(fd->imamap, adr);
        return NULL;
 }
 
-static void *newmclipadr(FileData *fd, void *adr)      /* used to restore movie clip data after undo */
+static void *newmclipadr(FileData *fd, void *adr)              /* used to restore movie clip data after undo */
 {
        if (fd->movieclipmap && adr)
                return oldnewmap_lookup_and_inc(fd->movieclipmap, adr);
@@ -1228,7 +1226,7 @@ static void *newpackedadr(FileData *fd, void *adr)      /* used to restore packe
 {
        if (fd->packedmap && adr)
                return oldnewmap_lookup_and_inc(fd->packedmap, adr);
-       
+
        return oldnewmap_lookup_and_inc(fd->datamap, adr);
 }
 
@@ -1323,10 +1321,12 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
                                oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0);
        }
        for (; sce; sce = sce->id.next) {
-               if (sce->nodetree) {
-                       bNode *node;
-                       for (node = sce->nodetree->nodes.first; node; node = node->next)
-                               oldnewmap_insert(fd->imamap, node->preview, node->preview, 0);
+               if (sce->nodetree && sce->nodetree->previews) {
+                       bNodeInstanceHashIterator iter;
+                       NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) {
+                               bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+                               oldnewmap_insert(fd->imamap, preview, preview, 0);
+                       }
                }
        }
 }
@@ -1365,10 +1365,23 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
                ima->gputexture = newimaadr(fd, ima->gputexture);
        }
        for (; sce; sce = sce->id.next) {
-               if (sce->nodetree) {
-                       bNode *node;
-                       for (node = sce->nodetree->nodes.first; node; node = node->next)
-                               node->preview = newimaadr(fd, node->preview);
+               if (sce->nodetree && sce->nodetree->previews) {
+                       bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews");
+                       bNodeInstanceHashIterator iter;
+                       
+                       /* reconstruct the preview hash, only using remaining pointers */
+                       NODE_INSTANCE_HASH_ITER(iter, sce->nodetree->previews) {
+                               bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+                               if (preview) {
+                                       bNodePreview *new_preview = newimaadr(fd, preview);
+                                       if (new_preview) {
+                                               bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+                                               BKE_node_instance_hash_insert(new_previews, key, new_preview);
+                                       }
+                               }
+                       }
+                       BKE_node_instance_hash_free(sce->nodetree->previews, NULL);
+                       sce->nodetree->previews = new_previews;
                }
        }
 }
@@ -1391,7 +1404,7 @@ void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain)
        for (; sce; sce = sce->id.next) {
                if (sce->nodetree) {
                        bNode *node;
-                       for (node = sce->nodetree->nodes.first; node; node= node->next)
+                       for (node = sce->nodetree->nodes.first; node; node = node->next)
                                if (node->type == CMP_NODE_MOVIEDISTORTION)
                                        oldnewmap_insert(fd->movieclipmap, node->storage, node->storage, 0);
                }
@@ -2296,17 +2309,42 @@ static void direct_link_motionpath(FileData *fd, bMotionPath *mpath)
 
 /* ************ READ NODE TREE *************** */
 
+static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock)
+{
+       /* Link ID Properties -- and copy this comment EXACTLY for easy finding
+        * of library blocks that implement this.*/
+       if (sock->prop)
+               IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+}
+
 /* singe node tree (also used for material/scene trees), ntree is not NULL */
 static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
 {
        bNode *node;
+       bNodeSocket *sock;
        
        if (ntree->adt) lib_link_animdata(fd, &ntree->id, ntree->adt);
        
        ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd);
        
-       for (node = ntree->nodes.first; node; node = node->next)
-               node->id = newlibadr_us(fd, id->lib, node->id);
+       for (node = ntree->nodes.first; node; node = node->next) {
+               /* Link ID Properties -- and copy this comment EXACTLY for easy finding
+                * of library blocks that implement this.*/
+               if (node->prop)
+                       IDP_LibLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+               
+               node->id= newlibadr_us(fd, id->lib, node->id);
+
+               for (sock = node->inputs.first; sock; sock = sock->next)
+                       lib_link_node_socket(fd, id, sock);
+               for (sock = node->outputs.first; sock; sock = sock->next)
+                       lib_link_node_socket(fd, id, sock);
+       }
+       
+       for (sock = ntree->inputs.first; sock; sock = sock->next)
+               lib_link_node_socket(fd, id, sock);
+       for (sock = ntree->outputs.first; sock; sock = sock->next)
+               lib_link_node_socket(fd, id, sock);
 }
 
 /* library ntree linking after fileread */
@@ -2323,131 +2361,49 @@ static void lib_link_nodetree(FileData *fd, Main *main)
        }
 }
 
-static void do_versions_socket_default_value(bNodeSocket *sock)
-{
-       bNodeSocketValueFloat *valfloat;
-       bNodeSocketValueVector *valvector;
-       bNodeSocketValueRGBA *valrgba;
-       
-       if (sock->default_value)
-               return;
-       
-       switch (sock->type) {
-               case SOCK_FLOAT:
-                       valfloat = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueFloat), "default socket value");
-                       valfloat->value = sock->ns.vec[0];
-                       valfloat->min = sock->ns.min;
-                       valfloat->max = sock->ns.max;
-                       valfloat->subtype = PROP_NONE;
-                       break;
-               case SOCK_VECTOR:
-                       valvector = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueVector), "default socket value");
-                       copy_v3_v3(valvector->value, sock->ns.vec);
-                       valvector->min = sock->ns.min;
-                       valvector->max = sock->ns.max;
-                       valvector->subtype = PROP_NONE;
-                       break;
-               case SOCK_RGBA:
-                       valrgba = sock->default_value = MEM_callocN(sizeof(bNodeSocketValueRGBA), "default socket value");
-                       copy_v4_v4(valrgba->value, sock->ns.vec);
-                       break;
-       }
-}
-
-void blo_do_versions_nodetree_default_value(bNodeTree *ntree)
-{
-       bNode *node;
-       bNodeSocket *sock;
-       for (node=ntree->nodes.first; node; node=node->next) {
-               for (sock=node->inputs.first; sock; sock=sock->next)
-                       do_versions_socket_default_value(sock);
-               for (sock=node->outputs.first; sock; sock=sock->next)
-                       do_versions_socket_default_value(sock);
-       }
-       for (sock=ntree->inputs.first; sock; sock=sock->next)
-               do_versions_socket_default_value(sock);
-       for (sock=ntree->outputs.first; sock; sock=sock->next)
-               do_versions_socket_default_value(sock);
-}
-
-static void lib_nodetree_init_types_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-       
-       ntreeInitTypes(ntree);
-       
-       /* need to do this here instead of in do_versions, otherwise next function can crash */
-       blo_do_versions_nodetree_default_value(ntree);
-       
-       /* XXX could be replaced by do_versions for new nodes */
-       for (node=ntree->nodes.first; node; node=node->next)
-               node_verify_socket_templates(ntree, node);
-}
-
-/* updates group node socket own_index so that
+/* updates group node socket identifier so that
  * external links to/from the group node are preserved.
  */
 static void lib_node_do_versions_group_indices(bNode *gnode)
 {
        bNodeTree *ngroup = (bNodeTree*)gnode->id;
-       bNode *intnode;
-       bNodeSocket *sock, *gsock, *intsock;
-       int found;
+       bNodeSocket *sock;
+       bNodeLink *link;
        
-       for (sock=gnode->outputs.first; sock; sock=sock->next) {
+       for (sock=gnode->outputs.first; sock; sock = sock->next) {
                int old_index = sock->to_index;
-               for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) {
-                       if (gsock->link && gsock->link->fromsock->own_index == old_index) {
-                               sock->own_index = gsock->own_index;
-                               break;
+               
+               for (link = ngroup->links.first; link; link = link->next) {
+                       if (link->tonode->type == NODE_GROUP_OUTPUT && link->fromsock->own_index == old_index) {
+                               strcpy(sock->identifier, link->fromsock->identifier);
+                               /* deprecated */
+                               sock->own_index = link->fromsock->own_index;
+                               sock->to_index = 0;
+                               sock->groupsock = NULL;
                        }
                }
        }
-       for (sock=gnode->inputs.first; sock; sock=sock->next) {
+       for (sock=gnode->inputs.first; sock; sock = sock->next) {
                int old_index = sock->to_index;
-               /* can't use break in double loop */
-               found = 0;
-               for (intnode=ngroup->nodes.first; intnode && !found; intnode=intnode->next) {
-                       for (intsock=intnode->inputs.first; intsock; intsock=intsock->next) {
-                               if (intsock->own_index == old_index && intsock->link) {
-                                       sock->own_index = intsock->link->fromsock->own_index;
-                                       found = 1;
-                                       break;
-                               }
+               
+               for (link = ngroup->links.first; link; link = link->next) {
+                       if (link->fromnode->type == NODE_GROUP_INPUT && link->tosock->own_index == old_index) {
+                               strcpy(sock->identifier, link->tosock->identifier);
+                               /* deprecated */
+                               sock->own_index = link->tosock->own_index;
+                               sock->to_index = 0;
+                               sock->groupsock = NULL;
                        }
                }
        }
 }
 
-/* updates external links for all group nodes in a tree */
-static void lib_nodetree_do_versions_group_indices_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-       
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (node->type == NODE_GROUP) {
-                       bNodeTree *ngroup = (bNodeTree*)node->id;
-                       if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE))
-                               lib_node_do_versions_group_indices(node);
-               }
-       }
-}
-
-/* make an update call for the tree */
-static void lib_nodetree_do_versions_update_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       if (ntree->update)
-               ntreeUpdateTree(ntree);
-}
-
 /* verify types for nodes and groups, all data has to be read */
 /* open = 0: appending/linking, open = 1: open new file (need to clean out dynamic
  * typedefs */
 static void lib_verify_nodetree(Main *main, int UNUSED(open))
 {
        bNodeTree *ntree;
-       int i;
-       bNodeTreeType *ntreetype;
        
        /* this crashes blender on undo/redo */
 #if 0
@@ -2457,41 +2413,138 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
 #endif
        
        /* set node->typeinfo pointers */
-       for (i = 0; i < NUM_NTREE_TYPES; ++i) {
-               ntreetype = ntreeGetType(i);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, lib_nodetree_init_types_cb);
-       }
-       for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
-               lib_nodetree_init_types_cb(NULL, NULL, ntree);
+       FOREACH_NODETREE(main, ntree, id) {
+               ntreeSetTypes(NULL, ntree);
+       } FOREACH_NODETREE_END
+       
+       /* verify static socket templates */
+       FOREACH_NODETREE(main, ntree, id) {
+               bNode *node;
+               for (node=ntree->nodes.first; node; node=node->next)
+                       node_verify_socket_templates(ntree, node);
+       } FOREACH_NODETREE_END
        
        {
                int has_old_groups = 0;
                /* XXX this should actually be part of do_versions, but since we need
                 * finished library linking, it is not possible there. Instead in do_versions
-                * we have set the NTREE_DO_VERSIONS flag, so at this point we can do the
+                * we have set the NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2 flag, so at this point we can do the
                 * actual group node updates.
                 */
                for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
-                       if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE) {
-                               /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
-                               node_group_expose_all_sockets(ntree);
+                       if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2)
                                has_old_groups = 1;
-                       }
                }
                
                if (has_old_groups) {
-                       for (i = 0; i < NUM_NTREE_TYPES; ++i) {
-                               ntreetype = ntreeGetType(i);
-                               if (ntreetype && ntreetype->foreach_nodetree)
-                                       ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_group_indices_cb);
-                       }
+                       FOREACH_NODETREE(main, ntree, id) {
+                               /* updates external links for all group nodes in a tree */
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == NODE_GROUP) {
+                                               bNodeTree *ngroup = (bNodeTree*)node->id;
+                                               if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2))
+                                                       lib_node_do_versions_group_indices(node);
+                                       }
+                               }
+                       } FOREACH_NODETREE_END
                }
                
                for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
-                       ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE;
+                       ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2;
        }
+       
+       {
+               /* Convert the previously used ntree->inputs/ntree->outputs lists to interface nodes.
+                * Pre 2.56.2 node trees automatically have all unlinked sockets exposed already
+                * (see NTREE_DO_VERSIONS_GROUP_EXPOSE_2_56_2).
+                *
+                * XXX this should actually be part of do_versions,
+                * but needs valid typeinfo pointers to create interface nodes.
+                */
                
+               for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+                       if (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP) {
+                               bNode *input_node = NULL, *output_node = NULL;
+                               int num_inputs = 0, num_outputs = 0;
+                               bNodeLink *link, *next_link;
+                               /* Only create new interface nodes for actual older files.
+                                * New file versions already have input/output nodes with duplicate links,
+                                * in that case just remove the invalid links.
+                                */
+                               int create_io_nodes = (ntree->flag & NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE);
+                               
+                               float input_locx = 1000000.0f, input_locy = 0.0f;
+                               float output_locx = -1000000.0f, output_locy = 0.0f;
+                               /* rough guess, not nice but we don't have access to UI constants here ... */
+                               static const float offsetx = 42 + 3*20 + 20;
+                               /*static const float offsety = 0.0f;*/
+                               
+                               if (create_io_nodes) {
+                                       if (ntree->inputs.first)
+                                               input_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_INPUT);
+                                       
+                                       if (ntree->outputs.first)
+                                               output_node = nodeAddStaticNode(NULL, ntree, NODE_GROUP_OUTPUT);
+                               }
+                               
+                               /* Redirect links from/to the node tree interface to input/output node.
+                                * If the fromnode/tonode pointers are NULL, this means a link from/to
+                                * the ntree interface sockets, which need to be redirected to new interface nodes.
+                                */
+                               for (link = ntree->links.first; link; link = next_link) {
+                                       int free_link = FALSE;
+                                       next_link = link->next;
+                                       
+                                       if (link->fromnode == NULL) {
+                                               if (input_node) {
+                                                       link->fromnode = input_node;
+                                                       link->fromsock = node_group_input_find_socket(input_node, link->fromsock->identifier);
+                                                       ++num_inputs;
+                                                       
+                                                       if (input_locx > link->tonode->locx - offsetx)
+                                                               input_locx = link->tonode->locx - offsetx;
+                                                       input_locy += link->tonode->locy;
+                                               }
+                                               else
+                                                       free_link = TRUE;
+                                       }
+                                       
+                                       if (link->tonode == NULL) {
+                                               if (output_node) {
+                                                       link->tonode = output_node;
+                                                       link->tosock = node_group_output_find_socket(output_node, link->tosock->identifier);
+                                                       ++num_outputs;
+                                                       
+                                                       if (output_locx < link->fromnode->locx + offsetx)
+                                                               output_locx = link->fromnode->locx + offsetx;
+                                                       output_locy += link->fromnode->locy;
+                                               }
+                                               else
+                                                       free_link = TRUE;
+                                       }
+                                       
+                                       if (free_link)
+                                               nodeRemLink(ntree, link);
+                               }
+                               
+                               if (num_inputs > 0) {
+                                       input_locy /= num_inputs;
+                                       input_node->locx = input_locx;
+                                       input_node->locy = input_locy;
+                               }
+                               if (num_outputs > 0) {
+                                       output_locy /= num_outputs;
+                                       output_node->locx = output_locx;
+                                       output_node->locy = output_locy;
+                               }
+                               
+                               /* clear do_versions flags */
+                               ntree->flag &= ~(NTREE_DO_VERSIONS_CUSTOMNODES_GROUP | NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE);
+                       }
+               }
+       }
+       
        /* verify all group user nodes */
        for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
                ntreeVerifyNodes(main, &ntree->id);
@@ -2499,21 +2552,22 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
        
        /* make update calls where necessary */
        {
-               for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
+               FOREACH_NODETREE(main, ntree, id) {
+                       /* make an update call for the tree */
                        if (ntree->update)
                                ntreeUpdateTree(ntree);
-               
-               for (i = 0; i < NUM_NTREE_TYPES; i++) {
-                       ntreetype = ntreeGetType(i);
-                       if (ntreetype && ntreetype->foreach_nodetree)
-                               ntreetype->foreach_nodetree(main, NULL, lib_nodetree_do_versions_update_cb);
-               }
+               } FOREACH_NODETREE_END
        }
 }
 
 static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
 {
+       sock->prop = newdataadr(fd, sock->prop);
+       if (sock->prop)
+               IDP_DirectLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+       
        sock->link = newdataadr(fd, sock->link);
+       sock->typeinfo = NULL;
        sock->storage = newdataadr(fd, sock->storage);
        sock->default_value = newdataadr(fd, sock->default_value);
        sock->cache = NULL;
@@ -2528,6 +2582,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
        bNodeLink *link;
        
        ntree->init = 0;                /* to set callbacks and force setting types */
+       ntree->is_updating = FALSE;
+       ntree->typeinfo= NULL;
+       ntree->interface_type = NULL;
+       
        ntree->progress = NULL;
        ntree->execdata = NULL;
        
@@ -2543,6 +2601,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                link_list(fd, &node->inputs);
                link_list(fd, &node->outputs);
                
+               node->prop = newdataadr(fd, node->prop);
+               if (node->prop)
+                       IDP_DirectLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+               
                link_list(fd, &node->internal_links);
                for (link = node->internal_links.first; link; link = link->next) {
                        link->fromnode = newdataadr(fd, link->fromnode);
@@ -2554,8 +2616,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                if (node->type == CMP_NODE_MOVIEDISTORTION) {
                        node->storage = newmclipadr(fd, node->storage);
                }
-               else
+               else {
                        node->storage = newdataadr(fd, node->storage);
+               }
                
                if (node->storage) {
                        /* could be handlerized at some point */
@@ -2566,9 +2629,6 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                                else if (node->type==SH_NODE_SCRIPT) {
                                        NodeShaderScript *nss = (NodeShaderScript *) node->storage;
                                        nss->bytecode = newdataadr(fd, nss->bytecode);
-                                       nss->prop = newdataadr(fd, nss->prop);
-                                       if (nss->prop)
-                                               IDP_DirectLinkProperty(nss->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
                                }
                        }
                        else if (ntree->type==NTREE_COMPOSIT) {
@@ -2587,14 +2647,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
        }
        link_list(fd, &ntree->links);
        
-       /* external sockets */
-       link_list(fd, &ntree->inputs);
-       link_list(fd, &ntree->outputs);
-       
        /* and we connect the rest */
        for (node = ntree->nodes.first; node; node = node->next) {
                node->parent = newdataadr(fd, node->parent);
-               node->preview = newimaadr(fd, node->preview);
                node->lasty = 0;
                
                for (sock = node->inputs.first; sock; sock = sock->next)
@@ -2602,6 +2657,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                for (sock = node->outputs.first; sock; sock = sock->next)
                        direct_link_node_socket(fd, sock);
        }
+       
+       /* interface socket lists */
+       link_list(fd, &ntree->inputs);
+       link_list(fd, &ntree->outputs);
        for (sock = ntree->inputs.first; sock; sock = sock->next)
                direct_link_node_socket(fd, sock);
        for (sock = ntree->outputs.first; sock; sock = sock->next)
@@ -2614,6 +2673,29 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                link->tosock = newdataadr(fd, link->tosock);
        }
        
+#if 0
+       if (ntree->previews) {
+               bNodeInstanceHash *new_previews = BKE_node_instance_hash_new("node previews");
+               bNodeInstanceHashIterator iter;
+               
+               NODE_INSTANCE_HASH_ITER(iter, ntree->previews) {
+                       bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+                       if (preview) {
+                               bNodePreview *new_preview = newimaadr(fd, preview);
+                               if (new_preview) {
+                                       bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
+                                       BKE_node_instance_hash_insert(new_previews, key, new_preview);
+                               }
+                       }
+               }
+               BKE_node_instance_hash_free(ntree->previews, NULL);
+               ntree->previews = new_previews;
+       }
+#else
+       /* XXX TODO */
+       ntree->previews = NULL;
+#endif
+       
        /* type verification is in lib-link */
 }
 
@@ -3256,7 +3338,9 @@ static void direct_link_curve(FileData *fd, Curve *cu)
        cu->strinfo= newdataadr(fd, cu->strinfo);
        cu->tb = newdataadr(fd, cu->tb);
 
-       if (cu->vfont == NULL) link_list(fd, &(cu->nurb));
+       if (cu->vfont == NULL) {
+               link_list(fd, &(cu->nurb));
+       }
        else {
                cu->nurb.first=cu->nurb.last= NULL;
                
@@ -3334,7 +3418,7 @@ static void direct_link_texture(FileData *fd, Tex *tex)
        tex->env = newdataadr(fd, tex->env);
        if (tex->env) {
                tex->env->ima = NULL;
-               memset(tex->env->cube, 0, 6 * sizeof(void *));
+               memset(tex->env->cube, 0, 6*sizeof(void *));
                tex->env->ok= 0;
        }
        tex->pd = newdataadr(fd, tex->pd);
@@ -3836,8 +3920,10 @@ static void lib_link_mesh(FileData *fd, Main *main)
                                        me->mat[i] = newlibadr_us(fd, me->id.lib, me->mat[i]);
                                }
                        }
-                       else me->totcol = 0;
-                       
+                       else {
+                               me->totcol = 0;
+                       }
+
                        me->ipo = newlibadr_us(fd, me->id.lib, me->ipo); // XXX: deprecated: old anim sys
                        me->key = newlibadr_us(fd, me->id.lib, me->key);
                        me->texcomesh = newlibadr_us(fd, me->id.lib, me->texcomesh);
@@ -4162,9 +4248,9 @@ static void lib_link_object(FileData *fd, Main *main)
                                        ob->proxy = NULL;
                                        
                                        if (ob->id.lib)
-                                               printf("Proxy lost from  object %s lib %s\n", ob->id.name+2, ob->id.lib->name);
+                                               printf("Proxy lost from  object %s lib %s\n", ob->id.name + 2, ob->id.lib->name);
                                        else
-                                               printf("Proxy lost from  object %s lib <NONE>\n", ob->id.name+2);
+                                               printf("Proxy lost from  object %s lib <NONE>\n", ob->id.name + 2);
                                }
                                else {
                                        /* this triggers object_update to always use a copy */
@@ -4178,9 +4264,9 @@ static void lib_link_object(FileData *fd, Main *main)
                        
                        if (ob->data==NULL && poin!=NULL) {
                                if (ob->id.lib)
-                                       printf("Can't find obdata of %s lib %s\n", ob->id.name+2, ob->id.lib->name);
+                                       printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->name);
                                else
-                                       printf("Object %s lost data.\n", ob->id.name+2);
+                                       printf("Object %s lost data.\n", ob->id.name + 2);
                                
                                ob->type = OB_EMPTY;
                                warn = 1;
@@ -4901,7 +4987,7 @@ static void composite_patch(bNodeTree *ntree, Scene *scene)
 {
        bNode *node;
        
-       for (node= ntree->nodes.first; node; node= node->next) {
+       for (node = ntree->nodes.first; node; node = node->next) {
                if (node->id==NULL && ELEM4(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS, CMP_NODE_OUTPUT_FILE))
                        node->id = &scene->id;
        }
@@ -5046,6 +5132,16 @@ static void lib_link_scene(FileData *fd, Main *main)
                        for (srl = sce->r.layers.first; srl; srl = srl->next) {
                                srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override);
                                srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override);
+#ifdef WITH_FREESTYLE
+                               {
+                                       FreestyleLineSet *fls;
+
+                                       for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+                                               fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle);
+                                               fls->group = newlibadr_us(fd, sce->id.lib, fls->group);
+                                       }
+                               }
+#endif
                        }
                        /*Game Settings: Dome Warp Text*/
                        sce->gm.dome.warptext = newlibadr(fd, sce->id.lib, sce->gm.dome.warptext);
@@ -5152,7 +5248,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                if (sce->toolsettings->vpaint) {
                        sce->toolsettings->vpaint->vpaint_prev = NULL;
                        sce->toolsettings->vpaint->tot = 0;
-               }
+       }
                if (sce->toolsettings->wpaint) {
                        sce->toolsettings->wpaint->wpaint_prev = NULL;
                        sce->toolsettings->wpaint->tot = 0;
@@ -5292,6 +5388,19 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        link_list(fd, &(sce->markers));
        link_list(fd, &(sce->transform_spaces));
        link_list(fd, &(sce->r.layers));
+
+#ifdef WITH_FREESTYLE
+       {
+               SceneRenderLayer *srl;
+
+               for(srl = sce->r.layers.first; srl; srl = srl->next) {
+                       link_list(fd, &(srl->freestyleConfig.modules));
+               }
+               for(srl = sce->r.layers.first; srl; srl = srl->next) {
+                       link_list(fd, &(srl->freestyleConfig.linesets));
+               }
+       }
+#endif
        
        sce->nodetree = newdataadr(fd, sce->nodetree);
        if (sce->nodetree) {
@@ -5319,8 +5428,9 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                /* link cache */
                direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, FALSE);
                /* make sure simulation starts from the beginning after loading file */
-               if (rbw->pointcache)
-                       rbw->ltime = rbw->pointcache->startframe;
+               if (rbw->pointcache) {
+                       rbw->ltime = (float)rbw->pointcache->startframe;
+               }
        }
 }
 
@@ -5548,28 +5658,34 @@ static void lib_link_screen(FileData *fd, Main *main)
                                        }
                                        else if (sl->spacetype == SPACE_NODE) {
                                                SpaceNode *snode = (SpaceNode *)sl;
+                                               bNodeTreePath *path, *path_next;
                                                
-                                               snode->id = newlibadr(fd, sc->id.lib, snode->id);
+                                               for (path=snode->treepath.first; path; path=path->next) {
+                                                       path->nodetree = newlibadr(fd, sc->id.lib, path->nodetree);
+                                                       
+                                                       if (!path->nodetree)
+                                                               break;
+                                               }
                                                
-                                               if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
-                                                       /* internal data, a bit patchy */
-                                                       snode->nodetree = NULL;
-                                                       if (snode->id) {
-                                                               if (GS(snode->id->name)==ID_MA)
-                                                                       snode->nodetree = ((Material *)snode->id)->nodetree;
-                                                               else if (GS(snode->id->name)==ID_WO)
-                                                                       snode->nodetree = ((World *)snode->id)->nodetree;
-                                                               else if (GS(snode->id->name)==ID_LA)
-                                                                       snode->nodetree = ((Lamp *)snode->id)->nodetree;
-                                                               else if (GS(snode->id->name)==ID_SCE)
-                                                                       snode->nodetree = ((Scene *)snode->id)->nodetree;
-                                                               else if (GS(snode->id->name)==ID_TE)
-                                                                       snode->nodetree = ((Tex *)snode->id)->nodetree;
-                                                       }
+                                               /* remaining path entries are invalid, remove */
+                                               for (; path; path = path_next) {
+                                                       path_next = path->next;
+                                                       
+                                                       BLI_remlink(&snode->treepath, path);
+                                                       MEM_freeN(path);
                                                }
-                                               else {
-                                                       snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree);
+                                               
+                                               snode->nodetree = newlibadr(fd, sc->id.lib, snode->nodetree);
+                                               /* edittree is just the last in the path,
+                                                * set this directly since the path may have been shortened above */
+                                               if (snode->treepath.last) {
+                                                       path = snode->treepath.last;
+                                                       snode->edittree = path->nodetree;
                                                }
+                                               else
+                                                       snode->edittree = NULL;
+                                               snode->id = newlibadr(fd, sc->id.lib, snode->id);
+                                               snode->from = newlibadr(fd, sc->id.lib, snode->from);
                                        }
                                        else if (sl->spacetype == SPACE_CLIP) {
                                                SpaceClip *sclip = (SpaceClip *)sl;
@@ -5589,6 +5705,24 @@ static void lib_link_screen(FileData *fd, Main *main)
        }
 }
 
+static bool restore_pointer(ID *id, ID *newid, int user)
+{
+       if (strcmp(newid->name + 2, id->name + 2) == 0) {
+               if (newid->lib == id->lib) {
+                       if (user == 1) {
+                               if (newid->us == 0) {
+                                       newid->us++;
+                               }
+                       }
+                       else if (user == 2) {
+                               id_us_ensure_real(newid);
+                       }
+                       return true;
+               }
+       }
+       return false;
+}
+
 /**
  * Only for undo files, or to restore a screen after reading without UI...
  *
@@ -5600,30 +5734,33 @@ static void lib_link_screen(FileData *fd, Main *main)
 static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
 {
        if (id) {
-               ListBase *lb = which_libbase(mainp, GS(id->name));
-               
-               if (lb) {       // there's still risk of checking corrupt mem (freed Ids in oops)
-                       ID *idn = lb->first;
-                       char *name = id->name + 2;
-                       
-                       for (; idn; idn = idn->next) {
-                               if (idn->name[2] == name[0] && strcmp(idn->name+2, name) == 0) {
-                                       if (idn->lib == id->lib) {
-                                               if (user == 1) {
-                                                       if (idn->us == 0) {
-                                                               idn->us++;
-                                                       }
-                                               }
-                                               else if (user == 2) {
-                                                       id_us_ensure_real(idn);
-                                               }
-                                               break;
-                                       }
+               /* node trees can be stored locally in other IDs, needs special handling ... */
+               if (GS(id->name) == ID_NT) {
+                       ID *idn = NULL;
+                       
+                       FOREACH_NODETREE(mainp, ntree, owner_id) {
+                               if (restore_pointer(id, &ntree->id, user)) {
+                                       idn = &ntree->id;
+                                       break;
                                }
                        }
+                       FOREACH_NODETREE_END
                        
                        return idn;
                }
+               else {
+                       ListBase *lb = which_libbase(mainp, GS(id->name));
+                       if (lb) {       // there's still risk of checking corrupt mem (freed Ids in oops)
+                               ID *idn = lb->first;
+                               
+                               for (; idn; idn = idn->next) {
+                                       if (restore_pointer(id, idn, user))
+                                               break;
+                               }
+                               
+                               return idn;
+                       }
+               }
        }
        return NULL;
 }
@@ -5724,7 +5861,9 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                                }
 #endif
                                        }
-                                       else if (v3d->scenelock) v3d->lay = sc->scene->lay;
+                                       else if (v3d->scenelock) {
+                                               v3d->lay = sc->scene->lay;
+                                       }
                                        
                                        /* not very nice, but could help */
                                        if ((v3d->layact & v3d->lay) == 0) v3d->layact = v3d->lay;
@@ -5851,24 +5990,34 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                }
                                else if (sl->spacetype == SPACE_NODE) {
                                        SpaceNode *snode= (SpaceNode *)sl;
+                                       bNodeTreePath *path, *path_next;
                                        
-                                       snode->id = restore_pointer_by_name(newmain, snode->id, 1);
-                                       snode->edittree = NULL;
+                                       for (path=snode->treepath.first; path; path=path->next) {
+                                               path->nodetree= restore_pointer_by_name(newmain, (ID*)path->nodetree, 0);
+                                               
+                                               if (!path->nodetree)
+                                                       break;
+                                       }
                                        
-                                       if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
-                                               snode->nodetree = NULL;
-                                               if (snode->id) {
-                                                       if (GS(snode->id->name)==ID_MA)
-                                                               snode->nodetree = ((Material *)snode->id)->nodetree;
-                                                       else if (GS(snode->id->name)==ID_SCE)
-                                                               snode->nodetree = ((Scene *)snode->id)->nodetree;
-                                                       else if (GS(snode->id->name)==ID_TE)
-                                                               snode->nodetree = ((Tex *)snode->id)->nodetree;
-                                               }
+                                       /* remaining path entries are invalid, remove */
+                                       for (; path; path = path_next) {
+                                               path_next = path->next;
+                                               
+                                               BLI_remlink(&snode->treepath, path);
+                                               MEM_freeN(path);
                                        }
-                                       else {
-                                               snode->nodetree= restore_pointer_by_name(newmain, &snode->nodetree->id, 1);
+                                       
+                                       snode->nodetree = restore_pointer_by_name(newmain, (ID*)snode->nodetree, 0);
+                                       /* edittree is just the last in the path,
+                                        * set this directly since the path may have been shortened above */
+                                       if (snode->treepath.last) {
+                                               path = snode->treepath.last;
+                                               snode->edittree = path->nodetree;
                                        }
+                                       else
+                                               snode->edittree = NULL;
+                                       snode->id = restore_pointer_by_name(newmain, snode->id, 1);
+                                       snode->from = restore_pointer_by_name(newmain, snode->from, 0);
                                }
                                else if (sl->spacetype == SPACE_CLIP) {
                                        SpaceClip *sclip = (SpaceClip *)sl;
@@ -5904,7 +6053,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
                pa->activedata = NULL;
                pa->type = NULL;
        }
-
+       
        link_list(fd, &ar->ui_lists);
 
        for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
@@ -5920,6 +6069,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
                        rv3d->clipbb = newdataadr(fd, rv3d->clipbb);
                        
                        rv3d->depths = NULL;
+                       rv3d->gpuoffscreen = NULL;
                        rv3d->ri = NULL;
                        rv3d->render_engine = NULL;
                        rv3d->sms = NULL;
@@ -6085,7 +6235,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                        soops->treestore->totelem = soops->treestore->usedelem;
                                        soops->storeflag |= SO_TREESTORE_CLEANUP;       // at first draw
                                }
-                                soops->tree.first = soops->tree.last= NULL;
+                               soops->tree.first = soops->tree.last= NULL;
                        }
                        else if (sl->spacetype == SPACE_IMAGE) {
                                SpaceImage *sima = (SpaceImage *)sl;
@@ -6118,6 +6268,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                        snode->gpd = newdataadr(fd, snode->gpd);
                                        direct_link_gpencil(fd, snode->gpd);
                                }
+                               
+                               link_list(fd, &snode->treepath);
                                snode->edittree = NULL;
                                snode->linkdrag.first = snode->linkdrag.last = NULL;
                        }
@@ -6216,7 +6368,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                sclip->scopes.track_preview = NULL;
                                sclip->draw_context = NULL;
                                sclip->scopes.ok = 0;
-                       }
+               }
                }
                
                sa->actionzones.first = sa->actionzones.last = NULL;
@@ -6256,7 +6408,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
        }
        /* make sure we have full path in lib->filepath */
        BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name));
-       cleanup_path(fd->relabase, lib->filepath);
+       BLI_cleanup_path(fd->relabase, lib->filepath);
        
 //     printf("direct_link_library: name %s\n", lib->name);
 //     printf("direct_link_library: filepath %s\n", lib->filepath);
@@ -6585,59 +6737,237 @@ static void lib_link_mask(FileData *fd, Main *main)
        }
 }
 
-/* ************** GENERAL & MAIN ******************** */
-
+#ifdef WITH_FREESTYLE
+/* ************ READ LINE STYLE ***************** */
 
-static const char *dataname(short id_code)
+static void lib_link_linestyle(FileData *fd, Main *main)
 {
-       switch (id_code) {
-               case ID_OB: return "Data from OB";
-               case ID_ME: return "Data from ME";
-               case ID_IP: return "Data from IP";
-               case ID_SCE: return "Data from SCE";
-               case ID_MA: return "Data from MA";
-               case ID_TE: return "Data from TE";
-               case ID_CU: return "Data from CU";
-               case ID_GR: return "Data from GR";
-               case ID_AR: return "Data from AR";
-               case ID_AC: return "Data from AC";
-               case ID_LI: return "Data from LI";
-               case ID_MB: return "Data from MB";
-               case ID_IM: return "Data from IM";
-               case ID_LT: return "Data from LT";
-               case ID_LA: return "Data from LA";
-               case ID_CA: return "Data from CA";
-               case ID_KE: return "Data from KE";
-               case ID_WO: return "Data from WO";
-               case ID_SCR: return "Data from SCR";
-               case ID_VF: return "Data from VF";
-               case ID_TXT     : return "Data from TXT";
-               case ID_SPK: return "Data from SPK";
-               case ID_SO: return "Data from SO";
-               case ID_NT: return "Data from NT";
-               case ID_BR: return "Data from BR";
-               case ID_PA: return "Data from PA";
-               case ID_GD: return "Data from GD";
-               case ID_MC: return "Data from MC";
-       }
-       return "Data from Lib Block";
-       
-}
+       FreestyleLineStyle *linestyle;
+       LineStyleModifier *m;
 
-static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *allocname)
-{
-       bhead = blo_nextbhead(fd, bhead);
-       
-       while (bhead && bhead->code==DATA) {
-               void *data;
-#if 0
-               /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */
-               short *sp = fd->filesdna->structs[bhead->SDNAnr];
-               char *tmp = malloc(100);
-               allocname = fd->filesdna->types[ sp[0] ];
-               strcpy(tmp, allocname);
-               data = read_struct(fd, bhead, tmp);
-#else
+       linestyle = main->linestyle.first;
+       while (linestyle) {
+               if (linestyle->id.flag & LIB_NEED_LINK) {
+                       linestyle->id.flag -= LIB_NEED_LINK;
+
+                       if (linestyle->id.properties)
+                               IDP_LibLinkProperty(linestyle->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+                       if (linestyle->adt)
+                               lib_link_animdata(fd, &linestyle->id, linestyle->adt);
+                       for (m = linestyle->color_modifiers.first; m; m = m->next) {
+                               switch (m->type) {
+                               case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+                                       {
+                                               LineStyleColorModifier_DistanceFromObject *cm = (LineStyleColorModifier_DistanceFromObject *)m;
+                                               cm->target = newlibadr(fd, linestyle->id.lib, cm->target);
+                                       }
+                                       break;
+                               }
+                       }
+                       for (m = linestyle->alpha_modifiers.first; m; m = m->next){
+                               switch (m->type) {
+                               case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+                                       {
+                                               LineStyleAlphaModifier_DistanceFromObject *am = (LineStyleAlphaModifier_DistanceFromObject *)m;
+                                               am->target = newlibadr(fd, linestyle->id.lib, am->target);
+                                       }
+                                       break;
+                               }
+                       }
+                       for (m = linestyle->thickness_modifiers.first; m; m = m->next){
+                               switch (m->type) {
+                               case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+                                       {
+                                               LineStyleThicknessModifier_DistanceFromObject *tm = (LineStyleThicknessModifier_DistanceFromObject *)m;
+                                               tm->target = newlibadr(fd, linestyle->id.lib, tm->target);
+                                       }
+                                       break;
+                               }
+                       }
+               }
+               linestyle = linestyle->id.next;
+       }
+}
+
+static void direct_link_linestyle_color_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+       switch (modifier->type) {
+       case LS_MODIFIER_ALONG_STROKE:
+               {
+                       LineStyleColorModifier_AlongStroke *m = (LineStyleColorModifier_AlongStroke *)modifier;
+                       m->color_ramp = newdataadr(fd, m->color_ramp);
+               }
+               break;
+       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+               {
+                       LineStyleColorModifier_DistanceFromCamera *m = (LineStyleColorModifier_DistanceFromCamera *)modifier;
+                       m->color_ramp = newdataadr(fd, m->color_ramp);
+               }
+               break;
+       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+               {
+                       LineStyleColorModifier_DistanceFromObject *m = (LineStyleColorModifier_DistanceFromObject *)modifier;
+                       m->color_ramp = newdataadr(fd, m->color_ramp);
+               }
+               break;
+       case LS_MODIFIER_MATERIAL:
+               {
+                       LineStyleColorModifier_Material *m = (LineStyleColorModifier_Material *)modifier;
+                       m->color_ramp = newdataadr(fd, m->color_ramp);
+               }
+               break;
+       }
+}
+
+static void direct_link_linestyle_alpha_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+       switch (modifier->type) {
+       case LS_MODIFIER_ALONG_STROKE:
+               {
+                       LineStyleAlphaModifier_AlongStroke *m = (LineStyleAlphaModifier_AlongStroke *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+               {
+                       LineStyleAlphaModifier_DistanceFromCamera *m = (LineStyleAlphaModifier_DistanceFromCamera *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+               {
+                       LineStyleAlphaModifier_DistanceFromObject *m = (LineStyleAlphaModifier_DistanceFromObject *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       case LS_MODIFIER_MATERIAL:
+               {
+                       LineStyleAlphaModifier_Material *m = (LineStyleAlphaModifier_Material *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       }
+}
+
+static void direct_link_linestyle_thickness_modifier(FileData *fd, LineStyleModifier *modifier)
+{
+       switch (modifier->type) {
+       case LS_MODIFIER_ALONG_STROKE:
+               {
+                       LineStyleThicknessModifier_AlongStroke *m = (LineStyleThicknessModifier_AlongStroke *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       case LS_MODIFIER_DISTANCE_FROM_CAMERA:
+               {
+                       LineStyleThicknessModifier_DistanceFromCamera *m = (LineStyleThicknessModifier_DistanceFromCamera *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       case LS_MODIFIER_DISTANCE_FROM_OBJECT:
+               {
+                       LineStyleThicknessModifier_DistanceFromObject *m = (LineStyleThicknessModifier_DistanceFromObject *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       case LS_MODIFIER_MATERIAL:
+               {
+                       LineStyleThicknessModifier_Material *m = (LineStyleThicknessModifier_Material *)modifier;
+                       m->curve = newdataadr(fd, m->curve);
+                       direct_link_curvemapping(fd, m->curve);
+               }
+               break;
+       }
+}
+
+static void direct_link_linestyle_geometry_modifier(FileData *UNUSED(fd), LineStyleModifier *UNUSED(modifier))
+{
+}
+
+static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
+{
+       LineStyleModifier *modifier;
+
+       linestyle->adt= newdataadr(fd, linestyle->adt);
+       direct_link_animdata(fd, linestyle->adt);
+       link_list(fd, &linestyle->color_modifiers);
+       for(modifier = linestyle->color_modifiers.first; modifier; modifier = modifier->next)
+               direct_link_linestyle_color_modifier(fd, modifier);
+       link_list(fd, &linestyle->alpha_modifiers);
+       for(modifier = linestyle->alpha_modifiers.first; modifier; modifier = modifier->next)
+               direct_link_linestyle_alpha_modifier(fd, modifier);
+       link_list(fd, &linestyle->thickness_modifiers);
+       for(modifier = linestyle->thickness_modifiers.first; modifier; modifier = modifier->next)
+               direct_link_linestyle_thickness_modifier(fd, modifier);
+       link_list(fd, &linestyle->geometry_modifiers);
+       for(modifier = linestyle->geometry_modifiers.first; modifier; modifier = modifier->next)
+               direct_link_linestyle_geometry_modifier(fd, modifier);
+}
+#endif
+
+/* ************** GENERAL & MAIN ******************** */
+
+
+static const char *dataname(short id_code)
+{
+       switch (id_code) {
+               case ID_OB: return "Data from OB";
+               case ID_ME: return "Data from ME";
+               case ID_IP: return "Data from IP";
+               case ID_SCE: return "Data from SCE";
+               case ID_MA: return "Data from MA";
+               case ID_TE: return "Data from TE";
+               case ID_CU: return "Data from CU";
+               case ID_GR: return "Data from GR";
+               case ID_AR: return "Data from AR";
+               case ID_AC: return "Data from AC";
+               case ID_LI: return "Data from LI";
+               case ID_MB: return "Data from MB";
+               case ID_IM: return "Data from IM";
+               case ID_LT: return "Data from LT";
+               case ID_LA: return "Data from LA";
+               case ID_CA: return "Data from CA";
+               case ID_KE: return "Data from KE";
+               case ID_WO: return "Data from WO";
+               case ID_SCR: return "Data from SCR";
+               case ID_VF: return "Data from VF";
+               case ID_TXT     : return "Data from TXT";
+               case ID_SPK: return "Data from SPK";
+               case ID_SO: return "Data from SO";
+               case ID_NT: return "Data from NT";
+               case ID_BR: return "Data from BR";
+               case ID_PA: return "Data from PA";
+               case ID_GD: return "Data from GD";
+               case ID_MC: return "Data from MC";
+#ifdef WITH_FREESTYLE
+               case ID_LS: return "Data from LS";
+#endif
+       }
+       return "Data from Lib Block";
+       
+}
+
+static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *allocname)
+{
+       bhead = blo_nextbhead(fd, bhead);
+       
+       while (bhead && bhead->code==DATA) {
+               void *data;
+#if 0
+               /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */
+               short *sp = fd->filesdna->structs[bhead->SDNAnr];
+               char *tmp = malloc(100);
+               allocname = fd->filesdna->types[ sp[0] ];
+               strcpy(tmp, allocname);
+               data = read_struct(fd, bhead, tmp);
+#else
                data = read_struct(fd, bhead, allocname);
 #endif
                
@@ -6795,6 +7125,11 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                case ID_MSK:
                        direct_link_mask(fd, (Mask *)id);
                        break;
+#ifdef WITH_FREESTYLE
+               case ID_LS:
+                       direct_link_linestyle(fd, (FreestyleLineStyle *)id);
+                       break;
+#endif
        }
        
        oldnewmap_free_unused(fd->datamap);
@@ -6857,7 +7192,6 @@ static void link_global(FileData *fd, BlendFileData *bfd)
        }
 }
 
-/* deprecated, only keep this for readfile.c */
 void convert_tface_mt(FileData *fd, Main *main)
 {
        Main *gmain;
@@ -6892,22 +7226,6 @@ static void do_versions_nodetree_image_default_alpha_output(bNodeTree *ntree)
        }
 }
 
-static void do_version_ntree_tex_mapping_260(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (node->type == SH_NODE_MAPPING) {
-                       TexMapping *tex_mapping;
-                       
-                       tex_mapping= node->storage;
-                       tex_mapping->projx= PROJ_X;
-                       tex_mapping->projy= PROJ_Y;
-                       tex_mapping->projz= PROJ_Z;
-               }
-       }
-}
-
 static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
 {
        bNode *node;
@@ -6927,7 +7245,7 @@ static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
                        /* Convert degrees to radians. */
                        NodeDefocus *nqd = node->storage;
                        /* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
-                       nqd->rotation = DEG2RADF(nqd->rotation * 255.0f);
+                       nqd->rotation = DEG2RADF(nqd->rotation*255.0f);
                }
                else if (node->type == CMP_NODE_CHROMA_MATTE) {
                        /* Convert degrees to radians. */
@@ -6939,7 +7257,7 @@ static void do_versions_nodetree_convert_angle(bNodeTree *ntree)
                        /* Convert degrees to radians. */
                        NodeGlare *ndg = node->storage;
                        /* XXX DNA char to float conversion seems to map the char value into the [0.0f, 1.0f] range... */
-                       ndg->angle_ofs = DEG2RADF(ndg->angle_ofs * 255.0f);
+                       ndg->angle_ofs = DEG2RADF(ndg->angle_ofs*255.0f);
                }
                /* XXX TexMapping struct is used by other nodes too (at least node_composite_mapValue),
                 *     but not the rot part...
@@ -7129,7 +7447,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
                                nimf->format = sce->r.im_format;
                        
                        /* transfer render format toggle to node format toggle */
-                       for (sock=node->inputs.first; sock; sock=sock->next) {
+                       for (sock = node->inputs.first; sock; sock = sock->next) {
                                NodeImageMultiFileSocket *simf = sock->storage;
                                simf->use_node_format = simf->use_render_format;
                        }
@@ -7183,7 +7501,7 @@ static void do_versions_nodetree_file_output_layers_2_64_5(bNodeTree *ntree)
        for (node=ntree->nodes.first; node; node=node->next) {
                if (node->type == CMP_NODE_OUTPUT_FILE) {
                        bNodeSocket *sock;
-                       for (sock=node->inputs.first; sock; sock=sock->next) {
+                       for (sock = node->inputs.first; sock; sock = sock->next) {
                                NodeImageMultiFileSocket *input = sock->storage;
                                
                                /* multilayer names are stored as separate strings now,
@@ -7242,134 +7560,6 @@ static void do_versions_nodetree_frame_2_64_6(bNodeTree *ntree)
        }
 }
 
-static void do_version_ntree_image_user_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
-                       NodeTexImage *tex = node->storage;
-
-                       tex->iuser.frames= 1;
-                       tex->iuser.sfra= 1;
-                       tex->iuser.fie_ima= 2;
-                       tex->iuser.ok= 1;
-               }
-       }
-}
-
-static void do_version_ntree_dilateerode_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (node->type == CMP_NODE_DILATEERODE) {
-                       if (node->storage == NULL) {
-                               NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
-                               data->falloff = PROP_SMOOTH;
-                               node->storage = data;
-                       }
-               }
-       }
-}
-
-static void do_version_ntree_defocus_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (node->type == CMP_NODE_DEFOCUS) {
-                       NodeDefocus *data = node->storage;
-                       if (data->maxblur == 0.0f) {
-                               data->maxblur = 16.0f;
-                       }
-               }
-       }
-}
-
-static void do_version_ntree_mask_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (node->type == CMP_NODE_MASK) {
-                       if (node->storage == NULL) {
-                               NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
-                               /* move settings into own struct */
-                               data->size_x = (int)node->custom3;
-                               data->size_y = (int)node->custom4;
-                               node->custom3 = 0.5f; /* default shutter */
-                               node->storage = data;
-                       }
-               }
-       }
-}
-
-static void do_version_ntree_keying_despill_balance(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (node->type == CMP_NODE_KEYING) {
-                       NodeKeyingData *data = node->storage;
-
-                       if (data->despill_balance == 0.0f) {
-                               data->despill_balance = 0.5f;
-                       }
-               }
-       }
-}
-
-static void do_version_ntree_tex_coord_from_dupli_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next)
-               if (node->type == SH_NODE_TEX_COORD)
-                       node->flag |= NODE_OPTIONS;
-}
-
-static void do_version_node_cleanup_dynamic_sockets_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-       bNodeSocket *sock;
-       
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (!ELEM(node->type, NODE_GROUP, CMP_NODE_IMAGE)) {
-                       for (sock = node->inputs.first; sock; sock = sock->next)
-                               sock->flag &= ~SOCK_DYNAMIC;
-                       for (sock = node->outputs.first; sock; sock = sock->next)
-                               sock->flag &= ~SOCK_DYNAMIC;
-               }
-       }
-}
-
-static void do_version_node_fix_translate_wrapping(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-
-       for (node = ntree->nodes.first; node; node = node->next) {
-               if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) {
-                       node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
-               }
-       }
-}
-
-static void do_version_node_fix_internal_links_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
-{
-       bNode *node;
-       bNodeLink *link, *nextlink;
-       
-       for (node = ntree->nodes.first; node; node = node->next) {
-               for (link = node->internal_links.first; link; link = nextlink) {
-                       nextlink = link->next;
-                       if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
-                               BLI_remlink(&node->internal_links, link);
-                       }
-               }
-       }
-}
-       
 static void do_version_logic_264(ListBase *regionbase)
 {
        ARegion *ar;
@@ -7422,6 +7612,160 @@ static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
 }
 
 
+static const char *node_get_static_idname(int type, int treetype)
+{
+       /* use static type info header to map static int type to identifier string */
+       #define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \
+               case ID: return #Category #StructName;
+       
+       /* XXX hack, group types share a single static integer identifier, but are registered as separate types */
+       if (type == NODE_GROUP) {
+               switch (treetype) {
+               case NTREE_COMPOSIT: return "CompositorNodeGroup";
+               case NTREE_SHADER: return "ShaderNodeGroup";
+               case NTREE_TEXTURE: return "TextureNodeGroup";
+               }
+       }
+       else {
+               switch (type) {
+               #include "NOD_static_types.h"
+               }
+       }
+       return "";
+}
+
+static const char *node_socket_get_static_idname(bNodeSocket *sock)
+{
+       switch (sock->type) {
+       case SOCK_FLOAT: {
+               bNodeSocketValueFloat *dval = sock->default_value;
+               return nodeStaticSocketType(SOCK_FLOAT, dval->subtype);
+       }
+       case SOCK_INT: {
+               bNodeSocketValueInt *dval = sock->default_value;
+               return nodeStaticSocketType(SOCK_INT, dval->subtype);
+       }
+       case SOCK_BOOLEAN: {
+               return nodeStaticSocketType(SOCK_BOOLEAN, PROP_NONE);
+       }
+       case SOCK_VECTOR: {
+               bNodeSocketValueVector *dval = sock->default_value;
+               return nodeStaticSocketType(SOCK_VECTOR, dval->subtype);
+       }
+       case SOCK_RGBA: {
+               return nodeStaticSocketType(SOCK_RGBA, PROP_NONE);
+       }
+       case SOCK_STRING: {
+               bNodeSocketValueString *dval = sock->default_value;
+               return nodeStaticSocketType(SOCK_STRING, dval->subtype);
+       }
+       case SOCK_SHADER: {
+               return nodeStaticSocketType(SOCK_SHADER, PROP_NONE);
+       }
+       }
+       return "";
+}
+
+static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_group))
+{
+       /* initialize node tree type idname */
+       {
+               bNode *node;
+               bNodeSocket *sock;
+               
+               ntree->typeinfo = NULL;
+               
+               /* tree type idname */
+               switch (ntree->type) {
+               case NTREE_COMPOSIT:
+                       strcpy(ntree->idname, "CompositorNodeTree");
+                       break;
+               case NTREE_SHADER:
+                       strcpy(ntree->idname, "ShaderNodeTree");
+                       break;
+               case NTREE_TEXTURE:
+                       strcpy(ntree->idname, "TextureNodeTree");
+                       break;
+               }
+               
+               /* node type idname */
+               for (node=ntree->nodes.first; node; node=node->next) {
+                       BLI_strncpy(node->idname, node_get_static_idname(node->type, ntree->type), sizeof(node->idname));
+                       
+                       /* existing old nodes have been initialized already */
+                       node->flag |= NODE_INIT;
+                       
+                       /* sockets idname */
+                       for (sock = node->inputs.first; sock; sock = sock->next)
+                               BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+                       for (sock = node->outputs.first; sock; sock = sock->next)
+                               BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+               }
+               /* tree sockets idname */
+               for (sock = ntree->inputs.first; sock; sock = sock->next)
+                       BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+               for (sock = ntree->outputs.first; sock; sock = sock->next)
+                       BLI_strncpy(sock->idname, node_socket_get_static_idname(sock), sizeof(sock->idname));
+       }
+       
+       /* initialize socket in_out values */
+       {
+               bNode *node;
+               bNodeSocket *sock;
+               
+               for (node=ntree->nodes.first; node; node=node->next) {
+                       for (sock = node->inputs.first; sock; sock = sock->next)
+                               sock->in_out = SOCK_IN;
+                       for (sock = node->outputs.first; sock; sock = sock->next)
+                               sock->in_out = SOCK_OUT;
+               }
+               for (sock = ntree->inputs.first; sock; sock = sock->next)
+                       sock->in_out = SOCK_IN;
+               for (sock = ntree->outputs.first; sock; sock = sock->next)
+                       sock->in_out = SOCK_OUT;
+       }
+       
+       /* initialize socket identifier strings */
+       {
+               bNode *node;
+               bNodeSocket *sock;
+               
+               for (node=ntree->nodes.first; node; node=node->next) {
+                       for (sock = node->inputs.first; sock; sock = sock->next) {
+                               BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+                               BLI_uniquename(&node->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+                       }
+                       for (sock = node->outputs.first; sock; sock = sock->next) {
+                               BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+                               BLI_uniquename(&node->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+                       }
+               }
+               for (sock = ntree->inputs.first; sock; sock = sock->next) {
+                       BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+                       BLI_uniquename(&ntree->inputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+               }
+               for (sock = ntree->outputs.first; sock; sock = sock->next) {
+                       BLI_strncpy(sock->identifier, sock->name, sizeof(sock->identifier));
+                       BLI_uniquename(&ntree->outputs, sock, sock->identifier, '.', offsetof(bNodeSocket, identifier), sizeof(sock->identifier));
+               }
+       }
+}
+
+/* initialize userdef with non-UI dependency stuff */
+/* other initializers (such as theme color defaults) go to resources.c */
+static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
+{
+       Main *bmain = bfd->main;
+       UserDef *user = bfd->user;
+       
+       if (user == NULL) return;
+       
+       if (bmain->versionfile < 267) {
+       
+               if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
+                       user->image_gpubuffer_limit = 10;
+       }
+}
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -7487,10 +7831,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
        
        if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 2)) {
-               bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-               
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_mapping_260);
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_SHADER) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == SH_NODE_MAPPING) {
+                                               TexMapping *tex_mapping;
+                                               
+                                               tex_mapping= node->storage;
+                                               tex_mapping->projx= PROJ_X;
+                                               tex_mapping->projy= PROJ_Y;
+                                               tex_mapping->projz= PROJ_Z;
+                                       }
+                               }
+                       }
+               } FOREACH_NODETREE_END
        }
 
        if (main->versionfile < 260 || (main->versionfile == 260 && main->subversionfile < 4)) {
@@ -7745,7 +8100,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                        prop = BKE_bproperty_object_get(ob, "Text");
                                        if (prop) {
                                                BKE_reportf_wrap(fd->reports, RPT_WARNING,
-                                                                TIP_("Game property name conflict in object '%s':\ntext objects reserve the "
+                                                                TIP_("Game property name conflict in object '%s': text objects reserve the "
                                                                      "['Text'] game property to change their content through logic bricks"),
                                                                 ob->id.name + 2);
                                        }
@@ -8126,16 +8481,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
 
        if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 9)) {
-               bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-               
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_ntree_image_user_264);
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_SHADER) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) {
+                                               NodeTexImage *tex = node->storage;
+                                               
+                                               tex->iuser.frames= 1;
+                                               tex->iuser.sfra= 1;
+                                               tex->iuser.fie_ima= 2;
+                                               tex->iuser.ok= 1;
+                                       }
+                               }
+                       }
+               } FOREACH_NODETREE_END
        }
 
        if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 10)) {
                {
                        Scene *scene;
-                       bNodeTreeType *ntreetype;
                        // composite redesign
                        for (scene=main->scene.first; scene; scene=scene->id.next) {
                                if (scene->nodetree) {
@@ -8144,11 +8509,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                        }
                                }
                        }
-                       ntreetype = ntreeGetType(NTREE_COMPOSIT);
-       
-                       if (ntreetype && ntreetype->foreach_nodetree)
-                               ntreetype->foreach_nodetree(main, NULL, do_version_ntree_defocus_264);
                        
+                       FOREACH_NODETREE(main, ntree, id) {
+                               if (ntree->type == NTREE_COMPOSIT) {
+                                       bNode *node;
+                                       for (node = ntree->nodes.first; node; node = node->next) {
+                                               if (node->type == CMP_NODE_DEFOCUS) {
+                                                       NodeDefocus *data = node->storage;
+                                                       if (data->maxblur == 0.0f) {
+                                                               data->maxblur = 16.0f;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } FOREACH_NODETREE_END
                }
 
                {
@@ -8206,19 +8580,40 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
 
        if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 13)) {
-               bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_ntree_dilateerode_264);
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == CMP_NODE_DILATEERODE) {
+                                               if (node->storage == NULL) {
+                                                       NodeDilateErode *data = MEM_callocN(sizeof(NodeDilateErode), __func__);
+                                                       data->falloff = PROP_SMOOTH;
+                                                       node->storage = data;
+                                               }
+                                       }
+                               }
+                       }
+               } FOREACH_NODETREE_END
        }
 
        if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 14)) {
                ParticleSettings *part;
-               bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_ntree_keying_despill_balance);
-
+               
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == CMP_NODE_KEYING) {
+                                               NodeKeyingData *data = node->storage;
+                                               
+                                               if (data->despill_balance == 0.0f) {
+                                                       data->despill_balance = 0.5f;
+                                               }
+                                       }
+                               }
+                       }
+               } FOREACH_NODETREE_END
+               
                /* keep compatibility for dupliobject particle size */
                for (part=main->particle.first; part; part=part->id.next)
                        if (ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))
@@ -8227,12 +8622,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
 
        if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 17)) {
-               bNodeTreeType *ntreetype = ntreeGetType(NTREE_COMPOSIT);
-
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_ntree_mask_264);
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == CMP_NODE_MASK) {
+                                               if (node->storage == NULL) {
+                                                       NodeMask *data = MEM_callocN(sizeof(NodeMask), __func__);
+                                                       /* move settings into own struct */
+                                                       data->size_x = (int)node->custom3;
+                                                       data->size_y = (int)node->custom4;
+                                                       node->custom3 = 0.5f; /* default shutter */
+                                                       node->storage = data;
+                                               }
+                                       }
+                               }
+                       }
+               } FOREACH_NODETREE_END
        }
-
+       
        if (main->versionfile < 263 || (main->versionfile == 263 && main->subversionfile < 18)) {
                Scene *scene;
 
@@ -8357,15 +8765,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
 
        if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) {
-               bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
-               bNodeTree *ntree;
-
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_coord_from_dupli_264);
-               
-               for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
-                       if (ntree->type==NTREE_SHADER)
-                               do_version_ntree_tex_coord_from_dupli_264(NULL, NULL, ntree);
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_SHADER) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next)
+                                       if (node->type == SH_NODE_TEX_COORD)
+                                               node->flag |= NODE_OPTIONS;
+                       }
+               } FOREACH_NODETREE_END
        }
 
        if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 2)) {
@@ -8451,28 +8858,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 4)) {
-               /* Fix for old node flags: Apparently the SOCK_DYNAMIC flag has been in use for other
-                * purposes before and then removed and later reused for SOCK_DYNAMIC. This socket should
-                * only be used by certain node types which don't use template lists, cleaning this up here.
-                */
-               bNodeTreeType *ntreetype;
-               bNodeTree *ntree;
-               
-               ntreetype = ntreeGetType(NTREE_COMPOSIT);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
-               ntreetype = ntreeGetType(NTREE_SHADER);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
-               ntreetype = ntreeGetType(NTREE_TEXTURE);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_node_cleanup_dynamic_sockets_264);
-               
-               for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
-                       do_version_node_cleanup_dynamic_sockets_264(NULL, NULL, ntree);
-       }
-
        if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 5)) {
                /* set a unwrapping margin and ABF by default */
                Scene *scene;
@@ -8489,22 +8874,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                /* Fix for bug #32982, internal_links list could get corrupted from r51630 onward.
                 * Simply remove bad internal_links lists to avoid NULL pointers.
                 */
-               bNodeTreeType *ntreetype;
-               bNodeTree *ntree;
-               
-               ntreetype = ntreeGetType(NTREE_COMPOSIT);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
-               ntreetype = ntreeGetType(NTREE_SHADER);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
-               ntreetype = ntreeGetType(NTREE_TEXTURE);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_internal_links_264);
-               
-               for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
-                       do_version_node_fix_internal_links_264(NULL, NULL, ntree);
-               
+               FOREACH_NODETREE(main, ntree, id)
+                       bNode *node;
+                       bNodeLink *link, *nextlink;
+                       
+                       for (node = ntree->nodes.first; node; node = node->next) {
+                               for (link = node->internal_links.first; link; link = nextlink) {
+                                       nextlink = link->next;
+                                       if (!link->fromnode || !link->fromsock || !link->tonode || !link->tosock) {
+                                               BLI_remlink(&node->internal_links, link);
+                                       }
+                               }
+                       }
+               FOREACH_NODETREE_END
        }
        
        if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
@@ -8646,8 +9028,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
        if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) {
                Scene *scene;
-               Image *image, *nimage;
-               Tex *tex, *otex;
+               Image *image;
+               Tex *tex;
 
                for (scene = main->scene.first; scene; scene = scene->id.next) {
                        Sequence *seq;
@@ -8665,7 +9047,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        SEQ_END
 
                        if (scene->r.bake_samples == 0)
-                       scene->r.bake_samples = 256;
+                               scene->r.bake_samples = 256;
 
                        if (scene->world) {
                                World *world = blo_do_versions_newlibadr(fd, scene->id.lib, scene->world);
@@ -8692,63 +9074,41 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        else {
                                BKE_image_alpha_mode_from_extension(image);
                        }
-
-                       image->flag &= ~IMA_DONE_TAG;
                }
 
-               /* use alpha flag moved from texture to image datablock */
                for (tex = main->tex.first; tex; tex = tex->id.next) {
                        if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) {
                                image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima);
 
-                               /* skip if no image or already tested */
-                               if (!image || (image->flag & (IMA_DONE_TAG|IMA_IGNORE_ALPHA)))
-                                       continue;
-
-                               image->flag |= IMA_DONE_TAG;
+                               if (image && (image->flag & IMA_DO_PREMUL) == 0)
+                                       image->flag |= IMA_IGNORE_ALPHA;
+                       }
+               }
 
-                               /* we might have some textures using alpha and others not, so we check if
-                                * they exist and duplicate the image datablock if necessary */
-                               for (otex = main->tex.first; otex; otex = otex->id.next)
-                                       if (otex->type == TEX_IMAGE && (otex->imaflag & TEX_USEALPHA))
-                                               if (image == blo_do_versions_newlibadr(fd, otex->id.lib, otex->ima))
-                                                       break;
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == CMP_NODE_IMAGE) {
+                                               Image *image = blo_do_versions_newlibadr(fd, ntree->id.lib, node->id);
 
-                               if (otex) {
-                                       /* copy image datablock */
-                                       nimage = BKE_image_copy(main, image);
-                                       nimage->flag |= IMA_IGNORE_ALPHA|IMA_DONE_TAG;
-                                       nimage->id.us--;
-
-                                       /* we need to do some trickery to make file loading think
-                                        * this new datablock is part of file we're loading */
-                                       blo_do_versions_oldnewmap_insert(fd->libmap, nimage, nimage, 0);
-                                       nimage->id.lib = image->id.lib;
-                                       nimage->id.flag |= (image->id.flag & LIB_NEED_LINK);
-
-                                       /* assign new image, and update the users counts accordingly */
-                                       for (otex = main->tex.first; otex; otex = otex->id.next) {
-                                               if (otex->type == TEX_IMAGE && (otex->imaflag & TEX_USEALPHA) == 0) {
-                                                       if (image == blo_do_versions_newlibadr(fd, otex->id.lib, otex->ima)) {
-                                                               if (!(otex->id.flag & LIB_NEED_LINK)) {
-                                                                       image->id.us--;
-                                                                       nimage->id.us++;
-                                                               }
-                                                               otex->ima = nimage;
-                                                               break;
-                                                       }
+                                               if (image) {
+                                                       if ((image->flag & IMA_DO_PREMUL) == 0 && image->alpha_mode == IMA_ALPHA_STRAIGHT)
+                                                               node->custom1 |= CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT;
                                                }
                                        }
                                }
-                               else {
-                                       /* no other textures using alpha, just set the flag */
-                                       image->flag |= IMA_IGNORE_ALPHA;
-                               }
                        }
-               }
+               } FOREACH_NODETREE_END
+       }
+       else if (main->versionfile < 266 || (main->versionfile == 266 && main->subversionfile < 1)) {
+               /* texture use alpha was removed for 2.66 but added back again for 2.66a,
+                * for compatibility all textures assumed it to be enabled */
+               Tex *tex;
 
-               for (image = main->image.first; image; image = image->id.next)
-                       image->flag &= ~IMA_DONE_TAG;
+               for (tex = main->tex.first; tex; tex = tex->id.next)
+                       if (tex->type == TEX_IMAGE)
+                               tex->imaflag |= TEX_USEALPHA;
        }
 
        if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
@@ -8786,14 +9146,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       if (!MAIN_VERSION_ATLEAST(main, 265, 8)) {
+       if (MAIN_VERSION_OLDER(main, 265, 9)) {
                Mesh *me;
                for (me = main->mesh.first; me; me = me->id.next) {
                        BKE_mesh_do_versions_cd_flag_init(me);
                }
        }
 
-       if (!MAIN_VERSION_ATLEAST(main, 265, 9)) {
+       if (MAIN_VERSION_OLDER(main, 265, 10)) {
                Brush *br;
                for (br = main->brush.first; br; br = br->id.next) {
                        if (br->ob_mode & OB_MODE_TEXTURE_PAINT) {
@@ -8803,22 +9163,191 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
 
        // add storage for compositor translate nodes when not existing
-       if (!MAIN_VERSION_ATLEAST(main, 265, 10)) {
-               bNodeTreeType *ntreetype;
+       if (MAIN_VERSION_OLDER(main, 265, 11)) {
+               FOREACH_NODETREE(main, ntree, id) {
+                       if (ntree->type == NTREE_COMPOSIT) {
+                               bNode *node;
+                               for (node = ntree->nodes.first; node; node = node->next) {
+                                       if (node->type == CMP_NODE_TRANSLATE && node->storage == NULL) {
+                                               node->storage = MEM_callocN(sizeof(NodeTranslateData), "node translate data");
+                                       }
+                               }
+                       }
+               } FOREACH_NODETREE_END
+       }
+
+       if (!MAIN_VERSION_ATLEAST(main, 266, 2)) {
+               FOREACH_NODETREE(main, ntree, id) {
+                       do_versions_nodetree_customnodes(ntree, ((ID *)ntree == id));
+               } FOREACH_NODETREE_END
+       }
+
+       if (!MAIN_VERSION_ATLEAST(main, 266, 2)) {
+               bScreen *sc;
+               for (sc= main->screen.first; sc; sc= sc->id.next) {
+                       ScrArea *sa;
+                       for (sa= sc->areabase.first; sa; sa= sa->next) {
+                               SpaceLink *sl;
+                               for (sl= sa->spacedata.first; sl; sl= sl->next) {
+                                       if (sl->spacetype==SPACE_NODE) {
+                                               SpaceNode *snode = (SpaceNode *)sl;
+                                               
+                                               /* reset pointers to force tree path update from context */
+                                               snode->nodetree = NULL;
+                                               snode->edittree = NULL;
+                                               snode->id = NULL;
+                                               snode->from = NULL;
+                                               
+                                               /* convert deprecated treetype setting to tree_idname */
+                                               switch (snode->treetype) {
+                                                       case NTREE_COMPOSIT:
+                                                               strcpy(snode->tree_idname, "CompositorNodeTree");
+                                                               break;
+                                                       case NTREE_SHADER:
+                                                               strcpy(snode->tree_idname, "ShaderNodeTree");
+                                                               break;
+                                                       case NTREE_TEXTURE:
+                                                               strcpy(snode->tree_idname, "TextureNodeTree");
+                                                               break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /* Set flag for delayed do_versions in lib_verify_nodetree. It needs valid typeinfo pointers ... */
+       {
                bNodeTree *ntree;
+               for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+                       /* XXX This should be kept without version check for now!
+                        * As long as USE_NODE_COMPAT_CUSTOMNODES is active, files will write links
+                        * to tree interface sockets for forward compatibility. These links need to be removed again
+                        * on file load in new versions.
+                        * Once forward compatibility is not required any longer, make a subversion bump
+                        * and only execute this for older versions.
+                        */
+                       ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP;
+                       
+                       /* Only add interface nodes once.
+                        * In old Blender versions they will be removed automatically due to undefined type */
+                       if (!MAIN_VERSION_ATLEAST(main, 266, 2))
+                               ntree->flag |= NTREE_DO_VERSIONS_CUSTOMNODES_GROUP_CREATE_INTERFACE;
+               }
+       }
 
-               ntreetype = ntreeGetType(NTREE_COMPOSIT);
-               if (ntreetype && ntreetype->foreach_nodetree)
-                       ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_translate_wrapping);
+       if (main->versionfile < 267) {
+               
+               /* TIP: to initialize new variables added, use the new function
+                  DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname")
+                  example: 
+                               if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
+                                       user->image_gpubuffer_limit = 10;
+                */
+               
+       }
+       
+#ifdef WITH_FREESTYLE
+       /* default values in Freestyle settings */
+       {
+               Scene *sce;
+               SceneRenderLayer *srl;
+               FreestyleLineStyle *linestyle;
 
-               for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next)
-                       do_version_node_fix_translate_wrapping(NULL, NULL, ntree);
+               for(sce = main->scene.first; sce; sce = sce->id.next) {
+                       if (sce->r.line_thickness_mode == 0) {
+                               sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE;
+                               sce->r.unit_line_thickness = 1.0f;
+                       }
+                       for(srl = sce->r.layers.first; srl; srl = srl->next) {
+                               if (srl->freestyleConfig.mode == 0)
+                                       srl->freestyleConfig.mode = FREESTYLE_CONTROL_EDITOR_MODE;
+                               if (srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE ||
+                                   srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_TRADITIONAL) {
+                                       srl->freestyleConfig.raycasting_algorithm = 0; /* deprecated */
+                                       srl->freestyleConfig.flags |= FREESTYLE_CULLING;
+                               }
+                       }
+               }
+               for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
+#if 1
+                       /* disable the Misc panel for now */
+                       if (linestyle->panel == LS_PANEL_MISC) {
+                               linestyle->panel = LS_PANEL_STROKES;
+                       }
+#endif
+                       if (linestyle->thickness_position == 0) {
+                               linestyle->thickness_position = LS_THICKNESS_CENTER;
+                               linestyle->thickness_ratio = 0.5f;
+                       }
+                       if (linestyle->chaining == 0)
+                               linestyle->chaining = LS_CHAINING_PLAIN;
+                       if (linestyle->rounds == 0)
+                               linestyle->rounds = 3;
+               }
        }
+       /* The code segment below will be removed when the trunk merger is done.
+          For now it is kept for backward compatibility, giving branch users time
+          to migrate to the new CustomData-based edge/face marks. */
+       {
+               Mesh *me;
+               MEdge *medge;
+               MPoly *mpoly;
+               int i, found;
 
-       // if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
+               for (me = main->mesh.first; me; me = me->id.next) {
+                       /* Freestyle edge marks */
+                       found = 0;
+                       medge = me->medge;
+                       for (i = 0; i < me->totedge; i++) {
+                               if (medge->flag & ME_FREESTYLE_EDGE) {
+                                       found = 1;
+                                       break;
+                               }
+                               medge++;
+                       }
+                       if (found) {
+                               FreestyleEdge *fed = CustomData_add_layer(&me->edata, CD_FREESTYLE_EDGE, CD_CALLOC, NULL, me->totedge);
+                               medge = me->medge;
+                               for (i = 0; i < me->totedge; i++) {
+                                       if (medge->flag & ME_FREESTYLE_EDGE) {
+                                               medge->flag &= ~ME_FREESTYLE_EDGE;
+                                               fed->flag |= FREESTYLE_EDGE_MARK;
+                                       }
+                                       medge++;
+                                       fed++;
+                               }
+                               printf("Migrated to CustomData-based Freestyle edge marks\n");
+                       }
+                       /* Freestyle face marks */
+                       found = 0;
+                       mpoly = me->mpoly;
+                       for (i = 0; i < me->totpoly; i++) {
+                               if (mpoly->flag & ME_FREESTYLE_FACE) {
+                                       found = 1;
+                                       break;
+                               }
+                               mpoly++;
+                       }
+                       if (found) {
+                               FreestyleFace *ffa = CustomData_add_layer(&me->pdata, CD_FREESTYLE_FACE, CD_CALLOC, NULL, me->totpoly);
+                               mpoly = me->mpoly;
+                               for (i = 0; i < me->totpoly; i++) {
+                                       if (mpoly->flag & ME_FREESTYLE_FACE) {
+                                               mpoly->flag &= ~ME_FREESTYLE_FACE;
+                                               ffa->flag |= FREESTYLE_FACE_MARK;
+                                       }
+                                       mpoly++;
+                                       ffa++;
+                               }
+                               printf("Migrated to CustomData-based Freestyle face marks\n");
+                       }
+               }
+       }
+#endif
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
-       /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
+       /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
 
        /* don't forget to set version number in blender.c! */
 }
@@ -8838,8 +9367,8 @@ static void lib_link_all(FileData *fd, Main *main)
        
        /* No load UI for undo memfiles */
        if (fd->memfile == NULL) {
-               lib_link_windowmanager(fd, main);
-               lib_link_screen(fd, main);
+       lib_link_windowmanager(fd, main);
+       lib_link_screen(fd, main);
        }
        lib_link_scene(fd, main);
        lib_link_object(fd, main);
@@ -8866,6 +9395,9 @@ static void lib_link_all(FileData *fd, Main *main)
        lib_link_particlesettings(fd, main);
        lib_link_movieclip(fd, main);
        lib_link_mask(fd, main);
+#ifdef WITH_FREESTYLE
+       lib_link_linestyle(fd, main);
+#endif
 
        lib_link_mesh(fd, main);                /* as last: tpage images with users at zero */
        
@@ -8929,7 +9461,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
                for (kmi=keymap->items.first; kmi; kmi=kmi->next)
                        direct_link_keymapitem(fd, kmi);
        }
-
+       
        for (addon = user->addons.first; addon; addon = addon->next) {
                addon->prop = newdataadr(fd, addon->prop);
                if (addon->prop) {
@@ -9015,9 +9547,11 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
        }
        
        /* do before read_libraries, but skip undo case */
-//     if (fd->memfile==NULL) (the mesh shuffle hacks don't work yet? ton)
+       if (fd->memfile==NULL)
                do_versions(fd, NULL, bfd->main);
        
+       do_versions_userdef(fd, bfd);
+       
        read_libraries(fd, &mainlist);
        
        blo_join_main(&mainlist);
@@ -9149,7 +9683,7 @@ static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
                                        return;
                                }
                                else
-                                       id = is_yet_read(fd, ptr, bhead);
+                               id = is_yet_read(fd, ptr, bhead);
                                
                                if (id == NULL) {
                                        read_libblock(fd, ptr, bhead, LIB_READ+LIB_INDIRECT, NULL);
@@ -9826,6 +10360,18 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
        for (srl = sce->r.layers.first; srl; srl = srl->next) {
                expand_doit(fd, mainvar, srl->mat_override);
                expand_doit(fd, mainvar, srl->light_override);
+
+#ifdef WITH_FREESTYLE
+               {
+                       FreestyleLineSet *lineset;
+
+                       for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+                               if (lineset->group)
+                                       expand_doit(fd, mainvar, lineset->group);
+                               expand_doit(fd, mainvar, lineset->linestyle);
+                       }
+               }
+#endif
        }
        
        if (sce->r.dometext)
@@ -9924,6 +10470,28 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask)
        }
 }
 
+#ifdef WITH_FREESTYLE
+static void expand_linestyle(FileData *fd, Main *mainvar, FreestyleLineStyle *linestyle)
+{
+       LineStyleModifier *m;
+
+       if (linestyle->adt)
+               expand_animdata(fd, mainvar, linestyle->adt);
+       for (m = linestyle->color_modifiers.first; m; m = m->next) {
+               if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+                       expand_doit(fd, mainvar, ((LineStyleColorModifier_DistanceFromObject *)m)->target);
+       }
+       for (m = linestyle->alpha_modifiers.first; m; m = m->next){
+               if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+                       expand_doit(fd, mainvar, ((LineStyleAlphaModifier_DistanceFromObject *)m)->target);
+       }
+       for (m = linestyle->thickness_modifiers.first; m; m = m->next){
+               if (m->type == LS_MODIFIER_DISTANCE_FROM_OBJECT)
+                       expand_doit(fd, mainvar, ((LineStyleThicknessModifier_DistanceFromObject *)m)->target);
+       }
+}
+#endif
+
 void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
 {
        expand_doit = expand_doit_func;
@@ -10014,6 +10582,11 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
                                        case ID_MSK:
                                                expand_mask(fd, mainvar, (Mask *)id);
                                                break;
+#ifdef WITH_FREESTYLE
+                                       case ID_LS:
+                                               expand_linestyle(fd, mainvar, (FreestyleLineStyle *)id);
+                                               break;
+#endif
                                        }
                                        
                                        do_it = TRUE;
@@ -10108,7 +10681,7 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
                        Base *base;
                        
                        /* BKE_object_add(...) messes with the selection */
-                       Object *ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name+2);
+                       Object *ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2);
                        ob->type = OB_EMPTY;
                        ob->lay = scene->lay;
                        
@@ -10122,7 +10695,7 @@ static void give_base_to_groups(Main *mainvar, Scene *scene)
                        /* assign the group */
                        ob->dup_group = group;
                        ob->transflag |= OB_DUPLIGROUP;
-                       rename_id(&ob->id, group->id.name+2);
+                       rename_id(&ob->id, group->id.name + 2);
                        copy_v3_v3(ob->loc, scene->cursor);
                }
        }
@@ -10155,7 +10728,8 @@ static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, cons
                                }
                                else {
                                        /* already linked */
-                                       printf("append: already linked\n");
+                                       if (G.debug)
+                                               printf("append: already linked\n");
                                        oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);
                                        if (id->flag & LIB_INDIRECT) {
                                                id->flag -= LIB_INDIRECT;
@@ -10426,7 +11000,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                PackedFile *pf = mainptr->curlib->packedfile;
                                                
                                                BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library:  '%s'"),
-                                                                                mainptr->curlib->name);
+                                                                mainptr->curlib->name);
                                                fd = blo_openblendermemory(pf->data, pf->size, basefd->reports);
                                                
                                                
@@ -10435,7 +11009,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                        }
                                        else {
                                                BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library:  '%s', '%s'"),
-                                                                                mainptr->curlib->filepath, mainptr->curlib->name);
+                                                                mainptr->curlib->filepath, mainptr->curlib->name);
                                                fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
                                        }
                                        /* allow typing in a new lib path */
@@ -10451,7 +11025,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                        if (scanf("%s", newlib_path) > 0) {
                                                                BLI_strncpy(mainptr->curlib->name, newlib_path, sizeof(mainptr->curlib->name));
                                                                BLI_strncpy(mainptr->curlib->filepath, newlib_path, sizeof(mainptr->curlib->filepath));
-                                                               cleanup_path(G.main->name, mainptr->curlib->filepath);
+                                                               BLI_cleanup_path(G.main->name, mainptr->curlib->filepath);
                                                                
                                                                fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
 
@@ -10483,7 +11057,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                /* subversion */
                                                read_file_version(fd, mainptr);
                                        }
-                                       else mainptr->curlib->filedata = NULL;
+                                       else {
+                                               mainptr->curlib->filedata = NULL;
+                                       }
                                        
                                        if (fd == NULL) {
                                                BKE_reportf_wrap(basefd->reports, RPT_WARNING, TIP_("Cannot find lib '%s'"),
@@ -10507,7 +11083,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                                        BKE_reportf_wrap(fd->reports, RPT_WARNING,
                                                                                         TIP_("LIB ERROR: %s: '%s' missing from '%s'"),
                                                                                         BKE_idcode_to_name(GS(id->name)),
-                                                                                        id->name+2, mainptr->curlib->filepath);
+                                                                                        id->name + 2, mainptr->curlib->filepath);
                                                                }
                                                                
                                                                change_idid_adr(mainlist, basefd, id, realid);