Skip to content
This repository has been archived by the owner on Nov 25, 2024. It is now read-only.

Commit

Permalink
-update atlas system to support sources from multiple files
Browse files Browse the repository at this point in the history
-update asset builder pipeline to be part of .csproj
  • Loading branch information
Cassunshine committed Jan 17, 2024
1 parent a6a9c04 commit cfa6a24
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 119 deletions.
27 changes: 17 additions & 10 deletions AssetBuilder/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,38 @@
using System.IO.Compression;
using Tomlyn;

string[] outputDirectories = {
"Release",
"Debug"
};
string[] outputDirectories = {"Release", "Debug"};

var buildSettings = Toml.ToModel(File.ReadAllText("build_settings.toml"));

Console.WriteLine($"Packing files...");

if (!buildSettings.TryGetValue("input_folder", out object? value) || value is not string inPath)
return;
if (!buildSettings.TryGetValue("output_folder", out value) || value is not string outPath)
return;

foreach (string directory in outputDirectories) {
inPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), inPath));
outPath = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), outPath));

var outDir = Path.Combine(outPath, directory);
Console.WriteLine($"Folders are {inPath} and {outPath}");

foreach (string directory in outputDirectories) {
var outDir = Path.GetFullPath(Path.Combine(outPath, directory));

if(!Directory.Exists(outDir))
if (!Directory.Exists(outDir)) {
Console.WriteLine($"Directory {outDir} doesn't exist.");
continue;

}

foreach (string s in Directory.EnumerateDirectories(outDir)) {
var finalPath = Path.Combine(s, Path.GetFileNameWithoutExtension(inPath) + ".zip");

finalPath = Path.GetFullPath(finalPath);

if (File.Exists(finalPath))
File.Delete(finalPath);

ZipFile.CreateFromDirectory(inPath, finalPath);
Console.WriteLine($"Packed files from {inPath} to {finalPath}");
}
}
4 changes: 2 additions & 2 deletions AssetBuilder/build_settings.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
input_folder = "../../../../Client/Content"
output_folder = "../../../../Client/bin"
input_folder = "../Client/Content"
output_folder = "../Client/bin"
61 changes: 33 additions & 28 deletions Client/Client.csproj
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<RollForward>Major</RollForward>
<PublishReadyToRun>false</PublishReadyToRun>
<RootNamespace>Voxel.Client</RootNamespace>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>CLIENT</DefineConstants>
<LangVersion>11</LangVersion>
</PropertyGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<RollForward>Major</RollForward>
<PublishReadyToRun>false</PublishReadyToRun>
<RootNamespace>Voxel.Client</RootNamespace>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>CLIENT</DefineConstants>
<LangVersion>11</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.2.7" />
<PackageReference Include="PeterO.Cbor" Version="4.5.2" />
<PackageReference Include="Tomlyn" Version="0.16.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
<PackageReference Include="NLog" Version="5.2.7"/>
<PackageReference Include="PeterO.Cbor" Version="4.5.2"/>
<PackageReference Include="Tomlyn" Version="0.16.2"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
<ProjectReference Include="..\Core\Core.csproj" />
</ItemGroup>

<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
<Message Text="Restoring dotnet tools" Importance="High" />
<Exec Command="dotnet tool restore" />
</Target>
<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj"/>
<ProjectReference Include="..\Core\Core.csproj"/>
</ItemGroup>

<!-- Builds the assets for the project-->
<Target Name="BuildAssets" BeforeTargets="BeforeBuild">
<Exec Command="dotnet run" WorkingDirectory="../AssetBuilder"/>
</Target>

<Target Name="RestoreDotnetTools" BeforeTargets="Restore">
<Message Text="Restoring dotnet tools" Importance="High"/>
<Exec Command="dotnet tool restore"/>
</Target>
</Project>
40 changes: 21 additions & 19 deletions Client/Content/textures/atlases/gui/gui.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
{
"texturePath": "gui.png",
"explicit": [
{
"name": "test",
"x": 0,
"y": 0,
"width": 128,
"height": 128
},
{
"name": "heart",
"x": 128,
"y": 0,
"width": 9,
"height": 8
}
]
}
[
{
"source": "gui.png",
"sprites": [
{
"name": "test",
"x": 0,
"y": 0,
"width": 128,
"height": 128
},
{
"name": "heart",
"x": 128,
"y": 0,
"width": 9,
"height": 8
}
]
}
]
52 changes: 27 additions & 25 deletions Client/Content/textures/atlases/main/terrain.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
{
"texturePath": "terrain.png",
"explicit": [
{
"name": "stone",
"x": 0,
"y": 0
},
{
"name": "dirt",
"x": 16,
"y": 0
},
{
"name": "grass_side",
"x": 32,
"y": 0
},
{
"name": "grass_top",
"x": 48,
"y": 0
}
]
}
[
{
"source": "terrain.png",
"sprites": [
{
"name": "stone",
"x": 0,
"y": 0
},
{
"name": "dirt",
"x": 16,
"y": 0
},
{
"name": "grass_side",
"x": 32,
"y": 0
},
{
"name": "grass_top",
"x": 48,
"y": 0
}
]
}
]
70 changes: 35 additions & 35 deletions Client/Rendering/Texture/AtlasLoader.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using GlmSharp;
Expand All @@ -8,59 +9,58 @@
namespace Voxel.Client.Rendering.Texture;

