== Constraints System ==
[blender.git] / source / blender / blenloader / intern / readfile.c
index e66a888aa4776fce4c9e74e0f248897671f1f098..c140ebb804eed205c68e163e192b1e6e2c50aebf 100644 (file)
@@ -64,6 +64,7 @@
 #include "DNA_controller_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_curve_types.h"
+#include "DNA_customdata_types.h"
 #include "DNA_effect_types.h"
 #include "DNA_fileglobal_types.h"
 #include "DNA_group_types.h"
 #include "BLI_arithb.h"
 #include "BLI_storage_types.h" // for relname flags
 
+#include "BDR_sculptmode.h"
+
 #include "BKE_bad_level_calls.h" // for reopen_text build_seqar (from WHILE_SEQ) set_rects_butspace check_imasel_copy
 
 #include "BKE_action.h"
 #include "BKE_armature.h"
 #include "BKE_constraint.h"
 #include "BKE_curve.h"
+#include "BKE_customdata.h"
 #include "BKE_deform.h"
 #include "BKE_depsgraph.h"
 #include "BKE_effect.h" // for give_parteff
 #include "BKE_global.h" // for G
 #include "BKE_group.h"
-#include "BKE_property.h" // for get_property
+#include "BKE_image.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h" // for wich_libbase
 #include "BKE_main.h" // for Main
 #include "BKE_modifier.h"
 #include "BKE_node.h" // for tree type defines
 #include "BKE_object.h"
+#include "BKE_property.h" // for get_property
 #include "BKE_sca.h" // for init_actuator
 #include "BKE_scene.h"
 #include "BKE_softbody.h"      // sbNew()
 #include "BKE_texture.h" // for open_plugin_tex
 #include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
+#include "BKE_idprop.h"
 
-#include "BIF_butspace.h" // for do_versions, patching event codes
-#include "BIF_previewrender.h" // for struct RenderInfo
+#include "BIF_butspace.h" // badlevel, for do_versions, patching event codes
+#include "BIF_previewrender.h" // bedlelvel, for struct RenderInfo
 #include "BLO_readfile.h"
 #include "BLO_undofile.h"
 #include "BLO_readblenfile.h" // streaming read pipe, for BLO_readblenfile BLO_readblenfilememory
 
+#include "multires.h"
+
 #include "readfile.h"
 
 #include "genfile.h"
@@ -233,7 +241,7 @@ typedef struct OldNewMap {
 
 
 /* local prototypes */
-extern          short freeN(void *vmemh); /* defined in util.h */  
+static void *read_struct(FileData *fd, BHead *bh, char *blockname);
 
 
 static OldNewMap *oldnewmap_new(void) 
@@ -313,7 +321,7 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr)
        return NULL;
 }
 
-/* for libdate, nr has ID code, no increment */
+/* for libdata, nr has ID code, no increment */
 static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) 
 {
        int i;
@@ -396,8 +404,10 @@ static void add_main_to_main(Main *mainvar, Main *from)
 
 void blo_join_main(ListBase *mainlist)
 {
-       Main *tojoin, *mainl= mainlist->first;
-
+       Main *tojoin, *mainl;
+       
+       
+       mainl= mainlist->first;
        while ((tojoin= mainl->next)) {
                add_main_to_main(mainl, tojoin);
                BLI_remlink(mainlist, tojoin);
@@ -431,22 +441,27 @@ static void split_libdata(ListBase *lb, Main *first)
        }
 }
 
-void blo_split_main(ListBase *mainlist)
+void blo_split_main(ListBase *mainlist, Main *main)
 {
-       Main *mainl= mainlist->first;
        ListBase *lbarray[MAX_LIBARRAY];
        Library *lib;
        int i;
 
-       for (lib= mainl->library.first; lib; lib= lib->id.next) {
+       mainlist->first= mainlist->last= main;
+       main->next= NULL;
+
+       if(main->library.first==NULL)
+               return;
+       
+       for (lib= main->library.first; lib; lib= lib->id.next) {
                Main *libmain= MEM_callocN(sizeof(Main), "libmain");
                libmain->curlib= lib;
                BLI_addtail(mainlist, libmain);
        }
 
-       i= set_listbasepointers(mainl, lbarray);
+       i= set_listbasepointers(main, lbarray);
        while(i--)
-               split_libdata(lbarray[i], mainl->next);
+               split_libdata(lbarray[i], main->next);
 }
 
 /* removes things like /blah/blah/../../blah/ etc, then writes in *name the full path */
@@ -465,7 +480,7 @@ static Main *blo_find_main(ListBase *mainlist, const char *name, const char *rel
        Library *lib;
        char name1[FILE_MAXDIR+FILE_MAXFILE];
        
-       strcpy(name1, name);
+       strncpy(name1, name, sizeof(name1)-1);
        cleanup_path(relabase, name1);
 //     printf("blo_find_main: original in  %s\n", name);
 //     printf("blo_find_main: converted to %s\n", name1);
@@ -474,7 +489,7 @@ static Main *blo_find_main(ListBase *mainlist, const char *name, const char *rel
                char *libname= (m->curlib)?m->curlib->filename:m->name;
                
                if (BLI_streq(name1, libname)) {
-                       printf("blo_find_main: found library %s\n", libname);
+                       if(G.f & G_DEBUG) printf("blo_find_main: found library %s\n", libname);
                        return m;
                }
        }
@@ -483,12 +498,12 @@ static Main *blo_find_main(ListBase *mainlist, const char *name, const char *rel
        BLI_addtail(mainlist, m);
 
        lib= alloc_libblock(&m->library, ID_LI, "lib");
-       strcpy(lib->name, name);
-       strcpy(lib->filename, name1);
+       strncpy(lib->name, name, sizeof(lib->name)-1);
+       BLI_strncpy(lib->filename, name1, sizeof(lib->filename));
        
        m->curlib= lib;
        
-       printf("blo_find_main: added new lib %s\n", name);
+       if(G.f & G_DEBUG) printf("blo_find_main: added new lib %s\n", name);
        return m;
 }
 
@@ -539,8 +554,7 @@ static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, int do_endian_swap)
                }
 
                /* this patch is to avoid a long long being read from not-eight aligned positions
-                  is necessary on SGI with -n32 compiling (no, is necessary on
-                  any modern 64bit architecture) */
+                  is necessary on any modern 64bit architecture) */
                memcpy(&old, &bhead8->old, 8);
                bhead4->old = (int) (old >> 3);
 
@@ -597,6 +611,7 @@ static BHeadN *get_bhead(FileData *fd)
                                        }
                                } else {
                                        fd->eof = 1;
+                                       bhead.len= 0;
                                }
                        } else {
                                bhead8.code = DATA;
@@ -614,6 +629,7 @@ static BHeadN *get_bhead(FileData *fd)
                                        }
                                } else {
                                        fd->eof = 1;
+                                       bhead.len= 0;
                                }
                        }
 
@@ -707,6 +723,26 @@ BHead *blo_nextbhead(FileData *fd, BHead *thisblock)
        return(bhead);
 }
 
+#if 0
+static void get_blender_subversion(FileData *fd)
+{
+       BHead *bhead;
+       
+       for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
+               if (bhead->code==GLOB) {
+                       FileGlobal *fg= read_struct(fd, bhead, "Global");
+                       fd->filesubversion= fg->subversion;
+                       fd->fileminversion= fg->minversion;
+                       fd->fileminsubversion= fg->minsubversion;
+                       MEM_freeN(fg);
+                       return;
+               } 
+               else if (bhead->code==ENDB)
+                       break;
+       }
+}
+#endif
+
 static void decode_blender_header(FileData *fd)
 {
        char header[SIZEOFBLENDERHEADER], num[4];
@@ -757,8 +793,12 @@ static int read_file_dna(FileData *fd)
                        int do_endian_swap= (fd->flags&FD_FLAGS_SWITCH_ENDIAN)?1:0;
 
                        fd->filesdna= dna_sdna_from_data(&bhead[1], bhead->len, do_endian_swap);
-                       if (fd->filesdna)
+                       if (fd->filesdna) {
+                               
                                fd->compflags= dna_get_structDNA_compareflags(fd->filesdna, fd->memsdna);
+                               /* used to retrieve ID names from (bhead+1) */
+                               fd->id_name_offs= dna_elem_offset(fd->filesdna, "ID", "char", "name[]");
+                       }
 
                        return 1;
                } else if (bhead->code==ENDB)
@@ -767,6 +807,7 @@ static int read_file_dna(FileData *fd)
 
        return 0;
 }
+
 static int fd_read_from_file(FileData *filedata, void *buffer, int size)
 {
        int readsize = read(filedata->filedes, buffer, size);
@@ -884,7 +925,8 @@ static FileData *blo_decode_and_check(FileData *fd, BlendReadError *error_r)
                        blo_freefiledata(fd);
                        fd= NULL;
                }
-       } else {
+       } 
+       else {
                *error_r = BRE_NOT_A_BLEND;
                blo_freefiledata(fd);
                fd= NULL;
@@ -979,6 +1021,8 @@ void blo_freefiledata(FileData *fd)
                        oldnewmap_free(fd->datamap);
                if (fd->globmap)
                        oldnewmap_free(fd->globmap);
+               if (fd->imamap)
+                       oldnewmap_free(fd->imamap);
                if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
                        oldnewmap_free(fd->libmap);
 
@@ -1005,6 +1049,14 @@ static void *newglobadr(FileData *fd, void *adr)         /* direct datablocks with glob
        return oldnewmap_lookup_and_inc(fd->globmap, adr);
 }
 
+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 *newlibadr(FileData *fd, void *lib, void *adr)             /* only lib data */
 {
        return oldnewmap_liblookup(fd->libmap, adr, lib);
@@ -1014,9 +1066,8 @@ static void *newlibadr_us(FileData *fd, void *lib, void *adr)     /* increases user
 {
        ID *id= newlibadr(fd, lib, adr);
 
-       if(id) {
+       if(id)
                id->us++;
-       }
 
        return id;
 }
@@ -1052,6 +1103,81 @@ static void change_idid_adr(ListBase *mainlist, FileData *basefd, void *old, voi
        }
 }
 
+/* assumed; G.main still exists */
+void blo_make_image_pointer_map(FileData *fd)
+{
+       Image *ima= G.main->image.first;
+       Scene *sce= G.main->scene.first;
+       
+       fd->imamap= oldnewmap_new();
+       
+       for(;ima; ima= ima->id.next) {
+               Link *ibuf= ima->ibufs.first;
+               for(; ibuf; ibuf= ibuf->next) 
+                       oldnewmap_insert(fd->imamap, ibuf, ibuf, 0);
+       }
+       for(; sce; sce= sce->id.next) {
+               if(sce->nodetree) {
+                       bNode *node;
+                       for(node= sce->nodetree->nodes.first; node; node= node->next)
+                               oldnewmap_insert(fd->imamap, node->preview, node->preview, 0);
+               }
+       }
+}
+
+/* set G.main image ibufs to zero if it has been restored */
+/* this works because freeing G.main only happens after this call */
+void blo_end_image_pointer_map(FileData *fd)
+{
+       OldNew *entry= fd->imamap->entries;
+       Image *ima= G.main->image.first;
+       Scene *sce= G.main->scene.first;
+       int i;
+       
+       /* used entries were restored, so we put them to zero */
+       for (i=0; i<fd->imamap->nentries; i++, entry++) {
+               if (entry->nr>0)
+                       entry->newp= NULL;
+       }
+       
+       for(;ima; ima= ima->id.next) {
+               Link *ibuf, *next;
+               
+               /* this mirrors direct_link_image */
+               for(ibuf= ima->ibufs.first; ibuf; ibuf= next) {
+                       next= ibuf->next;
+                       if(NULL==newimaadr(fd, ibuf)) { /* so was restored */
+                               BLI_remlink(&ima->ibufs, ibuf);
+                               ima->bindcode= 0;
+                       }
+               }
+       }
+       for(; sce; sce= sce->id.next) {
+               if(sce->nodetree) {
+                       bNode *node;
+                       for(node= sce->nodetree->nodes.first; node; node= node->next)
+                               node->preview= newimaadr(fd, node->preview);
+               }
+       }
+}
+
+/* undo file support: add all library pointers in lookup */
+void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd)
+{
+       Main *ptr= mainlist->first;
+       ListBase *lbarray[MAX_LIBARRAY];
+       
+       for(ptr= ptr->next; ptr; ptr= ptr->next) {
+               int i= set_listbasepointers(ptr, lbarray);
+               while(i--) {
+                       ID *id;
+                       for(id= lbarray[i]->first; id; id= id->next)
+                               oldnewmap_insert(fd->libmap, id, id, GS(id->name));
+               }
+       }
+}
+               
+
 /* ********** END OLD POINTERS ****************** */
 /* ********** READ FILE ****************** */
 
@@ -1060,7 +1186,7 @@ static void switch_endian_structs(struct SDNA *filesdna, BHead *bhead)
        int blocksize, nblocks;
        char *data;
 
-       data= (char *)(bhead+1); /*  BHEAD+DATA dependancy */
+       data= (char *)(bhead+1);
        blocksize= filesdna->typelens[ filesdna->structs[bhead->SDNAnr][0] ];
 
        nblocks= bhead->nr;
@@ -1076,6 +1202,7 @@ static void *read_struct(FileData *fd, BHead *bh, char *blockname)
        void *temp= NULL;
 
        if (bh->len) {
+               /* switch is based on file dna */
                if (bh->SDNAnr && (fd->flags & FD_FLAGS_SWITCH_ENDIAN))
                        switch_endian_structs(fd->filesdna, bh);
 
@@ -1084,7 +1211,7 @@ static void *read_struct(FileData *fd, BHead *bh, char *blockname)
                                temp= dna_reconstruct(fd->memsdna, fd->filesdna, fd->compflags, bh->SDNAnr, bh->nr, (bh+1));
                        } else {
                                temp= MEM_mallocN(bh->len, blockname);
-                               memcpy(temp, (bh+1), bh->len); /*  BHEAD+DATA dependancy */
+                               memcpy(temp, (bh+1), bh->len);
                        }
                }
        }
