constraints unique name length was set too long (could overrun the buffer), use sizeo...
[blender.git] / source / blender / blenkernel / intern / ipo.c
index 54618813a0bcd105273a7620f6b90e498451c15e..dbde6403226fc300603ccb6ee5ef6cdb07f229d2 100644 (file)
@@ -16,7 +16,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.
@@ -58,6 +58,7 @@
 #include "DNA_key_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_nla_types.h"
 #include "DNA_object_types.h"
 #include "DNA_object_force.h"
 #include "DNA_particle_types.h"
@@ -69,7 +70,7 @@
 #include "DNA_world_types.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_arithb.h"
+#include "BLI_math.h"
 #include "BLI_dynstr.h"
 
 #include "BKE_utildefines.h"
@@ -85,6 +86,7 @@
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_mesh.h"
+#include "BKE_nla.h"
 #include "BKE_object.h"
 
 
@@ -158,7 +160,7 @@ static AdrBit2Path ma_mode_bits[]= {
 //     {MA_SHADOW, "shadow", 0},
 //     {MA_SHLESS, "shadeless", 0},
 //     ...
-       {MA_RAYTRANSP, "raytrace_transparency.enabled", 0},
+       {MA_RAYTRANSP, "transparency", 0},
        {MA_RAYMIRROR, "raytrace_mirror.enabled", 0},
 //     {MA_HALO, "type", MA_TYPE_HALO}
 };
@@ -211,17 +213,17 @@ static char *ob_adrcodes_to_paths (int adrcode, int *array_index)
                        *array_index= 2; return "delta_location";
                
                case OB_ROT_X:
-                       *array_index= 0; return "rotation";
+                       *array_index= 0; return "rotation_euler";
                case OB_ROT_Y:
-                       *array_index= 1; return "rotation";
+                       *array_index= 1; return "rotation_euler";
                case OB_ROT_Z:
-                       *array_index= 2; return "rotation";
+                       *array_index= 2; return "rotation_euler";
                case OB_DROT_X:
-                       *array_index= 0; return "delta_rotation";
+                       *array_index= 0; return "delta_rotation_euler";
                case OB_DROT_Y:
-                       *array_index= 1; return "delta_rotation";
+                       *array_index= 1; return "delta_rotation_euler";
                case OB_DROT_Z:
-                       *array_index= 2; return "delta_rotation";
+                       *array_index= 2; return "delta_rotation_euler";
                        
                case OB_SIZE_X:
                        *array_index= 0; return "scale";
