Browse Source

Revert "Merge branch 'rect-based-undo' into palettes"

This reverts commit e3a526891ec2253093ef75c56f7f086d86240736.
flabbet 3 years ago
parent
commit
64170444bc

+ 18 - 19
PixiEditor/Models/Tools/BitmapOperationTool.cs

@@ -1,11 +1,9 @@
-using System;
-using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Undo;
 using SkiaSharp;
 using System.Collections.Generic;
-using PixiEditor.Models.Tools.ToolSettings.Settings;
 
 namespace PixiEditor.Models.Tools
 {
@@ -54,25 +52,26 @@ namespace PixiEditor.Models.Tools
         private void InitializeStorageBasedChange(SKRectI toolSessionRect)
         {
             Document doc = ViewModels.ViewModelMain.Current.BitmapManager.ActiveDocument;
-            var toolSize = Toolbar.GetSetting<SizeSetting>("ToolSize");
-            SKRectI finalRect = toolSessionRect;
-            if (toolSize != null)
-            {
-                int halfSize = (int)Math.Ceiling(toolSize.Value / 2f);
-                finalRect.Inflate(halfSize, halfSize);
-            }
+            //var toolSize = Toolbar.GetSetting<SizeSetting>("ToolSize");
+            //SKRectI finalRect = toolSessionRect;
+            //if (toolSize != null)
+            //{
+            //    int halfSize = (int)Math.Ceiling(toolSize.Value / 2f);
+            //    finalRect.Inflate(halfSize, halfSize);
+            //}
 
-            if (toolSessionRect.IsEmpty)
-            {
-                finalRect = SKRectI.Create(doc.ActiveLayer.OffsetX, doc.ActiveLayer.OffsetY, doc.ActiveLayer.Width, doc.ActiveLayer.Height);
-            }
+            //if (toolSessionRect.IsEmpty)
+            //{
+            //    finalRect = SKRectI.Create(doc.ActiveLayer.OffsetX, doc.ActiveLayer.OffsetY, doc.ActiveLayer.Width, doc.ActiveLayer.Height);
+            //}
 
-            if (UseDocumentRectForUndo)
-            {
-                finalRect = SKRectI.Create(0, 0, doc.Width, doc.Height);
-            }
+            //Commented, because rect based undo is still a little buggy
+            //if (UseDocumentRectForUndo)
+            //{
+            //    finalRect = SKRectI.Create(0, 0, doc.Width, doc.Height);
+            //}
 
-            _change = new StorageBasedChange(doc, new[] { new LayerChunk(doc.ActiveLayer, finalRect) });
+            _change = new StorageBasedChange(doc, new[] { doc.ActiveLayer });
         }
     }
 }

+ 422 - 126
PixiEditor/Models/Undo/StorageBasedChange.cs

@@ -1,13 +1,11 @@
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.Layers;
-using SkiaSharp;
 using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Text;
