mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-28 03:57:44 -06:00
Merge pull request #289 from storytold/fix/227-shape-effect-points
Effects: effect points on shape layers start at the layer centre (#227) # Conflicts: # crates/ui-egui/src/panels/puppet_tool.rs # crates/ui-egui/src/panels/viewer.rs
This commit is contained in:
+11
-2
@@ -242,6 +242,15 @@ build real projects through these interfaces; they are worked examples of everyt
|
||||
Save / Don't Save / Cancel prompt (`ui_click` on `dialog.unsaved.save` / `dontSave` / `cancel`;
|
||||
`dialog.unsaved.revert` for Revert); the control channel's `app.quit {"force": true}` skips it.
|
||||
|
||||
### Effect positions
|
||||
|
||||
Effect points, Puppet pins (`puppet.addPin`, `puppet.recordPin`), Paint, Liquify and Roto Brush
|
||||
strokes and `effect.pickColor` are in **effect space**: layer pixels from the top-left of the
|
||||
layer's effect bounds. For footage, solids and precomps that is the layer's own pixel grid. Shape
|
||||
and text layers have comp-sized bounds centred on their content's origin, so in a `w` × `h` comp
|
||||
the point `[w / 2, h / 2]` is that origin (a new effect's default point). `prop.get` / `prop.set`
|
||||
read and write these values as they are.
|
||||
|
||||
### Motion tracking
|
||||
|
||||
Trackers live on the tracked layer (`Motion Trackers ▸ Tracker n ▸ Track Point n`) and are driven
|
||||
@@ -372,7 +381,7 @@ effectcraft-cli run shot.ecproj camera.createFromSolve '{"kind":"solid","points"
|
||||
|
||||
The Roto Brush tool (Alt+W cycles Roto Brush / Refine Edge) paints in the Layer panel; agents use
|
||||
`roto.stroke {layer, kind: fg|bg|refine|refineErase, points: [[x, y], …], frame?, radius?}`
|
||||
(layer pixels, layer frames). The first foreground stroke applies the Roto Brush & Refine Edge
|
||||
(effect space, layer frames). The first foreground stroke applies the Roto Brush & Refine Edge
|
||||
effect and sets the base frame with a span of 20 frames each side. `roto.propagate {layer,
|
||||
direction?: forward|backward|both, to?, wait?}` segments the span (in the background unless
|
||||
`wait`); strokes on any other frame correct it and propagation restarts from there.
|
||||
@@ -477,7 +486,7 @@ that closes the dialog). File ▸ Scripts: `file.scripts.list`, `file.runScript
|
||||
states as a branch); `edit.history.goto {"index": n}` (or `id`, or `steps`) jumps to any of
|
||||
them. MCP: the `history` tool.
|
||||
* `puppet.recordPin {"layer": "#1", "pin": "Puppet Pin 1", "samples": [[t, x, y]…]}` records a
|
||||
drag (t = seconds since it began, layer space) into Position keys at the comp frame rate from the
|
||||
drag (t = seconds since it began, effect space) into Position keys at the comp frame rate from the
|
||||
current time; `puppet.recordOptions {speed, smoothing, useDraftDeformation, showMesh}`.
|
||||
* `puppet.selectPins {"layer": "#1", "pins": ["Puppet Pin 1"], "add"?, "toggle"?}` selects pins
|
||||
like the viewer's click / Shift-click (`pins: []` deselects); Edit ▸ Clear (Delete) then removes
|
||||
|
||||
+34
-1
@@ -82,13 +82,46 @@ a file that a newer EffectCraft saved shows a warning: fields this version doesn
|
||||
dropped if it saves the project. Save, Save As, Save a Copy and Increment and Save keep the
|
||||
file's format (`.ecprojx` stays XML).
|
||||
|
||||
`schema` changes when a saved value changes meaning; a project from an older schema is converted
|
||||
when it is opened (`effectcraft_engine::upgrade_effects`, which also refreshes effect instances
|
||||
from the registry) and saved with the current one, which older versions refuse to open rather than
|
||||
render wrongly. Schema 2 put effect positions on shape and text layers in effect space (§4,
|
||||
#227). Opening a schema 1 project moves what an effect on a shape or text layer (not an adjustment
|
||||
layer, whose effects see the comp below as before) holds as a position by half the comp size,
|
||||
so points that were set keep their place in the comp: point parameters with their keyframes, Paint
|
||||
stroke paths and clone positions, Puppet mesh seeds, pin rest points and positions, and Liquify
|
||||
and Roto Brush strokes. A point parameter still at its default and not animated is left alone:
|
||||
the old default sat at the comp's bottom-right corner, where most effects did nothing, and the
|
||||
same value is now the layer centre, as in After Effects. Expression controls (Point Control…)
|
||||
keep their values, because their meaning is up to the expressions that read them, and expressions
|
||||
are not rewritten, so an expression that computes an effect point on a shape or text layer from
|
||||
other values may need `+ [thisComp.width / 2, thisComp.height / 2]`. Effects that use the layer
|
||||
bounds (edge pinning, wipes, Offset, generators) now cover the whole comp-sized bounds instead of
|
||||
their bottom-right quarter. Tracking data of effects that analyse footage (Warp Stabilizer, 3D
|
||||
Camera Tracker, Mocha shape) is left as it is: footage has a source rectangle, whose effect space
|
||||
did not change.
|
||||
|
||||
## 4. Rendering
|
||||
|
||||
`Renderer::comp_frame(comp, t)` walks the layers bottom to top. For each visible layer it renders
|
||||
the **source** (solid, footage frame, text, shape contents, or a nested comp), applies **masks**,
|
||||
then **effects** in order, then **layer styles**, then the **transform** into comp space (with motion blur sub-samples
|
||||
when enabled), the **track matte**, and finally **blends** into the accumulator. Adjustment layers
|
||||
apply their effects to the accumulator. Runs of 3D layers are composited per pixel through the
|
||||
apply their effects to the accumulator.
|
||||
|
||||
Effects run in **effect space** (`effectcraft_render::effect_bounds`): layer pixels measured from
|
||||
the top-left of the layer's effect bounds, which are the source rectangle, or for layers without
|
||||
one (shape, text) a comp-sized rectangle centred on the layer's origin that their content
|
||||
surrounds. A shape layer's default effect point (the bounds' centre) is therefore its content's
|
||||
origin, as in After Effects. The renderer moves the layer buffer into effect space for the whole
|
||||
stack (`Buf::rebase`, on the CPU and the GPU alike) and hands effects everything else in it too:
|
||||
masks, other layers' pixels for layer parameters (each in its own effect space), the layer's own
|
||||
frames at other times (`Renderer::layer_input`, also what Puppet, Roto Brush and the Layer panel
|
||||
read) and the comp camera. Effect point handles, Puppet pins and the Layer panel map effect space
|
||||
to the comp with `EvalCtx::effect_to_comp`. Adjustment layers run their effects on the comp below
|
||||
as it is.
|
||||
|
||||
Runs of 3D layers are composited per pixel through the
|
||||
active camera, with lights, shadows and depth of field (Classic 3D), or rasterised as meshes by
|
||||
the Advanced 3D renderer (below).
|
||||
|
||||
|
||||
@@ -108,6 +108,15 @@ The most important missing piece: it turns every other estimate here into a meas
|
||||
- Regression evidence for the Turbulent Displace, Wave Warp and Bulge pinning of #227:
|
||||
`edge_pinning_displaces_all_of_a_centred_shape_layer` (render) and
|
||||
`edge_pinning_on_a_shape_layer` (GPU against CPU).
|
||||
- Regression evidence for the effect points of #227 (shape and text layers measure effect points
|
||||
from the top-left of their comp-sized bounds, so Twirl, Bulge, CC Lens, Ripple and Turbulent
|
||||
Displace's Offset default to the layer centre): `default_effect_points_sit_at_the_centre_of_a_shape_layer`
|
||||
and `layer_parameters_see_a_whole_shape_layer` (render), `effect_points_on_a_shape_layer` (GPU
|
||||
against CPU), and the schema 1 → 2 conversion in
|
||||
`opening_a_schema_1_project_moves_shape_layer_effect_points_into_effect_space` (engine) and
|
||||
`effect_points_move_into_effect_space_unless_left_at_their_default` /
|
||||
`puppet_paint_liquify_and_roto_data_move_into_effect_space` (effects); see
|
||||
[architecture.md](architecture.md) §3 for what the conversion keeps.
|
||||
- Regression evidence for the interface items of [#227](https://github.com/storytold/effectcraft/issues/227),
|
||||
checked headlessly on Windows: `spacebar_taps_preview_and_held_spacebar_pans_the_viewer` and
|
||||
`spacebar_drag_scrolls_the_time_graph` (Spacebar previews on its release, held it is the Hand
|
||||
|
||||
+1
-1
@@ -549,7 +549,7 @@ Since (M5.16): Key Light (After Effects' Keylight 1.2) is checked end to end on
|
||||
plate with an uneven screen, spill and soft edges (`effect.apply "Keylight (1.2)"`, pick, Clip
|
||||
Black / White, render). The colour eyedroppers of Keying effects sample the effect's input
|
||||
rather than the keyed frame (Ctrl/Cmd+click averages 5 × 5 pixels); agents do the same with
|
||||
`effect.pickColor {effect, param, x, y, average?}` (layer pixels). Searching "keylight" in
|
||||
`effect.pickColor {effect, param, x, y, average?}` (effect space). Searching "keylight" in
|
||||
Effects & Presets, or `list_effects`, finds it.
|
||||
|
||||
## Update: M4.9–M4.11 nested comps and motion blur
|
||||
|
||||
Reference in New Issue
Block a user