Sample footage pixels in script expressions (#1000)
A script reading an expression that calls sampleImage on a footage layer got [0,0,0,0]: the script evaluator built its EvalCtx with EvalCtx::new, which has no footage source, so the renderer substituted transparent frames (solids and shapes stayed correct because they are procedural). Pass the session's footage source, as the app's renderer and diagnostics already do.
This commit is contained in:
parent
9efe75330c
commit
de26297c36
|
|
@ -468,6 +468,9 @@ fn value(s: &Session, a: &J) -> R {
|
|||
} else {
|
||||
let mut ctx = EvalCtx::new(&s.project, cid, c, t);
|
||||
ctx.expr = s.expr.as_deref();
|
||||
// Sample expressions (`sampleImage`) read footage through the session's source; without
|
||||
// it footage layers sample as transparent (#1000).
|
||||
ctx.footage = Some(s.footage.as_ref());
|
||||
ctx.value(l, p)
|
||||
};
|
||||
Ok(js_value(c, &v))
|
||||
|
|
|
|||
|
|
@ -731,6 +731,42 @@ fn import_options_sequence_picks_one_still_or_the_run() {
|
|||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// A flat green footage source, so `sampleImage` on a footage layer has known pixels.
|
||||
struct Flat;
|
||||
impl effectcraft_engine::render::FootageSource for Flat {
|
||||
fn frame(
|
||||
&self,
|
||||
_item: effectcraft_engine::project::ItemId,
|
||||
f: &effectcraft_engine::project::Footage,
|
||||
_t: effectcraft_engine::time::Tick,
|
||||
) -> Option<Arc<effectcraft_engine::render::Image>> {
|
||||
Some(Arc::new(effectcraft_engine::render::Image::filled(f.width.max(1), f.height.max(1), [0.0, 1.0, 0.0, 1.0])))
|
||||
}
|
||||
}
|
||||
|
||||
/// `sampleImage` on a footage layer reads the footage's pixels from a script, not transparent
|
||||
/// black: the expression evaluator needs the session's footage source (#1000).
|
||||
#[test]
|
||||
fn sample_image_reads_footage_pixels_in_scripts() {
|
||||
let mut s = session();
|
||||
s.footage = Arc::new(Flat);
|
||||
s.importer = Some(Arc::new(Stills));
|
||||
let out = ok(
|
||||
&mut s,
|
||||
r#"
|
||||
var comp = app.project.items.addComp("Scene", 640, 360, 1, 1, 25);
|
||||
comp.openInViewer();
|
||||
var img = comp.layers.add(app.project.importFile(new ImportOptions(new File("/tmp/ec-flat.png"))));
|
||||
img.name = "Img";
|
||||
var cc = comp.layers.addNull().property("ADBE Effect Parade").addProperty("ADBE Color Control").property(1);
|
||||
cc.expression = 'thisComp.layer("Img").sampleImage([32, 16], [0.5, 0.5], true, time);';
|
||||
var v = cc.valueAtTime(0, false);
|
||||
[v[0], v[1], v[2], v[3], cc.expressionError];
|
||||
"#,
|
||||
);
|
||||
assert_eq!(out.result, json!([0, 1, 0, 1, ""]), "green footage sampled, not transparent black");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary_file_io_preserves_all_byte_values() {
|
||||
let dir = std::env::temp_dir().join(format!("ec-script-binary-{}", std::process::id()));
|
||||
|
|
|
|||
Loading…
Reference in New Issue