-using System.Windows;
 
 namespace PixiEditor.Models.Undo
 {
@@ -16,66 +14,47 @@ namespace PixiEditor.Models.Undo
     /// </summary>
     public class StorageBasedChange : IDisposable
     {
-        public static string DefaultUndoChangeLocation { get; } = Path.Join(Path.GetTempPath(), "PixiEditor", Guid.NewGuid().ToString(), "UndoStack");
+        public static string DefaultUndoChangeLocation => Path.Join(Path.GetTempPath(), "PixiEditor", "UndoStack");
 
         public string UndoChangeLocation { get; set; }
 
         public UndoLayer[] StoredLayers { get; set; }
 
-        private List<Guid> layersToStore = new List<Guid>();
+        private List<Guid> layersToStore;
         public Document Document { get; }
 
         public StorageBasedChange(Document doc, IEnumerable<Layer> layers, bool saveOnStartup = true)
         {
             Document = doc;
-            Initialize(layers, DefaultUndoChangeLocation, saveOnStartup);
-        }
-
-        public StorageBasedChange(Document doc, IEnumerable<Layer> layers, string undoChangeLocation, bool saveOnStartup = true)
-        {
-            Document = doc;
-            Initialize(layers, undoChangeLocation, saveOnStartup);
-        }
-
-        public StorageBasedChange(Document doc, IEnumerable<LayerChunk> chunks, bool saveOnStartup = true)
-        {
-            Document = doc;
-            var chunkData = chunks as LayerChunk[] ?? chunks.ToArray();
-            LayerChunk[] layerChunks = new LayerChunk[chunkData.Length];
-            for (var i = 0; i < chunkData.Length; i++)
-            {
-                var chunk = chunkData[i];
-                layerChunks[i] = chunk;
-                layersToStore.Add(chunk.Layer.GuidValue);
-            }
-
+            layersToStore = layers.Select(x => x.GuidValue).ToList();
             UndoChangeLocation = DefaultUndoChangeLocation;
-            GenerateUndoLayers(layerChunks);
+            GenerateUndoLayers();
             if (saveOnStartup)
             {
                 SaveLayersOnDevice();
             }
         }
 
-        private void Initialize(IEnumerable<Layer> layers, string undoChangeLocation, bool saveOnStartup)
+        public StorageBasedChange(Document doc, IEnumerable<Layer> layers, string undoChangeLocation, bool saveOnStartup = true)
         {
-            var layersArray = layers as Layer[] ?? layers.ToArray();
-            LayerChunk[] layerChunks = new LayerChunk[layersArray.Length];
-            for (var i = 0; i < layersArray.Length; i++)
-            {
-                var layer = layersArray[i];
-                layerChunks[i] = new LayerChunk(layer, SKRectI.Create(layer.OffsetX, layer.OffsetY, layer.Width, layer.Height));
-                layersToStore.Add(layer.GuidValue);
-            }
-
+            Document = doc;
+            layersToStore = layers.Select(x => x.GuidValue).ToList();
             UndoChangeLocation = undoChangeLocation;
-            GenerateUndoLayers(layerChunks);
+            GenerateUndoLayers();
+
             if (saveOnStartup)
             {
                 SaveLayersOnDevice();
             }
         }
 
+        public void Dispose()
+        {
+            var layers = LoadLayersFromDevice();
+            foreach (var layer in layers)
+                layer.LayerBitmap.Dispose();
+        }
+
         public void SaveLayersOnDevice()
         {
             int i = 0;
@@ -85,19 +64,7 @@ namespace PixiEditor.Models.Undo
                 UndoLayer storedLayer = StoredLayers[i];
                 if (Directory.Exists(Path.GetDirectoryName(storedLayer.StoredPngLayerName)))
                 {
-                    // Calculate absolute rect to relative rect
-                    SKRectI finalRect = SKRectI.Create(
-                        storedLayer.SerializedRect.Left - layer.OffsetX,
-                        storedLayer.SerializedRect.Top - layer.OffsetY,
-                        storedLayer.SerializedRect.Width,
-                        storedLayer.SerializedRect.Height);
-
-                    using var image = layer.LayerBitmap.SkiaSurface.Snapshot();
-                    Surface targetSizeSurface = new Surface(finalRect.Width, finalRect.Height);
-
-                    targetSizeSurface.SkiaSurface.Canvas.DrawImage(image, finalRect, SKRect.Create(0, 0, finalRect.Width, finalRect.Height), Surface.ReplacingPaint);
-
-                    Exporter.SaveAsGZippedBytes(storedLayer.StoredPngLayerName, targetSizeSurface);
+                    Exporter.SaveAsGZippedBytes(storedLayer.StoredPngLayerName, layer.LayerBitmap);
                 }
 
                 i++;
@@ -119,17 +86,16 @@ namespace PixiEditor.Models.Undo
                 var bitmap = Importer.LoadFromGZippedBytes(storedLayer.StoredPngLayerName);
                 layers[i] = new Layer(storedLayer.Name, bitmap)
                 {
-                    Width = storedLayer.Width,
-                    Height = storedLayer.Height,
-                    Offset = new Thickness(storedLayer.OffsetX, storedLayer.OffsetY, 0, 0),
+                    Offset = new System.Windows.Thickness(storedLayer.OffsetX, storedLayer.OffsetY, 0, 0),
                     Opacity = storedLayer.Opacity,
                     MaxWidth = storedLayer.MaxWidth,
                     MaxHeight = storedLayer.MaxHeight,
                     IsVisible = storedLayer.IsVisible,
                     IsActive = storedLayer.IsActive,
+                    Width = storedLayer.Width,
+                    Height = storedLayer.Height,
                     LayerHighlightColor = storedLayer.LayerHighlightColor
                 };
-
                 layers[i].ChangeGuid(storedLayer.LayerGuid);
 
                 File.Delete(StoredLayers[i].StoredPngLayerName);
@@ -173,19 +139,14 @@ namespace PixiEditor.Models.Undo
         /// <param name="undoRedoProcess">Process that is invoked on redo and undo.</param>
         /// <param name="processArgs">Custom parameters for undo and redo process.</param>
         /// <param name="description">Undo change description.</param>
-        /// <returns>UndoManager ready 'Change' instance.</returns>
+        /// <returns>UndoManager ready Change instance.</returns>
         public Change ToChange(Action<Layer[], UndoLayer[], object[]> undoRedoProcess, object[] processArgs, string description = "")
         {
             Action<object[]> finalProcess = processParameters =>
             {
-                Layer[] layers = LoadLayersFromDevice();
-                LayerChunk[] chunks = new LayerChunk[layers.Length];
-                for (int i = 0; i < layers.Length; i++)
-                {
-                    chunks[i] = new LayerChunk(layers[i], StoredLayers[i].SerializedRect);
-                }
 
-                GenerateUndoLayers(chunks);
+                Layer[] layers = LoadLayersFromDevice();
+                GenerateUndoLayers();
 
                 SaveLayersOnDevice();
 
@@ -282,7 +243,7 @@ namespace PixiEditor.Models.Undo
         /// <summary>
         /// Generates UndoLayer[] StoredLayers data.
         /// </summary>
-        private void GenerateUndoLayers(LayerChunk[] chunks)
+        private void GenerateUndoLayers()
         {
             StoredLayers = new UndoLayer[layersToStore.Count];
             int i = 0;
@@ -294,15 +255,16 @@ namespace PixiEditor.Models.Undo
                     throw new ArgumentException("Provided document doesn't contain selected layer");
                 }
 
+                layer.ClipCanvas();
+
                 int index = Document.Layers.IndexOf(layer);
-                string fileName = layer.Name + Guid.NewGuid();
+                string pngName = layer.Name + Guid.NewGuid().ToString();
                 StoredLayers[i] = new UndoLayer(
                     Path.Join(
                         UndoChangeLocation,
-                        Convert.ToBase64String(Encoding.UTF8.GetBytes(fileName)) + ".undoimg"),
+                        Convert.ToBase64String(Encoding.UTF8.GetBytes(pngName)) + ".png"),
                     layer,
-                    index,
-                    chunks[i].AbsoluteChunkRect);
+                    index);
                 i++;
             }
         }
@@ -311,74 +273,408 @@ namespace PixiEditor.Models.Undo
         {
             if (args.Length > 0 && args[0] is Document document)
             {
+                var ls = document.LayerStructure.CloneGroups();
+
                 for (int i = 0; i < layers.Length; i++)
                 {
                     Layer layer = layers[i];
-                    UndoLayer layerData = data[i];
-                    var foundLayer = document.Layers.FirstOrDefault(x => x.GuidValue == layerData.LayerGuid);
 
-                    if (foundLayer != null)
-                    {
-                        ApplyChunkToLayer(foundLayer, layerData, layer.LayerBitmap);
-                    }
-                    else
-                    {
-                        document.RemoveLayer(layerData.LayerIndex, false);
-                        document.Layers.Insert(layerData.LayerIndex, layer);
-                    }
+                    document.RemoveLayer(data[i].LayerIndex, false);
+                    document.Layers.Insert(data[i].LayerIndex, layer);
 
-                    if (layerData.IsActive)
+                    if (data[i].IsActive)
                     {
-                        document.SetMainActiveLayer(layerData.LayerIndex);
+                        document.SetMainActiveLayer(data[i].LayerIndex);
                     }
                 }
-            }
-        }
-
-        private static void ApplyChunkToLayer(Layer layer, UndoLayer layerData, Surface chunk)
-        {
-            bool widthBigger = layer.Width < chunk.Width;
-            bool heightBigger = layer.Height < chunk.Height;
-            int targetWidth = widthBigger ? chunk.Width : layer.Width;
-            int targetHeight = heightBigger ? chunk.Height : layer.Height;
 
-            int offsetDiffX = layerData.OffsetX - layer.OffsetX;
-            int offsetDiffY = layerData.OffsetY - layer.OffsetY;
-
-            int targetOffsetX = widthBigger ? layerData.SerializedRect.Left : layerData.OffsetX;
-            int targetOffsetY = heightBigger ? layerData.SerializedRect.Top : layerData.OffsetY;
-
-            Surface targetSizeSurface = new Surface(targetWidth, targetHeight);
-            using var foundLayerSnapshot = layer.LayerBitmap.SkiaSurface.Snapshot();
-            targetSizeSurface.SkiaSurface.Canvas.DrawImage(
-                foundLayerSnapshot,
-                SKRect.Create(offsetDiffX, offsetDiffY, layer.Width, layer.Height),
-                SKRect.Create(0, 0, targetWidth, targetHeight),
-                Surface.ReplacingPaint);
-
-            layer.Offset = new Thickness(targetOffsetX, targetOffsetY, 0, 0);
-
-            SKRect finalRect = SKRect.Create(
-                layerData.SerializedRect.Left - layer.OffsetX,
-                layerData.SerializedRect.Top - layer.OffsetY,
-                layerData.SerializedRect.Width,
-                layerData.SerializedRect.Height);
-
-            using var snapshot = chunk.SkiaSurface.Snapshot();
-
-            targetSizeSurface.SkiaSurface.Canvas.DrawImage(
-                snapshot,
-                finalRect,
-                Surface.ReplacingPaint);
-
-            layer.LayerBitmap = targetSizeSurface;
-        }
-
-        public void Dispose()
-        {
-            var layers = LoadLayersFromDevice();
-            foreach (var layer in layers)
-                layer.LayerBitmap.Dispose();
+                document.BuildLayerStructureProcess(new object[] { ls });
+            }
         }
     }
 }
