The Expressions Thread

MotionIdea said

Hey fellows, i have a question, is it possible to link the font and size of text layers with expressions ? Thanks!

Nope, unfortunately these are not accessible through expressions.

I want to share my experience from today:

I have this expression:

c =comp("_final 1920x1080").layer(ā€œcontrolsā€).effect(ā€œdepth of fieldā€)(ā€œCheckboxā€)
if (c==0){
opacity=0
}else if (c==1){
opacity=100}


And it can’t be translated with expression universalizer script. When I rename control ā€œdepth of fieldā€, everything works fine.

Ok, problem is solved and I will know next time, but I’m wondering why expression universalizer stopped to work because of ā€œdepth of fieldā€ in expression?

All what script need to do with this expression is to translate ā€œCheckboxā€ to ā€œADBE Checkbox Control-0001ā€.

dorde said

I want to share my experience from today:

I have this expression:

c =comp(ā€œ_final 1920x1080ā€).layer(ā€œcontrolsā€).effect(ā€œdepth of fieldā€)(ā€œCheckboxā€)
if (c==0){
opacity=0
}else if (c==1){
opacity=100}


And it can’t be translated with expression universalizer script. When I rename control ā€œdepth of fieldā€, everything works fine.

Ok, problem is solved and I will know next time, but I’m wondering why expression universalizer stopped to work because of ā€œdepth of fieldā€ in expression?

All what script need to do with this expression is to translate ā€œCheckboxā€ to ā€œADBE Checkbox Control-0001ā€.

I had that problem several times. It always appears when you rename effects to a custom name, and that custom name is the same as any other parameter inside after effects. For example, ā€œoffsetā€ does not work.
I guess if you name it ā€œcurvesā€ it would give an error, too.
So always use specific names.

By the way, in the comp where this problematic expression was, there is a new null created from Expression Universalizer. I guess that is used as a helper while it does its process, but doesn’t get deleted as it is stuck at a certain point in the code.

So if you haven’t already, you may want to delete that null to keep your project clean from unnecessary stuff.

Creattive said

So always use specific names.

Good to know. Thanks.

I also noticed temporary null when script stuck. Anyway I always before the final save double check if there is something to delete. I like when my projects are clean.
:slight_smile:

can anyone tell me how to use layer controller in expression control to select a one layer between few layers

video tutorial is better!!

CreativeZ said

video tutorial is better!!

So demanding! :wink:

felt_tips said
CreativeZ said

video tutorial is better!!

So demanding! :wink:

Thank You!!

felt_tips said
CreativeZ said

video tutorial is better!!

So demanding! :wink:

Finally something to do with this Layer control!! Awesome tut, thanks Felt! :slight_smile:

felipefbfx said

Hi, I’m trying to use valueAtTime on the scale propriety and It doesn’t work

delay =5; 
d = thisComp.frameDuration*(index-1);
a =  thisComp.layer(1).transform.scale.valueAtTime(time - d);
[a,a]

I don’t get to put it to work… some help please.

You’ve got the principle right, but I would reconsider using the layer index as your delay… and if you’re posting here (and actually in general) it’s a good idea to use more descriptive variable names. It’ll give us a clue as to what you’re trying to do… and it’ll help you understand your own code too.

So instead of using index, start by making an effect on the layer - An expression Slider Control - and let’s call it Delay Offset in Frames. You can set the value manually on each layer. A reference to this effect will replace your use of index in your code as the multiplier for your delay (well actually I’m going to use an additive delay offset - it’s probably rather more useful and predictable, and I’m guessing this is what you want). The problem with index, is that if you start adding layers, the layer index changes, and that can give unpredictable results, particularly if you’re using it as a multiplier. Sure, index is nice and quick to use, but I’d avoid it if I were you.

The other really weird thing about your code is that you set up the variable delay at the start and then never use it. ??? :-o
How about setting up an overall controller layer with a delay slider on it? Let’s do that… make a layer called Controller and add a Slider Control and call it Delay in Frames. This will act as an overall delay.

The final thing is that the sampling of the value of layer 1’s scale will give you an array of 2 or 3, depending on whether the layer is 3D or not. In your code, you take that value and put it in an array. So you’re putting an array inside an array. Assuming that layer 1 is 2D and has a scale of [70,70], the value you’re handing to scale from the expression (and the value of your variable a) will be
[[70,70], [70,70]]
…an array of arrays. No wonder After Effects is confused!

Here’s how it should look…

myDelayOffset = effect("Delay Offset in Frames")(1).value*thisComp.frameDuration;
masterDelay = thisComp.layer("Controller").effect("Delay in Frames")(1).value*thisComp.frameDuration;
thisComp.layer(1).scale.valueAtTime(time-masterDelay-myDelayOffset);

Other things you could do is have a central delay multiplier, stretching the whole delay… or you could have the various layers respond to their offset numbers in a non-linear way… i.e. cubic, quadratic or eased.

Here’s the code with a multiplier too…

