Corrections to alpha pipeline do_versions
[blender.git] / source / blender / blenloader / intern / readfile.c
index b6096ea..93bc050 100644 (file)
@@ -81,6 +81,7 @@
 #include "DNA_packedFile_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_property_types.h"
+#include "DNA_rigidbody_types.h"
 #include "DNA_text_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_screen_types.h"
  * - initialize FileGlobal and copy pointers to Global
  */
 
-/* also occurs in library.c */
-/* GS reads the memory pointed at in a specific ordering. There are,
- * however two definitions for it. I have jotted them down here, both,
- * but I think the first one is actually used. The thing is that
- * big-endian systems might read this the wrong way round. OTOH, we
- * constructed the IDs that are read out with this macro explicitly as
- * well. I expect we'll sort it out soon... */
-
-/* from blendef: */
-#define GS(a)  (*((short *)(a)))
-
-/* from misc_util: flip the bytes from x  */
-/*  #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */
-
 /***/
 
 typedef struct OldNew {
@@ -360,36 +347,39 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr)
 }
 
 /* for libdata, nr has ID code, no increment */
-static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) 
+static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
 {
-       int i;
-       
-       if (addr == NULL) return NULL;
-       
+       if (addr == NULL) {
+               return NULL;
+       }
+
        /* lasthit works fine for non-libdata, linking there is done in same sequence as writing */
        if (onm->sorted) {
                OldNew entry_s, *entry;
-               
+
                entry_s.old = addr;
-               
+
                entry = bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap);
                if (entry) {
                        ID *id = entry->newp;
-                       
+
                        if (id && (!lib || id->lib)) {
-                               return entry->newp;
+                               return id;
                        }
                }
        }
-       
-       for (i = 0; i < onm->nentries; i++) {
-               OldNew *entry = &onm->entries[i];
-               
-               if (entry->old == addr) {
-                       ID *id = entry->newp;
-                       
-                       if (id && (!lib || id->lib)) {
-                               return entry->newp;
+       else {
+               /* note, this can be a bottle neck when loading some files */
+               unsigned int nentries = (unsigned int)onm->nentries;
+               unsigned int i;
+               OldNew *entry;
+
+               for (i = 0, entry = onm->entries; i < nentries; i++, entry++) {
+                       if (entry->old == addr) {
+                               ID *id = id = entry->newp;
+                               if (id && (!lib || id->lib)) {
+                                       return id;
+                               }
                        }
                }
        }
@@ -540,7 +530,9 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
        
        BLI_strncpy(name1, filepath, sizeof(name1));
        cleanup_path(relabase, name1);
-//     printf("blo_find_main: original in  %s\n", name);
+       
+//     printf("blo_find_main: relabase  %s\n", relabase);
+//     printf("blo_find_main: original in  %s\n", filepath);
 //     printf("blo_find_main: converted to %s\n", name1);
        
        for (m = mainlist->first; m; m = m->next) {
@@ -1002,7 +994,7 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
        
        if (gzfile == (gzFile)Z_NULL) {
                BKE_reportf(reports, RPT_WARNING, "Unable to open '%s': %s",
-                           filepath, errno ? strerror(errno) : TIP_("Unknown error reading file"));
+                           filepath, errno ? strerror(errno) : TIP_("unknown error reading file"));
                return NULL;
        }
        else {
@@ -1017,6 +1009,46 @@ FileData *blo_openblenderfile(const char *filepath, ReportList *reports)
        }
 }
 
+static int fd_read_gzip_from_memory(FileData *filedata, void *buffer, unsigned int size)
+{
+       int err;
+
+       filedata->strm.next_out = (Bytef *) buffer;
+       filedata->strm.avail_out = size;
+
+       // Inflate another chunk.
+       err = inflate (&filedata->strm, Z_SYNC_FLUSH);
+
+       if (err == Z_STREAM_END) {
+               return 0;
+       }
+       else if (err != Z_OK)  {
+               printf("fd_read_gzip_from_memory: zlib error\n");
+               return 0;
+       }
+
+       filedata->seek += size;
+
+       return (size);
+}
+
+static int fd_read_gzip_from_memory_init(FileData *fd)
+{
+
+       fd->strm.next_in = (Bytef *) fd->buffer;
+       fd->strm.avail_in = fd->buffersize;
+       fd->strm.total_out = 0;
+       fd->strm.zalloc = Z_NULL;
+       fd->strm.zfree = Z_NULL;
+       
+       if (inflateInit2(&fd->strm, (16+MAX_WBITS)) != Z_OK)
+               return 0;
+
+       fd->read = fd_read_gzip_from_memory;
+       
+       return 1;
+}
+
 FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
 {
        if (!mem || memsize<SIZEOFBLENDERHEADER) {
@@ -1025,11 +1057,23 @@ FileData *blo_openblendermemory(void *mem, int memsize, ReportList *reports)
        }
        else {
                FileData *fd = filedata_new();
+               char *cp = mem;
+               
                fd->buffer = mem;
                fd->buffersize = memsize;
-               fd->read = fd_read_from_memory;
-               fd->flags |= FD_FLAGS_NOT_MY_BUFFER;
                
+               /* test if gzip */
+               if (cp[0] == 0x1f && cp[1] == 0x8b) {
+                       if (0 == fd_read_gzip_from_memory_init(fd)) {
+                               blo_freefiledata(fd);
+                               return NULL;
+                       }
+               }
+               else
+                       fd->read = fd_read_from_memory;
+                       
+               fd->flags |= FD_FLAGS_NOT_MY_BUFFER;
+
                return blo_decode_and_check(fd, reports);
        }
 }
@@ -1063,6 +1107,12 @@ void blo_freefiledata(FileData *fd)
                        gzclose(fd->gzfiledes);
                }
                
+               if (fd->strm.next_in) {
+                       if (inflateEnd (&fd->strm) != Z_OK) {
+                               printf("close gzip stream error\n");
+                       }
+               }
+               
                if (fd->buffer && !(fd->flags & FD_FLAGS_NOT_MY_BUFFER)) {
                        MEM_freeN(fd->buffer);
                        fd->buffer = NULL;
@@ -1086,6 +1136,8 @@ void blo_freefiledata(FileData *fd)
                        oldnewmap_free(fd->imamap);
                if (fd->movieclipmap)
                        oldnewmap_free(fd->movieclipmap);
+               if (fd->packedmap)
+                       oldnewmap_free(fd->packedmap);
                if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
                        oldnewmap_free(fd->libmap);
                if (fd->bheadmap)
@@ -1151,25 +1203,33 @@ 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);
        return NULL;
 }
 
+static void *newpackedadr(FileData *fd, void *adr)      /* used to restore packed data after undo */
+{
+       if (fd->packedmap && adr)
+               return oldnewmap_lookup_and_inc(fd->packedmap, adr);
+       
+       return oldnewmap_lookup_and_inc(fd->datamap, adr);
+}
+
 
 static void *newlibadr(FileData *fd, void *lib, void *adr)             /* only lib data */
 {
@@ -1293,6 +1353,7 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
                        if (NULL == newimaadr(fd, ibuf)) {      /* so was restored */
                                BLI_remlink(&ima->ibufs, ibuf);
                                ima->bindcode = 0;
+                               ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
                                ima->gputexture = NULL;
                        }
                }
@@ -1365,6 +1426,71 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
        }
 }
 
