use BLI_strncpy and BLI_snprintf when the size of the string is known.
[blender.git] / source / blender / blenkernel / intern / ipo.c
index a24f37b..40fe362 100644 (file)
@@ -1,7 +1,4 @@
-/* ipo.c
- * 
- * $Id$
- *
+/*
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/ipo.c
+ *  \ingroup bke
+ */
+
+
 /* NOTE:
  *
  * This file is no longer used to provide tools for the depreceated IPO system. Instead, it
@@ -41,7 +43,8 @@
 #include <string.h>
 #include <stddef.h>
 
-#include "MEM_guardedalloc.h"
+/* since we have versioning code here */
+#define DNA_DEPRECATED_ALLOW
 
 #include "DNA_anim_types.h"
 #include "DNA_constraint_types.h"
 #include "BLI_math.h" /* windows needs for M_PI */
 #include "BLI_blenlib.h"
 #include "BLI_dynstr.h"
+#include "BLI_utildefines.h"
 
-#include "BKE_utildefines.h"
 
+#include "BKE_ipo.h"
 #include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_fcurve.h"
@@ -70,6 +74,7 @@
 #include "BKE_nla.h"
 #include "BKE_sequencer.h"
 
+#include "MEM_guardedalloc.h"
 
 /* *************************************************** */
 /* Old-Data Freeing Tools */
@@ -102,7 +107,7 @@ void free_ipo (Ipo *ipo)
 /* Mapping Table for bitflag <-> RNA path */
 typedef struct AdrBit2Path {
        int bit;
-       char *path;
+       const char *path;
        int array_index;
 } AdrBit2Path;
 
