- assets/app-icon/: master and light SVGs, 1024 px PNG, .icns (Apple grid), .ico (16-256),
hicolor 16-512 + scalable, LICENSE.txt, README with palette (#e0368f / #efe9dc / #0b0b0c),
tile geometry and provenance; attribution sidecars + ATTRIBUTION.md rows.
- packaging/icons.sh regenerates everything with resvg, iconutil and the new `cargo xtask ico`.
- Runtime icon via ViewportBuilder::with_icon (padded variant on macOS) and Wayland app ID
ai.storyteller.effectcraft; packaging/linux/ai.storyteller.effectcraft.desktop.
- apps/effectcraft/build.rs embeds the .ico and VERSIONINFO into effectcraft.exe (winresource,
Windows targets only; a missing resource compiler is a warning).
- Web favicon.svg is now the unicorn icon.
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>
Analysis reads native-size footage frames straight from the footage source
(124 frames/s end to end for a 1080p single-point track in the test build).
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>
Tracker panel (Window > Tracker): Track Camera / Warp Stabilizer (disabled),
Track Motion / Stabilize Motion, Motion Source, Current Track, Track Type,
Position/Rotation/Scale, Motion Target with Edit Target..., Options...
(Motion Tracker Options dialog), Analyze (1 frame back, back, forward,
1 frame forward; stop while running) with progress, Reset and Apply (Apply
Dimensions dialog). Track point widgets in the viewer: feature and search
regions with corner handles, attach point crosshair and track path, all
draggable through track.setPoint (one undo step per drag). Automation ids for
every widget; headless UI test.
Tracker: featureless regions no longer drift (ties keep the prediction, only
confident matches predict motion). docs/agents.md: tracking example.
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>
≈64% weighted feature parity, 257/298 effects, ≈167 agent-hours remaining
(≈42–50 h wall clock with five parallel agents).
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>
Also: render uses web_time::Instant in layer styles; renderQueue.add documents
its render-settings/output-module keys so checked execution accepts them (+test).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A rayon worker running frame_at could wait on the in-flight condvar for a
frame whose decode sat lower on its own stack (work stealing during the
decoder's parallel join), hanging footage playback and the media tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- apps/effectcraft-web (L6): eframe web runner booting the shared EffectcraftApp with a browser
session: in-memory file table, <input type=file> pickers and drag-and-drop for open/import,
downloads for Save and Render Queue outputs (several files as one stored .zip), and the
window.effectcraft promise API over the control channel. Demo project on start.
- wasm32 runtime fixes: web-time for Instant/SystemTime (render, engine, export, ui-egui);
Frames renders queued jobs on the UI thread (Frames::pump) instead of a thread pool;
Render Queue runs inline; relative outputs resolve under / ; control PNGs inline.
- effectcraft-export: per-job output Sink (files to memory instead of disk); host FileExporter
carries it; test that sink exports touch no file.
- xtask web [--dev] [--serve PORT] (wasm-bindgen 0.2.129, optional wasm-opt, COOP/COEP server);
effectcraft-web in WEB_CRATES. docs/web.md, headless Chrome smoke test, favicon (+attribution).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve conflicts; register playback.audio (Composition > Preview > Audio)
as a real frontend command replacing its stub; layer_at uses content_buf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Audio effects (Backwards, Bass & Treble, Delay, Flange & Chorus,
High-Low Pass, Modulator, Parametric EQ, Reverb, Stereo Mixer, Tone)
applied per layer in the comp mixdown, so export and preview share them.
RBJ-cookbook biquads, Schroeder/Moorer reverb, modulated delay lines;
stateless per block via pre-roll. Tone makes any layer audible.
- Real-time audio preview: ui-egui AudioFeed/AudioPlayback (feeder thread
mixing ahead) behind an AudioDevice hook; the desktop app implements it
with cpal (L6). Audio clock drives playback (consumed frames minus device
latency, looped through the work area). Preview panel Include Audio /
playback.muteAudio.
- Audio panel VU meters with peak hold and clip indicators; selected
layer's Audio Levels.
- Timeline Audio > Waveform for footage with audio (L reveals Audio
Levels, LL the Waveform), drawn from a cached per-item peak summary.
- ui.playback reports audio state and meter levels.
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>
Layer Styles (Drop Shadow, Inner Shadow, Outer/Inner Glow, Bevel and Emboss, Satin,
Color/Gradient Overlay, Stroke) and Blending Options (Global Light, Fill Opacity, R/G/B,
Knockout, Blend Interior Styles as Group) as a layerStyles property group with AE names,
order and defaults. Rendered in layer space after effects (exterior passes composite with
their own blend modes below the body), cached per pass, scaled with render resolution.
Commands layer.style.* (menu Layer > Layer Styles), Global Light shared per comp, timeline
eye switches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
EffectHost gains self_at (the layer's source + masks + first N effects at
another layer time) and layer_at (another layer at another comp time);
EffectEnv carries the effect's stack index. The renderer serves these via
Renderer::layer_input, cached in the layer cache under input keys (footage
included, keyed by source time) with a depth guard against recursion.
Time effects are TIME_DEPENDENT so processed-layer keys fold in layer
time; layers with time effects and expressions are not cached.
Also registers the Effect > Audio specs (DSP in effects::audio_fx; the
mixdown integration follows in M11.2). Audio effects are skipped by the
video effect pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve conflicts with perf (layer cache / Arc<Buf>), export (RenderOpts.view: None
for output), timeline (separate dimensions + one-node POI visibility), mask/pen
viewer gestures (alongside camera tools and view-aware layer matrices), key
dialogs (alongside Camera/Light Settings), render queue + MCP command modules.
3D path tangent honours separated position; DOF blurs a per-frame copy so cached
layer buffers stay shared. New test: cached renders match uncached after camera,
focus, light and 3D view changes. Fix a clone-on-copy lint from main.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- layer.autoOrient {mode: off|alongPath|towardsCamera|towardsPointOfInterest}
(Layer > Transform > Auto-Orient…, Cmd+Alt+O); render support for Orient
Along Path (2D and 3D) and Orient Towards Camera (with recursion guard).
- Layers parented to cameras/lights follow their full rotation.
- Draft 3D turns off lights and shadows (and DOF).
- Turning the 3D switch off discards Z values, Orientation and X/Y Rotation.
- Tests for all of the above.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>