+/* XXX disabled this feature - packed files also belong in temp saves and quit.blend, to make restore work */
+
+static void insert_packedmap(FileData *fd, PackedFile *pf)
+{
+       oldnewmap_insert(fd->packedmap, pf, pf, 0);
+       oldnewmap_insert(fd->packedmap, pf->data, pf->data, 0);
+}
+
+void blo_make_packed_pointer_map(FileData *fd, Main *oldmain)
+{
+       Image *ima;
+       VFont *vfont;
+       bSound *sound;
+       Library *lib;
+       
+       fd->packedmap = oldnewmap_new();
+       
+       for (ima = oldmain->image.first; ima; ima = ima->id.next)
+               if (ima->packedfile)
+                       insert_packedmap(fd, ima->packedfile);
+                       
+       for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
+               if (vfont->packedfile)
+                       insert_packedmap(fd, vfont->packedfile);
+       
+       for (sound = oldmain->sound.first; sound; sound = sound->id.next)
+               if (sound->packedfile)
+                       insert_packedmap(fd, sound->packedfile);
+       
+       for (lib = oldmain->library.first; lib; lib = lib->id.next)
+               if (lib->packedfile)
+                       insert_packedmap(fd, lib->packedfile);
+
+}
+
+/* set old main packed data to zero if it has been restored */
+/* this works because freeing old main only happens after this call */
+void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
+{
+       Image *ima;
+       VFont *vfont;
+       bSound *sound;
+       Library *lib;
+       OldNew *entry = fd->packedmap->entries;
+       int i;
+       
+       /* used entries were restored, so we put them to zero */
+       for (i=0; i < fd->packedmap->nentries; i++, entry++) {
+               if (entry->nr > 0)
+                       entry->newp = NULL;
+       }
+       
+       for (ima = oldmain->image.first; ima; ima = ima->id.next)
+               ima->packedfile = newpackedadr(fd, ima->packedfile);
+       
+       for (vfont = oldmain->vfont.first; vfont; vfont = vfont->id.next)
+               vfont->packedfile = newpackedadr(fd, vfont->packedfile);
+
+       for (sound = oldmain->sound.first; sound; sound = sound->id.next)
+               sound->packedfile = newpackedadr(fd, sound->packedfile);
+               
+       for (lib = oldmain->library.first; lib; lib = lib->id.next)
+               lib->packedfile = newpackedadr(fd, lib->packedfile);
+}
+
 
 /* undo file support: add all library pointers in lookup */
 void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd)
@@ -1631,6 +1757,19 @@ static void IDP_LibLinkProperty(IDProperty *UNUSED(prop), int UNUSED(switch_endi
 {
 }
 
+/* ************ READ ID *************** */
+
+static void direct_link_id(FileData *fd, ID *id)
+{
+       /*link direct data of ID properties*/
+       if (id->properties) {
+               id->properties = newdataadr(fd, id->properties);
+               if (id->properties) { /* this case means the data was written incorrectly, it should not happen */
+                       IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+               }
+       }
+}
+
 /* ************ READ CurveMapping *************** */
 
 /* cuma itself has been read! */
@@ -1691,10 +1830,10 @@ static void direct_link_script(FileData *UNUSED(fd), Script *script)
 
 static PackedFile *direct_link_packedfile(FileData *fd, PackedFile *oldpf)
 {
-       PackedFile *pf = newdataadr(fd, oldpf);
+       PackedFile *pf = newpackedadr(fd, oldpf);
        
        if (pf) {
-               pf->data = newdataadr(fd, pf->data);
+               pf->data = newpackedadr(fd, pf->data);
        }
        
        return pf;
@@ -1712,6 +1851,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p
                        if (prv->rect[i]) {
                                prv->rect[i] = newdataadr(fd, prv->rect[i]);
                        }
+                       prv->gputexture[i] = NULL;
                }
        }
        
@@ -2392,6 +2532,8 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
        ntree->adt = newdataadr(fd, ntree->adt);
        direct_link_animdata(fd, ntree->adt);
        
+       ntree->id.flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA);
+
        link_list(fd, &ntree->nodes);
        for (node = ntree->nodes.first; node; node = node->next) {
                node->typeinfo = NULL;
@@ -2399,6 +2541,14 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                link_list(fd, &node->inputs);
                link_list(fd, &node->outputs);
                
+               link_list(fd, &node->internal_links);
+               for (link = node->internal_links.first; link; link = link->next) {
+                       link->fromnode = newdataadr(fd, link->fromnode);
+                       link->fromsock = newdataadr(fd, link->fromsock);
+                       link->tonode = newdataadr(fd, link->tonode);
+                       link->tosock = newdataadr(fd, link->tosock);
+               }
+               
                if (node->type == CMP_NODE_MOVIEDISTORTION) {
                        node->storage = newmclipadr(fd, node->storage);
                }
@@ -2407,8 +2557,18 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                
                if (node->storage) {
                        /* could be handlerized at some point */
-                       if (ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
-                               direct_link_curvemapping(fd, node->storage);
+                       if (ntree->type==NTREE_SHADER) {
+                               if (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB) {
+                                       direct_link_curvemapping(fd, node->storage);
+                               }
+                               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) {
                                if (ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT))
                                        direct_link_curvemapping(fd, node->storage);
@@ -2498,7 +2658,7 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
        cld.fd = fd;
        cld.id = id;
        
-       id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
+       BKE_id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
 }
 
 static void direct_link_constraints(FileData *fd, ListBase *lb)
@@ -2519,27 +2679,33 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
                                data->prop = newdataadr(fd, data->prop);
                                if (data->prop)
                                        IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
-                       }
                                break;
+                       }
                        case CONSTRAINT_TYPE_SPLINEIK:
                        {
                                bSplineIKConstraint *data= con->data;
-                               
+
                                data->points= newdataadr(fd, data->points);
-                       }
                                break;
+                       }
                        case CONSTRAINT_TYPE_KINEMATIC:
                        {
+                               bKinematicConstraint *data = con->data;
+
                                con->lin_error = 0.f;
                                con->rot_error = 0.f;
+
+                               /* version patch for runtime flag, was not cleared in some case */
+                               data->flag &= ~CONSTRAINT_IK_AUTO;
+                               break;
                        }
                        case CONSTRAINT_TYPE_CHILDOF:
                        {
                                /* XXX version patch, in older code this flag wasn't always set, and is inherent to type */
                                if (con->ownspace == CONSTRAINT_SPACE_POSE)
                                        con->flag |= CONSTRAINT_SPACEONCE;
-                       }
                                break;
+                       }
                }
        }
 }
@@ -2548,14 +2714,15 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
 {
        bPoseChannel *pchan;
        bArmature *arm = ob->data;
-       int rebuild;
+       int rebuild = 0;
        
        if (!pose || !arm)
                return;
        
-       
-       /* always rebuild to match proxy or lib changes */
-       rebuild = ob->proxy || (ob->id.lib==NULL && arm->id.lib);
+       /* always rebuild to match proxy or lib changes, but on Undo */
+       if (fd->memfile == NULL)
+               if (ob->proxy || (ob->id.lib==NULL && arm->id.lib))
+                       rebuild = 1;
        
        if (ob->proxy) {
                /* sync proxy layer */
@@ -2712,8 +2879,10 @@ static void direct_link_lamp(FileData *fd, Lamp *la)
                direct_link_curvemapping(fd, la->curfalloff);
 
        la->nodetree= newdataadr(fd, la->nodetree);
-       if (la->nodetree)
+       if (la->nodetree) {
+               direct_link_id(fd, &la->nodetree->id);
                direct_link_nodetree(fd, la->nodetree);
+       }
        
        la->preview = direct_link_preview_image(fd, la->preview);
 }
@@ -2776,7 +2945,7 @@ static void switch_endian_keyblock(Key *key, KeyBlock *kb)
                        
                        cp += 2;
                }
-               data+= elemsize;
+               data += elemsize;
        }
 }
 
@@ -2879,8 +3048,10 @@ static void direct_link_world(FileData *fd, World *wrld)
        }
        
        wrld->nodetree = newdataadr(fd, wrld->nodetree);
-       if (wrld->nodetree)
+       if (wrld->nodetree) {
+               direct_link_id(fd, &wrld->nodetree->id);
                direct_link_nodetree(fd, wrld->nodetree);
+       }
        
        wrld->preview = direct_link_preview_image(fd, wrld->preview);
 }
@@ -2935,11 +3106,10 @@ static void direct_link_text(FileData *fd, Text *text)
        if (text->flags & TXT_ISEXT) {
                BKE_text_reload(text);
                }
