Saturday merger of bf-blender in orange branch.
[blender.git] / source / blender / blenloader / intern / readfile.c
index 455c45b00ea2abba039d16309721e096169ffcb1..0cccf770fda0a19428f9f3942bb1b98f0133fd5a 100644 (file)
@@ -1,19 +1,12 @@
 /*
- * readfile.c
- *
- * .blend file reading
- *
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -31,7 +24,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  *
  */
 
@@ -235,7 +228,7 @@ typedef struct OldNew {
 typedef struct OldNewMap {
        OldNew *entries;
        int nentries, entriessize;
-
+       int sorted;
        int lasthit;
 } OldNewMap;
 
@@ -244,19 +237,39 @@ typedef struct OldNewMap {
 extern          short freeN(void *vmemh); /* defined in util.h */  
 
 
-static OldNewMap *oldnewmap_new(void) {
-       OldNewMap *onm= MEM_mallocN(sizeof(*onm), "OldNewMap");
-       onm->lasthit= 0;
-       onm->nentries= 0;
+static OldNewMap *oldnewmap_new(void) 
+{
+       OldNewMap *onm= MEM_callocN(sizeof(*onm), "OldNewMap");
+       
        onm->entriessize= 1024;
        onm->entries= MEM_mallocN(sizeof(*onm->entries)*onm->entriessize, "OldNewMap.entries");
-
+       
        return onm;
 }
 
-static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) {
+static int verg_oldnewmap(const void *v1, const void *v2)
+{
+       const struct OldNew *x1=v1, *x2=v2;
+       
+       if( x1->old > x2->old) return 1;
+       else if( x1->old < x2->old) return -1;
+       return 0;
+}
+
+
+static void oldnewmap_sort(FileData *fd) 
+{
+       qsort(fd->libmap->entries, fd->libmap->nentries, sizeof(OldNew), verg_oldnewmap);
+       fd->libmap->sorted= 1;
+}
+
+/* nr is zero for data, and ID code for libdata */
+static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) 
+{
        OldNew *entry;
 
+       if(oldaddr==NULL || newaddr==NULL) return;
+       
        if (onm->nentries==onm->entriessize) {
                int osize= onm->entriessize;
                OldNew *oentries= onm->entries;
@@ -274,7 +287,8 @@ static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int n
        entry->nr= nr;
 }
 
-static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) {
+static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) 
+{
        int i;
 
        if (onm->lasthit<onm->nentries-1) {
@@ -300,23 +314,29 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) {
        return NULL;
 }
 
-static void *oldnewmap_liblookup_and_inc(OldNewMap *onm, void *addr, void *lib) {
+/* for libdate, nr has ID code, no increment */
+static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) 
+{
        int i;
-
-       if (onm->lasthit<onm->nentries-1) {
-               OldNew *entry= &onm->entries[++onm->lasthit];
-
-               if (entry->old==addr) {
+       
+       if(addr==NULL) return NULL;
+       
+       /* lasthit works fine for non-libdata, linking there is done in same sequence as writing */
+       if(onm->sorted) {
+               OldNew entry_s, *entry;
+               
+               entry_s.old= addr;
+               
+               entry= bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap);
+               if(entry) {
                        ID *id= entry->newp;
-
+                       
                        if (id && (!lib || id->lib)) {
-                               entry->nr++;
-
                                return entry->newp;
                        }
                }
        }
-
+       
        for (i=0; i<onm->nentries; i++) {
                OldNew *entry= &onm->entries[i];
 
@@ -324,8 +344,6 @@ static void *oldnewmap_liblookup_and_inc(OldNewMap *onm, void *addr, void *lib)
                        ID *id= entry->newp;
 
                        if (id && (!lib || id->lib)) {
-                               entry->nr++;
-
                                return entry->newp;
                        }
                }
@@ -334,41 +352,8 @@ static void *oldnewmap_liblookup_and_inc(OldNewMap *onm, void *addr, void *lib)
        return NULL;
 }
 
-static void *oldnewmap_typelookup_and_inc(OldNewMap *onm, void *addr, short type) {
-       int i;
-
-       if (onm->lasthit<onm->nentries-1) {
-               OldNew *entry= &onm->entries[++onm->lasthit];
-
-               if (entry->old==addr) {
-                       ID *id= entry->newp;
-
-                       if (id && (GS(id->name) == type)) {
-                               entry->nr++;
-
-                               return entry->newp;
-                       }
-               }
-       }
-
-       for (i=0; i<onm->nentries; i++) {
-               OldNew *entry= &onm->entries[i];
-
-               if (entry->old==addr) {
-                       ID *id= entry->newp;
-
-                       if (id && (GS(id->name) == type)) {
-                               entry->nr++;
-
-                               return entry->newp;
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-static void oldnewmap_free_unused(OldNewMap *onm) {
+static void oldnewmap_free_unused(OldNewMap *onm) 
+{
        int i;
 
        for (i=0; i<onm->nentries; i++) {
@@ -380,12 +365,14 @@ static void oldnewmap_free_unused(OldNewMap *onm) {
        }
 }
 
-static void oldnewmap_clear(OldNewMap *onm) {
+static void oldnewmap_clear(OldNewMap *onm) 
+{
        onm->nentries= 0;
        onm->lasthit= 0;
 }
 
-static void oldnewmap_free(OldNewMap *onm) {
+static void oldnewmap_free(OldNewMap *onm) 
+{
        MEM_freeN(onm->entries);
        MEM_freeN(onm);
 }
@@ -455,7 +442,6 @@ void blo_split_main(ListBase *mainlist)
        for (lib= mainl->library.first; lib; lib= lib->id.next) {
                Main *libmain= MEM_callocN(sizeof(Main), "libmain");
                libmain->curlib= lib;
-
                BLI_addtail(mainlist, libmain);
        }
 
@@ -464,25 +450,42 @@ void blo_split_main(ListBase *mainlist)
                split_libdata(lbarray[i], mainl->next);
 }
 
+static void cleanup_path(const char *relabase, char *name)
+{
+       char filename[FILE_MAXFILE];
+       
+       BLI_splitdirstring(name, filename);
+       BLI_cleanup_dir(relabase, name);
+       strcat(name, filename);
+}
+
 static Main *blo_find_main(ListBase *mainlist, char *name)
 {
        Main *m;
        Library *lib;
        char name1[FILE_MAXDIR+FILE_MAXFILE];
        char libname1[FILE_MAXDIR+FILE_MAXFILE];
-
-       /* name can be stringcode too */
+       
+//     printf("G.sce %s\n", G.sce);
+       /* everything in absolute paths now */
+       
        strcpy(name1, name);
-       BLI_convertstringcode(name1, G.sce, 0);
+       cleanup_path(G.sce, name1);
+//     printf("original in  %s\n", name);
+//     printf("converted in %s\n", name1);
 
        for (m= mainlist->first; m; m= m->next) {
                char *libname= (m->curlib)?m->curlib->name:m->name;
                
+//             printf("libname %s\n", libname);
                strcpy(libname1, libname);
-               BLI_convertstringcode(libname1, G.sce, 0);
+               cleanup_path(G.sce, libname1);
+//             printf("libname1 %s\n", libname1, name1);
                
-               if (BLI_streq(name1, libname1))
+               if (BLI_streq(name1, libname1)) {
+                       printf("found library %s\n", libname);
                        return m;
+               }
        }
 
        m= MEM_callocN(sizeof(Main), "find_main");
@@ -491,7 +494,8 @@ static Main *blo_find_main(ListBase *mainlist, char *name)
        lib= alloc_libblock(&m->library, ID_LI, "lib");
        strcpy(lib->name, name);
        m->curlib= lib;
-
+       
+       printf("added new lib %s\n", name);
        return m;
 }
 
@@ -897,6 +901,19 @@ FileData *blo_openblenderfile(char *name, BlendReadError *error_r)
        gzFile gzfile;
        char name1[FILE_MAXDIR+FILE_MAXFILE];
        
+       /* relative path rescue... */
+       if(G.rt==111) {
+               int len= strlen(name);
+               printf("old %s\n", name);
+               while(len-- > 1) {
+                       if(name[len]=='/' && name[len-1]=='/') {
+                               strcpy(name, name+len-1);
+                               printf("new %s\n", name);
+                               break;
+                       }
+               }
+       }
+       
        /* library files can have stringcodes */
        strcpy(name1, name);
        if(name[0]=='/' && name[1]=='/')
@@ -1012,18 +1029,7 @@ static void *newglobadr(FileData *fd, void *adr)         /* direct datablocks with glob
 
 static void *newlibadr(FileData *fd, void *lib, void *adr)             /* only lib data */
 {
-       return oldnewmap_liblookup_and_inc(fd->libmap, adr, lib);
-}
-
-static void *newlibadr_us_type(FileData *fd, short type, void *adr)    /* only Lib data */
-{
-       ID *id= oldnewmap_typelookup_and_inc(fd->libmap, adr, type);
-
-       if (id) {
-               id->us++;
-       }
-
-       return id;
+       return oldnewmap_liblookup(fd->libmap, adr, lib);
 }
 
 static void *newlibadr_us(FileData *fd, void *lib, void *adr)  /* increases user number */
@@ -1037,51 +1043,36 @@ static void *newlibadr_us(FileData *fd, void *lib, void *adr)   /* increases user
        return id;
 }
 
-static void change_libadr(FileData *fd, void *old, void *new)
+static void change_idid_adr_fd(FileData *fd, void *old, void *new)
 {
        int i;
-
-               /* changed one thing here, the old change_libadr
-                * only remapped addresses that had an id->lib,
-                * but that doesn't make sense to me... its an
-                * old pointer, period, it needs to be remapped. - zr
-                */
-
-               /*
-                * Ton seemed to think it was necessary to look
-                * through all entries, and not return after finding
-                * a match, leaving this cryptic comment,
-                * // no return, maybe there can be more?
-                *
-                * That doesn't make sense to me either but I am
-                * too scared to remove it... it only would make
-                * sense if two distinct old address map to the
-                * same new address - obviously that shouldn't happen
-                * because memory addresses are unique.
-                *
-                * The only case it might happen is when two distinct
-                * libraries are mapped using the same table... this
-                * won't work to start with... At some point this
-                * all needs to be made sense of and made understandable,
-                * but I'm afraid I don't have time now. -zr
-                *
-                */
-    /* the code is nasty, and needs a lot of energy to get into full understanding
-       again... i now translate dutch comments, maybe that gives me more insight!
-       But i guess it has to do with the assumption that 2 addresses can be allocated
-       in different sessions, and therefore be the same... like the remark in the top
-       of this c file (ton) */
-
+       
        for (i=0; i<fd->libmap->nentries; i++) {
                OldNew *entry= &fd->libmap->entries[i];
-
-               if (old==entry->newp) {
+               
+               if (old==entry->newp && entry->nr==ID_ID) {
                        entry->newp= new;
+                       if(new) entry->nr= GS( ((ID *)new)->name );
                        break;
                }
        }
 }
 
+static void change_idid_adr(ListBase *mainlist, FileData *basefd, void *old, void *new)
+{
+       Main *main;
+       
+       for(main= mainlist->first; main; main= main->next) {
+               FileData *fd;
+               
+               if(main->curlib) fd= main->curlib->filedata;
+               else fd= basefd;
+               
+               if(fd) {
+                       change_idid_adr_fd(fd, old, new);
+               }
+       }
+}
 
 /* ********** END OLD POINTERS ****************** */
 /* ********** READ FILE ****************** */
@@ -1261,6 +1252,7 @@ static void lib_link_nlastrips(FileData *fd, ID *id, ListBase *striplist)
        bActionStrip *strip;
 
        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);
        }
@@ -1387,6 +1379,7 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
                lib_link_constraints(fd, (ID *)ob, &pchan->constraints);
                // 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;
        }
@@ -1990,6 +1983,7 @@ static void direct_link_texture(FileData *fd, Tex *tex)
 static void lib_link_material(FileData *fd, Main *main)
 {
        Material *ma;
+       MaterialLayer *ml;
        MTex *mtex;
        int a;
 
@@ -1998,6 +1992,7 @@ static void lib_link_material(FileData *fd, Main *main)
                if(ma->id.flag & LIB_NEEDLINK) {
 
                        ma->ipo= newlibadr_us(fd, ma->id.lib, ma->ipo);
+                       ma->group= newlibadr_us(fd, ma->id.lib, ma->group);
 
                        for(a=0; a<MAX_MTEX; a++) {
                                mtex= ma->mtex[a];
@@ -2007,6 +2002,10 @@ static void lib_link_material(FileData *fd, Main *main)
                                }
                        }
                        lib_link_scriptlink(fd, &ma->id, &ma->scriptlink);
+                       
+                       for (ml=ma->layers.first; ml; ml=ml->next)
+                               ml->mat= newlibadr_us(fd, ma->id.lib, ml->mat);
+                               
                        ma->id.flag -= LIB_NEEDLINK;
                }
                ma= ma->id.next;
@@ -2017,8 +2016,6 @@ static void direct_link_material(FileData *fd, Material *ma)
 {
        int a;
 
-       direct_link_scriptlink(fd, &ma->scriptlink);
-
        for(a=0; a<MAX_MTEX; a++) {
                ma->mtex[a]= newdataadr(fd, ma->mtex[a]);
        }
@@ -2026,6 +2023,10 @@ static void direct_link_material(FileData *fd, Material *ma)
        ma->ramp_col= newdataadr(fd, ma->ramp_col);
        ma->ramp_spec= newdataadr(fd, ma->ramp_spec);
        
+       direct_link_scriptlink(fd, &ma->scriptlink);
+       
+       link_list(fd, &ma->layers);
+
 }
 
 /* ************ READ MESH ***************** */
@@ -2041,8 +2042,9 @@ static void lib_link_mesh(FileData *fd, Main *main)
 
                        /* this check added for python created meshes */
                        if(me->mat) {
-                               for(i=0; i<me->totcol; i++)
+                               for(i=0; i<me->totcol; i++) {
                                        me->mat[i]= newlibadr_us(fd, me->id.lib, me->mat[i]);
+                               }
                        }
                        else me->totcol= 0;
 
@@ -2136,6 +2138,7 @@ static void lib_link_modifiers(FileData *fd, Object *ob)
 static void lib_link_object(FileData *fd, Main *main)
 {
        Object *ob;
+       PartEff *paf;
        bSensor *sens;
        bController *cont;
        bActuator *act;
@@ -2150,10 +2153,11 @@ static void lib_link_object(FileData *fd, Main *main)
                        ob->track= newlibadr(fd, ob->id.lib, ob->track);
                        ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
                        ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
-
+                       ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
+                       
                        poin= ob->data;
                        ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
-
+                          
                        if(ob->data==NULL && poin!=NULL) {
                                ob->type= OB_EMPTY;
                                warn= 1;
@@ -2171,6 +2175,11 @@ static void lib_link_object(FileData *fd, Main *main)
                        lib_link_nlastrips(fd, &ob->id, &ob->nlastrips);
                        lib_link_constraint_channels(fd, &ob->id, &ob->constraintChannels);
 
+                       for(paf= ob->effect.first; paf; paf= paf->next) {
+                               if(paf->type==EFF_PARTICLE) {
+                                       paf->group= newlibadr_us(fd, ob->id.lib, paf->group);
+                               }
+                       }                               
 
                        sens= ob->sensors.first;
                        while(sens) {
@@ -2344,7 +2353,7 @@ static void direct_link_object(FileData *fd, Object *ob)
        paf= ob->effect.first;
        while(paf) {
                if(paf->type==EFF_PARTICLE) {
-                       paf->keys= 0;
+                       paf->keys= NULL;
                }
                if(paf->type==EFF_WAVE) {
                        WaveEff *wav = (WaveEff*) paf;
@@ -2503,19 +2512,18 @@ static void lib_link_scene(FileData *fd, Main *main)
                        sce->world= newlibadr_us(fd, sce->id.lib, sce->world);
                        sce->set= newlibadr(fd, sce->id.lib, sce->set);
                        sce->ima= newlibadr_us(fd, sce->id.lib, sce->ima);
-                       sce->group= newlibadr_us(fd, sce->id.lib, sce->group);
 
                        base= sce->base.first;
                        while(base) {
                                next= base->next;
 
                                /* base->object= newlibadr_us(fd, sce->id.lib, base->object); */
-                               base->object= newlibadr_us_type(fd, ID_OB, base->object);
+                               base->object= newlibadr_us(fd, sce->id.lib, base->object);
                                
                                /* when save during radiotool, needs cleared */
                                base->flag &= ~OB_RADIO;
                                
-                               if(base->object==0) {
+                               if(base->object==NULL) {
                                        printf("LIB ERROR: base removed\n");
                                        BLI_remlink(&sce->base, base);
                                        if(base==sce->basact) sce->basact= 0;
@@ -3097,10 +3105,25 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
 /* ********** READ LIBRARY *************** */
 
 
-static void direct_link_library(FileData *fd, Library *lib)
+static void direct_link_library(FileData *fd, Library *lib, Main *main)
 {
        Main *newmain;
-
+       Library *libr;
+       
+       for(newmain= fd->mainlist.first; newmain; newmain= newmain->next) {
+               if(newmain->curlib) {
+                       if(strcmp(newmain->curlib->name, lib->name)==0) {
+                               printf("Fixed error in file; multiple instances of lib:\n %s\n", lib->name);
+                               
+                               change_idid_adr_fd(fd, lib, newmain->curlib);
+                               
+                               BLI_remlink(&main->library, lib);
+                               MEM_freeN(lib);
+                               return;
+                       }
+               }
+       }
+       
        /* new main */
        newmain= MEM_callocN(sizeof(Main), "directlink");
        BLI_addtail(&fd->mainlist, newmain);
@@ -3147,47 +3170,34 @@ static void lib_link_sound(FileData *fd, Main *main)
 
 static void direct_link_group(FileData *fd, Group *group)
 {
-       GroupObject *go;
-       ObjectKey *ok;
-
        link_list(fd, &group->gobject);
-       link_list(fd, &group->gkey);
-       group->active= newdataadr(fd, group->active);
-
-       go= group->gobject.first;
-       while(go) {
-               link_list(fd, &go->okey);
-               ok= go->okey.first;
-               while(ok) {
-                       ok->gkey= newdataadr(fd, ok->gkey);
-                       ok= ok->next;
-               }
-               go= go->next;
-       }
 }
 
 static void lib_link_group(FileData *fd, Main *main)
 {
        Group *group= main->group.first;
        GroupObject *go;
-       ObjectKey *ok;
-
+       int add_us;
+       
        while(group) {
                if(group->id.flag & LIB_NEEDLINK) {
                        group->id.flag -= LIB_NEEDLINK;
-
+                       
+                       add_us= 0;
+                       
                        go= group->gobject.first;
                        while(go) {
                                go->ob= newlibadr(fd, group->id.lib, go->ob);
-                               ok= go->okey.first;
-                               while(ok) {
-                                       ok->parent= newlibadr(fd, group->id.lib, ok->parent);
-                                       ok->track= newlibadr(fd, group->id.lib, ok->track);
-                                       ok->ipo= newlibadr_us(fd, group->id.lib, ok->ipo);
-                                       ok= ok->next;
+                               if(go->ob) {
+                                       /* if group has an object, it increments user... */
+                                       add_us= 1;
+                                       if(go->ob->id.us==0) 
+                                               go->ob->id.us= 1;
                                }
                                go= go->next;
                        }
+                       if(add_us) group->id.us++;
+                       rem_from_group(group, NULL);    /* removes NULL entries */
                }
                group= group->id.next;
        }
@@ -3220,8 +3230,8 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                *id_r= id;
        if (!id)
                return blo_nextbhead(fd, bhead);
-
-       oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+       
+       oldnewmap_insert(fd->libmap, bhead->old, id, bhead->code);      /* for ID_ID check */
        BLI_addtail(lb, id);
 
        /* clear first 8 bits */
@@ -3263,7 +3273,6 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
        case ID_SO: str= "ID_SO"; break;
        case ID_SAMPLE: str= "ID_SAMPLE"; break;
        case ID_GR: str= "ID_GR"; break;
-       case ID_ID: str= "ID_ID"; break;
        case ID_SEQ: str= "ID_SEQ"; break;
        case ID_AR: str= "ID_AR"; break;
        case ID_AC: str= "ID_AC"; break;
@@ -3330,7 +3339,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                        direct_link_world(fd, (World *)id);
                        break;
                case ID_LI:
-                       direct_link_library(fd, (Library *)id);
+                       direct_link_library(fd, (Library *)id, main);
                        break;
                case ID_CA:
                        direct_link_camera(fd, (Camera *)id);
@@ -3428,6 +3437,17 @@ static void bone_version_238(ListBase *lb)
        }
 }
 
+static void bone_version_239(ListBase *lb)
+{
+       Bone *bone;
+       
+       for(bone= lb->first; bone; bone= bone->next) {
+               if(bone->layer==0) 
+                       bone->layer= 1;
+               bone_version_239(&bone->childbase);
+       }
+}
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -5046,6 +5066,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                /* updating stepsize for ghost drawing */
                for(arm= main->armature.first; arm; arm= arm->id.next) {
                        if (arm->ghostsize==0) arm->ghostsize=1;
+                       bone_version_239(&arm->bonebase);
+                       if(arm->layer==0) arm->layer= 1;
                }
                
                for(;sce;sce= sce->id.next) {
@@ -5089,6 +5111,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                if(ma->mode & MA_TRACEBLE) ma->mode |= MA_SHADBUF;
                                ma->pad= 1;
                        }
+                       /* orange stuff, so should be done for 2.40 too */
+                       if(ma->layers.first==NULL) {
+                               ma->ml_flag= ML_RENDER;
+                       }
                }
        }
        
@@ -5100,6 +5126,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
 static void lib_link_all(FileData *fd, Main *main)
 {
+       oldnewmap_sort(fd);
+       
        lib_link_screen(fd, main);
        lib_link_scene(fd, main);
        lib_link_object(fd, main);
@@ -5202,6 +5230,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, BlendReadError *error_r)
        blo_join_main(&fd->mainlist);
 
        lib_link_all(fd, bfd->main);
+       
        link_global(fd, bfd, fg);       /* as last */
 
        /* removed here: check for existance of curscreen/scene, moved to kernel setup_app */
@@ -5268,6 +5297,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                        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);
 
                                id= is_yet_read(mainvar, bhead);
@@ -5277,7 +5307,9 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                                        printf("expand: other lib %s\n", lib->name);
                                }
                                else {
-                                       oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+                                       //oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+                                       
+                                       change_idid_adr_fd(fd, bhead->old, id);
                                        printf("expand: already linked: %s lib: %s\n", id->name, lib->name);
                                }
                        }
@@ -5290,13 +5322,24 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                                read_libblock(fd, mainvar, bhead, LIB_TESTIND, NULL);
                        }
                        else {
-                               oldnewmap_insert(fd->libmap, bhead->old, id, 1);
+                               /* removed line below... I *really* dont know whatfor (Id is read, so...) 
+                                  it caused a whole lot of extra and unneeded oldmap entries */
+                               /* oldnewmap_insert(fd->libmap, bhead->old, id, 1); */
                                /* printf("expand: already read %s\n", id->name); */
                        }
                }
        }
 }
 
+static void expand_group(FileData *fd, Main *mainvar, Group *group)
+{
+       GroupObject *go;
+       
+       for(go= group->gobject.first; go; go= go->next) {
+               expand_doit(fd, mainvar, go->ob);
+       }
+}
+
 static void expand_key(FileData *fd, Main *mainvar, Key *key)
 {
        expand_doit(fd, mainvar, key->ipo);
@@ -5311,6 +5354,7 @@ static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
 
 static void expand_material(FileData *fd, Main *mainvar, Material *ma)
 {
+       MaterialLayer *ml;
        int a;
 
        for(a=0; a<MAX_MTEX; a++) {
@@ -5319,7 +5363,13 @@ static void expand_material(FileData *fd, Main *mainvar, Material *ma)
                        expand_doit(fd, mainvar, ma->mtex[a]->object);
                }
        }
+       
        expand_doit(fd, mainvar, ma->ipo);
+       
+       for (ml=ma->layers.first; ml; ml=ml->next) {
+               if(ml->mat)
+                       expand_doit(fd, mainvar, ml->mat);
+       }
 }
 
 static void expand_lamp(FileData *fd, Main *mainvar, Lamp *la)
@@ -5565,6 +5615,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        expand_constraint_channels(fd, mainvar, &ob->constraintChannels);
 
        for (strip=ob->nlastrips.first; strip; strip=strip->next){
+               expand_doit(fd, mainvar, strip->object);
                expand_doit(fd, mainvar, strip->act);
                expand_doit(fd, mainvar, strip->ipo);
        }
@@ -5728,6 +5779,9 @@ static void expand_main(FileData *fd, Main *mainvar)
                                        case ID_AC:
                                                expand_action(fd, mainvar, (bAction *)id);
                                                break;
+                                       case ID_GR:
+                                               expand_group(fd, mainvar, (Group *)id);
+                                               break;
                                        }
 
                                        doit= 1;
@@ -5757,8 +5811,9 @@ static void give_base_to_objects(Scene *sce, ListBase *lb)
                                BLI_addtail(&(sce->base), base);
                                base->lay= ob->lay;
                                base->object= ob;
+                               base->flag= ob->flag;
                                ob->id.us= 1;
-
+                               
                                ob->id.flag -= LIB_INDIRECT;
                                ob->id.flag |= LIB_EXTERN;
 
@@ -5933,7 +5988,8 @@ void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
        
        /* make copy of the 'last loaded filename', we need to restore it */
        BLI_strncpy(filename, G.sce, sizeof(filename));
-       BLI_strncpy(G.sce, fd->filename, sizeof(filename));             // already opened file, to reconstruct relative paths
+       
+       BLI_strncpy(G.sce, G.main->name, sizeof(G.main->name));         // original file, to reconstruct relative paths for current append
        
        if(sfile->flag & FILE_AUTOSELECT) scene_deselect_all(G.scene);
 
@@ -5965,6 +6021,7 @@ void BLO_library_append(SpaceFile *sfile, char *dir, int idcode)
        read_libraries(fd, &fd->mainlist);
 
        if(sfile->flag & FILE_STRINGCODE) {
+
                /* uses old .blend file (*filename) as reference */
                BLI_makestringcode(filename, mainl->curlib->name);
                /* the caller checks for appended library, so we make sure names match */
@@ -6068,8 +6125,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                if (fd->libmap)
                                                        oldnewmap_free(fd->libmap);
 
-                                               fd->libmap= basefd->libmap;
-                                               fd->flags|= FD_FLAGS_NOT_MY_LIBMAP;
+                                               fd->libmap = oldnewmap_new();
                                                
                                                mainptr->curlib->filedata= fd;
                                                mainptr->versionfile= fd->fileversion;
@@ -6094,7 +6150,8 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                                append_id_part(fd, mainptr, id, &realid);
                                                                if (!realid)
                                                                        printf("LIB ERROR: can't find %s\n", id->name);
-                                                               change_libadr(fd, id, realid);
+                                                               
+                                                               change_idid_adr(mainlist, basefd, id, realid);
 
                                                                MEM_freeN(id);
                                                        }
@@ -6116,9 +6173,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                        mainptr= mainptr->next;
                }
        }
-       mainptr= mainl->next;
-       while(mainptr) {
-               /* test if there are unread libblocks */
+       
+       /* test if there are unread libblocks */
+       for(mainptr= mainl->next; mainptr; mainptr= mainptr->next) {
                a= set_listbasepointers(mainptr, lbarray);
                while(a--) {
                        ID *id= lbarray[a]->first;
@@ -6128,14 +6185,17 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                        BLI_remlink(lbarray[a], id);
 
                                        printf("LIB ERROR: can't find %s\n", id->name);
-                                       change_libadr(basefd, id, 0);
+                                       change_idid_adr(mainlist, basefd, id, NULL);
 
                                        MEM_freeN(id);
                                }
                                id= idn;
                        }
                }
-
+       }
+       
+       /* do versions, link, and free */
+       for(mainptr= mainl->next; mainptr; mainptr= mainptr->next) {
                /* some mains still have to be read, then
                 * versionfile is still zero! */
                if(mainptr->versionfile) {
@@ -6145,10 +6205,12 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                do_versions(basefd, NULL, mainptr);
                }
                
+               if(mainptr->curlib->filedata)
+                       lib_link_all(mainptr->curlib->filedata, mainptr);
+               
                if(mainptr->curlib->filedata) blo_freefiledata(mainptr->curlib->filedata);
                mainptr->curlib->filedata= NULL;
 
-               mainptr= mainptr->next;
        }
 }