@@ -279,24 +281,21 @@ static char *pchan_adrcodes_to_paths (int adrcode, int *array_index)
        /* result depends on adrcode */
        switch (adrcode) {
                case AC_QUAT_W:
-                       *array_index= 0; return "rotation";
+                       *array_index= 0; return "rotation_quaternion";
                case AC_QUAT_X:
-                       *array_index= 1; return "rotation";
+                       *array_index= 1; return "rotation_quaternion";
                case AC_QUAT_Y:
-                       *array_index= 2; return "rotation";
+                       *array_index= 2; return "rotation_quaternion";
                case AC_QUAT_Z:
-                       *array_index= 3; return "rotation";
+                       *array_index= 3; return "rotation_quaternion";
                        
                case AC_EUL_X:
-                       *array_index= 0; return "euler_rotation";
+                       *array_index= 0; return "rotation_euler";
                case AC_EUL_Y:
-                       *array_index= 1; return "euler_rotation";
+                       *array_index= 1; return "rotation_euler";
                case AC_EUL_Z:
-                       *array_index= 2; return "euler_rotation";
-                       
-               case -1: // XXX special case for rotation drivers... until eulers are added...
-                       *array_index= 0; return "rotation";
-                       
+                       *array_index= 2; return "rotation_euler";
+               
                case AC_LOC_X:
                        *array_index= 0; return "location";
                case AC_LOC_Y:
@@ -599,8 +598,9 @@ static char *camera_adrcodes_to_paths (int adrcode, int *array_index)
                                return "ortho_scale";
                        else
                                return "lens"; 
+#else // XXX lazy hack for now...
+                       return "lens";
 #endif // XXX this cannot be resolved easily
-                       break;
                        
                case CAM_STA:
                        return "clip_start";
@@ -818,13 +818,17 @@ 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...
  */
-char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index)
+static char *get_rna_access (int blocktype, int adrcode, char actname[], char constname[], int *array_index)
 {
        DynStr *path= BLI_dynstr_new();
        char *propname=NULL, *rpath=NULL;
        char buf[512];
        int dummy_index= 0;
        
+       /* hack: if constname is set, we can only be dealing with an Constraint curve */
+       if (constname)
+               blocktype= ID_CO;
+       
        /* get property name based on blocktype */
        switch (blocktype) {
                case ID_OB: /* object */
@@ -840,7 +844,7 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
                        break;
                        
                case ID_CO: /* constraint */
-                       propname= constraint_adrcodes_to_paths(adrcode, &dummy_index);
+                       propname= constraint_adrcodes_to_paths(adrcode, &dummy_index);  
                        break;
                        
                case ID_TE: /* texture */
@@ -861,20 +865,37 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
                
                case ID_SO: /* sound */
                        propname= sound_adrcodes_to_paths(adrcode, &dummy_index);
+                       break;
                
                case ID_WO: /* world */
                        propname= world_adrcodes_to_paths(adrcode, &dummy_index);
+                       break;
 
                case ID_PA: /* particle */
                        propname= particle_adrcodes_to_paths(adrcode, &dummy_index);
+                       break;
                        
                /* XXX problematic blocktypes */
                case ID_CU: /* curve */
-                       propname= "speed"; // XXX this was a 'dummy curve' that didn't really correspond to any real var...
+                       /* this used to be a 'dummy' curve which got evaluated on the fly... 
+                        * now we've got real var for this!
+                        */
+                       propname= "eval_time";
                        break;
                        
                case ID_SEQ: /* sequencer strip */
                        //SEQ_FAC1:
+                       switch (adrcode) {
+                       case SEQ_FAC1:
+                               propname= "effect_fader";
+                               break;
+                       case SEQ_FAC_SPEED:
+                               propname= "speed_fader";
+                               break;
+                       case SEQ_FAC_OPACITY:
+                               propname= "blend_opacity";
+                               break;
+                       }
                        //      poin= &(seq->facf0); // XXX this doesn't seem to be included anywhere in sequencer RNA...
                        break;
                        
@@ -909,11 +930,11 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
        /* append preceeding bits to path */
        if ((actname && actname[0]) && (constname && constname[0])) {
                /* Constraint in Pose-Channel */
-               sprintf(buf, "pose.pose_channels[\"%s\"].constraints[\"%s\"]", actname, constname);
+               sprintf(buf, "pose.bones[\"%s\"].constraints[\"%s\"]", actname, constname);
        }
        else if (actname && actname[0]) {
                /* Pose-Channel */
-               sprintf(buf, "pose.pose_channels[\"%s\"]", actname);
+               sprintf(buf, "pose.bones[\"%s\"]", actname);
        }
        else if (constname && constname[0]) {
                /* Constraint in Object */
@@ -923,14 +944,17 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
                strcpy(buf, ""); /* empty string */
        BLI_dynstr_append(path, buf);
        
-       /* append property to path (only if applicable) */
-       if (blocktype > 0) {
-               /* need to add dot before property if there was anything precceding this */
-               if (buf[0])
-                       BLI_dynstr_append(path, ".");
-               
-               /* now write name of property */
-               BLI_dynstr_append(path, propname);
+       /* need to add dot before property if there was anything precceding this */
+       if (buf[0])
+               BLI_dynstr_append(path, ".");
+       
+       /* now write name of property */
+       BLI_dynstr_append(path, propname);
+       
+       /* if there was no array index pointer provided, add it to the path */
+       if (array_index == NULL) {
+               sprintf(buf, "[\"%d\"]", dummy_index);
+               BLI_dynstr_append(path, buf);
        }
        
        /* convert to normal MEM_malloc'd string */
@@ -944,11 +968,40 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
 /* *************************************************** */
 /* Conversion Utilities */
 
+/* Convert adrcodes to driver target transform channel types */
+static short adrcode_to_dtar_transchan (short adrcode)
+{
+       switch (adrcode) {
+               case OB_LOC_X:  
+                       return DTAR_TRANSCHAN_LOCX;
+               case OB_LOC_Y:
+                       return DTAR_TRANSCHAN_LOCY;
+               case OB_LOC_Z:
+                       return DTAR_TRANSCHAN_LOCZ;
+               
+               case OB_ROT_X:  
+                       return DTAR_TRANSCHAN_ROTX;
+               case OB_ROT_Y:
+                       return DTAR_TRANSCHAN_ROTY;
+               case OB_ROT_Z:
+                       return DTAR_TRANSCHAN_ROTZ;
+               
+               case OB_SIZE_X: 
+                       return DTAR_TRANSCHAN_SCALEX;
+               case OB_SIZE_Y:
+                       return DTAR_TRANSCHAN_SCALEX;
+               case OB_SIZE_Z:
+                       return DTAR_TRANSCHAN_SCALEX;
+                       
+               default:
+                       return 0;
+       }
+}
+
 /* Convert IpoDriver to ChannelDriver - will free the old data (i.e. the old driver) */
 static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
 {
        ChannelDriver *cdriver;
-       DriverTarget *dtar=NULL, *dtar2=NULL;
        
        /* allocate memory for new driver */
        cdriver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
@@ -956,93 +1009,62 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
        /* if 'pydriver', just copy data across */
        if (idriver->type == IPO_DRIVER_TYPE_PYTHON) {
                /* PyDriver only requires the expression to be copied */
-               // TODO: but the expression will be useless...
+               // FIXME: expression will be useless due to API changes, but at least not totally lost
                cdriver->type = DRIVER_TYPE_PYTHON;
-               strcpy(cdriver->expression, idriver->name); // XXX is this safe? 
+               if (idriver->name[0])
+                       BLI_strncpy(cdriver->expression, idriver->name, sizeof(cdriver->expression));
        }
        else {
-               /* what to store depends on the 'blocktype' (ID_OB or ID_PO - object or posechannel) */
-               if (idriver->blocktype == ID_AR) {
-                       /* ID_PO */
+               DriverVar *dvar = NULL;
+               DriverTarget *dtar = NULL;
+               
+               /* this should be ok for all types here... */
+               cdriver->type= DRIVER_TYPE_AVERAGE;
+               
+               /* what to store depends on the 'blocktype' - object or posechannel */
+               if (idriver->blocktype == ID_AR) { /* PoseChannel */
                        if (idriver->adrcode == OB_ROT_DIFF) {
-                               /* Rotational Difference is a special type of driver now... */
-                               cdriver->type= DRIVER_TYPE_ROTDIFF;
-                               
-                               /* make 2 driver targets */
-                               dtar= driver_add_new_target(cdriver);
-                               dtar2= driver_add_new_target(cdriver);
+                               /* Rotational Difference requires a special type of variable */
+                               dvar= driver_add_new_variable(cdriver);
+                               driver_change_variable_type(dvar, DVAR_TYPE_ROT_DIFF);
                                
-                               /* driver must use bones from same armature... */
-                               dtar->id= dtar2->id= (ID *)idriver->ob;
+                                       /* first bone target */
+                               dtar= &dvar->targets[0];
+                               dtar->id= (ID *)idriver->ob;
+                               if (idriver->name[0])
+                                       BLI_strncpy(dtar->pchan_name, idriver->name, 32);
                                
-                               /* paths for the two targets get the pointers to the relevant Pose-Channels 
-                                *      - return pointers to Pose-Channels not rotation channels, as calculation code is picky
-                                *      - old bone names were stored in same var, in idriver->name
-                                *
-                                *      - we use several hacks here - blocktype == -1 specifies that no property needs to be found, and
-                                *        providing a name for 'actname' will automatically imply Pose-Channel with name 'actname'
-                                */
-                               dtar->rna_path= get_rna_access(-1, -1, idriver->name, NULL, NULL);
-                               dtar2->rna_path= get_rna_access(-1, -1, idriver->name+DRIVER_NAME_OFFS, NULL, NULL);
+                                       /* second bone target (name was stored in same var as the first one) */
+                               dtar= &dvar->targets[1];
+                               dtar->id= (ID *)idriver->ob;
+                               if (idriver->name[0]) // xxx... for safety
+                                       BLI_strncpy(dtar->pchan_name, idriver->name+DRIVER_NAME_OFFS, 32);
                        }
                        else {
-                               /* 'standard' driver */
-                               cdriver->type= DRIVER_TYPE_AVERAGE;
+                               /* only a single variable, of type 'transform channel' */
+                               dvar= driver_add_new_variable(cdriver);
+                               driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
                                
-                               /* make 1 driver target */
-                               dtar= driver_add_new_target(cdriver);
+                               /* only requires a single target */
+                               dtar= &dvar->targets[0];
                                dtar->id= (ID *)idriver->ob;
-                               
-                               switch (idriver->adrcode) {
-                                       case OB_LOC_X:  /* x,y,z location are quite straightforward */
-                                               dtar->rna_path= get_rna_access(ID_PO, AC_LOC_X, idriver->name, NULL, &dtar->array_index);
-                                               break;
-                                       case OB_LOC_Y:
-                                               dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Y, idriver->name, NULL, &dtar->array_index);
-                                               break;
-                                       case OB_LOC_Z:
-                                               dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Z, idriver->name, NULL, &dtar->array_index);
-                                               break;
-                                               
-                                       case OB_SIZE_X: /* x,y,z scaling are also quite straightforward */
-                                               dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_X, idriver->name, NULL, &dtar->array_index);
-                                               break;
-                                       case OB_SIZE_Y:
-                                               dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Y, idriver->name, NULL, &dtar->array_index);
-                                               break;
-                                       case OB_SIZE_Z:
-                                               dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Z, idriver->name, NULL, &dtar->array_index);
-                                               break;  
-                                               
-                                       case OB_ROT_X:  /* rotation - we need to be careful with this... XXX (another reason why we need eulers) */     
-                                       case OB_ROT_Y:
-                                       case OB_ROT_Z:
-                                       {
-                                               // XXX this is not yet a 1:1 map, since we'd need euler rotations to make this work nicely (unless we make some hacks)
-                                               // XXX -1 here is a special hack...
-                                               dtar->rna_path= get_rna_access(ID_PO, -1, idriver->name, NULL, NULL);
-                                               dtar->array_index= idriver->adrcode - OB_ROT_X;
-                                       }
-                                               break;
-                               }
+                               if (idriver->name[0])
+                                       BLI_strncpy(dtar->pchan_name, idriver->name, 32);
+                               dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode);
                        }
                }
-               else {
-                       /* ID_OB */
-                       cdriver->type= DRIVER_TYPE_AVERAGE;
-                       
-                       /* make 1 driver target */
-                       dtar= driver_add_new_target(cdriver);
+               else { /* Object */
+                       /* only a single variable, of type 'transform channel' */
+                       dvar= driver_add_new_variable(cdriver);
+                       driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
                        
+                               /* only requires single target */
+                       dtar= &dvar->targets[0];
                        dtar->id= (ID *)idriver->ob;
-                       dtar->rna_path= get_rna_access(ID_OB, idriver->adrcode, NULL, NULL, &dtar->array_index);
+                       dtar->transChan= adrcode_to_dtar_transchan(idriver->adrcode);
                }
        }
        
-       
-       /* free old driver */
-       MEM_freeN(idriver);
-       
        /* return the new one */
        return cdriver;
 }