-               else {
+               /* else { */
 #endif
        
        link_list(fd, &text->lines);
-       link_list(fd, &text->markers);
        
        text->curl = newdataadr(fd, text->curl);
        text->sell = newdataadr(fd, text->sell);
@@ -2999,10 +3169,11 @@ static void direct_link_image(FileData *fd, Image *ima)
                link_ibuf_list(fd, &ima->ibufs);
        else
                ima->ibufs.first = ima->ibufs.last = NULL;
-       
+
        /* if not restored, we keep the binded opengl index */
        if (ima->ibufs.first == NULL) {
                ima->bindcode = 0;
+               ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
                ima->gputexture = NULL;
        }
        
@@ -3161,7 +3332,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);
@@ -3187,8 +3358,10 @@ static void direct_link_texture(FileData *fd, Tex *tex)
        tex->ot = newdataadr(fd, tex->ot);
        
        tex->nodetree = newdataadr(fd, tex->nodetree);
-       if (tex->nodetree)
+       if (tex->nodetree) {
+               direct_link_id(fd, &tex->nodetree->id);
                direct_link_nodetree(fd, tex->nodetree);
+       }
        
        tex->preview = direct_link_preview_image(fd, tex->preview);
        
@@ -3247,8 +3420,10 @@ static void direct_link_material(FileData *fd, Material *ma)
        ma->ramp_spec = newdataadr(fd, ma->ramp_spec);
        
        ma->nodetree = newdataadr(fd, ma->nodetree);
-       if (ma->nodetree)
+       if (ma->nodetree) {
+               direct_link_id(fd, &ma->nodetree->id);
                direct_link_nodetree(fd, ma->nodetree);
+       }
        
        ma->preview = direct_link_preview_image(fd, ma->preview);
        ma->gpumaterial.first = ma->gpumaterial.last = NULL;
@@ -3368,32 +3543,31 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
                        if (part->dupliweights.first && part->dup_group) {
                                int index_ok = 0;
                                /* check for old files without indices (all indexes 0) */
-                               dw = part->dupliweights.first;
                                if (part->dupliweights.first == part->dupliweights.last) {
                                        /* special case for only one object in the group */
                                        index_ok = 1;
                                }
                                else {
-                                       for (; dw; dw=dw->next) {
+                                       for (dw = part->dupliweights.first; dw; dw = dw->next) {
                                                if (dw->index > 0) {
                                                        index_ok = 1;
                                                        break;
                                                }
                                        }
                                }
-                               
+
                                if (index_ok) {
                                        /* if we have indexes, let's use them */
-                                       dw = part->dupliweights.first;
-                                       for (; dw; dw=dw->next) {
+                                       for (dw = part->dupliweights.first; dw; dw = dw->next) {
                                                GroupObject *go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index);
-                                               dw->ob = go ? go->ob : NULL;
+                                               dw->ob = go ? newlibadr(fd, part->id.lib, dw->ob) : NULL;
                                        }
                                }
                                else {
                                        /* otherwise try to get objects from own library (won't work on library linked groups) */
-                                       for (; dw; dw=dw->next)
+                                       for (dw = part->dupliweights.first; dw; dw = dw->next) {
                                                dw->ob = newlibadr(fd, part->id.lib, dw->ob);
+                                       }
                                }
                        }
                        else {
@@ -3694,7 +3868,7 @@ static void lib_link_mesh(FileData *fd, Main *main)
                        /*
                         * Re-tessellate, even if the polys were just created from tessfaces, this
                         * is important because it:
-                        *  - fill the CD_POLYINDEX layer
+                        *  - fill the CD_ORIGINDEX layer
                         *  - gives consistency of tessface between loading from a file and
                         *    converting an edited BMesh back into a mesh (i.e. it replaces
                         *    quad tessfaces in a loaded mesh immediately, instead of lazily
@@ -3789,7 +3963,7 @@ static void direct_link_customdata(FileData *fd, CustomData *data, int count)
        /* annoying workaround for bug [#31079] loading legacy files with
         * no polygons _but_ have stale customdata */
        if (UNLIKELY(count == 0 && data->layers == NULL && data->totlayer != 0)) {
-               memset(data, 0, sizeof(*data));
+               CustomData_reset(data);
                return;
        }
        
@@ -3993,8 +4167,6 @@ static void lib_link_object(FileData *fd, Main *main)
                                else {
                                        /* this triggers object_update to always use a copy */
                                        ob->proxy->proxy_from = ob;
-                                       /* force proxy updates after load/undo, a bit weak */
-                                       ob->recalc = ob->proxy->recalc = (OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
                                }
                        }
                        ob->proxy_group = newlibadr(fd, ob->id.lib, ob->proxy_group);
@@ -4192,6 +4364,11 @@ static void lib_link_object(FileData *fd, Main *main)
                        
                        lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem);
                        lib_link_modifiers(fd, ob);
+
+                       if (ob->rigidbody_constraint) {
+                               ob->rigidbody_constraint->ob1 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob1);
+                               ob->rigidbody_constraint->ob2 = newlibadr(fd, ob->id.lib, ob->rigidbody_constraint->ob2);
+                       }
                }
        }
        
@@ -4615,6 +4792,20 @@ static void direct_link_object(FileData *fd, Object *ob)
        }
        ob->bsoft = newdataadr(fd, ob->bsoft);
        ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
+       
+       ob->rigidbody_object = newdataadr(fd, ob->rigidbody_object);
+       if (ob->rigidbody_object) {
+               RigidBodyOb *rbo = ob->rigidbody_object;
+               
+               /* must nullify the references to physics sim objects, since they no-longer exist 
+                * (and will need to be recalculated) 
+                */
+               rbo->physics_object = NULL;
+               rbo->physics_shape = NULL;
+       }
+       ob->rigidbody_constraint = newdataadr(fd, ob->rigidbody_constraint);
+       if (ob->rigidbody_constraint)
+               ob->rigidbody_constraint->physics_constraint = NULL;
 
        link_list(fd, &ob->particlesystem);
        direct_link_particlesystems(fd, &ob->particlesystem);
