Commit Graph
59 Commits
Author SHA1 Message Date
RealtaNuaandClaude Opus 5.5 649ba2e8cf Desktop: an unknown option or a bad --control port stops the launch (#997)
The desktop app imported any argument it didn't know as a file (writing it to Recent Footage)
and dropped a missing or non-numeric --control value, starting without a control server.
parse_args now returns an error for an unknown option, a --control value that isn't a port from
1 to 65535, or a bad EFFECTCRAFT_CONTROL_PORT (checked only when --control isn't given); main
prints it and exits with status 1 before anything starts. --control=<port> works, and -- ends
the options so a file named -x can still be opened.

Tests: parse_args unit tests, and tests/args.rs runs the binary with its own settings folder
and checks the exit, the message and that nothing was written.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-12 17:40:15 +07:00
Brandon Thomas 6ace9f7b0e Merge pull request #923 from itrycodinganditsbad/rotating-log
Desktop: write log records to standard error and a rotating log file
2026-10-12 04:20:56 -04:00
Fabio LussiandClaude Opus 5.5 16d9d7d30b Desktop: write log records to standard error and a rotating log file
A launch from the Dock, the Start menu or a launcher has no terminal, and
without RUST_LOG nothing reached standard error anyway, so start-up and
GPU warnings were lost unless Help > Enable Logging was already on.

The logger now writes EffectCraft's info records and everyone's warnings
to standard error and to Logs/effectcraft.log in the settings folder.
Each launch keeps the previous two runs' logs; the file is capped at
16 MiB. RUST_LOG still overrides the filter. Help > Reveal Logging File
shows this run's log unless Enable Logging is on.

Ported from storytold/pdfcraft#239.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:37:27 +02:00
pravdomilandClaude Opus 5.5 04e087ae58 Window: remember the window's size and position between launches
The window opened at a fixed 1680 × 1020 wherever the system put it. Its size, position
and maximized state are now saved to window.json in the config directory (when they change,
and on exit) and restored on the next launch, moved onto a monitor that is still connected.
The first launch fits the window to its screen. Agent-driven runs (--control) restore the
saved window but don't overwrite it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 15:54:29 +02:00
ClaudeandDennis M. Francis cb37c2511c App: a lost graphics device tells the user why the window closes and where the recovery copy is (#591)
Ported from #673: a native error dialog names the auto-saved recovery copy before the window
closes; agent runs through the control channel skip it. The UI calls Hooks::device_lost once.

Co-Authored-By: Dennis M. Francis <44986763+didpublishing@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 23:36:52 +00:00
Claude aaf23aa5f8 macOS: File menu dialogs open as sheets, so a drag over the window can't abort the app (#511)
The file dialogs were blocking rfd::FileDialog calls made inside eframe's frame,
that is inside winit's event handler. On macOS the dialog runs a nested modal
event loop there; a file dragged over the window while it was open reached
winit's handler again, which refuses re-entry with a panic across the
Objective-C boundary, aborting the app (Import with Cmd+I, then a drag).

Hooks gains file_dialog_async: a host that sets it shows a command's file dialog
(Import, Open, Save As, Save Frame As, presets, guides, templates, Collect Files,
Relink...) without blocking, and the command runs with the answer on a later
frame (menus::dialog_answered, drained at the start of each frame); a cancelled
dialog runs nothing. The macOS app implements it with rfd::AsyncFileDialog, a
sheet on the window answered when it closes, outside the frame. Other platforms
keep the blocking dialogs (winit queues their re-entrant events), as do the few
panel buttons that pick a file in place (Settings paths, shortcut import/export,
effect file pickers).

Test: with a non-blocking hook, Save As and Save Frame As return at once without
the blocking dialog, the save happens when the answer arrives from another
thread, and a cancelled dialog writes nothing. The macOS sheet itself needs a
manual check (Cmd+I, drag a file over the window, pick or cancel).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 22:54:56 +00:00
Claude ff56c5ad24 Audio: the short preview buffer is Linux-only and within the device's range (#614 follow-up)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 18:50:32 +00:00
Claude a3cc4d04b0 Merge pull request #614 from vbasky/fix/554-linux-audio-preview 2026-10-10 18:49:52 +00:00
Vikram Bhaskaran 139ff9a4e3 Start Linux audio preview after the first mixed samples, on a short device buffer.
Pulse and PipeWire were opening a large default period and playing silence until the feeder caught up, so the picture ran while the sound started late. The stream now waits for queued samples and requests about 10 ms of buffering.
2026-10-11 03:50:22 +11:00
Claude 4de3354806 Merge pull request #589 from JeremyYao/fix/amd-vulkan-launch-guard
The two test-only conflicts keep main's versions, which already carry the
same fixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 16:29:06 +00:00
Jeremy YaoandClaude Fable 5.1 d86c4aff52 Startup: a launch that stops as its window is shown switches the next to OpenGL
On an ASUS G513QY (Radeon RX 6800M, Adrenalin 26.9.2, Windows 11) every
launch died with STATUS_ACCESS_VIOLATION inside amdvlk64.dll, on a
driver worker thread, a moment after the first frame: eframe shows the
window it created hidden, the resulting resize re-creates the swapchain,
and the driver crashes there (same offset on two driver versions, with
the OBS/Steam/Epic Vulkan layers disabled, and with FIFO, immediate and
latency-1 presentation). DirectX 12 and OpenGL open the window fine.

A crash in a driver can't be caught, and the launch guard (#243) removed
its marker at the first frame, so this looked like a successful launch
every time and Window Graphics never switched. The marker now stays
until the window has kept drawing for SETTLE (3 s) or the app quits
normally before that; frame_drawn returns the time left and the app
asks for a repaint then, so an idle window settles too. The notice,
the Settings note and docs/preferences.md describe the new rule.

Verified on that machine with a scratch settings folder: launch 1
(Vulkan) crashed and left the marker, launch 2 switched to OpenGL with
the notice and closed with exit code 0, launch 3 stayed on OpenGL
without the notice.

Tests: effectcraft launch_guard
a_launch_that_stops_after_its_first_frame_switches_the_next_to_opengl
(a first frame then drop: the next launch gets GL and the notice; a
normal quit in that time leaves no marker), and the existing test now
asserts that the first frames don't settle a launch (marker present at
SETTLE/2, gone at SETTLE).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-10 09:36:59 -04:00
Claude 00e9e37c0a UI: the drop hint and drop errors go through the interface catalog; the Wayland notice points to the README (#447 follow-up)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:55:10 +00:00
Claude 63acbb1eb0 Merge pull request #447 from David-T-Campos/fix/footage-drag-drop
# Conflicts:
#	apps/effectcraft/src/main.rs
2026-10-10 12:54:44 +00:00
Claude ce743af717 Appearance: zbus follows eframe's version instead of an exact pin (#519 follow-up)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:54:31 +00:00
Claude d8c1711f52 Merge pull request #519 from luniiya/feat/system-appearance 2026-10-10 12:53:19 +00:00
Claude 8c2b464a4d Merge pull request #582 from LloydNicholson/macos-project-documents 2026-10-10 12:51:16 +00:00
Claude a12242c806 Format the merged community fixes (#561-#566 follow-up)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
2026-10-10 12:49:52 +00:00
lloydandClaude Opus 5.5 f041aa7782 macOS: projects open from Finder; .pcraft is PhotoCraft's again
The app bundle exported ai.storyteller.effectcraft.document with the
`.pcraft` extension, PhotoCraft's document format. Installing EffectCraft
took `.pcraft` over, and since EffectCraft declared no document types,
neither app was offered for PhotoCraft documents in Finder. EffectCraft's
own projects (.ecproj, .ecprojx) had no file type at all.

- Info.plist: the exported type now tags .ecproj and .ecprojx ("EffectCraft
  Project", conforming to public.data and public.content rather than
  public.image), and CFBundleDocumentTypes makes EffectCraft their owner.
- Finder double-click, Open With, Dock drops and `open -a EffectCraft
  x.ecproj` send a kAEOpenDocuments Apple event that winit 0.30 doesn't
  handle. Register it with the audited fmv-macos-events crate that
  PhotoCraft and PdfCraft use (it keeps the unsafe Objective-C interop out
  of this workspace). Opened paths go through the dropped-file handling, so
  a project opens after the unsaved-changes prompt and media is imported. A
  quit event closes the window.
- The event that launches the app arrives before the UI draws: the first
  frames skip the panels until the fonts are installed, which dropped it.
  The paths wait for EffectcraftApp::is_ready().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 14:22:22 +02:00
Nigel Ihza Firdausy da131fcd57 fix(app): open .ecprojx project copies passed on the command line (#528) 2026-10-10 15:51:14 +07:00
Luniiya fe27c375e3 feat: standardise system appearance modes with PhotoCraft 2026-10-10 02:15:26 +02:00
David Campos 95c7cf1f05 ui: import native file drops with drop-target hint (main.rs)
Add Wayland drop notice for unsupported file drops
2026-10-09 20:37:19 +04:00
bflatasticandClaude Opus 5.5 9da33c157e Plug-ins: ScriptUI Panels folder scripts dock as panels and reopen, as in After Effects
EffectCraft's extension points compared with After Effects' (public
user guide and Scripting Guide) are now in docs/plugins.md, which
becomes "Plug-ins and extensions": scripts, ScriptUI panels and effect
plug-ins, with a short guide and an example panel for writing your own.

ScriptUI panels already came from `Scripts/ScriptUI Panels/` in the
settings folder, were listed at the bottom of the Window menu and
docked as tabs. What was missing: After Effects reopens the panels
that were open when it quit. Now the open panels are remembered in
`scriptui_panels.json` in the settings folder (a panel is added when
it opens and dropped when its tab or its script closes it; quitting
leaves the list), and `window.restoreScriptPanels` opens them again;
the desktop and web apps run it at start-up. A panel whose script is
gone or fails is reported and forgotten, and the others still open.
Where a panel was docked isn't kept, as workspace layouts aren't saved
between launches.

Gaps recorded in plugins.md and gaps.md G8: the Startup and Shutdown
script folders, keyboard shortcuts for scripts, ExtendScript's
`#include` / `#target` directives and `.jsxbin`.

Test: open_panels_open_again_at_the_next_launch (fails before: no
restore command), a_panel_dropped_in_the_folder_is_listed_and_opens_as_a_panel
(script), panels_open_at_quit_dock_again_at_launch (UI: the restored
panel docks with its controls; closing the tab forgets it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:03:12 +07:00
bflatasticandClaude Opus 5.5 be926adb92 Render Queue: output files end in their format's extension once (#293)
Renders on macOS came out as `Comp 1.mov.ecproj`, and an image
sequence's every frame as `Comp 1_00001.png.ecproj`; another output
was `Comp 2.mov.mov`.

Cause: the save dialogs for anything but a project went through the
project dialog hook, which filters to `.ecproj`; macOS's save panel
appends the allowed extension to any other name. 0.4.0's Render Queue
Choose File… used it (#192 moved Output To to its own dialog since),
and Save Frame As, Save Current Preview, Export Lottie, Save a Copy As
XML, Collect Files, Watch Folder and the Premiere export form's Browse
still did. Nothing then fixed the name: Output To kept `.ecproj` (no
format claims it), and changing the format replaced only the last
extension (`Comp 2.mov.ecproj` → `Comp 2.mov.mov`). `[compName]` of a
comp named `Comp 2.mov` also doubled it.

Fix: `Hooks::save_dialog` asks the dialog for the default name's own
extension (`pick_save_file`), the project dialog only for projects or
on hosts without another (the web); the desktop dialog has no filter
for a name without an extension (folders). `OutputFormat::with_extension`
makes an output path end in the format's extension exactly once
(project extensions and repeats of the format's dropped, a missing one
added; `logo.png.mov` kept), used by Output To, format changes and
`resolve_output`, so existing projects and templates render to the
right name too. Output To picks the file type from the extension
before a stray `.ecproj`.

Test: output_names_end_in_the_format_extension_once (project),
output_to_ends_in_the_format_extension_once (engine) and
save_dialogs_offer_the_file_extension (ui); the engine and ui tests
fail with the fix reverted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 16:51:12 +07:00
Brandon ThomasandClaude Opus 5.5 11848da0a1 App: only a held lock means another launch is starting (#283 follow-up)
A filesystem without lock support returned an error from try_lock, which
read as 'held' and disabled crash detection for good.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:04:47 -04:00
prekabrekiandClaude Opus 5.5 384c8cc094 App: a second copy opening, or OpenGL that fails, no longer strands Window Graphics
Two copies opened close together made the second take the first's
launch-pending marker for a crash and switch Window Graphics to OpenGL.
Where OpenGL can't open a window (NVIDIA on X11: "gl not compatible with
provided surface"), every later launch then failed, with no way to reach
the setting.

The marker is now locked while its launch runs, so a locked marker is a
launch still opening, not a crash. And a window that fails to open on
OpenGL puts Window Graphics back to Automatic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:03:19 +02:00
bflatasticandClaude Opus 5.5 d554724aa4 App: a launch whose window never drew makes the next use OpenGL (#243)
On some older Intel integrated GPUs (UHD 600, UHD with 2020 drivers)
the graphics driver crashes EffectCraft as its window's DirectX 12 or
Vulkan device is created (exit code 0xC0000005): the process
disappears with no message, and only WGPU_BACKEND=gl helped. A driver
crash can't be caught, so each launch now leaves a marker in the
settings folder until its window draws. A launch that finds the
previous one's marker switches the new Settings ▸ Startup & Repair ▸
Window Graphics (Automatic / OpenGL) to OpenGL and says so in the
status bar. A window that fails to open says the next launch will try
OpenGL. WGPU_BACKEND still wins; macOS has no OpenGL backend, so it
never switches there.

Tests: a_launch_that_never_drew_switches_the_next_to_opengl (app),
window_graphics_is_validated (engine). Checked end to end with a
leftover marker: the app opened on OpenGL with the notice and cleared
the marker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:57:21 +07:00
bflatasticandClaude Opus 5.5 468ed0b297 Logging: RUST_LOG prints to stderr, and start-up logs its milestones (#234)
The logger kept warnings in memory and wrote to a file only after Help
▸ Enable Logging, and it ignored RUST_LOG. An app that never opens its
window (macOS 27 on Apple Silicon, #234) therefore left no trace. Now
RUST_LOG (a level, or env_logger-style `target=level` directives)
also prints what it lets through to stderr, including eframe, winit
and wgpu. The desktop app logs its start-up milestones: opening the
window, the graphics adapter, the app created, the first frame drawn,
the window being asked to close, and the window closed.

Test: rust_log_filters_by_level_and_target (engine logging). Checked
by running the app with RUST_LOG=info and quitting it over the control
channel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 13:32:16 +07:00
Claude 188cc06d2b App: the window's GPU device asks for what the adapter has (#198)
eframe's default device request asks for wgpu's default limits (8
storage buffers per stage and more). An older GPU such as Intel HD
Graphics 5500 can't meet them, so the device request failed before
EffectCraft ran, and the release build on Windows quit without a word.

The device now asks for the adapter's own limits (textures capped at
16384 px like the headless renderer). The compositor already checks
what it needs and composites on the CPU when the device can't run it.
If the window still can't open, a message dialog says why instead of
the app vanishing.

Test: device_limits_fit_the_adapter. Not checked on that GPU.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018gnTnH3Jmk5zr4tMq1Mc9f
2026-10-07 22:13:19 +00:00
Claude 24aed7f219 App: launching opens an empty project, not the demo (#204)
The desktop app opened the demo project whenever it wasn't given a
project file, so File ▸ New Composition on the Home screen added "Comp
4" to the three demo comps. As in After Effects, a launch now starts
with an empty Untitled Project. --demo opens the demo (Help ▸ Open
Demo Project and the Home screen tile still do); --empty is kept.

The arguments are parsed by a function now, with a test
(no_arguments_start_an_empty_project).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018gnTnH3Jmk5zr4tMq1Mc9f
2026-10-07 22:13:19 +00:00
BFlatandClaude Opus 5.5 f2b2fa811c Render Queue: clicking the Output To file name opens a save dialog (#192)
Clicking an item's Output To file name opened an inline editor on the
name template (`[compName].[fileExtension]`), so there was no way to
pick a folder from there. Choose File… in the menu beside it did open
a dialog, but the project save dialog: filtered to .ecproj and opening
wherever the OS chose.

As After Effects' Output Movie To, clicking the file name now opens a
save dialog at the current output (its folder and name) for the output
format's extension, and the chosen file becomes the output. Choose
File… opens the same dialog. Alt-click still edits the template in
place, and hosts without a save dialog (the web) keep the inline
editor. The desktop `pick_save_file` hook opens in the folder of a
default path.

Test: clicking_the_output_file_name_opens_the_save_dialog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 20:29:29 +07:00
Luskish 2fc7da7d29 Control: close the connection on input that isn't a request
A line that is not a JSON object with a string `method` (an HTTP request
line, other non-JSON text, a JSON array, invalid UTF-8, a line over 4 MiB)
now gets one error reply and the connection is closed, so a browser's
cross-origin fetch can't smuggle a command in its body. Connections are
capped at 16. Same transport as LightCraft (storytold/lightcraft#129) and
FilmCraft (storytold/filmcraft#123).
2026-10-06 22:54:21 -04:00
Dexter 94dbccf69f fix: contain GPU initialization and retire failed readbacks 2026-10-06 16:40:12 -05:00
BFlat c750b299cf Merge pull request #118 from storytold/claude/system-fonts-rmnw4m
G2: font menus list the installed fonts
2026-10-07 00:37:13 +07:00
Claude dda9961889 G2: font menus list the installed fonts
A Windows user reported that the Properties panel's font menu offered only the bundled Inter,
JetBrains Mono and Noto Serif. The system font folders were scanned only when a project asked for
a family the bundled fonts lack, so until then every font menu (Properties, Character, Essential
Graphics) and `file.findMissing {what: fonts}` saw the bundled families alone, on every
platform. Listing the families now scans the system fonts first, and the desktop app starts that
scan on a background thread at launch so the menus are complete when first opened.

The style menus in the Properties and Character panels list the chosen family's own styles
instead of a fixed Regular / Medium / SemiBold / Bold / Italic. Both menus build their lists only
while open.

New query for agents: `text.fonts {query?, rescan?}` (MCP tool `list_fonts`) lists every family
with its styles, origin (bundled / system / user) and own-language name; `rescan` picks up fonts
installed since launch.

Tests: a fresh-process test that the family list includes every family in the platform's font
folders without a prior scan (failed before), and `text.fonts` filtering, rescan and per-family
styles, and the `list_fonts` MCP tool.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019EjTYdt76hTG4Kh2CJFnCr
2026-10-06 15:14:55 +00:00
Brandon Thomas 633fbcfaeb Merge PR #71: Persist Japanese menu language in General settings 2026-10-06 08:42:00 -04:00
Brandon Thomas 98872a4690 Merge PR #95: Improve AE-style editing, easing fidelity and Windows GPU rendering 2026-10-06 08:41:33 -04:00
Brandon ThomasandClaude Opus 5.5 17b17bcce3 Windows packaging: Start Menu/Add-Remove icon, no console window, correct description
The MSI Icon id had no .ico/.exe extension, which Windows Installer needs for
advertised shortcuts and ARPPRODUCTICON, so both showed a blank icon. Release
builds of the desktop app are now GUI-subsystem (no console window; the CLI stays
a console program), the shortcut/summary description names what EffectCraft does, and
packaging-lint rejects an Icon id without an extension. Found in printcraft#57.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 07:51:06 -04:00
midasdf 25233abbcb G9: persist Japanese menu language without bundled fonts 2026-10-06 16:22:23 +09:00
Dexter 39e6907b5f G2: improve editing reliability and Windows rendering fidelity 2026-10-06 00:00:31 -05:00
bflatasticandClaude Opus 5.5 b424c321dc Fix #43: the AppImage's window shows the EffectCraft icon on Wayland
Wayland compositors take a window's icon from the desktop entry named by its app ID; the .deb,
.rpm and Flatpak install it, an AppImage installs nothing, so its window got the generic icon.
Started from an AppImage ($APPIMAGE), the app now writes a hidden (NoDisplay) desktop entry
pointing at it, and its 256 px icon, under $XDG_DATA_HOME (~/.local/share) before the window
opens. Nothing is written when an installed package or the user's own entry provides the ID;
the entry follows the AppImage when it moves; failures are only logged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:31:06 +07:00
bflatasticandClaude Opus 5.5 0286a49f0a Fix #68: open links in the system browser (Discord buttons, Help menu, Settings)
The desktop app built eframe without its `links` feature, so egui's open_url was a no-op
on native: the header and Home Discord buttons, Help menu links and Settings links did nothing.
Enabling it links the `webbrowser` crate (MIT OR Apache-2.0), which opens URLs with the
system browser on macOS, Windows and Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 23:26:29 +07: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 Thomas 339a05d771 Merge pull request #37 from storytold/pr/never-crash-clean-crates
Never crash: deny panic lints in the already-clean crates and apps
2026-10-04 15:34:52 -04: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 6144ca0804 Never crash: last-resort guard around command execution, and a logging panic hook
Session::execute runs every command (UI, CLI, control channel, MCP, scripts; file import,
export and save are commands too) through guard::guarded, which catch_unwinds a panic that
escapes the command and returns EngineError::Other("command `x` failed with an internal error
(...); it was stopped and your project is still open"). Edits work on a copy of the project, so
a command that panics mid-edit leaves the project untouched. The desktop app also installs a
panic hook that logs every panic through the app logger (then runs the default hook).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 13:27:33 -04:00
Brandon ThomasandClaude Opus 5.5 8a4a2bfc52 M13.14: lazy project open, non-blocking UI with large projects, bench --ops
- footage.check: background footage check after File > Open (Progress panel), not an undo step
- timeline: track-matte / parent menus built only while open (was O(n^2) per frame);
  expression-row lookup per layer; panels hold Arc<Comp> snapshots instead of deep clones
- Project panel: virtualised vertical scrolling, selection reveal, thumbnails rendered off
  the UI thread
- effectcraft-cli bench --ops (engine::perf + ui-egui::bench)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 11:49:55 -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 00eb951711 M13.1: ScriptUI frontend (dialogs, palettes, dockable panels), script menus, example plug-in, docs
- ui-egui: scriptui_view draws script windows at engine layout bounds; PanelKind::ScriptPanel; File ▸ Scripts and Window menu list scripts/panels (egui + native menus)
- examples/plugins/posterize-bands (WebAssembly, API v1); host plug-in tests; desktop loads <config>/Plug-ins
- MCP: script_ui and history tools; docs/plugins.md, agents.md, parity, architecture, ATTRIBUTION

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 04:24:01 -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 ThomasandClaude Opus 5.5 8404fead60 UI-8, UI-3: native macOS menu bar; timeline columns, search, reveal-add, UU, CTI snapping
Native menu bar (apps/effectcraft, muda, macOS only): the engine's After Effects
menu tree mirrored into NSMenu through a pure, serializable spec
(ui-egui native_menu: submenus, separators, live labels, check marks, enabled
state, Cmd/Ctrl/function-key shortcuts as accelerators, Open Recent). Hide /
Hide Others / Show All are macOS' predefined items (app.hideOthers/app.showAll
are real commands now, via NSApplication); Services added; About, Settings and
Quit dispatch our commands. State is pushed only when the session revision,
selection, history, settings or journal change; structural changes rebuild.
Activations dispatch the same command ids as the in-window bar; Edit
Cut/Copy/Paste/Select All/Undo/Redo act on a focused text field. Settings >
Appearance > Use In-Window Menu Bar on macOS switches back.

Timeline: column visibility from the column header's context menu (A/V
Features, Keys, Label, #, Comment, Switches, Modes, Parent & Link, In, Out,
Duration, Stretch; Source/Layer Name toggle), Comment editing
(layer.setComment), draggable In/Out/Duration cells, Stretch opens Time
Stretch; property search filters layers and reveals matching properties with
their groups; Shift+P/S/R/T/A/E/M/F/L/U add to the revealed properties; UU
reveals all modified properties; Shift-drag in the ruler snaps the CTI to keys,
in/out points, markers and the work area. Commands: timeline.column,
timeline.sourceName, timeline.search, timeline.revealAdd.*.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 22:21:08 -04:00