Commit Graph
31 Commits
Author SHA1 Message Date
Claude f3fe25fd67 Import: test that an animated GIF imported from disk plays (#651)
Animated GIFs came in as one still frame in 0.7.0; bfbdadd3 (after that
release) probes them as movies. This end-to-end test imports a GIF file
through the wired session into a comp and checks the layer shows each of
its frames at its time, the path the viewer and exports share.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 23:50:08 +00:00
bflatasticandClaude Opus 5.5 3cc9520685 Test: an imported GLB shows in a new composition in software (#264)
The host test writes a binary glTF cube (built in the test), imports it
with the real media layer, makes New Comp from Selection and renders
with no accelerator (the CPU path an Intel HD Graphics 5500 most likely
gets): the comp is Advanced 3D and the red cube covers part of the
frame. Before the fix the comp stayed Classic 3D and drew nothing. The
engine test checks the switch, its single undo step, the toasts, that a
second model doesn't switch again, and primitives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:45:07 +07:00
Dexter 39e6907b5f G2: improve editing reliability and Windows rendering fidelity 2026-10-06 00:00:31 -05:00
bflatasticandClaude Opus 5.5 7579de21c6 M13.35: Roto Brush trained model — swappable segment module, MobileSAM in pure Rust
- New L1 crate effectcraft-segment: the MaskModel interface (prompts → foreground probability),
  a registry of open-licensed models (licence must be MIT/Apache/BSD/…; URL, size, SHA-256),
  a PyTorch checkpoint reader (zip + pickle subset), dependency-free SHA-256, and MobileSAM
  (TinyViT-5M + SAM prompt encoder / two-way transformer / mask decoder) on rayon and ndarray's
  safe GEMM. Loads the official mobile_sam.pt as published; checked against candle
  (embedding 0.3% RMS, 99.9% equal mask pixels); ~0.7 s/frame encoder at 32 threads, cached
  per frame, ~0.1 s decoder.
- track::roto: segment_with / propagate_with prompt a model with the strokes or the flow-warped
  matte (box, core points, mask); its probability is a strong, unblurred prior for the same
  graph cut (strokes stay hard constraints); a failing model or one disagreeing with the flow
  (IoU < 0.5) is ignored. Prior gets a weight.
- effects::roto: Version 2.0 / 3.0 use the model chosen in Settings (set_model / model_for);
  the model id is part of the chain seed.
- engine: roto_models (roto.models, roto.model.select / install / download / remove), weights in
  the models folder (host::config_dir()/models, shared by the app, CLI and MCP), background
  loading, downloads through the system curl, verified; Settings ▸ Roto Brush page (prefs
  roto.model). host::config_dir moved from the desktop app.
- Tests: segment (kernels vs direct sums, checkpoint reader, SHA-256 vectors, registry), track
  (fake model: prior shapes the cut, failing / disagreeing models ignored; real weights with
  EFFECTCRAFT_MOBILESAM: base IoU 0.989, propagated ≥ 0.980 vs classic 0.973), engine (registry,
  verification, selection; real install + load), MCP.
- Docs: README, ROADMAP, parity (MSK-4 done: 90/2/0), preferences, agents, architecture,
  crates/segment/README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 17:55:02 +07:00
Brandon ThomasandClaude Opus 5.5 c5e33f1a02 Never crash: deny panic lints in the already-clean crates and apps
These crates have no production panic sites: add the deny attribute so they stay clean
(geom, color, model, automation, host, export, plugin, and the desktop, CLI and web apps). The
plugin's wasm-only test module gets a separate cfg(test) attribute so clippy recognises it as
test code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 14:52:39 -04:00
Brandon ThomasandClaude Opus 5.5 f3715aac32 M13.30: web depth and polish
- GPU in browser job workers: each job worker opens its own WebGPU device
  (deferred readbacks); the Render Queue export and the analyses' frame loops
  are futures (render::passes, offload::run_request_async) whose frames
  render in passes, awaiting the device between them. GPU particles and
  Advanced 3D read back under keys too. workers.jobs reports passes and
  readbacks; the smoke test measures them.
- Layer buffers in the browser's OPFS disk cache: frame workers back their
  layer caches with a PrefetchStore; the page plans what to fetch before a
  request from recent misses (LayerPrefetch over the shared DiskIndex).
- Templates embed footage (default on, size-capped with a warning) and
  creating from a template extracts it next to the new project / into
  browser storage.
- ICC LUT profiles (lut8/lut16/lutAtoB/lutBtoA, from the public ICC spec) in
  Simulate Output > My Custom RGB, baked into a 3D LUT for the viewer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:57:17 -04:00
Brandon Thomas 978e8d7f94 Merge branch 'worktree-agent-a12b9f39d35fe5457'
# Conflicts:
#	docs/parity.md
2026-10-03 05:25:26 -04:00
Brandon ThomasandClaude Opus 5.5 ad0f821fa8 Merge main into M10.2 (render queue + VP9 inter)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 05:09:51 -04:00
Brandon ThomasandClaude Opus 5.5 1242a775fe M10.2: Render Queue completeness (render settings, output module, templates, logs, overflow, notify)
Render Settings: field render with 3:2 pulldown phases, effects/solo/guide
layer/color depth/frame blending/motion blur overrides, custom time sampling
(duration), storage overflow through a quota hook. Output Module: crop
(edges or region of interest), resize (presets, lock aspect, quality),
straight/premultiplied/alpha-only channels, post-render actions, include
project link, audio channels and PCM formats, WebM bitrate and key frame
interval. Render Settings / Output Module templates with built-ins and
defaults per slot (Edit > Templates dialogs), render logs next to the
output, Notify on completion. All through renderQueue.* commands and
persisted in the project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:55:31 -04:00
Brandon ThomasandClaude Opus 5.5 47d2da04de Merge main into M13.1 (scripts in File ▸ Scripts / Window via @dynamic menu nodes)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:27:09 -04:00
Brandon ThomasandClaude Opus 5.5 89c9b1b6ee M13.1: branching history, puppet pin recording, WebAssembly plug-in API, ScriptUI model and hosts, File ▸ Scripts, deterministic render test
- engine: History keeps undone lines as branches; edit.history.list/goto; History panel tree; MCP history tool
- puppet.recordPin / puppet.recordOptions; viewer Cmd-drag records; Record Options form
- effects::plugin (EffectPlugin trait, register_plugin, API v1); effectcraft-plugin (wasmi, sandboxed, fuel-limited); effect.plugins.load/list
- ScriptUI: engine scriptui model + layout + scriptui.* commands; script crate scriptui.js and script-host threads (dialogs block show())
- File ▸ Scripts: install script / ScriptUI panel, sample scripts, window.scriptPanel
- host test: bit-identical renders across runs and thread counts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:07:20 -04:00
Brandon ThomasandClaude Opus 5.5 fa27d000ea Merge main into M14.5 (settings and menus)
Display Color Space setting joins the live list; View3D::Default maps to view.3d.default for
the Assign Shortcut submenu; stub tests use the stubs that remain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 03:29:39 -04:00
Brandon ThomasandClaude Opus 5.5 b17d2c05e6 Merge main into M14.5 (settings and menus)
Reconciled with main's keyframe labels (same Keyframe::label field; keys.setLabel and
keys.selectLabelGroup from main are kept, M14.5's duplicates removed; Edit ▸ Label on
selected keys delegates to the label helper), proxies (RenderOpts::proxy next to
nested_switches/draft_shadows), offloaded renders (Work carries nested_switches), wasm
audio pump (preview mix rate), variable font axes and mask feather points.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 03:11:45 -04:00
Brandon ThomasandClaude Opus 5.5 f855a4b55b M14.5: wire the remaining settings; keyframe assistants and labels; AE menu entries
Settings: 56 of 59 not-yet-wired settings now change behaviour (nested-comp switches,
constant vertex count, related-item time sync, match-name pick whip, split-layer order,
Home on open, motion path span, internal wireframes, zoom quality, label-coloured tabs,
mask colour cycling, gradients, grid/guide styles, text engine, font preview/recent/native
names, missing frames, unlabeled alpha, drag import, default output folder, segmenting,
bit depth names, preview sample rate, disk/media/conformed-audio caches, RAM reserve and
low-memory reduction, Video Preview window, 3D reference axes/extended viewer/draft
shadows, script file gate + File.execute warning, expression editor options and error
banner). Three stay display-only and are documented.

Features: Convert Audio to Keyframes, RPF Camera Import (JSON/CSV camera data),
keyframe colour labels + Select Keyframe Label Group, Recent Animation Presets.
Menus: Edit > History, File > Import Recent Footage, Replace Footage > With Layered
Comp, Save a Copy As XML (.ecprojx, opens again), Composition > VR (Create VR
Environment, Extract Cubemap), Assign Shortcut to 3D view / workspace, Window viewer
labels + open viewers, Help > System Compatibility Report / Enable Logging / Reveal
Logging File. Dynamic menu nodes (@dynamic:…) shared by the egui and native menus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 02:45:44 -04:00
Brandon Thomas 86b8e24417 Merge branch 'main' into worktree-agent-a15cecfec57d5290d
# Conflicts:
#	crates/effects/src/ocio.rs
#	crates/engine/src/commands/stubs.rs
#	docs/parity.md
2026-10-03 02:26:19 -04:00
Brandon ThomasandClaude Opus 5.5 8696d1e9ba M7.7: camera/light rigs and Advanced 3D motion blur, blend modes, track mattes
Layer > Camera > Create Stereo 3D Rig (left/right eye comps with expression-linked eye
cameras, Stereo 3D Controls effect, stereo comp through 3D Glasses), Create Orbit Null,
Create Cameras from 3D Model; Layer > Light > Create Lights from 3D Model
(KHR_lights_punctual), Control Light with Camera, Create Environment Light Background
Layer (equirectangular sky drawn through the camera). glTF cameras and punctual lights
are parsed by effectcraft-model.

Advanced 3D: per-sample motion blur over the comp shutter, and blend modes / track
mattes / Preserve Transparency composited through the 2D path in depth order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 00:27:47 -04:00
Brandon ThomasandClaude Opus 5.5 a4f32f8df2 Merge main into M13.5 long-tail polish
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 00:25:09 -04:00
Brandon ThomasandClaude Opus 5.5 dbcda2eba9 Merge main into CMP-7/ANM-5/PRJ-8/PRJ-3 work
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:43:41 -04:00
Brandon ThomasandClaude Opus 5.5 85c645f337 M13.5: camera iris bokeh depth of field and focus-link commands
3D-1: Classic 3D depth of field renders the camera's Iris Shape (Fast
Rectangle box or Triangle…Decagon polygon), Iris Rotation, Roundness, Aspect
Ratio and Diffraction Fringe as a span-kernel gather blur, with Highlight
Gain/Threshold/Saturation boosting highlights first; tilted layers blur
progressively by per-pixel camera depth. Layer > Camera > Link Focus Distance
to Point of Interest / to Layer (expressions) and Set Focus Distance to Layer
replace the stubs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 23:35:03 -04:00
Brandon ThomasandClaude Opus 5.5 c33b80614a PRJ-8: proxies — Set Proxy / None / Use Proxy / Create Proxy / Interpret Proxy, Proxy Use; PRJ-3 interpret fields, PAR, alpha guess
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>
2026-10-02 23:11:03 -04:00
Brandon ThomasandClaude Opus 5.5 6d0d7de922 ANM-5: sampleImage, data footage (JSON/CSV/TSV) with footage().sourceData, thisProject, error list, Expression Language menu
sampleImage renders the sampled layer through the evaluating renderer's footage source
(EvalCtx::footage), cached per thread and frame. File > Import reads .json/.csv/.tsv as data
footage kept in the project. expr.errors collects failing expressions for the error bar;
expr.languageMenu lists the categorised Expression Language menu. Marker keys expose
protectedRegion and cue points; colorDepth, timeToFeetAndFrames, comp.activeCamera.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:58:04 -04:00
Brandon Thomas 6723f87ecb Merge branch 'main' into worktree-agent-aba3d925078471ad6
# Conflicts:
#	docs/parity.md
2026-10-02 22:18:29 -04:00
Brandon ThomasandClaude Opus 5.5 d880746fec M14.4: scripting tests for layer/comp settings, import + save, console snapshot; Project.saveAs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:18:11 -04:00
Brandon ThomasandClaude Opus 5.5 78cd313d3c M14.4: scripting with an After Effects-style JavaScript object model
New crate effectcraft-script (L4): boa runtime with app/Project/CompItem/
Layer/PropertyGroup/Property/TextDocument/MarkerValue/RenderQueue/File
object model over engine commands (undoable, undo groups), AE match-name
table, file/network security gate. Entry points: script.run command,
File > Scripts > Run Script File (.jsx/.js), Window > Script Console,
effectcraft-cli script, MCP run_script. Engine: project.delete/duplicate,
prop.renameGroup/setGroupEnabled/removeGroup/duplicateGroup/moveGroup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:13:09 -04:00
Brandon ThomasandClaude Opus 5.5 dec091e575 M7.5: advanced 3D renderer
Advanced 3D comps render their 3D runs as one scene of world-space triangles: model and
primitive layers (meshes, skinning, animation clips by layer time), extruded text/shape
layers, and textured cards for every other layer with their Material Options. Shading is
physically based in linear light: Cook-Torrance GGX + Lambert for parallel/spot/point lights
(AE falloff and cone), ambient lights, image-based light from an Environment light's layer
(equirectangular; cosine irradiance map + roughness mip chain + split-sum BRDF fit), and
PCF shadow maps (spot/parallel/point cube faces). 2x2 SSAA, depth of field as a gather blur
by circle of confusion, back to the working encoding.

