Merge from Harmonic Skeleton branch
[blender.git] / source / blender / blenloader / intern / readfile.c
index e3ed6301fe02937f4cd218e2c506a382e24d4a6f..4b8418a78b908fd9a727d31fc9f6fcf2e356e15d 100644 (file)
@@ -86,6 +86,7 @@
 #include "DNA_oops_types.h"
 #include "DNA_object_force.h"
 #include "DNA_packedFile_types.h"
+#include "DNA_particle_types.h"
 #include "DNA_property_types.h"
 #include "DNA_text_types.h"
 #include "DNA_view3d_types.h"
 #include "BKE_global.h" // for G
 #include "BKE_group.h"
 #include "BKE_image.h"
+#include "BKE_key.h" //void set_four_ipo
 #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_particle.h"
 #include "BKE_property.h" // for get_property
 #include "BKE_sca.h" // for init_actuator
 #include "BKE_scene.h"
@@ -476,7 +479,27 @@ static void cleanup_path(const char *relabase, char *name)
        strcat(name, filename);
 }
 
-static Main *blo_find_main(ListBase *mainlist, const char *name, const char *relabase)
+static void read_file_version(FileData *fd, Main *main)
+{
+       BHead *bhead;
+       
+       for (bhead= blo_firstbhead(fd); bhead; bhead= blo_nextbhead(fd, bhead)) {
+               if (bhead->code==GLOB) {
+                       FileGlobal *fg= read_struct(fd, bhead, "Global");
+                       if(fg) {
+                               main->subversionfile= fg->subversion;
+                               main->minversionfile= fg->minversion;
+                               main->minsubversionfile= fg->minsubversion;
+                               MEM_freeN(fg);
+                       }
+                       else if (bhead->code==ENDB)
+                               break;
+               }
+       }
+}
+
+
+static Main *blo_find_main(FileData *fd, ListBase *mainlist, const char *name, const char *relabase)
 {
        Main *m;
        Library *lib;
@@ -505,6 +528,8 @@ static Main *blo_find_main(ListBase *mainlist, const char *name, const char *rel
        
        m->curlib= lib;
        
+       read_file_version(fd, m);
+       
        if(G.f & G_DEBUG) printf("blo_find_main: added new lib %s\n", name);
        return m;
 }
@@ -725,26 +750,6 @@ 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];
@@ -1616,7 +1621,9 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                if(con->data==NULL) {
                        con->type= CONSTRAINT_TYPE_NULL;
                }
-
+               /* own ipo, all constraints have it */
+               con->ipo= newlibadr_us(fd, id->lib, con->ipo);
+               
                switch (con->type) {
                case CONSTRAINT_TYPE_PYTHON:
                        {
@@ -2451,6 +2458,79 @@ static void direct_link_material(FileData *fd, Material *ma)
        ma->preview = direct_link_preview_image(fd, ma->preview);
 }
 
+/* ************ READ PARTICLE SETTINGS ***************** */
+
+static void lib_link_particlesettings(FileData *fd, Main *main)
+{
+       ParticleSettings *part;
+
+       part= main->particle.first;
+       while(part) {
+               if(part->id.flag & LIB_NEEDLINK) {
+                       part->ipo= newlibadr_us(fd, part->id.lib, part->ipo);
+                       part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
+                       part->dup_group = newlibadr(fd, part->id.lib, part->dup_group);
+                       part->eff_group = newlibadr(fd, part->id.lib, part->eff_group);
+                       part->bb_ob = newlibadr(fd, part->id.lib, part->bb_ob);
+                       part->id.flag -= LIB_NEEDLINK;
+               }
+               part= part->id.next;
+       }
+}
+
+static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
+{
+       part->pd= newdataadr(fd, part->pd);
+}
+
+static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles)
+{
+       ParticleSystem *psys;
+       int a;
+
+       for(psys=particles->first; psys; psys=psys->next){
+               ParticleData *pa;
+               psys->part = newlibadr_us(fd, id->lib, psys->part);
+               psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
+               psys->keyed_ob = newlibadr(fd, id->lib, psys->keyed_ob);
+
+               for(a=0,pa=psys->particles; a<psys->totpart; a++,pa++){
+                       pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob);
+               }
+       }
+}
+static void direct_link_particlesystems(FileData *fd, ListBase *particles)
+{
+       ParticleSystem *psys;
+       int a;
+
+       for(psys=particles->first; psys; psys=psys->next) {
+               psys->particles=newdataadr(fd,psys->particles);
+               if(psys->particles && psys->particles->hair){
+                       ParticleData *pa = psys->particles;
+                       for(a=0; a<psys->totpart; a++, pa++)
+                               pa->hair=newdataadr(fd,pa->hair);
+               }
+               psys->child=newdataadr(fd,psys->child);
+               psys->effectors.first=psys->effectors.last=0;
+
+               psys->soft= newdataadr(fd, psys->soft);
+               if(psys->soft) {
+                       SoftBody *sb = psys->soft;
+                       sb->particles = psys;
+                       sb->bpoint= NULL;       // init pointers so it gets rebuilt nicely
+                       sb->bspring= NULL;
+                       sb->scratch= NULL;
+               }
+
+               psys->edit = 0;
+               psys->pathcache = 0;
+               psys->childcache = 0;
+               psys->reactevents.first = psys->reactevents.last = 0;
+       }
+       return;
+}
+
 /* ************ READ MESH ***************** */
 
 static void lib_link_mtface(FileData *fd, Mesh *me, MTFace *mtface, int totface)
@@ -2830,8 +2910,14 @@ static void lib_link_object(FileData *fd, Main *main)
                        if(ob->fluidsimSettings) {
                                ob->fluidsimSettings->ipo = newlibadr_us(fd, ob->id.lib, ob->fluidsimSettings->ipo);
                        }
+                       
+                       /* texture field */
+                       if(ob->pd)
+                               if(ob->pd->tex)
+                                       ob->pd->tex=newlibadr_us(fd, ob->id.lib, ob->pd->tex);
 
                        lib_link_scriptlink(fd, &ob->id, &ob->scriptlink);
+                       lib_link_particlesystems(fd, &ob->id, &ob->particlesystem);
                        lib_link_modifiers(fd, ob);
                }
                ob= ob->id.next;
@@ -2888,20 +2974,38 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                                        SWITCH_INT(hmd->indexar[a]);
                                }
                        }
+               } else if (md->type==eModifierType_ParticleSystem) {
+                       ParticleSystemModifierData *psmd = (ParticleSystemModifierData*) md;
+
+                       psmd->dm=0;
+                       psmd->psys=newdataadr(fd, psmd->psys);
+                       psmd->flag &= ~eParticleSystemFlag_psys_updated;
+               } else if (md->type==eModifierType_Explode) {
+                       ExplodeModifierData *psmd = (ExplodeModifierData*) md;
+
+                       psmd->facepa=0;
                }
                else if (md->type==eModifierType_MeshDeform) {
                        MeshDeformModifierData *mmd = (MeshDeformModifierData*) md;
 
                        mmd->bindweights= newdataadr(fd, mmd->bindweights);
                        mmd->bindcos= newdataadr(fd, mmd->bindcos);
+                       mmd->dyngrid= newdataadr(fd, mmd->dyngrid);
+                       mmd->dyninfluences= newdataadr(fd, mmd->dyninfluences);
+                       mmd->dynverts= newdataadr(fd, mmd->dynverts);
 
                        if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
                                int a;
 
-                               for(a=0; a<mmd->totcagevert*mmd->totvert; a++)
-                                       SWITCH_INT(mmd->bindweights[a])
-                               for(a=0; a<mmd->totcagevert*3; a++)
-                                       SWITCH_INT(mmd->bindcos[a])
+                               if(mmd->bindweights)
+                                       for(a=0; a<mmd->totcagevert*mmd->totvert; a++)
+                                               SWITCH_INT(mmd->bindweights[a])
+                               if(mmd->bindcos)
+                                       for(a=0; a<mmd->totcagevert*3; a++)
+                                               SWITCH_INT(mmd->bindcos[a])
+                               if(mmd->dynverts)
+                                       for(a=0; a<mmd->totvert; a++)
+                                               SWITCH_INT(mmd->dynverts[a])
                        }
                }
        }
