diff --git a/.build/Build.sln b/.build/Build.sln deleted file mode 100644 index 5e0a3062..00000000 --- a/.build/Build.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Build", "Build.csproj", "{86E7FFCA-81BE-403B-A2EE-61D4C8526111}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {86E7FFCA-81BE-403B-A2EE-61D4C8526111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {86E7FFCA-81BE-403B-A2EE-61D4C8526111}.Debug|Any CPU.Build.0 = Debug|Any CPU - {86E7FFCA-81BE-403B-A2EE-61D4C8526111}.Release|Any CPU.ActiveCfg = Release|Any CPU - {86E7FFCA-81BE-403B-A2EE-61D4C8526111}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/.build/BuildContext.cs b/.build/BuildContext.cs deleted file mode 100644 index a5a82d57..00000000 --- a/.build/BuildContext.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.IO; -using Cake.Common; -using Cake.Common.Build; -using Cake.Common.Xml; -using Cake.Core; -using Cake.Frosting; - -namespace BuildScripts; - -public sealed class BuildContext : FrostingContext -{ - public readonly string ArtifactsDirectory; - public readonly string Version; - public readonly string? RepositoryOwner; - public readonly string? RepositoryUrl; - public readonly bool IsTag; - public readonly bool IsRunningOnGitHubActions; - public readonly string? GitHubToken; - public readonly string? NuGetAccessToken; - public readonly string MonoGameAsepritePath; - public readonly string MonoGameAsepriteContentPipelinePath; - public readonly string MonoGameAsepriteTestsPath; - - public BuildContext(ICakeContext context) : base(context) - { - ArtifactsDirectory = context.Argument(nameof(ArtifactsDirectory), ".artifacts"); - MonoGameAsepritePath = context.Argument(nameof(MonoGameAsepritePath), "source/MonoGame.Aseprite/MonoGame.Aseprite.csproj"); - MonoGameAsepriteContentPipelinePath = context.Argument(nameof(MonoGameAsepriteContentPipelinePath), "source/MonoGame.Aseprite.Content.Pipeline/MonoGame.Aseprite.Content.Pipeline.csproj"); - MonoGameAsepriteTestsPath = context.Argument(nameof(MonoGameAsepriteTestsPath), "tests/MonoGame.Aseprite.Tests/MonoGame.Aseprite.Tests.csproj"); - Version = context.XmlPeek("source/MonoGame.Aseprite/MonoGame.Aseprite.csproj", "/Project/PropertyGroup/Version"); - - IsRunningOnGitHubActions = context.BuildSystem().IsRunningOnGitHubActions; - if (IsRunningOnGitHubActions) - { - RepositoryOwner = context.EnvironmentVariable("GITHUB_REPOSITORY_OWNER"); - RepositoryUrl = $"https://github.com/{context.EnvironmentVariable("GITHUB_REPOSITORY")}"; - GitHubToken = context.EnvironmentVariable("GITHUB_TOKEN"); - IsTag = context.EnvironmentVariable("GITHUB_REF_TYPE") == "tag"; - - if (IsTag) - { - NuGetAccessToken = context.EnvironmentVariable("NUGET_ACCESS_TOKEN"); - } - } - } - - -} \ No newline at end of file diff --git a/.build/BuildTask.cs b/.build/BuildTask.cs deleted file mode 100644 index a923611c..00000000 --- a/.build/BuildTask.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Cake.Common.Tools.DotNet; -using Cake.Common.Tools.DotNet.Build; -using Cake.Common.Tools.DotNet.MSBuild; -using Cake.Frosting; - -namespace BuildScripts; - -[TaskName(nameof(BuildTask))] -public sealed class BuildTask : FrostingTask -{ - public override void Run(BuildContext context) - { - DotNetMSBuildSettings msBuildSettings = new DotNetMSBuildSettings(); - msBuildSettings.WithProperty("Version", context.Version); - - DotNetBuildSettings buildSettings = new DotNetBuildSettings() - { - MSBuildSettings = msBuildSettings, - Configuration = "Release", - Verbosity = DotNetVerbosity.Minimal, - NoLogo = true - }; - - context.DotNetBuild(context.MonoGameAsepritePath, buildSettings); - context.DotNetBuild(context.MonoGameAsepriteContentPipelinePath, buildSettings); - context.DotNetBuild(context.MonoGameAsepriteTestsPath, buildSettings); - } -} \ No newline at end of file diff --git a/.build/DeployToGithubTask.cs b/.build/DeployToGithubTask.cs deleted file mode 100644 index 49c78b0c..00000000 --- a/.build/DeployToGithubTask.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Cake.Common.Tools.DotNet; -using Cake.Common.Tools.DotNet.NuGet.Push; -using Cake.Frosting; - -namespace BuildScripts; - -[TaskName(nameof(DeployToGitHubTask))] -public sealed class DeployToGitHubTask : FrostingTask -{ - public override bool ShouldRun(BuildContext context) => context.IsRunningOnGitHubActions; - - public override void Run(BuildContext context) - { - DotNetNuGetPushSettings pushSettings = new DotNetNuGetPushSettings() - { - Source = $"https://nuget.pkg.github.com/{context.RepositoryOwner}/index.json", - ApiKey = context.GitHubToken - }; - - context.DotNetNuGetPush($"{context.ArtifactsDirectory}/*.nupkg", pushSettings); - } -} \ No newline at end of file diff --git a/.build/DeployToNuGetTask.cs b/.build/DeployToNuGetTask.cs deleted file mode 100644 index b10e686a..00000000 --- a/.build/DeployToNuGetTask.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using Cake.Common.Tools.DotNet; -using Cake.Common.Tools.DotNet.NuGet.Push; -using Cake.Frosting; - -namespace BuildScripts; - -[TaskName(nameof(DeployToNuGetTask))] -public sealed class DeployToNuGetTask : FrostingTask -{ - public override bool ShouldRun(BuildContext context) => - context.IsRunningOnGitHubActions && - context.IsTag && - !string.IsNullOrEmpty(context.RepositoryOwner) && - context.RepositoryOwner.Equals("AristurtleDev", StringComparison.InvariantCultureIgnoreCase); - - - public override void Run(BuildContext context) - { - DotNetNuGetPushSettings pushSettings = new DotNetNuGetPushSettings() - { - Source = "https://api.nuget.org/v3/index.json", - ApiKey = context.NuGetAccessToken - }; - - context.DotNetNuGetPush($"{context.ArtifactsDirectory}/*.nupkg", pushSettings); - } -} \ No newline at end of file diff --git a/.build/PackageTask.cs b/.build/PackageTask.cs deleted file mode 100644 index 7d9abe99..00000000 --- a/.build/PackageTask.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Cake.Common.IO; -using Cake.Common.Tools.DotNet; -using Cake.Common.Tools.DotNet.MSBuild; -using Cake.Common.Tools.DotNet.Pack; -using Cake.Frosting; - -namespace BuildScripts; - -[TaskName(nameof(PackageTask))] -public sealed class PackageTask : FrostingTask -{ - public override void Run(BuildContext context) - { - context.CleanDirectory(context.ArtifactsDirectory); - context.CreateDirectory(context.ArtifactsDirectory); - - DotNetMSBuildSettings msBuildSettings = new DotNetMSBuildSettings(); - msBuildSettings.WithProperty("Version", context.Version); - msBuildSettings.WithProperty("PackageVersion", context.Version); - - DotNetPackSettings packSettings = new DotNetPackSettings() - { - Configuration = "Release", - OutputDirectory = context.ArtifactsDirectory, - MSBuildSettings = msBuildSettings - }; - - context.DotNetPack(context.MonoGameAsepritePath, packSettings); - } -} \ No newline at end of file diff --git a/.build/Program.cs b/.build/Program.cs deleted file mode 100644 index ebb78742..00000000 --- a/.build/Program.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Threading.Tasks; -using Cake.Core; -using Cake.Core.Diagnostics; -using Cake.Frosting; - -namespace BuildScripts; - -public static class Program -{ - public static int Main(string[] args) - { - return new CakeHost() - .UseContext() - .UseWorkingDirectory("../") - .Run(args); - } -} - -[TaskName("Default")] -[IsDependentOn(typeof(RestoreTask))] -[IsDependentOn(typeof(BuildTask))] -[IsDependentOn(typeof(TestTask))] -[IsDependentOn(typeof(PackageTask))] -public sealed class DefaultTask : FrostingTask {} - -[TaskName("Deploy")] -[IsDependentOn(typeof(DeployToGitHubTask))] -[IsDependentOn(typeof(DeployToNuGetTask))] -public sealed class DeployTask : FrostingTask {} \ No newline at end of file diff --git a/.build/RestoreTask.cs b/.build/RestoreTask.cs deleted file mode 100644 index 5337ef65..00000000 --- a/.build/RestoreTask.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Cake.Common.Tools.DotNet; -using Cake.Common.Tools.DotNet.Restore; -using Cake.Frosting; - -namespace BuildScripts; - -[TaskName(nameof(RestoreTask))] -public sealed class RestoreTask : FrostingTask -{ - public override void Run(BuildContext context) - { - DotNetRestoreSettings restoreSettings = new DotNetRestoreSettings() - { - Verbosity = DotNetVerbosity.Quiet - }; - context.DotNetRestore(context.MonoGameAsepritePath, restoreSettings); - context.DotNetRestore(context.MonoGameAsepriteContentPipelinePath, restoreSettings); - context.DotNetRestore(context.MonoGameAsepriteTestsPath, restoreSettings); - } -} \ No newline at end of file diff --git a/.build/TestTask.cs b/.build/TestTask.cs deleted file mode 100644 index 0c0c2672..00000000 --- a/.build/TestTask.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Cake.Common.Tools.DotNet; -using Cake.Common.Tools.DotNet.Test; -using Cake.Frosting; - -namespace BuildScripts; - -[TaskName(nameof(TestTask))] -public sealed class TestTask : FrostingTask -{ - public override void Run(BuildContext context) - { - DotNetTestSettings testSettings = new DotNetTestSettings() - { - Configuration = "Release", - }; - context.DotNetTest(context.MonoGameAsepriteTestsPath, testSettings); - } -} \ No newline at end of file diff --git a/.github/workflows/buildandtest.yml b/.github/workflows/buildandtest.yml deleted file mode 100644 index 053ce43f..00000000 --- a/.github/workflows/buildandtest.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: build-and-test -on: - push: - tags: [v*] - pull_request: - branches: ['main'] - - -env: - DOTNET_VERSION: '6.0.400' - - -jobs: - build-test-pack-job: - name: "Build-Test-Pack" - runs-on: ubuntu-latest - steps: - - name: "Clone Repository" - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: "Setup .NET" - uses: actions/setup-dotnet@v3 - with: - dotnet-version: ${{ env.DOTNET_VERSION }} - - - name: "CAKE (Build -> Test -> Package)" - run: dotnet run --project ./.build/Build.csproj -- --target=Default - - - name: "Upload Artifacts For Deploy" - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@main - with: - name: MonoGame.Aseprite - path: ./artifacts/* - - deploy-job: - name: "Deploy NuGets" - runs-on: ubuntu-latest - permissions: - packages: write - contents: write - needs: [build-test-pack-job] - if: ${{ github.event_name == 'push' }} - steps: - - name: "Clone Repository" - uses: actions/checkout@v4 - - - name: "Download Artifacts For Deploy" - uses: actions/download-artifact@v3 - with: - name: MonoGame.Aseprite - path: artifacts - - - name: "Push Packages" - run: dotnet run --project ./.build/Build.csproj -- --target=Deploy - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NUGET_ACCESS_TOKEN: ${{ secrets.NUGET_ACCESS_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..481c94bd --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,89 @@ +name: Build AsepriteDotNet + +on: + pull_request: + branches: [ develop, main ] + push: + branches: [ main ] + tags: + - 'v*' + +jobs: + build: + name: Build + runs-on: ubuntu-latest + + steps: + - name: Expose GitHub Runtime + uses: crazy-max/ghaction-github-runtime@v3 + + - name: Clone Repository + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Build + run: dotnet run --project build/MonoGame.Aseprite.Build.csproj -- --target=Default + + - name: Upload Artifacts + run: dotnet run --project build/MonoGame.Aseprite.Build.csproj -- --target=UploadArtifacts + env: + ACTIONS_RUNTIME_TOKEN: ${{ env.ACTIONS_RUNTIME_TOKEN }} + ACTIONS_RUNTIME_URL: "${{ env.ACTIONS_RUNTIME_URL }}" + + deploy-to-github: + name: Deploy To GitHub + needs: [ build ] + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + permissions: + packages: write + contents: write + steps: + - name: Expose GitHub Runtime + uses: crazy-max/ghaction-github-runtime@v3 + + - name: Clone Repository + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Push GitHub NuGets + run: dotnet run --project build/MonoGame.Aseprite.Build.csproj -- --target=DeployNuGetsToGitHub + env: + ACTIONS_RUNTIME_TOKEN: ${{ env.ACTIONS_RUNTIME_TOKEN }} + ACTIONS_RUNTIME_URL: "${{ env.ACTIONS_RUNTIME_URL }}" + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + deploy-to-nuget: + name: Deploy To NuGet + needs: [ build ] + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }} + permissions: + packages: write + contents: write + steps: + - name: Expose GitHub Runtime + uses: crazy-max/ghaction-github-runtime@v3 + + - name: Clone Repository + uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: '8.0.x' + + - name: Push NuGets + run: dotnet run --project build/MonoGame.Aseprite.Build.csproj -- --target=DeployNuGets + env: + ACTIONS_RUNTIME_TOKEN: ${{ env.ACTIONS_RUNTIME_TOKEN }} + ACTIONS_RUNTIME_URL: "${{ env.ACTIONS_RUNTIME_URL }}" + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} diff --git a/.github/images/banner.png b/.images/banner.png similarity index 100% rename from .github/images/banner.png rename to .images/banner.png diff --git a/.github/images/banner.svg b/.images/banner.svg similarity index 100% rename from .github/images/banner.svg rename to .images/banner.svg diff --git a/.github/images/kofi-bg-black.webp b/.images/kofi-bg-black.webp similarity index 100% rename from .github/images/kofi-bg-black.webp rename to .images/kofi-bg-black.webp diff --git a/.github/images/kofi-bg-white.webp b/.images/kofi-bg-white.webp similarity index 100% rename from .github/images/kofi-bg-white.webp rename to .images/kofi-bg-white.webp diff --git a/.github/images/logo.svg b/.images/logo.svg similarity index 100% rename from .github/images/logo.svg rename to .images/logo.svg diff --git a/.nuget/img/icon.png b/.images/nuget-icon.png similarity index 100% rename from .nuget/img/icon.png rename to .images/nuget-icon.png diff --git a/.nuget/img/icon.svg b/.images/nuget-icon.svg similarity index 100% rename from .nuget/img/icon.svg rename to .images/nuget-icon.svg diff --git a/.nuget/README.md b/.nuget/README.md deleted file mode 100644 index ae594a53..00000000 --- a/.nuget/README.md +++ /dev/null @@ -1,91 +0,0 @@ -![MonoGame.Aseprite Banner](https://raw.githubusercontent.com/AristurtleDev/monogame-aseprite/main/.github/images/banner.png) - -A Cross Platform C# Library That Adds Support For Aseprite Files in MonoGame Projects. - -[![build-and-test](https://github.com/AristurtleDev/monogame-aseprite/actions/workflows/buildandtest.yml/badge.svg)](https://github.com/AristurtleDev/monogame-aseprite/actions/workflows/buildandtest.yml) -[![Nuget 5.1.3](https://img.shields.io/nuget/v/MonoGame.Aseprite?color=blue&style=flat-square)](https://www.nuget.org/packages/MonoGame.Aseprite/5.1.3) -[![License: MIT](https://img.shields.io/badge/📃%20license-MIT-blue?style=flat)](LICENSE) -[![Twitter](https://img.shields.io/badge/%20-Share%20On%20Twitter-555?style=flat&logo=twitter)](https://twitter.com/intent/tweet?text=MonoGame.Aseprite%20by%20%40aristurtledev%0A%0AA%20cross-platform%20C%23%20library%20that%20adds%20support%20for%20Aseprite%20files%20in%20MonoGame%20projects.%20https%3A%2F%2Fgithub.com%2FAristurtleDev%2Fmonogame-aseprite%0A%0A%23monogame%20%23aseprite%20%23dotnet%20%23csharp%20%23oss%0A) - -[MonoGame.Aseprite](https://monogameaseprite.net) is a free and open source library for the [MonoGame Framework](https://www.monogame.net) that assists in importing [Aseprite](https://www.aseprite.org) (.ase | .aseprite) files into your game project. No need to export a spritesheet from Aseprite and have to deal with a PNG + JSON file. With [MonoGame.Aseprite](https://monogameaseprite.net), you can use the Aseprite file directly. - -[MonoGame.Aseprite](https://monogameaseprite.net) supports importing the file **both with and without the MGCB Editor** (also known as the Content Pipeline Tool). Along with importing the file contents, several [**processors**](https://monogameaseprite.net/guides/processors/processors-overview.html) have been designed to transform the file contents into a more meaningful state to use within MonoGame. - -[MonoGame.Aseprite](https://monogameaseprite.net) also supports outputting the processed file content to disk in a binary format and reader classes to read the processed information back in. This adds support for pre-processing content using any build or content workflow the end user has as long as it can use the [MonoGame.Aseprite](https://monogameaseprite.net) library. - -## Getting Started - -To get started using [MonoGame.Aseprite](https://monogameaseprite.net) start with the [Installation document](https://monogameaseprite.net/guides/getting-started/installation.html). - -## Features - -- Import your Aseprite file at runtime with and without the MGCB Editor (Content Pipeline Tool) -- Multiple built-in [processors](https://monogameaseprite.net/guides/processors/processors-overview.html) that can be used to transform the data from your Aseprite file into any of the following: - - [Sprite](https://monogameaseprite.net/guides/processors/sprite-processor.html) - - [TextureAtlas](https://monogameaseprite.net/guides/processors/texture-atlas-processor.html) - - [SpriteSheet](https://monogameaseprite.net/guides/processors/sprite-sheet-processor.html) - - [Tileset](https://monogameaseprite.net/guides/processors/tileset-processor.html) - - [Tilemap](https://monogameaseprite.net/guides/processors/tilemap-processor.html) - - [AnimatedTilemap](https://monogameaseprite.net/guides/processors/animated-tilemap-processor.html). -- All blend modes in Aseprite supported 1:1. -- Runtime writers and readers that can be used in custom content processing workflows to preprocess content outside of the game. - -## What Next? - -- Read the [documentation](https://monogameaseprite.net/). -- Join the [Discord](https://discord.gg/8jFvHhuMJU) to ask questions or keep up to date. -- Submit an [issue on GitHub](https://github.com/AristurtleDev/monogame-aseprite/issues). -- Follow me on [Mastodon](https://mastodon.gamedev.place/@aristurtle) or [Twitter](https://www.twitter.com/aristurtledev). - -## Games Made With MonoGame.Aseprite -The following are games that have been made using MonoGame.Aseprite as part of the content workflow in MonoGame - -| Game | Developer Links | -|--- |---| -|

Superstar Strategy

| -|

Unnamed

| | - -## Support - -If you would like to support this project in any way, there are quite a few ways to do this no matter who you are. - -- Tell others about this project. -- Contribute to this project (Please ensure you read the [Contributing Guide](./CONTRIBUTING.md)). -- [Submit an Issue](https://github.com/AristurtleDev/monogame-aseprite/issues) if you find a problem -- [Star](https://docs.github.com/en/get-started/exploring-projects-on-github/saving-repositories-with-stars) this project on Github. - -If you would prefer to send me a tip/donation, you can do so at my [Ko-fi page](https://ko-fi.com/aristurtledev). This is always appreciated and all donations go towards funding projects of mine such as this one. - -[![](.github/images/kofi-bg-white.webp)](https://ko-fi.com/aristurtledev) - -You can also support me through [GitHub Sponsors](https://github.com/sponsors/AristurtleDev). This and the Ko-Fi links can both be found in the sidebar to the right on this repository page. - -The following is a list of amazing people that have donated to sponsor this project. If you have donated but weren't added to the list, please get in contact with me. - - -* [fdrobidoux](https://github.com/fdrobidoux) -* [Anticdope](https://twitter.com/anticdope) - ---- - -## License - -Copyright(c) 2018-2023 Chris Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..55644dc1 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,37 @@ + + + + + + $(MSBuildThisFileDirectory) + + + + + $(SolutionDirectory).artifacts/ + $(ProjectCategory)/$(MSBuildProjectName) + $(BaseArtifactsPath)obj/$(BaseArtifactsPathSuffix) + $(BaseArtifactsPath)bin/$(BaseArtifactsPathSuffix) + $(BaseArtifactsPath)pkg/$(BaseArtifactsPathSuffix)/$(Configuration)/ + + + + + en + enable + enable + 6.0.0 + + + + + true + AllEnabledByDefault + latest + true + true + false + false + nullable + + \ No newline at end of file diff --git a/MonoGame.Aseprite.sln b/MonoGame.Aseprite.sln new file mode 100644 index 00000000..db60aa8f --- /dev/null +++ b/MonoGame.Aseprite.sln @@ -0,0 +1,121 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "source", "source", "{CF520A36-B1B8-4CFA-9835-C3345A65D57B}" + ProjectSection(SolutionItems) = preProject + source\Directory.Build.props = source\Directory.Build.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Aseprite", "source\MonoGame.Aseprite\MonoGame.Aseprite.csproj", "{B5D9570E-E9BF-482B-BD73-8EA6EC4330F8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Aseprite.Content.Pipeline", "source\MonoGame.Aseprite.Content.Pipeline\MonoGame.Aseprite.Content.Pipeline.csproj", "{49903681-88CC-4B14-AD02-C475E78D4CE2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{78ECB0CA-72B0-4E08-BAB1-8BF2B98829D9}" + ProjectSection(SolutionItems) = preProject + build\Directory.Build.props = build\Directory.Build.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoGame.Aseprite.Build", "build\MonoGame.Aseprite.Build.csproj", "{4E3BCA48-A076-4ECE-A80A-F254DAE2D18E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".root", ".root", "{780173B6-AA4D-40B8-ADA6-D99531857B64}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitignore = .gitignore + Directory.Build.props = Directory.Build.props + LICENSE = LICENSE + README.md = README.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{C177CFCE-9FD8-4EFA-9046-B5ECC55401CE}" + ProjectSection(SolutionItems) = preProject + examples\Directory.Build.props = examples\Directory.Build.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AnimatedTilemapExample", "examples\AnimatedTilemapExample\AnimatedTilemapExample.csproj", "{6E52E54B-E074-4CEE-86D2-F0E3D429F4F6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ContentPipelineExample", "examples\ContentPipelineExample\ContentPipelineExample.csproj", "{615E3A66-5DDB-4691-88BA-6E10E71E1899}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpriteExample", "examples\SpriteExample\SpriteExample.csproj", "{2DEBEDB6-C604-4CC6-94CC-A6964E2781F4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpritesheetExample", "examples\SpritesheetExample\SpritesheetExample.csproj", "{7EBC52B4-982A-4CA1-AD88-CEEA4573E4EF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextureAtlasExample", "examples\TextureAtlasExample\TextureAtlasExample.csproj", "{55C32452-39B1-4FD0-92D2-1037909B0571}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TilemapExample", "examples\TilemapExample\TilemapExample.csproj", "{813FAB91-CDF4-4F50-8C1A-B4987E84E45A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TilesetExample", "examples\TilesetExample\TilesetExample.csproj", "{385D0648-538D-4A90-A1EA-FEF44C9F9517}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{9F695AEE-9518-4019-B1DE-9C3254FB0D2C}" + ProjectSection(SolutionItems) = preProject + .github\workflows\main.yml = .github\workflows\main.yml + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B5D9570E-E9BF-482B-BD73-8EA6EC4330F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5D9570E-E9BF-482B-BD73-8EA6EC4330F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5D9570E-E9BF-482B-BD73-8EA6EC4330F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5D9570E-E9BF-482B-BD73-8EA6EC4330F8}.Release|Any CPU.Build.0 = Release|Any CPU + {49903681-88CC-4B14-AD02-C475E78D4CE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49903681-88CC-4B14-AD02-C475E78D4CE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49903681-88CC-4B14-AD02-C475E78D4CE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49903681-88CC-4B14-AD02-C475E78D4CE2}.Release|Any CPU.Build.0 = Release|Any CPU + {4E3BCA48-A076-4ECE-A80A-F254DAE2D18E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E3BCA48-A076-4ECE-A80A-F254DAE2D18E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E3BCA48-A076-4ECE-A80A-F254DAE2D18E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E3BCA48-A076-4ECE-A80A-F254DAE2D18E}.Release|Any CPU.Build.0 = Release|Any CPU + {6E52E54B-E074-4CEE-86D2-F0E3D429F4F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E52E54B-E074-4CEE-86D2-F0E3D429F4F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E52E54B-E074-4CEE-86D2-F0E3D429F4F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E52E54B-E074-4CEE-86D2-F0E3D429F4F6}.Release|Any CPU.Build.0 = Release|Any CPU + {615E3A66-5DDB-4691-88BA-6E10E71E1899}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {615E3A66-5DDB-4691-88BA-6E10E71E1899}.Debug|Any CPU.Build.0 = Debug|Any CPU + {615E3A66-5DDB-4691-88BA-6E10E71E1899}.Release|Any CPU.ActiveCfg = Release|Any CPU + {615E3A66-5DDB-4691-88BA-6E10E71E1899}.Release|Any CPU.Build.0 = Release|Any CPU + {2DEBEDB6-C604-4CC6-94CC-A6964E2781F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2DEBEDB6-C604-4CC6-94CC-A6964E2781F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2DEBEDB6-C604-4CC6-94CC-A6964E2781F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DEBEDB6-C604-4CC6-94CC-A6964E2781F4}.Release|Any CPU.Build.0 = Release|Any CPU + {7EBC52B4-982A-4CA1-AD88-CEEA4573E4EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EBC52B4-982A-4CA1-AD88-CEEA4573E4EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EBC52B4-982A-4CA1-AD88-CEEA4573E4EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EBC52B4-982A-4CA1-AD88-CEEA4573E4EF}.Release|Any CPU.Build.0 = Release|Any CPU + {55C32452-39B1-4FD0-92D2-1037909B0571}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55C32452-39B1-4FD0-92D2-1037909B0571}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55C32452-39B1-4FD0-92D2-1037909B0571}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55C32452-39B1-4FD0-92D2-1037909B0571}.Release|Any CPU.Build.0 = Release|Any CPU + {813FAB91-CDF4-4F50-8C1A-B4987E84E45A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {813FAB91-CDF4-4F50-8C1A-B4987E84E45A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {813FAB91-CDF4-4F50-8C1A-B4987E84E45A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {813FAB91-CDF4-4F50-8C1A-B4987E84E45A}.Release|Any CPU.Build.0 = Release|Any CPU + {385D0648-538D-4A90-A1EA-FEF44C9F9517}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {385D0648-538D-4A90-A1EA-FEF44C9F9517}.Debug|Any CPU.Build.0 = Debug|Any CPU + {385D0648-538D-4A90-A1EA-FEF44C9F9517}.Release|Any CPU.ActiveCfg = Release|Any CPU + {385D0648-538D-4A90-A1EA-FEF44C9F9517}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B5D9570E-E9BF-482B-BD73-8EA6EC4330F8} = {CF520A36-B1B8-4CFA-9835-C3345A65D57B} + {49903681-88CC-4B14-AD02-C475E78D4CE2} = {CF520A36-B1B8-4CFA-9835-C3345A65D57B} + {4E3BCA48-A076-4ECE-A80A-F254DAE2D18E} = {78ECB0CA-72B0-4E08-BAB1-8BF2B98829D9} + {6E52E54B-E074-4CEE-86D2-F0E3D429F4F6} = {C177CFCE-9FD8-4EFA-9046-B5ECC55401CE} + {615E3A66-5DDB-4691-88BA-6E10E71E1899} = {C177CFCE-9FD8-4EFA-9046-B5ECC55401CE} + {2DEBEDB6-C604-4CC6-94CC-A6964E2781F4} = {C177CFCE-9FD8-4EFA-9046-B5ECC55401CE} + {7EBC52B4-982A-4CA1-AD88-CEEA4573E4EF} = {C177CFCE-9FD8-4EFA-9046-B5ECC55401CE} + {55C32452-39B1-4FD0-92D2-1037909B0571} = {C177CFCE-9FD8-4EFA-9046-B5ECC55401CE} + {813FAB91-CDF4-4F50-8C1A-B4987E84E45A} = {C177CFCE-9FD8-4EFA-9046-B5ECC55401CE} + {385D0648-538D-4A90-A1EA-FEF44C9F9517} = {C177CFCE-9FD8-4EFA-9046-B5ECC55401CE} + {9F695AEE-9518-4019-B1DE-9C3254FB0D2C} = {780173B6-AA4D-40B8-ADA6-D99531857B64} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {185C72A8-896C-42E7-93F4-99FCD65E0961} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md index 1fafd96b..66c5b02b 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,46 @@

-MonoGame.Aseprite Logo +MonoGame.Aseprite Logo
A Cross Platform C# Library That Adds Support For Aseprite Files in MonoGame Projects. -[![build-and-test](https://github.com/AristurtleDev/monogame-aseprite/actions/workflows/buildandtest.yml/badge.svg)](https://github.com/AristurtleDev/monogame-aseprite/actions/workflows/buildandtest.yml) -[![Nuget 5.1.3](https://img.shields.io/nuget/v/MonoGame.Aseprite?color=blue&style=flat-square)](https://www.nuget.org/packages/MonoGame.Aseprite/5.1.3) +[![build-and-test](https://github.com/AristurtleDev/monogame-aseprite/actions/workflows/main.yml/badge.svg)](https://github.com/AristurtleDev/monogame-aseprite/actions/workflows/main.yml) +[![NuGet 6.0.0](https://img.shields.io/nuget/v/MonoGame.Aseprite?color=blue&style=flat-square)](https://www.nuget.org/packages/MonoGame.Aseprite/6.0.0) [![License: MIT](https://img.shields.io/badge/📃%20license-MIT-blue?style=flat)](LICENSE) [![Twitter](https://img.shields.io/badge/%20-Share%20On%20Twitter-555?style=flat&logo=twitter)](https://twitter.com/intent/tweet?text=MonoGame.Aseprite%20by%20%40aristurtledev%0A%0AA%20cross-platform%20C%23%20library%20that%20adds%20support%20for%20Aseprite%20files%20in%20MonoGame%20projects.%20https%3A%2F%2Fgithub.com%2FAristurtleDev%2Fmonogame-aseprite%0A%0A%23monogame%20%23aseprite%20%23dotnet%20%23csharp%20%23oss%0A)

-# MonoGame.Aseprite +**Monogame.Aseprite** is a free and open source library for the [MonoGame Framework](https://monogame.net) that assists in importing [Aseprite](https://www.aseprite.org) files into your game project. No need to export a spritesheet from Aseprite and have to deal with a PNG + JSON import. With **MonoGame.Aseprite**, you can use the Aseprite file directly. -[MonoGame.Aseprite](https://monogameaseprite.net) is a free and open source library for the [MonoGame Framework](https://www.monogame.net) that assists in importing [Aseprite](https://www.aseprite.org) (.ase | .aseprite) files into your game project. No need to export a spritesheet from Aseprite and have to deal with a PNG + JSON file. With [MonoGame.Aseprite](https://monogameaseprite.net), you can use the Aseprite file directly. +# Features +- **MonoGame.Aseprite** internally uses [AsepriteDotNet](https://github.com/AristurtleDev/AsepriteDotNet) to read and parse the aseprite files. This means you get all the features of AsepriteDotNet including + - Supports Aseprite files using **RGBA**, **Grayscale**, and **Indexed** color modes. + - Supports all Aseprite layer blend modes. + - Supports Aseprite tilesets, tilemap layers, and tilemap cels. +- Provides processors to convert the Aseprite data into common formats including: + - Sprite + - SpriteSheet + - TextureAtlas + - Tileset + - Tilemap + - AnimatedTilemap -[MonoGame.Aseprite](https://monogameaseprite.net) supports importing the file **both with and without the MGCB Editor** (also known as the Content Pipeline Tool). Along with importing the file contents, several [**processors**](https://monogameaseprite.net/guides/processors/processors-overview.html) have been designed to transform the file contents into a more meaningful state to use within MonoGame. -[MonoGame.Aseprite](https://monogameaseprite.net) also supports outputting the processed file content to disk in a binary format and reader classes to read the processed information back in. This adds support for pre-processing content using any build or content workflow the end user has as long as it can use the [MonoGame.Aseprite](https://monogameaseprite.net) library. +# Installation +Install via NuGet +``` +dotnet add package MonoGame.Aseprite --version 6.0.0 +``` -## Getting Started +# Usage +Please refer to the [Examples](./examples) directory for samples of how to use this library. Each example is thoroughly commented with information to show you how to load the Aseprite file and use it within Monogame. -To get started using [MonoGame.Aseprite](https://monogameaseprite.net) start with the [Installation document](https://monogameaseprite.net/guides/getting-started/installation.html). - -## Features - -- Import your Aseprite file at runtime with and without the MGCB Editor (Content Pipeline Tool) -- Multiple built-in [processors](https://monogameaseprite.net/guides/processors/processors-overview.html) that can be used to transform the data from your Aseprite file into any of the following: - - [Sprite](https://monogameaseprite.net/guides/processors/sprite-processor.html) - - [TextureAtlas](https://monogameaseprite.net/guides/processors/texture-atlas-processor.html) - - [SpriteSheet](https://monogameaseprite.net/guides/processors/sprite-sheet-processor.html) - - [Tileset](https://monogameaseprite.net/guides/processors/tileset-processor.html) - - [Tilemap](https://monogameaseprite.net/guides/processors/tilemap-processor.html) - - [AnimatedTilemap](https://monogameaseprite.net/guides/processors/animated-tilemap-processor.html). -- All blend modes in Aseprite supported 1:1. -- Runtime writers and readers that can be used in custom content processing workflows to preprocess content outside of the game. - -## What Next? +# What Next? - Read the [documentation](https://monogameaseprite.net/). - Join the [Discord](https://discord.gg/8jFvHhuMJU) to ask questions or keep up to date. - Submit an [issue on GitHub](https://github.com/AristurtleDev/monogame-aseprite/issues). -- Follow me on [Mastodon](https://mastodon.gamedev.place/@aristurtle) or [Twitter](https://www.twitter.com/aristurtledev). +- [Twitter](https://www.twitter.com/aristurtledev). ## Games Made With MonoGame.Aseprite The following are games that have been made using MonoGame.Aseprite as part of the content workflow in MonoGame @@ -50,7 +50,7 @@ The following are games that have been made using MonoGame.Aseprite as part of t |

Superstar Strategy

| |

Unnamed

| | -## Support +# Support If you would like to support this project in any way, there are quite a few ways to do this no matter who you are. @@ -61,7 +61,7 @@ If you would like to support this project in any way, there are quite a few ways If you would prefer to send me a tip/donation, you can do so at my [Ko-fi page](https://ko-fi.com/aristurtledev). This is always appreciated and all donations go towards funding projects of mine such as this one. -[![](.github/images/kofi-bg-white.webp)](https://ko-fi.com/aristurtledev) +[![](.images/kofi-bg-white.webp)](https://ko-fi.com/aristurtledev) You can also support me through [GitHub Sponsors](https://github.com/sponsors/AristurtleDev). This and the Ko-Fi links can both be found in the sidebar to the right on this repository page. @@ -73,24 +73,12 @@ The following is a list of amazing people that have donated to sponsor this proj --- -## License - -Copyright(c) 2018-2023 Chris Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +# License +**MonoGame.Aseprite** is licensed under the **MIT License**. Please refer to the [LICENSE](LICENSE) file for full license text. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. +# Contributors + + + -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +Made with [contrib.rocks](https://contrib.rocks). \ No newline at end of file diff --git a/build/BuildContext.cs b/build/BuildContext.cs new file mode 100644 index 00000000..8fceebf0 --- /dev/null +++ b/build/BuildContext.cs @@ -0,0 +1,108 @@ +using System.Net.Mime; +using Cake.Common; +using Cake.Common.Build; +using Cake.Common.Build.GitHubActions.Data; +using Cake.Common.IO; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Build; +using Cake.Common.Tools.DotNet.MSBuild; +using Cake.Common.Tools.DotNet.Pack; +using Cake.Common.Tools.DotNet.Publish; +using Cake.Common.Tools.MSBuild; +using Cake.Common.Xml; +using Cake.Core; +using Cake.Core.Diagnostics; +using Cake.Core.IO; +using Cake.Frosting; + +namespace MonoGame.Aseprite.Build; + +public sealed class BuildContext : FrostingContext +{ + private const string DefaultRepositoryUrl = "https://github.com/AristurtleDev/monogame-aseprite"; + private const string DefaultBuildConfiguration = "Release"; + + + public string Version { get; } + public string BuildOutput { get; } + public string RepositoryUrl { get; } + public string BuildConfiguration { get; } + public bool IsPreRelease { get; } + + public DirectoryPath NuGetsDirectory { get; } + public DotNetMSBuildSettings DotNetMSBuildSettings { get; } + public DotNetPublishSettings DotNetPublishSettings { get; } + public MSBuildSettings MSBuildSettings { get; } + public MSBuildSettings MSPackSettings { get; } + + public BuildContext(ICakeContext context) : base(context) + { + RepositoryUrl = context.Argument(nameof(RepositoryUrl), DefaultRepositoryUrl); + BuildConfiguration = context.Argument(nameof(BuildConfiguration), DefaultBuildConfiguration); + BuildOutput = context.Argument(nameof(BuildOutput), ".artifacts"); + NuGetsDirectory = $"{BuildOutput}/NuGet/"; + IsPreRelease = context.Argument(nameof(IsPreRelease), false); + + Version = context.XmlPeek("Directory.Build.props", "/Project/PropertyGroup/Version"); + if (context.BuildSystem().IsRunningOnGitHubActions) + { + GitHubActionsWorkflowInfo workflow = context.BuildSystem().GitHubActions.Environment.Workflow; + RepositoryUrl = $"https://github.com/{workflow.Repository}"; + + if (!RepositoryUrl.Equals(DefaultRepositoryUrl, StringComparison.OrdinalIgnoreCase)) + { + Version = $"{Version}-{workflow.RepositoryOwner}"; + } + else if (workflow.RefType == GitHubActionsRefType.Branch && !workflow.RefName.Equals("refs/head/main", StringComparison.OrdinalIgnoreCase)) + { + Version = $"{Version}-develop"; + } + else if (IsPreRelease) + { + Version = $"{Version}-prerelease"; + } + else + { + Version = $"{Version}"; + } + } + + DotNetMSBuildSettings = new DotNetMSBuildSettings(); + DotNetMSBuildSettings.WithProperty(nameof(Version), Version); + DotNetMSBuildSettings.WithProperty(nameof(RepositoryUrl), RepositoryUrl); + + MSBuildSettings = new MSBuildSettings + { + Verbosity = Verbosity.Minimal, + Configuration = BuildConfiguration + }; + MSBuildSettings.WithProperty(nameof(Version), Version); + MSBuildSettings.WithProperty(nameof(RepositoryUrl), RepositoryUrl); + + MSPackSettings = new MSBuildSettings() + { + Verbosity = Verbosity.Minimal, + Configuration = BuildConfiguration, + Restore = true + }; + MSPackSettings.WithProperty(nameof(Version), Version); + MSPackSettings.WithProperty(nameof(RepositoryUrl), RepositoryUrl); + MSPackSettings.WithProperty("OutputDirectory", NuGetsDirectory.FullPath); + MSPackSettings.WithTarget("Pack"); + + DotNetPublishSettings = new DotNetPublishSettings() + { + MSBuildSettings = DotNetMSBuildSettings, + Verbosity = DotNetVerbosity.Minimal, + Configuration = BuildConfiguration, + SelfContained = false + }; + + Console.WriteLine($"{nameof(Version)}: {Version}"); + Console.WriteLine($"{nameof(RepositoryUrl)}: {RepositoryUrl}"); + Console.WriteLine($"{nameof(BuildConfiguration)}: {BuildConfiguration}"); + + context.CreateDirectory(BuildOutput); + } + +} diff --git a/build/Directory.Build.props b/build/Directory.Build.props new file mode 100644 index 00000000..2b254aba --- /dev/null +++ b/build/Directory.Build.props @@ -0,0 +1,11 @@ + + + + + + build + + + + + diff --git a/.build/Build.csproj b/build/MonoGame.Aseprite.Build.csproj similarity index 100% rename from .build/Build.csproj rename to build/MonoGame.Aseprite.Build.csproj diff --git a/build/Program.cs b/build/Program.cs new file mode 100644 index 00000000..f8f1facd --- /dev/null +++ b/build/Program.cs @@ -0,0 +1,7 @@ +using Cake.Frosting; +using MonoGame.Aseprite.Build; + +return new CakeHost() + .UseWorkingDirectory("../") + .UseContext() + .Run(args); diff --git a/build/Tasks/BuildTask.cs b/build/Tasks/BuildTask.cs new file mode 100644 index 00000000..458a1797 --- /dev/null +++ b/build/Tasks/BuildTask.cs @@ -0,0 +1,24 @@ +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Build; +using Cake.Frosting; + +namespace MonoGame.Aseprite.Build; + +[TaskName("Build")] +public sealed class BuildTask : FrostingTask +{ + public override void Run(BuildContext context) + { + ArgumentNullException.ThrowIfNull(context); + + DotNetBuildSettings settings = new DotNetBuildSettings() + { + MSBuildSettings = context.DotNetMSBuildSettings, + Verbosity = DotNetVerbosity.Minimal, + Configuration = context.BuildConfiguration + }; + + context.DotNetBuild("./source/MonoGame.Aseprite/MonoGame.Aseprite.csproj", settings); + context.DotNetBuild("./source/MonoGame.Aseprite.Content.Pipeline/MonoGame.Aseprite.Content.Pipeline.csproj", settings); + } +} \ No newline at end of file diff --git a/build/Tasks/GitHubTasks/DeployNuGetsToGitHubTask.cs b/build/Tasks/GitHubTasks/DeployNuGetsToGitHubTask.cs new file mode 100644 index 00000000..6b592487 --- /dev/null +++ b/build/Tasks/GitHubTasks/DeployNuGetsToGitHubTask.cs @@ -0,0 +1,29 @@ +using Cake.Common; +using Cake.Common.Build; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.NuGet.Push; +using Cake.Frosting; + + +namespace MonoGame.Aseprite.Build; + +[TaskName("DeployNuGetsToGithub")] +[IsDependentOn(typeof(DownloadArtifactsTask))] +public sealed class DeployNuGetsToGitHubTask : FrostingTask +{ + public override bool ShouldRun(BuildContext context) => context.BuildSystem().IsRunningOnGitHubActions; + + public override void Run(BuildContext context) + { + ArgumentNullException.ThrowIfNull(context); + + string repositoryOwner = context.GitHubActions().Environment.Workflow.RepositoryOwner; + DotNetNuGetPushSettings settings = new DotNetNuGetPushSettings() + { + ApiKey = context.EnvironmentVariable("GITHUB_TOKEN"), + Source = $"https://nuget.pkg.github.com/{repositoryOwner}/index.json" + }; + + context.DotNetNuGetPush("nugets/*.nupkg", settings); + } +} diff --git a/build/Tasks/GitHubTasks/DeployNugetsTask.cs b/build/Tasks/GitHubTasks/DeployNugetsTask.cs new file mode 100644 index 00000000..86aeaa11 --- /dev/null +++ b/build/Tasks/GitHubTasks/DeployNugetsTask.cs @@ -0,0 +1,27 @@ +using Cake.Common; +using Cake.Common.Build; +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.NuGet.Push; +using Cake.Frosting; + +namespace MonoGame.Aseprite.Build; + +[TaskName("DeployNuGets")] +[IsDependentOn(typeof(DownloadArtifactsTask))] +public sealed class DeployNuGetsTask : FrostingTask +{ + public override bool ShouldRun(BuildContext context) => context.BuildSystem().IsRunningOnGitHubActions; + + public override void Run(BuildContext context) + { + ArgumentNullException.ThrowIfNull(context); + + DotNetNuGetPushSettings settings = new DotNetNuGetPushSettings() + { + ApiKey = context.EnvironmentVariable("NUGET_API_KEY"), + Source = "https://api.nuget.org/v3/index.json" + }; + + context.DotNetNuGetPush("nugets/*.nupkg", settings); + } +} diff --git a/build/Tasks/GitHubTasks/DownloadArtifactsTask.cs b/build/Tasks/GitHubTasks/DownloadArtifactsTask.cs new file mode 100644 index 00000000..e16be305 --- /dev/null +++ b/build/Tasks/GitHubTasks/DownloadArtifactsTask.cs @@ -0,0 +1,22 @@ +using Cake.Common.Build; +using Cake.Common.IO; +using Cake.Frosting; + +namespace MonoGame.Aseprite.Build; + +[TaskName("DownloadArtifacts")] +public sealed class DownloadArtifactsTask : AsyncFrostingTask +{ + public override bool ShouldRun(BuildContext context) => context.BuildSystem().IsRunningOnGitHubActions; + + public override async Task RunAsync(BuildContext context) + { + ArgumentNullException.ThrowIfNull(context); + string path = "nugets"; + context.CreateDirectory(path); + await context.GitHubActions() + .Commands + .DownloadArtifact(path, path) + .ConfigureAwait(true); + } +} diff --git a/build/Tasks/GitHubTasks/UploadArtifactsTask.cs b/build/Tasks/GitHubTasks/UploadArtifactsTask.cs new file mode 100644 index 00000000..af9c51e2 --- /dev/null +++ b/build/Tasks/GitHubTasks/UploadArtifactsTask.cs @@ -0,0 +1,22 @@ +using Cake.Common.Build; +using Cake.Core.IO; +using Cake.Frosting; + +namespace MonoGame.Aseprite.Build; + +[TaskName("UploadArtifacts")] +public sealed class UploadArtifactsTask : AsyncFrostingTask +{ + public override bool ShouldRun(BuildContext context) => context.BuildSystem().IsRunningOnGitHubActions; + + public override async Task RunAsync(BuildContext context) + { + ArgumentNullException.ThrowIfNull(context); + DirectoryPath path = context.NuGetsDirectory.FullPath; + string artifactName = "nugets"; + await context.GitHubActions() + .Commands + .UploadArtifact(path, artifactName) + .ConfigureAwait(true); + } +} diff --git a/build/Tasks/PackTask.cs b/build/Tasks/PackTask.cs new file mode 100644 index 00000000..1010f4aa --- /dev/null +++ b/build/Tasks/PackTask.cs @@ -0,0 +1,23 @@ +using Cake.Common.Tools.DotNet; +using Cake.Common.Tools.DotNet.Pack; +using Cake.Frosting; + +namespace MonoGame.Aseprite.Build; + +[TaskName("Pack")] +public sealed class PackTask : FrostingTask +{ + public override void Run(BuildContext context) + { + ArgumentNullException.ThrowIfNull(context); + DotNetPackSettings settings = new DotNetPackSettings() + { + MSBuildSettings = context.DotNetMSBuildSettings, + Verbosity = DotNetVerbosity.Minimal, + OutputDirectory = context.NuGetsDirectory, + Configuration = context.BuildConfiguration + }; + + context.DotNetPack("./source/MonoGame.Aseprite/MonoGame.Aseprite.csproj", settings); + } +} diff --git a/build/Tasks/Tasks.cs b/build/Tasks/Tasks.cs new file mode 100644 index 00000000..52f3580a --- /dev/null +++ b/build/Tasks/Tasks.cs @@ -0,0 +1,8 @@ +using Cake.Frosting; + +namespace MonoGame.Aseprite.Build; + +[TaskName("Default")] +[IsDependentOn(typeof(BuildTask))] +[IsDependentOn(typeof(PackTask))] +public sealed class DefaultTask : FrostingTask { } diff --git a/examples/AnimatedTilemapExample/.config/dotnet-tools.json b/examples/AnimatedTilemapExample/.config/dotnet-tools.json new file mode 100644 index 00000000..efabe22e --- /dev/null +++ b/examples/AnimatedTilemapExample/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/examples/AnimatedTilemapExample/AnimatedTilemapExample.csproj b/examples/AnimatedTilemapExample/AnimatedTilemapExample.csproj new file mode 100644 index 00000000..df0fd772 --- /dev/null +++ b/examples/AnimatedTilemapExample/AnimatedTilemapExample.csproj @@ -0,0 +1,34 @@ + + + WinExe + net6.0 + Major + false + false + + + app.manifest + Icon.ico + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/examples/AnimatedTilemapExample/Content/Content.mgcb b/examples/AnimatedTilemapExample/Content/Content.mgcb new file mode 100644 index 00000000..ddc4c367 --- /dev/null +++ b/examples/AnimatedTilemapExample/Content/Content.mgcb @@ -0,0 +1,15 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + diff --git a/examples/AnimatedTilemapExample/Game1.cs b/examples/AnimatedTilemapExample/Game1.cs new file mode 100644 index 00000000..3982a28e --- /dev/null +++ b/examples/AnimatedTilemapExample/Game1.cs @@ -0,0 +1,91 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite; + +namespace AnimatedTilemapExample; + +public class Game1 : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + private AnimatedTilemap _animatedTilemap; + private Vector2 _scale; + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Load the file. In this example, we're not using the MGCB/Content Pipeline and have the Aseprite file set as + /// a file in our project that is copied the output directory. Because of this, we can use the + /// TitleContainer.OpenStream to get a stream to the file and use that to load it. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AsepriteFile aseFile; + using (Stream stream = TitleContainer.OpenStream("townmap.aseprite")) + { + aseFile = AsepriteFileLoader.FromStream("townmap", stream); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create an animated tilemap from the file based on all frames. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _animatedTilemap = aseFile.CreateAnimatedTilemap(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Size the tilemap is created 1:1 with the size it is in Aseprite, we're going to create a scale factor here + /// in this example to be the size of the game window. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _scale.X = _graphics.PreferredBackBufferWidth / (float)_animatedTilemap.GetFrame(0).GetLayer(0).Width; + _scale.Y = _graphics.PreferredBackBufferHeight / (float)_animatedTilemap.GetFrame(0).GetLayer(0).Height; + + } + + protected override void Update(GameTime gameTime) + { + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// The animated tilemap must be updated each frame to update the animations. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _animatedTilemap.Update(gameTime); + + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Spritebatch extension are provided to draw the tilemap + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _spriteBatch.Draw(_animatedTilemap, Vector2.Zero, Color.White, _scale, 0.0f); + + _spriteBatch.End(); + } +} diff --git a/examples/AnimatedTilemapExample/Icon.bmp b/examples/AnimatedTilemapExample/Icon.bmp new file mode 100644 index 00000000..2b481653 Binary files /dev/null and b/examples/AnimatedTilemapExample/Icon.bmp differ diff --git a/examples/AnimatedTilemapExample/Icon.ico b/examples/AnimatedTilemapExample/Icon.ico new file mode 100644 index 00000000..7d9dec18 Binary files /dev/null and b/examples/AnimatedTilemapExample/Icon.ico differ diff --git a/examples/AnimatedTilemapExample/Program.cs b/examples/AnimatedTilemapExample/Program.cs new file mode 100644 index 00000000..17691ad9 --- /dev/null +++ b/examples/AnimatedTilemapExample/Program.cs @@ -0,0 +1,6 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using var game = new AnimatedTilemapExample.Game1(); +game.Run(); diff --git a/examples/AnimatedTilemapExample/app.manifest b/examples/AnimatedTilemapExample/app.manifest new file mode 100644 index 00000000..5fffae64 --- /dev/null +++ b/examples/AnimatedTilemapExample/app.manifest @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/examples/AnimatedTilemapExample/townmap.aseprite b/examples/AnimatedTilemapExample/townmap.aseprite new file mode 100644 index 00000000..a7d176b3 Binary files /dev/null and b/examples/AnimatedTilemapExample/townmap.aseprite differ diff --git a/examples/ContentPipelineExample/.config/dotnet-tools.json b/examples/ContentPipelineExample/.config/dotnet-tools.json new file mode 100644 index 00000000..efabe22e --- /dev/null +++ b/examples/ContentPipelineExample/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/examples/ContentPipelineExample/Content/Content.mgcb b/examples/ContentPipelineExample/Content/Content.mgcb new file mode 100644 index 00000000..8567717e --- /dev/null +++ b/examples/ContentPipelineExample/Content/Content.mgcb @@ -0,0 +1,22 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + +/reference:..\..\..\.artifacts\bin\source\MonoGame.Aseprite.Content.Pipeline\Debug\net6.0\MonoGame.Aseprite.Content.Pipeline.dll + +#---------------------------------- Content ---------------------------------# + +#begin character_robot.aseprite +/importer:AsepriteFileContentImporter +/processor:AsepriteFileContentProcessor +/processorParam:PremultiplyAlpha=True +/build:character_robot.aseprite + diff --git a/examples/ContentPipelineExample/Content/character_robot.aseprite b/examples/ContentPipelineExample/Content/character_robot.aseprite new file mode 100644 index 00000000..f235a0fe Binary files /dev/null and b/examples/ContentPipelineExample/Content/character_robot.aseprite differ diff --git a/examples/ContentPipelineExample/ContentPipelineExample.csproj b/examples/ContentPipelineExample/ContentPipelineExample.csproj new file mode 100644 index 00000000..dda860d0 --- /dev/null +++ b/examples/ContentPipelineExample/ContentPipelineExample.csproj @@ -0,0 +1,34 @@ + + + WinExe + net6.0 + Major + false + false + + + app.manifest + Icon.ico + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/examples/ContentPipelineExample/Game1.cs b/examples/ContentPipelineExample/Game1.cs new file mode 100644 index 00000000..9a143a85 --- /dev/null +++ b/examples/ContentPipelineExample/Game1.cs @@ -0,0 +1,61 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite; + +namespace ContentPipelineExample; + +public class Game1 : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + private AnimatedSprite _animatedSprite; + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Load the Aseprite file using the Content Manager + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AsepriteFile aseFile = Content.Load("character_robot"); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Do something with i (see the other examples for more information + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + SpriteSheet sheet = aseFile.CreateSpriteSheet(GraphicsDevice); + _animatedSprite = sheet.CreateAnimatedSprite("walk"); + _animatedSprite.Play(); + } + + protected override void Update(GameTime gameTime) + { + _animatedSprite.Update(gameTime); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + _spriteBatch.Draw(_animatedSprite, new Vector2(10, 10)); + _spriteBatch.End(); + + base.Draw(gameTime); + } +} diff --git a/examples/ContentPipelineExample/Icon.bmp b/examples/ContentPipelineExample/Icon.bmp new file mode 100644 index 00000000..2b481653 Binary files /dev/null and b/examples/ContentPipelineExample/Icon.bmp differ diff --git a/examples/ContentPipelineExample/Icon.ico b/examples/ContentPipelineExample/Icon.ico new file mode 100644 index 00000000..7d9dec18 Binary files /dev/null and b/examples/ContentPipelineExample/Icon.ico differ diff --git a/examples/ContentPipelineExample/Program.cs b/examples/ContentPipelineExample/Program.cs new file mode 100644 index 00000000..707e703a --- /dev/null +++ b/examples/ContentPipelineExample/Program.cs @@ -0,0 +1,6 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using var game = new ContentPipelineExample.Game1(); +game.Run(); diff --git a/examples/ContentPipelineExample/app.manifest b/examples/ContentPipelineExample/app.manifest new file mode 100644 index 00000000..c006af3b --- /dev/null +++ b/examples/ContentPipelineExample/app.manifest @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/examples/Directory.Build.props b/examples/Directory.Build.props new file mode 100644 index 00000000..b9c088c7 --- /dev/null +++ b/examples/Directory.Build.props @@ -0,0 +1,23 @@ + + + + Exe + net8.0 + examples + false + false + Copyright © 2024 Christopher Whitley + Christopher Whitley and contributors + Aristurtle + + + + + + + + + + disable + + diff --git a/examples/SpriteExample/.config/dotnet-tools.json b/examples/SpriteExample/.config/dotnet-tools.json new file mode 100644 index 00000000..efabe22e --- /dev/null +++ b/examples/SpriteExample/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/examples/SpriteExample/Content/Content.mgcb b/examples/SpriteExample/Content/Content.mgcb new file mode 100644 index 00000000..ddc4c367 --- /dev/null +++ b/examples/SpriteExample/Content/Content.mgcb @@ -0,0 +1,15 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + diff --git a/examples/SpriteExample/Game1.cs b/examples/SpriteExample/Game1.cs new file mode 100644 index 00000000..4469b036 --- /dev/null +++ b/examples/SpriteExample/Game1.cs @@ -0,0 +1,71 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite; + +namespace SpriteExample; + +public class Game1 : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + private Sprite _sprite; + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Load the file. In this example, we're not using the MGCB/Content Pipeline and have the Aseprite file set as + /// a file in our project that is copied the output directory. Because of this, we can use the + /// TitleContainer.OpenStream to get a stream to the file and use that to load it. + /// + /// You can optionally enable/disable premultiply alpha for the color values when the file is loaded. If not + /// specified, it will default to true. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AsepriteFile aseFile; + using (Stream stream = TitleContainer.OpenStream("character_robot.aseprite")) + { + aseFile = AsepriteFileLoader.FromStream("character_robot", stream, preMultiplyAlpha: true); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create a sprite from any frame in the aseprite file + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _sprite = aseFile.CreateSprite(GraphicsDevice, 0); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// SpriteBatch extension methods are provided to draw the sprite + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _spriteBatch.Draw(_sprite, new Vector2(10, 10)); + + _spriteBatch.End(); + } +} diff --git a/examples/SpriteExample/Icon.bmp b/examples/SpriteExample/Icon.bmp new file mode 100644 index 00000000..2b481653 Binary files /dev/null and b/examples/SpriteExample/Icon.bmp differ diff --git a/examples/SpriteExample/Icon.ico b/examples/SpriteExample/Icon.ico new file mode 100644 index 00000000..7d9dec18 Binary files /dev/null and b/examples/SpriteExample/Icon.ico differ diff --git a/examples/SpriteExample/Program.cs b/examples/SpriteExample/Program.cs new file mode 100644 index 00000000..19678560 --- /dev/null +++ b/examples/SpriteExample/Program.cs @@ -0,0 +1,6 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using var game = new SpriteExample.Game1(); +game.Run(); diff --git a/examples/SpriteExample/SpriteExample.csproj b/examples/SpriteExample/SpriteExample.csproj new file mode 100644 index 00000000..40822a25 --- /dev/null +++ b/examples/SpriteExample/SpriteExample.csproj @@ -0,0 +1,34 @@ + + + WinExe + net6.0 + Major + false + false + + + app.manifest + Icon.ico + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/examples/SpriteExample/app.manifest b/examples/SpriteExample/app.manifest new file mode 100644 index 00000000..c322b00a --- /dev/null +++ b/examples/SpriteExample/app.manifest @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/examples/SpriteExample/character_robot.aseprite b/examples/SpriteExample/character_robot.aseprite new file mode 100644 index 00000000..f235a0fe Binary files /dev/null and b/examples/SpriteExample/character_robot.aseprite differ diff --git a/examples/SpritesheetExample/.config/dotnet-tools.json b/examples/SpritesheetExample/.config/dotnet-tools.json new file mode 100644 index 00000000..efabe22e --- /dev/null +++ b/examples/SpritesheetExample/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/examples/SpritesheetExample/Content/Content.mgcb b/examples/SpritesheetExample/Content/Content.mgcb new file mode 100644 index 00000000..ddc4c367 --- /dev/null +++ b/examples/SpritesheetExample/Content/Content.mgcb @@ -0,0 +1,15 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + diff --git a/examples/SpritesheetExample/Game1.cs b/examples/SpritesheetExample/Game1.cs new file mode 100644 index 00000000..b1cc76b1 --- /dev/null +++ b/examples/SpritesheetExample/Game1.cs @@ -0,0 +1,115 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite; + +namespace SpritesheetExample; + +public class Game1 : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + + private SpriteSheet _spriteSheet; + private AnimatedSprite _attackCycle; + private AnimatedSprite _runCycle; + private AnimatedSprite _walkCycle; + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Load the file. In this example, we're not using the MGCB/Content Pipeline and have the Aseprite file set as + /// a file in our project that is copied the output directory. Because of this, we can use the + /// TitleContainer.OpenStream to get a stream to the file and use that to load it. + /// + /// You can optionally enable/disable premultiply alpha for the color values when the file is loaded. If not + /// specified, it will default to true. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AsepriteFile aseFile; + using (Stream stream = TitleContainer.OpenStream("character_robot.aseprite")) + { + aseFile = AsepriteFileLoader.FromStream("character_robot", stream, preMultiplyAlpha: true); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create a sprite sheet from any frame in the aseprite file + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _spriteSheet = aseFile.CreateSpriteSheet(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create the animated sprites from the sprite sheet. + /// Each animated sprite correlates to a tag from Aseprite. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _walkCycle = _spriteSheet.CreateAnimatedSprite("walk"); + _runCycle = _spriteSheet.CreateAnimatedSprite("run"); + _attackCycle = _spriteSheet.CreateAnimatedSprite("attack"); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Tell the animated sprite to play. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _walkCycle.Play(); + _runCycle.Play(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// You can even set a specific loop count when telling it to play. Setting this will override the "Repeat" + /// value that was set in Aseprite. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _attackCycle.Play(loopCount: 3); + } + + protected override void Update(GameTime gameTime) + { + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Animations need to be updated every frame + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _walkCycle.Update(gameTime); + _runCycle.Update(gameTime); + _attackCycle.Update(gameTime); + } + + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// SpriteBatch extension methods are provided to draw the animated sprites + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _spriteBatch.Draw(_attackCycle, new Vector2(10, 10)); + _spriteBatch.Draw(_walkCycle, new Vector2(_attackCycle.Width, 10)); + _spriteBatch.Draw(_runCycle, new Vector2(_attackCycle.Width * 2, 10)); + + + _spriteBatch.End(); + } +} diff --git a/examples/SpritesheetExample/Icon.bmp b/examples/SpritesheetExample/Icon.bmp new file mode 100644 index 00000000..2b481653 Binary files /dev/null and b/examples/SpritesheetExample/Icon.bmp differ diff --git a/examples/SpritesheetExample/Icon.ico b/examples/SpritesheetExample/Icon.ico new file mode 100644 index 00000000..7d9dec18 Binary files /dev/null and b/examples/SpritesheetExample/Icon.ico differ diff --git a/examples/SpritesheetExample/Program.cs b/examples/SpritesheetExample/Program.cs new file mode 100644 index 00000000..1d7dbae3 --- /dev/null +++ b/examples/SpritesheetExample/Program.cs @@ -0,0 +1,6 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using var game = new SpritesheetExample.Game1(); +game.Run(); diff --git a/examples/SpritesheetExample/SpritesheetExample.csproj b/examples/SpritesheetExample/SpritesheetExample.csproj new file mode 100644 index 00000000..40822a25 --- /dev/null +++ b/examples/SpritesheetExample/SpritesheetExample.csproj @@ -0,0 +1,34 @@ + + + WinExe + net6.0 + Major + false + false + + + app.manifest + Icon.ico + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/examples/SpritesheetExample/app.manifest b/examples/SpritesheetExample/app.manifest new file mode 100644 index 00000000..529de5b1 --- /dev/null +++ b/examples/SpritesheetExample/app.manifest @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/examples/SpritesheetExample/character_robot.aseprite b/examples/SpritesheetExample/character_robot.aseprite new file mode 100644 index 00000000..f235a0fe Binary files /dev/null and b/examples/SpritesheetExample/character_robot.aseprite differ diff --git a/examples/TextureAtlasExample/.config/dotnet-tools.json b/examples/TextureAtlasExample/.config/dotnet-tools.json new file mode 100644 index 00000000..efabe22e --- /dev/null +++ b/examples/TextureAtlasExample/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/examples/TextureAtlasExample/Content/Content.mgcb b/examples/TextureAtlasExample/Content/Content.mgcb new file mode 100644 index 00000000..ddc4c367 --- /dev/null +++ b/examples/TextureAtlasExample/Content/Content.mgcb @@ -0,0 +1,15 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + diff --git a/examples/TextureAtlasExample/Game1.cs b/examples/TextureAtlasExample/Game1.cs new file mode 100644 index 00000000..40d66f62 --- /dev/null +++ b/examples/TextureAtlasExample/Game1.cs @@ -0,0 +1,96 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite; + +namespace TextureAtlasExample; + +public class Game1 : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + + private TextureAtlas _atlas; + private Sprite _sprite1; + private Sprite _sprite2; + private Sprite _sprite3; + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Load the file. In this example, we're not using the MGCB/Content Pipeline and have the Aseprite file set as + /// a file in our project that is copied the output directory. Because of this, we can use the + /// TitleContainer.OpenStream to get a stream to the file and use that to load it. + /// + /// You can optionally enable/disable premultiply alpha for the color values when the file is loaded. If not + /// specified, it will default to true. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AsepriteFile aseFile; + using (Stream stream = TitleContainer.OpenStream("character_robot.aseprite")) + { + aseFile = AsepriteFileLoader.FromStream("character_robot", stream, preMultiplyAlpha: true); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create a texture atlas from the aseprite file + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _atlas = aseFile.CreateTextureAtlas(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create the Sprites using the texture atlas and specifying the region index. The region index will the + /// the same as the frame index in Aseprite. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _sprite1 = _atlas.CreateSprite(regionIndex: 0); + _sprite2 = _atlas.CreateSprite(regionIndex: 1); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// You can also create sprites from the atlas using the region name. Region names are generated automatically + /// by the processor an follow the format of + /// + /// "[filename] [frameIndex]" + /// + /// So for this file "character_robot", if we wanted to use frame 2, we would do the following + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _sprite3 = _atlas.CreateSprite("character_robot 2"); + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// SpriteBatch extension methods are provided to draw the sprites + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _spriteBatch.Draw(_sprite1, new Vector2(10, 10)); + _spriteBatch.Draw(_sprite2, new Vector2(_sprite1.Width, 10)); + _spriteBatch.Draw(_sprite3, new Vector2(_sprite1.Width * 2, 10)); + + _spriteBatch.End(); + } +} diff --git a/examples/TextureAtlasExample/Icon.bmp b/examples/TextureAtlasExample/Icon.bmp new file mode 100644 index 00000000..2b481653 Binary files /dev/null and b/examples/TextureAtlasExample/Icon.bmp differ diff --git a/examples/TextureAtlasExample/Icon.ico b/examples/TextureAtlasExample/Icon.ico new file mode 100644 index 00000000..7d9dec18 Binary files /dev/null and b/examples/TextureAtlasExample/Icon.ico differ diff --git a/examples/TextureAtlasExample/Program.cs b/examples/TextureAtlasExample/Program.cs new file mode 100644 index 00000000..f164ce2a --- /dev/null +++ b/examples/TextureAtlasExample/Program.cs @@ -0,0 +1,6 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using var game = new TextureAtlasExample.Game1(); +game.Run(); diff --git a/examples/TextureAtlasExample/TextureAtlasExample.csproj b/examples/TextureAtlasExample/TextureAtlasExample.csproj new file mode 100644 index 00000000..40822a25 --- /dev/null +++ b/examples/TextureAtlasExample/TextureAtlasExample.csproj @@ -0,0 +1,34 @@ + + + WinExe + net6.0 + Major + false + false + + + app.manifest + Icon.ico + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/examples/TextureAtlasExample/app.manifest b/examples/TextureAtlasExample/app.manifest new file mode 100644 index 00000000..408105c2 --- /dev/null +++ b/examples/TextureAtlasExample/app.manifest @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/examples/TextureAtlasExample/character_robot.aseprite b/examples/TextureAtlasExample/character_robot.aseprite new file mode 100644 index 00000000..f235a0fe Binary files /dev/null and b/examples/TextureAtlasExample/character_robot.aseprite differ diff --git a/examples/TilemapExample/.config/dotnet-tools.json b/examples/TilemapExample/.config/dotnet-tools.json new file mode 100644 index 00000000..efabe22e --- /dev/null +++ b/examples/TilemapExample/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/examples/TilemapExample/Content/Content.mgcb b/examples/TilemapExample/Content/Content.mgcb new file mode 100644 index 00000000..ddc4c367 --- /dev/null +++ b/examples/TilemapExample/Content/Content.mgcb @@ -0,0 +1,15 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + diff --git a/examples/TilemapExample/Game1.cs b/examples/TilemapExample/Game1.cs new file mode 100644 index 00000000..e737b898 --- /dev/null +++ b/examples/TilemapExample/Game1.cs @@ -0,0 +1,77 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite; + +namespace TilemapExample; + +public class Game1 : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + private Tilemap _tilemap; + private Vector2 _scale; + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Load the file. In this example, we're not using the MGCB/Content Pipeline and have the Aseprite file set as + /// a file in our project that is copied the output directory. Because of this, we can use the + /// TitleContainer.OpenStream to get a stream to the file and use that to load it. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AsepriteFile aseFile; + using (Stream stream = TitleContainer.OpenStream("townmap.aseprite")) + { + aseFile = AsepriteFileLoader.FromStream("townmap", stream); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create a tilemap from the file based on the frame the tilemap is on. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _tilemap = aseFile.CreateTilemap(GraphicsDevice, frameIndex: 0); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Size the tilemap is created 1:1 with the size it is in Aseprite, we're going to create a scale factor here + /// in this example to be the size of the game window. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _scale.X = _graphics.PreferredBackBufferWidth / (float)_tilemap[0].Width; + _scale.Y = _graphics.PreferredBackBufferHeight / (float)_tilemap[0].Height; + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Spritebatch extension are provided to draw the tilemap + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _spriteBatch.Draw(_tilemap, Vector2.Zero, Color.White, _scale, 0.0f); + + _spriteBatch.End(); + } +} diff --git a/examples/TilemapExample/Icon.bmp b/examples/TilemapExample/Icon.bmp new file mode 100644 index 00000000..2b481653 Binary files /dev/null and b/examples/TilemapExample/Icon.bmp differ diff --git a/examples/TilemapExample/Icon.ico b/examples/TilemapExample/Icon.ico new file mode 100644 index 00000000..7d9dec18 Binary files /dev/null and b/examples/TilemapExample/Icon.ico differ diff --git a/examples/TilemapExample/Program.cs b/examples/TilemapExample/Program.cs new file mode 100644 index 00000000..56d608b0 --- /dev/null +++ b/examples/TilemapExample/Program.cs @@ -0,0 +1,6 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using var game = new TilemapExample.Game1(); +game.Run(); diff --git a/examples/TilemapExample/TilemapExample.csproj b/examples/TilemapExample/TilemapExample.csproj new file mode 100644 index 00000000..df0fd772 --- /dev/null +++ b/examples/TilemapExample/TilemapExample.csproj @@ -0,0 +1,34 @@ + + + WinExe + net6.0 + Major + false + false + + + app.manifest + Icon.ico + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/examples/TilemapExample/app.manifest b/examples/TilemapExample/app.manifest new file mode 100644 index 00000000..14fbec29 --- /dev/null +++ b/examples/TilemapExample/app.manifest @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/examples/TilemapExample/townmap.aseprite b/examples/TilemapExample/townmap.aseprite new file mode 100644 index 00000000..a7d176b3 Binary files /dev/null and b/examples/TilemapExample/townmap.aseprite differ diff --git a/examples/TilesetExample/.config/dotnet-tools.json b/examples/TilesetExample/.config/dotnet-tools.json new file mode 100644 index 00000000..efabe22e --- /dev/null +++ b/examples/TilesetExample/.config/dotnet-tools.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-mgcb": { + "version": "3.8.1.303", + "commands": [ + "mgcb" + ] + }, + "dotnet-mgcb-editor": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor" + ] + }, + "dotnet-mgcb-editor-linux": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-linux" + ] + }, + "dotnet-mgcb-editor-windows": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-windows" + ] + }, + "dotnet-mgcb-editor-mac": { + "version": "3.8.1.303", + "commands": [ + "mgcb-editor-mac" + ] + } + } +} \ No newline at end of file diff --git a/examples/TilesetExample/Content/Content.mgcb b/examples/TilesetExample/Content/Content.mgcb new file mode 100644 index 00000000..ddc4c367 --- /dev/null +++ b/examples/TilesetExample/Content/Content.mgcb @@ -0,0 +1,15 @@ + +#----------------------------- Global Properties ----------------------------# + +/outputDir:bin/$(Platform) +/intermediateDir:obj/$(Platform) +/platform:DesktopGL +/config: +/profile:Reach +/compress:False + +#-------------------------------- References --------------------------------# + + +#---------------------------------- Content ---------------------------------# + diff --git a/examples/TilesetExample/Game1.cs b/examples/TilesetExample/Game1.cs new file mode 100644 index 00000000..9e78ad02 --- /dev/null +++ b/examples/TilesetExample/Game1.cs @@ -0,0 +1,84 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.IO; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite; + +namespace TilesetExample; + +public class Game1 : Game +{ + private GraphicsDeviceManager _graphics; + private SpriteBatch _spriteBatch; + + private Tileset _tileset; + private TextureRegion _greenBushTile; + private TextureRegion _yellowBushTile; + private TextureRegion _mushroomsTile; + + + + public Game1() + { + _graphics = new GraphicsDeviceManager(this); + Content.RootDirectory = "Content"; + IsMouseVisible = true; + } + + protected override void LoadContent() + { + _spriteBatch = new SpriteBatch(GraphicsDevice); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Load the file. In this example, we're not using the MGCB/Content Pipeline and have the Aseprite file set as + /// a file in our project that is copied the output directory. Because of this, we can use the + /// TitleContainer.OpenStream to get a stream to the file and use that to load it. + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + AsepriteFile aseFile; + using (Stream stream = TitleContainer.OpenStream("townmap.aseprite")) + { + aseFile = AsepriteFileLoader.FromStream("townmap", stream); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create a tileset from the file based on the index of the tileset + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _tileset = aseFile.CreateTileset(GraphicsDevice, 0); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Create texture regions from the tiles in the tileset. You just give it the index of the tile in the + /// tileset. You can use the GetTile() method of the this[] indexor method + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _yellowBushTile = _tileset.GetTile(28); + _greenBushTile = _tileset[29]; + _mushroomsTile = _tileset[30]; + } + + protected override void Draw(GameTime gameTime) + { + GraphicsDevice.Clear(Color.CornflowerBlue); + + _spriteBatch.Begin(samplerState: SamplerState.PointClamp); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// + /// Spritebatch extension are provided to draw the tiles + /// + /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + _spriteBatch.Draw(_greenBushTile, new Vector2(10, 10), Color.White); + _spriteBatch.Draw(_yellowBushTile, new Vector2(10 + _tileset.TileWidth, 10), Color.White); + _spriteBatch.Draw(_mushroomsTile, new Vector2(10 + _tileset.TileWidth * 2, 10), Color.White); + + _spriteBatch.End(); + } +} diff --git a/examples/TilesetExample/Icon.bmp b/examples/TilesetExample/Icon.bmp new file mode 100644 index 00000000..2b481653 Binary files /dev/null and b/examples/TilesetExample/Icon.bmp differ diff --git a/examples/TilesetExample/Icon.ico b/examples/TilesetExample/Icon.ico new file mode 100644 index 00000000..7d9dec18 Binary files /dev/null and b/examples/TilesetExample/Icon.ico differ diff --git a/examples/TilesetExample/Program.cs b/examples/TilesetExample/Program.cs new file mode 100644 index 00000000..235511a5 --- /dev/null +++ b/examples/TilesetExample/Program.cs @@ -0,0 +1,6 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using var game = new TilesetExample.Game1(); +game.Run(); diff --git a/examples/TilesetExample/TilesetExample.csproj b/examples/TilesetExample/TilesetExample.csproj new file mode 100644 index 00000000..df0fd772 --- /dev/null +++ b/examples/TilesetExample/TilesetExample.csproj @@ -0,0 +1,34 @@ + + + WinExe + net6.0 + Major + false + false + + + app.manifest + Icon.ico + + + + + + + + + + + + + + + + PreserveNewest + + + + + + + \ No newline at end of file diff --git a/examples/TilesetExample/app.manifest b/examples/TilesetExample/app.manifest new file mode 100644 index 00000000..cba8c6d2 --- /dev/null +++ b/examples/TilesetExample/app.manifest @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true/pm + permonitorv2,permonitor + + + + diff --git a/examples/TilesetExample/townmap.aseprite b/examples/TilesetExample/townmap.aseprite new file mode 100644 index 00000000..a7d176b3 Binary files /dev/null and b/examples/TilesetExample/townmap.aseprite differ diff --git a/source/Directory.Build.props b/source/Directory.Build.props new file mode 100644 index 00000000..79566fed --- /dev/null +++ b/source/Directory.Build.props @@ -0,0 +1,42 @@ + + + + + + source + + + + + + true + + + + + Copyright © 2024 Christopher Whitley + Christopher Whitley and contributors + Aristurtle + https://github.com/AristurtleDev/monogame-aseprite + nuget-icon.png + README.md + + Version 5.1.3 + - Added `MonoGame.Aseprite.Configuration` + - When set to `false` this will assume frame index gets from the `AsepriteFile` start at index 1 and not 0. + - Removed `MonoGame.Aserpite.Configuration` + - Moved `ZeroIndexedFrames` to be property of `AsepriteFile` + - Added unit testing for `AsepriteFile.ZeroIndexedFrames` functionality + - Added proper support for new tile rotation introduced in Aseprite 1.3 + - Read Old Palette Chunk for Indexed mode due to Aseprite 1.3.5 file spec change + + MonoGame;Aseprite;import;processes;read;write;sprite;animation;tileset;tilemap;spritesheet;pipeline;mgcb + git + main + https://github.com/AristurtleDev/monogame-aseprite + MIT + + + + + \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/AsepriteFileImportResult.cs b/source/MonoGame.Aseprite.Content.Pipeline/AsepriteFileImportResult.cs index 7169eaf7..302fa79a 100644 --- a/source/MonoGame.Aseprite.Content.Pipeline/AsepriteFileImportResult.cs +++ b/source/MonoGame.Aseprite.Content.Pipeline/AsepriteFileImportResult.cs @@ -1,27 +1,7 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. namespace MonoGame.Aseprite.Content.Pipeline; -internal record AsepriteFileImportResult(byte[] Data, AsepriteFile AsepriteFile); \ No newline at end of file +internal record AsepriteFileImportResult(string FilePath); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/AsepriteFileProcessResult.cs b/source/MonoGame.Aseprite.Content.Pipeline/AsepriteFileProcessResult.cs new file mode 100644 index 00000000..31c0483a --- /dev/null +++ b/source/MonoGame.Aseprite.Content.Pipeline/AsepriteFileProcessResult.cs @@ -0,0 +1,7 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +namespace MonoGame.Aseprite.Content.Pipeline; + +internal record AsepriteFileProcessResult(string Name, bool PremultiplyAlpha, byte[] Data); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ContentImportException.cs b/source/MonoGame.Aseprite.Content.Pipeline/ContentImportException.cs deleted file mode 100644 index bd06e2b1..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ContentImportException.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ -namespace MonoGame.Aseprite.Content.Pipeline; - -internal sealed class ContentImportException : Exception -{ - public string? ContentPath { get; set; } = default; - public ContentImportException() { } - public ContentImportException(string message) : base(message) { } - public ContentImportException(string message, string contentPath) : base(message) => ContentPath = contentPath; - public ContentImportException(string message, string contentPath, Exception? innerException) : base(message, innerException) => ContentPath = contentPath; -} \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/AnimatedTilemapContent.cs b/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/AnimatedTilemapContent.cs deleted file mode 100644 index 7dd45f36..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/AnimatedTilemapContent.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -internal record AnimatedTilemapContent(RawAnimatedTilemap RawAnimatedTilemap, Texture2DContent[] Texture2DContents); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/SpriteContent.cs b/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/SpriteContent.cs deleted file mode 100644 index 57f78b8d..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/SpriteContent.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; - -namespace MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -internal record SpriteContent(string Name, Texture2DContent Texture2DContent); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/SpriteSheetContent.cs b/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/SpriteSheetContent.cs deleted file mode 100644 index 1ad47794..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/SpriteSheetContent.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -internal record SpriteSheetContent(RawSpriteSheet RawSpriteSheet, Texture2DContent Texture2DContent); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TextureAtlasContent.cs b/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TextureAtlasContent.cs deleted file mode 100644 index d16d4da8..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TextureAtlasContent.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -internal record TextureAtlasContent(RawTextureAtlas RawTextureAtlas, Texture2DContent Texture2DContent); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TilemapContent.cs b/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TilemapContent.cs deleted file mode 100644 index 579b61d3..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TilemapContent.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -internal record TilemapContent(RawTilemap RawTilemap, Texture2DContent[] Texture2DContents); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TilesetContent.cs b/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TilesetContent.cs deleted file mode 100644 index af2b70e2..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ContentTypes/TilesetContent.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -internal record TilesetContent(RawTileset RawTileset, Texture2DContent Texture2DContent); \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Importers/AsepriteFileContentImporter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Importers/AsepriteFileContentImporter.cs index 7d2e7c55..e0b22a08 100644 --- a/source/MonoGame.Aseprite.Content.Pipeline/Importers/AsepriteFileContentImporter.cs +++ b/source/MonoGame.Aseprite.Content.Pipeline/Importers/AsepriteFileContentImporter.cs @@ -1,26 +1,6 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. using Microsoft.Xna.Framework.Content.Pipeline; using MonoGame.Aseprite.Content.Pipeline.Processors; @@ -33,18 +13,6 @@ internal class AsepriteFileContentImporter : ContentImporter - - net6.0 - enable - enable - True - 5.1.3 - + - Christopher Whitley - Aristurtle - Copyright (c) 2018 - 2023 Christoipher Whitley - https://monogameaseprite.net - https://github.com/AristurtleDev/monogame-aseprite - git - main - en + net6.0 - + MonoGame.Aseprite.Content.Pipeline - 5.1.2 - 5.1.2 - 5.1.2 - Christopher Whitley - Aristurtle - MIT - Copyright (c) 2018 - 2023 Christoipher Whitley - https://monogameaseprite.net - icon.png - README.md - https://github.com/AristurtleDev/monogame-aseprite - git - stable - - MonoGame;Aseprite;import;processes;read;write;sprite;animation;tileset;tilemap;spritesheet;pipeline;mgcb - - - Version 5.1.3 - - Added `MonoGame.Aseprite.Configuration` - - When set to `false` this will assume frame index gets from the `AsepriteFile` start at index 1 and not 0. - - Removed `MonoGame.Aserpite.Configuration` - - Moved `ZeroIndexedFrames` to be property of `AsepriteFile` - - Added unit testing for `AsepriteFile.ZeroIndexedFrames` functionality - - Added proper support for new tile rotation introduced in Aseprite 1.3 - - Read Old Palette Chunk for Indexed mode due to Aseprite 1.3.5 file spec change - MonoGame.Aseprite.Content.Pipeline is a cross-platform C# library that adds an extension to the MonoGame MGCB Editor for importing Aseprite (.ase | .aseprite) files to be used in a MonoGame project using the MonoGame.Aseprite library. - en @@ -61,18 +21,12 @@ - + - - All - - - All - - + + + - - - + \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/ProcessParamterException.cs b/source/MonoGame.Aseprite.Content.Pipeline/ProcessParamterException.cs deleted file mode 100644 index 24fd28b7..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/ProcessParamterException.cs +++ /dev/null @@ -1,34 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ -namespace MonoGame.Aseprite.Content.Pipeline; - -internal sealed class ProcessorParameterException : Exception -{ - public string? ProcessorName { get; set; } = default; - public string? ParameterName { get; set; } = default; - public ProcessorParameterException() { } - public ProcessorParameterException(string message) : base(message) { } - public ProcessorParameterException(string message, string processorName, string parameterName) : base(message) => (ProcessorName, ParameterName) = (processorName, parameterName); - public ProcessorParameterException(string message, string contentPath, string processorName, string parameterName, Exception? innerException) : base(message, innerException) => (ProcessorName, ParameterName) = (processorName, parameterName); -} \ No newline at end of file diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/AnimatedTilemapContentProcessor.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/AnimatedTilemapContentProcessor.cs deleted file mode 100644 index 74891cb1..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/AnimatedTilemapContentProcessor.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.ComponentModel; -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Processors; - -[ContentProcessor(DisplayName = "Aseprite Animated Tilemap Processor - MonoGame.Aseprite")] -internal sealed class AnimatedTilemapContentProcessor : ContentProcessor -{ - [DisplayName("Only Visible Layers")] - public bool OnlyVisibleLayer { get; set; } = true; - - [DisplayName("Generate Mipmaps")] - public bool GenerateMipmaps { get; set; } = false; - - public override AnimatedTilemapContent Process(AsepriteFileImportResult content, ContentProcessorContext context) - { - RawAnimatedTilemap rawAnimatedTilemap = AnimatedTilemapProcessor.ProcessRaw(content.AsepriteFile, OnlyVisibleLayer); - - Texture2DContent[] texture2DContents = ProcessTilesetTexture(rawAnimatedTilemap.RawTilesets); - return new(rawAnimatedTilemap, texture2DContents); - } - - private Texture2DContent[] ProcessTilesetTexture(ReadOnlySpan rawTilesets) - { - Texture2DContent[] texture2DContents = new Texture2DContent[rawTilesets.Length]; - - for (int i = 0; i < rawTilesets.Length; i++) - { - RawTexture rawTexture = rawTilesets[i].RawTexture; - - Texture2DContent texture2DContent = ProcessorHelpers.CreateTexture2DContent(rawTexture.Pixels, rawTexture.Width, rawTexture.Height); - - if (GenerateMipmaps) - { - texture2DContent.GenerateMipmaps(true); - } - texture2DContents[i] = texture2DContent; - } - - return texture2DContents; - } -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/AsepriteFileContentProcessor.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/AsepriteFileContentProcessor.cs index f91aff24..749faa88 100644 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/AsepriteFileContentProcessor.cs +++ b/source/MonoGame.Aseprite.Content.Pipeline/Processors/AsepriteFileContentProcessor.cs @@ -1,37 +1,23 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. +using System.ComponentModel; using Microsoft.Xna.Framework.Content.Pipeline; namespace MonoGame.Aseprite.Content.Pipeline.Processors; [ContentProcessor(DisplayName = "Aseprite File Processor - MonoGame.Aseprite")] -internal sealed class AsepriteFileContentProcessor : ContentProcessor +internal sealed class AsepriteFileContentProcessor : ContentProcessor { - public override AsepriteFileImportResult Process(AsepriteFileImportResult content, ContentProcessorContext context) + [DisplayName("Premultiply Alpha")] + public bool PremultiplyAlpha { get; set; } = true; + + public override AsepriteFileProcessResult Process(AsepriteFileImportResult content, ContentProcessorContext context) { - // No processing needed since this is just for importing the file content itself. - return content; + string name = Path.GetFileNameWithoutExtension(content.FilePath); + byte[] data = File.ReadAllBytes(content.FilePath); + AsepriteFileProcessResult result = new AsepriteFileProcessResult(name, PremultiplyAlpha, data); + return result; } } diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/ProcessorHelpers.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/ProcessorHelpers.cs deleted file mode 100644 index 9dd94348..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/ProcessorHelpers.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; - -namespace MonoGame.Aseprite.Content.Pipeline.Processors; - -internal static class ProcessorHelpers -{ - internal static Texture2DContent CreateTexture2DContent(ReadOnlySpan pixels, int width, int height) - { - PixelBitmapContent face = new(width, height); - - for (int i = 0; i < pixels.Length; i++) - { - int x = i % width; - int y = i / width; - - face.SetPixel(x, y, pixels[i]); - } - - Texture2DContent textureContent = new(); - textureContent.Faces[0].Add(face); - return textureContent; - } -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/SpriteContentProcessor.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/SpriteContentProcessor.cs deleted file mode 100644 index a09bcd56..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/SpriteContentProcessor.cs +++ /dev/null @@ -1,85 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.ComponentModel; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Processors; - -[ContentProcessor(DisplayName = "Aseprite Sprite Processor - MonoGame.Aseprite")] -internal sealed class SpriteContentProcessor : ContentProcessor -{ - [DisplayName("Zero Indexed Frames")] - public bool ZeroIndexedFrames {get; set;} = true; - - [DisplayName("Frame Index")] - public int FrameIndex { get; set; } = 0; - - [DisplayName("Only Visible Layers")] - public bool OnlyVisibleLayers { get; set; } = true; - - [DisplayName("Include Background Layer")] - public bool IncludeBackgroundLayer { get; set; } = false; - - [DisplayName("Include Tilemap Layers")] - public bool IncludeTilemapLayers { get; set; } = true; - - [DisplayName("Generate Mipmaps")] - public bool GenerateMipmaps { get; set; } = false; - - public override SpriteContent Process(AsepriteFileImportResult content, ContentProcessorContext context) - { - FrameIndex = ZeroIndexedFrames ? FrameIndex : FrameIndex - 1; - - if (FrameIndex < 0 || FrameIndex >= content.AsepriteFile.FrameCount) - { - ProcessorParameterException ex; - if(ZeroIndexedFrames) - { - ex = new ($"The 'Frame Index' parameter cannot be less than zero or greater than or equal to the total number of frames in the Aseprite file", nameof(SpriteContentProcessor), nameof(FrameIndex)); - } - else - { - ex = new ($"The 'Frame Index' parameter cannot be less than one or greater than the total number of frames in the Aseprite file when {nameof(ZeroIndexedFrames)} is 'false'.", nameof(SpriteContentProcessor), nameof(FrameIndex)); - } - - throw ex; - } - - AsepriteFrame aseFrame = content.AsepriteFile.Frames[FrameIndex]; - Color[] pixels = aseFrame.FlattenFrame(OnlyVisibleLayers, IncludeBackgroundLayer, IncludeTilemapLayers); - Texture2DContent texture2DContent = ProcessorHelpers.CreateTexture2DContent(pixels, aseFrame.Width, aseFrame.Height); - - if (GenerateMipmaps) - { - texture2DContent.GenerateMipmaps(true); - } - - return new(aseFrame.Name, texture2DContent); - } -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/SpriteSheetContentProcessor.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/SpriteSheetContentProcessor.cs deleted file mode 100644 index 3feb6d99..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/SpriteSheetContentProcessor.cs +++ /dev/null @@ -1,78 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.ComponentModel; -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Processors; - -[ContentProcessor(DisplayName = "Aseprite SpriteSheet Processor - MonoGame.Aseprite")] -internal sealed class SpriteSheetContentProcessor : ContentProcessor -{ - [DisplayName("Frame Index")] - public int FrameIndex { get; set; } = 0; - - [DisplayName("Only Visible Layers")] - public bool OnlyVisibleLayers { get; set; } = true; - - [DisplayName("Include Background Layer")] - public bool IncludeBackgroundLayer { get; set; } = false; - - [DisplayName("Include Tilemap Layers")] - public bool IncludeTilemapLayers { get; set; } = true; - - [DisplayName("Merge Duplicate Frames")] - public bool MergeDuplicateFrames { get; set; } = true; - - [DisplayName("Border Padding")] - public int BorderPadding { get; set; } = 0; - - [DisplayName("Spacing")] - public int Spacing { get; set; } = 0; - - [DisplayName("Inner Padding")] - public int InnerPadding { get; set; } = 0; - - [DisplayName("Generate Mipmaps")] - public bool GenerateMipmaps { get; set; } = false; - - public override SpriteSheetContent Process(AsepriteFileImportResult content, ContentProcessorContext context) - { - RawSpriteSheet rawSpriteSheet = SpriteSheetProcessor.ProcessRaw(content.AsepriteFile, OnlyVisibleLayers, IncludeBackgroundLayer, IncludeTilemapLayers, MergeDuplicateFrames, BorderPadding, Spacing, InnerPadding); - RawTexture rawTexture = rawSpriteSheet.RawTextureAtlas.RawTexture; - - Texture2DContent texture2DContent = ProcessorHelpers.CreateTexture2DContent(rawTexture.Pixels, rawTexture.Width, rawTexture.Height); - - if (GenerateMipmaps) - { - texture2DContent.GenerateMipmaps(true); - } - - return new(rawSpriteSheet, texture2DContent); - } -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/TextureAtlasContentProcessor.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/TextureAtlasContentProcessor.cs deleted file mode 100644 index 2fd2d824..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/TextureAtlasContentProcessor.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.ComponentModel; -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Processors; - -[ContentProcessor(DisplayName = "Aseprite TextureAtlas Processor - MonoGame.Aseprite")] -internal sealed class TextureAtlasContentProcessor : ContentProcessor -{ - [DisplayName("Only Visible Layers")] - public bool OnlyVisibleLayers { get; set; } = true; - - [DisplayName("Include Background Layer")] - public bool IncludeBackgroundLayer { get; set; } = false; - - [DisplayName("Include Tilemap Layers")] - public bool IncludeTilemapLayers { get; set; } = true; - - [DisplayName("Merge Duplicate Frames")] - public bool MergeDuplicateFrames { get; set; } = true; - - [DisplayName("Border Padding")] - public int BorderPadding { get; set; } = 0; - - [DisplayName("Spacing")] - public int Spacing { get; set; } = 0; - - [DisplayName("Inner Padding")] - public int InnerPadding { get; set; } = 0; - - [DisplayName("Generate Mipmaps")] - public bool GenerateMipmaps { get; set; } = false; - - public override TextureAtlasContent Process(AsepriteFileImportResult content, ContentProcessorContext context) - { - RawTextureAtlas rawTextureAtlas = TextureAtlasProcessor.ProcessRaw(content.AsepriteFile, OnlyVisibleLayers, IncludeBackgroundLayer, IncludeTilemapLayers, MergeDuplicateFrames, BorderPadding, Spacing, InnerPadding); - RawTexture rawTexture = rawTextureAtlas.RawTexture; - - Texture2DContent texture2DContent = ProcessorHelpers.CreateTexture2DContent(rawTexture.Pixels, rawTexture.Width, rawTexture.Height); - - if (GenerateMipmaps) - { - texture2DContent.GenerateMipmaps(true); - } - - return new(rawTextureAtlas, texture2DContent); - } -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/TilemapContentProcessor.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/TilemapContentProcessor.cs deleted file mode 100644 index a741fcbc..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/TilemapContentProcessor.cs +++ /dev/null @@ -1,77 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.ComponentModel; -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Processors; - -[ContentProcessor(DisplayName = "Aseprite Tilemap Processor - MonoGame.Aseprite")] -internal sealed class TilemapContentProcessor : ContentProcessor -{ - [DisplayName("Zero Indexed Frames")] - public bool ZeroIndexedFrames { get; set; } = true; - - [DisplayName("Frame Index")] - public int FrameIndex { get; set; } = 0; - - [DisplayName("Only Visible Layers")] - public bool OnlyVisibleLayer { get; set; } = true; - - [DisplayName("Generate Mipmaps")] - public bool GenerateMipmaps { get; set; } = false; - - public override TilemapContent Process(AsepriteFileImportResult content, ContentProcessorContext context) - { - content.AsepriteFile.ZeroIndexedFrames = ZeroIndexedFrames; - RawTilemap rawTilemap = TilemapProcessor.ProcessRaw(content.AsepriteFile, FrameIndex, OnlyVisibleLayer); - Texture2DContent[] texture2DContents = ProcessTilesetTexture(rawTilemap.RawTilesets); - return new(rawTilemap, texture2DContents); - } - - private Texture2DContent[] ProcessTilesetTexture(ReadOnlySpan rawTilesets) - { - Texture2DContent[] texture2DContents = new Texture2DContent[rawTilesets.Length]; - - for (int i = 0; i < rawTilesets.Length; i++) - { - RawTexture rawTexture = rawTilesets[i].RawTexture; - - Texture2DContent texture2DContent = ProcessorHelpers.CreateTexture2DContent(rawTexture.Pixels, rawTexture.Width, rawTexture.Height); - - if (GenerateMipmaps) - { - texture2DContent.GenerateMipmaps(true); - } - - texture2DContents[i] = texture2DContent; - } - - return texture2DContents; - } -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Processors/TilesetContentProcessor.cs b/source/MonoGame.Aseprite.Content.Pipeline/Processors/TilesetContentProcessor.cs deleted file mode 100644 index eb810abd..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Processors/TilesetContentProcessor.cs +++ /dev/null @@ -1,57 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.ComponentModel; -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Processors; - -[ContentProcessor(DisplayName = "Aseprite Tileset Processor - MonoGame.Aseprite")] -internal sealed class TilesetContentProcessor : ContentProcessor -{ - [DisplayName("Tileset Name")] - public string TilesetName { get; set; } = string.Empty; - - [DisplayName("Generate Mipmaps")] - public bool GenerateMipmaps { get; set; } = false; - - public override TilesetContent Process(AsepriteFileImportResult content, ContentProcessorContext context) - { - RawTileset rawTileset = TilesetProcessor.ProcessRaw(content.AsepriteFile, TilesetName); - RawTexture rawTexture = rawTileset.RawTexture; - - Texture2DContent texture2DContent = ProcessorHelpers.CreateTexture2DContent(rawTexture.Pixels, rawTexture.Width, rawTexture.Height); - - if (GenerateMipmaps) - { - texture2DContent.GenerateMipmaps(true); - } - - return new(rawTileset, texture2DContent); - } -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Writers/AnimatedTilemapContentTypeWriter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Writers/AnimatedTilemapContentTypeWriter.cs deleted file mode 100644 index 61800578..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Writers/AnimatedTilemapContentTypeWriter.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Writers; - -[ContentTypeWriter] -internal sealed class AnimatedTilemapContentTypeWriter : ContentTypeWriter -{ - protected override void Write(ContentWriter writer, AnimatedTilemapContent content) - { - RawAnimatedTilemap rawAnimated = content.RawAnimatedTilemap; - - writer.Write(rawAnimated.Name); - WriteTilesets(writer, rawAnimated.RawTilesets, content.Texture2DContents); - writer.Write(rawAnimated.RawTilemapFrames); - } - - private void WriteTilesets(ContentWriter writer, ReadOnlySpan rawTilesets, ReadOnlySpan tilesetTextures) - { - writer.Write(rawTilesets.Length); - - for (int i = 0; i < rawTilesets.Length; i++) - { - writer.Write(rawTilesets[i].Name); - writer.Write(rawTilesets[i].ID); - writer.Write(rawTilesets[i].TileWidth); - writer.Write(rawTilesets[i].TileHeight); - writer.WriteObject(tilesetTextures[i]); - } - } - - public override string GetRuntimeType(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Tilemaps.AnimatedTilemap, MonoGame.Aseprite"; - - public override string GetRuntimeReader(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Content.Pipeline.Readers.AnimatedTilemapContentTypeReader, MonoGame.Aseprite"; -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Writers/AsepriteFileContentTypeWriter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Writers/AsepriteFileContentTypeWriter.cs index e457982a..5b5392d1 100644 --- a/source/MonoGame.Aseprite.Content.Pipeline/Writers/AsepriteFileContentTypeWriter.cs +++ b/source/MonoGame.Aseprite.Content.Pipeline/Writers/AsepriteFileContentTypeWriter.cs @@ -1,26 +1,6 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. using Microsoft.Xna.Framework.Content.Pipeline; using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; @@ -28,14 +8,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE namespace MonoGame.Aseprite.Content.Pipeline.Writers; [ContentTypeWriter] -internal sealed class AsepriteFileContentTypeWriter : ContentTypeWriter +internal sealed class AsepriteFileContentTypeWriter : ContentTypeWriter { - protected override void Write(ContentWriter writer, AsepriteFileImportResult content) + protected override void Write(ContentWriter writer, AsepriteFileProcessResult content) { + writer.Write(content.Name); + writer.Write(content.PremultiplyAlpha); writer.Write(content.Data.Length); writer.Write(content.Data); } - + public override string GetRuntimeType(TargetPlatform targetPlatform) => "MonoGame.Aseprite.AsepriteFile, MonoGame.Aseprite"; diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Writers/SpriteContentTypeWriter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Writers/SpriteContentTypeWriter.cs deleted file mode 100644 index d80bfc83..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Writers/SpriteContentTypeWriter.cs +++ /dev/null @@ -1,45 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Writers; - -[ContentTypeWriter] -internal sealed class SpriteContentTypeWriter : ContentTypeWriter -{ - protected override void Write(ContentWriter writer, SpriteContent content) - { - writer.Write(content.Name); - writer.WriteObject(content.Texture2DContent); - } - - public override string GetRuntimeType(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Sprites.Sprite, MonoGame.Aseprite"; - - public override string GetRuntimeReader(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Content.Pipeline.Readers.SpriteContentTypeReader, MonoGame.Aseprite"; -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Writers/SpriteSheetContentTypeWriter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Writers/SpriteSheetContentTypeWriter.cs deleted file mode 100644 index c55bbbc3..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Writers/SpriteSheetContentTypeWriter.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Writers; - -[ContentTypeWriter] -internal sealed class SpriteSheetContentTypeWriter : ContentTypeWriter -{ - protected override void Write(ContentWriter writer, SpriteSheetContent content) - { - RawSpriteSheet rawSpriteSheet = content.RawSpriteSheet; - writer.Write(rawSpriteSheet.Name); - writer.Write(rawSpriteSheet.RawTextureAtlas.Name); - writer.WriteObject(content.Texture2DContent); - writer.Write(rawSpriteSheet.RawTextureAtlas.RawTextureRegions); - writer.Write(rawSpriteSheet.RawAnimationTags); - } - - public override string GetRuntimeType(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Sprites.SpriteSheet, MonoGame.Aseprite"; - - public override string GetRuntimeReader(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Content.Pipeline.Readers.SpriteSheetContentTypeReader, MonoGame.Aseprite"; -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Writers/TextureAtlasContentTypeWriter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Writers/TextureAtlasContentTypeWriter.cs deleted file mode 100644 index ba374e0e..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Writers/TextureAtlasContentTypeWriter.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Writers; - -[ContentTypeWriter] -internal sealed class TextureAtlasContentTypeWriter : ContentTypeWriter -{ - protected override void Write(ContentWriter writer, TextureAtlasContent content) - { - RawTextureAtlas rawTextureAtlas = content.RawTextureAtlas; - writer.Write(rawTextureAtlas.Name); - writer.WriteObject(content.Texture2DContent); - writer.Write(rawTextureAtlas.RawTextureRegions); - } - - public override string GetRuntimeType(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Sprites.TextureAtlas, MonoGame.Aseprite"; - - public override string GetRuntimeReader(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Content.Pipeline.Readers.TextureAtlasContentTypeReader, MonoGame.Aseprite"; -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Writers/TilemapContentTypeWriter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Writers/TilemapContentTypeWriter.cs deleted file mode 100644 index 31b757fd..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Writers/TilemapContentTypeWriter.cs +++ /dev/null @@ -1,63 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Writers; - -[ContentTypeWriter] -internal sealed class TilemapContentTypeWriter : ContentTypeWriter -{ - protected override void Write(ContentWriter writer, TilemapContent content) - { - RawTilemap rawTilemap = content.RawTilemap; - - writer.Write(rawTilemap.Name); - WriteTilesets(writer, rawTilemap.RawTilesets, content.Texture2DContents); - writer.Write(rawTilemap.RawLayers); - } - - private void WriteTilesets(ContentWriter writer, ReadOnlySpan rawTilesets, ReadOnlySpan tilesetTextures) - { - writer.Write(rawTilesets.Length); - - for (int i = 0; i < rawTilesets.Length; i++) - { - writer.Write(rawTilesets[i].Name); - writer.Write(rawTilesets[i].ID); - writer.Write(rawTilesets[i].TileWidth); - writer.Write(rawTilesets[i].TileHeight); - writer.WriteObject(tilesetTextures[i]); - } - } - public override string GetRuntimeType(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Tilemaps.Tilemap, MonoGame.Aseprite"; - - public override string GetRuntimeReader(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Content.Pipeline.Readers.TilemapContentTypeReader, MonoGame.Aseprite"; -} diff --git a/source/MonoGame.Aseprite.Content.Pipeline/Writers/TilesetContentTypeWriter.cs b/source/MonoGame.Aseprite.Content.Pipeline/Writers/TilesetContentTypeWriter.cs deleted file mode 100644 index e1be0de2..00000000 --- a/source/MonoGame.Aseprite.Content.Pipeline/Writers/TilesetContentTypeWriter.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content.Pipeline; -using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler; -using MonoGame.Aseprite.Content.Pipeline.ContentTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Pipeline.Writers; - -[ContentTypeWriter] -internal sealed class TilesetContentTypeWriter : ContentTypeWriter -{ - protected override void Write(ContentWriter writer, TilesetContent content) - { - RawTileset rawTileset = content.RawTileset; - writer.Write(rawTileset.Name); - writer.Write(rawTileset.TileWidth); - writer.Write(rawTileset.TileHeight); - writer.WriteObject(content.Texture2DContent); - } - - public override string GetRuntimeType(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Tilemaps.Tileset, MonoGame.Aseprite"; - - public override string GetRuntimeReader(TargetPlatform targetPlatform) => - "MonoGame.Aseprite.Content.Pipeline.Readers.TilesetContentTypeReader, MonoGame.Aseprite"; -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteFile.cs b/source/MonoGame.Aseprite.Shared/AsepriteFile.cs deleted file mode 100644 index 5933bbae..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteFile.cs +++ /dev/null @@ -1,707 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Readers; - -namespace MonoGame.Aseprite; - -/// -/// Defines the contents of an imported aseprite file. -/// -public sealed class AsepriteFile -{ - private Color[] _palette = Array.Empty(); - private AsepriteFrame[] _frames; - private AsepriteLayer[] _layers; - private AsepriteTag[] _tags; - private AsepriteSlice[] _slices; - private AsepriteTileset[] _tilesets; - - /// - /// if, when referencing frames by index, the first frame is index 0; otherwise - /// if the first frame is index 1. - /// - public bool ZeroIndexedFrames = true; - - /// - /// Gets a read-only span of all elements in this . - /// - /// - /// The ordering of elements is not affected by . - /// - public ReadOnlySpan Frames => _frames; - - /// - /// Gets the total number of elements in this . - /// - public int FrameCount => _frames.Length; - - /// - /// Gets a read-only span of all elements in this . - /// Order of elements if from bottom-to-top. - /// - public ReadOnlySpan Layers => _layers; - - /// - /// Gets the total number of elements in this . - /// - public int LayerCount => _layers.Length; - - /// - /// Gets a read-only span of all elements in this . - /// - public ReadOnlySpan Tags => _tags; - - /// - /// Gets the total number of elements in this . - /// - public int TagCount => _tags.Length; - - /// - /// Gets a read-only span of all elements in this . - /// - public ReadOnlySpan Slices => _slices; - - /// - /// Gets the total number of elements in this . - /// - public int SliceCount => _slices.Length; - - /// - /// Gets a read-only span of all elements in this . - /// - public ReadOnlySpan Tilesets => _tilesets; - - /// - /// Gets the total number of elements in this . - /// - public int TilesetCount => _tilesets.Length; - - /// - /// Gets a read-only span of the color values that represent the palette of this . - /// - public ReadOnlySpan Palette => _palette; - - /// - /// Gets the total number of color values in this palette of this . - /// - public int PaletteCount => _palette.Length; - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the width, in pixels, of the canvas. - /// - public int CanvasWidth { get; } - - /// - /// Gets the height, in pixels, of the canvas. - /// - public int CanvasHeight { get; } - - /// - /// Gets the that was set for the sprite element in aseprite. - /// - public AsepriteUserData UserData { get; } - - internal AsepriteFile(string name, int width, int height, Color[] palette, AsepriteFrame[] frames, AsepriteLayer[] layers, AsepriteTag[] tags, AsepriteSlice[] slices, AsepriteTileset[] tilesets, AsepriteUserData userData) - { - Name = name; - CanvasWidth = width; - CanvasHeight = height; - _palette = palette; - _frames = frames; - _layers = layers; - _tags = tags; - _slices = slices; - _tilesets = tilesets; - UserData = userData; - } - - /// - /// Gets the at the specified index in this . - /// - /// - /// The index of the to locate. - /// - /// - /// You can specify non-zero indexed frames using - /// - /// - /// - /// The located. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public AsepriteFrame GetFrame(int frameIndex) - { - int index = ZeroIndexedFrames ? frameIndex : frameIndex - 1; - - if (index < 0 || index >= _frames.Length) - { - ArgumentOutOfRangeException ex; - if (ZeroIndexedFrames) - { - ex = new(nameof(frameIndex), $"{nameof(frameIndex)} cannot be less than zero or greater than or equal to the total number of frames in this aseprite file."); - } - else - { - ex = new(nameof(frameIndex), $"{nameof(frameIndex)} cannot be less than one or greater than the total number of frames in this aseprite file when '{nameof(ZeroIndexedFrames)}' is 'false'."); - } - ex.Data.Add("TotalFrames", _frames.Length); - ex.Data.Add("ZeroIndexed", ZeroIndexedFrames); - throw ex; - } - - return _frames[index]; - } - - /// - /// Gets the at the specified index from this . - /// - /// - /// The index of the to locate - /// - /// - /// When this method returns , contains the frame located; otherwise, - /// . - /// - /// - /// if the was located; otherwise, . - /// This method returns if this frame index specified is less than zero or is greater - /// than or equal to the total number of elements in this - /// . - /// - public bool TryGetFrame(int frameIndex, [NotNullWhen(true)] out AsepriteFrame? located) - { - int index = ZeroIndexedFrames ? frameIndex : frameIndex - 1; - located = default; - - if (index < 0 || index >= _frames.Length) - { - return false; - } - - located = _frames[index]; - return located is not null; - } - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public AsepriteLayer GetLayer(int layerIndex) - { - if (layerIndex < 0 || layerIndex >= LayerCount) - { - throw new ArgumentOutOfRangeException(); - } - - return _layers[layerIndex]; - } - - /// - /// Gets the element with the specified name from this . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if this does not contain an element with the - /// specified name. - /// - public AsepriteLayer GetLayer(string layerName) - { - List layersFound = new(); - - for (int i = 0; i < _layers.Length; i++) - { - AsepriteLayer aseLayer = _layers[i]; - layersFound.Add($"'{aseLayer.Name}'"); - - if (aseLayer.Name == layerName) - { - return aseLayer; - } - } - - InvalidOperationException ex = new($"No aseprite layer element found with the name '{layerName}' in this aseprite file."); - ex.Data.Add(nameof(layersFound), layersFound); - throw ex; - } - - /// - /// Gets the element at the specified index from this . - /// - /// - /// The index of the element to locate - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// if the element was located; otherwise, - /// . This method returns if this index specified is less than - /// zero or is greater than or equal to the total number of elements in this - /// . - /// - public bool TryGetLayer(int layerIndex, [NotNullWhen(true)] out AsepriteLayer? located) - { - located = default; - - if (layerIndex < 0 || layerIndex >= LayerCount) - { - return false; - } - - located = _layers[layerIndex]; - return located is not null; - } - - /// - /// Gets the element with the specified name from this . - /// - /// - /// The name of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if the element was located; otherwise, - /// . This method returns if this - /// does not contain an element with the specified name. - /// - public bool TryGetLayer(string layerName, [NotNullWhen(true)] out AsepriteLayer? located) - { - located = default; - - for (int i = 0; i < _layers.Length; i++) - { - if (_layers[i].Name == layerName) - { - located = _layers[i]; - break; - } - } - - return located is not null; - } - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public AsepriteTag GetTag(int tagIndex) - { - if (tagIndex < 0 || tagIndex >= _tags.Length) - { - ArgumentOutOfRangeException ex = new(nameof(tagIndex), $"{nameof(tagIndex)} cannot be less than zero or greater than or equal to the total number of tags in this aseprite file."); - ex.Data.Add("TotalTags", _tags.Length); - throw ex; - } - - return _tags[tagIndex]; - } - - /// - /// Gets the element with the specified name from this . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if this does not contain an element with the - /// specified name. - /// - public AsepriteTag GetTag(string tagName) - { - List tagsFound = new(); - - for (int i = 0; i < _tags.Length; i++) - { - AsepriteTag aseTag = _tags[i]; - tagsFound.Add($"'{aseTag.Name}'"); - - if (aseTag.Name == tagName) - { - return aseTag; - } - } - - InvalidOperationException ex = new($"No aseprite tag element found with the name '{tagName}' in this aseprite file."); - ex.Data.Add(nameof(tagsFound), tagsFound); - throw ex; - } - - /// - /// Gets the element at the specified index from this . - /// - /// - /// The index of the element to locate - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// if the element was located; otherwise, - /// . This method returns if this index specified is less than - /// zero or is greater than or equal to the total number of elements in this - /// . - /// - public bool TryGetTag(int tagIndex, [NotNullWhen(true)] out AsepriteTag? located) - { - located = default; - - if (tagIndex < 0 || tagIndex >= _tags.Length) - { - return false; - } - - located = _tags[tagIndex]; - return located is not null; - } - - /// - /// Gets the element with the specified name from this . - /// - /// - /// The name of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if the element was located; otherwise, - /// . This method returns if this - /// does not contain an element with the specified name. - /// - public bool TryGetTag(string tagName, [NotNullWhen(true)] out AsepriteTag? located) - { - located = default; - - for (int i = 0; i < _tags.Length; i++) - { - if (_tags[i].Name == tagName) - { - located = _tags[i]; - break; - } - } - - return located is not null; - } - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public AsepriteSlice GetSlice(int sliceIndex) - { - if (sliceIndex < 0 || sliceIndex >= _slices.Length) - { - ArgumentOutOfRangeException ex = new(nameof(sliceIndex), $"{nameof(sliceIndex)} cannot be less than zero or greater than or equal to the total number of slices in this aseprite file."); - ex.Data.Add(nameof(sliceIndex), sliceIndex); - ex.Data.Add(nameof(SliceCount), SliceCount); - throw ex; - } - - return _slices[sliceIndex]; - } - - /// - /// Gets the with the specified name from this . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if this does not contain a element with the - /// specified name. - /// - public AsepriteSlice GetSlice(string sliceName) - { - List slicesFound = new(); - - for (int i = 0; i < _slices.Length; i++) - { - AsepriteSlice aseSlice = _slices[i]; - slicesFound.Add($"'{aseSlice.Name}'"); - - if (aseSlice.Name == sliceName) - { - return aseSlice; - } - } - - InvalidOperationException ex = new($"This aseprite file does not contain an aseprite slice element with the name '{sliceName}'."); - ex.Data.Add(nameof(sliceName), sliceName); - ex.Data.Add(nameof(slicesFound), slicesFound); - throw ex; - } - - /// - /// Gets the element at the specified index from this . - /// - /// - /// The index of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if the element was located; otherwise, - /// . This method returns if this index specified is less than - /// zero or is greater than or equal to the total number of elements in this - /// . - /// - public bool TryGetSlice(int sliceIndex, [NotNullWhen(true)] out AsepriteSlice? located) - { - located = default; - - if (sliceIndex < 0 || sliceIndex >= _slices.Length) - { - return false; - } - - located = _slices[sliceIndex]; - return located is not null; - } - - /// - /// Gets the element with the specified name from this . - /// - /// - /// The name of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if the element was located; otherwise, - /// . This method returns if this - /// does not contain an element with the specified name. - /// - public bool TryGetSlice(string sliceName, [NotNullWhen(true)] out AsepriteSlice? located) - { - located = default; - - for (int i = 0; i < _slices.Length; i++) - { - if (_slices[i].Name == sliceName) - { - located = _slices[i]; - break; - } - } - - return located is not null; - } - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public AsepriteTileset GetTileset(int tilesetIndex) - { - if (tilesetIndex < 0 || tilesetIndex >= _tilesets.Length) - { - ArgumentOutOfRangeException ex = new(nameof(tilesetIndex), $"{nameof(tilesetIndex)} cannot be less than zero or greater than or equal to the total number of tilesets in this aseprite file."); - ex.Data.Add("TotalTilesets", _tilesets.Length); - throw ex; - } - - return _tilesets[tilesetIndex]; - } - - /// - /// Gets the element with the specified name from this . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if this does not contain a element with the - /// specified name. - /// - public AsepriteTileset GetTileset(string tilesetName) - { - List tilesetsFound = new(); - - for (int i = 0; i < _tilesets.Length; i++) - { - AsepriteTileset aseTileset = _tilesets[i]; - tilesetsFound.Add($"'{aseTileset.Name}'"); - - if (aseTileset.Name == tilesetName) - { - return aseTileset; - } - } - - InvalidOperationException ex = new($"Unable to locate a tileset with the name '{tilesetName}' in this aseprite file."); - ex.Data.Add(nameof(tilesetsFound), tilesetsFound); - throw ex; - } - - /// - /// Gets the element at the specified index from this . - /// - /// - /// The index of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if the element was located; otherwise, - /// . This method returns if this index specified is less than - /// zero or is greater than or equal to the total number of elements in this - /// . - /// - public bool TryGetTileset(int tilesetIndex, [NotNullWhen(true)] out AsepriteTileset? located) - { - located = default; - - if (tilesetIndex < 0 || tilesetIndex >= _tilesets.Length) - { - return false; - } - - located = _tilesets[tilesetIndex]; - return located is not null; - } - - /// - /// Gets the element with the specified name from this - /// . - /// - /// - /// The name of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if the element was located; otherwise, - /// . This method returns if this - /// does not contain a element with the specified name. - /// - public bool TryGetTileset(string tilesetName, [NotNullWhen(true)] out AsepriteTileset? located) - { - located = default; - - for (int i = 0; i < _tilesets.Length; i++) - { - if (_tilesets[i].Name == tilesetName) - { - located = _tilesets[i]; - break; - } - } - - return located is not null; - } - - /// - /// Loads the contents of the aseprite file at the specified path. The result is a new instance of the - /// class containing the contents of the file read. - /// - /// - /// The path and name of the aseprite file to load. - /// - /// - /// A new instance of the class create by this method. - /// - /// - /// Thrown if no file is located at the specified path. - /// - /// - /// Thrown if an error occurs during the reading of the . The exception message will - /// contain the cause of the exception. - /// - public static AsepriteFile Load(string path) => AsepriteFileReader.ReadFile(path); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteBlendMode.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteBlendMode.cs deleted file mode 100644 index b3014197..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteBlendMode.cs +++ /dev/null @@ -1,171 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines te blend mode values used by aseprite to determine the mode to use when blending two color values. -/// -public enum AsepriteBlendMode -{ - /// - /// Normal blend mode is the standard blend mode that takes the top layer alone without mixing any color from - /// the layer beneath it. - /// f(a,b) = b - /// - Normal = 0, - - /// - /// Multiply blend mode that takes the RGB component values of each pixel from the top layer and multiplies them - /// with the RGB component values of the corresponding pixel from the bottom layer. - /// f(a,b) = ab - /// - Multiply = 1, - - /// - /// Screen blend mode takes the RGB component values of each pixel from the top and bottom layer and inverts - /// them, then multiples the RGB component values of each pixel from the top layer with the RGB component values - /// of the corresponding pixel from the bottom layer, then the RGB component value of each resulting pixel is - /// inverted again. - /// f(a,b) = 1-(1-a)(1-b) - /// - Screen = 2, - - /// - /// Overlay blend combines the Multiply and Screen blend modes based on the tonal value of the bottom layer. If - /// the bottom layer is darker than 50% gray, then the tonal values are multiplied; otherwise, they get - /// screened. In both cases the resulting value is doubled after. - /// f(a,b) = 2ab when a less than 0.5 - /// f(a,b) = 1-2(1-a)(1-b) when a equal to or greater than 0.5 - /// - Overlay = 3, - - /// - /// Darken blend retains the smallest of each RGB component for each corresponding pixel from the top and bottom - /// layer. - /// f((r1,g1,b1), (r2,b2,g2)) = [min(r1,r2), min(g1,g2), min(b1,b2)] - /// - Darken = 4, - - /// - /// Lighten blend retains the largest of each RGB component for each corresponding pixel from the top and bottom - /// layer. - /// f((r1,g1,b1), (r2,b2,g2)) = [max(r1,r2), max(g1,g2), max(b1,b2)] - /// - Lighten = 5, - - /// - /// Color Dodge blend divides each pixel from the bottom layer with the corresponding inverted pixel from the - /// top layer. - /// f(a,b) = a/(1-b) - /// - ColorDodge = 6, - - /// - /// Color Burn blend divides each inverted pixel from the bottom layer with the corresponding pixel from the top - /// layer, then inverts the resulting value. - /// f(a,b) = 1-(1-a)/b - /// - ColorBurn = 7, - - /// - /// Hard Light blend combines the Multiply and Screen blend modes based on the tonal value of the top layer. - /// If the top layer is darker than 50% gray, then the tonal values are multiplied; otherwise, they get - /// screened. In both cases the resulting value is doubled after. - /// f(a,b) = 2ab when b less than 0.5 - /// f(a,b) = 1-2(1-a)(1-b) when b equal to or greater than 0.5 - /// - HardLight = 8, - - /// - /// Soft Light blend modulates the tonal values of the bottom layer by the tonal values of the top layer. - /// f(a,b) = (2b-1)(a-a^2)+a when b is less than 0.5 - /// f(a,b) = (2b-1)(sqrt(a)-a)+a when b is equal to or greater than 0.5 - /// - SoftLight = 9, - - /// - /// Difference blend returns the absolute value in the difference between RGB component value of each pixel in - /// the top layer from the RGB component value in the corresponding pixel in the bottom layer. - /// f(a,b) = |a-b| - /// - Difference = 10, - - /// - /// Exclusion blend mode takes the sum of the RGB component values of each pixel in the top layer with the RGB - /// component value of each corresponding pixel in the bottom layer, then subtracts the doubled product of top - /// and bottom layer. - /// f(a,b) = a+b-2ab - /// - Exclusion = 11, - - /// - /// Hue blend mode preserves the luma and chroma of each pixel in the bottom layer and adopts the hue of the - /// corresponding pixel in the top layer. - /// f((Ha,Sa,La),(Hb,Sb,Lb)) = (Hb, Sa, La) - /// - Hue = 12, - - /// - /// Saturation blend mode preserves the luma and hue of each pixel in the bottom layer and adopts the chroma of - /// the corresponding pixel in the top layer. - /// f((Ha,Sa,La),(Hb,Sb,Lb)) = (Ha, Sb, La) - /// - Saturation = 13, - - /// - /// The color blend mode preserves the luma of each pixel in the bottom layer and adopts the hue and chorma of - /// corresponding pixel in the top layer. - /// f((Ha,Sa,La),(Hb,Sb,Lb)) = (Hb, Sb, La) - /// - Color = 14, - - /// - /// Luminosity blend mode preserves the hue and chroma of each pixel in the bottom layer and adopts the luma of - /// the corresponding pixel in then top layer. - /// f((Ha,Sa,La),(Hb,Sb,Lb)) = (Ha, Sa, Lb) - /// - Luminosity = 15, - - /// - /// Addition blend mode adds the RGB component values of each pixel from the top layer with the RGB component - /// values of each corresponding pixel in the bottom layer. - /// f(a,b) = a + b - /// - Addition = 16, - - /// - /// Subtract blend mode subtracts the RGB component values of each pixel from the top layer from the RGB - /// component values of each corresponding pixel in the bottom layer. - /// f(a,b) = a - b - /// - Subtract = 17, - - /// - /// Divide blend mode divides the RGB component values of each pixel from the bottom layer by the RGB component - /// values of each corresponding pixel from the top layer. - /// f(a,b) = a/b - /// - Divide = 18 -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteCel.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteCel.cs deleted file mode 100644 index 4300df59..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteCel.cs +++ /dev/null @@ -1,79 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a single cel in an frame. -/// -public abstract class AsepriteCel -{ - /// - /// Gets a reference to the this is on. - /// - public AsepriteLayer Layer { get; } - - /// - /// Gets the x- and y-coordinate location of this relative to the bounds of the - /// it is in. - /// - public Point Position { get; } - - /// - /// Gets the opacity level of this . - /// - public int Opacity { get; } - - /// - /// Gets the custom that was set for this in aseprite. - /// - public AsepriteUserData UserData { get; } = new(); - - internal AsepriteCel(AsepriteLayer layer, Point position, int opacity) => - (Layer, Position, Opacity) = (layer, position, opacity); - - /// - /// Returns the this is on as the specified type. - /// - /// - /// The type to return as. - /// - /// - /// The this is on as the specified type. - /// - /// - /// Thrown if the this is on is not of the type specified. - /// - public T LayerAs() where T : AsepriteLayer - { - if (Layer is T asT) - { - return asT; - } - - throw new InvalidOperationException($"The layer of this cel is not of type '{typeof(T)}'. It is of type '{Layer.GetType()}'"); - } -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteFileBuilder.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteFileBuilder.cs deleted file mode 100644 index 42f88504..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteFileBuilder.cs +++ /dev/null @@ -1,302 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.IO.Compression; -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -internal class AsepriteFileBuilder -{ - private Color[] _palette = Array.Empty(); - private byte _transparentIndex = new(); - private ushort _colorDepth; - private bool _layerOpacityValid; - private ushort _frameWidth; - private ushort _frameHeight; - private List _frames = new(); - private List _layers = new(); - private List _tags = new(); - private List _slices = new(); - private List _tilesets = new(); - private List _nextFrameCels = new(); - private string _name; - private AsepriteUserData _spriteUserData = new(); - - internal AsepriteFileBuilder(string name) => _name = name; - - internal void SetFrameWidth(ushort width) => _frameWidth = width; - internal void SetFrameHeight(ushort height) => _frameHeight = height; - internal void SetColorDepth(ushort depth) => _colorDepth = depth; - internal void SetTransparentIndex(byte index) - { - if (_colorDepth != 8) - { - // Non-zero transparent index is only valid when color depth is 8 (Indexed mode) - _transparentIndex = 0; - } - else - { - _transparentIndex = index; - } - } - internal void SetLayerOpacityValid(bool isValid) => _layerOpacityValid = isValid; - - internal void AddFrame(int duration) - { - AsepriteFrame frame = new($"{_name} {_frames.Count}", _frameWidth, _frameHeight, duration, _nextFrameCels.ToArray()); - _nextFrameCels.Clear(); - _frames.Add(frame); - } - - internal void AddLayer(AsepriteLayerFlags flags, ushort blend, byte opacity, string name) - { - if (!_layerOpacityValid) - { - opacity = 255; - } - - AsepriteLayer layer = new(flags, (AsepriteBlendMode)blend, opacity, name); - _layers.Add(layer); - } - - internal void AddTilemapLayer(uint tilesetIndex, AsepriteLayerFlags flags, ushort blend, byte opacity, string name) - { - AsepriteTileset tileset = _tilesets[(int)tilesetIndex]; - AsepriteTilemapLayer layer = new(tileset, /*(int)tilesetIndex,*/ flags, (AsepriteBlendMode)blend, opacity, name); - _layers.Add(layer); - } - - internal void AddRawImageCel(short x, short y, ushort width, ushort height, ushort layerIndex, byte opacity, ReadOnlySpan data) - { - Color[] pixels = new Color[width * height]; - ToColor(data, pixels); - AsepriteLayer layer = _layers[layerIndex]; - Point position = new(x, y); - AsepriteImageCel cel = new(width, height, pixels, layer, position, opacity); - _nextFrameCels.Add(cel); - } - - internal void AddLinkedCel(ushort frameIndex) - { - AsepriteFrame frame = _frames[frameIndex]; - // If the first cel is a linked cel, then we haven't added cels yet - // so the " - 1" will result in -1. So we only do so when the count is - // greater than 0 - AsepriteCel linkedCel = frame.Cels[_nextFrameCels.Count > 0 ? _nextFrameCels.Count - 1 : 0]; - _nextFrameCels.Add(linkedCel); - } - - internal void AddCompressedImageCel(short x, short y, ushort width, ushort height, ushort layerIndex, byte opacity, byte[] compressedData) - { - Color[] pixels = new Color[width * height]; - byte[] decompressedData = Decompress(compressedData); - AddRawImageCel(x, y, width, height, layerIndex, opacity, decompressedData); - } - - internal void AddCompressedTilemapCel(short x, short y, ushort columns, ushort rows, ushort layerIndex, byte opacity, byte[] compressedData, ushort bitsPerTile, uint idBitmask, uint xFlipBitmask, uint yFlipBitmask, uint dFlipBitmask) - { - Span decompressedData = Decompress(compressedData); - - int bytesPerTile = bitsPerTile / 8; - int tileCount = decompressedData.Length / bytesPerTile; - AsepriteTile[] tiles = new AsepriteTile[tileCount]; - - for (int i = 0, b = 0; i < tileCount; i++, b += bytesPerTile) - { - ReadOnlySpan dword = decompressedData.Slice(b, bytesPerTile); - uint value = BitConverter.ToUInt32(dword); - uint id = (value & idBitmask) >> 0; - bool xFlip = (value & xFlipBitmask) == xFlipBitmask; - bool yFlip = (value & yFlipBitmask) == yFlipBitmask; - bool dFlip = (value & dFlipBitmask) == dFlipBitmask; - AsepriteTile tile = new((int)id, xFlip, yFlip, dFlip); - tiles[i] = tile; - } - - AsepriteLayer layer = _layers[layerIndex]; - Point position = new(x, y); - AsepriteTilemapCel cel = new(columns, rows, tiles, layer, position, opacity); - _nextFrameCels.Add(cel); - } - - internal void AddTag(ushort from, ushort to, byte direction, ushort repeat, ReadOnlySpan rgb, string name) - { - Color color = Color.FromNonPremultiplied(rgb[0], rgb[1], rgb[2], (byte)255); - AsepriteTag tag = new(from, to, (AsepriteLoopDirection)direction, repeat, color, name); - _tags.Add(tag); - } - - internal void ResizePalette(uint newSize) - { - if (newSize > 0 && newSize > _palette.Length) - { - Color[] tmp = new Color[newSize]; - Array.Copy(_palette, tmp, _palette.Length); - _palette = tmp; - } - } - - internal void AddPaletteEntry(uint index, ReadOnlySpan rgba) - { - _palette[index] = Color.FromNonPremultiplied(rgba[0], rgba[1], rgba[2], rgba[3]); - } - - internal void AddSlice(string name, bool isNinePatch, bool hasPivot, AsepriteSliceKey[] keys) - { - AsepriteSlice slice = new(name, isNinePatch, hasPivot, keys); - _slices.Add(slice); - } - - internal void AddTileset(uint id, uint count, ushort tileWidth, ushort tileHeight, string name, byte[] compressedData) - { - byte[] decompressedData = Decompress(compressedData); - Color[] pixels = new Color[tileWidth * (tileHeight * count)]; - ToColor(decompressedData, pixels); - AsepriteTileset tileset = new((int)id, (int)count, tileWidth, tileHeight, name, pixels); - _tilesets.Add(tileset); - } - - internal void SetLastCelUserData(string? text, Color? color) - { - AsepriteCel cel = _nextFrameCels[_nextFrameCels.Count - 1]; - cel.UserData.Text = text; - cel.UserData.Color = color; - } - - internal void SetLastLayerUserData(string? text, Color? color) - { - AsepriteLayer layer = _layers[_layers.Count - 1]; - layer.UserData.Text = text; - layer.UserData.Color = color; - } - - internal void SetLastSliceUserData(string? text, Color? color) - { - AsepriteSlice slice = _slices[_slices.Count - 1]; - slice.UserData.Text = text; - slice.UserData.Color = color; - } - - internal void SetTagUserData(int index, string? text, Color? color) - { - AsepriteTag tag = _tags[index]; - tag.UserData.Text = text; - tag.UserData.Color = color; - } - - internal void SetSpriteUserData(string? text, Color? color) - { - _spriteUserData.Text = text; - _spriteUserData.Color = color; - } - - internal void SetTilesetUserData(string? text, Color? color) - { - AsepriteTileset tileset = _tilesets[_tilesets.Count - 1]; - tileset.UserData.Text = text; - tileset.UserData.Color = color; - } - - internal AsepriteFile Build() => - new(_name, _frameWidth, _frameHeight, _palette, _frames.ToArray(), _layers.ToArray(), _tags.ToArray(), _slices.ToArray(), _tilesets.ToArray(), _spriteUserData); - - private static byte[] Decompress(byte[] buffer) - { - using MemoryStream compressedStream = new(buffer); - - // First 2 bytes are the zlib header information, skip past them. - _ = compressedStream.ReadByte(); - _ = compressedStream.ReadByte(); - - using MemoryStream decompressedStream = new(); - using DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress); - deflateStream.CopyTo(decompressedStream); - return decompressedStream.ToArray(); - } - - private void ToColor(ReadOnlySpan source, Span dest) - { - const ushort INDEXED_COLOR_DEPTH = 8; - const ushort GRAYSCALE_COLOR_DEPTH = 16; - const ushort RGBA_COLOR_DEPTH = 32; - - int bytesPerPixel = _colorDepth / 8; - - switch (_colorDepth) - { - case INDEXED_COLOR_DEPTH: - IndexedToColor(source, dest); - break; - case GRAYSCALE_COLOR_DEPTH: - GrayscaleToColor(source, dest); - break; - case RGBA_COLOR_DEPTH: - RgbaToColor(source, dest); - break; - default: - throw new InvalidOperationException($"Invalid Color Depth '{_colorDepth}'"); - } - } - - private void IndexedToColor(ReadOnlySpan source, Span dest) - { - for (int i = 0; i < source.Length; i++) - { - int paletteIndex = source[i]; - - if (paletteIndex == _transparentIndex) - { - dest[i] = Color.FromNonPremultiplied(0, 0, 0, 0); - } - else - { - dest[i] = _palette[paletteIndex]; - } - } - } - - private void GrayscaleToColor(ReadOnlySpan source, Span dest) - { - for (int i = 0, b = 0; i < dest.Length; i++, b += 2) - { - byte rgb = source[b]; - byte a = source[b + 1]; - dest[i] = Color.FromNonPremultiplied(rgb, rgb, rgb, a); - } - } - - private void RgbaToColor(ReadOnlySpan source, Span dest) - { - for (int i = 0, b = 0; i < dest.Length; i++, b += 4) - { - byte red = source[b]; - byte green = source[b + 1]; - byte blue = source[b + 2]; - byte alpha = source[b + 3]; - dest[i] = Color.FromNonPremultiplied(red, green, blue, alpha); - } - } -} - diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteFrame.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteFrame.cs deleted file mode 100644 index d1697a83..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteFrame.cs +++ /dev/null @@ -1,170 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.Utilities; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a in an aseprite image. -/// -public sealed class AsepriteFrame -{ - private AsepriteCel[] _cels; - - /// - /// Gets a read-only span of the elements in this . - /// - public ReadOnlySpan Cels => _cels; - - /// - /// Gets the name assigned this . - /// - public string Name { get; } - - /// - /// Gets the width, in pixels, of this . - /// - public int Width { get; } - - /// - /// Gets the height, in pixels, of this . - /// - public int Height { get; } - - /// - /// Gets the duration, in milliseconds, of this . - /// - public int DurationInMilliseconds { get; } - - internal AsepriteFrame(string name, int width, int height, int duration, AsepriteCel[] cels) => - (Name, Width, Height, DurationInMilliseconds, _cels) = (name, width, height, duration, cels); - - /// - /// Flattens this by combining all elements into a single - /// image representation. - /// - /// - /// Indicates whether only elements on visible elements - /// should be included. - /// - /// - /// Indicates whether elements are on a marked as a - /// background layer should be included. - /// - /// - /// Indicates whether elements are on - /// elements should be included. - /// - /// - /// A new of color values that represent the image of this . - /// - public Color[] FlattenFrame(bool onlyVisibleLayers = true, bool includeBackgroundLayer = false, bool includeTilemapCel = true) - { - Color[] result = new Color[Width * Height]; - - for (int c = 0; c < _cels.Length; c++) - { - AsepriteCel cel = _cels[c]; - - // Are we only processing cels on visible layers? - if (onlyVisibleLayers && !cel.Layer.IsVisible) { continue; } - - // Are we processing cels on background layers? - if (cel.Layer.IsBackground && !includeBackgroundLayer) { continue; } - - if (cel is AsepriteImageCel imageCel) - { - BlendCel(backdrop: result, - source: imageCel.Pixels, - blendMode: imageCel.Layer.BlendMode, - celX: imageCel.Position.X, - celY: imageCel.Position.Y, - celWidth: imageCel.Width, - celOpacity: imageCel.Opacity, - layerOpacity: imageCel.Layer.Opacity); - } - else if (includeTilemapCel && cel is AsepriteTilemapCel tilemapCel) - { - BlendTilemapCel(backdrop: result, - cel: tilemapCel); - } - } - - return result; - } - - private void BlendTilemapCel(Span backdrop, AsepriteTilemapCel cel) - { - // Premultiply the opacity of the cel and the opacity of the layer - byte opacity = BlendFunctions.MUL_UN8(cel.Opacity, cel.Layer.Opacity); - - AsepriteTileset tileset = cel.Tileset; - int width = cel.Columns * tileset.TileWidth; - int height = cel.Rows * tileset.TileHeight; - int x = cel.Position.X; - int y = cel.Position.Y; - - Span pixels = new Color[width * height]; - ReadOnlySpan tiles = cel.Tiles; - for (int i = 0; i < tiles.Length; i++) - { - AsepriteTile tile = tiles[i]; - int column = i % cel.Columns; - int row = i / cel.Columns; - ReadOnlySpan tilePixels = tileset[tile.TilesetTileID]; - - for (int j = 0; j < tilePixels.Length; j++) - { - int px = (j % tileset.TileWidth) + (column * tileset.TileHeight); - int py = (j / tileset.TileWidth) + (row * tileset.TileHeight); - int index = py * width + px; - pixels[index] = tilePixels[j]; - } - } - - BlendCel(backdrop, pixels, cel.Layer.BlendMode, x, y, width, cel.Opacity, cel.Layer.Opacity); - } - - private void BlendCel(Span backdrop, ReadOnlySpan source, AsepriteBlendMode blendMode, int celX, int celY, int celWidth, int celOpacity, int layerOpacity) - { - for (int i = 0; i < source.Length; i++) - { - int x = (i % celWidth) + celX; - int y = (i / celWidth) + celY; - int index = y * Width + x; - - // Sometimes a cel can have a negative x and/or y value. This is caused by selecting an area in within - // Aseprite and then moving a portion of the selected pixels outside the canvas. We don't care about these - // pixels, so if the index is outside the range of the array to store them in, then we'll just ignore them. - if (index < 0 || index >= backdrop.Length) { continue; } - - Color b = backdrop[index]; - Color s = source[i]; - byte opacity = BlendFunctions.MUL_UN8(celOpacity, layerOpacity); - backdrop[index] = BlendFunctions.Blend(blendMode, b, s, opacity); - } - } -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteImageCel.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteImageCel.cs deleted file mode 100644 index ffefe5df..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteImageCel.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a cel in an that contains pixel data. -/// -public sealed class AsepriteImageCel : AsepriteCel -{ - private Color[] _pixels { get; } - - /// - /// Gets a read-only span of the pixel data for this . Pixel order is from - /// top-to-bottom, read left-to-right. - /// - public ReadOnlySpan Pixels => _pixels; - - /// - /// Gets the width, in pixels, of this - /// - public int Width { get; } - - /// - /// Gets the height, in pixels, of this . - /// - public int Height { get; } - - internal AsepriteImageCel(int width, int height, Color[] pixels, AsepriteLayer layer, Point position, int opacity) - : base(layer, position, opacity) => (Width, Height, _pixels) = (width, height, pixels); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLayer.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLayer.cs deleted file mode 100644 index 11eb6730..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLayer.cs +++ /dev/null @@ -1,78 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a of an aseprite image. -/// -public class AsepriteLayer -{ - // Used for serialization when writing to file with AsepriteFileWriter - internal int SerializationID { get; set; } - - /// - /// Gets the flags set for this . - /// - public AsepriteLayerFlags Flags { get; } - - /// - /// Gets a value that indicates whether this is visible. - /// - public bool IsVisible => Flags.HasFlag(AsepriteLayerFlags.Visible); - - /// - /// Gets a value that indicates whether this was set as the background - /// layer in aseprite. - /// - public bool IsBackground => Flags.HasFlag(AsepriteLayerFlags.Background); - - /// - /// Gets a value that indicates whether this is a reference layer. - /// - public bool IsReference => Flags.HasFlag(AsepriteLayerFlags.ReferenceLayer); - - /// - /// Gets a the used by this . - /// - public AsepriteBlendMode BlendMode { get; } - - /// - /// Gets the opacity level of this . - /// - public int Opacity { get; } - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the that was set for this in aseprite. - /// - public AsepriteUserData UserData { get; } = new(); - - internal AsepriteLayer(AsepriteLayerFlags flags, AsepriteBlendMode blendMode, int opacity, string name) => - (Flags, BlendMode, Opacity, Name) = (flags, blendMode, opacity, name); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLayerFlags.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLayerFlags.cs deleted file mode 100644 index 8ac6aa47..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLayerFlags.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines the flag values for a . -/// -public enum AsepriteLayerFlags : ushort -{ - /// - /// Defines that no flags are set - /// - None = 0, - - /// - /// Defines that the is visible. - /// - Visible = 1, - - /// - /// Defines that the is editable in the Aseprite application. - /// - Editable = 2, - - /// - /// Defines that the movement is locked in the Aseprite application. - /// - LockMovement = 4, - - /// - /// Defines that the was set as the background layer. - /// - Background = 8, - - /// - /// Defines that the layer prefers linked cels. - /// - PreferLinkedCels = 16, - - /// - /// Defines that the should be displayed collapsed in the Aseprite application. - /// - DisplayedCollapsed = 32, - - /// - /// Defines that the is a reference layer. - /// - ReferenceLayer = 64 -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLoopDirection.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLoopDirection.cs deleted file mode 100644 index 69772d43..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteLoopDirection.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines the direction for an animation defined by a . -/// -public enum AsepriteLoopDirection : byte -{ - /// - /// Defines that the animation for the is played in a forward direction from the first - /// frame of animation to the last. - /// - Forward = 0, - - /// - /// Defines that the animation for the is played in reversed from the last frame of - /// animation to the first. - /// - Reverse = 1, - - /// - /// Defines that the animation for the ping-pongs by first going from the first frame - /// of animation to the last then playing in reverse from the last frame of animation to the first. - /// - PingPong = 2, - - /// - /// Defines that the animation for the ping-pongs by first going in reverse from the - /// last frame of animation to the first then playing forward from the first frame of animation to the last. - /// - PingPongReverse = 3 -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteSlice.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteSlice.cs deleted file mode 100644 index 614a3738..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteSlice.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a named slice region with keys in aseprite. -/// -public sealed class AsepriteSlice -{ - private AsepriteSliceKey[] _keys; - - /// - /// Gets a read-only span of the for this slice. - /// - public ReadOnlySpan Keys => _keys; - - /// - /// Gets a value that indicates if this , and its , - /// elements represent a nine-patch region. - /// - public bool IsNinePatch { get; } - - /// - /// Gets a value that indicates if this , and its , - /// contain pivot values. - /// - public bool HasPivot { get; } - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the total number of elements in this . - /// - public int KeyCount => _keys.Length; - - /// - /// Gets the set for this in aseprite. - /// - public AsepriteUserData UserData { get; } = new(); - - internal AsepriteSlice(string name, bool isNine, bool hasPivot, AsepriteSliceKey[] keys) => - (Name, IsNinePatch, HasPivot, _keys) = (name, isNine, hasPivot, keys); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteSliceKey.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteSliceKey.cs deleted file mode 100644 index 261c32c2..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteSliceKey.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines the values of a key for a . -/// -public sealed class AsepriteSliceKey -{ - /// - /// Gets the index of the this is valid starting on. - /// - public int FrameIndex { get; } - - /// - /// Gets the rectangular bounds of the during this . - /// - public Rectangle Bounds { get; } - - /// - /// Gets the rectangular bounds of the center rectangle of the , relative to the - /// , during this , if the is a - /// nine-patch slice, otherwise, . - /// - public Rectangle? CenterBounds { get; } - - /// - /// Gets the x- and y-coordinate location of the pivot point of the , relative to the - /// , during this , if the contains - /// pivot values; otherwise, . - /// - public Point? Pivot { get; } - - /// - /// Gets a value that indicates if this is for a nine-patch - /// . When , guarantees that the - /// value is not . - /// - [MemberNotNullWhen(true, nameof(CenterBounds))] - public bool IsNinePatch => CenterBounds is not null; - - /// - /// Gets a value that indicates if this contains pivot values. When - /// , guarantees that the value is not . - /// - [MemberNotNullWhen(true, nameof(Pivot))] - public bool HasPivot => Pivot is not null; - - internal AsepriteSliceKey(int frameIndex, Rectangle bounds, Rectangle? centerBounds, Point? pivot) => - (FrameIndex, Bounds, CenterBounds, Pivot) = (frameIndex, bounds, centerBounds, pivot); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTag.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTag.cs deleted file mode 100644 index 8dd09ff8..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTag.cs +++ /dev/null @@ -1,99 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines an animation tag in aseprite. -/// -public sealed class AsepriteTag -{ - internal Color _tagColor; - - /// - /// Gets the index of the first of animation defined by this - /// . - /// - public int From { get; } - - /// - /// Gets the index of the last see cref="AsepriteFrame"/> of animation defined by this - /// . - /// - public int To { get; } - - /// - /// Gets the of the animation defined by this . - /// - public AsepriteLoopDirection Direction { get; } - - /// - /// Gets the repeat count of the animation defined by this - /// - /// - /// - /// - /// Value - /// Meaning - /// - /// - /// 0 - /// Infinite - /// - /// - /// 1 - /// Plays once (for ping-pong, it plays just in one direction) - /// - /// - /// 2 - /// Plays twice (for ping-pong, it plays once in one direction, and once in reverse) - /// - /// - /// N - /// Plays N times - /// - /// - /// - public int Repeat { get; } - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the set for this . - /// - public AsepriteUserData UserData { get; } = new(); - - /// - /// Gets the color assigned to this . - /// - public Color Color => UserData.Color ?? _tagColor; - - internal AsepriteTag(ushort from, ushort to, AsepriteLoopDirection direction, ushort repeat, Color color, string name) => - (From, To, Direction, Repeat, _tagColor, Name) = (from, to, direction, repeat, color, name); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTile.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTile.cs deleted file mode 100644 index 202504ab..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTile.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a tile in a -/// -public sealed class AsepriteTile : IEquatable -{ - /// - /// Gets the id of the source tile in the that contains the source image data for - /// this . - /// - public int TilesetTileID { get; } - - /// - /// Gets a value that indicates if this is - /// flipped on the x-axis. - /// - public bool XFlip { get; } - - /// - /// Gets a value that indicates if this is - /// flipped on the y-axis. - /// - public bool YFlip { get; } - - /// - /// Gets a value that indicates if this is - /// flipped on its diagonal-axis. - /// - public bool DFlip { get; } - - internal AsepriteTile(int tilesetTileId, bool xFlip, bool yFlip, bool dFlip) => - (TilesetTileID, XFlip, YFlip, DFlip) = (tilesetTileId, xFlip, yFlip, dFlip); - - /// - /// Returns a value that indicates whether the specified . is equal to this - /// .. - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the specified is equal to this - /// ; otherwise, . - /// - public bool Equals(AsepriteTile? other) => other is not null && - XFlip == other.XFlip && - YFlip == other.YFlip && - DFlip == other.DFlip && - TilesetTileID == other.TilesetTileID; -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTilemapCel.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTilemapCel.cs deleted file mode 100644 index b06de39b..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTilemapCel.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a cel in an that contains tile data for a tilemap. -/// -public sealed class AsepriteTilemapCel : AsepriteCel -{ - private AsepriteTile[] _tiles; - - /// - /// Gets a read-only span of the data for this . - /// - public ReadOnlySpan Tiles => _tiles; - - /// - /// Gets the total number of columns in this . - /// - public int Columns { get; } - - /// - /// Gets the total number of rows in this . - /// - public int Rows { get; } - - /// - /// Gets the total number of tiles in this . - /// - public int TileCount => _tiles.Length; - - /// - /// Gets a reference to the used by this tiles in this - /// . - /// - public AsepriteTileset Tileset => LayerAs().Tileset; - - internal AsepriteTilemapCel(int columns, int rows, AsepriteTile[] tiles, AsepriteLayer layer, Point position, int opacity) - : base(layer, position, opacity) => (Columns, Rows, _tiles) = (columns, rows, tiles); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTilemapLayer.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTilemapLayer.cs deleted file mode 100644 index 67f8f7ef..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTilemapLayer.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a layer that elements are on. -/// -public sealed class AsepriteTilemapLayer : AsepriteLayer -{ - /// - /// Gets a reference to the used by the - /// elements on this tilemap layer. - /// - public AsepriteTileset Tileset { get; } - - internal AsepriteTilemapLayer(AsepriteTileset tileset, /*int tilesetID,*/ AsepriteLayerFlags flags, AsepriteBlendMode blend, byte opacity, string name) - : base(flags, blend, opacity, name) => (Tileset/*, TilesetID*/) = (tileset/*, tilesetID*/); -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTileset.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTileset.cs deleted file mode 100644 index e8a76e2e..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteTileset.cs +++ /dev/null @@ -1,132 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Defines a tileset in an aseprite file. -/// -public sealed class AsepriteTileset -{ - private Color[] _pixels; - - /// - /// Gets a read-only span of the pixel data for this . Pixel order is from - /// top-to-bottom, read left-to-right. - /// - public ReadOnlySpan Pixels => _pixels; - - /// - /// Gets the id assigned to this . - /// - public int ID { get; } - - /// - /// Gets the total number of tiles in this . - /// - public int TileCount { get; } - - /// - /// Gets the width, in pixels, of each tile in this . - /// - public int TileWidth { get; } - - /// - /// Gets the height, in pixels, of each tile in this . - /// - public int TileHeight { get; } - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the width, in pixels, of the source image for this . - /// - public int Width { get; } - - /// - /// Gets the height, in pixels, of the source image for this . - /// - public int Height { get; } - - /// - /// Gets the set for this in aseprite. - /// - /// - /// User Data for tilesets was added in Aseprite 1.3-rc1. It currently doesn't appear that you can set user - /// data for a tileset within the Aseprite UI itself, but can set it through the LUA Scripting API. - /// - public AsepriteUserData UserData { get; } = new(); - - /// - /// Gets a read-only span of the color values that represent the pixel data for a the tile at the specified - /// index in this . Pixel order is from top-to-bottom, read left-to-right. - /// - /// - /// The index of the tile in this to get the pixel data for. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// tiles in this . - /// - public ReadOnlySpan this[int tileIndex] => GetTile(tileIndex); - - internal AsepriteTileset(int id, int count, int tileWidth, int tileHeight, string name, Color[] pixels) - { - ID = id; - TileCount = count; - TileWidth = tileWidth; - TileHeight = tileHeight; - Name = name; - _pixels = pixels; - Width = tileWidth; - Height = tileHeight * TileCount; - } - - /// - /// Gets a read-only span of the color values that represent the pixel data for a the tile at the specified - /// index in this . Pixel order is from top-to-bottom, read left-to-right. - /// - /// - /// The index of the tile in this to get the pixel data for. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// tiles in this . - /// - public ReadOnlySpan GetTile(int tileIndex) - { - if (tileIndex < 0 || tileIndex >= TileCount) - { - throw new ArgumentOutOfRangeException(nameof(tileIndex)); - } - - int len = TileWidth * TileHeight; - return Pixels.Slice(tileIndex * len, len); - } -} diff --git a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteUserData.cs b/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteUserData.cs deleted file mode 100644 index 269895c5..00000000 --- a/source/MonoGame.Aseprite.Shared/AsepriteTypes/AsepriteUserData.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.AsepriteTypes; - -/// -/// Represents the custom userdata that can be set for a , , -/// , , or element in aseprite. -/// -public sealed class AsepriteUserData -{ - /// - /// Gets a value that indicates if this contains a text value. When this is - /// , guarantees that the value is not . - /// - [MemberNotNullWhen(true, nameof(Text))] - public bool HasText => Text is not null; - - /// - /// Gets the custom text that was set for this , if any was set in aseprite; - /// otherwise, . - /// - public string? Text { get; internal set; } = default; - - /// - /// Gets a value that indicates whether this contains a color value. When - /// , guarantees that the value is not - /// . - /// - [MemberNotNullWhen(true, nameof(Color))] - public bool HasColor => Color is not null; - - /// - /// Gets the custom color that was set for this , if any was set in aseprite; - /// otherwise, . - /// - public Color? Color { get; internal set; } = default; - - internal AsepriteUserData() { } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/BinaryReaderExtensions.cs b/source/MonoGame.Aseprite.Shared/Content/BinaryReaderExtensions.cs deleted file mode 100644 index 17910c1e..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/BinaryReaderExtensions.cs +++ /dev/null @@ -1,277 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content; - -internal static class BinaryReaderExtensions -{ - internal static void ReadMagic(this BinaryReader reader) - { - byte m = reader.ReadByte(); // [M]onoGame - byte a = reader.ReadByte(); // [A]seprite - byte c = reader.ReadByte(); // [C]ontent - - - if (m != 'M' || a != 'A' || c != 'C') - { - // Dispose of reader so stream is closed in case the caller has a try-catch that handles this exception. - reader.Dispose(); - throw new InvalidOperationException($"File contains invalid magic number. Was this processed using the MonoGame.Aseprite library?"); - } - } - - internal static Rectangle ReadRectangle(this BinaryReader reader) - { - Rectangle result = new(); - result.Location = ReadPoint(reader); - result.Size = ReadPoint(reader); - return result; - } - - internal static Point ReadPoint(this BinaryReader reader) - { - Point result = new(); - result.X = reader.ReadInt32(); - result.Y = reader.ReadInt32(); - return result; - } - - internal static Vector2 ReadVector2(this BinaryReader reader) - { - Vector2 result = new(); - result.X = reader.ReadSingle(); - result.Y = reader.ReadSingle(); - return result; - } - - internal static Color ReadColor(this BinaryReader reader) - { - Color result = new(); - result.R = reader.ReadByte(); - result.G = reader.ReadByte(); - result.B = reader.ReadByte(); - result.A = reader.ReadByte(); - return result; - } - - internal static RawTexture ReadRawTexture(this BinaryReader reader) - { - string name = reader.ReadString(); - int width = reader.ReadInt32(); - int height = reader.ReadInt32(); - - Color[] pixels = reader.ReadColors(); - - return new(name, pixels, width, height); - } - - internal static Color[] ReadColors(this BinaryReader reader) - { - int count = reader.ReadInt32(); - Color[] pixels = new Color[count]; - for (int i = 0; i < count; i++) - { - pixels[i] = reader.ReadColor(); - } - return pixels; - } - - internal static RawSlice ReadRawSlice(this BinaryReader reader) - { - string name = reader.ReadString(); - Rectangle bounds = reader.ReadRectangle(); - Vector2 origin = reader.ReadVector2(); - Color color = reader.ReadColor(); - - bool isNine = reader.ReadBoolean(); - - if (isNine) - { - Rectangle centerBounds = reader.ReadRectangle(); - return new RawNinePatchSlice(name, bounds, centerBounds, origin, color); - } - - return new RawSlice(name, bounds, origin, color); - } - - internal static RawAnimationTag[] ReadRawAnimationTags(this BinaryReader reader) - { - int count = reader.ReadInt32(); - RawAnimationTag[] tags = new RawAnimationTag[count]; - for (int i = 0; i < count; i++) - { - tags[i] = reader.ReadRawAnimationTag(); - } - return tags; - } - - internal static RawAnimationTag ReadRawAnimationTag(this BinaryReader reader) - { - string name = reader.ReadString(); - int loopCount = reader.ReadInt32(); - bool isReversed = reader.ReadBoolean(); - bool isPingPong = reader.ReadBoolean(); - RawAnimationFrame[] frames = reader.ReadRawAnimationFrames(); - return new(name, frames, loopCount, isReversed, isPingPong); - } - - internal static RawAnimationFrame[] ReadRawAnimationFrames(this BinaryReader reader) - { - int count = reader.ReadInt32(); - RawAnimationFrame[] frames = new RawAnimationFrame[count]; - for (int i = 0; i < count; i++) - { - frames[i] = reader.ReadRawAnimationFrame(); - } - return frames; - } - - internal static RawAnimationFrame ReadRawAnimationFrame(this BinaryReader reader) - { - int index = reader.ReadInt32(); - int duration = reader.ReadInt32(); - return new(index, duration); - } - - internal static RawTextureAtlas ReadRawTextureAtlas(this BinaryReader reader) - { - string name = reader.ReadString(); - RawTexture texture = reader.ReadRawTexture(); - RawTextureRegion[] regions = reader.ReadRawTextureRegions(); - return new(name, texture, regions); - } - - internal static RawTextureRegion[] ReadRawTextureRegions(this BinaryReader reader) - { - int count = reader.ReadInt32(); - RawTextureRegion[] regions = new RawTextureRegion[count]; - - for (int i = 0; i < count; i++) - { - regions[i] = reader.ReadRawTextureRegion(); - } - - return regions; - } - - internal static RawTextureRegion ReadRawTextureRegion(this BinaryReader reader) - { - string name = reader.ReadString(); - Rectangle bounds = reader.ReadRectangle(); - RawSlice[] slices = reader.ReadRawSlices(); - return new(name, bounds, slices); - } - - internal static RawSlice[] ReadRawSlices(this BinaryReader reader) - { - int count = reader.ReadInt32(); - RawSlice[] slices = new RawSlice[count]; - - for (int i = 0; i < count; i++) - { - slices[i] = reader.ReadRawSlice(); - } - - return slices; - } - - internal static RawTileset ReadRawTileset(this BinaryReader reader) - { - int id = reader.ReadInt32(); - string name = reader.ReadString(); - RawTexture texture = reader.ReadRawTexture(); - int tileWidth = reader.ReadInt32(); - int tileHeight = reader.ReadInt32(); - - return new(id, name, texture, tileWidth, tileHeight); - } - - internal static RawTilemapLayer[] ReadRawTilemapLayers(this BinaryReader reader) - { - int count = reader.ReadInt32(); - RawTilemapLayer[] layers = new RawTilemapLayer[count]; - for (int i = 0; i < count; i++) - { - layers[i] = reader.ReadRawTilemapLayer(); - } - return layers; - } - - internal static RawTilemapLayer ReadRawTilemapLayer(this BinaryReader reader) - { - string name = reader.ReadString(); - int tilesetID = reader.ReadInt32(); - int columns = reader.ReadInt32(); - int rows = reader.ReadInt32(); - Point offset = reader.ReadPoint(); - RawTilemapTile[] tiles = reader.ReadRawTilemapTiles(); - return new(name, tilesetID, columns, rows, tiles, offset); - } - - internal static RawTilemapTile[] ReadRawTilemapTiles(this BinaryReader reader) - { - int count = reader.ReadInt32(); - RawTilemapTile[] rawTilemapTiles = new RawTilemapTile[count]; - - for (int i = 0; i < count; i++) - { - rawTilemapTiles[i] = reader.ReadRawTilemapTile(); - } - - return rawTilemapTiles; - } - - internal static RawTilemapTile ReadRawTilemapTile(this BinaryReader reader) - { - int tilesetTileID = reader.ReadInt32(); - bool flipHorizontally = reader.ReadBoolean(); - bool flipVertically = reader.ReadBoolean(); - bool flipDiagonally = reader.ReadBoolean(); - - return new RawTilemapTile(tilesetTileID, flipHorizontally, flipVertically, flipDiagonally); - } - - internal static RawTilemapFrame[] ReadRawTilemapFrames(this BinaryReader reader) - { - int count = reader.ReadInt32(); - RawTilemapFrame[] rawTilemapFrames = new RawTilemapFrame[count]; - - for (int i = 0; i < count; i++) - { - rawTilemapFrames[i] = reader.ReadRawTilemapFrame(); - } - - return rawTilemapFrames; - } - - internal static RawTilemapFrame ReadRawTilemapFrame(this BinaryReader reader) - { - int duration = reader.ReadInt32(); - RawTilemapLayer[] layers = reader.ReadRawTilemapLayers(); - return new(duration, layers); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/BinaryWriterExtensions.cs b/source/MonoGame.Aseprite.Shared/Content/BinaryWriterExtensions.cs deleted file mode 100644 index 74d3878d..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/BinaryWriterExtensions.cs +++ /dev/null @@ -1,224 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content; - -internal static class BinaryWriterExtensions -{ - internal static void WriteMagic(this BinaryWriter writer) - { - writer.Write((byte)'M'); // [M]onoGame - writer.Write((byte)'A'); // [A]seprite - writer.Write((byte)'C'); // [C]ontent - } - - internal static void Write(this BinaryWriter writer, Rectangle value) - { - writer.Write(value.Location); - writer.Write(value.Size); - } - - internal static void Write(this BinaryWriter writer, Point value) - { - writer.Write(value.X); - writer.Write(value.Y); - } - - internal static void Write(this BinaryWriter writer, Vector2 value) - { - writer.Write(value.X); - writer.Write(value.Y); - } - - internal static void Write(this BinaryWriter writer, Color value) - { - writer.Write(value.R); - writer.Write(value.G); - writer.Write(value.B); - writer.Write(value.A); - } - - internal static void Write(this BinaryWriter writer, RawTexture value) - { - writer.Write(value.Name); - writer.Write(value.Width); - writer.Write(value.Height); - writer.Write(value.Pixels); - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, RawSlice value) - { - writer.Write(value.Name); - writer.Write(value.Bounds); - writer.Write(value.Origin); - writer.Write(value.Color); - - if (value is RawNinePatchSlice ninePatch) - { - writer.Write(true); - writer.Write(ninePatch.CenterBounds); - } - else - { - writer.Write(false); - } - } - - internal static void Write(this BinaryWriter writer, RawTextureAtlas value) - { - writer.Write(value.Name); - writer.Write(value.RawTexture); - writer.Write(value.RawTextureRegions); - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, RawTextureRegion value) - { - writer.Write(value.Name); - writer.Write(value.Bounds); - writer.Write(value.Slices); - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, RawAnimationTag value) - { - writer.Write(value.Name); - writer.Write(value.LoopCount); - writer.Write(value.IsReversed); - writer.Write(value.IsPingPong); - writer.Write(value.RawAnimationFrames); - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, RawAnimationFrame value) - { - writer.Write(value.FrameIndex); - writer.Write(value.DurationInMilliseconds); - } - - internal static void Write(this BinaryWriter writer, RawTileset value) - { - writer.Write(value.ID); - writer.Write(value.Name); - writer.Write(value.RawTexture); - writer.Write(value.TileWidth); - writer.Write(value.TileHeight); - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, RawTilemapLayer value) - { - writer.Write(value.Name); - writer.Write(value.TilesetID); - writer.Write(value.Columns); - writer.Write(value.Rows); - writer.Write(value.Offset); - writer.Write(value.RawTilemapTiles); - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, RawTilemapTile value) - { - writer.Write(value.TilesetTileID); - writer.Write(value.FlipHorizontally); - writer.Write(value.FlipVertically); - writer.Write(value.FlipDiagonally); - } - - internal static void Write(this BinaryWriter writer, ReadOnlySpan value) - { - writer.Write(value.Length); - for (int i = 0; i < value.Length; i++) - { - writer.Write(value[i]); - } - } - - internal static void Write(this BinaryWriter writer, RawTilemapFrame value) - { - writer.Write(value.DurationInMilliseconds); - writer.Write(value.RawTilemapLayers); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Processors/AnimatedTilemapProcessor.cs b/source/MonoGame.Aseprite.Shared/Content/Processors/AnimatedTilemapProcessor.cs deleted file mode 100644 index f9f96a9b..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Processors/AnimatedTilemapProcessor.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -public static partial class AnimatedTilemapProcessor -{ - /// - /// Processes a from the given . - /// - /// - /// The to processes the from. - /// - /// - /// Indicates if only elements that are visible should be processed. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if elements are found in the with duplicate - /// names. Tilemaps must contain layers with unique names even though Aseprite does not enforce unique names - /// for layers. - /// - public static RawAnimatedTilemap ProcessRaw(AsepriteFile aseFile, bool onlyVisibleLayers = true) - { - List rawTilesets = new(); - RawTilemapFrame[] rawFrames = new RawTilemapFrame[aseFile.Frames.Length]; - HashSet tilesetIDCheck = new(); - - for (int f = 0; f < aseFile.Frames.Length; f++) - { - AsepriteFrame aseFrame = aseFile.Frames[f]; - List rawLayers = new(); - HashSet layerNameCheck = new(); - - for (int c = 0; c < aseFrame.Cels.Length; c++) - { - // Only care about tilemap cels. - if (aseFrame.Cels[c] is not AsepriteTilemapCel tilemapCel) - { - continue; - } - - // Only continue if layer is visible or if explicitly told to include non-visible layers. - if (!tilemapCel.Layer.IsVisible && onlyVisibleLayers) - { - continue; - } - - // Need to perform a check that we don't have duplicate layer names. This is because aseprite allows - // duplicate layer names, but we require unique names from this point on. - AsepriteTilemapLayer aseTilemapLayer = tilemapCel.LayerAs(); - string layerName = aseTilemapLayer.Name; - - if (!layerNameCheck.Add(layerName)) - { - throw new InvalidOperationException($"Duplicate layer name '{tilemapCel.Layer.Name}' found. Layer names must be unique for tilemaps"); - } - - int tilesetID = aseTilemapLayer.Tileset.ID; - - if (tilesetIDCheck.Add(tilesetID)) - { - RawTileset rawTileset = TilesetProcessor.ProcessRaw(aseTilemapLayer.Tileset); - rawTilesets.Add(rawTileset); - } - - RawTilemapTile[] tiles = new RawTilemapTile[tilemapCel.Tiles.Length]; - - for (int t = 0; t < tilemapCel.Tiles.Length; t++) - { - AsepriteTile aseTile = tilemapCel.Tiles[t]; - tiles[t] = new RawTilemapTile(aseTile.TilesetTileID, aseTile.YFlip, aseTile.XFlip, aseTile.DFlip); - } - - int columns = tilemapCel.Columns; - int rows = tilemapCel.Rows; - Point offset = tilemapCel.Position; - - RawTilemapLayer rawLayer = new(layerName, tilesetID, columns, rows, tiles, offset); - rawLayers.Add(rawLayer); - - } - - rawFrames[f] = new(aseFrame.DurationInMilliseconds, rawLayers.ToArray()); - } - - return new(aseFile.Name, rawTilesets.ToArray(), rawFrames); - - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Processors/SpriteProcessor.cs b/source/MonoGame.Aseprite.Shared/Content/Processors/SpriteProcessor.cs deleted file mode 100644 index 414a380e..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Processors/SpriteProcessor.cs +++ /dev/null @@ -1,124 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -public static partial class SpriteProcessor -{ - /// - /// Processes a from the at the specified index in the - /// given . - /// - /// - /// The that contains the to processes. - /// - /// - /// The index of the in the to process. - /// - /// - /// Indicates if only elements on visible elements should - /// be included. - /// - /// - /// Indicates if elements on an marked as the background - /// layer should be included. - /// - /// - /// Indicates if elements on a should be included. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to - /// the total number of elements in the given . - /// - public static RawSprite ProcessRaw(AsepriteFile aseFile, int aseFrameIndex, bool onlyVisibleLayers = true, bool includeBackgroundLayer = false, bool includeTilemapLayers = true) - { - AsepriteFrame aseFrame = aseFile.GetFrame(aseFrameIndex); - - Color[] pixels = aseFrame.FlattenFrame(onlyVisibleLayers, includeBackgroundLayer, includeTilemapLayers); - RawTexture rawTexture = new(aseFrame.Name, pixels, aseFrame.Width, aseFrame.Height); - - RawSlice[] slices = ProcessSlices(aseFrameIndex, aseFile.Slices); - - return new(aseFrame.Name, rawTexture, slices); - } - - private static RawSlice[] ProcessSlices(int frameIndex, ReadOnlySpan slices) - { - List result = new(); - HashSet sliceNameCheck = new(); - - for (int s = 0; s < slices.Length; s++) - { - AsepriteSlice slice = slices[s]; - ReadOnlySpan keys = slice.Keys; - - // Traverse keys backwards until we find a match for the frame index - for (int k = keys.Length - 1; k >= 0; k--) - { - AsepriteSliceKey key = keys[k]; - - if (key.FrameIndex > frameIndex) - { - continue; - } - - string name = slice.Name; - - if (sliceNameCheck.Contains(name)) - { - throw new InvalidOperationException($"Duplicate slice name '{name}' found. Slices must have unique names"); - } - - Rectangle bounds = key.Bounds; - Color color = slice.UserData.Color.GetValueOrDefault(); - Vector2 origin = key.Pivot.GetValueOrDefault().ToVector2(); - - RawSlice rawSlice; - - if (key.IsNinePatch) - { - rawSlice = new RawNinePatchSlice(name, bounds, key.CenterBounds.GetValueOrDefault(), origin, color); - } - else - { - rawSlice = new RawSlice(name, bounds, origin, color); - } - - result.Add(rawSlice); - sliceNameCheck.Add(name); - break; - } - } - - return result.ToArray(); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Processors/SpriteSheetProcessor.cs b/source/MonoGame.Aseprite.Shared/Content/Processors/SpriteSheetProcessor.cs deleted file mode 100644 index e07ef265..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Processors/SpriteSheetProcessor.cs +++ /dev/null @@ -1,114 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -public static partial class SpriteSheetProcessor -{ - /// - /// Processes a from the given . - /// - /// - /// The to process the from. - /// - /// - /// Indicates if only elements on visible elements should - /// be included. - /// - /// - /// Indicates if elements on the marked as the background - /// layer should be included. - /// - /// - /// Indicates if elements on a should be included. - /// - /// - /// Indicates if duplicate elements should be merged into one. - /// - /// - /// The amount of transparent pixels to add between the edge of the generated image - /// - /// - /// The amount of transparent pixels to add between each texture region in the generated image. - /// - /// - /// The amount of transparent pixels to add around the edge of each texture region in the generated image. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if elements are found in the with duplicate - /// names. Spritesheets must contain elements with unique names even though aseprite - /// does not enforce unique names for elements. - /// - public static RawSpriteSheet ProcessRaw(AsepriteFile aseFile, bool onlyVisibleLayers = true, bool includeBackgroundLayer = false, bool includeTilemapLayers = true, bool mergeDuplicates = true, int borderPadding = 0, int spacing = 0, int innerPadding = 0) - { - RawTextureAtlas rawAtlas = TextureAtlasProcessor.ProcessRaw(aseFile, onlyVisibleLayers, includeBackgroundLayer, includeTilemapLayers, mergeDuplicates, borderPadding, spacing, innerPadding); - - RawAnimationTag[] rawTags = new RawAnimationTag[aseFile.Tags.Length]; - HashSet tagNameCheck = new(); - - for (int i = 0; i < aseFile.Tags.Length; i++) - { - AsepriteTag aseTag = aseFile.GetTag(i); - - if (!tagNameCheck.Add(aseTag.Name)) - { - throw new InvalidOperationException($"Duplicate tag name '{aseTag.Name}' found. Tags must have unique names for a spritesheet."); - } - - rawTags[i] = ProcessRawTag(aseTag, aseFile.Frames); - } - - return new(aseFile.Name, rawAtlas, rawTags); - - } - - private static RawAnimationTag ProcessRawTag(AsepriteTag aseTag, ReadOnlySpan aseFrames) - { - int frameCount = aseTag.To - aseTag.From + 1; - RawAnimationFrame[] rawAnimationFrames = new RawAnimationFrame[frameCount]; - int[] frames = new int[frameCount]; - int[] durations = new int[frameCount]; - - for (int i = 0; i < frameCount; i++) - { - int index = aseTag.From + i; - rawAnimationFrames[i] = new(index, aseFrames[index].DurationInMilliseconds); - } - - // In aseprite, all tags are looping - int loopCount = aseTag.Repeat; - bool isReversed = aseTag.Direction == AsepriteLoopDirection.Reverse || aseTag.Direction == AsepriteLoopDirection.PingPongReverse; - bool isPingPong = aseTag.Direction == AsepriteLoopDirection.PingPong || aseTag.Direction == AsepriteLoopDirection.PingPongReverse; - - return new(aseTag.Name, rawAnimationFrames, loopCount, isReversed, isPingPong); - } -} - diff --git a/source/MonoGame.Aseprite.Shared/Content/Processors/TextureAtlasProcessor.cs b/source/MonoGame.Aseprite.Shared/Content/Processors/TextureAtlasProcessor.cs deleted file mode 100644 index ca48f312..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Processors/TextureAtlasProcessor.cs +++ /dev/null @@ -1,211 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -public static partial class TextureAtlasProcessor -{ - /// - /// Processes a from the given . - /// - /// - /// The to process the from. - /// - /// - /// Indicates if only elements on visible elements should - /// be included. - /// - /// - /// Indicates if elements on the marked as the background - /// layer should be included. - /// - /// - /// Indicates if elements on a should be included. - /// - /// - /// Indicates if duplicate elements should be merged into one. - /// - /// - /// The amount of transparent pixels to add between the edge of the generated image - /// - /// - /// The amount of transparent pixels to add between each texture region in the generated image. - /// - /// - /// The amount of transparent pixels to add around the edge of each texture region in the generated image. - /// - /// The created by this method. - public static RawTextureAtlas ProcessRaw(AsepriteFile aseFile, bool onlyVisibleLayers = true, bool includeBackgroundLayer = false, bool includeTilemapLayers = true, bool mergeDuplicates = true, int borderPadding = 0, int spacing = 0, int innerPadding = 0) - { - int frameWidth = aseFile.CanvasWidth; - int frameHeight = aseFile.CanvasHeight; - int frameCount = aseFile.Frames.Length; - - Color[][] flattenedFrames = new Color[frameCount][]; - - for (int i = 0; i < frameCount; i++) - { - flattenedFrames[i] = aseFile.Frames[i].FlattenFrame(onlyVisibleLayers, includeBackgroundLayer, includeTilemapLayers); - } - - Dictionary duplicateMap = new(); - Dictionary originalToDuplicateLookup = new(); - - for (int i = 0; i < flattenedFrames.GetLength(0); i++) - { - for (int d = 0; d < i; d++) - { - if (flattenedFrames[i].SequenceEqual(flattenedFrames[d])) - { - duplicateMap.Add(i, d); - break; - } - } - } - - if (mergeDuplicates) - { - frameCount -= duplicateMap.Count; - } - - double sqrt = Math.Sqrt(frameCount); - int columns = (int)Math.Ceiling(sqrt); - int rows = (frameCount + columns - 1) / columns; - - int imageWidth = (columns * frameWidth) - + (borderPadding * 2) - + (spacing * (columns - 1)) - + (innerPadding * 2 * columns); - - int imageHeight = (rows * frameHeight) - + (borderPadding * 2) - + (spacing * (rows - 1)) - + (innerPadding * 2 * rows); - - Color[] imagePixels = new Color[imageWidth * imageHeight]; - RawTextureRegion[] regions = new RawTextureRegion[aseFile.Frames.Length]; - - int offset = 0; - - for (int i = 0; i < flattenedFrames.GetLength(0); i++) - { - if (mergeDuplicates && duplicateMap.ContainsKey(i)) - { - RawTextureRegion original = originalToDuplicateLookup[duplicateMap[i]]; - RawTextureRegion duplicate = new($"{aseFile.Name} {i}", original.Bounds, GetSlicesForFrame(i, aseFile.Slices)); - regions[i] = duplicate; - offset++; - continue; - } - - int column = (i - offset) % columns; - int row = (i - offset) / columns; - Color[] frame = flattenedFrames[i]; - - int x = (column * frameWidth) - + borderPadding - + (spacing * column) - + (innerPadding * (column + column + 1)); - - int y = (row * frameHeight) - + borderPadding - + (spacing * row) - + (innerPadding * (row + row + 1)); - - for (int p = 0; p < frame.Length; p++) - { - int px = (p % frameWidth) + x; - int py = (p / frameWidth) + y; - - int index = py * imageWidth + px; - imagePixels[index] = frame[p]; - - } - - Rectangle bounds = new(x, y, frameWidth, frameHeight); - RawTextureRegion rawTextureRegion = new($"{aseFile.Name} {i}", bounds, GetSlicesForFrame(i, aseFile.Slices)); - regions[i] = rawTextureRegion; - originalToDuplicateLookup.Add(i, rawTextureRegion); - } - - RawTexture rawTexture = new(aseFile.Name, imagePixels, imageWidth, imageHeight); - return new(aseFile.Name, rawTexture, regions); - } - - private static RawSlice[] GetSlicesForFrame(int frameIndex, ReadOnlySpan slices) - { - List result = new(); - HashSet sliceNameCheck = new(); - - for (int s = 0; s < slices.Length; s++) - { - AsepriteSlice slice = slices[s]; - ReadOnlySpan keys = slice.Keys; - - // Traverse keys backwards until we find a match for the frame index - for (int k = keys.Length - 1; k >= 0; k--) - { - AsepriteSliceKey key = keys[k]; - - if (key.FrameIndex > frameIndex) - { - continue; - } - - string name = slice.Name; - - if (sliceNameCheck.Contains(name)) - { - throw new InvalidOperationException($"Duplicate slice name '{name}' found. Slices must have unique names"); - } - - Rectangle bounds = key.Bounds; - Color color = slice.UserData.Color.GetValueOrDefault(); - Vector2 origin = key.Pivot.GetValueOrDefault().ToVector2(); - - RawSlice rawSlice; - - if (key.IsNinePatch) - { - rawSlice = new RawNinePatchSlice(name, bounds, key.CenterBounds.GetValueOrDefault(), origin, color); - } - else - { - rawSlice = new RawSlice(name, bounds, origin, color); - } - - result.Add(rawSlice); - sliceNameCheck.Add(name); - break; - } - } - - return result.ToArray(); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Processors/TilemapProcessor.cs b/source/MonoGame.Aseprite.Shared/Content/Processors/TilemapProcessor.cs deleted file mode 100644 index 3f4216a2..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Processors/TilemapProcessor.cs +++ /dev/null @@ -1,118 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -public static partial class TilemapProcessor -{ - /// - /// Processes a from the elements as the specified index - /// in the given . - /// - /// - /// The to processes the from. - /// - /// - /// The index of the element in the to processes. - /// - /// - /// Indicates if only elements that are visible should be processed. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in the given . - /// - /// - /// Thrown if elements are found in the with duplicate - /// names. Tilemaps must contain layers with unique names even though aseprite does not enforce unique names - /// for elements. - /// - public static RawTilemap ProcessRaw(AsepriteFile aseFile, int frameIndex, bool onlyVisibleLayers = true) - { - AsepriteFrame aseFrame = aseFile.GetFrame(frameIndex); - - List rawTilesets = new(); - List rawLayers = new(); - HashSet layerNameCheck = new(); - HashSet tilesetIDCheck = new(); - - for (int c = 0; c < aseFrame.Cels.Length; c++) - { - // Only care about tilemap cels. - if (aseFrame.Cels[c] is not AsepriteTilemapCel tilemapCel) - { - continue; - } - - // Only continue if layer is visible or if explicitly told to include non-visible elements. - if (!tilemapCel.Layer.IsVisible && onlyVisibleLayers) - { - continue; - } - - // Need to perform a check that we don't have duplicate layer names. This is because aseprite allows - // duplicate layer names, but we require unique names from this point on. - AsepriteTilemapLayer aseTilemapLayer = tilemapCel.LayerAs(); - string layerName = aseTilemapLayer.Name; - - if (!layerNameCheck.Add(layerName)) - { - throw new InvalidOperationException($"Duplicate layer name '{tilemapCel.Layer.Name}' found. Layer names must be unique for tilemaps"); - } - - int tilesetID = aseTilemapLayer.Tileset.ID; - - if (tilesetIDCheck.Add(tilesetID)) - { - RawTileset rawTileset = TilesetProcessor.ProcessRaw(aseTilemapLayer.Tileset); - rawTilesets.Add(rawTileset); - } - - RawTilemapTile[] tiles = new RawTilemapTile[tilemapCel.Tiles.Length]; - - for (int t = 0; t < tilemapCel.Tiles.Length; t++) - { - AsepriteTile aseTile = tilemapCel.Tiles[t]; - tiles[t] = new RawTilemapTile(aseTile.TilesetTileID, aseTile.YFlip, aseTile.XFlip, aseTile.DFlip); - } - - int columns = tilemapCel.Columns; - int rows = tilemapCel.Rows; - Point offset = tilemapCel.Position; - - RawTilemapLayer rawLayer = new(layerName, tilesetID, columns, rows, tiles, offset); - rawLayers.Add(rawLayer); - } - - return new(aseFile.Name, rawLayers.ToArray(), rawTilesets.ToArray()); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Processors/TilesetProcessor.cs b/source/MonoGame.Aseprite.Shared/Content/Processors/TilesetProcessor.cs deleted file mode 100644 index 349637c8..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Processors/TilesetProcessor.cs +++ /dev/null @@ -1,93 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -public static partial class TilesetProcessor -{ - /// - /// Processes a from the at the specified index in the - /// given . - /// - /// - /// The that contains the to process. - /// - /// - /// The index of the in the to process. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to - /// the total number of elements in the given . - /// - public static RawTileset ProcessRaw(AsepriteFile aseFile, int tilesetIndex) - { - AsepriteTileset aseTileset = aseFile.GetTileset(tilesetIndex); - return ProcessRaw(aseTileset); - } - - /// - /// Processes a from the with the specified name in the - /// given . - /// - /// - /// The that contains the to process. - /// - /// - /// The name of the in the to process. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the given does not contain an element - /// with the specified name. - /// - public static RawTileset ProcessRaw(AsepriteFile aseFile, string tilesetName) - { - AsepriteTileset aseTileset = aseFile.GetTileset(tilesetName); - return ProcessRaw(aseTileset); - } - - /// - /// Processes a from the given . - /// - /// - /// The to process. - /// - /// - /// The created by this method. - /// - public static RawTileset ProcessRaw(AsepriteTileset aseTileset) - { - RawTexture texture = new(aseTileset.Name, aseTileset.Pixels.ToArray(), aseTileset.Width, aseTileset.Height); - return new(aseTileset.ID, aseTileset.Name, texture, aseTileset.TileWidth, aseTileset.TileHeight); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Readers/AsepriteFileReader.cs b/source/MonoGame.Aseprite.Shared/Content/Readers/AsepriteFileReader.cs deleted file mode 100644 index 460de24f..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Readers/AsepriteFileReader.cs +++ /dev/null @@ -1,598 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Diagnostics.CodeAnalysis; -using System.Text; -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; - -namespace MonoGame.Aseprite.Content.Readers; - -/// -/// Defines a reader that reads an . -/// -public static class AsepriteFileReader -{ - const ushort CHUNK_TYPE_OLD_PALETTE_1 = 0x0004; - const ushort CHUNK_TYPE_OLD_PALETTE_2 = 0x0011; - const ushort CHUNK_TYPE_LAYER = 0x2004; - const ushort CHUNK_TYPE_CEL = 0x2005; - const ushort CHUNK_TYPE_CEL_EXTRA = 0x2006; - const ushort CHUNK_TYPE_COLOR_PROFILE = 0x2007; - const ushort CHUNK_TYPE_EXTERNAL_FILES = 0x2008; - const ushort CHUNK_TYPE_MASK = 0x2016; - const ushort CHUNK_TYPE_PATH = 0x2017; - const ushort CHUNK_TYPE_TAGS = 0x2018; - const ushort CHUNK_TYPE_PALETTE = 0x2019; - const ushort CHUNK_TYPE_USER_DATA = 0x2020; - const ushort CHUNK_TYPE_SLICE = 0x2022; - const ushort CHUNK_TYPE_TILESET = 0x2023; - - /// - /// Reads the at the given path. - /// - /// - /// The path and name of the aseprite file to read. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if no file is located at the specified path. - /// - /// - /// Thrown if an error occurs during the reading of the aseprite file. The exception message will contain the - /// cause of the exception. - /// - public static AsepriteFile ReadFile(string path) - { - if (!File.Exists(path)) - { - throw new FileNotFoundException($"Unable to locate a file at the path '{path}'"); - } - - using Stream stream = File.OpenRead(path); - using BinaryReader reader = new(stream); - - string name = Path.GetFileNameWithoutExtension(path); - return Read(name, reader); - } - - /// - /// Reads the using the provided . - ///
- /// Use this method with to load raw .aseprite files on Android - /// or other platforms. - ///
- /// - /// The name of the Aseprite file. - /// - /// - /// A file stream, preferably instantiated from calling . - /// - /// - /// The created by this method. - /// - /// - /// Thrown if no file is located at the specified path. - /// - /// - /// Thrown if an error occurs during the reading of the aseprite file. The exception message will contain the - /// cause of the exception. - /// - public static AsepriteFile ReadStream(string name, [NotNull] Stream fileStream) - { - using BinaryReader reader = new(fileStream); - return Read(name, reader); - } - - internal static AsepriteFile Read(string name, BinaryReader reader) - { - AsepriteFileBuilder fileBuilder = new(name); - - ReadFileHeader(reader, fileBuilder, out ushort nFrames); - ReadFrames(reader, fileBuilder, nFrames); - - AsepriteFile file = fileBuilder.Build(); - - return file; - } - - private static void ReadFileHeader(BinaryReader reader, AsepriteFileBuilder builder, out ushort nFrames) - { - const uint LAYER_OPACITY_VALID_FLAG = 1; - - IgnoreDword(reader); - ushort magic = ReadWord(reader); - - if (magic != 0xA5E0) - { - throw new InvalidOperationException($"Invalid header magic number (0x{magic:X4})."); - } - - nFrames = ReadWord(reader); - ushort frameWidth = ReadWord(reader); - ushort frameHeight = ReadWord(reader); - - ushort colorDepth = ReadWord(reader); - uint flags = ReadDword(reader); - - bool layerOpacityValid = (flags & LAYER_OPACITY_VALID_FLAG) != 0; - - IgnoreWord(reader); - IgnoreDword(reader); - IgnoreDword(reader); - - byte transparentIndex = ReadByte(reader); - IgnoreBytes(reader, 3); - ushort nColors = ReadWord(reader); - - reader.BaseStream.Position = 128; - - builder.SetFrameWidth(frameWidth); - builder.SetFrameHeight(frameHeight); - builder.SetColorDepth(colorDepth); - builder.SetTransparentIndex(transparentIndex); - builder.SetLayerOpacityValid(layerOpacityValid); - } - - private static void ReadFrames(BinaryReader reader, AsepriteFileBuilder builder, ushort nFrames) - { - for (int frameNum = 0; frameNum < nFrames; frameNum++) - { - IgnoreDword(reader); - ushort magic = ReadWord(reader); - - if (magic != 0xF1FA) - { - throw new InvalidOperationException($"Invalid frame magic in frame number {frameNum}"); - } - - ushort nChunksA = ReadWord(reader); - ushort duration = ReadWord(reader); - IgnoreBytes(reader, 2); - uint nChunksB = ReadDword(reader); - - uint nChunks = nChunksA == 0xFFFF && nChunksA < nChunksB ? - nChunksB : - nChunksA; - - - // Start iterator at -1 so after tags chunk is read, it'll - // increment to 0 to kick off the user data read. - int tagIterator = -1; - ushort lastChunkType = default; - - List cels = new(); - - for (uint chunkNum = 0; chunkNum < nChunks; chunkNum++) - { - lastChunkType = ReadChunk(reader, builder, lastChunkType, tagIterator, cels); - if (lastChunkType == CHUNK_TYPE_TAGS) - { - tagIterator++; - } - } - - builder.AddFrame(duration); - } - - } - - private static ushort ReadChunk(BinaryReader reader, AsepriteFileBuilder builder, ushort lastChunkType, int tagIterator, List cels) - { - long start = reader.BaseStream.Position; - - uint len = ReadDword(reader); - ushort type = ReadWord(reader); - - long end = start + len; - - switch (type) - { - case CHUNK_TYPE_LAYER: - ReadLayerChunk(reader, builder); - break; - case CHUNK_TYPE_CEL: - ReadCelChunk(reader, builder, end); - break; - case CHUNK_TYPE_TAGS: - ReadTagsChunk(reader, builder); - break; - case CHUNK_TYPE_PALETTE: - ReadPaletteChunk(reader, builder); - break; - case CHUNK_TYPE_SLICE: - ReadSliceChunk(reader, builder); - break; - case CHUNK_TYPE_TILESET: - ReadTilesetChunk(reader, builder); - break; - case CHUNK_TYPE_USER_DATA: - ReadUserDataChunk(reader, builder, lastChunkType, tagIterator); - break; - case CHUNK_TYPE_OLD_PALETTE_1: - ReadOldPalette1Chunk(reader, builder); - break; - case CHUNK_TYPE_OLD_PALETTE_2: - case CHUNK_TYPE_CEL_EXTRA: - case CHUNK_TYPE_COLOR_PROFILE: - case CHUNK_TYPE_EXTERNAL_FILES: - case CHUNK_TYPE_MASK: - case CHUNK_TYPE_PATH: - reader.BaseStream.Position = end; - break; - default: - throw new InvalidOperationException($"Unknown chunk type (0x{type:X4})"); - } - - if (type == CHUNK_TYPE_USER_DATA) - { - return lastChunkType; - } - - return type; - } - - private static void ReadLayerChunk(BinaryReader reader, AsepriteFileBuilder builder) - { - const int NORMAL_LAYER_TYPE = 0; - const int GROUP_LAYER_TYPE = 1; - const int TILEMAP_LAYER_TYPE = 2; - - ushort flagsValue = ReadWord(reader); - ushort type = ReadWord(reader); - IgnoreWord(reader); - IgnoreWord(reader); - IgnoreWord(reader); - ushort blend = ReadWord(reader); - byte opacity = ReadByte(reader); - IgnoreBytes(reader, 3); - string name = ReadString(reader); - - AsepriteLayerFlags flags = (AsepriteLayerFlags)flagsValue; - - switch (type) - { - case NORMAL_LAYER_TYPE: - case GROUP_LAYER_TYPE: - builder.AddLayer(flags, blend, opacity, name); - break; - case TILEMAP_LAYER_TYPE: - ReadTilemapLayerChunk(reader, builder, flags, blend, opacity, name); - break; - default: - throw new InvalidOperationException($"Unknown layer type '{type}'"); - } - } - - private static void ReadTilemapLayerChunk(BinaryReader reader, AsepriteFileBuilder builder, AsepriteLayerFlags flags, ushort blend, byte opacity, string name) - { - uint index = ReadDword(reader); - builder.AddTilemapLayer(index, flags, blend, opacity, name); - } - - private static void ReadCelChunk(BinaryReader reader, AsepriteFileBuilder builder, long chunkEnd) - { - const ushort RAW_IMAGE_TYPE = 0; - const ushort LINKED_CEL_TYPE = 1; - const ushort COMPRESSED_IMAGE_TYPE = 2; - const ushort COMPRESSED_TILEMAP_TYPE = 3; - - ushort layerIndex = ReadWord(reader); - short x = ReadShort(reader); - short y = ReadShort(reader); - byte opacity = ReadByte(reader); - ushort type = ReadWord(reader); - IgnoreBytes(reader, 7); - - Point position = new(x, y); - - switch (type) - { - case RAW_IMAGE_TYPE: - ReadRawImageCel(reader, builder, x, y, layerIndex, opacity, chunkEnd); - break; - case LINKED_CEL_TYPE: - ReadLinkedCel(reader, builder); - break; - case COMPRESSED_IMAGE_TYPE: - ReadCompressedImageCel(reader, builder, x, y, layerIndex, opacity, chunkEnd); - break; - case COMPRESSED_TILEMAP_TYPE: - ReadCompressedTilemapCel(reader, builder, x, y, layerIndex, opacity, chunkEnd); - break; - default: - throw new InvalidOperationException($"Unknown cel type '{type}'"); - } - } - - private static void ReadRawImageCel(BinaryReader reader, AsepriteFileBuilder builder, short x, short y, ushort layerIndex, byte opacity, long chunkEnd) - { - ushort width = ReadWord(reader); - ushort height = ReadWord(reader); - - int len = (int)(chunkEnd - reader.BaseStream.Position); - byte[] data = ReadBytes(reader, len); - - builder.AddRawImageCel(x, y, width, height, layerIndex, opacity, data); - } - - private static void ReadLinkedCel(BinaryReader reader, AsepriteFileBuilder builder) - { - ushort frameIndex = ReadWord(reader); - builder.AddLinkedCel(frameIndex); - } - - private static void ReadCompressedImageCel(BinaryReader reader, AsepriteFileBuilder builder, short x, short y, ushort layerIndex, byte opacity, long chunkEnd) - { - ushort width = ReadWord(reader); - ushort height = ReadWord(reader); - - int len = (int)(chunkEnd - reader.BaseStream.Position); - byte[] compressedData = ReadBytes(reader, len); - builder.AddCompressedImageCel(x, y, width, height, layerIndex, opacity, compressedData); - } - - private static void ReadCompressedTilemapCel(BinaryReader reader, AsepriteFileBuilder builder, short x, short y, ushort layerIndex, byte opacity, long chunkEnd) - { - ushort columns = ReadWord(reader); - ushort rows = ReadWord(reader); - ushort bitsPerTile = ReadWord(reader); - uint idBitmask = ReadDword(reader); - uint xFlipBitmask = ReadDword(reader); - uint yFlipBitmask = ReadDword(reader); - uint dFlipBitmask = ReadDword(reader); - IgnoreBytes(reader, 10); - - int len = (int)(chunkEnd - reader.BaseStream.Position); - byte[] compressedData = ReadBytes(reader, len); - builder.AddCompressedTilemapCel(x, y, columns, rows, layerIndex, opacity, compressedData, bitsPerTile, idBitmask, xFlipBitmask, yFlipBitmask, dFlipBitmask); - } - - private static void ReadTagsChunk(BinaryReader reader, AsepriteFileBuilder builder) - { - ushort count = ReadWord(reader); - IgnoreBytes(reader, 8); - - for (int tagNum = 0; tagNum < count; tagNum++) - { - ushort from = ReadWord(reader); - ushort to = ReadWord(reader); - byte direction = ReadByte(reader); - ushort repeat = ReadWord(reader); - IgnoreBytes(reader, 6); - ReadOnlySpan rgb = ReadBytes(reader, 3); - IgnoreByte(reader); - string name = ReadString(reader); - - builder.AddTag(from, to, direction, repeat, rgb, name); - } - } - - private static void ReadOldPalette1Chunk(BinaryReader reader, AsepriteFileBuilder builder) - { - ushort packets = ReadWord(reader); - int skip = 0; - int size = 0; - Span rgb = stackalloc byte[4]; - - for(int i = 0; i < packets; i++) - { - skip += ReadByte(reader); - size = ReadByte(reader); - - if(size == 0) - { - size = 256; - } - - builder.ResizePalette((uint)size); - - for(int c = skip; c < skip + size; c++) - { - rgb.Clear(); - rgb[0] = ReadByte(reader); - rgb[1] = ReadByte(reader); - rgb[2] = ReadByte(reader); - rgb[3] = 255; - builder.AddPaletteEntry((uint)c, rgb); - } - } - } - - private static void ReadPaletteChunk(BinaryReader reader, AsepriteFileBuilder builder) - { - const ushort HAS_NAME_FLAG = 1; - - uint newSize = ReadDword(reader); - uint from = ReadDword(reader); - uint to = ReadDword(reader); - IgnoreBytes(reader, 8); - - builder.ResizePalette(newSize); - - - for (uint entry = from; entry <= to; entry++) - { - ushort flags = ReadWord(reader); - ReadOnlySpan rgba = ReadBytes(reader, 4); - - if ((flags & HAS_NAME_FLAG) != 0) - { - IgnoreString(reader); - } - - builder.AddPaletteEntry(entry, rgba); - } - } - - private static void ReadSliceChunk(BinaryReader reader, AsepriteFileBuilder builder) - { - const uint NINE_PATCH_FLAG = 1; - const uint HAS_PIVOT_FLAG = 2; - - uint count = ReadDword(reader); - uint flags = ReadDword(reader); - IgnoreDword(reader); - string name = ReadString(reader); - - bool isNinePatch = (flags & NINE_PATCH_FLAG) != 0; - bool hasPivot = (flags & HAS_PIVOT_FLAG) != 0; - - AsepriteSliceKey[] keys = new AsepriteSliceKey[count]; - - for (uint keyNum = 0; keyNum < count; keyNum++) - { - uint start = ReadDword(reader); - int x = ReadLong(reader); - int y = ReadLong(reader); - uint width = ReadDword(reader); - uint height = ReadDword(reader); - - Rectangle bounds = new(x, y, (int)width, (int)height); - Rectangle? center = default; - Point? pivot = default; - - if (isNinePatch) - { - int cx = ReadLong(reader); - int cy = ReadLong(reader); - uint cw = ReadDword(reader); - uint ch = ReadDword(reader); - - center = new(cx, cy, (int)cw, (int)ch); - } - - if (hasPivot) - { - int px = ReadLong(reader); - int py = ReadLong(reader); - - pivot = new(px, py); - } - - AsepriteSliceKey key = new((int)start, bounds, center, pivot); - keys[keyNum] = key; - } - - builder.AddSlice(name, isNinePatch, hasPivot, keys); - } - - private static void ReadTilesetChunk(BinaryReader reader, AsepriteFileBuilder builder) - { - const uint EXTERNAL_FILE_FLAG = 1; - const uint EMBEDDED_FLAG = 2; - - uint id = ReadDword(reader); - uint flags = ReadDword(reader); - uint count = ReadDword(reader); - ushort tileWidth = ReadWord(reader); - ushort tileHeight = ReadWord(reader); - IgnoreShort(reader); - IgnoreBytes(reader, 14); - string name = ReadString(reader); - - if ((flags & EXTERNAL_FILE_FLAG) != 0) - { - throw new InvalidOperationException($"Tileset '{name}' includes tileset in external file. This is not supported at this time"); - } - - if ((flags & EMBEDDED_FLAG) == 0) - { - throw new InvalidOperationException($"Tileset '{name}' does not include tileset image in file"); - } - - uint len = ReadDword(reader); - byte[] compressedData = ReadBytes(reader, (int)len); - - builder.AddTileset(id, count, tileWidth, tileHeight, name, compressedData); - } - - private static void ReadUserDataChunk(BinaryReader reader, AsepriteFileBuilder builder, ushort lastChunkType, int tagIterator) - { - const uint HAS_TEXT_FLAG = 1; - const uint HAS_COLOR_FLAG = 2; - uint flags = ReadDword(reader); - - string? text = default; - Color? color = default; - - if ((flags & HAS_TEXT_FLAG) != 0) - { - text = ReadString(reader); - } - - if ((flags & HAS_COLOR_FLAG) != 0) - { - ReadOnlySpan rgba = ReadBytes(reader, 4); - color = new Color(rgba[0], rgba[1], rgba[2], rgba[3]); - } - - switch (lastChunkType) - { - case CHUNK_TYPE_CEL: - builder.SetLastCelUserData(text, color); - break; - case CHUNK_TYPE_LAYER: - builder.SetLastLayerUserData(text, color); - break; - case CHUNK_TYPE_SLICE: - builder.SetLastSliceUserData(text, color); - break; - case CHUNK_TYPE_TAGS: - builder.SetTagUserData(tagIterator, text, color); - break; - case CHUNK_TYPE_OLD_PALETTE_1: - // Starting in Aseprite 1.3-beta21, after the first palette chunk in the first frame, if user data is - // detected, then that is user data for the "sprite" itself - builder.SetSpriteUserData(text, color); - break; - case CHUNK_TYPE_TILESET: - // Starting in Aseprite 1.3-rc1, Tilesets can have user data, though it appears it's not settable in - // the Aseprite UI, and only settable through the LUA Scripting API within Aseprite. Regardless, - // we have to handle it - builder.SetTilesetUserData(text, color); - break; - default: - throw new InvalidOperationException($"Invalid chunk type (0x{lastChunkType:X4}) for user data"); - } - } - - private static byte ReadByte(BinaryReader reader) => reader.ReadByte(); - private static byte[] ReadBytes(BinaryReader reader, int len) => reader.ReadBytes(len); - private static ushort ReadWord(BinaryReader reader) => reader.ReadUInt16(); - private static short ReadShort(BinaryReader reader) => reader.ReadInt16(); - private static uint ReadDword(BinaryReader reader) => reader.ReadUInt32(); - private static int ReadLong(BinaryReader reader) => reader.ReadInt32(); - private static string ReadString(BinaryReader reader) => Encoding.UTF8.GetString(ReadBytes(reader, ReadWord(reader))); - - private static void IgnoreBytes(BinaryReader reader, int len) => reader.BaseStream.Position += len; - private static void IgnoreByte(BinaryReader reader) => IgnoreBytes(reader, 1); - private static void IgnoreWord(BinaryReader reader) => IgnoreBytes(reader, 2); - private static void IgnoreShort(BinaryReader reader) => IgnoreBytes(reader, 2); - private static void IgnoreDword(BinaryReader reader) => IgnoreBytes(reader, 4); - private static void IgnoreLong(BinaryReader reader) => IgnoreBytes(reader, 4); - private static void IgnoreString(BinaryReader reader) => IgnoreBytes(reader, ReadWord(reader)); -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Readers/RawAnimatedTilemapReader.cs b/source/MonoGame.Aseprite.Shared/Content/Readers/RawAnimatedTilemapReader.cs deleted file mode 100644 index 487f196a..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Readers/RawAnimatedTilemapReader.cs +++ /dev/null @@ -1,84 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Readers; - -/// -/// Defines a reader that reads a from a file. -/// -public static class RawAnimatedTilemapReader -{ - /// - /// Reads the from the file at the specified path. - /// - /// - /// The path and name of the file that contains the to read. - /// - /// - /// The that was read. - /// - public static RawAnimatedTilemap Read(string path) - { - using Stream stream = File.OpenRead(path); - using BinaryReader reader = new(stream); - return Read(reader); - } - - internal static RawAnimatedTilemap Read(BinaryReader reader) - { - reader.ReadMagic(); - string name = reader.ReadString(); - int tilesetCount = reader.ReadInt32(); - - RawTileset[] tilesets = new RawTileset[tilesetCount]; - - for (int i = 0; i < tilesetCount; i++) - { - tilesets[i] = reader.ReadRawTileset(); - } - - int frameCount = reader.ReadInt32(); - - RawTilemapFrame[] frames = new RawTilemapFrame[frameCount]; - - for (int i = 0; i < frameCount; i++) - { - int duration = reader.ReadInt32(); - int layerCount = reader.ReadInt32(); - - RawTilemapLayer[] layers = new RawTilemapLayer[layerCount]; - - for (int j = 0; j < layerCount; j++) - { - layers[j] = reader.ReadRawTilemapLayer(); - } - - frames[i] = new(duration, layers); - } - - return new(name, tilesets, frames); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Readers/RawSpriteReader.cs b/source/MonoGame.Aseprite.Shared/Content/Readers/RawSpriteReader.cs deleted file mode 100644 index 87fba6c1..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Readers/RawSpriteReader.cs +++ /dev/null @@ -1,66 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Readers; - -/// -/// Defines a reader that reads a from a file. -/// -public static class RawSpriteReader -{ - /// - /// Reads the from the file at the specified path. - /// - /// - /// The path and name of the file that contains the to read. - /// - /// - /// The that was read. - /// - public static RawSprite Read(string path) - { - using Stream stream = File.OpenRead(path); - using BinaryReader reader = new(stream); - return Read(reader); - } - - internal static RawSprite Read(BinaryReader reader) - { - reader.ReadMagic(); - - string name = reader.ReadString(); - RawTexture rawTexture = reader.ReadRawTexture(); - int count = reader.ReadInt32(); - RawSlice[] slices = new RawSlice[count]; - - for (int i = 0; i < count; i++) - { - slices[i] = reader.ReadRawSlice(); - } - - return new(name, rawTexture, slices); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Readers/RawSpriteSheetReader.cs b/source/MonoGame.Aseprite.Shared/Content/Readers/RawSpriteSheetReader.cs deleted file mode 100644 index 4e7a9588..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Readers/RawSpriteSheetReader.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Readers; - -/// -/// Defines a reader that reads a from a file. -/// -public static class RawSpriteSheetReader -{ - /// - /// Reads the from the file at the specified path. - /// - /// - /// The path and name of the file that contains the to read. - /// - /// - /// The that was read. - /// - public static RawSpriteSheet Read(string path) - { - using Stream stream = File.OpenRead(path); - using BinaryReader reader = new(stream); - return Read(reader); - } - - internal static RawSpriteSheet Read(BinaryReader reader) - { - reader.ReadMagic(); - string name = reader.ReadString(); - RawTextureAtlas atlas = reader.ReadRawTextureAtlas(); - int tagCount = reader.ReadInt32(); - - RawAnimationTag[] tags = new RawAnimationTag[tagCount]; - - for (int i = 0; i < tagCount; i++) - { - string tagName = reader.ReadString(); - int loopCount = reader.ReadInt32(); - bool isReversed = reader.ReadBoolean(); - bool isPingPong = reader.ReadBoolean(); - int frameCount = reader.ReadInt32(); - - RawAnimationFrame[] frames = new RawAnimationFrame[frameCount]; - - for (int j = 0; j < frameCount; j++) - { - int index = reader.ReadInt32(); - int duration = reader.ReadInt32(); - frames[j] = new(index, duration); - } - - tags[i] = new(tagName, frames, loopCount, isReversed, isPingPong); - } - - return new(name, atlas, tags); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Readers/RawTextureAtlasReader.cs b/source/MonoGame.Aseprite.Shared/Content/Readers/RawTextureAtlasReader.cs deleted file mode 100644 index 2860a9dc..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Readers/RawTextureAtlasReader.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Readers; - -/// -/// Defines a reader that reads a from a file. -/// -public static class RawTextureAtlasReader -{ - /// - /// Reads the from the file at the specified path. - /// - /// - /// The path and name of the file that contains the to read. - /// - /// - /// The that was read. - /// - public static RawTextureAtlas Read(string path) - { - using Stream stream = File.OpenRead(path); - using BinaryReader reader = new(stream); - return Read(reader); - } - - internal static RawTextureAtlas Read(BinaryReader reader) - { - reader.ReadMagic(); - return reader.ReadRawTextureAtlas(); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Readers/RawTilemapReader.cs b/source/MonoGame.Aseprite.Shared/Content/Readers/RawTilemapReader.cs deleted file mode 100644 index 0fec02d2..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Readers/RawTilemapReader.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Readers; - -/// -/// Defines a reader that reads a from a file. -/// -public static class RawTilemapReader -{ - /// - /// Reads the from the file at the specified path. - /// - /// - /// The path and name of the file that contains the to read. - /// - /// - /// The that was read. - /// - public static RawTilemap Read(string path) - { - using Stream stream = File.OpenRead(path); - using BinaryReader reader = new(stream); - return Read(reader); - } - - internal static RawTilemap Read(BinaryReader reader) - { - reader.ReadMagic(); - string name = reader.ReadString(); - int tilesetCount = reader.ReadInt32(); - - RawTileset[] tilesets = new RawTileset[tilesetCount]; - - for (int i = 0; i < tilesetCount; i++) - { - tilesets[i] = reader.ReadRawTileset(); - } - - int layerCount = reader.ReadInt32(); - - RawTilemapLayer[] layers = new RawTilemapLayer[layerCount]; - - for (int i = 0; i < layerCount; i++) - { - layers[i] = reader.ReadRawTilemapLayer(); - } - - return new(name, layers, tilesets); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Readers/RawTilesetReader.cs b/source/MonoGame.Aseprite.Shared/Content/Readers/RawTilesetReader.cs deleted file mode 100644 index ec7f1e37..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Readers/RawTilesetReader.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Readers; - -/// -/// Defines a reader that reads a from a file. -/// -public static class RawTilesetReader -{ - /// - /// Reads the from the file at the specified path. - /// - /// - /// The path and name of the file that contains the to read. - /// - /// - /// The that was read. - /// - public static RawTileset Read(string path) - { - using Stream stream = File.OpenRead(path); - using BinaryReader reader = new(stream); - return Read(reader); - } - - internal static RawTileset Read(BinaryReader reader) - { - reader.ReadMagic(); - return reader.ReadRawTileset(); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Writers/RawAnimatedTilemapWriter.cs b/source/MonoGame.Aseprite.Shared/Content/Writers/RawAnimatedTilemapWriter.cs deleted file mode 100644 index 7582fc6d..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Writers/RawAnimatedTilemapWriter.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Writers; - -/// -/// Defines a writer that writes the contents of an to a file. -/// -public static class RawAnimatedTilemapWriter -{ - /// - /// Writes the contents of the given to the file at the path specified. - /// - /// - /// The path and name of the file to write the contents of the to. If no - /// file exists at this path, one will be created. If a file already exists, it will be overwritten. - /// - /// The to write. - public static void Write(string path, RawAnimatedTilemap rawAnimatedTilemap) - { - using Stream stream = File.Create(path); - using BinaryWriter writer = new(stream); - Write(writer, rawAnimatedTilemap); - } - - internal static void Write(BinaryWriter writer, RawAnimatedTilemap rawAnimatedTilemap) - { - writer.WriteMagic(); - writer.Write(rawAnimatedTilemap.Name); - writer.Write(rawAnimatedTilemap.RawTilesets.Length); - - for (int i = 0; i < rawAnimatedTilemap.RawTilesets.Length; i++) - { - writer.Write(rawAnimatedTilemap.RawTilesets[i]); - } - - writer.Write(rawAnimatedTilemap.RawTilemapFrames.Length); - - for (int i = 0; i < rawAnimatedTilemap.RawTilemapFrames.Length; i++) - { - RawTilemapFrame rawTilemapFrame = rawAnimatedTilemap.RawTilemapFrames[i]; - writer.Write(rawTilemapFrame.DurationInMilliseconds); - writer.Write(rawTilemapFrame.RawTilemapLayers.Length); - - for (int j = 0; j < rawTilemapFrame.RawTilemapLayers.Length; j++) - { - writer.Write(rawTilemapFrame.RawTilemapLayers[j]); - } - } - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Writers/RawSpriteSheetWriter.cs b/source/MonoGame.Aseprite.Shared/Content/Writers/RawSpriteSheetWriter.cs deleted file mode 100644 index c635d21b..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Writers/RawSpriteSheetWriter.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Writers; - -/// -/// Defines a writer that writes the contents of a to a file. -/// -public static class RawSpriteSheetWriter -{ - /// - /// Writes the contents of the given to the file at the path specified. - /// - /// - /// The path and name of the file to write the contents of the to. If no file - /// exists at this path, one will be created. If a file already exists, it will be overwritten. - /// - /// The to write. - public static void Write(string path, RawSpriteSheet rawSpriteSheet) - { - using Stream stream = File.Create(path); - using BinaryWriter writer = new(stream); - Write(writer, rawSpriteSheet); - } - - internal static void Write(BinaryWriter writer, RawSpriteSheet rawSpriteSheet) - { - writer.WriteMagic(); - writer.Write(rawSpriteSheet.Name); - writer.Write(rawSpriteSheet.RawTextureAtlas); - writer.Write(rawSpriteSheet.RawAnimationTags.Length); - - for (int i = 0; i < rawSpriteSheet.RawAnimationTags.Length; i++) - { - RawAnimationTag rawAnimationTag = rawSpriteSheet.RawAnimationTags[i]; - - writer.Write(rawAnimationTag.Name); - writer.Write(rawAnimationTag.LoopCount); - writer.Write(rawAnimationTag.IsReversed); - writer.Write(rawAnimationTag.IsPingPong); - writer.Write(rawAnimationTag.RawAnimationFrames.Length); - - for (int j = 0; j < rawAnimationTag.RawAnimationFrames.Length; j++) - { - writer.Write(rawAnimationTag.RawAnimationFrames[j].FrameIndex); - writer.Write(rawAnimationTag.RawAnimationFrames[j].DurationInMilliseconds); - } - } - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Writers/RawSpriteWriter.cs b/source/MonoGame.Aseprite.Shared/Content/Writers/RawSpriteWriter.cs deleted file mode 100644 index 22c285e2..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Writers/RawSpriteWriter.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Writers; - -/// -/// Defines a writer that writes the contents of a to a file. -/// -public static class RawSpriteWriter -{ - /// - /// Writes the contents of the given to the file at the path specified. - /// - /// - /// The path and name of the file to write the contents of the to. If no file exists at - /// this path, one will be created. If a file already exists, it will be overwritten. - /// - /// The to write. - public static void Write(string path, RawSprite rawSprite) - { - using Stream stream = File.Create(path); - using BinaryWriter writer = new(stream); - Write(writer, rawSprite); - } - - internal static void Write(BinaryWriter writer, RawSprite rawSprite) - { - writer.WriteMagic(); - writer.Write(rawSprite.Name); - writer.Write(rawSprite.RawTexture); - writer.Write(rawSprite.Slices.Length); - - for (int i = 0; i < rawSprite.Slices.Length; i++) - { - writer.Write(rawSprite.Slices[i]); - } - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Writers/RawTextureAtlasWriter.cs b/source/MonoGame.Aseprite.Shared/Content/Writers/RawTextureAtlasWriter.cs deleted file mode 100644 index ea7382e7..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Writers/RawTextureAtlasWriter.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Writers; - -/// -/// Defines a writer that writes the contents of a to a file. -/// -public static class RawTextureAtlasWriter -{ - /// - /// Writes the contents of the given to the file at the path specified. - /// - /// - /// The path and name of the file to write the contents of the to. If no file - /// exists at this path, one will be created. If a file already exists, it will be overwritten. - /// - /// The to write. - public static void Write(string path, RawTextureAtlas rawTextureAtlas) - { - using Stream stream = File.Create(path); - using BinaryWriter writer = new(stream); - Write(writer, rawTextureAtlas); - } - - internal static void Write(BinaryWriter writer, RawTextureAtlas rawTextureAtlas) - { - writer.WriteMagic(); - writer.Write(rawTextureAtlas); - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Writers/RawTilemapWriter.cs b/source/MonoGame.Aseprite.Shared/Content/Writers/RawTilemapWriter.cs deleted file mode 100644 index eea84aa2..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Writers/RawTilemapWriter.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Writers; - -/// -/// Defines a writer that writes the contents of a to a file. -/// -public static class RawTilemapWriter -{ - /// - /// Writes the contents of the given to the file at the path specified. - /// - /// - /// The path and name of the file to write the contents of the to. If no file exists - /// at this path, one will be created. If a file already exists, it will be overwritten. - /// - /// The to write. - public static void Write(string path, RawTilemap rawTilemap) - { - using Stream stream = File.Create(path); - using BinaryWriter writer = new(stream); - Write(writer, rawTilemap); - } - - internal static void Write(BinaryWriter writer, RawTilemap rawTilemap) - { - writer.WriteMagic(); - writer.Write(rawTilemap.Name); - writer.Write(rawTilemap.RawTilesets.Length); - - for (int i = 0; i < rawTilemap.RawTilesets.Length; i++) - { - writer.Write(rawTilemap.RawTilesets[i]); - } - - writer.Write(rawTilemap.RawLayers.Length); - - for (int i = 0; i < rawTilemap.RawLayers.Length; i++) - { - writer.Write(rawTilemap.RawLayers[i]); - } - } -} diff --git a/source/MonoGame.Aseprite.Shared/Content/Writers/RawTilesetWriter.cs b/source/MonoGame.Aseprite.Shared/Content/Writers/RawTilesetWriter.cs deleted file mode 100644 index 26951a54..00000000 --- a/source/MonoGame.Aseprite.Shared/Content/Writers/RawTilesetWriter.cs +++ /dev/null @@ -1,54 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Content.Writers; - -/// -/// Defines a writer that writes the contents of a to a file. -/// -public static class RawTilesetWriter -{ - /// - /// Writes the contents of the given to the file at the path specified. - /// - /// - /// The path and name of the file to write the contents of the to. If no file exists - /// at this path, one will be created. If a file already exists, it will be overwritten. - /// - /// The to write. - public static void Write(string path, RawTileset rawTileset) - { - using Stream stream = File.Create(path); - using BinaryWriter writer = new(stream); - Write(writer, rawTileset); - } - - internal static void Write(BinaryWriter writer, RawTileset rawTileset) - { - writer.WriteMagic(); - writer.Write(rawTileset); - } -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimatedTilemap.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimatedTilemap.cs deleted file mode 100644 index 3d098188..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimatedTilemap.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines the raw data for an animated tilemap. -/// -public sealed class RawAnimatedTilemap : IEquatable -{ - private readonly RawTileset[] _rawTilesets; - private readonly RawTilemapFrame[] _rawTilemapFrames; - - /// - /// Gets the name assigned to the animated tilemap. - /// - public string Name { get; } - - /// - /// Gets a read-only span of the data for the tilesets used by the layers of the - /// animated tilemap. - /// - public ReadOnlySpan RawTilesets => _rawTilesets; - - /// - /// Gets a read-only span of the data for animated tilemap. - /// - public ReadOnlySpan RawTilemapFrames => _rawTilemapFrames; - - internal RawAnimatedTilemap(string name, RawTileset[] rawTilesets, RawTilemapFrame[] rawTilemapFrames) => - (Name, _rawTilesets, _rawTilemapFrames) = (name, rawTilesets, rawTilemapFrames); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawAnimatedTilemap? other) => other is not null - && Name == other.Name - && RawTilesets.SequenceEqual(other.RawTilesets); -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimationFrame.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimationFrame.cs deleted file mode 100644 index 900856f1..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimationFrame.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of an animation frame. -/// -public sealed class RawAnimationFrame : IEquatable -{ - /// - /// Gets the index of the source frame for the animation frame. - /// - public int FrameIndex { get; } - - /// - /// Gets the duration, in milliseconds, of the animation frame. - /// - public int DurationInMilliseconds { get; } - - internal RawAnimationFrame(int frameIndex, int durationInMilliseconds) => - (FrameIndex, DurationInMilliseconds) = (frameIndex, durationInMilliseconds); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawAnimationFrame? other) => other is not null - && FrameIndex == other.FrameIndex - && DurationInMilliseconds == other.DurationInMilliseconds; -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimationTag.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimationTag.cs deleted file mode 100644 index 7994895b..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawAnimationTag.cs +++ /dev/null @@ -1,89 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of an animation tag. -/// -public sealed class RawAnimationTag : IEquatable -{ - private RawAnimationFrame[] _rawAnimationFrames; - - /// - /// Gets the name assigned to the animation tag. - /// - public string Name { get; } - - /// - /// Gets a read-only span of the elements that represent the frames of animation - /// for the animation tag. - /// - public ReadOnlySpan RawAnimationFrames => _rawAnimationFrames; - - /// - /// Gets a value that indicates the total number of loops/cycles of this animation that should play. - /// - /// - /// - /// 0 = infinite looping - /// - /// - /// If the animation is ping-pong, each direction of the ping-pong will count as a loop. - /// - /// - public int LoopCount { get; } - - /// - /// Gets a value that indicates whether the animation defined by the animation tag should play in reverse. - /// - public bool IsReversed { get; } - - /// - /// Gets a value that indicates whether the animation defined by the animation tag should ping-pong once - /// reaching the last frame of animation. - /// - public bool IsPingPong { get; } - - internal RawAnimationTag(string name, RawAnimationFrame[] rawAnimationFrames, int loopCount, bool isReversed, bool isPingPong) => - (Name, _rawAnimationFrames, LoopCount, IsReversed, IsPingPong) = (name, rawAnimationFrames, loopCount, isReversed, isPingPong); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawAnimationTag? other) => other is not null - && Name == other.Name - && RawAnimationFrames.SequenceEqual(other.RawAnimationFrames) - && LoopCount == other.LoopCount - && IsReversed == other.IsReversed - && IsPingPong == other.IsPingPong; -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawNinePatchSlice.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawNinePatchSlice.cs deleted file mode 100644 index 4205e266..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawNinePatchSlice.cs +++ /dev/null @@ -1,60 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a nine-patch slice. -/// -public sealed class RawNinePatchSlice : RawSlice, IEquatable -{ - - /// - /// Gets the rectangular bounds of the center of the nine-patch slice. - /// - public Rectangle CenterBounds { get; } - - internal RawNinePatchSlice(string name, Rectangle bounds, Rectangle centerBounds, Vector2 origin, Color color) - : base(name, bounds, origin, color) => CenterBounds = centerBounds; - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawNinePatchSlice? other) => other is not null - && CenterBounds == other.CenterBounds - && Name == other.Name - && Bounds == other.Bounds - && Origin == other.Origin - && Color == other.Color; -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawSlice.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawSlice.cs deleted file mode 100644 index 89e65686..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawSlice.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a slice. -/// -public class RawSlice : IEquatable -{ - /// - /// Gets the name assigned to the slice. - /// - public string Name { get; } - - /// - /// Gets the rectangular bounds of the slice. - /// - public Rectangle Bounds { get; } - - /// - /// Gets the x- and y-coordinate point of the slice. - /// - public Vector2 Origin { get; } - - /// - /// Gets the color of the slice. - /// - public Color Color { get; } - - internal RawSlice(string name, Rectangle bounds, Vector2 origin, Color color) => - (Name, Bounds, Origin, Color) = (name, bounds, origin, color); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawSlice? other) => other is not null - && Name == other.Name - && Bounds == other.Bounds - && Origin == other.Origin - && Color == other.Color; -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawSprite.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawSprite.cs deleted file mode 100644 index 62472652..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawSprite.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a sprite. -/// -public sealed class RawSprite : IEquatable -{ - private RawSlice[] _slices; - - /// - /// Gets the name assigned to the sprite. - /// - public string Name { get; } - - /// - /// Gets the raw texture that represents the source texture for the sprite. - /// - public RawTexture RawTexture { get; } - - /// - /// Gets a read-only span of the raw slice values the texture region that will be generated for the sprite. - /// - public ReadOnlySpan Slices => _slices; - - internal RawSprite(string name, RawTexture rawTexture, RawSlice[] slices) => - (Name, RawTexture, _slices) = (name, rawTexture, slices); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawSprite? other) => other is not null - && Name == other.Name - && RawTexture.Equals(other.RawTexture) - && Slices.SequenceEqual(other.Slices); -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawSpriteSheet.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawSpriteSheet.cs deleted file mode 100644 index b3678fd8..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawSpriteSheet.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a spritesheet. -/// -public sealed class RawSpriteSheet : IEquatable -{ - private RawAnimationTag[] _rawAnimationTags; - - /// - /// Gets the name assigned to the spritesheet. - /// - public string Name { get; } - - /// - /// Gets raw texture atlas that represents the source texture atlas for the spritesheet. - /// - public RawTextureAtlas RawTextureAtlas { get; } - - /// - /// Gets a read-only span of the raw animation tags that represent the animations tags for the spritesheet. - /// - public ReadOnlySpan RawAnimationTags => _rawAnimationTags; - - internal RawSpriteSheet(string name, RawTextureAtlas rawAtlas, RawAnimationTag[] rawAnimationTags) => - (Name, RawTextureAtlas, _rawAnimationTags) = (name, rawAtlas, rawAnimationTags); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawSpriteSheet? other) => other is not null - && Name == other.Name - && RawTextureAtlas.Equals(other.RawTextureAtlas) - && RawAnimationTags.SequenceEqual(other.RawAnimationTags); -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTexture.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTexture.cs deleted file mode 100644 index faf46866..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTexture.cs +++ /dev/null @@ -1,75 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a texture. -/// -public sealed class RawTexture : IEquatable -{ - private Color[] _pixels; - - /// - /// Get the name assigned to the texture. - /// - public string Name { get; } - - /// - /// Gets a read-only span of the color values that represent the pixel data for the texture. - /// - public ReadOnlySpan Pixels => _pixels; - - /// - /// Gets the width, in pixels of the texture. - /// - public int Width { get; } - - /// - /// Gets the height, in pixels of the texture. - /// - public int Height { get; } - - internal RawTexture(string name, Color[] pixels, int width, int height) => - (Name, _pixels, Width, Height) = (name, pixels, width, height); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawTexture? other) => other is not null - && Name == other.Name - && Pixels.SequenceEqual(other.Pixels) - && Width == other.Width - && Height == other.Height; -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTextureAtlas.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTextureAtlas.cs deleted file mode 100644 index e78205b7..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTextureAtlas.cs +++ /dev/null @@ -1,67 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a texture atlas. -/// -public sealed class RawTextureAtlas : IEquatable -{ - private RawTextureRegion[] _rawTextureRegions; - - /// - /// Gets the name assigned to the texture atlas. - /// - public string Name { get; } - - /// - /// Gets the raw texture that represents the source texture of the texture atlas. - /// - public RawTexture RawTexture { get; } - - /// - /// Gets a read-only span of the raw texture regions that represent the texture regions for the texture atlas. - /// - public ReadOnlySpan RawTextureRegions => _rawTextureRegions; - - internal RawTextureAtlas(string name, RawTexture rawTexture, RawTextureRegion[] rawRegions) => - (Name, RawTexture, _rawTextureRegions) = (name, rawTexture, rawRegions); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawTextureAtlas? other) => other is not null - && Name == other.Name - && RawTexture.Equals(other.RawTexture) - && RawTextureRegions.SequenceEqual(other.RawTextureRegions); -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTextureRegion.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTextureRegion.cs deleted file mode 100644 index 2c36e13c..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTextureRegion.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a texture region. -/// -public sealed class RawTextureRegion : IEquatable -{ - private RawSlice[] _slices; - - /// - /// Gets the name assigned to the texture region. - /// - public string Name { get; } - - /// - /// Gets the rectangular bounds of the texture region. - /// - public Rectangle Bounds { get; } - - /// - /// Gets a read-only span of the slices for the texture region. - /// - public ReadOnlySpan Slices => _slices; - - internal RawTextureRegion(string name, Rectangle bounds, RawSlice[] slices) => - (Name, Bounds, _slices) = (name, bounds, slices); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawTextureRegion? other) => other is not null - && Name == other.Name - && Bounds == other.Bounds - && Slices.SequenceEqual(other.Slices); -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemap.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemap.cs deleted file mode 100644 index 9f840ae8..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemap.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a tilemap. -/// -public sealed class RawTilemap : IEquatable -{ - private RawTileset[] _rawTilesets; - private RawTilemapLayer[] _rawLayers; - - /// - /// Gets the name assigned to the tilemap. - /// - public string Name { get; } - - /// - /// Gets a read-only span of the elements that represent the tilesets used by the - /// tilemap layers in the tilemap. - /// - public ReadOnlySpan RawTilesets => _rawTilesets; - - /// - /// Gets a read-only span of the that represent the tilemap layers for the - /// tilemap. - /// - public ReadOnlySpan RawLayers => _rawLayers; - - internal RawTilemap(string name, RawTilemapLayer[] rawLayers, RawTileset[] rawTilesets) => - (Name, _rawTilesets, _rawLayers) = (name, rawTilesets, rawLayers); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawTilemap? other) => other is not null - && Name == other.Name - && RawTilesets.SequenceEqual(other.RawTilesets) - && RawLayers.SequenceEqual(other.RawLayers); -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapFrame.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapFrame.cs deleted file mode 100644 index d1f6d3f7..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapFrame.cs +++ /dev/null @@ -1,62 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a tilemap frame. -/// -public sealed class RawTilemapFrame : IEquatable -{ - private RawTilemapLayer[] _rawTilemapLayers; - - /// - /// Gets the duration, in milliseconds, of the tilemap frame. - /// - public int DurationInMilliseconds { get; } - - /// - /// Gets a read-only span of the that represent the tilemap layers for the - /// tilemap frame. - /// - public ReadOnlySpan RawTilemapLayers => _rawTilemapLayers; - - internal RawTilemapFrame(int durationInMilliseconds, RawTilemapLayer[] rawLayers) => - (DurationInMilliseconds, _rawTilemapLayers) = (durationInMilliseconds, rawLayers); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawTilemapFrame? other) => other is not null - && DurationInMilliseconds == other.DurationInMilliseconds - && RawTilemapLayers.SequenceEqual(other.RawTilemapLayers); -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapLayer.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapLayer.cs deleted file mode 100644 index bdf748cd..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapLayer.cs +++ /dev/null @@ -1,88 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a tilemap layer. -/// -public sealed class RawTilemapLayer : IEquatable -{ - private RawTilemapTile[] _rawTilemapTiles; - - /// - /// Gets the name assigned to the tilemap layer. - /// - public string Name { get; } - - /// - /// Gets the id of the source tileset used by the tilemap layer. - /// - public int TilesetID { get; } - - /// - /// Gets the total number of columns in tilemap layer. - /// - public int Columns { get; } - - /// - /// Gets the total number of rows in tilemap layer. - /// - public int Rows { get; } - - /// - /// Gets a read-only span of the elements that represent the tiles for the tilemap - /// layer. - /// - public ReadOnlySpan RawTilemapTiles => _rawTilemapTiles; - - /// - /// Gets the offset of the tilemap layer. - /// - public Point Offset { get; } - - internal RawTilemapLayer(string name, int tilesetID, int columns, int rows, RawTilemapTile[] rawTilemapTiles, Point offset) => - (Name, TilesetID, Columns, Rows, _rawTilemapTiles, Offset) = (name, tilesetID, columns, rows, rawTilemapTiles, offset); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawTilemapLayer? other) => other is not null - && Name == other.Name - && TilesetID == other.TilesetID - && Columns == other.Columns - && Rows == other.Rows - && RawTilemapTiles.SequenceEqual(other.RawTilemapTiles) - && Offset == other.Offset; -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapTile.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapTile.cs deleted file mode 100644 index 2a52ebc4..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTilemapTile.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a tilemap tile. -/// -public sealed class RawTilemapTile : IEquatable -{ - /// - /// Gets the ID of the source tile in the tileset that represents the texture region used by the tilemap tile. - /// - public int TilesetTileID { get; } - - /// - /// Gets a value that indicates if the tilemap tile should be flipped horizontally. - /// - public bool FlipHorizontally { get; } - - /// - /// Gets a value that indicates if the tilemap tile should be flipped vertically. - /// - public bool FlipVertically { get; } - - /// - /// Gets a value that indicates if the tilemap tile should be flipped diagonally. - /// - public bool FlipDiagonally { get; } - - internal RawTilemapTile(int tilesetTileID, bool flipHorizontally, bool flipVertically, bool flipDiagonally) => - (TilesetTileID, FlipHorizontally, FlipVertically, FlipDiagonally) = (tilesetTileID, flipHorizontally, flipVertically, flipDiagonally); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this - /// ; otherwise, . - /// - public bool Equals(RawTilemapTile? other) => other is not null - && TilesetTileID == other.TilesetTileID - && FlipHorizontally == other.FlipHorizontally - && FlipVertically == other.FlipVertically; -} diff --git a/source/MonoGame.Aseprite.Shared/RawTypes/RawTileset.cs b/source/MonoGame.Aseprite.Shared/RawTypes/RawTileset.cs deleted file mode 100644 index cbc7ff4a..00000000 --- a/source/MonoGame.Aseprite.Shared/RawTypes/RawTileset.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.RawTypes; - -/// -/// Defines a class that represents the raw values of a tileset. -/// -public sealed class RawTileset : IEquatable -{ - /// - /// Gets the unique ID assigned to the tileset. - /// - public int ID { get; } - - /// - /// Gets the name assigned to the tileset. - /// - public string Name { get; } - - /// - /// Gets the that represents the source texture of the tileset. - /// - public RawTexture RawTexture { get; } - - /// - /// Gets the width, in pixels, of each tile in the tileset. - /// - public int TileWidth { get; } - - /// - /// Gets the height, in pixels, of each tile in the tileset. - /// - public int TileHeight { get; } - - internal RawTileset(int id, string name, RawTexture rawTexture, int tileWidth, int tileHeight) => - (ID, Name, RawTexture, TileWidth, TileHeight) = (id, name, rawTexture, tileWidth, tileHeight); - - /// - /// Returns a value that indicates if the given is equal to this - /// . - /// - /// - /// The other to check for equality with this . - /// - /// - /// if the given is equal to this ; - /// otherwise, . - /// - public bool Equals(RawTileset? other) => other is not null - && Name == other.Name - && RawTexture.Equals(other.RawTexture) - && TileWidth == other.TileWidth - && TileHeight == other.TileHeight; -} diff --git a/source/MonoGame.Aseprite.Shared/Utilities/BlendFunctions.cs b/source/MonoGame.Aseprite.Shared/Utilities/BlendFunctions.cs deleted file mode 100644 index a1207685..00000000 --- a/source/MonoGame.Aseprite.Shared/Utilities/BlendFunctions.cs +++ /dev/null @@ -1,555 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -// ============================================================================= -// Blend Functions are ported from C++ to C# from Aseprite source code. -// Aseprite licensed is as follows -// -// Copyright (c) 2018-2022 Igara Studio S.A. -// Copyright (c) 2001-2018 David Capello - -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ============================================================================= - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; - -namespace MonoGame.Aseprite.Utilities; - -internal static class BlendFunctions -{ - private const byte RGBA_R_SHIFT = 0; - private const byte RGBA_G_SHIFT = 8; - private const byte RGBA_B_SHIFT = 16; - private const byte RGBA_A_SHIFT = 24; - private const uint RGBA_R_MASK = 0x000000ff; - private const uint RGBA_G_MASK = 0x0000ff00; - private const uint RGBA_B_MASK = 0x00ff0000; - private const uint RGBA_RGB_MASK = 0x00ffffff; - private const uint RGBA_A_MASK = 0xff000000; - - internal static Color Blend(AsepriteBlendMode mode, Color backdrop, Color source, int opacity) - { - if (backdrop.A == 0 && source.A == 0) - { - return Color.Transparent; - } - else if (backdrop.A == 0) - { - return source; - } - else if (source.A == 0) - { - return backdrop; - } - - uint b = RGBA(backdrop.R, backdrop.G, backdrop.B, backdrop.A); - uint s = RGBA(source.R, source.G, source.B, source.A); - - uint blended = mode switch - { - AsepriteBlendMode.Normal => Normal(b, s, opacity), - AsepriteBlendMode.Multiply => Multiply(b, s, opacity), - AsepriteBlendMode.Screen => Screen(b, s, opacity), - AsepriteBlendMode.Overlay => Overlay(b, s, opacity), - AsepriteBlendMode.Darken => Darken(b, s, opacity), - AsepriteBlendMode.Lighten => Lighten(b, s, opacity), - AsepriteBlendMode.ColorDodge => ColorDodge(b, s, opacity), - AsepriteBlendMode.ColorBurn => ColorBurn(b, s, opacity), - AsepriteBlendMode.HardLight => HardLight(b, s, opacity), - AsepriteBlendMode.SoftLight => SoftLight(b, s, opacity), - AsepriteBlendMode.Difference => Difference(b, s, opacity), - AsepriteBlendMode.Exclusion => Exclusion(b, s, opacity), - AsepriteBlendMode.Hue => HslHue(b, s, opacity), - AsepriteBlendMode.Saturation => HslSaturation(b, s, opacity), - AsepriteBlendMode.Color => HslColor(b, s, opacity), - AsepriteBlendMode.Luminosity => HslLuminosity(b, s, opacity), - AsepriteBlendMode.Addition => Addition(b, s, opacity), - AsepriteBlendMode.Subtract => Subtract(b, s, opacity), - AsepriteBlendMode.Divide => Divide(b, s, opacity), - _ => throw new InvalidOperationException($"Unknown blend mode '{mode}'") - }; - - byte red = GetR(blended); - byte green = GetG(blended); - byte blue = GetB(blended); - byte alpha = GetA(blended); - - return new Color(red, green, blue, alpha); - } - - private static uint RGBA(int r, int g, int b, int a) => (uint)r << RGBA_R_SHIFT | - (uint)g << RGBA_G_SHIFT | - (uint)b << RGBA_B_SHIFT | - (uint)a << RGBA_A_SHIFT; - - private static byte GetR(uint value) => (byte)((value >> RGBA_R_SHIFT) & 0xFF); - private static byte GetG(uint value) => (byte)((value >> RGBA_G_SHIFT) & 0xFF); - private static byte GetB(uint value) => (byte)((value >> RGBA_B_SHIFT) & 0xFF); - private static byte GetA(uint value) => (byte)((value >> RGBA_A_SHIFT) & 0xFF); - - private static double Sat(double r, double g, double b) => Math.Max(r, Math.Max(g, b)) - Math.Min(r, Math.Min(g, b)); - - private static double Lum(double r, double g, double b) => 0.3 * r + 0.59 * g + 0.11 * b; - - private static void SetSat(ref double r, ref double g, ref double b, double s) - { - ref double MIN(ref double x, ref double y) => ref (x < y ? ref x : ref y); - ref double MAX(ref double x, ref double y) => ref (x > y ? ref x : ref y); - ref double MID(ref double x, ref double y, ref double z) => - ref (x > y ? ref (y > z ? ref y : ref (x > z ? ref z : ref x)) : ref (y > z ? ref (z > x ? ref z : ref x) : ref y)); - - ref double min = ref MIN(ref r, ref MIN(ref g, ref b)); - ref double mid = ref MID(ref r, ref g, ref b); - ref double max = ref MAX(ref r, ref MAX(ref g, ref b)); - - if (max > min) - { - mid = ((mid - min) * s) / (max - min); - max = s; - } - else - { - mid = max = 0; - } - - min = 0; - } - - private static void SetLum(ref double r, ref double g, ref double b, double l) - { - double d = l - Lum(r, g, b); - r += d; - g += d; - b += d; - ClipColor(ref r, ref g, ref b); - } - - private static void ClipColor(ref double r, ref double g, ref double b) - { - double l = Lum(r, g, b); - double n = Math.Min(r, Math.Min(g, b)); - double x = Math.Max(r, Math.Max(g, b)); - - if (n < 0) - { - r = l + (((r - l) * l) / (l - n)); - g = l + (((g - l) * l) / (l - n)); - b = l + (((b - l) * l) / (l - n)); - } - - if (x > 1) - { - r = l + (((r - l) * (1 - l)) / (x - l)); - g = l + (((g - l) * (1 - l)) / (x - l)); - b = l + (((b - l) * (1 - l)) / (x - l)); - } - } - - internal static byte MUL_UN8(int a, int b) - { - int t = (a * b) + 0x80; - return (byte)(((t >> 8) + t) >> 8); - } - - internal static byte DIV_UN8(int a, int b) - { - return (byte)(((ushort)a * 0xFF + (b / 2)) / b); - } - - private static uint Normal(uint backdrop, uint src, int opacity) - { - if ((backdrop & RGBA_A_MASK) == 0) - { - int a = GetA(src); - a = MUL_UN8(a, opacity); - a <<= RGBA_A_SHIFT; - return (uint)((src & RGBA_RGB_MASK) | (uint)a); - } - else if ((src & RGBA_A_MASK) == 0) - { - return backdrop; - } - - int Br = GetR(backdrop); - int Bg = GetG(backdrop); - int Bb = GetB(backdrop); - int Ba = GetA(backdrop); - - int Sr = GetR(src); - int Sg = GetG(src); - int Sb = GetB(src); - int Sa = GetA(src); - Sa = MUL_UN8(Sa, opacity); - - - int Ra = Sa + Ba - MUL_UN8(Ba, Sa); - - int Rr = Br + (Sr - Br) * Sa / Ra; - int Rg = Bg + (Sg - Bg) * Sa / Ra; - int Rb = Bb + (Sb - Bb) * Sa / Ra; - - return RGBA(Rr, Rg, Rb, Ra); - } - - private static uint Multiply(uint backdrop, uint source, int opacity) - { - int r = MUL_UN8(GetR(backdrop), GetR(source)); - int g = MUL_UN8(GetG(backdrop), GetG(source)); - int b = MUL_UN8(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Screen(uint backdrop, uint source, int opacity) - { - int r = GetR(backdrop) + GetR(source) - MUL_UN8(GetR(backdrop), GetR(source)); - int g = GetG(backdrop) + GetG(source) - MUL_UN8(GetG(backdrop), GetG(source)); - int b = GetB(backdrop) + GetB(source) - MUL_UN8(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Overlay(uint backdrop, uint source, int opacity) - { - int overlay(int b, int s) - { - if (b < 128) - { - b <<= 1; - return MUL_UN8(s, b); - } - else - { - b = (b << 1) - 255; - return s + b - MUL_UN8(s, b); - } - } - - int r = overlay(GetR(backdrop), GetR(source)); - int g = overlay(GetG(backdrop), GetG(source)); - int b = overlay(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Darken(uint backdrop, uint source, int opacity) - { - int blend(int b, int s) => Math.Min(b, s); - - int r = blend(GetR(backdrop), GetR(source)); - int g = blend(GetG(backdrop), GetG(source)); - int b = blend(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Lighten(uint backdrop, uint source, int opacity) - { - int lighten(int b, int s) => Math.Max(b, s); - - int r = lighten(GetR(backdrop), GetR(source)); - int g = lighten(GetG(backdrop), GetG(source)); - int b = lighten(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint ColorDodge(uint backdrop, uint source, int opacity) - { - int dodge(int b, int s) - { - if (b == 0) - { - return 0; - } - - s = 255 - s; - - if (b >= s) - { - return 255; - } - else - { - return DIV_UN8(b, s); - } - } - - int r = dodge(GetR(backdrop), GetR(source)); - int g = dodge(GetG(backdrop), GetG(source)); - int b = dodge(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint ColorBurn(uint backdrop, uint source, int opacity) - { - int burn(int b, int s) - { - if (b == 255) - { - return 255; - } - - b = (255 - b); - - if (b >= s) - { - return 0; - } - else - { - return 255 - DIV_UN8(b, s); - } - } - - int r = burn(GetR(backdrop), GetR(source)); - int g = burn(GetG(backdrop), GetG(source)); - int b = burn(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - // Not working - private static uint HardLight(uint backdrop, uint source, int opacity) - { - int hardlight(int b, int s) - { - if (s < 128) - { - s <<= 1; - return MUL_UN8(b, s); - } - else - { - s = (s << 1) - 255; - return b + s - MUL_UN8(b, s); - } - } - - int r = hardlight(GetR(backdrop), GetR(source)); - int g = hardlight(GetG(backdrop), GetG(source)); - int b = hardlight(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint SoftLight(uint backdrop, uint source, int opacity) - { - int softlight(int _b, int _s) - { - double b = _b / 255.0; - double s = _s / 255.0; - double r, d; - - if (b <= 0.25) - { - d = ((16 * b - 12) * b + 4) * b; - } - else - { - d = Math.Sqrt(b); - } - - if (s <= 0.5) - { - r = b - (1.0 - 2.0 * s) * b * (1.0 - b); - } - else - { - r = b + (2.0 * s - 1.0) * (d - b); - } - - return (int)(r * 255 + 0.5); - } - - int r = softlight(GetR(backdrop), GetR(source)); - int g = softlight(GetG(backdrop), GetG(source)); - int b = softlight(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Difference(uint backdrop, uint source, int opacity) - { - int difference(int b, int s) - { - return Math.Abs(b - s); - } - - int r = difference(GetR(backdrop), GetR(source)); - int g = difference(GetG(backdrop), GetG(source)); - int b = difference(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Exclusion(uint backdrop, uint source, int opacity) - { - int exclusion(int b, int s) - { - return b + s - 2 * MUL_UN8(b, s); - } - - int r = exclusion(GetR(backdrop), GetR(source)); - int g = exclusion(GetG(backdrop), GetG(source)); - int b = exclusion(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint HslHue(uint backdrop, uint source, int opacity) - { - double r = GetR(backdrop) / 255.0; - double g = GetG(backdrop) / 255.0; - double b = GetB(backdrop) / 255.0; - double s = Sat(r, g, b); - double l = Lum(r, g, b); - - r = GetR(source) / 255.0; - g = GetG(source) / 255.0; - b = GetB(source) / 255.0; - - SetSat(ref r, ref g, ref b, s); - SetLum(ref r, ref g, ref b, l); - - uint src = RGBA((int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b), 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint HslSaturation(uint backdrop, uint source, int opacity) - { - double r = GetR(source) / 255.0; - double g = GetG(source) / 255.0; - double b = GetB(source) / 255.0; - double s = Sat(r, g, b); - - r = GetR(backdrop) / 255.0; - g = GetG(backdrop) / 255.0; - b = GetB(backdrop) / 255.0; - double l = Lum(r, g, b); - - SetSat(ref r, ref g, ref b, s); - SetLum(ref r, ref g, ref b, l); - - uint src = RGBA((int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b), 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint HslColor(uint backdrop, uint source, int opacity) - { - double r = GetR(backdrop) / 255.0; - double g = GetG(backdrop) / 255.0; - double b = GetB(backdrop) / 255.0; - double l = Lum(r, g, b); - - r = GetR(source) / 255.0; - g = GetG(source) / 255.0; - b = GetB(source) / 255.0; - - SetLum(ref r, ref g, ref b, l); - - uint src = RGBA((int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b), 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint HslLuminosity(uint backdrop, uint source, int opacity) - { - double r = GetR(source) / 255.0; - double g = GetG(source) / 255.0; - double b = GetB(source) / 255.0; - double l = Lum(r, g, b); - - r = GetR(backdrop) / 255.0; - g = GetG(backdrop) / 255.0; - b = GetB(backdrop) / 255.0; - - SetLum(ref r, ref g, ref b, l); - - uint src = RGBA((int)(255.0 * r), (int)(255.0 * g), (int)(255.0 * b), 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Addition(uint backdrop, uint source, int opacity) - { - int r = GetR(backdrop) + GetR(source); - int g = GetG(backdrop) + GetG(source); - int b = GetB(backdrop) + GetB(source); - uint src = RGBA(Math.Min(r, 255), - Math.Min(g, 255), - Math.Min(b, 255), 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Subtract(uint backdrop, uint source, int opacity) - { - int r = GetR(backdrop) - GetR(source); - int g = GetG(backdrop) - GetG(source); - int b = GetB(backdrop) - GetB(source); - uint src = RGBA(Math.Max(r, 0), Math.Max(g, 0), Math.Max(b, 0), 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } - - private static uint Divide(uint backdrop, uint source, int opacity) - { - int divide(int b, int s) - { - if (b == 0) - { - return 0; - } - else if (b >= s) - { - return 255; - } - else - { - return DIV_UN8(b, s); - } - } - int r = divide(GetR(backdrop), GetR(source)); - int g = divide(GetG(backdrop), GetG(source)); - int b = divide(GetB(backdrop), GetB(source)); - uint src = RGBA(r, g, b, 0) | (source & RGBA_A_MASK); - return Normal(backdrop, src, opacity); - } -} diff --git a/source/MonoGame.Aseprite/Sprites/AnimatedSprite.cs b/source/MonoGame.Aseprite/AnimatedSprite.cs similarity index 54% rename from source/MonoGame.Aseprite/Sprites/AnimatedSprite.cs rename to source/MonoGame.Aseprite/AnimatedSprite.cs index 169c1a43..298ba550 100644 --- a/source/MonoGame.Aseprite/Sprites/AnimatedSprite.cs +++ b/source/MonoGame.Aseprite/AnimatedSprite.cs @@ -1,494 +1,468 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.Sprites; - -/// -/// Defines an animated sprite with methods to control the playing of the sprite animation. -/// -public sealed class AnimatedSprite : Sprite -{ - private int _currentIndex; - private int _direction; - private int _loopCount; - private int _loopsRemaining; - private bool _hasBegun = false; - private double _speed = 1.0f; - private AnimationTag _animationTag; - - /// - /// Gets a value that indicates if this is currently paused. - /// - public bool IsPaused { get; private set; } - - /// - /// Gets a value that indicates if this has completed its animation. - /// - public bool IsAnimating { get; private set; } - - /// - /// Gets or Sets a value that indicates if this plays it's frames in reverse order. - /// - public bool IsReversed - { - get => _direction == -1; - set => _direction = value ? -1 : 1; - } - - /// - /// Gets or Sets a value that indicates if this should ping-pong once reaching the - /// last frame of animation. - /// - public bool IsPingPong { get; set; } - - /// - /// Gets a value that indicates the total number of loops/cycles of the animation that should play for - /// this . - /// - /// - /// - /// 0 = infinite looping - /// - /// - /// If is equal to , each direction of the - /// ping-pong will count as a loop. - /// - /// - public int LoopCount => _loopCount; - - /// - /// Sets the rate at which the animation is played. - /// - /// - /// This value is clamped between 0.0d and - /// - /// - /// Default (normal) speed is 1.0d - /// - public double Speed - { - get => _speed; - set - { - _speed = Math.Clamp(value, 0, double.MaxValue); - } - } - - /// - /// Gets the total number of frames in this - /// - public int FrameCount => _animationTag.FrameCount; - - /// - /// Gets the source of the current frame of animation for this - /// . - /// - public AnimationFrame CurrentFrame => _animationTag.Frames[_currentIndex]; - - /// - /// Gets or Sets an method to invoke at the start of each frame of animation. - /// - public Action? OnFrameBegin { get; set; } = default; - - /// - /// Gets or Sets an method to invoke at the end of each frame of animation. - /// - public Action? OnFrameEnd { get; set; } = default; - - /// - /// Gets or Sets an method to invoke at the start of the animation. - /// - /// - /// This will trigger only once when the animation starts before the the first frame's - /// triggers. - /// - public Action? OnAnimationBegin { get; set; } = default; - - /// - /// Gets or Sets an to invoke each time the animation loops. - /// - /// - /// This will trigger each time the animation loops after the last frame's triggers. - /// - public Action? OnAnimationLoop { get; set; } = default; - - /// - /// Gets or Sets an method to invoke when the animation ends. - /// - /// - /// This will only trigger when the animation ends in a non-looping animation, or if a looping animation is - /// stopped by calling manually. - /// - public Action? OnAnimationEnd { get; set; } = default; - - /// - /// Gets the amount of time remaining for the before moving to the next frame. - /// - public TimeSpan CurrentFrameTimeRemaining { get; private set; } - - internal AnimatedSprite(AnimationTag tag) - : base(tag.Name, tag.Frames[0].TextureRegion) - { - _animationTag = tag; - Reset(); - } - - /// - /// Updates this . - /// - /// - /// This should only be called once per update cycle. - /// - /// - /// The amount of time, in seconds, that have elapsed since the last update cycle in the game. - /// - public void Update(double deltaTimeInSeconds) - { - Update(TimeSpan.FromSeconds(deltaTimeInSeconds)); - } - - /// - /// Updates this . - /// - /// - /// This should only be called once per update cycle. - /// - /// - /// A snapshot of the game timing values for the current update cycle. - /// - public void Update(GameTime gameTime) - { - Update(gameTime.ElapsedGameTime); - } - - /// - /// Updates this . - /// - /// - /// This should only be called once per update cycle. - /// - /// - /// The amount of time, that have elapsed since the last update cycle in the game. - /// - public void Update(in TimeSpan elapsedTime) - { - if (!IsAnimating || IsPaused) - { - return; - } - - if (!_hasBegun) - { - _hasBegun = true; - OnAnimationBegin?.Invoke(this); - } - - if (CurrentFrameTimeRemaining == CurrentFrame.Duration) - { - OnFrameBegin?.Invoke(this); - } - - CurrentFrameTimeRemaining -= elapsedTime * Speed; - - if (CurrentFrameTimeRemaining <= TimeSpan.Zero) - { - AdvanceFrame(); - } - } - - /// - /// Sets the current frame of animation for this . - /// - /// - /// The index of the frame to set. Value must be greater than zero and less than the total count of frames. You - /// can use to determine the total number of frames. - /// - /// - /// Thrown if the value provided is less than zero or is greater than or equal to - /// the total number of frames in this . - /// - public void SetFrame(int frameIndex) - { - if(frameIndex < 0 || frameIndex >= FrameCount) - { - throw new ArgumentOutOfRangeException(nameof(frameIndex), $"{nameof(frameIndex)} must be greater than zero and less than the total number of frames in this AnimatedSprite"); - } - - _currentIndex = frameIndex; - TextureRegion = CurrentFrame.TextureRegion; - CurrentFrameTimeRemaining = CurrentFrame.Duration; - } - - private void AdvanceFrame() - { - OnFrameEnd?.Invoke(this); - - _currentIndex += _direction; - - if (_currentIndex >= _animationTag.FrameCount || _currentIndex < 0) - { - bool shouldLoop = _loopCount == 0 || _loopsRemaining > 1; - - if (shouldLoop) - { - ReduceLoopsRemaining(); - - if (IsPingPong) - { - _direction = -_direction; - - // Adjust the current index again after ping ponging so we don't repeat the - // same frame twice in a row - _currentIndex += _direction * 2; - - } - else - { - _currentIndex = IsReversed ? _animationTag.FrameCount - 1 : 0; - } - OnAnimationLoop?.Invoke(this); - } - else - { - _currentIndex += -_direction; - Stop(); - } - } - - TextureRegion = CurrentFrame.TextureRegion; - CurrentFrameTimeRemaining = CurrentFrame.Duration; - } - - private void ReduceLoopsRemaining() - { - _loopsRemaining = Math.Max(--_loopsRemaining, 0); - } - - /// - /// Starts the animation for this - /// - /// - /// - /// When a value is provided, specifies the total number of loop/cycles to perform before stopping the - /// animation. - /// - /// - /// When is provided, loop count will default to the value defined in the - /// used to create this - /// - /// - /// 0 = infinite looping - /// - /// - /// If is equal to , each direction of the - /// ping-pong will count as a loop. - /// - /// - /// - /// - /// When this value is provided, specifies the frame to start the animation at - /// - /// - /// When is provided, play will start at frame 0 of the animation. - /// - /// - /// - /// if animation play was successfully started for this ; - /// otherwise, . This method returns if the animation is already - /// playing (when equals ). - /// - /// - /// Thrown if the value provided is less than zero or is greater than or equal to - /// the total number of frames in this . - /// - public bool Play(int? loopCount = default, int? startingFrame = 0) - { - if(startingFrame < 0 || startingFrame >= FrameCount) - { - throw new ArgumentOutOfRangeException(nameof(startingFrame), $"{nameof(startingFrame)} must be greater than zero and less than the total number of frames in this AnimatedSprite"); - } - - // Cannot play something that's already playing - if (IsAnimating) - { - return false; - } - - if (loopCount is null) - { - loopCount = _animationTag.LoopCount; - } - - _loopCount = loopCount.Value; - _loopsRemaining = _loopCount; - - IsAnimating = true; - IsPaused = false; - - _currentIndex = startingFrame ?? 0; - - if (IsReversed) - { - _currentIndex = _animationTag.Frames.Length - 1; - } - - TextureRegion = CurrentFrame.TextureRegion; - CurrentFrameTimeRemaining = CurrentFrame.Duration; - _hasBegun = false; - - return true; - } - - - /// - /// Paused this and prevents it from being updated until it is unpaused. - /// - /// - /// A value that indicates whether the should be reset. When this - /// method returns , this indicates the was not - /// reset even if this was specified as . - /// - /// - /// if this was successfully paused; otherwise, - /// . This method returns if this - /// is not currently animating or if it is already paused. - /// - public bool Pause(bool resetFrameDuration = false) - { - // We can only pause something that is animating and is not already paused. This is to prevent improper usage - // that could accidentally reset frame duration if it was set to true. - if (!IsAnimating || IsPaused) - { - return false; - } - - IsPaused = true; - - if (resetFrameDuration) - { - CurrentFrameTimeRemaining = CurrentFrame.Duration; - } - - return true; - } - - /// - /// Unpaused this . - /// - /// - /// A value that indicates whether this should immediately advance to the next - /// frame after unpausing. When this method returns , this - /// will -not- be advanced to the next frame, even if this was specified as . - /// - /// - /// if this was successfully unpaused; otherwise, - /// . This method returns if this - /// is not currently animating or if it is not paused. - /// - public bool Unpause(bool advanceToNextFrame = false) - { - // We can't unpause something that's not animating and also isn't paused. This is to prevent improper usage - // that could accidentally advance to the next frame if it was set to true. - if (!IsAnimating || !IsPaused) - { - return false; - } - - IsPaused = false; - - if (advanceToNextFrame) - { - AdvanceFrame(); - } - - return true; - } - - /// - /// Stops this on the current frame. - /// - /// - /// This will trigger the action if one was set. - /// - /// - /// if this was successfully stopped; otherwise, - /// . This method returns if this - /// is not currently animating. If this method returns , this also indicates that the - /// was not triggered. - /// - public bool Stop() - { - // We can't stop something that's not animating. This is to prevent - // accidentally invoking the OnAnimationEnd action - if (!IsAnimating) - { - return false; - } - - IsAnimating = false; - IsPaused = true; - OnAnimationEnd?.Invoke(this); - return true; - } - - /// - /// Resets this back to its initial state as defined by the - /// used to create it. You will need to call - /// after resetting to start the playback of the animation. - /// - /// - /// - /// This is useful if you've adjusted the or - /// properties, or specified a override to the loop count when - /// initially playing the animation. - /// - /// - /// This also resets the to 1.0d. - /// - /// - public void Reset() - { - IsReversed = _animationTag.IsReversed; - IsPingPong = _animationTag.IsPingPong; - _loopCount = _animationTag.LoopCount; - _loopsRemaining = _loopCount; - - IsAnimating = false; - IsPaused = true; - - Speed = 1.0d; - - _currentIndex = 0; - if(IsReversed) - { - _currentIndex = _animationTag.Frames.Length - 1; - } - - TextureRegion = CurrentFrame.TextureRegion; - CurrentFrameTimeRemaining = CurrentFrame.Duration; - _hasBegun = false; - } -} +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using Microsoft.Xna.Framework; + +namespace MonoGame.Aseprite; + +/// +/// Defines an animated sprite with methods to control the playing of the sprite animation. +/// +public sealed class AnimatedSprite : Sprite +{ + private int _currentIndex; + private int _direction; + private int _loopCount; + private int _loopsRemaining; + private bool _hasBegun = false; + private double _speed = 1.0f; + private AnimationTag _animationTag; + + /// + /// Gets a value that indicates if this is currently paused. + /// + public bool IsPaused { get; private set; } + + /// + /// Gets a value that indicates if this has completed its animation. + /// + public bool IsAnimating { get; private set; } + + /// + /// Gets or Sets a value that indicates if this plays it's frames in reverse order. + /// + public bool IsReversed + { + get => _direction == -1; + set => _direction = value ? -1 : 1; + } + + /// + /// Gets or Sets a value that indicates if this should ping-pong once reaching the + /// last frame of animation. + /// + public bool IsPingPong { get; set; } + + /// + /// Gets a value that indicates the total number of loops/cycles of the animation that should play for + /// this . + /// + /// + /// + /// 0 = infinite looping + /// + /// + /// If is equal to , each direction of the + /// ping-pong will count as a loop. + /// + /// + public int LoopCount => _loopCount; + + /// + /// Sets the rate at which the animation is played. + /// + /// + /// This value is clamped between 0.0d and + /// Default (normal) speed is 1.0d + /// + public double Speed + { + get => _speed; + set + { + _speed = Math.Clamp(value, 0, double.MaxValue); + } + } + + /// + /// Gets the total number of frames in this + /// + public int FrameCount => _animationTag.FrameCount; + + /// + /// Gets the source of the current frame of animation for this + /// . + /// + public AnimationFrame CurrentFrame => _animationTag.Frames[_currentIndex]; + + /// + /// Gets or Sets an method to invoke at the start of each frame of animation. + /// + public Action? OnFrameBegin { get; set; } = default; + + /// + /// Gets or Sets an method to invoke at the end of each frame of animation. + /// + public Action? OnFrameEnd { get; set; } = default; + + /// + /// Gets or Sets an method to invoke at the start of the animation. + /// + /// + /// This will trigger only once when the animation starts before the the first frame's + /// triggers. + /// + public Action? OnAnimationBegin { get; set; } = default; + + /// + /// Gets or Sets an to invoke each time the animation loops. + /// + /// + /// This will trigger each time the animation loops after the last frame's triggers. + /// + public Action? OnAnimationLoop { get; set; } = default; + + /// + /// Gets or Sets an method to invoke when the animation ends. + /// + /// + /// This will only trigger when the animation ends in a non-looping animation, or if a looping animation is + /// stopped by calling manually. + /// + public Action? OnAnimationEnd { get; set; } = default; + + /// + /// Gets the amount of time remaining for the before moving to the next frame. + /// + public TimeSpan CurrentFrameTimeRemaining { get; private set; } + + internal AnimatedSprite(AnimationTag tag) + : base(tag.Name, tag.Frames[0].TextureRegion) + { + _animationTag = tag; + Reset(); + } + + /// + /// Updates this . + /// + /// + /// This should only be called once per update cycle. + /// + /// + /// The amount of time, in seconds, that have elapsed since the last update cycle in the game. + /// + public void Update(double deltaTimeInSeconds) + { + Update(TimeSpan.FromSeconds(deltaTimeInSeconds)); + } + + /// + /// Updates this . + /// + /// + /// This should only be called once per update cycle. + /// + /// A snapshot of the game timing values for the current update cycle. + public void Update(GameTime gameTime) + { + Update(gameTime.ElapsedGameTime); + } + + /// + /// Updates this . + /// + /// + /// This should only be called once per update cycle. + /// + /// The amount of time, that have elapsed since the last update cycle in the game. + public void Update(in TimeSpan elapsedTime) + { + if (!IsAnimating || IsPaused) + { + return; + } + + if (!_hasBegun) + { + _hasBegun = true; + OnAnimationBegin?.Invoke(this); + } + + if (CurrentFrameTimeRemaining == CurrentFrame.Duration) + { + OnFrameBegin?.Invoke(this); + } + + CurrentFrameTimeRemaining -= elapsedTime * Speed; + + if (CurrentFrameTimeRemaining <= TimeSpan.Zero) + { + AdvanceFrame(); + } + } + + /// + /// Sets the current frame of animation for this . + /// + /// + /// The index of the frame to set. Value must be greater than zero and less than the total count of frames. You + /// can use to determine the total number of frames. + /// + /// + /// Thrown if the value provided is less than zero or is greater than or equal to + /// the total number of frames in this . + /// + public void SetFrame(int frameIndex) + { + if (frameIndex < 0 || frameIndex >= FrameCount) + { + throw new ArgumentOutOfRangeException(nameof(frameIndex), $"{nameof(frameIndex)} must be greater than zero and less than the total number of frames in this AnimatedSprite"); + } + + _currentIndex = frameIndex; + TextureRegion = CurrentFrame.TextureRegion; + CurrentFrameTimeRemaining = CurrentFrame.Duration; + } + + private void AdvanceFrame() + { + OnFrameEnd?.Invoke(this); + + _currentIndex += _direction; + + if (_currentIndex >= _animationTag.FrameCount || _currentIndex < 0) + { + bool shouldLoop = _loopCount == 0 || _loopsRemaining > 1; + + if (shouldLoop) + { + ReduceLoopsRemaining(); + + if (IsPingPong) + { + _direction = -_direction; + + // Adjust the current index again after ping ponging so we don't repeat the + // same frame twice in a row + _currentIndex += _direction * 2; + + } + else + { + _currentIndex = IsReversed ? _animationTag.FrameCount - 1 : 0; + } + OnAnimationLoop?.Invoke(this); + } + else + { + _currentIndex += -_direction; + Stop(); + } + } + + TextureRegion = CurrentFrame.TextureRegion; + CurrentFrameTimeRemaining = CurrentFrame.Duration; + } + + private void ReduceLoopsRemaining() + { + _loopsRemaining = Math.Max(--_loopsRemaining, 0); + } + + /// + /// Starts the animation for this + /// + /// + /// + /// When a value is provided, specifies the total number of loop/cycles to perform before stopping the + /// animation. + /// + /// + /// When is provided, loop count will default to the value defined in the + /// used to create this + /// + /// + /// 0 = infinite looping + /// + /// + /// If is equal to , each direction of the + /// ping-pong will count as a loop. + /// + /// + /// + /// + /// When this value is provided, specifies the frame to start the animation at + /// + /// + /// When is provided, play will start at frame 0 of the animation. + /// + /// + /// + /// if animation play was successfully started for this ; + /// otherwise, . This method returns if the animation is already + /// playing (when equals ). + /// + /// + /// Thrown if the value provided is less than zero or is greater than or equal to + /// the total number of frames in this . + /// + public bool Play(int? loopCount = default, int? startingFrame = 0) + { + if (startingFrame < 0 || startingFrame >= FrameCount) + { + throw new ArgumentOutOfRangeException(nameof(startingFrame), $"{nameof(startingFrame)} must be greater than zero and less than the total number of frames in this AnimatedSprite"); + } + + // Cannot play something that's already playing + if (IsAnimating) + { + return false; + } + + if (loopCount is null) + { + loopCount = _animationTag.LoopCount; + } + + _loopCount = loopCount.Value; + _loopsRemaining = _loopCount; + + IsAnimating = true; + IsPaused = false; + + _currentIndex = startingFrame ?? 0; + + if (IsReversed) + { + _currentIndex = _animationTag.Frames.Length - 1; + } + + TextureRegion = CurrentFrame.TextureRegion; + CurrentFrameTimeRemaining = CurrentFrame.Duration; + _hasBegun = false; + + return true; + } + + + /// + /// Paused this and prevents it from being updated until it is unpaused. + /// + /// + /// A value that indicates whether the should be reset. When this method + /// returns , this indicates the was not reset even + /// if this was specified as . + /// + /// + /// if this was successfully paused; otherwise, + /// . This method returns if this + /// is not currently animating or if it is already paused. + /// + public bool Pause(bool resetFrameDuration = false) + { + // We can only pause something that is animating and is not already paused. This is to prevent improper usage + // that could accidentally reset frame duration if it was set to true. + if (!IsAnimating || IsPaused) + { + return false; + } + + IsPaused = true; + + if (resetFrameDuration) + { + CurrentFrameTimeRemaining = CurrentFrame.Duration; + } + + return true; + } + + /// + /// Unpaused this . + /// + /// + /// A value that indicates whether this should immediately advance to the next frame + /// after unpausing. When this method returns , this will + /// -not- be advanced to the next frame, even if this was specified as . + /// + /// + /// if this was successfully unpaused; otherwise, + /// . This method returns if this + /// is not currently animating or if it is not paused. + /// + public bool Unpause(bool advanceToNextFrame = false) + { + // We can't unpause something that's not animating and also isn't paused. This is to prevent improper usage + // that could accidentally advance to the next frame if it was set to true. + if (!IsAnimating || !IsPaused) + { + return false; + } + + IsPaused = false; + + if (advanceToNextFrame) + { + AdvanceFrame(); + } + + return true; + } + + /// + /// Stops this on the current frame. + /// + /// + /// This will trigger the action if one was set. + /// + /// + /// if this was successfully stopped; otherwise, + /// . This method returns if this + /// is not currently animating. If this method returns , this also indicates that the + /// was not triggered. + /// + public bool Stop() + { + // We can't stop something that's not animating. This is to prevent + // accidentally invoking the OnAnimationEnd action + if (!IsAnimating) + { + return false; + } + + IsAnimating = false; + IsPaused = true; + OnAnimationEnd?.Invoke(this); + return true; + } + + /// + /// Resets this back to its initial state as defined by the + /// used to create it. You will need to call + /// after resetting to start the playback of the animation. + /// + /// + /// + /// This is useful if you've adjusted the or + /// properties, or specified a override to the loop count when + /// initially playing the animation. + /// + /// + /// This also resets the to 1.0d. + /// + /// + public void Reset() + { + IsReversed = _animationTag.IsReversed; + IsPingPong = _animationTag.IsPingPong; + _loopCount = _animationTag.LoopCount; + _loopsRemaining = _loopCount; + + IsAnimating = false; + IsPaused = true; + + Speed = 1.0d; + + _currentIndex = 0; + if (IsReversed) + { + _currentIndex = _animationTag.Frames.Length - 1; + } + + TextureRegion = CurrentFrame.TextureRegion; + CurrentFrameTimeRemaining = CurrentFrame.Duration; + _hasBegun = false; + } +} diff --git a/source/MonoGame.Aseprite/AnimatedTIlemapFrame.cs b/source/MonoGame.Aseprite/AnimatedTIlemapFrame.cs new file mode 100644 index 00000000..7aa08e2b --- /dev/null +++ b/source/MonoGame.Aseprite/AnimatedTIlemapFrame.cs @@ -0,0 +1,283 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Xna.Framework; + +namespace MonoGame.Aseprite; + +/// +/// Defines a frame of animation in an , containing zero or more +/// elements. +/// +public sealed class AnimatedTilemapFrame : IEnumerable +{ + private List _layers = new(); + private Dictionary _layerLookup = new(); + + /// + /// Gets the duration of this . + /// + public TimeSpan Duration { get; } + + /// + /// Gets the total number of elements in this . + /// + public int LayerCount => _layers.Count; + + /// + /// Gets the element at the specified index in this . + /// + /// The index of the element to locate. + /// The element located. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public TilemapLayer this[int layerIndex] => GetLayer(layerIndex); + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the element to locate. + /// The element located. + /// + /// Thrown if this does not contain a element with + /// the specified name. + /// + public TilemapLayer this[string layerName] => GetLayer(layerName); + + /// + /// Initializes a new instance of the class. + /// + /// The duration to assign the . + public AnimatedTilemapFrame(TimeSpan duration) => Duration = duration; + + /// + /// Creates a new element and adds it to this . + /// + /// + /// The name to assign the element created by this method. The name must be unique + /// across all elements in this . + /// + /// + /// The source to assign the element created by this method. + /// + /// + /// The total number of columns to assign the element created by this method. + /// + /// + /// The total of rows in the element created by this method. + /// + /// + /// The x- and y-position offset, relative to the location the is rendered, to + /// assign the element created by this method. + /// + /// The created by this method. + /// + /// Thrown if this already contains a element with + /// the specified name. + /// + public TilemapLayer CreateLayer(string layerName, Tileset tileset, int columns, int rows, Vector2 offset) + { + TilemapLayer layer = new(layerName, tileset, columns, rows, offset); + AddLayer(layer); + return layer; + } + + /// + /// Adds the given element to this . + /// + /// The element to add. + /// + /// Thrown if this already contains a element with + /// the same name as the element given. + /// + public void AddLayer(TilemapLayer layer) + { + if (_layerLookup.ContainsKey(layer.Name)) + { + throw new InvalidOperationException($"This tileset frame already contains a tilemap layer element with the name '{layer.Name}'."); + } + + _layers.Add(layer); + _layerLookup.Add(layer.Name, layer); + } + + /// + /// Gets the element at the specified index in this + /// . + /// + /// The index of the element to locate. + /// The element located. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public TilemapLayer GetLayer(int index) + { + if (index < 0 || index >= LayerCount) + { + throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of tilemap layer elements in this animated tilemap frame."); + } + + return _layers[index]; + } + + /// + /// Gets the element with the specified name in this + /// . + /// + /// The name of the element to locate. + /// The element located. + /// + /// Thrown if this does not contain a element with + /// the specified name. + /// + public TilemapLayer GetLayer(string name) + { + if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) + { + return layer; + } + + throw new KeyNotFoundException($"This animated tilemap frame does not contain a tilemap layer element with the name '{name}'."); + } + + /// + /// Get the element at the specified index in this . + /// + /// The index of the element to locate. + /// + /// When this method returns , contains the element located; + /// otherwise, . + /// + /// + /// if a element was located at the specified index in this + /// ; otherwise, . This method return + /// when the specified index is less than zero or is greater than or equal to the total + /// number of elements in this . + /// + public bool TryGetLayer(int index, [NotNullWhen(true)] out TilemapLayer? layer) + { + layer = default; + + if (index < 0 || index >= LayerCount) + { + return false; + } + + layer = _layers[index]; + return true; + } + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the element to locate. + /// + /// When this method returns , contains the element located; + /// otherwise, . + /// + /// + /// if a element was located in this + /// with the specified name; otherwise . This method + /// returns if this does not contain a + /// element with the specified name. + /// + public bool TryGetLayer(string name, [NotNullWhen(true)] out TilemapLayer? layer) => + _layerLookup.TryGetValue(name, out layer); + + /// + /// Removes the element at the specified index in this + /// . + /// + /// + /// The index of the element to remove from this . + /// + /// + /// if the element was successfully removed; otherwise, + /// . This method returns if the specified index is less than + /// zero or is greater than or equal to the total number of elements in this tilemap + /// frame. + /// + public bool RemoveLayer(int index) + { + if (index < 0 || index >= LayerCount) + { + return false; + } + + TilemapLayer layer = _layers[index]; + return RemoveLayer(layer); + } + + /// + /// Removes the element with the specified name from this + /// . + /// + /// + /// The name of the element to remove from this + /// + /// + /// if the element was successfully removed; otherwise, + /// . This method returns if this tilemap frame does not + /// contain a element with the specified name. + /// + public bool RemoveLayer(string name) + { + if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) + { + return RemoveLayer(layer); + } + + return false; + } + + /// + /// Removes the given element from this . + /// + /// + /// The element to remove from this . + /// + /// + /// if the element was removed successfully; otherwise, + /// . This method returns if this tilemap frame does not contain + /// the element given. + /// + public bool RemoveLayer(TilemapLayer layer) => + _layers.Remove(layer) && _layerLookup.Remove(layer.Name); + + /// + /// Removes all elements from this . + /// + public void Clear() + { + _layerLookup.Clear(); + _layers.Clear(); + } + + /// + /// Returns an enumerator used to iterate through all of the elements in this + /// . The order of elements in the enumeration is from bottom layer to top + /// layer. + /// + /// + /// An enumerator used to iterate through all of the elements in this + /// . + /// + public IEnumerator GetEnumerator() => _layers.GetEnumerator(); + + /// + /// Returns an enumerator used to iterate through all of the elements in this + /// . The order of elements in the enumeration is from bottom layer to top + /// layer. + /// + /// + /// An enumerator used to iterate through all of the elements in this + /// . + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/source/MonoGame.Aseprite/AnimatedTilemap.cs b/source/MonoGame.Aseprite/AnimatedTilemap.cs new file mode 100644 index 00000000..f284109a --- /dev/null +++ b/source/MonoGame.Aseprite/AnimatedTilemap.cs @@ -0,0 +1,582 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Collections; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace MonoGame.Aseprite; + +/// +/// Defines a consisting of elements +/// +public sealed class AnimatedTilemap : IEnumerable +{ + private bool _hasBegun; + private int _currentIndex; + private int _direction; + private List _frames = new(); + + /// + /// Gets the name assigned to this . + /// + public string Name { get; } + + /// + /// Gets the total number of elements in this . + /// + public int frameCount => _frames.Count; + + /// + /// Gets the element at the specified index in this + /// . + /// + /// + /// The index of the element to locate. + /// + /// + /// The element that was located at the specified index in this + /// . + /// + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public AnimatedTilemapFrame this[int frameIndex] => GetFrame(frameIndex); + + /// + /// Gets a value that indicates if this is currently paused. + /// + public bool IsPaused { get; private set; } + + /// + /// Gets a value that indicates if this is currently animating. + /// + public bool IsAnimating { get; private set; } + + /// + /// Gets a value that indicates whether the animation this should loop. + /// + public bool IsLooping { get; } + + /// + /// Gets a value that indicates whether the animation this should play frames in + /// reverse order. + /// + public bool IsReversed { get; } + + /// + /// Gets a value that indicates whether the animation for this should ping-pong once + /// reaching the last frame of animation. + /// + public bool IsPingPong { get; } + + /// + /// Gets the source element for the current animation frame. + /// + /// + /// Thrown if no elements have been added to this + /// prior to accessing this property. + /// + public AnimatedTilemapFrame CurrentFrame + { + get + { + if (_frames.Count == 0) + { + throw new InvalidOperationException($"Unable to get current frame as no frames have been added to this animated tilemap."); + } + + return this[_currentIndex]; + } + } + + /// + /// Gets or Sets an method to invoke at the start of each animation frame. + /// + public Action? OnFrameBegin { get; set; } = default; + + /// + /// Gets or Sets an method to invoke at the end of each animation frame. + /// + public Action? OnFrameEnd { get; set; } = default; + + /// + /// Gets or Sets an method to invoke at the start of the animation. This will trigger only + /// once when the animation starts before the first frame's triggers. + /// + public Action? OnAnimationBegin { get; set; } = default; + + /// + /// Gets or Sets an method to invoke each time the animation loops. This will trigger each + /// time the animation loops after the last frame's triggers. + /// + public Action? OnAnimationLoop { get; set; } = default; + + /// + /// Gets or Sets an method to invoke when the animation ends. This will only trigger when + /// the animation ends in a non-looping animation, or if a looping animation is stopped by calling the + /// method manually. + /// + public Action? OnAnimationEnd { get; set; } = default; + + /// + /// Gets the amount of time remaining for the before moving to the next frame. + /// + public TimeSpan CurrentFrameTimeRemaining { get; private set; } + + + /// + /// Initializes a new instance of the class. + /// + /// + /// The name to assign the . + /// + /// + /// Indicates whether the animation for the should loop + /// + /// + /// Indicates whether the frames for the should play in reverse order. + /// + /// + /// Indicates whether the animation for this should ping-pong once reaching the + /// last frame of animation + /// + public AnimatedTilemap(string name, bool isLooping = true, bool isReversed = false, bool isPingPong = false) + { + Name = name; + IsLooping = isLooping; + IsReversed = isReversed; + IsPingPong = isPingPong; + Reset(); + } + + /// + /// Updates this . + /// + /// + /// This should only be called once per game update cycle. + /// + /// + /// The amount of time, in seconds, that have elapsed since the last update cycle in the game. + /// + public void Update(double deltaTimeInSeconds) + { + Update(TimeSpan.FromSeconds(deltaTimeInSeconds)); + } + + /// + /// Updates this . + /// + /// + /// This should only be called once per game update cycle. + /// + /// A snapshot of the game timing values for the current update cycle. + public void Update(GameTime gameTime) + { + Update(gameTime.ElapsedGameTime); + } + + /// + /// Updates this . + /// + /// + /// This should only be called once per game update cycle. + /// + /// The amount of time, that have elapsed since the last update cycle in the game. + public void Update(in TimeSpan elapsedTime) + { + if (!IsAnimating || IsPaused) + { + return; + } + + if (!_hasBegun) + { + _hasBegun = true; + OnAnimationBegin?.Invoke(this); + } + + if (CurrentFrameTimeRemaining == CurrentFrame.Duration) + { + OnFrameBegin?.Invoke(this); + } + + CurrentFrameTimeRemaining -= elapsedTime; + + if (CurrentFrameTimeRemaining <= TimeSpan.Zero) + { + AdvanceFrame(); + } + } + + private void AdvanceFrame() + { + OnFrameEnd?.Invoke(this); + + _currentIndex += _direction; + + switch (IsReversed, IsPingPong) + { + case (true, true): + ReversePingPongLoopCheck(); + break; + case (true, false): + ReverseLoopCheck(); + break; + case (false, true): + PingPongLoopCheck(); + break; + case (false, false): + LoopCheck(); + break; + } + + CurrentFrameTimeRemaining = CurrentFrame.Duration; + } + + private void LoopCheck() + { + if (_currentIndex >= _frames.Count) + { + if (IsLooping) + { + _currentIndex = 0; + OnAnimationLoop?.Invoke(this); + } + else + { + _currentIndex = _frames.Count - 1; + Stop(); + } + } + } + + private void ReverseLoopCheck() + { + if (_currentIndex < 0) + { + if (IsLooping) + { + _currentIndex = _frames.Count - 1; + OnAnimationLoop?.Invoke(this); + } + else + { + _currentIndex = 0; + Stop(); + } + } + } + + private void PingPongLoopCheck() + { + if (_currentIndex < 0 || _currentIndex >= _frames.Count) + { + _direction = -_direction; + + if (_direction == -1) + { + _currentIndex = _frames.Count - 2; + } + else + { + if (IsLooping) + { + _currentIndex = 1; + OnAnimationLoop?.Invoke(this); + } + else + { + _currentIndex = 0; + Stop(); + } + } + } + } + + private void ReversePingPongLoopCheck() + { + if (_currentIndex < 0 || _currentIndex >= _frames.Count) + { + _direction = -_direction; + + if (_direction == 1) + { + _currentIndex = 1; + } + else + { + if (IsLooping) + { + _currentIndex = _frames.Count - 2; + OnAnimationLoop?.Invoke(this); + } + else + { + _currentIndex = _frames.Count - 1; + Stop(); + } + } + } + } + + /// + /// Pauses this and prevents it from being updated until it is unpaused. + /// + /// + /// A value that indicates whether the the duration of the should be reset. When + /// this method returns , the duration will not be reset even if this is specified as + /// . + /// + /// + /// this was successfully paused; otherwise, + /// . This method returns this + /// is not currently animating or if it is already paused. + /// + public bool Pause(bool resetFrameDuration = false) + { + // We can only pause something that is animating and is not already paused. This is to prevent improper usage + // that could accidentally reset frame duration if it was set to true. + if (!IsAnimating || IsPaused) + { + return false; + } + + IsPaused = true; + + if (resetFrameDuration) + { + CurrentFrameTimeRemaining = CurrentFrame.Duration; + } + + return true; + } + + /// + /// Unpauses this . + /// + /// + /// A value that indicates whether this should immediately be advanced to the next + /// frame after unpausing. When this method returns , this + /// will -not- be advanced to the next frame, even if this was specified as . + /// + /// + /// if this was successfully unpaused; otherwise, + /// . This method return this is + /// not currently animating or if it has not already been paused. + /// + public bool Unpause(bool advanceToNextFrame = false) + { + // We can't unpause something that's not animating and also isn't paused. This is to prevent improper usage + // that could accidentally advance to the next frame if it was set to true. + if (!IsAnimating || !IsPaused) + { + return false; + } + + IsPaused = false; + + if (advanceToNextFrame) + { + AdvanceFrame(); + } + + return true; + } + + /// + /// Stops this on the . This will trigger the + /// if one was set. + /// + /// + /// this was successfully stopped; otherwise, + /// . This method returns this is + /// not currently animating. If this method returns , this indicates that the + /// action method was not invoked. + /// + public bool Stop() + { + // We can't stop something that's not animating. This is to prevent accidentally invoking the OnAnimationEnd + // action + if (!IsAnimating) + { + return false; + } + + IsAnimating = false; + OnAnimationEnd?.Invoke(this); + return true; + } + + /// + /// Resets this back to its first frame of animation. + /// + /// + /// A value that indicates whether his should be paused after it is reset. + /// + public void Reset(bool paused = false) + { + IsAnimating = true; + IsPaused = paused; + + if (IsReversed) + { + _direction = -1; + _currentIndex = _frames.Count; + } + else + { + _direction = 1; + _currentIndex = 0; + } + + _hasBegun = false; + } + + /// + /// Creates and adds a new element as the next frame of animation in this + /// . + /// + /// The duration to assign the created. + /// + /// The created. + /// + public AnimatedTilemapFrame CreateFrame(TimeSpan duration) + { + AnimatedTilemapFrame frame = new(duration); + AddFrame(frame); + return frame; + } + + /// + /// Adds the given as the next frame of animation in this + /// . + /// + /// The to add + public void AddFrame(AnimatedTilemapFrame frame) => _frames.Add(frame); + + /// + /// Gets the element at the specified index in this + /// . + /// + /// The index of the element to locate. + /// + /// The element that was located. + /// + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public AnimatedTilemapFrame GetFrame(int frameIndex) + { + if (frameIndex < 0 || frameIndex >= frameCount) + { + throw new ArgumentOutOfRangeException(nameof(frameIndex), $"{nameof(frameIndex)} cannot be less than zero or greater than or equal to the total number of animated tilemap frame elements in this animated tilemap."); + } + + return _frames[frameIndex]; + } + + /// + /// Gets the element at the specified index in this + /// . + /// + /// The index of the element to locate. + /// + /// When this method returns , contains the located; + /// otherwise, . + /// + /// + /// if the element was located; otherwise, + /// . This method returns when the specified index is less than + /// zero or is greater than or equal to the total number of elements in this + /// . + /// + public bool TryGetFrame(int index, out AnimatedTilemapFrame? frame) + { + if (index < 0 || index >= frameCount) + { + frame = default; + return false; + } + + frame = _frames[index]; + return true; + } + + /// + /// Removes the element at the specified index from this + /// . + /// + /// The index of the element to remove. + /// + /// if the was removed successfully; otherwise, + /// . This method returns when the specified index is less than + /// zero or is greater that or equal to the total number of elements in this + /// . + /// + public bool RemoveFrame(int index) + { + if (index < 0 || index >= frameCount) + { + return false; + } + + _frames.RemoveAt(index); + return true; + } + + /// + /// Removes all elements from this . + /// + public void Clear() => _frames.Clear(); + + + /// + /// Draws this using the . + /// + /// + /// The to use for rendering this + /// . + /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color) => + Draw(spriteBatch, position, color, Vector2.One, 0.0f); + + /// + /// Draws this using the . + /// + /// + /// The to use for rendering this + /// . + /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . + /// The amount of scaling to apply when rendering this . + /// The layer depth to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float scale, float layerDepth) => + Draw(spriteBatch, position, color, new Vector2(scale, scale), layerDepth); + + /// + /// Draws this using the . + /// + /// + /// The to use for rendering the + /// . + /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . + /// The amount of scaling to apply when rendering this . + /// The layer depth to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, Vector2 scale, float layerDepth) => + spriteBatch.Draw(this, position, color, scale, layerDepth); + + /// + public IEnumerator GetEnumerator() => _frames.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/source/MonoGame.Aseprite/AnimationFrame.cs b/source/MonoGame.Aseprite/AnimationFrame.cs new file mode 100644 index 00000000..68ef222c --- /dev/null +++ b/source/MonoGame.Aseprite/AnimationFrame.cs @@ -0,0 +1,31 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +namespace MonoGame.Aseprite; + +/// +/// Defines the source and duration of a single frame of animation in an +/// . +/// +public sealed class AnimationFrame +{ + /// + /// Gets the index of the source in the of the + /// . + /// + public int FrameIndex { get; } + + /// + /// Gets the source for this . + /// + public TextureRegion TextureRegion { get; } + + /// + /// Gets the duration of this . + /// + public TimeSpan Duration { get; } + + internal AnimationFrame(int frameIndex, TextureRegion textureRegion, TimeSpan duration) => + (FrameIndex, TextureRegion, Duration) = (frameIndex, textureRegion, duration); +} diff --git a/source/MonoGame.Aseprite/AnimationTag.cs b/source/MonoGame.Aseprite/AnimationTag.cs new file mode 100644 index 00000000..cf2b3af7 --- /dev/null +++ b/source/MonoGame.Aseprite/AnimationTag.cs @@ -0,0 +1,95 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +namespace MonoGame.Aseprite; + +/// +/// Defines the definition of an animation. +/// +public sealed class AnimationTag +{ + private AnimationFrame[] _frames; + + /// + /// Gets the name of the animation + /// + public string Name { get; } + + /// + /// Gets a read-only span of the elements that make up the animation. The order of + /// elements is from first frame to last frame in non-reverse order. + /// + public ReadOnlySpan Frames => _frames; + + /// + /// Gets the total number of , elements. + /// + public int FrameCount => _frames.Length; + + /// + /// Gets the element at the specified index from this . + /// + /// The index of the to locate. + /// The located. + /// + /// Thrown if the specified is less than zero or is greater than or equal to the total + /// number of elements in this . + /// + public AnimationFrame this[int index] => GetFrame(index); + + /// + /// Gets a value that indicates whether the animation should loop. + /// + public bool IsLooping => LoopCount == 0; + + /// + /// Gets or Sets a value that indicates whether the animation should play in reverse. + /// + public bool IsReversed { get; set; } + + /// + /// Gets or Sets a value that indicates whether the animation should ping-pong once reaching the last frame of + /// animation. + /// + public bool IsPingPong { get; set; } + + /// + /// Gets or Sets a value that indicates the total number of loops/cycles of this animation that should play. + /// + /// + /// + /// 0 = infinite looping + /// + /// + /// If is equal to , each direction of the + /// ping-pong will count as a loop. + /// + /// + public int LoopCount { get; set; } + + internal AnimationTag(string name, AnimationFrame[] frames, int loopCount, bool isReversed, bool isPingPong) => + (Name, _frames, LoopCount, IsReversed, IsPingPong) = (name, frames, loopCount, isReversed, isPingPong); + + /// + /// Gets the element at the specified index from this . + /// + /// The index of the to locate. + /// The located. + /// + /// Thrown if the specified is less than zero or is greater than or equal to the total + /// number of elements in this . + /// + public AnimationFrame GetFrame(int index) + { + if (index < 0 || index >= FrameCount) + { + ArgumentOutOfRangeException ex = new(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of animation frames in this animation tag."); + ex.Data.Add(nameof(index), index); + ex.Data.Add(nameof(FrameCount), FrameCount); + throw ex; + } + + return _frames[index]; + } +} diff --git a/source/MonoGame.Aseprite/AnimationTagBuilder.cs b/source/MonoGame.Aseprite/AnimationTagBuilder.cs new file mode 100644 index 00000000..48c49ada --- /dev/null +++ b/source/MonoGame.Aseprite/AnimationTagBuilder.cs @@ -0,0 +1,120 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +namespace MonoGame.Aseprite; + +/// +/// Defines a builder building an for a . +/// +public sealed class AnimationTagBuilder +{ + private string _name; + private List _frames = new(); + private SpriteSheet _spriteSheet; + private int _loopCount = 0; + private bool _isReversed = false; + private bool _isPingPong = false; + + internal AnimationTagBuilder(string name, SpriteSheet spriteSheet) => + (_name, _spriteSheet) = (name, spriteSheet); + + /// + /// Adds a new frame of animation to the using the + /// located at the specified index in the of the and with + /// the specified duration. + /// + /// + /// The index of the source in the of the + /// . + /// + /// The duration of the frame of animation. + /// This instance of the class. + /// + /// Throw if the specified index is less than zero or is greater than or equal to the total number of regions in + /// the . + /// + public AnimationTagBuilder AddFrame(int regionIndex, TimeSpan duration) + { + TextureRegion region = _spriteSheet.TextureAtlas.GetRegion(regionIndex); + AnimationFrame frame = new(regionIndex, region, duration); + _frames.Add(frame); + return this; + } + + /// + /// Adds a new frame of animation to the using the with + /// the specified name in the of the and with the specified + /// duration. + /// + /// + /// The name of the source in the of the + /// . + /// + /// The duration of the frame of animation. + /// This instance of the class. + /// + /// Thrown if the of the does not contain a + /// with the specified name. + /// + public AnimationTagBuilder AddFrame(string regionName, TimeSpan duration) + { + TextureRegion region = _spriteSheet.TextureAtlas.GetRegion(regionName); + int index = _spriteSheet.TextureAtlas.GetIndexOfRegion(regionName); + AnimationFrame frame = new(index, region, duration); + _frames.Add(frame); + return this; + } + + /// + /// Sets the total number of loops/cycles of the animation that should play. + /// + /// + /// + /// 0 = infinite looping + /// + /// + /// If is equal to , each direction of the + /// ping-pong will count as a loop. + /// + /// + /// + /// A value that indicates the total number of loops/cycles of the animation that should play. + /// + /// + /// This instance of the class. + /// + public AnimationTagBuilder LoopCount(int count) + { + _loopCount = count; + return this; + } + + /// + /// Sets whether the animation should play in reverse. + /// + /// A value that indicates whether the animation should play in reverse + /// This instance of the class. + public AnimationTagBuilder IsReversed(bool isReversed) + { + _isReversed = isReversed; + return this; + } + + /// + /// Sets whether the animation should ping-pong once reaching the last frame of animation. + /// + /// A value that indicates whether the animation should ping-pong. + /// This instance of the class. + public AnimationTagBuilder IsPingPong(bool isPingPong) + { + _isPingPong = isPingPong; + return this; + } + + internal AnimationTag Build() + { + AnimationTag tag = new(_name, _frames.ToArray(), _loopCount, _isReversed, _isPingPong); + return tag; + } +} diff --git a/source/MonoGame.Aseprite/AsepriteFileExtensions.cs b/source/MonoGame.Aseprite/AsepriteFileExtensions.cs new file mode 100644 index 00000000..068a99e4 --- /dev/null +++ b/source/MonoGame.Aseprite/AsepriteFileExtensions.cs @@ -0,0 +1,388 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.Processors; +using Microsoft.Xna.Framework.Graphics; +using MonoGame.Aseprite.Utils; +using AseAnimatedTilemap = AsepriteDotNet.AnimatedTilemap; +using AseAnimationFrame = AsepriteDotNet.AnimationFrame; +using AseNinepatchSlice = AsepriteDotNet.NinePatchSlice; +using AseSlice = AsepriteDotNet.Slice; +using AseSprite = AsepriteDotNet.Sprite; +using AseSpriteSheet = AsepriteDotNet.SpriteSheet; +using AseTag = AsepriteDotNet.AnimationTag; +using AseTextureAtlas = AsepriteDotNet.TextureAtlas; +using AseTextureRegion = AsepriteDotNet.TextureRegion; +using AseTilemap = AsepriteDotNet.Tilemap; +using AseTilemapFrame = AsepriteDotNet.TilemapFrame; +using AseTilemapLayer = AsepriteDotNet.TilemapLayer; +using AseTilemapTile = AsepriteDotNet.TilemapTile; +using AseTileset = AsepriteDotNet.Tileset; + + +namespace MonoGame.Aseprite; + +/// +/// Extension methods for working with an Aseprite File loaded by the AsepriteDotNet library. +/// +public static class AsepriteFileExtensions +{ + /// + /// Creates a new from the specified frame index of the provided aseprite file instance. + /// + /// The aseprite file instance. + /// The graphics device used to create graphical resources. + /// The index of the frame in the aseprite file to create the sprite from. + /// The options to use when processing the sprite. + /// The created by this method. + /// + /// Thrown if the parameter is . + /// + /// -or- + /// + /// Thrown if the parameter is . + /// + /// + /// Thrown if is less than zero or greater than or equal to the total number of + /// frames in the aseprite file. + /// + public static Sprite CreateSprite(this AsepriteFile aseFile, GraphicsDevice device, int frameIndex, ProcessorOptions? options = null) + { + ArgumentNullException.ThrowIfNull(aseFile); + ArgumentNullException.ThrowIfNull(device); + + options ??= ProcessorOptions.Default; + AseSprite aseSprite = SpriteProcessor.Process(aseFile, frameIndex, options); + Texture2D texture = aseSprite.Texture.ToTexture2D(device); + TextureRegion region = new TextureRegion(texture.Name, texture, texture.Bounds); + + for (int i = 0; i < aseSprite.Slices.Length; i++) + { + AddSliceToRegion(region, aseSprite.Slices[i]); + } + + return new Sprite(aseSprite.Name, region); + } + + /// + /// Creates a new from the provided aseprite file. + /// + /// The aseprite file instance. + /// The graphics device used to create graphical resources. + /// The options to use when processing the texture atlas.. + /// The created by this method. + /// + /// Thrown if the parameter is . + /// + /// -or- + /// + /// Thrown if the parameter is . + /// + public static TextureAtlas CreateTextureAtlas(this AsepriteFile aseFile, GraphicsDevice device, ProcessorOptions? options = null) + { + ArgumentNullException.ThrowIfNull(aseFile); + ArgumentNullException.ThrowIfNull(device); + + options ??= ProcessorOptions.Default; + AseTextureAtlas aseAtlas = TextureAtlasProcessor.Process(aseFile, options); + Texture2D texture = aseAtlas.Texture.ToTexture2D(device); + TextureAtlas atlas = new TextureAtlas(texture.Name, texture); + GenerateRegions(atlas, aseAtlas); + return atlas; + } + + /// + /// Creates a new from the provided aseprite file. + /// + /// The aseprite file instance. + /// The graphics device used to create graphical resources. + /// The options to use when processing the sprite sheet.. + /// The created by this method. + /// + /// Thrown if the parameter is . + /// + /// -or- + /// + /// Thrown if the parameter is . + /// + public static SpriteSheet CreateSpriteSheet(this AsepriteFile aseFile, GraphicsDevice device, ProcessorOptions? options = null) + { + ArgumentNullException.ThrowIfNull(aseFile); + ArgumentNullException.ThrowIfNull(device); + + options ??= ProcessorOptions.Default; + AseSpriteSheet aseSheet = SpriteSheetProcessor.Process(aseFile, options); + Texture2D texture = aseSheet.TextureAtlas.Texture.ToTexture2D(device); + TextureAtlas atlas = new TextureAtlas(texture.Name, texture); + GenerateRegions(atlas, aseSheet.TextureAtlas); + SpriteSheet sheet = new SpriteSheet(atlas.Name, atlas); + + for (int i = 0; i < aseSheet.Tags.Length; i++) + { + AseTag aseTag = aseSheet.Tags[i]; + sheet.CreateAnimationTag(aseTag.Name, builder => + { + builder.LoopCount(aseTag.LoopCount) + .IsReversed(aseTag.IsReversed) + .IsPingPong(aseTag.IsPingPong); + + for (int j = 0; j < aseTag.Frames.Length; j++) + { + AseAnimationFrame aseAnimationFrame = aseTag.Frames[j]; + builder.AddFrame(aseAnimationFrame.FrameIndex, aseAnimationFrame.Duration); + } + }); + } + + + return sheet; + } + + /// + /// Creates a new from the frame at the specified index in provided aseprite file. + /// + /// The aseprite file instance. + /// The graphics device used to create graphical resources. + /// The index of the frame that contains the tileset. + /// The created by this method. + /// + /// Thrown if the parameter is . + /// + /// -or- + /// + /// Throw if the is less than zero or greater than or equal to the total number of + /// frames in the aseprite file + /// + /// -or- + /// + /// Thrown if the parameter is . + /// + public static Tileset CreateTileset(this AsepriteFile aseFile, GraphicsDevice device, int frameIndex) + { + ArgumentNullException.ThrowIfNull(aseFile); + ArgumentNullException.ThrowIfNull(device); + + AseTileset aseTileset = TilesetProcessor.Process(aseFile, frameIndex); + return aseTileset.CreateTileset(device); + } + + /// + /// Creates a new with the specified name in provided aseprite file. + /// + /// The aseprite file instance. + /// The graphics device used to create graphical resources. + /// The name of the tileset. + /// The created by this method. + /// + /// Thrown if the parameter is . + /// + /// -or- + /// + /// Thrown if the parameter is . + /// + /// + /// Throw if no tileset with the specified exists in the aseprite file. + /// + public static Tileset CreateTileset(this AsepriteFile aseFile, GraphicsDevice device, string tilesetName) + { + ArgumentNullException.ThrowIfNull(aseFile); + ArgumentNullException.ThrowIfNull(device); + + AseTileset aseTileset = TilesetProcessor.Process(aseFile, tilesetName); + return aseTileset.CreateTileset(device); + } + + /// + /// Creates a new from the specified aseprite tileset. + /// + /// The Aseprite tileset to create the tileset from.. + /// The graphics device used to create graphical resources. + /// The created by this method. + /// + /// Thrown if the parameter is . + /// + /// -or- + /// + /// Thrown if the parameter is . + /// + public static Tileset CreateTileset(this AseTileset aseTileset, GraphicsDevice device) + { + ArgumentNullException.ThrowIfNull(aseTileset); + ArgumentNullException.ThrowIfNull(device); + + Texture2D texture = aseTileset.Texture.ToTexture2D(device); + return new Tileset(aseTileset.Name, + texture, + aseTileset.TileSize.Width, + aseTileset.TileSize.Height); + } + + /// + /// Creates a new from a specified frame in the provided aseprite file. + /// + /// The aseprite file instance. + /// The graphics device used to create graphical resources. + /// The index of the frame with the tilemap. + /// The options to use when processing the tilemap. + /// The created by this method. + /// + /// Thrown if is . + /// + /// -or- + /// + /// throw if is . + /// + public static Tilemap CreateTilemap(this AsepriteFile aseFile, GraphicsDevice device, int frameIndex, ProcessorOptions? options = null) + { + ArgumentNullException.ThrowIfNull(aseFile); + ArgumentNullException.ThrowIfNull(device); + + options ??= ProcessorOptions.Default; + AseTilemap aseTilemap = TilemapProcessor.Process(aseFile, frameIndex, options); + Tilemap tilemap = new Tilemap(aseTilemap.Name); + Dictionary tilesets = GenereateTilesets(device, aseTilemap); + + for (int i = 0; i < aseTilemap.Layers.Length; i++) + { + AseTilemapLayer aseTilemapLayer = aseTilemap.Layers[i]; + Tileset tileset = tilesets[aseTilemapLayer.TilesetID]; + TilemapLayer tilemapLayer = tilemap.CreateLayer(aseTilemapLayer.Name, + tileset, + aseTilemapLayer.Columns, + aseTilemapLayer.Rows, + aseTilemapLayer.Offset.ToXnaVector2()); + + for (int t = 0; t < aseTilemapLayer.Tiles.Length; t++) + { + AseTilemapTile aseTilemapTile = aseTilemapLayer.Tiles[t]; + tilemapLayer.SetTile(t, + aseTilemapTile.TilesetTileID, + aseTilemapTile.FlipHorizontally, + aseTilemapTile.FlipVertically, + aseTilemapTile.FlipDiagonally); + } + } + + return tilemap; + } + + /// + /// Creates a new from the all frames in the provided aseprite file. + /// + /// The aseprite file instance. + /// The graphics device used to create graphical resources. + /// The options to use when processing the animated tilemap. + /// the created by this method. + /// + /// Thrown if is . + /// + /// -or- + /// + /// throw if is . + /// + public static AnimatedTilemap CreateAnimatedTilemap(this AsepriteFile aseFile, GraphicsDevice device, ProcessorOptions? options = null) + { + ArgumentNullException.ThrowIfNull(aseFile); + ArgumentNullException.ThrowIfNull(device); + + options ??= ProcessorOptions.Default; + AseAnimatedTilemap aseAnimatedTilemap = AnimatedTilemapProcessor.Process(aseFile, options); + AnimatedTilemap animatedTilemap = new AnimatedTilemap(aseAnimatedTilemap.Name); + Dictionary tilesets = new Dictionary(); + + ParallelOptions parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }; + for (int i = 0; i < aseAnimatedTilemap.Tilesets.Length; i++) + { + AseTileset aseTileset = aseAnimatedTilemap.Tilesets[i]; + Texture2D texture = aseTileset.Texture.ToTexture2D(device); + Tileset tileset = new Tileset(aseTileset.Name, + texture, + aseTileset.TileSize.Width, + aseTileset.TileSize.Height); + tilesets.Add(aseTileset.ID, tileset); + } + + for (int i = 0; i < aseAnimatedTilemap.Frames.Length; i++) + { + AseTilemapFrame aseTilemapFrame = aseAnimatedTilemap.Frames[i]; + AnimatedTilemapFrame animatedTilemapFrame = animatedTilemap.CreateFrame(aseTilemapFrame.Duration); + + for (int l = 0; l < aseTilemapFrame.Layers.Length; l++) + { + AseTilemapLayer aseTilemapLayer = aseTilemapFrame.Layers[l]; + TilemapLayer tilemapLayer = animatedTilemapFrame.CreateLayer(aseTilemapLayer.Name, + tilesets[aseTilemapLayer.TilesetID], + aseTilemapLayer.Columns, + aseTilemapLayer.Rows, + aseTilemapLayer.Offset.ToXnaVector2()); + + for (int t = 0; t < aseTilemapLayer.Tiles.Length; t++) + { + AseTilemapTile aseTilemapTile = aseTilemapLayer.Tiles[t]; + tilemapLayer.SetTile(t, + aseTilemapTile.TilesetTileID, + aseTilemapTile.FlipHorizontally, + aseTilemapTile.FlipVertically, + aseTilemapTile.FlipDiagonally); + } + } + } + + + return animatedTilemap; + } + + + private static void GenerateRegions(TextureAtlas atlas, AseTextureAtlas aseAtlas) + { + for (int i = 0; i < aseAtlas.Regions.Length; i++) + { + AseTextureRegion aseRegion = aseAtlas.Regions[i]; + TextureRegion region = atlas.CreateRegion(aseRegion.Name, aseRegion.Bounds.ToXnaRectangle()); + + for (int j = 0; j < aseRegion.Slices.Length; j++) + { + AddSliceToRegion(region, aseRegion.Slices[j]); + } + } + + } + + private static void AddSliceToRegion(TextureRegion region, AseSlice aseSlice) + { + if (aseSlice is AseNinepatchSlice aseNinePatchSlice) + { + region.CreateNinePatchSlice(aseNinePatchSlice.Name, + aseNinePatchSlice.Bounds.ToXnaRectangle(), + aseNinePatchSlice.CenterBounds.ToXnaRectangle(), + aseNinePatchSlice.Origin.ToXnaVector2(), + aseNinePatchSlice.Color.ToXnaColor()); + } + else + { + region.CreateSlice(aseSlice.Name, + aseSlice.Bounds.ToXnaRectangle(), + aseSlice.Origin.ToXnaVector2(), + aseSlice.Color.ToXnaColor()); + } + } + + private static Dictionary GenereateTilesets(GraphicsDevice device, AseTilemap aseTilemap) + { + Dictionary result = new Dictionary(); + for (int i = 0; i < aseTilemap.Tilesets.Length; i++) + { + AseTileset aseTileset = aseTilemap.Tilesets[i]; + Texture2D texture = aseTileset.Texture.ToTexture2D(device); + Tileset tileset = new Tileset(aseTileset.Name, + texture, + aseTileset.TileSize.Width, + aseTileset.TileSize.Height); + result.Add(aseTileset.ID, tileset); + } + + return result; + } +} diff --git a/source/MonoGame.Aseprite/Content/Pipeline/Readers/AnimatedTilemapContentTypeReader.cs b/source/MonoGame.Aseprite/Content/Pipeline/Readers/AnimatedTilemapContentTypeReader.cs deleted file mode 100644 index acd0c439..00000000 --- a/source/MonoGame.Aseprite/Content/Pipeline/Readers/AnimatedTilemapContentTypeReader.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Tilemaps; - -namespace MonoGame.Aseprite.Content.Pipeline.Readers; - -internal sealed class AnimatedTilemapContentTypeReader : ContentTypeReader -{ - protected override AnimatedTilemap Read(ContentReader reader, AnimatedTilemap? existingInstance) - { - if (existingInstance is not null) - { - return existingInstance; - } - - string name = reader.ReadString(); - AnimatedTilemap animatedTilemap = new(name); - Dictionary tilesets = ReadTilesets(reader); - RawTilemapFrame[] rawFrames = reader.ReadRawTilemapFrames(); - - for (int f = 0; f < rawFrames.Length; f++) - { - RawTilemapFrame rawFrame = rawFrames[f]; - TimeSpan duration = TimeSpan.FromMilliseconds(rawFrame.DurationInMilliseconds); - AnimatedTilemapFrame animatedTilemapFrame = animatedTilemap.CreateFrame(duration); - - for (int l = 0; l < rawFrame.RawTilemapLayers.Length; l++) - { - RawTilemapLayer rawLayer = rawFrame.RawTilemapLayers[l]; - TilemapLayer tilemapLayer = animatedTilemapFrame.CreateLayer(rawLayer.Name, tilesets[rawLayer.TilesetID], rawLayer.Columns, rawLayer.Rows, rawLayer.Offset.ToVector2()); - - for (int t = 0; t < rawLayer.RawTilemapTiles.Length; t++) - { - RawTilemapTile rawTile = rawLayer.RawTilemapTiles[t]; - tilemapLayer.SetTile(t, rawTile.TilesetTileID, rawTile.FlipVertically, rawTile.FlipHorizontally, rawTile.FlipDiagonally); - } - } - } - - return animatedTilemap; - } - - private Dictionary ReadTilesets(ContentReader reader) - { - Dictionary tilesets = new(); - - int count = reader.ReadInt32(); - for (int i = 0; i < count; i++) - { - string name = reader.ReadString(); - int id = reader.ReadInt32(); - int tileWidth = reader.ReadInt32(); - int tileHeight = reader.ReadInt32(); - Texture2D texture = reader.ReadObject(); - Tileset tileset = new(name, texture, tileWidth, tileHeight); - tilesets.Add(id, tileset); - } - - return tilesets; - } -} diff --git a/source/MonoGame.Aseprite/Content/Pipeline/Readers/AsepriteFileContentTypeReader.cs b/source/MonoGame.Aseprite/Content/Pipeline/Readers/AsepriteFileContentTypeReader.cs index bef1d92c..36ec4d90 100644 --- a/source/MonoGame.Aseprite/Content/Pipeline/Readers/AsepriteFileContentTypeReader.cs +++ b/source/MonoGame.Aseprite/Content/Pipeline/Readers/AsepriteFileContentTypeReader.cs @@ -1,29 +1,10 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. +using AsepriteDotNet.Aseprite; +using AsepriteDotNet.IO; using Microsoft.Xna.Framework.Content; -using MonoGame.Aseprite.Content.Readers; namespace MonoGame.Aseprite.Content.Pipeline.Readers; @@ -31,16 +12,17 @@ internal sealed class AsepriteFileContentTypeReader : ContentTypeReader -{ - protected override Sprite Read(ContentReader reader, Sprite? existingInstance) - { - if (existingInstance is not null) - { - return existingInstance; - } - - string name = reader.ReadString(); - Texture2D texture = reader.ReadObject(); - return new(name, texture); - } -} diff --git a/source/MonoGame.Aseprite/Content/Pipeline/Readers/SpriteSheetContentTypeReader.cs b/source/MonoGame.Aseprite/Content/Pipeline/Readers/SpriteSheetContentTypeReader.cs deleted file mode 100644 index fa88349e..00000000 --- a/source/MonoGame.Aseprite/Content/Pipeline/Readers/SpriteSheetContentTypeReader.cs +++ /dev/null @@ -1,91 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Sprites; - -namespace MonoGame.Aseprite.Content.Pipeline.Readers; - -internal sealed class SpriteSheetContentTypeReader : ContentTypeReader -{ - protected override SpriteSheet Read(ContentReader reader, SpriteSheet? existingInstance) - { - if (existingInstance is not null) - { - return existingInstance; - } - - string spriteSheetName = reader.ReadString(); - string textureAtlasName = reader.ReadString(); - - Texture2D texture = reader.ReadObject(); - TextureAtlas textureAtlas = new(textureAtlasName, texture); - - RawTextureRegion[] rawTextureRegions = reader.ReadRawTextureRegions(); - - for (int i = 0; i < rawTextureRegions.Length; i++) - { - RawTextureRegion rawTextureRegion = rawTextureRegions[i]; - - TextureRegion textureRegion = textureAtlas.CreateRegion(rawTextureRegion.Name, rawTextureRegion.Bounds); - - foreach (RawSlice rawSlice in rawTextureRegion.Slices) - { - if (rawSlice is RawNinePatchSlice rawNinePatchSlice) - { - textureRegion.CreateNinePatchSlice(rawNinePatchSlice.Name, rawNinePatchSlice.Bounds, rawNinePatchSlice.CenterBounds, rawNinePatchSlice.Origin, rawNinePatchSlice.Color); - } - else - { - textureRegion.CreateSlice(rawSlice.Name, rawSlice.Bounds, rawSlice.Origin, rawSlice.Color); - } - } - } - - SpriteSheet spriteSheet = new(spriteSheetName, textureAtlas); - RawAnimationTag[] tags = reader.ReadRawAnimationTags(); - for (int i = 0; i < tags.Length; i++) - { - RawAnimationTag tag = tags[i]; - - spriteSheet.CreateAnimationTag(tag.Name, builder => - { - builder.LoopCount(tag.LoopCount) - .IsReversed(tag.IsReversed) - .IsPingPong(tag.IsPingPong); - - for (int j = 0; j < tag.RawAnimationFrames.Length; j++) - { - RawAnimationFrame rawAnimationFrame = tag.RawAnimationFrames[j]; - TimeSpan duration = TimeSpan.FromMilliseconds(rawAnimationFrame.DurationInMilliseconds); - builder.AddFrame(rawAnimationFrame.FrameIndex, duration); - } - }); - } - - return spriteSheet; - } -} diff --git a/source/MonoGame.Aseprite/Content/Pipeline/Readers/TextureAtlasContentTypeReader.cs b/source/MonoGame.Aseprite/Content/Pipeline/Readers/TextureAtlasContentTypeReader.cs deleted file mode 100644 index 2158d4c1..00000000 --- a/source/MonoGame.Aseprite/Content/Pipeline/Readers/TextureAtlasContentTypeReader.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Sprites; - -namespace MonoGame.Aseprite.Content.Pipeline.Readers; - -internal sealed class TextureAtlasContentTypeReader : ContentTypeReader -{ - protected override TextureAtlas Read(ContentReader reader, TextureAtlas? existingInstance) - { - if (existingInstance is not null) - { - return existingInstance; - } - - string name = reader.ReadString(); - Texture2D texture = reader.ReadObject(); - TextureAtlas textureAtlas = new(name, texture); - - RawTextureRegion[] rawTextureRegions = reader.ReadRawTextureRegions(); - - for (int i = 0; i < rawTextureRegions.Length; i++) - { - RawTextureRegion rawTextureRegion = rawTextureRegions[i]; - - TextureRegion textureRegion = textureAtlas.CreateRegion(rawTextureRegion.Name, rawTextureRegion.Bounds); - - foreach (RawSlice rawSlice in rawTextureRegion.Slices) - { - if (rawSlice is RawNinePatchSlice rawNinePatchSlice) - { - textureRegion.CreateNinePatchSlice(rawNinePatchSlice.Name, rawNinePatchSlice.Bounds, rawNinePatchSlice.CenterBounds, rawNinePatchSlice.Origin, rawNinePatchSlice.Color); - } - else - { - textureRegion.CreateSlice(rawSlice.Name, rawSlice.Bounds, rawSlice.Origin, rawSlice.Color); - } - } - } - - return textureAtlas; - } -} diff --git a/source/MonoGame.Aseprite/Content/Pipeline/Readers/TilemapContentTypeReader.cs b/source/MonoGame.Aseprite/Content/Pipeline/Readers/TilemapContentTypeReader.cs deleted file mode 100644 index 36636a36..00000000 --- a/source/MonoGame.Aseprite/Content/Pipeline/Readers/TilemapContentTypeReader.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Tilemaps; - -namespace MonoGame.Aseprite.Content.Pipeline.Readers; - -internal sealed class TilemapContentTypeReader : ContentTypeReader -{ - protected override Tilemap Read(ContentReader reader, Tilemap? existingInstance) - { - if (existingInstance is not null) - { - return existingInstance; - } - - string name = reader.ReadString(); - Tilemap tilemap = new(name); - - Dictionary tilesets = ReadTilesets(reader); - RawTilemapLayer[] layers = reader.ReadRawTilemapLayers(); - - for (int i = 0; i < layers.Length; i++) - { - RawTilemapLayer rawLayer = layers[i]; - Tileset tileset = tilesets[rawLayer.TilesetID]; - - TilemapLayer layer = tilemap.CreateLayer(rawLayer.Name, tileset, rawLayer.Columns, rawLayer.Rows, rawLayer.Offset.ToVector2()); - for (int j = 0; j < rawLayer.RawTilemapTiles.Length; j++) - { - RawTilemapTile rawTile = rawLayer.RawTilemapTiles[j]; - layer.SetTile(j, rawTile.TilesetTileID, rawTile.FlipVertically, rawTile.FlipHorizontally, rawTile.FlipDiagonally); - } - } - - return tilemap; - } - - private Dictionary ReadTilesets(ContentReader reader) - { - Dictionary tilesets = new(); - - int count = reader.ReadInt32(); - for (int i = 0; i < count; i++) - { - string name = reader.ReadString(); - int id = reader.ReadInt32(); - int tileWidth = reader.ReadInt32(); - int tileHeight = reader.ReadInt32(); - Texture2D texture = reader.ReadObject(); - Tileset tileset = new(name, texture, tileWidth, tileHeight); - tilesets.Add(id, tileset); - } - - return tilesets; - } -} diff --git a/source/MonoGame.Aseprite/Content/Pipeline/Readers/TilesetContentTypeReader.cs b/source/MonoGame.Aseprite/Content/Pipeline/Readers/TilesetContentTypeReader.cs deleted file mode 100644 index 50dd0695..00000000 --- a/source/MonoGame.Aseprite/Content/Pipeline/Readers/TilesetContentTypeReader.cs +++ /dev/null @@ -1,46 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Content; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.Tilemaps; - -namespace MonoGame.Aseprite.Content.Pipeline.Readers; - -internal sealed class TilesetContentTypeReader : ContentTypeReader -{ - protected override Tileset Read(ContentReader reader, Tileset? existingInstance) - { - if (existingInstance is not null) - { - return existingInstance; - } - - string name = reader.ReadString(); - int tileWidth = reader.ReadInt32(); - int tileHeight = reader.ReadInt32(); - Texture2D texture = reader.ReadObject(); - return new(name, texture, tileWidth, tileHeight); - } -} diff --git a/source/MonoGame.Aseprite/Content/Processors/AnimatedTilemapProcessor.cs b/source/MonoGame.Aseprite/Content/Processors/AnimatedTilemapProcessor.cs deleted file mode 100644 index ffde632f..00000000 --- a/source/MonoGame.Aseprite/Content/Processors/AnimatedTilemapProcessor.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Tilemaps; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -/// Defines a processor that processes an from an . -/// -/// -public static partial class AnimatedTilemapProcessor -{ - /// - /// Processes an from the given . - /// - /// - /// When using this processor, all elements from the - /// are processed. elements - /// are ignored at this time (though may be implemented to support tags in the future). Only - /// elements in each frame are processed to - /// generate the tile data. - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to processed the from. - /// - /// - /// Indicates if only layers that are visible should be processed. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if layers are found in the with duplicate names. Tilemaps must contain - /// layers with unique names even though Aseprite does not enforce unique names for layers. - /// - /// - /// - public static AnimatedTilemap Process(GraphicsDevice device, AsepriteFile aseFile, bool onlyVisibleLayers = true) - { - RawAnimatedTilemap rawTilemap = ProcessRaw(aseFile, onlyVisibleLayers); - return AnimatedTilemap.FromRaw(device, rawTilemap); - } -} diff --git a/source/MonoGame.Aseprite/Content/Processors/SpriteProcessor.cs b/source/MonoGame.Aseprite/Content/Processors/SpriteProcessor.cs deleted file mode 100644 index 101a32c8..00000000 --- a/source/MonoGame.Aseprite/Content/Processors/SpriteProcessor.cs +++ /dev/null @@ -1,76 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Sprites; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -/// Defines a processor that processes a from an frame in an -/// -/// -public static partial class SpriteProcessor -{ - /// - /// Processes a from the at the specified index in the given - /// - /// - /// - /// The used to create graphical resources. - /// - /// - /// The that contains the to processes. - /// - /// - /// The index of the in the to process. - /// - /// - /// Indicates if only elements on visible elements should - /// be included. - /// - /// - /// Indicates if on the marked as the background layer - /// should be included. - /// - /// - /// Indicates if on a should be included. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the specified frame index is less than zero or is greater than or equal to the total number - /// elements in the given . - /// - /// - /// - public static Sprite Process(GraphicsDevice device, AsepriteFile aseFile, int aseFrameIndex, bool onlyVisibleLayers = true, bool includeBackgroundLayer = false, bool includeTilemapLayers = true) - { - RawSprite rawSprite = ProcessRaw(aseFile, aseFrameIndex, onlyVisibleLayers, includeBackgroundLayer, includeTilemapLayers); - return Sprite.FromRaw(device, rawSprite); - } -} diff --git a/source/MonoGame.Aseprite/Content/Processors/SpriteSheetProcessor.cs b/source/MonoGame.Aseprite/Content/Processors/SpriteSheetProcessor.cs deleted file mode 100644 index 1ff1d55a..00000000 --- a/source/MonoGame.Aseprite/Content/Processors/SpriteSheetProcessor.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Sprites; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -/// Defines a processor that processes a from an . -/// -/// -public static partial class SpriteSheetProcessor -{ - /// - /// Processes a from the given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to process the from. - /// - /// - /// Indicates if only elements on visible elements should - /// be included. - /// - /// - /// Indicates if elements on the elements marked as the - /// background layer should be included. - /// - /// - /// Indicates if elements on a element should be - /// included. - /// - /// Indicates if duplicate elements should be merged into one. - /// - /// - /// The amount of transparent pixels to add between the edge of the generated image - /// - /// - /// The amount of transparent pixels to add between each texture region in the generated image. - /// - /// - /// The amount of transparent pixels to add around the edge of each texture region in the generated image. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if elements are found in the with duplicate - /// names. A must contain tags with unique names even though aseprite does not - /// enforce unique names for elements. - /// - /// - /// - public static SpriteSheet Process(GraphicsDevice device, AsepriteFile aseFile, bool onlyVisibleLayers = true, bool includeBackgroundLayer = false, bool includeTilemapLayers = true, bool mergeDuplicates = true, int borderPadding = 0, int spacing = 0, int innerPadding = 0) - { - RawSpriteSheet rawSpritSheet = ProcessRaw(aseFile, onlyVisibleLayers, includeBackgroundLayer, includeTilemapLayers, mergeDuplicates, borderPadding, spacing, innerPadding); - return SpriteSheet.FromRaw(device, rawSpritSheet); - } -} - diff --git a/source/MonoGame.Aseprite/Content/Processors/TextureAtlasProcessor.cs b/source/MonoGame.Aseprite/Content/Processors/TextureAtlasProcessor.cs deleted file mode 100644 index eeb3c1d8..00000000 --- a/source/MonoGame.Aseprite/Content/Processors/TextureAtlasProcessor.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Sprites; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -/// Defines a processor that processes a from an aseprite file. -/// -/// -public static partial class TextureAtlasProcessor -{ - /// - /// Processes a from the given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to process the from. - /// - /// - /// Indicates if only elements on visible elements should - /// be included. - /// - /// - /// Indicates if elements on the elements marked as the - /// background layer should be included. - /// - /// - /// Indicates if elements on a element should be - /// included. - /// - /// Indicates if duplicate elements should be merged into one. - /// - /// - /// The amount of transparent pixels to add between the edge of the generated image - /// - /// - /// The amount of transparent pixels to add between each texture region in the generated image. - /// - /// - /// The amount of transparent pixels to add around the edge of each texture region in the generated image. - /// - /// - /// The created by this method. - /// - /// - /// - public static Sprites.TextureAtlas Process(GraphicsDevice device, AsepriteFile aseFile, bool onlyVisibleLayers = true, bool includeBackgroundLayer = false, bool includeTilemapLayers = true, bool mergeDuplicates = true, int borderPadding = 0, int spacing = 0, int innerPadding = 0) - { - RawTextureAtlas rawAtlas = ProcessRaw(aseFile, onlyVisibleLayers, includeBackgroundLayer, includeTilemapLayers, mergeDuplicates, borderPadding, spacing, innerPadding); - return TextureAtlas.FromRaw(device, rawAtlas); - } -} diff --git a/source/MonoGame.Aseprite/Content/Processors/TilemapProcessor.cs b/source/MonoGame.Aseprite/Content/Processors/TilemapProcessor.cs deleted file mode 100644 index ed242090..00000000 --- a/source/MonoGame.Aseprite/Content/Processors/TilemapProcessor.cs +++ /dev/null @@ -1,73 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Tilemaps; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -/// Defines a processor that processes a from an . -/// -/// -public static partial class TilemapProcessor -{ - /// - /// Processes a from the at the specified index in the given - /// . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The that contains the animated to process. - /// - /// - /// The index of the element in the to process. - /// - /// - /// Indicates if only elements that are visible should be processed. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the frame index specified is less than zero or is greater than or equal to the total number of - /// elements in the given . - /// - /// - /// Thrown if elements are found in the with duplicate - /// names. A must contain layers with unique names even though aseprite does not enforce - /// unique names for elements. - /// - /// - /// - public static Tilemap Process(GraphicsDevice device, AsepriteFile aseFile, int frameIndex, bool onlyVisibleLayers = true) - { - RawTilemap rawTilemap = ProcessRaw(aseFile, frameIndex, onlyVisibleLayers); - return Tilemap.FromRaw(device, rawTilemap); - } -} diff --git a/source/MonoGame.Aseprite/Content/Processors/TilesetProcessor.cs b/source/MonoGame.Aseprite/Content/Processors/TilesetProcessor.cs deleted file mode 100644 index 9a54790c..00000000 --- a/source/MonoGame.Aseprite/Content/Processors/TilesetProcessor.cs +++ /dev/null @@ -1,114 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.RawTypes; -using MonoGame.Aseprite.Tilemaps; - -namespace MonoGame.Aseprite.Content.Processors; - -/// -/// Defines a processor that processes a from an . -/// -/// -public static partial class TilesetProcessor -{ - /// - /// Processes a from the element at the specified index in the - /// given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The that contains the to processes. - /// - /// - /// The index of the element in the to processes. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in the given . - /// - /// - /// - public static Tileset Process(GraphicsDevice device, AsepriteFile aseFile, int tilesetIndex) - { - AsepriteTileset aseTileset = aseFile.GetTileset(tilesetIndex); - return Process(device, aseTileset); - } - - /// - /// Processes a from the with the specified name in the - /// given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The that contains the to process. - /// - /// - /// The name of the element in the to process. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if the given does not contain an element - /// with the specified name. - /// - /// - /// - public static Tileset Process(GraphicsDevice device, AsepriteFile aseFile, string tilesetName) - { - AsepriteTileset aseTileset = aseFile.GetTileset(tilesetName); - return Process(device, aseTileset); - } - - /// - /// Processes a from an . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to process. - /// - /// - /// The created by this method. - /// - /// - /// - /// - public static Tileset Process(GraphicsDevice device, AsepriteTileset aseTileset) - { - RawTileset rawTileset = ProcessRaw(aseTileset); - return Tileset.FromRaw(device, rawTileset); - } -} diff --git a/source/MonoGame.Aseprite/MonoGame.Aseprite.csproj b/source/MonoGame.Aseprite/MonoGame.Aseprite.csproj index 6a7af45c..98e15cbc 100644 --- a/source/MonoGame.Aseprite/MonoGame.Aseprite.csproj +++ b/source/MonoGame.Aseprite/MonoGame.Aseprite.csproj @@ -1,86 +1,48 @@  - - net6.0 - enable - enable - True - 5.1.3 - + - Christopher Whitley - Aristurtle - Copyright (c) 2018 - 2023 Christoipher Whitley - https://monogameaseprite.net - https://github.com/AristurtleDev/monogame-aseprite - git - main - en + net6.0;net8.0 + true - + MonoGame.Aseprite - MIT - https://monogameaseprite.net - icon.png - - MonoGame;Aseprite;import;processes;read;write;sprite;animation;tileset;tilemap;spritesheet;pipeline;mgcb - - README.md - - Version 5.1.3 - - Added `MonoGame.Aseprite.Configuration` - - When set to `false` this will assume frame index gets from the `AsepriteFile` start at index 1 and not 0. - - Removed `MonoGame.Aserpite.Configuration` - - Moved `ZeroIndexedFrames` to be property of `AsepriteFile` - - Added unit testing for `AsepriteFile.ZeroIndexedFrames` functionality - - Added proper support for new tile rotation introduced in Aseprite 1.3 - - Read Old Palette Chunk for Indexed mode due to Aseprite 1.3.5 file spec change - - MonoGame.Aseprite is a cross-platofrm C# library that adds support to MonoGame projects for + MonoGame.Aseprite is a cross-platform C# library that adds support to MonoGame projects for Aseprite (.asepirte/.ase) files. - + - - + + - + - + - - All - + + - + <_Parameter1>MonoGame.Aseprite.Tests - - - <_Parameter1>MonoGame.Aseprite.Content.Pipeline - + - + NU5100 - - - - - \ No newline at end of file diff --git a/source/MonoGame.Aseprite/NinePatchSlice.cs b/source/MonoGame.Aseprite/NinePatchSlice.cs index 1200779c..94870ac1 100644 --- a/source/MonoGame.Aseprite/NinePatchSlice.cs +++ b/source/MonoGame.Aseprite/NinePatchSlice.cs @@ -1,39 +1,19 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. using Microsoft.Xna.Framework; namespace MonoGame.Aseprite; /// -/// Defines a with center bounds. +/// Defines a with center bounds. /// public sealed class NinePatchSlice : Slice { /// - /// Gets the rectangular bounds of the center rectangle for this , - /// relative to it's bounds. + /// Gets the rectangular bounds of the center rectangle for this , + /// relative to it's bounds. /// public Rectangle CenterBounds { get; } diff --git a/source/MonoGame.Aseprite/Slice.cs b/source/MonoGame.Aseprite/Slice.cs index bb1d93df..fe6cda39 100644 --- a/source/MonoGame.Aseprite/Slice.cs +++ b/source/MonoGame.Aseprite/Slice.cs @@ -1,56 +1,36 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. using Microsoft.Xna.Framework; namespace MonoGame.Aseprite; /// -/// Defines a named slice for a with a bounds, origin, and color. +/// Defines a named slice for a with a bounds, origin, and color. /// public class Slice { /// - /// Gets the name assigned to this . + /// Gets the name assigned to this . /// public string Name { get; } /// - /// Gets the rectangular bounds of this relative to the bounds of the - /// it is in. + /// Gets the rectangular bounds of this relative to the bounds of the + /// it is in. /// public Rectangle Bounds { get; } /// - /// Gets the x- and y-coordinate origin point for this relative to the - /// upper-left corner of the bonds of the it is in. + /// Gets the x- and y-coordinate origin point for this relative to the + /// upper-left corner of the bonds of the it is in. /// public Vector2 Origin { get; } /// - /// Gets the value assigned to this - /// . + /// Gets the value assigned to this + /// . /// public Color Color { get; } diff --git a/source/MonoGame.Aseprite/Sprite.cs b/source/MonoGame.Aseprite/Sprite.cs new file mode 100644 index 00000000..58659e4b --- /dev/null +++ b/source/MonoGame.Aseprite/Sprite.cs @@ -0,0 +1,188 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace MonoGame.Aseprite; + +/// +/// Defines a named sprite +/// +public class Sprite +{ + private TextureRegion _textureRegion; + + private Vector2 _origin; + private Vector2 _scale; + private float _transparency; + + /// + /// Gets the name assigned to this . + /// + public string Name { get; } + + /// + /// Gets the source of this . + /// + public TextureRegion TextureRegion + { + get => _textureRegion; + protected set => _textureRegion = value; + } + + /// + /// Gets the width, in pixels, of this + /// + public int Width => _textureRegion.Bounds.Width; + + /// + /// Gets the height, in pixels, of this + /// + public int Height => _textureRegion.Bounds.Height; + + /// + /// Gets or Sets the color mask to apply when rendering this . + /// + public Color Color { get; set; } + + /// + /// Gets or Sets the level of transparency, between 0.0f, and 1.0f, to apply when rendering this + /// . + /// + public float Transparency + { + get => _transparency; + set => _transparency = MathHelper.Clamp(value, 0.0f, 1.0f); + } + + /// + /// Gets or Sets the rotation, in radians, to apply when rendering this . + /// + public float Rotation { get; set; } + + /// + /// Gets or Sets the x- and y-coordinate point of origin to apply when rendering this . + /// + public Vector2 Origin + { + get => _origin; + set => _origin = value; + } + + /// + /// Gets or Sets the x-coordinate point of origin to apply when rendering this . + /// + public float OriginX + { + get => _origin.X; + set => _origin.X = value; + } + + /// + /// Gets or Sets the y-coordinate point of origin to apply when rendering this . + /// + public float OriginY + { + get => _origin.Y; + set => _origin.Y = value; + } + + /// + /// Gets or Sets the x- and y-axis scale factor to use when rendering this . + /// + public Vector2 Scale + { + get => _scale; + set => _scale = value; + } + + /// + /// Gets or Sets the x-axis scale factor to use when rendering this . + /// + public float ScaleX + { + get => _scale.X; + set => _scale.X = value; + } + + /// + /// Gets or Sets the y-axis scale factor to use when rendering this . + /// + public float ScaleY + { + get => _scale.Y; + set => _scale.Y = value; + } + + /// + /// Gets or Sets the to apply for vertical and + /// horizontal flipping when rendering this . + /// + public SpriteEffects SpriteEffects { get; set; } + + /// + /// Gets or Sets a value that indicates whether to flip this horizontally when rendering. + /// + public bool FlipHorizontally + { + get => SpriteEffects.HasFlag(SpriteEffects.FlipHorizontally); + set => SpriteEffects = value ? SpriteEffects | SpriteEffects.FlipHorizontally : SpriteEffects & ~SpriteEffects.FlipHorizontally; + } + + /// + /// Gets or Sets a value that indicates whether to flip this vertically when rendering. + /// + public bool FlipVertically + { + get => SpriteEffects.HasFlag(SpriteEffects.FlipVertically); + set => SpriteEffects = value ? SpriteEffects | SpriteEffects.FlipVertically : SpriteEffects & ~SpriteEffects.FlipVertically; + } + + /// + /// Gets or Sets the layer depth to render this at. + /// + public float LayerDepth { get; set; } + + /// + /// Gets or Sets a value that indicates if this is visible and can be rendered. + /// + public bool IsVisible { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The name to assign the . + /// + /// The source to assign the . + /// + public Sprite(string name, TextureRegion textureRegion) + { + _textureRegion = textureRegion; + Color = Color.White; + _transparency = 1.0f; + Rotation = 0.0f; + _origin = Vector2.Zero; + _scale = Vector2.One; + SpriteEffects = SpriteEffects.None; + LayerDepth = 0.0f; + IsVisible = true; + Name = name; + } + + /// + /// Initializes a new instance of the class. + /// + /// The name to assign the . + /// The source image for the . + public Sprite(string name, Texture2D texture) + : this(name, new TextureRegion(name, texture, texture.Bounds)) { } + + /// + /// Renders this . + /// + /// The to use for rendering this. + /// The x- and y-coordinate location to render this at. + public void Draw(SpriteBatch spriteBatch, Vector2 position) => spriteBatch.Draw(this, position); +} diff --git a/source/MonoGame.Aseprite/SpriteBatchExtensions.cs b/source/MonoGame.Aseprite/SpriteBatchExtensions.cs index c44c2db7..2440af56 100644 --- a/source/MonoGame.Aseprite/SpriteBatchExtensions.cs +++ b/source/MonoGame.Aseprite/SpriteBatchExtensions.cs @@ -1,31 +1,9 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.Sprites; -using MonoGame.Aseprite.Tilemaps; namespace MonoGame.Aseprite; @@ -37,155 +15,116 @@ public static class SpriteBatchExtensions #region Texture Region /// - /// Draws a using the . + /// Draws a using the . /// /// - /// The to use for rendering. - /// - /// - /// The to render. + /// The to use for rendering. /// + /// The to render. /// - /// A rectangular bound that defines the destination to render the into. - /// - /// - /// The color mask to apply when rendering the . + /// A rectangular bound that defines the destination to render the into. /// + /// The color mask to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TextureRegion region, Rectangle destinationRectangle, Color color) => spriteBatch.Draw(region.Texture, destinationRectangle, region.Bounds, color); /// - /// Draws a using the . + /// Draws a using the . /// /// - /// The to use for rendering. - /// - /// - /// The to render. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . + /// The to use for rendering. /// + /// The to render. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TextureRegion region, Vector2 position, Color color) => spriteBatch.Draw(region.Texture, position, region.Bounds, color); /// - /// Draws a using the . + /// Draws a using the . /// /// - /// The to use for rendering. - /// - /// - /// The to render. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . + /// The to use for rendering. /// + /// The to render. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . /// - /// The amount of rotation, in radians, to apply when rendering the . + /// The amount of rotation, in radians, to apply when rendering the . /// /// - /// The x- and y-coordinate point of origin to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . + /// The x- and y-coordinate point of origin to apply when rendering the . /// + /// The amount of scaling to apply when rendering the . /// - /// The to apply for horizontal and vertical axis - /// flipping when rendering the . - /// - /// - /// The layer depth to apply when rendering the . + /// The to apply for horizontal and vertical axis + /// flipping when rendering the . /// + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TextureRegion region, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) => spriteBatch.Draw(region.Texture, position, region.Bounds, color, rotation, origin, scale, effects, layerDepth); + /// - /// Draws a using the . + /// Draws a using the . /// /// - /// The to use for rendering. - /// - /// - /// The to render. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . + /// The to use for rendering. /// + /// The to render. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . /// - /// The amount of rotation, in radians, to apply when rendering the . + /// The amount of rotation, in radians, to apply when rendering the . /// /// - /// The x- and y-coordinate point of origin to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . + /// The x- and y-coordinate point of origin to apply when rendering the . /// + /// The amount of scaling to apply when rendering the . /// - /// The to apply for horizontal and vertical axis - /// flipping when rendering the . - /// - /// - /// The layer depth to apply when rendering the . + /// The to apply for horizontal and vertical axis + /// flipping when rendering the . /// + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TextureRegion region, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) => spriteBatch.Draw(region.Texture, position, region.Bounds, color, rotation, origin, scale, effects, layerDepth); /// - /// Draws a using the . + /// Draws a using the . /// /// - /// The to use for rendering. - /// - /// - /// The to render. + /// The to use for rendering. /// + /// The to render. /// - /// A rectangular bound that defines the destination to render the into. - /// - /// - /// The color mask to apply when rendering the . + /// A rectangular bound that defines the destination to render the into. /// + /// The color mask to apply when rendering the . /// - /// The amount of rotation, in radians, to apply when rendering the . + /// The amount of rotation, in radians, to apply when rendering the . /// /// - /// The x- and y-coordinate point of origin to apply when rendering the . + /// The x- and y-coordinate point of origin to apply when rendering the . /// /// - /// The to apply for horizontal and vertical axis - /// flipping when rendering the . - /// - /// - /// The layer depth to apply when rendering the . + /// The to apply for horizontal and vertical axis + /// flipping when rendering the . /// + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TextureRegion region, Rectangle destinationRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth) => spriteBatch.Draw(region.Texture, destinationRectangle, region.Bounds, color, rotation, origin, effects, layerDepth); #endregion Texture Region /// - /// Draws a using the . + /// Draws a using the . /// /// - /// The to use for rendering the - /// . + /// The to use for rendering the . /// - /// - /// The to render. - /// - /// - /// The x- and y-coordinate location to render the at. + /// The to render. /// + /// The x- and y-coordinate location to render the at. public static void Draw(this SpriteBatch spriteBatch, Sprite sprite, Vector2 position) => spriteBatch.Draw(sprite.TextureRegion, position, sprite.Color * sprite.Transparency, sprite.Rotation, sprite.Origin, sprite.Scale, sprite.SpriteEffects, sprite.LayerDepth); @@ -193,71 +132,45 @@ public static void Draw(this SpriteBatch spriteBatch, Sprite sprite, Vector2 pos #region Animated Tilemap /// - /// Draws an using the . + /// Draws an using the . /// /// - /// The to use for rendering the - /// . - /// - /// - /// The to draw. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . + /// The to use for rendering the + /// . /// + /// The to draw. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, AnimatedTilemap animatedTilemap, Vector2 position, Color color) => Draw(spriteBatch, animatedTilemap, position, color, Vector2.One, 0.0f); /// - /// Draws an using the . + /// Draws an using the . /// /// - /// The to use for rendering the - /// . - /// - /// - /// The to draw. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . - /// - /// - /// The layer depth to apply when rendering the . - /// + /// The to use for rendering the + /// . + /// + /// The to draw. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . + /// The amount of scaling to apply when rendering the . + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, AnimatedTilemap animatedTilemap, Vector2 position, Color color, float scale, float layerDepth) => Draw(spriteBatch, animatedTilemap, position, color, new Vector2(scale, scale), layerDepth); /// - /// Draws an using the . + /// Draws an using the . /// /// - /// The to use for rendering the - /// . - /// - /// - /// The to draw. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . - /// - /// - /// The layer depth to apply when rendering the . - /// + /// The to use for rendering the + /// . + /// + /// The to draw. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . + /// The amount of scaling to apply when rendering the . + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, AnimatedTilemap animatedTilemap, Vector2 position, Color color, Vector2 scale, float layerDepth) { AnimatedTilemapFrame frame = animatedTilemap.CurrentFrame; @@ -277,68 +190,42 @@ public static void Draw(this SpriteBatch spriteBatch, AnimatedTilemap animatedTi #region Tilemap /// - /// Draws a using the . + /// Draws a using the . /// /// /// The to use for rendering the . /// - /// - /// The to draw. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . - /// + /// The to draw. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, Tilemap tilemap, Vector2 position, Color color) => Draw(spriteBatch, tilemap, position, color, Vector2.One, 0.0f); /// - /// Draws a using the . + /// Draws a using the . /// /// /// The to use for rendering the . /// - /// - /// The to draw. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . - /// - /// - /// The layer depth to apply when rendering the . - /// + /// The to draw. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . + /// The amount of scaling to apply when rendering the . + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, Tilemap tilemap, Vector2 position, Color color, float scale, float layerDepth) => Draw(spriteBatch, tilemap, position, color, new Vector2(scale, scale), layerDepth); /// - /// Draws a using the . + /// Draws a using the . /// /// /// The to use for rendering the . /// - /// - /// The to draw. - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . - /// - /// - /// The layer depth to apply when rendering the . - /// + /// The to draw. + /// The x- and y-coordinate location to render the at. + /// The color mask to apply when rendering the . + /// The amount of scaling to apply when rendering the . + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, Tilemap tilemap, Vector2 position, Color color, Vector2 scale, float layerDepth) { foreach (TilemapLayer layer in tilemap) @@ -356,77 +243,55 @@ public static void Draw(this SpriteBatch spriteBatch, Tilemap tilemap, Vector2 p #region Tilemap Layer /// - /// Draws a layer using the - /// . + /// Draws a layer using the . /// /// - /// The to use for rendering the - /// . - /// - /// - /// The to draw. + /// The to use for rendering the + /// . /// + /// The to draw. /// - /// The x- and y-coordinate location to draw the at. Drawing the - /// using this method ignores the . - /// - /// - /// The color mask to apply when rendering the . + /// The x- and y-coordinate location to draw the at. Drawing the + /// using this method ignores the . /// + /// The color mask to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TilemapLayer layer, Vector2 position, Color color) => Draw(spriteBatch, layer, position, color, Vector2.One, 0.0f); /// - /// Draws a layer using the - /// . + /// Draws a layer using the . /// /// - /// The to use for rendering the - /// . - /// - /// - /// The to draw. + /// The to use for rendering the + /// . /// + /// The to draw. /// - /// The x- and y-coordinate location to draw the at. Drawing the - /// using this method ignores the . - /// - /// - /// The color mask to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . - /// - /// - /// The layer depth to apply when rendering the . + /// The x- and y-coordinate location to draw the at. Drawing the + /// using this method ignores the . /// + /// The color mask to apply when rendering the . + /// The amount of scaling to apply when rendering the . + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TilemapLayer layer, Vector2 position, Color color, float scale, float layerDepth) => Draw(spriteBatch, layer, position, color, new Vector2(scale, scale), layerDepth); + /// - /// Draws a layer using the - /// . + /// Draws a layer using the . /// /// - /// The to use for rendering the - /// . - /// - /// - /// The to draw. + /// The to use for rendering the + /// . /// + /// The to draw. /// - /// The x- and y-coordinate location to draw the at. Drawing the - /// using this method ignores the . - /// - /// - /// The color mask to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . - /// - /// - /// The layer depth to apply when rendering the . + /// The x- and y-coordinate location to draw the at. Drawing the + /// using this method ignores the . /// + /// The color mask to apply when rendering the . + /// The amount of scaling to apply when rendering the . + /// The layer depth to apply when rendering the . public static void Draw(this SpriteBatch spriteBatch, TilemapLayer layer, Vector2 position, Color color, Vector2 scale, float layerDepth) { Vector2 tPosition = position; @@ -445,15 +310,9 @@ public static void Draw(this SpriteBatch spriteBatch, TilemapLayer layer, Vector SpriteEffects flipEffects = DetermineFlipEffectForTile(tile.FlipHorizontally, tile.FlipVertically, tile.FlipDiagonally); float rotation = tile.FlipDiagonally ? MathHelper.ToRadians(90.0f) : 0.0f; - // Since Aseprite allows tile rotation now, tile are rotated in Aseprite based on - // center origin. So we need an origin point, as well as to offset the position - // draw due to the origin point. - Vector2 origin = new Vector2(layer.Tileset.TileWidth, layer.Tileset.TileHeight) * 0.5f; - tPosition += origin; - TextureRegion textureRegion = layer.Tileset[tile.TilesetTileID]; - Draw(spriteBatch, textureRegion, tPosition, renderColor, rotation, origin, scale, flipEffects, layerDepth); + Draw(spriteBatch, textureRegion, tPosition, renderColor, rotation, Vector2.Zero, scale, flipEffects, layerDepth); } } } @@ -461,14 +320,14 @@ public static void Draw(this SpriteBatch spriteBatch, TilemapLayer layer, Vector private static SpriteEffects DetermineFlipEffectForTile(bool flipHorizontally, bool flipVertically, bool flipDiagonally) { SpriteEffects effects = SpriteEffects.None; - if(!flipDiagonally) + if (!flipDiagonally) { - if(flipHorizontally) + if (flipHorizontally) { effects |= SpriteEffects.FlipHorizontally; } - if(flipVertically) + if (flipVertically) { effects |= SpriteEffects.FlipVertically; } diff --git a/source/MonoGame.Aseprite/SpriteSheet.cs b/source/MonoGame.Aseprite/SpriteSheet.cs new file mode 100644 index 00000000..b3df85b2 --- /dev/null +++ b/source/MonoGame.Aseprite/SpriteSheet.cs @@ -0,0 +1,253 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Diagnostics.CodeAnalysis; + +namespace MonoGame.Aseprite; + +/// +/// Defines a spritesheet with a source and methods for creating +/// and elements. +/// +public sealed class SpriteSheet +{ + private static readonly TimeSpan s_defaultDuration = TimeSpan.FromMilliseconds(100); + + private Dictionary _animationTagLookup = new(); + + /// + /// Gets the total number of elements that have been defined for this + /// . + /// + public int AnimationTagCount => _animationTagLookup.Count; + + /// + /// Gets the name assigned to this . + /// + public string Name { get; } + + /// + /// Gets the source of this . + /// + public TextureAtlas TextureAtlas { get; } + + /// + /// Initializes a new instance of the class. + /// + /// The name assign the . + /// The source to give the . + public SpriteSheet(string name, TextureAtlas atlas) => (Name, TextureAtlas) = (name, atlas); + + /// + /// Creates a new from the at the specified index in the + /// of this . + /// + /// The name to assign the that is created. + /// + /// The index of the element in the assign the + /// that is created. + /// + /// The that is created by this method. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in the . + /// + public Sprite CreateSprite(string spriteName, int regionIndex) + { + TextureRegion region = TextureAtlas.GetRegion(regionIndex); + Sprite sprite = new(spriteName, region); + return sprite; + } + + /// + /// Creates a new from the at the specified index in the + /// of this . + /// + /// + /// The index of the element to assign the that is created. + /// + /// The that is created by this method. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in the . + /// + public Sprite CreateSprite(int regionIndex) + { + TextureRegion region = TextureAtlas.GetRegion(regionIndex); + Sprite sprite = new(region.Name, region); + return sprite; + } + + /// + /// Creates a new from the at the specified index in the + /// of this . + /// + /// The name to assign the that is created. + /// + /// The name of the element in the assign the + /// that is created. + /// + /// The that is created by this method. + /// + /// Thrown if the does not contain a with the name + /// specified. + /// + public Sprite CreateSprite(string spriteName, string regionName) + { + TextureRegion region = TextureAtlas.GetRegion(regionName); + Sprite sprite = new(spriteName, region); + return sprite; + } + + /// + /// Creates a new from the at the specified index in the + /// of this . + /// + /// + /// The name of the element in the assign the + /// that is created. + /// + /// The that is created by this method. + /// + /// Thrown if the does not contain a with the name + /// specified. + /// + public Sprite CreateSprite(string regionName) + { + TextureRegion region = TextureAtlas.GetRegion(regionName); + Sprite sprite = new(region.Name, region); + return sprite; + } + + #region Animations + + internal void AddAnimationTag(AnimationTag tag) + { + if (_animationTagLookup.ContainsKey(tag.Name)) + { + throw new InvalidOperationException($"{nameof(SpriteSheet)} '{Name}' already contains an {nameof(AnimationTag)} with the name '{tag.Name}'"); + } + + _animationTagLookup.Add(tag.Name, tag); + } + + /// + /// Creates a new and adds it to this . + /// + /// + /// The name to assign the that is created by this method. This name must be unique + /// across all elements defined in this . + /// + /// + /// An method used to build the with an + /// . + /// + /// The that is created by this method. + /// + /// Thrown if this already contains an element with the + /// name specified. + /// + public AnimationTag CreateAnimationTag(string name, Action builder) + { + AnimationTagBuilder localBuilder = new(name, this); + builder(localBuilder); + + AnimationTag tag = localBuilder.Build(); + AddAnimationTag(tag); + + return tag; + } + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the to locate. + /// The that was located. + /// + /// Thrown if this does not contain an element with the + /// specified name. + /// + public AnimationTag GetAnimationTag(string name) + { + if (TryGetAnimationTag(name, out AnimationTag? tag)) + { + return tag; + } + + throw new KeyNotFoundException($"{nameof(SpriteSheet)} '{Name}' does not contain an {nameof(AnimationTag)} with the name '{name}'"); + } + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the to locate. + /// + /// When this method returns , contains the located; otherwise, + /// + /// + /// + /// if the was located; otherwise, . + /// This method returns if this does not contain an + /// element with the specified name. + /// + public bool TryGetAnimationTag(string name, [NotNullWhen(true)] out AnimationTag? tag) => + _animationTagLookup.TryGetValue(name, out tag); + + /// + /// Returns a new containing the name of all elements that + /// have been defined in this . + /// + /// + /// A new containing the name of all elements that have been + /// defined in this . + /// + public List GetAnimationTagNames() => _animationTagLookup.Keys.ToList(); + + /// + /// Returns a value that indicates whether this contains an + /// with the specified name. + /// + /// The name of the element to locate. + /// + /// if this contains an with the + /// specified name; otherwise, . + /// + public bool ContainsAnimationTag(string name) => _animationTagLookup.ContainsKey(name); + + /// + /// Removes the element with the specified name from this . + /// + /// + /// The name of the element to remove from this . + /// + /// + /// if the element was successfully removed from this + /// ; otherwise, . This method returns + /// if this does not contain an element with the specified + /// name. + /// + public bool RemoveAnimationTag(string name) => _animationTagLookup.Remove(name); + + /// + /// Creates a new using the element with the specified + /// name in this . + /// + /// + /// The name of the element in this to create the + /// with. + /// + /// The that is created by this method. + /// + /// Thrown if this does not contain an element with the + /// specified name. + /// + public AnimatedSprite CreateAnimatedSprite(string tagName) + { + AnimationTag tag = GetAnimationTag(tagName); + AnimatedSprite sprite = new(tag); + return sprite; + } + + #endregion Animations +} diff --git a/source/MonoGame.Aseprite/Sprites/AnimationFrame.cs b/source/MonoGame.Aseprite/Sprites/AnimationFrame.cs deleted file mode 100644 index a870bd3c..00000000 --- a/source/MonoGame.Aseprite/Sprites/AnimationFrame.cs +++ /dev/null @@ -1,51 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.Sprites; - -/// -/// Defines the source and duration of a single frame of animation in an -/// . -/// -public sealed class AnimationFrame -{ - /// - /// Gets the index of the source in the of the - /// . - /// - public int FrameIndex { get; } - - /// - /// Gets the source for this . - /// - public TextureRegion TextureRegion { get; } - - /// - /// Gets the duration of this . - /// - public TimeSpan Duration { get; } - - internal AnimationFrame(int frameIndex, TextureRegion textureRegion, TimeSpan duration) => - (FrameIndex, TextureRegion, Duration) = (frameIndex, textureRegion, duration); -} diff --git a/source/MonoGame.Aseprite/Sprites/AnimationTag.cs b/source/MonoGame.Aseprite/Sprites/AnimationTag.cs deleted file mode 100644 index 0fd9ca91..00000000 --- a/source/MonoGame.Aseprite/Sprites/AnimationTag.cs +++ /dev/null @@ -1,123 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.Sprites; - -/// -/// Defines the definition of an animation. -/// -public sealed class AnimationTag -{ - private AnimationFrame[] _frames; - - /// - /// Gets the name of the animation - /// - public string Name { get; } - - /// - /// Gets a read-only span of the elements that make up the animation. The order of - /// elements is from first frame to last frame in non-reverse order. - /// - public ReadOnlySpan Frames => _frames; - - /// - /// Gets the total number of , elements. - /// - public int FrameCount => _frames.Length; - - /// - /// Gets the element at the specified index from this . - /// - /// - /// The index of the to locate. - /// - /// - /// The located. - /// - /// - /// Thrown if the specified is less than zero or is greater than or equal to the total - /// number of elements in this . - /// - public AnimationFrame this[int index] => GetFrame(index); - - /// - /// Gets a value that indicates whether the animation should loop. - /// - public bool IsLooping => LoopCount == 0; - - /// - /// Gets or Sets a value that indicates whether the animation should play in reverse. - /// - public bool IsReversed { get; set; } - - /// - /// Gets or Sets a value that indicates whether the animation should ping-pong once reaching the last frame of - /// animation. - /// - public bool IsPingPong { get; set; } - - /// - /// Gets or Sets a value that indicates the total number of loops/cycles of this animation that should play. - /// - /// - /// - /// 0 = infinite looping - /// - /// - /// If is equal to , each direction of the - /// ping-pong will count as a loop. - /// - /// - public int LoopCount { get; set; } - - internal AnimationTag(string name, AnimationFrame[] frames, int loopCount, bool isReversed, bool isPingPong) => - (Name, _frames, LoopCount, IsReversed, IsPingPong) = (name, frames, loopCount, isReversed, isPingPong); - - /// - /// Gets the element at the specified index from this . - /// - /// - /// The index of the to locate. - /// - /// - /// The located. - /// - /// - /// Thrown if the specified is less than zero or is greater than or equal to the total - /// number of elements in this . - /// - public AnimationFrame GetFrame(int index) - { - if (index < 0 || index >= FrameCount) - { - ArgumentOutOfRangeException ex = new(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of animation frames in this animation tag."); - ex.Data.Add(nameof(index), index); - ex.Data.Add(nameof(FrameCount), FrameCount); - throw ex; - } - - return _frames[index]; - } -} diff --git a/source/MonoGame.Aseprite/Sprites/AnimationTagBuilder.cs b/source/MonoGame.Aseprite/Sprites/AnimationTagBuilder.cs deleted file mode 100644 index 959aabfa..00000000 --- a/source/MonoGame.Aseprite/Sprites/AnimationTagBuilder.cs +++ /dev/null @@ -1,156 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.Sprites; - -/// -/// Defines a builder building an for a . -/// -public sealed class AnimationTagBuilder -{ - private string _name; - private List _frames = new(); - private SpriteSheet _spriteSheet; - private int _loopCount = 0; - private bool _isReversed = false; - private bool _isPingPong = false; - - internal AnimationTagBuilder(string name, SpriteSheet spriteSheet) => - (_name, _spriteSheet) = (name, spriteSheet); - - /// - /// Adds a new frame of animation to the using the - /// located at the specified index in the of the and with - /// the specified duration. - /// - /// - /// The index of the source in the of the - /// . - /// - /// - /// The duration of the frame of animation. - /// - /// - /// This instance of the class. - /// - /// - /// Throw if the specified index is less than zero or is greater than or equal to the total number of regions in - /// the . - /// - public AnimationTagBuilder AddFrame(int regionIndex, TimeSpan duration) - { - TextureRegion region = _spriteSheet.TextureAtlas.GetRegion(regionIndex); - AnimationFrame frame = new(regionIndex, region, duration); - _frames.Add(frame); - return this; - } - - /// - /// Adds a new frame of animation to the using the with - /// the specified name in the of the and with the specified - /// duration. - /// - /// - /// The name of the source in the of the - /// . - /// - /// - /// The duration of the frame of animation. - /// - /// - /// This instance of the class. - /// - /// - /// Thrown if the of the does not contain a - /// with the specified name. - /// - public AnimationTagBuilder AddFrame(string regionName, TimeSpan duration) - { - TextureRegion region = _spriteSheet.TextureAtlas.GetRegion(regionName); - int index = _spriteSheet.TextureAtlas.GetIndexOfRegion(regionName); - AnimationFrame frame = new(index, region, duration); - _frames.Add(frame); - return this; - } - - /// - /// Sets the total number of loops/cycles of the animation that should play. - /// - /// - /// - /// 0 = infinite looping - /// - /// - /// If is equal to , each direction of the - /// ping-pong will count as a loop. - /// - /// - /// - /// A value that indicates the total number of loops/cycles of the animation that should play. - /// - /// - /// This instance of the class. - /// - public AnimationTagBuilder LoopCount(int count) - { - _loopCount = count; - return this; - } - - /// - /// Sets whether the animation should play in reverse. - /// - /// - /// A value that indicates whether the animation should play in reverse - /// - /// - /// This instance of the class. - /// - public AnimationTagBuilder IsReversed(bool isReversed) - { - _isReversed = isReversed; - return this; - } - - /// - /// Sets whether the animation should ping-pong once reaching the last frame of animation. - /// - /// - /// A value that indicates whether the animation should ping-pong. - /// - /// - /// This instance of the class. - /// - public AnimationTagBuilder IsPingPong(bool isPingPong) - { - _isPingPong = isPingPong; - return this; - } - - internal AnimationTag Build() - { - AnimationTag tag = new(_name, _frames.ToArray(), _loopCount, _isReversed, _isPingPong); - return tag; - } -} diff --git a/source/MonoGame.Aseprite/Sprites/Sprite.cs b/source/MonoGame.Aseprite/Sprites/Sprite.cs deleted file mode 100644 index 13f26a2d..00000000 --- a/source/MonoGame.Aseprite/Sprites/Sprite.cs +++ /dev/null @@ -1,350 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Sprites; - -/// -/// -/// Defines a named sprite -/// -/// -/// The class is a general purpose wrapper around a -/// with properties to control how it is rendered. When creating -/// a from an , it represents the image of the frame used to -/// create it. -/// -/// -/// The most common methods for creating a will be either by using the -/// to create an instance from a frame in -/// your Aseprite File, or by using a to create a from one of -/// the regions in the atlas. An instance can also be created manually using the constructor for a more general -/// purpose use. -/// -/// -/// -/// -/// The , , , -/// , and are passed automatically to the -/// when rendering this sprite. For one-off rendering -/// where you can override the parameter values passed to the -/// , you can render the -/// instead. -/// -/// -/// ### Performance Considerations -/// -/// -/// If you plan to create multiple instances from various frames in your Aseprite file, -/// consider first creating a , then creating each instance -/// using the . By doing this, you will be generating a single source -/// for the . Each -/// that is then created from the will be references the single -/// source instead of separate instances per -/// . -/// -/// -/// This is beneficial because it reduces the amount of texture swapping done on the -/// when rendering the -/// instances. -/// -/// -/// -/// -/// The following examples demonstrate various ways to create a : -/// -/// -/// // Load an Aseprite file -/// AsepriteFile aseFile = AsepriteFile.Load("path-to-file"); -/// -/// // Use the SpriteProcessor to create a Sprite -/// Sprite sprite = SpriteProcessor.Process(GraphicsDevice, aseFile, frameIndex: 0); -/// -/// -/// -/// // Load an Aseprite File -/// AsepriteFile aseFile = AsepriteFile.Load("path-to-file") -/// -/// // Create a TextureAtlas from the AsepriteFile using the TextureAtlasProcessor -/// TextureAtlas atlas = TextureAtlasProcessor.Process(GraphicsDevice, aseFile); -/// -/// // Create a Sprite from region 0 in the TextureAtlas -/// Sprite sprite = atlas.CreateSprite(regionIndex: 0); -/// -/// -/// -/// // Load an Aseprite File -/// AsepriteFile aseFile = AsepriteFile.Load("path-to-file") -/// -/// // Create a SpriteSheet from the AsepriteFile using the SpriteSheetProcessor -/// SpriteSheet spriteSheet = SpriteSheetProcessor.Process(GraphicsDevice, aseFile); -/// -/// // Create a Sprite from region 0 in the SpriteSheet -/// Sprite sprite = spriteSheet.CreateSprite(regionIndex: 0); -/// -/// -/// -/// -/// -/// -/// -/// -public class Sprite -{ - private TextureRegion _textureRegion; - - private Vector2 _origin; - private Vector2 _scale; - private float _transparency; - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the source of this . - /// - public TextureRegion TextureRegion - { - get => _textureRegion; - protected set => _textureRegion = value; - } - - /// - /// Gets the width, in pixels, of this - /// - /// - /// The width, in pixels, of this . - /// - public int Width => _textureRegion.Bounds.Width; - - /// - /// Gets the height, in pixels, of this - /// - /// - /// The height, in pixels, of this . - /// - public int Height => _textureRegion.Bounds.Height; - - /// - /// Gets or Sets the color mask to apply when rendering this . - /// - /// - /// The color mask to apply when rendering this . - /// - public Color Color { get; set; } - - /// - /// Gets or Sets the level of transparency, between 0.0f, and 1.0f, to apply when rendering this - /// . - /// - public float Transparency - { - get => _transparency; - set => _transparency = MathHelper.Clamp(value, 0.0f, 1.0f); - } - - /// - /// Gets or Sets the rotation, in radians, to apply when rendering this . - /// - public float Rotation { get; set; } - - /// - /// Gets or Sets the x- and y-coordinate point of origin to apply when rendering this . - /// - public Vector2 Origin - { - get => _origin; - set => _origin = value; - } - - /// - /// Gets or Sets the x-coordinate point of origin to apply when rendering this . - /// - public float OriginX - { - get => _origin.X; - set => _origin.X = value; - } - - /// - /// Gets or Sets the y-coordinate point of origin to apply when rendering this . - /// - public float OriginY - { - get => _origin.Y; - set => _origin.Y = value; - } - - /// - /// Gets or Sets the x- and y-axis scale factor to use when rendering this . - /// - public Vector2 Scale - { - get => _scale; - set => _scale = value; - } - - /// - /// Gets or Sets the x-axis scale factor to use when rendering this . - /// - public float ScaleX - { - get => _scale.X; - set => _scale.X = value; - } - - /// - /// Gets or Sets the y-axis scale factor to use when rendering this . - /// - public float ScaleY - { - get => _scale.Y; - set => _scale.Y = value; - } - - /// - /// Gets or Sets the to apply for vertical and - /// horizontal flipping when rendering this . - /// - public SpriteEffects SpriteEffects { get; set; } - - /// - /// Gets or Sets a value that indicates whether to flip this horizontally when rendering. - /// - public bool FlipHorizontally - { - get => SpriteEffects.HasFlag(SpriteEffects.FlipHorizontally); - set => SpriteEffects = value ? (SpriteEffects | SpriteEffects.FlipHorizontally) : (SpriteEffects & ~SpriteEffects.FlipHorizontally); - } - - /// - /// Gets or Sets a value that indicates whether to flip this vertically when rendering. - /// - public bool FlipVertically - { - get => SpriteEffects.HasFlag(SpriteEffects.FlipVertically); - set => SpriteEffects = value ? (SpriteEffects | SpriteEffects.FlipVertically) : (SpriteEffects & ~SpriteEffects.FlipVertically); - } - - /// - /// Gets or Sets the layer depth to render this at. - /// - public float LayerDepth { get; set; } - - /// - /// Gets or Sets a value that indicates if this is visible and can be rendered. - /// - public bool IsVisible { get; set; } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The name to assign the . - /// - /// - /// The source to assign the . - /// - public Sprite(string name, TextureRegion textureRegion) - { - _textureRegion = textureRegion; - Color = Color.White; - _transparency = 1.0f; - Rotation = 0.0f; - _origin = Vector2.Zero; - _scale = Vector2.One; - SpriteEffects = SpriteEffects.None; - LayerDepth = 0.0f; - IsVisible = true; - Name = name; - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The name to assign the . - /// - /// - /// The source image for the . - /// - public Sprite(string name, Texture2D texture) - : this(name, new TextureRegion(name, texture, texture.Bounds)) { } - - /// - /// Renders this . - /// - /// - /// The to use for rendering this - /// . - /// - /// - /// The x- and y-coordinate location to render this at. - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position) => spriteBatch.Draw(this, position); - - /// - /// Creates a new instance of the class from the given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to create the from. - /// - /// - /// The created by this method. - /// - public static Sprite FromRaw(GraphicsDevice device, RawSprite rawSprite) - { - RawTexture rawTexture = rawSprite.RawTexture; - - Texture2D texture = new(device, rawTexture.Width, rawTexture.Height, mipmap: false, SurfaceFormat.Color); - texture.Name = rawTexture.Name; - texture.SetData(rawTexture.Pixels.ToArray()); - - TextureRegion textureRegion = new(texture.Name, texture, texture.Bounds); - - for (int i = 0; i < rawSprite.Slices.Length; i++) - { - RawSlice slice = rawSprite.Slices[i]; - - if (slice is RawNinePatchSlice ninePatch) - { - _ = textureRegion.CreateNinePatchSlice(ninePatch.Name, ninePatch.Bounds, ninePatch.CenterBounds, ninePatch.Origin, ninePatch.Color); - } - else - { - _ = textureRegion.CreateSlice(slice.Name, slice.Bounds, slice.Origin, slice.Color); - } - } - - return new(rawSprite.Name, textureRegion); - } -} diff --git a/source/MonoGame.Aseprite/Sprites/SpriteSheet.cs b/source/MonoGame.Aseprite/Sprites/SpriteSheet.cs deleted file mode 100644 index 215a7a09..00000000 --- a/source/MonoGame.Aseprite/Sprites/SpriteSheet.cs +++ /dev/null @@ -1,338 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Sprites; - -/// -/// Defines a spritesheet with a source and methods for creating -/// and elements. -/// -public sealed class SpriteSheet -{ - private static readonly TimeSpan s_defaultDuration = TimeSpan.FromMilliseconds(100); - - private Dictionary _animationTagLookup = new(); - - /// - /// Gets the total number of elements that have been defined for this - /// . - /// - public int AnimationTagCount => _animationTagLookup.Count; - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the source of this . - /// - public TextureAtlas TextureAtlas { get; } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The name assign the . - /// - /// - /// The source to give the . - /// - public SpriteSheet(string name, TextureAtlas atlas) => (Name, TextureAtlas) = (name, atlas); - - /// - /// Creates a new from the at the specified index in the - /// of this . - /// - /// - /// The name to assign the that is created. - /// - /// - /// The index of the element in the assign the - /// that is created. - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in the . - /// - public Sprite CreateSprite(string spriteName, int regionIndex) - { - TextureRegion region = TextureAtlas.GetRegion(regionIndex); - Sprite sprite = new(spriteName, region); - return sprite; - } - - /// - /// Creates a new from the at the specified index in the - /// of this . - /// - /// - /// The index of the element to assign the that is created. - /// - /// The that is created by this method. - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in the . - /// - public Sprite CreateSprite(int regionIndex) - { - TextureRegion region = TextureAtlas.GetRegion(regionIndex); - Sprite sprite = new(region.Name, region); - return sprite; - } - - /// - /// Creates a new from the at the specified index in the - /// of this . - /// - /// - /// The name to assign the that is created. - /// - /// - /// The name of the element in the assign the - /// that is created. - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if the does not contain a with the name - /// specified. - /// - public Sprite CreateSprite(string spriteName, string regionName) - { - TextureRegion region = TextureAtlas.GetRegion(regionName); - Sprite sprite = new(spriteName, region); - return sprite; - } - - /// - /// Creates a new from the at the specified index in the - /// of this . - /// - /// - /// The name of the element in the assign the - /// that is created. - /// - /// The that is created by this method. - /// - /// Thrown if the does not contain a with the name - /// specified. - /// - public Sprite CreateSprite(string regionName) - { - TextureRegion region = TextureAtlas.GetRegion(regionName); - Sprite sprite = new(region.Name, region); - return sprite; - } - - #region Animations - - internal void AddAnimationTag(AnimationTag tag) - { - if (_animationTagLookup.ContainsKey(tag.Name)) - { - throw new InvalidOperationException($"{nameof(SpriteSheet)} '{Name}' already contains an {nameof(AnimationTag)} with the name '{tag.Name}'"); - } - - _animationTagLookup.Add(tag.Name, tag); - } - - /// - /// Creates a new and adds it to this . - /// - /// - /// The name to assign the that is created by this method. This name must be unique - /// across all elements defined in this . - /// - /// - /// An method used to build the with an - /// . - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if this already contains an element with the - /// name specified. - /// - public AnimationTag CreateAnimationTag(string name, Action builder) - { - AnimationTagBuilder localBuilder = new(name, this); - builder(localBuilder); - - AnimationTag tag = localBuilder.Build(); - AddAnimationTag(tag); - - return tag; - } - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the to locate. - /// - /// - /// The that was located. - /// - /// - /// Thrown if this does not contain an element with the - /// specified name. - /// - public AnimationTag GetAnimationTag(string name) - { - if (TryGetAnimationTag(name, out AnimationTag? tag)) - { - return tag; - } - - throw new KeyNotFoundException($"{nameof(SpriteSheet)} '{Name}' does not contain an {nameof(AnimationTag)} with the name '{name}'"); - } - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the to locate. - /// - /// - /// When this method returns , contains the located; otherwise, - /// - /// - /// - /// if the was located; otherwise, . - /// This method returns if this does not contain an - /// element with the specified name. - /// - public bool TryGetAnimationTag(string name, [NotNullWhen(true)] out AnimationTag? tag) => - _animationTagLookup.TryGetValue(name, out tag); - - /// - /// Returns a new containing the name of all elements that - /// have been defined in this . - /// - /// - /// A new containing the name of all elements that have been - /// defined in this . - /// - public List GetAnimationTagNames() => _animationTagLookup.Keys.ToList(); - - /// - /// Returns a value that indicates whether this contains an - /// with the specified name. - /// - /// - /// The name fo the element to locate. - /// - /// - /// if this contains an with the - /// specified name; otherwise, . - /// - public bool ContainsAnimationTag(string name) => _animationTagLookup.ContainsKey(name); - - /// - /// Removes the element with the specified name from this . - /// - /// - /// The name of the element to remove from this . - /// - /// - /// if the element was successfully removed from this - /// ; otherwise, . This method returns - /// if this does not contain an element with the specified - /// name. - /// - public bool RemoveAnimationTag(string name) => _animationTagLookup.Remove(name); - - /// - /// Creates a new using the element with the specified - /// name in this . - /// - /// - /// The name of the element in this to create the - /// with. - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if this does not contain an element with the - /// specified name. - /// - public AnimatedSprite CreateAnimatedSprite(string tagName) - { - AnimationTag tag = GetAnimationTag(tagName); - AnimatedSprite sprite = new(tag); - return sprite; - } - - #endregion Animations - - /// - /// Creates a new instance of the class from the given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to create the from. - /// - /// - /// The created by this method. - /// - public static SpriteSheet FromRaw(GraphicsDevice device, RawSpriteSheet rawSpriteSheet) - { - TextureAtlas atlas = TextureAtlas.FromRaw(device, rawSpriteSheet.RawTextureAtlas); - SpriteSheet spriteSheet = new(rawSpriteSheet.Name, atlas); - - for (int i = 0; i < rawSpriteSheet.RawAnimationTags.Length; i++) - { - RawAnimationTag tag = rawSpriteSheet.RawAnimationTags[i]; - - spriteSheet.CreateAnimationTag(tag.Name, builder => - { - builder.LoopCount(tag.LoopCount) - .IsReversed(tag.IsReversed) - .IsPingPong(tag.IsPingPong); - - for (int j = 0; j < tag.RawAnimationFrames.Length; j++) - { - RawAnimationFrame rawAnimationFrame = tag.RawAnimationFrames[j]; - TimeSpan duration = TimeSpan.FromMilliseconds(rawAnimationFrame.DurationInMilliseconds); - builder.AddFrame(rawAnimationFrame.FrameIndex, duration); - } - }); - } - - return spriteSheet; - } -} diff --git a/source/MonoGame.Aseprite/Sprites/TextureAtlas.cs b/source/MonoGame.Aseprite/Sprites/TextureAtlas.cs deleted file mode 100644 index 4855d342..00000000 --- a/source/MonoGame.Aseprite/Sprites/TextureAtlas.cs +++ /dev/null @@ -1,594 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Collections; -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Sprites; - -/// -/// Defines a with a source image and zero or more elements. -/// -public class TextureAtlas : IEnumerable -{ - private List _regions = new(); - private Dictionary _regionLookup = new(); - - /// - /// G ets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the source image of this . - /// - public Texture2D Texture { get; } - - /// - /// Gets the total number of elements in this . - /// - public int RegionCount => _regions.Count; - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element in this to locate. - /// - /// - /// The element that was located at the specified index in this - /// . - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public TextureRegion this[int index] => GetRegion(index); - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the element in this to locate. - /// - /// - /// The element that was located with the specified name in this - /// . - /// - /// - /// Thrown if this does not contain a with the specified - /// name. - /// - public TextureRegion this[string name] => GetRegion(name); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The name to assign the . - /// - /// T - /// he source image to give the . - /// - public TextureAtlas(string name, Texture2D texture) => (Name, Texture) = (name, texture); - - private void AddRegion(TextureRegion region) - { - if (_regionLookup.ContainsKey(region.Name)) - { - throw new InvalidOperationException($"This {nameof(TextureAtlas)} already contains a {nameof(TextureRegion)} with the name '{region.Name}'."); - } - - _regions.Add(region); - _regionLookup.Add(region.Name, region); - } - - private bool RemoveRegion(TextureRegion region) => - _regions.Remove(region) && _regionLookup.Remove(region.Name); - - /// - /// Creates a new and adds it to this . - /// - /// - /// The name to assign the that is created. The name must be unique across all - /// in this . - /// - /// - /// The x-coordinate location of the upper-left corner of the within the source - /// image of this . - /// - /// - /// The y-coordinate location of the upper-left corner of the within the source - /// image of this . - /// - /// - /// The width, in pixels, of the . - /// - /// - /// The height, in pixels, of the . - /// - /// - /// Thrown if this already contains a element with the - /// specified name. - /// - /// - /// The created by this method. - /// - public TextureRegion CreateRegion(string name, int x, int y, int width, int height) => - CreateRegion(name, new Rectangle(x, y, width, height)); - - /// - /// Creates a new and adds it to this . - /// - /// - /// The name to assign the that is created. The name must be unique across all - /// in this . - /// - /// - /// The x- and y-coordinate location of the upper-left corner of the within the - /// source image of this . - /// - /// The width and height extents, in pixels, of the . - /// - /// Thrown if this already contains a element with the - /// specified name. - /// - /// - /// The created by this method. - /// - public TextureRegion CreateRegion(string name, Point location, Point size) => - CreateRegion(name, new Rectangle(location, size)); - - /// - /// Creates a new and adds it to this . - /// - /// - /// The name to assign the that is created. The name must be unique across all - /// in this . - /// - /// - /// The rectangular bounds of the within the source image of this - /// . - /// - /// - /// Thrown if this already contains a element with the - /// specified name. - /// - /// - /// The created by this method. - /// - public TextureRegion CreateRegion(string name, Rectangle bounds) - { - TextureRegion region = new(name, Texture, bounds); - AddRegion(region); - return region; - } - - /// - /// Returns a value that indicates whether this contains a - /// element with the specified name. - /// - /// - /// The name of the to locate. - /// - /// - /// if this contains a element - /// with the specified name; otherwise, . - /// - public bool ContainsRegion(string name) => _regionLookup.ContainsKey(name); - - /// - /// Returns the index of the element with the specified name in this - /// . - /// - /// - /// The name of the to locate. - /// - /// - /// The index of the located. - /// - /// - /// if this contains a element - /// with the specified name; otherwise, . - /// - public int GetIndexOfRegion(string name) - { - for (int i = 0; i < _regions.Count; i++) - { - if (_regions[i].Name == name) - { - return i; - } - } - - KeyNotFoundException ex = new($"This texture atlas does not contain a texture region with the name '{name}'."); - ex.Data.Add("TextureRegions", _regions); - throw ex; - } - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element that was located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public TextureRegion GetRegion(int index) - { - if (index < 0 || index >= _regions.Count) - { - throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of {nameof(TextureRegion)} elements in this {nameof(TextureAtlas)}."); - } - - return _regions[index]; - } - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element that was located. - /// - /// - /// Thrown if this does not contain a element with the - /// specified name. - /// - public TextureRegion GetRegion(string name) - { - if (_regionLookup.TryGetValue(name, out TextureRegion? frame)) - { - return frame; - } - - KeyNotFoundException ex = new($"This texture atlas does not contain a texture region with the name '{name}'."); - ex.Data.Add("TextureRegions", _regions); - throw ex; - } - - /// - /// Gets a new of all elements at the specified indexes in - /// this . Order of the elements in the collection returned is the same as the order - /// of the indexes specified. - /// - /// - /// The indexes of the elements to locate. - /// - /// - /// A new containing the elements located. - /// - /// - /// Thrown if any of the specified indexes are less than zero or if any are greater than or equal to the total - /// number of elements in this . - /// - public List GetRegions(params int[] indexes) - { - List regions = new(); - for (int i = 0; i < indexes.Length; i++) - { - regions.Add(GetRegion(indexes[i])); - } - - return regions; - } - - /// - /// Gets a new of all elements with the specified names in - /// this . Order of the elements in the collection returned is the same as the order - /// of names specified. - /// - /// - /// The names of the elements to locate. - /// - /// - /// A new containing the elements located. - /// - /// - /// Thrown if any of the specified names do not match a element in this - /// . - /// - public List GetRegions(params string[] names) - { - List regions = new(); - - for (int i = 0; i < names.Length; i++) - { - regions.Add(GetRegion(names[i])); - } - - return regions; - } - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// When this method returns , contains the located; - /// otherwise, . - /// - /// - /// if a element was located; otherwise, - /// . This method returns if the index specified is less than - /// zero or is greater than or equal to the total number of elements in this - /// . - /// - public bool TryGetRegion(int index, [NotNullWhen(true)] out TextureRegion? region) - { - region = default; - - if (index < 0 || index >= _regions.Count) - { - return false; - } - - region = _regions[index]; - return true; - } - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the element to locate. - /// - /// - /// When this method returns , contains the located; - /// otherwise, . - /// - /// - /// if a element was located; otherwise, - /// . This method returns if this - /// does not contain a element with the specified name. - /// - public bool TryGetRegion(string name, [NotNullWhen(true)] out TextureRegion? region) => - _regionLookup.TryGetValue(name, out region); - - /// - /// Removes the element at the specified index from this . - /// - /// - /// The index of the element to remove. - /// - /// - /// if the element was successfully removed; otherwise, - /// . This method returns if the specified index is less than - /// zero or is greater than or equal to the total number of element in this - /// . - /// - public bool RemoveRegion(int index) - { - if (TryGetRegion(index, out TextureRegion? region)) - { - return RemoveRegion(region); - } - - return false; - } - - /// - /// Removes the element with the specified name from this - /// . - /// - /// - /// The name of the element to remove. - /// - /// - /// if the element was successfully removed; otherwise, - /// . This method returns if this - /// does not contain a element with the specified name. - /// - public bool RemoveRegion(string name) - { - if (TryGetRegion(name, out TextureRegion? region)) - { - return RemoveRegion(region); - } - - return false; - } - - /// - /// Creates a new from the at the specified index in this - /// . - /// - /// - /// The name to assign the that is created. - /// - /// - /// The index of the element in this assign the - /// that is created. - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public Sprite CreateSprite(string spriteName, int regionIndex) - { - TextureRegion region = GetRegion(regionIndex); - Sprite sprite = new(spriteName, region); - return sprite; - } - - /// - /// Creates a new from the at the specified index in this - /// . - /// - /// - /// The index of the element to assign the that is created. - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public Sprite CreateSprite(int regionIndex) - { - TextureRegion region = GetRegion(regionIndex); - Sprite sprite = new(region.Name, region); - return sprite; - } - - /// - /// Creates a new from the with the specified name in this - /// . - /// - /// - /// The name to assign the that is created. - /// - /// - /// The name of the element in this assign the - /// that is created. - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if this does not contain a with the name - /// specified. - /// - public Sprite CreateSprite(string spriteName, string regionName) - { - TextureRegion region = GetRegion(regionName); - Sprite sprite = new(spriteName, region); - return sprite; - } - - /// - /// Creates a new from the with the specified name in this - /// . - /// - /// - /// The name of the element in this assign the - /// that is created. - /// - /// - /// The that is created by this method. - /// - /// - /// Thrown if this does not contain a with the name - /// specified. - /// - public Sprite CreateSprite(string regionName) - { - TextureRegion region = GetRegion(regionName); - Sprite sprite = new(region.Name, region); - return sprite; - } - - /// - /// Removes all elements from this . - /// - public void Clear() - { - // Remove them in a foreach so that each region is disposed of properly as it's removed - foreach (TextureRegion region in this) - { - RemoveRegion(region); - } - } - - /// - /// Returns an enumerator that iterates each element in this - /// . - /// - /// - /// An enumerator that iterates each elements in this . - /// - public IEnumerator GetEnumerator() => _regions.GetEnumerator(); - - /// - /// Returns an enumerator that iterates each element in this - /// . - /// - /// - /// An enumerator that iterates each elements in this . - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Creates a new instance of the class from the given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to create the from. - /// - /// - /// The created by this method. - /// - public static TextureAtlas FromRaw(GraphicsDevice device, RawTextureAtlas rawTextureAtlas) - { - RawTexture rawTexture = rawTextureAtlas.RawTexture; - - Texture2D texture = new(device, rawTexture.Width, rawTexture.Height, mipmap: false, SurfaceFormat.Color); - texture.SetData(rawTexture.Pixels.ToArray()); - texture.Name = rawTexture.Name; - - TextureAtlas atlas = new(rawTextureAtlas.Name, texture); - - ReadOnlySpan rawTextureRegions = rawTextureAtlas.RawTextureRegions; - - for (int i = 0; i < rawTextureRegions.Length; i++) - { - RawTextureRegion rawTextureRegion = rawTextureRegions[i]; - TextureRegion textureRegion = atlas.CreateRegion(rawTextureRegion.Name, rawTextureRegion.Bounds); - - for (int s = 0; s < rawTextureRegion.Slices.Length; s++) - { - RawSlice slice = rawTextureRegion.Slices[s]; - - if (slice is RawNinePatchSlice ninePatch) - { - _ = textureRegion.CreateNinePatchSlice(ninePatch.Name, ninePatch.Bounds, ninePatch.CenterBounds, ninePatch.Origin, ninePatch.Color); - } - else - { - _ = textureRegion.CreateSlice(slice.Name, slice.Bounds, slice.Origin, slice.Color); - } - } - } - - return atlas; - } -} diff --git a/source/MonoGame.Aseprite/TextureAtlas.cs b/source/MonoGame.Aseprite/TextureAtlas.cs new file mode 100644 index 00000000..7e2ac7b8 --- /dev/null +++ b/source/MonoGame.Aseprite/TextureAtlas.cs @@ -0,0 +1,458 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace MonoGame.Aseprite; + +/// +/// Defines a with a source image and zero or more elements. +/// +public class TextureAtlas : IEnumerable +{ + private List _regions = new(); + private Dictionary _regionLookup = new(); + + /// + /// Gets the name assigned to this . + /// + public string Name { get; } + + /// + /// Gets the source image of this . + /// + public Texture2D Texture { get; } + + /// + /// Gets the total number of elements in this . + /// + public int RegionCount => _regions.Count; + + /// + /// Gets the element at the specified index in this . + /// + /// + /// The index of the element in this to locate. + /// + /// + /// The element that was located at the specified index in this + /// . + /// + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public TextureRegion this[int index] => GetRegion(index); + + /// + /// Gets the element with the specified name in this . + /// + /// + /// The name of the element in this to locate. + /// + /// + /// The element that was located with the specified name in this + /// . + /// + /// + /// Thrown if this does not contain a with the specified + /// name. + /// + public TextureRegion this[string name] => GetRegion(name); + + /// + /// Initializes a new instance of the class. + /// + /// The name to assign the . + /// The source image to give the . + public TextureAtlas(string name, Texture2D texture) => (Name, Texture) = (name, texture); + + private void AddRegion(TextureRegion region) + { + if (_regionLookup.ContainsKey(region.Name)) + { + throw new InvalidOperationException($"This {nameof(TextureAtlas)} already contains a {nameof(TextureRegion)} with the name '{region.Name}'."); + } + + _regions.Add(region); + _regionLookup.Add(region.Name, region); + } + + private bool RemoveRegion(TextureRegion region) => + _regions.Remove(region) && _regionLookup.Remove(region.Name); + + /// + /// Creates a new and adds it to this . + /// + /// + /// The name to assign the that is created. The name must be unique across all + /// in this . + /// + /// + /// The x-coordinate location of the upper-left corner of the within the source + /// image of this . + /// + /// + /// The y-coordinate location of the upper-left corner of the within the source + /// image of this . + /// + /// The width, in pixels, of the . + /// The height, in pixels, of the . + /// + /// Thrown if this already contains a element with the + /// specified name. + /// + /// The created by this method. + public TextureRegion CreateRegion(string name, int x, int y, int width, int height) => + CreateRegion(name, new Rectangle(x, y, width, height)); + + /// + /// Creates a new and adds it to this . + /// + /// + /// The name to assign the that is created. The name must be unique across all + /// in this . + /// + /// + /// The x- and y-coordinate location of the upper-left corner of the within the + /// source image of this . + /// + /// The width and height extents, in pixels, of the . + /// + /// Thrown if this already contains a element with the + /// specified name. + /// + /// The created by this method. + public TextureRegion CreateRegion(string name, Point location, Point size) => + CreateRegion(name, new Rectangle(location, size)); + + /// + /// Creates a new and adds it to this . + /// + /// + /// The name to assign the that is created. The name must be unique across all + /// in this . + /// + /// + /// The rectangular bounds of the within the source image of this + /// . + /// + /// + /// Thrown if this already contains a element with the + /// specified name. + /// + /// The created by this method. + public TextureRegion CreateRegion(string name, Rectangle bounds) + { + TextureRegion region = new(name, Texture, bounds); + AddRegion(region); + return region; + } + + /// + /// Returns a value that indicates whether this contains a + /// element with the specified name. + /// + /// The name of the to locate. + /// + /// if this contains a element + /// with the specified name; otherwise, . + /// + public bool ContainsRegion(string name) => _regionLookup.ContainsKey(name); + + /// + /// Returns the index of the element with the specified name in this + /// . + /// + /// The name of the to locate. + /// The index of the located. + /// + /// if this contains a element + /// with the specified name; otherwise, . + /// + public int GetIndexOfRegion(string name) + { + for (int i = 0; i < _regions.Count; i++) + { + if (_regions[i].Name == name) + { + return i; + } + } + + KeyNotFoundException ex = new($"This texture atlas does not contain a texture region with the name '{name}'."); + ex.Data.Add("TextureRegions", _regions); + throw ex; + } + + /// + /// Gets the element at the specified index in this . + /// + /// The index of the element to locate. + /// The element that was located. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public TextureRegion GetRegion(int index) + { + if (index < 0 || index >= _regions.Count) + { + throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of {nameof(TextureRegion)} elements in this {nameof(TextureAtlas)}."); + } + + return _regions[index]; + } + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the element to locate. + /// The element that was located. + /// + /// Thrown if this does not contain a element with the + /// specified name. + /// + public TextureRegion GetRegion(string name) + { + if (_regionLookup.TryGetValue(name, out TextureRegion? frame)) + { + return frame; + } + + KeyNotFoundException ex = new($"This texture atlas does not contain a texture region with the name '{name}'."); + ex.Data.Add("TextureRegions", _regions); + throw ex; + } + + /// + /// Gets a new of all elements at the specified indexes in + /// this . Order of the elements in the collection returned is the same as the order + /// of the indexes specified. + /// + /// The indexes of the elements to locate. + /// A new containing the elements located. + /// + /// Thrown if any of the specified indexes are less than zero or if any are greater than or equal to the total + /// number of elements in this . + /// + public List GetRegions(params int[] indexes) + { + List regions = new(); + for (int i = 0; i < indexes.Length; i++) + { + regions.Add(GetRegion(indexes[i])); + } + + return regions; + } + + /// + /// Gets a new of all elements with the specified names in + /// this . Order of the elements in the collection returned is the same as the order + /// of names specified. + /// + /// The names of the elements to locate. + /// A new containing the elements located. + /// + /// Thrown if any of the specified names do not match a element in this + /// . + /// + public List GetRegions(params string[] names) + { + List regions = new(); + + for (int i = 0; i < names.Length; i++) + { + regions.Add(GetRegion(names[i])); + } + + return regions; + } + + /// + /// Gets the element at the specified index in this . + /// + /// The index of the element to locate. + /// + /// When this method returns , contains the located; + /// otherwise, . + /// + /// + /// if a element was located; otherwise, + /// . This method returns if the index specified is less than + /// zero or is greater than or equal to the total number of elements in this + /// . + /// + public bool TryGetRegion(int index, [NotNullWhen(true)] out TextureRegion? region) + { + region = default; + + if (index < 0 || index >= _regions.Count) + { + return false; + } + + region = _regions[index]; + return true; + } + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the element to locate. + /// + /// When this method returns , contains the located; + /// otherwise, . + /// + /// + /// if a element was located; otherwise, + /// . This method returns if this + /// does not contain a element with the specified name. + /// + public bool TryGetRegion(string name, [NotNullWhen(true)] out TextureRegion? region) => + _regionLookup.TryGetValue(name, out region); + + /// + /// Removes the element at the specified index from this . + /// + /// The index of the element to remove. + /// + /// if the element was successfully removed; otherwise, + /// . This method returns if the specified index is less than + /// zero or is greater than or equal to the total number of element in this + /// . + /// + public bool RemoveRegion(int index) + { + if (TryGetRegion(index, out TextureRegion? region)) + { + return RemoveRegion(region); + } + + return false; + } + + /// + /// Removes the element with the specified name from this + /// . + /// + /// The name of the element to remove. + /// + /// if the element was successfully removed; otherwise, + /// . This method returns if this + /// does not contain a element with the specified name. + /// + public bool RemoveRegion(string name) + { + if (TryGetRegion(name, out TextureRegion? region)) + { + return RemoveRegion(region); + } + + return false; + } + + /// + /// Creates a new from the at the specified index in this + /// . + /// + /// The name to assign the that is created. + /// + /// The index of the element in this assign the + /// that is created. + /// + /// The that is created by this method. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public Sprite CreateSprite(string spriteName, int regionIndex) + { + TextureRegion region = GetRegion(regionIndex); + Sprite sprite = new(spriteName, region); + return sprite; + } + + /// + /// Creates a new from the at the specified index in this + /// . + /// + /// + /// The index of the element to assign the that is created. + /// + /// The that is created by this method. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public Sprite CreateSprite(int regionIndex) + { + TextureRegion region = GetRegion(regionIndex); + Sprite sprite = new(region.Name, region); + return sprite; + } + + /// + /// Creates a new from the with the specified name in this + /// . + /// + /// The name to assign the that is created. + /// + /// The name of the element in this assign the + /// that is created. + /// + /// The that is created by this method. + /// + /// Thrown if this does not contain a with the name + /// specified. + /// + public Sprite CreateSprite(string spriteName, string regionName) + { + TextureRegion region = GetRegion(regionName); + Sprite sprite = new(spriteName, region); + return sprite; + } + + /// + /// Creates a new from the with the specified name in this + /// . + /// + /// + /// The name of the element in this assign the + /// that is created. + /// + /// The that is created by this method. + /// + /// Thrown if this does not contain a with the name + /// specified. + /// + public Sprite CreateSprite(string regionName) + { + TextureRegion region = GetRegion(regionName); + Sprite sprite = new(region.Name, region); + return sprite; + } + + /// + /// Removes all elements from this . + /// + public void Clear() + { + // Remove them in a foreach so that each region is disposed of properly as it's removed + foreach (TextureRegion region in this) + { + RemoveRegion(region); + } + } + + /// + public IEnumerator GetEnumerator() => _regions.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/source/MonoGame.Aseprite/TextureRegion.cs b/source/MonoGame.Aseprite/TextureRegion.cs index bf4ffbfc..3a905060 100644 --- a/source/MonoGame.Aseprite/TextureRegion.cs +++ b/source/MonoGame.Aseprite/TextureRegion.cs @@ -1,26 +1,6 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; @@ -35,62 +15,54 @@ public class TextureRegion private Dictionary _objects = new(); /// - /// Gets the name assigned to this . + /// Gets the name assigned to this . /// public string Name { get; } /// - /// Gets the source texture used by this . + /// Gets the source texture used by this . /// public Texture2D Texture { get; } /// - /// Gets the rectangular bounds that define the location and width and height extents, in pixels, of the region - /// within the source texture that is represented by this . + /// Gets the rectangular bounds that define the location and width and height extents, in pixels, of the region + /// within the source texture that is represented by this . /// public Rectangle Bounds { get; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// - /// The name to assign the . - /// - /// - /// The source texture image this region is from. - /// - /// - /// The rectangular bounds of this region within the source texture. - /// + /// The name to assign the . + /// The source texture image this region is from. + /// The rectangular bounds of this region within the source texture. public TextureRegion(string name, Texture2D texture, Rectangle bounds) => (Name, Texture, Bounds) = (name, texture, bounds); /// - /// Creates and adds a new element to this . + /// Creates and adds a new element to this . /// /// - /// The name to assign the that is created by this method. The name must be - /// unique across all elements in this . + /// The name to assign the that is created by this method. The name must be + /// unique across all elements in this . /// /// - /// The bounds to assign the created by this method. This should be relative to the bounds - /// of this . + /// The bounds to assign the created by this method. This should be relative to the bounds + /// of this . /// /// - /// The x- and y-coordinate origin point to assign the created by this method. - /// This should be relative to the upper-left corner of the bounds of this . + /// The x- and y-coordinate origin point to assign the created by this method. + /// This should be relative to the upper-left corner of the bounds of this . /// /// - /// A value to assign the created - /// by this method. + /// A value to assign the created + /// by this method. /// - /// - /// The created by this method. - /// + /// The created by this method. /// - /// Thrown if this already contains a with the - /// specified name. + /// Thrown if this already contains a with the + /// specified name. /// public Slice CreateSlice(string name, Rectangle bounds, Vector2 origin, Color color) { @@ -100,34 +72,32 @@ public Slice CreateSlice(string name, Rectangle bounds, Vector2 origin, Color co } /// - /// Creates and adds a new element to this . + /// Creates and adds a new element to this . /// /// - /// The name to assign the that is created by this method. The name must be - /// unique across all elements in this . + /// The name to assign the that is created by this method. The name must be + /// unique across all elements in this . /// /// - /// The bounds to assign the created by this method. This should be relative to - /// the bounds of this . + /// The bounds to assign the created by this method. This should be relative to + /// the bounds of this . /// /// - /// The center bounds to assign the created by this method. This should be - /// relative to the . + /// The center bounds to assign the created by this method. This should be + /// relative to the . /// /// - /// The x- and y-coordinate origin point to assign the created by this method. - /// This should be relative to the upper-left corner of the bounds of this . + /// The x- and y-coordinate origin point to assign the created by this method. + /// This should be relative to the upper-left corner of the bounds of this . /// /// - /// A value to assign the created - /// by this method. + /// A value to assign the created + /// by this method. /// - /// - /// The created by this method. - /// + /// The created by this method. /// - /// Thrown if this already contains a with the - /// specified name. + /// Thrown if this already contains a with the + /// specified name. /// public NinePatchSlice CreateNinePatchSlice(string name, Rectangle bounds, Rectangle centerBounds, Vector2 origin, Color color) { @@ -147,17 +117,13 @@ private void AddSlice(Slice slice) } /// - /// Returns the element with the specified name from this . + /// Returns the element with the specified name from this . /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// + /// The name of the element to locate. + /// The element located. /// - /// Thrown if this does not contain a element with the specified - /// name. + /// Thrown if this does not contain a element with the specified + /// name. /// public Slice GetSlice(string name) { @@ -170,36 +136,30 @@ public Slice GetSlice(string name) } /// - /// Returns the element with the specified name from this . + /// Returns the element with the specified name from this . /// - /// - /// The name of the element to locate. - /// + /// The name of the element to locate. /// - /// When this method returns , contains the located; otherwise, - /// + /// When this method returns , contains the located; otherwise, + /// /// /// - /// if the was located; otherwise, . - /// This method returns if this does not contain - /// a element with the specified name. + /// if the was located; otherwise, . + /// This method returns if this does not contain + /// a element with the specified name. /// public bool TryGetSlice(string name, out Slice? slice) => _objects.TryGetValue(name, out slice); /// - /// Returns the element with the specified name from this as the - /// type specified. + /// Returns the element with the specified name from this as the + /// type specified. /// /// - /// The type to return the located element as. Must derived from the base type - /// . + /// The type to return the located element as. Must derived from the base type + /// . /// - /// - /// The name of the element to locate. - /// - /// - /// The element located as the type specified. - /// + /// The name of the element to locate. + /// The element located as the type specified. public T GetSlice(string name) where T : Slice { if (_objects.TryGetValue(name, out Slice? slice)) @@ -211,24 +171,22 @@ public T GetSlice(string name) where T : Slice } /// - /// Returns the element with the specified name from this as the - /// type specified. + /// Returns the element with the specified name from this as the + /// type specified. /// /// - /// The type to return the located element as. Must derived from the base type - /// . + /// The type to return the located element as. Must derived from the base type + /// . /// - /// - /// The name of the element to locate. - /// + /// The name of the element to locate. /// - /// When this method returns , contains the located; otherwise, - /// + /// When this method returns , contains the located; otherwise, + /// /// /// - /// if the was located; otherwise, . - /// This method returns if this does not contain - /// a element with the specified name. + /// if the was located; otherwise, . + /// This method returns if this does not contain + /// a element with the specified name. /// public bool TryGetSlice(string name, out T? slice) where T : Slice { @@ -245,145 +203,117 @@ public bool TryGetSlice(string name, out T? slice) where T : Slice } /// - /// Removes the element with the specified name from this . + /// Removes the element with the specified name from this . /// - /// - /// The name of the element to remove. - /// + /// The name of the element to remove. /// - /// if the element was successfully removed; otherwise, - /// . This method returns when this - /// does not have a element with the specified name. + /// if the element was successfully removed; otherwise, + /// . This method returns when this + /// does not have a element with the specified name. /// public bool RemoveSlice(string name) => _objects.Remove(name); /// - /// Removes all elements from this . + /// Removes all elements from this . /// public void RemoveAllSlices() => _objects.Clear(); /// - /// Draws this instance using the - /// provided. + /// Draws this instance using the + /// provided. /// /// - /// The to use for rendering. + /// The to use for rendering. /// /// - /// A rectangular bound that defines the destination to render this into. - /// - /// - /// The color mask to apply when rendering this . + /// A rectangular bound that defines the destination to render this into. /// + /// The color mask to apply when rendering this . public void Draw(SpriteBatch spriteBatch, Rectangle destinationRectangle, Color color) => spriteBatch.Draw(this, destinationRectangle, color); /// - /// Draws this instance using the - /// provided. + /// Draws this instance using the + /// provided. /// /// - /// The to use for rendering. - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . + /// The to use for rendering. /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color) => spriteBatch.Draw(this, position, color); /// - /// Draws this using the - /// provided. + /// Draws this instance using the + /// provided. /// /// - /// The to use for rendering. - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . + /// The to use for rendering. /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . /// - /// The amount of rotation, in radians, to apply when rendering this . + /// The amount of rotation, in radians, to apply when rendering this . /// /// - /// The x- and y-coordinate point of origin to apply when rendering this . - /// - /// - /// The amount of scaling to apply when rendering this . + /// The x- and y-coordinate point of origin to apply when rendering this . /// + /// The amount of scaling to apply when rendering this . /// - /// The to apply for horizontal and vertical axis - /// flipping when rendering this . - /// - /// - /// The layer depth to apply when rendering this . + /// The to apply for horizontal and vertical axis + /// flipping when rendering this . /// + /// The layer depth to apply when rendering this . public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth) => spriteBatch.Draw(this, position, color, rotation, origin, scale, effects, layerDepth); /// - /// Draws this using the - /// provided. + /// Draws this instance using the + /// provided. /// /// - /// The to use for rendering. - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . + /// The to use for rendering. /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . /// - /// The amount of rotation, in radians, to apply when rendering this . + /// The amount of rotation, in radians, to apply when rendering this . /// /// - /// The x- and y-coordinate point of origin to apply when rendering this . - /// - /// - /// The amount of scaling to apply when rendering this . + /// The x- and y-coordinate point of origin to apply when rendering this . /// + /// The amount of scaling to apply when rendering this . /// - /// The to apply for horizontal and vertical axis - /// flipping when rendering this . - /// - /// - /// The layer depth to apply when rendering this . + /// The to apply for horizontal and vertical axis + /// flipping when rendering this . /// + /// The layer depth to apply when rendering this . public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth) => spriteBatch.Draw(this, position, color, rotation, origin, scale, effects, layerDepth); /// - /// Draws this using the - /// provided. + /// Draws this instance using the + /// provided. /// /// - /// The to use for rendering. + /// The to use for rendering. /// /// - /// A rectangular bound that defines the destination to render this into. - /// - /// - /// The color mask to apply when rendering this . + /// A rectangular bound that defines the destination to render this into. /// + /// The color mask to apply when rendering this . /// - /// The amount of rotation, in radians, to apply when rendering this . + /// The amount of rotation, in radians, to apply when rendering this . /// /// - /// The x- and y-coordinate point of origin to apply when rendering this . + /// The x- and y-coordinate point of origin to apply when rendering this . /// /// - /// The to apply for horizontal and vertical axis - /// flipping when rendering this . - /// - /// - /// The layer depth to apply when rendering this . + /// The to apply for horizontal and vertical axis + /// flipping when rendering this . /// + /// The layer depth to apply when rendering this . public void Draw(SpriteBatch spriteBatch, Rectangle destinationRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth) => spriteBatch.Draw(this, destinationRectangle, color, rotation, origin, effects, layerDepth); diff --git a/source/MonoGame.Aseprite/Tile.cs b/source/MonoGame.Aseprite/Tile.cs new file mode 100644 index 00000000..f6b03c68 --- /dev/null +++ b/source/MonoGame.Aseprite/Tile.cs @@ -0,0 +1,78 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +namespace MonoGame.Aseprite; + +/// +/// Defines a tile value in a . +/// +public struct Tile +{ + /// + /// Represents a with its properties left uninitialized. + /// + public static readonly Tile Empty; + + /// + /// The ID (or index) of the source tile in the that represents the + /// to render for this . + /// + public int TilesetTileID = 0; + + /// + /// Indicates whether this should be flipped horizontally rendered. + /// + public bool FlipHorizontally = false; + + /// + /// Indicates whether this should be flipped vertically rendered. + /// + public bool FlipVertically = false; + + /// + /// Indicates whether this should be flipped diagonally when rendered. + /// + public bool FlipDiagonally = false; + + /// + /// Gets a value that indicates if this is an empty . + /// + /// + /// Empty tiles have a equal to zero. + /// + public bool IsEmpty => TilesetTileID == 0; + + /// + /// Initializes a new instance of the class. + /// + public Tile() { } + + /// + /// Initializes a new value. + /// + /// + /// The ID (or index) of the source tile in the that represents the + /// to assign for this . + /// + public Tile(int tilesetTileID) => TilesetTileID = tilesetTileID; + + /// + /// Initializes a new value. + /// + /// + /// The ID (or index) of the source tile in the that represents the + /// to assign for this . + /// + /// + /// Indicates whether the should be flipped horizontally when rendered. + /// + /// + /// Indicates whether the should be flipped vertically when rendered. + /// + /// + /// Indicates whether the should be flipped diagonally when rendered. + /// + public Tile(int tilesetTileID, bool flipHorizontally, bool flipVertically, bool flipDiagonally) => + (TilesetTileID, FlipHorizontally, FlipVertically, FlipDiagonally) = (tilesetTileID, flipHorizontally, flipVertically, flipDiagonally); +} diff --git a/source/MonoGame.Aseprite/Tilemap.cs b/source/MonoGame.Aseprite/Tilemap.cs new file mode 100644 index 00000000..c6d47433 --- /dev/null +++ b/source/MonoGame.Aseprite/Tilemap.cs @@ -0,0 +1,298 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + + +namespace MonoGame.Aseprite; + +/// +/// Defines a with zero or more elements. +/// +public sealed class Tilemap : IEnumerable +{ + private List _layers = new(); + private Dictionary _layerLookup = new(); + + /// + /// Gets the name assigned to this . + /// + public string Name { get; } + + /// + /// Gets the total number of elements in this . + /// + public int LayerCount => _layers.Count; + + /// + /// Gets the element at the specified index in this . + /// + /// The index of the element to locate. + /// The element located. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public TilemapLayer this[int layerIndex] => GetLayer(layerIndex); + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the element to locate. + /// The element located. + /// + /// Thrown if this does not contain a element with the + /// specified name. + /// + public TilemapLayer this[string layerName] => GetLayer(layerName); + + /// + /// Initializes a new instance of the class. + /// + /// The name to assign . + public Tilemap(string name) => Name = name; + + /// + /// Creates a new element and adds it to this . + /// + /// + /// The name to give the element created by this method. The name must be unique + /// across all elements in this . + /// + /// + /// The source tileset to assign the element created by this method. + /// + /// + /// The total number of columns to assign the element created by this method. + /// + /// + /// The total of rows to assign the element created by this method. + /// + /// + /// The x- and y-position offset, relative to the location the is rendered, to + /// assign the element created by this method. + /// + /// The created by this method. + /// + /// Thrown if this already contains a element with the + /// specified name. + /// + public TilemapLayer CreateLayer(string layerName, Tileset tileset, int columns, int rows, Vector2 offset) + { + TilemapLayer layer = new(layerName, tileset, columns, rows, offset); + AddLayer(layer); + return layer; + } + + /// + /// Adds the given element to this . + /// + /// The element to add. + /// + /// Thrown if this already contains a element with the same + /// name as the element given. + /// + public void AddLayer(TilemapLayer layer) + { + if (_layerLookup.ContainsKey(layer.Name)) + { + throw new InvalidOperationException($"This tileset already contains a tilemap layer element with the name '{layer.Name}'."); + } + + _layers.Add(layer); + _layerLookup.Add(layer.Name, layer); + } + + /// + /// Get the element at the specified index in this . + /// + /// The index of the element to locate. + /// The element located. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public TilemapLayer GetLayer(int index) + { + if (index < 0 || index >= LayerCount) + { + throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of tilemap layer elements in this tilemap."); + } + + return _layers[index]; + } + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the element to locate. + /// The located. + /// + /// Thrown if this does not contain a element with the + /// specified name. + /// + public TilemapLayer GetLayer(string name) + { + if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) + { + return layer; + } + + throw new KeyNotFoundException($"This tilemap does not contain a tilemap layer element with the name '{name}'."); + } + + /// + /// Get the element at the specified index in this . + /// + /// The index of the element to locate. + /// + /// When this method returns , contains the element located; + /// otherwise, . + /// + /// + /// if a element was located at the specified index in this + /// ; otherwise, . This method return when + /// the specified index is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public bool TryGetLayer(int index, [NotNullWhen(true)] out TilemapLayer? layer) + { + layer = default; + + if (index < 0 || index >= LayerCount) + { + return false; + } + + layer = _layers[index]; + return true; + } + + /// + /// Gets the element with the specified name in this . + /// + /// The name of the element to locate. + /// + /// When this method returns , contains the element located; + /// otherwise, . + /// + /// + /// if a element was located in this + /// with the specified name; otherwise . This method returns if + /// this does not contain a element with the specified name. + /// + public bool TryGetLayer(string name, [NotNullWhen(true)] out TilemapLayer? layer) => + _layerLookup.TryGetValue(name, out layer); + + /// + /// Removes the element at the specified index in this . + /// + /// + /// The index of the element to remove from this . + /// + /// + /// if the element was successfully removed; otherwise, + /// . This method returns if the specified index is less than + /// zero or is greater than or equal to the total number of elements in this + /// . + /// + public bool RemoveLayer(int index) + { + if (index < 0 || index >= LayerCount) + { + return false; + } + + TilemapLayer layer = _layers[index]; + return RemoveLayer(layer); + } + + /// + /// Removes the element with the specified name from this . + /// + /// + /// The name of the element to remove from this + /// + /// + /// if the element was successfully removed; otherwise, + /// . This method returns if this does not + /// contain a element with the specified name. + /// + public bool RemoveLayer(string name) + { + if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) + { + return RemoveLayer(layer); + } + + return false; + } + + /// + /// Removes the given element from this . + /// + /// The element to remove from this . + /// + /// if the element was removed successfully; otherwise, + /// . This method returns false if this does not contain the + /// element given. + /// + public bool RemoveLayer(TilemapLayer layer) => + _layers.Remove(layer) && _layerLookup.Remove(layer.Name); + + /// + /// Removes all elements from this . + /// + public void Clear() + { + _layerLookup.Clear(); + _layers.Clear(); + } + + /// + /// Draws this using the . + /// + /// + /// The to use for rendering this . + /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color) => + Draw(spriteBatch, position, color, Vector2.One, 0.0f); + + /// + /// Draws this using the . + /// + /// + /// The to use for rendering this . + /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . + /// The amount of scaling to apply when rendering this . + /// The layer depth to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float scale, float layerDepth) => + Draw(spriteBatch, position, color, new Vector2(scale, scale), layerDepth); + + /// + /// Draws this using the . + /// + /// + /// The to use for rendering this . + /// + /// The x- and y-coordinate location to render this at. + /// The color mask to apply when rendering this . + /// The amount of scaling to apply when rendering this . + /// The layer depth to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, Vector2 scale, float layerDepth) => + spriteBatch.Draw(this, position, color, scale, layerDepth); + + /// + public IEnumerator GetEnumerator() => _layers.GetEnumerator(); + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/source/MonoGame.Aseprite/TilemapLayer.cs b/source/MonoGame.Aseprite/TilemapLayer.cs new file mode 100644 index 00000000..7c686937 --- /dev/null +++ b/source/MonoGame.Aseprite/TilemapLayer.cs @@ -0,0 +1,532 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Collections; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace MonoGame.Aseprite; + +/// +/// Defines a grid-like layer in a tilemap that contains a collection of tiles. +/// +public sealed class TilemapLayer : IEnumerable +{ + private Tile[] _tiles; + private Vector2 _offset = Vector2.Zero; + + /// + /// Gets a read-only span of the elements in this . + /// + public ReadOnlySpan Tiles => _tiles; + + /// + /// Gets the name assigned to this . + /// + public string Name { get; } + + /// + /// Gets or Sets the source referenced by the elements in this + /// . + /// + public Tileset Tileset { get; set; } + + /// + /// Gets the total number of columns in this . + /// + public int Columns { get; } + + /// + /// Gets the total number of rows in this . + /// + public int Rows { get; } + + /// + /// Gets the width, in pixels, of this . + /// Width = Tileset.TileWidth * Columns + /// + public int Width => Tileset.TileWidth * Columns; + + /// + /// Gets the height, in pixels, of this . + /// Height = Tileset.TileHeight * Rows + /// + public int Height => Tileset.TileHeight * Rows; + + /// + /// Gets or Sets the transparency of this . + /// + public float Transparency { get; set; } = 1.0f; + + /// + /// Gets or Sets a value that indicates whether this is visible and should be + /// rendered. + /// + public bool IsVisible { get; set; } = true; + + /// + /// Gets or Sets the x- and y-coordinate position offset, relative to the position of the , + /// to render this at + /// + public Vector2 Offset + { + get => _offset; + set => _offset = value; + } + + /// + /// Gets or Sets the x-position offset, relative to the position of the , to render this + /// at + /// + public float OffsetX + { + get => _offset.X; + set => _offset.X = value; + } + + /// + /// Gets or Sets the y-position offset, relative to the position of the , to render this + /// at + /// + public float OffsetY + { + get => _offset.Y; + set => _offset.Y = value; + } + + /// + /// Gets the total number of elements in this . + /// + public int TileCount => _tiles.Length; + + /// + /// Gets the element at the specified index in this + /// + /// The index of the element to locate. + /// The element located. + /// + /// Thrown if the index specified is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public Tile this[int tileIndex] => GetTile(tileIndex); + + /// + /// Gets the element located at the specified column and row in this + /// . + /// + /// The column of the element to locate. + /// The row of the element to locate. + /// The element located. + /// + /// Thrown if either the column or rows specified is less than zero or if either is greater than or equal to the + /// total number of columns or rows in this . + /// + public Tile this[int column, int row] => GetTile(column, row); + + /// + /// Gets the element located at the specified column and row location in this + /// . + /// + /// The column and row location of the element to locate. + /// The element located. + /// + /// Thrown if either the column or rows specified in the location is less than zero or if either is greater + /// than or equal to the total number of columns or rows in this . + /// + public Tile this[Point location] => GetTile(location); + + /// + /// Initializes a new instance of the class. + /// + /// The name assign the . + /// The source tileset used by the tiles in this . + /// The total number of columns to assign the . + /// The total number of rows to assign the . + /// + /// The x- and y-coordinate position offset, relative to the position of the to assign the + /// . + /// + public TilemapLayer(string name, Tileset tileset, int columns, int rows, Vector2 offset) + { + Tileset = tileset; + Name = name; + _offset = offset; + Columns = columns; + Rows = rows; + _tiles = new Tile[columns * rows]; + } + + /// + /// Returns a value that indicates whether the element at the specified index in this + /// is empty. + /// + /// The index of the element to check. + /// + /// if the element at the specified index is empty; otherwise, + /// . + /// + /// + /// Thrown if the index specified is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public bool IsEmpty(int index) => GetTile(index).IsEmpty; + + /// + /// Returns a value that indicates whether the element at the specified column and row in + /// this is empty. + /// + /// The column of the element to check. + /// The row of the element to check. + /// + /// if the element at the specified column and row in this + /// is empty; otherwise, . + /// + /// + /// Thrown if either the column or row specified is less than zero or if either is greater than or equal to the + /// total number of columns or rows in this . + /// + public bool IsEmpty(int column, int row) => GetTile(column, row).IsEmpty; + + /// + /// Returns a value that indicates whether the element at the specified column and row + /// location in this is empty. + /// + /// The column and row location of the element to check. + /// + /// if the element at the specified column and row location in this + /// is empty; otherwise, . + /// + /// + /// Thrown if either the column or row in the specified location is less than zero or if either is greater + /// than or equal to the total number of columns or rows in this . + /// + public bool IsEmpty(Point location) => GetTile(location).IsEmpty; + + /// + /// Sets the element at the specified index in this using the + /// values provided. + /// + /// The index of the element in this to set. + /// + /// The ID of the source tile in the that represents the to + /// render for the element being set. + /// + /// + /// Indicates whether the element being set should be flipped horizontally when rendered. + /// + /// + /// Indicates if the element being set should be flipped vertically when rendered. + /// + /// + /// Indicates if the element being set should be flipped diagonally when rendered. + /// + /// + /// Thrown if the index specified is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public void SetTile(int index, int tilesetTileID, bool flipHorizontally = false, bool flipVertically = false, bool flipDiagonally = false) + { + Tile tile; + tile.TilesetTileID = tilesetTileID; + tile.FlipHorizontally = flipHorizontally; + tile.FlipVertically = flipVertically; + tile.FlipDiagonally = flipDiagonally; + SetTile(index, tile); + } + + /// + /// Sets the element at the specified column and row in this + /// using the values provided. + /// + /// + /// The column in this to set the element at. + /// + /// + /// The row in this to set the element at. + /// + /// + /// The ID of the source tile in the that represents the to + /// render for the element being set. + /// + /// + /// Indicates whether the element being set should be flipped horizontally when rendered. + /// + /// + /// Indicates if the element being set should be flipped vertically when rendered. + /// + /// + /// Indicates if the element being set should be flipped diagonally when rendered. + /// + /// + /// Thrown if either the column or row specified is less than zero or are greater than or equal to the total + /// number of columns or rows in this . + /// + public void SetTile(int column, int row, int tilesetTileID, bool flipHorizontally = false, bool flipVertically = false, bool flipDiagonally = false) + { + Tile tile; + tile.TilesetTileID = tilesetTileID; + tile.FlipHorizontally = flipHorizontally; + tile.FlipVertically = flipVertically; + tile.FlipDiagonally = flipDiagonally; + SetTile(column, row, tile); + } + + /// + /// Sets the element at the specified column and row location in this + /// using the values provided. + /// + /// + /// The column and row location in this to set the element at. + /// + /// + /// The ID of the source tile in the that represents the to + /// render for the element being set. + /// + /// + /// Indicates whether the element being set should be flipped horizontally when rendered. + /// + /// + /// Indicates if the element being set should be flipped vertically when rendered. + /// + /// + /// Indicates if the element being set should be flipped diagonally when rendered. + /// + /// + /// Thrown if either the column or row in the specified location is less than zero or are greater than or equal + /// to the total number of columns or rows in this . + /// + public void SetTile(Point location, int tilesetTileID, bool flipHorizontally = false, bool flipVertically = false, bool flipDiagonally = false) + { + Tile tile; + tile.TilesetTileID = tilesetTileID; + tile.FlipHorizontally = flipHorizontally; + tile.FlipVertically = flipVertically; + tile.FlipDiagonally = flipDiagonally; + SetTile(location, tile); + } + + /// + /// Sets the specified index in this to the element given. + /// + /// The index in this to set. + /// The element to set at the index. + /// + /// Thrown if the index specified is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public void SetTile(int index, Tile tile) + { + CheckIndex(index); + _tiles[index] = tile; + } + + /// + /// Sets the specified column and row in this to the element + /// given. + /// + /// The column in this to set. + /// The row in this to set. + /// The element to set at the column and row. + /// + /// Thrown if either the column or row specified are less than zero or are greater than or equal to the total + /// number of columns or rows in this . + /// + public void SetTile(int column, int row, Tile tile) + { + CheckColumn(column); + CheckRow(row); + int index = ToIndex(column, row); + _tiles[index] = tile; + } + + /// + /// Sets the specified column and row location in this to the + /// element given. + /// + /// The column and row location in this to set. + /// The element to set at the column and row location. + /// + /// Thrown if either the column or row in the specified location are less than zero or are greater than or equal + /// to the total number of columns or rows in this . + /// + public void SetTile(Point location, Tile tile) + { + CheckLocation(location); + int index = ToIndex(location.X, location.Y); + _tiles[index] = tile; + } + + /// + /// Gets the element located at the specified index in this . + /// + /// The index of the element in this to locate. + /// The element located + /// + /// Thrown if the index specified is less than zero or is greater than or equal to the total number of + /// elements in this . + /// + public Tile GetTile(int index) + { + CheckIndex(index); + return _tiles[index]; + } + + /// + /// Gets the element located at the specified column and row in this + /// . + /// + /// The column of the element to locate. + /// The row of the element to locate. + /// The element located. + /// + /// Thrown if either the column or rows specified are less than zero or are greater than or equal to the total + /// number of columns or rows in this . + /// + public Tile GetTile(int column, int row) + { + CheckColumn(column); + CheckRow(row); + int index = ToIndex(column, row); + return _tiles[index]; + } + + /// + /// Gets the element located at the specified column and row location in this + /// . + /// + /// The column and row location of the element to locate. + /// The element located. + /// + /// Thrown if either the column or rows in the specified location are less than zero or are greater than or + /// equal to the total number of columns or rows in this . + /// + public Tile GetTile(Point location) + { + CheckLocation(location); + int index = ToIndex(location.X, location.Y); + return _tiles[index]; + } + + + /// + /// Clears all elements in this by resetting them to an empty value. + /// + public void Clear() + { + Array.Clear(_tiles); + } + + /// + /// Draws this layer using the . + /// + /// + /// The to use for rendering this . + /// + /// + /// The x- and y-coordinate location to draw this at. Drawing this + /// using this method ignores the . + /// + /// The color mask to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color) => + Draw(spriteBatch, position, color, Vector2.One, 0.0f); + + /// + /// Draws this layer using the . + /// + /// + /// The to use for rendering this . + /// + /// + /// The x- and y-coordinate location to draw this at. Drawing this + /// using this method ignores the . + /// + /// The color mask to apply when rendering this . + /// The amount of scaling to apply when rendering this . + /// The layer depth to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float scale, float layerDepth) => + Draw(spriteBatch, position, color, new Vector2(scale, scale), layerDepth); + + /// + /// Draws this layer using the . + /// + /// + /// The to use for rendering this . + /// + /// + /// The x- and y-coordinate location to draw this at. Drawing this + /// using this method ignores the . + /// + /// The color mask to apply when rendering this . + /// The amount of scaling to apply when rendering this . + /// The layer depth to apply when rendering this . + public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, Vector2 scale, float layerDepth) => + spriteBatch.Draw(this, position, color, scale, layerDepth); + + + /// + public IEnumerator GetEnumerator() + { + for (int i = 0; i < _tiles.Length; i++) + { + yield return _tiles[i]; + } + } + + /// + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + private int ToIndex(int column, int row) => row * Columns + column; + + private void CheckIndex(int index) + { + if (index < 0 || index >= TileCount) + { + ArgumentOutOfRangeException ex = new(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of tiles in this tilemap layer."); + ex.Data.Add(nameof(index), index); + ex.Data.Add(nameof(TileCount), TileCount); + throw ex; + } + } + + private void CheckRow(int row) + { + if (row < 0 || row >= Rows) + { + ArgumentOutOfRangeException ex = new(nameof(row), $"{nameof(row)} cannot be less than zero or greater than or equal to the total number of rows in this tilemap layer."); + ex.Data.Add(nameof(row), row); + ex.Data.Add(nameof(Rows), Rows); + throw ex; + } + } + + private void CheckColumn(int column) + { + if (column < 0 || column >= Columns) + { + ArgumentOutOfRangeException ex = new(nameof(column), $"{nameof(column)} cannot be less than zero or greater than or equal to the total number of columns in this tilemap layer."); + ex.Data.Add(nameof(column), column); + ex.Data.Add(nameof(Columns), Columns); + throw ex; + } + } + + private void CheckLocation(Point location) + { + if (location.X < 0 || location.X >= Columns) + { + ArgumentOutOfRangeException ex = new(nameof(location), $"The column in the location cannot be less than zero or greater than or equal to the total number of columns in this tilemap layer."); + ex.Data.Add(nameof(location), location); + ex.Data.Add(nameof(Columns), Columns); + throw ex; + } + + if (location.Y < 0 || location.Y >= Rows) + { + ArgumentOutOfRangeException ex = new(nameof(location), $"The row in the location cannot be less than zero or greater than or equal to the total number of rows in this tilemap layer."); + ex.Data.Add(nameof(location), location); + ex.Data.Add(nameof(Rows), Rows); + throw ex; + } + } +} diff --git a/source/MonoGame.Aseprite/Tilemaps/AnimatedTIlemapFrame.cs b/source/MonoGame.Aseprite/Tilemaps/AnimatedTIlemapFrame.cs deleted file mode 100644 index 740c734c..00000000 --- a/source/MonoGame.Aseprite/Tilemaps/AnimatedTIlemapFrame.cs +++ /dev/null @@ -1,330 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Collections; -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework; - -namespace MonoGame.Aseprite.Tilemaps; - -/// -/// Defines a frame of animation in an , containing zero or more -/// elements. -/// -public sealed class AnimatedTilemapFrame : IEnumerable -{ - private List _layers = new(); - private Dictionary _layerLookup = new(); - - /// - /// Gets the duration of this . - /// - public TimeSpan Duration { get; } - - /// - /// Gets the total number of elements in this . - /// - public int LayerCount => _layers.Count; - - /// - /// Gets the element at the specified index in this - /// . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public TilemapLayer this[int layerIndex] => GetLayer(layerIndex); - - /// - /// Gets the element with the specified name in this - /// . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if this does not contain a element with - /// the specified name. - /// - public TilemapLayer this[string layerName] => GetLayer(layerName); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The duration to assign the . - /// - public AnimatedTilemapFrame(TimeSpan duration) => Duration = duration; - - /// - /// Creates a new element and adds it to this . - /// - /// - /// The name to assign the element created by this method. The name must be unique - /// across all elements in this . - /// - /// - /// The source to assign the element created by this method. - /// - /// - /// The total number of columns to assign the element created by this method. - /// - /// - /// The total of rows in the element created by this method. - /// - /// - /// The x- and y-position offset, relative to the location the is rendered, to - /// assign the element created by this method. - /// - /// - /// The created by this method. - /// - /// Thrown if this already contains a element with - /// the specified name. - /// - public TilemapLayer CreateLayer(string layerName, Tileset tileset, int columns, int rows, Vector2 offset) - { - TilemapLayer layer = new(layerName, tileset, columns, rows, offset); - AddLayer(layer); - return layer; - } - - /// - /// Adds the given element to this . - /// - /// The element to add. - /// - /// Thrown if this already contains a element with - /// the same name as the element given. - /// - public void AddLayer(TilemapLayer layer) - { - if (_layerLookup.ContainsKey(layer.Name)) - { - throw new InvalidOperationException($"This tileset frame already contains a tilemap layer element with the name '{layer.Name}'."); - } - - _layers.Add(layer); - _layerLookup.Add(layer.Name, layer); - } - - /// - /// Gets the element at the specified index in this - /// . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public TilemapLayer GetLayer(int index) - { - if (index < 0 || index >= LayerCount) - { - throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of tilemap layer elements in this animated tilemap frame."); - } - - return _layers[index]; - } - - /// - /// Gets the element with the specified name in this - /// . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if this does not contain a element with - /// the specified name. - /// - public TilemapLayer GetLayer(string name) - { - if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) - { - return layer; - } - - throw new KeyNotFoundException($"This animated tilemap frame does not contain a tilemap layer element with the name '{name}'."); - } - - /// - /// Get the element at the specified index in this - /// . - /// - /// - /// The index of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if a element was located at the specified index in this - /// ; otherwise, . This method return - /// when the specified index is less than zero or is greater than or equal to the total - /// number of elements in this . - /// - public bool TryGetLayer(int index, [NotNullWhen(true)] out TilemapLayer? layer) - { - layer = default; - - if (index < 0 || index >= LayerCount) - { - return false; - } - - layer = _layers[index]; - return true; - } - - /// - /// Gets the element with the specified name in this - /// . - /// - /// - /// The name of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if a element was located in this - /// with the specified name; otherwise . This method - /// returns if this does not contain a - /// element with the specified name. - /// - public bool TryGetLayer(string name, [NotNullWhen(true)] out TilemapLayer? layer) => - _layerLookup.TryGetValue(name, out layer); - - /// - /// Removes the element at the specified index in this - /// . - /// - /// - /// The index of the element to remove from this . - /// - /// - /// if the element was successfully removed; otherwise, - /// . This method returns if the specified index is less than - /// zero or is greater than or equal to the total number of elements in this tilemap - /// frame. - /// - public bool RemoveLayer(int index) - { - if (index < 0 || index >= LayerCount) - { - return false; - } - - TilemapLayer layer = _layers[index]; - return RemoveLayer(layer); - } - - /// - /// Removes the element with the specified name from this - /// . - /// - /// - /// The name of the element to remove from this - /// - /// - /// if the element was successfully removed; otherwise, - /// . This method returns if this tilemap frame does not - /// contain a element with the specified name. - /// - public bool RemoveLayer(string name) - { - if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) - { - return RemoveLayer(layer); - } - - return false; - } - - /// - /// Removes the given element from this . - /// - /// - /// The element to remove from this . - /// - /// - /// if the element was removed successfully; otherwise, - /// . This method returns if this tilemap frame does not contain - /// the element given. - /// - public bool RemoveLayer(TilemapLayer layer) => - _layers.Remove(layer) && _layerLookup.Remove(layer.Name); - - /// - /// Removes all elements from this . - /// - public void Clear() - { - _layerLookup.Clear(); - _layers.Clear(); - } - - /// - /// Returns an enumerator used to iterate through all of the elements in this - /// . The order of elements in the enumeration is from bottom layer to top - /// layer. - /// - /// - /// An enumerator used to iterate through all of the elements in this - /// . - /// - public IEnumerator GetEnumerator() => _layers.GetEnumerator(); - - /// - /// Returns an enumerator used to iterate through all of the elements in this - /// . The order of elements in the enumeration is from bottom layer to top - /// layer. - /// - /// - /// An enumerator used to iterate through all of the elements in this - /// . - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); -} diff --git a/source/MonoGame.Aseprite/Tilemaps/AnimatedTilemap.cs b/source/MonoGame.Aseprite/Tilemaps/AnimatedTilemap.cs deleted file mode 100644 index f47a634d..00000000 --- a/source/MonoGame.Aseprite/Tilemaps/AnimatedTilemap.cs +++ /dev/null @@ -1,705 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Collections; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tilemaps; - -/// -/// Defines a consisting of elements -/// -public sealed class AnimatedTilemap : IEnumerable -{ - private bool _hasBegun; - private int _currentIndex; - private int _direction; - private List _frames = new(); - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the total number of elements in this . - /// - public int frameCount => _frames.Count; - - /// - /// Gets the element at the specified index in this - /// . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element that was located at the specified index in this - /// . - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public AnimatedTilemapFrame this[int frameIndex] => GetFrame(frameIndex); - - /// - /// Gets a value that indicates if this is currently paused. - /// - public bool IsPaused { get; private set; } - - /// - /// Gets a value that indicates if this is currently animating. - /// - public bool IsAnimating { get; private set; } - - /// - /// Gets a value that indicates whether the animation this should loop. - /// - public bool IsLooping { get; } - - /// - /// Gets a value that indicates whether the animation this should play frames - /// in reverse order. - /// - public bool IsReversed { get; } - - /// - /// Gets a value that indicates whether the animation for this should ping-pong - /// once reaching the last frame of animation. - /// - public bool IsPingPong { get; } - - /// - /// Gets the source element for the current animation frame. - /// - /// - /// Thrown if no elements have been added to this - /// prior to accessing this property. - /// - public AnimatedTilemapFrame CurrentFrame - { - get - { - if (_frames.Count == 0) - { - throw new InvalidOperationException($"Unable to get current frame as no frames have been added to this animated tilemap."); - } - - return this[_currentIndex]; - } - } - - /// - /// Gets or Sets an method to invoke at the start of each animation frame. - /// - public Action? OnFrameBegin { get; set; } = default; - - /// - /// Gets or Sets an method to invoke at the end of each animation frame. - /// - public Action? OnFrameEnd { get; set; } = default; - - /// - /// Gets or Sets an method to invoke at the start of the animation. This will trigger only - /// once when the animation starts before the first frame's triggers. - /// - public Action? OnAnimationBegin { get; set; } = default; - - /// - /// Gets or Sets an method to invoke each time the animation loops. This will trigger each - /// time the animation loops after the last frame's triggers. - /// - public Action? OnAnimationLoop { get; set; } = default; - - /// - /// Gets or Sets an method to invoke when the animation ends. This will only trigger when - /// the animation ends in a non-looping animation, or if a looping animation is stopped by calling the - /// method manually. - /// - public Action? OnAnimationEnd { get; set; } = default; - - /// - /// Gets the amount of time remaining for the before moving to the next frame. - /// - public TimeSpan CurrentFrameTimeRemaining { get; private set; } - - - /// - /// Initializes a new instance of the class. - /// - /// - /// The name to assign the . - /// - /// - /// Indicates whether the animation for the should loop - /// - /// - /// Indicates whether the frames for the should play in reverse order. - /// - /// - /// Indicates whether the animation for this should ping-pong once reaching the - /// last frame of animation - /// - public AnimatedTilemap(string name, bool isLooping = true, bool isReversed = false, bool isPingPong = false) - { - Name = name; - IsLooping = isLooping; - IsReversed = isReversed; - IsPingPong = isPingPong; - Reset(); - } - - /// - /// Updates this . - /// - /// - /// This should only be called once per game update cycle. - /// - /// - /// The amount of time, in seconds, that have elapsed since the last update cycle in the game. - /// - public void Update(double deltaTimeInSeconds) - { - Update(TimeSpan.FromSeconds(deltaTimeInSeconds)); - } - - /// - /// Updates this . - /// - /// - /// This should only be called once per game update cycle. - /// - /// - /// A snapshot of the game timing values for the current update cycle. - /// - public void Update(GameTime gameTime) - { - Update(gameTime.ElapsedGameTime); - } - - /// - /// Updates this . - /// - /// - /// This should only be called once per game update cycle. - /// - /// - /// The amount of time, that have elapsed since the last update cycle in the game. - /// - public void Update(in TimeSpan elapsedTime) - { - if (!IsAnimating || IsPaused) - { - return; - } - - if (!_hasBegun) - { - _hasBegun = true; - OnAnimationBegin?.Invoke(this); - } - - if (CurrentFrameTimeRemaining == CurrentFrame.Duration) - { - OnFrameBegin?.Invoke(this); - } - - CurrentFrameTimeRemaining -= elapsedTime; - - if (CurrentFrameTimeRemaining <= TimeSpan.Zero) - { - AdvanceFrame(); - } - } - - private void AdvanceFrame() - { - OnFrameEnd?.Invoke(this); - - _currentIndex += _direction; - - switch (IsReversed, IsPingPong) - { - case (true, true): - ReversePingPongLoopCheck(); - break; - case (true, false): - ReverseLoopCheck(); - break; - case (false, true): - PingPongLoopCheck(); - break; - case (false, false): - LoopCheck(); - break; - } - - CurrentFrameTimeRemaining = CurrentFrame.Duration; - } - - private void LoopCheck() - { - if (_currentIndex >= _frames.Count) - { - if (IsLooping) - { - _currentIndex = 0; - OnAnimationLoop?.Invoke(this); - } - else - { - _currentIndex = _frames.Count - 1; - Stop(); - } - } - } - - private void ReverseLoopCheck() - { - if (_currentIndex < 0) - { - if (IsLooping) - { - _currentIndex = _frames.Count - 1; - OnAnimationLoop?.Invoke(this); - } - else - { - _currentIndex = 0; - Stop(); - } - } - } - - private void PingPongLoopCheck() - { - if (_currentIndex < 0 || _currentIndex >= _frames.Count) - { - _direction = -_direction; - - if (_direction == -1) - { - _currentIndex = _frames.Count - 2; - } - else - { - if (IsLooping) - { - _currentIndex = 1; - OnAnimationLoop?.Invoke(this); - } - else - { - _currentIndex = 0; - Stop(); - } - } - } - } - - private void ReversePingPongLoopCheck() - { - if (_currentIndex < 0 || _currentIndex >= _frames.Count) - { - _direction = -_direction; - - if (_direction == 1) - { - _currentIndex = 1; - } - else - { - if (IsLooping) - { - _currentIndex = _frames.Count - 2; - OnAnimationLoop?.Invoke(this); - } - else - { - _currentIndex = _frames.Count - 1; - Stop(); - } - } - } - } - - /// - /// Pauses this and prevents it from being updated until it is unpaused. - /// - /// - /// A value that indicates whether the the duration of the should be reset. When - /// this method returns , the duration will not be reset even if this is specified as - /// . - /// - /// - /// this was successfully paused; otherwise, - /// . This method returns this - /// is not currently animating or if it is already paused. - /// - public bool Pause(bool resetFrameDuration = false) - { - // We can only pause something that is animating and is not already paused. This is to prevent improper usage - // that could accidentally reset frame duration if it was set to true. - if (!IsAnimating || IsPaused) - { - return false; - } - - IsPaused = true; - - if (resetFrameDuration) - { - CurrentFrameTimeRemaining = CurrentFrame.Duration; - } - - return true; - } - - /// - /// Unpauses this . - /// - /// - /// A value that indicates whether this should immediately be advanced to the next - /// frame after unpausing. When this method returns , this - /// will -not- be advanced to the next frame, even if this was specified as . - /// - /// - /// if this was successfully unpaused; otherwise, - /// . This method return this is - /// not currently animating or if it has not already been paused. - /// - public bool Unpause(bool advanceToNextFrame = false) - { - // We can't unpause something that's not animating and also isn't paused. This is to prevent improper usage - // that could accidentally advance to the next frame if it was set to true. - if (!IsAnimating || !IsPaused) - { - return false; - } - - IsPaused = false; - - if (advanceToNextFrame) - { - AdvanceFrame(); - } - - return true; - } - - /// - /// Stops this on the . This will trigger the - /// if one was set. - /// - /// - /// this was successfully stopped; otherwise, - /// . This method returns this is - /// not currently animating. If this method returns , this indicates that the - /// action method was not invoked. - /// - public bool Stop() - { - // We can't stop something that's not animating. This is to prevent accidentally invoking the OnAnimationEnd - // action - if (!IsAnimating) - { - return false; - } - - IsAnimating = false; - OnAnimationEnd?.Invoke(this); - return true; - } - - /// - /// Resets this back to its first frame of animation. - /// - /// - /// A value that indicates whether his should be paused after it is reset. - /// - public void Reset(bool paused = false) - { - IsAnimating = true; - IsPaused = paused; - - if (IsReversed) - { - _direction = -1; - _currentIndex = _frames.Count; - } - else - { - _direction = 1; - _currentIndex = 0; - } - - _hasBegun = false; - } - - /// - /// Creates and adds a new element as the next frame of animation in this - /// . - /// - /// - /// The duration to assign the created. - /// - /// - /// The created. - /// - public AnimatedTilemapFrame CreateFrame(TimeSpan duration) - { - AnimatedTilemapFrame frame = new(duration); - AddFrame(frame); - return frame; - } - - /// - /// Adds the given as the next frame of animation in this - /// . - /// - /// - /// The to add - /// - public void AddFrame(AnimatedTilemapFrame frame) => _frames.Add(frame); - - /// - /// Gets the element at the specified index in this - /// . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element that was located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public AnimatedTilemapFrame GetFrame(int frameIndex) - { - if (frameIndex < 0 || frameIndex >= frameCount) - { - throw new ArgumentOutOfRangeException(nameof(frameIndex), $"{nameof(frameIndex)} cannot be less than zero or greater than or equal to the total number of animated tilemap frame elements in this animated tilemap."); - } - - return _frames[frameIndex]; - } - - /// - /// Gets the element at the specified index in this - /// . - /// - /// - /// The index of the element to locate. - /// - /// - /// When this method returns , contains the located; - /// otherwise, . - /// - /// - /// if the element was located; otherwise, - /// . This method returns when the specified index is less than - /// zero or is greater than or equal to the total number of elements in this - /// . - /// - public bool TryGetFrame(int index, out AnimatedTilemapFrame? frame) - { - if (index < 0 || index >= frameCount) - { - frame = default; - return false; - } - - frame = _frames[index]; - return true; - } - - /// - /// Removes the element at the specified index from this - /// . - /// - /// - /// The index of the element to remove. - /// - /// - /// if the was removed successfully; otherwise, - /// . This method returns when the specified index is less than - /// zero or is greater that or equal to the total number of elements in this - /// . - /// - public bool RemoveFrame(int index) - { - if (index < 0 || index >= frameCount) - { - return false; - } - - _frames.RemoveAt(index); - return true; - } - - /// - /// Removes all elements from this . - /// - public void Clear() => _frames.Clear(); - - - /// - /// Draws this using the - /// . - /// - /// - /// The to use for rendering this - /// . - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color) => - Draw(spriteBatch, position, color, Vector2.One, 0.0f); - - /// - /// Draws this using the - /// . - /// - /// - /// The to use for rendering this - /// . - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . - /// - /// - /// The amount of scaling to apply when rendering this . - /// - /// - /// The layer depth to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float scale, float layerDepth) => - Draw(spriteBatch, position, color, new Vector2(scale, scale), layerDepth); - - /// - /// Draws this using the - /// . - /// - /// - /// The to use for rendering the - /// . - /// - /// - /// The x- and y-coordinate location to render the at. - /// - /// - /// The color mask to apply when rendering the . - /// - /// - /// The amount of scaling to apply when rendering the . - /// - /// - /// The layer depth to apply when rendering the . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, Vector2 scale, float layerDepth) => - spriteBatch.Draw(this, position, color, scale, layerDepth); - - /// - /// Returns an enumerator used to iterate through all of the elements in this - /// . The order of elements in the enumeration is from first frame to last frame. - /// - /// - /// An enumerator used to iterate through all of the elements in this - /// . - /// - public IEnumerator GetEnumerator() => _frames.GetEnumerator(); - - /// - /// Returns an enumerator used to iterate through all of the elements in this - /// . The order of elements in the enumeration is from first frame to last frame. - /// - /// - /// An enumerator used to iterate through all of the elements in this - /// . - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Creates a new instance of the class from the given - /// . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to create the from. - /// - /// - /// The created by this method. - /// - public static AnimatedTilemap FromRaw(GraphicsDevice device, RawAnimatedTilemap rawTilemap) - { - AnimatedTilemap animatedTilemap = new(rawTilemap.Name); - - Dictionary tilesetLookup = new(); - - for (int i = 0; i < rawTilemap.RawTilesets.Length; i++) - { - RawTileset rawTileset = rawTilemap.RawTilesets[i]; - Tileset tileset = Tileset.FromRaw(device, rawTileset); - tilesetLookup.Add(rawTileset.ID, tileset); - } - - for (int f = 0; f < rawTilemap.RawTilemapFrames.Length; f++) - { - RawTilemapFrame rawFrame = rawTilemap.RawTilemapFrames[f]; - - TimeSpan duration = TimeSpan.FromMilliseconds(rawFrame.DurationInMilliseconds); - AnimatedTilemapFrame animatedTilemapFrame = animatedTilemap.CreateFrame(duration); - - for (int l = 0; l < rawFrame.RawTilemapLayers.Length; l++) - { - RawTilemapLayer rawLayer = rawFrame.RawTilemapLayers[l]; - - TilemapLayer layer = animatedTilemapFrame.CreateLayer(rawLayer.Name, tilesetLookup[rawLayer.TilesetID], rawLayer.Columns, rawLayer.Rows, rawLayer.Offset.ToVector2()); - - for (int t = 0; t < rawLayer.RawTilemapTiles.Length; t++) - { - RawTilemapTile rawTile = rawLayer.RawTilemapTiles[t]; - - layer.SetTile(t, rawTile.TilesetTileID, rawTile.FlipVertically, rawTile.FlipHorizontally, rawTile.FlipDiagonally); - } - } - } - - return animatedTilemap; - } -} diff --git a/source/MonoGame.Aseprite/Tilemaps/Tile.cs b/source/MonoGame.Aseprite/Tilemaps/Tile.cs deleted file mode 100644 index acfe31f4..00000000 --- a/source/MonoGame.Aseprite/Tilemaps/Tile.cs +++ /dev/null @@ -1,98 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.Tilemaps; - -/// -/// Defines a tile value in a . -/// -public struct Tile -{ - /// - /// Represents a with its properties left uninitialized. - /// - public static readonly Tile Empty; - - /// - /// The ID (or index) of the source tile in the that represents the - /// to render for this . - /// - public int TilesetTileID = 0; - - /// - /// Indicates whether this should be flipped horizontally rendered. - /// - public bool FlipHorizontally = false; - - /// - /// Indicates whether this should be flipped vertically rendered. - /// - public bool FlipVertically = false; - - /// - /// Indicates whether this should be flipped diagonally when rendered. - /// - public bool FlipDiagonally = false; - - /// - /// Gets a value that indicates if this is an empty . - /// - /// - /// Empty tiles have a equal to zero. - /// - public bool IsEmpty => TilesetTileID == 0; - - /// - /// Initializes a new instance of the class. - /// - public Tile() { } - - /// - /// Initializes a new value. - /// - /// - /// The ID (or index) of the source tile in the that represents the - /// to assign for this . - /// - public Tile(int tilesetTileID) => TilesetTileID = tilesetTileID; - - /// - /// Initializes a new value. - /// - /// - /// The ID (or index) of the source tile in the that represents the - /// to assign for this . - /// - /// - /// Indicates whether the should be flipped horizontally when rendered. - /// - /// - /// Indicates whether the should be flipped vertically when rendered. - /// - /// - /// Indicates whether the should be flipped diagonally when rendered. - /// - public Tile(int tilesetTileID, bool flipHorizontally, bool flipVertically, bool flipDiagonally) => - (TilesetTileID, FlipHorizontally, FlipVertically, FlipDiagonally) = (tilesetTileID, flipHorizontally, flipVertically, flipDiagonally); -} diff --git a/source/MonoGame.Aseprite/Tilemaps/Tilemap.cs b/source/MonoGame.Aseprite/Tilemaps/Tilemap.cs deleted file mode 100644 index 176a479a..00000000 --- a/source/MonoGame.Aseprite/Tilemaps/Tilemap.cs +++ /dev/null @@ -1,422 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Collections; -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tilemaps; - -/// -/// Defines a with zero or more elements. -/// -public sealed class Tilemap : IEnumerable -{ - private List _layers = new(); - private Dictionary _layerLookup = new(); - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the total number of elements in this . - /// - public int LayerCount => _layers.Count; - - /// - /// Gets the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public TilemapLayer this[int layerIndex] => GetLayer(layerIndex); - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if this does not contain a element with the - /// specified name. - /// - public TilemapLayer this[string layerName] => GetLayer(layerName); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The name to assign . - /// - public Tilemap(string name) => Name = name; - - /// - /// Creates a new element and adds it to this . - /// - /// - /// The name to give the element created by this method. The name must be unique - /// across all elements in this . - /// - /// - /// The source tileset to assign the element created by this method. - /// - /// - /// The total number of columns to assign the element created by this method. - /// - /// - /// The total of rows to assign the element created by this method. - /// - /// - /// The x- and y-position offset, relative to the location the is rendered, to - /// assign the element created by this method. - /// - /// - /// The created by this method. - /// - /// - /// Thrown if this already contains a element with the - /// specified name. - /// - public TilemapLayer CreateLayer(string layerName, Tileset tileset, int columns, int rows, Vector2 offset) - { - TilemapLayer layer = new(layerName, tileset, columns, rows, offset); - AddLayer(layer); - return layer; - } - - /// - /// Adds the given element to this . - /// - /// - /// The element to add. - /// - /// - /// Thrown if this already contains a element with the same - /// name as the element given. - /// - public void AddLayer(TilemapLayer layer) - { - if (_layerLookup.ContainsKey(layer.Name)) - { - throw new InvalidOperationException($"This tileset already contains a tilemap layer element with the name '{layer.Name}'."); - } - - _layers.Add(layer); - _layerLookup.Add(layer.Name, layer); - } - - /// - /// Get the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public TilemapLayer GetLayer(int index) - { - if (index < 0 || index >= LayerCount) - { - throw new ArgumentOutOfRangeException(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of tilemap layer elements in this tilemap."); - } - - return _layers[index]; - } - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the element to locate. - /// - /// - /// The located. - /// - /// - /// Thrown if this does not contain a element with the - /// specified name. - /// - public TilemapLayer GetLayer(string name) - { - if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) - { - return layer; - } - - throw new KeyNotFoundException($"This tilemap does not contain a tilemap layer element with the name '{name}'."); - } - - /// - /// Get the element at the specified index in this . - /// - /// - /// The index of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if a element was located at the specified index in this - /// ; otherwise, . This method return when - /// the specified index is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public bool TryGetLayer(int index, [NotNullWhen(true)] out TilemapLayer? layer) - { - layer = default; - - if (index < 0 || index >= LayerCount) - { - return false; - } - - layer = _layers[index]; - return true; - } - - /// - /// Gets the element with the specified name in this . - /// - /// - /// The name of the element to locate. - /// - /// - /// When this method returns , contains the element located; - /// otherwise, . - /// - /// - /// if a element was located in this - /// with the specified name; otherwise . This method returns if - /// this does not contain a element with the specified name. - /// - public bool TryGetLayer(string name, [NotNullWhen(true)] out TilemapLayer? layer) => - _layerLookup.TryGetValue(name, out layer); - - /// - /// Removes the element at the specified index in this . - /// - /// - /// The index of the element to remove from this . - /// - /// - /// if the element was successfully removed; otherwise, - /// . This method returns if the specified index is less than - /// zero or is greater than or equal to the total number of elements in this - /// . - /// - public bool RemoveLayer(int index) - { - if (index < 0 || index >= LayerCount) - { - return false; - } - - TilemapLayer layer = _layers[index]; - return RemoveLayer(layer); - } - - /// - /// Removes the element with the specified name from this . - /// - /// - /// The name of the element to remove from this - /// - /// - /// if the element was successfully removed; otherwise, - /// . This method returns if this does not - /// contain a element with the specified name. - /// - public bool RemoveLayer(string name) - { - if (_layerLookup.TryGetValue(name, out TilemapLayer? layer)) - { - return RemoveLayer(layer); - } - - return false; - } - - /// - /// Removes the given element from this . - /// - /// - /// The element to remove from this . - /// - /// - /// if the element was removed successfully; otherwise, - /// . This method returns false if this does not contain the - /// element given. - /// - public bool RemoveLayer(TilemapLayer layer) => - _layers.Remove(layer) && _layerLookup.Remove(layer.Name); - - /// - /// Removes all elements from this . - /// - public void Clear() - { - _layerLookup.Clear(); - _layers.Clear(); - } - - /// - /// Draws this using the . - /// - /// - /// The to use for rendering this . - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color) => - Draw(spriteBatch, position, color, Vector2.One, 0.0f); - - /// - /// Draws this using the . - /// - /// - /// The to use for rendering this . - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . - /// - /// - /// The amount of scaling to apply when rendering this . - /// - /// - /// The layer depth to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float scale, float layerDepth) => - Draw(spriteBatch, position, color, new Vector2(scale, scale), layerDepth); - - /// - /// Draws a using this . - /// - /// - /// The to use for rendering this . - /// - /// - /// The x- and y-coordinate location to render this at. - /// - /// - /// The color mask to apply when rendering this . - /// - /// - /// The amount of scaling to apply when rendering this . - /// - /// - /// The layer depth to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, Vector2 scale, float layerDepth) => - spriteBatch.Draw(this, position, color, scale, layerDepth); - - /// - /// Returns an enumerator used to iterate through all of the elements in this - /// . The order of elements in the enumeration is from bottom layer to top layer. - /// - /// - /// An enumerator used to iterate through all of the elements in this - /// . - /// - public IEnumerator GetEnumerator() => _layers.GetEnumerator(); - - /// - /// Returns an enumerator used to iterate through all of the elements in this - /// . The order of elements in the enumeration is from bottom layer to top layer. - /// - /// - /// An enumerator used to iterate through all of the elements in this - /// . - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - /// - /// Creates a new instance of the class from the given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to create the from. - /// - /// - /// The created by this method. - /// - public static Tilemap FromRaw(GraphicsDevice device, RawTilemap rawTilemap) - { - Tilemap tilemap = new(rawTilemap.Name); - Dictionary tilesetLookup = new(); - - for (int i = 0; i < rawTilemap.RawTilesets.Length; i++) - { - RawTileset rawTileset = rawTilemap.RawTilesets[i]; - Tileset tileset = Tileset.FromRaw(device, rawTileset); - tilesetLookup.Add(rawTileset.ID, tileset); - } - - for (int l = 0; l < rawTilemap.RawLayers.Length; l++) - { - RawTilemapLayer rawLayer = rawTilemap.RawLayers[l]; - Tileset tileset = tilesetLookup[rawLayer.TilesetID]; - - TilemapLayer layer = tilemap.CreateLayer(rawLayer.Name, tileset, rawLayer.Columns, rawLayer.Rows, rawLayer.Offset.ToVector2()); - - for (int t = 0; t < rawLayer.RawTilemapTiles.Length; t++) - { - RawTilemapTile rawTile = rawLayer.RawTilemapTiles[t]; - - layer.SetTile(t, rawTile.TilesetTileID, rawTile.FlipVertically, rawTile.FlipHorizontally, rawTile.FlipDiagonally); - } - } - - return tilemap; - } -} diff --git a/source/MonoGame.Aseprite/Tilemaps/TilemapLayer.cs b/source/MonoGame.Aseprite/Tilemaps/TilemapLayer.cs deleted file mode 100644 index ba2648ae..00000000 --- a/source/MonoGame.Aseprite/Tilemaps/TilemapLayer.cs +++ /dev/null @@ -1,645 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Collections; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; - -namespace MonoGame.Aseprite.Tilemaps; - -/// -/// Defines a grid-like layer in a tilemap that contains a collection of tiles. -/// -public sealed class TilemapLayer : IEnumerable -{ - private Tile[] _tiles; - private Vector2 _offset = Vector2.Zero; - - /// - /// Gets a read-only span of the elements in this . - /// - public ReadOnlySpan Tiles => _tiles; - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets or Sets the source referenced by the elements in this - /// . - /// - public Tileset Tileset { get; set; } - - /// - /// Gets the total number of columns in this . - /// - public int Columns { get; } - - /// - /// Gets the total number of rows in this . - /// - public int Rows { get; } - - /// - /// Gets the width, in pixels, of this . - /// Width = Tileset.TileWidth * Columns - /// - public int Width => Tileset.TileWidth * Columns; - - /// - /// Gets the height, in pixels, of this . - /// Height = Tileset.TileHeight * Rows - /// - public int Height => Tileset.TileHeight * Rows; - - /// - /// Gets or Sets the transparency of this . - /// - public float Transparency { get; set; } = 1.0f; - - /// - /// Gets or Sets a value that indicates whether this is visible and should be - /// rendered. - /// - public bool IsVisible { get; set; } = true; - - /// - /// Gets or Sets the x- and y-coordinate position offset, relative to the position of the , - /// to render this at - /// - public Vector2 Offset - { - get => _offset; - set => _offset = value; - } - - /// - /// Gets or Sets the x-position offset, relative to the position of the , to render this - /// at - /// - public float OffsetX - { - get => _offset.X; - set => _offset.X = value; - } - - /// - /// Gets or Sets the y-position offset, relative to the position of the , to render this - /// at - /// - public float OffsetY - { - get => _offset.Y; - set => _offset.Y = value; - } - - /// - /// Gets the total number of elements in this . - /// - public int TileCount => _tiles.Length; - - /// - /// Gets the element at the specified index in this - /// - /// - /// The index of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public Tile this[int tileIndex] => GetTile(tileIndex); - - /// - /// Gets the element located at the specified column and row in this - /// . - /// - /// - /// The column of the element to locate. - /// - /// - /// The row of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if either the column or rows specified is less than zero or if either is greater than or equal to the - /// total number of columns or rows in this . - /// - public Tile this[int column, int row] => GetTile(column, row); - - /// - /// Gets the element located at the specified column and row location in this - /// . - /// - /// - /// The column and row location of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if either the column or rows specified in the location is less than zero or if either is greater - /// than or equal to the total number of columns or rows in this . - /// - public Tile this[Point location] => GetTile(location); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The name assign the . - /// - /// - /// The source tileset used by the tiles in this . - /// - /// - /// The total number of columns to assign the . - /// - /// - /// The total number of rows to assign the . - /// - /// - /// The x- and y-coordinate position offset, relative to the position of the to assign the - /// . - /// - public TilemapLayer(string name, Tileset tileset, int columns, int rows, Vector2 offset) - { - Tileset = tileset; - Name = name; - _offset = offset; - Columns = columns; - Rows = rows; - _tiles = new Tile[columns * rows]; - } - - /// - /// Returns a value that indicates whether the element at the specified index in this - /// is empty. - /// - /// - /// The index of the element to check. - /// - /// - /// if the element at the specified index is empty; otherwise, - /// . - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public bool IsEmpty(int index) => GetTile(index).IsEmpty; - - /// - /// Returns a value that indicates whether the element at the specified column and row in - /// this is empty. - /// - /// - /// The column of the element to check. - /// - /// - /// The row of the element to check. - /// - /// - /// if the element at the specified column and row in this - /// is empty; otherwise, . - /// - /// - /// Thrown if either the column or row specified is less than zero or if either is greater than or equal to the - /// total number of columns or rows in this . - /// - public bool IsEmpty(int column, int row) => GetTile(column, row).IsEmpty; - - /// - /// Returns a value that indicates whether the element at the specified column and row - /// location in this is empty. - /// - /// - /// The column and row location of the element to check. - /// - /// - /// if the element at the specified column and row location in this - /// is empty; otherwise, . - /// - /// - /// Thrown if either the column or row in the specified location is less than zero or if either is greater - /// than or equal to the total number of columns or rows in this . - /// - public bool IsEmpty(Point location) => GetTile(location).IsEmpty; - - /// - /// Sets the element at the specified index in this using the - /// values provided. - /// - /// - /// The index of the element in this to set. - /// - /// - /// The ID of the source tile in the that represents the to - /// render for the element being set. - /// - /// - /// Indicates whether the element being set should be flipped horizontally when rendered. - /// - /// - /// Indicates if the element being set should be flipped vertically when rendered. - /// - /// - /// Indicates if the element being set should be flipped diagonally when rendered. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public void SetTile(int index, int tilesetTileID, bool flipHorizontally = false, bool flipVertically = false, bool flipDiagonally = false) - { - Tile tile; - tile.TilesetTileID = tilesetTileID; - tile.FlipHorizontally = flipHorizontally; - tile.FlipVertically = flipVertically; - tile.FlipDiagonally = flipDiagonally; - SetTile(index, tile); - } - - /// - /// Sets the element at the specified column and row in this - /// using the values provided. - /// - /// - /// The column in this to set the element at. - /// - /// - /// The row in this to set the element at. - /// - /// - /// The ID of the source tile in the that represents the to - /// render for the element being set. - /// - /// - /// Indicates whether the element being set should be flipped horizontally when rendered. - /// - /// - /// Indicates if the element being set should be flipped vertically when rendered. - /// - /// - /// Indicates if the element being set should be flipped diagonally when rendered. - /// - /// - /// Thrown if either the column or row specified is less than zero or are greater than or equal to the total - /// number of columns or rows in this . - /// - public void SetTile(int column, int row, int tilesetTileID, bool flipHorizontally = false, bool flipVertically = false, bool flipDiagonally = false) - { - Tile tile; - tile.TilesetTileID = tilesetTileID; - tile.FlipHorizontally = flipHorizontally; - tile.FlipVertically = flipVertically; - tile.FlipDiagonally = flipDiagonally; - SetTile(column, row, tile); - } - - /// - /// Sets the element at the specified column and row location in this - /// using the values provided. - /// - /// - /// The column and row location in this to set the element at. - /// - /// - /// The ID of the source tile in the that represents the to - /// render for the element being set. - /// - /// - /// Indicates whether the element being set should be flipped horizontally when rendered. - /// - /// - /// Indicates if the element being set should be flipped vertically when rendered. - /// - /// - /// Indicates if the element being set should be flipped diagonally when rendered. - /// - /// - /// Thrown if either the column or row in the specified location is less than zero or are greater than or equal - /// to the total number of columns or rows in this . - /// - public void SetTile(Point location, int tilesetTileID, bool flipHorizontally = false, bool flipVertically = false, bool flipDiagonally = false) - { - Tile tile; - tile.TilesetTileID = tilesetTileID; - tile.FlipHorizontally = flipHorizontally; - tile.FlipVertically = flipVertically; - tile.FlipDiagonally = flipDiagonally; - SetTile(location, tile); - } - - /// - /// Sets the specified index in this to the element given. - /// - /// - /// The index in this to set. - /// - /// - /// The element to set at the index. - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public void SetTile(int index, Tile tile) - { - CheckIndex(index); - _tiles[index] = tile; - } - - /// - /// Sets the specified column and row in this to the element - /// given. - /// - /// - /// The column in this to set. - /// - /// - /// The row in this to set. - /// - /// - /// The element to set at the column and row. - /// - /// - /// Thrown if either the column or row specified are less than zero or are greater than or equal to the total - /// number of columns or rows in this . - /// - public void SetTile(int column, int row, Tile tile) - { - CheckColumn(column); - CheckRow(row); - int index = ToIndex(column, row); - _tiles[index] = tile; - } - - /// - /// Sets the specified column and row location in this to the - /// element given. - /// - /// - /// The column and row location in this to set. - /// - /// - /// The element to set at the column and row location. - /// - /// - /// Thrown if either the column or row in the specified location are less than zero or are greater than or equal - /// to the total number of columns or rows in this . - /// - public void SetTile(Point location, Tile tile) - { - CheckLocation(location); - int index = ToIndex(location.X, location.Y); - _tiles[index] = tile; - } - - /// - /// Gets the element located at the specified index in this . - /// - /// - /// The index of the element in this to locate. - /// - /// - /// The element located - /// - /// - /// Thrown if the index specified is less than zero or is greater than or equal to the total number of - /// elements in this . - /// - public Tile GetTile(int index) - { - CheckIndex(index); - return _tiles[index]; - } - - /// - /// Gets the element located at the specified column and row in this - /// . - /// - /// - /// The column of the element to locate. - /// - /// - /// The row of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if either the column or rows specified are less than zero or are greater than or equal to the total - /// number of columns or rows in this . - /// - public Tile GetTile(int column, int row) - { - CheckColumn(column); - CheckRow(row); - int index = ToIndex(column, row); - return _tiles[index]; - } - - /// - /// Gets the element located at the specified column and row location in this - /// . - /// - /// - /// The column and row location of the element to locate. - /// - /// - /// The element located. - /// - /// - /// Thrown if either the column or rows in the specified location are less than zero or are greater than or - /// equal to the total number of columns or rows in this . - /// - public Tile GetTile(Point location) - { - CheckLocation(location); - int index = ToIndex(location.X, location.Y); - return _tiles[index]; - } - - - /// - /// Clears all elements in this by resetting them to an empty - /// value. - /// - public void Clear() - { - Array.Clear(_tiles); - } - - /// - /// Draws this layer using the - /// . - /// - /// - /// The to use for rendering this - /// . - /// - /// - /// The x- and y-coordinate location to draw this at. Drawing this - /// using this method ignores the . - /// - /// - /// The color mask to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color) => - Draw(spriteBatch, position, color, Vector2.One, 0.0f); - - /// - /// Draws this layer using the - /// . - /// - /// - /// The to use for rendering this - /// . - /// - /// - /// The x- and y-coordinate location to draw this at. Drawing this - /// using this method ignores the . - /// - /// - /// The color mask to apply when rendering this . - /// - /// - /// The amount of scaling to apply when rendering this . - /// - /// - /// The layer depth to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, float scale, float layerDepth) => - Draw(spriteBatch, position, color, new Vector2(scale, scale), layerDepth); - - /// - /// Draws this layer using the - /// . - /// - /// - /// The to use for rendering this - /// . - /// - /// - /// The x- and y-coordinate location to draw this at. Drawing this - /// using this method ignores the . - /// - /// - /// The color mask to apply when rendering this . - /// - /// - /// The amount of scaling to apply when rendering this . - /// - /// - /// The layer depth to apply when rendering this . - /// - public void Draw(SpriteBatch spriteBatch, Vector2 position, Color color, Vector2 scale, float layerDepth) => - spriteBatch.Draw(this, position, color, scale, layerDepth); - - - /// - /// Returns an enumerator that iterates through all elements in this - /// . The order tiles in the enumeration is from top-to-bottom, read left-to-right. - /// - /// - /// An enumerator that iterates through all elements in this . - /// - public IEnumerator GetEnumerator() - { - for (int i = 0; i < _tiles.Length; i++) - { - yield return _tiles[i]; - } - } - - /// - /// Returns an enumerator that iterates through all elements in this - /// . The order tiles in the enumeration is from top-to-bottom, read left-to-right. - /// - /// - /// An enumerator that iterates through all elements in this . - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - private int ToIndex(int column, int row) => row * Columns + column; - - private void CheckIndex(int index) - { - if (index < 0 || index >= TileCount) - { - ArgumentOutOfRangeException ex = new(nameof(index), $"{nameof(index)} cannot be less than zero or greater than or equal to the total number of tiles in this tilemap layer."); - ex.Data.Add(nameof(index), index); - ex.Data.Add(nameof(TileCount), TileCount); - throw ex; - } - } - - private void CheckRow(int row) - { - if (row < 0 || row >= Rows) - { - ArgumentOutOfRangeException ex = new(nameof(row), $"{nameof(row)} cannot be less than zero or greater than or equal to the total number of rows in this tilemap layer."); - ex.Data.Add(nameof(row), row); - ex.Data.Add(nameof(Rows), Rows); - throw ex; - } - } - - private void CheckColumn(int column) - { - if (column < 0 || column >= Columns) - { - ArgumentOutOfRangeException ex = new(nameof(column), $"{nameof(column)} cannot be less than zero or greater than or equal to the total number of columns in this tilemap layer."); - ex.Data.Add(nameof(column), column); - ex.Data.Add(nameof(Columns), Columns); - throw ex; - } - } - - private void CheckLocation(Point location) - { - if (location.X < 0 || location.X >= Columns) - { - ArgumentOutOfRangeException ex = new(nameof(location), $"The column in the location cannot be less than zero or greater than or equal to the total number of columns in this tilemap layer."); - ex.Data.Add(nameof(location), location); - ex.Data.Add(nameof(Columns), Columns); - throw ex; - } - - if (location.Y < 0 || location.Y >= Rows) - { - ArgumentOutOfRangeException ex = new(nameof(location), $"The row in the location cannot be less than zero or greater than or equal to the total number of rows in this tilemap layer."); - ex.Data.Add(nameof(location), location); - ex.Data.Add(nameof(Rows), Rows); - throw ex; - } - } -} diff --git a/source/MonoGame.Aseprite/Tilemaps/Tileset.cs b/source/MonoGame.Aseprite/Tilemaps/Tileset.cs deleted file mode 100644 index 84b5d017..00000000 --- a/source/MonoGame.Aseprite/Tilemaps/Tileset.cs +++ /dev/null @@ -1,370 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Diagnostics.CodeAnalysis; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Graphics; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tilemaps; - -/// -/// Defines a with a source image and named elements that -/// represent the tiles. -/// -/// -/// A is similar in function to a in that it uses a single -/// source image and has named for sections within that image. The difference is that -/// a autogenerates the elements into a grid like structure and -/// the accessor for each is by location id or column and row only. -/// -public sealed class Tileset -{ - private TextureRegion[] _regions; - - /// - /// Gets the name assigned to this . - /// - public string Name { get; } - - /// - /// Gets the source texture image used by this . - /// - public Texture2D Texture { get; } - - /// - /// Gets the width, in pixels, of each tile in this . - /// - public int TileWidth { get; } - - /// - /// Gets the height, in pixels of each tile in this . - /// - public int TileHeight { get; } - - /// - /// Gets the total number of rows in this . - /// - public int RowCount { get; } - - /// - /// Gets the total number of columns in this . - /// - public int ColumnCount { get; } - - /// - /// G ets the total number of tiles in this . - /// - public int TileCount { get; } - - /// - /// Gets a read-only span of the elements that represent the tiles in this - /// . - /// - public ReadOnlySpan Tiles => _regions; - - /// - /// Gets the of the tile at the specified index in this . - /// - /// - /// The index of the tile to locate. - /// - /// - /// The for the tile located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of tiles in - /// this . - /// - public TextureRegion this[int index] => GetTile(index); - - /// - /// Gets the for the tile at the specified column and row in this - /// . - /// - /// - /// The column of the tile to locate in this . - /// - /// - /// The row of the tile to locate in this . - /// - /// - /// The for the tile located. - /// - /// - /// Thrown if either the column or row specified are less than zero or if either are greater than or equal to - /// the total number of columns or rows in this . - /// - public TextureRegion this[int column, int row] => GetTile(column, row); - - /// - /// Gets the for the tile at the specified column and row location in this - /// . - /// - /// - /// The column and row location of the tile to locate in this . - /// - /// - /// The for the tile located. - /// - /// - /// Thrown if either the column or row in the location specified are less than zero or if either are greater - /// than or equal to the total number of columns or rows in this . - /// - public TextureRegion this[Point location] => GetTile(location); - - /// - /// Initializes a new instance of the class. - /// - /// - /// The elements for each tile in this are auto-generated - /// based on the and specified. Both of these values - /// must be greater than zero and the width of the must divide evenly by - /// the and the height of the must divide evenly by the - /// - /// - /// - /// The name to assign the . - /// - /// - /// The source texture used by this . - /// - /// - /// The width, in pixels, of each tile in this . - /// - /// - /// The height, in pixels, of each tile in this . - /// - /// - /// Thrown if the or values are less than one. - /// - /// - /// Thrown if the width of the does not divide evenly by the - /// specified or if the height of the does not divide - /// evenly by the specified. - /// - public Tileset(string name, Texture2D texture, int tileWidth, int tileHeight) - { - if (tileWidth < 1) - { - throw new ArgumentOutOfRangeException(nameof(tileWidth), $"{nameof(tileWidth)} must be greater than zero"); - } - - if (tileHeight < 1) - { - throw new ArgumentOutOfRangeException(nameof(tileHeight), $"{nameof(tileHeight)} must be greater than zero"); - } - - if (texture.Width % tileWidth != 0) - { - throw new ArgumentException($"The texture width ({texture.Width}) does not divide evenly by the tile width ({tileWidth} given."); - } - - if (texture.Height % tileHeight != 0) - { - throw new ArgumentException($"The texture height ({texture.Height}) does not divide evenly by the tile height ({tileHeight}) given."); - } - - Name = name; - Texture = texture; - TileWidth = tileWidth; - TileHeight = tileHeight; - ColumnCount = texture.Width / tileWidth; - RowCount = texture.Height / tileHeight; - TileCount = ColumnCount * RowCount; - CreateTextureRegions(); - } - - [MemberNotNull(nameof(_regions))] - private void CreateTextureRegions() - { - _regions = new TextureRegion[TileCount]; - - for (int i = 0; i < TileCount; i++) - { - int x = (i % ColumnCount) * TileWidth; - int y = (i / ColumnCount) * TileHeight; - - Rectangle bounds = new(x, y, TileWidth, TileHeight); - _regions[i] = new TextureRegion($"{Name}_{i}", Texture, bounds); - } - } - - /// - /// Gets the of the tile at the specified index in this . - /// - /// - /// The index of the tile to locate. - /// - /// - /// The for the tile located. - /// - /// - /// Thrown if the specified index is less than zero or is greater than or equal to the total number of tiles in - /// this . - /// - public TextureRegion GetTile(int index) - { - if (index < 0 || index >= TileCount) - { - throw new ArgumentOutOfRangeException(); - } - - return _regions[index]; - } - - /// - /// Gets the for the tile at the specified column and row in this - /// . - /// - /// - /// The column and row location of the tile to locate in this . - /// - /// - /// The for the tile located. - /// - /// - /// Thrown if either the column or row in the specified location are less than zero or if either are greater - /// than or equal to the total number of columns or rows respectively. - /// - public TextureRegion GetTile(Point location) => GetTile(location.X, location.Y); - - /// - /// Gets the for the tile at the specified column and row in this - /// . - /// - /// - /// The column of the tile to locate in this . - /// - /// - /// The row of the tile to locate in this . - /// - /// - /// The for the tile located. - /// - /// - /// Thrown if either the column or row specified are less than zero or if either are greater than or equal to - /// the total number of columns or rows in this . - /// - public TextureRegion GetTile(int column, int row) - { - int index = row * ColumnCount + column; - return GetTile(index); - } - - /// - /// Gets the of the tile at the specified index in this - /// . - /// - /// - /// The index of the tile to locate. - /// - /// - /// When this method returns , contains the of the tile - /// located; otherwise, . - /// - /// - /// if a tile was located at the specified index; otherwise, . - /// This method returns if the specified index is less than zero or is greater than or - /// equal to the total number of tiles in this . - /// - public bool TryGetTile(int index, [NotNullWhen(true)] out TextureRegion? tile) - { - tile = default; - - if (index < 0 || index >= TileCount) - { - return false; - } - - tile = _regions[index]; - return true; - } - - /// - /// Gets the for the tile at the specified column and row in this - /// . - /// - /// - /// The column and row location of the tile to locate in this . - /// - /// - /// When this method returns , contains the of the tile - /// located; otherwise, . - /// - /// - /// if a tile was located at the specified column and row location; otherwise - /// . This method return if the column or row in the location - /// specified is less than zero or if either are greater than or equal to the total number of columns or rows - /// in this . - /// - public bool TryGetTile(Point location, [NotNullWhen(true)] out TextureRegion? tile) => - TryGetTile(location.X, location.Y, out tile); - - /// - /// Gets the for the tile at the specified column and row in this - /// . - /// - /// - /// The column of the tile to locate in this . - /// - /// - /// The row of the tile to locate in this . - /// - /// - /// When this method returns , contains the of the tile - /// located; otherwise, . - /// - /// - /// if a tile was located at the specified column and row; otherwise - /// . This method return if the column or row in the location - /// specified is less than zero or if either are greater than or equal to the total number of columns or rows - /// in this . - /// - public bool TryGetTile(int column, int row, [NotNullWhen(true)] out TextureRegion? tile) - { - int index = row * ColumnCount + column; - return TryGetTile(index, out tile); - } - - /// - /// Creates a new instance of the class from the given . - /// - /// - /// The used to create graphical resources. - /// - /// - /// The to create the from. - /// - /// - /// The created by this method. - /// - public static Tileset FromRaw(GraphicsDevice device, RawTileset rawTileset) - { - Texture2D texture = new(device, rawTileset.RawTexture.Width, rawTileset.RawTexture.Height, mipmap: false, SurfaceFormat.Color); - texture.SetData(rawTileset.RawTexture.Pixels.ToArray()); - texture.Name = rawTileset.RawTexture.Name; - return new(rawTileset.Name, texture, rawTileset.TileWidth, rawTileset.TileHeight); - } -} diff --git a/source/MonoGame.Aseprite/Tileset.cs b/source/MonoGame.Aseprite/Tileset.cs new file mode 100644 index 00000000..1f8872b1 --- /dev/null +++ b/source/MonoGame.Aseprite/Tileset.cs @@ -0,0 +1,286 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Diagnostics.CodeAnalysis; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + + +namespace MonoGame.Aseprite; + +/// +/// Defines a with a source image and named elements that +/// represent the tiles. +/// +/// +/// A is similar in function to a in that it uses a single +/// source image and has named for sections within that image. The difference is that +/// a auto generates the elements into a grid like structure and +/// the accessor for each is by location id or column and row only. +/// +public sealed class Tileset +{ + private TextureRegion[] _regions; + + /// + /// Gets the name assigned to this . + /// + public string Name { get; } + + /// + /// Gets the source texture image used by this . + /// + public Texture2D Texture { get; } + + /// + /// Gets the width, in pixels, of each tile in this . + /// + public int TileWidth { get; } + + /// + /// Gets the height, in pixels of each tile in this . + /// + public int TileHeight { get; } + + /// + /// Gets the total number of rows in this . + /// + public int RowCount { get; } + + /// + /// Gets the total number of columns in this . + /// + public int ColumnCount { get; } + + /// + /// Gets the total number of tiles in this . + /// + public int TileCount { get; } + + /// + /// Gets a read-only span of the elements that represent the tiles in this + /// . + /// + public ReadOnlySpan Tiles => _regions; + + /// + /// Gets the of the tile at the specified index in this . + /// + /// The index of the tile to locate. + /// The for the tile located. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of tiles in + /// this . + /// + public TextureRegion this[int index] => GetTile(index); + + /// + /// Gets the for the tile at the specified column and row in this + /// . + /// + /// The column of the tile to locate in this . + /// The row of the tile to locate in this . + /// The for the tile located. + /// + /// Thrown if either the column or row specified are less than zero or if either are greater than or equal to + /// the total number of columns or rows in this . + /// + public TextureRegion this[int column, int row] => GetTile(column, row); + + /// + /// Gets the for the tile at the specified column and row location in this + /// . + /// + /// The column and row location of the tile to locate in this . + /// The for the tile located. + /// + /// Thrown if either the column or row in the location specified are less than zero or if either are greater + /// than or equal to the total number of columns or rows in this . + /// + public TextureRegion this[Point location] => GetTile(location); + + /// + /// Initializes a new instance of the class. + /// + /// + /// The elements for each tile in this are auto-generated + /// based on the and specified. Both of these values + /// must be greater than zero and the width of the must divide evenly by + /// the and the height of the must divide evenly by the + /// + /// + /// The name to assign the . + /// The source texture used by this . + /// The width, in pixels, of each tile in this . + /// The height, in pixels, of each tile in this . + /// + /// Thrown if the or values are less than one. + /// + /// + /// Thrown if the width of the does not divide evenly by the + /// specified or if the height of the does not divide + /// evenly by the specified. + /// + public Tileset(string name, Texture2D texture, int tileWidth, int tileHeight) + { + if (tileWidth < 1) + { + throw new ArgumentOutOfRangeException(nameof(tileWidth), $"{nameof(tileWidth)} must be greater than zero"); + } + + if (tileHeight < 1) + { + throw new ArgumentOutOfRangeException(nameof(tileHeight), $"{nameof(tileHeight)} must be greater than zero"); + } + + if (texture.Width % tileWidth != 0) + { + throw new ArgumentException($"The texture width ({texture.Width}) does not divide evenly by the tile width ({tileWidth} given."); + } + + if (texture.Height % tileHeight != 0) + { + throw new ArgumentException($"The texture height ({texture.Height}) does not divide evenly by the tile height ({tileHeight}) given."); + } + + Name = name; + Texture = texture; + TileWidth = tileWidth; + TileHeight = tileHeight; + ColumnCount = texture.Width / tileWidth; + RowCount = texture.Height / tileHeight; + TileCount = ColumnCount * RowCount; + CreateTextureRegions(); + } + + [MemberNotNull(nameof(_regions))] + private void CreateTextureRegions() + { + _regions = new TextureRegion[TileCount]; + + for (int i = 0; i < TileCount; i++) + { + int x = i % ColumnCount * TileWidth; + int y = i / ColumnCount * TileHeight; + + Rectangle bounds = new(x, y, TileWidth, TileHeight); + _regions[i] = new TextureRegion($"{Name}_{i}", Texture, bounds); + } + } + + /// + /// Gets the of the tile at the specified index in this . + /// + /// The index of the tile to locate. + /// The for the tile located. + /// + /// Thrown if the specified index is less than zero or is greater than or equal to the total number of tiles in + /// this . + /// + public TextureRegion GetTile(int index) + { + if (index < 0 || index >= TileCount) + { + throw new ArgumentOutOfRangeException(); + } + + return _regions[index]; + } + + /// + /// Gets the for the tile at the specified column and row in this + /// . + /// + /// The column and row location of the tile to locate in this . + /// The for the tile located. + /// + /// Thrown if either the column or row in the specified location are less than zero or if either are greater + /// than or equal to the total number of columns or rows respectively. + /// + public TextureRegion GetTile(Point location) => GetTile(location.X, location.Y); + + /// + /// Gets the for the tile at the specified column and row in this + /// . + /// + /// The column of the tile to locate in this . + /// The row of the tile to locate in this . + /// The for the tile located. + /// + /// Thrown if either the column or row specified are less than zero or if either are greater than or equal to + /// the total number of columns or rows in this . + /// + public TextureRegion GetTile(int column, int row) + { + int index = row * ColumnCount + column; + return GetTile(index); + } + + /// + /// Gets the of the tile at the specified index in this + /// . + /// + /// The index of the tile to locate. + /// + /// When this method returns , contains the of the tile + /// located; otherwise, . + /// + /// + /// if a tile was located at the specified index; otherwise, . + /// This method returns if the specified index is less than zero or is greater than or + /// equal to the total number of tiles in this . + /// + public bool TryGetTile(int index, [NotNullWhen(true)] out TextureRegion? tile) + { + tile = default; + + if (index < 0 || index >= TileCount) + { + return false; + } + + tile = _regions[index]; + return true; + } + + /// + /// Gets the for the tile at the specified column and row in this + /// . + /// + /// The column and row location of the tile to locate in this . + /// + /// When this method returns , contains the of the tile + /// located; otherwise, . + /// + /// + /// if a tile was located at the specified column and row location; otherwise + /// . This method return if the column or row in the location + /// specified is less than zero or if either are greater than or equal to the total number of columns or rows + /// in this . + /// + public bool TryGetTile(Point location, [NotNullWhen(true)] out TextureRegion? tile) => + TryGetTile(location.X, location.Y, out tile); + + /// + /// Gets the for the tile at the specified column and row in this + /// . + /// + /// The column of the tile to locate in this . + /// The row of the tile to locate in this . + /// + /// When this method returns , contains the of the tile + /// located; otherwise, . + /// + /// + /// if a tile was located at the specified column and row; otherwise + /// . This method return if the column or row in the location + /// specified is less than zero or if either are greater than or equal to the total number of columns or rows + /// in this . + /// + public bool TryGetTile(int column, int row, [NotNullWhen(true)] out TextureRegion? tile) + { + int index = row * ColumnCount + column; + return TryGetTile(index, out tile); + } +} diff --git a/source/MonoGame.Aseprite/Utils/AsepriteDotNetExtensions.cs b/source/MonoGame.Aseprite/Utils/AsepriteDotNetExtensions.cs new file mode 100644 index 00000000..2dc0f641 --- /dev/null +++ b/source/MonoGame.Aseprite/Utils/AsepriteDotNetExtensions.cs @@ -0,0 +1,61 @@ +// Copyright (c) Christopher Whitley. All rights reserved. +// Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +using System.Runtime.CompilerServices; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using AseColor = AsepriteDotNet.Common.Rgba32; +using AsePoint = AsepriteDotNet.Common.Point; +using AseRectangle = AsepriteDotNet.Common.Rectangle; +using AseTexture = AsepriteDotNet.Texture; + +namespace MonoGame.Aseprite.Utils; + +/// +/// Defines extension methods for translating between AsepriteDotNet types to MonoGame types. +/// +public static class AsepriteDotNetExtensions +{ + /// + /// Converts an AsepriteDotNet Texture to a MonoGame Texture2D object. + /// + /// The AsepriteDotNet texture to convert. + /// The graphics device used to create graphical resources. + /// The converted MonoGame Texture2D object. + public static Texture2D ToTexture2D(this AseTexture texture, GraphicsDevice device) + { + Texture2D texture2D = new Texture2D(device, texture.Size.Width, texture.Size.Height); + texture2D.Name = texture.Name; + texture2D.SetData(texture.Pixels.ToArray()); + return texture2D; + } + + /// + /// Converts an AsepriteDotNet color to a MonoGame Color object. + /// + /// The AsepriteDotNet color to convert. + /// The converted MonoGame Color object. + public unsafe static Color ToXnaColor(this AseColor color) => Unsafe.As(ref color); + + /// + /// Converts an AsepriteDotNet point to a MonoGame Point object. + /// + /// The AsepriteDotNet point to convert. + /// The converted MonoGame Point object. + public static Point ToXnaPoint(this AsePoint point) => new Point(point.X, point.Y); + + /// + /// Converts an AsepriteDotNet point to a MonoGame Vector2 object. + /// + /// The AsepriteDotNet point to convert. + /// The converted MonoGame Vector2 object. + public static Vector2 ToXnaVector2(this AsePoint point) => new Vector2(point.X, point.Y); + + /// + /// Converts an AsepriteDotNet rectangle to a MonoGame Rectangle object. + /// + /// The AsepriteDotNet rectangle to convert. + /// The converted MonoGame Rectangle object. + public static Rectangle ToXnaRectangle(this AseRectangle rect) => new Rectangle(rect.X, rect.Y, rect.Width, rect.Height); +} diff --git a/source/Monogame.Aseprite.sln b/source/Monogame.Aseprite.sln deleted file mode 100644 index da4da035..00000000 --- a/source/Monogame.Aseprite.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Aseprite", "MonoGame.Aseprite\MonoGame.Aseprite.csproj", "{E896ADEA-72E5-43AD-9DA7-D088E3126482}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Aseprite.Content.Pipeline", "MonoGame.Aseprite.Content.Pipeline\MonoGame.Aseprite.Content.Pipeline.csproj", "{37D0A33F-5E1A-47B7-91F8-627EAD7EC319}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E896ADEA-72E5-43AD-9DA7-D088E3126482}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E896ADEA-72E5-43AD-9DA7-D088E3126482}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E896ADEA-72E5-43AD-9DA7-D088E3126482}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E896ADEA-72E5-43AD-9DA7-D088E3126482}.Release|Any CPU.Build.0 = Release|Any CPU - {37D0A33F-5E1A-47B7-91F8-627EAD7EC319}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {37D0A33F-5E1A-47B7-91F8-627EAD7EC319}.Debug|Any CPU.Build.0 = Debug|Any CPU - {37D0A33F-5E1A-47B7-91F8-627EAD7EC319}.Release|Any CPU.ActiveCfg = Release|Any CPU - {37D0A33F-5E1A-47B7-91F8-627EAD7EC319}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/tests/MonoGame.Aseprite.Tests.sln b/tests/MonoGame.Aseprite.Tests.sln deleted file mode 100644 index ebd3630a..00000000 --- a/tests/MonoGame.Aseprite.Tests.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Aseprite.Tests", "MonoGame.Aseprite.Tests\MonoGame.Aseprite.Tests.csproj", "{CA70FF5A-3331-4C7D-90C5-491D35F33825}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoGame.Aseprite", "..\source\MonoGame.Aseprite\MonoGame.Aseprite.csproj", "{943BBD8C-B128-4C0C-B028-177805E4C277}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CA70FF5A-3331-4C7D-90C5-491D35F33825}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA70FF5A-3331-4C7D-90C5-491D35F33825}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA70FF5A-3331-4C7D-90C5-491D35F33825}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA70FF5A-3331-4C7D-90C5-491D35F33825}.Release|Any CPU.Build.0 = Release|Any CPU - {943BBD8C-B128-4C0C-B028-177805E4C277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {943BBD8C-B128-4C0C-B028-177805E4C277}.Debug|Any CPU.Build.0 = Debug|Any CPU - {943BBD8C-B128-4C0C-B028-177805E4C277}.Release|Any CPU.ActiveCfg = Release|Any CPU - {943BBD8C-B128-4C0C-B028-177805E4C277}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/tests/MonoGame.Aseprite.Tests/AsepriteTypeTests/AsepriteFileTests.cs b/tests/MonoGame.Aseprite.Tests/AsepriteTypeTests/AsepriteFileTests.cs deleted file mode 100644 index 6679c650..00000000 --- a/tests/MonoGame.Aseprite.Tests/AsepriteTypeTests/AsepriteFileTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; - -namespace MonoGame.Aseprite.Tests; - -public sealed class AsepriteFileTests -{ - // https://github.com/AristurtleDev/monogame-aseprite/issues/93 - [Fact] - public void TryGetSlice_True_When_Slice_Exists() - { - Color[] palette = Array.Empty(); - AsepriteFrame[] frames = Array.Empty(); - AsepriteLayer[] layers = Array.Empty(); - AsepriteTag[] tags = Array.Empty(); - AsepriteTileset[] tilesets = Array.Empty(); - AsepriteUserData userData = new AsepriteUserData(); - - string expectedSliceName = "TestSlice"; - - AsepriteSlice[] slices = new AsepriteSlice[] - { - new AsepriteSlice(expectedSliceName, false, false, Array.Empty()) - }; - - AsepriteFile aseFile = new AsepriteFile("Test", 1, 1, palette, frames, layers, tags, slices, tilesets, userData); - - Assert.True(aseFile.TryGetSlice(expectedSliceName, out AsepriteSlice? slice)); - } - - [Fact] - public void Get_Frame_When_ZeroIndexed_False() - { - Color[] palette = Array.Empty(); - AsepriteFrame frame = new AsepriteFrame("Frame0", 1, 1, 1, Array.Empty()); - AsepriteFrame[] frames = new AsepriteFrame[] - { - new AsepriteFrame("Frame0", 1, 1, 1, Array.Empty()), - new AsepriteFrame("Frame1", 1, 1, 1, Array.Empty()) - }; - - AsepriteLayer[] layers = Array.Empty(); - AsepriteTag[] tags = Array.Empty(); - AsepriteTileset[] tilesets = Array.Empty(); - AsepriteUserData userData = new AsepriteUserData(); - - AsepriteSlice[] slices = Array.Empty(); - AsepriteFile aseFile = new AsepriteFile("Test", 1, 1, palette, frames, layers, tags, slices, tilesets, userData); - - aseFile.ZeroIndexedFrames = false; - - AsepriteFrame expected = frames[0]; - AsepriteFrame actual = aseFile.GetFrame(1); - Assert.Equal(expected, actual); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/AsepriteTypeTests/AsepriteFrameTests.cs b/tests/MonoGame.Aseprite.Tests/AsepriteTypeTests/AsepriteFrameTests.cs deleted file mode 100644 index 077d4888..00000000 --- a/tests/MonoGame.Aseprite.Tests/AsepriteTypeTests/AsepriteFrameTests.cs +++ /dev/null @@ -1,165 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; - -namespace MonoGame.Aseprite.Tests; - -public sealed class AsepriteFrameTestsFixture -{ - public string Name { get; } - public AsepriteFrame Frame { get; } - - public AsepriteFrameTestsFixture() - { - Name = "aseprite-frame-test"; - - AsepriteTileset[] tilesets = new AsepriteTileset[] - { - new(0, 4, 1, 1, "tileset", new Color[] {Color.Transparent, Color.Yellow, Color.Purple, Color.Teal}) - }; - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new(AsepriteLayerFlags.Visible | AsepriteLayerFlags.Background, AsepriteBlendMode.Normal, 255, "background"), - new(AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "visible"), - new AsepriteTilemapLayer(tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "tilemap"), - new(AsepriteLayerFlags.None, AsepriteBlendMode.Normal, 255, "hidden") - }; - - AsepriteTile[] tiles = new AsepriteTile[] - { - new AsepriteTile(1, false, false, false), - new AsepriteTile(2, false, false, false), - new AsepriteTile(3, false, false, false), - new AsepriteTile(0, false, false, false) - }; - - AsepriteCel[] cels = new AsepriteCel[] - { - new AsepriteImageCel(2, 2, new Color[]{Color.Black, Color.Black, Color.Black, Color.Black}, layers[0], Point.Zero, 255), - new AsepriteImageCel(2, 2, new Color[]{Color.Red, Color.Transparent, Color.Transparent, Color.Red}, layers[1], Point.Zero, 255), - new AsepriteTilemapCel(2, 2, tiles, layers[2], Point.Zero, 255), - new AsepriteImageCel(2, 1, new Color[] {Color.White, Color.White}, layers[3], new Point(0, 1), 255) - }; - - Frame = new($"{Name} 0", 2, 2, 100, cels); - } -} - -public sealed class AsepriteFrameTests : IClassFixture -{ - private readonly AsepriteFrameTestsFixture _fixture; - - public AsepriteFrameTests(AsepriteFrameTestsFixture fixture) => _fixture = fixture; - - [Fact] - public void Flatten_OnlyVisible_True_IncludeBackground_True_IncludeTilemap_True() - { - Color[] expected = new Color[] { Color.Yellow, Color.Purple, Color.Teal, Color.Red }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: true, - includeBackgroundLayer: true, - includeTilemapCel: true); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Flatten_OnlyVisible_True_IncludeBackground_True_IncludeTilemap_False() - { - Color[] expected = new Color[] { Color.Red, Color.Black, Color.Black, Color.Red }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: true, - includeBackgroundLayer: true, - includeTilemapCel: false); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Flatten_OnlyVisible_True_IncludeBackground_False_IncludeTilemap_True() - { - Color[] expected = new Color[] { Color.Yellow, Color.Purple, Color.Teal, Color.Red }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: true, - includeBackgroundLayer: false, - includeTilemapCel: true); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Flatten_OnlyVisible_True_IncludeBackground_False_IncludeTilemap_False() - { - Color[] expected = new Color[] { Color.Red, Color.Transparent, Color.Transparent, Color.Red }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: true, - includeBackgroundLayer: false, - includeTilemapCel: false); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Flatten_OnlyVisible_False_IncludeBackground_True_IncludeTilemap_True() - { - Color[] expected = new Color[] { Color.Yellow, Color.Purple, Color.White, Color.White }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: false, - includeBackgroundLayer: true, - includeTilemapCel: true); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Flatten_OnlyVisible_False_IncludeBackground_True_IncludeTilemap_False() - { - Color[] expected = new Color[] { Color.Red, Color.Black, Color.White, Color.White }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: false, - includeBackgroundLayer: true, - includeTilemapCel: false); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Flatten_OnlyVisible_False_IncludeBackground_False_IncludeTilemap_True() - { - Color[] expected = new Color[] { Color.Yellow, Color.Purple, Color.White, Color.White }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: false, - includeBackgroundLayer: false, - includeTilemapCel: true); - - Assert.Equal(expected, actual); - } - - [Fact] - public void Flatten_OnlyVisible_False_IncludeBackground_False_IncludeTilemap_False() - { - Color[] expected = new Color[] { Color.Red, Color.Transparent, Color.White, Color.White }; - Color[] actual = _fixture.Frame.FlattenFrame(onlyVisibleLayers: false, - includeBackgroundLayer: false, - includeTilemapCel: false); - - Assert.Equal(expected, actual); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/ContentTests/AnimatedTilemapProcessorTests.cs b/tests/MonoGame.Aseprite.Tests/ContentTests/AnimatedTilemapProcessorTests.cs deleted file mode 100644 index 3f9f397a..00000000 --- a/tests/MonoGame.Aseprite.Tests/ContentTests/AnimatedTilemapProcessorTests.cs +++ /dev/null @@ -1,265 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; - -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tests; - - -public sealed class AnimatedTilemapProcessorTestFixture -{ - public AsepriteFile AsepriteFile { get; } - - public AnimatedTilemapProcessorTestFixture() - { - string fileName = "raw-animated-tilemap-processor-tests"; - - Color[] palette = Array.Empty(); - AsepriteTag[] tags = Array.Empty(); - AsepriteSlice[] slices = Array.Empty(); - AsepriteUserData userData = new(); - - AsepriteTileset[] tilesets = new AsepriteTileset[] - { - new(0, 4, 1, 1, "tileset-0", new Color[] {Color.Transparent, Color.Red, Color.Green, Color.Blue}), - new(1, 4, 1, 1, "tileset-1", new Color[] {Color.Transparent, Color.White, Color.Gray, Color.Black}), - }; - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new AsepriteTilemapLayer(tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "visible"), - new AsepriteTilemapLayer(tilesets[1], AsepriteLayerFlags.None, AsepriteBlendMode.Normal, 255, "hidden") - }; - - AsepriteTile[] frame0Cel0Tiles = new AsepriteTile[] - { - new AsepriteTile(0, false, false, false), - new AsepriteTile(1, false, false, false), - new AsepriteTile(2, false, false, false), - new AsepriteTile(3, false, false, false) - }; - - AsepriteTile[] frame0Cel1Tiles = new AsepriteTile[] - { - new AsepriteTile(2, false, false, false), - new AsepriteTile(3, false, false, false) - }; - - AsepriteCel[] frame0Cels = new AsepriteCel[] - { - new AsepriteTilemapCel(2, 2, frame0Cel0Tiles, layers[0], Point.Zero, 255), - new AsepriteTilemapCel(2, 1, frame0Cel1Tiles, layers[1], new Point(0, 1), 255) - }; - - AsepriteTile[] frame1Cel0Tiles = new AsepriteTile[] - { - new AsepriteTile(3, false, false, false), - new AsepriteTile(2, false, false, false), - new AsepriteTile(1, false, false, false), - new AsepriteTile(0, false, false, false) - }; - - AsepriteTile[] frame1Cel1Tiles = new AsepriteTile[] - { - new AsepriteTile(3, false, false, false), - new AsepriteTile(2, false, false, false) - }; - - AsepriteCel[] frame1Cels = new AsepriteCel[] - { - new AsepriteTilemapCel(2, 2, frame1Cel0Tiles, layers[0], Point.Zero, 255), - new AsepriteTilemapCel(2, 1, frame1Cel1Tiles, layers[1], new Point(0, 1), 255) - }; - - AsepriteFrame[] frames = new AsepriteFrame[] - { - new($"{fileName} 0", 2, 2, 100, frame0Cels), - new($"{fileName} 1", 2, 2, 200, frame1Cels) - }; - - AsepriteFile = new(fileName, 0, 0, palette, frames, layers, tags, slices, tilesets, userData); - } -} - -public sealed class AnimatedTilemapProcessorTests : IClassFixture -{ - private readonly AnimatedTilemapProcessorTestFixture _fixture; - - public AnimatedTilemapProcessorTests(AnimatedTilemapProcessorTestFixture fixture) => _fixture = fixture; - - [Fact] - public void ProcessRaw_OnlyVisibleLayers_True_Processes_Only_Visible_Layers() - { - RawAnimatedTilemap tilemap = AnimatedTilemapProcessor.ProcessRaw(_fixture.AsepriteFile, onlyVisibleLayers: true); - - // Expect the name of the aseprite file to be the name of the tilemap. - Assert.Equal(_fixture.AsepriteFile.Name, tilemap.Name); - - // File has 2 layers, but one is hidden, so expect only 1 layer. - Assert.Equal(1, tilemap.RawTilesets.Length); - - // Each layer uses a different tileset, but again, one is hidden, so expect only one tileset. - Assert.Equal(1, tilemap.RawTilesets.Length); - - // Expect that the tileset was processed correctly - RawTileset tileset = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, 0); - Assert.Equal(tileset, tilemap.RawTilesets[0]); - - // The file has 2 frames, so expect 2 frames - Assert.Equal(2, tilemap.RawTilemapFrames.Length); - - // Expect that the duration of the tilemap frames was taken from the frames in the file - Assert.Equal(_fixture.AsepriteFile.Frames[0].DurationInMilliseconds, tilemap.RawTilemapFrames[0].DurationInMilliseconds); - Assert.Equal(_fixture.AsepriteFile.Frames[1].DurationInMilliseconds, tilemap.RawTilemapFrames[1].DurationInMilliseconds); - - // Again, one of the layers is hidden, so expect only one layer processed for each frame. - Assert.Equal(1, tilemap.RawTilemapFrames[0].RawTilemapLayers.Length); - Assert.Equal(1, tilemap.RawTilemapFrames[1].RawTilemapLayers.Length); - - // Getting reference to the aseprite layers and cels used to construct the raw tilemap layers - AsepriteTilemapLayer aseLayer0 = (AsepriteTilemapLayer)_fixture.AsepriteFile.Layers[0]; - AsepriteTilemapCel aseFrame0Cel = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[0].Cels[0]; - AsepriteTilemapCel aseFrame1Cel = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[1].Cels[0]; - - // Expect that the single layer of each frame was constructed properly from the aseprite layer and cel data. - AssertRawLayer(tilemap.RawTilemapFrames[0].RawTilemapLayers[0], aseLayer0, aseFrame0Cel); - AssertRawLayer(tilemap.RawTilemapFrames[1].RawTilemapLayers[0], aseLayer0, aseFrame1Cel); - } - - [Fact] - public void ProcessRaw_OnlyVisibleLayers_False_Processes_All_Layers() - { - RawAnimatedTilemap tilemap = AnimatedTilemapProcessor.ProcessRaw(_fixture.AsepriteFile, onlyVisibleLayers: false); - - // Expect the name of the aseprite file to be the name of the tilemap. - Assert.Equal(_fixture.AsepriteFile.Name, tilemap.Name); - - // Since all layers were processed, and there are 2 layers, each with a different tileset, expect 2 tilesets - Assert.Equal(2, tilemap.RawTilesets.Length); - - // Each layer uses a different tileset, and since both were processed, expect two tilesets. - Assert.Equal(2, tilemap.RawTilesets.Length); - - // Expect that both of the tilesets were processed correctly - RawTileset tileset0 = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, 0); - RawTileset tileset1 = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, 1); - Assert.Equal(tileset0, tilemap.RawTilesets[0]); - Assert.Equal(tileset1, tilemap.RawTilesets[1]); - - // The file has 2 frames, so expect 2 frames - Assert.Equal(2, tilemap.RawTilemapFrames.Length); - - // Expect that the duration of the tilemap frames was taken from the frames in the file - Assert.Equal(_fixture.AsepriteFile.Frames[0].DurationInMilliseconds, tilemap.RawTilemapFrames[0].DurationInMilliseconds); - Assert.Equal(_fixture.AsepriteFile.Frames[1].DurationInMilliseconds, tilemap.RawTilemapFrames[1].DurationInMilliseconds); - - // Since all layers were processed, and there are 2 layers, expect that each frame has 2 layers. - Assert.Equal(2, tilemap.RawTilemapFrames[0].RawTilemapLayers.Length); - Assert.Equal(2, tilemap.RawTilemapFrames[1].RawTilemapLayers.Length); - - // Getting reference to the aseprite layers and cels used to construct the raw tilemap layers - AsepriteTilemapLayer aseLayer0 = (AsepriteTilemapLayer)_fixture.AsepriteFile.Layers[0]; - AsepriteTilemapLayer aseLayer1 = (AsepriteTilemapLayer)_fixture.AsepriteFile.Layers[1]; - AsepriteTilemapCel aseFrame0Cel0 = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[0].Cels[0]; - AsepriteTilemapCel aseFrame0Cel1 = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[0].Cels[1]; - AsepriteTilemapCel aseFrame1Cel0 = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[1].Cels[0]; - AsepriteTilemapCel aseFrame1Cel1 = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[1].Cels[1]; - - // Expect that the the layers on each frame were constructed properly from the aseprite layer and cel data - AssertRawLayer(tilemap.RawTilemapFrames[0].RawTilemapLayers[0], aseLayer0, aseFrame0Cel0); - AssertRawLayer(tilemap.RawTilemapFrames[0].RawTilemapLayers[1], aseLayer1, aseFrame0Cel1); - AssertRawLayer(tilemap.RawTilemapFrames[1].RawTilemapLayers[0], aseLayer0, aseFrame1Cel0); - AssertRawLayer(tilemap.RawTilemapFrames[1].RawTilemapLayers[1], aseLayer1, aseFrame1Cel1); - } - - [Fact] - public void ProcessRaw_Duplicate_AsepriteLayer_Names_Throws_Exception() - { - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new AsepriteTilemapLayer(_fixture.AsepriteFile.Tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer-0"), - new AsepriteTilemapLayer(_fixture.AsepriteFile.Tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer-1"), - new AsepriteTilemapLayer(_fixture.AsepriteFile.Tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer-0") - }; - - AsepriteTile[] tiles = new AsepriteTile[] - { - new AsepriteTile(0, false, false, false), - new AsepriteTile(1, false, false, false), - new AsepriteTile(2, false, false, false), - new AsepriteTile(3, false, false, false) - }; - - AsepriteCel[] cels = new AsepriteCel[] - { - new AsepriteTilemapCel(2, 2, tiles, layers[0], Point.Zero, 255), - new AsepriteTilemapCel(2, 2, tiles, layers[1], Point.Zero, 255), - new AsepriteTilemapCel(2, 2, tiles, layers[2], Point.Zero, 255) - }; - - AsepriteFrame[] frames = new AsepriteFrame[] - { - new($"{_fixture.AsepriteFile.Name} 0", 2, 2, 100, cels) - }; - - // Reuse the fixture, but use the layers array from above with duplicate layer names - AsepriteFile aseFile = new(_fixture.AsepriteFile.Name, - _fixture.AsepriteFile.CanvasWidth, - _fixture.AsepriteFile.CanvasHeight, - _fixture.AsepriteFile.Palette.ToArray(), - frames, - layers, - _fixture.AsepriteFile.Tags.ToArray(), - _fixture.AsepriteFile.Slices.ToArray(), - _fixture.AsepriteFile.Tilesets.ToArray(), - _fixture.AsepriteFile.UserData); - - Assert.Throws(() => AnimatedTilemapProcessor.ProcessRaw(aseFile)); - } - - private void AssertRawLayer(RawTilemapLayer tilemapLayer, AsepriteTilemapLayer aseLayer, AsepriteTilemapCel aseCel) - { - Assert.Equal(aseLayer.Name, tilemapLayer.Name); - Assert.Equal(aseLayer.Tileset.ID, tilemapLayer.TilesetID); - Assert.Equal(aseCel.Columns, tilemapLayer.Columns); - Assert.Equal(aseCel.Rows, tilemapLayer.Rows); - Assert.Equal(aseCel.Position, tilemapLayer.Offset); - - for (int i = 0; i < aseCel.Tiles.Length; i++) - { - AsepriteTile aseTile = aseCel.Tiles[i]; - RawTilemapTile tilemapTile = tilemapLayer.RawTilemapTiles[i]; - - Assert.Equal(aseTile.TilesetTileID, tilemapTile.TilesetTileID); - Assert.Equal(aseTile.XFlip, tilemapTile.FlipHorizontally); - Assert.Equal(aseTile.YFlip, tilemapTile.FlipVertically); - Assert.Equal(aseTile.DFlip, tilemapTile.FlipDiagonally); - } - } -} diff --git a/tests/MonoGame.Aseprite.Tests/ContentTests/RawTypeWriteReadTests.cs b/tests/MonoGame.Aseprite.Tests/ContentTests/RawTypeWriteReadTests.cs deleted file mode 100644 index 62a37c60..00000000 --- a/tests/MonoGame.Aseprite.Tests/ContentTests/RawTypeWriteReadTests.cs +++ /dev/null @@ -1,250 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using System.Text; -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.Content.Readers; -using MonoGame.Aseprite.Content.Writers; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tests; - -public sealed class RawTypeWriteReadTests -{ - [Fact] - public void Write_Then_Read_RawSprite() - { - RawTexture texture = new(nameof(RawTexture), new Color[] { Color.Transparent, Color.Red, Color.Green, Color.Blue }, 2, 2); - - RawSlice[] slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(0, 0, 0, 0), new(0, 0), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(1, 1, 1, 1), new(2, 2, 2, 2), new(3, 3), Color.Green) - }; - - RawSprite sprite = new(nameof(RawSprite), texture, slices); - - Write((writer) => RawSpriteWriter.Write(writer, sprite), out MemoryStream stream); - Read(stream, (reader) => RawSpriteReader.Read(reader), out RawSprite actual); - - Assert.Equal(sprite, actual); - } - - [Fact] - public void Write_Then_Read_RawSpriteSheet() - { - RawTexture texture = new(nameof(RawTexture), new Color[] { Color.Transparent, Color.Red, Color.Green, Color.Blue }, 2, 2); - - RawSlice[] region0Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(0, 0, 0, 0), new(0, 0), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(0, 0, 0, 0), new(0, 0, 0, 0), new(0, 0), Color.Green) - }; - - RawSlice[] region1Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(1, 1, 1, 1), new(1, 1), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(1, 1, 1, 1), new(1, 1, 1, 1), new(1, 1), Color.Green) - }; - - RawSlice[] region2Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(2, 2, 2, 2), new(2, 2), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(2, 2, 2, 2), new(2, 2, 2, 2), new(2, 2), Color.Green) - }; - - RawSlice[] region3Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(3, 3, 3, 3), new(3, 3), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(3, 3, 3, 3), new(3, 3, 3, 3), new(3, 3), Color.Green) - }; - - RawTextureRegion[] regions = new RawTextureRegion[] - { - new(nameof(RawTextureRegion), new Rectangle(0, 0, 0, 0), region0Slices), - new(nameof(RawTextureRegion), new Rectangle(1, 1, 1, 1), region1Slices), - new(nameof(RawTextureRegion), new Rectangle(2, 2, 2, 2), region2Slices), - new(nameof(RawTextureRegion), new Rectangle(3, 3, 3, 3), region3Slices) - }; - RawTextureAtlas atlas = new(nameof(RawTextureAtlas), texture, regions); - RawAnimationFrame[] frames = new RawAnimationFrame[] - { - new(0, 0), - new(1, 100), - new(2, 200), - new(3, 300) - }; - RawAnimationTag[] tags = new RawAnimationTag[] - { - new(nameof(RawAnimationTag), frames, 0, true, true), - new(nameof(RawAnimationTag), frames, 1, false, false), - new(nameof(RawAnimationTag), frames, 0, false, true), - new(nameof(RawAnimationTag), frames, 1, true, false), - }; - RawSpriteSheet sheet = new(nameof(RawSpriteSheet), atlas, tags); - - Write(writer => RawSpriteSheetWriter.Write(writer, sheet), out MemoryStream stream); - Read(stream, (reader) => RawSpriteSheetReader.Read(reader), out RawSpriteSheet actual); - - Assert.Equal(sheet, actual); - } - - [Fact] - public void Write_Then_Read_RawTextureAtlas() - { - RawTexture texture = new(nameof(RawTexture), new Color[] { Color.Transparent, Color.Red, Color.Green, Color.Blue }, 2, 2); - - RawSlice[] region0Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(0, 0, 0, 0), new(0, 0), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(0, 0, 0, 0), new(0, 0, 0, 0), new(0, 0), Color.Green) - }; - - RawSlice[] region1Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(1, 1, 1, 1), new(1, 1), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(1, 1, 1, 1), new(1, 1, 1, 1), new(1, 1), Color.Green) - }; - - RawSlice[] region2Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(2, 2, 2, 2), new(2, 2), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(2, 2, 2, 2), new(2, 2, 2, 2), new(2, 2), Color.Green) - }; - - RawSlice[] region3Slices = new RawSlice[] - { - new RawSlice(nameof(RawSlice), new(3, 3, 3, 3), new(3, 3), Color.Red), - new RawNinePatchSlice(nameof(RawNinePatchSlice), new(3, 3, 3, 3), new(3, 3, 3, 3), new(3, 3), Color.Green) - }; - - RawTextureRegion[] regions = new RawTextureRegion[] - { - new(nameof(RawTextureRegion), new Rectangle(0, 0, 0, 0), region0Slices), - new(nameof(RawTextureRegion), new Rectangle(1, 1, 1, 1), region1Slices), - new(nameof(RawTextureRegion), new Rectangle(2, 2, 2, 2), region2Slices), - new(nameof(RawTextureRegion), new Rectangle(3, 3, 3, 3), region3Slices) - }; - RawTextureAtlas atlas = new(nameof(RawTextureAtlas), texture, regions); - - Write((writer) => RawTextureAtlasWriter.Write(writer, atlas), out MemoryStream stream); - Read(stream, (reader) => RawTextureAtlasReader.Read(reader), out RawTextureAtlas actual); - - Assert.Equal(atlas, actual); - } - - [Fact] - public void Write_Then_Read_RawTileset() - { - RawTexture texture = new(nameof(RawTexture), new Color[] { Color.Transparent, Color.Red, Color.Green, Color.Blue }, 2, 2); - RawTileset tileset = new(0, nameof(RawTileset), texture, 1, 1); - - Write((writer) => RawTilesetWriter.Write(writer, tileset), out MemoryStream stream); - Read(stream, (reader) => RawTilesetReader.Read(reader), out RawTileset actual); - - Assert.Equal(tileset, actual); - } - - [Fact] - public void Write_Then_Read_RawTilemap() - { - RawTexture texture = new(nameof(RawTexture), new Color[] { Color.Transparent, Color.Red, Color.Green, Color.Blue }, 2, 2); - - RawTileset[] tilesets = new RawTileset[] - { - new(0, nameof(RawTileset), texture, 1, 1) - }; - - RawTilemapTile[] tiles = new RawTilemapTile[] - { - new RawTilemapTile(0, true, true, false), - new RawTilemapTile(1, true, false, true), - new RawTilemapTile(2, false, true, false), - new RawTilemapTile(3, false, false, true) - }; - - RawTilemapLayer[] layers = new RawTilemapLayer[] - { - new(nameof(RawTilemapLayer), 0, 1, 2, tiles, new(1, 2)) - }; - - RawTilemap tilemap = new(nameof(RawTilemap), layers, tilesets); - - Write((writer) => RawTilemapWriter.Write(writer, tilemap), out MemoryStream stream); - Read(stream, (reader) => RawTilemapReader.Read(reader), out RawTilemap actual); - - Assert.Equal(tilemap, actual); - } - - [Fact] - public void Write_Then_Read_RawAnimatedTilemap() - { - RawTexture texture = new(nameof(RawTexture), new Color[] { Color.Transparent, Color.Red, Color.Green, Color.Blue }, 2, 2); - - RawTileset[] tilesets = new RawTileset[] - { - new(0, nameof(RawTileset), texture, 1, 1) - }; - - RawTilemapTile[] tiles = new RawTilemapTile[] - { - new RawTilemapTile(0, true, true, false), - new RawTilemapTile(1, true, false, true), - new RawTilemapTile(2, false, true, false), - new RawTilemapTile(3, false, false, true) - }; - - RawTilemapLayer[] layers = new RawTilemapLayer[] - { - new(nameof(RawTilemapLayer), 0, 1, 2, tiles, new(1, 2)) - }; - - RawTilemapFrame[] frames = new RawTilemapFrame[] - { - new(100, layers) - }; - - RawAnimatedTilemap tilemap = new(nameof(RawAnimatedTilemap), tilesets, frames); - - Write((writer) => RawAnimatedTilemapWriter.Write(writer, tilemap), out MemoryStream stream); - Read(stream, (reader) => RawAnimatedTilemapReader.Read(reader), out RawAnimatedTilemap actual); - - Assert.Equal(tilemap, actual); - } - private void Write(Action writeAction, out MemoryStream stream) - { - stream = new(); - using BinaryWriter writer = new(stream, Encoding.UTF8, leaveOpen: true); - writeAction(writer); - } - - private void Read(MemoryStream stream, Func readFunc, out T result) - { - stream.Position = 0; - using (BinaryReader reader = new(stream, Encoding.UTF8, leaveOpen: false)) - { - result = readFunc(reader); - } - } -} \ No newline at end of file diff --git a/tests/MonoGame.Aseprite.Tests/ContentTests/SpriteProcessorTests.cs b/tests/MonoGame.Aseprite.Tests/ContentTests/SpriteProcessorTests.cs deleted file mode 100644 index 2ac1ab98..00000000 --- a/tests/MonoGame.Aseprite.Tests/ContentTests/SpriteProcessorTests.cs +++ /dev/null @@ -1,117 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tests; - -public sealed class SpriteProcessorTestsFixture -{ - public string Name { get; } = "raw-sprite-processor-test"; - public AsepriteFile AsepriteFile { get; } - - public SpriteProcessorTestsFixture() - { - Color[] palette = new Color[] { Color.Black, Color.White }; - - AsepriteTileset[] tilesets = Array.Empty(); - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new(AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer") - }; - - AsepriteCel[] frame0Cels = new AsepriteCel[] - { - new AsepriteImageCel(2, 2, new Color[] {Color.Black, Color.Black, Color.Black, Color.Black}, layers[0], Point.Zero, 255) - }; - - AsepriteCel[] frame1Cels = new AsepriteCel[] - { - new AsepriteImageCel(2, 2, new Color[] {Color.White, Color.White, Color.White, Color.White}, layers[0], Point.Zero, 255) - }; - - AsepriteFrame[] frames = new AsepriteFrame[] - { - new($"{Name} 0", 2, 2, 100, frame0Cels), - new($"{Name} 1", 2, 2, 100, frame1Cels) - }; - - AsepriteTag[] tags = Array.Empty(); - AsepriteSlice[] slices = Array.Empty(); - - - AsepriteUserData userData = new(); - AsepriteFile = new(Name, 2, 2, palette, frames, layers, tags, slices, tilesets, userData); - } -} - -public sealed class SpriteProcessorTests : IClassFixture -{ - private readonly SpriteProcessorTestsFixture _fixture; - - - public SpriteProcessorTests(SpriteProcessorTestsFixture fixture) => _fixture = fixture; - - [Theory] - [InlineData(0)] - [InlineData(1)] - public void ProcessRaw_Sprite_And_Texture_Name_Include_Correct_Index(int frame) - { - RawSprite sprite = SpriteProcessor.ProcessRaw(_fixture.AsepriteFile, frame); - - string name = $"{_fixture.Name} {frame}"; - - Assert.Equal(name, sprite.Name); - Assert.Equal(name, sprite.RawTexture.Name); - } - - [Theory] - [InlineData(-1)] - [InlineData(2)] - public void ProcessRaw_Throws_Exception_When_Frame_Index_Out_Of_Range(int frame) - { - Exception ex = Record.Exception(() => SpriteProcessor.ProcessRaw(_fixture.AsepriteFile, frame)); - Assert.IsType(ex); - } - - [Fact] - public void ProcessRaw_Processes_Given_Frame() - { - RawSprite frame0Sprite = SpriteProcessor.ProcessRaw(_fixture.AsepriteFile, 0); - RawSprite frame1Sprite = SpriteProcessor.ProcessRaw(_fixture.AsepriteFile, 1); - - Color[] frame0Expected= new Color[] { Color.Black, Color.Black, Color.Black, Color.Black }; - Color[] frame1Expected = new Color[] { Color.White, Color.White, Color.White, Color.White }; - - Color[] frame0Actual = frame0Sprite.RawTexture.Pixels.ToArray(); - Color[] frame1Actual = frame1Sprite.RawTexture.Pixels.ToArray(); - - Assert.Equal(frame0Expected, frame0Actual); - Assert.Equal(frame1Expected, frame1Actual); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/ContentTests/SpriteSheetProcessorTests.cs b/tests/MonoGame.Aseprite.Tests/ContentTests/SpriteSheetProcessorTests.cs deleted file mode 100644 index 5e092e53..00000000 --- a/tests/MonoGame.Aseprite.Tests/ContentTests/SpriteSheetProcessorTests.cs +++ /dev/null @@ -1,158 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tests; - - -public sealed class SpriteSheetProcessorTestFixture -{ - public string Name { get; } = "raw-sprite-processor-test"; - public AsepriteFile AsepriteFile { get; } - - public SpriteSheetProcessorTestFixture() - { - int width = 2; - int height = 2; - - Color[] palette = new Color[] { Color.Red, Color.Green, Color.Blue, Color.Yellow }; - AsepriteTileset[] tilesets = Array.Empty(); - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new(AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer") - }; - - AsepriteCel[] frame0Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[]{Color.Red, Color.Red, Color.Red, Color.Red}, layers[0], Point.Zero, 255) - }; - - AsepriteCel[] frame1Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[] {Color.Green, Color.Green, Color.Green, Color.Green}, layers[0], Point.Zero, 255) - }; - - AsepriteCel[] frame2Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[] {Color.Blue, Color.Blue, Color.Blue, Color.Blue}, layers[0], Point.Zero, 255) - }; - - AsepriteCel[] frame3Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[] {Color.Red, Color.Red, Color.Red, Color.Red}, layers[0], Point.Zero, 255) - }; - - AsepriteFrame[] frames = new AsepriteFrame[] - { - new($"{Name} 0", width, height, 100, frame0Cels), - new($"{Name} 1", width, height, 100, frame1Cels), - new($"{Name} 2", width, height, 100, frame2Cels), - new($"{Name} 3", width, height, 100, frame3Cels), - }; - - AsepriteTag[] tags = new AsepriteTag[] - { - new(0, 0, AsepriteLoopDirection.Forward, 0, Color.Red, "tag-0"), - new(0, 1, AsepriteLoopDirection.Forward, 0, Color.Green, "tag-1"), - new(1, 2, AsepriteLoopDirection.PingPong, 0, Color.Blue, "tag-2") - }; - - AsepriteSlice[] slices = Array.Empty(); - AsepriteUserData userData = new(); - AsepriteFile = new(Name, width, height, palette, frames, layers, tags, slices, tilesets, userData); - } -} - -public sealed class SpriteSheetProcessorTests : IClassFixture -{ - private readonly SpriteSheetProcessorTestFixture _fixture; - - public SpriteSheetProcessorTests(SpriteSheetProcessorTestFixture fixture) => _fixture = fixture; - - [Theory] - [InlineData(true, true, true, true, 1, 1, 1)] - [InlineData(true, false, true, true, 1, 0, 1)] - [InlineData(true, true, false, true, 1, 1, 0)] - [InlineData(true, true, true, false, 0, 1, 1)] - [InlineData(false, true, true, true, 0, 1, 0)] - [InlineData(false, false, true, true, 0, 0, 1)] - [InlineData(false, true, false, true, 0, 0, 0)] - [InlineData(false, true, true, false, 0, 0, 0)] - [InlineData(false, false, false, true, 0, 0, 0)] - [InlineData(false, false, true, false, 0, 0, 0)] - [InlineData(false, false, false, false, 0, 0, 0)] - public void ProcessRaw_asses_Parameters_To_TextureAtlasProcess_Correctly(bool onlyVisible, bool includeBackground, bool includeTilemap, bool mergeDuplicates, int borderPadding, int spacing, int innerPadding) - { - RawSpriteSheet sheet = SpriteSheetProcessor.ProcessRaw(_fixture.AsepriteFile, onlyVisible, includeBackground, includeTilemap, mergeDuplicates, borderPadding, spacing, innerPadding); - RawTextureAtlas expected = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile, onlyVisible, includeBackground, includeTilemap, mergeDuplicates, borderPadding, spacing, innerPadding); - - Assert.Equal(expected, sheet.RawTextureAtlas); - } - - [Fact] - public void ProcessRaw_SpriteSheet_Atlas_and_Texture_Names_Same_As_File_Name() - { - RawSpriteSheet sheet = SpriteSheetProcessor.ProcessRaw(_fixture.AsepriteFile); - Assert.Equal(_fixture.Name, sheet.Name); - Assert.Equal(_fixture.Name, sheet.RawTextureAtlas.Name); - Assert.Equal(_fixture.Name, sheet.RawTextureAtlas.RawTexture.Name); - } - - [Fact] - public void ProcessRaw_Processes_All_Tags() - { - RawSpriteSheet sheet = SpriteSheetProcessor.ProcessRaw(_fixture.AsepriteFile); - Assert.Equal(_fixture.AsepriteFile.Tags.Length, sheet.RawAnimationTags.Length); - } - - [Fact] - public void ProcessRaw_Duplicate_AsepriteTag_Names_Throws_Exception() - { - AsepriteTag[] tags = new AsepriteTag[] - { - new(0, 0, AsepriteLoopDirection.Forward, 0, Color.Red, "tag-0"), - new(0, 1, AsepriteLoopDirection.Forward, 0, Color.Green, "tag-1"), - new(1, 2, AsepriteLoopDirection.PingPong, 0, Color.Blue, "tag-0") - }; - - // Reuse the fixture, but use the tags array from above with duplicate tag names - AsepriteFile aseFile = new(_fixture.Name, - _fixture.AsepriteFile.CanvasWidth, - _fixture.AsepriteFile.CanvasHeight, - _fixture.AsepriteFile.Palette.ToArray(), - _fixture.AsepriteFile.Frames.ToArray(), - _fixture.AsepriteFile.Layers.ToArray(), - tags, - _fixture.AsepriteFile.Slices.ToArray(), - _fixture.AsepriteFile.Tilesets.ToArray(), - _fixture.AsepriteFile.UserData); - - Assert.Throws(() => SpriteSheetProcessor.ProcessRaw(aseFile)); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/ContentTests/TextureAtlasProcessorTests.cs b/tests/MonoGame.Aseprite.Tests/ContentTests/TextureAtlasProcessorTests.cs deleted file mode 100644 index 8eb96cc6..00000000 --- a/tests/MonoGame.Aseprite.Tests/ContentTests/TextureAtlasProcessorTests.cs +++ /dev/null @@ -1,270 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tests; - -public sealed class TextureAtlasProcessorTestFixture -{ - public string Name { get; } = "raw-sprite-processor-test"; - public AsepriteFile AsepriteFile { get; } - - public TextureAtlasProcessorTestFixture() - { - int width = 2; - int height = 2; - - Color[] palette = new Color[] { Color.Red, Color.Green, Color.Blue, Color.Yellow }; - AsepriteTileset[] tilesets = Array.Empty(); - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new(AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer") - }; - - AsepriteCel[] frame0Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[]{Color.Red, Color.Red, Color.Red, Color.Red}, layers[0], Point.Zero, 255) - }; - - AsepriteCel[] frame1Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[] {Color.Green, Color.Green, Color.Green, Color.Green}, layers[0], Point.Zero, 255) - }; - - AsepriteCel[] frame2Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[] {Color.Blue, Color.Blue, Color.Blue, Color.Blue}, layers[0], Point.Zero, 255) - }; - - AsepriteCel[] frame3Cels = new AsepriteCel[] - { - new AsepriteImageCel(width, height, new Color[] {Color.Red, Color.Red, Color.Red, Color.Red}, layers[0], Point.Zero, 255) - }; - - AsepriteFrame[] frames = new AsepriteFrame[] - { - new($"{Name} 0", width, height, 100, frame0Cels), - new($"{Name} 1", width, height, 100, frame1Cels), - new($"{Name} 2", width, height, 100, frame2Cels), - new($"{Name} 3", width, height, 100, frame3Cels), - }; - - AsepriteTag[] tags = Array.Empty(); - AsepriteSlice[] slices = Array.Empty(); - AsepriteUserData userData = new(); - AsepriteFile = new(Name, width, height, palette, frames, layers, tags, slices, tilesets, userData); - } -} - -public sealed class TextureAtlasProcessorTests : IClassFixture -{ - private readonly TextureAtlasProcessorTestFixture _fixture; - - // These are the colors that will be expected in the raw texture created during each process. They are created - // here an named this way so that it's easier to visualize what the pixel array should be in the test below. - private readonly Color _ = Color.Transparent; // Represents a transparent pixel from padding/spacing, not source - private readonly Color r = Color.Red; // Represents a red pixel - private readonly Color g = Color.Green; // Represents a green pixel - private readonly Color b = Color.Blue; // Represents a blue pixel - private readonly Color t = Color.Transparent; // Represents a transparent pixel from source, not padding/spacing. - - public TextureAtlasProcessorTests(TextureAtlasProcessorTestFixture fixture) => _fixture = fixture; - - [Fact] - public void ProcessRaw_Atlas_And_Texture_Name_Same_As_File_Name() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile); - Assert.Equal(_fixture.Name, atlas.Name); - Assert.Equal(_fixture.Name, atlas.RawTexture.Name); - } - - [Fact] - public void ProcessRaw_One_Region_Per_Frame() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile); - Assert.Equal(_fixture.AsepriteFile.Frames.Length, atlas.RawTextureRegions.Length); - } - - [Fact] - public void ProcessRawRegion_Names_Are_Frame_Names() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile); - - Assert.Equal(_fixture.AsepriteFile.Frames[0].Name, atlas.RawTextureRegions[0].Name); - Assert.Equal(_fixture.AsepriteFile.Frames[1].Name, atlas.RawTextureRegions[1].Name); - Assert.Equal(_fixture.AsepriteFile.Frames[2].Name, atlas.RawTextureRegions[2].Name); - Assert.Equal(_fixture.AsepriteFile.Frames[3].Name, atlas.RawTextureRegions[3].Name); - } - - [Fact] - public void ProcessRaw_Duplicate_Frame_Is_Merged() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile, mergeDuplicates: true); - - Color[] expected = new Color[] - { - r, r, g, g, - r, r, g, g, - b, b, t, t, - b, b, t, t - }; - - Color[] actual = atlas.RawTexture.Pixels.ToArray(); - - Assert.Equal(expected, actual); - Assert.Equal(new Rectangle(0, 0, 2, 2), atlas.RawTextureRegions[0].Bounds); - Assert.Equal(new Rectangle(2, 0, 2, 2), atlas.RawTextureRegions[1].Bounds); - Assert.Equal(new Rectangle(0, 2, 2, 2), atlas.RawTextureRegions[2].Bounds); - Assert.Equal(new Rectangle(0, 0, 2, 2), atlas.RawTextureRegions[3].Bounds); - } - - [Fact] - public void ProcessRaw_Duplicate_Frame_Not_Merged() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile, mergeDuplicates: false); - - Color[] expected = new Color[] - { - r, r, g, g, - r, r, g, g, - b, b, r, r, - b, b, r, r, - }; - - Color[] actual = atlas.RawTexture.Pixels.ToArray(); - - Assert.Equal(expected, actual); - Assert.Equal(new Rectangle(0, 0, 2, 2), atlas.RawTextureRegions[0].Bounds); - Assert.Equal(new Rectangle(2, 0, 2, 2), atlas.RawTextureRegions[1].Bounds); - Assert.Equal(new Rectangle(0, 2, 2, 2), atlas.RawTextureRegions[2].Bounds); - Assert.Equal(new Rectangle(2, 2, 2, 2), atlas.RawTextureRegions[3].Bounds); - } - - [Fact] - public void ProcessRaw_Border_Padding_Added_Correctly() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile, borderPadding: 1); - - Color[] expected = new Color[] - { - _, _, _, _, _, _, - _, r, r, g, g, _, - _, r, r, g, g, _, - _, b, b, t, t, _, - _, b, b, t, t, _, - _, _, _, _, _, _ - }; - - Color[] actual = atlas.RawTexture.Pixels.ToArray(); - - Assert.Equal(expected, actual); - Assert.Equal(new Rectangle(1, 1, 2, 2), atlas.RawTextureRegions[0].Bounds); - Assert.Equal(new Rectangle(3, 1, 2, 2), atlas.RawTextureRegions[1].Bounds); - Assert.Equal(new Rectangle(1, 3, 2, 2), atlas.RawTextureRegions[2].Bounds); - Assert.Equal(new Rectangle(1, 1, 2, 2), atlas.RawTextureRegions[3].Bounds); - } - - [Fact] - public void ProcessRaw_Spacing_Added_Correctly() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile, spacing: 1); - - Color[] expected = new Color[] - { - r, r, _, g, g, - r, r, _, g, g, - _, _, _, _, _, - b, b, _, t, t, - b, b, _, t, t - }; - - Color[] actual = atlas.RawTexture.Pixels.ToArray(); - - Assert.Equal(expected, actual); - Assert.Equal(new Rectangle(0, 0, 2, 2), atlas.RawTextureRegions[0].Bounds); - Assert.Equal(new Rectangle(3, 0, 2, 2), atlas.RawTextureRegions[1].Bounds); - Assert.Equal(new Rectangle(0, 3, 2, 2), atlas.RawTextureRegions[2].Bounds); - Assert.Equal(new Rectangle(0, 0, 2, 2), atlas.RawTextureRegions[3].Bounds); - } - - [Fact] - public void ProcessRaw_InnerPadding_Added_Correctly() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile, innerPadding: 1); - - Color[] expected = new Color[] - { - _, _, _, _, _, _, _, _, - _, r, r, _, _, g, g, _, - _, r, r, _, _, g, g, _, - _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, - _, b, b, _, _, t, t, _, - _, b, b, _, _, t, t, _, - _, _, _, _, _, _, _, _, - }; - - Color[] actual = atlas.RawTexture.Pixels.ToArray(); - - Assert.Equal(expected, actual); - Assert.Equal(new Rectangle(1, 1, 2, 2), atlas.RawTextureRegions[0].Bounds); - Assert.Equal(new Rectangle(5, 1, 2, 2), atlas.RawTextureRegions[1].Bounds); - Assert.Equal(new Rectangle(1, 5, 2, 2), atlas.RawTextureRegions[2].Bounds); - Assert.Equal(new Rectangle(1, 1, 2, 2), atlas.RawTextureRegions[3].Bounds); - } - - [Fact] - public void ProcessRaw_Combined_Border_Padding_Spacing_Inner_Padding_Added_Correctly() - { - RawTextureAtlas atlas = TextureAtlasProcessor.ProcessRaw(_fixture.AsepriteFile, borderPadding: 1, spacing: 1, innerPadding: 1); - - Color[] expected = new Color[] - { - _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, - _, _, r, r, _, _, _, g, g, _, _, - _, _, r, r, _, _, _, g, g, _, _, - _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _, - _, _, b, b, _, _, _, t, t, _, _, - _, _, b, b, _, _, _, t, t, _, _, - _, _, _, _, _, _, _, _, _, _, _, - _, _, _, _, _, _, _, _, _, _, _ - }; - - Color[] actual = atlas.RawTexture.Pixels.ToArray(); - - Assert.Equal(expected, actual); - Assert.Equal(new Rectangle(2, 2, 2, 2), atlas.RawTextureRegions[0].Bounds); - Assert.Equal(new Rectangle(7, 2, 2, 2), atlas.RawTextureRegions[1].Bounds); - Assert.Equal(new Rectangle(2, 7, 2, 2), atlas.RawTextureRegions[2].Bounds); - Assert.Equal(new Rectangle(2, 2, 2, 2), atlas.RawTextureRegions[3].Bounds); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/ContentTests/TilemapProcessorTests.cs b/tests/MonoGame.Aseprite.Tests/ContentTests/TilemapProcessorTests.cs deleted file mode 100644 index d97bb726..00000000 --- a/tests/MonoGame.Aseprite.Tests/ContentTests/TilemapProcessorTests.cs +++ /dev/null @@ -1,204 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tests; - - -public sealed class TilemapProcessorTestFixture -{ - public AsepriteFile AsepriteFile { get; } - - public TilemapProcessorTestFixture() - { - string fileName = "raw-tilemap-processor-tests"; - - Color[] palette = Array.Empty(); - AsepriteTag[] tags = Array.Empty(); - AsepriteSlice[] slices = Array.Empty(); - AsepriteUserData userData = new(); - - AsepriteTileset[] tilesets = new AsepriteTileset[] - { - new(0, 4, 1, 1, "tileset-0", new Color[] {Color.Transparent, Color.Red, Color.Green, Color.Blue}), - new(1, 4, 1, 1, "tileset-1", new Color[] {Color.Transparent, Color.White, Color.Gray, Color.Black}), - }; - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new AsepriteTilemapLayer(tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "visible"), - new AsepriteTilemapLayer(tilesets[1], AsepriteLayerFlags.None, AsepriteBlendMode.Normal, 255, "hidden") - }; - - AsepriteTile[] cel0Tiles = new AsepriteTile[] - { - new AsepriteTile(0, false, false, false), - new AsepriteTile(1, false, false, false), - new AsepriteTile(2, false, false, false), - new AsepriteTile(3, false, false, false) - }; - - AsepriteTile[] cel1Tiles = new AsepriteTile[] - { - new AsepriteTile(2, false, false, false), - new AsepriteTile(3, false, false, false) - }; - - AsepriteCel[] cels = new AsepriteCel[] - { - new AsepriteTilemapCel(2, 2, cel0Tiles, layers[0], Point.Zero, 255), - new AsepriteTilemapCel(2, 2, cel1Tiles, layers[1], new Point(0, 1), 255) - }; - - AsepriteFrame[] frames = new AsepriteFrame[] - { - new($"{fileName} 0", 2, 2, 100, cels) - }; - - AsepriteFile = new(fileName, 0, 0, palette, frames, layers, tags, slices, tilesets, userData); - } -} - -public sealed class TilemapProcessorTests : IClassFixture -{ - private readonly TilemapProcessorTestFixture _fixture; - - public TilemapProcessorTests(TilemapProcessorTestFixture fixture) => _fixture = fixture; - - [Fact] - public void ProcessRaw_OnlyVisibleLayers_True_Processes_Only_Visible_Layers() - { - RawTilemap tilemap = TilemapProcessor.ProcessRaw(_fixture.AsepriteFile, 0, onlyVisibleLayers: true); - - Assert.Equal(_fixture.AsepriteFile.Name, tilemap.Name); - - Assert.Equal(1, tilemap.RawTilesets.Length); - RawTileset rawTileset = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, 0); - Assert.Equal(rawTileset, tilemap.RawTilesets[0]); - - Assert.Equal(1, tilemap.RawLayers.Length); - AsepriteTilemapLayer aseLayer = (AsepriteTilemapLayer)_fixture.AsepriteFile.Layers[0]; - AsepriteTilemapCel aseCel = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[0].Cels[0]; - AssertRawLayer(tilemap.RawLayers[0], aseLayer.Name, aseLayer.Tileset.ID, aseCel.Columns, aseCel.Rows, aseCel.Position, aseCel.Tiles); - } - - [Fact] - public void ProcessRaw_OnlyVisibleLayers_False_Processes_All_Layers() - { - RawTilemap tilemap = TilemapProcessor.ProcessRaw(_fixture.AsepriteFile, 0, onlyVisibleLayers: false); - - Assert.Equal(_fixture.AsepriteFile.Name, tilemap.Name); - - Assert.Equal(2, tilemap.RawTilesets.Length); - RawTileset rawTileset0 = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, 0); - RawTileset rawTileset1 = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, 1); - Assert.Equal(rawTileset0, tilemap.RawTilesets[0]); - Assert.Equal(rawTileset1, tilemap.RawTilesets[1]); - - Assert.Equal(2, tilemap.RawLayers.Length); - - AsepriteTilemapLayer aseLayer0 = (AsepriteTilemapLayer)_fixture.AsepriteFile.Layers[0]; - AsepriteTilemapCel aseCel0 = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[0].Cels[0]; - AssertRawLayer(tilemap.RawLayers[0], aseLayer0.Name, aseLayer0.Tileset.ID, aseCel0.Columns, aseCel0.Rows, aseCel0.Position, aseCel0.Tiles); - - AsepriteTilemapLayer aseLayer1 = (AsepriteTilemapLayer)_fixture.AsepriteFile.Layers[1]; - AsepriteTilemapCel aseCel1 = (AsepriteTilemapCel)_fixture.AsepriteFile.Frames[0].Cels[1]; - AssertRawLayer(tilemap.RawLayers[1], aseLayer1.Name, aseLayer1.Tileset.ID, aseCel1.Columns, aseCel1.Rows, aseCel1.Position, aseCel1.Tiles); - } - - [Fact] - public void ProcessRaw_Index_Out_Of_Range_Throws_Exception() - { - Assert.Throws(() => TilemapProcessor.ProcessRaw(_fixture.AsepriteFile, -1)); - Assert.Throws(() => TilemapProcessor.ProcessRaw(_fixture.AsepriteFile, _fixture.AsepriteFile.Frames.Length)); - Assert.Throws(() => TilemapProcessor.ProcessRaw(_fixture.AsepriteFile, _fixture.AsepriteFile.Frames.Length + 1)); - } - - [Fact] - public void ProcessRaw_Duplicate_AsepriteLayer_Names_Throws_Exception() - { - - AsepriteLayer[] layers = new AsepriteLayer[] - { - new AsepriteTilemapLayer(_fixture.AsepriteFile.Tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer-0"), - new AsepriteTilemapLayer(_fixture.AsepriteFile.Tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer-1"), - new AsepriteTilemapLayer(_fixture.AsepriteFile.Tilesets[0], AsepriteLayerFlags.Visible, AsepriteBlendMode.Normal, 255, "layer-0") - }; - - AsepriteTile[] tiles = new AsepriteTile[] - { - new AsepriteTile(0, false, false, false), - new AsepriteTile(1, false, false, false), - new AsepriteTile(2, false, false, false), - new AsepriteTile(3, false, false, false) - }; - - AsepriteCel[] cels = new AsepriteCel[] - { - new AsepriteTilemapCel(2, 2, tiles, layers[0], Point.Zero, 255), - new AsepriteTilemapCel(2, 2, tiles, layers[1], Point.Zero, 255), - new AsepriteTilemapCel(2, 2, tiles, layers[2], Point.Zero, 255) - }; - - AsepriteFrame[] frames = new AsepriteFrame[] - { - new($"{_fixture.AsepriteFile.Name} 0", 2, 2, 100, cels) - }; - - // Reuse the fixture, but use the layers array from above with duplicate layer names - AsepriteFile aseFile = new(_fixture.AsepriteFile.Name, - _fixture.AsepriteFile.CanvasWidth, - _fixture.AsepriteFile.CanvasHeight, - _fixture.AsepriteFile.Palette.ToArray(), - frames, - layers, - _fixture.AsepriteFile.Tags.ToArray(), - _fixture.AsepriteFile.Slices.ToArray(), - _fixture.AsepriteFile.Tilesets.ToArray(), - _fixture.AsepriteFile.UserData); - - Assert.Throws(() => TilemapProcessor.ProcessRaw(aseFile, 0)); - } - - private void AssertRawLayer(RawTilemapLayer layer, string name, int tilesetID, int columns, int rows, Point offset, ReadOnlySpan tiles) - { - Assert.Equal(name, layer.Name); - Assert.Equal(tilesetID, layer.TilesetID); - Assert.Equal(columns, layer.Columns); - Assert.Equal(rows, layer.Rows); - Assert.Equal(offset, layer.Offset); - - for (int i = 0; i < tiles.Length; i++) - { - Assert.Equal(tiles[i].TilesetTileID, layer.RawTilemapTiles[i].TilesetTileID); - Assert.Equal(tiles[i].XFlip, layer.RawTilemapTiles[i].FlipHorizontally); - Assert.Equal(tiles[i].YFlip, layer.RawTilemapTiles[i].FlipVertically); - Assert.Equal(tiles[i].DFlip, layer.RawTilemapTiles[i].FlipDiagonally); - } - } -} diff --git a/tests/MonoGame.Aseprite.Tests/ContentTests/TilesetProcessorTests.cs b/tests/MonoGame.Aseprite.Tests/ContentTests/TilesetProcessorTests.cs deleted file mode 100644 index db8ea141..00000000 --- a/tests/MonoGame.Aseprite.Tests/ContentTests/TilesetProcessorTests.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Processors; -using MonoGame.Aseprite.RawTypes; - -namespace MonoGame.Aseprite.Tests; - - -public sealed class TilesetProcessorTestFixture -{ - public AsepriteFile AsepriteFile { get; } - - public TilesetProcessorTestFixture() - { - Color[] palette = Array.Empty(); - AsepriteFrame[] frames = Array.Empty(); - AsepriteLayer[] layers = Array.Empty(); - AsepriteTag[] tags = Array.Empty(); - AsepriteSlice[] slices = Array.Empty(); - AsepriteUserData userData = new(); - - AsepriteTileset[] tilesets = new AsepriteTileset[] - { - new(0, 4, 1, 1, "tileset-0", new Color[] {Color.Transparent, Color.Red, Color.Green, Color.Blue}), - new(1, 4, 1, 1, "tileset-1", new Color[] {Color.Transparent, Color.White, Color.Gray, Color.Black}), - }; - - AsepriteFile = new("file", 0, 0, palette, frames, layers, tags, slices, tilesets, userData); - } -} - -public sealed class TilesetProcessorTests : IClassFixture -{ - private readonly TilesetProcessorTestFixture _fixture; - - public TilesetProcessorTests(TilesetProcessorTestFixture fixture) => _fixture = fixture; - - [Fact] - public void ProcessRaw_By_Index() - { - int index = 0; - AsepriteTileset aseTileset = _fixture.AsepriteFile.Tilesets[index]; - - RawTileset rawTileset = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, index); - - Assert.Equal(aseTileset.ID, rawTileset.ID); - Assert.Equal(aseTileset.Name, rawTileset.Name); - Assert.Equal(aseTileset.TileWidth, rawTileset.TileWidth); - Assert.Equal(aseTileset.TileHeight, rawTileset.TileHeight); - Assert.Equal(aseTileset.Name, rawTileset.RawTexture.Name); - Assert.Equal(aseTileset.Width, rawTileset.RawTexture.Width); - Assert.Equal(aseTileset.Height, rawTileset.RawTexture.Height); - Assert.Equal(aseTileset.Pixels.ToArray(), rawTileset.RawTexture.Pixels.ToArray()); - } - - [Fact] - public void ProcessRaw_By_Name() - { - AsepriteTileset aseTileset = _fixture.AsepriteFile.Tilesets[0]; - - RawTileset rawTileset = TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, aseTileset.Name); - - Assert.Equal(aseTileset.ID, rawTileset.ID); - Assert.Equal(aseTileset.Name, rawTileset.Name); - Assert.Equal(aseTileset.TileWidth, rawTileset.TileWidth); - Assert.Equal(aseTileset.TileHeight, rawTileset.TileHeight); - Assert.Equal(aseTileset.Name, rawTileset.RawTexture.Name); - Assert.Equal(aseTileset.Width, rawTileset.RawTexture.Width); - Assert.Equal(aseTileset.Height, rawTileset.RawTexture.Height); - Assert.Equal(aseTileset.Pixels.ToArray(), rawTileset.RawTexture.Pixels.ToArray()); - } - - [Fact] - public void ProcessRaw_Index_Out_Of_Range_Throws_Exception() - { - Assert.Throws(() => TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, -1)); - Assert.Throws(() => TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, _fixture.AsepriteFile.Tilesets.Length)); - Assert.Throws(() => TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, _fixture.AsepriteFile.Tilesets.Length + 1)); - } - - [Fact] - public void ProcessRaw_Bad_Name_Throws_Exception() - { - Assert.Throws(() => TilesetProcessor.ProcessRaw(_fixture.AsepriteFile, string.Empty)); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/FileUtils.cs b/tests/MonoGame.Aseprite.Tests/FileUtils.cs deleted file mode 100644 index 7a837e09..00000000 --- a/tests/MonoGame.Aseprite.Tests/FileUtils.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -namespace MonoGame.Aseprite.Tests; - -internal static class FileUtils -{ - internal static string GetLocalPath(string fileName) - { - return Path.Combine(Environment.CurrentDirectory, "Files", fileName); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.2.9-file-reader-test.aseprite b/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.2.9-file-reader-test.aseprite deleted file mode 100644 index d2ea6f70..00000000 Binary files a/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.2.9-file-reader-test.aseprite and /dev/null differ diff --git a/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.3.0-file-reader-test.aseprite b/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.3.0-file-reader-test.aseprite deleted file mode 100644 index 3e565943..00000000 Binary files a/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.3.0-file-reader-test.aseprite and /dev/null differ diff --git a/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.3.0-rc1-file-reader-test.aseprite b/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.3.0-rc1-file-reader-test.aseprite deleted file mode 100644 index 3a792070..00000000 Binary files a/tests/MonoGame.Aseprite.Tests/Files/aseprite-1.3.0-rc1-file-reader-test.aseprite and /dev/null differ diff --git a/tests/MonoGame.Aseprite.Tests/Files/raw-sprite-processor-test.aseprite b/tests/MonoGame.Aseprite.Tests/Files/raw-sprite-processor-test.aseprite deleted file mode 100644 index 96fce4b8..00000000 Binary files a/tests/MonoGame.Aseprite.Tests/Files/raw-sprite-processor-test.aseprite and /dev/null differ diff --git a/tests/MonoGame.Aseprite.Tests/IOTests/AsepriteFileReaderTests.cs b/tests/MonoGame.Aseprite.Tests/IOTests/AsepriteFileReaderTests.cs deleted file mode 100644 index 633c0004..00000000 --- a/tests/MonoGame.Aseprite.Tests/IOTests/AsepriteFileReaderTests.cs +++ /dev/null @@ -1,623 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Content.Readers; - -namespace MonoGame.Aseprite.Tests; - -public sealed class AsepriteFileReaderTests -{ - private readonly Color _black = new Color(0, 0, 0, 255); - private readonly Color _white = new Color(255, 255, 255, 255); - private readonly Color _red = new Color(255, 0, 0, 255); - private readonly Color _green = new Color(0, 255, 0, 255); - private readonly Color _blue = new Color(0, 0, 255, 255); - private readonly Color _transparent = new Color(0, 0, 0, 0); - - - [Fact] - public void ReadsStream_Version_1_3_0_RC1_Expected_Values() - { - string path = FileUtils.GetLocalPath("aseprite-1.3.0-rc1-file-reader-test.aseprite"); - Stream fileStream = File.OpenRead(path); - AsepriteFile aseFile = AsepriteFileReader.ReadStream(Path.GetFileNameWithoutExtension(path), fileStream); - - Reads_Version_1_3_0_RC1_Assertions(aseFile); - } - - [Fact] - public void Reads_Version_1_3_0_RC1_Expected_Values() - { - string path = FileUtils.GetLocalPath("aseprite-1.3.0-rc1-file-reader-test.aseprite"); - AsepriteFile aseFile = AsepriteFileReader.ReadFile(path); - - Reads_Version_1_3_0_RC1_Assertions(aseFile); - } - - private void Reads_Version_1_3_0_RC1_Assertions(AsepriteFile aseFile) - { - // ************************************************************ - // File properties - // ************************************************************ - Assert.Equal("aseprite-1.3.0-rc1-file-reader-test", aseFile.Name); - Assert.Equal(2, aseFile.CanvasWidth); - Assert.Equal(2, aseFile.CanvasHeight); - AssertUserData(aseFile.UserData, "hello sprite", _blue); - - // ************************************************************ - // Layers - // ************************************************************ - Assert.Equal(9, aseFile.Layers.Length); - AssertLayer(aseFile.Layers[0], "background", true, true, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[1], "hidden", false, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[2], "100-opacity", true, false, false, AsepriteBlendMode.Normal, 100, null, null); - AssertLayer(aseFile.Layers[3], "userdata", true, false, false, AsepriteBlendMode.Normal, 255, "hello layer", _blue); - AssertLayer(aseFile.Layers[4], "group", true, false, false, AsepriteBlendMode.Normal, 0, null, null); - AssertLayer(aseFile.Layers[5], "child", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[6], "tilemap", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AsepriteTilemapLayer tilemapLayer = Assert.IsType(aseFile.Layers[6]); - AssertTilemapLayer(tilemapLayer, "tileset"); - AssertLayer(aseFile.Layers[7], "eight-frames", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[8], "blend-color-dodge", true, false, false, AsepriteBlendMode.ColorDodge, 255, null, null); - - - // ************************************************************ - // Tags - // ************************************************************ - Assert.Equal(6, aseFile.Tags.Length); - AssertTag(aseFile.Tags[0], "forward", 0, 0, AsepriteLoopDirection.Forward, 0, _black, null, _black); - AssertTag(aseFile.Tags[1], "reversed", 1, 1, AsepriteLoopDirection.Reverse, 0, _black, null, _black); - AssertTag(aseFile.Tags[2], "pingpong", 2, 2, AsepriteLoopDirection.PingPong, 0, _black, null, _black); - AssertTag(aseFile.Tags[3], "frames-4-to-6", 3, 5, AsepriteLoopDirection.Forward, 0, _black, null, _black); - AssertTag(aseFile.Tags[4], "userdata", 6, 6, AsepriteLoopDirection.Forward, 0, _green, "hello tag", _green); - AssertTag(aseFile.Tags[5], "repeat-x100", 7, 7, AsepriteLoopDirection.Forward, 100, _black, null, _black); - - // ************************************************************ - // Frames - // ************************************************************ - Assert.Equal(8, aseFile.Frames.Length); - AssertFrame(aseFile.Frames[0], 3, 2, 2, 100); - AssertFrame(aseFile.Frames[1], 2, 2, 2, 200); - AssertFrame(aseFile.Frames[2], 2, 2, 2, 300); - AssertFrame(aseFile.Frames[3], 2, 2, 2, 400); - AssertFrame(aseFile.Frames[4], 2, 2, 2, 500); - AssertFrame(aseFile.Frames[5], 2, 2, 2, 600); - AssertFrame(aseFile.Frames[6], 2, 2, 2, 700); - AssertFrame(aseFile.Frames[7], 2, 2, 2, 800); - - // ************************************************************ - // Cels - // ************************************************************ - // Frame 0 - Assert.Equal(3, aseFile.Frames[0].Cels.Length); - AssertCel(aseFile.Frames[0].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame0Cel0 = Assert.IsType(aseFile.Frames[0].Cels[0]); - AssertImageCel(frame0Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[0].Cels[1], "tilemap", 0, 0, 255, null, null); - AsepriteTilemapCel frame0cel1 = Assert.IsType(aseFile.Frames[0].Cels[1]); - AssertTilemapCel(frame0cel1, 2, 2, 4, "tileset"); - AssertTile(frame0cel1.Tiles[0], 1, false, false, false); - AssertTile(frame0cel1.Tiles[1], 2, false, false, false); - AssertTile(frame0cel1.Tiles[2], 3, false, false, false); - AssertTile(frame0cel1.Tiles[3], 4, false, false, false); - - AssertCel(aseFile.Frames[0].Cels[2], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame0cel2 = Assert.IsType(aseFile.Frames[0].Cels[2]); - AssertImageCel(frame0cel2, 1, 1, new Color[] { _red }); - - // Frame 1 - AssertCel(aseFile.Frames[1].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame1Cel0 = Assert.IsType(aseFile.Frames[1].Cels[0]); - AssertImageCel(frame1Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[1].Cels[1], "eight-frames", 1, 0, 255, null, null); - AsepriteImageCel frame1cel1 = Assert.IsType(aseFile.Frames[1].Cels[1]); - AssertImageCel(frame1cel1, 1, 1, new Color[] { _red }); - - // Frame 2 - AssertCel(aseFile.Frames[2].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame2Cel0 = Assert.IsType(aseFile.Frames[2].Cels[0]); - AssertImageCel(frame2Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[2].Cels[1], "eight-frames", 0, 1, 255, null, null); - AsepriteImageCel frame2cel1 = Assert.IsType(aseFile.Frames[2].Cels[1]); - AssertImageCel(frame2cel1, 1, 1, new Color[] { _red }); - - // Frame 3 - AssertCel(aseFile.Frames[3].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame3cel0 = Assert.IsType(aseFile.Frames[3].Cels[0]); - AssertImageCel(frame3cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[3].Cels[1], "eight-frames", 1, 1, 255, null, null); - AsepriteImageCel frame3cel1 = Assert.IsType(aseFile.Frames[3].Cels[1]); - AssertImageCel(frame3cel1, 1, 1, new Color[] { _red }); - - // Frame 4 - AssertCel(aseFile.Frames[4].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame4cel0 = Assert.IsType(aseFile.Frames[4].Cels[0]); - AssertImageCel(frame4cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[4].Cels[1], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame4cel1 = Assert.IsType(aseFile.Frames[4].Cels[1]); - AssertImageCel(frame4cel1, 2, 1, new Color[] { _red, _red }); - - // Frame 5 - AssertCel(aseFile.Frames[5].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame5cel0 = Assert.IsType(aseFile.Frames[5].Cels[0]); - AssertImageCel(frame5cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[5].Cels[1], "eight-frames", 0, 1, 255, null, null); - AsepriteImageCel frame5cel1 = Assert.IsType(aseFile.Frames[5].Cels[1]); - AssertImageCel(frame5cel1, 2, 1, new Color[] { _red, _red }); - - // Frame 6 - AssertCel(aseFile.Frames[6].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame6cel0 = Assert.IsType(aseFile.Frames[6].Cels[0]); - AssertImageCel(frame6cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[6].Cels[1], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame6cel1 = Assert.IsType(aseFile.Frames[6].Cels[1]); - AssertImageCel(frame6cel1, 2, 2, new Color[] { _red, _red, _red, _transparent }); - - // Frame 7 - AssertCel(aseFile.Frames[7].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame7cel0 = Assert.IsType(aseFile.Frames[7].Cels[0]); - AssertImageCel(frame7cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[7].Cels[1], "eight-frames", 0, 0, 255, "hello cel", _red); - AsepriteImageCel frame7cel1 = Assert.IsType(aseFile.Frames[7].Cels[1]); - AssertImageCel(frame7cel1, 2, 2, new Color[] { _red, _red, _transparent, _red }); - - // ************************************************************ - // Slices - // ************************************************************ - Assert.Equal(1, aseFile.Slices.Length); - AssertSlice(aseFile.Slices[0], "slice", 1, true, true, "hello slice", _green); - AssertSliceKey(aseFile.Slices[0].Keys[0], 0, new Rectangle(0, 0, 2, 2), new Rectangle(0, 0, 1, 2), new Point(1, 2)); - - // ************************************************************ - // Tilesets - // ************************************************************ - Assert.Equal(1, aseFile.Tilesets.Length); - AssertTileset(aseFile.Tilesets[0], 0, "tileset", 5, 1, 1, 1, 5, new Color[] { _transparent, _white, _red, _green, _blue }); - } - - - - [Fact] - public void ReadsStream_Version_1_3_0_Expected_Values() - { - string path = FileUtils.GetLocalPath("aseprite-1.3.0-file-reader-test.aseprite"); - Stream fileStream = File.OpenRead(path); - AsepriteFile aseFile = AsepriteFileReader.ReadStream(Path.GetFileNameWithoutExtension(path), fileStream); - - Reads_Version_1_3_0_Assertions(aseFile); - } - - [Fact] - public void Reads_Version_1_3_0_Expected_Values() - { - string path = FileUtils.GetLocalPath("aseprite-1.3.0-file-reader-test.aseprite"); - AsepriteFile aseFile = AsepriteFileReader.ReadFile(path); - - Reads_Version_1_3_0_Assertions(aseFile); - } - - private void Reads_Version_1_3_0_Assertions(AsepriteFile aseFile) - { - // ************************************************************ - // File properties - // ************************************************************ - Assert.Equal("aseprite-1.3.0-file-reader-test", aseFile.Name); - Assert.Equal(2, aseFile.CanvasWidth); - Assert.Equal(2, aseFile.CanvasHeight); - AssertUserData(aseFile.UserData, "hello sprite", _blue); - - // ************************************************************ - // Layers - // ************************************************************ - Assert.Equal(9, aseFile.Layers.Length); - AssertLayer(aseFile.Layers[0], "background", true, true, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[1], "hidden", false, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[2], "100-opacity", true, false, false, AsepriteBlendMode.Normal, 100, null, null); - AssertLayer(aseFile.Layers[3], "userdata", true, false, false, AsepriteBlendMode.Normal, 255, "hello layer", _blue); - AssertLayer(aseFile.Layers[4], "group", true, false, false, AsepriteBlendMode.Normal, 0, null, null); - AssertLayer(aseFile.Layers[5], "child", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[6], "tilemap", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AsepriteTilemapLayer tilemapLayer = Assert.IsType(aseFile.Layers[6]); - AssertTilemapLayer(tilemapLayer, "tileset"); - AssertLayer(aseFile.Layers[7], "eight-frames", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[8], "blend-color-dodge", true, false, false, AsepriteBlendMode.ColorDodge, 255, null, null); - - - // ************************************************************ - // Tags - // ************************************************************ - Assert.Equal(5, aseFile.Tags.Length); - AssertTag(aseFile.Tags[0], "forward", 0, 0, AsepriteLoopDirection.Forward, 0, _black, null, _black); - AssertTag(aseFile.Tags[1], "reversed", 1, 1, AsepriteLoopDirection.Reverse, 0, _black, null, _black); - AssertTag(aseFile.Tags[2], "pingpong", 2, 2, AsepriteLoopDirection.PingPong, 0, _black, null, _black); - AssertTag(aseFile.Tags[3], "frames-4-to-6", 3, 5, AsepriteLoopDirection.Forward, 0, _black, null, _black); - AssertTag(aseFile.Tags[4], "userdata", 6, 6, AsepriteLoopDirection.Forward, 0, _green, "hello tag", _green); - - // ************************************************************ - // Frames - // ************************************************************ - Assert.Equal(8, aseFile.Frames.Length); - AssertFrame(aseFile.Frames[0], 3, 2, 2, 100); - AssertFrame(aseFile.Frames[1], 2, 2, 2, 200); - AssertFrame(aseFile.Frames[2], 2, 2, 2, 300); - AssertFrame(aseFile.Frames[3], 2, 2, 2, 400); - AssertFrame(aseFile.Frames[4], 2, 2, 2, 500); - AssertFrame(aseFile.Frames[5], 2, 2, 2, 600); - AssertFrame(aseFile.Frames[6], 2, 2, 2, 700); - AssertFrame(aseFile.Frames[7], 2, 2, 2, 800); - - // ************************************************************ - // Cels - // ************************************************************ - // Frame 0 - Assert.Equal(3, aseFile.Frames[0].Cels.Length); - AssertCel(aseFile.Frames[0].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame0Cel0 = Assert.IsType(aseFile.Frames[0].Cels[0]); - AssertImageCel(frame0Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[0].Cels[1], "tilemap", 0, 0, 255, null, null); - AsepriteTilemapCel frame0cel1 = Assert.IsType(aseFile.Frames[0].Cels[1]); - AssertTilemapCel(frame0cel1, 2, 2, 4, "tileset"); - AssertTile(frame0cel1.Tiles[0], 1, false, false, false); - AssertTile(frame0cel1.Tiles[1], 2, false, false, false); - AssertTile(frame0cel1.Tiles[2], 3, false, false, false); - AssertTile(frame0cel1.Tiles[3], 4, false, false, false); - - AssertCel(aseFile.Frames[0].Cels[2], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame0cel2 = Assert.IsType(aseFile.Frames[0].Cels[2]); - AssertImageCel(frame0cel2, 1, 1, new Color[] { _red }); - - // Frame 1 - AssertCel(aseFile.Frames[1].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame1Cel0 = Assert.IsType(aseFile.Frames[1].Cels[0]); - AssertImageCel(frame1Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[1].Cels[1], "eight-frames", 1, 0, 255, null, null); - AsepriteImageCel frame1cel1 = Assert.IsType(aseFile.Frames[1].Cels[1]); - AssertImageCel(frame1cel1, 1, 1, new Color[] { _red }); - - // Frame 2 - AssertCel(aseFile.Frames[2].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame2Cel0 = Assert.IsType(aseFile.Frames[2].Cels[0]); - AssertImageCel(frame2Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[2].Cels[1], "eight-frames", 0, 1, 255, null, null); - AsepriteImageCel frame2cel1 = Assert.IsType(aseFile.Frames[2].Cels[1]); - AssertImageCel(frame2cel1, 1, 1, new Color[] { _red }); - - // Frame 3 - AssertCel(aseFile.Frames[3].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame3cel0 = Assert.IsType(aseFile.Frames[3].Cels[0]); - AssertImageCel(frame3cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[3].Cels[1], "eight-frames", 1, 1, 255, null, null); - AsepriteImageCel frame3cel1 = Assert.IsType(aseFile.Frames[3].Cels[1]); - AssertImageCel(frame3cel1, 1, 1, new Color[] { _red }); - - // Frame 4 - AssertCel(aseFile.Frames[4].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame4cel0 = Assert.IsType(aseFile.Frames[4].Cels[0]); - AssertImageCel(frame4cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[4].Cels[1], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame4cel1 = Assert.IsType(aseFile.Frames[4].Cels[1]); - AssertImageCel(frame4cel1, 2, 1, new Color[] { _red, _red }); - - // Frame 5 - AssertCel(aseFile.Frames[5].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame5cel0 = Assert.IsType(aseFile.Frames[5].Cels[0]); - AssertImageCel(frame5cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[5].Cels[1], "eight-frames", 0, 1, 255, null, null); - AsepriteImageCel frame5cel1 = Assert.IsType(aseFile.Frames[5].Cels[1]); - AssertImageCel(frame5cel1, 2, 1, new Color[] { _red, _red }); - - // Frame 6 - AssertCel(aseFile.Frames[6].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame6cel0 = Assert.IsType(aseFile.Frames[6].Cels[0]); - AssertImageCel(frame6cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[6].Cels[1], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame6cel1 = Assert.IsType(aseFile.Frames[6].Cels[1]); - AssertImageCel(frame6cel1, 2, 2, new Color[] { _red, _red, _red, _transparent }); - - // Frame 7 - AssertCel(aseFile.Frames[7].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame7cel0 = Assert.IsType(aseFile.Frames[7].Cels[0]); - AssertImageCel(frame7cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[7].Cels[1], "eight-frames", 0, 0, 255, "hello cel", _red); - AsepriteImageCel frame7cel1 = Assert.IsType(aseFile.Frames[7].Cels[1]); - AssertImageCel(frame7cel1, 2, 2, new Color[] { _red, _red, _transparent, _red }); - - // ************************************************************ - // Slices - // ************************************************************ - Assert.Equal(1, aseFile.Slices.Length); - AssertSlice(aseFile.Slices[0], "slice", 1, true, true, "hello slice", _green); - AssertSliceKey(aseFile.Slices[0].Keys[0], 0, new Rectangle(0, 0, 2, 2), new Rectangle(0, 0, 1, 2), new Point(1, 2)); - - // ************************************************************ - // Tilesets - // ************************************************************ - Assert.Equal(1, aseFile.Tilesets.Length); - AssertTileset(aseFile.Tilesets[0], 0, "tileset", 5, 1, 1, 1, 5, new Color[] { _transparent, _white, _red, _green, _blue }); - } - - [Fact] - public void Reads_Version_1_2_9_Expected_Values() - { - string path = FileUtils.GetLocalPath("aseprite-1.2.9-file-reader-test.aseprite"); - AsepriteFile aseFile = AsepriteFileReader.ReadFile(path); - - // ************************************************************ - // File properties - // ************************************************************ - Assert.Equal("aseprite-1.2.9-file-reader-test", aseFile.Name); - Assert.Equal(2, aseFile.CanvasWidth); - Assert.Equal(2, aseFile.CanvasHeight); - AssertUserData(aseFile.UserData, default, default); - - // ************************************************************ - // Layers - // ************************************************************ - Assert.Equal(8, aseFile.Layers.Length); - AssertLayer(aseFile.Layers[0], "background", true, true, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[1], "hidden", false, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[2], "100-opacity", true, false, false, AsepriteBlendMode.Normal, 100, null, null); - AssertLayer(aseFile.Layers[3], "userdata", true, false, false, AsepriteBlendMode.Normal, 255, "hello layer", _blue); - AssertLayer(aseFile.Layers[4], "group", true, false, false, AsepriteBlendMode.Normal, 0, null, null); - AssertLayer(aseFile.Layers[5], "child", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[6], "eight-frames", true, false, false, AsepriteBlendMode.Normal, 255, null, null); - AssertLayer(aseFile.Layers[7], "blend-color-dodge", true, false, false, AsepriteBlendMode.ColorDodge, 255, null, null); - - - // ************************************************************ - // Tags - // ************************************************************ - Assert.Equal(5, aseFile.Tags.Length); - AssertTag(aseFile.Tags[0], "forward", 0, 0, AsepriteLoopDirection.Forward, 0, _black, null, null); - AssertTag(aseFile.Tags[1], "reversed", 1, 1, AsepriteLoopDirection.Reverse, 0, _black, null, null); - AssertTag(aseFile.Tags[2], "pingpong", 2, 2, AsepriteLoopDirection.PingPong, 0, _black, null, null); - AssertTag(aseFile.Tags[3], "frames-4-to-6", 3, 5, AsepriteLoopDirection.Forward, 0, _black, null, null); - AssertTag(aseFile.Tags[4], "userdata", 6, 6, AsepriteLoopDirection.Forward, 0, _green, null, null); - - // ************************************************************ - // Frames - // ************************************************************ - Assert.Equal(8, aseFile.Frames.Length); - AssertFrame(aseFile.Frames[0], 2, 2, 2, 100); - AssertFrame(aseFile.Frames[1], 2, 2, 2, 200); - AssertFrame(aseFile.Frames[2], 2, 2, 2, 300); - AssertFrame(aseFile.Frames[3], 2, 2, 2, 400); - AssertFrame(aseFile.Frames[4], 2, 2, 2, 500); - AssertFrame(aseFile.Frames[5], 2, 2, 2, 600); - AssertFrame(aseFile.Frames[6], 2, 2, 2, 700); - AssertFrame(aseFile.Frames[7], 2, 2, 2, 800); - - // ************************************************************ - // Cels - // ************************************************************ - // Frame 0 - Assert.Equal(2, aseFile.Frames[0].Cels.Length); - AssertCel(aseFile.Frames[0].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame0Cel0 = Assert.IsType(aseFile.Frames[0].Cels[0]); - AssertImageCel(frame0Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[0].Cels[1], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame0cel1 = Assert.IsType(aseFile.Frames[0].Cels[1]); - AssertImageCel(frame0cel1, 1, 1, new Color[] { _red }); - - // Frame 1 - AssertCel(aseFile.Frames[1].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame1Cel0 = Assert.IsType(aseFile.Frames[1].Cels[0]); - AssertImageCel(frame1Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[1].Cels[1], "eight-frames", 1, 0, 255, null, null); - AsepriteImageCel frame1cel1 = Assert.IsType(aseFile.Frames[1].Cels[1]); - AssertImageCel(frame1cel1, 1, 1, new Color[] { _red }); - - // Frame 2 - AssertCel(aseFile.Frames[2].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame2Cel0 = Assert.IsType(aseFile.Frames[2].Cels[0]); - AssertImageCel(frame2Cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[2].Cels[1], "eight-frames", 0, 1, 255, null, null); - AsepriteImageCel frame2cel1 = Assert.IsType(aseFile.Frames[2].Cels[1]); - AssertImageCel(frame2cel1, 1, 1, new Color[] { _red }); - - // Frame 3 - AssertCel(aseFile.Frames[3].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame3cel0 = Assert.IsType(aseFile.Frames[3].Cels[0]); - AssertImageCel(frame3cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[3].Cels[1], "eight-frames", 1, 1, 255, null, null); - AsepriteImageCel frame3cel1 = Assert.IsType(aseFile.Frames[3].Cels[1]); - AssertImageCel(frame3cel1, 1, 1, new Color[] { _red }); - - // Frame 4 - AssertCel(aseFile.Frames[4].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame4cel0 = Assert.IsType(aseFile.Frames[4].Cels[0]); - AssertImageCel(frame4cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[4].Cels[1], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame4cel1 = Assert.IsType(aseFile.Frames[4].Cels[1]); - AssertImageCel(frame4cel1, 2, 1, new Color[] { _red, _red }); - - // Frame 5 - AssertCel(aseFile.Frames[5].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame5cel0 = Assert.IsType(aseFile.Frames[5].Cels[0]); - AssertImageCel(frame5cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[5].Cels[1], "eight-frames", 0, 1, 255, null, null); - AsepriteImageCel frame5cel1 = Assert.IsType(aseFile.Frames[5].Cels[1]); - AssertImageCel(frame5cel1, 2, 1, new Color[] { _red, _red }); - - // Frame 6 - AssertCel(aseFile.Frames[6].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame6cel0 = Assert.IsType(aseFile.Frames[6].Cels[0]); - AssertImageCel(frame6cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[6].Cels[1], "eight-frames", 0, 0, 255, null, null); - AsepriteImageCel frame6cel1 = Assert.IsType(aseFile.Frames[6].Cels[1]); - AssertImageCel(frame6cel1, 2, 2, new Color[] { _red, _red, _red, _transparent }); - - // Frame 7 - AssertCel(aseFile.Frames[7].Cels[0], "background", 0, 0, 255, null, null); - AsepriteImageCel frame7cel0 = Assert.IsType(aseFile.Frames[7].Cels[0]); - AssertImageCel(frame7cel0, 2, 2, new Color[] { _black, _black, _black, _black }); - - AssertCel(aseFile.Frames[7].Cels[1], "eight-frames", 0, 0, 255, "hello cel", _red); - AsepriteImageCel frame7cel1 = Assert.IsType(aseFile.Frames[7].Cels[1]); - AssertImageCel(frame7cel1, 2, 2, new Color[] { _red, _red, _transparent, _red }); - - // ************************************************************ - // Slices - // ************************************************************ - Assert.Equal(1, aseFile.Slices.Length); - AssertSlice(aseFile.Slices[0], "slice", 1, true, true, "hello slice", _green); - AssertSliceKey(aseFile.Slices[0].Keys[0], 0, new Rectangle(0, 0, 2, 2), new Rectangle(0, 0, 1, 2), new Point(1, 2)); - - // ************************************************************ - // Tilesets - // ************************************************************ - Assert.Equal(0, aseFile.Tilesets.Length); - } - - private void AssertLayer(AsepriteLayer layer, string name, bool isVisible, bool isBackground, bool isReference, AsepriteBlendMode blendMode, int opacity, string? userDataText, Color? userDataColor) - { - Assert.Equal(name, layer.Name); - Assert.Equal(isVisible, layer.IsVisible); - Assert.Equal(isBackground, layer.IsBackground); - Assert.Equal(isReference, layer.IsReference); - Assert.Equal(blendMode, layer.BlendMode); - Assert.Equal(opacity, layer.Opacity); - AssertUserData(layer.UserData, userDataText, userDataColor); - } - - private void AssertTilemapLayer(AsepriteTilemapLayer tilemapLayer, string tilesetName) - { - Assert.Equal(tilesetName, tilemapLayer.Tileset.Name); - } - - private void AssertTag(AsepriteTag tag, string name, int from, int to, AsepriteLoopDirection direction, int repeat, Color color, string? userDataText, Color? userDataColor) - { - Assert.Equal(name, tag.Name); - Assert.Equal(from, tag.From); - Assert.Equal(to, tag.To); - Assert.Equal(repeat, tag.Repeat); - Assert.Equal(direction, tag.Direction); - Assert.Equal(color, tag.Color); - AssertUserData(tag.UserData, userDataText, userDataColor); - } - - private void AssertFrame(AsepriteFrame frame, int celCount, int width, int height, int duration) - { - Assert.Equal(celCount, frame.Cels.Length); - Assert.Equal(width, frame.Width); - Assert.Equal(height, frame.Height); - Assert.Equal(duration, frame.DurationInMilliseconds); - } - - private void AssertCel(AsepriteCel cel, string layerName, int x, int y, int opacity, string? userDataText, Color? userDataColor) - { - Assert.Equal(layerName, cel.Layer.Name); - Assert.Equal(x, cel.Position.X); - Assert.Equal(y, cel.Position.Y); - Assert.Equal(opacity, cel.Opacity); - AssertUserData(cel.UserData, userDataText, userDataColor); - } - - private void AssertImageCel(AsepriteImageCel imageCel, int width, int height, Color[] pixels) - { - Assert.Equal(width, imageCel.Width); - Assert.Equal(height, imageCel.Height); - Assert.Equal(pixels, imageCel.Pixels.ToArray()); - } - - private void AssertTilemapCel(AsepriteTilemapCel tilemapCel, int columns, int rows, int tileCount, string tilesetName) - { - Assert.Equal(columns, tilemapCel.Columns); - Assert.Equal(rows, tilemapCel.Rows); - Assert.Equal(tileCount, tilemapCel.Tiles.Length); - Assert.Equal(tileCount, tilemapCel.TileCount); - Assert.Equal(tilesetName, tilemapCel.Tileset.Name); - } - - private void AssertTile(AsepriteTile tile, int tilesetTileID, bool xFlip, bool yFlip, bool dFlip) - { - Assert.Equal(tilesetTileID, tile.TilesetTileID); - Assert.Equal(xFlip, tile.XFlip); - Assert.Equal(yFlip, tile.YFlip); - Assert.Equal(dFlip, tile.DFlip); - } - - private void AssertSlice(AsepriteSlice slice, string name, int keyCount, bool isNine, bool hasPivot, string? userDataText, Color? userDataColor) - { - Assert.Equal(name, slice.Name); - Assert.Equal(isNine, slice.IsNinePatch); - Assert.Equal(hasPivot, slice.HasPivot); - Assert.Equal(keyCount, slice.Keys.Length); - Assert.Equal(keyCount, slice.KeyCount); - AssertUserData(slice.UserData, userDataText, userDataColor); - } - - private void AssertSliceKey(AsepriteSliceKey key, int frame, Rectangle bounds, Rectangle? center, Point? pivot) - { - Assert.Equal(frame, key.FrameIndex); - Assert.Equal(bounds, key.Bounds); - Assert.Equal(center, key.CenterBounds); - Assert.Equal(center is not null, key.IsNinePatch); - Assert.Equal(pivot, key.Pivot); - Assert.Equal(pivot is not null, key.HasPivot); - } - - private void AssertTileset(AsepriteTileset tileset, int id, string name, int tileCount, int tileWidth, int tileHeight, int width, int height, Color[] pixels) - { - Assert.Equal(id, tileset.ID); - Assert.Equal(name, tileset.Name); - Assert.Equal(tileCount, tileset.TileCount); - Assert.Equal(tileWidth, tileset.TileWidth); - Assert.Equal(tileHeight, tileset.TileHeight); - Assert.Equal(width, tileset.Width); - Assert.Equal(height, tileset.Height); - Assert.Equal(pixels, tileset.Pixels.ToArray()); - } - - private void AssertUserData(AsepriteUserData userData, string? text, Color? color) - { - Assert.Equal(text, userData.Text); - Assert.Equal(color, userData.Color); - } -} diff --git a/tests/MonoGame.Aseprite.Tests/MonoGame.Aseprite.Tests.csproj b/tests/MonoGame.Aseprite.Tests/MonoGame.Aseprite.Tests.csproj deleted file mode 100644 index 3a21415d..00000000 --- a/tests/MonoGame.Aseprite.Tests/MonoGame.Aseprite.Tests.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - net6.0 - enable - enable - - false - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - All - - - - - - - - - - - - diff --git a/tests/MonoGame.Aseprite.Tests/Usings.cs b/tests/MonoGame.Aseprite.Tests/Usings.cs deleted file mode 100644 index 8c927eb7..00000000 --- a/tests/MonoGame.Aseprite.Tests/Usings.cs +++ /dev/null @@ -1 +0,0 @@ -global using Xunit; \ No newline at end of file diff --git a/tests/MonoGame.Aseprite.Tests/UtilityTests/BlendFunctionsTests.cs b/tests/MonoGame.Aseprite.Tests/UtilityTests/BlendFunctionsTests.cs deleted file mode 100644 index 6e61c4bc..00000000 --- a/tests/MonoGame.Aseprite.Tests/UtilityTests/BlendFunctionsTests.cs +++ /dev/null @@ -1,723 +0,0 @@ -/* ---------------------------------------------------------------------------- -MIT License - -Copyright (c) 2018-2023 Christopher Whitley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ----------------------------------------------------------------------------- */ - -using Microsoft.Xna.Framework; -using MonoGame.Aseprite.AsepriteTypes; -using MonoGame.Aseprite.Utilities; - -namespace MonoGame.Aseprite.Tests; - -/* - In order to test the blend modes, I needed to have hard factual values to assert as the expected values after - performing a blend. Since the blend functions were ported form Aseprite, we'll use Aseprite itself as the source - of truth for what the values should be. - - To get these values, a 4x4 sprite was created with the following colors - - * orange = argb(255, 223, 113, 38) - * green = argb(255, 106, 190, 48) - * purple = argb(255, 63, 63, 116) - * pink = argb(255, 215, 123, 186) - * red = argb(255, 172, 50, 50) - * transparent = argb(0, 0, 0, 0) - - Next two layers were added to the sprite. The bottom layer consists of the following pixels, in order from - top-to-bottom, read left-to-right - - [Layer 1] - green, green, purple, purple, - green, green, purple, purple, - pink, pink, red, red, - pink, pink, red, red, - - The top layers consists fo the following pixels, in order from top-to-bottom, read left-to-right - - [Layer 2] - transparent, transparent, transparent, transparent, - transparent, orange, orange, transparent, - transparent, orange, orange, transparent, - transparent, transparent, transparent, transparent, - - There is much simpler ways of doing this (like making it a 2x2 image and trimming off the transparent border), but - this is what i did. Anyway, the next steps was to set the Blend Mode used by the top layer, then copy the RGBA value - of each pixel where it overlapped one of the base layer colors into the test for that blend mode. - - It was a manual process, but the point of the tests is to ensure that the ported code blends colors the same way - that Aseprite does to match it 1:1. -*/ -public sealed class BlendFunctionsTests -{ - private static readonly Color _green = new Color(106, 190, 48, 255); - private static readonly Color _purple = new Color(63, 63, 116, 255); - private static readonly Color _pink = new Color(215, 123, 186, 255); - private static readonly Color _red = new Color(172, 50, 50, 255); - private static readonly Color _orange = new Color(223, 113, 38, 255); - private static readonly Color _transparent = new Color(0, 0, 0, 0); - - [Fact] - public void BlendFunctions_Blend_Normal_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Normal; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(_orange, BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(_orange, BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(_orange, BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Normal_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Normal; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Normal_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Normal; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Normal_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Normal; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Darken_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Darken; - Assert.Equal(new Color(106, 113, 38, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(63, 63, 38, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(215, 113, 38, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(172, 50, 38, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Darken_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Darken; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Darken_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Darken; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Darken_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Darken; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Multiply_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Multiply; - Assert.Equal(new Color(93, 84, 7, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(55, 28, 17, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(188, 55, 28, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(150, 22, 7, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Multiply_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Multiply; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Multiply_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Multiply; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Multiply_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Multiply; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorBurn_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorBurn; - Assert.Equal(new Color(85, 108, 0, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(35, 0, 0, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(209, 0, 0, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(160, 0, 0, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorBurn_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorBurn; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorBurn_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorBurn; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorBurn_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorBurn; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Lighten_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Lighten; - Assert.Equal(new Color(223, 190, 48, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(223, 113, 116, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(223, 123, 186, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(223, 113, 50, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Lighten_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Lighten; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Lighten_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Lighten; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Lighten_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Lighten; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Screen_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Screen; - Assert.Equal(new Color(236, 219, 79, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(231, 148, 137, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(250, 181, 196, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(245, 141, 81, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Screen_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Screen; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Screen_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Screen; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Screen_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Screen; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorDodge_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorDodge; - Assert.Equal(new Color(255, 255, 56, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(255, 113, 136, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(255, 221, 219, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(255, 90, 59, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorDodge_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorDodge; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorDodge_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorDodge; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_ColorDodge_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.ColorDodge; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Addition_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Addition; - Assert.Equal(new Color(255, 255, 86, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(255, 176, 154, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(255, 236, 224, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(255, 163, 88, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Addition_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Addition; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Addition_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Addition; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Addition_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Addition; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Overlay_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Overlay; - Assert.Equal(new Color(185, 183, 14, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(110, 56, 35, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(245, 109, 138, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(234, 44, 15, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Overlay_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Overlay; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Overlay_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Overlay; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Overlay_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Overlay; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_SoftLight_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.SoftLight; - Assert.Equal(new Color(150, 184, 21, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(111, 58, 72, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(229, 116, 151, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(200, 45, 22, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_SoftLight_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.SoftLight; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_SoftLight_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.SoftLight; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_SoftLight_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.SoftLight; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_HardLight_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.HardLight; - Assert.Equal(new Color(218, 168, 14, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(207, 56, 35, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(245, 109, 55, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(234, 44, 15, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_HardLight_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.HardLight; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_HardLight_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.HardLight; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_HardLight_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.HardLight; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Difference_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Difference; - Assert.Equal(new Color(117, 77, 10, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(160, 50, 78, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(8, 10, 148, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(51, 63, 12, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Difference_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Difference; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Difference_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Difference; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Difference_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Difference; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Exclusion_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Exclusion; - Assert.Equal(new Color(143, 135, 72, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(176, 120, 120, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(62, 126, 168, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(95, 119, 74, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Exclusion_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Exclusion; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Exclusion_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Exclusion; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Exclusion_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Exclusion; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Subtract_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Subtract; - Assert.Equal(new Color(0, 77, 10, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(0, 0, 78, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(0, 10, 148, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(0, 0, 12, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Subtract_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Subtract; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Subtract_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Subtract; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Subtract_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Subtract; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Divide_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Divide; - Assert.Equal(new Color(121, 255, 255, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(72, 142, 255, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(246, 255, 255, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(197, 113, 255, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Divide_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Divide; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Divide_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Divide; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Divide_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Divide; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Hue_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Hue; - Assert.Equal(new Color(214, 130, 72, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(93, 61, 40, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(199, 145, 107, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(142, 70, 20, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Hue_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Hue; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Hue_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Hue; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Hue_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Hue; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Saturation_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Saturation; - Assert.Equal(new Color(92, 202, 17, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(92, 29, 214, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(255, 98, 205, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(186, 51, 1, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Saturation_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Saturation; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Saturation_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Saturation; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Saturation_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Saturation; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Color_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Color; - Assert.Equal(new Color(234, 124, 49, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(127, 51, 0, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(242, 132, 57, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(160, 65, 0, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Color_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Color; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Color_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Color; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Color_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Color; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Luminosity_ColorOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Luminosity; - Assert.Equal(new Color(94, 178, 36, 255), BlendFunctions.Blend(mode, _green, _orange, 255)); - Assert.Equal(new Color(131, 131, 184, 255), BlendFunctions.Blend(mode, _purple, _orange, 255)); - Assert.Equal(new Color(195, 103, 166, 255), BlendFunctions.Blend(mode, _pink, _orange, 255)); - Assert.Equal(new Color(223, 101, 101, 255), BlendFunctions.Blend(mode, _red, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Luminosity_ColorOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Luminosity; - Assert.Equal(_orange, BlendFunctions.Blend(mode, _transparent, _orange, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Luminosity_TransparentOnColorTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Luminosity; - Assert.Equal(_green, BlendFunctions.Blend(mode, _green, _transparent, 255)); - Assert.Equal(_purple, BlendFunctions.Blend(mode, _purple, _transparent, 255)); - Assert.Equal(_pink, BlendFunctions.Blend(mode, _pink, _transparent, 255)); - Assert.Equal(_red, BlendFunctions.Blend(mode, _red, _transparent, 255)); - } - - [Fact] - public void BlendFunctions_Blend_Luminosity_TransparentOnTransparentTest() - { - AsepriteBlendMode mode = AsepriteBlendMode.Luminosity; - Assert.Equal(_transparent, BlendFunctions.Blend(mode, _transparent, _transparent, 255)); - } -}