Browse Source

Various fixes

Equbuxu 3 years ago
parent
commit
4049155bb6

+ 27 - 0
PixiEditor/Helpers/Converters/DockingManagerActiveContentConverter.cs

@@ -0,0 +1,27 @@
+using PixiEditor.Models.DataHolders;
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+
+namespace PixiEditor.Helpers.Converters
+{
+    class DockingManagerActiveContentConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value == null)
+                return DependencyProperty.UnsetValue;
+            if (value is Document document)
+                return document;
+            return DependencyProperty.UnsetValue;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is Document document)
+                return document;
+            return DependencyProperty.UnsetValue;
+        }
+    }
+}

+ 6 - 6
PixiEditor/Helpers/Converters/IndexOfConverter.cs

@@ -1,9 +1,8 @@
-using System;
+using PixiEditor.Models.Layers;
+using PixiEditor.ViewModels;
+using System;
 using System.Globalization;
 using System.Globalization;
-using System.Linq;
 using System.Windows.Data;
 using System.Windows.Data;
-using PixiEditor.Models.Layers;
-using PixiEditor.ViewModels;
 
 
 namespace PixiEditor.Helpers.Converters
 namespace PixiEditor.Helpers.Converters
 {
 {
@@ -13,7 +12,8 @@ namespace PixiEditor.Helpers.Converters
         {
         {
             if (value is Layer layer && ViewModelMain.Current.BitmapManager.ActiveDocument != null)
             if (value is Layer layer && ViewModelMain.Current.BitmapManager.ActiveDocument != null)
             {
             {
-                return ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.IndexOf(layer);
+                int index = ViewModelMain.Current.BitmapManager.ActiveDocument.Layers.IndexOf(layer);
+                return index;
             }
             }
 
 
             return Binding.DoNothing;
             return Binding.DoNothing;
@@ -24,4 +24,4 @@ namespace PixiEditor.Helpers.Converters
             throw new NotImplementedException();
             throw new NotImplementedException();
         }
         }
     }
     }
-}
+}

+ 25 - 6
PixiEditor/Helpers/Converters/LayersToStructuredLayersConverter.cs

@@ -4,6 +4,7 @@ using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
 using System.Globalization;
 using System.Globalization;
 using System.Linq;
 using System.Linq;
+using System.Windows;
 using System.Windows.Data;
 using System.Windows.Data;
 
 
 namespace PixiEditor.Helpers.Converters
 namespace PixiEditor.Helpers.Converters
@@ -12,7 +13,8 @@ namespace PixiEditor.Helpers.Converters
     public class LayersToStructuredLayersConverter : IMultiValueConverter
     public class LayersToStructuredLayersConverter : IMultiValueConverter
     {
     {
         private static StructuredLayerTree cachedTree;
         private static StructuredLayerTree cachedTree;
-        private List<Guid> lastLayers = new List<Guid>();
+        private List<Guid> lastLayerGuids = new List<Guid>();
+        private IList<Layer> lastLayers = new List<Layer>();
         private ObservableCollection<GuidStructureItem> lastStructure = new ObservableCollection<GuidStructureItem>();
         private ObservableCollection<GuidStructureItem> lastStructure = new ObservableCollection<GuidStructureItem>();
 
 
         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
@@ -24,18 +26,21 @@ namespace PixiEditor.Helpers.Converters
                     cachedTree = new StructuredLayerTree(layers, structure);
                     cachedTree = new StructuredLayerTree(layers, structure);
                 }
                 }
 
 
-                if (TryFindStructureDifferences(structure) || lastLayers.Count != layers.Count || LayerOrderIsDifferent(layers))
+                if (TryFindStructureDifferences(structure) ||
+                    lastLayerGuids.Count != layers.Count ||
+                    LayerOrderIsDifferent(layers) ||
+                    LayersAreDifferentObjects(layers, lastLayers))
                 {
                 {
                     cachedTree = new StructuredLayerTree(layers, structure);
                     cachedTree = new StructuredLayerTree(layers, structure);
-
-                    lastLayers = layers.Select(x => x.LayerGuid).ToList();
+                    lastLayers = layers;
+                    lastLayerGuids = layers.Select(x => x.LayerGuid).ToList();
                     lastStructure = structure.CloneGroups();
                     lastStructure = structure.CloneGroups();
                 }
                 }
 
 
                 return cachedTree.RootDirectoryItems;
                 return cachedTree.RootDirectoryItems;
             }
             }
 
 
