Add MrGameEng.Atlases: texture atlas builder, runtime loader and CLI tool
CI / build-test (push) Failing after 1m13s
CI / build-test (push) Failing after 1m13s
AtlasBuilder packs a directory tree of loose images into atlas pages plus JSON metadata (deterministic shelf packing, incremental rebuilds, orphan cleanup); TextureAtlas loads them back handing out Texture2DRegions, so sprites from one page batch into a single draw call. The asset handle generator maps .atlas files to TextureAtlas and skips page images. Demonstrated in the sample (Assets/Atlases + 'atlas' console command), wrapped as tools/MrGameEng.AtlasTool for build scripts. Documented dependency exception: Atlases depends on Graphics and Assets.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\MrGameEng.Atlases\MrGameEng.Atlases.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,58 @@
|
||||
using System.Diagnostics;
|
||||
using MrGameEng.Atlases;
|
||||
|
||||
if (args.Length < 2 || args.Contains("--help") || args.Contains("-h"))
|
||||
{
|
||||
Console.WriteLine(
|
||||
"""
|
||||
MrGameEng.AtlasTool — packs a directory tree of images into texture atlases.
|
||||
|
||||
Usage: MrGameEng.AtlasTool <source-dir> <output-dir> [options]
|
||||
|
||||
Options:
|
||||
--group-depth <n> directories forming one atlas (0 = single atlas; default 1)
|
||||
--page-size <n> maximum page size in pixels (default 2048)
|
||||
--padding <n> gap between images in pixels (default 2)
|
||||
--root-name <name> atlas name for files above group depth (default "Atlas")
|
||||
--force rebuild even when sources are unchanged
|
||||
""");
|
||||
return args.Length < 2 && !args.Contains("--help") && !args.Contains("-h") ? 1 : 0;
|
||||
}
|
||||
|
||||
int Option(string name, int fallback)
|
||||
{
|
||||
var index = Array.IndexOf(args, name);
|
||||
return index >= 0 && index + 1 < args.Length ? int.Parse(args[index + 1]) : fallback;
|
||||
}
|
||||
|
||||
var rootNameIndex = Array.IndexOf(args, "--root-name");
|
||||
var options = new AtlasBuildOptions
|
||||
{
|
||||
SourceDirectory = args[0],
|
||||
OutputDirectory = args[1],
|
||||
GroupDepth = Option("--group-depth", 1),
|
||||
MaxPageSize = Option("--page-size", 2048),
|
||||
Padding = Option("--padding", 2),
|
||||
RootAtlasName = rootNameIndex >= 0 && rootNameIndex + 1 < args.Length ? args[rootNameIndex + 1] : "Atlas",
|
||||
Force = args.Contains("--force"),
|
||||
};
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
var result = AtlasBuilder.Build(options);
|
||||
stopwatch.Stop();
|
||||
|
||||
foreach (var group in result.Groups)
|
||||
{
|
||||
Console.WriteLine(group.Skipped
|
||||
? $" {group.Name}: up to date ({group.RegionCount} regions, {group.PageCount} pages)"
|
||||
: $" {group.Name}: {group.RegionCount} regions -> {group.PageCount} pages");
|
||||
}
|
||||
|
||||
foreach (var orphan in result.DeletedOrphans)
|
||||
{
|
||||
Console.WriteLine($" deleted orphan {orphan}");
|
||||
}
|
||||
|
||||
var built = result.Groups.Count(g => !g.Skipped);
|
||||
Console.WriteLine($"Done: {built} atlases built, {result.Groups.Count - built} up to date, {stopwatch.Elapsed.TotalSeconds:F1}s.");
|
||||
return 0;
|
||||
Reference in New Issue
Block a user