Layer: Un-precompose a selected pre-comp layer back into its parent composition (#3081)

* Layer: Un-precompose a selected pre-comp layer back into its parent composition (#2918)

layer.unprecompose copies the nested composition's layers into the parent at the pre-comp
layer's place with timing and position carried over, and refuses what it can't keep exactly.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Un-precompose: refuse a pre-comp layer with Solo or Guide on

A soloed pre-comp layer hides the comp's other layers and a guide layer is
left out of renders; the expanded copies carry neither switch, so the picture
would change. Listed with the other blockers, in the command description and
the agents.md Cookbook entry; the refusal test covers both switches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Un-precompose: warn instead of refusing, only a locked layer stops it

A locked pre-comp layer is still refused, with or without `force`. Every
other former refusal reason is a warning: without `force`,
`layer.unprecompose` returns an error that lists the reasons and changes
nothing. `dryRun` returns `{dryRun, warnings}`. With `force` the layer is
unpacked in one undo step and the result carries `warnings`. Whatever the
pre-comp layer itself carried is dropped, and other layers' parent, track
matte and layer-property links to it are removed.

Layer > Un-precompose in the UI lists the reasons in a prompt with
Unpack Anyway / Cancel (`dialog.unprecompose.force` /
`dialog.unprecompose.cancel`). A layer without reasons unpacks at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Un-precompose: warn about expressions that refer to the pre-comp layer

An expression on another layer of the comp that names the pre-comp layer
would no longer find it once the layer is unpacked. The expression can
name it in quotes or call `layer(<index>)` with its index, bare or on
thisComp; another comp's comp("…").layer(…) is not counted. Each such
property is now listed once as a warning. Like the other warnings,
`force` unpacks and `dryRun` lists it. The expressions are left as
written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Un-precompose: warn about lost frame sampling and Position expressions, keep markers in order

Review follow-up (CodeRabbit on #3081):
- A nested comp that preserves a frame rate other than the parent's
  samples its layers on its own frames, and the expanded copies would
  lose that. Motion-blurred nested layers under a different shutter
  would also blur with the parent's shutter. Both are now warnings.
- When the pre-comp layer's Position differs from its Anchor Point, the
  move is added to the stored Position of the unparented nested layers.
  An unparented layer whose Position, or a separated axis, has an
  expression may ignore that move, so it is now a warning.
- Copied comp markers are sorted into time order with the comp's own.
- New tests: a 10 fps nested comp with Preserve Frame Rate in a 30 fps
  comp, a different shutter, a Position expression with and without a
  move, and nested matte and layer-value remapping with shifted markers
  merged in order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Un-precompose: warn when an expression's layer numbers shift; the prompt keeps its target

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Un-precompose: a shorter renumbering warning

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-11-07 00:56:54 +01:00
1 parent 52bca964f5
commit bb2d2005ce
11 files changed
+1009 -1

No files matched your search

+24
View File
@@ -261,6 +261,30 @@ build real projects through these interfaces; they are worked examples of everyt
`layer.centerAnchor` skip them and fail when every target is locked ("… is locked"); Select
All and `layer.selectNext` / `selectPrevious` step over them. Unlock with
`layer.setSwitch {"layers": [...], "switch": "lock", "value": false}` or `layer.unlockAll`.
* **Un-precompose**: `layer.unprecompose {layer?, force?, dryRun?}` (Layer ▸ Un-precompose) expands the
selected pre-comp layer into copies of its composition's layers at its place (order, keyframes,
effects, masks, parenting, mattes, markers kept; timing moved by the layer's Start and trimmed to
what it showed; Position minus Anchor Point added to the unparented ones). One undo step; the
nested comp stays in the project; the nested comp's frame no longer clips what its layers draw
outside it. Only a **locked** pre-comp layer is refused (with or without `force`), changing
nothing. Everything that would change the picture or drop something is a warning: the pre-comp
layer has a parent or matte, effects, masks, layer styles, a non-default Scale / Rotation /
Opacity, an animated transform, time remap or stretch, a blending mode, Video or Audio off, Solo
or Guide on, the 3D / collapse / adjustment switch or Preserve Transparency, or is used by another
layer (parent, matte or a layer property), or an expression of another layer names it (by name in
quotes or as `layer(<index>)`; listed per property, the expression is left as written and will
no longer find it); or the nested comp holds a camera, light, adjustment,
3D, collapsing or soloed layer, or a layer with a blending mode or Preserve Transparency, preserves
a frame rate other than the comp's, has a motion-blur shutter other than the comp's (with motion
blur layers), or has an unparented layer with a Position expression while the pre-comp layer's
Position differs from its Anchor Point (the move is added to stored values only). Without
`force` such a call is an error listing every reason and nothing changes; `dryRun: true` returns
`{dryRun, warnings}` without changing anything. With `force: true` it unpacks anyway and returns
`{layers, warnings}`: what the pre-comp layer itself carried (effects, masks, styles, transform
beyond Position, time remap, blending mode, switches, its parent and matte) is dropped, and other
layers' parent, track matte and layer-property links to it are removed. The menu shows the
reasons and asks (Unpack Anyway / Cancel, `dialog.unprecompose.force` /
`dialog.unprecompose.cancel`); a layer without reasons unpacks without asking.
* **Quick Set Anchor**: `layer.quickSetAnchor {point: topLeft|top|topRight|left|center|right|bottomLeft|bottom|bottomRight, layers?}`
(Layer ▸ Transform ▸ Quick Set Anchor) moves the Anchor Point of 2D layers to that point of their
content and shifts Position and its keys so the layers don't move, in one undo step. 3D and