Przeglądaj źródła

Merge branch 'master' into fixes/conflicting-tool-shortcuts

Krzysztof Krysiński 3 dni temu
rodzic
commit
8f6c4434ea

+ 21 - 23
src/ChunkyImageLib/Operations/RectangleOperation.cs

@@ -44,7 +44,7 @@ internal class RectangleOperation : IMirroredDrawOperation
 
         if (Data.AntiAliasing)
         {
-            DrawAntiAliased(surf, rect, radiusInPx);
+            DrawAntiAliased(surf, rect, innerRect, radiusInPx);
         }
         else
         {
@@ -90,8 +90,24 @@ internal class RectangleOperation : IMirroredDrawOperation
         surf.Canvas.DrawPaintable(Data.Stroke, Data.BlendMode);
     }
 
-    private void DrawAntiAliased(DrawingSurface surf, RectD rect, double radius)
+    private void DrawAntiAliased(DrawingSurface surf, RectD rect, RectD innerRect, double radius)
     {
+        surf.Canvas.Save();
+        paint.StrokeWidth = Data.StrokeWidth > 0 ? Data.StrokeWidth : 1;
+        paint.SetPaintable(Data.StrokeWidth > 0 ? Data.Stroke : Data.FillPaintable);
+        paint.Style = PaintStyle.Fill;
+
+        if (radius == 0)
+        {
+            surf.Canvas.DrawRect((float)rect.Left, (float)rect.Top, (float)rect.Width,
+                (float)rect.Height, paint);
+        }
+        else
+        {
+            surf.Canvas.DrawRoundRect((float)rect.Left, (float)rect.Top, (float)rect.Width,
+                (float)rect.Height, (float)radius, (float)radius, paint);
+        }
+
         // draw fill
         if (Data.FillPaintable.AnythingVisible)
         {
@@ -102,34 +118,16 @@ internal class RectangleOperation : IMirroredDrawOperation
             paint.Style = PaintStyle.Fill;
             if (radius == 0)
             {
-                surf.Canvas.DrawRect((float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height, paint);
+                surf.Canvas.DrawRect((float)innerRect.Left, (float)innerRect.Top, (float)innerRect.Width, (float)innerRect.Height, paint);
             }
             else
             {
-                surf.Canvas.DrawRoundRect((float)rect.Left, (float)rect.Top, (float)rect.Width,
-                    (float)rect.Height, (float)radius, (float)radius, paint);
+                surf.Canvas.DrawRoundRect((float)innerRect.Left, (float)innerRect.Top, (float)innerRect.Width,
+                    (float)innerRect.Height, (float)radius, (float)radius, paint);
             }
 
             surf.Canvas.RestoreToCount(saved);
         }
-
-        // draw stroke
-        surf.Canvas.Save();
-        paint.StrokeWidth = Data.StrokeWidth > 0 ? Data.StrokeWidth : 1;
-        paint.SetPaintable(Data.StrokeWidth > 0 ? Data.Stroke : Data.FillPaintable);
-        paint.Style = PaintStyle.Stroke;
-        RectD innerRect = rect.Inflate(-Data.StrokeWidth / 2f);
-
-        if (radius == 0)
-        {
-            surf.Canvas.DrawRect((float)innerRect.Left, (float)innerRect.Top, (float)innerRect.Width,
-                (float)innerRect.Height, paint);
-        }
-        else
-        {
-            surf.Canvas.DrawRoundRect((float)innerRect.Left, (float)innerRect.Top, (float)innerRect.Width,
-                (float)innerRect.Height, (float)radius, (float)radius, paint);
-        }
     }
 
     public AffectedArea FindAffectedArea(VecI imageSize)

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Animations/KeyFrameData.cs

@@ -8,7 +8,7 @@ public class KeyFrameData : IDisposable, IReadOnlyKeyFrameData
 {
     public int StartFrame { get; set; }
     public int Duration { get; set; }
-    public Guid KeyFrameGuid { get; }
+    public Guid KeyFrameGuid { get; internal set; }
     public string AffectedElement { get; set; }
     public object Data { get; set; }
     public bool IsVisible { get; set; } = true;

+ 4 - 4
src/PixiEditor.ChangeableDocument/Changeables/Document.cs

@@ -444,12 +444,12 @@ internal class Document : IChangeable, IReadOnlyDocument
 
     private void ExtractLayers(FolderNode folder, List<Guid> list)
     {
-        List<Guid> result = new();
-        folder.TraverseBackwards(node =>
+        if(folder.Content.Connection == null) return;
+        folder.Content.Connection.Node.TraverseBackwards(node =>
         {
-            if (node is LayerNode layer && !result.Contains(layer.Id))
+            if (node is LayerNode layer && !list.Contains(layer.Id))
             {
-                result.Add(layer.Id);
+                list.Add(layer.Id);
             }
 
             return true;

+ 73 - 0
src/PixiEditor.ChangeableDocument/Changes/Animation/CreateAnimationDataFromFolder_Change.cs

@@ -0,0 +1,73 @@
+using PixiEditor.ChangeableDocument.Changeables.Animations;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ChangeableDocument.ChangeInfos.Animation;
+
+namespace PixiEditor.ChangeableDocument.Changes.Animation;
+
+internal class CreateAnimationDataFromFolder_Change : Change
+{
+    private readonly Guid folderGuid;
+    private Guid[] layerGuids;
+
+    [GenerateMakeChangeAction]
+    public CreateAnimationDataFromFolder_Change(Guid folderGuid)
+    {
+        this.folderGuid = folderGuid;
+    }
+
+    public override bool InitializeAndValidate(Document target)
+    {
+        if (!target.TryFindMember<FolderNode>(folderGuid, out FolderNode? layer))
+        {
+            return false;
+        }
+
+        var layers = target.ExtractLayers([layer.Id]);
+        if (layers.Count == 0) return false;
+
+        return true;
+    }
+
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply,
+        out bool ignoreInUndo)
+    {
+        FolderNode folder = target.FindNode(folderGuid) as FolderNode;
+        List<IChangeInfo> infos = new List<IChangeInfo>();
+        layerGuids = target.ExtractLayers([folder.Id]).ToArray();
+
+        foreach (var layer in layerGuids)
+        {
+            var node = target.FindNode(layer);
+            if(node is not LayerNode) continue;
+            foreach (var frame in node.KeyFrames)
+            {
+                Guid keyFrameId = frame.KeyFrameGuid;
+                target.AnimationData.AddKeyFrame(new RasterKeyFrame(keyFrameId, folder.Id, frame.StartFrame, target)
+                {
+                    Duration = frame.Duration
+                });
+                infos.Add(new CreateRasterKeyFrame_ChangeInfo(folder.Id, frame.StartFrame, keyFrameId, true));
+            }
+        }
+
+        ignoreInUndo = false;
+        return infos;
+    }
+
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
+    {
+        var layer = target.FindNode(folderGuid) as FolderNode;
+        List<IChangeInfo> infos = new List<IChangeInfo>();
+
+        var keyFrame = target.AnimationData.KeyFrames;
+        var ids = keyFrame.Where(x => x.NodeId == layer.Id || layerGuids.Contains(x.NodeId)).Select(x => x.Id).ToList();
+
+        foreach (var id in ids)
+        {
+            target.AnimationData.RemoveKeyFrame(id);
+            infos.Add(new DeleteKeyFrame_ChangeInfo(id));
+        }
+
+        return infos;
+    }
+}

+ 62 - 14
src/PixiEditor.ChangeableDocument/Changes/Structure/DuplicateFolder_Change.cs

@@ -1,6 +1,7 @@
 using System.Collections.Immutable;
 using System.Collections.ObjectModel;
 using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Graph;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.ChangeInfos.NodeGraph;
@@ -17,6 +18,8 @@ internal class DuplicateFolder_Change : Change
     private Guid[] contentDuplicateGuids;
 
     private Guid[]? childGuidsToUse;
+    private Dictionary<Guid, List<Guid>> keyFramesMap = new();
+    private Dictionary<Guid, Guid> nodeMap = new();
 
     private ConnectionsData? connectionsData;
     private Dictionary<Guid, ConnectionsData> contentConnectionsData = new();
@@ -64,14 +67,15 @@ internal class DuplicateFolder_Change : Change
         List<IChangeInfo> operations = new();
 
         target.NodeGraph.AddNode(clone);
-        
+
         var previousConnection = targetInput.Connection;
 
         operations.Add(CreateNode_ChangeInfo.CreateFromNode(clone));
         operations.AddRange(NodeOperations.AppendMember(targetInput, clone.Output, clone.Background, clone.Id));
-        operations.AddRange(NodeOperations.AdjustPositionsAfterAppend(clone, targetInput.Node, previousConnection?.Node as Node, out originalPositions));
+        operations.AddRange(NodeOperations.AdjustPositionsAfterAppend(clone, targetInput.Node,
+            previousConnection?.Node as Node, out originalPositions));
 
-        DuplicateContent(target, clone, existingLayer, operations);
+        DuplicateContent(target, clone, existingLayer, operations, firstApply);
 
         ignoreInUndo = false;
 
@@ -116,29 +120,70 @@ internal class DuplicateFolder_Change : Change
     }
 
     private void DuplicateContent(Document target, FolderNode clone, FolderNode existingLayer,
-        List<IChangeInfo> operations)
+        List<IChangeInfo> operations, bool firstApply)
     {
-        Dictionary<Guid, Guid> nodeMap = new Dictionary<Guid, Guid>();
+        if (firstApply)
+        {
+            nodeMap = new Dictionary<Guid, Guid>();
+            nodeMap[existingLayer.Id] = clone.Id;
+        }
 
-        nodeMap[existingLayer.Id] = clone.Id;
         int counter = 0;
         List<Guid> contentGuidList = new();
 
+        if (firstApply)
+        {
+            keyFramesMap = new Dictionary<Guid, List<Guid>>();
+        }
+
+        int childCounter = 0;
+
         existingLayer.Content.Connection?.Node.TraverseBackwards(x =>
         {
             if (x is not Node targetNode)
                 return false;
 
             Node? node = targetNode.Clone();
-            
-            if(node is not FolderNode && childGuidsToUse is not null && counter < childGuidsToUse.Length)
+
+            if (contentDuplicateGuids != null && contentDuplicateGuids.Length > 0)
+            {
+                node.Id = contentDuplicateGuids[childCounter];
+                childCounter++;
+            }
+            else
             {
-                node.Id = childGuidsToUse[counter];
-                counter++;
+                if (node is not FolderNode && childGuidsToUse is not null && counter < childGuidsToUse.Length)
+                {
+                    node.Id = childGuidsToUse[counter];
+                    counter++;
+                }
+            }
+
+            if (firstApply)
+            {
+                keyFramesMap[node.Id] = new List<Guid>();
+                keyFramesMap[node.Id].AddRange(x.KeyFrames.Select(kf => kf.KeyFrameGuid));
+            }
+            else
+            {
+                if (keyFramesMap.TryGetValue(node.Id, out List<Guid>? keyFrameGuids))
+                {
+                    for (int i = 0; i < x.KeyFrames.Count; i++)
+                    {
+                        if (i < keyFrameGuids.Count)
+                        {
+                            var kf = x.KeyFrames[i] as KeyFrameData;
+                            kf.KeyFrameGuid = keyFrameGuids[i];
+                        }
+                    }
+                }
+            }
+
+            if (firstApply)
+            {
+                nodeMap[x.Id] = node.Id;
+                contentGuidList.Add(node.Id);
             }
-            
-            nodeMap[x.Id] = node.Id;
-            contentGuidList.Add(node.Id);
 
             target.NodeGraph.AddNode(node);
 
@@ -154,6 +199,9 @@ internal class DuplicateFolder_Change : Change
                 target.FindNodeOrThrow<Node>(targetNodeId), target.NodeGraph));
         }
 
-        contentDuplicateGuids = contentGuidList.ToArray();
+        if (firstApply)
+        {
+            contentDuplicateGuids = contentGuidList.ToArray();
+        }
     }
 }

+ 2 - 1
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -235,7 +235,8 @@ internal class DocumentOperationsModule : IDocumentOperations
         {
             Internals.ActionAccumulator.AddFinishedActions(
                 new DuplicateFolder_Action(guidValue, newGuid, null),
-                new SetSelectedMember_PassthroughAction(newGuid));
+                new SetSelectedMember_PassthroughAction(newGuid),
+                new CreateAnimationDataFromFolder_Action(newGuid));
         }
 
         return newGuid;