浏览代码

Merge pull request #1277 from PixiEditor/brush-engine

Fixed clipboard on linux
Krzysztof Krysiński 1 周之前
父节点
当前提交
39effd7adc

+ 25 - 1
src/ChunkyImageLib/ChunkyImage.cs

@@ -393,6 +393,30 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
         }
     }
 
+    public ChunkyImage CloneFromLatest()
+    {
+        lock (lockObject)
+        {
+            ThrowIfDisposed();
+            ChunkyImage output = new(LatestSize, ProcessingColorSpace);
+            var chunks = FindAllChunks();
+            foreach (var chunk in chunks)
+            {
+                var image = GetLatestChunk(chunk, ChunkResolution.Full);
+                if (image is null)
+                {
+                    image = GetCommittedChunk(chunk, ChunkResolution.Full);
+                    if (image is null)
+                        continue;
+                }
+                output.EnqueueDrawTexture(chunk * FullChunkSize, image.Surface);
+            }
+
+            output.CommitChanges();
+            return output;
+        }
+    }
+
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
     public Color GetCommittedPixel(VecI posOnImage)
     {
@@ -1736,7 +1760,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
         lock (lockObject)
         {
             ThrowIfDisposed();
-            ChunkyImage clone = CloneFromCommitted();
+            ChunkyImage clone = CloneFromLatest();
             return clone;
         }
     }

+ 8 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs

@@ -22,8 +22,8 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
 
     public const int AccuratePreviewMaxSize = 2048;
 
-    public override VecD GetScenePosition(KeyFrameTime time) => layerImage.CommittedSize / 2f;
-    public override VecD GetSceneSize(KeyFrameTime time) => layerImage.CommittedSize;
+    public override VecD GetScenePosition(KeyFrameTime time) => layerImage?.CommittedSize / 2f ?? VecD.Zero;
+    public override VecD GetSceneSize(KeyFrameTime time) => layerImage?.CommittedSize ?? VecD.Zero;
 
     public bool LockTransparency { get; set; }
 
@@ -130,6 +130,12 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         int saved = workingSurface.Save();
 
         var sceneSize = GetSceneSize(ctx.FrameTime);
+        if (sceneSize.X == 0 || sceneSize.Y == 0)
+        {
+            workingSurface.RestoreToCount(saved);
+            return;
+        }
+
         RectI latestSize = new(0, 0, layerImage.LatestSize.X, layerImage.LatestSize.Y);
         var region = ctx.VisibleDocumentRegion ?? latestSize;
 

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Structure/ImportFolder_Change.cs

