Add double-click state node to open per-state sub-graph tab

- GetLayerName: also match _StateResult nodes for per-state layer naming
- PrefixStateMachineLayerNames: per-state layers get 3-level path prefix
  (e.g., "AnimGraph > Locomotion > Idle")
- TryOpenSubGraph: state nodes navigate to per-state sub-graph layer

Co-authored-by: LoogLong <86428208+LoogLong@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-03-03 12:15:40 +00:00
parent 22ba7668eb
commit 2711be76e0
2 changed files with 16 additions and 8 deletions

View File

@ -239,8 +239,8 @@ public class AnimGraphViewModel
/// <summary>
/// Renames state machine internal layers with a parent path prefix
/// (e.g., "AnimGraph > Locomotion") to avoid name collisions with
/// linked anim layer sub-graphs that may share the same base name.
/// (e.g., "AnimGraph > Locomotion" for the overview, or
/// "AnimGraph > Locomotion > Idle" for per-state sub-graphs).
/// </summary>
private static void PrefixStateMachineLayerNames(AnimGraphViewModel vm)
{
@ -272,7 +272,14 @@ public class AnimGraphViewModel
if (string.IsNullOrEmpty(smName))
continue;
if (smParentLayer.TryGetValue(smName, out var parentName))
if (!smParentLayer.TryGetValue(smName, out var parentName))
continue;
// Per-state layers have a name different from the machine name
// (named after the StateResult node's Name property)
if (!layer.Name.Equals(smName, StringComparison.OrdinalIgnoreCase))
layer.Name = $"{parentName}{SubGraphPathSeparator}{smName}{SubGraphPathSeparator}{layer.Name}";
else
layer.Name = $"{parentName}{SubGraphPathSeparator}{smName}";
}
}
@ -421,7 +428,8 @@ public class AnimGraphViewModel
private static string GetLayerName(List<AnimGraphNode> nodes, int index)
{
var rootNode = nodes.FirstOrDefault(n =>
n.ExportType.EndsWith("_Root", StringComparison.OrdinalIgnoreCase) &&
(n.ExportType.EndsWith("_Root", StringComparison.OrdinalIgnoreCase) ||
n.ExportType.EndsWith("_StateResult", StringComparison.OrdinalIgnoreCase)) &&
n.AdditionalProperties.TryGetValue("Name", out _));
if (rootNode != null &&
rootNode.AdditionalProperties.TryGetValue("Name", out var rootName) &&

View File

@ -563,10 +563,10 @@ public partial class AnimGraphViewer
}
else if (node.IsStateMachineState)
{
// State nodes within an overview: try to open internal per-state layer
// Internal layers share the state machine's path prefix name
// (future: individual state layers could be opened here)
return;
// State nodes within an overview: open the per-state internal sub-graph
// Per-state layers are named "overviewPath > stateName"
var overviewName = _currentLayerState?.Layer.Name ?? string.Empty;
layerName = $"{overviewName}{AnimGraphViewModel.SubGraphPathSeparator}{node.Name}";
}
else if (node.ExportType.Contains("StateMachine", StringComparison.OrdinalIgnoreCase))
{