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

size and position a solid to the animated words of an expression selector based on words

Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

i'm trying to have Words highlight with an effect applied to a solid, which is assigned to the text layer, as they are spoken in a paragraph. i'm was planning to be using markers to trigger when each Word is said with this: https://www.youtube.com/watch?v=diaCkKp5lpY


Something kind of close was discussed here:
https://community.adobe.com/t5/after-effects-discussions/text-range-selector-position-value-expressi...

but i'm working with a weird way of highlighting text with an expression selector and i think the text box remains the same width (sourceRectAtTime()).

TOPICS
Scripting

Views

2.1K

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

Community Expert , May 01, 2023 May 01, 2023

This is a better version that creates a tiny, off-screen mask when there's no text layer to proces (so the mask layer doesn't show up) and corrects a logic error:

pad = 10;
c = thisComp.layer("Scripture");
m = c.marker;
n = m.nearestKey(time).index;
if (time < m.key(n).time) n--;
if (n > 0 && n < index - c.index){
  L = thisComp.layer(c.index + n);
  r = L.sourceRectAtTime(time,false);
  ul = L.toComp([r.left,r.top]);
  ur = L.toComp([r.left+r.width,r.top]);
  lr = L.toComp([r.left+r.width,r.top
...

Votes

Translate

Translate
Community Expert ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

So what's your question, exactly?

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

how can i put an effect on Words using an expression selector that uses the option of "based on words"?
something like this would be awesome:
https://www.youtube.com/watch?v=u7SxaTMgCJQ

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

maybe i could have an extra layer of paragraph text with the effect applied and then have a mask that sizes and positions based on which word needs to be highlighted? i have no idea how to do that. i would do this manually ...but i plan on doing this a whole lot with different paragraphs.

Votes

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
Community Expert ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

If I'm understanding what you're after, it sounds like you need a way to get access to the per-word animator value outside of the expression selector. I think the only possible way of doing that would be to detect it from the animated property assigned to the animator. I theory, that shouldn't be too tough to do, but whatever you animate affects how the text looks. I don't know that there's not a good solution for this, I just don't know what it would be.

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

i don't have to use an expression selector. i just need something based on markers. maybe i could use text exploder to get each Word on it's own text layer. but if i'm using saber ...that means i will have to create a new solid and assign a new saber effect to each new text layer. do you know of a way to automate doing that? i think i could then have a sub comp with the highlighted words that trigger on makers?

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

is there a way to use text exploder and then use those text layers with sourceRectAtTime() to make a mask set to markers?

Votes

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
Community Expert ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

I'm sure there's a magic combination that will do just what you want. I just don't have enough experience with Saber or Text Exploder to be much help.

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

good grief dude, i know you know how to do this, i've seen your responses on other questions. forget about saber or text exploder ...they are not important:

i think i need something that will set mask vertices on comp 2 incrementally with each new marker by marker.key(textIndex).time

so imagine a paragraph of text and i want the mask to be in the position over the Word spoken. so the position and size needs to be dynamic.

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

your code here is awesome ...but i'm new to after effects code https://community.adobe.com/t5/after-effects-discussions/sourcerectattime-from-multiple-layers/td-p/...

i don't know how to combine this with setting a mask to change size based on markers. that paragraph of text i mentioned ...picture each word being its own text layer.

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

select a composite in the timeline, hit ctrl+alt+t to do a layer/time/enable time remapping

click the stopwatch and paste this in to see code that works with markers ...it deals with markers that have comments but my project doesn't need to. the composite you just added that code to has a layer called "Markers" for a second set of markers to match ...well, that's what i think it is doing.

https://gist.github.com/animoplex/cecf1c64aec4f2733ecd0edbebf4786d

i just feel like this is a starting area to figure this problem out.

i need code to grab the first text layer's position and size and tell a mask on the composite where to position and size ...but after it does that, i need it to go to the next text layer and do the same thing.

Votes

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
Community Expert ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

If all your text words are one separate layers, you could have mask path expressions that build mask paths to fit the extends of the individular words, but the paths would have to already exist (createPath() has to be applied to an existing path) unless--you have a script do it. It might be simpler if you just assume you're going to need a script to assemble this thing for you.

Votes

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
Explorer ,
Apr 29, 2023 Apr 29, 2023

Copy link to clipboard

Copied

The Words would just be dummy to know the position of size of the single mask i want to move around. can you give me an example of a mask using createPath() that then gets its shape changed and moved?

if i'm forced to assemble, is there a way to write something that would create a new solid that is already sized per text layer it finds?

Votes

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
Community Expert ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

I'm not sure exactly what you're asking for, but this path expression would find text layer "Text 2" and create a mask outline to fit that text layer. If you want it to outline a different text layer, you'd change the n = 2; line:

n = 2;

L = thisComp.layer("Text " + n);
r = L.sourceRectAtTime(time,false);
ul = L.toComp([r.left,r.top]);
ur = L.toComp([r.left+r.width,r.top]);
lr = L.toComp([r.left+r.width,r.top+r.height]);
ll = L.toComp([r.left,r.top+r.height]);

p = [fromComp(ul), fromComp(ur), fromComp(lr), fromComp(ll)];
createPath(p,[],[],true);

 

Votes

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
Explorer ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

i really don't know what i'm doing, where does that code go? i get a createPath is not defined in a time remap expression.

Votes

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
Community Expert ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

Make sure you have a text layer named "Text 2", create a comp-sized solid, and click anywhere on the solid with the pen tool. Add the expression to the resulting Mask Path property on the solid.

Also, you'll probably have to change the mask mode from None to Add to see it.

Votes

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
Explorer ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

Thanks, but then how would i have it trigger with markers if it isn't on a time expression?

Votes

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
Community Expert ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

OK, one step at a time. Now create a null layer named "Control" and put some layer markers on it. Make sure you have as many text layers (of various sizes and positions) named "Text 1", "Text 2" and so on, as Control has markers. Then change the mask path expression on the solid to this:

m = thisComp.layer("Control").marker;
n = m.nearestKey(time).index;
if (time < m.key(n).time) n--;
if (n > 0){
  L = thisComp.layer("Text " + n);
  r = L.sourceRectAtTime(time,false);
  ul = L.toComp([r.left,r.top]);
  ur = L.toComp([r.left+r.width,r.top]);
  lr = L.toComp([r.left+r.width,r.top+r.height]);
  ll = L.toComp([r.left,r.top+r.height]);
  p = [fromComp(ul), fromComp(ur), fromComp(lr), fromComp(ll)];
  createPath(p,[],[],true);
}else
  value

Votes

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
Explorer ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

Thank you very much. can you clue me in on how to add padding? i tried this but didn't work:

padding = 10;
ul = L.toComp([r.left+padding,r.top+padding]);
ur = L.toComp([r.left+r.width+padding,r.top+padding]);
lr = L.toComp([r.left+r.width+padding,r.top+r.height+padding]);
ll = L.toComp([r.left+padding,r.top+r.height+padding]);

Votes

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
Community Expert ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

I think I'd do it like this:

pad = 10;
m = thisComp.layer("Control").marker;
n = m.nearestKey(time).index;
if (time < m.key(n).time) n--;
if (n > 0){
  L = thisComp.layer("Text " + n);
  r = L.sourceRectAtTime(time,false);
  ul = L.toComp([r.left,r.top]);
  ur = L.toComp([r.left+r.width,r.top]);
  lr = L.toComp([r.left+r.width,r.top+r.height]);
  ll = L.toComp([r.left,r.top+r.height]);
  p = [fromComp(ul)+[-pad,-pad], fromComp(ur)+[pad,-pad], fromComp(lr)+[pad,pad], fromComp(ll)+[-pad,pad]];
  createPath(p,[],[],true);
}else
  value

Votes

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
Explorer ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

This is great ...can i ask you to add feather to it?

Votes

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
Community Expert ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

That's a separate property, so it would take its own expression, unless you have a script set everything up for you. Or, you could just do it by hand. It depends on where your workflow is headed with this thing...

Votes

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
Explorer ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

oh, it doesn't have to be in code, so i just set them all to have the same amount of feather, thanks.

i don't want to rename every text layer, so i'm thinking of using your other code of something like this:
c = thisComp.layer("controller");
L = thisComp.layer(c.index+i);

is there a way to test what type of layer it is indexing?

Votes

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
Community Expert ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

You could use try/catch to differentiate based on a property that only that type of layer has, for example, you could do this to see if it's a text layer:

c = thisComp.layer("controller");
L = thisComp.layer(c.index+1);
try{
  L.text.sourceText;
  // end up here if it's a text layer
}catch(e){
  // end up here if not text layer
}

Votes

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
Explorer ,
Apr 30, 2023 Apr 30, 2023

Copy link to clipboard

Copied

is there a way to make it not care if the number of markers doesn't match the number of layers? i tried this but then it gives me nonsense about the pad varible:

pad = 10;
m = thisComp.layer("Scripture").marker;
n = m.nearestKey(time).index;
if (time < m.key(n).time) n--;
if (n > 0){
c = thisComp.layer("Scripture");
try{
L = thisComp.layer(c.index+n);
r = L.sourceRectAtTime(time,false);
ul = L.toComp([r.left,r.top]);
ur = L.toComp([r.left+r.width,r.top]);
lr = L.toComp([r.left+r.width,r.top+r.height]);
ll = L.toComp([r.left,r.top+r.height]);
p = [fromComp(ul)+[-pad,-pad], fromComp(ur)+[pad,-pad], fromComp(lr)+[pad,pad], fromComp(ll)+[-pad,pad]];
createPath(p,[],[],true);
}catch(e){
}
}else
value

Votes

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