Scripting: text range selectors resolve by match name and limit the animator (#837)

This commit is contained in:
MarekSpodBiedry committed 2026-10-11 19:13:39 +02:00
1 parent 67434e9038
commit 55f4d163f8
3 files changed
+47

No files matched your search

+7
View File
@@ -115,6 +115,13 @@ fn add_animator(s: &mut Session, p: &Value) -> Result<Value> {
if added == 0 && !kinds.is_empty() {
return Err(bad(C, "unknown animator property"));
}
// Like After Effects, a scripted animator has no selectors until the script adds one
// (addProperty("ADBE Text Selector")); a default 0-100% one would select every character.
if kinds.is_empty()
&& let Some(sels) = g.sub_mut("selectors")
{
sels.children.clear();
}
let uid = g.uid;
anims.children.push(g.into());
proj.next_id = next;
+18
View File
@@ -63,6 +63,11 @@ const TEXT: &[(&str, &str)] = &[
const TEXT_ANIMATOR: &[(&str, &str)] = &[("selectors", "ADBE Text Selectors"), ("properties", "ADBE Text Animator Properties")];
const TEXT_SELECTORS: &[(&str, &str)] =
&[("rangeSelector", "ADBE Text Selector"), ("wigglySelector", "ADBE Text Wiggly Selector"), ("expressionSelector", "ADBE Text Expressible Selector")];
const TEXT_RANGE_SELECTOR: &[(&str, &str)] = &[("start", "ADBE Text Percent Start"), ("end", "ADBE Text Percent End"), ("offset", "ADBE Text Percent Offset")];
const CAMERA: &[(&str, &str)] = &[
("zoom", "ADBE Camera Zoom"),
("dof", "ADBE Camera Depth of Field"),
@@ -412,6 +417,8 @@ pub fn node(chain: &[&Node]) -> String {
}
"text" if chain.len() == 2 => find(TEXT, id).map(str::to_string).unwrap_or_else(own),
"text" if pid == "animators" => "ADBE Text Animator".into(),
"text" if pid == "selectors" => find(TEXT_SELECTORS, id).map(str::to_string).unwrap_or_else(own),
"text" if pid == "rangeSelector" => find(TEXT_RANGE_SELECTOR, id).map(str::to_string).unwrap_or_else(own),
"text" if grand.map(|g| g.match_id()) == Some("animators") => find(TEXT_ANIMATOR, id).map(str::to_string).unwrap_or_else(own),
"cameraOptions" => find(CAMERA, id).map(str::to_string).unwrap_or_else(own),
"lightOptions" => find(LIGHT, id).map(str::to_string).unwrap_or_else(own),
@@ -458,4 +465,15 @@ mod tests {
assert_eq!(shape_kind("ADBE Vector Graphic - Fill"), Some("fill"));
assert_eq!(shape_kind("nope"), None);
}
#[test]
fn text_range_selector_names() {
let n = |m: &str| Node::from(effectcraft_project::PropGroup::new(1, m, m));
let (text, animators, animator, selectors, range, start, end, offset) =
(n("text"), n("animators"), n("animator"), n("selectors"), n("rangeSelector"), n("start"), n("end"), n("offset"));
assert_eq!(node(&[&text, &animators, &animator, &selectors, &range]), "ADBE Text Selector");
assert_eq!(node(&[&text, &animators, &animator, &selectors, &range, &start]), "ADBE Text Percent Start");
assert_eq!(node(&[&text, &animators, &animator, &selectors, &range, &end]), "ADBE Text Percent End");
assert_eq!(node(&[&text, &animators, &animator, &selectors, &range, &offset]), "ADBE Text Percent Offset");
}
}
+22
View File
@@ -730,3 +730,25 @@ fn import_options_sequence_picks_one_still_or_the_run() {
assert_eq!(kind_of(&s, "shot_[0001-0003].png"), FootageKind::Sequence);
let _ = std::fs::remove_dir_all(&dir);
}
/// A scripted text animator has only the selectors the script adds, and the Range Selector and
/// its Start/End/Offset resolve by After Effects match name (#837).
#[test]
fn scripted_text_range_selector_resolves_and_is_the_only_selector() {
let mut s = session();
let o = ok(
&mut s,
r#"
var c = app.project.items.addComp("Sel", 960, 300, 1, 3, 30);
var t = c.layers.addText("MOVARA");
var a = t.property("ADBE Text Properties").property("ADBE Text Animators").addProperty("ADBE Text Animator");
a.property("ADBE Text Animator Properties").addProperty("ADBE Text Opacity").setValue(0);
var sels = a.property("ADBE Text Selectors");
var sel = sels.addProperty("ADBE Text Selector");
sel.property("ADBE Text Percent Start").setValue(50);
var end = sel.property("ADBE Text Percent End").value;
[sels.numProperties, sel.matchName, sel.property("start").value, end, sel.property("ADBE Text Percent Offset").matchName]
"#,
);
assert_eq!(o.result, json!([1, "ADBE Text Selector", 50, 100, "ADBE Text Percent Offset"]));
}