浏览代码

Merge branch 'fixes/2.0.1.7' into development

Krzysztof Krysiński 1 月之前
父节点
当前提交
e96207e2a1

+ 36 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/FolderNode.cs

@@ -176,6 +176,42 @@ public class FolderNode : StructureNode, IReadOnlyFolderNode, IClipSource
         return null;
     }
 
+    public override ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
+    {
+        RectD? bounds = null;
+        if (!IsVisible.Value)
+            return new ShapeCorners();
+
+        if (Content.Connection != null)
+        {
+            Content.Connection.Node.TraverseBackwards(
+                (n, input) =>
+                {
+                    if (n is StructureNode { IsVisible.Value: true } structureNode)
+                    {
+                        ShapeCorners childBounds = structureNode.GetTransformationCorners(frameTime);
+                        if (childBounds != default)
+                        {
+                            if (bounds == null)
+                            {
+                                bounds = childBounds.AABBBounds;
+                            }
+                            else
+                            {
+                                bounds = bounds.Value.Union(childBounds.AABBBounds);
+                            }
+                        }
+                    }
+
+                    return true;
+                }, FilterInvisibleFolders);
+
+            return bounds != null ? new ShapeCorners(bounds.Value) : new ShapeCorners();
+        }
+
+        return new ShapeCorners();
+    }
+
     public override RectD? GetApproxBounds(KeyFrameTime frameTime)
     {
         RectD? bounds = null;

+ 17 - 0
src/PixiEditor.ChangeableDocument/Changes/Structure/ImportFolder_Change.cs

@@ -152,6 +152,11 @@ internal class ImportFolder_Change : Change
                     counter++;
                 }
 
+                if (node is LayerNode layerNode)
+                {
+                    ResizeImageData(layerNode, target.Size);
+                }
+
                 contentGuidToNodeMap[x.Id] = node.Id;
 
                 target.NodeGraph.AddNode(node);
@@ -179,6 +184,18 @@ internal class ImportFolder_Change : Change
         }
     }
 
+    private void ResizeImageData(LayerNode layerNode, VecI docSize)
+    {
+        foreach (var imageData in layerNode.KeyFrames)
+        {
+            if (imageData.Data is ChunkyImage img)
+            {
+                img.EnqueueResize(docSize);
+                img.CommitChanges();
+            }
+        }
+    }
+
     public override void Dispose()
     {
         base.Dispose();

+ 42 - 26
src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs

@@ -164,38 +164,50 @@ public class DocumentRenderer : IPreviewRenderable, IDisposable
 
         fullGraph.OutputNode.TraverseBackwards((node, input) =>
         {
-            if (node is StructureNode structureNode && membersToCombine != null &&
-                !membersToCombine.Contains(structureNode.Id))
-            {
-                return true;
-            }
+            return CloneElement(membersToCombine, fullGraph, node, membersOnlyGraph, input, nodeMapping);
+        });
 
-            if (node is LayerNode layer)
-            {
-                LayerNode clone = (LayerNode)layer.Clone();
-                membersOnlyGraph.AddNode(clone);
+        return membersOnlyGraph;
+    }
 
+    private static bool CloneElement(HashSet<Guid>? membersToCombine, IReadOnlyNodeGraph fullGraph, IReadOnlyNode node,
+        NodeGraph membersOnlyGraph, IInputProperty input, Dictionary<Guid, Guid> nodeMapping,
+        IInputProperty? fallback = null)
+    {
+        if (node is StructureNode structureNode && membersToCombine != null &&
+            !membersToCombine.Contains(structureNode.Id))
+        {
+            return true;
+        }
 
-                IInputProperty targetInput = GetTargetInput(input, fullGraph, membersOnlyGraph, nodeMapping);
+        if (node is LayerNode layer)
+        {
+            LayerNode clone = (LayerNode)layer.Clone();
+            membersOnlyGraph.AddNode(clone);
 
-                clone.Output.ConnectTo(targetInput);
-                nodeMapping[layer.Id] = clone.Id;
-            }
-            else if (node is FolderNode folder)
-            {
-                FolderNode clone = (FolderNode)folder.Clone();
-                membersOnlyGraph.AddNode(clone);
+            IInputProperty targetInput = GetTargetInput(input, fullGraph, membersOnlyGraph, nodeMapping, fallback);
 
-                var targetInput = GetTargetInput(input, fullGraph, membersOnlyGraph, nodeMapping);
+            clone.Output.ConnectTo(targetInput);
+            nodeMapping[layer.Id] = clone.Id;
+        }
+        else if (node is FolderNode folder)
+        {
+            FolderNode clone = (FolderNode)folder.Clone();
+            membersOnlyGraph.AddNode(clone);
 
-                clone.Output.ConnectTo(targetInput);
-                nodeMapping[folder.Id] = clone.Id;
-            }
+            var targetInput = GetTargetInput(input, fullGraph, membersOnlyGraph, nodeMapping, fallback);
 
-            return true;
-        });
+            clone.Output.ConnectTo(targetInput);
+            nodeMapping[folder.Id] = clone.Id;
 