The software rasteriser (depth buffer, top-left rule, perspective-correct, opaque visibility
then sorted transparent blending) is the reference and CI path; effectcraft-gpu implements
Accelerator::raster_3d with a wgpu render pipeline (advanced3d.wgsl) and matches it within
tolerance. Environment layers are hidden from both renderers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 21:27:59 -04:00
Brandon ThomasandClaude Opus 5.5 485f562e19 M12.2: gpu compositor and gpu effects
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>
2026-10-02 10:59:08 -04:00
Brandon ThomasandClaude Opus 5.5 31f192e2a9 M15.1: web build (eframe wasm) + xtask web
- 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>
2026-10-02 00:19:35 -04:00
Brandon Thomas c6af0fa2e9 Merge branch 'worktree-agent-a549a3d1a8812e372'
# Conflicts:
#	apps/effectcraft-cli/src/main.rs
#	crates/host/src/lib.rs
#	crates/render/src/lib.rs
2026-10-01 22:42:32 -04:00
Brandon ThomasandClaude Opus 5.5 7f9c3a85c0 M10: render queue + export
- crates/export (effectcraft-export): render a comp's span to H.264 MP4 (+AAC),
  ProRes 422/4444 MOV (+PCM, alpha), PNG/JPEG/TIFF/EXR sequences and animated GIF
  via FilmCraft's pure-Rust encoders and MP4/MOV muxer; parallel batched frame
  rendering, progress callback with cancellation.
