Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Control time remap with spreadsheet

  • Bryan Woods

    March 22, 2014 at 12:55 am

    Well, I’ve tried adding it, multiplying it, dividing it, etc. and I’m not getting the right result. Some of the keyframes are moving, but the first one stays where it is. The second on are moved a certain amount, so there’s a large gap forming between the first and second keyframes. So i’m not sure how I should be adding the curTime variable into my var for t.

  • Bryan Woods

    March 24, 2014 at 5:39 pm

    Hi Dan, I still have not been successful including the curTime variable into “t”. I can’t figure out how I should add it in. The closest I’ve come is the code below. But this shifts all but the first keyframe ahead of the playhead, but not by any defined amount I can tell.

    {

    {

    //Set Undo Group
    app.beginUndoGroup("xsheet_remap");

    //Define project and active items
    var activeItem = app.project.activeItem;
    var selectedLayer = activeItem.selectedLayers[0];
    var curTime = activeItem.time;

    //testing variables
    var numFrames = 10 //parseFloat(prompt("Number of Frames"));
    var holdLength = 10 //parseFloat(prompt("Frame Hold Length"));

    //Meat and Potatoes

    if (! selectedLayer.timeRemapEnabled) selectedLayer.timeRemapEnabled = true;
    for (var f=1; f <= numFrames; f++){
    var t = f*holdLength*activeItem.frameDuration+curTime;
    selectedLayer.timeRemap.setValueAtTime(t,f*activeItem.frameDuration);
    selectedLayer.timeRemap.setInterpolationTypeAtKey(f, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.HOLD);

    }

    selectedLayer.timeRemap.removeKey(numFrames+1);
    app.endUndoGroup();

    }

    }

  • Dan Ebberts

    March 24, 2014 at 6:29 pm

    I’m not sure this is exactly what you’re after, but it should get you closer:


    function main(){
    //Set Undo Group
    app.beginUndoGroup("xsheet_remap");
    //Define project and active items
    var activeItem = app.project.activeItem;
    var selectedLayer = activeItem.selectedLayers[0];
    var curTime = activeItem.time;
    //testing variables
    var numFrames = 10 //parseFloat(prompt("Number of Frames"));
    var holdLength = 10 //parseFloat(prompt("Frame Hold Length"));
    //Meat and Potatoes
    if (! selectedLayer.timeRemapEnabled){
    selectedLayer.timeRemapEnabled = true;
    selectedLayer.timeRemap.removeKey(2);
    selectedLayer.timeRemap.setInterpolationTypeAtKey(1, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.HOLD);
    var n = 0;
    }else{
    var n = selectedLayer.timeRemap.numKeys;
    }
    var t;
    for (var f=0; f < numFrames; f++){
    t = f*holdLength*activeItem.frameDuration+curTime;
    selectedLayer.timeRemap.setValueAtTime(t,(f+n)*activeItem.frameDuration);
    selectedLayer.timeRemap.setInterpolationTypeAtKey(f+n+1, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.HOLD);
    }
    app.endUndoGroup();
    }
    main();

    Dan

  • Bryan Woods

    March 24, 2014 at 11:58 pm

    Thank you Dan, this works really well. I took some time to pull it apart to see what you had done. It looks like I was fairly close, but the order at which I was doing things was wrong. The process however for checking whether there were keyframes present before running the loop I had no clue how to start, so thank you for throwing that in. I think I understand the process, I just needed to see it in front of me to connect the dots.

    One thing I noticed is that if the layer has an inpoint that is different from its origin (like it was trimmed up to a certain point), a keyframe is still made at the beginning of the layer, regardless of its trimmed inpoint. Do you know why that is? I notice in the beginning of the process you delete the keyframes created by activating timeremap, so i’m not sure why a keyframe still gets made for a layer with a trimmed inpoint. But this is a minor issue. I just wanted your thoughts on why that might be happening.

    Thank you again for your time and patience troubleshooting this with me! You’re helping me and many weary traditional 2D animator out in a big way because of this script!

  • Dan Ebberts

    March 25, 2014 at 12:12 am

    The script does assume the layer is not trimmed. When in turns on time remapping, it removes the second keyframe, but not the first, because I think removing all keyframes would time remapping off (at least that’s how it works when you do it manually). I think that situation (layer trimmed) would throw the count off, so you might need some code in there to defend against that, if the layer being trimmed is a possibility. There are probably other “boundary conditions” that aren’t handled well (it was a hastily constructed example). Hopefully it will help get you where you want to go though.

    Dan

  • Bryan Woods

    March 25, 2014 at 7:36 pm

    Ah, one last question; something that just came up from testing with the animators. They would like the script to move the CTI the same number of frames indicated after the last keyframe+1. So if they put in hold each frame for 5 frames, when the script finishes, advance the CTI by 6 frames (5 frame hold, the 6th is the start of the next key frame where they would run the script again with different values). Do you know how to move just the CTI? This would just run after the loop finishes.

  • Dan Ebberts

    March 25, 2014 at 9:22 pm

    Here’s an example that moves the play head to 2 seconds:

    var activeItem = app.project.activeItem;
    activeItem.time = 2; // set CTI 2 seconds

    Dan

  • Bryan Woods

    March 25, 2014 at 10:31 pm

    Got it. I keep thinking the CTI is its own property that you have to move, but its actually represented by the active layer’s current time. Thanks for that.

    this seems to work well, after the loop:

    activeItem.time = (holdLength*activeItem.frameDuration)+t;

    and if I’m understanding correctly, we multiply the holdLength variable by the activeItem’s frame duration to convert to frames instead of AE interpreting it as seconds? And then adding the last value of t from the loop to it.

    **********
    Here is the final script for anyone who stumbles across this thread looking to do something similar:

    function main(){

    //Set Undo Group
    app.beginUndoGroup("xsheet_remap");

    //Define project and active items
    var activeItem = app.project.activeItem;
    var selectedLayer = activeItem.selectedLayers[0];
    var curTime = activeItem.time;

    //User Input
    var numFrames = parseFloat(prompt("Number of Frames"));
    var holdLength = parseFloat(prompt("Frame Hold Length"));

    //Meat and Potatoes
    if (! selectedLayer.timeRemapEnabled){
    selectedLayer.timeRemapEnabled = true;
    selectedLayer.timeRemap.removeKey(2);
    selectedLayer.timeRemap.setInterpolationTypeAtKey(1, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.HOLD);
    var nKeys = 0;
    }else{
    var nKeys = selectedLayer.timeRemap.numKeys;
    }
    var t;
    for (var f=0; f < numFrames; f++){ t = f*holdLength*activeItem.frameDuration+curTime; //t is the frame number read as frames and not seconds selectedLayer.timeRemap.setValueAtTime(t,(f+nKeys)*activeItem.frameDuration); selectedLayer.timeRemap.setInterpolationTypeAtKey(f+nKeys+1, KeyframeInterpolationType.LINEAR, KeyframeInterpolationType.HOLD); } activeItem.time = (holdLength*activeItem.frameDuration)+t; app.endUndoGroup(); } main();

Page 3 of 3

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy