Browse Source

Node view caching

Krzysztof Krysiński 2 months ago
parent
commit
b5e512333c

+ 2 - 2
src/PixiEditor/Styles/Templates/NodeView.axaml

@@ -39,7 +39,7 @@
                         </Border>
                         <Border Grid.Row="1" Background="{DynamicResource ThemeControlMidBrush}">
                             <StackPanel>
-                                <ItemsControl ItemsSource="{TemplateBinding Outputs}"
+                                <ItemsControl Name="PART_Outputs" ItemsSource="{TemplateBinding Outputs}"
                                               ClipToBounds="False">
                                     <ItemsControl.ItemContainerTheme>
                                         <ControlTheme TargetType="ContentPresenter">
@@ -47,7 +47,7 @@
                                         </ControlTheme>
                                     </ItemsControl.ItemContainerTheme>
                                 </ItemsControl>
-                                <ItemsControl ItemsSource="{TemplateBinding Inputs}" ClipToBounds="False">
+                                <ItemsControl Name="PART_Inputs" ItemsSource="{TemplateBinding Inputs}" ClipToBounds="False">
                                     <ItemsControl.ItemContainerTheme>
                                         <ControlTheme TargetType="ContentPresenter">
                                             <Setter Property="DataContext" Value="." />

+ 2 - 1
src/PixiEditor/Views/Nodes/ConnectionView.cs

@@ -67,6 +67,7 @@ internal class ConnectionView : TemplatedControl
         set { SetValue(OutputNodePositionProperty, value); }
     }
 
+    private Canvas? mainCanvas;
 
     static ConnectionView()
     {
@@ -102,7 +103,7 @@ internal class ConnectionView : TemplatedControl
             return default;
         }
 
-        Canvas canvas = this.FindAncestorOfType<NodeGraphView>().FindDescendantOfType<Canvas>();
+        Canvas canvas = mainCanvas ??= this.FindAncestorOfType<NodeGraphView>().FindDescendantOfType<Canvas>();
 
         if (property.Node is null || canvas is null)
         {

+ 0 - 1
src/PixiEditor/Views/Nodes/NodeGraphView.cs

@@ -239,7 +239,6 @@ internal class NodeGraphView : Zoombox.Zoombox
 
         Dispatcher.UIThread.Post(() =>
         {
-            nodeItemsControl.ItemsPanelRoot.Children.CollectionChanged += NodeItems_CollectionChanged;
             nodeViewsCache = nodeItemsControl.ItemsPanelRoot.Children.ToList();
             HandleNodesAdded(nodeViewsCache);
         });

+ 42 - 6
src/PixiEditor/Views/Nodes/NodeView.cs

@@ -1,4 +1,5 @@
 using System.Collections.ObjectModel;
+using System.Collections.Specialized;
 using System.Windows.Input;
 using Avalonia;
 using Avalonia.Controls;
@@ -6,6 +7,7 @@ using Avalonia.Controls.Metadata;
 using Avalonia.Controls.Primitives;
 using Avalonia.Input;
 using Avalonia.Media;
+using Avalonia.Threading;
 using Avalonia.VisualTree;
 using ChunkyImageLib;
 using PixiEditor.Helpers;
@@ -19,6 +21,8 @@ using PixiEditor.Views.Nodes.Properties;
 namespace PixiEditor.Views.Nodes;
 
 [PseudoClasses(":selected")]
+[TemplatePart("PART_Inputs", typeof(ItemsControl))]
+[TemplatePart("PART_Outputs", typeof(ItemsControl))]
 public class NodeView : TemplatedControl
 {
     public static readonly StyledProperty<INodeHandler> NodeProperty =
@@ -155,11 +159,41 @@ public class NodeView : TemplatedControl
     public static readonly StyledProperty<int> ActiveFrameProperty =
         AvaloniaProperty.Register<NodeView, int>("ActiveFrame");
 
+    private Dictionary<INodePropertyHandler, NodePropertyView> propertyViews = new();
+
+    private ItemsControl inputsControl;
+    private ItemsControl outputsControl;
+
     static NodeView()
     {
         IsSelectedProperty.Changed.Subscribe(NodeSelectionChanged);
     }
 
+    protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
+    {
+        base.OnApplyTemplate(e);
+
+        inputsControl = e.NameScope.Find<ItemsControl>("PART_Inputs");
+        outputsControl = e.NameScope.Find<ItemsControl>("PART_Outputs");
+
+        Dispatcher.UIThread.Post(
+            () =>
+        {
+            inputsControl.ItemsPanelRoot.Children.CollectionChanged += ChildrenOnCollectionChanged;
+            outputsControl.ItemsPanelRoot.Children.CollectionChanged += ChildrenOnCollectionChanged;
+
+            propertyViews.Clear();
+            propertyViews = this.GetVisualDescendants().OfType<NodePropertyView>()
+                .ToDictionary(x => (INodePropertyHandler)x.DataContext, x => x);
+        }, DispatcherPriority.Render);
+    }
+
+    private void ChildrenOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
+    {
+        propertyViews = this.GetVisualDescendants().OfType<NodePropertyView>()
+            .ToDictionary(x => (INodePropertyHandler)x.DataContext, x => x);
+    }
+
     protected override void OnPointerPressed(PointerPressedEventArgs e)
     {
         base.OnPointerPressed(e);
@@ -233,15 +267,17 @@ public class NodeView : TemplatedControl
 
     public NodeSocket GetSocket(INodePropertyHandler property)
     {
-        NodePropertyView propertyView = this.GetVisualDescendants().OfType<NodePropertyView>()
-            .FirstOrDefault(x => x.DataContext == property);
-
-        if (propertyView is null)
+        if (propertyViews.TryGetValue(property, out var view))
         {
-            return default;
+            if (view is null)
+            {
+                return default;
+            }
+
+            return property.IsInput ? view.InputSocket : view.OutputSocket;
         }
 
-        return property.IsInput ? propertyView.InputSocket : propertyView.OutputSocket;
+        return null;
     }
 
     public Point GetSocketPoint(INodePropertyHandler property, Canvas canvas)