@@ -1096,11 +1223,11 @@ static void link_list(FileData *fd, ListBase *lb)               /* only direct data */
 {
        Link *ln, *prev;
 
-       if(lb->first==0) return;
+       if(lb->first==NULL) return;
 
        lb->first= newdataadr(fd, lb->first);
        ln= lb->first;
-       prev= 0;
+       prev= NULL;
        while(ln) {
                ln->next= newdataadr(fd, ln->next);
                ln->prev= prev;
@@ -1183,8 +1310,67 @@ static void test_pointer_array(FileData *fd, void **mat)
        }
 }
 
-/* ************ READ Brush *************** */
+/* ************ READ ID Properties *************** */
+
+void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, void *fd);
+void IDP_LibLinkProperty(IDProperty *prop, int switch_endian, void *fd);
+
+void IDP_DirectLinkArray(IDProperty *prop, int switch_endian, void *fd)
+{
+       int i;
+
+       /*since we didn't save the extra buffer, set totallen to len.*/
+       prop->totallen = prop->len;
+       prop->data.pointer = newdataadr(fd, prop->data.pointer);
+
+       if (switch_endian) {
+               for (i=0; i<prop->len; i++) {
+                       SWITCH_INT(((int*)prop->data.pointer)[i]);
+               }
+       }
+}
+
+void IDP_DirectLinkString(IDProperty *prop, int switch_endian, void *fd)
+{
+       /*since we didn't save the extra string buffer, set totallen to len.*/
+       prop->totallen = prop->len;
+       prop->data.pointer = newdataadr(fd, prop->data.pointer);
+}
+
+void IDP_DirectLinkGroup(IDProperty *prop, int switch_endian, void *fd)
+{
+       ListBase *lb = &prop->data.group;
+       IDProperty *loop;
+
+       link_list(fd, lb);
+
+       /*Link child id properties now*/
+       for (loop=prop->data.group.first; loop; loop=loop->next) {
+               IDP_DirectLinkProperty(loop, switch_endian, fd);
+       }
+}
+
+void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, void *fd)
+{
+       switch (prop->type) {
+               case IDP_GROUP:
+                       IDP_DirectLinkGroup(prop, switch_endian, fd);
+                       break;
+               case IDP_STRING:
+                       IDP_DirectLinkString(prop, switch_endian, fd);
+                       break;
+               case IDP_ARRAY:
+                       IDP_DirectLinkArray(prop, switch_endian, fd);
+                       break;
+       }
+}
+
+/*stub function*/
+void IDP_LibLinkProperty(IDProperty *prop, int switch_endian, void *fd)
+{
+}
 
+/* ************ READ Brush *************** */
 /* library brush linking after fileread */
 static void lib_link_brush(FileData *fd, Main *main)
 {
@@ -1292,7 +1478,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
        bNodeSocket *sock;
        bNodeLink *link;
        
-       ntree->init= 0;         /* to set callbacks */
+       ntree->init= 0;         /* to set callbacks and force setting types */
        ntree->owntype= NULL;
        ntree->timecursor= NULL;
        
@@ -1304,9 +1490,12 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                        /* 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);
-                       else if(ntree->type==NTREE_COMPOSIT && (node->type==CMP_NODE_TIME || node->type==CMP_NODE_CURVE_VEC || node->type==CMP_NODE_CURVE_RGB))
-                               direct_link_curvemapping(fd, node->storage);
-                       
+                       else if(ntree->type==NTREE_COMPOSIT) {
+                               if( ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB))
+                                       direct_link_curvemapping(fd, node->storage);
+                               else if(ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
+                                       ((ImageUser *)node->storage)->ok= 1;
+                       }
                }
                link_list(fd, &node->inputs);
                link_list(fd, &node->outputs);
@@ -1315,7 +1504,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
        
        /* and we connect the rest */
        for(node= ntree->nodes.first; node; node= node->next) {
-               node->preview= NULL;
+               node->preview= newimaadr(fd, node->preview);
                node->lasty= 0;
                for(sock= node->inputs.first; sock; sock= sock->next)
                        sock->link= newdataadr(fd, sock->link);
@@ -1390,11 +1579,14 @@ static void direct_link_scriptlink(FileData *fd, ScriptLink *slink)
 static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist)
 {
        bActionStrip *strip;
-
+       bActionModifier *amod;
+       
        for (strip=striplist->first; strip; strip=strip->next){
                strip->object = newlibadr(fd, id->lib, strip->object);
                strip->act = newlibadr_us(fd, id->lib, strip->act);
                strip->ipo = newlibadr(fd, id->lib, strip->ipo);
+               for(amod= strip->modifiers.first; amod; amod= amod->next)
+                       amod->ob= newlibadr(fd, id->lib, amod->ob);
        }
 }
 
@@ -1419,6 +1611,15 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                }
 
                switch (con->type) {
+               case CONSTRAINT_TYPE_PYTHON:
+                       {
+                               bPythonConstraint *data;
+                               data= (bPythonConstraint*)con->data;
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                               data->text = newlibadr(fd, id->lib, data->text);
+                               //IDP_LibLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+                       }
+                       break;
                case CONSTRAINT_TYPE_ACTION:
                        {
                                bActionConstraint *data;
@@ -1432,21 +1633,21 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                bLocateLikeConstraint *data;
                                data= ((bLocateLikeConstraint*)con->data);
                                data->tar = newlibadr(fd, id->lib, data->tar);
-                       };
+                       }
                        break;
                case CONSTRAINT_TYPE_ROTLIKE:
                        {
                                bRotateLikeConstraint *data;
                                data= ((bRotateLikeConstraint*)con->data);
                                data->tar = newlibadr(fd, id->lib, data->tar);
-                       };
+                       }
                        break;
                case CONSTRAINT_TYPE_SIZELIKE:
                        {
                                bSizeLikeConstraint *data;
                                data= ((bSizeLikeConstraint*)con->data);
                                data->tar = newlibadr(fd, id->lib, data->tar);
-                       };
+                       }
                        break;
                case CONSTRAINT_TYPE_KINEMATIC:
                        {
@@ -1474,48 +1675,43 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                bLockTrackConstraint *data;
                                data= ((bLockTrackConstraint*)con->data);
                                data->tar = newlibadr(fd, id->lib, data->tar);
-                       };
+                       }
                        break;
                case CONSTRAINT_TYPE_FOLLOWPATH:
                        {
                                bFollowPathConstraint *data;
                                data= ((bFollowPathConstraint*)con->data);
                                data->tar = newlibadr(fd, id->lib, data->tar);
-                       };
-                       break;
-               case CONSTRAINT_TYPE_DISTANCELIMIT:
-                       {
-                               bDistanceLimitConstraint *data;
-                               data= ((bDistanceLimitConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       };
+                       }
                        break;
                case CONSTRAINT_TYPE_STRETCHTO:
                        {
                                bStretchToConstraint *data;
                                data= ((bStretchToConstraint*)con->data);
                                data->tar = newlibadr(fd, id->lib, data->tar);
-                       };
+                       }
                        break;
-               case CONSTRAINT_TYPE_LOCLIMIT:
+               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
                        {
-                               bLocLimitConstraint *data;
-                               data= ((bLocLimitConstraint*)con->data);
-                       };
+                               bRigidBodyJointConstraint *data;
+                               data= ((bRigidBodyJointConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       }
                        break;
-               case CONSTRAINT_TYPE_ROTLIMIT:
+               case CONSTRAINT_TYPE_CLAMPTO:
                        {
-                               bRotLimitConstraint *data;
-                               data= ((bRotLimitConstraint*)con->data);
-                       };
+                               bClampToConstraint *data;
+                               data= ((bClampToConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       }
                        break;
-               case CONSTRAINT_TYPE_SIZELIMIT:
+               case CONSTRAINT_TYPE_CHILDOF:
                        {
-                               bSizeLimitConstraint *data;
-                               data= ((bSizeLimitConstraint*)con->data);
-                       };
+                               bChildOfConstraint *data;
+                               data= ((bChildOfConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       }
                        break;
-
                case CONSTRAINT_TYPE_NULL:
                        break;
                }
@@ -1529,6 +1725,11 @@ static void direct_link_constraints(FileData *fd, ListBase *lb)
        link_list(fd, lb);
        for (cons=lb->first; cons; cons=cons->next) {
                cons->data = newdataadr(fd, cons->data);
+               if (cons->type == CONSTRAINT_TYPE_PYTHON) {
+                       bPythonConstraint *data= cons->data;
+                       data->prop = newdataadr(fd, data->prop);
+                       IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+               }
        }
 }
 
@@ -1536,18 +1737,30 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
 {
        bPoseChannel *pchan;
        bArmature *arm= ob->data;
-       int rebuild= 0;
+       int rebuild;
+       
        if (!pose || !arm)
                return;
+       
+       /* always rebuild to match proxy or lib changes */
+       rebuild= ob->proxy || (ob->id.lib==NULL && arm->id.lib);
 
        for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
                lib_link_constraints(fd, (ID *)ob, &pchan->constraints);
-               // hurms... loop in a loop, but yah... later... (ton)
+               
+               /* hurms... loop in a loop, but yah... later... (ton) */
                pchan->bone= get_named_bone(arm, pchan->name);
+               
                pchan->custom= newlibadr(fd, arm->id.lib, pchan->custom);
                if(pchan->bone==NULL)
                        rebuild= 1;
+               else if(ob->id.lib==NULL && arm->id.lib) {
+                       /* local pose selection copied to armature, bit hackish */
+                       pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE);
+                       pchan->bone->flag |= pchan->selectflag;
+               }
        }
