Fix #21577: incorrect camera selected when loading file without UI.
[blender.git] / source / blender / blenloader / intern / readfile.c
index 84cb61af5aec92b018e52b97f034b9b4de72cac2..1f6d36dc95710cacf469cbd93e4ee0ff988f2e29 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 #include <limits.h>
 #include <stdio.h> // for printf fopen fwrite fclose sprintf FILE
 #include <stdlib.h> // for getenv atoi
+#include <stddef.h> // for offsetof
 #include <fcntl.h> // for open
 #include <string.h> // for strrchr strncmp strstr
 #include <math.h> // for fabs
 
 #ifndef WIN32
-    #include <unistd.h> // for read close
-    #include <sys/param.h> // for MAXPATHLEN
+       #include <unistd.h> // for read close
+       #include <sys/param.h> // for MAXPATHLEN
 #else
-    #include <io.h> // for open close read
+       #include <io.h> // for open close read
 #include "winsock2.h"
 #include "BLI_winstuff.h"
 #endif
 #include "MEM_guardedalloc.h"
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
-#include "BLI_storage_types.h" // for relname flags
 
-#include "BKE_animsys.h"
 #include "BKE_anim.h"
 #include "BKE_action.h"
 #include "BKE_armature.h"
 #include "BKE_brush.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_cloth.h"
 #include "BKE_colortools.h"
 #include "BKE_constraint.h"
 #include "BKE_context.h"
 #include "BKE_curve.h"
-#include "BKE_customdata.h"
 #include "BKE_deform.h"
-#include "BKE_depsgraph.h"
 #include "BKE_effect.h" /* give_parteff */
 #include "BKE_fcurve.h"
 #include "BKE_global.h" // for G
 #include "BKE_group.h"
 #include "BKE_image.h"
-#include "BKE_ipo.h" 
 #include "BKE_lattice.h"
-#include "BKE_library.h" // for wich_libbase
+#include "BKE_library.h" // for which_libbase
 #include "BKE_main.h" // for Main
 #include "BKE_mesh.h" // for ME_ defines (patching)
 #include "BKE_modifier.h"
 #include "BKE_sca.h" // for init_actuator
 #include "BKE_scene.h"
 #include "BKE_screen.h"
-#include "BKE_softbody.h"      // sbNew()
-#include "BKE_bullet.h"                // bsbNew()
 #include "BKE_sequencer.h"
 #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 "BKE_sound.h"
 
@@ -203,10 +194,10 @@ READ
        - read file
        - read SDNA
        - per LibBlock
-               - read recursive
-               - read associated direct data
-               - link direct data (internal and to LibBlock)
-        - free file
+                          - read recursive
+                          - read associated direct data
+                          - link direct data (internal and to LibBlock)
+               - free file
 - join all Mains
 - link all LibBlocks and indirect pointers to libblocks
 - initialize FileGlobal and copy pointers to Global
@@ -228,12 +219,12 @@ READ
 
 // only used here in readfile.c
 #define SWITCH_LONGINT(a) { \
-    char s_i, *p_i; \
-    p_i= (char *)&(a);  \
-    s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
-    s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
-    s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
-    s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
+       char s_i, *p_i; \
+       p_i= (char *)&(a);  \
+       s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
+       s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
+       s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
+       s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
 
 /***/
 