@@ -4768,7 +4959,7 @@ static void lib_link_scene(FileData *fd, Main *main)
                                base->object = newlibadr_us(fd, sce->id.lib, base->object);
                                
                                if (base->object == NULL) {
-                                       BKE_reportf_wrap(fd->reports, RPT_WARNING, "LIB ERROR: object lost from scene: '%s'",
+                                       BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: object lost from scene: '%s'"),
                                                         sce->id.name + 2);
                                        BLI_remlink(&sce->base, base);
                                        if (base == sce->basact) sce->basact = NULL;
@@ -4833,6 +5024,18 @@ static void lib_link_scene(FileData *fd, Main *main)
                        BKE_sequencer_update_muting(sce->ed);
                        BKE_sequencer_update_sound_bounds_all(sce);
                        
+                       
+                       /* rigidbody world relies on it's linked groups */
+                       if (sce->rigidbody_world) {
+                               RigidBodyWorld *rbw = sce->rigidbody_world;
+                               if (rbw->group)
+                                       rbw->group = newlibadr(fd, sce->id.lib, rbw->group);
+                               if (rbw->constraints)
+                                       rbw->constraints = newlibadr(fd, sce->id.lib, rbw->constraints);
+                               if (rbw->effector_weights)
+                                       rbw->effector_weights->group = newlibadr(fd, sce->id.lib, rbw->effector_weights->group);
+                       }
+                       
                        if (sce->nodetree) {
                                lib_link_ntree(fd, &sce->id, sce->nodetree);
                                composite_patch(sce->nodetree, sce);
@@ -4909,6 +5112,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        Editing *ed;
        Sequence *seq;
        MetaStack *ms;
+       RigidBodyWorld *rbw;
        
        sce->theDag = NULL;
        sce->dagisvalid = 0;
@@ -4942,6 +5146,16 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                
                sce->toolsettings->imapaint.paintcursor = NULL;
                sce->toolsettings->particle.paintcursor = NULL;
+
+               /* in rare cases this is needed, see [#33806] */
+               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;
+               }
        }
 
        if (sce->ed) {
@@ -5079,10 +5293,34 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        link_list(fd, &(sce->r.layers));
        
        sce->nodetree = newdataadr(fd, sce->nodetree);
-       if (sce->nodetree)
+       if (sce->nodetree) {
+               direct_link_id(fd, &sce->nodetree->id);
                direct_link_nodetree(fd, sce->nodetree);
+       }
 
        direct_link_view_settings(fd, &sce->view_settings);
+       
+       sce->rigidbody_world = newdataadr(fd, sce->rigidbody_world);
+       rbw = sce->rigidbody_world;
+       if (rbw) {
+               /* must nullify the reference to physics sim object, since it no-longer exist 
+                * (and will need to be recalculated) 
+                */
+               rbw->physics_world = NULL;
+               rbw->objects = NULL;
+               rbw->numbodies = 0;
+
+               /* set effector weights */
+               rbw->effector_weights = newdataadr(fd, rbw->effector_weights);
+               if (!rbw->effector_weights)
+                       rbw->effector_weights = BKE_add_effector_weights(NULL);
+
+               /* 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;
+       }
 }
 
 /* ************ READ WM ***************** */
@@ -5109,6 +5347,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
                win->drawdata = NULL;
                win->drawmethod = -1;
                win->drawfail = 0;
+               win->active = 0;
        }
        
        wm->timers.first = wm->timers.last = NULL;
@@ -5180,27 +5419,6 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
 
 /* ****************** READ SCREEN ***************** */
 
-static void butspace_version_132(SpaceButs *buts)
-{
-       buts->v2d.tot.xmin = 0.0f;
-       buts->v2d.tot.ymin = 0.0f;
-       buts->v2d.tot.xmax = 1279.0f;
-       buts->v2d.tot.ymax = 228.0f;
-       
-       buts->v2d.min[0] = 256.0f;
-       buts->v2d.min[1] = 42.0f;
-       
-       buts->v2d.max[0] = 2048.0f;
-       buts->v2d.max[1] = 450.0f;
-       
-       buts->v2d.minzoom = 0.5f;
-       buts->v2d.maxzoom = 1.21f;
-       
-       buts->v2d.scroll = 0;
-       buts->v2d.keepzoom = 1;
-       buts->v2d.keeptot = 1;
-}
-
 /* note: file read without screens option G_FILE_NO_UI; 
  * check lib pointers in call below */
 static void lib_link_screen(FileData *fd, Main *main)
@@ -5254,18 +5472,9 @@ static void lib_link_screen(FileData *fd, Main *main)
                                        else if (sl->spacetype == SPACE_BUTS) {
                                                SpaceButs *sbuts = (SpaceButs *)sl;
                                                sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid);
-                                               sbuts->mainbo = sbuts->mainb;
-                                               sbuts->mainbuser = sbuts->mainb;
-                                               if (main->versionfile < 132)
-                                                       butspace_version_132(sbuts);
                                        }
                                        else if (sl->spacetype == SPACE_FILE) {
-                                               SpaceFile *sfile = (SpaceFile *)sl;
-                                               sfile->files = NULL;
-                                               sfile->op = NULL;
-                                               sfile->layout = NULL;
-                                               sfile->folders_prev = NULL;
-                                               sfile->folders_next = NULL;
+                                               ;
                                        }
                                        else if (sl->spacetype == SPACE_ACTION) {
                                                SpaceAction *saction = (SpaceAction *)sl;
@@ -5297,12 +5506,6 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                 */
                                                sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd);
 
-                                               sseq->scopes.reference_ibuf = NULL;
-                                               sseq->scopes.zebra_ibuf = NULL;
-                                               sseq->scopes.waveform_ibuf = NULL;
-                                               sseq->scopes.sep_waveform_ibuf = NULL;
-                                               sseq->scopes.vector_ibuf = NULL;
-                                               sseq->scopes.histogram_ibuf = NULL;
                                        }
                                        else if (sl->spacetype == SPACE_NLA) {
                                                SpaceNla *snla= (SpaceNla *)sl;
@@ -5317,7 +5520,6 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                SpaceText *st= (SpaceText *)sl;
                                                
                                                st->text= newlibadr(fd, sc->id.lib, st->text);
-                                               st->drawcache= NULL;
                                        }
                                        else if (sl->spacetype == SPACE_SCRIPT) {
                                                SpaceScript *scpt = (SpaceScript *)sl;
@@ -5334,7 +5536,6 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                TreeStoreElem *tselem;
                                                int a;
                                                
-                                               so->tree.first = so->tree.last= NULL;
                                                so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
                                                
                                                if (so->treestore) {
@@ -5348,7 +5549,6 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                SpaceNode *snode = (SpaceNode *)sl;
                                                
                                                snode->id = newlibadr(fd, sc->id.lib, snode->id);
-                                               snode->edittree = NULL;
                                                
                                                if (ELEM3(snode->treetype, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE)) {
                                                        /* internal data, a bit patchy */
@@ -5369,19 +5569,12 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                else {
                                                        snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree);
                                                }
-                                               
-                                               snode->linkdrag.first = snode->linkdrag.last = NULL;
                                        }
                                        else if (sl->spacetype == SPACE_CLIP) {
                                                SpaceClip *sclip = (SpaceClip *)sl;
                                                
                                                sclip->clip = newlibadr_us(fd, sc->id.lib, sclip->clip);
                                                sclip->mask_info.mask = newlibadr_us(fd, sc->id.lib, sclip->mask_info.mask);
-                                               
-                                               sclip->scopes.track_search = NULL;
-                                               sclip->scopes.track_preview = NULL;
-                                               sclip->draw_context = NULL;
-                                               sclip->scopes.ok = 0;
                                        }
                                        else if (sl->spacetype == SPACE_LOGIC) {
                                                SpaceLogic *slogic = (SpaceLogic *)sl;
@@ -5395,7 +5588,14 @@ static void lib_link_screen(FileData *fd, Main *main)
        }
 }
 
