-
-
Save gfxhacks/058618bf728accb85c1c9895bdb3ab1c to your computer and use it in GitHub Desktop.
// Usage: In AE 2020 (17.0) or above, create a new composition or open an existing one. Then choose File -> Scripts -> Run Script File... to launch this script. | |
/* | |
Title: timer_rig.jsx | |
Author: gfxhacks.com | |
Description: Create a new Timer object in the active After Effects composition. | |
More Info: https://gfxhacks.com/timer-rig-in-after-effects-using-expressions | |
*/ | |
app.beginUndoGroup("Create Timer"); | |
// define timer expression | |
exp = '// get Timer properties\nrate = clamp(effect("Rate")("Slider"), 0, 100);\nh = effect("Start Time - Hours")("Slider");\nm = effect("Start Time - Minutes")("Slider");\ns = effect("Start Time - Seconds")("Slider");\nc = effect("Countdown")("Checkbox").value;\nms = effect("Milliseconds")("Checkbox").value;\nformat = effect("Time Format")("Menu").value;\nn = effect("Negative Time")("Checkbox").value;\n// convert Start Times to seconds and sum.\nst = h*3600 + m*60 + s;\n// count up or count down based on checkbox value\nt = c ? st - rate*(time - inPoint) : st + rate*(time - inPoint);\n// initialize time as [HH:MM:SS:MSS]\nf = t <= 0 ? [00, 00, 00, 000] : [t/3600, (t%3600)/60, t%60, t.toFixed(3).substr(-3)];\n// Round to whole numbers and add zero padding\nfor (i in f){ f[i] = String(Math.floor(f[i])).padStart(i>2?3:2, "0") }\n// remove ms if checkbox is off\nif(!ms) f.pop();\n// change Timer display based on chosen format\nswitch (format){\n // HH:MM:SS\n case 1:\n t = f.join(":");\n break;\n // MM:SS\n case 2:\n t = f.slice(1).join(":");\n break;\n // SS\n case 3:\n t = f.slice(2).join(":");\n}\n// prepend minus symbol to time if checkbox is on\nn ? "-" + t : t;'; | |
// define expression control effects | |
effects = [ | |
{ | |
"type": "Checkbox Control", | |
"name": "Countdown", | |
"value": "1" | |
}, | |
{ | |
"type": "Dropdown Menu Control", | |
"name": "Time Format", | |
"value": ["HH:MM:SS", "MM:SS", "SS"] | |
}, | |
{ | |
"type": "Slider Control", | |
"name": "Rate", | |
"value": "1" | |
}, | |
{ | |
"type": "Slider Control", | |
"name": "Start Time - Hours", | |
"value": "24" | |
}, | |
{ | |
"type": "Slider Control", | |
"name": "Start Time - Minutes", | |
"value": "0" | |
}, | |
{ | |
"type": "Slider Control", | |
"name": "Start Time - Seconds", | |
"value": "0" | |
}, | |
{ | |
"type": "Checkbox Control", | |
"name": "Milliseconds", | |
"value": "1" | |
}, | |
{ | |
"type": "Checkbox Control", | |
"name": "Negative Time", | |
"value": "0" | |
}, | |
] | |
try { | |
// get current comp | |
c = app.project.activeItem; | |
// add new text layer | |
t = c.layers.addText(); | |
// rename text layer | |
t.name = "Timer"; | |
try { | |
for (i in effects) { | |
// get current expression control effect | |
e = effects[i]; | |
// add current expression control effect | |
s = t.property('Effects').addProperty(e.type); | |
// get current expression control effect index | |
id = s.propertyIndex; | |
// check if effect is of type dropdown, then set values. | |
// Dropdown Menu effect (new in 2020) is the only effect that requires to set values with: setPropertyParameters | |
s.property(1).isDropdownEffect ? s.property(1).setPropertyParameters(e.value) : s.property(1).setValue(e.value); | |
// rename effect using index reference - previous reference is lost when setting values. | |
t.property('Effects')(id).name = e.name; | |
} | |
// add timer expression to source text | |
t.text.sourceText.expression = exp; | |
} catch (e) { | |
alert('Script Failed!\nDropdown Menu control not found. Make sure you are running AE 2020 (17.0) or above.') | |
} | |
} catch (e) { | |
alert('Create or open a composition first!'); | |
} | |
// add expression control effects to text layer | |
app.endUndoGroup(); |
Hey, just duplicate each Start Time
slider and rename to End Time
- make sure to set the total end time to be greater than the total start time. Try this code - the timer should stop when the end time is reached (enabled only when counting up).
// get Timer properties
rate = clamp(effect("Rate")("Slider"), 0, 100);
h = effect("Start Time - Hours")("Slider");
eh = effect("End Time - Hours")("Slider");
m = effect("Start Time - Minutes")("Slider");
em = effect("End Time - Minutes")("Slider");
s = effect("Start Time - Seconds")("Slider");
es = effect("End Time - Seconds")("Slider");
c = effect("Countdown")("Checkbox").value;
ms = effect("Milliseconds")("Checkbox").value;
format = effect("Time Format")("Menu").value;
n = effect("Negative Time")("Checkbox").value;
// convert Start Times to seconds and sum.
st = h*3600 + m*60 + s;
// convert End Times to seconds and sum.
et = eh*3600 + em*60 + es;
// count up or count down based on checkbox value
t = c ? st - rate*(time - inPoint) : st + rate*(time - inPoint);
// if counting up and count is greater than end time, stop counting (return end time)
t = !c && (t > et) ? et : t;
// initialize time as [HH:MM:SS:MSS]
f = t <= 0 ? [00, 00, 00, 000] : [t/3600, (t%3600)/60, t%60, t.toFixed(3).substr(-3)];
// Round to whole numbers and add zero padding
for (i in f){ f[i] = String(Math.floor(f[i])).padStart(i>2?3:2, "0") }
// remove ms if checkbox is off
if(!ms) f.pop();
// change Timer display based on chosen format
switch (format){
// HH:MM:SS
case 1:
t = f.join(":");
break;
// MM:SS
case 2:
t = f.slice(1).join(":");
break;
// SS
case 3:
t = f.slice(2).join(":");
}
// prepend minus symbol to time if checkbox is on
n ? "-" + t : t;
For your reference, this is the added code:
eh = effect("End Time - Hours")("Slider");
em = effect("End Time - Minutes")("Slider");
es = effect("End Time - Seconds")("Slider");
// convert End Times to seconds and sum.
et = eh*3600 + em*60 + es;
// if counting up and count is greater than end time, stop counting (return end time)
t = !c && (t > et) ? et : t;
Lmk if this is what you were looking for 😊
Excuse my language but HOLYSH*T, YOU ROCK!!! It's working great for me! Is there somewhere I can donate to you for helping me with this?
No worries 🤗 happy to help!
Hello, I tried to run the script and I got an error "Dropdown Menu Control" not found. I am running AE v17.1.4
I also have an issue regarding the script, I am getting "Error: String().padStart is not a function".
Any help would be appreciated!
Hey, make sure to have the Expression Engine in the Project Settings set to Javascript
. You can find out more about the differences here: https://helpx.adobe.com/after-effects/user-guide.html/after-effects/using/legacy-and-extend-script-engine.ug.html
Unless working with older expressions, you may want to always use the more modern Javascript engine. Hope this solves the issue..
Hey, make sure to have the Expression Engine in the Project Settings set to
Javascript
. You can find out more about the differences here: https://helpx.adobe.com/after-effects/user-guide.html/after-effects/using/legacy-and-extend-script-engine.ug.html
Unless working with older expressions, you may want to always use the more modern Javascript engine. Hope this solves the issue..
Alright that worked! Sorry, still new to AE scripting.
There is still that bug regarding the Dropdown Menu control but the script still works... not sure why this is giving me an error!
Cool 🙌 - Regarding the dropdown not found issue, do you see an error at the bottom of your composition panel? Similar to this: Screen Shot 2021-01-26 at 18 47 25
What line does it mention the problem is at?
No errors. That is the odd thing. it works fine but the popup message appears after running the script.
I see are you getting this error? Script Failed! Dropdown Menu control not found. Make sure you are running AE 2020 (17.0) or above.
If so there might be a bug with the script running on your version of AE. You can try upgrading.. Otherwise try setting up the controls manually, following this guide: https://gfxhacks.com/timer-rig-in-after-effects-using-expressions/#quick-reference
Hi. This is such a cool script! It beats what I've used in the past by far.
I have a question about Zero Padding.
What could changes could I make to make it so that the zero padding in the HH part of an HH:MM:SS clock does not appear but still does in the MM and SS parts?
Heya,
You can chain a second conditional within the padstart method: .padStart(i>2?3:i<1?1:2, "0")
Not very pretty but works nonetheless! - basically considering HH:MM:SS:MSS positioned in the array at [0, 1, 2, 3], if the current item's position is greater than 2 (so the MSS at pos 3), pad with 3 zeros. If the position is less than 1 (so the HH at pos 0), pad with 1 zero. MM and SS (at pos 1 and 2 respectively) will pad with 2. Hope it helps :)
Thank you so much!! This is exactly what I was looking for.
Hi Dan, Thanks so much for this! I was playing around and noticed when I switch from counting down to counting up, it starts at the number I chose for the countdown. What code can I add-in for an End Time for the counting up? ie. starting at 0:00 and stopping at the End Time 0:20.