@@ -438,7 +429,7 @@ static void split_libdata(ListBase *lb, Main *first)
                        mainvar= first;
                        while(mainvar) {
                                if(mainvar->curlib==id->lib) {
-                                       lbn= wich_libbase(mainvar, GS(id->name));
+                                       lbn= which_libbase(mainvar, GS(id->name));
                                        BLI_remlink(lb, id);
                                        BLI_addtail(lbn, id);
                                        break;
@@ -580,7 +571,8 @@ static void bh4_from_bh8(BHead *bhead, BHead8 *bhead8, int do_endian_swap)
 
        if (bhead4->code != ENDB) {
 
-               // why is this here ??
+               //perform a endian swap on 64bit pointers, otherwise the pointer might map to zero
+               //0x0000000000000000000012345678 would become 0x12345678000000000000000000000000
                if (do_endian_swap) {
                        SWITCH_LONGINT(bhead8->old);
                }
@@ -1068,7 +1060,7 @@ int BLO_has_bfile_extension(char *str)
        return (BLI_testextensie(str, ".ble") || BLI_testextensie(str, ".blend")||BLI_testextensie(str, ".blend.gz"));
 }
 
-int BLO_is_a_library(char *path, char *dir, char *group)
+int BLO_is_a_library(const char *path, char *dir, char *group)
 {
        /* return ok when a blenderfile, in dir is the filename,
         * in group the type of libdata
@@ -1085,7 +1077,7 @@ int BLO_is_a_library(char *path, char *dir, char *group)
        dir[len-1]= 0;
 
        /* Find the last slash */
-       fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
+       fd= BLI_last_slash(dir);
 
        if(fd==0) return 0;
        *fd= 0;
@@ -1097,7 +1089,7 @@ int BLO_is_a_library(char *path, char *dir, char *group)
                char *gp = fd+1; // in case we have a .blend file, gp points to the group
 
                /* Find the last slash */
-               fd= (strrchr(dir, '/')>strrchr(dir, '\\'))?strrchr(dir, '/'):strrchr(dir, '\\');
+               fd= BLI_last_slash(dir);
                if (!fd || !BLO_has_bfile_extension(fd+1)) return 0;
 
                /* now we know that we are in a blend file and it is safe to 
@@ -1191,6 +1183,7 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
 {
        Image *ima= oldmain->image.first;
        Scene *sce= oldmain->scene.first;
+       int a;
        
        fd->imamap= oldnewmap_new();
        
@@ -1200,6 +1193,9 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
                        oldnewmap_insert(fd->imamap, ibuf, ibuf, 0);
                if(ima->gputexture)
                        oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0);
+               for(a=0; a<IMA_MAX_RENDER_SLOT; a++)
+                       if(ima->renders[a])
+                               oldnewmap_insert(fd->imamap, ima->renders[a], ima->renders[a], 0);
        }
        for(; sce; sce= sce->id.next) {
                if(sce->nodetree) {
@@ -1217,11 +1213,11 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
        OldNew *entry= fd->imamap->entries;
        Image *ima= oldmain->image.first;
        Scene *sce= oldmain->scene.first;
-       int i;
+       int i, a;
        
        /* used entries were restored, so we put them to zero */
        for (i=0; i<fd->imamap->nentries; i++, entry++) {
-               if (entry->nr>0)
+                if (entry->nr>0)
                        entry->newp= NULL;
        }
        
@@ -1239,6 +1235,8 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
                }
 
                ima->gputexture= newimaadr(fd, ima->gputexture);
+               for(a=0; a<IMA_MAX_RENDER_SLOT; a++)
+                       ima->renders[a]= newimaadr(fd, ima->renders[a]);
        }
        for(; sce; sce= sce->id.next) {
                if(sce->nodetree) {
@@ -1524,6 +1522,7 @@ static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap)
        for(a=0; a<CM_TOT; a++) {
                cumap->cm[a].curve= newdataadr(fd, cumap->cm[a].curve);
                cumap->cm[a].table= NULL;
+               cumap->cm[a].premultable= NULL;
        }
 }
 
@@ -2137,10 +2136,24 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
 
 /* ************ READ ARMATURE ***************** */
 
+/* temp struct used to transport needed info to lib_link_constraint_cb() */
+typedef struct tConstraintLinkData {
+       FileData *fd;
+       ID *id;
+} tConstraintLinkData;
+/* callback function used to relink constraint ID-links */
+static void lib_link_constraint_cb(bConstraint *con, ID **idpoin, void *userdata)
+{
+       tConstraintLinkData *cld= (tConstraintLinkData *)userdata;
+       *idpoin = newlibadr(cld->fd, cld->id->lib, *idpoin);
+}
+
 static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
 {
+       tConstraintLinkData cld;
        bConstraint *con;
-
+       
+       /* legacy fixes */
        for (con = conlist->first; con; con=con->next) {
                /* patch for error introduced by changing constraints (dunno how) */
                /* if con->data type changes, dna cannot resolve the pointer! (ton) */
@@ -2149,184 +2162,48 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                }
                /* own ipo, all constraints have it */
                con->ipo= newlibadr_us(fd, id->lib, con->ipo); // XXX depreceated - old animation system
+       }
+       
+       /* relink all ID-blocks used by the constraints */
+       cld.fd= fd;
+       cld.id= id;
+       
+       id_loop_constraints(conlist, lib_link_constraint_cb, &cld);
+}
+
+static void direct_link_constraints(FileData *fd, ListBase *lb)
+{
+       bConstraint *con;
+
+       link_list(fd, lb);
+       for (con=lb->first; con; con=con->next) {
+               con->data = newdataadr(fd, con->data);
                
                switch (con->type) {
-               case CONSTRAINT_TYPE_PYTHON:
+                       case CONSTRAINT_TYPE_PYTHON:
                        {
-                               bPythonConstraint *data= (bPythonConstraint*)con->data;
-                               bConstraintTarget *ct;
+                               bPythonConstraint *data= con->data;
                                
-                               for (ct= data->targets.first; ct; ct= ct->next)
-                                       ct->tar = newlibadr(fd, id->lib, ct->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;
-                               data= ((bActionConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                               data->act = newlibadr(fd, id->lib, data->act);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCLIKE:
-                       {
-                               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);
+                               link_list(fd, &data->targets);
+                               
+                               data->prop = newdataadr(fd, data->prop);
+                               if (data->prop)
+                                       IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
                        }
-                       break;
-               case CONSTRAINT_TYPE_SIZELIKE:
+                               break;
+                       case CONSTRAINT_TYPE_SPLINEIK:
                        {
-                               bSizeLikeConstraint *data;
-                               data= ((bSizeLikeConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
+                               bSplineIKConstraint *data= con->data;
+                               
+                               data->points= newdataadr(fd, data->points);
                        }
-                       break;
-               case CONSTRAINT_TYPE_KINEMATIC:
+                               break;
+                       case CONSTRAINT_TYPE_KINEMATIC:
                        {
-                               bKinematicConstraint *data;
-                               data = ((bKinematicConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                               data->poletar = newlibadr(fd, id->lib, data->poletar);
                                con->lin_error = 0.f;
                                con->rot_error = 0.f;
                        }
-                       break;
-               case CONSTRAINT_TYPE_TRACKTO:
-                       {
-                               bTrackToConstraint *data;
-                               data = ((bTrackToConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_MINMAX:
-                       {
-                               bMinMaxConstraint *data;
-                               data = ((bMinMaxConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCKTRACK:
-                       {
-                               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_STRETCHTO:
-                       {
-                               bStretchToConstraint *data;
-                               data= ((bStretchToConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-                       {
-                               bRigidBodyJointConstraint *data;
-                               data= ((bRigidBodyJointConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_CLAMPTO:
-                       {
-                               bClampToConstraint *data;
-                               data= ((bClampToConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_CHILDOF:
-                       {
-                               bChildOfConstraint *data;
-                               data= ((bChildOfConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_TRANSFORM:
-                       {
-                               bTransformConstraint *data;
-                               data= ((bTransformConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_DISTLIMIT:
-                       {
-                               bDistLimitConstraint *data;
-                               data= ((bDistLimitConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_SHRINKWRAP:
-                       {
-                               bShrinkwrapConstraint *data;
-                               data= ((bShrinkwrapConstraint*)con->data);
-                               data->target = newlibadr(fd, id->lib, data->target);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_DAMPTRACK:
-                       {
-                               bDampTrackConstraint *data;
-                               data= ((bDampTrackConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_SPLINEIK:
-                       {
-                               bSplineIKConstraint *data;
-                               data= ((bSplineIKConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_TRANSLIKE:
-                       {
-                               bTransLikeConstraint *data;
-                               data= ((bTransLikeConstraint*)con->data);
-                               data->tar = newlibadr(fd, id->lib, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_NULL:
-                       break;
-               }
-       }
-}
-
-static void direct_link_constraints(FileData *fd, ListBase *lb)
-{
-       bConstraint *cons;
-
-       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;
-                       
-                       link_list(fd, &data->targets);
-                       
-                       data->prop = newdataadr(fd, data->prop);
-                       if (data->prop)
-                               IDP_DirectLinkProperty(data->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
-               }
-               else if (cons->type == CONSTRAINT_TYPE_SPLINEIK) {
-                       bSplineIKConstraint *data= cons->data;
-                       
-                       data->points= newdataadr(fd, data->points);
+                               break;
                }
        }
 }
@@ -2782,7 +2659,8 @@ static void direct_link_image(FileData *fd, Image *ima)
        ima->anim= NULL;
        ima->rr= NULL;
        ima->repbind= NULL;
-       ima->render_text= newdataadr(fd, ima->render_text);
+       memset(ima->renders, 0, sizeof(ima->renders));
+       ima->last_render_slot= ima->render_slot;
        
        ima->packedfile = direct_link_packedfile(fd, ima->packedfile);
        ima->preview = direct_link_preview_image(fd, ima->preview);
@@ -3149,6 +3027,7 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
        part->pd= newdataadr(fd, part->pd);
        part->pd2= newdataadr(fd, part->pd2);
 
+       direct_link_animdata(fd, part->adt);
        direct_link_partdeflect(part->pd);
        direct_link_partdeflect(part->pd2);
 
@@ -3159,6 +3038,7 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
        link_list(fd, &part->dupliweights);
 
        part->boids= newdataadr(fd, part->boids);
+       part->fluid= newdataadr(fd, part->fluid);
 
        if(part->boids) {
                BoidState *state;
@@ -3187,6 +3067,14 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase
                                pt->ob=newlibadr(fd, id->lib, pt->ob);
 
                        psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
+
+                       if(psys->clmd) {
+                               /* XXX - from reading existing code this seems correct but intended usage of
+                                * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */
+                               psys->clmd->point_cache= psys->pointcache;
+                               psys->clmd->ptcaches.first= psys->clmd->ptcaches.last= NULL;
+                               psys->clmd->coll_parms->group= newlibadr(fd, id->lib, psys->clmd->coll_parms->group);
+                       }
                }
                else {
                        /* particle modifier must be removed before particle system */
@@ -3310,6 +3198,7 @@ static void lib_link_mesh(FileData *fd, Main *main)
                        /*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);
+                       if (me->adt) lib_link_animdata(fd, &me->id, me->adt);
 
                        /* this check added for python created meshes */
                        if(me->mat) {
@@ -3397,6 +3286,9 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
        mesh->msticky= newdataadr(fd, mesh->msticky);
        mesh->dvert= newdataadr(fd, mesh->dvert);
        
+       mesh->adt= newdataadr(fd, mesh->adt);
+       direct_link_animdata(fd, mesh->adt);
+
        /* Partial-mesh visibility (do this before using totvert, totface, or totedge!) */
        mesh->pv= newdataadr(fd, mesh->pv);
        if(mesh->pv) {
@@ -3501,7 +3393,7 @@ static void direct_link_latt(FileData *fd, Lattice *lt)
 /* ************ READ OBJECT ***************** */
 
 static void lib_link_modifiers__linkModifiers(void *userData, Object *ob,
-                                              ID **idpoin)
+                                                                                         ID **idpoin)
 {
        FileData *fd = userData;
 
@@ -3547,6 +3439,11 @@ static void lib_link_object(FileData *fd, Main *main)
                                if(ob->proxy->id.lib==NULL) {
                                        ob->proxy->proxy_from= NULL;
                                        ob->proxy= NULL;
+                                       
+                                       if (ob->id.lib)
+                                               printf("Proxy lost from  object %s lib %s\n", ob->id.name+2, ob->id.lib->name);
+                                       else
+                                               printf("Proxy lost from  object %s lib <NONE>\n", ob->id.name+2);
                                }
                                else {
                                        /* this triggers object_update to always use a copy */
@@ -3561,11 +3458,14 @@ static void lib_link_object(FileData *fd, Main *main)
                        ob->data= newlibadr_us(fd, ob->id.lib, ob->data);
                           
                        if(ob->data==NULL && poin!=NULL) {
+                               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.\n", ob->id.name+2);
+
                                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.\n", ob->id.name+2);
-                               
+
                                if(ob->pose) {
                                        free_pose(ob->pose);
                                        ob->pose= NULL;
@@ -3575,7 +3475,8 @@ static void lib_link_object(FileData *fd, Main *main)
                        for(a=0; a<ob->totcol; a++) ob->mat[a]= newlibadr_us(fd, ob->id.lib, ob->mat[a]);
                        
                        ob->gpd= newlibadr_us(fd, ob->id.lib, ob->gpd);
-                       
+                       ob->duplilist= NULL;
+            
                        ob->id.flag -= LIB_NEEDLINK;
                        /* if id.us==0 a new base will be created later on */
                        
@@ -3606,7 +3507,7 @@ static void lib_link_object(FileData *fd, Main *main)
                                else if(sens->type==SENS_MESSAGE) {
                                        bMessageSensor *ms= sens->data;
                                        ms->fromObject=
-                                           newlibadr(fd, ob->id.lib, ms->fromObject);
+                                               newlibadr(fd, ob->id.lib, ms->fromObject);
                                }
                                sens= sens->next;
                        }
@@ -3733,6 +3634,7 @@ static void lib_link_object(FileData *fd, Main *main)
                                if(clmd) 
                                {
                                        clmd->sim_parms->effector_weights->group = newlibadr(fd, ob->id.lib, clmd->sim_parms->effector_weights->group);
+                                       clmd->coll_parms->group= newlibadr(fd, ob->id.lib, clmd->coll_parms->group);
                                }
                        }
                        
@@ -3764,6 +3666,8 @@ static void direct_link_pose(FileData *fd, bPose *pose)
        link_list(fd, &pose->chanbase);
        link_list(fd, &pose->agroups);
 
+       pose->chanhash= NULL;
+
        for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) {
                pchan->bone= NULL;
                pchan->parent= newdataadr(fd, pchan->parent);
@@ -3839,6 +3743,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
                        FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;
                        
                        fluidmd->fss= newdataadr(fd, fluidmd->fss);
+                       fluidmd->fss->fmd= fluidmd;
                        fluidmd->fss->meshSurfNormals = 0;
                }
                else if (md->type==eModifierType_Smoke) {
@@ -4247,16 +4152,20 @@ static void lib_link_scene(FileData *fd, Main *main)
 
                        SEQ_BEGIN(sce->ed, seq) {
                                if(seq->ipo) seq->ipo= newlibadr_us(fd, sce->id.lib, seq->ipo);
-                               if(seq->scene) seq->scene= newlibadr(fd, sce->id.lib, seq->scene);
+                               if(seq->scene) {
+                                       seq->scene= newlibadr(fd, sce->id.lib, seq->scene);
+                                       seq->scene_sound = sound_scene_add_scene_sound(sce, seq, seq->startdisp, seq->enddisp, seq->startofs);
+                               }
+                               if(seq->scene_camera) seq->scene_camera= newlibadr(fd, sce->id.lib, seq->scene_camera);
                                if(seq->sound) {
-                                       seq->sound_handle= NULL;
+                                       seq->scene_sound = NULL;
                                        if(seq->type == SEQ_HD_SOUND)
                                                seq->type = SEQ_SOUND;
                                        else
                                                seq->sound= newlibadr(fd, sce->id.lib, seq->sound);
                                        if (seq->sound) {
                                                seq->sound->id.us++;
-                                               seq->sound_handle= sound_new_handle(sce, seq->sound, seq->startdisp, seq->enddisp, seq->startofs);
+                                               seq->scene_sound = sound_add_scene_sound(sce, seq, seq->startdisp, seq->enddisp, seq->startofs);
                                        }
                                }
                                seq->anim= 0;
@@ -4272,7 +4181,7 @@ static void lib_link_scene(FileData *fd, Main *main)
 #endif
 
                        if(sce->ed)
-                               seq_update_muting(sce->ed);
+                               seq_update_muting(sce, sce->ed);
                        
                        if(sce->nodetree) {
                                lib_link_ntree(fd, &sce->id, sce->nodetree);
@@ -4327,8 +4236,9 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        sce->dagisvalid = 0;
        sce->obedit= NULL;
        sce->stats= 0;
+       sce->fps_info= NULL;
 
-       memset(&sce->sound_handles, 0, sizeof(sce->sound_handles));
+       sound_create_scene(sce);
 
        /* set users to one by default, not in lib-link, this will increase it for compo nodes */
        sce->id.us= 1;
@@ -4704,6 +4614,11 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                SpaceImage *sima= (SpaceImage *)sl;
 
                                                sima->image= newlibadr_us(fd, sc->id.lib, sima->image);
+                                               
+                                               /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+                                                * so fingers crossed this works fine!
+                                                */
+                                               sima->gpd= newlibadr_us(fd, sc->id.lib, sima->gpd);
                                        }
                                        else if(sl->spacetype==SPACE_NLA){
                                                SpaceNla *snla= (SpaceNla *)sl;
@@ -4779,7 +4694,7 @@ static void *restore_pointer_by_name(Main *mainp, ID *id, int user)
 {
                
        if(id) {
-               ListBase *lb= wich_libbase(mainp, GS(id->name));
+               ListBase *lb= which_libbase(mainp, GS(id->name));
                
                if(lb) {        // there's still risk of checking corrupt mem (freed Ids in oops)
                        ID *idn= lb->first;
@@ -4842,7 +4757,10 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
                                        View3D *v3d= (View3D*) sl;
                                        BGpic *bgpic;
                                        
-                                       v3d->camera= restore_pointer_by_name(newmain, (ID *)v3d->camera, 1);
+                                       if(v3d->scenelock)
+                                               v3d->camera= NULL; /* always get from scene */
+                                       else
+                                               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);
@@ -4900,7 +4818,7 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
                                        sfile->op= NULL;
                                }
                                else if(sl->spacetype==SPACE_IMASEL) {
-                    SpaceImaSel *simasel= (SpaceImaSel *)sl;
+                                       SpaceImaSel *simasel= (SpaceImaSel *)sl;
                                        if (simasel->files) {
                                                //XXX BIF_filelist_freelib(simasel->files);
                                        }
@@ -4918,6 +4836,11 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
                                        SpaceImage *sima= (SpaceImage *)sl;
 
                                        sima->image= restore_pointer_by_name(newmain, (ID *)sima->image, 1);
+                                       
+                                       /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+                                        * so assume that here we're doing for undo only...
+                                        */
+                                       sima->gpd= restore_pointer_by_name(newmain, (ID *)sima->gpd, 1);
                                }
                                else if(sl->spacetype==SPACE_NLA){
                                        SpaceNla *snla= (SpaceNla *)sl;
@@ -5180,13 +5103,18 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                SpaceImage *sima= (SpaceImage *)sl;
                                
                                sima->cumap= newdataadr(fd, sima->cumap);
-                               sima->gpd= newdataadr(fd, sima->gpd);
-                               if (sima->gpd)
-                                       direct_link_gpencil(fd, sima->gpd);
                                if(sima->cumap)
                                        direct_link_curvemapping(fd, sima->cumap);
+                               
                                sima->iuser.scene= NULL;
                                sima->iuser.ok= 1;
+                               
+                               /* WARNING: gpencil data is no longer stored directly in sima after 2.5 
+                                * so sacrifice a few old files for now to avoid crashes with new files!
+                                */
+                               //sima->gpd= newdataadr(fd, sima->gpd);
+                               //if (sima->gpd)
+                               //      direct_link_gpencil(fd, sima->gpd);
                        }
                        else if(sl->spacetype==SPACE_NODE) {
                                SpaceNode *snode= (SpaceNode *)sl;
@@ -5230,6 +5158,18 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                //      cl->line= newdataadr(fd, cl->line);
                                
                        }
+                       else if(sl->spacetype==SPACE_FILE) {
+                               SpaceFile *sfile= (SpaceFile *)sl;
+                               
+                               /* this sort of info is probably irrelevant for reloading...
+                                * plus, it isn't saved to files yet!
+                                */
+                               sfile->folders_prev= sfile->folders_next= NULL;
+                               sfile->files= NULL;
+                               sfile->layout= NULL;
+                               sfile->op= NULL;
+                               sfile->params= NULL;
+                       }
                }
                
                sa->actionzones.first= sa->actionzones.last= NULL;
@@ -5301,7 +5241,7 @@ static void fix_relpaths_library(const char *basepath, Main *main)
                 * relative to the blend file since indirectly linked libs will be relative to their direct linked library */
                if (strncmp(lib->name, "//", 2)==0) { /* if this is relative to begin with? */
                        strncpy(lib->name, lib->filename, sizeof(lib->name));
-                       BLI_makestringcode(basepath, lib->name);
+                       BLI_path_rel(lib->name, basepath);
                }
        }
 }
@@ -5311,6 +5251,7 @@ static void fix_relpaths_library(const char *basepath, Main *main)
 static void direct_link_sound(FileData *fd, bSound *sound)
 {
        sound->handle = NULL;
+       sound->playback_handle = NULL;
 
        sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
        sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
@@ -5416,7 +5357,7 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, char *allocna
 
        while(bhead && bhead->code==DATA) {
                void *data;
-#if 0          
+#if 0
                /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */         
                short *sp= fd->filesdna->structs[bhead->SDNAnr];
                char *allocname = fd->filesdna->types[ sp[0] ];
@@ -5424,8 +5365,9 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, char *allocna
                
                strcpy(tmp, allocname);
                data= read_struct(fd, bhead, tmp);
-#endif
+#else
                data= read_struct(fd, bhead, allocname);
+#endif
                
                if (data) {
                        oldnewmap_insert(fd->datamap, bhead->old, data, 0);
@@ -5458,10 +5400,10 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
        
        /* do after read_struct, for dna reconstruct */
        if(bhead->code==ID_ID) {
-               lb= wich_libbase(main, GS(id->name));
+               lb= which_libbase(main, GS(id->name));
        }
        else {
-               lb= wich_libbase(main, bhead->code);
+               lb= which_libbase(main, bhead->code);
        }
        
        BLI_addtail(lb, id);
@@ -6032,6 +5974,29 @@ static void area_add_header_region(ScrArea *sa, ListBase *lb)
        ar->v2d.flag = (V2D_PIXELOFS_X|V2D_PIXELOFS_Y);
 }
 
+static void sequencer_init_preview_region(ARegion* ar)
+{
+       // XXX a bit ugly still, copied from space_sequencer
+       /* NOTE: if you change values here, also change them in space_sequencer.c, sequencer_new */
+       ar->regiontype= RGN_TYPE_PREVIEW;
+       ar->alignment= RGN_ALIGN_TOP;
+       ar->flag |= RGN_FLAG_HIDDEN;
+       ar->v2d.keepzoom= V2D_KEEPASPECT | V2D_KEEPZOOM;
+       ar->v2d.minzoom= 0.00001f;
+       ar->v2d.maxzoom= 100000.0f;
+       ar->v2d.tot.xmin= -960.0f; /* 1920 width centered */
+       ar->v2d.tot.ymin= -540.0f; /* 1080 height centered */
+       ar->v2d.tot.xmax= 960.0f;
+       ar->v2d.tot.ymax= 540.0f;
+       ar->v2d.min[0]= 0.0f;
+       ar->v2d.min[1]= 0.0f;
+       ar->v2d.max[0]= 12000.0f;
+       ar->v2d.max[1]= 12000.0f;
+       ar->v2d.cur= ar->v2d.tot;
+       ar->v2d.align= V2D_ALIGN_FREE; // (V2D_ALIGN_NO_NEG_X|V2D_ALIGN_NO_NEG_Y);
+       ar->v2d.keeptot= V2D_KEEPTOT_FREE;
+}
+
 /* 2.50 patch */
 static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
 {
@@ -6112,9 +6077,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
                                }
                                ar= MEM_callocN(sizeof(ARegion), "preview area for sequencer");
                                BLI_insertlinkbefore(lb, ar_main, ar);
-                               ar->regiontype= RGN_TYPE_PREVIEW;
-                               ar->alignment= RGN_ALIGN_TOP;
-                               ar->flag |= RGN_FLAG_HIDDEN;
+                               sequencer_init_preview_region(ar);
                                break;
                        case SPACE_VIEW3D:
                                /* toolbar */
@@ -6250,10 +6213,10 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
                                ar->v2d.cur= ar->v2d.tot;
                                
                                ar->v2d.min[0]= 0.0f;
-                               ar->v2d.min[1]= 0.0f;
+                                ar->v2d.min[1]= 0.0f;
                                
                                ar->v2d.max[0]= MAXFRAMEF;
-                               ar->v2d.max[1]= FLT_MAX;
+                                ar->v2d.max[1]= FLT_MAX;
                                
                                ar->v2d.minzoom= 0.01f;
                                ar->v2d.maxzoom= 50;
@@ -6293,7 +6256,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
                                break;
                        }
                        case SPACE_FILE:
-                       {
+                        {
                                // SpaceFile *sfile= (SpaceFile *)sl;
                                ar->v2d.tot.xmin = ar->v2d.tot.ymin = 0;
                                ar->v2d.tot.xmax = ar->winx;
@@ -6497,6 +6460,25 @@ static void do_version_constraints_radians_degrees_250(ListBase *lb)
        }
 }
 
+/* NOTE: this version patch is intended for versions < 2.52.2, but was initially introduced in 2.27 already */
+static void do_version_old_trackto_to_constraints(Object *ob)
+{
+       /* create new trackto constraint from the relationship */
+       if (ob->track)
+       {
+               bConstraint *con= add_ob_constraint(ob, "AutoTrack", CONSTRAINT_TYPE_TRACKTO);
+               bTrackToConstraint *data = con->data;
+               
+               /* copy tracking settings from the object */
+               data->tar = ob->track;
+               data->reserved1 = ob->trackflag;
+               data->reserved2 = ob->upflag;
+       }
+       
+       /* clear old track setting */
+       ob->track = NULL;
+}
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -6638,8 +6620,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Tex *tex = main->tex.first;
                while (tex) {
                        if ((tex->rfac == 0.0) &&
-                           (tex->gfac == 0.0) &&
-                           (tex->bfac == 0.0)) {
+                               (tex->gfac == 0.0) &&
+                               (tex->bfac == 0.0)) {
                                tex->rfac = 1.0;
                                tex->gfac = 1.0;
                                tex->bfac = 1.0;
@@ -6653,8 +6635,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Tex *tex = main->tex.first;
                while (tex) {
                        if ((tex->rfac == 0.0) &&
-                           (tex->gfac == 0.0) &&
-                           (tex->bfac == 0.0)) {
+                               (tex->gfac == 0.0) &&
+                               (tex->bfac == 0.0)) {
                                tex->rfac = 1.0;
                                tex->gfac = 1.0;
                                tex->bfac = 1.0;
@@ -6844,7 +6826,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Object *ob= main->object.first;
                while(ob) {
                        ob->scaflag = ob->gameflag & (64+128+256+512+1024+2048);
-                           /* 64 is do_fh */
+                               /* 64 is do_fh */
                        ob->gameflag &= ~(128+256+512+1024+2048);
                        ob = ob->id.next;
                }
@@ -6956,8 +6938,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                bRaySensor *rs;
                bCollisionSensor *cs;
                while(ob) {
-                   /* Set anisotropic friction off for old objects,
-                    * values to 1.0.  */
+                       /* Set anisotropic friction off for old objects,
+                        * values to 1.0.  */
                        ob->gameflag &= ~OB_ANISOTROPIC_FRICTION;
                        ob->anisotropicFriction[0] = 1.0;
                        ob->anisotropicFriction[1] = 1.0;
@@ -7278,7 +7260,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                Object *ob;
 
                /*  As of now, this insures that the transition from the old Track system
-                   to the new full constraint Track is painless for everyone. - theeth
+                       to the new full constraint Track is painless for everyone. - theeth
                */
                ob = main->object.first;
 
@@ -7315,40 +7297,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                                        }
                                                }
                                        }
-                }
+                               }
                        }
 
                        /* Change Ob->Track in real TrackTo constraint */
-
-                       if (ob->track){
-                               bConstraint *con;
-                               bConstraintTypeInfo *cti;
-                               bTrackToConstraint *data;
-                               void *cdata;
-
-                               list = &ob->constraints;
-                               if (list)
-                               {
-                                       con = MEM_callocN(sizeof(bConstraint), "constraint");
-                                       strcpy (con->name, "AutoTrack");
-                                       unique_constraint_name(con, list);
-                                       con->flag |= CONSTRAINT_EXPAND;
-                                       con->enforce=1.0F;
-                                       con->type = CONSTRAINT_TYPE_TRACKTO;
-                                       
-                                       cti= get_constraint_typeinfo(CONSTRAINT_TYPE_TRACKTO);
-                                       cdata= MEM_callocN(cti->size, cti->structName);
-                                       cti->new_data(cdata);
-                                       data = (bTrackToConstraint *)cdata;
-                                       
-                                       data->tar = ob->track;
-                                       data->reserved1 = ob->trackflag;
-                                       data->reserved2 = ob->upflag;
-                                       con->data= (void*) data;
-                                       BLI_addtail(list, con);
-                               }
-                               ob->track = 0;
-                       }
+                       do_version_old_trackto_to_constraints(ob);
                        
                        ob = ob->id.next;
                }
@@ -7395,7 +7348,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
 
                /*  As of now, this insures that the transition from the old Track system
-                   to the new full constraint Track is painless for everyone.*/
+                       to the new full constraint Track is painless for everyone.*/
                ob = main->object.first;
 
                while (ob) {
@@ -7431,7 +7384,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                                        }
                                                }
                                        }
-                }
+                               }
                        }
 
                        ob = ob->id.next;
@@ -9552,7 +9505,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                /* check if top parent has compound shape set and if yes, set this object
                                   to compound shaper as well (was the behaviour before, now it's optional) */
                                Object *parent= newlibadr(fd, lib, ob->parent);
-                               while (parent && parent->parent != NULL) {
+                               while (parent && parent != ob &&  parent->parent != NULL) {
                                        parent = newlibadr(fd, lib, parent->parent);
                                }
                                if(parent) {
@@ -9682,7 +9635,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                        {
                                                char str[FILE_MAX];
                                                BLI_join_dirfile(str, seq->strip->dir, seq->strip->stripdata->name);
-                                               BLI_convertstringcode(str, G.sce);
+                                               BLI_path_abs(str, G.sce);
                                                seq->sound = sound_new_file(main, str);
                                        }
                                }
@@ -9819,7 +9772,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                void *olddata = ob->data;
                                ob->data = me;
 
-                               if(me && me->id.lib==NULL && me->mr) /* XXX - library meshes crash on loading most yoFrankie levels, the multires pointer gets invalid -  Campbell */
+                               if(me && me->id.lib==NULL && me->mr && me->mr->level_count > 1) /* XXX - library meshes crash on loading most yoFrankie levels, the multires pointer gets invalid -  Campbell */
                                        multires_load_old(ob, me);
 
                                ob->data = olddata;
@@ -10193,12 +10146,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                
                                if(sce->r.frame_step==0)
                                        sce->r.frame_step= 1;
+                               if (sce->r.mblur_samples==0)
+                                       sce->r.mblur_samples = sce->r.osa;
                                
                                if(sce->ed && sce->ed->seqbasep)
                                {
                                        seq=sce->ed->seqbasep->first;
                                        while(seq) {
-                                               seqUniqueName(sce->ed->seqbasep, seq);
+                                               seqbase_unique_name_recursive(&sce->ed->seqbase, seq);
                                                seq=seq->next;
                                        }
                                }
@@ -10409,7 +10364,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                                                break;
                                                }
 
-                                               if (ar) {
+                                               if (ar && (ar->regiontype == RGN_TYPE_PREVIEW)) {
                                                        SpaceType *st= BKE_spacetype_from_id(SPACE_SEQ);
                                                        BKE_area_region_free(st, ar);
                                                        BLI_freelinkN(regionbase, ar);
@@ -10454,9 +10409,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                                        }
                                                        ar= MEM_callocN(sizeof(ARegion), "preview area for sequencer");
                                                        BLI_insertlinkbefore(regionbase, ar_main, ar);
-                                                       ar->regiontype= RGN_TYPE_PREVIEW;
-                                                       ar->alignment= RGN_ALIGN_TOP;
-                                                       ar->flag |= RGN_FLAG_HIDDEN;
+                                                       sequencer_init_preview_region(ar);
                                                }
                                        }
                                }
@@ -10563,7 +10516,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                ma->vol.ms_intensity = 1.f;     
                        }
                }
-               
        }
        
        if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 13)) {
@@ -10653,10 +10605,134 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
        
-       /* put 2.50 compatibility code here until next subversion bump */
-       //{
+       if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 17)) {
+               Scene *sce;
+               Sequence *seq;
+               Material *ma;
+
+               /* initialize to sane default so toggling on border shows something */
+               for(sce = main->scene.first; sce; sce = sce->id.next) {
+                       if(sce->r.border.xmin == 0.0f && sce->r.border.ymin == 0.0f &&
+                          sce->r.border.xmax == 0.0f && sce->r.border.ymax == 0.0f) {
+                               sce->r.border.xmin= 0.0f;
+                               sce->r.border.ymin= 0.0f;
+                               sce->r.border.xmax= 1.0f;
+                               sce->r.border.ymax= 1.0f;
+                       }
+
+                       if((sce->r.ffcodecdata.flags & FFMPEG_MULTIPLEX_AUDIO) == 0)
+                               sce->r.ffcodecdata.audio_codec = 0x0; // CODEC_ID_NONE
+
+                       SEQ_BEGIN(sce->ed, seq) {
+                               seq->volume = 1.0f;
+                       }
+                       SEQ_END
+               }
+
+               for(ma = main->mat.first; ma; ma=ma->id.next)
+                       if(ma->mode & MA_TRACEBLE)
+                               ma->shade_flag |= MA_APPROX_OCCLUSION;
+
+               /* sequencer changes */
+               {
+                       bScreen *screen;
+                       ScrArea *sa;
+                       SpaceLink *sl;
+
+                       for(screen= main->screen.first; screen; screen= screen->id.next) {
+                               for(sa= screen->areabase.first; sa; sa= sa->next) {
+                                       for(sl= sa->spacedata.first; sl; sl= sl->next) {
+                                               if(sl->spacetype==SPACE_SEQ) {
+                                                       ARegion *ar_preview;
+                                                       ListBase *regionbase;
+
+                                                       if (sl == sa->spacedata.first) {
+                                                               regionbase = &sa->regionbase;
+                                                       } else {
+                                                               regionbase = &sl->regionbase;
+                                                       }
+
+                                                       ar_preview = (ARegion*)regionbase->first;
+                                                       for (; ar_preview; ar_preview = ar_preview->next) {
+                                                               if (ar_preview->regiontype == RGN_TYPE_PREVIEW)
+                                                                       break;
+                                                       }
+                                                       if (ar_preview && (ar_preview->regiontype == RGN_TYPE_PREVIEW)) {
+                                                               sequencer_init_preview_region(ar_preview);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               } /* sequencer changes */
+       }
+
+       if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 1)) {
+               Brush *brush;
+               Object *ob;
+               Scene *scene;
+               bNodeTree *ntree;
+               
+               for (brush= main->brush.first; brush; brush= brush->id.next) {
+                       if (brush->curve) brush->curve->preset = CURVE_PRESET_SMOOTH;
+               }
+               
+               /* properly initialise active flag for fluidsim modifiers */
+               for(ob = main->object.first; ob; ob = ob->id.next) {
+                       ModifierData *md;
+                       for(md= ob->modifiers.first; md; md= md->next) {
+                               if (md->type == eModifierType_Fluidsim) {
+                                       FluidsimModifierData *fmd = (FluidsimModifierData *)md;
+                                       fmd->fss->flag |= OB_FLUIDSIM_ACTIVE; 
+                                       fmd->fss->flag |= OB_FLUIDSIM_OVERRIDE_TIME;
+                               }
+                       }
+               }
+               
+               /* adjustment to color balance node values */
+               for(scene= main->scene.first; scene; scene= scene->id.next) {
+                       if(scene->nodetree) {
+                               bNode *node=scene->nodetree->nodes.first;
+                               
+                               while(node) {
+                                       if (node->type == CMP_NODE_COLORBALANCE) {
+                                               NodeColorBalance *n= (NodeColorBalance *)node->storage;
+                                               n->lift[0] += 1.f;
+                                               n->lift[1] += 1.f;
+                                               n->lift[2] += 1.f;
+                                       }
+                                       node= node->next;
+                               }
+                       }
+               }
+               /* check inside node groups too */
+               for (ntree= main->nodetree.first; ntree; ntree=ntree->id.next) {
+                       bNode *node=ntree->nodes.first;
+                       
+                       while(node) {
+                               if (node->type == CMP_NODE_COLORBALANCE) {
+                                       NodeColorBalance *n= (NodeColorBalance *)node->storage;
+                                       n->lift[0] += 1.f;
+                                       n->lift[1] += 1.f;
+                                       n->lift[2] += 1.f;
+                               }
+                               node= node->next;
+                       }
+               }
+       }
        
-       //}
+       /* old-track -> constraints (this time we're really doing it!) */
+       if (main->versionfile < 252 || (main->versionfile == 252 && main->subversionfile < 2)) {
+               Object *ob;
+               
+               for (ob = main->object.first; ob; ob = ob->id.next)
+                       do_version_old_trackto_to_constraints(ob);
+       }
+       
+       /* put 2.50 compatibility code here until next subversion bump */
+       {
+               
+       }
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
@@ -10712,6 +10788,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
 
        link_list(fd, &user->themes);
        link_list(fd, &user->keymaps);
+       link_list(fd, &user->addons);
 
        for(keymap=user->keymaps.first; keymap; keymap=keymap->next) {
                keymap->modal_items= NULL;
@@ -10737,7 +10814,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
        return bhead;
 }
 
-BlendFileData *blo_read_file_internal(FileData *fd, char *file)
+BlendFileData *blo_read_file_internal(FileData *fd, const char *filename)
 {
        BHead *bhead= blo_firstbhead(fd);
        BlendFileData *bfd;
@@ -10749,7 +10826,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, char *file)
        bfd->main->versionfile= fd->fileversion;
        
        bfd->type= BLENFILETYPE_BLEND;
-       strncpy(bfd->main->name, file, sizeof(bfd->main->name)-1);
+       strncpy(bfd->main->name, filename, sizeof(bfd->main->name)-1);
 
        while(bhead) {
                switch(bhead->code) {
@@ -10904,20 +10981,9 @@ char *bhead_id_name(FileData *fd, BHead *bhead)
 
 static ID *is_yet_read(FileData *fd, Main *mainvar, BHead *bhead)
 {
-       ListBase *lb;
-       char *idname= bhead_id_name(fd, bhead);
-
-       lb= wich_libbase(mainvar, GS(idname));
-       
-       if(lb) {
-               ID *id= lb->first;
-               while(id) {
-                       if( strcmp(id->name, idname)==0 ) 
-                               return id;
-                       id= id->next;
-               }
-       }
-       return NULL;
+       const char *idname= bhead_id_name(fd, bhead);
+       /* which_libbase can be NULL, intentionally not using idname+2 */
+       return BLI_findstring(which_libbase(mainvar, GS(idname)), idname, offsetof(ID, name));
 }
 
 static void expand_doit(FileData *fd, Main *mainvar, void *old)
@@ -10971,7 +11037,8 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
                                /* 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);
-                               if(G.f & G_DEBUG) printf("expand: already read %s\n", id->name);
+                               // commented because this can print way too much
+                               // if(G.f & G_DEBUG) printf("expand: already read %s\n", id->name);
                        }
                }
        }
@@ -11295,148 +11362,33 @@ static void expand_mesh(FileData *fd, Main *mainvar, Mesh *me)
        }
 }
 
+/* temp struct used to transport needed info to expand_constraint_cb() */
+typedef struct tConstraintExpandData {
+       FileData *fd;
+       Main *mainvar;
+} tConstraintExpandData;
+/* callback function used to expand constraint ID-links */
+static void expand_constraint_cb(bConstraint *con, ID **idpoin, void *userdata)
+{
+       tConstraintExpandData *ced= (tConstraintExpandData *)userdata;
+       expand_doit(ced->fd, ced->mainvar, *idpoin);
+}
+
 static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
 {
+       tConstraintExpandData ced;
        bConstraint *curcon;
-
+       
+       /* relink all ID-blocks used by the constraints */
+       ced.fd= fd;
+       ced.mainvar= mainvar;
+       
+       id_loop_constraints(lb, expand_constraint_cb, &ced);
+       
+       /* depreceated manual expansion stuff */
        for (curcon=lb->first; curcon; curcon=curcon->next) {
-               
                if (curcon->ipo)
                        expand_doit(fd, mainvar, curcon->ipo); // XXX depreceated - old animation system
-               
-               switch (curcon->type) {
-               case CONSTRAINT_TYPE_NULL:
-                       break;
-               case CONSTRAINT_TYPE_PYTHON:
-                       {
-                               bPythonConstraint *data = (bPythonConstraint*)curcon->data;
-                               bConstraintTarget *ct;
-                               
-                               for (ct= data->targets.first; ct; ct= ct->next)
-                                       expand_doit(fd, mainvar, ct->tar);
-                               
-                               expand_doit(fd, mainvar, data->text);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_ACTION:
-                       {
-                               bActionConstraint *data = (bActionConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                               expand_doit(fd, mainvar, data->act);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCLIKE:
-                       {
-                               bLocateLikeConstraint *data = (bLocateLikeConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_ROTLIKE:
-                       {
-                               bRotateLikeConstraint *data = (bRotateLikeConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_SIZELIKE:
-                       {
-                               bSizeLikeConstraint *data = (bSizeLikeConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_KINEMATIC:
-                       {
-                               bKinematicConstraint *data = (bKinematicConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                               expand_doit(fd, mainvar, data->poletar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_TRACKTO:
-                       {
-                               bTrackToConstraint *data = (bTrackToConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_MINMAX:
-                       {
-                               bMinMaxConstraint *data = (bMinMaxConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_LOCKTRACK:
-                       {
-                               bLockTrackConstraint *data = (bLockTrackConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_FOLLOWPATH:
-                       {
-                               bFollowPathConstraint *data = (bFollowPathConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_STRETCHTO:
-                       {
-                               bStretchToConstraint *data = (bStretchToConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-                       {
-                               bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_CLAMPTO:
-                       {
-                               bClampToConstraint *data = (bClampToConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_CHILDOF:
-                       {
-                               bChildOfConstraint *data = (bChildOfConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_TRANSFORM:
-                       {
-                               bTransformConstraint *data = (bTransformConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_DISTLIMIT: 
-                       {
-                               bDistLimitConstraint *data = (bDistLimitConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_SHRINKWRAP:
-                       {
-                               bShrinkwrapConstraint *data = (bShrinkwrapConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->target);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_DAMPTRACK:
-                       {
-                               bDampTrackConstraint *data = (bDampTrackConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_SPLINEIK:
-                       {
-                               bSplineIKConstraint *data = (bSplineIKConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               case CONSTRAINT_TYPE_TRANSLIKE:
-                       {
-                               bTransLikeConstraint *data = (bTransLikeConstraint*)curcon->data;
-                               expand_doit(fd, mainvar, data->tar);
-                       }
-                       break;
-               default:
-                       break;
-               }
        }
 }
 
@@ -11700,6 +11652,7 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
 
                SEQ_BEGIN(sce->ed, seq) {
                        if(seq->scene) expand_doit(fd, mainvar, seq->scene);
+                       if(seq->scene_camera) expand_doit(fd, mainvar, seq->scene_camera);
                        if(seq->sound) expand_doit(fd, mainvar, seq->sound);
                }
                SEQ_END
@@ -12083,13 +12036,13 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in
        read_libraries(*fd, &(*fd)->mainlist);
 
        /* make the lib path relative if required */
-       if(flag & FILE_STRINGCODE) {
+       if(flag & FILE_RELPATH) {
 
                /* 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);
+               BLI_path_rel(mainl->curlib->name, G.sce);
        }
 
        blo_join_main(&(*fd)->mainlist);
@@ -12200,8 +12153,8 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                                if(fd==NULL) {
 
                                        /* printf and reports for now... its important users know this */
-                                       printf("read library: %s\n", mainptr->curlib->name);
-                                       BKE_reportf(basefd->reports, RPT_INFO, "read library: '%s'\n", mainptr->curlib->name);
+                                       printf("read library: '%s', '%s'\n", mainptr->curlib->filename, mainptr->curlib->name);
+                                       BKE_reportf(basefd->reports, RPT_INFO, "read library:  '%s', '%s'\n", mainptr->curlib->filename, mainptr->curlib->name);
 
                                        fd= blo_openblenderfile(mainptr->curlib->filename, basefd->reports);