mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-11 16:33:01 -06:00
Reload Footage shows new pixels and keeps Photoshop layers; Reload Footage Changed on Disk
Reload Footage (Cmd+Alt+L) updated an item's metadata but left the media pool's decoded frames and the layer cache in place, so the old image kept rendering until Edit > Purge. It also replaced the footage with a probe of the merged document, so a Photoshop layer item lost its layer and its Retain Layer Sizes bounds. Reload now re-reads only what the file decides (size, a movie's duration, streams and frame rate, codec, a data file's text), keeps the layer or page and the interpretation, finds a Photoshop layer again by name, and makes the media layer forget the file (FootageSource::forget, which also drops the EXR aux-channel cache) and clears the layer cache. Settings > Import > Reload Footage Changed on Disk (on by default): the desktop app stamps footage files (size + modification time) on a worker thread every two seconds and when the window comes back to the front, and reloads what changed. Not an undo step and it doesn't modify the project; a file still being written is retried on the next check. footage.reloadChanged runs one check (CLI, MCP, agents). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ pub mod commands;
|
||||
pub mod config;
|
||||
pub mod demo;
|
||||
pub mod footage_check;
|
||||
pub mod footage_reload;
|
||||
pub mod guard;
|
||||
pub mod history;
|
||||
pub mod jobs;
|
||||
@@ -101,6 +102,13 @@ pub trait Services: Send + Sync {
|
||||
fn exists(&self, path: &str) -> bool {
|
||||
std::path::Path::new(path).exists()
|
||||
}
|
||||
/// A file's size and modification time (nanoseconds since 1970), to notice that it changed
|
||||
/// on disk (Settings ▸ Import ▸ Reload Footage Changed on Disk); `None` when it can't be read.
|
||||
fn stamp(&self, path: &str) -> Option<(u64, u128)> {
|
||||
let meta = std::fs::metadata(path).ok()?;
|
||||
let modified = meta.modified().ok()?.duration_since(std::time::UNIX_EPOCH).ok()?;
|
||||
Some((meta.len(), modified.as_nanos()))
|
||||
}
|
||||
/// Keep a file the app made for itself (footage extracted from a template): like
|
||||
/// [`Services::write_file`], creating its folder, but never offered as a download (web: it
|
||||
/// goes to browser storage only).
|
||||
@@ -459,6 +467,11 @@ pub struct Session {
|
||||
/// event loop (the desktop app) turn this on; headless sessions run `footage.check` when
|
||||
/// they want it.
|
||||
pub check_footage_on_open: bool,
|
||||
/// Each footage file's size and modification time when last seen (Settings ▸ Import ▸
|
||||
/// Reload Footage Changed on Disk, [`footage_reload`]).
|
||||
pub footage_stamps: std::collections::HashMap<String, footage_reload::Stamp>,
|
||||
/// The stamps being taken on a worker thread ([`footage_reload::start_scan`]).
|
||||
pub footage_scan: Option<footage_reload::Scan>,
|
||||
}
|
||||
|
||||
/// A thumbnail render ([`Session::thumbnail_job`]): (width, height, RGBA8).
|
||||
@@ -544,6 +557,8 @@ impl Default for Session {
|
||||
next_task_id: 1,
|
||||
learn: None,
|
||||
check_footage_on_open: false,
|
||||
footage_stamps: Default::default(),
|
||||
footage_scan: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user