The 3D Camera Tracker analysis joins the offloaded jobs. The disk cache stays off in the
browser (std::env::temp_dir panics on wasm32 once a config store exists).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Persistence: settings, shortcuts, recent projects, imported media, saved projects and
auto-saves live in OPFS (IndexedDB fallback) through an in-memory mirror flushed in the
background (apps/effectcraft-web/src/store.rs, persist.rs); ConfigStore gains FileOps so
auto-save / recovery work in the browser store; the session snapshot restores the last
project + editor state on reload; File > Open Recent works from storage.
- Audio: Web Audio output (AudioWorklet, ScriptProcessor fallback) fed by AudioPlayback::pump
on wasm32; A/V sync from AudioContext.currentTime; meters; unlock on first gesture.
- Background jobs: engine::offload (WorkerRequest/WorkerReply protocol, Offload trait,
run_request); Render Queue, tracker, mask tracker, Warp Stabilizer and Roto Freeze run in Web
Workers (a second engine instance on the shared compiled module), progress streamed back;
cancel terminates the worker.
- GPU: WebGPU viewer frames drawn straight from the compositor's texture (gpu_display on
wasm32 when the viewer draws plainly); async readback (Gpu::read_display_async) for pixels.
- PWA: manifest, service worker precaching the build (xtask fills list/version), icons copied
from assets/app-icon; COOP/COEP kept from cached responses; offline reload works.
- window.effectcraft: saveToBrowser, listStored, removeStored, flush; info() reports storage,
audio, gpu, workers.
- Tests: native store + protocol + offload (render, track, cancel) tests; smoke.mjs extended
(GPU path, worker render responsiveness, audio gesture + playback, reload persistence,
Open Recent, offline reload).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shapes (SHP-2): Stroke Taper (pixels/percent start/end length, width, ease) and
Wave (amount, pixels/cycles, wavelength, phase) rendered as a variable-width
outline; Dash 2/Gap 2/Dash 3/Gap 3 (shape.dashes.add/remove, timeline +/-
buttons); radial gradient Highlight Length/Angle as a focal gradient.
Masks (MSK-1): mask feather points on the Mask Path (mask.featherPoint.*,
Mask Feather tool add/drag), per-point signed radius and tension, rendered
from the signed distance to the path; carried through vertex edits.
Motion blur (LYR-10): Adaptive Sample Limit comp setting; 2D layers take one
sample per pixel of shutter travel between Samples Per Frame and the limit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Items (footage and comps) carry a proxy rendered in their place at the source's size when
its switch and Render Settings > Proxy Use allow it; Create Proxy queues a half-resolution
render whose post-render action attaches it. Interpret Footage gains Separate Fields
(upper/lower first, fields become frames at twice the rate), Guess alpha with matte colour,
explicit matte colour, Invert Alpha, Interpret As Linear Light; non-square footage, solids
and precomps are stretched by their pixel aspect in the comp. The four proxy stubs are gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comps expose controls (properties typed as text/color/slider/checkbox/point/angle/dropdown,
Media Replacement, groups, comments); precomp layers get an Essential Properties group whose
edits override per instance (Push to Comp / Revert); templates export/import as an open ZIP
(manifest.json + project subset + media + poster). Stretched precomps keep protected regions
at their original speed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New crate effectcraft-model (L2): glTF 2.0 (.gltf/.glb, data URIs, external buffers and
images, PBR metallic-roughness with base/MR/normal/occlusion/emissive textures, node
hierarchy, skins, step/linear/cubic animations) and OBJ/MTL import, parametric primitives,
extruded/bevelled outline meshes and polygon triangulation with holes.
Project: FootageKind::Model, LayerSource::Model/Primitive, Layer::environment, Geometry and
Material Options builders, Environment light Source. Media probes and loads models
(FootageSource::model). Engine: layer.newModel, layer.new3dPrimitive/newPrimitive,
comp.renderer, layer.environment, material.set/reset/duplicateAssign/revealSource (stubs
replaced); File > Import and layer.addItem pick up models. Hand-written fixtures with
attribution sidecars.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Auto backend keeps comps with 3D layers on the CPU compositor (3D runs are
still CPU-composited; the GPU round-trip made them slower).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Region-of-interest frames render on the CPU path; the viewer keeps main's
frame drawing (Show Channel, exposure, ROI) and reads GPU-composited frames
back. Keeping frames as native egui-wgpu textures stays implemented behind
RenderSource::gpu_display (off).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New L3 crate effectcraft-gpu: a wgpu compute backend for the per-frame
compositing walk (layer transforms with the CPU's nearest/bilinear/bicubic
sampling and minification pre-filter, motion-blur accumulation, track
mattes, Preserve Transparency, layer style passes and knockout, all 38
blend modes as a WGSL port of color::blend, 8/16 bpc clamp+quantise,
colour-space conversions). 3D runs, adjustment and wireframe layers run on
the CPU between GPU steps. GPU effects with the CPU semantics: Gaussian,
Fast Box and Directional Blur, Glow, Levels, Curves, Hue/Saturation, Tint,
Fill, Gradient Ramp, Fractal Noise, Drop Shadow, Brightness & Contrast,
Exposure, Invert, Transform (registry gpu badge from effects::GPU_EFFECTS).
render: Backend (Cpu/Gpu/Auto) in RenderOpts, the Accelerator trait and
Renderer::accel, GPU effect chains in the effect stack, hooks for the GPU
walk. Project setting gpu_acceleration (Mercury GPU Acceleration / Software
Only), render.backend command, file.projectSettings renderer. Session and
Render Queue exports carry the accelerator. CLI --gpu and bench --gpu.
Tests compare GPU vs CPU renders (blend modes x bit depths, transforms,
masks, mattes, motion blur, colour management, styles, collapse,
adjustment fallback, every GPU effect) and skip without an adapter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- project.select/rename/move/setLabel/setComment engine commands (undoable; no folder into
itself).
- Drag items onto folders / the root, Enter or double-click the name to rename, double-click
the Comment cell to edit, label colour popup on the label column, Media Duration / File
Path / Comment columns shown or hidden from the header context menu, rendered comp/footage
thumbnails in the info header.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Type tool point/box text creation, double-click editing, caret and selection
in the viewer (viewer_text.rs), keyboard/IME/clipboard, box handles; engine
text.edit/endEdit/setSelection/moveCaret/insert/delete, layer.setText range,
caret insertion style, Paste Text and Match Formatting / Paste Text
Formatting Only (stubs removed); Character/Paragraph/Properties panels act
on the selection.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Composition viewer interaction parity with After Effects:
- Snapping (View > Snapping, the Tools bar checkbox, Cmd/Ctrl inverts while
dragging): layer edges, centres and anchor points, mask and shape-path
vertices, comp edges/centre, guides (Snap to Guides) and grid (Snap to
Grid), with highlighted target box / line / cross feedback. Pure maths in
engine::viewer (nearest target within tolerance, priority ties).
- Rulers (Cmd+R) with live pointer markers and a draggable zero point;
guides dragged out of the rulers, moved in the viewer, dragged off to
remove (view.moveGuide / view.removeGuide), lock respected; proportional
grid.
- Show Channel (RGB/Red/Green/Blue/Alpha/RGB Straight, Colorize), exposure
(+/- stops in linear light, reset), Take Snapshot (Shift+F5) with a stored
render and Show Snapshot (F5 held / button held), Fast Previews (Off,
Adaptive Resolution, Draft, Fast Draft, Wireframe), Resolution > Custom.
- Region of interest: drawn in the viewer; RenderOpts.roi renders only that
rectangle (crop of the full render, tested), Crop Comp to ROI uses it.
- Bottom bar in AE 2026 order ("136.1 %", "(Full)").
- Shape Pen (SHP-1): Pen on a shape layer / nothing selected draws Shape n
groups (Path 1, Stroke 1, Fill 1) via shape.newPath; the G slot cycles
Add / Delete / Convert Vertex and Mask Feather; mask.* vertex commands
work on shape paths; mask.insertVertex / mask.convertVertex; marquee
vertex selection, Alt-drag/click converts, double-click free transform
box (path.freeTransform on masks and shape paths).
- Motion paths (ANM-3): keyframe dots and spatial tangent handles, dragging
keys (keys.set) and tangents (keys.setSpatialTangents), parented layers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Frame Mix and Pixel Motion for footage and precomp layers when the layer's
Frame Blending switch and the comp's Enable Frame Blending are on and the
source time falls between source frames (rate conform, time stretch, time
remap). Exact frame positions from tick arithmetic. Pixel Motion is a
hierarchical block-matching optical flow (SAD search, sub-pixel parabola
fit, vector median) with a bidirectional warp-blend (raster::flow). Blended
footage frames are cached.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8/16 bpc projects clamp and quantise layer pixels after source/masks and
every effect, and the comp after every layer (16 bpc = 0..32768); 32 bpc
keeps over-range values. Blend modes without HDR support clamp their inputs
in 32 bpc. Working space (sRGB, Rec. 709, Rec. 2020, Display P3; matrices
derived from the published primaries), footage colour profiles from stream
metadata or Interpret Footage, Linearize Working Space and Blend Colors Using
1.0 Gamma. Layer cache keys include the colour settings. Project panel depth
button: click cycles, Alt-click opens Project Settings.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Implement 20 formerly disabled menu stubs: Look at Selected/All Layers
(2D viewer fit, 3D view cameras, active camera), Switch View Layout (1/2/4
views in the viewer) and Share View Options, Create Camera from 3D View,
Add Output Module (every module encodes the item's frames), Pre-render
(queue + Import & Replace Usage post-render action), Save Current Preview,
RotoBezier / Convert To Bezier Path, Group / Ungroup Shapes, Set First
Vertex, Free Transform Points, mask Motion Blur (sub-frame mask samples),
Feather Falloff (smooth/linear), Hide Locked Masks, and workspace
save / save as / edit. Tests incl. undo.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PRJ-7. `engine::autosave` with the session hooks the frontends call:
- Auto-save: every N minutes a dirty project is written to "EffectCraft Auto-Save" next to
it (or a custom folder; untitled projects use the custom folder or the config dir) as
"<name> auto-save N.ecproj", rotating through max versions (oldest overwritten, extra
slots dropped when the maximum shrinks). Optional save when the render queue starts.
- Atomic writes for projects, auto-saves and config files: temp file + fsync + rename; a
failed write removes the temp file and leaves the previous file intact.
- Crash recovery: a session.lock sentinel in the config dir records the open project and
its latest auto-save; a clean exit removes it. At launch a leftover sentinel offers the
latest auto-save in a Recover Project dialog (Settings > Startup can turn it off).
- File > Open Recent (stored in the settings) with Clear Recent Projects; Increment and
Save uses After Effects naming ("Intro 2.ecproj"); Revert reloads the saved file.
- Commands: file.autoSave, file.recoveryInfo, file.openRecent {index|path},
file.clearRecent.
- Tests: rotation, interval/dirty tick, simulated crash mid-write, unclean-exit detection
and recovery, Open Recent / Increment and Save / Revert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keyboard shortcut presets in the engine (`engine::shortcuts`): every menu entry (including
ones with bound parameters), registry command and frontend command is bindable, scoped
application-wide or to a panel. "EffectCraft Default" is After Effects' layout and
read-only; editing it creates a custom preset that stores only its differences. Presets
are saved in the config store; the shortcut dispatcher and the menus read the active one.
- Commands: shortcuts.list, shortcuts.set {command, params?, keys}, shortcuts.reset,
shortcuts.preset {select|new|duplicate|delete|rename}, shortcuts.export/import (JSON),
shortcuts.conflicts.
- Edit > Keyboard Shortcuts: preset bar, modifier toggles (or held keys), an on-screen
keyboard coloured by scope (application-wide / panel-specific / both), key details,
a searchable list of every command, record-or-type assignment with conflict warnings,
reset to default; all widgets have automation ids.
- Tests: normalization, defaults conflict-free, conflict detection, custom preset creation
and persistence, preset lifecycle + export/import, dispatch uses the custom preset.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A real Settings model in the engine (`engine::prefs`): serde, versioned, dotted keys
(`general.undoLevels`, `labels.3.name`), migration of older layouts, unknown keys kept,
persisted through a `ConfigStore` trait (platform config dir on the desktop; MemoryConfig
for tests; the web app can back it with localStorage).
- After Effects 2026 pages (General … Scripting & Expressions) as a schema shared by the
dialog, `prefs.pages` and docs/preferences.md (rows not wired yet are listed there and
kept in step by a test).
- Commands: prefs.get, prefs.set {key, value | values}, prefs.reset {page?}, prefs.open
{page?}, prefs.pages.
- Wired settings: undo levels, path point size, tool tips, layers at comp start / CTI,
default spatial interpolation linear, Home screen on launch, new project template,
rendering progress in Info, adaptive resolution limit, cache when idle, fast previews,
theme + UI brightness, label names/colours everywhere (Label menu, timeline, project,
render queue, viewer), label colour for handles, grid colour/spacing/subdivisions, guide
colour, safe margins, still footage duration, sequence fps, audio output device and
output mapping, layer / footage / preview cache budgets, default 3D renderer.
- Settings dialog: AE's left page list + right content, OK / Cancel (restores) / Previous /
Next, every widget with an automation id.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paint: non-destructive Paint effect with Brush/Clone/Eraser stroke groups
(Path, Stroke Options, Transform, Duration spans, Write On End keys),
dab rasterizer (diameter/angle/roundness/hardness/spacing/flow/opacity,
pressure dynamics, modes, channels), eraser modes, clone from layer/time,
cache keys include visible strokes. paint.stroke/options/brushPreset/
setCloneSource/removeStroke/presets. Layer panel with paint tools, Paint
and Brushes panels.
Puppet: Puppet effect with meshes and Position/Advanced/Bend/Starch/Overlap
pins; alpha contour -> expansion (exact EDT) -> simplified outline ->
Delaunay with constraint recovery; ARAP (Igarashi 2005) two-step solve with
CG; anti-aliased texture-mapped rendering with overlap depth. puppet.addPin/
movePin/setPin/removePin/mesh/info. Puppet tools in the viewer with mesh
overlay and header options.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Angle dial with revolutions (0x+45.0°), point crosshair + on-viewer effect
point controls via a small viewer hook, colour eyedropper sampling the
composited frame, Curves graph editor and Levels histogram/triangles bound
to their params, layer params with a Source/Masks/Effects & Masks companion,
mask (Path) popups, keyframe navigator, drag-to-reorder effect headers.
Engine: effect.copy / effect.paste / effect.reset; effect.remove takes the
selection; Edit > Copy/Paste/Duplicate/Clear act on selected effects; all
undoable.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New crate effectcraft-lottie (L3): export a comp to Lottie JSON / dotLottie
(precomp and base64 image assets; shape, solid, null, precomp, image and text
layers or glyph shapes; transforms with parenting, separated position,
anchor; keyframes with speed/influence converted to normalised i/o tangents,
hold keys, spatial ti/to; all shape items incl. gradients, dashes, trim,
repeater and path operators; masks, track mattes, blend modes, time remap,
timing, markers, optional expressions, a few Lottie effects) with a warnings
list for what Lottie cannot express, and the inverse import. Commands
file.exportLottie / file.importLottie with File > Export / Import entries.
Round-trip tests (values and rendered frames) and hand-written fixtures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New L2 crate effectcraft-track: per-point feature/search region tracking with
pyramid normalized cross-correlation and Lucas-Kanade (similarity + gain/bias)
sub-pixel refinement, confidence, adapt/stop/extrapolate/continue actions,
RGB/luminance/saturation channels, blur/enhance pre-processing, and
homography/affine/similarity solves.
Project: Motion Trackers > Tracker n > Track Point n property tree
(GroupKind::Tracker with type, target and options). Engine: track.* commands
(new/motion/stabilize/property/select/setType/setTarget/options/setPoint/
analyze/stop/apply/reset/delete/status), background or blocking analysis
job with progress and cancel (one undo step), apply to Transform, Stabilize
and Corner Pin. Renderer::layer_source for the tracker's frames.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Animation ▸ Animate Text (Enable Per-character 3D, every animator property,
Fill/Stroke Color RGB/Hue/Saturation/Brightness/Opacity submenus, Line Anchor,
Character Value), Add Text Selector ▸ Range/Wiggly/Expression (text.addSelector
now supports all kinds) and Text Animation Presets after Browse Presets, in the
engine menu tree. Stubs replaced: text.perCharacter3d, animatorLineAnchor,
animatorCharacterValue, addWigglySelector, addExpressionSelector.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Convert to Editable Styles / Show All / Remove All / Drop Shadow ... Stroke now
run main's layer.style.* commands; the layer.styles stub is gone.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Timeline: Text group 'Animate:' and animator 'Add:' pop-ups (properties and
Range/Wiggly/Expression selectors), selectors/properties listed directly under
each animator, Path Options ▸ Path lists the layer's masks and hides the
other path options until one is chosen. Properties panel Add Animator lists
every animator property plus Enable Per-character 3D, and a Presets menu.
Animation menu: Animate Text, Add Text Selector, Text Animation Presets.
Expression Selector result replaces the selection (no Mode); selector popups
are non-keyframable like AE.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Integrate main (render queue, timeline/keys, time remap, masks/pen, 3D, MCP/CLI).
- Menu tree now runs renderQueue.add, layer.enableTimeRemap, layer.timeReverse,
layer.freezeFrame/OnLastFrame, prop.separateDimensions, mask.setClosed,
layer.cameraSettings, view.3d.* / view.3d.last / view.reset3DView, main's
layer.autoOrient and keyframe velocity/interpolation/time-stretch dialogs;
matching stubs deleted (view.3d.default stays disabled).
- Keyframe clipboard is main's (keys.copy/paste); Paste Reversed Keyframes
reuses it. Animation-menu commands moved to commands/animation.rs.
- Main's spec menu paths/labels aligned with AE (Camera Settings under
Layer > Camera, "..." labels, Freeze On Last Frame).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Range selector complete (units, based on, modes, shapes, smoothness, ease
high/low, randomize), Wiggly and Expression selectors combined by mode;
all AE animator properties incl. line anchor, character offset/value,
skew axis, tracking type, fill/stroke HSB+opacity, blur; More Options
(anchor grouping, fill & stroke order, inter-character blending); Path
Options (text on a mask path); per-character 3D rendered as planes in
the 3D compositor; text animation commands and original presets.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>