@@ -1050,7 +1072,7 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
 /* Add F-Curve to the correct list 
  *     - grpname is needed to be used as group name where relevant, and is usually derived from actname
  */
-static void fcurve_add_to_list (ListBase *groups, ListBase *list, FCurve *fcu, char *grpname)
+static void fcurve_add_to_list (ListBase *groups, ListBase *list, FCurve *fcu, char *grpname, int muteipo)
 {
        /* If we're adding to an action, we will have groups to write to... */
        if (groups && grpname) {
@@ -1077,10 +1099,12 @@ static void fcurve_add_to_list (ListBase *groups, ListBase *list, FCurve *fcu, c
                                agrp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
                                
                                agrp->flag = AGRP_SELECTED;
-                               BLI_snprintf(agrp->name, 64, grpname);
+                               if(muteipo) agrp->flag |= AGRP_MUTED;
+
+                               strncpy(agrp->name, grpname, sizeof(agrp->name));
                                
                                BLI_addtail(&tmp_act.groups, agrp);
-                               BLI_uniquename(&tmp_act.groups, agrp, "Group", '.', offsetof(bActionGroup, name), 64);
+                               BLI_uniquename(&tmp_act.groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name));
                        }
                }
                
@@ -1088,6 +1112,9 @@ static void fcurve_add_to_list (ListBase *groups, ListBase *list, FCurve *fcu, c
                /* WARNING: this func should only need to look at the stuff we initialised, if not, things may crash */
                action_groups_add_channel(&tmp_act, agrp, fcu);
                
+               if(agrp->flag & AGRP_MUTED) /* flush down */
+                       fcu->flag |= FCURVE_MUTED;
+
                /* set the output lists based on the ones in the temp action */
                groups->first= tmp_act.groups.first;
                groups->last= tmp_act.groups.last;
@@ -1105,7 +1132,7 @@ static void fcurve_add_to_list (ListBase *groups, ListBase *list, FCurve *fcu, c
  *     actname: name of Action-Channel (if applicable) that IPO-Curve's IPO-block belonged to
  *     constname: name of Constraint-Channel (if applicable) that IPO-Curve's IPO-block belonged to
  */
-static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, char *actname, char *constname)
+static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, char *actname, char *constname, int muteipo)
 {
        AdrBit2Path *abp;
        FCurve *fcu;
@@ -1114,11 +1141,9 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
        /* allocate memory for a new F-Curve */
        fcu= MEM_callocN(sizeof(FCurve), "FCurve");
        
-       /* convert driver - will free the old one... */
-       if (icu->driver) {
+       /* convert driver */
+       if (icu->driver)
                fcu->driver= idriver_to_cdriver(icu->driver);
-               icu->driver= NULL;
-       }
        
        /* copy flags */
        if (icu->flag & IPO_VISIBLE) fcu->flag |= FCURVE_VISIBLE;
@@ -1144,7 +1169,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
                        /* Add a new FModifier (Cyclic) instead of setting extend value 
                         * as that's the new equivilant of that option. 
                         */
-                       FModifier *fcm= fcurve_add_modifier(fcu, FMODIFIER_TYPE_CYCLES);
+                       FModifier *fcm= add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES);
                        FMod_Cycles *data= (FMod_Cycles *)fcm->data;
                        
                        /* if 'offset' one is in use, set appropriate settings */
