* Layer: Quick Set Anchor, nine anchor points with Position compensation (#2967)
layer.quickSetAnchor moves the Anchor Point of 2D layers to a corner, edge midpoint or the
centre of their content and shifts Position and its keys so nothing moves. Layer > Transform >
Quick Set Anchor lists the nine points.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Quick Set Anchor: skip layers with an animated Anchor Point, Scale or Rotation
The anchor is set at the current time and the Position shift is worked out
from the current Anchor Point, Scale and Rotation, so on a layer where any of
them is keyed or has an expression the layer would move at other frames.
Such layers are skipped like 3D and locked ones (an error when none is left).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Quick Set Anchor: skip layers with a Position expression or Auto-Orient along the path
An expression on Position (or the separated X/Y) overrides the shifted value,
and Auto-Orient along the path adds a rotation the shift does not account for;
both would make the layer jump, so they are skipped like 3D layers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Quick Set Anchor: error when no selected layer has content bounds
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Quick Set Anchor: test separated, keyed Position keeps the layer in place
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
An empty layers list cleared the composition's markers too (CodeRabbit);
the composition-marker menu uses comp.deleteAllMarkers instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every undoable edit keeps the previous project for undo, so the comp it touches
is shared and Arc::make_mut deep-copies it: every layer and every keyframe. An
edit therefore costs time in proportion to the comp's size, and a script that
sets many keyframes in a big comp goes quadratic (a 1,600-layer build with
~100k sampled keys took ~45 minutes).
Comp::layers is now a Layers collection backed by Vec<Arc<Layer>>: copying the
stack copies pointers, and only the layer an edit changes is copied. The API
mirrors Vec<Layer>; serialized form is unchanged (a list of layers).
Comp::layer_mut and the iter_mut().filter/find call sites use find_mut /
iter_mut_where so they copy only the layers they actually change.
- prop.addKey in a 400-layer comp: 1.36 ms -> 0.16 ms per key (flat in comp size)
- the 1,600-layer script build: ~45 min -> 47 s, frames pixel-identical
- regression tests: an edit leaves the other layers shared with undo; layers
round-trip as a plain list
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VkpGcKfWyCudfSsQNiWAaG