using UnityEngine;
namespace Vanguard.Board3D
{
/// Колода, дроп или душа: стопка карт с подписью и коллайдером.
public sealed class Pile3D : MonoBehaviour
{
private PlaymatLayoutConfig _config;
private readonly GameObject[] _layers = new GameObject[3];
private MeshRenderer _top;
private MaterialPropertyBlock _block;
private TextMesh _label;
private int _count;
public BoardZone Zone { get; private set; }
public int Player { get; private set; }
public BoardCardRef Ref => BoardCardRef.Pile(Zone, Player, _count);
public void SetPlayer(int player)
{
Player = player;
}
public static Pile3D Create(
Transform parent,
PlaymatLayoutConfig config,
BoardZone zone,
int player,
Vector3 position,
string title,
Color accent)
{
var go = new GameObject("Pile " + zone);
go.transform.SetParent(parent, false);
go.transform.localPosition = position;
var pile = go.AddComponent();
pile.Zone = zone;
pile.Player = player;
pile._config = config;
pile._block = new MaterialPropertyBlock();
pile.Build(title, accent, config);
return pile;
}
private void Build(string title, Color accent, PlaymatLayoutConfig config)
{
var width = config.cardWidth;
var height = config.cardHeight;
var thickness = Mathf.Max(0.006f, config.cardThickness * 1.2f);
for (var i = 0; i < _layers.Length; i++)
{
var layer = GameObject.CreatePrimitive(PrimitiveType.Cube);
layer.name = "Layer " + i;
RemoveCollider(layer);
layer.transform.SetParent(transform, false);
layer.transform.localPosition = new Vector3(0f, i * thickness, 0f);
layer.transform.localScale = new Vector3(width, thickness, height);
var renderer = layer.GetComponent();
renderer.sharedMaterial = Zone == BoardZone.Soul
? BoardMaterials.CreateUnlit(null, accent)
: BoardMaterials.Back;
BoardMaterials.SetShadows(renderer, true);
_layers[i] = layer;
}
var topGo = new GameObject("Top");
topGo.transform.SetParent(transform, false);
var topFilter = topGo.AddComponent();
topFilter.sharedMesh = BoardMeshLibrary.CardFace(width, height, front: true);
_top = topGo.AddComponent();
_top.sharedMaterial = BoardMaterials.White;
BoardMaterials.SetShadows(_top, false);
if (Zone != BoardZone.Soul)
{
_label = BoardText.Create(
transform,
title,
0.05f,
new Color(0.86f, 0.90f, 1f),
new Vector3(0f, 0.02f, -(height * 0.78f)));
}
var collider = gameObject.AddComponent();
collider.size = new Vector3(width * 1.06f, 0.16f, height * 1.06f);
collider.center = new Vector3(0f, 0.08f, 0f);
}
public void SetCount(int count, Texture2D topTexture, string title, Color accent)
{
_count = count;
var safe = Mathf.Max(0, count);
var layers = safe <= 0 ? 1 : safe < 5 ? 1 : safe < 20 ? 2 : 3;
if (Zone == BoardZone.Soul)
layers = safe < 10 ? 1 : 2;
var thickness = Mathf.Max(0.006f, _config.cardThickness * 1.2f);
for (var i = 0; i < _layers.Length; i++)
_layers[i].SetActive(i < layers);
_top.transform.localPosition = new Vector3(
0f,
((layers - 0.5f) * thickness) + 0.0015f,
0f);
if (topTexture != null)
{
_top.GetPropertyBlock(_block);
_block.Clear();
BoardMaterials.SetTexture(_block, _top.sharedMaterial, topTexture);
BoardMaterials.SetColor(_block, _top.sharedMaterial, Color.white);
_top.SetPropertyBlock(_block);
}
else
{
_top.GetPropertyBlock(_block);
_block.Clear();
if (Zone == BoardZone.Soul)
{
BoardMaterials.SetTexture(_block, _top.sharedMaterial, BoardTextures.White);
BoardMaterials.SetColor(_block, _top.sharedMaterial, accent);
}
else
{
BoardMaterials.SetTexture(_block, _top.sharedMaterial, BoardTextures.Back);
BoardMaterials.SetColor(_block, _top.sharedMaterial, Color.white);
}
_top.SetPropertyBlock(_block);
}
BoardText.SetText(_label, title);
}
private static void RemoveCollider(GameObject target)
{
var collider = target.GetComponent();
if (collider == null)
return;
if (Application.isPlaying)
Destroy(collider);
else
DestroyImmediate(collider);
}
}
}