myDelayOffset = effect("Delay Offset in Frames")(1).value*thisComp.frameDuration;
masterDelayOffset = thisComp.layer("Controller").effect("Delay in Frames")(1).value*thisComp.frameDuration;
masterDelayMult = thisComp.layer("Controller").effect("Delay Stretch %")(1).value/100;
thisComp.layer(1).scale.valueAtTime(time-masterDelayOffset- masterDelayMult*myDelayOffset);

You have to explain a bit better what you want to achieve.

felipefbfx said

Dear friend, I’m really thankful for ur help! :wink: but I’ve tried like this…

myDelayOffset = thisComp.layer("Controller").effect("DelayOffset")("Slider")*thisComp.frameDuration;
masterDelay = thisComp.layer("Controller").effect("Delay in Frames").value*thisComp.frameDuration;
thisComp.layer(1).scale.valueAtTime(time-masterDelay-myDelayOffset);

remaning not work!;
this expression ā€œvalueAtTimeā€ with position, rotation works very well, I don’t know why with the postion it really doesn’t work. What I do ?
PS: I really like to learn it, and I want to put it to work.:wink: thank u so much again!

It does work. I just tested it.

Since you have added the Controller layer (probably at the top) is it possible that the layer(1) that your code refers to is no longer the layer you want to follow, but the controller layer?

Here’s a video tutorial…

Hey guy, today I watcehd the video that you’ve teached a animation with cameras and targets…
So nice, but I’m trying and trying to understand what expression ā€œtoWorldā€ and fromWorld means…
Some people has tried to explain to me but it has messed even more…
Beats me, Could you explain to me what it menas? I’ve read adobe manual’s of expressions too but this is not enough sometimes.Thank you.

felipefbfx said

Hey guy, today I watcehd the video that you’ve teached a animation with cameras and targets…
So nice, but I’m trying and trying to understand what expression ā€œtoWorldā€ and fromWorld means…
Some people has tried to explain to me but it has messed even more…
Beats me, Could you explain to me what it menas? I’ve read adobe manual’s of expressions too but this is not enough sometimes.Thank you.

There’s a whole in-depth series on this a couple of years ago. It’s here…

If you want to skip the start (I recommend you watch the whole thing in order) Part 3 is a 17 minute visual demonstration of what I explain above…

DOGmotion said

Or the whole of that last bit in one line…

clamp(Math.round(value), min = 1, max = 5);

Note: You don’t need the min = and max=, but it can be helpful in remembering which arguments are which.

(-f.)

You are awesome! Thanks, my attempts at clamping and rounding at the same time were just not happening.

yeaboy said
DOGmotion said

Or the whole of that last bit in one line…

clamp(Math.round(value), min = 1, max = 5);

Note: You don’t need the min = and max=, but it can be helpful in remembering which arguments are which.

(-f.)

You are awesome! Thanks, my attempts at clamping and rounding at the same time were just not happening.

Good to hear the expression thread is helping out! :slight_smile:

I need a little help.
I have a master null and then 7 more null objects
The 7 null objects are equally offset from the master null in x axis.
The distribution between them is controlled by a slider control
Now i want to control their X axis position by 7 different slides so that they are equally distributed in x axis but the distribution in y axis could be controlled manually by 7 different slider controls.

when the value is set to zero in y axis of all the 7 sliders, you should only see a straight line in x axis.

Something like a line graph thing. where you set different points in y axis but distance is equal in x axis.

How can i do that?

bilalmarri said

I need a little help.
I have a master null and then 7 more null objects
The 7 null objects are equally offset from the master null in x axis.
The distribution between them is controlled by a slider control
Now i want to control their X axis position by 7 different slides so that they are equally distributed in x axis but the distribution in y axis could be controlled manually by 7 different slider controls.

when the value is set to zero in y axis of all the 7 sliders, you should only see a straight line in x axis.

Something like a line graph thing. where you set different points in y axis but distance is equal in x axis.

How can i do that?

A quick question first of all… Why would you set up 7 expression sliders each of which controls the y position of a single layer? Isn’t it easier just to manually adjust the y position?

Anyway…

//myID is an integer between 0 and numLayers-1
//spacing is the horizontal space between layers
//myYVal is the y value you want to give it
myXPos = thisComp.layer("null layer").effect("spacing").value * thisLayer.effect("myID");
myYPos = thisLayer.effect("myYVal");

value + [myXPos, myYPos];
//the value+ bit allows you to add an offset by altering the pre-expression value of position.

sorry i forget to mention it.
I have 7 layers infact. I just want make a control panel for them so that the end user could also be able to control it by simply changing the values of each layer from the controller.

bilalmarri said

sorry i forget to mention it.
I have 7 layers infact. I just want make a control panel for them so that the end user could also be able to control it by simply changing the values of each layer from the controller.

Then as above, but change this line to link to one of the effects on your controller null

myYPos = thisLayer.effect("myYVal");

becomes

myYPos = thisComp.layer("null").effect("value 1").value;

or you could even use

myID=thisLayer.effect("myID");
myYPos = thisComp.layer("null").effect("value " + myID.toString()).value;

But you need to make sure you get your naming right.

Thanks

I will try and will respond here :slight_smile: