Merging r58475 through r58700 from trunk into soc-2013-depsgraph_mt
[blender.git] / source / blender / blenloader / intern / readfile.c
index 3e963f376406f92be406705d303ebbc29876c68e..e71b3c644599f66c1f4a7e0f736b7e4f9162c713 100644 (file)
@@ -71,6 +71,7 @@
 #include "DNA_key_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_lamp_types.h"
+#include "DNA_linestyle_types.h"
 #include "DNA_meta_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_edgehash.h"
+#include "BLI_threads.h"
 
 #include "BLF_translation.h"
 
@@ -1314,6 +1316,8 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
                        oldnewmap_insert(fd->imamap, ibuf, ibuf, 0);
                if (ima->gputexture)
                        oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0);
+               if (ima->rr)
+                       oldnewmap_insert(fd->imamap, ima->rr, ima->rr, 0);
                for (a=0; a < IMA_MAX_RENDER_SLOT; a++)
                        if (ima->renders[a])
                                oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0);
@@ -1355,12 +1359,14 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
                                ima->bindcode = 0;
                                ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
                                ima->gputexture = NULL;
+                               ima->rr = NULL;
                        }
                }
                for (i = 0; i < IMA_MAX_RENDER_SLOT; i++)
                        ima->renders[i] = newimaadr(fd, ima->renders[i]);
                
                ima->gputexture = newimaadr(fd, ima->gputexture);
+               ima->rr = newimaadr(fd, ima->rr);
        }
        for (; sce; sce = sce->id.next) {
                if (sce->nodetree && sce->nodetree->previews) {
@@ -2360,6 +2366,21 @@ static void lib_link_nodetree(FileData *fd, Main *main)
        }
 }
 
+/* get node tree stored locally in other IDs */
+static bNodeTree *nodetree_from_id(ID *id)
+{
+       if (!id)
+               return NULL;
+       switch (GS(id->name)) {
+               case ID_SCE: return ((Scene *)id)->nodetree;
+               case ID_MA: return ((Material *)id)->nodetree;
+               case ID_WO: return ((World *)id)->nodetree;
+               case ID_LA: return ((Lamp *)id)->nodetree;
+               case ID_TE: return ((Tex *)id)->nodetree;
+       }
+       return NULL;
+}
+
 /* updates group node socket identifier so that
  * external links to/from the group node are preserved.
  */
@@ -2505,9 +2526,11 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
                                                        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;
+                                                       if (link->tonode) {
+                                                               if (input_locx > link->tonode->locx - offsetx)
+                                                                       input_locx = link->tonode->locx - offsetx;
+                                                               input_locy += link->tonode->locy;
+                                                       }
                                                }
                                                else
                                                        free_link = TRUE;
@@ -2519,9 +2542,11 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
                                                        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;
+                                                       if (link->fromnode) {
+                                                               if (output_locx < link->fromnode->locx + offsetx)
+                                                                       output_locx = link->fromnode->locx + offsetx;
+                                                               output_locy += link->fromnode->locy;
+                                                       }
                                                }
                                                else
                                                        free_link = TRUE;
@@ -2558,8 +2583,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
        {
                FOREACH_NODETREE(main, ntree, id) {
                        /* make an update call for the tree */
-                       if (ntree->update)
-                               ntreeUpdateTree(ntree);
+                       ntreeUpdateTree(main, ntree);
                } FOREACH_NODETREE_END
        }
 }
@@ -2943,8 +2967,10 @@ static void lib_link_lamp(FileData *fd, Main *main)
                        
                        la->ipo = newlibadr_us(fd, la->id.lib, la->ipo); // XXX deprecated - old animation system
                        
-                       if (la->nodetree)
+                       if (la->nodetree) {
                                lib_link_ntree(fd, &la->id, la->nodetree);
+                               la->nodetree->id.lib = la->id.lib;
+                       }
                        
                        la->id.flag -= LIB_NEED_LINK;
                }
@@ -3089,7 +3115,6 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
        
        mb->disp.first = mb->disp.last = NULL;
        mb->editelems = NULL;