-        return membersOnlyGraph;
+            folder.Content.Connection?.Node.TraverseBackwards((childNode, childInput) =>
+            {
+                return CloneElement(membersToCombine, fullGraph, childNode, membersOnlyGraph, childInput,
+                    nodeMapping, clone.Content);
+            });
+        }
+
+        return true;
     }
 
     RectD? IPreviewRenderable.GetPreviewBounds(int frame, string elementNameToRender = "") =>
@@ -324,9 +336,13 @@ public class DocumentRenderer : IPreviewRenderable, IDisposable
     private static IInputProperty GetTargetInput(IInputProperty? input,
         IReadOnlyNodeGraph sourceGraph,
         NodeGraph membersOnlyGraph,
-        Dictionary<Guid, Guid> nodeMapping)
+        Dictionary<Guid, Guid> nodeMapping, IInputProperty? fallback = null)
     {
-        if (input == null)
+        if (input == null && fallback != null)
+        {
+            return fallback;
+        }
+        else if (input == null)
         {
             if (membersOnlyGraph.OutputNode is IRenderInput inputNode) return inputNode.Background;
 

+ 6 - 6
src/PixiEditor/Models/Controllers/ClipboardController.cs

@@ -372,7 +372,7 @@ internal static class ClipboardController
             pos = await GetVecD(ClipboardDataFormats.PositionFormat, dataFormats);
         }
 
-        RectD? tightBounds = null;
+        RectD? transformBounds = null;
         for (var i = 0; i < layerIds.Length; i++)
         {
             var layerId = layerIds[i];
@@ -381,17 +381,17 @@ internal static class ClipboardController
 
             if (layer == null) return false;
 
-            if (tightBounds == null)
+            if (transformBounds == null)
             {
-                tightBounds = layer.TransformationCorners.AABBBounds;
+                transformBounds = layer.TransformationCorners.AABBBounds;
             }
-            else if (layer.TightBounds.HasValue)
+            else if (!layer.TransformationCorners.HasNaNOrInfinity)
             {
-                tightBounds = tightBounds.Value.Union(layer.TransformationCorners.AABBBounds);
+                transformBounds = transformBounds.Value.Union(layer.TransformationCorners.AABBBounds);
             }
         }
 
-        return tightBounds.HasValue && tightBounds.Value.Pos.AlmostEquals(pos);
+        return transformBounds.HasValue && transformBounds.Value.Pos.AlmostEquals(pos);
     }
 
     private static async Task<Guid[]> GetLayerIds(IImportObject[] formats)

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

@@ -297,7 +297,8 @@ internal class DocumentOperationsModule : IDocumentOperations
         {
             Internals.ActionAccumulator.AddFinishedActions(
                 new ImportFolder_Action(sourceDocument.ShareNode<IReadOnlyFolderNode>(folder.Id), newGuid, null),
-                new SetSelectedMember_PassthroughAction(newGuid));
+                new SetSelectedMember_PassthroughAction(newGuid),
+                new CreateAnimationDataFromFolder_Action(newGuid));
         }
 
         return newGuid;

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

@@ -460,7 +460,8 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
                 {
                     object value =
                         SerializationUtil.Deserialize(propertyValue.Value, config, allFactories, serializerData);
-                    acc.AddActions(new UpdatePropertyValue_Action(guid, propertyValue.Key, value), new EndUpdatePropertyValue_Action());
+                    acc.AddActions(new UpdatePropertyValue_Action(guid, propertyValue.Key, value),
+                        new EndUpdatePropertyValue_Action());
                 }
             }
 
@@ -826,6 +827,21 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         if (bounds.IsZeroOrNegativeArea)
             return new None();
 
+        var toAdd = new HashSet<Guid>();
+        foreach (var layer in selectedLayers)
+        {
+            var parents = StructureHelper.GetParents(layer);
+            if (parents is null)
+                continue;
+
+            foreach (var parent in parents)
+            {
+                toAdd.Add(parent.Id);
+            }
+        }
+
+        selectedLayers.UnionWith(toAdd);
+
         RectI finalBounds = default;
 
         for (int i = 0; i < selectedLayers.Count; i++)