Browse Source

Made Document parser work

flabbet 2 years ago
parent
commit
ba1919405d

+ 14 - 3
src/PixiEditor/Helpers/DocumentViewModelBuilder.cs

@@ -24,6 +24,8 @@ internal class DocumentViewModelBuilder : ChildrenBuilder
     {
         private MaskBuilder maskBuilder;
         
+        public int OrderInStructure { get; set; }
+
         public string Name { get; set; }
         
         public bool IsVisible { get; set; }
@@ -45,6 +47,12 @@ internal class DocumentViewModelBuilder : ChildrenBuilder
             Opacity = 1;
         }
         
+        public StructureMemberBuilder WithOrderInStructure(int order)
+        {
+            OrderInStructure = order;
+            return this;
+        }
+        
         public StructureMemberBuilder WithName(string name)
         {
             Name = name;
@@ -155,7 +163,7 @@ internal class DocumentViewModelBuilder : ChildrenBuilder
 
     public class FolderBuilder : StructureMemberBuilder
     {
-        public IEnumerable<StructureMemberBuilder> Children { get; set; }
+        public List<StructureMemberBuilder> Children { get; set; } = new List<StructureMemberBuilder>();
 
         public new FolderBuilder WithName(string name) => base.WithName(name) as FolderBuilder;
         
@@ -168,9 +176,12 @@ internal class DocumentViewModelBuilder : ChildrenBuilder
         public new FolderBuilder WithMask(Action<MaskBuilder> mask) => base.WithMask(mask) as FolderBuilder;
         
         public new FolderBuilder WithGuid(Guid guid) => base.WithGuid(guid) as FolderBuilder;
-        
+
         public FolderBuilder WithChildren(Action<ChildrenBuilder> children)
         {
+            ChildrenBuilder childrenBuilder = new();
+            children(childrenBuilder);
+            Children = childrenBuilder.Children;
             return this;
         }
     }
@@ -229,7 +240,7 @@ internal class DocumentViewModelBuilder : ChildrenBuilder
 
 internal class ChildrenBuilder
 {
-    public ICollection<DocumentViewModelBuilder.StructureMemberBuilder> Children { get; set; } = new List<DocumentViewModelBuilder.StructureMemberBuilder>();
+    public List<DocumentViewModelBuilder.StructureMemberBuilder> Children { get; set; } = new List<DocumentViewModelBuilder.StructureMemberBuilder>();
         
     public ChildrenBuilder WithLayer(Action<DocumentViewModelBuilder.LayerBuilder> layer)
     {

+ 137 - 16
src/PixiEditor/Helpers/Extensions/ParserHelpers.cs

@@ -1,31 +1,152 @@
-using PixiEditor.Models.DataHolders;
-using PixiEditor.Parser;
+using PixiEditor.Parser;
+using PixiEditor.Parser.Collections;
+using PixiEditor.ViewModels.SubViewModels.Document;
 
 namespace PixiEditor.Helpers.Extensions;
 
 internal static class ParserHelpers
 {
-    /*public static Document ToDocument(this SerializableDocument serializableDocument)
+    public static DocumentViewModel ToDocument(this SerializableDocument serializableDocument)
     {
-        
-        Document document = new Document(serializableDocument.Width, serializableDocument.Height)
+        List<SerializableLayer> builtLayers = new List<SerializableLayer>();
+        DocumentViewModel vm = DocumentViewModel.Build(builder =>
         {
-            Layers = serializableDocument.ToLayers(),
-            Swatches = new WpfObservableRangeCollection<SKColor>(serializableDocument.Swatches.ToSKColors()),
-            Palette = new WpfObservableRangeCollection<SKColor>(serializableDocument.Palette.ToSKColors())
-        };
+            builder.WithSize(serializableDocument.Width, serializableDocument.Height);
+            
+            if (serializableDocument.Groups != null)
+            {
+                foreach (var group in serializableDocument.Groups)
+                {
+                    builder.WithFolder((folderBuilder =>
+                    {
+                        builtLayers = BuildFolder(folderBuilder, group,
+                            GatherFolderLayers(group, serializableDocument.Layers),
+                            serializableDocument);
+                    }));
+                }
+            }
+            
+            BuildLayers(serializableDocument.Layers.Where(x => !builtLayers.Contains(x)), builder, serializableDocument);
+            SortMembers(builder.Children);
+        });
+
+        return vm;
+    }
 
-        document.LayerStructure.Groups = serializableDocument.ToGroups(document);
+    /// <summary>
+    ///     Builds folder and its children.
+    /// </summary>
+    /// <param name="folderBuilder">Folder to build.</param>
+    /// <param name="group">Serialized folder (group), which will be used to build.</param>
+    /// <param name="layers">Layers only in this folder.</param>
+    /// <param name="doc">Document which contains all the serialized data.</param>
+    /// <returns>List of layers which were built.</returns>
+    private static List<SerializableLayer> BuildFolder(DocumentViewModelBuilder.FolderBuilder folderBuilder, SerializableGroup group, List<SerializableLayer> layers, SerializableDocument doc)
+    {
+        List<SerializableLayer> builtLayers = new List<SerializableLayer>(layers);
+        folderBuilder
+            .WithName(group.Name)
+            .WithOpacity(group.Opacity)
+            .WithVisibility(group.IsVisible)
+            .WithOrderInStructure(group.StartLayer);
+            
+        folderBuilder.WithChildren((childrenBuilder =>
+            {
+                if (group.Subgroups != null)
+                {
+                    foreach (var subGroup in group.Subgroups)
+                    {
+                        childrenBuilder.WithFolder((subFolderBuilder =>
+                        {
+                            builtLayers.AddRange(BuildFolder(subFolderBuilder, subGroup,
+                                GatherFolderLayers(subGroup, doc.Layers), doc));
+                        }));
+                    }
+                }
+
+                BuildLayers(layers, childrenBuilder, doc);
+            }));
+
+        return builtLayers;
+    }
 
-        if (document.Layers.Count > 0)
+    private static void BuildLayers(IEnumerable<SerializableLayer> layers, ChildrenBuilder builder, SerializableDocument document)
+    {
+        if (layers != null)
         {
-            document.SetMainActiveLayer(0);
+            foreach (var layer in layers)
+            {
+                builder.WithLayer((layerBuilder) =>
+                {
+                    layerBuilder
+                        .WithSize(layer.Width, layer.Height)
+                        .WithName(layer.Name)
+                        .WithOpacity(layer.Opacity)
+                        .WithVisibility(layer.IsVisible)
+                        .WithRect(layer.Width, layer.Height, layer.OffsetX, layer.OffsetY)
+                        .WithSurface((surfaceBuilder) => surfaceBuilder.WithImage(layer.PngBytes))
+                        .WithOrderInStructure(document.Layers.IndexOf(layer));
+                });
+            }
         }
-        document.Renderer.ForceRerender();
+    }
+    
+    /// <summary>
+    ///     Gathers all layers which are in the folder. Excludes layers which are in subfolders.
+    /// </summary>
+    /// <param name="group">Group which contains folder data.</param>
+    /// <param name="serializableDocumentLayers">All layers in document.</param>
+    /// <returns>List of layers in folder, excluding layers in nested folders.</returns>
+    private static List<SerializableLayer> GatherFolderLayers(SerializableGroup group, LayerCollection serializableDocumentLayers)
+    {
+        List<SerializableLayer> layers = new List<SerializableLayer>();
 
-        return document;
-        throw new NotImplementedException();
-    }*/
+        for (int i = group.StartLayer; i <= group.EndLayer; i++)
+        {
+            layers.Add(serializableDocumentLayers[i]);
+        }
+        
+        if(group.Subgroups is { Count: > 0 })
+        {
+            foreach (var subGroup in group.Subgroups)
+            {
+                var nestedGroupLayers = GatherFolderLayers(subGroup, serializableDocumentLayers);
+                layers.RemoveAll(x => nestedGroupLayers.Contains(x));
+            }
+        }
+
+        return layers;
+    }
+    
+    /// <summary>
+    /// Sorts StructureMemberBuilder by its OrderInStructure property.
+    /// </summary>
+    /// <param name="builderChildren">Structure to sort</param>
+    private static void SortMembers(List<DocumentViewModelBuilder.StructureMemberBuilder> builderChildren)
+    {
+        int previousOrder = -1;
+        int previousIndex = -1;
+
+        for (var index = 0; index < builderChildren.Count; index++)
+        {
+            var child = builderChildren[index];
+            if (child is DocumentViewModelBuilder.FolderBuilder folderBuilder)
+            {
+                SortMembers(folderBuilder.Children);
+            }
+
+            int order = child.OrderInStructure;
+            if (order < previousOrder)
+            {
+                builderChildren.Remove(child);
+                builderChildren.Insert(previousIndex, child);
+            }
+
+            previousIndex = builderChildren.IndexOf(child);
+            previousOrder = order;
+        }
+    }
+    
     /*
     public static WpfObservableRangeCollection<Layer> ToLayers(this SerializableDocument document)
     {

+ 4 - 5
src/PixiEditor/Models/IO/Importer.cs

@@ -11,6 +11,7 @@ using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
 using PixiEditor.Exceptions;
 using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
+using PixiEditor.Parser;
 using PixiEditor.ViewModels.SubViewModels.Document;
 
 namespace PixiEditor.Models.IO;
@@ -60,18 +61,16 @@ internal class Importer : NotifyableObject
 
     public static DocumentViewModel ImportDocument(string path)
     {
-        /*
         try
         {
-            Document doc = PixiEditor.Parser.PixiParser.Deserialize(path).ToDocument();
-            doc.DocumentFilePath = path;
+            DocumentViewModel doc = PixiParser.Deserialize(path).ToDocument();
+            doc.FullFilePath = path;
             return doc;
         }
         catch (InvalidFileException)
         {
             throw new CorruptedFileException();
-        }*/
-        return null;
+        }
     }
 
     public static bool IsSupportedFile(string path)

+ 4 - 0
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs

@@ -211,6 +211,10 @@ internal class DocumentViewModel : NotifyableObject
             {
                 PasteImage(member.GuidValue, layer.Surface, layer.Width, layer.Height, layer.OffsetX, layer.OffsetY, false);
             }
+            
+            acc.AddActions(
+                new StructureMemberOpacity_Action(member.GuidValue, member.Opacity),
+                new EndStructureMemberOpacity_Action());
 
             if (member.HasMask)
             {

+ 1 - 0
src/PixiEditor/ViewModels/SubViewModels/Main/FileViewModel.cs

@@ -222,6 +222,7 @@ internal class FileViewModel : SubViewModel<ViewModelMain>
         if (manager.Documents.Select(x => x.FullFilePath).All(y => y != path))
         {
             manager.Documents.Add(document);
+            Owner.WindowSubViewModel.CreateNewViewport(document);
             Owner.WindowSubViewModel.MakeDocumentViewportActive(document);
         }
         else