-       mb->bb = NULL;
 /*     mb->edit_elems.first= mb->edit_elems.last= NULL;*/
        mb->lastelem = NULL;
 }
@@ -3116,8 +3141,10 @@ static void lib_link_world(FileData *fd, Main *main)
                                }
                        }
                        
-                       if (wrld->nodetree)
+                       if (wrld->nodetree) {
                                lib_link_ntree(fd, &wrld->id, wrld->nodetree);
+                               wrld->nodetree->id.lib = wrld->id.lib;
+                       }
                        
                        wrld->id.flag -= LIB_NEED_LINK;
                }
@@ -3263,10 +3290,10 @@ static void direct_link_image(FileData *fd, Image *ima)
                ima->bindcode = 0;
                ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
                ima->gputexture = NULL;
+               ima->rr = NULL;
        }
        
        ima->anim = NULL;
-       ima->rr = NULL;
        ima->repbind = NULL;
        
        /* undo system, try to restore render buffers */
@@ -3363,11 +3390,8 @@ static void direct_link_curve(FileData *fd, Curve *cu)
                if (cu->wordspace == 0.0f) cu->wordspace = 1.0f;
        }
 
-       cu->bev.first = cu->bev.last = NULL;
-       cu->disp.first = cu->disp.last = NULL;
        cu->editnurb = NULL;
        cu->lastsel = NULL;
-       cu->path = NULL;
        cu->editfont = NULL;
        
        for (nu = cu->nurb.first; nu; nu = nu->next) {
@@ -3405,8 +3429,10 @@ static void lib_link_texture(FileData *fd, Main *main)
                        if (tex->ot)
                                tex->ot->object = newlibadr(fd, tex->id.lib, tex->ot->object);
                        
-                       if (tex->nodetree)
+                       if (tex->nodetree) {
                                lib_link_ntree(fd, &tex->id, tex->nodetree);
+                               tex->nodetree->id.lib = tex->id.lib;
+                       }
                        
                        tex->id.flag -= LIB_NEED_LINK;
                }
@@ -3487,8 +3513,10 @@ static void lib_link_material(FileData *fd, Main *main)
                                }
                        }
                        
-                       if (ma->nodetree)
+                       if (ma->nodetree) {
                                lib_link_ntree(fd, &ma->id, ma->nodetree);
+                               ma->nodetree->id.lib = ma->id.lib;
+                       }
                        
                        ma->id.flag -= LIB_NEED_LINK;
                }
@@ -4116,6 +4144,11 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
        mesh->bb = NULL;
        mesh->edit_btmesh = NULL;
        
+       /* happens with old files */
+       if (mesh->mselect == NULL) {
+               mesh->totselect = 0;
+       }
+
        /* Multires data */
        mesh->mr= newdataadr(fd, mesh->mr);
        if (mesh->mr) {
@@ -4576,6 +4609,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                                smd->domain->smd = smd;
                                
                                smd->domain->fluid = NULL;
+                               smd->domain->fluid_mutex = BLI_rw_mutex_alloc();
                                smd->domain->wt = NULL;
                                smd->domain->shadow = NULL;
                                smd->domain->tex = NULL;
@@ -4783,8 +4817,6 @@ static void direct_link_object(FileData *fd, Object *ob)
                ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
        }
        
-       ob->disp.first = ob->disp.last = NULL;
-       
        ob->adt = newdataadr(fd, ob->adt);
        direct_link_animdata(fd, ob->adt);
        
@@ -4979,6 +5011,9 @@ static void direct_link_object(FileData *fd, Object *ob)
        ob->gpulamp.first= ob->gpulamp.last = NULL;
        link_list(fd, &ob->pc_ids);
 
+       /* Runtime curve data  */
+       ob->curve_cache = NULL;
+
        /* in case this value changes in future, clamp else we get undefined behavior */
        CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
 
@@ -5025,6 +5060,8 @@ static void lib_link_scene(FileData *fd, Main *main)
        Sequence *seq;
        SceneRenderLayer *srl;
        TimeMarker *marker;