@@ -111,27 +116,26 @@ typedef struct AdrBit2Path {
 
 /* Object layers */
 static AdrBit2Path ob_layer_bits[]= {
-       {(1<<0), "layer", 0},
-       {(1<<1), "layer", 1},
-       {(1<<2), "layer", 2},
-       {(1<<3), "layer", 3},
-       {(1<<4), "layer", 4},
-       {(1<<5), "layer", 5},
-       {(1<<6), "layer", 6},
-       {(1<<7), "layer", 7},
-       {(1<<8), "layer", 8},
-       {(1<<9), "layer", 9},
-       {(1<<10), "layer", 10},
-       {(1<<11), "layer", 11},
-       {(1<<12), "layer", 12},
-       {(1<<13), "layer", 13},
-       {(1<<14), "layer", 14},
-       {(1<<15), "layer", 15},
-       {(1<<16), "layer", 16},
-       {(1<<17), "layer", 17},
-       {(1<<18), "layer", 18},
-       {(1<<19), "layer", 19},
-       {(1<<20), "layer", 20}
+       {(1<<0), "layers", 0},
+       {(1<<1), "layers", 1},
+       {(1<<2), "layers", 2},
+       {(1<<3), "layers", 3},
+       {(1<<4), "layers", 4},
+       {(1<<5), "layers", 5},
+       {(1<<6), "layers", 6},
+       {(1<<7), "layers", 7},
+       {(1<<8), "layers", 8},
+       {(1<<9), "layers", 9},
+       {(1<<10), "layers", 10},
+       {(1<<11), "layers", 11},
+       {(1<<12), "layers", 12},
+       {(1<<13), "layers", 13},
+       {(1<<14), "layers", 14},
+       {(1<<15), "layers", 15},
+       {(1<<16), "layers", 16},
+       {(1<<17), "layers", 17},
+       {(1<<18), "layers", 18},
+       {(1<<19), "layers", 19}
 };
 
 /* Material mode */
@@ -172,7 +176,7 @@ static AdrBit2Path *adrcode_bitmaps_to_paths (int blocktype, int adrcode, int *t
 /* ADRCODE to RNA-Path Conversion Code  - Standard */
 
 /* Object types */
-static char *ob_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *ob_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -253,7 +257,7 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index)
 /* PoseChannel types 
  * NOTE: pchan name comes from 'actname' added earlier... 
  */
-static char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -297,7 +301,7 @@ static char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* Constraint types */
-static char *constraint_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *constraint_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -315,25 +319,25 @@ static char *constraint_adrcodes_to_paths (int adrcode, int *array_index)
 
 /* ShapeKey types 
  * NOTE: as we don't have access to the keyblock where the data comes from (for now), 
- *             we'll just use numerical indicies for now... 
+ *       we'll just use numerical indices for now...
  */
-static char *shapekey_adrcodes_to_paths (int adrcode, int *array_index)
+static char *shapekey_adrcodes_to_paths (int adrcode, int *UNUSED(array_index))
 {
        static char buf[128];
        
        /* block will be attached to ID_KE block, and setting that we alter is the 'value' (which sets keyblock.curval) */
        // XXX adrcode 0 was dummy 'speed' curve 
        if (adrcode == 0) 
-               sprintf(buf, "speed");
+               strcpy(buf, "speed");
        else
-               sprintf(buf, "keys[%d].value", adrcode);
+               BLI_snprintf(buf, sizeof(buf), "key_blocks[%d].value", adrcode);
        return buf;
 }
 
 /* MTex (Texture Slot) types */
-static char *mtex_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *mtex_adrcodes_to_paths (int adrcode, int *UNUSED(array_index))
 {
-       char *base=NULL, *prop=NULL;
+       const char *base=NULL, *prop=NULL;
        static char buf[128];
        
        /* base part of path */
@@ -401,7 +405,7 @@ static char *mtex_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* Texture types */
-static char *texture_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *texture_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -481,7 +485,7 @@ static char *texture_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* Material Types */
-static char *material_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *material_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -513,7 +517,7 @@ static char *material_adrcodes_to_paths (int adrcode, int *array_index)
                        return "alpha";
                        
                case MA_REF:
-                       return "diffuse_reflection";
+                       return "diffuse_intensity";
                
                case MA_EMIT:
                        return "emit";
@@ -522,7 +526,7 @@ static char *material_adrcodes_to_paths (int adrcode, int *array_index)
                        return "ambient";
                
                case MA_SPEC:
-                       return "specular_reflection";
+                       return "specular_intensity";
                
                case MA_HARD:
                        return "specular_hardness";
@@ -546,13 +550,13 @@ static char *material_adrcodes_to_paths (int adrcode, int *array_index)
                        return "raytrace_mirror.fresnel";
                        
                case MA_FRESMIRI:
-                       return "raytrace_mirror.fresnel_fac";
+                       return "raytrace_mirror.fresnel_factor";
                        
                case MA_FRESTRA:
                        return "raytrace_transparency.fresnel";
                        
                case MA_FRESTRAI:
-                       return "raytrace_transparency.fresnel_fac";
+                       return "raytrace_transparency.fresnel_factor";
                        
                case MA_ADD:
                        return "halo.add";
@@ -565,7 +569,7 @@ static char *material_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* Camera Types */
-static char *camera_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *camera_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -605,7 +609,7 @@ static char *camera_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* Lamp Types */
-static char *lamp_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *lamp_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -647,7 +651,7 @@ static char *lamp_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* Sound Types */
-static char *sound_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *sound_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -670,7 +674,7 @@ static char *sound_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* World Types */
-static char *world_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *world_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -701,14 +705,12 @@ static char *world_adrcodes_to_paths (int adrcode, int *array_index)
                        return "mist.start";
                case WO_MISTHI:
                        return "mist.height";
-               
-       /*      Star Color is unused -- recommend removal */
-       /*      case WO_STAR_R:
-                       *array_index= 0; return "stars.color";
+
+               case WO_STAR_R:
                case WO_STAR_G:
-                       *array_index= 1; return "stars.color";
                case WO_STAR_B:
-                       *array_index= 2; return "stars.color"; */
+                       printf("WARNING: WO_STAR_R/G/B deprecated\n");
+                       return NULL;
                
                case WO_STARDIST:
                        return "stars.min_distance";
@@ -723,7 +725,7 @@ static char *world_adrcodes_to_paths (int adrcode, int *array_index)
 }
 
 /* Particle Types */
-static char *particle_adrcodes_to_paths (int adrcode, int *array_index)
+static const char *particle_adrcodes_to_paths (int adrcode, int *array_index)
 {
        /* set array index like this in-case nothing sets it correctly  */
        *array_index= 0;
@@ -798,10 +800,11 @@ static char *particle_adrcodes_to_paths (int adrcode, int *array_index)
  *             - array_index                   - index in property's array (if applicable) to use
  *             - return                                - the allocated path...
  */
-static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], Sequence * seq, int *array_index)
+static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], Sequence *seq, int *array_index)
 {
        DynStr *path= BLI_dynstr_new();
-       char *propname=NULL, *rpath=NULL;
+       const char *propname=NULL;
+       char *rpath=NULL;
        char buf[512];
        int dummy_index= 0;
        
@@ -906,27 +909,40 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co
                if (array_index)
                        *array_index= dummy_index;
        }
