Kursach_StealthAction/Assets/Tremble/Utils/TextureUtil.cs
2026-10-11 19:16:11 +03:00

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;
}
}
}