@@ -1206,6 +1231,9 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
                                        /* interpolation can only be constant... */
                                        dst->ipo= BEZT_IPO_CONST;
                                        
+                                       /* 'hide' flag is now used for keytype - only 'keyframes' existed before */
+                                       dst->hide= BEZT_KEYTYPE_KEYFRAME;
+                                       
                                        /* 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;
@@ -1220,12 +1248,8 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
                        }
                        
                        /* add new F-Curve to list */
-                       fcurve_add_to_list(groups, list, fcurve, actname);
+                       fcurve_add_to_list(groups, list, fcurve, actname, muteipo);
                }
-               
-               /* free old data of curve now that it's no longer needed for converting any more curves */
-               if (icu->bezt) MEM_freeN(icu->bezt);
-               if (icu->bp) MEM_freeN(icu->bezt);
        }
        else {
                /* get rna-path
@@ -1256,8 +1280,13 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
                                if (icu->ipo != IPO_MIXED)
                                        dst->ipo= icu->ipo;
                                        
-                               /* correct values for euler rotation curves - they were degrees/10 */
-                               // XXX for now, just make them into radians as RNA sets/reads directly in that form
+                               /* 'hide' flag is now used for keytype - only 'keyframes' existed before */
+                               dst->hide= BEZT_KEYTYPE_KEYFRAME;
+                                       
+                               /* correct values for euler rotation curves 
+                                *      - they were degrees/10 
+                                *      - we need radians for RNA to do the right thing
+                                */
                                if ( ((icu->blocktype == ID_OB) && ELEM3(icu->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) ||
                                         ((icu->blocktype == ID_PO) && ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z)) )
                                {
@@ -1267,10 +1296,24 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
                                        dst->vec[1][1] *= fac;
                                        dst->vec[2][1] *= fac;
                                }
+                               
+                               /* correct times for rotation drivers 
+                                *      - need to go from degrees to radians...
+                                *      - there's only really 1 target to worry about 
+                                */
+                               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;
+                                               
+                                               dst->vec[0][0] *= fac;
+                                               dst->vec[1][0] *= fac;
+                                               dst->vec[2][0] *= fac;
+                                       }
+                               }
                        }
