Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Re-using expression-generated values to input into other expressions (read-out)

Participant ,
Jun 12, 2014 Jun 12, 2014

Hi there everyone. I was wondering if there is a way to 'capture' expression generated values and either buffer these values or re-using them directly in other expressions. I am trying to track rotations of parented layers, which are generated from the DuDuf IK expressions. Getting the rotation through a pick-whip will always return zero, of course; but as After Effects is able to physically show the expression generated value as a number, I guess it should also be able to output this number somewhere as a (buffered) digital value to be re-used somewhere again.

Anyone ideas?

TOPICS
Expressions
1.6K
Translate
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
Community Expert ,
Jun 12, 2014 Jun 12, 2014

An expression's only way to communicate with other expressions is by affecting the value of the host property. One thing you could do is apply the piece of the expression that calculates the angle you want to an angle control.

Dan

Translate
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 ,
Jun 13, 2014 Jun 13, 2014

Hai Dan, thanks for your reply. Now in general, let me see if I understand this right: an expression is always dynamic, 'active' so to speak. It will never stop generating values. So it's impossible for an expression which, let's say, generates a layer rotation over time with a constant speed, to output one certain value at a certain point in the timeline as a 'fixed' value. Like a snapshot function: measured data of one single moment in time to be put in some kind of passive container after which the active link with the expression is disconnected, so to speak.

So what I tried to describe above , is not possible using expressions?

Thanks for taking the trouble to answer, this question has everything to do with the function sampleImage, which I only want to use on the first frame of a timeline generating an alpha value. This value should be set on frame zero and after that remain unchanged.

Translate
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
Community Expert ,
Jun 13, 2014 Jun 13, 2014

I'm not sure if this is what you mean, but you could have the expression freeze a calculation at a particular time, or do a different calculation, or present a constant value. For example, your rotation calculation could do something like this:

if (time < 5){

  (calculate a rotation value)

}else{

  (recalculate the 5-second value)

}

which does its calculation for the first five seconds, then, for each frame after that, it re-calculates the 5-second result so that it appears to "hold" that value.

I'm not sure if any of that helps...

Dan

Translate
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 ,
Jun 16, 2014 Jun 16, 2014

Hi Dan and thanks for your answer,

It is exactly what I am trying to do, with the only difference that I want to avoid recalculating... in short, I use the function 'sampleImage' to track the exact location of the first white pixel in a text layer;  this search starts from the right edge of the comp to the left edge. The next part of the expression positions some other layer based on the retrieved location value of the sampleImage function. I used sampleImage because there is no other way to retrieve the exact position of a single character in a text layer.

The text is static, by the way. But when sampleImage needs to sample every frame over and over again for 125 frames it takes ages to render the tiny 5 seconds. So I would prefer the sampling to be done once, then buffer the value and stop sampling...

Translate
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
Explorer ,
Aug 05, 2014 Aug 05, 2014

You could use the expression from Dan and then "bake" the keyframes with Animation> Keyframe Assistant> Convert Expression to Keyframes.

This will greatly reduce your render times. And if you ever need to go back and change something, you can just delete the keyframes, make the change, and then Convert Expression to Keyframes again!

Trent

Translate
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 ,
Aug 20, 2014 Aug 20, 2014

Hi Trent,

Thanks for your answer!

the problem is in the recalculating of the value. In my case, the calculation is based on a sampleImage expression written to 'scan' the entire comps surface for an alpha value > 0 and it takes a lot of time to sample at every single frame (in a 5 sec. comp). So the solution would ideally be something like

if (time < 0.04){

  (sampleImage) then (storeValueInBuffer)

}else{

  (getStoredValueFromBuffer)

}

but this appears to be impossible. But your idea of converting expressions to keyframes would be a great workaround, especially with a script Dan wrote for 'bulk baking' expressions in an active comp.

I just need a little understanding of how to make a small modification to that fine script of Dan Ebbers.

I have between 300 and 400 (scriptgenerated) comps in an AE project, they are all exactly the same except for the contents. They are actually all different subtitles and the text differs from comp to comp, as does the layout (which is where the sampleImage expression comes in).

If I could modify Dan's script so that it batch bakes all the expressions of every comp in that project (i.e. not limited to the active comp), I would save a huge amount of rendertime, as you said. Another idea might be a script that opens the first comp in the project, then runs the baking script, then closes the comp and then opens the next comp. I have too little experience in Java scripting to come up with the entire script myself, but if you could give me a hint I could work it out further I think.

Translate
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
Community Expert ,
Aug 21, 2014 Aug 21, 2014

So are you doing this to find one or more extents of the text? If so, and you're going to run a script anyway, I would suggest you take advantage of the fact that scripting can measure text elements directly, and have the script either save that value somewhere, or reposition any elements that depend on the text size.

Dan

Translate
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 ,
Aug 21, 2014 Aug 21, 2014

Hi Dan, good to hear from you. I know, it sounds that easy. I'll try to explain this thing with a little more detail. If I can find a way to tackle this challenge, it will save me about 60 hours rendering each time this job passes my desk.

I have a standard (5 sec.) comp with four lines of text in just one font with a fixed size and everything. As explained before, I run a script that generates between 300 and 400 copies of this comp, giving each new comp a logical and unique name, ánd... replacing the contents of all text lines in every copy of the comp. Now the first line of text is easy: just a number. It's left justified and the layout is always correct. The second, third and fourth line are actually a few people's names (the whole comp is actually a crew title for participants in the Dakar rally), where every name is followed by a three-character nationality abbreviation, like USA, or GER or FRA and so on. You must understand that the comp is built up in seven independant text fields, of which each one gets its content automatically through the mentioned script from an Excel sheet. Now here is the problem:

The designer who created the layout for the titles wants to have the three-character nationality abbreviation exactly one character space BEHIND the name in every title. Ofcourse, the name (set in its own text field and AE layer) is pretty variable in length, so the position of the nationality field that comes right next to the name field, needs to be automatically adjusted in accordance with the name field length. To determine this position, the designer wrote (or adapted) an expression that samples the 'image' of the preceding name title, thus finding the rightmost white pixel (the titles are all simply white on black) and thus, with a certain offset, generating the right basic position for the following title.

Now I thought I checked thoroughly for a possibility to extract the rightmost 'bounding box line' of a title in another video layer in AE somehow, and I couldn't find it; whereas you mention this can be done. If that is really possible, it would save my day...

All I ran into was that text layers are always comp size (thisLayer.height and thisLayer.width always give 1920x1080 in an HD comp, no matter how small the text in the text layer) and therefore it seemed impossible to me (and the man who wrote the expression probably) to get any useful info concerning the characters positions and bounding boxes etc.

So: how can this be done? How can I measure directly what the position value of the rightmost pixel of a line of text is and pass that on to another layer's position? In that case I can work around the time consuming sampleImage expression.

I'm sure someone is going to send you a big bottle of wine on this one .... 🙂

Translate
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
Community Expert ,
Aug 21, 2014 Aug 21, 2014

You need to do it with a script, not an expression. With a script, you can use yourTextLayer.sourceRectAtTime() to get the left, top, width, and height of the actual text. Since you are already running a script, that would be the ideal place to put such code, but it could also be done in a second script that you would run after you populate your comps with the new text. That would let you get rid of the sampleImage() expressions, which should save you a ton of render time. It depends on your project set up (and to some extent on how script-friendly it is), but such a script could probably be written and tested in a few hours if you know what you're doing. It would be specific to your project though--it would be tough (I think) to write a general purpose tool for this.

Dan

Translate
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 ,
Sep 01, 2014 Sep 01, 2014
LATEST

Hi Dan, sorry for the delayed reply. Busy times at the moment. I think your mention of myTextLayer.sourceRectAtTime() is the magic word I was looking for. Haven't had time to write the script yet, but then again there is no hurry, as long as I have it ready before Christmas (litterally).

The script could best be run after the comps have been created; so what it should basically do is check every comp in the project to find (always three) text layers (that, by the way, use the same name in each comp) and set their x position value to be the sum of left and width (probably with one constant offset) that have been traced by myTextLayer.sourceRectAtTime(). That should be pretty simple, although I am a 'read-only' scripter 🙂

Most of the time I combine and modify existing scripts. But I recall a script you created, designed to 'bake' expressions for most common parameters of a layer. It includes After Effects searching through comps one by one, which is the most essential ingredient in the script I need to write. So I guess I'll be OK and I am sure this is going to work! So glad to hear that such a .sourceRectAtTime() exists.... Thanks! I'll let you know how it worked out!

Translate
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
Explorer ,
Aug 14, 2014 Aug 14, 2014

Also, something I do from time to time is set up an expression control effect (slider, angle, etc) and put the expression in there. If you do that, you would be able to "freeze" that expression with .valueAtTime({yourTimeToFreeze}).

You could even have it where whatever you enter in the value field would be the freeze time for that particular expression controller. Then just pickwhip everything to it and create as many of those controllers as you want.   

Translate
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
Explorer ,
Aug 22, 2014 Aug 22, 2014

I will always default to Dan!

Were you able to get this solved yet?!

Trent    

Translate
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 ,
Sep 01, 2014 Sep 01, 2014

Hi Trent, I think Dan found the answer yes. Sorry for the late reply. Thanks!

Translate
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