@@ -188,7 +188,7 @@ internal class ImportFolder_Change : Change
     {
         foreach (var imageData in layerNode.KeyFrames)
         {
-            if (imageData.Data is ChunkyImage img)
+            if (imageData.Data is ChunkyImage img && (img.LatestSize.X < docSize.X || img.LatestSize.Y < docSize.Y))
             {
                 img.EnqueueResize(docSize);
                 img.CommitChanges();

+ 3 - 1
src/PixiEditor/Models/Clipboard/PixiEditorClipboard.cs

@@ -1,4 +1,5 @@
-using Avalonia.Input;
+using System.Collections.Concurrent;
+using Avalonia.Input;
 using Avalonia.Input.Platform;
 using Avalonia.Platform.Storage;
 
@@ -7,6 +8,7 @@ namespace PixiEditor.Models.Clipboard;
 public class PixiEditorClipboard : IPixiEditorClipboard
 {
     private IClipboard avaloniaClipboard;
+    private List<IAsyncDataTransferItem>? lastProcessingDataTransfers;
 
     public PixiEditorClipboard(IClipboard avaloniaClipboard)
     {

+ 35 - 21
src/PixiEditor/Models/Controllers/ClipboardController.cs

@@ -11,6 +11,7 @@ using Avalonia.Input.Platform;
 using Avalonia.Media.Imaging;
 using Avalonia.Platform;
 using Avalonia.Platform.Storage;
+using Avalonia.Threading;
 using ChunkyImageLib;
 using PixiEditor.Helpers.Extensions;
 using PixiEditor.ChangeableDocument.Enums;
@@ -64,7 +65,8 @@ internal static class ClipboardController
     /// </summary>
     public static async Task CopyToClipboard(DocumentViewModel document, RectD? lastTransform)
     {
-        await Clipboard.ClearAsync();
+        // This breaks often on X11 and macos
+        //await Clipboard.ClearAsync();
 
         DataTransfer transfer = new DataTransfer();
 
@@ -145,7 +147,8 @@ internal static class ClipboardController
 
     public static async Task CopyVisibleToClipboard(DocumentViewModel document, string? output = null)
     {
-        await Clipboard.ClearAsync();
+        // This breaks often on X11 and macos
+        //await Clipboard.ClearAsync();
 
         DataTransfer data = new DataTransfer();
 
@@ -255,6 +258,7 @@ internal static class ClipboardController
             List<Guid> adjustedLayerIds = AdjustIdsForImport(layerIds, targetDoc);
             List<Guid?> newIds = new();
             using var block = document.Operations.StartChangeBlock();
+            manager.Owner.ToolsSubViewModel.SetActiveTool<MoveToolViewModel>(false);
             foreach (var layerId in adjustedLayerIds)
             {
                 if (targetDoc.StructureHelper.Find(layerId) == null)
@@ -270,7 +274,6 @@ internal static class ClipboardController
                 }
             }
 
-            manager.Owner.ToolsSubViewModel.SetActiveTool<MoveToolViewModel>(false);
             Guid? mainGuid = newIds.FirstOrDefault(x => x != null);
             if (mainGuid != null)
             {
@@ -293,29 +296,38 @@ internal static class ClipboardController
         List<DataImage> images = await GetImage(data);
         if (images.Count == 0 || pasteAsNew)
         {
-            return await TryPasteNestedDocument(document, manager, data);
+            if (await TryPasteNestedDocument(document, manager, data))
+            {
+                manager.Owner.ToolsSubViewModel.SetActiveTool<MoveToolViewModel>(false);
+                return true;
+            }
         }
 
-        if (images.Count == 1 || (images.Count > 1 && !pasteAsNew))
+        if (images.Count > 0)
         {
-            var dataImage = images[0];
-            var position = dataImage.Position;
-
-            if (document.SizeBindable.X < position.X || document.SizeBindable.Y < position.Y || !hasPos)
+            if (!pasteAsNew)
             {
-                position = VecI.Zero;
-            }
+                var dataImage = images[0];
+                var position = dataImage.Position;
 
-            manager.Owner.ToolsSubViewModel.SetActiveTool<MoveToolViewModel>(false);
-            document.Operations.InvokeCustomAction(() =>
-            {
-                document.Operations.PasteImageWithTransform(dataImage.Image, position);
-            });
+                if (document.SizeBindable.X < position.X || document.SizeBindable.Y < position.Y || !hasPos)
+                {
+                    position = VecI.Zero;
+                }
 
-            return true;
+                manager.Owner.ToolsSubViewModel.SetActiveTool<MoveToolViewModel>(false);
+                document.Operations.InvokeCustomAction(() =>
+                {
+                    document.Operations.PasteImageWithTransform(dataImage.Image, position);
+                });
+            }
+            else
+            {
+                manager.Owner.ToolsSubViewModel.SetActiveTool<MoveToolViewModel>(false);
+                document.Operations.PasteImagesAsLayers(images, document.AnimationDataViewModel.ActiveFrameBindable, images.Count > 1);
+            }
         }
 
-        document.Operations.PasteImagesAsLayers(images, document.AnimationDataViewModel.ActiveFrameBindable);
         return true;
     }
 
@@ -346,7 +358,7 @@ internal static class ClipboardController
                 }
 
                 bool imported = TryPlaceNestedDocument(document, manager, path, out _);
-                if(!imported)
+                if (!imported)
                 {
                     continue;
                 }
@@ -360,7 +372,8 @@ internal static class ClipboardController
         return false;
     }
 
-    public static bool TryPlaceNestedDocument(DocumentViewModel document, DocumentManagerViewModel manager, string path, out string? error)
+    public static bool TryPlaceNestedDocument(DocumentViewModel document, DocumentManagerViewModel manager, string path,
+        out string? error)
     {
         try
         {
@@ -980,7 +993,8 @@ internal static class ClipboardController
 
     public static async Task CopyIds(Guid[] ids, DataFormat<byte[]> format, Guid docId)
     {
-        await Clipboard.ClearAsync();
+        // This breaks often on X11 and macos
+        //await Clipboard.ClearAsync();
 
         DataTransfer data = new DataTransfer();
 

+ 13 - 0
src/PixiEditor/Models/DocumentModels/ActionAccumulator.cs

@@ -80,6 +80,19 @@ internal class ActionAccumulator
         }
     }
 
+    public void AddActions(ActionSource actionSource, params IAction[] actions)
+    {
+        foreach (var action in actions)
+        {
+            queuedActions.Add((actionSource, action));
+        }
+
+        if (!isChangeBlockActive)
+        {
+            TryExecuteAccumulatedActions();
+        }
+    }
+
     public void AddActions(ActionSource source, IAction action)
     {
         queuedActions.Add((source, action));

+ 0 - 6
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -1069,12 +1069,6 @@ internal class DocumentUpdater
                 info.OriginalFilePath, info.ReferenceId);
         }
 
-        if (info.OriginalFilePath != node.FilePath)
-        {
-            ViewModelMain.Current.DocumentManagerSubViewModel.ReloadDocumentReference(info.ReferenceId,
-                info.OriginalFilePath);
-        }
-
         node.SetOriginalFilePath(info.OriginalFilePath);
         node.SetReferenceId(info.ReferenceId);
         node.UpdateLinkedStatus();

+ 10 - 7
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -189,7 +189,7 @@ internal class DocumentOperationsModule : IDocumentOperations
     /// Pastes the <paramref name="images"/> as new layers
     /// </summary>
     /// <param name="images">The images to paste</param>
-    public void PasteImagesAsLayers(List<DataImage> images, int frame)
+    public void PasteImagesAsLayers(List<DataImage> images, int frame, bool resizeCanvasIfNeeded = true)
     {
         if (Internals.ChangeController.IsBlockingChangeActive)
             return;
@@ -198,14 +198,17 @@ internal class DocumentOperationsModule : IDocumentOperations
 
         var changeBlock = Document.Operations.StartChangeBlock();
 
-        RectI maxSize = new RectI(VecI.Zero, Document.SizeBindable);
-        foreach (var imageWithName in images)
+        if (resizeCanvasIfNeeded)
         {
-            maxSize = maxSize.Union(new RectI(imageWithName.Position, imageWithName.Image.Size));
-        }
+            RectI maxSize = new RectI(VecI.Zero, Document.SizeBindable);
+            foreach (var imageWithName in images)
+            {
+                maxSize = maxSize.Union(new RectI(imageWithName.Position, imageWithName.Image.Size));
+            }
 
-        if (maxSize.Size != Document.SizeBindable)
-            Internals.ActionAccumulator.AddActions(new ResizeCanvas_Action(maxSize.Size, ResizeAnchor.TopLeft));
+            if (maxSize.Size != Document.SizeBindable)
+                Internals.ActionAccumulator.AddActions(new ResizeCanvas_Action(maxSize.Size, ResizeAnchor.TopLeft));
+        }
 
         foreach (var imageWithName in images)
         {

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

@@ -953,7 +953,6 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         Surface output = Surface.ForDisplay(finalBounds.Size);
 
         VectorPath clipPath = new VectorPath(SelectionPathBindable) { FillType = PathFillType.EvenOdd };
-        //clipPath.Transform(Matrix3X3.CreateTranslation(-bounds.X, -bounds.Y));
         output.DrawingSurface.Canvas.Save();
         output.DrawingSurface.Canvas.Translate(-finalBounds.X, -finalBounds.Y);
         if (!clipPath.IsEmpty)

+ 9 - 0
tests/nuget.config

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <packageSources>
+    <!--To inherit the global NuGet package sources remove the <clear/> line below -->
+    <clear />
+    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
+    <add key="PixiloniaNugetFeed" value="https://pkgs.dev.azure.com/flabbet/Pixilonia/_packaging/PixiloniaNugetFeed/nuget/v3/index.json" />
+  </packageSources>
+</configuration>