From 87bfaa8f1c3848d11f5d7ecdf723c6b3e96c38a6 Mon Sep 17 00:00:00 2001 From: nazar-gavrylyk Date: Fri, 6 Nov 2026 07:13:15 +0100 Subject: [PATCH] Preview: Cache Frames When Idle is on by default, as in After Effects A comp left alone for a second fills its RAM preview from the current time, so the first playback is cached instead of rendering frame by frame. Saved settings keep their value. Two UI tests that assumed the old default set it explicitly. --- crates/engine/src/settings/prefs/sections.rs | 2 +- crates/ui-egui/src/state.rs | 2 +- crates/ui-egui/tests/it/ui_comp_presets.rs | 2 ++ crates/ui-egui/tests/it/ui_preview_align.rs | 5 +++-- docs/preferences.md | 3 ++- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/engine/src/settings/prefs/sections.rs b/crates/engine/src/settings/prefs/sections.rs index 328f93bf4..9a9f4ab21 100644 --- a/crates/engine/src/settings/prefs/sections.rs +++ b/crates/engine/src/settings/prefs/sections.rs @@ -93,7 +93,7 @@ page!(Previews { /// Largest downsampling while playing back: `1/2`, `1/4`, `1/8`. adaptive_resolution_limit: String = "1/8".into(), show_internal_wireframes: bool = false, - cache_frames_when_idle: bool = false, + cache_frames_when_idle: bool = true, fast_previews: bool = false, /// `faster` or `moreAccurate`. zoom_quality: String = "moreAccurate".into(), diff --git a/crates/ui-egui/src/state.rs b/crates/ui-egui/src/state.rs index 612aa0a10..635b46acd 100644 --- a/crates/ui-egui/src/state.rs +++ b/crates/ui-egui/src/state.rs @@ -806,7 +806,7 @@ impl Default for UiState { home_learn: false, home_templates: false, align_to_selection: false, - cache_when_idle: false, + cache_when_idle: true, tracker_source: None, layer_panel: None, layer_view: None, diff --git a/crates/ui-egui/tests/it/ui_comp_presets.rs b/crates/ui-egui/tests/it/ui_comp_presets.rs index 3fda8a8cc..93cd02030 100644 --- a/crates/ui-egui/tests/it/ui_comp_presets.rs +++ b/crates/ui-egui/tests/it/ui_comp_presets.rs @@ -174,6 +174,8 @@ fn composition_settings_view_stays_put_when_it_scrolls() { #[test] fn composition_settings_refits_when_the_language_changes() { let mut s = Session::default(); + // Idle caching keeps repainting while it renders; this test waits for repaints to stop. + s.prefs.previews.cache_frames_when_idle = false; s.execute("comp.new", json!({"name": "Edit", "width": 2560, "height": 1440, "frameRate": 60, "duration": 4})).unwrap(); let mut h = Harness::builder() .with_size(egui::vec2(1600.0, 1000.0)) diff --git a/crates/ui-egui/tests/it/ui_preview_align.rs b/crates/ui-egui/tests/it/ui_preview_align.rs index 1469a5e9e..622df0397 100644 --- a/crates/ui-egui/tests/it/ui_preview_align.rs +++ b/crates/ui-egui/tests/it/ui_preview_align.rs @@ -238,8 +238,9 @@ fn cache_frames_when_idle_fills_the_work_area() { let mut h = harness(); let cid = h.state().session.active_comp_id().unwrap(); let cached = |h: &Harness<'_, EffectcraftApp>| h.state().frames.cached_frames(&h.state().shown_series(cid)).len(); - // Off: only a few frames ahead of the current time are prefetched (the work area is the - // whole 240 frames). + // Off (it is on by default): only a few frames ahead of the current time are prefetched (the + // work area is the whole 240 frames). + invoke(&mut h, "playback.cacheWhenIdle", json!({"value": false})); for _ in 0..120 { h.step(); std::thread::sleep(std::time::Duration::from_millis(2)); diff --git a/docs/preferences.md b/docs/preferences.md index 927b66788..de7e426bc 100644 --- a/docs/preferences.md +++ b/docs/preferences.md @@ -55,7 +55,8 @@ Commands (CLI, MCP, control channel): Adaptive Resolution drops to while you drag; a playing preview keeps the viewer's resolution) - `previews.cacheFramesWhenIdle`: Cache Frames When Idle (Composition ▸ Preview): after a second without input or edits, the viewer renders the work area into the RAM preview in the - background, from the current time on, until it is cached or the budget is full + background, from the current time on, until it is cached or the budget is full. On by default, + as in After Effects, so the first playback of a comp left alone for a second is already cached - `previews.fastPreviews`: Fast Previews (Draft 3D, Faster Effects) - `appearance.appearanceMode`: Appearance Mode (`auto` / `dark` / `light`). `auto` (Sync with System) follows the operating system's light or dark appearance while the app runs: on Linux the desktop app reads the XDG desktop portal (`org.freedesktop.appearance` `color-scheme`) once and then listens for its `SettingChanged` signal on a worker thread, repainting only when the value changes (nothing polls); `gsettings` runs at most once at start-up, by absolute path, when the portal gives no answer. Elsewhere it uses what the window system reports. With no answer it shows the dark theme. New installs stay `dark`; Sync with System is opt-in. The Tools bar's appearance button (a monitor, sun or moon) cycles Sync with System, Light and Dark (`view.theme.toggle`, Next Appearance Mode). - `appearance.darkTheme`: Dark Theme (`dark` / `darker`), shown in dark appearance