Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Wrapping multiple layers in a rectangle, then dynamically aligning the rectangle

  • Wrapping multiple layers in a rectangle, then dynamically aligning the rectangle

    Posted by Steve Lewis on August 26, 2023 at 10:38 pm

    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.

    Steve Lewis replied 9 months, 3 weeks ago 2 Members · 2 Replies
  • 2 Replies
  • Filip Vandueren

    August 31, 2023 at 7:35 pm

    Hi Steve,

    Presumably you’re putting the containing composition at the bottom of the layer-order, but because of compositing it has to be rendered first, so that’s what’s throwing a wrench in the works:

    the other layers have not yet been rasterized, which would define their sourceRect, and their position depends on their parent, which is sampling the sourceRect of its childs, etc. there’s the circular logic.

    If the Shape Layer is on Top, the problem disappears. So you could get creative with extra copies of the contained layers on top of the shape, that are parented to their hidden counterparts ?

  • Steve Lewis

    September 1, 2023 at 2:25 pm

    Thanks for the reply, I’m trying to build a re-usable preset so it’s needs to be very adaptable and can’t involve needing specific stacking order etc.

    However I have found a solve if you’re interested, I was finding that the toComp function was breaking things no matter how I approached it, so I’ve essentially written my own function that is equivalent to toComp, I’ve used this along with some other adjustments to my expressions and it now works perfectly:

    function toCompClean(layer, rectPos) {

    let radians = layer.transform.rotation * (Math.PI / 180);

    let translatedX = rectPos[0] - layer.transform.anchorPoint[0];

    let translatedY = rectPos[1] - layer.transform.anchorPoint[1];

    let rotatedX = translatedX * Math.cos(radians) - translatedY * Math.sin(radians);

    let rotatedY = translatedX * Math.sin(radians) + translatedY * Math.cos(radians);

    let scaledX = rotatedX * (layer.transform.scale[0] / 100);

    let scaledY = rotatedY * (layer.transform.scale[1] / 100);

    let finalX = scaledX + layer.transform.position[0];

    let finalY = scaledY + layer.transform.position[1];

    return [finalX, finalY];

    }

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy