From faea101c9bcc93486be3093079134a00a00df9e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Mar 2026 08:47:00 +0000 Subject: [PATCH] Center SaveCachedPose node in view when navigating from UseCachedPose When double-clicking a UseCachedPose node to jump to the SaveCachedPose node's tab, the view now centers on the target node. Added CenterOnNode helper that adjusts TranslateTransform to place the node at the viewport center while preserving the current zoom level. Co-authored-by: LoogLong <86428208+LoogLong@users.noreply.github.com> --- FModel/Views/AnimGraphViewer.xaml.cs | 36 +++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/FModel/Views/AnimGraphViewer.xaml.cs b/FModel/Views/AnimGraphViewer.xaml.cs index 471f90a9..677b7aa4 100644 --- a/FModel/Views/AnimGraphViewer.xaml.cs +++ b/FModel/Views/AnimGraphViewer.xaml.cs @@ -810,7 +810,7 @@ public partial class AnimGraphViewer else AddLayerTab(targetLayer); - // Select and highlight the SaveCachedPose node in the target layer. + // Select, highlight, and center the SaveCachedPose node in the target layer. // Use Dispatcher.BeginInvoke to ensure the visual tree is fully updated // after the tab switch before attempting to select the node. Dispatcher.BeginInvoke(() => @@ -819,6 +819,7 @@ public partial class AnimGraphViewer state.NodeVisuals.TryGetValue(savePoseNode, out var visual)) { SelectNode(savePoseNode, visual.border); + CenterOnNode(savePoseNode, state); } }); } @@ -1504,6 +1505,39 @@ public partial class AnimGraphViewer ZoomText.Text = "Zoom: 100%"; } + /// + /// Adjusts the translate transform so that the specified node is centered + /// in the viewport, keeping the current zoom level unchanged. + /// + private void CenterOnNode(AnimGraphNode node, LayerCanvasState state) + { + if (!state.NodePositions.TryGetValue(node, out var pos)) + return; + + var scale = state.ScaleTransform.ScaleX; + + // Determine node dimensions + double nodeW = NodeWidth, nodeH = 150; + if (state.NodeVisuals.TryGetValue(node, out var vis)) + { + nodeW = vis.width; + nodeH = vis.height; + } + + // Viewport size + var tabContent = LayerTabControl.SelectedContent as FrameworkElement; + var viewWidth = tabContent?.ActualWidth > 0 ? tabContent.ActualWidth : (ActualWidth > 0 ? ActualWidth * DefaultGraphWidthRatio : 800); + var viewHeight = tabContent?.ActualHeight > 0 ? tabContent.ActualHeight : (ActualHeight > 0 ? ActualHeight - 120 : 600); + + // Center of the node in graph space + var nodeCenterX = pos.X + nodeW / 2; + var nodeCenterY = pos.Y + nodeH / 2; + + // Set translate so that the node center maps to the viewport center + state.TranslateTransform.X = viewWidth / 2 - nodeCenterX * scale; + state.TranslateTransform.Y = viewHeight / 2 - nodeCenterY * scale; + } + /// /// Holds per-layer canvas state (positions, visuals, transforms). ///