Prechádzať zdrojové kódy

Fix node zone not being calculated correctly on document creation

CPKreuz 2 týždňov pred
rodič
commit
6f722cb22a

+ 41 - 9
src/PixiEditor/Models/Structures/ObservableHashSet.cs

@@ -1,4 +1,5 @@
 using System.Collections;
 using System.Collections;
+using System.Collections.Immutable;
 using System.Collections.Specialized;
 using System.Collections.Specialized;
 using System.Runtime.Serialization;
 using System.Runtime.Serialization;
 
 
@@ -35,7 +36,7 @@ public class ObservableHashSet<T> : ISet<T>, IReadOnlySet<T>, IDeserializationCa
     public void Clear()
     public void Clear()
     {
     {
         setImplementation.Clear();
         setImplementation.Clear();
-        CallCollectionChanged(NotifyCollectionChangedAction.Reset);
+        CallCollectionChanged(NotifyCollectionChangedAction.Reset, Array.Empty<T>(), setImplementation.ToList());
     }
     }
 
 
     public bool Remove(T item)
     public bool Remove(T item)
@@ -50,28 +51,53 @@ public class ObservableHashSet<T> : ISet<T>, IReadOnlySet<T>, IDeserializationCa
         return isRemoved;
         return isRemoved;
     }
     }
 
 
+    /// <summary>
+    /// Not implemented
+    /// </summary>
+    /// <exception cref="NotSupportedException">This method is not implemented.</exception>
     public void ExceptWith(IEnumerable<T> other)
     public void ExceptWith(IEnumerable<T> other)
     {
     {
-        setImplementation.ExceptWith(other);
-        CallCollectionChanged(NotifyCollectionChangedAction.Reset);
+        throw new NotSupportedException();
     }
     }
 
 
+    /// <summary>
+    /// Not implemented
+    /// </summary>
+    /// <exception cref="NotSupportedException">This method is not implemented.</exception>
     public void IntersectWith(IEnumerable<T> other)
     public void IntersectWith(IEnumerable<T> other)
     {
     {
-        setImplementation.IntersectWith(other);
-        CallCollectionChanged(NotifyCollectionChangedAction.Reset);
+        throw new NotSupportedException();
     }
     }
 
 
+    /// <summary>
+    /// Not implemented
+    /// </summary>
+    /// <exception cref="NotSupportedException">This method is not implemented.</exception>
     public void SymmetricExceptWith(IEnumerable<T> other)
     public void SymmetricExceptWith(IEnumerable<T> other)
     {
     {
-        setImplementation.SymmetricExceptWith(other);
-        CallCollectionChanged(NotifyCollectionChangedAction.Reset);
+        throw new NotSupportedException();
     }
     }
 
 
     public void UnionWith(IEnumerable<T> other)
     public void UnionWith(IEnumerable<T> other)
     {
     {
-        setImplementation.UnionWith(other);
-        CallCollectionChanged(NotifyCollectionChangedAction.Reset);
+        var allOther = other.ToImmutableHashSet();
+        var addedOnly = allOther.Except(setImplementation);
+        
+        setImplementation.UnionWith(allOther);
+        CallCollectionChanged(
+            NotifyCollectionChangedAction.Reset, 
+            addedOnly.ToList());
+    }
+
+    public void ReplaceBy(IEnumerable<T> other)
+    {
+        var otherOriginal = other.ToHashSet();
+        var original = setImplementation.ToImmutableHashSet();
+        var removed = original.Except(otherOriginal);
+
+        setImplementation.Clear();
+        setImplementation.UnionWith(otherOriginal);
+        CallCollectionChanged(NotifyCollectionChangedAction.Replace, otherOriginal.ToList(), removed.ToList());
     }
     }
 
 
     public bool IsProperSubsetOf(IEnumerable<T> other) => setImplementation.IsProperSubsetOf(other);
     public bool IsProperSubsetOf(IEnumerable<T> other) => setImplementation.IsProperSubsetOf(other);
@@ -105,6 +131,12 @@ public class ObservableHashSet<T> : ISet<T>, IReadOnlySet<T>, IDeserializationCa
     private void CallCollectionChanged(NotifyCollectionChangedAction action) =>
     private void CallCollectionChanged(NotifyCollectionChangedAction action) =>
         CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action));
         CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action));
     
     
+    private void CallCollectionChanged(NotifyCollectionChangedAction action, IList added, IList removed) =>
+        CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, added, removed));
+
+    private void CallCollectionChanged(NotifyCollectionChangedAction action, IList changed) =>
+        CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, changed));
+
     private void CallCollectionChanged(NotifyCollectionChangedAction action, T item) =>
     private void CallCollectionChanged(NotifyCollectionChangedAction action, T item) =>
         CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, item));
         CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, item));
 
 

+ 2 - 0
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -379,6 +379,8 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
             factory.ResourceLocator = null;
             factory.ResourceLocator = null;
         }
         }
 
 
+        viewModel.NodeGraph.FinalizeCreation();
+
         return viewModel;
         return viewModel;
 
 
 
 

+ 42 - 1
src/PixiEditor/ViewModels/Document/NodeGraphViewModel.cs

@@ -19,6 +19,8 @@ namespace PixiEditor.ViewModels.Document;
 
 
 internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler, IDisposable
 internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler, IDisposable
 {
 {
+    private bool isFullyCreated;
+    
     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();
@@ -142,8 +144,11 @@ internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler, IDisposabl
         StructureTree.Update(this);
         StructureTree.Update(this);
     }
     }
 
 
-    private void UpdatesFramesPartOf(INodeHandler node)
+    public void UpdatesFramesPartOf(INodeHandler node)
     {
     {
+        if (!isFullyCreated)
+            return;
+
         var lastKnownFramesPartOf = node.Frames.OfType<NodeZoneViewModel>().ToHashSet();
         var lastKnownFramesPartOf = node.Frames.OfType<NodeZoneViewModel>().ToHashSet();
         var startLookup = Frames.OfType<NodeZoneViewModel>().ToDictionary(x => x.Start);
         var startLookup = Frames.OfType<NodeZoneViewModel>().ToDictionary(x => x.Start);
         var currentlyPartOf = new HashSet<NodeZoneViewModel>();
         var currentlyPartOf = new HashSet<NodeZoneViewModel>();
@@ -176,6 +181,42 @@ internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler, IDisposabl
         }
         }
     }
     }
 
 
+    public void FinalizeCreation()
+    {
+        if (isFullyCreated)
+            return;
+        
+        isFullyCreated = true;
+        
+        foreach (var nodeZoneViewModel in Frames.OfType<NodeZoneViewModel>())
+        {
+            UpdateNodesPartOf(nodeZoneViewModel);
+        }
+    }
+
+    private static void UpdateNodesPartOf(NodeZoneViewModel zone)
+    {
+        var currentlyPartOf = new HashSet<INodeHandler>([zone.Start, zone.End]);
+
+        foreach (var node in zone.Start
+                     .Outputs
+                     .SelectMany(x => x.ConnectedInputs)
+                     .Select(x => x.Node))
+        {
+            node.TraverseForwards((x, _, _) =>
+            {
+                if (x is IPairNodeEndViewModel)
+                    return false;
+
+                currentlyPartOf.Add(x);
+
+                return true;
+            });
+        }
+
+        zone.Nodes.ReplaceBy(currentlyPartOf);
+    }
+
     public void RemoveConnections(Guid nodeId)
     public void RemoveConnections(Guid nodeId)
     {
     {
         var connections = Connections
         var connections = Connections