-/* Only for undo files, or to restore a screen after reading without UI... */
+/**
+ * Only for undo files, or to restore a screen after reading without UI...
+ *
+ * user
+ * - 0: no usercount change
+ * - 1: ensure a user
+ * - 2: ensure a real user (even if a fake one is set)
+ */
 static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
 {
        if (id) {
@@ -5408,7 +5608,14 @@ static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
                        for (; idn; idn = idn->next) {
                                if (idn->name[2] == name[0] && strcmp(idn->name+2, name) == 0) {
                                        if (idn->lib == id->lib) {
-                                               if (user && idn->us == 0) idn->us++;
+                                               if (user == 1) {
+                                                       if (idn->us == 0) {
+                                                               idn->us++;
+                                                       }
+                                               }
+                                               else if (user == 2) {
+                                                       id_us_ensure_real(idn);
+                                               }
                                                break;
                                        }
                                }
@@ -5574,7 +5781,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                else if (sl->spacetype == SPACE_IMAGE) {
                                        SpaceImage *sima = (SpaceImage *)sl;
                                        
-                                       sima->image = restore_pointer_by_name(newmain, (ID *)sima->image, 1);
+                                       sima->image = restore_pointer_by_name(newmain, (ID *)sima->image, 2);
                                        
                                        /* this will be freed, not worth attempting to find same scene,
                                         * since it gets initialized later */
@@ -5590,7 +5797,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                         * so assume that here we're doing for undo only...
                                         */
                                        sima->gpd = restore_pointer_by_name(newmain, (ID *)sima->gpd, 1);
-                                       sima->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sima->mask_info.mask, 1);
+                                       sima->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sima->mask_info.mask, 2);
                                }
                                else if (sl->spacetype == SPACE_SEQ) {
                                        SpaceSeq *sseq = (SpaceSeq *)sl;
@@ -5665,8 +5872,8 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
                                else if (sl->spacetype == SPACE_CLIP) {
                                        SpaceClip *sclip = (SpaceClip *)sl;
                                        
-                                       sclip->clip = restore_pointer_by_name(newmain, (ID *)sclip->clip, 1);
-                                       sclip->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sclip->mask_info.mask, 1);
+                                       sclip->clip = restore_pointer_by_name(newmain, (ID *)sclip->clip, 2);
+                                       sclip->mask_info.mask = restore_pointer_by_name(newmain, (ID *)sclip->mask_info.mask, 2);
                                        
                                        sclip->scopes.ok = 0;
                                }
@@ -5686,6 +5893,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
 static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
 {
        Panel *pa;
+       uiList *ui_list;
 
        link_list(fd, &ar->panels);
 
@@ -5695,7 +5903,13 @@ 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) {
+               ui_list->type = NULL;
+       }
+
        ar->regiondata = newdataadr(fd, ar->regiondata);
        if (ar->regiondata) {
                if (spacetype == SPACE_VIEW3D) {
@@ -5723,6 +5937,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
        ar->type = NULL;
        ar->swap = 0;
        ar->do_draw = FALSE;
+       ar->regiontimer = NULL;
        memset(&ar->drawrct, 0, sizeof(ar->drawrct));
 }
 
@@ -5791,6 +6006,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                
                sa->handlers.first = sa->handlers.last = NULL;
                sa->type = NULL;        /* spacetype callbacks */
+               sa->region_active_win = -1;
                
                for (ar = sa->regionbase.first; ar; ar = ar->next)
                        direct_link_region(fd, ar, sa->spacetype);
@@ -5839,6 +6055,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                v3d->afterdraw_xray.first = v3d->afterdraw_xray.last = NULL;
                                v3d->afterdraw_xraytransp.first = v3d->afterdraw_xraytransp.last = NULL;
                                v3d->properties_storage = NULL;
+                               v3d->defmaterial = NULL;
                                
                                /* render can be quite heavy, set to wire on load */
                                if (v3d->drawtype == OB_RENDER)
@@ -5867,6 +6084,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;
                        }
                        else if (sl->spacetype == SPACE_IMAGE) {
                                SpaceImage *sima = (SpaceImage *)sl;
@@ -5899,6 +6117,13 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                        snode->gpd = newdataadr(fd, snode->gpd);
                                        direct_link_gpencil(fd, snode->gpd);
                                }
+                               snode->edittree = NULL;
+                               snode->linkdrag.first = snode->linkdrag.last = NULL;
+                       }
+                       else if (sl->spacetype == SPACE_TEXT) {
+                               SpaceText *st= (SpaceText *)sl;
+                               
+                               st->drawcache= NULL;
                        }
                        else if (sl->spacetype == SPACE_TIME) {
                                SpaceTime *stime = (SpaceTime *)sl;
@@ -5914,6 +6139,8 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                }
                        }
                        else if (sl->spacetype == SPACE_SEQ) {
+                               SpaceSeq *sseq = (SpaceSeq *)sl;
+                               
                                /* grease pencil data is not a direct data and can't be linked from direct_link*
                                 * functions, it should be linked from lib_link* functions instead
                                 *
@@ -5922,17 +6149,26 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                 * simple return NULL here (sergey)
                                 */
 #if 0
-                               SpaceSeq *sseq = (SpaceSeq *)sl;
                                if (sseq->gpd) {
                                        sseq->gpd = newdataadr(fd, sseq->gpd);
                                        direct_link_gpencil(fd, sseq->gpd);
                                }
 #endif
+                               sseq->scopes.reference_ibuf = NULL;
+                               sseq->scopes.zebra_ibuf = NULL;
+                               sseq->scopes.waveform_ibuf = NULL;
+                               sseq->scopes.sep_waveform_ibuf = NULL;
+                               sseq->scopes.vector_ibuf = NULL;
+                               sseq->scopes.histogram_ibuf = NULL;
+
                        }
                        else if (sl->spacetype == SPACE_BUTS) {
                                SpaceButs *sbuts = (SpaceButs *)sl;
+                               
                                sbuts->path= NULL;
                                sbuts->texuser= NULL;
+                               sbuts->mainbo = sbuts->mainb;
+                               sbuts->mainbuser = sbuts->mainb;
                        }
                        else if (sl->spacetype == SPACE_CONSOLE) {
                                SpaceConsole *sconsole = (SpaceConsole *)sl;
@@ -5972,6 +6208,14 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                sfile->op = NULL;
                                sfile->params = newdataadr(fd, sfile->params);
                        }
+                       else if (sl->spacetype == SPACE_CLIP) {
+                               SpaceClip *sclip = (SpaceClip *)sl;
+                               
+                               sclip->scopes.track_search = NULL;
+                               sclip->scopes.track_preview = NULL;
+                               sclip->draw_context = NULL;
+                               sclip->scopes.ok = 0;
+                       }
                }
                
                sa->actionzones.first = sa->actionzones.last = NULL;
@@ -5990,15 +6234,16 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
 {
        Main *newmain;
        
+       /* check if the library was already read */
        for (newmain = fd->mainlist->first; newmain; newmain = newmain->next) {
                if (newmain->curlib) {
                        if (BLI_path_cmp(newmain->curlib->filepath, lib->filepath) == 0) {
                                BKE_reportf_wrap(fd->reports, RPT_WARNING,
-                                                "Library '%s', '%s' had multiple instances, save and reload!",
+                                                TIP_("Library '%s', '%s' had multiple instances, save and reload!"),
                                                 lib->name, lib->filepath);
                                
                                change_idid_adr(fd->mainlist, fd, lib, newmain->curlib);
-//                             change_idid_adr_fd(fd, lib, newmain->curlib);
+/*                             change_idid_adr_fd(fd, lib, newmain->curlib); */
                                
                                BLI_remlink(&main->library, lib);
                                MEM_freeN(lib);
@@ -6008,12 +6253,14 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
                        }
                }
        }
-       /* make sure we have full path in lib->filename */
+       /* make sure we have full path in lib->filepath */
        BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name));
        cleanup_path(fd->relabase, lib->filepath);
        
 //     printf("direct_link_library: name %s\n", lib->name);
-//     printf("direct_link_library: filename %s\n", lib->filename);
+//     printf("direct_link_library: filepath %s\n", lib->filepath);
+       
+       lib->packedfile = direct_link_packedfile(fd, lib->packedfile);
        
        /* new main */
        newmain= MEM_callocN(sizeof(Main), "directlink");
@@ -6450,6 +6697,8 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
        bhead = read_data_into_oldnewmap(fd, bhead, allocname);
        
        /* init pointers direct data */
+       direct_link_id(fd, id);
+       
        switch (GS(id->name)) {
                case ID_WM:
                        direct_link_windowmanager(fd, (wmWindowManager *)id);
@@ -6546,14 +6795,6 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                        break;
        }
        
-       /*link direct data of ID properties*/
-       if (id->properties) {
-               id->properties = newdataadr(fd, id->properties);
-               if (id->properties) { /* this case means the data was written incorrectly, it should not happen */
-                       IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
-               }
-       }
-       
        oldnewmap_free_unused(fd->datamap);
        oldnewmap_clear(fd->datamap);
        
@@ -6578,6 +6819,17 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
        bfd->globalf = fg->globalf;
        BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
        
+       /* error in 2.65 and older: main->name was not set if you save from startup (not after loading file) */
+       if (bfd->filename[0] == 0) {
+               if (fd->fileversion < 265 || (fd->fileversion == 265 && fg->subversion < 1))
+                       if ((G.fileflags & G_FILE_RECOVER)==0)
+                               BLI_strncpy(bfd->filename, bfd->main->name, sizeof(bfd->filename));
+               
+               /* early 2.50 version patch - filename not in FileGlobal struct at all */
+               if (fd->fileversion <= 250)
+                       BLI_strncpy(bfd->filename, bfd->main->name, sizeof(bfd->filename));
+       }
+       
        if (G.fileflags & G_FILE_RECOVER)
                BLI_strncpy(fd->relabase, fg->filename, sizeof(fd->relabase));
        
