mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 10:09:32 -06:00
Scripting: CompItem.saveFrameToPng writes the frame as a PNG (#816)
After Effects scripts save a comp frame with saveFrameToPng(time, file); EffectCraft only had the comp.saveFrameAs command, so the method was undefined. It now runs comp.saveFrameAs at the given comp time, after the same file-gate check as other script writes (Allow Scripts to Write Files). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
470ea7a3af
commit
a96c80788a
@@ -1600,6 +1600,14 @@ CompItem.prototype.constructor = CompItem;
|
||||
__call("essential.rename", { comp: this.__id, control: c[i - 1].id, name: String(name) });
|
||||
return String(name);
|
||||
};
|
||||
// After Effects' CompItem.saveFrameToPng(time, file): Composition ▸ Save Frame As ▸ File at
|
||||
// `time` (comp seconds), behind the scripting file gate like other writes (#816).
|
||||
P.saveFrameToPng = function (time, file) {
|
||||
var f = __str(file);
|
||||
if (!f) throw __err("saveFrameToPng: missing file");
|
||||
__file("write", f, "");
|
||||
__call("comp.saveFrameAs", { comp: this.__id, path: f, time: __num(time, "time") });
|
||||
};
|
||||
P.openInEssentialGraphics = function () { __call("comp.openInEssentialGraphics", { comp: this.__id }); };
|
||||
P.exportAsMotionGraphicsTemplate = function (overwrite, path) {
|
||||
var f = __str(path);
|
||||
|
||||
@@ -362,6 +362,29 @@ fn security_gate_for_files() {
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// #816: CompItem.saveFrameToPng writes the frame as a PNG, behind the file-write preference.
|
||||
#[test]
|
||||
fn save_frame_to_png_writes_behind_the_file_gate() {
|
||||
let dir = std::env::temp_dir().join(format!("ec-save-frame-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let png = dir.join("frame.png");
|
||||
let mut s = session();
|
||||
let code = format!(
|
||||
"var c = app.project.items.addComp('F', 40, 30, 1, 2, 25); c.layers.addSolid([1, 0, 0], 'S', 40, 30, 1); c.saveFrameToPng(1, new File({}))",
|
||||
serde_json::to_string(&png.to_string_lossy()).unwrap()
|
||||
);
|
||||
let o = run_code(&mut s, &code, "frame.jsx");
|
||||
assert!(o.error.expect("refused").message.contains("Allow Scripts to Write Files"));
|
||||
assert!(!png.exists() || std::fs::metadata(&png).unwrap().len() == 0);
|
||||
s.prefs.scripting.allow_scripts_write_files = true;
|
||||
ok(&mut s, &code);
|
||||
let bytes = std::fs::read(&png).unwrap();
|
||||
assert_eq!(&bytes[..8], b"\x89PNG\r\n\x1a\n");
|
||||
// IHDR width and height.
|
||||
assert_eq!((u32::from_be_bytes(bytes[16..20].try_into().unwrap()), u32::from_be_bytes(bytes[20..24].try_into().unwrap())), (40, 30));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// #590: a script can't give itself file and network access (or turn off the warning before
|
||||
/// executing files) by changing Settings ▸ Scripting & Expressions; the user still can.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user