+       FreestyleModuleConfig *fmc;
+       FreestyleLineSet *fls;
        
        for (sce = main->scene.first; sce; sce = sce->id.next) {
                if (sce->id.flag & LIB_NEED_LINK) {
@@ -5133,12 +5170,20 @@ static void lib_link_scene(FileData *fd, Main *main)
                        
                        if (sce->nodetree) {
                                lib_link_ntree(fd, &sce->id, sce->nodetree);
+                               sce->nodetree->id.lib = sce->id.lib;
                                composite_patch(sce->nodetree, sce);
                        }
                        
                        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);
+                               for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+                                       fmc->script = newlibadr(fd, sce->id.lib, fmc->script);
+                               }
+                               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);
+                               }
                        }
                        /*Game Settings: Dome Warp Text*/
                        sce->gm.dome.warptext = newlibadr(fd, sce->id.lib, sce->gm.dome.warptext);
@@ -5208,6 +5253,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        Sequence *seq;
        MetaStack *ms;
        RigidBodyWorld *rbw;
+       SceneRenderLayer *srl;
        
        sce->theDag = NULL;
        sce->obedit = NULL;
@@ -5385,6 +5431,13 @@ 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));
+
+       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));
+       }
        
        sce->nodetree = newdataadr(fd, sce->nodetree);
        if (sce->nodetree) {
@@ -5463,6 +5516,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
        wm->winactive = NULL;
        wm->initialized = 0;
        wm->op_undo_depth = 0;
+       wm->is_interface_locked = 0;
 }
 
 static void lib_link_windowmanager(FileData *fd, Main *main)
@@ -5643,9 +5697,26 @@ static void lib_link_screen(FileData *fd, Main *main)
                                        else if (sl->spacetype == SPACE_NODE) {
                                                SpaceNode *snode = (SpaceNode *)sl;
                                                bNodeTreePath *path, *path_next;
+                                               bNodeTree *ntree;
+                                               
+                                               /* node tree can be stored locally in id too, link this first */
+                                               snode->id = newlibadr(fd, sc->id.lib, snode->id);
+                                               snode->from = newlibadr(fd, sc->id.lib, snode->from);
                                                
-                                               for (path=snode->treepath.first; path; path=path->next) {
-                                                       path->nodetree = newlibadr(fd, sc->id.lib, path->nodetree);
+                                               ntree = nodetree_from_id(snode->id);
+                                               if (ntree)
+                                                       snode->nodetree = ntree;
+                                               else {
+                                                       snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree);
+                                               }
+                                               
+                                               for (path = snode->treepath.first; path; path = path->next) {
+                                                       if (path == snode->treepath.first) {
+                                                               /* first nodetree in path is same as snode->nodetree */
+                                                               path->nodetree = snode->nodetree;
+                                                       }
+                                                       else
+                                                               path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree);
                                                        
                                                        if (!path->nodetree)
                                                                break;
@@ -5659,7 +5730,6 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                        MEM_freeN(path);
                                                }
                                                
-                                               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) {
@@ -5668,8 +5738,6 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                }
                                                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;
