This is a tricky one. I'll try and explain!
I have an animation of a fly buzzing, the fly floats around via a wiggle expression that gets it's amplitude value from a slider in the parent comp. Easy so far. The issue is the slider's keyframe and the fly's corresponding animation only line up if the fly comp starts at 0 on the main timeline. If it starts at say, 2 seconds in, then whatever the key frame on the slider is, the fly comp isn't effected until 2 seconds later. I'll include a graphic to clarify. So I'm trying to write an expression that looks at where on the timeline the fly comp starts, and then offsets it's value from the slide by that amount of time. It's not working lol. Below is the code AND the diagram (I'm trying to create the bottom instance). Help!
As easy as accounting for the layer inPoint() in your time calculation and subtracting that value...
Ok - I'm punching above my weight class on all this stuff - how would I write it then?
Layer.sourceTime(t) will get you the time in the layer's source (here the nested comp) that corresponds to time t in the comp in which the expression is evaluated. This will be more reliable than doing the math yourself, since it will also account for time remapping, time stretch, reverse, etc.
Edit: I might have misunderstood how you have these comps nested. Are you trying to reference the time of the slider from an expression inside a comp nested in the same comp that the slider is in? If that is the case, my solution wouldn't help, since it is for the reverse situation, where you are trying to reference properties inside a nested comp in an expression that is in the containing comp.
So the slider is on the main timeline, and it's controlling an expression inside another comp on that timeline (that would be the nested comp).
Offsetting the time based on the start time is the simplest way to go for this application, I think.
This seems to do the trick:
var mainComp = comp("_VIRGIN-PLUS-MOCK-ENG"); var controlLayer = mainComp.layer("shakeControl 1"); var nestedLayer = mainComp.layer(thisComp.name); var amp = controlLayer.effect("Slider Control").slider.valueAtTime(time + nestedLayer.startTime); wiggle(2, amp)
This won't account for time stretch or reverse. It would be possible to do those with some interpolation, but time remap would be off the table due to its ability to map the same source time value to multiple different comp time values.
Very likely, that comp framerates should be also taken into account, as a precaution.
Time is measured in seconds here, so the frame rate shouldn't matter, unless I'm missing something. What would matter is if the nested comp was time stretched or remapped.
Ok - so I'm having some success here, but when adding another instance of the fly later in the timeline, it's messing up the timing on previous instances (presumably because it looks for the first fly-1 on the timeline).
Instead of referencing the fly-1 layer absolutely for nestedLayer, how would I reference it as the layer below the slider? Like what's a non absolute way to say shakeControl index-1
Does this make sense? That way the location of the effected later is always just the layer below the slider layer.
If what you are trying to do is nest the same comp an arbitrary number of times and you want to control properties inside each instance independently, essential properties is the way to do this. You won't be able to do this using expressions inside the nested comp, since without using essential properties all the nested comp layers refer back to the same comp.
There are a lot of ways you could set it up, but if the amplitude is the only thing you need to pass into each instance, set up a slider control somewhere inside your fly comp, reference it from your wiggle expression, and add the amplitude slider property to the essential graphics panel for the fly comp. Now the new slider property will show up under the essential properties group for any nested layer sourced to that comp. You can then either control the slider property directly on the nested layer (NOT in the EG panel, but rather on the timeline under the Essential Properties group of the layer) or you can set an expression on the slider master property to have it reference another slider control in your main comp.
If you do it this way, you'll want to remove the code offsetting the time from your fly comp. Essential Properties should translate the time between the main comp and each instance of the nested comp, but if it doesn't there should be a way to work around that, just not from inside the fly comp for the reasons I explained above.
I can't seem to find any information about Essential Properties? Is this the same as Essential Graphics? Maybe you can point me to some info about it. Thanks!
Yes, the Essential Graphics panel is where you designate Essential Properties (and yes, the nomenclature is a little confusing, even more so in previous versions of AE where Essential Properties were called Master Properties).
The quick version is if you open the nested comp in Essential Graphics (easiest way to do this is to right click on the comp in the project panel or on blank space in the layer list in the timeline window) then you can drag certain kinds of properties into the EG panel to designate them as Essential Properties for that comp. Once you've done this the property will show up in the Essentisl Properties property group for the nested comp layer. Modifying the value there will only modify that instance of the nested comp, leaving other instances unchanged. So you could have as many copies of your fly comp and each can have different values for that property, something that would be impossible to do by changing the value inside the nested comp.
This means that by setting up an amplitude slider inside the comp, adding it to the EG panel for the comp, and editing the slider value in the EP group, you can have as many fly layers as you like, all sourced from the same comp, but each with its own independent amplitude property animation. You don't even need to involve expressions if that is all you are trying to do.
I gave up on the expressions. This essential graphics thing looks like it's going to work perfectly. Thanks for all your help!
Awesome. Essential Properties can kind of revolutionize your approach to solving complex problems in AE once you start to get a feel for how they work.
But also don't give up on expressions in general. They can be really powerful even with very simple code, and are definitely worth learning how to use. And when you start combining them with other features like Essential Properties the possibilities can really make your head spin.
It's been spinning for 2 days now haha. But I totally see what you mean. Even just incorporating Essential Graphics is going to really simplify my workflow. It seems like such a simpler way to access deep properties without having to script your way into it.
Copy link to clipboard
Ok, first off - thank you all for your help. I have one last shot at this. I simplified the comps so that it was just a null with 2 sliders to control the fly floating and it's wings flapping. Fly Comp (parent, with the expression on it's position property because I wasn't sure where else to put it) -> body of fly (layer 1), wings of fly (layers 2 & 3). Here's the expression with comments describing my intention and what's not working. If I can't get somewhere with this I'll have to make a bunch of different fly comps etc and do it the dirty way. I've also included a screen of the expression if that's easier to read.
// this is the control null layer with sliders - always the null layer above a layer called 'Fly-1'. 'Fly-1' contains to layers which I later access by their index (1 &2) var controlLayer = thisComp.layer(thisLayer.index-1); // first slider on the null, intended to add position wiggle amp value to a comp INSIDE of this comp (remember this comp is 'fly-1') var pAmp = controlLayer.effect("shake").slider.value; // second slider on the null, intended to add rotation wiggle amp value to a comp INSIDE of this comp (remember this comp is 'fly-1') var rAmp = controlLayer.effect("flap").slider.value; // the layers I want to access INSIDE this comp ('fly-1') - when checked with a throw Error, this returns the correct layers inside this comp var theFly = source.layer(1) var theWings = source.layer(2) // problem: theFly is being wiggled, instead of layer 1, inside the fly theFly.position.wiggle(2,pAmp) // problem: theWings line throws a 'expression must be of dimension 3, not 1' error and causes the entire thing to fail theWings.transform.zRotation.wiggle(40,rAmp)