@@ -3006,7 +3110,8 @@ static void direct_link_object(FileData *fd, Object *ob)
                sb->bspring= NULL;
                sb->scratch= NULL;
 
-               
+               /* although not used anymore */
+               /* still have to be loaded to be compatible with old files */
                sb->keys= newdataadr(fd, sb->keys);
                test_pointer_array(fd, (void **)&sb->keys);
                if(sb->keys) {
@@ -3023,6 +3128,9 @@ static void direct_link_object(FileData *fd, Object *ob)
                ob->fluidsimSettings->meshBB = NULL;
                ob->fluidsimSettings->meshSurfNormals = NULL;
        }
+
+       link_list(fd, &ob->particlesystem);
+       direct_link_particlesystems(fd,&ob->particlesystem);
        
        link_list(fd, &ob->prop);
        prop= ob->prop.first;
@@ -3196,7 +3304,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        Editing *ed;
        Sequence *seq;
        MetaStack *ms;
-       StripElem *se;
        int a;
 
        sce->theDag = NULL;
@@ -3232,8 +3339,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                        /* a patch: after introduction of effects with 3 input strips */
                        if(seq->seq3==0) seq->seq3= seq->seq2;
 
-                       seq->curelem= 0;
-
                        seq->plugin= newdataadr(fd, seq->plugin);
                        seq->effectdata= newdataadr(fd, seq->effectdata);
                        
@@ -3244,59 +3349,17 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                        seq->strip= newdataadr(fd, seq->strip);
                        if(seq->strip && seq->strip->done==0) {
                                seq->strip->done= 1;
-
-                               /* standard: strips from effects/metas are not written, but are mallocced */
-
-                               if(seq->type==SEQ_IMAGE) {
-                                       seq->strip->stripdata= newdataadr(fd, seq->strip->stripdata);
-                                       se= seq->strip->stripdata;
-                                       if(se) {
-                                               for(a=0; a<seq->strip->len; a++, se++) {
-                                                       se->ok= 1;
-                                                       se->ibuf= 0;
-                                               }
-                                       }
-                               }
-                               else if(seq->type==SEQ_MOVIE) {
-                                       /* only first stripelem is in file */
-                                       se= newdataadr(fd, seq->strip->stripdata);
-
-                                       if(se) {
-                                               seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
-                                               *seq->strip->stripdata= *se;
-                                               MEM_freeN(se);
-
-                                               se= seq->strip->stripdata;
-
-                                               for(a=0; a<seq->strip->len; a++, se++) {
-                                                       se->ok= 1;
-                                                       se->ibuf= 0;
-                                                       se->nr= a + 1;
-                                               }
-                                       }
-                               }
-                               else if(seq->type==SEQ_RAM_SOUND
-                                       || seq->type == SEQ_HD_SOUND) {
-                                       /* only first stripelem is in file */
-                                       se= newdataadr(fd, seq->strip->stripdata);
-
-                                       if(se) {
-                                               seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
-                                               *seq->strip->stripdata= *se;
-                                               MEM_freeN(se);
-
-                                               se= seq->strip->stripdata;
-
-                                               for(a=0; a<seq->strip->len; a++, se++) {
-                                                       se->ok= 2; /* why? */
-                                                       se->ibuf= 0;
-                                                       se->nr= a + 1;
-                                               }
-                                       }
+                               seq->strip->tstripdata = 0;
+
+                               if(seq->type == SEQ_IMAGE ||
+                                  seq->type == SEQ_MOVIE ||
+                                  seq->type == SEQ_RAM_SOUND ||
+                                  seq->type == SEQ_HD_SOUND) {
+                                       seq->strip->stripdata = newdataadr(
+                                               fd, seq->strip->stripdata);
+                               } else {
+                                       seq->strip->stripdata = 0;
                                }
-                               else if(seq->len>0)
-                                       seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
-
                        }
                }
                END_SEQ