-       
+
+       /* 'buf' _must_ be initialized in this block */
        /* append preceding bits to path */
+       /* note, strings are not escapted and they should be! */
        if ((actname && actname[0]) && (constname && constname[0])) {
                /* Constraint in Pose-Channel */
-               sprintf(buf, "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname);
+               BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname);
        }
        else if (actname && actname[0]) {
-               /* Pose-Channel */
-               sprintf(buf, "pose.bones[\"%s\"]", actname);
+               if ((blocktype == ID_OB) && strcmp(actname, "Object")==0) {
+                       /* Actionified "Object" IPO's... no extra path stuff needed */
+                       buf[0]= '\0'; /* empty string */
+               }
+               else if ((blocktype == ID_KE) && strcmp(actname, "Shape")==0) {
+                       /* Actionified "Shape" IPO's - these are forced onto object level via the action container there... */
+                       strcpy(buf, "data.shape_keys");
+               }
+               else {
+                       /* Pose-Channel */
+                       BLI_snprintf(buf, sizeof(buf), "pose.bones[\"%s\"]", actname);
+               }
        }
        else if (constname && constname[0]) {
                /* Constraint in Object */
-               sprintf(buf, "constraints[\"%s\"]", constname);
+               BLI_snprintf(buf, sizeof(buf), "constraints[\"%s\"]", constname);
        }
        else if (seq) {
                /* Sequence names in Scene */
-               sprintf(buf, "sequence_editor.sequences_all[\"%s\"]", 
-                       seq->name+2);
+               BLI_snprintf(buf, sizeof(buf), "sequence_editor.sequences_all[\"%s\"]", seq->name+2);
        }
-       else
-               strcpy(buf, ""); /* empty string */
+       else {
+               buf[0]= '\0'; /* empty string */
+       }
+
        BLI_dynstr_append(path, buf);
        
        /* need to add dot before property if there was anything precceding this */
@@ -938,7 +954,7 @@ static char *get_rna_access (int blocktype, int adrcode, char actname[], char co
        
        /* if there was no array index pointer provided, add it to the path */
        if (array_index == NULL) {
-               sprintf(buf, "[\"%d\"]", dummy_index);
+               BLI_snprintf(buf, sizeof(buf), "[\"%d\"]", dummy_index);
                BLI_dynstr_append(path, buf);
        }
        
@@ -1016,14 +1032,16 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
                                        /* first bone target */
                                dtar= &dvar->targets[0];
                                dtar->id= (ID *)idriver->ob;
+                               dtar->idtype= ID_OB;
                                if (idriver->name[0])
-                                       BLI_strncpy(dtar->pchan_name, idriver->name, 32);
+                                       BLI_strncpy(dtar->pchan_name, idriver->name, sizeof(dtar->pchan_name));
                                
                                        /* second bone target (name was stored in same var as the first one) */
                                dtar= &dvar->targets[1];
                                dtar->id= (ID *)idriver->ob;
+                               dtar->idtype= ID_OB;
                                if (idriver->name[0]) // xxx... for safety
-                                       BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, 32);
+                                       BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, sizeof(dtar->pchan_name));
                        }
                        else {
                                /* only a single variable, of type 'transform channel' */
@@ -1033,8 +1051,9 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
                                /* only requires a single target */
                                dtar= &dvar->targets[0];
                                dtar->id= (ID *)idriver->ob;
+                               dtar->idtype= ID_OB;
                                if (idriver->name[0])
-                                       BLI_strncpy(dtar->pchan_name, idriver->name, 32);
+                                       BLI_strncpy(dtar->pchan_name, idriver->name, sizeof(dtar->pchan_name));
                                dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode);
                                dtar->flag |= DTAR_FLAG_LOCALSPACE; /* old drivers took local space */
                        }