@@ -6673,7 +6925,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. */
@@ -6685,7 +6937,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...
@@ -7019,6 +7271,20 @@ static void do_version_ntree_dilateerode_264(void *UNUSED(data), ID *UNUSED(id),
        }
 }
 
+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;
@@ -7076,6 +7342,84 @@ static void do_version_node_cleanup_dynamic_sockets_264(void *UNUSED(data), ID *
        }
 }
 
+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;
+       
+       /* view settings for logic changed */
+       for (ar = regionbase->first; ar; ar = ar->next) {
+               if (ar->regiontype == RGN_TYPE_WINDOW) {
+                       if (ar->v2d.keeptot == 0) {
+                               ar->v2d.maxzoom = 1.5f;
+                               
+                               ar->v2d.keepzoom = V2D_KEEPZOOM | V2D_LIMITZOOM | V2D_KEEPASPECT;
+                               ar->v2d.keeptot = V2D_KEEPTOT_BOUNDS;
+                               ar->v2d.align = V2D_ALIGN_NO_POS_Y | V2D_ALIGN_NO_NEG_X;
+                               ar->v2d.keepofs = V2D_KEEPOFS_Y;
+                       }
+               }
+       }
+       
+
+}
+
+static void do_versions_affine_tracker_track(MovieTrackingTrack *track)
+{
+       int i;
+
+       for (i = 0; i < track->markersnr; i++) {
+               MovieTrackingMarker *marker = &track->markers[i];
+
+               if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) &&
+                   is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3]))
+                       {
+                               marker->pattern_corners[0][0] = track->pat_min[0];
+                               marker->pattern_corners[0][1] = track->pat_min[1];
+
+                               marker->pattern_corners[1][0] = track->pat_max[0];
+                               marker->pattern_corners[1][1] = track->pat_min[1];
+
+                               marker->pattern_corners[2][0] = track->pat_max[0];
+                               marker->pattern_corners[2][1] = track->pat_max[1];
+
+                               marker->pattern_corners[3][0] = track->pat_min[0];
+                               marker->pattern_corners[3][1] = track->pat_max[1];
+                       }
+
+               if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) {
+                       copy_v2_v2(marker->search_min, track->search_min);
+                       copy_v2_v2(marker->search_max, track->search_max);
+               }
+       }
+}
+
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -7375,7 +7719,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        for (ob = main->object.first; ob; ob = ob->id.next) {
                                bConstraint *con;
                                for (con = ob->constraints.first; con; con = con->next) {
-                                       bConstraintTypeInfo *cti = constraint_get_typeinfo(con);
+                                       bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
                                        
                                        if (!cti)
                                                continue;
@@ -7399,8 +7743,8 @@ 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,
-                                                                "Game property name conflict in object '%s':\ntext objects reserve the "
-                                                                "['Text'] game property to change their content through logic bricks",
+                                                                TIP_("Game property name conflict in object '%s':\ntext objects reserve the "
+                                                                     "['Text'] game property to change their content through logic bricks"),
                                                                 ob->id.name + 2);
                                        }
                                }