-            return new StructuredLayerTree(null, null);
+            return DependencyProperty.UnsetValue;
         }
         }
         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
         {
         {
@@ -44,7 +49,21 @@ namespace PixiEditor.Helpers.Converters
         private bool LayerOrderIsDifferent(IList<Layer> layers)
         private bool LayerOrderIsDifferent(IList<Layer> layers)
         {
         {
             var guids = layers.Select(x => x.LayerGuid).ToArray();
             var guids = layers.Select(x => x.LayerGuid).ToArray();
-            return !guids.SequenceEqual(lastLayers);
+            return !guids.SequenceEqual(lastLayerGuids);
+        }
+
+        /// <summary>
+        /// This should trigger if you open and close the same files twice.
+        /// Even though the layers are technically the same, having two different objects screws things up down the line.
+        /// </summary>
+        private bool LayersAreDifferentObjects(IList<Layer> layers, IList<Layer> lastLayers)
+        {
+            for (int i = 0; i < layers.Count; i++)
+            {
+                if (layers[i] != lastLayers[i])
+                    return true;
+            }
+            return false;
         }
         }
         private bool TryFindStructureDifferences(LayerStructure structure)
         private bool TryFindStructureDifferences(LayerStructure structure)
         {
         {

+ 31 - 0
PixiEditor/Helpers/Extensions/Int32RectEx.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Windows;
+
+namespace PixiEditor.Helpers.Extensions
+{
+    static class Int32RectEx
+    {
+        public static Int32Rect Intersect(this Int32Rect rect, Int32Rect other)
+        {
+            int rectX2 = rect.X + rect.Width;
+            int rectY2 = rect.Y + rect.Height;
+
+            int otherX2 = other.X + other.Width;
+            int otherY2 = other.Y + other.Height;
+
+            int maxX1 = Math.Max(rect.X, other.X);
+            int maxY1 = Math.Max(rect.Y, other.Y);
+
+            int minX2 = Math.Min(rectX2, otherX2);
+            int minY2 = Math.Min(rectY2, otherY2);
+
+            int width = minX2 - maxX1;
+            int height = minY2 - maxY1;
+
+            if (width <= 0 || height <= 0)
+                return Int32Rect.Empty;
+
+            return new Int32Rect(maxX1, maxY1, width, height);
+        }
+    }
+}

+ 24 - 1
PixiEditor/Models/Controllers/LayerStackRenderer.cs

@@ -1,4 +1,5 @@
-using PixiEditor.Models.DataHolders;
+using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Layers.Utils;
 using PixiEditor.Models.Layers.Utils;
 using SkiaSharp;
 using SkiaSharp;
@@ -39,6 +40,7 @@ namespace PixiEditor.Models.Controllers
             this.layers = layers;
             this.layers = layers;
             this.structure = structure;
             this.structure = structure;
             layers.CollectionChanged += OnLayersChanged;
             layers.CollectionChanged += OnLayersChanged;
+            SubscribeToAllLayers(layers);
             Resize(width, height);
             Resize(width, height);
         }
         }
 
 
@@ -56,7 +58,9 @@ namespace PixiEditor.Models.Controllers
         public void SetNewLayersCollection(ObservableCollection<Layer> layers)
         public void SetNewLayersCollection(ObservableCollection<Layer> layers)
         {
         {
             layers.CollectionChanged -= OnLayersChanged;
             layers.CollectionChanged -= OnLayersChanged;
+            UnsubscribeFromAllLayers(this.layers);
             this.layers = layers;
             this.layers = layers;
+            SubscribeToAllLayers(layers);
             layers.CollectionChanged += OnLayersChanged;
             layers.CollectionChanged += OnLayersChanged;
             Update(new Int32Rect(0, 0, finalSurface.Width, finalSurface.Height));
             Update(new Int32Rect(0, 0, finalSurface.Width, finalSurface.Height));
         }
         }
@@ -69,6 +73,22 @@ namespace PixiEditor.Models.Controllers
             layers.CollectionChanged -= OnLayersChanged;
             layers.CollectionChanged -= OnLayersChanged;
         }
         }
 
 
