Skip to content

Commit 4d8cf5d

Browse files
committed
get/set animation node state
1 parent dccecd6 commit 4d8cf5d

3 files changed

Lines changed: 105 additions & 2 deletions

File tree

MCPForUnity/Editor/Tools/Animation/ControllerCreate.cs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,105 @@ public static object AssignToGameObject(JObject @params)
422422
};
423423
}
424424

425+
// Reads node graph positions for every state in all layers (recurses into
426+
// sub-state-machines). Returns [{ name, x, y, layer }] so a caller can analyze
427+
// the current layout before sending back a revised one.
428+
public static object GetStatePositions(JObject @params)
429+
{
430+
var controller = LoadController(@params);
431+
if (controller == null)
432+
return ControllerNotFoundError(@params);
433+
434+
var nodes = new List<object>();
435+
for (int li = 0; li < controller.layers.Length; li++)
436+
CollectPositions(controller.layers[li].stateMachine, li, nodes);
437+
438+
return new
439+
{
440+
success = true,
441+
message = $"Read {nodes.Count} state position(s).",
442+
data = new { count = nodes.Count, nodes }
443+
};
444+
}
445+
446+
private static void CollectPositions(AnimatorStateMachine sm, int layer, List<object> outList)
447+
{
448+
var children = sm.states;
449+
for (int i = 0; i < children.Length; i++)
450+
outList.Add(new
451+
{
452+
name = children[i].state.name,
453+
x = children[i].position.x,
454+
y = children[i].position.y,
455+
layer
456+
});
457+
foreach (var sub in sm.stateMachines)
458+
CollectPositions(sub.stateMachine, layer, outList);
459+
}
460+
461+
// Sets node graph positions from a 'positions' array of { name, x, y }.
462+
// Matches states by name across all layers (recurses into sub-state-machines)
463+
// and reassigns stateMachine.states so the edits persist on the asset.
464+
public static object SetStatePositions(JObject @params)
465+
{
466+
var controller = LoadController(@params);
467+
if (controller == null)
468+
return ControllerNotFoundError(@params);
469+
470+
if (!(@params["positions"] is JArray positions) || positions.Count == 0)
471+
return new { success = false, message = "'positions' array is required: [{ name, x, y }, ...]" };
472+
473+
var want = new Dictionary<string, Vector2>();
474+
foreach (var token in positions)
475+
{
476+
string name = token["name"]?.ToString();
477+
if (string.IsNullOrEmpty(name))
478+
continue;
479+
float x = token["x"]?.ToObject<float>() ?? 0f;
480+
float y = token["y"]?.ToObject<float>() ?? 0f;
481+
want[name] = new Vector2(x, y);
482+
}
483+
if (want.Count == 0)
484+
return new { success = false, message = "No valid entries in 'positions' (each needs a 'name')." };
485+
486+
var matched = new HashSet<string>();
487+
for (int li = 0; li < controller.layers.Length; li++)
488+
ApplyPositions(controller.layers[li].stateMachine, want, matched);
489+
490+
EditorUtility.SetDirty(controller);
491+
AssetDatabase.SaveAssets();
492+
493+
var unmatched = want.Keys.Where(k => !matched.Contains(k)).ToList();
494+
return new
495+
{
496+
success = true,
497+
message = $"Positioned {matched.Count} state(s); {unmatched.Count} name(s) unmatched.",
498+
data = new
499+
{
500+
matched = matched.Count,
501+
requested = want.Count,
502+
unmatched
503+
}
504+
};
505+
}
506+
507+
private static void ApplyPositions(AnimatorStateMachine sm, Dictionary<string, Vector2> want, HashSet<string> matched)
508+
{
509+
var children = sm.states;
510+
for (int i = 0; i < children.Length; i++)
511+
{
512+
if (want.TryGetValue(children[i].state.name, out var p))
513+
{
514+
children[i].position = new Vector3(p.x, p.y, 0f);
515+
matched.Add(children[i].state.name);
516+
}
517+
}
518+
sm.states = children; // reassign so position edits persist
519+
520+
foreach (var sub in sm.stateMachines)
521+
ApplyPositions(sub.stateMachine, want, matched);
522+
}
523+
425524
private static AnimatorController LoadController(JObject @params)
426525
{
427526
string controllerPath = @params["controllerPath"]?.ToString();

MCPForUnity/Editor/Tools/Animation/ManageAnimation.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ private static object HandleControllerAction(JObject @params, string action)
217217
{
218218
case "create": return ControllerCreate.Create(@params);
219219
case "add_state": return ControllerCreate.AddState(@params);
220+
case "set_state_positions": return ControllerCreate.SetStatePositions(@params);
221+
case "get_state_positions": return ControllerCreate.GetStatePositions(@params);
220222
case "add_transition": return ControllerCreate.AddTransition(@params);
221223
case "add_parameter": return ControllerCreate.AddParameter(@params);
222224
case "get_info": return ControllerCreate.GetInfo(@params);
@@ -228,7 +230,7 @@ private static object HandleControllerAction(JObject @params, string action)
228230
case "create_blend_tree_2d": return ControllerBlendTrees.CreateBlendTree2D(@params);
229231
case "add_blend_tree_child": return ControllerBlendTrees.AddBlendTreeChild(@params);
230232
default:
231-
return new { success = false, message = $"Unknown controller action: {action}. Valid: create, add_state, add_transition, add_parameter, get_info, assign, add_layer, remove_layer, set_layer_weight, create_blend_tree_1d, create_blend_tree_2d, add_blend_tree_child" };
233+
return new { success = false, message = $"Unknown controller action: {action}. Valid: create, add_state, set_state_positions, get_state_positions, add_transition, add_parameter, get_info, assign, add_layer, remove_layer, set_layer_weight, create_blend_tree_1d, create_blend_tree_2d, add_blend_tree_child" };
232234
}
233235
}
234236

Server/src/services/tools/manage_animation.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
]
1616

1717
CONTROLLER_ACTIONS = [
18-
"controller_create", "controller_add_state", "controller_add_transition",
18+
"controller_create", "controller_add_state",
19+
"controller_set_state_positions", "controller_get_state_positions",
20+
"controller_add_transition",
1921
"controller_add_parameter", "controller_get_info", "controller_assign",
2022
"controller_add_layer", "controller_remove_layer", "controller_set_layer_weight",
2123
"controller_create_blend_tree_1d", "controller_create_blend_tree_2d", "controller_add_blend_tree_child",

0 commit comments

Comments
 (0)