@@ -7756,7 +8100,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                if (md->type == eModifierType_Smoke) {
                                        SmokeModifierData *smd = (SmokeModifierData *)md;
                                        if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
-                                               int maxres = MAX3(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
+                                               int maxres = max_iii(smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
                                                smd->domain->scale = smd->domain->dx * maxres;
                                                smd->domain->dx = 1.0f / smd->domain->scale;
                                        }
@@ -7789,6 +8133,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        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) {
@@ -7797,6 +8142,11 @@ 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);
+                       
                }
 
                {
@@ -7838,32 +8188,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
                        track = clip->tracking.tracks.first;
                        while (track) {
-                               int i;
-
-                               for (i = 0; i < track->markersnr; i++) {
-                                       MovieTrackingMarker *marker = &track->markers[i];
-
-                                       if (is_zero_v2(marker->pattern_corners[0]) && is_zero_v2(marker->pattern_corners[1]) &&
-                                           is_zero_v2(marker->pattern_corners[2]) && is_zero_v2(marker->pattern_corners[3]))
-                                       {
-                                               marker->pattern_corners[0][0] = track->pat_min[0];
-                                               marker->pattern_corners[0][1] = track->pat_min[1];
-
-                                               marker->pattern_corners[1][0] = track->pat_max[0];
-                                               marker->pattern_corners[1][1] = track->pat_min[1];
-
-                                               marker->pattern_corners[2][0] = track->pat_max[0];
-                                               marker->pattern_corners[2][1] = track->pat_max[1];
-
-                                               marker->pattern_corners[3][0] = track->pat_min[0];
-                                               marker->pattern_corners[3][1] = track->pat_max[1];
-                                       }
-
-                                       if (is_zero_v2(marker->search_min) && is_zero_v2(marker->search_max)) {
-                                               copy_v2_v2(marker->search_min, track->search_min);
-                                               copy_v2_v2(marker->search_max, track->search_max);
-                                       }
-                               }
+                               do_versions_affine_tracker_track(track);
 
                                track = track->next;
                        }
@@ -8007,6 +8332,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                {
                        Mesh *me;
                        for (me = main->mesh.first; me; me = me->id.next) {
+                               CustomData_update_typemap(&me->vdata);
                                CustomData_free_layers(&me->vdata, CD_MSTICKY, me->totvert);
                        }
                }
@@ -8145,6 +8471,340 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        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;
+
+               for (scene=main->scene.first; scene; scene=scene->id.next) {
+                       if (scene->toolsettings->uvcalc_margin == 0.0f) {
+                               scene->toolsettings->uvcalc_margin = 0.001f;
+                               scene->toolsettings->unwrapper = 0;
+                       }
+               }
+       }
+
+       if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
+               /* 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);
+               
+       }
+       
+       if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 6)) {
+               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;
+                               if ( sa->spacetype == SPACE_LOGIC)
+                                       do_version_logic_264(&sa->regionbase);
+                               
+                               for (sl = sa->spacedata.first; sl; sl = sl->next) {
+                                       if (sl->spacetype == SPACE_LOGIC)
+                                               do_version_logic_264(&sl->regionbase);
+                               }
+                       }
+               }
+       }
+
+       if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) {
+               /* convert tiles size from resolution and number of tiles */
+               {
+                       Scene *scene;
+
+                       for (scene = main->scene.first; scene; scene = scene->id.next) {
+                               if (scene->r.tilex == 0 || scene->r.tiley == 1) {
+                                       if (scene->r.xparts && scene->r.yparts) {
+                                               /* scene could be set for panoramic rendering, so clamp with the
+                                                * lowest possible tile size value
+                                                */
+                                               scene->r.tilex = max_ii(scene->r.xsch * scene->r.size / scene->r.xparts / 100, 8);
+                                               scene->r.tiley = max_ii(scene->r.ysch * scene->r.size / scene->r.yparts / 100, 8);
+                                       }
+                                       else {
+                                               /* happens when mixing using current trunk and previous release */
+                                               scene->r.tilex = scene->r.tiley = 64;
+                                       }
+                               }
+                       }
+               }
+
+               /* collision masks */
+               {
+                       Object *ob;
+                       for (ob = main->object.first; ob; ob = ob->id.next) {
+                               if (ob->col_group == 0) {
+                                       ob->col_group = 0x01;
+                                       ob->col_mask = 0xff;
+                               }
+                       }
+               }
+
+               /* fallbck resection method settings */
+               {
+                       MovieClip *clip;
+
+                       for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+                               if (clip->tracking.settings.reconstruction_success_threshold == 0.0f) {
+                                       clip->tracking.settings.reconstruction_success_threshold = 1e-3f;
+                               }
+                       }
+               }
+       }
+
+       if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 7)) {
+               MovieClip *clip;
+
+               for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+                       MovieTrackingTrack *track;
+                       MovieTrackingObject *object;
+
+                       for (track = clip->tracking.tracks.first; track; track = track->next) {
+                               do_versions_affine_tracker_track(track);
+                       }
+
+                       for (object = clip->tracking.objects.first; object; object = object->next) {
+                               for (track = object->tracks.first; track; track = track->next) {
+                                       do_versions_affine_tracker_track(track);
+                               }
+                       }
+               }
+       }
+
+       if (main->versionfile < 265) {
+               Object *ob;
+               for (ob = main->object.first; ob; ob = ob->id.next) {
+                       if (ob->step_height == 0.0f) {
+                               ob->step_height = 0.15f;
+                               ob->jump_speed = 10.0f;
+                               ob->fall_speed = 55.0f;
+                       }
+               }
+       }
+
+       if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 3)) {
+               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) {
+                                       switch (sl->spacetype) {
+                                               case SPACE_VIEW3D:
+                                               {
+                                                       View3D *v3d = (View3D *)sl;
+                                                       v3d->flag2 |= V3D_SHOW_GPENCIL;
+                                                       break;
+                                               }
+                                               case SPACE_SEQ:
+                                               {
+                                                       SpaceSeq *sseq = (SpaceSeq *)sl;
+                                                       sseq->flag |= SEQ_SHOW_GPENCIL;
+                                                       break;
+                                               }
+                                               case SPACE_IMAGE:
+                                               {
+                                                       SpaceImage *sima = (SpaceImage *)sl;
+                                                       sima->flag |= SI_SHOW_GPENCIL;
+                                                       break;
+                                               }
+                                               case SPACE_NODE:
+                                               {
+                                                       SpaceNode *snode = (SpaceNode *)sl;
+                                                       snode->flag |= SNODE_SHOW_GPENCIL;
+                                                       break;
+                                               }
+                                               case SPACE_CLIP:
+                                               {
+                                                       SpaceClip *sclip = (SpaceClip *)sl;
+                                                       sclip->flag |= SC_SHOW_GPENCIL;
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) {
+               Scene *scene;
+               Image *image, *nimage;
+               Tex *tex, *otex;
+
+               for (scene = main->scene.first; scene; scene = scene->id.next) {
+                       Sequence *seq;
+                       bool set_premul = false;
+
+                       SEQ_BEGIN (scene->ed, seq)
+                       {
+                               if (seq->flag & SEQ_MAKE_PREMUL)
+                                       seq->alpha_mode = SEQ_ALPHA_STRAIGHT;
+                       }
+                       SEQ_END
+
+                       if (scene->r.bake_samples == 0)
+                       scene->r.bake_samples = 256;
+
+                       if (scene->world) {
+                               World *world = blo_do_versions_newlibadr(fd, scene->id.lib, scene->world);
+
+                               if (is_zero_v3(&world->horr)) {
+                                       if ((world->skytype & WO_SKYBLEND) == 0 || is_zero_v3(&world->zenr)) {
+                                               set_premul = true;
+                                       }
+                               }
+                       }
+                       else
+                               set_premul = true;
+
+                       if (set_premul) {
+                               printf("2.66 versioning fix: replacing black sky with premultiplied alpha for scene %s\n", scene->id.name + 2);
+                               scene->r.alphamode = R_ALPHAPREMUL;
+                       }
+               }
+
+               for (image = main->image.first; image; image = image->id.next) {
+                       if (image->flag & IMA_DO_PREMUL)
+                               image->alpha_mode = IMA_ALPHA_STRAIGHT;
+
+                       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;
+
+                               /* 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;
+
+                               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;
+                                                       }
+                                               }
+                                       }
+                               }
+                               else {
+                                       /* no other textures using alpha, just set the flag */
+                                       image->flag |= IMA_IGNORE_ALPHA;
+                               }
+                       }
+               }
+
+               for (image = main->image.first; image; image = image->id.next)
+                       image->flag &= ~IMA_DONE_TAG;
+       }
+
+       if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
+               Curve *cu;
+
+               for (cu = main->curve.first; cu; cu = cu->id.next) {
+                       if (cu->flag & (CU_FRONT | CU_BACK)) {
+                               if ( cu->ext1 != 0.0f || cu->ext2 != 0.0f) {
+                                       Nurb *nu;
+
+                                       for (nu = cu->nurb.first; nu; nu = nu->next) {
+                                               int a;
+
+                                               if (nu->bezt) {
+                                                       BezTriple *bezt = nu->bezt;
+                                                       a = nu->pntsu;
+
+                                                       while (a--) {
+                                                               bezt->radius = 1.0f;
+                                                               bezt++;
+                                                       }
+                                               }
+                                               else if (nu->bp) {
+                                                       BPoint *bp = nu->bp;
+                                                       a = nu->pntsu * nu->pntsv;
+
+                                                       while (a--) {
+                                                               bp->radius = 1.0f;
+                                                               bp++;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (!MAIN_VERSION_ATLEAST(main, 265, 8)) {
+               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)) {
+               Brush *br;
+               for (br = main->brush.first; br; br = br->id.next) {
+                       if (br->ob_mode & OB_MODE_TEXTURE_PAINT) {
+                               br->mtex.brush_map_mode = MTEX_MAP_MODE_TILED;
+                       }
+               }
+       }
+
+       // add storage for compositor translate nodes when not existing
+       if (!MAIN_VERSION_ATLEAST(main, 265, 10)) {
+               bNodeTreeType *ntreetype;
+
+               ntreetype = ntreeGetType(NTREE_COMPOSIT);
+               if (ntreetype && ntreetype->foreach_nodetree)
+                       ntreetype->foreach_nodetree(main, NULL, do_version_node_fix_translate_wrapping);
+       }
+
+
+
+       // if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) {
+
        /* 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! */
 
@@ -8164,8 +8824,11 @@ static void lib_link_all(FileData *fd, Main *main)
 {
        oldnewmap_sort(fd);
        
-       lib_link_windowmanager(fd, main);
-       lib_link_screen(fd, main);
+       /* No load UI for undo memfiles */
+       if (fd->memfile == NULL) {
+               lib_link_windowmanager(fd, main);
+               lib_link_screen(fd, main);
+       }
        lib_link_scene(fd, main);
        lib_link_object(fd, main);
        lib_link_curve(fd, main);
@@ -8212,6 +8875,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
        wmKeyMap *keymap;
        wmKeyMapItem *kmi;
        wmKeyMapDiffItem *kmdi;
+       bAddon *addon;
        
        bfd->user = user= read_struct(fd, bhead, "user def");
        
@@ -8249,7 +8913,14 @@ 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) {
+                       IDP_DirectLinkProperty(addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+               }
+       }
+
        // XXX
        user->uifonts.first = user->uifonts.last= NULL;
        
@@ -8373,7 +9044,7 @@ static void sort_bhead_old_map(FileData *fd)
        fd->tot_bheadmap = tot;
        if (tot == 0) return;
        
-       bhs = fd->bheadmap = MEM_mallocN(tot*sizeof(struct BHeadSort), STRINGIFY(BHeadSort));
+       bhs = fd->bheadmap = MEM_mallocN(tot * sizeof(struct BHeadSort), "BHeadSort");
        
        for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead), bhs++) {
                bhs->bhead = bhead;
@@ -8438,9 +9109,10 @@ static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
        return BLI_findstring(which_libbase(mainvar, GS(idname)), idname, offsetof(ID, name));
 }
 
-static void expand_doit(FileData *fd, Main *mainvar, void *old)
+static void expand_doit_library(void *fdhandle, Main *mainvar, void *old)
 {
        BHead *bhead;
+       FileData *fd = fdhandle;
        ID *id;
        
        bhead = find_bhead(fd, old);
@@ -8453,7 +9125,15 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                                Library *lib = read_struct(fd, bheadlib, "Library");
                                Main *ptr = blo_find_main(fd, lib->name, fd->relabase);
                                
-                               id = is_yet_read(fd, ptr, bhead);
+                               if (ptr->curlib == NULL) {
+                                       const char *idname= bhead_id_name(fd, bhead);
+                                       
+                                       BKE_reportf_wrap(fd->reports, RPT_WARNING, TIP_("LIB ERROR: Data refers to main .blend file: '%s' from %s"),
+                                                        idname, mainvar->curlib->filepath);
+                                       return;
+                               }
+                               else
+                                       id = is_yet_read(fd, ptr, bhead);
                                
                                if (id == NULL) {
                                        read_libblock(fd, ptr, bhead, LIB_READ+LIB_INDIRECT, NULL);
@@ -8507,7 +9187,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
        }
 }
 
-
+static void (*expand_doit)(void *, Main *, void *);
 
 // XXX deprecated - old animation system
 static void expand_ipo(FileData *fd, Main *mainvar, Ipo *ipo)
@@ -8892,7 +9572,7 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
        ced.fd = fd;
        ced.mainvar = mainvar;
        
-       id_loop_constraints(lb, expand_constraint_cb, &ced);
+       BKE_id_loop_constraints(lb, expand_constraint_cb, &ced);
        
        /* deprecated manual expansion stuff */
        for (curcon = lb->first; curcon; curcon = curcon->next) {
@@ -9098,7 +9778,12 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        
        if (ob->pd && ob->pd->tex)
                expand_doit(fd, mainvar, ob->pd->tex);
-       
+
+       if (ob->rigidbody_constraint) {
+               expand_doit(fd, mainvar, ob->rigidbody_constraint->ob1);
+               expand_doit(fd, mainvar, ob->rigidbody_constraint->ob2);
+       }
+
 }
 
 static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
@@ -9144,6 +9829,11 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
                }
                SEQ_END
        }
+       
+       if (sce->rigidbody_world) {
+               expand_doit(fd, mainvar, sce->rigidbody_world->group);
+               expand_doit(fd, mainvar, sce->rigidbody_world->constraints);
+       }
 
 #ifdef DURIAN_CAMERA_SWITCH
        {
@@ -9218,20 +9908,24 @@ static void expand_mask(FileData *fd, Main *mainvar, Mask *mask)
        }
 }
 
