mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-14 19:27:05 -04:00
MCP: set_property and add_keyframe take timeBase too (#522 follow-up)
Issue #257 names these tools: an agent can now give comp times on an offset layer through MCP, as it can through prop.addKey and keys.select. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01QiAJeFttZp83Fh7YuzAR5f
This commit is contained in:
2 files changed
+27
-1
No files matched your search
@@ -153,6 +153,20 @@ fn headless_workflow() {
|
||||
let mid = call_json(&mut s, "get_property", json!({"layer": l, "path": "transform/position", "time": 1.0}));
|
||||
assert!((mid["value"][0].as_f64().unwrap() - 160.0).abs() < 1.0, "{mid}");
|
||||
|
||||
// Comp-time keys on an offset layer (#257): the key lands where the Timeline shows it.
|
||||
call_json(&mut s, "execute_command", json!({"command": "layer.timing", "params": {"layer": l, "start": 1.0}}));
|
||||
let p = call_json(
|
||||
&mut s,
|
||||
"add_keyframe",
|
||||
json!({"layer": l, "path": "transform/scale", "keys": [{"time": 1.5, "value": [50, 50]}, {"time": 2.5, "value": [100, 100]}], "timeBase": "comp", "interpolation": "hold"}),
|
||||
);
|
||||
let times: Vec<f64> = p["keys"].as_array().unwrap().iter().map(|k| k["time"].as_f64().unwrap()).collect();
|
||||
assert!((times[0] - 0.5).abs() < 1e-6 && (times[1] - 1.5).abs() < 1e-6, "layer-time keys: {times:?}");
|
||||
assert_eq!(p["keys"][0]["out"], "Hold", "the comp-time keys were selected for the interpolation");
|
||||
call_json(&mut s, "set_property", json!({"layer": l, "path": "transform/scale", "value": [75, 75], "time": 3.0, "timeBase": "comp"}));
|
||||
let p = call_json(&mut s, "get_property", json!({"layer": l, "path": "transform/scale"}));
|
||||
assert!(p["keys"].as_array().unwrap().iter().any(|k| (k["time"].as_f64().unwrap() - 2.0).abs() < 1e-6), "{p}");
|
||||
|
||||
// Expression via set_property.
|
||||
let p = call_json(&mut s, "set_property", json!({"layer": l, "path": "transform/rotation", "expression": "time * 90"}));
|
||||
assert_eq!(p["expression"], "time * 90");
|
||||
|
||||
@@ -319,6 +319,9 @@ fn set_property(b: &mut Backend, a: &Value) -> Result<Reply> {
|
||||
match time {
|
||||
Some(t) => {
|
||||
p["time"] = t.clone();
|
||||
if let Some(tb) = get(a, "timeBase") {
|
||||
p["timeBase"] = tb.clone();
|
||||
}
|
||||
b.exec("prop.addKey", p)?;
|
||||
}
|
||||
None => {
|
||||
@@ -351,6 +354,9 @@ fn add_keyframe(b: &mut Backend, a: &Value) -> Result<Reply> {
|
||||
if let Some(v) = get(k, "value") {
|
||||
p["value"] = v.clone();
|
||||
}
|
||||
if let Some(tb) = get(a, "timeBase") {
|
||||
p["timeBase"] = tb.clone();
|
||||
}
|
||||
b.exec("prop.addKey", p)?;
|
||||
}
|
||||
let info = b.exec("prop.get", obj(&base))?;
|
||||
@@ -360,7 +366,11 @@ fn add_keyframe(b: &mut Backend, a: &Value) -> Result<Reply> {
|
||||
b.exec("comp.open", json!({"comp": c}))?;
|
||||
}
|
||||
let sel: Vec<Value> = keys.iter().map(|k| json!({"layer": info["layer"], "prop": info["uid"], "time": k["time"]})).collect();
|
||||
b.exec("keys.select", json!({"keys": sel}))?;
|
||||
let mut select = json!({"keys": sel});
|
||||
if let Some(tb) = get(a, "timeBase") {
|
||||
select["timeBase"] = tb.clone();
|
||||
}
|
||||
b.exec("keys.select", select)?;
|
||||
match interp.to_ascii_lowercase().as_str() {
|
||||
"easyease" | "ease" => b.exec("keys.easyEase", json!({}))?,
|
||||
"easyeasein" => b.exec("keys.easyEase", json!({"which": "in"}))?,
|
||||
@@ -628,6 +638,7 @@ static TOOLS: &[ToolDef] = &[
|
||||
json!({
|
||||
"layer": layer_s(), "path": path_s(), "value": value_s(), "comp": comp_s(),
|
||||
"time": {"type": "number", "description": "Keyframe time in seconds (layer time; equals comp time unless the layer is offset/stretched)."},
|
||||
"timeBase": {"type": "string", "enum": ["layer", "comp"], "description": "What `time` counts: layer time (the default) or comp time, as the Timeline shows it."},
|
||||
"expression": {"type": "string", "description": "Expression text; empty string removes the expression."}
|
||||
}),
|
||||
&["layer", "path"],
|
||||
@@ -644,6 +655,7 @@ static TOOLS: &[ToolDef] = &[
|
||||
json!({
|
||||
"layer": layer_s(), "path": path_s(), "comp": comp_s(),
|
||||
"time": {"type": "number", "description": "Key time in seconds (layer time)."},
|
||||
"timeBase": {"type": "string", "enum": ["layer", "comp"], "description": "What `time` counts: layer time (the default) or comp time, as the Timeline shows it."},
|
||||
"value": value_s(),
|
||||
"keys": {"type": "array", "items": {"type": "object", "properties": {"time": {"type": "number"}, "value": value_s()}, "required": ["time"]}, "description": "Several keys at once."},
|
||||
"interpolation": {"type": "string", "enum": ["linear", "bezier", "hold", "easyEase", "easyEaseIn", "easyEaseOut"]}
|
||||
|
||||
Reference in new issue
Block a user