+        private void SubscribeToAllLayers(ObservableCollection<Layer> layers)
+        {
+            foreach (var layer in layers)
+            {
+                layer.LayerBitmapChanged += OnLayerBitmapChanged;
+            }
+        }
+
+        private void UnsubscribeFromAllLayers(ObservableCollection<Layer> layers)
+        {
+            foreach (var layer in layers)
+            {
+                layer.LayerBitmapChanged -= OnLayerBitmapChanged;
+            }
+        }
+
         private void Update(Int32Rect dirtyRectangle)
         private void Update(Int32Rect dirtyRectangle)
         {
         {
             finalSurface.SkiaSurface.Canvas.Clear();
             finalSurface.SkiaSurface.Canvas.Clear();
@@ -85,6 +105,9 @@ namespace PixiEditor.Models.Controllers
             }
             }
             finalBitmap.Lock();
             finalBitmap.Lock();
             finalSurface.SkiaSurface.Draw(backingSurface.Canvas, 0, 0, Surface.ReplacingPaint);
             finalSurface.SkiaSurface.Draw(backingSurface.Canvas, 0, 0, Surface.ReplacingPaint);
+
+            dirtyRectangle = dirtyRectangle.Intersect(new Int32Rect(0, 0, finalBitmap.PixelWidth, finalBitmap.PixelHeight));
+
             finalBitmap.AddDirtyRect(dirtyRectangle);
             finalBitmap.AddDirtyRect(dirtyRectangle);
             finalBitmap.Unlock();
             finalBitmap.Unlock();
         }
         }

+ 4 - 1
PixiEditor/Models/Controllers/SingleLayerRenderer.cs

@@ -1,4 +1,5 @@
-using PixiEditor.Models.Layers;
+using PixiEditor.Helpers.Extensions;
+using PixiEditor.Models.Layers;
 using SkiaSharp;
 using SkiaSharp;
 using System;
 using System;
 using System.ComponentModel;
 using System.ComponentModel;
@@ -63,6 +64,8 @@ namespace PixiEditor.Models.Controllers
                     layer.OffsetY,
                     layer.OffsetY,
                     BlendingPaint);
                     BlendingPaint);
             }
             }
+            dirtyRectangle = dirtyRectangle.Intersect(new Int32Rect(0, 0, finalBitmap.PixelWidth, finalBitmap.PixelHeight));
+
             finalBitmap.AddDirtyRect(dirtyRectangle);
             finalBitmap.AddDirtyRect(dirtyRectangle);
             finalBitmap.Unlock();
             finalBitmap.Unlock();
         }
         }

+ 4 - 4
PixiEditor/Models/DataHolders/Document/Document.cs