public class AtlasLoader {

private static readonly JsonSerializer Serializer = new();

public static void LoadAtlas(AssetReader reader, Atlas target, RenderSystem renderSystem) {
foreach (var (_, stream, _) in reader.LoadAll($"textures/atlases/{target.Name.ToLower()}", ".json")) {
using var sr = new StreamReader(stream);
using var jsonTextReader = new JsonTextReader(sr);

var jsonObject = Serializer.Deserialize<AtlasJson>(jsonTextReader);
var entries = Serializer.Deserialize<AtlasJsonEntry[]>(jsonTextReader);

if (jsonObject == null || jsonObject.TexturePath == null)
return;
foreach (var entry in entries) {
if (entry.Source == null)
throw new InvalidOperationException("Atlas entries must have a source file specified");

if (!renderSystem.TextureManager.TryGetTextureAndSet($"textures/atlases/{target.Name.ToLower()}/{jsonObject.TexturePath}", out var texture, out var set))
return;
if (!renderSystem.TextureManager.TryGetTextureAndSet($"textures/atlases/{target.Name.ToLower()}/{entry.Source}", out var texture, out var set))
throw new InvalidOperationException($"Texture 'textures/atlases/{target.Name.ToLower()}/{entry.Source}' not found");

if (jsonObject.Auto != null) {
var spriteCount = (ivec2)vec2.Floor(new vec2(texture.Width, texture.Height) / jsonObject.Auto.Size);
var spriteSize = new ivec2(jsonObject.Auto.Size, jsonObject.Auto.Size);
//If no sprite is specified, use the entire file as the sprite.
entry.Sprites ??= new AtlasJsonSprite[] {
new() {
X = 0,
Y = 0,
Width = (int)texture.Width,
Height = (int)texture.Height,
Name = string.Empty
}
};

for (int x = 0; x < spriteCount.x; x++)
for (int y = 0; y < spriteCount.y; y++) {
var spritePos = new ivec2(x, y) * spriteSize;
target.StitchTexture($"{target.Name.ToLower()}:{x},{y}", texture, set, spritePos, spriteSize);
foreach (var sprite in entry.Sprites) {
if (sprite.X == null || sprite.Y == null)
throw new InvalidOperationException("X and Y position of sprite must be specified!");

var finalName = sprite.Name == string.Empty ? target.Name.ToLower() : $"{target.Name.ToLower()}/{sprite.Name}";
target.StitchTexture(finalName, texture, set, new ivec2(sprite.X ?? 0, sprite.Y ?? 0), new ivec2(sprite.Width ?? 16, sprite.Height ?? 16));
}
}

if (jsonObject.Explicit != null && jsonObject.Explicit != null)
foreach (var entry in jsonObject.Explicit)
target.StitchTexture($"{target.Name.ToLower()}/{entry.Name}", texture, set, new ivec2(entry.X, entry.Y), new ivec2(entry.Width, entry.Height));
}

target.GenerateMipmaps();
renderSystem.MainCommandList.SetFramebuffer(renderSystem.GraphicsDevice.SwapchainFramebuffer);
}

private class AtlasJson {
public string? TexturePath { get; set; }

public AutoAtlas? Auto { get; set; }
public ExplicitEntry[]? Explicit { get; set; }

public class ExplicitEntry {
public string? Name { get; set; }
public int X { get; set; }
public int Y { get; set; }

public int Width { get; set; } = 16;
public int Height { get; set; } = 16;
}


private class AtlasJsonEntry {
public string? Source { get; set; }
public AtlasJsonSprite[]? Sprites { get; set; }
}

private class AutoAtlas {
public int Size { get; set; }
private class AtlasJsonSprite {
public string Name { get; set; }
public int? X { get; set; }
public int? Y { get; set; }
public int? Width { get; set; }
public int? Height { get; set; }
}
}

0 comments on commit cfa6a24

Please sign in to comment.