M13.15: qa scenarios 1-4 (kinetic type, shape logo, compositing, tracking) and fixes

engine.batch + MCP batch tool; layer.newText/newShape name; prop.get evaluated
expression value; keys.select by path with errors; @uid paths; plain-JSON gradients;
addShapeItem/effect.apply return paths; unknown layers error; conform rescales
footage duration; render log name for [###]; render_frame transparent; clearer
mask errors; truncated groups in flat get_layer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas
2026-10-03 12:09:41 -04:00
co-authored by Claude Opus 5.5
parent 95766755f3
commit fecf054e5f
24 changed files with 1138 additions and 34 deletions
+5 -2
View File
@@ -1277,10 +1277,12 @@ impl RenderLog {
pub fn log_path(output: &str) -> String {
let p = std::path::Path::new(output);
let stem = p.file_stem().map(|s| s.to_string_lossy().to_string()).unwrap_or_default();
let mut stem: String = stem.replace("_[#####]", "").replace("[#####]", "");
let mut stem = stem;
if let Some(i) = stem.find('#') {
// The run of `#`s, with its brackets when it has them (`[###]`, `[#####]`).
let n = stem[i..].chars().take_while(|c| *c == '#').count();
stem.replace_range(i..i + n, "");
let (a, b) = if stem[..i].ends_with('[') && stem[i + n..].starts_with(']') { (i - 1, i + n + 1) } else { (i, i + n) };
stem.replace_range(a..b, "");
}
let stem = stem.trim_end_matches(['_', '.', ' ']);
let name = format!("{}_RenderLog.txt", if stem.is_empty() { "Render" } else { stem });
@@ -1529,6 +1531,7 @@ mod tests {
assert_eq!(log_path("/out/Main_[#####].png"), "/out/Main_RenderLog.txt");
assert_eq!(log_path("/out/a.mov"), "/out/a_RenderLog.txt");
assert_eq!(log_path("seq###.tif"), "seq_RenderLog.txt");
assert_eq!(log_path("gen/g_[###].png"), "gen/g_RenderLog.txt", "any bracketed run (M13.15)");
}
#[test]