38 Commits
Author SHA1 Message Date
bflatastic 334bf0f785 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/engine/Cargo.toml
2026-10-30 17:22:12 +07:00
Kristian Myram a0ad0d5bbd #1829: recheck queued screenshot paths before writing 2026-10-30 08:45:51 +01:00
Claude 020d5cf980 Roto model loading: drop a load for an old choice, key viewer frames by the active model
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDvxCS8xcR28VArjzn1x7U
2026-10-30 08:43:32 +01:00
bflatastic 8af1df7093 Merge remote-tracking branch 'origin/main' into HEAD 2026-10-30 11:05:29 +07:00
bflatasticandClaude Opus 5.5 666d929b51 Merge main into #1342; carry main's Mute/Unmute Keyframes (keys.setMuted) into the shared key_menu, gated off on locked layers like the other edits (test covers it), delete_keys keeps locked keys selected and runs main's polystar sync, keep both sides' timeline tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 10:27:51 +07:00
BFlat a934abff07 Merge pull request #2642 from storytold/fix/1961-reveal-windows
Windows: Reveal in Explorer opens File Explorer, not the browser (#1961)
2026-10-30 10:19:20 +07:00
tylerjenningsw 7880fd0213 Merge main into enhance/audio-levels-link
# Conflicts:
#	crates/ui-egui/src/app/frame.rs
2026-10-29 22:59:39 -04:00
bflatasticandClaude Opus 5.5 b37847429c Windows: Reveal in Explorer opens File Explorer, not the browser (#1961)
Reveal in Explorer sent the folder as a file:/// URL, which egui opens
with the web browser on Windows. The frontend now opens file:// folders
in File Explorer on Windows (the engine already checks they are plain
folders); other platforms and other URLs are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 09:59:01 +07:00
bflatastic 310068215b Merge remote-tracking branch 'pr/1328' into HEAD 2026-10-30 09:27:11 +07:00
Kristian Myram 725750eabb #1328: sample the displayed frame and guard modal ownership 2026-10-30 03:23:57 +01:00
bflatastic 0ddcc676bb Merge main into #1328; i18n/ui.rs: keep both new pt-BR rows (Click to sample color, Export Scene to Blender...), add the pl row for main's new Polish catalog 2026-10-30 09:22:35 +07:00
tylerjenningsw 0138e0ec8a Merge main into enhance/audio-levels-link
# Conflicts:
#	crates/ui-egui/src/panels/timeline.rs
#	crates/ui-egui/src/state.rs
2026-10-29 22:09:27 -04:00
bflatastic 0c96a1a0bd Merge remote-tracking branch 'origin/main' into HEAD 2026-10-30 09:02:25 +07:00
bflatasticandClaude Opus 5.5 cb2b83ae86 Merge main into #2368; adapt main's ui_env_light_gpu test (#2436) to the async compositor build
The test opened its project before the window existed, so its 'GPU' frames could be the ones the CPU composited while the compositor was built. It now waits for the compositor (ui_gpu::wait_for_compositor, made pub(crate)) and then opens the project, as the PR does for ui_gpu.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 07:44:38 +07:00
bflatasticandClaude Opus 5.5 0967102432 Merge main into #2369; clean
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 07:41:47 +07:00
bflatastic 36fab2ab17 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/ui-egui/src/panels/dialogs.rs
#	crates/ui-egui/src/panels/dialogs_3d.rs
2026-10-30 07:10:59 +07:00
Jason LukerandClaude Opus 5.5 83bb74d21c UI: "Preparing the GPU compositor…" stays until the compositor is attached
The status line is the toast that clears itself after 5 s, so the
preparing notice went blank while the viewer was still on the CPU for the
rest of a cold-cache build (tens of seconds), though `init_gpu` says the
status bar tells the user so. draw_toast now leaves that one status up
while `gpu_initializing()`; `finish_gpu_build` clears it when the
compositor lands, and the worker's repaint brings that frame, so the
toast doesn't tick meanwhile. A click still dismisses it; every other
status clears as before.

Test: with the build held on its gate, 30 more steps (7.5 s) leave the
status as it was; before this change it was empty by then.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 16:10:41 -07:00
bflatastic 72a2c4a1bc Merge main into #1439; Preview checkbox moved into main's split comp_settings::show (tab_body), gradient editor keeps main's pub(super) to_color32 2026-10-30 06:03:52 +07:00
Jason LukerandClaude Fable 5.1 57adb3e3ed UI: open the window before the GPU compositor is built
`init_gpu` built the compositor on the UI thread in the first frame, and eframe shows the window
only after that frame has painted. The compositor's ~235 compute pipelines take tens of seconds to
compile on a cold Metal shader cache (first launch, after an OS update, after an update that touched
a shader): about 40 s of no window at all, measured 39–41 s on an M2 Max.

On the desktop the compositor is now built on a worker thread (`gpu-compositor`), inside the same
`catch_unwind`, and attached when its result arrives; the worker requests a repaint, so nothing
polls. Until then the viewer composites on the CPU, as it already does without a GPU, and the
status line and `help.systemInfo` say "Preparing the GPU compositor…". A device failure during the
build discards the result; a thread that can't be spawned, and the browser, build in place as
before. `Hooks::before_gpu_build` lets tests hold or fail the build; `gpu_initializing()` exposes
the pending state.

Measured (release, cold cache, A/B interleaved): time to the window 39.0/40.9 s → 1.9/0.5 s, and
the control channel answers right after; with a heavy project opened at launch 38.3 s → 0.64 s
(first frame 88 ms after the app was created). Warm: 776 → 355 ms. The compile itself is not
faster; #1705 (effect kernels on first use) is the complementary half.

Tests: the interface draws, composites a CPU frame and reports the preparing state while the build
is held on a gate, then attaches the compositor; a build that panics leaves the viewer on the CPU
with the reason; the existing GPU/CPU parity test waits for the asynchronous hand-over.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-29 15:43:42 -07:00
bflatastic 8d051b3e9a Merge remote-tracking branch 'origin/main' into HEAD 2026-10-30 05:42:41 +07:00
Jason LukerandClaude Fable 5.1 26e6145cee Footage: one watcher thread that wakes the interface only when a file changed, instead of a 2 s poll
Settings ▸ Import ▸ Reload Footage Changed on Disk used to spawn a stat thread every two seconds
from the UI thread, request a repaint 100 ms later to collect it, and request another repaint every
2 s in between, for every project with items, focused or not: the whole interface redrew on a timer
for footage that hadn't changed.

`footage_reload::Watcher` is one long-lived worker: the interface tells it what to watch (recomputed
when the project revision or the preference changes) and whether the window is in front; it stamps
the files every 2 s while the window is in front, every 10 s while another app has the front, at once
on focus regain and on a new set, and hands the stamps over — calling `ctx.request_repaint()` — only
when one differs from its last look. Nothing watched means the thread sleeps. `apply_stamps` and the
reload semantics are unchanged; `start_scan`/`poll_scan`/`Session::footage_scan` are gone. No new
dependencies: the stat loop is also what footage on a network share relies on, where FSEvents would
not report another machine's writes.

Tests: the watcher wakes the interface for the first stamps and for each change and never for an
unchanged file; behind another app it rests until the window is back; nothing watched is nothing
stamped and a new set is reported whole (and dropping it ends the thread); the host test
`the_watcher_notices_a_footage_file_changed_on_disk` saves a PSD from "another app" and sees it
reloaded once.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-29 15:41:53 -07:00
Kristian Myram f93d336f9d Graph Editor: protect selection tools and restore queue-close focus 2026-10-29 22:38:53 +01:00
pravdomilandClaude Opus 5.5 7fe5f5225f #595: RAM preview no longer stalls on a gap right after the playhead
Problem: pressing play on frames that still had to render left the playhead
standing still for seconds. The cache bar showed a gap of a few frames right
after the playhead while frames further ahead turned green, and playback
started only once the whole prefetch window was cached. The earlier #595
change (prefetch order, eviction) started the right frames first, but they
still finished last. Cache Frames When Idle left the same late-filling gaps.

Cause: prefetch frames render side by side on one rayon pool, and each
frame's own parallel loops run on that pool too. An idle thread steals a
piece of a frame that is rendering; when that piece waits on a nested
parallel loop, the thread picks up a queued frame job instead and renders
queued frames until the queue is empty. Only then does it return to the
piece it stole, so the frame that piece belongs to cannot finish while
frames keep being queued. The frames started first are the ones just ahead
of the playhead.

Fix: the frames of a playing preview and of Cache Frames When Idle render on
lanes: one single-thread pool per frame thread, one frame at a time each. A
lane's thread only ever works on its own frame, so no frame waits under
another. The shared pool keeps the viewer's frame, which still uses every
thread, and the few frames prefetched around it while paused. Queued frames
change hands when a preview starts or stops, or when the viewer shows one.
Idle caching takes every lane instead of half the pool's threads.

Tests: frames_started_first_are_done_first (a playing preview, idle
caching) and queued_frames_render_when_a_preview_starts_or_stops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 20:19:06 +01:00
BFlat 9cb5255575 Merge pull request #1177 from tylerjenningsw/fix/947-preview-opening-audio
Preview: preserve opening audio while preparing video playback (#947)
2026-10-30 01:20:53 +07:00
Claude de7c5760c8 Merge main into fix/1436-gradient-editor-preview
lib.rs and menus.rs were split (#2491): the dialog_state accessors, the undimmed canvas while a
dialog previews, and Escape-as-Cancel for the Gradient Editor and Preview move to app/window.rs,
app/frame.rs and menus/shortcuts.rs. Layer Styles' rollback keeps main's text-editor handling inside
the shared restore(). The dialog preview integration test joins the tests/it binary.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDvxCS8xcR28VArjzn1x7U
2026-10-29 10:00:59 +00:00
Claude eee8fa786c Merge main into fix/712-eyedroppers-everywhere
The Effect Controls viewer hook moved to effect_controls/viewer.rs and the frame loop to
app/frame.rs (#2491); the popup eyedropper is carried over as its own function there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RDvxCS8xcR28VArjzn1x7U
2026-10-29 09:48:05 +00:00
Vikram Bhaskaran 835a793096 Merge origin/main into fix/1089-fedora-fonts. 2026-10-29 17:11:12 +11:00
BFlat b0e202a6e5 Merge pull request #1762 from dotCooCoo/fix/macos-quit-crash
Fix #341: on macOS, a quit goes through `terminate:`
2026-10-29 10:10:16 +07:00
tylerjenningsw b758d7173e Timeline: chain links are rescoped after a shortcut or menu replaces the project (#2485) 2026-10-28 21:24:20 -04:00
tylerjenningsw 2314e8923f Timeline: chain links don't carry into a new or opened project (#2485) 2026-10-28 19:54:09 -04:00
dotCooCoo 0702cd23ee Merge main 2026-10-28 15:31:46 -07:00
dotCooCoo 5f560d7075 Merge #1762: Fix #341: on macOS, a quit goes through terminate:
# Conflicts:
#	Cargo.toml
#	crates/ui-egui/src/app/frame.rs
2026-10-28 15:31:45 -07:00
Dylan M. Taylor 6e72ab3b57 Refactor ui-egui for strict Clippy checks 2026-10-28 06:09:21 +00:00
dotCooCoo d4e33b2bda Fix #341: the platform quit runs last in App::logic
The merge of main put craft_quit::on_close_request inside
EffectcraftApp::tick, so the control channel, autosave, screenshots and the
desktop host's file dialogs still ran after it in the same logic callback.
The tick keeps the unsaved-changes check; each desktop host's logic now calls
panels::unsaved::quit_on_close last, after the device-loss close as well.
2026-10-27 22:46:27 -07:00
dotCooCoo 49ba71b0ce Merge main into fix/macos-quit-crash 2026-10-27 14:21:30 -07:00
tylerjenningsw 2dcd1b27a9 Merge remote-tracking branch 'origin/main' into fix/947-preview-opening-audio
# Conflicts:
#	crates/ui-egui/src/lib.rs
2026-10-27 14:13:31 -04:00
dotCooCoo 97ef73d592 Preserve bug fixes after main module moves and bound workspace migration 2026-10-27 07:45:09 -07:00
aiongg 03f5ba581d refactor(ui-egui): move EffectcraftApp methods to app/*.rs 2026-10-26 21:49:11 +00:00