@@ -5718,52 +5786,38 @@ static bool restore_pointer(ID *id, ID *newid, int user)
 static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
 {
        if (id) {
-               /* node trees can be stored locally in other IDs, needs special handling ... */
-               if (GS(id->name) == ID_NT) {
-                       ID *idn = NULL;
+               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;
                        
-                       FOREACH_NODETREE(mainp, ntree, owner_id) {
-                               if (restore_pointer(id, &ntree->id, user)) {
-                                       idn = &ntree->id;
+                       for (; idn; idn = idn->next) {
+                               if (restore_pointer(id, idn, user))
                                        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;
 }
 
+static void lib_link_seq_clipboard_pt_restore(ID *id, Main *newmain)
+{
+       if (id) {
+               /* clipboard must ensure this */
+               BLI_assert(id->newid != NULL);
+               id->newid = restore_pointer_by_name(newmain, (ID *)id->newid, 1);
+       }
+}
 static int lib_link_seq_clipboard_cb(Sequence *seq, void *arg_pt)
 {
        Main *newmain = (Main *)arg_pt;
-       
-       if (seq->sound) {
-               seq->sound = restore_pointer_by_name(newmain, (ID *)seq->sound, 0);
-               seq->sound->id.us++;
-       }
-       
-       if (seq->scene)
-               seq->scene = restore_pointer_by_name(newmain, (ID *)seq->scene, 1);
-       
-       if (seq->scene_camera)
-               seq->scene_camera = restore_pointer_by_name(newmain, (ID *)seq->scene_camera, 1);
-       
+
+       lib_link_seq_clipboard_pt_restore((ID *)seq->scene, newmain);
+       lib_link_seq_clipboard_pt_restore((ID *)seq->scene_camera, newmain);
+       lib_link_seq_clipboard_pt_restore((ID *)seq->clip, newmain);
+       lib_link_seq_clipboard_pt_restore((ID *)seq->mask, newmain);
+       lib_link_seq_clipboard_pt_restore((ID *)seq->sound, newmain);
        return 1;
 }
 
@@ -5975,9 +6029,25 @@ 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;
+                                       bNodeTree *ntree;
                                        
-                                       for (path=snode->treepath.first; path; path=path->next) {
-                                               path->nodetree= restore_pointer_by_name(newmain, (ID*)path->nodetree, 0);
+                                       /* node tree can be stored locally in id too, link this first */
+                                       snode->id = restore_pointer_by_name(newmain, snode->id, 1);
+                                       snode->from = restore_pointer_by_name(newmain, snode->from, 0);
+                                       
+                                       ntree = nodetree_from_id(snode->id);
+                                       if (ntree)
+                                               snode->nodetree = ntree;
+                                       else
+                                               snode->nodetree = restore_pointer_by_name(newmain, (ID*)snode->nodetree, 0);
+                                       
+                                       for (path = snode->treepath.first; path; path = path->next) {
+                                               if (path == snode->treepath.first) {
+                                                       /* first nodetree in path is same as snode->nodetree */
+                                                       path->nodetree = snode->nodetree;
+                                               }
+                                               else
+                                                       path->nodetree= restore_pointer_by_name(newmain, (ID*)path->nodetree, 2);
                                                
                                                if (!path->nodetree)
                                                        break;
@@ -5991,7 +6061,6 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                                MEM_freeN(path);
                                        }
                                        
-                                       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) {
@@ -6000,8 +6069,6 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                        }
                                        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;
@@ -6100,11 +6167,12 @@ void blo_do_versions_view3d_split_250(View3D *v3d, ListBase *regions)
                v3d->twtype = V3D_MANIP_TRANSLATE;
 }
 
-static void direct_link_screen(FileData *fd, bScreen *sc)
+static bool direct_link_screen(FileData *fd, bScreen *sc)
 {
        ScrArea *sa;
        ScrVert *sv;
        ScrEdge *se;
+       bool wrong_id = false;
        
        link_list(fd, &(sc->vertbase));
        link_list(fd, &(sc->edgebase));
@@ -6126,8 +6194,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                }
                
                if (se->v1 == NULL) {
-                       printf("error reading screen... file corrupt\n");
-                       se->v1 = se->v2;
+                       printf("Error reading Screen %s... removing it.\n", sc->id.name+2);
+                       BLI_remlink(&sc->edgebase, se);
+                       wrong_id = true;
                }
        }
        
@@ -6192,9 +6261,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                v3d->properties_storage = NULL;
                                v3d->defmaterial = NULL;
                                
-                               /* render can be quite heavy, set to wire on load */
+                               /* render can be quite heavy, set to solid on load */
                                if (v3d->drawtype == OB_RENDER)
-                                       v3d->drawtype = OB_WIRE;
+                                       v3d->drawtype = OB_SOLID;
                                
                                blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
                        }
@@ -6361,6 +6430,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                sa->v3 = newdataadr(fd, sa->v3);
                sa->v4 = newdataadr(fd, sa->v4);
        }
+       
+       return wrong_id;
 }
 
 /* ********** READ LIBRARY *************** */