-                       
-                       /* free this data now */
-                       MEM_freeN(icu->bezt);
                }
                else if (icu->bp) {
                        /* TODO: need to convert from BPoint type to the more compact FPoint type... but not priority, since no data used this */
@@ -1279,7 +1322,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
                }
                
                /* add new F-Curve to list */
-               fcurve_add_to_list(groups, list, fcu, actname);
+               fcurve_add_to_list(groups, list, fcu, actname, muteipo);
        }
 }
 
@@ -1291,7 +1334,7 @@ static void icu_to_fcurves (ListBase *groups, ListBase *list, IpoCurve *icu, cha
  */
 static void ipo_to_animato (Ipo *ipo, char actname[], char constname[], ListBase *animgroups, ListBase *anim, ListBase *drivers)
 {
-       IpoCurve *icu, *icn;
+       IpoCurve *icu;
        
        /* sanity check */
        if (ELEM3(NULL, ipo, anim, drivers))
@@ -1313,25 +1356,44 @@ static void ipo_to_animato (Ipo *ipo, char actname[], char constname[], ListBase
        }
        
        /* loop over IPO-Curves, freeing as we progress */
-       for (icu= ipo->curve.first; icu; icu= icn) {
-               /* get link to next (for later) */
-               icn= icu->next;
-               
+       for (icu= ipo->curve.first; icu; icu= icu->next) {
                /* Since an IPO-Curve may end up being made into many F-Curves (i.e. bitflag curves), 
                 * we figure out the best place to put the channel, then tell the curve-converter to just dump there
                 */
                if (icu->driver) {
                        /* Blender 2.4x allowed empty drivers, but we don't now, since they cause more trouble than they're worth */
-                       if ((icu->driver->ob) || (icu->driver->type == IPO_DRIVER_TYPE_PYTHON))
-                               icu_to_fcurves(NULL, drivers, icu, actname, constname);
-                       else
+                       if ((icu->driver->ob) || (icu->driver->type == IPO_DRIVER_TYPE_PYTHON)) {
+                               icu_to_fcurves(NULL, drivers, icu, actname, constname, ipo->muteipo);
+                       }
+                       else {
                                MEM_freeN(icu->driver);
+                               icu->driver= NULL;
+                       }
                }
                else
-                       icu_to_fcurves(animgroups, anim, icu, actname, constname);
+                       icu_to_fcurves(animgroups, anim, icu, actname, constname, ipo->muteipo);
+       }
+       
+       /* 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)) ) 
+       {
+               IpoCurve *icn;
                
-               /* free this IpoCurve now that it's been converted */
-               BLI_freelinkN(&ipo->curve, icu);
+               for (icu= ipo->curve.first; icu; icu= icn) {
+                       icn= icu->next;
+                       
+                       /* free driver */
+                       if (icu->driver)
+                               MEM_freeN(icu->driver);
+                               
+                       /* free old data of curve now that it's no longer needed for converting any more curves */
+                       if (icu->bezt) MEM_freeN(icu->bezt);
+                       if (icu->bp) MEM_freeN(icu->bezt);
+                       
+                       /* free this IPO-Curve */
+                       BLI_freelinkN(&ipo->curve, icu);
+               }
        }
 }
 
@@ -1463,6 +1525,87 @@ static void action_to_animdata (ID *id, bAction *act)
        action_to_animato(act, &adt->action->groups, &adt->action->curves, &adt->drivers);
 }
 