-static void expand_main(FileData *fd, Main *mainvar)
+void BLO_main_expander(void (*expand_doit_func)(void *, Main *, void *))
+{
+       expand_doit = expand_doit_func;
+}
+
+void BLO_expand_main(void *fdhandle, Main *mainvar)
 {
        ListBase *lbarray[MAX_LIBARRAY];
+       FileData *fd = fdhandle;
        ID *id;
        int a, do_it = TRUE;
        
-       if (fd == NULL) return;
-       
        while (do_it) {
                do_it = FALSE;
                
                a = set_listbasepointers(mainvar, lbarray);
                while (a--) {
-                       id= lbarray[a]->first;
+                       id = lbarray[a]->first;
                        while (id) {
                                if (id->flag & LIB_NEED_EXPAND) {
                                        switch (GS(id->name)) {
@@ -9316,6 +10010,9 @@ static void expand_main(FileData *fd, Main *mainvar)
        }
 }
 
+
+/* ***************************** */
+       
 static int object_in_any_scene(Main *mainvar, Object *ob)
 {
        Scene *sce;
@@ -9371,7 +10068,7 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const
                                
                                if (do_it) {
                                        base = MEM_callocN(sizeof(Base), "add_ext_base");
-                                       BLI_addtail(&(sce->base), base);
+                                       BLI_addtail(&sce->base, base);
                                        base->lay = ob->lay;
                                        base->object = ob;
                                        base->flag = ob->flag;
@@ -9395,7 +10092,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(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;
                        
@@ -9464,6 +10161,28 @@ static ID *append_named_part(Main *mainl, FileData *fd, const char *idname, cons
        return (found) ? id : NULL;
 }
 
+/* simple reader for copy/paste buffers */
+void BLO_library_append_all(Main *mainl, BlendHandle *bh)
+{
+       FileData *fd = (FileData *)(bh);
+       BHead *bhead;
+       ID *id = NULL;
+       
+       for (bhead = blo_firstbhead(fd); bhead; bhead = blo_nextbhead(fd, bhead)) {
+               if (bhead->code == ENDB)
+                       break;
+               if (bhead->code == ID_OB)
+                       read_libblock(fd, mainl, bhead, LIB_TESTIND, &id);
+                       
+               if (id) {
+                       /* sort by name in list */
+                       ListBase *lb = which_libbase(mainl, GS(id->name));
+                       id_sort_by_name(lb, id);
+               }
+       }
+}
+
+
 static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, const char *idname, const int idcode, const int flag)
 {
        ID *id= append_named_part(mainl, fd, idname, idcode);
@@ -9568,8 +10287,11 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in
        Main *mainvar;
        Library *curlib;
        
+       /* expander now is callback function */
+       BLO_main_expander(expand_doit_library);
+       
        /* make main consistent */
-       expand_main(*fd, mainl);
+       BLO_expand_main(*fd, mainl);
        
        /* do this when expand found other libs */
        read_libraries(*fd, (*fd)->mainlist);
@@ -9664,6 +10386,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
        ListBase *lbarray[MAX_LIBARRAY];
        int a, do_it = TRUE;
        
+       /* expander now is callback function */
+       BLO_main_expander(expand_doit_library);
+       
        while (do_it) {
                do_it = FALSE;
                
@@ -9677,13 +10402,26 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                FileData *fd = mainptr->curlib->filedata;
                                
                                if (fd == NULL) {
+                                       
                                        /* printf and reports for now... its important users know this */
-                                       BKE_reportf_wrap(basefd->reports, RPT_INFO,
-                                                        "Read library:  '%s', '%s'",
-                                                        mainptr->curlib->filepath, mainptr->curlib->name);
                                        
-                                       fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
-
+                                       /* if packed file... */
+                                       if (mainptr->curlib->packedfile) {
+                                               PackedFile *pf = mainptr->curlib->packedfile;
+                                               
+                                               BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library:  '%s'"),
+                                                                                mainptr->curlib->name);
+                                               fd = blo_openblendermemory(pf->data, pf->size, basefd->reports);
+                                               
+                                               
+                                               /* needed for library_append and read_libraries */
+                                               BLI_strncpy(fd->relabase, mainptr->curlib->filepath, sizeof(fd->relabase));
+                                       }
+                                       else {
+                                               BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library:  '%s', '%s'"),
+                                                                                mainptr->curlib->filepath, mainptr->curlib->name);
+                                               fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports);
+                                       }
                                        /* allow typing in a new lib path */
                                        if (G.debug_value == -666) {
                                                while (fd == NULL) {
@@ -9732,8 +10470,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                        else mainptr->curlib->filedata = NULL;
                                        
                                        if (fd == NULL) {
-                                               BKE_reportf_wrap(basefd->reports, RPT_WARNING,
-                                                                "Cannot find lib '%s'",
+                                               BKE_reportf_wrap(basefd->reports, RPT_WARNING, TIP_("Cannot find lib '%s'"),
                                                                 mainptr->curlib->filepath);
                                        }
                                }
@@ -9752,7 +10489,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                                append_id_part(fd, mainptr, id, &realid);
                                                                if (!realid) {
                                                                        BKE_reportf_wrap(fd->reports, RPT_WARNING,
-                                                                                        "LIB ERROR: %s: '%s' missing from '%s'",
+                                                                                        TIP_("LIB ERROR: %s: '%s' missing from '%s'"),
                                                                                         BKE_idcode_to_name(GS(id->name)),
                                                                                         id->name+2, mainptr->curlib->filepath);
                                                                }
@@ -9765,7 +10502,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                }
                                        }
                                        
-                                       expand_main(fd, mainptr);
+                                       BLO_expand_main(fd, mainptr);
                                }
                        }
                        
@@ -9784,7 +10521,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                if (id->flag & LIB_READ) {
                                        BLI_remlink(lbarray[a], id);
                                        BKE_reportf_wrap(basefd->reports, RPT_WARNING,
-                                                        "LIB ERROR: %s: '%s' unread libblock missing from '%s'",
+                                                        TIP_("LIB ERROR: %s: '%s' unread lib block missing from '%s'"),
                                                         BKE_idcode_to_name(GS(id->name)), id->name + 2, mainptr->curlib->filepath);
                                        change_idid_adr(mainlist, basefd, id, NULL);