@@ -3995,6 +4058,7 @@ static char *dataname(short id_code)
                case ID_SO: return "Data from SO";
                case ID_NT: return "Data from NT";
                case ID_BR: return "Data from BR";
+               case ID_PA: return "Data from PA";
        }
        return "Data from Lib Block";
        
@@ -4131,6 +4195,9 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
                case ID_BR:
                        direct_link_brush(fd, (Brush*)id);
                        break;
+               case ID_PA:
+                       direct_link_particlesettings(fd, (ParticleSettings*)id);
+                       break;
        }
        
        /*link direct data of ID properties*/
@@ -6605,6 +6672,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Image *ima;
                Lamp *la;
                Material *ma;
+               ParticleSettings *part;
                
                /* unless the file was created 2.44.3 but not 2.45, update the constraints */
                if ( !(main->versionfile==244 && main->subversionfile==3) &&
@@ -6767,8 +6835,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ma->fadeto_mir = MA_RAYMIR_FADETOSKY;
                        }
                }
-               
-               if (main->versionfile < 245 || main->subversionfile < 9)
+
+               for(part=main->particle.first; part; part=part->id.next)
+                       if(part->ren_child_nbr==0)
+                               part->ren_child_nbr= part->child_nbr;
+               if (main->versionfile < 245 || main->subversionfile < 11)
                {
                        /* initialize skeleton generation toolsettings */
                        for(sce=main->scene.first; sce; sce = sce->id.next)
@@ -6783,9 +6854,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                sce->toolsettings->skgen_symmetry_limit                 = 0.1f;
                                sce->toolsettings->skgen_postpro = SKGEN_SMOOTH;
                                sce->toolsettings->skgen_postpro_passes = 1;
-                               sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_CUT_LENGTH|SKGEN_SUB_CORRELATION;
-                               sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_LENGTH;
-                               sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_CORRELATION;
+                               sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL|SKGEN_FILTER_EXTERNAL|SKGEN_SUB_CORRELATION;
+                               sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION;
+                               sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH;
                                sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE;
                        }
                }
@@ -6838,6 +6909,91 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
        