@@ -1047,6 +1066,7 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
                                /* only requires single target */
                        dtar= &dvar->targets[0];
                        dtar->id= (ID *)idriver->ob;
+                       dtar->idtype= ID_OB;
                        dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode);
                }
        }
@@ -1087,7 +1107,7 @@ static void fcurve_add_to_list (ListBase *groups, ListBase *list, FCurve *fcu, c
                                agrp->flag = AGRP_SELECTED;
                                if (muteipo) agrp->flag |= AGRP_MUTED;
                                
-                               strncpy(agrp->name, grpname, sizeof(agrp->name));
+                               BLI_strncpy(agrp->name, grpname, sizeof(agrp->name));
                                
                                BLI_addtail(&tmp_act.groups, agrp);
                                BLI_uniquename(&tmp_act.groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name));
@@ -1123,7 +1143,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
 {
        AdrBit2Path *abp;
        FCurve *fcu;
-       int i=0, totbits;
+       int totbits;
        
        /* allocate memory for a new F-Curve */
        fcu= MEM_callocN(sizeof(FCurve), "FCurve");
@@ -1138,7 +1158,6 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
        if (icu->flag & IPO_ACTIVE) fcu->flag |= FCURVE_ACTIVE;
        if (icu->flag & IPO_MUTE) fcu->flag |= FCURVE_MUTED;
        if (icu->flag & IPO_PROTECT) fcu->flag |= FCURVE_PROTECTED;
-       if (icu->flag & IPO_AUTO_HORIZ) fcu->flag |= FCURVE_AUTO_HANDLES;
        
        /* set extrapolation */
        switch (icu->extrap) {
@@ -1188,6 +1207,8 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                 * 3) filter the keyframes for the flag of interest
                 */
                for (b=0; b < totbits; b++, abp++) {
+                       unsigned int i=0;
+                       
                        /* make a copy of existing base-data if not the last curve */
                        if (b < (totbits-1))
                                fcurve= copy_fcurve(fcu);
@@ -1195,7 +1216,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                                fcurve= fcu;
                                
                        /* set path */
-                       fcurve->rna_path= BLI_strdupn(abp->path, strlen(abp->path));
+                       fcurve->rna_path= BLI_strdup(abp->path);
                        fcurve->array_index= abp->array_index;
                        
                        /* convert keyframes 
@@ -1211,7 +1232,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                                fcurve->bezt= MEM_callocN(sizeof(BezTriple)*fcurve->totvert, "BezTriples");
                                
                                /* loop through copying all BezTriples individually, as we need to modify a few things */
-                               for (dst=fcurve->bezt, src=icu->bezt; i < fcurve->totvert; i++, dst++, src++) {
+                               for (dst=fcurve->bezt, src=icu->bezt, i=0; i < fcurve->totvert; i++, dst++, src++) {
                                        /* firstly, copy BezTriple data */
                                        *dst= *src;
                                        
@@ -1221,6 +1242,12 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                                        /* 'hide' flag is now used for keytype - only 'keyframes' existed before */
                                        dst->hide= BEZT_KEYTYPE_KEYFRAME;
                                        
+                                       /* auto-handles - per curve to per handle */
+                                       if (icu->flag & IPO_AUTO_HORIZ) {
+                                               if (dst->h1 == HD_AUTO) dst->h1 = HD_AUTO_ANIM;
+                                               if (dst->h2 == HD_AUTO) dst->h2 = HD_AUTO_ANIM;
+                                       }
+                                       
                                        /* correct values, by checking if the flag of interest is set */
                                        if ( ((int)(dst->vec[1][1])) & (abp->bit) )
                                                dst->vec[0][1]= dst->vec[1][1]= dst->vec[2][1] = 1.0f;
@@ -1239,6 +1266,8 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                }
        }
        else {
+               unsigned int i=0;
+               
                /* get rna-path
                 *      - we will need to set the 'disabled' flag if no path is able to be made (for now)
                 */
@@ -1259,7 +1288,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                        fcu->bezt= MEM_callocN(sizeof(BezTriple)*fcu->totvert, "BezTriples");
                        
                        /* loop through copying all BezTriples individually, as we need to modify a few things */
-                       for (dst=fcu->bezt, src=icu->bezt; i < fcu->totvert; i++, dst++, src++) {
+                       for (dst=fcu->bezt, src=icu->bezt, i=0; i < fcu->totvert; i++, dst++, src++) {
                                /* firstly, copy BezTriple data */
                                *dst= *src;
                                
@@ -1269,6 +1298,12 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                                        
                                /* 'hide' flag is now used for keytype - only 'keyframes' existed before */
                                dst->hide= BEZT_KEYTYPE_KEYFRAME;
+                               
+                               /* auto-handles - per curve to per handle */
+                               if (icu->flag & IPO_AUTO_HORIZ) {
+                                       if (dst->h1 == HD_AUTO) dst->h1 = HD_AUTO_ANIM;
+                                       if (dst->h2 == HD_AUTO) dst->h2 = HD_AUTO_ANIM;
+                               }
                                        
                                /* correct values for euler rotation curves 
                                 *      - they were degrees/10 
@@ -1301,13 +1336,14 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                                /* correct times for rotation drivers 
                                 *      - need to go from degrees to radians...
                                 *      - there's only really 1 target to worry about 
+                                *  - were also degrees/10
                                 */
                                if (fcu->driver && fcu->driver->variables.first) {
                                        DriverVar *dvar= fcu->driver->variables.first;
                                        DriverTarget *dtar= &dvar->targets[0];
                                        
                                        if (ELEM3(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
-                                               const float fac= (float)M_PI / 180.0f;
+                                               const float fac= (float)M_PI / 18.0f;
                                                
                                                dst->vec[0][0] *= fac;
                                                dst->vec[1][0] *= fac;
@@ -1315,20 +1351,17 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
                                        }
                                }
                                
-                               /* correct values for sequencer curves,
-                                  that were not locked to frame */
-
-                               if (seq && 
-                                   (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) {
+                               /* correct values for sequencer curves, that were not locked to frame */
+                               if (seq && (seq->flag & SEQ_IPO_FRAME_LOCKED) == 0) {
                                        double mul= (seq->enddisp-seq->startdisp)/100.0f;
                                        double offset= seq->startdisp;
                                        
                                        dst->vec[0][0] *= mul;
                                        dst->vec[0][0] += offset;
-
+                                       
                                        dst->vec[1][0] *= mul;
                                        dst->vec[1][0] += offset;
-
+                                       
                                        dst->vec[2][0] *= mul;
                                        dst->vec[2][0] += offset;
                                }
@@ -1351,7 +1384,7 @@ static void icu_to_fcurves (ID *id, ListBase *groups, ListBase *list, IpoCurve *
  * This does not assume that any ID or AnimData uses it, but does assume that
  * it is given two lists, which it will perform driver/animation-data separation.
  */
-static void ipo_to_animato (ID *id, Ipo *ipo, char actname[], char constname[], Sequence * seq, ListBase *animgroups, ListBase *anim, ListBase *drivers)
+static void ipo_to_animato (ID *id, Ipo *ipo, char actname[], char constname[], Sequence *seq, ListBase *animgroups, ListBase *anim, ListBase *drivers)
 {
        IpoCurve *icu;
        
@@ -1395,8 +1428,7 @@ static void ipo_to_animato (ID *id, Ipo *ipo, char actname[], char constname[],
        
        /* if this IPO block doesn't have any users after this one, free... */
        ipo->id.us--;
-       if ( (ipo->id.us == 0) || ((ipo->id.us == 1) && (ipo->id.flag & LIB_FAKEUSER)) ) 
-       {
+       if (ID_REAL_USERS(ipo) <= 0) {
                IpoCurve *icn;
                
                for (icu= ipo->curve.first; icu; icu= icn) {
@@ -1475,7 +1507,7 @@ static void action_to_animato (ID *id, bAction *act, ListBase *groups, ListBase
  * This assumes that AnimData has been added already. Separation of drivers
  * from animation data is accomplished here too...
  */
-static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[], Sequence * seq)
+static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[], Sequence *seq)
 {
        AnimData *adt= BKE_animdata_from_id(id);
        ListBase anim = {NULL, NULL};
@@ -1506,19 +1538,23 @@ static void ipo_to_animdata (ID *id, Ipo *ipo, char actname[], char constname[],
                if (G.f & G_DEBUG) printf("\thas anim \n");
                /* try to get action */
                if (adt->action == NULL) {
-                       adt->action= add_empty_action("ConvData_Action"); // XXX we need a better name for this
-                       if (G.f & G_DEBUG) printf("\t\tadded new action \n");
+                       char nameBuf[MAX_ID_NAME];
+                       
+                       BLI_snprintf(nameBuf, sizeof(nameBuf), "CDA:%s", ipo->id.name+2);
+                       
+                       adt->action= add_empty_action(nameBuf);
+                       if (G.f & G_DEBUG) printf("\t\tadded new action - '%s' \n", nameBuf);
                }
                
                /* add F-Curves to action */
-               addlisttolist(&adt->action->curves, &anim);
+               BLI_movelisttolist(&adt->action->curves, &anim);
        }
        
        /* deal with drivers */
        if (drivers.first) {
                if (G.f & G_DEBUG) printf("\thas drivers \n");
                /* add drivers to end of driver stack */
-               addlisttolist(&adt->drivers, &drivers);
+               BLI_movelisttolist(&adt->drivers, &drivers);
        }
 }
 
@@ -1643,7 +1679,6 @@ void do_versions_ipos_to_animato(Main *main)
 {
        ListBase drivers = {NULL, NULL};
        ID *id;
-       AnimData *adt;
        
        if (main == NULL) {
                printf("Argh! Main is NULL in do_versions_ipos_to_animato() \n");
@@ -1672,7 +1707,7 @@ void do_versions_ipos_to_animato(Main *main)
                /* check if object has any animation data */
                if (ob->nlastrips.first) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       BKE_id_add_animdata(id);
                        
                        /* IPO first to take into any non-NLA'd Object Animation */
                        if (ob->ipo) {
@@ -1695,7 +1730,7 @@ void do_versions_ipos_to_animato(Main *main)
                }
                else if ((ob->ipo) || (ob->action)) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Action first - so that Action name get conserved */
                        if (ob->action) {
@@ -1779,6 +1814,13 @@ void do_versions_ipos_to_animato(Main *main)
                                BLI_freelinkN(&ob->constraintChannels, conchan);
                        }
                }
+               
+               /* object's action will always be object-rooted */
+               {
+                       AnimData *adt= BKE_animdata_from_id(id);
+                       if (adt && adt->action)
+                               adt->action->idroot = ID_OB;
+               }
        }
        
        /* shapekeys */
@@ -1793,10 +1835,14 @@ void do_versions_ipos_to_animato(Main *main)
                 */
                if (key->ipo) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Convert Shapekey data... */
                        ipo_to_animdata(id, key->ipo, NULL, NULL, NULL);
+                       
+                       if (adt->action)
+                               adt->action->idroot = key->ipo->blocktype;
+                       
                        key->ipo->id.us--;
                        key->ipo= NULL;
                }
@@ -1811,10 +1857,14 @@ void do_versions_ipos_to_animato(Main *main)
                /* we're only interested in the IPO */
                if (ma->ipo) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Convert Material data... */
                        ipo_to_animdata(id, ma->ipo, NULL, NULL, NULL);
+                       
+                       if (adt->action)
+                               adt->action->idroot = ma->ipo->blocktype;
+                       
                        ma->ipo->id.us--;
                        ma->ipo= NULL;
                }
@@ -1829,10 +1879,14 @@ void do_versions_ipos_to_animato(Main *main)
                /* we're only interested in the IPO */
                if (wo->ipo) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Convert World data... */
                        ipo_to_animdata(id, wo->ipo, NULL, NULL, NULL);
+                       
+                       if (adt->action)
+                               adt->action->idroot = wo->ipo->blocktype;
+                       
                        wo->ipo->id.us--;
                        wo->ipo= NULL;
                }
@@ -1845,7 +1899,7 @@ void do_versions_ipos_to_animato(Main *main)
                if (ed && ed->seqbasep) {
                        Sequence * seq;
                        
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        SEQ_BEGIN(ed, seq) {
                                IpoCurve *icu = (seq->ipo) ? seq->ipo->curve.first : NULL;
@@ -1863,7 +1917,7 @@ void do_versions_ipos_to_animato(Main *main)
                                   to different DNA variables later 
                                   (semi-hack (tm) )
                                */
-                               switch(seq->type) {
+                               switch (seq->type) {
                                        case SEQ_IMAGE:
                                        case SEQ_META:
                                        case SEQ_SCENE:
@@ -1879,6 +1933,10 @@ void do_versions_ipos_to_animato(Main *main)
                                
                                /* convert IPO */
                                ipo_to_animdata((ID *)scene, seq->ipo, NULL, NULL, seq);
+                               
+                               if (adt->action)
+                                       adt->action->idroot = ID_SCE; /* scene-rooted */
+                               
                                seq->ipo->id.us--;
                                seq->ipo = NULL;
                        }
@@ -1896,10 +1954,14 @@ void do_versions_ipos_to_animato(Main *main)
                /* we're only interested in the IPO */
                if (te->ipo) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Convert Texture data... */
                        ipo_to_animdata(id, te->ipo, NULL, NULL, NULL);
+                       
+                       if (adt->action)
+                               adt->action->idroot = te->ipo->blocktype;
+                       
                        te->ipo->id.us--;
                        te->ipo= NULL;
                }
@@ -1914,10 +1976,14 @@ void do_versions_ipos_to_animato(Main *main)
                /* we're only interested in the IPO */
                if (ca->ipo) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Convert Camera data... */
                        ipo_to_animdata(id, ca->ipo, NULL, NULL, NULL);
+                       
+                       if (adt->action)
+                               adt->action->idroot = ca->ipo->blocktype;
+                       
                        ca->ipo->id.us--;
                        ca->ipo= NULL;
                }
@@ -1932,10 +1998,14 @@ void do_versions_ipos_to_animato(Main *main)
                /* we're only interested in the IPO */
                if (la->ipo) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Convert Lamp data... */
                        ipo_to_animdata(id, la->ipo, NULL, NULL, NULL);
+                       
+                       if (adt->action)
+                               adt->action->idroot = la->ipo->blocktype;
+                       
                        la->ipo->id.us--;
                        la->ipo= NULL;
                }
@@ -1950,10 +2020,14 @@ void do_versions_ipos_to_animato(Main *main)
                /* we're only interested in the IPO */
                if (cu->ipo) {
                        /* Add AnimData block */
-                       adt= BKE_id_add_animdata(id);
+                       AnimData *adt= BKE_id_add_animdata(id);
                        
                        /* Convert Curve data... */
                        ipo_to_animdata(id, cu->ipo, NULL, NULL, NULL);
+                       
+                       if (adt->action)
+                               adt->action->idroot = cu->ipo->blocktype;
+                       
                        cu->ipo->id.us--;
                        cu->ipo= NULL;
                }
@@ -1976,6 +2050,10 @@ void do_versions_ipos_to_animato(Main *main)
                
                if (G.f & G_DEBUG) printf("\tconverting action %s \n", id->name+2);
                
+               /* if old action, it will be object-only... */
+               if (act->chanbase.first)
+                       act->idroot = ID_OB;
+               
                /* be careful! some of the actions we encounter will be converted ones... */
                action_to_animato(NULL, act, &act->groups, &act->curves, &drivers);
        }
@@ -1993,6 +2071,7 @@ void do_versions_ipos_to_animato(Main *main)
                        /* add a new action for this, and convert all data into that action */
                        new_act= add_empty_action("ConvIPO_Action"); // XXX need a better name...
                        ipo_to_animato(NULL, ipo, NULL, NULL, NULL, NULL, &new_act->curves, &drivers);
+                       new_act->idroot = ipo->blocktype;
                }
                
                /* clear fake-users, and set user-count to zero to make sure it is cleared on file-save */