+
+//using PixiEditor.Models.DataHolders;
+//using PixiEditor.Models.IO;
+//using PixiEditor.Models.Layers;
+//using SkiaSharp;
+//using System;
+//using System.Collections.Generic;
+//using System.IO;
+//using System.Linq;
+//using System.Text;
+//using System.Windows;
+
+//namespace PixiEditor.Models.Undo
+//{
+//    /// <summary>
+//    ///     A class that allows to save layers on disk and load them on Undo/Redo.
+//    /// </summary>
+//    public class StorageBasedChange : IDisposable
+//    {
+//        public static string DefaultUndoChangeLocation { get; } = Path.Join(Path.GetTempPath(), "PixiEditor", Guid.NewGuid().ToString(), "UndoStack");
+
+//        public string UndoChangeLocation { get; set; }
+
+//        public UndoLayer[] StoredLayers { get; set; }
+
+//        private List<Guid> layersToStore = new List<Guid>();
+//        public Document Document { get; }
+
+//        public StorageBasedChange(Document doc, IEnumerable<Layer> layers, bool saveOnStartup = true)
+//        {
+//            Document = doc;
+//            Initialize(layers, DefaultUndoChangeLocation, saveOnStartup);
+//        }
+
+//        public StorageBasedChange(Document doc, IEnumerable<Layer> layers, string undoChangeLocation, bool saveOnStartup = true)
+//        {
+//            Document = doc;
+//            Initialize(layers, undoChangeLocation, saveOnStartup);
+//        }
+
+//        public StorageBasedChange(Document doc, IEnumerable<LayerChunk> chunks, bool saveOnStartup = true)
+//        {
+//            Document = doc;
+//            var chunkData = chunks as LayerChunk[] ?? chunks.ToArray();
+//            LayerChunk[] layerChunks = new LayerChunk[chunkData.Length];
+//            for (var i = 0; i < chunkData.Length; i++)
+//            {
+//                var chunk = chunkData[i];
+//                layerChunks[i] = chunk;
+//                layersToStore.Add(chunk.Layer.GuidValue);
+//            }
+
+//            UndoChangeLocation = DefaultUndoChangeLocation;
+//            GenerateUndoLayers(layerChunks);
+//            if (saveOnStartup)
+//            {
+//                SaveLayersOnDevice();
+//            }
+//        }
+
+//        private void Initialize(IEnumerable<Layer> layers, string undoChangeLocation, bool saveOnStartup)
+//        {
+//            var layersArray = layers as Layer[] ?? layers.ToArray();
+//            LayerChunk[] layerChunks = new LayerChunk[layersArray.Length];
+//            for (var i = 0; i < layersArray.Length; i++)
+//            {
+//                var layer = layersArray[i];
+//                layerChunks[i] = new LayerChunk(layer, SKRectI.Create(layer.OffsetX, layer.OffsetY, layer.Width, layer.Height));
+//                layersToStore.Add(layer.GuidValue);
+//            }
+
+//            UndoChangeLocation = undoChangeLocation;
+//            GenerateUndoLayers(layerChunks);
+//            if (saveOnStartup)
+//            {
+//                SaveLayersOnDevice();
+//            }
+//        }
+
+//        public void SaveLayersOnDevice()
+//        {
+//            int i = 0;
+//            foreach (var layerGuid in layersToStore)
+//            {
+//                Layer layer = Document.Layers.First(x => x.GuidValue == layerGuid);
+//                UndoLayer storedLayer = StoredLayers[i];
+//                if (Directory.Exists(Path.GetDirectoryName(storedLayer.StoredPngLayerName)))
+//                {
+//                    // Calculate absolute rect to relative rect
+//                    SKRectI finalRect = SKRectI.Create(
+//                        storedLayer.SerializedRect.Left - layer.OffsetX,
+//                        storedLayer.SerializedRect.Top - layer.OffsetY,
+//                        storedLayer.SerializedRect.Width,
+//                        storedLayer.SerializedRect.Height);
+
+//                    using var image = layer.LayerBitmap.SkiaSurface.Snapshot();
+//                    Surface targetSizeSurface = new Surface(finalRect.Width, finalRect.Height);
+
+//                    targetSizeSurface.SkiaSurface.Canvas.DrawImage(image, finalRect, SKRect.Create(0, 0, finalRect.Width, finalRect.Height), Surface.ReplacingPaint);
+
+//                    Exporter.SaveAsGZippedBytes(storedLayer.StoredPngLayerName, targetSizeSurface);
+//                }
+
+//                i++;
+//            }
+
+//            layersToStore = new List<Guid>();
+//        }
+
+//        /// <summary>
+//        /// Loads saved layers from disk.
+//        /// </summary>
+//        /// <returns>Array of saved layers.</returns>
+//        public Layer[] LoadLayersFromDevice()
+//        {
+//            Layer[] layers = new Layer[StoredLayers.Length];
+//            for (int i = 0; i < StoredLayers.Length; i++)
+//            {
+//                UndoLayer storedLayer = StoredLayers[i];
+//                var bitmap = Importer.LoadFromGZippedBytes(storedLayer.StoredPngLayerName);
+//                layers[i] = new Layer(storedLayer.Name, bitmap)
+//                {
+//                    Width = storedLayer.Width,
+//                    Height = storedLayer.Height,
+//                    Offset = new Thickness(storedLayer.OffsetX, storedLayer.OffsetY, 0, 0),
+//                    Opacity = storedLayer.Opacity,
+//                    MaxWidth = storedLayer.MaxWidth,
+//                    MaxHeight = storedLayer.MaxHeight,
+//                    IsVisible = storedLayer.IsVisible,
+//                    IsActive = storedLayer.IsActive,
+//                    LayerHighlightColor = storedLayer.LayerHighlightColor
+//                };
+
+//                layers[i].ChangeGuid(storedLayer.LayerGuid);
+
+//                File.Delete(StoredLayers[i].StoredPngLayerName);
+//            }
+
+//            layersToStore = layers.Select(x => x.GuidValue).ToList();
+//            return layers;
+//        }
+
+//        /// <summary>
+//        ///     Creates UndoManager ready Change instance, where undo process loads layers from device, and redo saves them.
+//        /// </summary>
+//        /// <param name="undoProcess">Method that is invoked on undo, with loaded layers parameter and UndoLayer array data.</param>
+//        /// <param name="processArgs">Custom parameters for undo process.</param>
+//        /// <param name="redoProcess">Method that is invoked on redo with custom object array parameters.</param>
+//        /// <param name="redoProcessParameters">Parameters for redo process.</param>
+//        /// <param name="description">Undo change description.</param>
+//        /// <returns>UndoManager ready Change instance.</returns>
+//        public Change ToChange(Action<Layer[], UndoLayer[], object[]> undoProcess, object[] processArgs, Action<object[]> redoProcess, object[] redoProcessParameters, string description = "")
+//        {
+//            Action<object[]> finalUndoProcess = processParameters =>
+//            {
+//                Layer[] layers = LoadLayersFromDevice();
+//                undoProcess(layers, StoredLayers, processParameters);
+//            };
+
+//            Action<object[]> finalRedoProcess = parameters =>
+//            {
+//                SaveLayersOnDevice();
+//                redoProcess(parameters);
+//            };
+
+//            var change = new Change(finalUndoProcess, processArgs, finalRedoProcess, redoProcessParameters, description);
+//            change.DisposeProcess = (_, _) => Dispose();
+//            return change;
+//        }
+
+//        /// <summary>
+//        ///     Creates UndoManager ready Change instance, where undo and redo is the same, before process images are loaded from disk and current ones are saved.
+//        /// </summary>
+//        /// <param name="undoRedoProcess">Process that is invoked on redo and undo.</param>
+//        /// <param name="processArgs">Custom parameters for undo and redo process.</param>
+//        /// <param name="description">Undo change description.</param>
+//        /// <returns>UndoManager ready 'Change' instance.</returns>
+//        public Change ToChange(Action<Layer[], UndoLayer[], object[]> undoRedoProcess, object[] processArgs, string description = "")
+//        {
+//            Action<object[]> finalProcess = processParameters =>
+//            {
+//                Layer[] layers = LoadLayersFromDevice();
+//                LayerChunk[] chunks = new LayerChunk[layers.Length];
+//                for (int i = 0; i < layers.Length; i++)
+//                {
+//                    chunks[i] = new LayerChunk(layers[i], StoredLayers[i].SerializedRect);
+//                }
+
+//                GenerateUndoLayers(chunks);
+
+//                SaveLayersOnDevice();
+
+//                undoRedoProcess(layers, StoredLayers, processParameters);
+//            };
+
+//            var change = new Change(finalProcess, processArgs, finalProcess, processArgs, description);
+//            change.DisposeProcess = (_, _) => Dispose();
+//            return change;
+//        }
+
+//        /// <summary>
+//        ///     Creates UndoManager ready Change instance, where undo process loads layers from device, and redo saves them.
+//        /// </summary>
+//        /// <param name="undoProcess">Method that is invoked on undo, with loaded layers parameter and UndoLayer array data.</param>
+//        /// <param name="redoProcess">Method that is invoked on redo with custom object array parameters.</param>
+//        /// <param name="redoProcessParameters">Parameters for redo process.</param>
+//        /// <param name="description">Undo change description.</param>
+//        /// <returns>UndoManager ready Change instance.</returns>
+//        public Change ToChange(Action<Layer[], UndoLayer[]> undoProcess, Action<object[]> redoProcess, object[] redoProcessParameters, string description = "")
+//        {
+//            Action<object[]> finalUndoProcess = _ =>
+//            {
+//                Layer[] layers = LoadLayersFromDevice();
+//                undoProcess(layers, StoredLayers);
+//            };
+
+//            Action<object[]> finalRedoProcess = parameters =>
+//            {
+//                SaveLayersOnDevice();
+//                redoProcess(parameters);
+//            };
+
+//            var change = new Change(finalUndoProcess, null, finalRedoProcess, redoProcessParameters, description);
+//            change.DisposeProcess = (_, _) => Dispose();
+//            return change;
+//        }
+
+//        /// <summary>
+//        ///     Creates UndoManager ready Change instance, where undo process saves layers on device, and redo loads them.
+//        /// </summary>
+//        /// <param name="undoProcess">Method that is invoked on undo, with loaded layers parameter and UndoLayer array data.</param>
+//        /// <param name="undoProcessParameters">Parameters for undo process.</param>
+//        /// <param name="redoProcess">Method that is invoked on redo with custom object array parameters.</param>
+//        /// <param name="description">Undo change description.</param>
+//        /// <returns>UndoManager ready Change instance.</returns>
+//        public Change ToChange(Action<object[]> undoProcess, object[] undoProcessParameters, Action<Layer[], UndoLayer[]> redoProcess, string description = "")
+//        {
+//            Action<object[]> finalUndoProcess = parameters =>
+//            {
+//                SaveLayersOnDevice();
+//                undoProcess(parameters);
+//            };
+
+//            Action<object[]> finalRedoProcess = parameters =>
+//            {
+//                Layer[] layers = LoadLayersFromDevice();
+//                redoProcess(layers, StoredLayers);
+//            };
+
+//            var change = new Change(finalUndoProcess, undoProcessParameters, finalRedoProcess, null, description);
+//            change.DisposeProcess = (_, _) => Dispose();
+//            return change;
+//        }
+
+//        /// <summary>
+//        ///     Creates UndoManager ready Change instance, where undo process saves layers on device, and redo loads them.
+//        /// </summary>
+//        /// <param name="undoProcess">Method that is invoked on undo, with loaded layers parameter and UndoLayer array data.</param>
+//        /// <param name="undoProcessParameters">Parameters for undo process.</param>
+//        /// <param name="redoProcess">Method that is invoked on redo with custom object array parameters.</param>
+//        /// <param name="redoProcessArgs">Parameters for redo process.</param>
+//        /// <param name="description">Undo change description.</param>
+//        /// <returns>UndoManager ready Change instance.</returns>
+//        public Change ToChange(Action<object[]> undoProcess, object[] undoProcessParameters, Action<Layer[], UndoLayer[], object[]> redoProcess, object[] redoProcessArgs, string description = "")
+//        {
+//            Action<object[]> finalUndoProcess = parameters =>
+//            {
+//                SaveLayersOnDevice();
+//                undoProcess(parameters);
+//            };
+
+//            Action<object[]> finalRedoProcess = parameters =>
+//            {
+//                Layer[] layers = LoadLayersFromDevice();
+//                redoProcess(layers, StoredLayers, parameters);
+//            };
+
+//            var change = new Change(finalUndoProcess, undoProcessParameters, finalRedoProcess, redoProcessArgs, description);
+//            change.DisposeProcess = (_, _) => Dispose();
+//            return change;
+//        }
+
+//        /// <summary>
+//        /// Generates UndoLayer[] StoredLayers data.
+//        /// </summary>
+//        private void GenerateUndoLayers(LayerChunk[] chunks)
+//        {
+//            StoredLayers = new UndoLayer[layersToStore.Count];
+//            int i = 0;
+//            foreach (var layerGuid in layersToStore)
+//            {
+//                Layer layer = Document.Layers.First(x => x.GuidValue == layerGuid);
+//                if (!Document.Layers.Contains(layer))
+//                {
+//                    throw new ArgumentException("Provided document doesn't contain selected layer");
+//                }
+
+//                int index = Document.Layers.IndexOf(layer);
+//                string fileName = layer.Name + Guid.NewGuid();
+//                StoredLayers[i] = new UndoLayer(
+//                    Path.Join(
+//                        UndoChangeLocation,
+//                        Convert.ToBase64String(Encoding.UTF8.GetBytes(fileName)) + ".undoimg"),
+//                    layer,
+//                    index,
+//                    chunks[i].AbsoluteChunkRect);
+//                i++;
+//            }
+//        }
+
+//        public static void BasicUndoProcess(Layer[] layers, UndoLayer[] data, object[] args)
+//        {
+//            if (args.Length > 0 && args[0] is Document document)
+//            {
+//                for (int i = 0; i < layers.Length; i++)
+//                {
+//                    Layer layer = layers[i];
+//                    UndoLayer layerData = data[i];
+//                    var foundLayer = document.Layers.FirstOrDefault(x => x.GuidValue == layerData.LayerGuid);
+
+//                    if (foundLayer != null)
+//                    {
+//                        ApplyChunkToLayer(foundLayer, layerData, layer.LayerBitmap);
+//                    }
+//                    else
+//                    {
+//                        document.RemoveLayer(layerData.LayerIndex, false);
+//                        document.Layers.Insert(layerData.LayerIndex, layer);
+//                    }
+
+//                    if (layerData.IsActive)
+//                    {
+//                        document.SetMainActiveLayer(layerData.LayerIndex);
+//                    }
+//                }
+//            }
+//        }
+
+//        private static void ApplyChunkToLayer(Layer layer, UndoLayer layerData, Surface chunk)
+//        {
+//            bool widthBigger = layer.Width < chunk.Width;
+//            bool heightBigger = layer.Height < chunk.Height;
+//            int targetWidth = widthBigger ? chunk.Width : layer.Width;
+//            int targetHeight = heightBigger ? chunk.Height : layer.Height;
+
+//            int offsetDiffX = layerData.OffsetX - layer.OffsetX;
+//            int offsetDiffY = layerData.OffsetY - layer.OffsetY;
+
+//            int targetOffsetX = layerData.OffsetX == 0 && widthBigger ? layerData.SerializedRect.Left : layerData.OffsetX;
+//            int targetOffsetY = layerData.OffsetY == 0 && heightBigger ? layerData.SerializedRect.Top : layerData.OffsetY;
+
+//            Surface targetSizeSurface = new Surface(targetWidth, targetHeight);
+//            using var foundLayerSnapshot = layer.LayerBitmap.SkiaSurface.Snapshot();
+//            targetSizeSurface.SkiaSurface.Canvas.DrawImage(
+//                foundLayerSnapshot,
+//                SKRect.Create(offsetDiffX, offsetDiffY, layer.Width, layer.Height),
+//                SKRect.Create(0, 0, targetWidth, targetHeight),
+//                Surface.ReplacingPaint);
+
+//            layer.Offset = new Thickness(targetOffsetX, targetOffsetY, 0, 0);
+
+//            SKRect finalRect = SKRect.Create(
+//                layerData.SerializedRect.Left - layer.OffsetX,
+//                layerData.SerializedRect.Top - layer.OffsetY,
+//                layerData.SerializedRect.Width,
+//                layerData.SerializedRect.Height);
+
+//            using var snapshot = chunk.SkiaSurface.Snapshot();
+
+//            targetSizeSurface.SkiaSurface.Canvas.DrawImage(
+//                snapshot,
+//                finalRect,
+//                Surface.ReplacingPaint);
+
+//            layer.LayerBitmap = targetSizeSurface;
+//        }
+
+//        public void Dispose()
+//        {
+//            var layers = LoadLayersFromDevice();
+//            foreach (var layer in layers)
+//                layer.LayerBitmap.Dispose();
+//        }
+//    }
+//}

