mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-01 05:58:19 -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:
@@ -911,41 +911,7 @@ fn replace_with_solid(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
fn reload(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let items = items_p(s, p);
|
||||
if s.importer.is_none() {
|
||||
return Err(EngineError::Other("media import is not available in this build".into()));
|
||||
}
|
||||
let mut updates = vec![];
|
||||
for i in &items {
|
||||
if let Some(ItemKind::Footage(f)) = s.project.item(*i).map(|x| &x.kind) {
|
||||
// An image sequence picks up frames added to (or removed from) its run.
|
||||
let mut nf = match s.probe_footage(&f.path) {
|
||||
Ok(n) => n,
|
||||
Err(_) => Footage { missing: true, ..f.clone() },
|
||||
};
|
||||
// Keep the interpretation.
|
||||
nf.alpha = f.alpha;
|
||||
nf.loop_count = f.loop_count;
|
||||
nf.pixel_aspect = f.pixel_aspect;
|
||||
nf.start_timecode = f.start_timecode;
|
||||
if nf.kind == FootageKind::Sequence && f.kind == FootageKind::Sequence {
|
||||
nf.frame_rate = f.frame_rate;
|
||||
nf.native_rate = f.native_rate;
|
||||
nf.alphabetical = f.alphabetical;
|
||||
nf.sync_sequence_duration();
|
||||
}
|
||||
updates.push((*i, nf));
|
||||
}
|
||||
}
|
||||
let n = updates.len();
|
||||
s.edit("Reload Footage", None, |proj, _| {
|
||||
for (i, f) in updates {
|
||||
if let Some(it) = proj.item_mut(i) {
|
||||
it.kind = ItemKind::Footage(f);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
s.events.push(crate::Event::PurgeCaches);
|
||||
let n = crate::footage_reload::reload_items(s, &items)?;
|
||||
Ok(json!({"reloaded": n}))
|
||||
}
|
||||
|
||||
@@ -1009,6 +975,15 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
has_items,
|
||||
crate::footage_check::command
|
||||
),
|
||||
cmd!(
|
||||
"footage.reloadChanged",
|
||||
"Reload Changed Footage",
|
||||
[],
|
||||
None,
|
||||
"{} — reload the footage whose file changed on disk since it was last seen (size or modification time; Settings ▸ Import ▸ Reload Footage Changed on Disk runs this in the background); files seen for the first time are only remembered. Returns {files, reloaded}",
|
||||
has_items,
|
||||
crate::footage_reload::command
|
||||
),
|
||||
cmd!(
|
||||
"file.runScript",
|
||||
"Run Script File...",
|
||||
|
||||
Reference in New Issue
Block a user