- project: Render Queue model (Render Settings, Output Module, output path
  templates, status) saved with the project.
- render: FootageSource::audio hook + comp audio mixdown (levels, in/out, solo,
  precomps); media implements it.
- engine: Exporter hook, background/blocking render job, renderQueue.* commands
  (add Cmd+M, remove, setRender, setRenderSettings, setOutputModule, setOutput,
  move, duplicate, render, stop, list, formats).
- host wires the exporter; CLI `render` subcommand.
- ui-egui: After Effects-style Render Queue panel with automation ids.
- tests: encode/decode round trips for every format (FilmCraft decoders,
  ffmpeg/ffprobe oracle when installed), audio, cancel, engine commands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 22:02:06 -04:00
Brandon ThomasandClaude Opus 5.5 951ed1fa3d M5.2–M5.5: keyframe clipboard, easy ease, velocity/interpolation dialogs, roving, time remap/stretch/reverse/freeze, graph editor, separate dimensions, pick-whip
Engine (all commands with undo/redo + tests in engine/src/tests_timeline.rs):
- keys.copy/paste (Edit Copy/Cut/Paste route to keys when keys are selected;
  relative timing kept, paste at CTI, cross-property paste of same type),
  keys.selectAll (Cmd+Alt+A), keys.nudge* (Alt+Arrow, Alt+Shift+Arrow),
  keys.set / keys.setEase (graph editor drags), keys.info (dialog data),
  keys.timeReverse; keys.interpolation gains continuous/auto Bezier, spatial
  interpolation and roving; keys.velocity takes per-dimension values and
  Continuous.