+       if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 7)) {
+               Object *ob;
+               bPoseChannel *pchan;
+               bConstraint *con;
+               bConstraintTarget *ct;
+               
+               for (ob = main->object.first; ob; ob= ob->id.next) {
+                       if (ob->pose) {
+                               for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
+                                       for (con=pchan->constraints.first; con; con=con->next) {
+                                               if (con->type == CONSTRAINT_TYPE_PYTHON) {
+                                                       bPythonConstraint *data= (bPythonConstraint *)con->data;
+                                                       if (data->tar) {
+                                                               /* version patching needs to be done */
+                                                               ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
+                                                               
+                                                               ct->tar = data->tar;
+                                                               strcpy(ct->subtarget, data->subtarget);
+                                                               ct->space = con->tarspace;
+                                                               
+                                                               BLI_addtail(&data->targets, ct);
+                                                               data->tarnum++;
+                                                               
+                                                               /* clear old targets to avoid problems */
+                                                               data->tar = NULL;
+                                                               strcpy(data->subtarget, "");
+                                                       }
+                                               }
+                                               else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
+                                                       bLocateLikeConstraint *data= (bLocateLikeConstraint *)con->data;
+                                                       
+                                                       /* new headtail functionality makes Bone-Tip function obsolete */
+                                                       if (data->flag & LOCLIKE_TIP)
+                                                               con->headtail = 1.0f;
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       for (con=ob->constraints.first; con; con=con->next) {
+                               if (con->type==CONSTRAINT_TYPE_PYTHON) {
+                                       bPythonConstraint *data= (bPythonConstraint *)con->data;
+                                       if (data->tar) {
+                                               /* version patching needs to be done */
+                                               ct= MEM_callocN(sizeof(bConstraintTarget), "PyConTarget");
+                                               
+                                               ct->tar = data->tar;
+                                               strcpy(ct->subtarget, data->subtarget);
+                                               ct->space = con->tarspace;
+                                               
+                                               BLI_addtail(&data->targets, ct);
+                                               data->tarnum++;
+                                               
+                                               /* clear old targets to avoid problems */
+                                               data->tar = NULL;
+                                               strcpy(data->subtarget, "");
+                                       }
+                               }
+                               else if (con->type == CONSTRAINT_TYPE_LOCLIKE) {
+                                       bLocateLikeConstraint *data= (bLocateLikeConstraint *)con->data;
+                                       
+                                       /* new headtail functionality makes Bone-Tip function obsolete */
+                                       if (data->flag & LOCLIKE_TIP)
+                                               con->headtail = 1.0f;
+                               }
+                       }
+
+                       if(ob->soft && ob->soft->keys) {
+                               SoftBody *sb = ob->soft;
+                               int k;
+
+                               for(k=0; k<sb->totkey; k++) {
+                                       if(sb->keys[k])
+                                               MEM_freeN(sb->keys[k]);
+                               }
+
+                               MEM_freeN(sb->keys);
+
+                               sb->keys = NULL;
+                               sb->totkey = 0;
+                               ob->softflag &= ~OB_SB_BAKESET;
+                       }
+               }
+       }
+
        if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 7)) {
                Object *ob;
                bPoseChannel *pchan;
@@ -6893,6 +7049,196 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
+       if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 8)) {
+               Scene *sce;
+               Object *ob;
+               PartEff *paf=0;
+
+               for(ob = main->object.first; ob; ob= ob->id.next) {
+                       if(ob->soft && ob->soft->keys) {
+                               SoftBody *sb = ob->soft;
+                               int k;
+
+                               for(k=0; k<sb->totkey; k++) {
+                                       if(sb->keys[k])
+                                               MEM_freeN(sb->keys[k]);
+                               }
+
+                               MEM_freeN(sb->keys);
+
+                               sb->keys = NULL;
+                               sb->totkey = 0;
+                               ob->softflag &= ~OB_SB_BAKESET;
+                       }
+
+                       /* convert old particles to new system */
+                       if((paf = give_parteff(ob))) {
+                               ParticleSystem *psys;
+                               ModifierData *md;
+                               ParticleSystemModifierData *psmd;
+                               ParticleSettings *part;
+
+                               /* create new particle system */
+                               psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
+
+                               part = psys->part = psys_new_settings("PSys", main);
+                               
+                               /* needed for proper libdata lookup */
+                               oldnewmap_insert(fd->libmap, psys->part, psys->part, 0);
+
+                               part->id.us--;
+                               
+                               psys->totpart=0;
+                               psys->flag=PSYS_ENABLED|PSYS_CURRENT;
+
+                               BLI_addtail(&ob->particlesystem, psys);
+
+                               md= modifier_new(eModifierType_ParticleSystem);
+                               sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
+                               psmd= (ParticleSystemModifierData*) md;
+                               psmd->psys=psys;
+                               BLI_addtail(&ob->modifiers, md);
+
+                               /* convert settings from old particle system */
+                               /* general settings */
+                               part->totpart = MIN2(paf->totpart, 100000);
+                               part->sta = paf->sta;
+                               part->end = paf->end;
+                               part->lifetime = paf->lifetime;
+                               part->randlife = paf->randlife;
+                               psys->seed = paf->seed;
+                               part->disp = paf->disp;
+                               part->omat = paf->mat[0];
+                               part->hair_step = paf->totkey;
+
+                               part->eff_group = paf->group;
+
+                               /* physics */
+                               part->normfac = paf->normfac * 25.0f;
+                               part->obfac = paf->obfac;
+                               part->randfac = paf->randfac * 25.0f;
+                               part->dampfac = paf->damp;
+                               VECCOPY(part->acc, paf->force);
+
+                               /* flags */
+                               if(paf->stype & PAF_VECT) {
+                                       if(paf->flag & PAF_STATIC) {
+                                               /* new hair lifetime is always 100.0f */
+                                               float fac = paf->lifetime / 100.0f;
+
+                                               part->draw_as = PART_DRAW_PATH;
+                                               part->type = PART_HAIR;
+                                               psys->recalc |= PSYS_RECALC_HAIR;
+
+                                               part->normfac *= fac;
+                                               part->randfac *= fac;
+                                       }
+                                       else {
+                                               part->draw_as = PART_DRAW_LINE;
+                                               part->draw |= PART_DRAW_VEL_LENGTH;
+                                               part->draw_line[1] = 0.04f;
+                                       }
+                               }
+
+                               part->rotmode = PART_ROT_VEL;
+                               
+                               part->flag |= (paf->flag & PAF_BSPLINE) ? PART_HAIR_BSPLINE : 0;
+                               part->flag |= (paf->flag & PAF_TRAND) ? PART_TRAND : 0;
+                               part->flag |= (paf->flag & PAF_EDISTR) ? PART_EDISTR : 0;
+                               part->flag |= (paf->flag & PAF_UNBORN) ? PART_UNBORN : 0;
+                               part->flag |= (paf->flag & PAF_DIED) ? PART_DIED : 0;
+                               part->from |= (paf->flag & PAF_FACE) ? PART_FROM_FACE : 0;
+                               part->draw |= (paf->flag & PAF_SHOWE) ? PART_DRAW_EMITTER : 0;
+
+                               psys->vgroup[PSYS_VG_DENSITY] = paf->vertgroup;
+                               psys->vgroup[PSYS_VG_VEL] = paf->vertgroup_v;
+                               psys->vgroup[PSYS_VG_LENGTH] = paf->vertgroup_v;
+
+                               /* dupliobjects */
+                               if(ob->transflag & OB_DUPLIVERTS) {
+                                       Object *dup = main->object.first;
+
+                                       for(; dup; dup= dup->id.next) {
+                                               if(ob == newlibadr(fd, lib, dup->parent)) {
+                                                       part->dup_ob = dup;
+                                                       ob->transflag |= OB_DUPLIPARTS;
+                                                       ob->transflag &= ~OB_DUPLIVERTS;
+
+                                                       part->draw_as = PART_DRAW_OB;
+                                               }
+                                       }
+                               }
+
+                               free_effects(&ob->effect);
+
+                               printf("Old particle system converted to new system.\n");
+                       }
+               }
+
+               for(sce= main->scene.first; sce; sce=sce->id.next) {
+                       ParticleEditSettings *pset= &sce->toolsettings->particle;
+                       int a;
+
+                       if(pset->brush[0].size == 0) {
+                               pset->flag= PE_KEEP_LENGTHS|PE_LOCK_FIRST|PE_DEFLECT_EMITTER;
+                               pset->emitterdist= 0.25f;
+                               pset->totrekey= 5;
+                               pset->totaddkey= 5;
+                               pset->brushtype= PE_BRUSH_NONE;
+
+                               for(a=0; a<PE_TOT_BRUSH; a++) {
+                                       pset->brush[a].strength= 50;
+                                       pset->brush[a].size= 50;
+                                       pset->brush[a].step= 10;
+                               }
+
+                               pset->brush[PE_BRUSH_CUT].strength= 100;
+                       }
+               }
+       }
+       if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 9)) {
+               Material *ma;
+               int a;
+
+               for(ma=main->mat.first; ma; ma= ma->id.next)
+                       if(ma->mode & MA_NORMAP_TANG)
+                               for(a=0; a<MAX_MTEX; a++)
+                                       if(ma->mtex[a] && ma->mtex[a]->tex)
+                                               ma->mtex[a]->normapspace = MTEX_NSPACE_TANGENT;
+       }
+       
+       if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 10)) {
+               Object *ob;
+               
+               /* dupliface scale */
+               for(ob= main->object.first; ob; ob= ob->id.next)
+                       ob->dupfacesca = 1.0f;
+       }
+       
+       if ((main->versionfile < 245) || (main->versionfile == 245 && main->subversionfile < 11)) {
+               Object *ob;
+               bActionStrip *strip;
+               
+               /* nla-strips - scale */                
+               for (ob= main->object.first; ob; ob= ob->id.next) {
+                       for (strip= ob->nlastrips.first; strip; strip= strip->next) {
+                               float length, actlength, repeat;
+                               
+                               if (strip->flag & ACTSTRIP_USESTRIDE)
+                                       repeat= 1.0f;
+                               else
+                                       repeat= strip->repeat;
+                               
+                               length = strip->end-strip->start;
+                               if (length == 0.0f) length= 1.0f;
+                               actlength = strip->actend-strip->actstart;
+                               
+                               strip->scale = length / (repeat * actlength);
+                               if (strip->scale == 0.0f) strip->scale= 1.0f;
+                       }       
+               }
+       }
+
        
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
@@ -6927,6 +7273,7 @@ static void lib_link_all(FileData *fd, Main *main)
        lib_link_screen_sequence_ipos(main);
        lib_link_nodetree(fd, main);    /* has to be done after scene/materials, this will verify group nodes */
        lib_link_brush(fd, main);
