diff --git a/source/AsepriteDotNet/Processors/TextureAtlasProcessor.cs b/source/AsepriteDotNet/Processors/TextureAtlasProcessor.cs index 3450c28..067b403 100644 --- a/source/AsepriteDotNet/Processors/TextureAtlasProcessor.cs +++ b/source/AsepriteDotNet/Processors/TextureAtlasProcessor.cs @@ -43,6 +43,7 @@ public static TextureAtlas Process(AsepriteFile file, ProcessorOptions? options /// The amount of transparent pixels to add to the edge of the generated texture. /// The amount of transparent pixels to add between each texture region in the generated texture. /// The amount of transparent pixels to add around the edge of each texture region in the generated texture. + /// Indicates whether each layer should be processed separately. /// The . /// Thrown when is . public static TextureAtlas Process(AsepriteFile file, @@ -52,7 +53,8 @@ public static TextureAtlas Process(AsepriteFile file, bool mergeDuplicateFrames = true, int borderPadding = 0, int spacing = 0, - int innerPadding = 0) + int innerPadding = 0, + bool splitLayers = false) { ArgumentNullException.ThrowIfNull(file); @@ -66,7 +68,7 @@ public static TextureAtlas Process(AsepriteFile file, layers.Add(layer.Name); } - return Process(file, layers, mergeDuplicateFrames, borderPadding, spacing, innerPadding); + return Process(file, layers, mergeDuplicateFrames, borderPadding, spacing, innerPadding, splitLayers); } /// @@ -81,12 +83,14 @@ public static TextureAtlas Process(AsepriteFile file, /// The amount of transparent pixels to add to the edge of the generated texture. /// The amount of transparent pixels to add between each texture region in the generated texture. /// The amount of transparent pixels to add around the edge of each texture region in the generated texture. + /// Indicates whether each layer should be processed separately instead of being flattened together. /// /// The created by this method. If is empty or contains zero /// elements, then is returned. /// /// Thrown when is . - public static TextureAtlas Process(AsepriteFile file, ICollection layers, bool mergeDuplicateFrames = true, int borderPadding = 0, int spacing = 0, int innerPadding = 0) + public static TextureAtlas Process(AsepriteFile file, ICollection layers, bool mergeDuplicateFrames = true, int borderPadding = 0, int spacing = 0, int innerPadding = 0, bool splitLayers = false) + { ArgumentNullException.ThrowIfNull(file); @@ -99,12 +103,55 @@ public static TextureAtlas Process(AsepriteFile file, ICollection layers int frameHeight = file.CanvasHeight; int frameCount = file.Frames.Length; - Rgba32[][] flattenedFrames = new Rgba32[frameCount][]; + Rgba32[][] flattenedFrames; - for (int i = 0; i < frameCount; i++) + if (splitLayers) { - flattenedFrames[i] = file.Frames[i].FlattenFrame(layers); + flattenedFrames = new Rgba32[layers.Count * frameCount][]; + + List layerList = new List(layers); + + for (int i = 0; i < frameCount; i++) + { + for (int layerIndex = 0; layerIndex < layerList.Count; layerIndex++) + { + string layerName = layerList[layerIndex]; + AsepriteCel? cel = null; + + foreach (AsepriteCel frameCel in file.Frames[i].Cels) + { + if (frameCel.Layer.Name == layerName) + { + cel = frameCel; + break; + } + } + + if (cel is null) continue; + + if (cel is AsepriteLinkedCel linkedCel) + { + cel = linkedCel.Cel; + } + + if (cel is AsepriteImageCel imageCel) + { + flattenedFrames[i * layers.Count + layerIndex] = imageCel.Pixels.ToArray(); + } + } + } } + else + { + flattenedFrames = new Rgba32[frameCount][]; + + for (int i = 0; i < frameCount; i++) + { + flattenedFrames[i] = file.Frames[i].FlattenFrame(layers); + } + } + + frameCount = flattenedFrames.Length; Dictionary duplicateMap = new Dictionary(); Dictionary originalToDuplicateLookup = new Dictionary(); @@ -141,7 +188,7 @@ public static TextureAtlas Process(AsepriteFile file, ICollection layers + (innerPadding * 2 * rows); Rgba32[] imagePixels = new Rgba32[imageWidth * imageHeight]; - TextureRegion[] regions = new TextureRegion[file.Frames.Length]; + TextureRegion[] regions = new TextureRegion[flattenedFrames.Length]; int offset = 0;