+       
        if(rebuild) {
                ob->recalc= OB_RECALC;
                pose->flag |= POSE_RECALC;
@@ -1961,6 +2174,7 @@ static void lib_link_image(FileData *fd, Main *main)
        ima= main->image.first;
        while (ima) {
                if(ima->id.flag & LIB_NEEDLINK) {
+                       if (ima->id.properties) IDP_LibLinkProperty(ima->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 
                        ima->id.flag -= LIB_NEEDLINK;
                }
@@ -1968,14 +2182,40 @@ static void lib_link_image(FileData *fd, Main *main)
        }
 }
 
+static void link_ibuf_list(FileData *fd, ListBase *lb)
+{
+       Link *ln, *prev;
+       
+       if(lb->first==NULL) return;
+       
+       lb->first= newimaadr(fd, lb->first);
+       ln= lb->first;
+       prev= NULL;
+       while(ln) {
+               ln->next= newimaadr(fd, ln->next);
+               ln->prev= prev;
+               prev= ln;
+               ln= ln->next;
+       }
+       lb->last= prev;
+}
+
 static void direct_link_image(FileData *fd, Image *ima)
 {
-       ima->ibuf= NULL;
+       /* for undo system, pointers could be restored */
+       if(fd->imamap)
+               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->anim= NULL;
-       memset(ima->mipmap, 0, sizeof(ima->mipmap));
-       ima->repbind= 0;
-       ima->bindcode= 0;
-
+       ima->rr= NULL;
+       ima->repbind= NULL;
+       
        ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
        ima->preview = direct_link_preview_image(fd, ima->preview);
        ima->ok= 1;
@@ -2107,14 +2347,20 @@ static void direct_link_texture(FileData *fd, Tex *tex)
        if(tex->plugin) {
                tex->plugin->handle= 0;
                open_plugin_tex(tex->plugin);
+               /* initialize data for this instance, if an initialization
+                * function exists.
+                */
+               if (tex->plugin->instance_init)
+                       tex->plugin->instance_init((void *) tex->plugin->data);
        }
        tex->coba= newdataadr(fd, tex->coba);
        tex->env= newdataadr(fd, tex->env);
        if(tex->env) {
-               tex->env->ima= 0;
+               tex->env->ima= NULL;
                memset(tex->env->cube, 0, 6*sizeof(void *));
                tex->env->ok= 0;
        }
+       tex->iuser.ok= 1;
 }
 
 
@@ -2130,6 +2376,9 @@ static void lib_link_material(FileData *fd, Main *main)
        ma= main->mat.first;
        while(ma) {
                if(ma->id.flag & LIB_NEEDLINK) {
+                       /*Link ID Properties -- and copy this comment EXACTLY for easy finding
+                       of library blocks that implement this.*/
+                       if (ma->id.properties) IDP_LibLinkProperty(ma->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 
                        ma->ipo= newlibadr_us(fd, ma->id.lib, ma->ipo);
                        ma->group= newlibadr_us(fd, ma->id.lib, ma->group);
@@ -2172,6 +2421,30 @@ static void direct_link_material(FileData *fd, Material *ma)
 
 /* ************ READ MESH ***************** */
 
+static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
+{
+       MTFace *tf= mtface;
+       int i;
+
+       for (i=0; i<totface; i++, tf++) {
+               tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
+               if(tf->tpage && tf->tpage->id.us==0)
+                       tf->tpage->id.us= 1;
+       }
+}
+
+static void lib_link_customdata_mtface(FileData *fd, Mesh *me, CustomData *fdata, int totface)
+{
+       int i;  
+       for(i=0; i<fdata->totlayer; i++) {
+               CustomDataLayer *layer = &fdata->layers[i];
+               
+               if(layer->type == CD_MTFACE)
+                       lib_link_mtface(fd, me, layer->data, totface);
+       }
+
+}
+
 static void lib_link_mesh(FileData *fd, Main *main)
 {
        Mesh *me;
@@ -2181,6 +2454,10 @@ static void lib_link_mesh(FileData *fd, Main *main)
                if(me->id.flag & LIB_NEEDLINK) {
                        int i;
 
+                       /*Link ID Properties -- and copy this comment EXACTLY for easy finding
+                       of library blocks that implement this.*/
+                       if (me->id.properties) IDP_LibLinkProperty(me->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
                        /* this check added for python created meshes */
                        if(me->mat) {
                                for(i=0; i<me->totcol; i++) {
@@ -2193,20 +2470,11 @@ static void lib_link_mesh(FileData *fd, Main *main)
                        me->key= newlibadr_us(fd, me->id.lib, me->key);
                        me->texcomesh= newlibadr_us(fd, me->id.lib, me->texcomesh);
 
-                       if(me->tface) {
-                               TFace *tfaces= me->tface;
-
-                               for (i=0; i<me->totface; i++) {
-                                       TFace *tf= &tfaces[i];
+                       lib_link_customdata_mtface(fd, me, &me->fdata, me->totface);
+                       if(me->mr && me->mr->levels.first)
+                               lib_link_customdata_mtface(fd, me, &me->mr->fdata,
+                                                          ((MultiresLevel*)me->mr->levels.first)->totface);
 
-                                       tf->tpage= newlibadr(fd, me->id.lib, tf->tpage);
-                                       if(tf->tpage) {
-                                               Image *ima= tf->tpage;
-                                               if(ima->id.us==0)
-                                                       ima->id.us= 1;
-                                       }
-                               }
-                       }
                        me->id.flag -= LIB_NEEDLINK;
                }
                me= me->id.next;
@@ -2227,6 +2495,22 @@ static void direct_link_dverts(FileData *fd, int count, MDeformVert *mdverts)
        }
 }
 
+static void direct_link_customdata(FileData *fd, CustomData *data, int count)
+{
+       int i = 0;
+
+       data->layers= newdataadr(fd, data->layers);
+
+       while (i < data->totlayer) {
+               CustomDataLayer *layer = &data->layers[i];
+
+               if (CustomData_verify_versions(data, i)) {
+                       layer->data = newdataadr(fd, layer->data);
+                       i++;
+               }
+       }
+}
+
 static void direct_link_mesh(FileData *fd, Mesh *mesh)
 {
        mesh->mat= newdataadr(fd, mesh->mat);
@@ -2236,30 +2520,76 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
        mesh->medge= newdataadr(fd, mesh->medge);
        mesh->mface= newdataadr(fd, mesh->mface);
        mesh->tface= newdataadr(fd, mesh->tface);
+       mesh->mtface= newdataadr(fd, mesh->mtface);
        mesh->mcol= newdataadr(fd, mesh->mcol);
        mesh->msticky= newdataadr(fd, mesh->msticky);
-
        mesh->dvert= newdataadr(fd, mesh->dvert);
-       direct_link_dverts(fd, mesh->totvert, mesh->dvert);
+       
+       /* Partial-mesh visibility (do this before using totvert, totface, or totedge!) */
+       mesh->pv= newdataadr(fd, mesh->pv);
+       if(mesh->pv) {
+               mesh->pv->vert_map= newdataadr(fd, mesh->pv->vert_map);
+               mesh->pv->edge_map= newdataadr(fd, mesh->pv->edge_map);
+               mesh->pv->old_faces= newdataadr(fd, mesh->pv->old_faces);
+               mesh->pv->old_edges= newdataadr(fd, mesh->pv->old_edges);
+       }
+
+       /* normally direct_link_dverts should be called in direct_link_customdata,
+          but for backwards compat in do_versions to work we do it here */
+       direct_link_dverts(fd, mesh->pv ? mesh->pv->totvert : mesh->totvert, mesh->dvert);
+
+       direct_link_customdata(fd, &mesh->vdata, mesh->pv ? mesh->pv->totvert : mesh->totvert);
+       direct_link_customdata(fd, &mesh->edata, mesh->pv ? mesh->pv->totedge : mesh->totedge);
+       direct_link_customdata(fd, &mesh->fdata, mesh->pv ? mesh->pv->totface : mesh->totface);
 
        mesh->bb= NULL;
        mesh->oc= 0;
-       mesh->dface= NULL;
        mesh->mselect= NULL;
+
+       /* Multires data */
+       mesh->mr= newdataadr(fd, mesh->mr);
+       if(mesh->mr) {
+               MultiresLevel *lvl;
+               
+               link_list(fd, &mesh->mr->levels);
+               lvl= mesh->mr->levels.first;
+               
+               direct_link_customdata(fd, &mesh->mr->vdata, lvl->totvert);
+               direct_link_dverts(fd, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT));
+               direct_link_customdata(fd, &mesh->mr->fdata, lvl->totface);
+               
+               if(mesh->mr->edge_flags)
+                       mesh->mr->edge_flags= newdataadr(fd, mesh->mr->edge_flags);
+               if(mesh->mr->edge_creases)
+                       mesh->mr->edge_creases= newdataadr(fd, mesh->mr->edge_creases);
+               
+               if(!mesh->mr->edge_flags)
+                       mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags");
+               if(!mesh->mr->edge_creases)
+                       mesh->mr->edge_creases= MEM_callocN(sizeof(char)*lvl->totedge, "Multires Edge Creases");
+
+               mesh->mr->verts = newdataadr(fd, mesh->mr->verts);
+                       
+               for(; lvl; lvl= lvl->next) {
+                       lvl->verts= newdataadr(fd, lvl->verts);
+                       lvl->faces= newdataadr(fd, lvl->faces);
+                       lvl->edges= newdataadr(fd, lvl->edges);
+                       lvl->colfaces= newdataadr(fd, lvl->colfaces);
+                       lvl->edge_boundary_states= NULL;
+                       lvl->vert_face_map = lvl->vert_edge_map = NULL;
+                       lvl->map_mem= NULL;
+               }
+       }
        
-       if (mesh->tface) {
-               TFace *tfaces= mesh->tface;
+       if((fd->flags & FD_FLAGS_SWITCH_ENDIAN) && mesh->tface) {
+               TFace *tf= mesh->tface;
                int i;
 
-               for (i=0; i<mesh->totface; i++) {
-                       TFace *tf= &tfaces[i];
-
-                       if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
-                               SWITCH_INT(tf->col[0]);
-                               SWITCH_INT(tf->col[1]);
-                               SWITCH_INT(tf->col[2]);
-                               SWITCH_INT(tf->col[3]);
-                       }
+               for (i=0; i< (mesh->pv ? mesh->pv->totface : mesh->totface); i++, tf++) {
+                       SWITCH_INT(tf->col[0]);
+                       SWITCH_INT(tf->col[1]);
+                       SWITCH_INT(tf->col[2]);
+                       SWITCH_INT(tf->col[3]);
                }
        }
 }
@@ -2300,6 +2630,9 @@ static void lib_link_modifiers__linkModifiers(void *userData, Object *ob,
        FileData *fd = userData;
 
        *idpoin = newlibadr(fd, ob->id.lib, *idpoin);
+       /* hardcoded bad exception; non-object modifier data gets user count (texture, displace) */
+       if(*idpoin && GS((*idpoin)->name)!=ID_OB)
+               (*idpoin)->us++;
 }
 static void lib_link_modifiers(FileData *fd, Object *ob)
 {
@@ -2319,6 +2652,7 @@ static void lib_link_object(FileData *fd, Main *main)
        ob= main->object.first;
        while(ob) {
                if(ob->id.flag & LIB_NEEDLINK) {
+                       if (ob->id.properties) IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
 
                        ob->parent= newlibadr(fd, ob->id.lib, ob->parent);
                        ob->track= newlibadr(fd, ob->id.lib, ob->track);
@@ -2326,6 +2660,22 @@ static void lib_link_object(FileData *fd, Main *main)
                        ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
                        ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
                        
+                       ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
+                       if(ob->proxy) {
+                               /* paranoia check, actually a proxy_from pointer should never be written... */
+                               if(ob->proxy->id.lib==NULL) {
+                                       ob->proxy->proxy_from= NULL;
+                                       ob->proxy= NULL;
+                               }
+                               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->proxy_group= newlibadr(fd, ob->id.lib, ob->proxy_group);
+
                        poin= ob->data;
                        ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
                           
@@ -2333,7 +2683,14 @@ static void lib_link_object(FileData *fd, Main *main)
                                ob->type= OB_EMPTY;
                                warn= 1;
                                if(ob->id.lib) printf("Can't find obdata of %s lib %s\n", ob->id.name+2, ob->id.lib->name);
-                               else printf("Object %s lost data. Lib:%x\n", ob->id.name+2, (unsigned int) ob->id.lib);
+                               else printf("Object %s lost data.", ob->id.name+2);
+                               
+                               if(ob->pose) {
+                                       free_pose_channels(ob->pose);
+                                       MEM_freeN(ob->pose);
+                                       ob->pose= NULL;
+                                       ob->flag &= ~OB_POSEMODE;
+                               }
                        }
                        for(a=0; a<ob->totcol; a++) ob->mat[a]= newlibadr_us(fd, ob->id.lib, ob->mat[a]);
 
@@ -2414,8 +2771,10 @@ static void lib_link_object(FileData *fd, Main *main)
                                        if(eoa==NULL) {
                                                init_actuator(act);
                                        }
-                                       eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
-                                       eoa->me= newlibadr(fd, ob->id.lib, eoa->me);
+                                       else {
+                                               eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
+                                               eoa->me= newlibadr(fd, ob->id.lib, eoa->me);
+                                       }
                                }
                                else if(act->type==ACT_SCENE) {
                                        bSceneActuator *sa= act->data;
@@ -2502,6 +2861,16 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
        }
 }
 
+static void direct_link_nlastrips(FileData *fd, ListBase *strips)
+{
+       bActionStrip *strip;
+       
+       link_list(fd, strips);
+       
+       for(strip= strips->first; strip; strip= strip->next)
+               link_list(fd, &strip->modifiers);
+}
+
 static void direct_link_object(FileData *fd, Object *ob)
 {
        PartEff *paf;
@@ -2520,7 +2889,7 @@ static void direct_link_object(FileData *fd, Object *ob)
        direct_link_pose(fd, ob->pose);
 
        link_list(fd, &ob->defbase);
-       link_list(fd, &ob->nlastrips);
+       direct_link_nlastrips(fd, &ob->nlastrips);
        link_list(fd, &ob->constraintChannels);
 
        direct_link_scriptlink(fd, &ob->scriptlink);
@@ -2589,6 +2958,8 @@ static void direct_link_object(FileData *fd, Object *ob)
                
                sb->bpoint= NULL;       // init pointers so it gets rebuilt nicely
                sb->bspring= NULL;
+               sb->scratch= NULL;
+
                
                sb->keys= newdataadr(fd, sb->keys);
                test_pointer_array(fd, (void **)&sb->keys);
@@ -2686,11 +3057,16 @@ static void lib_link_scene(FileData *fd, Main *main)
        Base *base, *next;
        Editing *ed;
        Sequence *seq;
-
+       SceneRenderLayer *srl;
+       int a;
+       
        sce= main->scene.first;
        while(sce) {
                if(sce->id.flag & LIB_NEEDLINK) {
-                       
+                       /*Link ID Properties -- and copy this comment EXACTLY for easy finding
+                       of library blocks that implement this.*/
+                       if (sce->id.properties) IDP_LibLinkProperty(sce->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
                        sce->camera= newlibadr(fd, sce->id.lib, sce->camera);
                        sce->world= newlibadr_us(fd, sce->id.lib, sce->world);
                        sce->set= newlibadr(fd, sce->id.lib, sce->set);
@@ -2698,8 +3074,14 @@ static void lib_link_scene(FileData *fd, Main *main)
                        sce->toolsettings->imapaint.brush=
                                newlibadr_us(fd, sce->id.lib, sce->toolsettings->imapaint.brush);
 
-                       base= sce->base.first;
-                       while(base) {
+                       /* Sculptdata textures */
+                       for(a=0; a<MAX_MTEX; ++a) {
+                               MTex *mtex= sce->sculptdata.mtex[a];
+                               if(mtex)
+                                       mtex->tex= newlibadr_us(fd, sce->id.lib, mtex->tex);
+                       }
+
+                       for(base= sce->base.first; base; base= next) {
                                next= base->next;
 
                                /* base->object= newlibadr_us(fd, sce->id.lib, base->object); */
@@ -2714,7 +3096,6 @@ static void lib_link_scene(FileData *fd, Main *main)
                                        if(base==sce->basact) sce->basact= 0;
                                        MEM_freeN(base);
                                }
-                               base= next;
                        }
 
                        ed= sce->ed;
@@ -2739,7 +3120,12 @@ static void lib_link_scene(FileData *fd, Main *main)
                        
                        if(sce->nodetree)
                                lib_link_ntree(fd, &sce->id, sce->nodetree);
-
+                       
+                       for(srl= sce->r.layers.first; srl; srl= srl->next) {
+                               srl->mat_override= newlibadr_us(fd, sce->id.lib, srl->mat_override);
+                               srl->light_override= newlibadr_us(fd, sce->id.lib, srl->light_override);
+                       }
+                       
                        sce->id.flag -= LIB_NEEDLINK;
                }
 
@@ -2771,7 +3157,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        sce->dagisvalid = 0;
        /* set users to one by default, not in lib-link, this will increase it for compo nodes */
        sce->id.us= 1;
-       
+
        link_list(fd, &(sce->base));
 
        sce->basact= newdataadr(fd, sce->basact);
@@ -2779,8 +3165,15 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        sce->radio= newdataadr(fd, sce->radio);
        
        sce->toolsettings= newdataadr(fd, sce->toolsettings);
-       
+
+       sce->sculptdata.session= NULL;
+       /* SculptData textures */
+       for(a=0; a<MAX_MTEX; ++a)
+               sce->sculptdata.mtex[a]= newdataadr(fd,sce->sculptdata.mtex[a]);
+
        if(sce->ed) {
+               ListBase *old_seqbasep= &((Editing *)sce->ed)->seqbase;
+               
                ed= sce->ed= newdataadr(fd, sce->ed);
 
                /* recursive link sequences, lb will be correctly initialized */
@@ -2867,28 +3260,37 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                        Sequence temp;
                        char *poin;
                        long offset;
-                       /*int seted=0;*/ /*unused*/
                        
                        offset= ((long)&(temp.seqbase)) - ((long)&temp);
-
-                       /* root pointer */
-                       poin= (char *)ed->seqbasep;
-                       poin -= offset;
-                       poin= newdataadr(fd, poin);
-                       if(poin) ed->seqbasep= (ListBase *)(poin+offset);
-                       else ed->seqbasep= &ed->seqbase;
                        
+                       /* root pointer */
+                       if(ed->seqbasep == old_seqbasep) {
+                               ed->seqbasep= &ed->seqbase;
+                       }
+                       else {
+                               
+                               poin= (char *)ed->seqbasep;
+                               poin -= offset;
+                               
+                               poin= newdataadr(fd, poin);
+                               if(poin) ed->seqbasep= (ListBase *)(poin+offset);
+                               else ed->seqbasep= &ed->seqbase;
+                       }                       
                        /* stack */
                        link_list(fd, &(ed->metastack));
                        
                        for(ms= ed->metastack.first; ms; ms= ms->next) {
                                ms->parseq= newdataadr(fd, ms->parseq);
                                
-                               poin= (char *)ms->oldbasep;
-                               poin -= offset;
-                               poin= newdataadr(fd, poin);
-                               if(poin) ms->oldbasep= (ListBase *)(poin+offset);
-                               else ms->oldbasep= &ed->seqbase;
+                               if(ms->oldbasep == old_seqbasep)
+                                       ms->oldbasep= &ed->seqbase;
+                               else {
+                                       poin= (char *)ms->oldbasep;
+                                       poin -= offset;
+                                       poin= newdataadr(fd, poin);
+                                       if(poin) ms->oldbasep= (ListBase *)(poin+offset);
+                                       else ms->oldbasep= &ed->seqbase;
+                               }
                        }
                }
        }
@@ -2960,10 +3362,8 @@ static void lib_link_screen_sequence_ipos(Main *main)
        bScreen *sc;
        ScrArea *sa;
 
-       sc= main->screen.first;
-       while(sc) {
-               sa= sc->areabase.first;
-               while(sa) {
+       for(sc= main->screen.first; sc; sc= sc->id.next) {
+               for(sa= sc->areabase.first; sa; sa= sa->next) {
                        SpaceLink *sl;
                        for (sl= sa->spacedata.first; sl; sl= sl->next) {
                                if(sl->spacetype == SPACE_IPO) {
@@ -2973,9 +3373,7 @@ static void lib_link_screen_sequence_ipos(Main *main)
                                        }
                                }
                        }
-                       sa= sa->next;
                }
-               sc= sc->id.next;
        }
 }
 
@@ -2988,8 +3386,7 @@ static void lib_link_screen(FileData *fd, Main *main)
        bScreen *sc;
        ScrArea *sa;
 
-       sc= main->screen.first;
-       while(sc) {
+       for(sc= main->screen.first; sc; sc= sc->id.next) {
                if(sc->id.flag & LIB_NEEDLINK) {
                        sc->id.us= 1;
                        sc->scene= newlibadr(fd, sc->id.lib, sc->scene);
@@ -3008,15 +3405,15 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                View3D *v3d= (View3D*) sl;
 
                                                v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
+                                               v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
 
                                                if(v3d->bgpic) {
                                                        v3d->bgpic->ima= newlibadr_us(fd, sc->id.lib, v3d->bgpic->ima);
-                                                       v3d->bgpic->tex= newlibadr_us(fd, sc->id.lib, v3d->bgpic->tex);
-                                                       v3d->bgpic->rect= NULL;
                                                }
                                                if(v3d->localvd) {
                                                        v3d->localvd->camera= newlibadr(fd, sc->id.lib, v3d->localvd->camera);
                                                }
+                                               v3d->depths= NULL;
                                                v3d->ri= NULL;
                                        }
                                        else if(sl->spacetype==SPACE_IPO) {
@@ -3038,9 +3435,11 @@ static void lib_link_screen(FileData *fd, Main *main)
                                        else if(sl->spacetype==SPACE_FILE) {
                                                SpaceFile *sfile= (SpaceFile *)sl;
 
-                                               sfile->filelist= 0;
-                                               sfile->libfiledata= 0;
-                                               sfile->returnfunc= 0;
+                                               sfile->filelist= NULL;
+                                               sfile->libfiledata= NULL;
+                                               sfile->returnfunc= NULL;
+                                               sfile->menup= NULL;
+                                               sfile->pupmenu= NULL;
                                        }
                                        else if(sl->spacetype==SPACE_IMASEL) {
                                                check_imasel_copy((SpaceImaSel *)sl);
@@ -3081,6 +3480,7 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                }
                                                so->lockpoin= NULL;
                                                so->tree.first= so->tree.last= NULL;
+                                               so->search_tse.id= newlibadr(fd, NULL, so->search_tse.id);
                                                
                                                if(so->treestore) {
                                                        tselem= so->treestore->data;
@@ -3099,30 +3499,33 @@ static void lib_link_screen(FileData *fd, Main *main)
                        }
                        sc->id.flag -= LIB_NEEDLINK;
                }
-               sc= sc->id.next;
        }
 }
 
+/* Only for undo files, or to restore a screen after reading without UI... */
 static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
 {
-       ListBase *lb;
-       ID *idn=NULL;
                
        if(id) {
-               lb= wich_libbase(mainp, GS(id->name));
+               ListBase *lb= wich_libbase(mainp, GS(id->name));
                
                if(lb) {        // there's still risk of checking corrupt mem (freed Ids in oops)
-                       idn= lb->first;
+                       ID *idn= lb->first;
+                       char *name= id->name+2;
+                       
                        while(idn) {
-                               if( strcmp(idn->name, id->name)==0) {
-                                       if(user && idn->us==0) idn->us++;
-                                       break;
+                               if(idn->name[2]==name[0] && strcmp(idn->name+2, name)==0) {
+                                       if(idn->lib==id->lib) {
+                                               if(user && idn->us==0) idn->us++;
+                                               break;
+                                       }
                                }
                                idn= idn->next;
                        }
+                       return idn;
                }
        }
-       return idn;
+       return NULL;
 }
 
 /* called from kernel/blender.c */
@@ -3133,8 +3536,7 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene)
        bScreen *sc;
        ScrArea *sa;
 
-       sc= newmain->screen.first;
-       while(sc) {
+       for(sc= newmain->screen.first; sc; sc= sc->id.next) {
                
                sc->scene= curscene;
 
@@ -3159,12 +3561,10 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene)
                                        v3d->camera= restore_pointer_by_name(newmain, (ID *)v3d->camera, 1);
                                        if(v3d->camera==NULL)
                                                v3d->camera= sc->scene->camera;
+                                       v3d->ob_centre= restore_pointer_by_name(newmain, (ID *)v3d->ob_centre, 1);
                                        
                                        if(v3d->bgpic) {
                                                v3d->bgpic->ima= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->ima, 1);
-                                               v3d->bgpic->tex= restore_pointer_by_name(newmain, (ID *)v3d->bgpic->tex, 1);
-                                               if(v3d->bgpic->rect) freeN(v3d->bgpic->rect);
-                                               v3d->bgpic->rect= NULL;
                                        }
                                        if(v3d->localvd) {
                                                Base *base;
@@ -3240,14 +3640,15 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene)
                                else if(sl->spacetype==SPACE_OOPS) {
                                        SpaceOops *so= (SpaceOops *)sl;
                                        Oops *oops;
-                                       
                                        int a;
+                                       
                                        oops= so->oops.first;
                                        while(oops) {
                                                oops->id= restore_pointer_by_name(newmain, (ID *)oops->id, 0);
                                                oops= oops->next;
                                        }
                                        so->lockpoin= NULL;
+                                       so->search_tse.id= restore_pointer_by_name(newmain, so->search_tse.id, 0);
                                        
                                        if(so->treestore) {
                                                TreeStore *ts= so->treestore;
@@ -3271,10 +3672,7 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene)
                        }
                        sa= sa->next;
                }
-
-               sc= sc->id.next;
        }
-
 }
 
 static void direct_link_screen(FileData *fd, bScreen *sc)
@@ -3326,19 +3724,27 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                link_list(fd, &(sa->spacedata));
                link_list(fd, &(sa->panels));
 
+               /* accident can happen when read/save new file with older version */
+               if(sa->spacedata.first==NULL && sa->spacetype>SPACE_NLA)
+                       sa->spacetype= SPACE_EMPTY;
+               
                for(pa= sa->panels.first; pa; pa=pa->next) {
                        pa->paneltab= newdataadr(fd, pa->paneltab);
                        pa->active= 0;
                        pa->sortcounter= 0;
                }
-
+               
                for (sl= sa->spacedata.first; sl; sl= sl->next) {
                        if (sl->spacetype==SPACE_VIEW3D) {
                                View3D *v3d= (View3D*) sl;
                                v3d->bgpic= newdataadr(fd, v3d->bgpic);
+                               if(v3d->bgpic)
+                                       v3d->bgpic->iuser.ok= 1;
                                v3d->localvd= newdataadr(fd, v3d->localvd);
                                v3d->afterdraw.first= v3d->afterdraw.last= NULL;
                                v3d->clipbb= newdataadr(fd, v3d->clipbb);
+                               v3d->retopo_view_data= NULL;
+                               v3d->properties_storage= NULL;
                        }
                        else if (sl->spacetype==SPACE_OOPS) {
                                SpaceOops *soops= (SpaceOops*) sl;
@@ -3364,7 +3770,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                sima->cumap= newdataadr(fd, sima->cumap);
                                if(sima->cumap)
                                        direct_link_curvemapping(fd, sima->cumap);
-                               sima->info_str= NULL;
+                               sima->info_str= sima->info_spare= NULL;
+                               sima->spare= NULL;
+                               sima->iuser.ok= 1;
                        }
                        else if(sl->spacetype==SPACE_NODE) {
                                SpaceNode *snode= (SpaceNode *)sl;
@@ -3423,6 +3831,8 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
        newmain= MEM_callocN(sizeof(Main), "directlink");
        BLI_addtail(&fd->mainlist, newmain);
        newmain->curlib= lib;
+
+       lib->parent= NULL;
 }
 
 static void lib_link_library(FileData *fd, Main *main)
@@ -3528,7 +3938,6 @@ static char *dataname(short id_code)
                case ID_VF: return "Data from VF";
                case ID_TXT     : return "Data from TXT";
                case ID_SO: return "Data from SO";
-               case ID_SAMPLE: return "Data from SAMPLE";
                case ID_NT: return "Data from NT";
                case ID_BR: return "Data from BR";
        }
@@ -3546,15 +3955,6 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
        ListBase *lb;
        char *allocname;
        
-       if(bhead->code==ID_ID) {
-               ID *linkedid= (ID *)(bhead + 1); /*  BHEAD+DATA dependancy */
-
-               lb= wich_libbase(main, GS(linkedid->name));
-       }
-       else {
-               lb= wich_libbase(main, bhead->code);
-       }
-
        /* read libblock */
        id = read_struct(fd, bhead, "lib block");
        if (id_r)
@@ -3563,6 +3963,15 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                return blo_nextbhead(fd, bhead);
        
        oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);      /* for ID_ID check */
+       
+       /* do after read_struct, for dna reconstruct */
+       if(bhead->code==ID_ID) {
+               lb= wich_libbase(main, GS(id->name));
+       }
+       else {
+               lb= wich_libbase(main, bhead->code);
+       }
+       
        BLI_addtail(lb, id);
 
        /* clear first 8 bits */
@@ -3668,6 +4077,12 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                        direct_link_brush(fd, (Brush*)id);
                        break;
        }
+       
+       /*link direct data of ID properties*/
+       if (id->properties) {
+               id->properties = newdataadr(fd, id->properties);
+               IDP_DirectLinkProperty(id->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+       }
 
        oldnewmap_free_unused(fd->datamap);
        oldnewmap_clear(fd->datamap);
@@ -3682,6 +4097,7 @@ static void link_global(FileData *fd, BlendFileData *bfd, FileGlobal *fg)
        bfd->fileflags= fg->fileflags;
        bfd->displaymode= fg->displaymode;
        bfd->globalf= fg->globalf;
+       
        bfd->curscreen= newlibadr(fd, 0, fg->curscreen);
        bfd->curscene= newlibadr(fd, 0, fg->curscene);
        // this happens in files older than 2.35
@@ -3787,10 +4203,187 @@ static void ntree_version_241(bNodeTree *ntree)
        }
 }
 
+static void ntree_version_242(bNodeTree *ntree)
+{
+       bNode *node;
+       
+       if(ntree->type==NTREE_COMPOSIT) {
+               for(node= ntree->nodes.first; node; node= node->next) {
+                       if(node->type==CMP_NODE_HUE_SAT) {
+                               if(node->storage) {
+                                       NodeHueSat *nhs= node->storage;
+                                       if(nhs->val==0.0f) nhs->val= 1.0f;
+                               }
+                       }
+               }
+       }
+       else if(ntree->type==NTREE_SHADER) {
+               for(node= ntree->nodes.first; node; node= node->next)
+                       if(node->type == SH_NODE_GEOMETRY && node->storage == NULL)
+                               node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry");
+       }
+       
+}
+
+
+/* somehow, probably importing via python, keyblock adrcodes are not in order */
+static void sort_shape_fix(Main *main)
+{
+       Key *key;
+       KeyBlock *kb;
+       int sorted= 0;
+       
+       while(sorted==0) {
+               sorted= 1;
+               for(key= main->key.first; key; key= key->id.next) {
+                       for(kb= key->block.first; kb; kb= kb->next) {
+                               if(kb->next && kb->adrcode>kb->next->adrcode) {
+                                       KeyBlock *next= kb->next;
+                                       BLI_remlink(&key->block, kb);
+                                       BLI_insertlink(&key->block, next, kb);
+                                       kb= next;
+                                       sorted= 0;
+                               }
+                       }
+               }
+               if(sorted==0) printf("warning, shape keys were sorted incorrect, fixed it!\n");
+       }
+}
+
+static void customdata_version_242(Mesh *me)
+{
+       CustomDataLayer *layer;
+       MTFace *mtf;
+       MCol *mcol;
+       TFace *tf;
+       int a, mtfacen, mcoln;
+
+       if (!me->vdata.totlayer) {
+               CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, me->mvert, me->totvert);
+
+               if (me->msticky)
+                       CustomData_add_layer(&me->vdata, CD_MSTICKY, CD_ASSIGN, me->msticky, me->totvert);
+               if (me->dvert)
+                       CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_ASSIGN, me->dvert, me->totvert);
+       }
+
+       if (!me->edata.totlayer)
+               CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, me->medge, me->totedge);
+       
+       if (!me->fdata.totlayer) {
+               CustomData_add_layer(&me->fdata, CD_MFACE, CD_ASSIGN, me->mface, me->totface);
+
+               if (me->tface) {
+                       if (me->mcol)
+                               MEM_freeN(me->mcol);
+
+                       me->mcol= CustomData_add_layer(&me->fdata, CD_MCOL, CD_CALLOC, NULL, me->totface);
+                       me->mtface= CustomData_add_layer(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, me->totface);
+
+                       mtf= me->mtface;
+                       mcol= me->mcol;
+                       tf= me->tface;
+
+                       for (a=0; a < me->totface; a++, mtf++, tf++, mcol+=4) {
+                               memcpy(mcol, tf->col, sizeof(tf->col));
+                               memcpy(mtf->uv, tf->uv, sizeof(tf->uv));
+
+                               mtf->flag= tf->flag;
+                               mtf->unwrap= tf->unwrap;
+                               mtf->mode= tf->mode;
+                               mtf->tile= tf->tile;
+                               mtf->tpage= tf->tpage;
+                               mtf->transp= tf->transp;
+                       }
+
+                       MEM_freeN(me->tface);
+                       me->tface= NULL;
+               }
+               else if (me->mcol) {
+                       me->mcol= CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, me->mcol, me->totface);
+               }
+       }
+
+       if (me->tface) {
+               MEM_freeN(me->tface);
+               me->tface= NULL;
+       }
+
+       for (a=0, mtfacen=0, mcoln=0; a < me->fdata.totlayer; a++) {
+               layer= &me->fdata.layers[a];
+
+               if (layer->type == CD_MTFACE) {
+                       if (layer->name[0] == 0) {
+                               if (mtfacen == 0) strcpy(layer->name, "UVTex");
+                               else sprintf(layer->name, "UVTex.%.3d", mtfacen);
+                       }
+                       mtfacen++;
+               }
+               else if (layer->type == CD_MCOL) {
+                       if (layer->name[0] == 0) {
+                               if (mcoln == 0) strcpy(layer->name, "Col");
+                               else sprintf(layer->name, "Col.%.3d", mcoln);
+                       }
+                       mcoln++;
+               }
+       }
+
+       mesh_update_customdata_pointers(me);
+}
+
+/*only copy render texface layer from active*/
+static void customdata_version_243(Mesh *me)
+{
+       CustomDataLayer *layer;
+       int a;
+
+       for (a=0; a < me->fdata.totlayer; a++) {
+               layer= &me->fdata.layers[a];
+               layer->active_rnd = layer->active;
+       }
+}
+
+/* struct NodeImageAnim moved to ImageUser, and we make it default available */
+static void do_version_ntree_242_2(bNodeTree *ntree)
+{
+       bNode *node;
+       
+       if(ntree->type==NTREE_COMPOSIT) {
+               for(node= ntree->nodes.first; node; node= node->next) {
+                       if(ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
+                               /* only image had storage */
+                               if(node->storage) {
+                                       NodeImageAnim *nia= node->storage;
+                                       ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "ima user node");
+
+                                       iuser->frames= nia->frames;
+                                       iuser->sfra= nia->sfra;
+                                       iuser->offset= nia->nr-1;
+                                       iuser->cycl= nia->cyclic;
+                                       iuser->fie_ima= 2;
+                                       iuser->ok= 1;
+                                       
+                                       node->storage= iuser;
+                                       MEM_freeN(nia);
+                               }
+                               else {
+                                       ImageUser *iuser= node->storage= MEM_callocN(sizeof(ImageUser), "node image user");
+                                       iuser->sfra= 1;
+                                       iuser->fie_ima= 2;
+                                       iuser->ok= 1;
+                               }
+                       }
+               }
+       }
+}
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
 