@@ -204,12 +204,12 @@ namespace PixiEditor.Models.DataHolders
         {
         {
             if (anchor.HasFlag(AnchorPoint.Center))
             if (anchor.HasFlag(AnchorPoint.Center))
             {
             {
-                return Math.Abs((destWidth / 2) - (srcWidth / 2));
+                return (destWidth / 2) - (srcWidth / 2);
             }
             }
 
 
             if (anchor.HasFlag(AnchorPoint.Right))
             if (anchor.HasFlag(AnchorPoint.Right))
             {
             {
-                return Math.Abs(destWidth - srcWidth);
+                return destWidth - srcWidth;
             }
             }
 
 
             return 0;
             return 0;
@@ -219,12 +219,12 @@ namespace PixiEditor.Models.DataHolders
         {
         {
             if (anchor.HasFlag(AnchorPoint.Middle))
             if (anchor.HasFlag(AnchorPoint.Middle))
             {
             {
-                return Math.Abs((destHeight / 2) - (srcHeight / 2));
+                return (destHeight / 2) - (srcHeight / 2);
             }
             }
 
 
             if (anchor.HasFlag(AnchorPoint.Bottom))
             if (anchor.HasFlag(AnchorPoint.Bottom))
             {
             {
-                return Math.Abs(destHeight - srcHeight);
+                return destHeight - srcHeight;
             }
             }
 
 
             return 0;
             return 0;

+ 2 - 1
PixiEditor/Models/Layers/Layer.cs

@@ -14,7 +14,6 @@ namespace PixiEditor.Models.Layers
     [DebuggerDisplay("'{name,nq}' {width}x{height}")]
     [DebuggerDisplay("'{name,nq}' {width}x{height}")]
     public class Layer : BasicLayer
     public class Layer : BasicLayer
     {
     {
-        private const int SizeOfArgb = 4;
         private bool clipRequested;
         private bool clipRequested;
 
 
         private bool isActive;
         private bool isActive;
@@ -151,6 +150,7 @@ namespace PixiEditor.Models.Layers
             get => opacity;
             get => opacity;
             set
             set
             {
             {
+                opacity = value;
                 RaisePropertyChanged(nameof(OpacityUndoTriggerable));
                 RaisePropertyChanged(nameof(OpacityUndoTriggerable));
                 ViewModelMain.Current?.ToolsSubViewModel?.TriggerCacheOutdated();
                 ViewModelMain.Current?.ToolsSubViewModel?.TriggerCacheOutdated();
                 InvokeLayerBitmapChange();
                 InvokeLayerBitmapChange();
@@ -189,6 +189,7 @@ namespace PixiEditor.Models.Layers
             {
             {
                 offset = value;
                 offset = value;
                 RaisePropertyChanged("Offset");
                 RaisePropertyChanged("Offset");
+                InvokeLayerBitmapChange();
             }
             }
         }
         }
 
 

+ 2 - 1
PixiEditor/Views/MainWindow.xaml

@@ -31,6 +31,7 @@
             <converters:IsSpecifiedTypeConverter SpecifiedType="{x:Type tools:ZoomTool}" x:Key="IsZoomToolConverter"/>
             <converters:IsSpecifiedTypeConverter SpecifiedType="{x:Type tools:ZoomTool}" x:Key="IsZoomToolConverter"/>
             <converters:IsSpecifiedTypeConverter SpecifiedType="{x:Type tools:MoveViewportTool}" x:Key="IsMoveViewportToolConverter"/>
             <converters:IsSpecifiedTypeConverter SpecifiedType="{x:Type tools:MoveViewportTool}" x:Key="IsMoveViewportToolConverter"/>
             <converters:SKColorToMediaColorConverter x:Key="SKColorToMediaColorConverter"/>
             <converters:SKColorToMediaColorConverter x:Key="SKColorToMediaColorConverter"/>
+            <converters:DockingManagerActiveContentConverter x:Key="DockingManagerActiveContentConverter"/>
             <ResourceDictionary.MergedDictionaries>
             <ResourceDictionary.MergedDictionaries>
                 <ResourceDictionary Source="pack://application:,,,/ColorPicker;component/Styles/DefaultColorPickerStyle.xaml" />
                 <ResourceDictionary Source="pack://application:,,,/ColorPicker;component/Styles/DefaultColorPickerStyle.xaml" />
             </ResourceDictionary.MergedDictionaries>
             </ResourceDictionary.MergedDictionaries>
@@ -240,7 +241,7 @@
         </StackPanel>
         </StackPanel>
         <Grid Grid.Column="1" Grid.Row="2" Background="#303030">
         <Grid Grid.Column="1" Grid.Row="2" Background="#303030">
             <Grid AllowDrop="True" Drop="MainWindow_Drop">
             <Grid AllowDrop="True" Drop="MainWindow_Drop">
-                <DockingManager ActiveContent="{Binding BitmapManager.ActiveDocument, Mode=TwoWay}" 
+                <DockingManager ActiveContent="{Binding BitmapManager.ActiveDocument, Mode=TwoWay, Converter={StaticResource DockingManagerActiveContentConverter}}" 
                                            DocumentsSource="{Binding BitmapManager.Documents}">
                                            DocumentsSource="{Binding BitmapManager.Documents}">
                     <DockingManager.Theme>
                     <DockingManager.Theme>
                         <avalonDockTheme:PixiEditorDockTheme />
                         <avalonDockTheme:PixiEditorDockTheme />

+ 13 - 0
PixiEditorTests/ModelsTests/DataHoldersTests/SurfaceTests.cs

@@ -91,5 +91,18 @@ namespace PixiEditorTests.ModelsTests.DataHoldersTests
             int offset = (30 * 5 + 5) * 4;
             int offset = (30 * 5 + 5) * 4;
             Assert.Equal(greenColor, new SKColor(pixels[2 + offset], pixels[1 + offset], pixels[0 + offset], pixels[3 + offset]));
             Assert.Equal(greenColor, new SKColor(pixels[2 + offset], pixels[1 + offset], pixels[0 + offset], pixels[3 + offset]));
         }
         }
+
+        [Fact]
+        public void TestSurfaceFromWriteableBitmap()
+        {
+            using Surface original = new Surface(30, 30);
+            original.SkiaSurface.Canvas.Clear(SKColors.Transparent);
+            original.SkiaSurface.Canvas.DrawRect(5, 5, 20, 20, redPaint);
+            original.SkiaSurface.Canvas.DrawRect(10, 10, 20, 20, greenPaint);
+            using Surface fromWriteable = new Surface(original.ToWriteableBitmap());
+            Assert.Equal(original.GetSRGBPixel(0, 0), fromWriteable.GetSRGBPixel(0, 0));
+            Assert.Equal(original.GetSRGBPixel(6, 6), fromWriteable.GetSRGBPixel(6, 6));
+            Assert.Equal(original.GetSRGBPixel(15, 15), fromWriteable.GetSRGBPixel(15, 15));
+        }
     }
     }
 }
 }