+       lib_link_particlesettings(fd, main);
 
        lib_link_mesh(fd, main);                /* as last: tpage images with users at zero */
 
@@ -7084,7 +7431,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
 
                        if(bheadlib) {
                                Library *lib= read_struct(fd, bheadlib, "Library");
-                               Main *ptr= blo_find_main(&fd->mainlist, lib->name, fd->filename);
+                               Main *ptr= blo_find_main(fd, &fd->mainlist, lib->name, fd->filename);
 
                                id= is_yet_read(fd, ptr, bhead);
 
@@ -7286,6 +7633,10 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
        bConstraint *curcon;
 
        for (curcon=lb->first; curcon; curcon=curcon->next) {
+               
+               if (curcon->ipo)
+                       expand_doit(fd, mainvar, curcon->ipo);
+               
                switch (curcon->type) {
                case CONSTRAINT_TYPE_NULL:
                        break;
@@ -7459,6 +7810,11 @@ static void expand_modifier(FileData *fd, Main *mainvar, ModifierData *md)
                expand_doit(fd, mainvar, amd->curve_ob);
                expand_doit(fd, mainvar, amd->offset_ob);
        }
+       else if (md->type==eModifierType_Mirror) {
+               MirrorModifierData *mmd = (MirrorModifierData*) md;
+                       
+               expand_doit(fd, mainvar, mmd->mirror_ob);
+       }
 }
 
 static void expand_scriptlink(FileData *fd, Main *mainvar, ScriptLink *slink)
@@ -7473,6 +7829,7 @@ static void expand_scriptlink(FileData *fd, Main *mainvar, ScriptLink *slink)
 static void expand_object(FileData *fd, Main *mainvar, Object *ob)
 {
        ModifierData *md;
+       ParticleSystem *psys;
        bSensor *sens;
        bController *cont;
        bActuator *act;
@@ -7515,6 +7872,9 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
        if(ob->proxy_group)
                expand_doit(fd, mainvar, ob->proxy_group);
 
+       for(psys=ob->particlesystem.first; psys; psys=psys->next)
+               expand_doit(fd, mainvar, psys->part);
+
        sens= ob->sensors.first;
        while(sens) {
                for(a=0; a<sens->totlinks; a++) {
@@ -7841,7 +8201,7 @@ static Library* library_append( Scene *scene, char* file, char *dir, int idcode,
        blo_split_main(&fd->mainlist, G.main);
 
        /* which one do we need? */
-       mainl = blo_find_main(&fd->mainlist, dir, G.sce);
+       mainl = blo_find_main(fd, &fd->mainlist, dir, G.sce);
        
        mainl->versionfile= fd->fileversion;    /* needed for do_version */
        
@@ -8050,6 +8410,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                                
                                                mainptr->curlib->filedata= fd;
                                                mainptr->versionfile= fd->fileversion;
+                                               
+                                               /* subversion */
+                                               read_file_version(fd, mainptr);
                                        }
                                        else mainptr->curlib->filedata= NULL;