Skip to content

Commit

Permalink
Build Texture Pages during compilation (#203)
Browse files Browse the repository at this point in the history
  • Loading branch information
Miepee authored May 11, 2024
1 parent 4610a46 commit 7af336a
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 59 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
- name: Install Python packages
run: python -m pip install --upgrade pip build

- name: Generate Texture Page
run: dotnet run --project ./GenerateTexturePage/GenerateTexturePage.csproj

- name: Build YAMS-Lib into proper directory
run: dotnet publish YAMS-LIB -c Release -o am2r_yams/yams

Expand Down
19 changes: 19 additions & 0 deletions GenerateTexturePage/GenerateTexturePage.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

</PropertyGroup>
<ItemGroup>
<AssemblyAttribute Include="GenerateTexturePage.ProjectCompileDirectoryAttribute">
<_Parameter1 Condition=" '$(ProjectCompileDirectory)' == '' ">$(ProjectDir)../YAMS-LIB</_Parameter1>
<_Parameter1 Condition=" '$(ProjectCompileDirectory)' != '' ">$(ProjectCompileDirectory)</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4"/>
</ItemGroup>
</Project>
20 changes: 20 additions & 0 deletions GenerateTexturePage/PageItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Text.Json.Serialization;



namespace GenerateTexturePage;

// Needs to be synced with YAMS-LIB
public class PageItem
{
[JsonInclude]
public string Name = "";
[JsonInclude]
public ushort X;
[JsonInclude]
public ushort Y;
[JsonInclude]
public ushort Width;
[JsonInclude]
public ushort Height;
}
71 changes: 71 additions & 0 deletions GenerateTexturePage/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// See https://aka.ms/new-console-template for more information

using System.Reflection;
using System.Text.Json;
using GenerateTexturePage;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

var yamsLibDirectory = Assembly.GetExecutingAssembly()

Check warning on line 10 in GenerateTexturePage/Program.cs

View workflow job for this annotation

GitHub Actions / Build YAMS-Lib and Python Wheel

Dereference of a possibly null reference.
.GetCustomAttribute<ProjectCompileDirectoryAttribute>()
.ProjectCompileDirectory;
Console.WriteLine($"Identified YAMS-LIB directory as: {yamsLibDirectory}");

const int pageDimension = 1024;
var newTexturePage = new Image<Rgba32>(pageDimension, pageDimension);
var textureInfo = new List<PageItem>();
int lastUsedX = 0, lastUsedY = 0, currentShelfHeight = 0;

// TODO: Now that we have a seperate project for generating the pages, we should think about making this more optimized.
void AddAllSpritesFromDir(string dirPath)
{
// Recursively add sprites from subdirs
foreach (string subDir in Directory.GetDirectories(dirPath))
{
AddAllSpritesFromDir(subDir);
}

foreach (string filePath in Directory.GetFiles(dirPath))
{
string extension = new FileInfo(filePath).Extension;
if (String.IsNullOrWhiteSpace(extension) || extension == ".md" || extension == ".txt" || extension == ".gitignore" || extension == ".json")
continue;
if (filePath.EndsWith("texturepage.png"))
continue;

Image sprite = Image.Load(filePath);
currentShelfHeight = Math.Max(currentShelfHeight, sprite.Height);
if (lastUsedX + sprite.Width > pageDimension)
{
lastUsedX = 0;
lastUsedY += currentShelfHeight;
currentShelfHeight = sprite.Height + 1; // One pixel padding

if (sprite.Width > pageDimension)
{
throw new NotSupportedException($"Currently a sprite ({filePath}) is bigger than the max size of a {pageDimension} texture page!");
}
}

if (lastUsedY + sprite.Height > pageDimension) throw new NotSupportedException($"Currently all the sprites would be above a {pageDimension} texture page!");

int xCoord = lastUsedX;
int yCoord = lastUsedY;
newTexturePage.Mutate(i => i.DrawImage(sprite, new Point(xCoord, yCoord), 1));
PageItem pageItem = new PageItem();
pageItem.X = (ushort)xCoord;
pageItem.Y = (ushort)yCoord;
pageItem.Width = (ushort)sprite.Width;
pageItem.Height = (ushort)sprite.Height;
pageItem.Name = Path.GetFileNameWithoutExtension(filePath);
textureInfo.Add(pageItem);
lastUsedX += sprite.Width + 1; //One pixel padding
}
}

AddAllSpritesFromDir(yamsLibDirectory + "/sprites");
newTexturePage.SaveAsPng(yamsLibDirectory + "/sprites/texturepage.png");
File.WriteAllText(yamsLibDirectory + "/sprites/texturepageiteminfo.json", JsonSerializer.Serialize(textureInfo));

Console.WriteLine("Written texture page and texture page info.");
11 changes: 11 additions & 0 deletions GenerateTexturePage/ProjectDirAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace GenerateTexturePage;

[System.AttributeUsage(System.AttributeTargets.Assembly, Inherited = false, AllowMultiple = false)]
sealed class ProjectCompileDirectoryAttribute : System.Attribute
{
public string ProjectCompileDirectory { get; }
public ProjectCompileDirectoryAttribute(string configurationLocation)
{
this.ProjectCompileDirectory = configurationLocation;
}
}
17 changes: 17 additions & 0 deletions YAMS-LIB/PageItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Text.Json.Serialization;
namespace YAMS_LIB;

// Needs to be synced with GenerateTexturePage
public class PageItem
{
[JsonInclude]
public string Name = "";
[JsonInclude]
public ushort X;
[JsonInclude]
public ushort Y;
[JsonInclude]
public ushort Width;
[JsonInclude]
public ushort Height;
}
69 changes: 18 additions & 51 deletions YAMS-LIB/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,63 +69,30 @@ public static void Main(string am2rPath, string outputAm2rPath, string jsonPath)

// Import new Sprites
var nameToPageItemDict = new Dictionary<string, int>();
const int pageDimension = 1024;
int lastUsedX = 0, lastUsedY = 0, currentShelfHeight = 0;
var newTexturePage = new Image<Rgba32>(pageDimension, pageDimension);
UndertaleEmbeddedTexture? utTexturePage = new UndertaleEmbeddedTexture();
utTexturePage.TextureHeight = utTexturePage.TextureWidth = pageDimension;
gmData.EmbeddedTextures.Add(utTexturePage);

void AddAllSpritesFromDir(string dirPath)
{
// Recursively add sprites from subdirs
foreach (string subDir in Directory.GetDirectories(dirPath))
{
AddAllSpritesFromDir(subDir);
}

foreach (string filePath in Directory.GetFiles(dirPath))
{
string extension = new FileInfo(filePath).Extension;
if (String.IsNullOrWhiteSpace(extension) || extension == ".md" || extension == ".txt") continue;

Image sprite = Image.Load(filePath);
currentShelfHeight = Math.Max(currentShelfHeight, sprite.Height);
if (lastUsedX + sprite.Width > pageDimension)
{
lastUsedX = 0;
lastUsedY += currentShelfHeight;
currentShelfHeight = sprite.Height + 1; // One pixel padding

if (sprite.Width > pageDimension)
{
throw new NotSupportedException($"Currently a sprite ({filePath}) is bigger than the max size of a {pageDimension} texture page!");
}
}

if (lastUsedY + sprite.Height > pageDimension) throw new NotSupportedException($"Currently all the sprites would be above a {pageDimension} texture page!");

int xCoord = lastUsedX;
int yCoord = lastUsedY;
newTexturePage.Mutate(i => i.DrawImage(sprite, new Point(xCoord, yCoord), 1));
UndertaleTexturePageItem pageItem = new UndertaleTexturePageItem();
pageItem.SourceX = (ushort)xCoord;
pageItem.SourceY = (ushort)yCoord;
pageItem.SourceWidth = pageItem.TargetWidth = pageItem.BoundingWidth = (ushort)sprite.Width;
pageItem.SourceHeight = pageItem.TargetHeight = pageItem.BoundingHeight = (ushort)sprite.Height;
pageItem.TexturePage = utTexturePage;
gmData.TexturePageItems.Add(pageItem);
lastUsedX += sprite.Width + 1; //One pixel padding
nameToPageItemDict.Add(Path.GetFileNameWithoutExtension(filePath), gmData.TexturePageItems.Count - 1);
}
}

AddAllSpritesFromDir(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/sprites");
using (MemoryStream ms = new MemoryStream())
{
newTexturePage.Save(ms, PngFormat.Instance);
var texturePage = Image.Load(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/sprites/texturepage.png");
utTexturePage.TextureWidth = texturePage.Width;
utTexturePage.TextureHeight = texturePage.Height;
texturePage.Save(ms, PngFormat.Instance);
utTexturePage.TextureData = new UndertaleEmbeddedTexture.TexData { TextureBlob = ms.ToArray() };
}
gmData.EmbeddedTextures.Add(utTexturePage);

List<PageItem> pageItemInfo = JsonSerializer.Deserialize<List<PageItem>>(File.ReadAllText(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/sprites/texturepageiteminfo.json"));
foreach (var item in pageItemInfo)
{
UndertaleTexturePageItem pageItem = new UndertaleTexturePageItem();
pageItem.SourceX = item.X;
pageItem.SourceY = item.Y;
pageItem.SourceWidth = pageItem.TargetWidth = pageItem.BoundingWidth = item.Width;
pageItem.SourceHeight = pageItem.TargetHeight = pageItem.BoundingHeight = item.Height;
pageItem.TexturePage = utTexturePage;
gmData.TexturePageItems.Add(pageItem);
nameToPageItemDict.Add(item.Name, gmData.TexturePageItems.Count - 1);
}

// Replace A4 doors
{
Expand Down
21 changes: 13 additions & 8 deletions YAMS-LIB/YAMS-LIB.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@
<ItemGroup>
<ProjectReference Include="..\UndertaleModTool\UndertaleModLib\UndertaleModLib.csproj"/>
</ItemGroup>

<ItemGroup>
<Folder Include="sprites\"/>
<Content Include="sprites/**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</Content>
</ItemGroup>


<ItemGroup>
<PackageReference Include="Macross.Json.Extensions" Version="3.0.0"/>
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.4"/>
<PackageReference Include="NaturalSort.Extension" Version="4.3.0" />
</ItemGroup>


<ItemGroup>
<Content Include="sprites\texturepageiteminfo.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</Content>
<Content Include="sprites\texturepage.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
</Content>
</ItemGroup>

</Project>
2 changes: 2 additions & 0 deletions YAMS-LIB/sprites/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
texturepage.png
texturepageiteminfo.json
6 changes: 6 additions & 0 deletions YAMS.sln
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YAMS-LIB", "YAMS-LIB\YAMS-L
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YAMS-CLI", "YAMS-CLI\YAMS-CLI.csproj", "{FA35C27E-C6AB-4CCF-912E-17452EE393D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenerateTexturePage", "GenerateTexturePage\GenerateTexturePage.csproj", "{CAB600BD-1104-40A4-852F-93BB4BBD5178}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -24,5 +26,9 @@ Global
{FA35C27E-C6AB-4CCF-912E-17452EE393D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA35C27E-C6AB-4CCF-912E-17452EE393D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA35C27E-C6AB-4CCF-912E-17452EE393D7}.Release|Any CPU.Build.0 = Release|Any CPU
{CAB600BD-1104-40A4-852F-93BB4BBD5178}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CAB600BD-1104-40A4-852F-93BB4BBD5178}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CAB600BD-1104-40A4-852F-93BB4BBD5178}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CAB600BD-1104-40A4-852F-93BB4BBD5178}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

0 comments on commit 7af336a

Please sign in to comment.