-
Wrapping multiple layers in a rectangle, then dynamically aligning the rectangle
Hey all, I have a bit of a tricky challenge here and was wondering if any geniuses can help me out.
I’m essentially trying to make a setup where I have a rectangle shape layer, this shape layer will wrap around any other layers that are parented to it, ie. this shape layer rectangle will extend its left side to the furthest left point of all the child layers, it’s bottom side the furthest bottom point on children etc. etc. so that it perfectly wraps all children.
I then want to be able to dynamically center this shape layer with an expression on the anchorPoint of the shape layer, so all of the children wrapped by this rectangle will be centered as a group.
I am very close to getting it there, I have the wrapping working fine, but I’m not able to get the whole rectangle to be dynamically centered, after adding the expression to anchorPoint the positioning of the layers becomes glitched, in a way that I know is generally indicative of a circular logic issue in my expressions. (The positioning is bugging out and visually rendering the box at one point of the screen while it is actually at a different point)
I believe the issue is to do with my use of toComp and fromComp, I’m using these so that the layer wrapping will work perfectly even if the layers are rotated and scaled.
Here is my project file so you can see what I mean.
Open up the project and move things around a bit and you’ll see positions glitching out, disable the anchorPoint expression and you’ll see the wrapping in action and working correctly without any position glitching. Interestingly it almost works correctly if you just move the GROUP shape layer to the top of the layer stack, but this is likely just due to order or expression execution working slightly more in my favour.
Here’s my expression on the rectangle path to wrap all the children:
let left = [];
let right = [];
let top = [];
let bottom = [];
for (let i = 1; i <= thisComp.numLayers; i++) {
if (thisComp.layer(i).hasParent && thisComp.layer(i).parent.index == thisLayer.index) {
let layer = thisComp.layer(i);
let s = layer.sourceRectAtTime();
// Get the precise toComp position of all 4 corners of this layer
let tl = fromComp(layer.toComp([s.left, s.top]));
let tr = fromComp(layer.toComp([s.left + s.width, s.top]));
let br = fromComp(layer.toComp([s.left + s.width, s.top + s.height]));
let bl = fromComp(layer.toComp([s.left, s.top + s.height]));
// push the furthest edges of these points into left, right, top and bottom
left.push(Math.min(tl[0], tr[0], br[0], bl[0]));
right.push(Math.max(tl[0], tr[0], br[0], bl[0]));
top.push(Math.min(tl[1], tr[1], br[1], bl[1]));
bottom.push(Math.max(tl[1], tr[1], br[1], bl[1]));
}
}
if (left.length) {
// Get the furthest edges of all layers
let farLeft = Math.min(...left);
let farRight = Math.max(...right);
let farTop = Math.min(...top);
let farBottom = Math.max(...bottom);
createPath([[farLeft, farTop], [farRight, farTop], [farRight, farBottom], [farLeft, farBottom]], [], [], true);
} else {
createPath([[0, 0]], [], [], true);
}
And a simple expression on anchorPoint to center the entire rectangle:
let sr = sourceRectAtTime();
let x = sr.left + (sr.width / 2);
let y = sr.top + (sr.height / 2);
[x, y];
I’ve been hitting head against this for ages! Any assistance would be hugely appreciated.