using System.Collections.Generic;
using UnityEngine;
namespace Vanguard.UI
{
///
/// Процедурные карточные текстуры без внешних артов: цвет клана,
/// градиент, рубашка. Позже заменяется Addressables-артом.
///
public static class CardArt
{
private static readonly Dictionary Cache =
new Dictionary();
private static Sprite _back;
public static Color ClanColor(string clan) => clan switch
{
"RoyalPaladin" => new Color(0.20f, 0.40f, 0.78f),
"OracleThinkTank" => new Color(0.72f, 0.58f, 0.22f),
"Kagero" => new Color(0.68f, 0.18f, 0.18f),
"Nubatama" => new Color(0.38f, 0.22f, 0.62f),
"Tachikaze" => new Color(0.22f, 0.56f, 0.34f),
"NovaGrappler" => new Color(0.78f, 0.40f, 0.16f),
"SpikeBrothers" => new Color(0.52f, 0.34f, 0.20f),
"DarkIrregulars" => new Color(0.30f, 0.18f, 0.38f),
"Granblue" => new Color(0.16f, 0.46f, 0.54f),
"Megacolony" => new Color(0.40f, 0.48f, 0.18f),
_ => new Color(0.28f, 0.34f, 0.46f),
};
public static Sprite ForClan(string clan)
{
var key = "clan:" + clan;
if (Cache.TryGetValue(key, out var sprite))
return sprite;
var color = ClanColor(clan);
sprite = Gradient(
Color.Lerp(color, Color.black, 0.55f),
Color.Lerp(color, Color.white, 0.18f),
accent: Color.Lerp(color, Color.white, 0.35f),
variant: 0);
Cache[key] = sprite;
return sprite;
}
public static Sprite ForCard(string nameId, string clan)
{
var key = "card:" + nameId;
if (Cache.TryGetValue(key, out var sprite))
return sprite;
var color = ClanColor(clan);
var hash = StableHash(nameId ?? string.Empty);
var accent = Color.HSVToRGB(
(hash % 360) / 360f,
0.62f,
0.98f);
sprite = Gradient(
Color.Lerp(color, Color.black, 0.58f),
Color.Lerp(color, Color.white, 0.16f),
accent,
(int)(hash % 5));
Cache[key] = sprite;
return sprite;
}
private static uint StableHash(string value)
{
var hash = 2166136261u;
foreach (var ch in value)
{
hash ^= ch;
hash *= 16777619u;
}
return hash;
}
public static Sprite Back
{
get
{
if (_back != null)
return _back;
_back = BackTexture();
return _back;
}
}
private static Sprite Gradient(Color bottom, Color top, Color accent, int variant)
{
const int width = 32;
const int height = 48;
var texture = new Texture2D(width, height, TextureFormat.RGBA32, false)
{
filterMode = FilterMode.Bilinear,
wrapMode = TextureWrapMode.Clamp,
};
var pixels = new Color[width * height];
for (var y = 0; y < height; y++)
{
var t = y / (float)(height - 1);
var row = Color.Lerp(bottom, top, t);
for (var x = 0; x < width; x++)
{
var stripe = ((x + y + variant * 3) % 11) < 2 ? 0.12f : 0f;
var glow = Mathf.Clamp01(1f - Mathf.Abs(x - width * 0.5f) / (width * 0.5f)) * 0.12f;
var cx = x - width * 0.5f;
var cy = y - height * 0.38f;
var radius = 6f + variant;
var sigil = Mathf.Abs(cx) + Mathf.Abs(cy) < radius ? 0.22f : 0f;
if (variant == 2 && Mathf.Abs(cx) < 2f && Mathf.Abs(cy) < 9f)
sigil += 0.18f;
pixels[y * width + x] = Color.Lerp(row, accent, Mathf.Clamp01(stripe + glow + sigil));
}
}
texture.SetPixels(pixels);
texture.Apply();
return Sprite.Create(
texture,
new Rect(0f, 0f, width, height),
new Vector2(0.5f, 0.5f),
100f);
}
private static Sprite BackTexture()
{
const int width = 32;
const int height = 48;
var texture = new Texture2D(width, height, TextureFormat.RGBA32, false)
{
filterMode = FilterMode.Point,
wrapMode = TextureWrapMode.Clamp,
};
var pixels = new Color[width * height];
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var border = x == 0 || y == 0 || x == width - 1 || y == height - 1;
var diamond = (x + y) % 8 == 0 || (x - y + 64) % 8 == 0;
pixels[y * width + x] = border
? new Color(0.42f, 0.56f, 0.82f)
: diamond
? new Color(0.12f, 0.22f, 0.42f)
: new Color(0.05f, 0.09f, 0.17f);
}
}
texture.SetPixels(pixels);
texture.Apply();
return Sprite.Create(
texture,
new Rect(0f, 0f, width, height),
new Vector2(0.5f, 0.5f),
100f);
}
}
}