+ 3 - 3
PixiEditor/Models/Undo/UndoLayer.cs

@@ -36,9 +36,9 @@ namespace PixiEditor.Models.Undo
 
         public float Opacity { get; set; }
 
-        public SKRectI SerializedRect { get; set; }
+        //public SKRectI SerializedRect { get; set; }
 
-        public UndoLayer(string storedPngLayerName, Layer layer, int layerIndex, SKRectI serializedRect)
+        public UndoLayer(string storedPngLayerName, Layer layer, int layerIndex/*, SKRectI serializedRect*/)
         {
             StoredPngLayerName = storedPngLayerName;
             LayerIndex = layerIndex;
@@ -54,7 +54,7 @@ namespace PixiEditor.Models.Undo
             IsActive = layer.IsActive;
             LayerGuid = layer.GuidValue;
             LayerHighlightColor = layer.LayerHighlightColor;
-            SerializedRect = serializedRect;
+            //SerializedRect = serializedRect;
         }
     }
 }

+ 0 - 5
azure-pipelines.yml

@@ -11,11 +11,6 @@ variables:
   buildConfiguration: 'Release'
 
 steps:
-- task: UseDotNet@2
-  inputs:
-    packageType: 'sdk'
-    version: '6.0.100'
-
 - task: NuGetToolInstaller@1
 
 - task: NuGetCommand@2