Selaa lähdekoodia

Fixed connections disconnecting in graph view

flabbet 9 kuukautta sitten
vanhempi
commit
b61bd43c5d

+ 1 - 0
src/PixiEditor/Styles/Templates/NodeGraphView.axaml

@@ -17,6 +17,7 @@
                         </Flyout>
                         </Grid.ContextFlyout>
                         <ItemsControl ZIndex="1" ClipToBounds="False"
+                                      Name="PART_Nodes"
                                       ItemsSource="{Binding NodeGraph.AllNodes, RelativeSource={RelativeSource TemplatedParent}}">
                             <ItemsControl.ItemsPanel>
                                 <ItemsPanelTemplate>

+ 6 - 0
src/PixiEditor/Views/Nodes/ConnectionView.cs

@@ -87,6 +87,12 @@ internal class ConnectionView : TemplatedControl
             EndPoint = CalculateSocketPoint(OutputProperty);
         }, DispatcherPriority.Render);
     }
+    
+    public void UpdateSocketPoints()
+    {
+        StartPoint = CalculateSocketPoint(InputProperty);
+        EndPoint = CalculateSocketPoint(OutputProperty);
+    }
 
     private Point CalculateSocketPoint(BindingValue<NodePropertyViewModel> argsNewValue)
     {

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

@@ -7,6 +7,7 @@ using Avalonia.Controls.Presenters;
 using Avalonia.Controls.Primitives;
 using Avalonia.Input;
 using Avalonia.Media;
+using Avalonia.Threading;
 using Avalonia.VisualTree;
 using CommunityToolkit.Mvvm.Input;
 using PixiEditor.Helpers;
@@ -190,6 +191,9 @@ internal class NodeGraphView : Zoombox.Zoombox
     private Color _startingPropColor;
     private VecD _lastMouseClickPos;
 
+    private ItemsControl nodeItemsControl;
+    private ItemsControl connectionItemsControl;
+
     public static readonly StyledProperty<int> ActiveFrameProperty =
         AvaloniaProperty.Register<NodeGraphView, int>("ActiveFrame");
 
@@ -206,6 +210,52 @@ internal class NodeGraphView : Zoombox.Zoombox
         AllNodeTypeInfos = new ObservableCollection<NodeTypeInfo>(AllNodeTypes.Select(x => new NodeTypeInfo(x)));
     }
 
+    protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
+    {
+        base.OnApplyTemplate(e);
+        nodeItemsControl = e.NameScope.Find<ItemsControl>("PART_Nodes");
+        connectionItemsControl = e.NameScope.Find<ItemsControl>("PART_Connections");
+
+        Dispatcher.UIThread.Post(() =>
+        {
+            nodeItemsControl.ItemsPanelRoot.Children.CollectionChanged += Items_CollectionChanged;
+        });
+    }
+
+    private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+    {
+        if (e.Action == NotifyCollectionChangedAction.Add)
+        {
+            foreach (Control control in e.NewItems)
+            {
+                if (control is not ContentPresenter presenter)
+                {
+                    continue;
+                }
+
+                if (presenter.Child == null)
+                {
+                    presenter.PropertyChanged += OnPresenterPropertyChanged;
+                    continue;
+                }
+
+                NodeView nodeView = (NodeView)presenter.Child;
+                nodeView.PropertyChanged += NodeView_PropertyChanged;
+            }
+        }
+    }
+
+    private void OnPresenterPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
+    {
+        if (e.Property == ContentPresenter.ChildProperty)
+        {
+            if (e.NewValue is NodeView nodeView)
+            {
+                nodeView.PropertyChanged += NodeView_PropertyChanged;
+            }
+        }
+    }
+
     private void CreateNodeType(NodeTypeInfo nodeType)
     {
         var type = nodeType.NodeType;
@@ -323,6 +373,11 @@ internal class NodeGraphView : Zoombox.Zoombox
             isDraggingConnection = false;
             _hiddenConnection = null;
         }
+
+        if (e.Source is NodeView nodeView)
+        {
+            UpdateConnections(nodeView);
+        }
     }
 
     private IEnumerable<Type> GatherAssemblyTypes<T>()
@@ -365,6 +420,15 @@ internal class NodeGraphView : Zoombox.Zoombox
         }
     }
 
+    private void NodeView_PropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
+    {
+        if (e.Property == BoundsProperty)
+        {
+            NodeView nodeView = (NodeView)sender!;
+            UpdateConnections(nodeView);
+        }
+    }
+
     private NodeView FindNodeView(INodeHandler node)
     {
         return this.GetVisualDescendants().OfType<NodeView>().FirstOrDefault(x => x.Node == node);
@@ -395,6 +459,32 @@ internal class NodeGraphView : Zoombox.Zoombox
         startDragConnectionPoint = _previewConnectionLine.StartPoint;
     }
 
+    private void UpdateConnections(NodeView nodeView)
+    {
+        foreach (NodePropertyView propertyView in nodeView.GetVisualDescendants().OfType<NodePropertyView>())
+        {
+            NodePropertyViewModel property = (NodePropertyViewModel)propertyView.DataContext;
+            UpdateConnectionView(property);
+        }
+    }
+
+    private void UpdateConnectionView(NodePropertyViewModel? propertyView)
+    {
+        foreach (var connection in connectionItemsControl.ItemsPanelRoot.Children)
+        {
+            if (connection is ContentPresenter contentPresenter)
+            {
+                ConnectionView connectionView = (ConnectionView)contentPresenter.FindDescendantOfType<ConnectionView>();
+
+                if (connectionView.InputProperty == propertyView || connectionView.OutputProperty == propertyView)
+                {
+                    connectionView.UpdateSocketPoints();
+                    connectionView.InvalidateVisual();
+                }
+            }
+        }
+    }
+
     private void Dragged(PointerEventArgs e)
     {
         if (isDraggingNodes)