+       if(G.f & G_DEBUG)
+               printf("read file %s\n  Version %d sub %d\n", fd->filename, main->versionfile, main->subversionfile);
+       
        if(main->versionfile == 100) {
                /* tex->extend and tex->imageflag have changed: */
                Tex *tex = main->tex.first;
@@ -3805,10 +4398,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                        }
                                }
 
-                               if(tex->imaflag & TEX_ANIM5) {
-                                       tex->imaflag |= TEX_MORKPATCH;
-                                       tex->imaflag |= TEX_ANTIALI;
-                               }
                        }
                        tex= tex->id.next;
                }
@@ -4325,16 +4914,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                /* have to check the exact multiplier */
        }
 
-       if(main->versionfile <= 210) {
-               Scene *sce= main->scene.first;
-
-               while(sce) {
-                       if(sce->r.postmul== 0.0) sce->r.postmul= 1.0;
-                       if(sce->r.postgamma== 0.0) sce->r.postgamma= 1.0;
-                       sce= sce->id.next;
-               }
-       }
-
        if(main->versionfile <= 211) {
                /* Render setting: per scene, the applicable gamma value
                 * can be set. Default is 1.0, which means no
@@ -4342,11 +4921,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                bActuator *act;
                bObjectActuator *oa;
                Object *ob;
-               Scene *sce= main->scene.first;
-               while(sce) {
-                       sce->r.gamma = 2.0;
-                       sce= sce->id.next;
-               }
 
                /* added alpha in obcolor */
                ob= main->object.first;
@@ -4552,8 +5126,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Mesh *me;
                bScreen *sc;
 
-               for (sound=main->sound.first; sound; sound=sound->id.next)
-               {
+               for (sound=main->sound.first; sound; sound=sound->id.next) {
                        if (sound->packedfile) {
                                if (sound->newpackedfile == NULL) {
                                        sound->newpackedfile = sound->packedfile;
@@ -4883,21 +5456,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Lamp *la;
                World *wrld;
 
+               /* introduction of raytrace */
                while(ma) {
                        if(ma->fresnel_tra_i==0.0) ma->fresnel_tra_i= 1.25;
                        if(ma->fresnel_mir_i==0.0) ma->fresnel_mir_i= 1.25;
-                       if(ma->ang==0.0) {
-                               ma->ang= 1.0;
-                               ma->ray_depth= 2;
-                               ma->ray_depth_tra= 2;
-                               ma->fresnel_tra= 0.0;
-                               ma->fresnel_mir= 0.0;
-                       }
-                       else if(ma->ang<1.0) {          // temporal, because of IOR & fresnel change
-                               ma->ang= 1.0f/ma->ang;
-                               ma->fresnel_tra= ma->ang;
-                               ma->fresnel_mir= ma->ang;
-                       }
+
+                       ma->ang= 1.0;
+                       ma->ray_depth= 2;
+                       ma->ray_depth_tra= 2;
+                       ma->fresnel_tra= 0.0;
+                       ma->fresnel_mir= 0.0;
+
                        ma= ma->id.next;
                }
                sce= main->scene.first;
@@ -5091,7 +5660,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        tex= tex->id.next;
                }
                while(sce) {
-                       sce->r.postsat= 1.0;
                        ed= sce->ed;
                        if(ed) {
                                WHILE_SEQ(&ed->seqbase) {
@@ -5111,16 +5679,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                bScreen *sc;
 
                while(sce) {
-                       
-                       if(sce->r.postsat==0.0) sce->r.postsat= 1.0f;
-                       
-                       if(sce->r.zgamma==0.0) {
-                               sce->r.focus= 0.9f;
-                               sce->r.zgamma= 1.0f;
-                               sce->r.zsigma= 4.0f;
-                               sce->r.zblur= 10.0f;
-                               sce->r.zmin= 0.8f;
-                       }
                        if(sce->editbutsize==0.0) sce->editbutsize= 0.1f;
                        
                        sce= sce->id.next;
@@ -5591,13 +6149,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Object *ob;
                Curve *cu;
                Material *ma;
+               Mesh *me;
+               Group *group;
                Nurb *nu;
                BezTriple *bezt;
                BPoint *bp;
+               bNodeTree *ntree;
                int a;
-
-               sc= main->screen.first;
-               while(sc) {
+               
+               for(sc= main->screen.first; sc; sc= sc->id.next) {
                        ScrArea *sa;
                        sa= sc->areabase.first;
                        while(sa) {
@@ -5612,14 +6172,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                }
                                sa = sa->next;
                        }
-                       sc = sc->id.next;
                }
                
                for(sce= main->scene.first; sce; sce= sce->id.next) {
                        if (sce->toolsettings->select_thresh == 0.0f)
                                sce->toolsettings->select_thresh= 0.01f;
+                       if (sce->toolsettings->clean_thresh == 0.0f) 
+                               sce->toolsettings->clean_thresh = 0.1f;
+                               
+                       if (sce->r.threads==0) {
+                               if (sce->r.mode & R_THREADS)
+                                       sce->r.threads= 2;
+                               else
+                                       sce->r.threads= 1;
+                       }
+                       if(sce->nodetree)
+                               ntree_version_242(sce->nodetree);
                }
                
+               for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
+                       ntree_version_242(ntree);
+               
                /* add default radius values to old curve points */
                for(cu= main->curve.first; cu; cu= cu->id.next) {
                        for(nu= cu->nurb.first; nu; nu= nu->next) {
@@ -5649,13 +6222,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        if (list){
                                bConstraint *curcon;
                                for (curcon = list->first; curcon; curcon=curcon->next){
-                                       if (curcon->type == CONSTRAINT_TYPE_MINMAX){
-                                               bMinMaxConstraint *data = curcon->data;
-                                               if (data->sticky==1) {
-                                                       data->flag|=MINMAX_STICKY;
-                                               } else {
-                                                       data->flag&=~MINMAX_STICKY;
+                                       switch (curcon->type) {
+                                               case CONSTRAINT_TYPE_MINMAX:
+                                               {
+                                                       bMinMaxConstraint *data = curcon->data;
+                                                       if (data->sticky==1) 
+                                                               data->flag |= MINMAX_STICKY;
+                                                       else 
+                                                               data->flag &= ~MINMAX_STICKY;
                                                }
+                                                       break;
+                                               case CONSTRAINT_TYPE_ROTLIKE:
+                                               {
+                                                       bRotateLikeConstraint *data = curcon->data;
+                                                       
+                                                       /* version patch from buttons_object.c */
+                                                       if(data->flag==0) 
+                                                               data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
+                                               }
+                                                       break;
                                        }
                                }
                        }
@@ -5664,17 +6249,36 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                if (ob->pose){
                                        bConstraint *curcon;
                                        bPoseChannel *pchan;
-                                       for (pchan = ob->pose->chanbase.first;
-                                                pchan; pchan=pchan->next){
-                                               for (curcon = pchan->constraints.first;
-                                                        curcon; curcon=curcon->next){
-                                                       if (curcon->type == CONSTRAINT_TYPE_MINMAX){
-                                                               bMinMaxConstraint *data = curcon->data;
-                                                               if (data->sticky==1) {
-                                                                       data->flag|=MINMAX_STICKY;
-                                                               } else {
-                                                                       data->flag&=~MINMAX_STICKY;
+                                       for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
+                                               for (curcon = pchan->constraints.first; curcon; curcon=curcon->next){
+                                                       switch (curcon->type) {
+                                                               case CONSTRAINT_TYPE_MINMAX:
+                                                               {
+                                                                       bMinMaxConstraint *data = curcon->data;
+                                                                       if (data->sticky==1) 
+                                                                               data->flag |= MINMAX_STICKY;
+                                                                       else 
+                                                                               data->flag &= ~MINMAX_STICKY;
                                                                }
+                                                                       break;
+                                                               case CONSTRAINT_TYPE_KINEMATIC:
+                                                               {
+                                                                       bKinematicConstraint *data = curcon->data;
+                                                                       if (!(data->flag & CONSTRAINT_IK_POS)) {
+                                                                               data->flag |= CONSTRAINT_IK_POS;
+                                                                               data->flag |= CONSTRAINT_IK_STRETCH;
+                                                                       }
+                                                               }
+                                                                       break;
+                                                               case CONSTRAINT_TYPE_ROTLIKE:
+                                                               {
+                                                                       bRotateLikeConstraint *data = curcon->data;
+                                                                       
+                                                                       /* version patch from buttons_object.c */
+                                                                       if(data->flag==0) 
+                                                                               data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z;
+                                                               }
+                                                                       break;
                                                        }
                                                }
                                        }
@@ -5695,11 +6299,322 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                for(ma = main->mat.first; ma; ma= ma->id.next) {
                        if(ma->shad_alpha==0.0f)
                                ma->shad_alpha= 1.0f;
+                       if(ma->nodetree)
+                               ntree_version_242(ma->nodetree);
+               }
+
+               for(me=main->mesh.first; me; me=me->id.next)
+                       customdata_version_242(me);
+               
+               for(group= main->group.first; group; group= group->id.next)
+                       if(group->layer==0)
+                          group->layer= (1<<20)-1;
+               
+               /* History fix (python?), shape key adrcode numbers have to be sorted */
+               sort_shape_fix(main);
+                               
+               /* now, subversion control! */
+               if(main->subversionfile < 3) {
+                       bScreen *sc;
+                       Image *ima;
+                       Tex *tex;
+                       
+                       /* Image refactor initialize */
+                       for(ima= main->image.first; ima; ima= ima->id.next) {
+                               ima->source= IMA_SRC_FILE;
+                               ima->type= IMA_TYPE_IMAGE;
+                               
+                               ima->gen_x= 256; ima->gen_y= 256;
+                               ima->gen_type= 1;
+                               
+                               if(0==strncmp(ima->id.name+2, "Viewer Node", sizeof(ima->id.name+2))) {
+                                       ima->source= IMA_SRC_VIEWER;
+                                       ima->type= IMA_TYPE_COMPOSITE;
+                               }
+                               if(0==strncmp(ima->id.name+2, "Render Result", sizeof(ima->id.name+2))) {
+                                       ima->source= IMA_SRC_VIEWER;
+                                       ima->type= IMA_TYPE_R_RESULT;
+                               }
+                               
+                       }
+                       for(tex= main->tex.first; tex; tex= tex->id.next) {
+                               if(tex->type==TEX_IMAGE && tex->ima) {
+                                       ima= newlibadr(fd, lib, tex->ima);
+                                       if(tex->imaflag & TEX_ANIM5_)
+                                               ima->source= IMA_SRC_MOVIE;
+                                       if(tex->imaflag & TEX_FIELDS_)
+                                               ima->flag |= IMA_FIELDS;
+                                       if(tex->imaflag & TEX_STD_FIELD_)
+                                               ima->flag |= IMA_STD_FIELD;
+                                       if(tex->imaflag & TEX_ANTIALI_)
+                                               ima->flag |= IMA_ANTIALI;
+                               }
+                               tex->iuser.frames= tex->frames;
+                               tex->iuser.fie_ima= tex->fie_ima;
+                               tex->iuser.offset= tex->offset;
+                               tex->iuser.sfra= tex->sfra;
+                               tex->iuser.cycl= (tex->imaflag & TEX_ANIMCYCLIC_)!=0;
+                       }
+                       for(sce= main->scene.first; sce; sce= sce->id.next) {
+                               if(sce->nodetree)
+                                       do_version_ntree_242_2(sce->nodetree);
+                       }
+                       for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
+                               do_version_ntree_242_2(ntree);
+                       for(ma = main->mat.first; ma; ma= ma->id.next)
+                               if(ma->nodetree)
+                                       do_version_ntree_242_2(ma->nodetree);
+                       
+                       for(sc= main->screen.first; sc; sc= sc->id.next) {
+                               ScrArea *sa;
+                               for(sa= sc->areabase.first; sa; sa= sa->next) {
+                                       SpaceLink *sl;
+                                       for (sl= sa->spacedata.first; sl; sl= sl->next) {
+                                               if(sl->spacetype==SPACE_IMAGE)
+                                                       ((SpaceImage *)sl)->iuser.fie_ima= 2;
+                                               else if(sl->spacetype==SPACE_VIEW3D) {
+                                                       View3D *v3d= (View3D *)sl;
+                                                       if(v3d->bgpic)
+                                                               v3d->bgpic->iuser.fie_ima= 2;
+                                               }
+                                       }
+                               }
+                       }
                }
                
+               if(main->subversionfile < 4) {
+                       for(sce= main->scene.first; sce; sce= sce->id.next) {
+                               sce->r.bake_mode= 1;    /* prevent to include render stuff here */
+                               sce->r.bake_filter= 2;
+                               sce->r.bake_osa= 5;
+                               sce->r.bake_flag= R_BAKE_CLEAR;
+                       }
+               }
 
+               if(main->subversionfile < 5) {
+                       for(sce= main->scene.first; sce; sce= sce->id.next) {
+                               /* improved triangle to quad conversion settings */
+                               if(sce->toolsettings->jointrilimit==0.0f)
+                                       sce->toolsettings->jointrilimit= 0.8f;
+                       }
+               }
        }
-       
+       if(main->versionfile <= 243) {
+               Object *ob= main->object.first;
+               Camera *cam = main->camera.first;
+               Material *ma;
+               
+               for(; cam; cam= cam->id.next) {
+                       cam->angle= 360.0f * atan(16.0f/cam->lens) / M_PI;
+               }
+
+               for(ma=main->mat.first; ma; ma= ma->id.next) {
+                       if(ma->sss_scale==0.0f) {
+                               ma->sss_radius[0]= 1.0f;
+                               ma->sss_radius[1]= 1.0f;
+                               ma->sss_radius[2]= 1.0f;
+                               ma->sss_col[0]= 0.8f;
+                               ma->sss_col[1]= 0.8f;
+                               ma->sss_col[2]= 0.8f;
+                               ma->sss_error= 0.05f;
+                               ma->sss_scale= 0.1f;
+                               ma->sss_ior= 1.3f;
+                               ma->sss_colfac= 1.0f;
+                               ma->sss_texfac= 0.0f;
+                       }
+                       if(ma->sss_front==0 && ma->sss_back==0) {
+                               ma->sss_front= 1.0f;
+                               ma->sss_back= 1.0f;
+                       }
+                       if(ma->sss_col[0]==0 && ma->sss_col[1]==0 && ma->sss_col[2]==0) {
+                               ma->sss_col[0]= ma->r;
+                               ma->sss_col[1]= ma->g;
+                               ma->sss_col[2]= ma->b;
+                       }
+               }
+               
+               for(; ob; ob= ob->id.next) {
+                       bDeformGroup *curdef;
+                       
+                       for(curdef= ob->defbase.first; curdef; curdef=curdef->next) {
+                               /* replace an empty-string name with unique name */
+                               if (curdef->name[0] == '\0') {
+                                       unique_vertexgroup_name(curdef, ob);
+                               }
+                       }
+
+                       if(main->versionfile < 243 || main->subversionfile < 1) {
+                               ModifierData *md;
+
+                               /* translate old mirror modifier axis values to new flags */
+                               for (md=ob->modifiers.first; md; md=md->next) {
+                                       if (md->type==eModifierType_Mirror) {
+                                               MirrorModifierData *mmd = (MirrorModifierData*) md;
+
+                                               switch(mmd->axis)
+                                               {
+                                               case 0:
+                                                       mmd->flag |= MOD_MIR_AXIS_X;
+                                                       break;
+                                               case 1:
+                                                       mmd->flag |= MOD_MIR_AXIS_Y;
+                                                       break;
+                                               case 2:
+                                                       mmd->flag |= MOD_MIR_AXIS_Z;
+                                                       break;
+                                               }
+
+                                               mmd->axis = 0;
+                                       }
+                               }
+                       }
+               }
+               
+               /* render layer added, this is not the active layer */
+               if(main->versionfile <= 243 || main->subversionfile < 2) {
+                       Mesh *me;
+                       for(me=main->mesh.first; me; me=me->id.next)
+                               customdata_version_243(me);
+               }
+       }
+       if(main->versionfile <= 244) {
+               Scene *sce;
+               bScreen *sc;
+               Object *ob;
+
+               if(main->versionfile != 244 || main->subversionfile < 2) {
+                       Mesh *me;
+                       
+                       for(sce= main->scene.first; sce; sce= sce->id.next)
+                               sce->r.mode |= R_SSS;
+
+                       /* Copy over old per-level multires vertex data
+                          into a single vertex array in struct Multires */
+                       
+                       for(me = main->mesh.first; me; me=me->id.next) {
+                               if(me->mr) {
+                                       MultiresLevel *lvl = me->mr->levels.last;
+                                       if(lvl) {
+                                               me->mr->verts = lvl->verts;
+                                               lvl->verts = NULL;
+                                               /* Don't need the other vert arrays */
+                                               for(lvl = lvl->prev; lvl; lvl = lvl->prev) {
+                                                       MEM_freeN(lvl->verts);
+                                                       lvl->verts = NULL;
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       /* correct older action editors - incorrect scrolling */
+                       for(sc= main->screen.first; sc; sc= sc->id.next) {
+                               ScrArea *sa;
+                               sa= sc->areabase.first;
+                               while(sa) {
+                                       SpaceLink *sl;
+
+                                       for (sl= sa->spacedata.first; sl; sl= sl->next) {
+                                               if(sl->spacetype==SPACE_ACTION) {
+                                                       SpaceAction *saction= (SpaceAction*) sl;
+                                                       
+                                                       saction->v2d.tot.ymin= -1000.0;
+                                                       saction->v2d.tot.ymax= 0.0;
+                                                       
+                                                       saction->v2d.cur.ymin= -75.0;
+                                                       saction->v2d.cur.ymax= 5.0;
+                                               }
+                                       }
+                                       sa = sa->next;
+                               }
+                       }
+               }
+               if (main->subversionfile < 3) {
+                       for(ob = main->object.first; ob; ob= ob->id.next) {
+                               ListBase *list;
+                               list = &ob->constraints;
+                               float temp_size[3];
+
+                               /* fix up constraints due to constraint recode changes */
+                               if (list) {
+                                       bConstraint *curcon;
+                                       for (curcon = list->first; curcon; curcon=curcon->next) {
+                                               /* old CONSTRAINT_LOCAL check -> convert to CONSTRAINT_SPACE_LOCAL */
+                                               if (curcon->flag & 0x20) {
+                                                       curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+                                                       curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+                                               }
+                                               
+                                               switch (curcon->type) {
+                                                       case CONSTRAINT_TYPE_ACTION:
+                                                       {
+                                                               bActionConstraint *data= (bActionConstraint *)curcon->data;
+                                                               
+                                                               if (data->local)
+                                                                       curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+                                                       }                                                       
+                                                               break;
+                                                       case CONSTRAINT_TYPE_LOCLIMIT:
+                                                       {
+                                                               bLocLimitConstraint *data= (bLocLimitConstraint *)curcon->data;
+                                                               
+                                                               if (data->flag2) {
+                                                                       curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+                                                                       curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+                                                               }
+                                                       }
+                                                               break;
+                                               }       
+                                       }
+                               }
+                               
+                               /* correctly initialise constinv matrix */
+                               Mat4One(ob->constinv);
+
+                               if (ob->type == OB_ARMATURE) {
+                                       if (ob->pose) {
+                                               bConstraint *curcon;
+                                               bPoseChannel *pchan;
+                                               
+                                               for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+                                                       /* make sure constraints are all up to date */
+                                                       for (curcon = pchan->constraints.first; curcon; curcon=curcon->next) {
+                                                               /* old CONSTRAINT_LOCAL check -> convert to CONSTRAINT_SPACE_LOCAL */
+                                                               if (curcon->flag & 0x20) {
+                                                                       curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+                                                                       curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+                                                               }
+                                                               
+                                                               switch (curcon->type) {
+                                                                       case CONSTRAINT_TYPE_ACTION:
+                                                                       {
+                                                                               bActionConstraint *data= (bActionConstraint *)curcon->data;
+                                                                               
+                                                                               if (data->local)
+                                                                                       curcon->tarspace = CONSTRAINT_SPACE_LOCAL;
+                                                                       }                                                       
+                                                                               break;
+                                                                       case CONSTRAINT_TYPE_LOCLIMIT:
+                                                                       {
+                                                                               bLocLimitConstraint *data= (bLocLimitConstraint *)curcon->data;
+                                                                               
+                                                                               if (data->flag2) {
+                                                                                       curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+                                                                                       curcon->ownspace = CONSTRAINT_SPACE_LOCAL;
+                                                                               }
+                                                                       }
+                                                                               break;
+                                                               }
+                                                       }
+                                                       
+                                                       /* correctly initialise constinv matrix */
+                                                       Mat4One(pchan->constinv);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
 
@@ -5769,7 +6684,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
        BLI_addtail(&fd->mainlist, bfd->main);
 
        bfd->main->versionfile= fd->fileversion;
-
+       
        while(bhead) {
                switch(bhead->code) {
                case GLOB:
@@ -5778,7 +6693,11 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
                case TEST:
                case REND:
                        if (bhead->code==GLOB) {
-                               fg= read_struct(fd, bhead, "REND");
+                               fg= read_struct(fd, bhead, "Global");
+                               /* set right away */
+                               bfd->main->subversionfile= fg->subversion;
+                               bfd->main->minversionfile= fg->minversion;
+                               bfd->main->minsubversionfile= fg->minsubversion;
                        }
                        bhead = blo_nextbhead(fd, bhead);
                        break;
@@ -5799,30 +6718,29 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
                                 */
                        bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
                        break;
-//             case ID_GR:
-//                     bhead = blo_nextbhead(fd, bhead);
-//                     break;
                        
                default:
                        bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
                }
        }
 
-       /* before read_libraries */
-       do_versions(fd, NULL, bfd->main);
+       /* do before read_libraries, but skip undo case */
+//     if(fd->memfile==NULL) (the mesh shuffle hacks don't work yet? ton)
+               do_versions(fd, NULL, bfd->main);
        
        read_libraries(fd, &fd->mainlist);
+       
        blo_join_main(&fd->mainlist);
 
        lib_link_all(fd, bfd->main);
        lib_verify_nodetree(bfd->main);
        
-       link_global(fd, bfd, fg);       /* as last */
+       if(fg)
+               link_global(fd, bfd, fg);       /* as last */
 
        /* removed here: check for existance of curscreen/scene, moved to kernel setup_app */
-
        MEM_freeN(fg);
-
+       
        return bfd;
 }
 
@@ -5851,22 +6769,27 @@ static BHead *find_bhead(FileData *fd, void *old)
        return NULL;
 }
 
-static ID *is_yet_read(Main *mainvar, BHead *bhead)
+char *bhead_id_name(FileData *fd, BHead *bhead)
+{
+       return ((char *)(bhead+1)) + fd->id_name_offs;
+}
+
+static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
 {
        ListBase *lb;
-       ID *idtest, *id;
+       char *idname= bhead_id_name(fd, bhead);
 
-       // BHEAD+DATA dependancy
-       idtest= (ID *)(bhead +1);
-       lb= wich_libbase(mainvar, GS(idtest->name));
+       lb= wich_libbase(mainvar, GS(idname));
+       
        if(lb) {
-               id= lb->first;
+               ID *id= lb->first;
                while(id) {
-                       if( strcmp(id->name, idtest->name)==0 ) return id;
+                       if( strcmp(id->name, idname)==0 ) 
+                               return id;
                        id= id->next;
                }
        }
-       return 0;
+       return NULL;
 }
 
 static void expand_doit(FileData *fd, Main *mainvar, void *old)
@@ -5881,37 +6804,38 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                        BHead *bheadlib= find_previous_lib(fd, bhead);
 
                        if(bheadlib) {
-                               // BHEAD+DATA dependancy
-                               Library *lib= (Library *)(bheadlib+1);
-                               /* we read the lib->name directly from the bhead, potential danger (64 bits?) */
-                               mainvar= blo_find_main(&fd->mainlist, lib->name, fd->filename);
+                               Library *lib= read_struct(fd, bheadlib, "Library");
+                               Main *ptr= blo_find_main(&fd->mainlist, lib->name, fd->filename);
 
-                               id= is_yet_read(mainvar, bhead);
+                               id= is_yet_read(fd, ptr, bhead);
 
-                               if(id==0) {
-                                       read_libblock(fd, mainvar, bhead, LIB_READ+LIB_INDIRECT, NULL);
-                                       printf("expand_doit: other lib %s\n", lib->name);
+                               if(id==NULL) {
+                                       read_libblock(fd, ptr, bhead, LIB_READ+LIB_INDIRECT, NULL);
+                                       if(G.f & G_DEBUG) printf("expand_doit: other lib %s\n", lib->name);
+                                       
+                                       /* for outliner dependency only */
+                                       ptr->curlib->parent= mainvar->curlib;
                                }
                                else {
                                        //oldnewmap_insert(fd->libmap, bhead->old, id, 1);
                                        
                                        change_idid_adr_fd(fd, bhead->old, id);
-                                       printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
+                                       if(G.f & G_DEBUG) printf("expand_doit: already linked: %s lib: %s\n", id->name, lib->name);
                                }
+                               
+                               MEM_freeN(lib);
                        }
                }
                else {
-                       id= is_yet_read(mainvar, bhead);
+                       id= is_yet_read(fd, mainvar, bhead);
                        if(id==NULL) {
-                               // BHEAD+DATA dependancy
-                               id= (ID *)(bhead+1);
                                read_libblock(fd, mainvar, bhead, LIB_TESTIND, NULL);
                        }
                        else {
                                /* this is actually only needed on UI call? when ID was already read before, and another append
                                   happens which invokes same ID... in that case the lookup table needs this entry */
                                oldnewmap_insert(fd->libmap, bhead->old, id, 1);
-                               // printf("expand: already read %s\n", id->name);
+                               if(G.f & G_DEBUG) printf("expand: already read %s\n", id->name);
                        }
                }
        }
@@ -6047,8 +6971,10 @@ static void expand_curve(FileData *fd, Main *mainvar, Curve *cu)
 
 static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
 {
-       int a;
-       TFace *tface;
+       CustomDataLayer *layer;
+       MTFace *mtf;
+       TFace *tf;
+       int a, i;
        
        for(a=0; a<me->totcol; a++) {
                expand_doit(fd, mainvar, me->mat[a]);
@@ -6058,11 +6984,20 @@ static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
        expand_doit(fd, mainvar, me->texcomesh);
 
        if(me->tface) {
-               tface= me->tface;
-               a= me->totface;
-               while(a--) {
-                       if(tface->tpage) expand_doit(fd, mainvar, tface->tpage);
-                       tface++;
+               tf= me->tface;
+               for(i=0; i<me->totface; i++, tf++)
+                       if(tf->tpage)
+                               expand_doit(fd, mainvar, tf->tpage);
+       }
+
+       for(a=0; a<me->fdata.totlayer; a++) {
+               layer= &me->fdata.layers[a];
+
+               if(layer->type == CD_MTFACE) {
+                       mtf= (MTFace*)layer->data;
+                       for(i=0; i<me->totface; i++, mtf++)
+                               if(mtf->tpage)
+                                       expand_doit(fd, mainvar, mtf->tpage);
                }
        }
 }
@@ -6073,6 +7008,15 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
 
        for (curcon=lb->first; curcon; curcon=curcon->next) {
                switch (curcon->type) {
+               case CONSTRAINT_TYPE_NULL:
+                       break;
+               case CONSTRAINT_TYPE_PYTHON:
+                       {
+                               bPythonConstraint *data = (bPythonConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
+                               expand_doit(fd, mainvar, data->text);
+                       }
+                       break;
                case CONSTRAINT_TYPE_ACTION:
                        {
                                bActionConstraint *data = (bActionConstraint*)curcon->data;
@@ -6084,78 +7028,73 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
                        {
                                bLocateLikeConstraint *data = (bLocateLikeConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_ROTLIKE:
                        {
                                bRotateLikeConstraint *data = (bRotateLikeConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_SIZELIKE:
                        {
                                bSizeLikeConstraint *data = (bSizeLikeConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_KINEMATIC:
                        {
                                bKinematicConstraint *data = (bKinematicConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_TRACKTO:
                        {
                                bTrackToConstraint *data = (bTrackToConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_MINMAX:
                        {
                                bMinMaxConstraint *data = (bMinMaxConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_LOCKTRACK:
                        {
                                bLockTrackConstraint *data = (bLockTrackConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_FOLLOWPATH:
                        {
                                bFollowPathConstraint *data = (bFollowPathConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
-                       }
-               case CONSTRAINT_TYPE_DISTANCELIMIT:
-                       {
-                               bDistanceLimitConstraint *data = (bDistanceLimitConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
+                       break;
                case CONSTRAINT_TYPE_STRETCHTO:
                        {
                                bStretchToConstraint *data = (bStretchToConstraint*)curcon->data;
                                expand_doit(fd, mainvar, data->tar);
-                               break;
                        }
-               case CONSTRAINT_TYPE_LOCLIMIT:
+                       break;
+               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
                        {
-                               bLocLimitConstraint *data = (bLocLimitConstraint*)curcon->data;
-                               break;
+                               bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
                        }
-               case CONSTRAINT_TYPE_ROTLIMIT:
+                       break;
+               case CONSTRAINT_TYPE_CLAMPTO:
                        {
-                               bRotLimitConstraint *data = (bRotLimitConstraint*)curcon->data;
-                               break;
+                               bClampToConstraint *data = (bClampToConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
                        }
-               case CONSTRAINT_TYPE_SIZELIMIT:
+                       break;
+               case CONSTRAINT_TYPE_CHILDOF:
                        {
-                               bSizeLimitConstraint *data = (bSizeLimitConstraint*)curcon->data;
-                               break;
+                               bChildOfConstraint *data = (bChildOfConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
                        }
-               case CONSTRAINT_TYPE_NULL:
                        break;
                default:
                        break;
@@ -6182,6 +7121,7 @@ static void expand_pose(FileData *fd, Main *mainvar, bPose *pose)
 
        for (chan = pose->chanbase.first; chan; chan=chan->next) {
                expand_constraints(fd, mainvar, &chan->constraints);
+               expand_doit(fd, mainvar, chan->custom);
        }
 }
 
@@ -6231,6 +7171,15 @@ static void expand_modifier(FileData *fd, Main *mainvar, ModifierData *md)
        }
 }
 
+static void expand_scriptlink(FileData *fd, Main *mainvar, ScriptLink *slink)
+{
+       int i;
+       
+       for(i=0; i<slink->totscript; i++) {
+               expand_doit(fd, mainvar, slink->scripts[i]);
+       }
+}
+
 static void expand_object(FileData *fd, Main *mainvar, Object *ob)
 {
        ModifierData *md;
@@ -6270,6 +7219,11 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
 
        if(ob->dup_group)
                expand_doit(fd, mainvar, ob->dup_group);
+       
+       if(ob->proxy)
+               expand_doit(fd, mainvar, ob->proxy);
+       if(ob->proxy_group)
+               expand_doit(fd, mainvar, ob->proxy_group);
 
        sens= ob->sensors.first;
        while(sens) {
@@ -6335,22 +7289,29 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
                }
                act= act->next;
        }
+       
+       expand_scriptlink(fd, mainvar, &ob->scriptlink);
 }
 
 static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
 {
        Base *base;
+       SceneRenderLayer *srl;
 
-       base= sce->base.first;
-       while(base) {
+       for(base= sce->base.first; base; base= base->next) {
                expand_doit(fd, mainvar, base->object);
-               base= base->next;
        }
        expand_doit(fd, mainvar, sce->camera);
        expand_doit(fd, mainvar, sce->world);
        
        if(sce->nodetree)
                expand_nodetree(fd, mainvar, sce->nodetree);
+       
+       for(srl= sce->r.layers.first; srl; srl= srl->next) {
+               expand_doit(fd, mainvar, srl->mat_override);
+               expand_doit(fd, mainvar, srl->light_override);
+       }
+                               
 }
 
 static void expand_camera(FileData *fd, Main *mainvar, Camera *ca)
@@ -6504,19 +7465,19 @@ static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *n
        Base *base;
        BHead *bhead;
        ID *id;
-       int afbreek=0;
+       int endloop=0;
 
        bhead = blo_firstbhead(fd);
-       while(bhead && afbreek==0) {
+       while(bhead && endloop==0) {
 
-               if(bhead->code==ENDB) afbreek= 1;
+               if(bhead->code==ENDB) endloop= 1;
                else if(bhead->code==idcode) {
-                       // BHEAD+DATA dependancy
-                       id= (ID *)(bhead+1);
-                       if(strcmp(id->name+2, name)==0) {
+                       char *idname= bhead_id_name(fd, bhead);
+                               
+                       if(strcmp(idname+2, name)==0) {
 
-                               id= is_yet_read(mainvar, bhead);
-                               if(id==0) {
+                               id= is_yet_read(fd, mainvar, bhead);
+                               if(id==NULL) {
                                        read_libblock(fd, mainvar, bhead, LIB_TESTEXT, NULL);
                                }
                                else {
@@ -6532,7 +7493,7 @@ static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *n
                                        base= MEM_callocN( sizeof(Base), "app_nam_part");
                                        BLI_addtail(&scene->base, base);
 
-                                       if(id==0) ob= mainvar->object.last;
+                                       if(id==NULL) ob= mainvar->object.last;
                                        else ob= (Object *)id;
                                        
                                        /* this is bad code... G.vd nor G.scene should be used on this level... */
@@ -6550,7 +7511,7 @@ static void append_named_part(FileData *fd, Main *mainvar, Scene *scene, char *n
                                                /* do NOT make base active here! screws up GUI stuff, if you want it do it on src/ level */
                                        }
                                }
-                               afbreek= 1;
+                               endloop= 1;
                        }
                }
 
@@ -6564,9 +7525,8 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r)
 
        for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
                if (bhead->code == GS(id->name)) {
-                       ID *idread= (ID *)(bhead+1); /*  BHEAD+DATA dependancy */
-
-                       if (BLI_streq(id->name, idread->name)) {
+                       
+                       if (BLI_streq(id->name, bhead_id_name(fd, bhead))) {
                                id->flag &= ~LIB_READ;
                                id->flag |= LIB_TEST;
 //                             printf("read lib block %s\n", id->name);
@@ -6579,39 +7539,96 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r)
        }
 }
 
-/* this is a version of BLO_library_append needed by the BPython API, so
- * scripts can load data from .blend files -- see Blender.Library module.*/
+/* common routine to append/link something from a library */
 
-/* append to G.scene */
-void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcode, short flag)
+static Library* library_append( Scene *scene, SpaceFile *sfile, char *dir, int idcode,
+               int totsel, FileData *fd)
 {
-       ListBase mainlist;
        Main *mainl;
-       FileData *fd = (FileData *)bh;
-
-       mainlist.first= mainlist.last= G.main;
-       G.main->next= NULL;
+       Library *curlib;
 
        /* make mains */
-       blo_split_main(&mainlist);
+       blo_split_main(&fd->mainlist, G.main);
 
        /* which one do we need? */
-       mainl = blo_find_main(&mainlist, dir, G.sce);
-
-       append_named_part(fd, mainl, G.scene, name, idcode, flag);
+       mainl = blo_find_main(&fd->mainlist, dir, G.sce);
+       
+       mainl->versionfile= fd->fileversion;    /* needed for do_version */
+       
+       curlib= mainl->curlib;
+       
+       if(totsel==0) {
+               append_named_part(fd, mainl, scene, sfile->file, idcode, sfile->flag);
+       }
+       else {
+               int a;
+               for(a=0; a<sfile->totfile; a++) {
+                       if(sfile->filelist[a].flags & ACTIVE) {
+                               append_named_part(fd, mainl, scene, sfile->filelist[a].relname, idcode, sfile->flag);
+                       }
+               }
+       }
 
        /* make main consistant */
        expand_main(fd, mainl);
 
        /* do this when expand found other libs */
-       read_libraries(fd, &mainlist);
+       read_libraries(fd, &fd->mainlist);
 
-       blo_join_main(&mainlist);
-       G.main= mainlist.first;
+       if(sfile->flag & FILE_STRINGCODE) {
+
+               /* use the full path, this could have been read by other library even */
+               BLI_strncpy(mainl->curlib->name, mainl->curlib->filename, sizeof(mainl->curlib->name));
+               
+               /* uses current .blend file as reference */
+               BLI_makestringcode(G.sce, mainl->curlib->name);
+       }
+
+       blo_join_main(&fd->mainlist);
+       G.main= fd->mainlist.first;
 
        lib_link_all(fd, G.main);
        lib_verify_nodetree(G.main);
 
+       /* give a base to loose objects. If group append, do it for objects too */
+       if(idcode==ID_GR)
+               give_base_to_objects(scene, &(G.main->object), (sfile->flag & FILE_LINK)?NULL:curlib);
+       else
+               give_base_to_objects(scene, &(G.main->object), NULL);
+       
+       /* has been removed... erm, why? s..ton) */
+       /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */
+       /* 20041208: put back. It only linked direct, not indirect objects (ton) */
+       
+       /* patch to prevent switch_endian happens twice */
+       if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+               blo_freefiledata( fd );
+               sfile->libfiledata= 0;
+       }
+
+       return curlib;
+}
+
+/* this is a version of BLO_library_append needed by the BPython API, so
+ * scripts can load data from .blend files -- see Blender.Library module.*/
+/* append to G.scene */
+/* this should probably be moved into the Python code anyway */
+
+void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, 
+               int idcode, short flag, Scene *scene )
+{
+       SpaceFile sfile;
+
+       /* build a minimal "fake" SpaceFile object */
+       sfile.flag = flag;
+       sfile.totfile = 0;
+       strcpy(sfile.file, name);
+
+       /* try to append the requested object */
+
+       library_append( scene, &sfile, dir, idcode, 0, (FileData *)bh );
+
+       /* do we need to do this? */
        DAG_scene_sort(G.scene);
 }
 
@@ -6620,14 +7637,11 @@ void BLO_script_library_append(BlendHandle *bh, char *dir, char *name, int idcod
 void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
 {
        FileData *fd= (FileData*) sfile->libfiledata;
-       Main *mainl;
+       Library *curlib;
        Base *centerbase;
        Object *ob;
-       float *curs,centerloc[3],vec[3],min[3],max[3];
-       int a, totsel=0,count=0;
+       int a, totsel=0;
        
-       INIT_MINMAX(min, max);
-
        /* are there files selected? */
        for(a=0; a<sfile->totfile; a++) {
                if(sfile->filelist[a].flags & ACTIVE) {
@@ -6655,94 +7669,45 @@ void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
        
        if(sfile->flag & FILE_AUTOSELECT) scene_deselect_all(G.scene);
 
-       fd->mainlist.first= fd->mainlist.last= G.main;
-       G.main->next= NULL;
-
-       /* make mains */
-       blo_split_main(&fd->mainlist);
-
-       /* which one do we need? */
-       mainl = blo_find_main(&fd->mainlist, dir, G.sce);
-       mainl->versionfile= fd->fileversion;    // needed for do_version
-       
-       if(totsel==0) {
-               append_named_part(fd, mainl, G.scene, sfile->file, idcode, sfile->flag);
-       }
-       else {
-               for(a=0; a<sfile->totfile; a++) {
-                       if(sfile->filelist[a].flags & ACTIVE) {
-                               append_named_part(fd, mainl, G.scene, sfile->filelist[a].relname, idcode, sfile->flag);
-                       }
-               }
-       }
-
-       /* make main consistant */
-       expand_main(fd, mainl);
-
-       /* do this when expand found other libs */
-       read_libraries(fd, &fd->mainlist);
-
-       if(sfile->flag & FILE_STRINGCODE) {
-
-               /* use the full path, this could have been read by other library even */
-               BLI_strncpy(mainl->curlib->name, mainl->curlib->filename, sizeof(mainl->curlib->name));
-               
-               /* uses current .blend file as reference */
-               BLI_makestringcode(G.sce, mainl->curlib->name);
-       }
-
-       blo_join_main(&fd->mainlist);
-       G.main= fd->mainlist.first;
+       curlib = library_append( G.scene, sfile, dir, idcode, totsel, fd );
 
-       lib_link_all(fd, G.main);
-       lib_verify_nodetree(G.main);
-
-       /* give a base to loose objects. If group append, do it for objects too */
-       if(idcode==ID_GR)
-               give_base_to_objects(G.scene, &(G.main->object), (sfile->flag & FILE_LINK)?NULL:mainl->curlib);
-       else
-               give_base_to_objects(G.scene, &(G.main->object), NULL);
-       
-       /* has been removed... erm, why? (ton) */
-       /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */
-       /* 20041208: put back. It only linked direct, not indirect objects (ton) */
-       
-       /* patch to prevent switch_endian happens twice */
-       if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
-               blo_freefiledata((FileData*) sfile->libfiledata);
-               sfile->libfiledata= 0;
-       }       
-       
-       if(sfile->flag & FILE_ATCURSOR) {
-               centerbase= (G.scene->base.first);
-               while(centerbase) {
-                       if(((centerbase)->flag & SELECT)) {
-                               VECCOPY(vec, centerbase->object->loc);
-                               DO_MINMAX(vec, min, max);
-                               count++;
-                       }
-                       centerbase= centerbase->next;
-               }
-               if(count) {
-                       centerloc[0]= (min[0]+max[0])/2;
-                       centerloc[1]= (min[1]+max[1])/2;
-                       centerloc[2]= (min[2]+max[2])/2;
-                       curs = G.scene->cursor;
-                       VECSUB(centerloc,curs,centerloc);
-               
+       /* when not linking (appending)... */
+       if((sfile->flag & FILE_LINK)==0) {
+               if(sfile->flag & FILE_ATCURSOR) {
+                       float *curs, centerloc[3], vec[3], min[3], max[3];
+                       int count= 0;
+                       
+                       INIT_MINMAX(min, max);
+                       
                        centerbase= (G.scene->base.first);
                        while(centerbase) {
-                               if( ((centerbase)->flag & SELECT)) {
-                                       ob= centerbase->object;
-                                       ob->loc[0] += centerloc[0];
-                                       ob->loc[1] += centerloc[1];
-                                       ob->loc[2] += centerloc[2];
+                               if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) {
+                                       VECCOPY(vec, centerbase->object->loc);
+                                       DO_MINMAX(vec, min, max);
+                                       count++;
                                }
                                centerbase= centerbase->next;
                        }
+                       if(count) {
+                               centerloc[0]= (min[0]+max[0])/2;
+                               centerloc[1]= (min[1]+max[1])/2;
+                               centerloc[2]= (min[2]+max[2])/2;
+                               curs = G.scene->cursor;
+                               VECSUB(centerloc,curs,centerloc);
+                       
+                               centerbase= (G.scene->base.first);
+                               while(centerbase) {
+                                       if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) {
+                                               ob= centerbase->object;
+                                               ob->loc[0] += centerloc[0];
+                                               ob->loc[1] += centerloc[1];
+                                               ob->loc[2] += centerloc[2];
+                                       }
+                                       centerbase= centerbase->next;
+                               }
+                       }
                }
        }
-       DAG_scene_sort(G.scene);
 }
 
 /* ************* READ LIBRARY ************** */
@@ -6778,13 +7743,13 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                while(mainptr) {
                        int tot= mainvar_count_libread_blocks(mainptr);
                        
-                       //printf("found LIB_READ %s\n", mainptr->curlib->name);
+                       // printf("found LIB_READ %s\n", mainptr->curlib->name);
                        if(tot) {
                                FileData *fd= mainptr->curlib->filedata;
 
                                if(fd==NULL) {
                                        BlendReadError err;
-                                       printf("read_libraries: lib %s\n", mainptr->curlib->name);
+                                       printf("read library: lib %s\n", mainptr->curlib->name);
                                        fd= blo_openblenderfile(mainptr->curlib->filename, &err);
                                        if (fd) {
                                                if (fd->libmap)