- Roving keys (keyframe::retime_roving): constant speed along the motion path.
- Layer > Time: layer.timeStretch (percent|duration, hold in/current/out),
  layer.timeReverse (Cmd+Alt+R), layer.enableTimeRemap (Cmd+Alt+T),
  layer.freezeFrame, layer.freezeOnLastFrame; render uses Time Remap as the
  source time for precomp/footage layers.
- prop.separateDimensions (X/Y/Z Position; prop.set on Position writes them).
- layer.setParent compensates so the layer stays in place (compensate:false
  to opt out).
- prop.pickWhip writes AE-style reference expressions (thisComp.layer(..),
  effect(..)(..), mask(..).maskFeather, temp=…;[temp,temp], …[0]).
- prop.setExpression: syntax errors keep the text but disable the expression.
- expr: arrays of properties returned by an expression are resolved.

UI: Keyframe Velocity, Keyframe Interpolation and Time Stretch dialogs;
Graph Editor (value + speed graphs, draggable keys and Bezier/influence
handles, auto-zoom, fit, show selected, separate dimensions, hold/linear/
auto Bezier/Easy Ease buttons); key + layer context menus. Clears the
workspace clippy -D warnings failures.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 21:47:29 -04:00
Brandon ThomasandClaude Opus 5.5 3a59a8470d M0.9–M0.10: egui frontend (AE-style panels, viewer, timeline, effect controls, dialogs), desktop app with control channel, host wiring; cargo fmt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:48:31 -04:00