+/* ------------------------- */
+
+// TODO:
+//     - NLA group duplicators info
+//     - NLA curve/stride modifiers...
+
+/* Convert NLA-Strip to new system */
+static void nlastrips_to_animdata (ID *id, ListBase *strips)
+{
+       AnimData *adt= BKE_animdata_from_id(id);
+       NlaTrack *nlt = NULL;
+       NlaStrip *strip;
+       bActionStrip *as, *asn;
+       
+       /* for each one of the original strips, convert to a new strip and free the old... */
+       for (as= strips->first; as; as= asn) {
+               asn= as->next;
+               
+               /* this old strip is only worth something if it had an action... */
+               if (as->act) {
+                       /* convert Action data (if not yet converted), storing the results in the same Action */
+                       action_to_animato(as->act, &as->act->groups, &as->act->curves, &adt->drivers);
+                       
+                       /* create a new-style NLA-strip which references this Action, then copy over relevant settings */
+                       {
+                               /* init a new strip, and assign the action to it 
+                                *      - no need to muck around with the user-counts, since this is just 
+                                *        passing over the ref to the new owner, not creating an additional ref
+                                */
+                               strip= MEM_callocN(sizeof(NlaStrip), "NlaStrip");
+                               strip->act= as->act;
+                               
+                                       /* endpoints */
+                               strip->start= as->start;
+                               strip->end= as->end;
+                               strip->actstart= as->actstart;
+                               strip->actend= as->actend;
+                               
+                                       /* action reuse */
+                               strip->repeat= as->repeat;
+                               strip->scale= as->scale;
+                               if (as->flag & ACTSTRIP_LOCK_ACTION)    strip->flag |= NLASTRIP_FLAG_SYNC_LENGTH;
+                               
+                                       /* blending */
+                               strip->blendin= as->blendin;
+                               strip->blendout= as->blendout;
+                               strip->blendmode= (as->mode==ACTSTRIPMODE_ADD) ? NLASTRIP_MODE_ADD : NLASTRIP_MODE_REPLACE;
+                               if (as->flag & ACTSTRIP_AUTO_BLENDS)    strip->flag |= NLASTRIP_FLAG_AUTO_BLENDS;
+                                       
+                                       /* assorted setting flags */
+                               if (as->flag & ACTSTRIP_SELECT)                 strip->flag |= NLASTRIP_FLAG_SELECT;
+                               if (as->flag & ACTSTRIP_ACTIVE)                 strip->flag |= NLASTRIP_FLAG_ACTIVE;
+                               
+                               if (as->flag & ACTSTRIP_MUTE)                   strip->flag |= NLASTRIP_FLAG_MUTED;
+                               if (as->flag & ACTSTRIP_REVERSE)                strip->flag |= NLASTRIP_FLAG_REVERSE;
+                               
+                                       /* by default, we now always extrapolate, while in the past this was optional */
+                               if ((as->flag & ACTSTRIP_HOLDLASTFRAME)==0) 
+                                       strip->extendmode= NLASTRIP_EXTEND_NOTHING;
+                       }       
+                       
+                       /* try to add this strip to the current NLA-Track (i.e. the 'last' one on the stack atm) */
+                       if (BKE_nlatrack_add_strip(nlt, strip) == 0) {
+                               /* trying to add to the current failed (no space), 
+                                * so add a new track to the stack, and add to that...
+                                */
+                               nlt= add_nlatrack(adt, NULL);
+                               BKE_nlatrack_add_strip(nlt, strip);
+                       }
+               }
+               
+               /* modifiers */
+               // FIXME: for now, we just free them...
+               if (as->modifiers.first)
+                       BLI_freelistN(&as->modifiers);
+               
+               /* free the old strip */
+               BLI_freelinkN(strips, as);
+       }
+}
+
 /* *************************************************** */
 /* External API - Only Called from do_versions() */
 
