201 lines
5.6 KiB
C#
201 lines
5.6 KiB
C#
//
|
|
// This file is part of the Tremble package by Tiny Goose.
|
|
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
|
//
|
|
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace TinyGoose.Tremble
|
|
{
|
|
public static class TextureUtil
|
|
{
|
|
public static Texture2D GenerateColourTexture(Color32 colour)
|
|
{
|
|
int size = TrembleSyncSettings.Get().MaterialExportSize.ToIntSize();
|
|
int sizeSqr = size * size;
|
|
|
|
Texture2D texture = new(size, size);
|
|
|
|
if (s_ColourBuffer == null || s_ColourBuffer.Length != sizeSqr)
|
|
{
|
|
s_ColourBuffer = new Color32[sizeSqr];
|
|
}
|
|
|
|
for (int i = 0; i < sizeSqr; i++)
|
|
{
|
|
s_ColourBuffer[i] = colour;
|
|
s_ColourBuffer[i].a = 0xFF;
|
|
}
|
|
|
|
texture.SetPixels32(s_ColourBuffer);
|
|
return texture;
|
|
}
|
|
|
|
public static Texture2D GenerateCheckerTexture(int checkerSize = 64) => GenerateCheckerTexture(Color.black, Color.white, checkerSize);
|
|
|
|
public static Texture2D GenerateCheckerTexture(Color32 colour1, Color32 colour2, int checkerSize = 64)
|
|
{
|
|
int size = TrembleSyncSettings.Get().MaterialExportSize.ToIntSize();
|
|
|
|
Texture2D texture = new(size, size);
|
|
texture.SetPixels32(GenerateCheckerColours(size, colour1, colour2, checkerSize));
|
|
return texture;
|
|
}
|
|
|
|
public static Texture2D GenerateClipTexture(Color32 colour1, Color32 colour2, Color32 clipText, int checkerSize = 64)
|
|
{
|
|
int size = TrembleSyncSettings.Get().MaterialExportSize.ToIntSize();
|
|
|
|
Texture2D texture = new(size, size);
|
|
Color32[] image = GenerateCheckerColours(size, colour1, colour2, checkerSize);
|
|
ApplyClipTexture(image, size, clipText, checkerSize);
|
|
texture.SetPixels32(image);
|
|
|
|
return texture;
|
|
}
|
|
|
|
public static Texture2D GenerateSkipTexture(Color32 colour1, Color32 colour2, Color32 clipText, int checkerSize = 64)
|
|
{
|
|
int size = TrembleSyncSettings.Get().MaterialExportSize.ToIntSize();
|
|
|
|
Texture2D texture = new(size, size);
|
|
Color32[] image = GenerateCheckerColours(size, colour1, colour2, checkerSize);
|
|
ApplySkipTexture(image, size, clipText, checkerSize);
|
|
texture.SetPixels32(image);
|
|
|
|
return texture;
|
|
}
|
|
|
|
private static Color32[] s_ColourBuffer;
|
|
|
|
private static Color32[] GenerateCheckerColours(int size, Color32 colour1, Color32 colour2, int checkerSize = 64)
|
|
{
|
|
int sizeSqr = size * size;
|
|
|
|
if (s_ColourBuffer == null || s_ColourBuffer.Length != sizeSqr)
|
|
{
|
|
s_ColourBuffer = new Color32[sizeSqr];
|
|
}
|
|
|
|
for (int x = 0; x < size; x++)
|
|
{
|
|
for (int y = 0; y < size; y++)
|
|
{
|
|
int xCoord = x / checkerSize;
|
|
int yCoord = y / checkerSize;
|
|
|
|
if ((xCoord + yCoord) % 2 == 0)
|
|
{
|
|
s_ColourBuffer[y * size + x] = colour1;
|
|
}
|
|
else
|
|
{
|
|
s_ColourBuffer[y * size + x] = colour2;
|
|
}
|
|
|
|
s_ColourBuffer[y * size + x].a = 0xFF;
|
|
}
|
|
}
|
|
|
|
return s_ColourBuffer;
|
|
}
|
|
|
|
// Cheeky clip texture
|
|
private const char _ = ' ';
|
|
|
|
private static readonly string[] s_ClipTexture =
|
|
{
|
|
"", "", // 2-line space
|
|
_ + "/--" + _ + "| " + _ + "|" + _ + "/-|" + _ + _ + _,
|
|
_ + "| " + _ + "| " + _ + " " + _ + "| |" + _ + _ + _,
|
|
_ + "| " + _ + "| " + _ + "|" + _ + "+_/" + _ + _ + _,
|
|
_ + "| " + _ + "| " + _ + "|" + _ + "| " + _ + _ + _,
|
|
_ + "|__" + _ + "|__" + _ + "|" + _ + "| " + _ + _ + _,
|
|
"", // 1-line space
|
|
};
|
|
|
|
private static readonly string[] s_SkipTexture =
|
|
{
|
|
"", "", // 2-line space
|
|
_ + "/--" + _ + "| |" + _ + "|" + _ + "/-|" + _ + _ + _,
|
|
_ + "| " + _ + "| /" + _ + " " + _ + "| |" + _ + _ + _,
|
|
_ + "---" + _ + "|/ " + _ + "|" + _ + "+-/" + _ + _ + _,
|
|
_ + " |" + _ + "|+ " + _ + "|" + _ + "| " + _ + _ + _,
|
|
_ + "--+" + _ + "| +" + _ + "|" + _ + "| " + _ + _ + _,
|
|
"", // 1-line space
|
|
};
|
|
|
|
private static void ApplyClipTexture(Color32[] image, int size, Color32 textColour, int checkerSize = 64)
|
|
=> ApplyWordTexture(image, s_ClipTexture, size, textColour, checkerSize);
|
|
|
|
private static void ApplySkipTexture(Color32[] image, int size, Color32 textColour, int checkerSize = 64)
|
|
=> ApplyWordTexture(image, s_SkipTexture, size, textColour, checkerSize);
|
|
|
|
private static void ApplyWordTexture(Color32[] image, string[] wordTexture, int size, Color32 textColour, int checkerSize = 64)
|
|
{
|
|
int clipWidth = 16;
|
|
float clipScale = (float)size / (float)checkerSize;
|
|
|
|
for (int x = 0; x < size; x++)
|
|
{
|
|
for (int y = 0; y < size; y++)
|
|
{
|
|
// Offset every other row
|
|
int offset = ((y / checkerSize) & 1) == 0 ? 0 : checkerSize;
|
|
|
|
// Scale the text
|
|
int scaledX = (int)((x + offset) / clipScale);
|
|
int scaledY = (int)(y / clipScale);
|
|
|
|
// Flip rows (textures, amirite?!)
|
|
int row = size - scaledY - 1;
|
|
|
|
// Pull the pixel data from the array
|
|
string wordRow = wordTexture[row % wordTexture.Length];
|
|
char wordValue = wordRow.Length > 0 ? wordRow[scaledX % clipWidth] : _;
|
|
|
|
if (wordValue != _)
|
|
{
|
|
// Write pixel if it's on
|
|
image[y * size + x] = textColour;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Account for weird custom choices for main texture names
|
|
private static readonly int[] LIKELY_MAIN_TEXTURE_IDS =
|
|
{
|
|
Shader.PropertyToID("_BaseColor"),
|
|
Shader.PropertyToID("_Color"),
|
|
Shader.PropertyToID("_maintex"),
|
|
Shader.PropertyToID("_Maintex"),
|
|
};
|
|
public static bool TryGetMainTex(this Material material, out Texture2D mainTexture)
|
|
{
|
|
if (!material)
|
|
{
|
|
mainTexture = null;
|
|
return false;
|
|
}
|
|
|
|
// First check for _MainTex or [MainTexture]
|
|
mainTexture = material.mainTexture as Texture2D;
|
|
|
|
if (!mainTexture)
|
|
{
|
|
foreach (int name in LIKELY_MAIN_TEXTURE_IDS)
|
|
{
|
|
if (!material.HasTexture(name))
|
|
continue;
|
|
|
|
mainTexture = material.GetTexture(name) as Texture2D;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return mainTexture;
|
|
}
|
|
}
|
|
} |