Copy link to clipboard
Copied
Hi guys,
I'm looking for something very basic with expressions but can't seem to find it. I want to define a function and use that function inside ~100 or so layers. At the moment I'm typing a couple of lines of code inside each expression layer to drive the position of each layer which is insane of course. I just want to define one function (and define it only once):
function getPosition(null1,null2,offset){
...stuff..
return position
}
And in my comp, use that function everywhere to drive the position attribute for example:
getPosition("null5",null6",0)
Writing that function inside each expression is a bit daft of course but I can't seem to find a way to define such a function to use throughout my comp. Could anyone point me in the right direction? Thanks!
Copy link to clipboard
Copied
There is no such thing. Expressions always evaluate within the context of the property stream they are applied to. You can of course make them aware of other layers in a million ways, but you will have to write your own loops and use e.g. regular expressions and specific naming patterns to automate this/ smarten it up. Otherwise you will have to stick with explicit references every time.
Mylenium
Copy link to clipboard
Copied
Really...? I just can't imagine this to be the case, that would make the whole concept of expressions useless except for the most basic/trivial applications? If I were to apply a complex expression to a hundred layers or more, I would need to go back to all those layers in order to change anything? I want to use scripting to avoid that kind of manual nightmare...
This must be something to come up very often, maybe it's because I mainly do 3D animation where this sort of thing would be crazy 15 years ago let alone today. People actually write the same function inside each layer again and again..? It just goes against all my scripting sensibilities to accept that this is actually the case...
Thanks for your reply anyway, it's very hard to wrap my mind around this workflow, the idea of creating a function and actually using it more than once is so incredibly basic it hurts my brain I can't do it in AE..
Copy link to clipboard
Copied
I mainly do 3D animation where this sort of thing would be crazy 15 years ago let alone today.
Not really. You could not apply scene-level expressions in many programs back then and some didn't even have "local" expressions per attribute or per item, so I'm not sure what you're getting at. Of course AE is behind the times and should have unified its scripting and expression engines years ago, but that's just the way it is.
Mylenium
Copy link to clipboard
Copied
Well, 15 years ago this at least was trivial to do in lightwave LScript which I used at the time and is anything but known for its scripting capabilities.
To be a bit more constructive, in modo I often create "user channels" for my items and control items, I would be very happy to be able to do this in AE as well. A "user channel" is just any number, string, vector, color or matrix (any type of available channel to an object). This way I would be able to create a much cleaner interface to my comp. I would create a set of channels which are easy to set/change/keyframe without having to go into the expressions which use them. The channels I want to control through expressions use one global function which I can easily change and maintain and they use the custom channels I set on the object as well as those on a central control null.
Not trying to bash AE at all but some relatively minor changes can be made to make the use of expressions/scripting a lot easier and more powerful. I was just a bit surprised this part of AE is so far behind, let's hope some attention will be given to the expressions relatively soon.
Copy link to clipboard
Copied
LScript in Layout started out as a channel modifier, so I'm not sure if it's a correct analogy. Pixel filters, Scene Masters and other stuff were only added later and still were limited. The rest is a matter of endless debate. modo still has its own limitations and is only now in 901 getting better at integrating scripts, channel expressions and the schematic. Same is true for Cinema 4D and I would predict that even Python in LW has its limitations... It's an imperfect world. The only thing we can agree on is that AE certainly is at the end of any list when it comes to automation and scriptability, but you can't unmake design decisions from 20 years ago and the neglect of the expression engine easily.
Mylenium
Copy link to clipboard
Copied
If you want to apply an expression to a bunch of layers you can use Edit>Copy Expression Only, then select all the layers and paste. You can also create an animation preset and apply that to as many layers as you want with one click. You can point a bunch of layers at controllers on a single layer. You can use the layer number or index to offset properties by different amounts. For example by applying an expression based on the position of layer 1 and adding the index value times 20 to the position of layer 2 will be offset 20 pixels. You can make expressions respond to the in and out points of a layer or make them do something based on a layer marker or a layer marker on another layer.
I'm not exactly sure what you are trying to do but if you want to have two nulls in your composition and 100 layers and then make the offset between each layer a percentage of the distance between the nulls so the layers fan out like a deck of playing cards this is entirely possible by defining the distance between the two nulls and then using the layer number to control the percentage. This way you can write one expression, copy it or make it an animation preset, then properly name your nulls, then select the 100 layers you want to distribute and apply your animation preset to the group. For example if I were to name my nulls L null and R null and want to distribute the layers in X between the two nulls starting at the right null the expression would look something like this:
L = thisComp.layer("L null").position;
R = thisComp.layer("R null").position;
C = [width/2, height/2];
len = length(L, R);
numl = thisComp.numLayers -2;
tl = index - 2;
ofst = 1/numl;
np = tl * (len * ofst);
[np, value[1]]
Just save this as an animation preset or apply it to the first layer in the timeline below the two nulls and copy the expression only and paste and you'll get something like this:
If you explain in detail what you are trying to do then maybe we can help....
Copy link to clipboard
Copied
Here is another approach to the problem of distributing a bunch of layers uniformly between two master layers. If you set up your composition with the top and bottom layers as controllers or nulls then this expression will distribute all layers in-between evenly between the controllers. You name the top and bottom controller "left" and "right" then add your in-between layers between them and apply the animation presets as needed.
l = thisComp.layer("left");
r = thisComp.layer("right");
thisLayer = index - l.index;
numLayer = r.index - l.index - 1;
if (numLayer <= 1){
ofst = (r.position - l.position)/2;
ofst + l.position
}
if (numLayer > 1) {
ofstMlt = 1/(numLayer -1);
ofst = (r.position - l.position) * ofstMlt;
ofstAdj = (ofst * thisLayer);
l.position + ofstAdj - ofst;
}
Here is how this works. The first two lines define the left and right layers as variables so we can extract their properties without a lot of typing. The third line extracts the adjusted layer number of the layers we are going to be distributing. The numLayer line extracts the number of layers between the "left" and "right" layers.
Now there's an if statement the corrects a divide by zero error if there is only one layer and centers that single layer between the "left" and "right" layer.
The next if statement sets up the position calculations for the distributed layers by first creating a multiplier so the distance between the controlling left and right layers can be evenly divided. For example, if you have 3 layers you'll want the first and third layer to be at the same position as the controllers and the middle layer to be half way between them so you divide 1 by one less than the total number of layers and end up with .5. Now it's a simple matter of subtracting the position of the left layer from the position of the right layer and multiplying it by .5
Here's the tricky part, you have to adjust the offset of the copies by multiplying the distributed layer's number by the layer number. In the three layer example the offset or distance between the first layer and the left controller would be the offset of the first layer multiplied by 1, the second layer would be the position of the would be the offset multiplied by 2 and the third would be the offset multiplied by 3.
The last finally positions the layer by starting with the "left" layer's position and adding the offset adjustment minus the offset to the position of the left controller.
This expression works with 2D and 3D layers and automatically evenly distributes as many layers as you like between your left and right controllers. Here's an animation preset you can use with CS6 or later: Dropbox - distribute left right.ffx
Here's what the composition looks like:
Find more inspiration, events, and resources on the new Adobe Community
Explore Now