@@ -1482,6 +1625,7 @@ void do_versions_ipos_to_animato(Main *main)
        ListBase drivers = {NULL, NULL};
        ID *id;
        AnimData *adt;
+       Scene *scene;
        
        if (main == NULL) {
                printf("Argh! Main is NULL in do_versions_ipos_to_animato() \n");
@@ -1509,7 +1653,30 @@ void do_versions_ipos_to_animato(Main *main)
                if (G.f & G_DEBUG) printf("\tconverting ob %s \n", id->name+2);
                
                /* check if object has any animation data */
-               if ((ob->ipo) || (ob->action) || (ob->nlastrips.first)) {
+               if (ob->nlastrips.first) {
+                       /* Add AnimData block */
+                       adt= BKE_id_add_animdata(id);
+                       
+                       /* IPO first to take into any non-NLA'd Object Animation */
+                       if (ob->ipo) {
+                               ipo_to_animdata(id, ob->ipo, NULL, NULL);
+                               
+                               ob->ipo->id.us--;
+                               ob->ipo= NULL;
+                       }
+                       
+                       /* Action is skipped since it'll be used by some strip in the NLA anyway, 
+                        * causing errors with evaluation in the new evaluation pipeline
+                        */
+                       if (ob->action) {
+                               ob->action->id.us--;
+                               ob->action= NULL;
+                       }
+                       
+                       /* finally NLA */
+                       nlastrips_to_animdata(id, &ob->nlastrips);
+               }
+               else if ((ob->ipo) || (ob->action)) {
                        /* Add AnimData block */
                        adt= BKE_id_add_animdata(id);
                        
@@ -1530,9 +1697,6 @@ void do_versions_ipos_to_animato(Main *main)
                                ob->ipo->id.us--;
                                ob->ipo= NULL;
                        }
-                       
-                       /* finally NLA */
-                       // XXX todo... for now, new NLA code not hooked up yet, so keep old stuff (but not for too long!)
                }
                
                /* check PoseChannels for constraints with local data */
@@ -1639,6 +1803,69 @@ void do_versions_ipos_to_animato(Main *main)
                }
        }
        
+       /* worlds */
+       for (id= main->world.first; id; id= id->next) {
+               World *wo= (World *)id;
+               
+               if (G.f & G_DEBUG) printf("\tconverting world %s \n", id->name+2);
+               
+               /* we're only interested in the IPO */
+               if (wo->ipo) {
+                       /* Add AnimData block */
+                       adt= BKE_id_add_animdata(id);
+                       
+                       /* Convert World data... */
+                       ipo_to_animdata(id, wo->ipo, NULL, NULL);
+                       wo->ipo->id.us--;
+                       wo->ipo= NULL;
+               }
+       }
+       
+       /* sequence strips */
+       for(scene = main->scene.first; scene; scene = scene->id.next) {
+               if(scene->ed && scene->ed->seqbasep) {
+                       Sequence * seq;
+                       
+                       for(seq = scene->ed->seqbasep->first; 
+                           seq; seq = seq->next) {
+                               short adrcode = SEQ_FAC1;
+                               
+                               if (G.f & G_DEBUG) 
+                                       printf("\tconverting sequence strip %s \n", seq->name+2);
+                               
+                               if (!seq->ipo || !seq->ipo->curve.first) {
+                                       seq->flag |= 
+                                               SEQ_USE_EFFECT_DEFAULT_FADE;
+                                       continue;
+                               }
+                               
+                               /* patch adrcode, so that we can map
+                                  to different DNA variables later 
+                                  (semi-hack (tm) )
+                               */
+                               switch(seq->type) {
+                               case SEQ_IMAGE:
+                               case SEQ_META:
+                               case SEQ_SCENE:
+                               case SEQ_MOVIE:
+                               case SEQ_COLOR:
+                                       adrcode = SEQ_FAC_OPACITY;
+                                       break;
+                               case SEQ_SPEED:
+                                       adrcode = SEQ_FAC_SPEED;
+                                       break;
+                               }
+                               ((IpoCurve*) seq->ipo->curve.first)
+                                       ->adrcode = adrcode;
+                               ipo_to_animdata((ID*) seq, seq->ipo,
+                                               NULL, NULL);
+                               seq->ipo->id.us--;
+                               seq->ipo = NULL;
+                       }
+               }
+       }
+
+
        /* textures */
        for (id= main->tex.first; id; id= id->next) {
                Tex *te= (Tex *)id;