Browse Source

Added proper zones

CPKreuz 1 year ago
parent
commit
1f25b0aeac

+ 8 - 0
src/PixiEditor.AvaloniaUI/Models/DocumentModels/DocumentUpdater.cs

@@ -173,6 +173,9 @@ internal class DocumentUpdater
             case CreateNodeFrame_ChangeInfo info:
             case CreateNodeFrame_ChangeInfo info:
                 ProcessCreateNodeFrame(info);
                 ProcessCreateNodeFrame(info);
                 break;
                 break;
+            case CreateNodeZone_ChangeInfo info:
+                ProcessCreateNodeZone(info);
+                break;
             case DeleteNodeFrame_ChangeInfo info:
             case DeleteNodeFrame_ChangeInfo info:
                 ProcessDeleteNodeFrame(info);
                 ProcessDeleteNodeFrame(info);
                 break;
                 break;
@@ -523,6 +526,11 @@ internal class DocumentUpdater
         doc.NodeGraphHandler.AddFrame(info.Id, info.NodeIds);
         doc.NodeGraphHandler.AddFrame(info.Id, info.NodeIds);
     }
     }
 
 
+    private void ProcessCreateNodeZone(CreateNodeZone_ChangeInfo info)
+    {
+        doc.NodeGraphHandler.AddZone(info.Id, info.StartId, info.EndId);
+    }
+
     private void ProcessDeleteNodeFrame(DeleteNodeFrame_ChangeInfo info)
     private void ProcessDeleteNodeFrame(DeleteNodeFrame_ChangeInfo info)
     {
     {
         doc.NodeGraphHandler.RemoveFrame(info.Id);
         doc.NodeGraphHandler.RemoveFrame(info.Id);

+ 2 - 1
src/PixiEditor.AvaloniaUI/Models/Handlers/INodeGraphHandler.cs

@@ -8,13 +8,14 @@ internal interface INodeGraphHandler
 {
 {
    public ObservableCollection<INodeHandler> AllNodes { get; }
    public ObservableCollection<INodeHandler> AllNodes { get; }
    public ObservableCollection<NodeConnectionViewModel> Connections { get; }
    public ObservableCollection<NodeConnectionViewModel> Connections { get; }
-   public ObservableCollection<NodeFrameViewModel> Frames { get; }
+   public ObservableCollection<NodeFrameViewModelBase> Frames { get; }
    public INodeHandler OutputNode { get; }
    public INodeHandler OutputNode { get; }
    public StructureTree StructureTree { get; }
    public StructureTree StructureTree { get; }
    public bool TryTraverse(Func<INodeHandler, bool> func);
    public bool TryTraverse(Func<INodeHandler, bool> func);
    public void AddNode(INodeHandler node);
    public void AddNode(INodeHandler node);
    public void RemoveNode(Guid nodeId);
    public void RemoveNode(Guid nodeId);
    public void AddFrame(Guid frameId, IEnumerable<Guid> nodeIds);
    public void AddFrame(Guid frameId, IEnumerable<Guid> nodeIds);
+   public void AddZone(Guid frameId, Guid startId, Guid endId);
    public void RemoveFrame(Guid frameId);
    public void RemoveFrame(Guid frameId);
    public void SetConnection(NodeConnectionViewModel connection);
    public void SetConnection(NodeConnectionViewModel connection);
    public void RemoveConnection(Guid nodeId, string property);
    public void RemoveConnection(Guid nodeId, string property);

+ 11 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Document/NodeGraphViewModel.cs

@@ -15,7 +15,7 @@ internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler
     public DocumentViewModel DocumentViewModel { get; }
     public DocumentViewModel DocumentViewModel { get; }
     public ObservableCollection<INodeHandler> AllNodes { get; } = new();
     public ObservableCollection<INodeHandler> AllNodes { get; } = new();
     public ObservableCollection<NodeConnectionViewModel> Connections { get; } = new();
     public ObservableCollection<NodeConnectionViewModel> Connections { get; } = new();
-    public ObservableCollection<NodeFrameViewModel> Frames { get; } = new();
+    public ObservableCollection<NodeFrameViewModelBase> Frames { get; } = new();
     public StructureTree StructureTree { get; } = new();
     public StructureTree StructureTree { get; } = new();
     public INodeHandler? OutputNode { get; private set; }
     public INodeHandler? OutputNode { get; private set; }
 
 
@@ -57,6 +57,16 @@ internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler
         Frames.Add(frame);
         Frames.Add(frame);
     }
     }
 
 
+    public void AddZone(Guid frameId, Guid startId, Guid endId)
+    {
+        var start = AllNodes.First(x => x.Id == startId);
+        var end = AllNodes.First(x => x.Id == endId);
+        
+        var zone = new NodeZoneViewModel(frameId, start, end);
+        
+        Frames.Add(zone);
+    }
+
     public void RemoveFrame(Guid guid)
     public void RemoveFrame(Guid guid)
     {
     {
         var frame = Frames.FirstOrDefault(x => x.Id == guid);
         var frame = Frames.FirstOrDefault(x => x.Id == guid);

+ 3 - 78
src/PixiEditor.AvaloniaUI/ViewModels/Nodes/NodeFrameViewModel.cs

@@ -7,89 +7,14 @@ using PixiEditor.Numerics;
 
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Nodes;
 namespace PixiEditor.AvaloniaUI.ViewModels.Nodes;
 
 
-internal class NodeFrameViewModel : ObservableObject
+internal sealed class NodeFrameViewModel : NodeFrameViewModelBase
 {
 {
-    private Guid id;
-    private VecD topLeft;
-    private VecD bottomRight;
-    private VecD size;
-    
-    public ObservableCollection<INodeHandler> Nodes { get; }
-
-    public Guid Id
-    {
-        get => id;
-        set => SetProperty(ref id, value);
-    }
-    
-    public VecD TopLeft
-    {
-        get => topLeft;
-        set => SetProperty(ref topLeft, value);
-    }
-
-    public VecD BottomRight
-    {
-        get => bottomRight;
-        set => SetProperty(ref bottomRight, value);
-    }
-
-    public VecD Size
-    {
-        get => size;
-        set => SetProperty(ref size, value);
-    }
-
-    public NodeFrameViewModel(Guid id, IEnumerable<INodeHandler> nodes)
-    {
-        Id = id;
-        Nodes = new ObservableCollection<INodeHandler>(nodes);
-
-        Nodes.CollectionChanged += OnCollectionChanged;
-        AddHandlers(Nodes);
-
-        CalculateBounds();
-    }
-
-    private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
+    public NodeFrameViewModel(Guid id, IEnumerable<INodeHandler> nodes) : base(id, nodes)
     {
     {
-        var action = e.Action;
-        if (action != NotifyCollectionChangedAction.Add && action != NotifyCollectionChangedAction.Remove && action != NotifyCollectionChangedAction.Replace && action != NotifyCollectionChangedAction.Reset)
-        {
-            return;
-        }
-        
-        AddHandlers((IEnumerable<NodeViewModel>)e.NewItems);
-        RemoveHandlers((IEnumerable<NodeViewModel>)e.OldItems);
-    }
-
-    private void AddHandlers(IEnumerable<INodeHandler> nodes)
-    {
-        foreach (var node in nodes)
-        {
-            node.PropertyChanged += NodePropertyChanged;
-        }
-    }
-
-    private void RemoveHandlers(IEnumerable<INodeHandler> nodes)
-    {
-        foreach (var node in nodes)
-        {
-            node.PropertyChanged -= NodePropertyChanged;
-        }
-    }
-
-    private void NodePropertyChanged(object? sender, PropertyChangedEventArgs e)
-    {
-        if (e.PropertyName != nameof(INodeHandler.PositionBindable))
-        {
-            return;
-        }
-        
         CalculateBounds();
         CalculateBounds();
     }
     }
 
 
-    private void CalculateBounds()
+    protected override void CalculateBounds()
     {
     {
         if (Nodes.Count == 0)
         if (Nodes.Count == 0)
         {
         {

+ 91 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Nodes/NodeFrameViewModelBase.cs

@@ -0,0 +1,91 @@
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using CommunityToolkit.Mvvm.ComponentModel;
+using PixiEditor.AvaloniaUI.Models.Handlers;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.AvaloniaUI.ViewModels.Nodes;
+
+public abstract class NodeFrameViewModelBase : ObservableObject
+{
+    private Guid id;
+    private VecD topLeft;
+    private VecD bottomRight;
+    private VecD size;
+    
+    public ObservableCollection<INodeHandler> Nodes { get; }
+
+    public Guid Id
+    {
+        get => id;
+        set => SetProperty(ref id, value);
+    }
+    
+    public VecD TopLeft
+    {
+        get => topLeft;
+        set => SetProperty(ref topLeft, value);
+    }
+
+    public VecD BottomRight
+    {
+        get => bottomRight;
+        set => SetProperty(ref bottomRight, value);
+    }
+
+    public VecD Size
+    {
+        get => size;
+        set => SetProperty(ref size, value);
+    }
+
+    public NodeFrameViewModelBase(Guid id, IEnumerable<INodeHandler> nodes)
+    {
+        Id = id;
+        Nodes = new ObservableCollection<INodeHandler>(nodes);
+
+        Nodes.CollectionChanged += OnCollectionChanged;
+        AddHandlers(Nodes);
+    }
+
+    private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
+    {
+        var action = e.Action;
+        if (action != NotifyCollectionChangedAction.Add && action != NotifyCollectionChangedAction.Remove && action != NotifyCollectionChangedAction.Replace && action != NotifyCollectionChangedAction.Reset)
+        {
+            return;
+        }
+        
+        AddHandlers((IEnumerable<NodeViewModel>)e.NewItems);
+        RemoveHandlers((IEnumerable<NodeViewModel>)e.OldItems);
+    }
+
+    private void AddHandlers(IEnumerable<INodeHandler> nodes)
+    {
+        foreach (var node in nodes)
+        {
+            node.PropertyChanged += NodePropertyChanged;
+        }
+    }
+
+    private void RemoveHandlers(IEnumerable<INodeHandler> nodes)
+    {
+        foreach (var node in nodes)
+        {
+            node.PropertyChanged -= NodePropertyChanged;
+        }
+    }
+
+    private void NodePropertyChanged(object? sender, PropertyChangedEventArgs e)
+    {
+        if (e.PropertyName != nameof(INodeHandler.PositionBindable))
+        {
+            return;
+        }
+        
+        CalculateBounds();
+    }
+
+    protected abstract void CalculateBounds();
+}

+ 71 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Nodes/NodeZoneViewModel.cs

@@ -0,0 +1,71 @@
+using PixiEditor.AvaloniaUI.Models.Handlers;
+using PixiEditor.Numerics;
+
+namespace PixiEditor.AvaloniaUI.ViewModels.Nodes;
+
+public sealed class NodeZoneViewModel : NodeFrameViewModelBase
+{
+    private INodeHandler start;
+    private INodeHandler end;
+    
+    public NodeZoneViewModel(Guid id, INodeHandler start, INodeHandler end) : base(id, [start, end])
+    {
+        this.start = start;
+        this.end = end;
+        
+        CalculateBounds();
+    }
+
+    protected override void CalculateBounds()
+    {
+        if (Nodes.Count == 0)
+        {
+            if (TopLeft == BottomRight)
+            {
+                BottomRight = TopLeft + new VecD(100, 100);
+            }
+            
+            return;
+        }
+
+        var bounds = GetBounds();
+        
+        var minX = bounds.Min(n => n.X);
+        var minY = bounds.Min(n => n.Y);
+        
+        var maxX = bounds.Max(n => n.Right);
+        var maxY = bounds.Max(n => n.Bottom);
+
+        TopLeft = new VecD(minX, minY);
+        BottomRight = new VecD(maxX, maxY);
+
+        Size = BottomRight - TopLeft;
+    }
+
+    private List<RectD> GetBounds()
+    {
+        var list = new List<RectD>();
+
+        const int defaultXOffset = -30;
+        const int defaultYOffset = -45;
+        
+        foreach (var node in Nodes)
+        {
+            if (node == start)
+            {
+                list.Add(new RectD(node.PositionBindable + new VecD(50, defaultYOffset), new VecD(100, 400)));
+                continue;
+            }
+
+            if (node == end)
+            {
+                list.Add(new RectD(node.PositionBindable + new VecD(defaultXOffset, defaultYOffset), new VecD(100, 400)));
+                continue;
+            }
+            
+            list.Add(new RectD(node.PositionBindable + new VecD(defaultXOffset, defaultYOffset), new VecD(200, 400)));
+        }
+        
+        return list;
+    }
+}

+ 3 - 0
src/PixiEditor.ChangeableDocument/ChangeInfos/NodeGraph/CreateNodeZone_ChangeInfo.cs

@@ -0,0 +1,3 @@
+namespace PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
+
+public record CreateNodeZone_ChangeInfo(Guid Id, Guid StartId, Guid EndId) : IChangeInfo;

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/CreateModifyImageNodePair_Change.cs

@@ -38,7 +38,7 @@ internal class CreateModifyImageNodePair_Change : Change
         {
         {
             CreateNode_ChangeInfo.CreateFromNode(start, "Modify Image"),
             CreateNode_ChangeInfo.CreateFromNode(start, "Modify Image"),
             CreateNode_ChangeInfo.CreateFromNode(end, "Modify Image"),
             CreateNode_ChangeInfo.CreateFromNode(end, "Modify Image"),
-            new CreateNodeFrame_ChangeInfo(zoneId, [startId, endId])
+            new CreateNodeZone_ChangeInfo(zoneId, startId, endId)
         };
         };
     }
     }
 
 
@@ -51,7 +51,7 @@ internal class CreateModifyImageNodePair_Change : Change
         return new List<IChangeInfo> { startChange, endChange, zoneChange };
         return new List<IChangeInfo> { startChange, endChange, zoneChange };
     }
     }
 
 
-    private DeleteNode_ChangeInfo RemoveNode(Document target, Guid id)
+    private static DeleteNode_ChangeInfo RemoveNode(Document target, Guid id)
     {
     {
         Node node = target.FindNodeOrThrow<Node>(id);
         Node node = target.FindNodeOrThrow<Node>(id);
         target.NodeGraph.RemoveNode(node);
         target.NodeGraph.RemoveNode(node);