MCP: get_property and get_layer list an enum property's options (#2085)

This commit is contained in:
Marco Arnulfo
2026-10-30 00:44:58 +01:00
parent a8d83b9717
commit 701d9df8a5
9 changed files with 59 additions and 10 deletions
+2 -2
View File
@@ -163,8 +163,8 @@ pub use enabled::always;
pub(crate) use enabled::{has_comp, has_keys, has_layers, has_project_selection, not_yet, not_yet_run};
pub use params::match_path_of;
pub(crate) use params::{
b_p, bad, comp_id, f_p, frontend, layer_mut, layer_p, layers_p, merge_p, resolve_effect_path, resolve_layer, selectable, selected_leaf_props, str_p,
time_p, unlocked, visible_p,
b_p, bad, comp_id, f_p, frontend, layer_mut, layer_p, layers_p, merge_p, popup_options, resolve_effect_path, resolve_layer, selectable,
selected_leaf_props, str_p, time_p, unlocked, visible_p,
};
pub use schema::{accepted_params, check_params, params_schema};
+2 -3
View File
@@ -999,9 +999,8 @@ fn list(_: &mut Session, p: &Value) -> Result<Value> {
json!({"id": e.id, "name": e.name, "category": e.category, "gpu": e.gpu, "float": e.float, "params": e.params.iter().map(|p| {
let mut out = json!({"id": p.id, "name": p.name, "type": p.default.kind_name(), "default": p.default.to_json()});
match &p.ui {
effectcraft_project::ParamUi::Popup { options } => {
// Engine/MCP popup values are zero-based; JSX exposes one-based values.
out["options"] = json!(options.iter().enumerate().map(|(value, label)| json!({"value": value, "label": label})).collect::<Vec<_>>());
effectcraft_project::ParamUi::Popup { .. } => {
out["options"] = super::popup_options(&p.ui).unwrap_or_default();
}
effectcraft_project::ParamUi::Slider { min, max, slider_min, slider_max, decimals } => {
out["min"] = json!(min);
+7
View File
@@ -58,6 +58,13 @@ pub(crate) fn selected_leaf_props(s: &Session) -> Vec<(LayerId, effectcraft_proj
out
}
/// A popup property's `[{value, label}]`, as `effect.list`, `prop.get` and `layer.tree` report it.
/// Engine/MCP popup values are zero-based; JSX exposes one-based values.
pub(crate) fn popup_options(ui: &effectcraft_project::ParamUi) -> Option<Value> {
let effectcraft_project::ParamUi::Popup { options } = ui else { return None };
Some(serde_json::json!(options.iter().enumerate().map(|(value, label)| serde_json::json!({"value": value, "label": label})).collect::<Vec<_>>()))
}
// ---------- params ----------
pub(crate) fn bad(cmd: &str, msg: impl Into<String>) -> EngineError {
+3
View File
@@ -491,6 +491,9 @@ fn get(s: &mut Session, p: &Value) -> Result<Value> {
"time": t.seconds(), "value": raw.to_json(), "animated": !pr.keys.is_empty(),
"keys": keys, "expression": pr.expr.as_ref().map(|e| e.text.clone()),
});
if let Some(o) = super::popup_options(&pr.ui) {
out["options"] = o;
}
// With an expression, `value` is the keyframed (pre-expression) value; also report what the
// expression makes of it (what renders), or why it fails. A disabled one renders `value`; one
// disabled by its syntax error (prop.setExpression) reports that error.
+3
View File
@@ -129,6 +129,9 @@ fn group_json(g: &PropGroup, path: &str, l: &Layer, t: effectcraft_time::Tick, d
if let Some(e) = &p.expr {
o["expression"] = json!(e.text);
}
if let Some(opts) = super::popup_options(&p.ui) {
o["options"] = opts;
}
o
}
Node::Group(g) => group_json(g, &cpath, l, t, depth + 1, max_depth),