Advanced AfterEffects Question: Keyframe-able Dropdown?

Participant ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

Greetings all,

 

I'm looking to try to simplify something I typically do in AfterEffects by hand that's extremely tedious. Basically, I want to try to create a key-frame-able dropdown. Here's the scenario:

One of the motion graphic effects that I use for my podcast is movable talent windows (kind of like when you're watching the news and they do a splitscreen with two people in different places, and the windows change size and position). I've got all the window sizes and positions mapped out in an Excel spreadsheet for easy reference, but it gets tedious having to go through and change everything if I have to adjust any of said sizes or positions.

This may not even be possible, but what I'm looking for is a way to have a dropdown menu that specifies different layouts (i.e. "Splitscreen x2 Even," "Right Video x3 Even," and so on), and have all the other layers look at that and adjust their size and position accordingly. That way if I do have to change a size or a position, all I have to do is change the master (maybe have a set of sliders on some control layers, each with a name corresponding to a different layout). In my vision, the individual layers would be keyed to pull the value from the dropdown, and then pull slider values from a control layer corresponding to the name they see in the dropdown.

The question is, is there a way to key frame a dropdown selection to make it change, say over a span of a single second?

For an example of what I'm trying to simplify: https://youtu.be/UNAxqMYS8Jg?t=868

In order to do this I had to manually keyframe the sizes and positions for three windows, mine and my guest's, plus the large video window as it animates in from its off-camera position. This can be a little complicated when I just have one guest, but it's an even bigger challenge when I have multiple guests.

TOPICS
Expressions , How to , Performance , Scripting

Views

392

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Adobe Community Professional , Jul 15, 2022 Jul 15, 2022

OK. I haven't tested this, but I think this is the edit necessary for my previous expression:

L = thisComp.layer("Dropdown Menu");
menu = L.effect("Dropdown Menu Control")("Menu");
moveTime = 1;
val = value;
if (menu.numKeys > 0){
  n = menu.nearestKey(time).index;
  if (time < menu.key(n).time) n--;
  if (n < 2){
    L1name = L.text.sourceText.valueAtTime(menu.key(1).time);
    val = thisComp.layer(L1name).effect(name + " Position X")("Slider").value;
  }else{
    t = menu.key(n).time;
    L1na
...

Likes

Translate

Translate
Adobe Community Professional ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

The values must be present in the child expressions themselves and then be used accordingly. Of course once they are it could easily be that you use a dropdown to trigger them, including keyframing the value and interpolating using something like a linear(time, value A, value B, start time, start time + delay), but none of this is going to be trivial as you constantly need to check what the current time is, which keyframe is current, what layout and so on. Lots of valueAtTime() and nearestKey() stuff. The change in the dropdown itself is always immediate, since it only has hold keyframes, anyway. that's the easy part. The hard part is the rest.

 

Mylenium

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

quote

The values must be present in the child expressions themselves and then be used accordingly.

By @Mylenium

In this scenario I don't think that's correct. What I'm looking to do is this:

> layer: "Shape Dynamics," which will have a dropdown with the various layout options

> individual layers with the names of each layout that appears in the dropdown, each with a set of sliders set to values appropriate for that layout

> the layers for the individual windows I'm working with, each with a set of sliders

 

So let's say from the dropdown I select a layout named "Splitscreen x2 Even." There will be a layer with that name.

 

The expressions on the child layers will be setup something like this: thisLayer.transform.xPosition = thisComp.layer(layer("Shape Dynamics".sourceText).slider("X Position")

In other words, which layer the various windows will pull their values from will change depending on what the dropdown value is. That means I won't have to set up all the values in every slider, just point them all to the wherever the dropdown value will be reflected (I'm guessing that'll be sourceText), but what it'll do is pull the layer name from the source text value.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

You can do that, but why make your life even more complicated by introducing string processing into the equation - literally? Doesn't really make a lot of sense, since you would need to fetch the paths of the effect controls and then have extra code that constructs the correct reference. I think you're underestimating how complex this could get. I would definitely simply set up a dedicated "Controller" layer in the parent comp and glean all values from there, not mess around with scattering stuff on individual layers and pre-comps. You have to keep in mind that AE's expressiosn still work based on absolute references and creating cascading setups based on pseudo-realtive references such as you propose is in itself already prone to errors and potentially breaking down just by accidentally having a wrong value somewhere or renaming a layer or effect.

 

Mylenium

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

I know exactly what I'm doing and with my workflow, this is precisely the way to do it. My entire workflow is based around "change it once, propagate everywhere," and what you're describing complicates my life a lot more than how I want to do it. Your way, I have to change every value in every single layer if I want to make a change, which defeats the entire purpose of trying to set up a master layer in the first place. My way, I have to work harder with the initial setup, but down the line anytime I need to make a change it's a snap.

 

To put my workflow into perspective, I've developed an entire motion graphics package, and it's all in a single project file. The colors, fonts, sizes, everything is parented to an "appearance template" comp, and animations in the individual comps are all parented to "shape dynamics" layers that operate based on math. I had to work hard to get everything set up the way I want it, but now when I need to make a change I don't have to go through fifty different project files and make the same change in each one. I just make it once, and it propagates everywhere. At worst I have to re-export some standalone MOVs but that's no problem at all.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

It sounds interesting, but a little confusing. Besides knowing which layout is currently selected, each layer also needs to know the template layer to which it is assigned in the scenario. For example, say you have three layers participating, one of the layers needs to know to be offscreen in a 2-layer layout. How do you see that working?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

In my mind, the template layer for each layout will specify an X and Y coordinate for each window, and for any window that'll need to be offscreened for that specific layout, the X position will simply be out of frame. (So for instance, if I have six windows total but only three of them are needed onscreen, the other three will have positions that are out of frame.)

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

In watching your YouTube example, I notice that a layer's aspect ratio may change, depending on the layout (e.g full-screen vs 2@side-by-side). Would you accomplish this with masking to crop off the left and right edges? So you'd need expressions for positon, scale, and mask path?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

quoteWould you accomplish this with masking to crop off the left and right edges? So you'd need expressions for positon, scale, and mask path?

By @Dan Ebberts

It would probably be easier to share a sample file than it would be to try to explain it. What I've done is set up each individual input so that it has its own sliders to control frame size. Then, in another comp, I've got another set of rectangles parented to them to match their size and position, with an adjustment layer above that in the main comp. That way, when anything moves in the main composition, its mask moves with it, and the contents of each talent window are configured to resize dynamically based on frame height. (The exception is the video window, which stays at a 16:9 aspect ratio at all times based on the frame height.)

The AfterEffects file that I've attached is the same one from my YouTube example, but I've pulled out all the dependencies and replaced them with solid color layers so you can use them without getting nagged by that pesky unlinked-file dialog.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

That's a pretty complex setup. It would take too long for me to wrap my brain around all the interconnections, but in general, I think it's possible to do what you want. I'd be happy to try and answer any specific expressions questions you might have. It might be better to start with a really simple project file and tackle one particular concept at a time. 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

This AE file is the product of a lot of time Googling and combining expressions and techniques. This file does everything I need it to do...but like you see, it's all done by hand. (But now you see why I'm trying to make it easier.)

There's an Excel sheet that goes along with this that has all the frame positions and sizes, and animating it literally involves manually setting keyframes on every slider of every layer when I want things to move.

The only things that matter are the ones in "Animated Multi-View New"--everything elsewhere is parented to things in that comp. And you can ignore everything on the "Master Size Sliders" layer except the frame thickness.

If you look at the pre-comps in "Animated Multi-View," each one has a bunch of sliders on it, and those sliders control the sizew of the frame and the position. "Scale Adjust" and "X/Y Offset" are manual controls for if I need to make an adjustment to the contents of a frame--you can ignore those too, along with anything below the adjustment layer. Everything is parented to the pre-comps that you see ("Camera Input Talent 1," "Camera Input Talent 2," and so forth), and those pre-comps are the only things that I need to animate.

 

The only things I'm looking to animate are "Frame Width" and "Frame Height," along with the X and Y transform for each of the pre-comps. I'm not even sure where to start with solving this one; I've never done a dropdown list before and I don't know how to even start trying to keyframe it.

Dan, if you can help me with the basics of building a dropdown list and keyframing it so that it can have different values at different points along the timeline, I think I can handle the rest. What do you think?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 13, 2022 Jul 13, 2022

Copy link to clipboard

Copied

This is a simple example of a position expression where a layer has 3 possible positions selected by a drop down menu. The menu choices are "1-Up", "2-Up", and "3-Up". The corresponding positions are included in the expression, and are: [960,540], [480,540], and [320,270]. The amount of time to move from one position to another (moveTime, 1 second in this example) is also defined in the expression. Nothing happens until the second keyframe of the dropdown, when the layer slides from the position defined by the first keyframe to the postion defined by the second keyframe. Note that this example is just for postion and doesn't account for scale, but the concept for a scale expression would be pretty much the same.

 

menu = effect("Dropdown Menu Control")("Menu");
positions = [[960,540],[480,540],[320,270]]; // positions for 1-Up, 2-Up, and 3-Up
moveTime = 1;
val = value;
if (menu.numKeys > 0){
  n = menu.nearestKey(time).index;
  if (time < menu.key(n).time) n--;
  if (n < 2){
    idx1 = menu.key(1).value - 1;
    val = positions[idx1];
  }else{
    t = menu.key(n).time;
    idx1 = menu.key(n-1).value - 1;
    v1 = positions[idx1];
    idx2 = menu.key(n).value - 1
    v2 = positions[idx2];
    val = linear(time,t,t + moveTime,v1,v2);
  }
}
val

 

. The expression assumes the dropdown menu control is on the layer itself.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

This sounds very close to what I'm looking for, but could we tweak it a little? (Full disclosure, I'm not a programmer so I know I'm about to ask some dumb questions.)

Instead of encoding positions into the expression itself, I want to set up the expression to pull values from specific layers. In other words, if the dropdown is set to "Splitscreen x2 Even Talent 1 and Talent 3," I want whatever layer this is on to pull its X and Y position values from the sliders on a layer with that name, and then if I change the dropdown to "Talent 1 Right Video," to change the layer it pulls from. Likewise for the slider values for frame width and height.

Basically, if we could change the positions included within the expression to something like:

"transform.xPosition = thisComp.layer(DropdownMenuValue).slider.xPosition"

but keep the syntax that tells it to move when the keyframe changes, that'd be perfect. All I'd have to do from that point is change which slider to pull from.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

Ah. With a dropdown menu control the expression doesn't have access to the text of the menu item, just its index in the list (the top item is 1, etc.). So the expression would either have to have an embedded list of layer names that correspond to each menu index, or maybe it would be better to use a layer control, which returns a reference to the layer itself (although a layer control will include all the layers in the comp).

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

Could we work around that by instead of having it pull the sourceText value itself, rather than the effect?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

OK, you lost me. sourceText value from where?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

Sorry, that wasn't the best explanation. I'm more a visual guy anyway, I sketched out a quick illustration of what I was trying to say.

/As best I understand how the dropdown menu effect works, if you apply it to a text layer (in this flow diagram the DropDownLayer is a text layer), you can set an expression to change the SourceText value based on what the selection is from the dropdown. What I'm thinking is if I set up a master layer that has the dropdown on it and then set up the SourceText layer, I can have the SourceText value list the name of the layer that the others need to pull from.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

So the list of layer names corresponding to the dropdown entries is embedded in a source text expression on the text layer hosting the dropdown menu control? Or are the layer names, say, embedded in the source text itself? In the frist case, to make a change, you have to edit the expession. In the second case, you have to turn the expression off, edit the text in the text layer, and turn the expression back on. Or is it something else entirely?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

This is the expression I came across that does what I described (modified with a few concept names):

var x = effect("Dropdown Menu Control")("Menu").value;

if ( x === 1 ) {
"Splitscreen x2 Even";
} else if ( x === 2 ) {
"Splitscreen x5 Even";

} else if ( x === 3 ) {
"Right Video Talent 1";

}

I tested this out in AfterEffects and it appears to automatically change the SourceText value to match whatever list entry in the dropdown is selected. In this case it'd be the first scenario you describe--I'd have to embed the list of layer names in the expression.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

Or, I guess I should put it another way--since it looks like the keyframe value for the sourceText layer will only do a Hold interpolate, maybe I should ask: what expression would let the child layers detect the keyframe change, pull the value from the new source layer, and as you described with your previous expression, take a full second to move everything into the new positions?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

I haven't tested this at all, but I think it should be close. It assumes the text layer's name is "Dropdown Menu":

L = thisComp.layer("Dropdown Menu");
menu = L.effect("Dropdown Menu Control")("Menu");
moveTime = 1;
val = value;
if (menu.numKeys > 0){
  n = menu.nearestKey(time).index;
  if (time < menu.key(n).time) n--;
  if (n < 2){
    L1name = L.text.sourceText.valueAtTime(menu.key(1).time);
    val = thisComp.layer(L1name).position;
  }else{
    t = menu.key(n).time;
    L1name = L.text.sourceText.valueAtTime(menu.key(n-1).time);
    v1 = thisComp.layer(L1name).position;
    L2name = L.text.sourceText.valueAtTime(menu.key(n).time);
    v2 = thisComp.layer(L2name).position;
    val = linear(time,t,t + moveTime,v1,v2);
  }
}
val

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

I will give it a try and report back! Might take a bit to set it up given all the moving pieces (if you'll pardon the pun) to this. Either way I greatly appreciate the assist!

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

Slight hiccup: I can't seem to combine values the way I thought I could. Here's my modified expression:

L = thisComp.layer("Dropdown Menu");
menu = L.effect("Dropdown Menu Control")("Menu");
moveTime = 1;
temp1 = thisComp.layer("Dropdown Menu").text.sourceText;
temp2 = thisLayer.name + " Position X";
val = thisComp.layer(temp1).effect(temp2 + " Position X")("Slider");
if (menu.numKeys > 0){
  n = menu.nearestKey(time).index;
  if (time < menu.key(n).time) n--;
  if (n < 2){
    L1name = L.text.sourceText.valueAtTime(menu.key(1).time);
    val = thisComp.layer(L1name).position;
  }else{
    t = menu.key(n).time;
    L1name = L.text.sourceText.valueAtTime(menu.key(n-1).time);
    v1 = thisComp.layer(L1name).position;
    L2name = L.text.sourceText.valueAtTime(menu.key(n).time);
    v2 = thisComp.layer(L2name).position;
    val = linear(time,t,t + moveTime,v1,v2);
  }
}
val

Trouble is it's giving me an error: "Layer index -2147483648 out of range."

The trouble seems to start with the variable temp1. I've tested the expressions for both temp1 and temp2 on their own layers and they work exactly the way they're supposed to, but for whatever reason AfterEffects doesn't seem happy.

So temp1 is pulling the value from the dropdown menu, which tells our expression what layer name to look for. Then, temp2 pulls the name of the layer it's actually being applied to and then adds the suffix " Position X" to it (for instance "Camera Input Talent 1," so what AE should be seeing is "Camera Input Talent 1 Position X"), which matches the name of a slider on the layer temp1 provided, which should tell AfterEffects what value to pull. It works when I pickwhip it directly, but not when I try to do it this way.

I can pickwhip these individually if I need to since that works, but if AE can put the pieces together from contextual references it would make it easier to copy and paste. Any idea what I might be doing wrong?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

Strike my last, using the pickwhip does work but it hard-links the "value" variable to a single layer, which isn't what I was looking for. That leaves us figuring out why I'm getting an out-of-range error.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jul 14, 2022 Jul 14, 2022

Copy link to clipboard

Copied

I have finally tested the last expression I posted, and I can confirm that it does work the way I intended. I'm not sure what's going on with your modifications though.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines