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

Help adjusting an expression for 3D layers (2d layer expression works fine)

Explorer ,
May 18, 2023 May 18, 2023

Copy link to clipboard

Copied

Hello,

 

I’m trying to create a column of 3d layers.

 

Layer 1 is the reference.

 

Then each new layer below Layer 1 should be N pixels down on the Y axis. Regardless of the size or shape of the layer above it.

 

I’ve been using this expression successfully, but fails when the layers are 3D:

 

l = thisComp.layer(index-1);
l.toComp([l.sourceRectAtTime(time).left + l.sourceRectAtTime(time).width/2, l.sourceRectAtTime(time).top + l.sourceRectAtTime(time).height])+[[0],[1]+thisComp.layer("Control").effect("Spacing")("Slider")]

 

 

So I’ve been trying to update it, so it has the exact same function but works for 3D layers. I came up with this;

 

a = thisComp.layer(index - 1).sourceRectAtTime();
s = thisComp.layer("Control").effect("Spacing")("Slider");

x = a.width / 2;
y = a.top + a.height + s;
z = thisComp.layer(index - 1).position[2];

toComp([x, y, z]);

 

 

Two failures come out of this.

 

1. The first layer works as intended but then every other layer doesn’t offset, and they just pile in on the same position. 

 

2. Instead of aligning with the layer above, the position changes on the X and Z axis and I’m not sure why. For example it’s a 1920x1080 composition. After applying this expression, instead of being position z=0, it comes out z=2665.7

 

Any thoughts to simply make the first expression with 3D layers would be a massive help. 

 

Thank you

TOPICS
Expressions

Views

861

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 19, 2023 May 19, 2023

I took a few minutes and created a couple of expressions and 3 Sliders that will stack and offset a bunch of other shape layers. A controller layer is needed, and, to prevent expression errors, the top layer in the stack must be named Top, but that's easy.

 

If you are going to stack layers based on their size, the first thing you have to do is fix any Anchor Point problems. Shape layers have a Shape/Transform Shape property. This expression is added to Contents/Shape/Transform Shape/Anchor poin

...

Votes

Translate

Translate
Community Expert ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

If you want to move layers based on the previous layer's position, you have to reference that position. All your expression does is take the top, width, and Z position of the layer above. The top layer won't have an expression. If all the shapes are the same size, all layers below the top one will be in the same position. The first step would be to use the current Layer Index - 1 as a multiplier for the position values. 

 

Here's a quick hack that stacks and offsets the layers based on the layer size and the index.

r = thisComp.layer(index - 1);
a = r.sourceRectAtTime();
s = thisComp.layer("Control").effect("Spacing")("Slider");
p = r.position;
x = a.width / 2;
y = a.top + a.height + s;
z = thisComp.layer(index - 1).position[2] * r.index;

p - [x, y, x];

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 ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

 

Thank you.

 

Unfortuntely that gives me the same results as I had - the first layers works and is offset, but then each layer under that just stays in the same position.

 

I assume the last line of the expression is a typo? Should it be p = [x, y, z]; ?

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 ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

The expression offsets each layer in X, Y, and Z. It's just not very useful. Did you copy it correctly? 

RickGerard_0-1684498147947.gif

Here is a more useful 3D layer stacking option. 3 sliders instead of one, multiplied by the index of the layer.

 

ref = thisComp.layer(index - 1);
ctrl = thisComp.layer("Control");
xOfst = ctrl.effect("x ofst")("Slider") * ref.index;
yOfst = ctrl.effect("y ofst")("Slider") * ref.index;
zOfst = ctrl.effect("z, ofst")("Slider") * ref.index;
startPos = ref.position;
startPos + [xOfst, yOfst, zOfst]

 

There is no need for sourceRectAtTime() if you are only offsetting the position unless you want to base the offset on the size of the layer. All you need to create a cumulative offset is to multiply the offset distance by the layer index. 

RickGerard_1-1684500207312.gif

Your first expression does not move the layer's x value based on the layer index. It just offsets each layer in X by a portion of the width and offsets the layer in Y based on the slider. There is no need to fiddle with toComp or toWorld to build an effective layer-stacking 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
Explorer ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

Thank you. I'll have to try that in the morning. But yes, I did copy it correctly 🙂

 

Just to be clear - my original expression works perfectly as yes, I need to take the distance off the bottom of the layer above as they're all different sizes. So simply offsetting the position will not work. 

The only issue is that expression only works with 2d layers and I need it to work with 3d layers. 

X position will always be 960 (middle of comp) and Z position will always be 0. 

Y will be bottom of the layer above + whatever I set the slider to. 

hopefully that makes sense. 

Thank 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
Community Expert ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

If you want to offset layers based on their size, you do need to throw sourceRectAtTime into the mix, but you still need to use the index as a multiplier, and you need to throw in the layer's position in case the shape does not have the layer's anchor point at the center. 

 

If I get some free time later this morning, I'll post the expression that I would use. toComp or toWorld would be unnecessary to offset each layer based on a percentage of the size of the content and adjust the spacing with a slider.

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
LEGEND ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

That expression doesn't make much sense. You'll probably have better luck working with layer space transforms like toWorld() to figure out where in space your shapes actually are. And if the sizes of the shapes are variable, you need to run it in a loop or else there's no way to persistently determine any of the actual cumulative positions and spacing.

 

Mylenium

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 ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

I took a few minutes and created a couple of expressions and 3 Sliders that will stack and offset a bunch of other shape layers. A controller layer is needed, and, to prevent expression errors, the top layer in the stack must be named Top, but that's easy.

 

If you are going to stack layers based on their size, the first thing you have to do is fix any Anchor Point problems. Shape layers have a Shape/Transform Shape property. This expression is added to Contents/Shape/Transform Shape/Anchor point:

b = sourceRectAtTime();
[b.width/2 + b.left, b.height/2 + b.top]

The property could be Contents/Rectangle 1/Transform Rectangle 1/Anchor Point or Contents/Shape 1/Transform Shape 1/Anchor Point.

 

When you apply that expression to a shape layer, unless the Anchor Point is already in the center of the graphic, the layer position will change.

 

The next step is to add some Controls/Sliders for X, Y, and Z offset. I used a solid that can be placed above or below the stack of shape layers.

 

If you start the Position expression with an if statement that checks the layer name and uses the default value for position when the layer name is Top or makes some calculations if the layer name is not Top, you can add this expression to the Shape Layer/Transform/Position property.

// Controls
xAdj = thisComp.layer("Control").effect("X Offset")("Slider")/100;
yAdj = thisComp.layer("Control").effect("Y Offset")("Slider")/100;
zAdj = thisComp.layer("Control").effect("Z Offset")("Slider");
if(thisLayer.name == "Top"){
	value
}
else{
	// Stack Lyrs X and Y and align them
	ref = thisComp.layer(index - 1);
	refBox = ref.sourceRectAtTime();
	lyrBox = sourceRectAtTime();
	xOfst = refBox.width/2 * xAdj + lyrBox.width/2 * xAdj;
	yOfst = yAdj * refBox.height/2 + yAdj * lyrBox.height/2;
	ofstPos = ref.position + [xOfst, yOfst, zAdj];
}

The X and Y offset sliders work on a percentage of the current layer's height and width. When the sliders are set to zero, the layers will stack on top of each other. As you adjust the X and Y slider until the value for either is 100%, the layers will be perfectly lined up edge to edge. The Z slider does nothing until you make the Shape Layers 3D. Then it just offsets each layer by the value you set with the slider. 

 

I think this will do everything you want to do. With some modifications, the math will also work with text layers or a combination of text and shape layers.

RickGerard_0-1684532417616.gif

I hope this helps. I have uploaded a project file.

 

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 ,
May 19, 2023 May 19, 2023

Copy link to clipboard

Copied

LATEST

 

Morning Rick,

 

 Thank you for taking the time to buid this and write up an explanation. I can see I wasn't even the ballpark of being correct.

 

 I've already put this into my project and it's working really well.

 

Thanks again for the 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