@@ -6581,7 +6652,6 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip)
        clip->tracking.stats = NULL;
 
        clip->tracking.stabilization.ok = 0;
-       clip->tracking.stabilization.scaleibuf = NULL;
        clip->tracking.stabilization.rot_track = newdataadr(fd, clip->tracking.stabilization.rot_track);
 
        clip->tracking.dopesheet.ok = 0;
@@ -6720,6 +6790,179 @@ static void lib_link_mask(FileData *fd, Main *main)
        }
 }
 
+/* ************ READ LINE STYLE ***************** */
+
+static void lib_link_linestyle(FileData *fd, Main *main)
+{
+       FreestyleLineStyle *linestyle;
+       LineStyleModifier *m;
+
+       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);
+}
+
 /* ************** GENERAL & MAIN ******************** */
 
 
@@ -6754,6 +6997,7 @@ static const char *dataname(short id_code)
                case ID_PA: return "Data from PA";
                case ID_GD: return "Data from GD";
                case ID_MC: return "Data from MC";
+               case ID_LS: return "Data from LS";
        }
        return "Data from Lib Block";
        
@@ -6794,6 +7038,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
        ID *id;
        ListBase *lb;
        const char *allocname;
+       bool wrong_id = false;
        
        /* read libblock */
        id = read_struct(fd, bhead, "lib block");
@@ -6841,7 +7086,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                        direct_link_windowmanager(fd, (wmWindowManager *)id);
                        break;
                case ID_SCR:
-                       direct_link_screen(fd, (bScreen *)id);
+                       wrong_id = direct_link_screen(fd, (bScreen *)id);
                        break;
                case ID_SCE:
                        direct_link_scene(fd, (Scene *)id);
@@ -6930,11 +7175,18 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                case ID_MSK:
                        direct_link_mask(fd, (Mask *)id);
                        break;
+               case ID_LS:
+                       direct_link_linestyle(fd, (FreestyleLineStyle *)id);
+                       break;
        }
        
        oldnewmap_free_unused(fd->datamap);
        oldnewmap_clear(fd->datamap);
        
+       if (wrong_id) {
+               BKE_libblock_free(lb, id);
+       }
+       
        return (bhead);
 }
 
@@ -7170,7 +7422,6 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
                        bNodeSocket *old_image = BLI_findlink(&node->inputs, 0);
                        bNodeSocket *old_z = BLI_findlink(&node->inputs, 1);
                        bNodeSocket *sock;
-                       char basepath[FILE_MAXDIR];
                        char filename[FILE_MAXFILE];
                        
                        /* ugly, need to remove the old inputs list to avoid bad pointer checks when adding new sockets.
@@ -7182,6 +7433,8 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
                        
                        /* looks like storage data can be messed up somehow, stupid check here */
                        if (old_data) {
+                               char basepath[FILE_MAXDIR];
+
                                /* split off filename from the old path, to be used as socket sub-path */
                                BLI_split_dirfile(old_data->name, basepath, filename, sizeof(basepath), sizeof(filename));
                                
@@ -7189,7 +7442,6 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
                                nimf->format = old_data->im_format;
                        }
                        else {
-                               basepath[0] = '\0';
                                BLI_strncpy(filename, old_image->name, sizeof(filename));
                        }
                        
@@ -7437,31 +7689,38 @@ static const char *node_get_static_idname(int type, int treetype)
 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);
-       }
+               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 "";
 }
@@ -7533,27 +7792,27 @@ static void do_versions_nodetree_customnodes(bNodeTree *ntree, int UNUSED(is_gro
                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));
+                               BLI_uniquename(&node->inputs, sock, "socket", '.', 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));
+                               BLI_uniquename(&node->outputs, sock, "socket", '.', 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));
+                       BLI_uniquename(&ntree->inputs, sock, "socket", '.', 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));
+                       BLI_uniquename(&ntree->outputs, sock, "socket", '.', 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)
+static void do_versions_userdef(FileData *UNUSED(fd), BlendFileData *bfd)
 {
        Main *bmain = bfd->main;
        UserDef *user = bfd->user;
@@ -7569,14 +7828,8 @@ static void do_versions_userdef(FileData *fd, BlendFileData *bfd)
                        copy_v4_v4_char(btheme->tseq.grid, btheme->tseq.back);
                }
        }
