|
@@ -1,13 +1,11 @@
|
|
using PixiEditor.Models.DataHolders;
|
|
using PixiEditor.Models.DataHolders;
|
|
using PixiEditor.Models.IO;
|
|
using PixiEditor.Models.IO;
|
|
using PixiEditor.Models.Layers;
|
|
using PixiEditor.Models.Layers;
|
|
-using SkiaSharp;
|
|
|
|
using System;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text;
|
|
-using System.Windows;
|
|
|
|
|
|
|
|
namespace PixiEditor.Models.Undo
|
|
namespace PixiEditor.Models.Undo
|
|
{
|
|
{
|
|
@@ -16,66 +14,47 @@ namespace PixiEditor.Models.Undo
|
|
/// </summary>
|
|
/// </summary>
|
|
public class StorageBasedChange : IDisposable
|
|
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 string UndoChangeLocation { get; set; }
|
|
|
|
|
|
public UndoLayer[] StoredLayers { get; set; }
|
|
public UndoLayer[] StoredLayers { get; set; }
|
|
|
|
|
|
- private List<Guid> layersToStore = new List<Guid>();
|
|
|
|
|
|
+ private List<Guid> layersToStore;
|
|
public Document Document { get; }
|
|
public Document Document { get; }
|
|
|
|
|
|
public StorageBasedChange(Document doc, IEnumerable<Layer> layers, bool saveOnStartup = true)
|
|
public StorageBasedChange(Document doc, IEnumerable<Layer> layers, bool saveOnStartup = true)
|
|
{
|
|
{
|
|
Document = doc;
|
|
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;
|
|
UndoChangeLocation = DefaultUndoChangeLocation;
|
|
- GenerateUndoLayers(layerChunks);
|
|
|
|
|
|
+ GenerateUndoLayers();
|
|
if (saveOnStartup)
|
|
if (saveOnStartup)
|
|
{
|
|
{
|
|
SaveLayersOnDevice();
|
|
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;
|
|
UndoChangeLocation = undoChangeLocation;
|
|
- GenerateUndoLayers(layerChunks);
|
|
|
|
|
|
+ GenerateUndoLayers();
|
|
|
|
+
|
|
if (saveOnStartup)
|
|
if (saveOnStartup)
|
|
{
|
|
{
|
|
SaveLayersOnDevice();
|
|
SaveLayersOnDevice();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public void Dispose()
|
|
|
|
+ {
|
|
|
|
+ var layers = LoadLayersFromDevice();
|
|
|
|
+ foreach (var layer in layers)
|
|
|
|
+ layer.LayerBitmap.Dispose();
|
|
|
|
+ }
|
|
|
|
+
|
|
public void SaveLayersOnDevice()
|
|
public void SaveLayersOnDevice()
|
|
{
|
|
{
|
|
int i = 0;
|
|
int i = 0;
|
|
@@ -85,19 +64,7 @@ namespace PixiEditor.Models.Undo
|
|
UndoLayer storedLayer = StoredLayers[i];
|
|
UndoLayer storedLayer = StoredLayers[i];
|
|
if (Directory.Exists(Path.GetDirectoryName(storedLayer.StoredPngLayerName)))
|
|
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++;
|
|
i++;
|
|
@@ -119,17 +86,16 @@ namespace PixiEditor.Models.Undo
|
|
var bitmap = Importer.LoadFromGZippedBytes(storedLayer.StoredPngLayerName);
|
|
var bitmap = Importer.LoadFromGZippedBytes(storedLayer.StoredPngLayerName);
|
|
layers[i] = new Layer(storedLayer.Name, bitmap)
|
|
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,
|
|
Opacity = storedLayer.Opacity,
|
|
MaxWidth = storedLayer.MaxWidth,
|
|
MaxWidth = storedLayer.MaxWidth,
|
|
MaxHeight = storedLayer.MaxHeight,
|
|
MaxHeight = storedLayer.MaxHeight,
|
|
IsVisible = storedLayer.IsVisible,
|
|
IsVisible = storedLayer.IsVisible,
|
|
IsActive = storedLayer.IsActive,
|
|
IsActive = storedLayer.IsActive,
|
|
|
|
+ Width = storedLayer.Width,
|
|
|
|
+ Height = storedLayer.Height,
|
|
LayerHighlightColor = storedLayer.LayerHighlightColor
|
|
LayerHighlightColor = storedLayer.LayerHighlightColor
|
|
};
|
|
};
|
|
-
|
|
|
|
layers[i].ChangeGuid(storedLayer.LayerGuid);
|
|
layers[i].ChangeGuid(storedLayer.LayerGuid);
|
|
|
|
|
|
File.Delete(StoredLayers[i].StoredPngLayerName);
|
|
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="undoRedoProcess">Process that is invoked on redo and undo.</param>
|
|
/// <param name="processArgs">Custom parameters for undo and redo process.</param>
|
|
/// <param name="processArgs">Custom parameters for undo and redo process.</param>
|
|
/// <param name="description">Undo change description.</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 = "")
|
|
public Change ToChange(Action<Layer[], UndoLayer[], object[]> undoRedoProcess, object[] processArgs, string description = "")
|
|
{
|
|
{
|
|
Action<object[]> finalProcess = processParameters =>
|
|
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();
|
|
SaveLayersOnDevice();
|
|
|
|
|
|
@@ -282,7 +243,7 @@ namespace PixiEditor.Models.Undo
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Generates UndoLayer[] StoredLayers data.
|
|
/// Generates UndoLayer[] StoredLayers data.
|
|
/// </summary>
|
|
/// </summary>
|
|
- private void GenerateUndoLayers(LayerChunk[] chunks)
|
|
|
|
|
|
+ private void GenerateUndoLayers()
|
|
{
|
|
{
|
|
StoredLayers = new UndoLayer[layersToStore.Count];
|
|
StoredLayers = new UndoLayer[layersToStore.Count];
|
|
int i = 0;
|
|
int i = 0;
|
|
@@ -294,15 +255,16 @@ namespace PixiEditor.Models.Undo
|
|
throw new ArgumentException("Provided document doesn't contain selected layer");
|
|
throw new ArgumentException("Provided document doesn't contain selected layer");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ layer.ClipCanvas();
|
|
|
|
+
|
|
int index = Document.Layers.IndexOf(layer);
|
|
int index = Document.Layers.IndexOf(layer);
|
|
- string fileName = layer.Name + Guid.NewGuid();
|
|
|
|
|
|
+ string pngName = layer.Name + Guid.NewGuid().ToString();
|
|
StoredLayers[i] = new UndoLayer(
|
|
StoredLayers[i] = new UndoLayer(
|
|
Path.Join(
|
|
Path.Join(
|
|
UndoChangeLocation,
|
|
UndoChangeLocation,
|
|
- Convert.ToBase64String(Encoding.UTF8.GetBytes(fileName)) + ".undoimg"),
|
|
|
|
|
|
+ Convert.ToBase64String(Encoding.UTF8.GetBytes(pngName)) + ".png"),
|
|
layer,
|
|
layer,
|
|
- index,
|
|
|
|
- chunks[i].AbsoluteChunkRect);
|
|
|
|
|
|
+ index);
|
|
i++;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -311,74 +273,408 @@ namespace PixiEditor.Models.Undo
|
|
{
|
|
{
|
|
if (args.Length > 0 && args[0] is Document document)
|
|
if (args.Length > 0 && args[0] is Document document)
|
|
{
|
|
{
|
|
|
|
+ var ls = document.LayerStructure.CloneGroups();
|
|
|
|
+
|
|
for (int i = 0; i < layers.Length; i++)
|
|
for (int i = 0; i < layers.Length; i++)
|
|
{
|
|
{
|
|
Layer layer = layers[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 = 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();
|
|
|
|
|
|
+ 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();
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+//}
|