-       
-       if (bmain->versionfile < 267) {
-       
-               if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit"))
-                       user->image_gpubuffer_limit = 20;
-               
-       }
 }
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -9071,11 +9324,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Brush *brush;
                for (brush = main->brush.first; brush; brush = brush->id.next) {
                        default_mtex(&brush->mask_mtex);
+
+                       if (brush->ob_mode & OB_MODE_TEXTURE_PAINT) {
+                               brush->spacing /= 2;
+                       }
                }
        }
 
+       if (!MAIN_VERSION_ATLEAST(main, 266, 6)) {
+               Brush *brush;
+               #define BRUSH_TEXTURE_OVERLAY (1 << 21)
+
+               for (brush = main->brush.first; brush; brush = brush->id.next) {
+                       brush->overlay_flags = 0;
+                       if (brush->flag & BRUSH_TEXTURE_OVERLAY)
+                               brush->overlay_flags |= (BRUSH_OVERLAY_PRIMARY | BRUSH_OVERLAY_CURSOR);
+               }
+               #undef BRUSH_TEXTURE_OVERLAY
+       }
+
        if (main->versionfile < 267) {
-               //if(!DNA_struct_elem_find(fd->filesdna, "Brush", "int", "stencil_pos")) {
+               //if (!DNA_struct_elem_find(fd->filesdna, "Brush", "int", "stencil_pos")) {
                Brush *brush;
 
                for (brush = main->brush.first; brush; brush = brush->id.next) {
@@ -9085,17 +9354,185 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                brush->stencil_pos[0] = 256;
                                brush->stencil_pos[1] = 256;
                        }
+                       if (brush->mask_stencil_dimension[0] == 0) {
+                               brush->mask_stencil_dimension[0] = 256;
+                               brush->mask_stencil_dimension[1] = 256;
+                               brush->mask_stencil_pos[0] = 256;
+                               brush->mask_stencil_pos[1] = 256;
+                       }
                }
 
                /* 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;
+                * 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;
                 */
                
        }
        
+       /* default values in Freestyle settings */
+       if (main->versionfile < 267) {
+               Scene *sce;
+               SceneRenderLayer *srl;
+               FreestyleLineStyle *linestyle;
+
+               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;
+                               }
+                       }
+
+                       /* not freestyle */
+                       {
+                               MeshStatVis *statvis = &sce->toolsettings->statvis;
+                               if (statvis->thickness_samples == 0) {
+                                       statvis->overhang_axis = OB_NEGZ;
+                                       statvis->overhang_min = 0;
+                                       statvis->overhang_max = DEG2RADF(45.0f);
+
+                                       statvis->thickness_max = 0.1f;
+                                       statvis->thickness_samples = 1;
+
+                                       statvis->distort_min = DEG2RADF(5.0f);
+                                       statvis->distort_max = DEG2RADF(45.0f);
+
+                                       statvis->sharp_min = DEG2RADF(90.0f);
+                                       statvis->sharp_max = DEG2RADF(180.0f);
+                               }
+                       }
+
+               }
+               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;
+               }
+       }
+
+       if (main->versionfile < 267) {
+               /* Initialize the active_viewer_key for compositing */
+               bScreen *screen;
+               Scene *scene;
+               bNodeInstanceKey active_viewer_key = {0};
+               /* simply pick the first node space and use that for the active viewer key */
+               for (screen = main->screen.first; screen; screen = screen->id.next) {
+                       ScrArea *sa;
+                       for (sa = screen->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;
+                                               bNodeTreePath *path = snode->treepath.last;
+                                               if (!path)
+                                                       continue;
+                                               
+                                               active_viewer_key = path->parent_key;
+                                               break;
+                                       }
+                               }
+                               if (active_viewer_key.value != 0)
+                                       break;
+                       }
+                       if (active_viewer_key.value != 0)
+                               break;
+               }
+               
+               for (scene = main->scene.first; scene; scene = scene->id.next) {
+                       /* NB: scene->nodetree is a local ID block, has been direct_link'ed */
+                       if (scene->nodetree)
+                               scene->nodetree->active_viewer_key = active_viewer_key;
+               }
+       }
+
+       if (MAIN_VERSION_OLDER(main, 267, 1))
+       {
+               Object *ob;
+
+               for (ob = main->object.first; ob; ob = ob->id.next) {
+                       ModifierData *md;
+                       for (md = ob->modifiers.first; md; md = md->next) {
+                               if (md->type == eModifierType_Smoke) {
+                                       SmokeModifierData *smd = (SmokeModifierData *)md;
+                                       if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
+                                               if (smd->domain->flags & MOD_SMOKE_HIGH_SMOOTH) {
+                                                       smd->domain->highres_sampling = SM_HRES_LINEAR;
+                                               }
+                                               else {
+                                                       smd->domain->highres_sampling = SM_HRES_NEAREST;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (!MAIN_VERSION_ATLEAST(main, 268, 1)) {
+               Brush *brush;
+               for (brush = main->brush.first; brush; brush = brush->id.next) {
+                       brush->spacing = MAX2(1, brush->spacing);
+               }
+       }
+       
+       {
+               bScreen *sc;
+               Object *ob;
+
+               for (ob = main->object.first; ob; ob = ob->id.next) {
+                       ModifierData *md;
+                       for (md = ob->modifiers.first; md; md = md->next) {
+                               if (md->type == eModifierType_Smoke) {
+                                       SmokeModifierData *smd = (SmokeModifierData *)md;
+                                       if ((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow) {
+                                               if (!smd->flow->particle_size) {
+                                                       smd->flow->particle_size = 1.0f;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               /*
+                * FIX some files have a zoom level of 0, and was checked during the drawing of the node space
+                *
+                * We moved this check to the do versions to be sure the value makes any sense.
+                */
+               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;
+                                               if (snode->zoom < 0.02f) {
+                                                       snode->zoom = 1.0;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */
 
@@ -9145,6 +9582,7 @@ static void lib_link_all(FileData *fd, Main *main)
        lib_link_particlesettings(fd, main);
        lib_link_movieclip(fd, main);
        lib_link_mask(fd, main);
+       lib_link_linestyle(fd, main);
 
        lib_link_mesh(fd, main);                /* as last: tpage images with users at zero */
        
@@ -9186,6 +9624,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
        link_list(fd, &user->themes);
        link_list(fd, &user->user_keymaps);
        link_list(fd, &user->addons);
+       link_list(fd, &user->autoexec_paths);
        
        for (keymap=user->user_keymaps.first; keymap; keymap=keymap->next) {
                keymap->modal_items= NULL;
@@ -10087,6 +10526,8 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
 {
        Base *base;
        SceneRenderLayer *srl;
+       FreestyleModuleConfig *module;
+       FreestyleLineSet *lineset;
        
        for (base = sce->base.first; base; base = base->next) {
                expand_doit(fd, mainvar, base->object);
@@ -10107,6 +10548,15 @@ 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);
+               for (module = srl->freestyleConfig.modules.first; module; module = module->next) {
+                       if (module->script)
+                               expand_doit(fd, mainvar, module->script);
+               }
+               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);
+               }
        }
        
        if (sce->r.dometext)
@@ -10205,6 +10655,26 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask)
        }
 }
 
+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);
+       }
+}
+
 void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
 {
        expand_doit = expand_doit_func;
@@ -10295,6 +10765,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
                                        case ID_MSK:
                                                expand_mask(fd, mainvar, (Mask *)id);
                                                break;
+                                       case ID_LS:
+                                               expand_linestyle(fd, mainvar, (FreestyleLineStyle *)id);
+                                               break;
                                        }
                                        
                                        do_it = TRUE;