VanguardReMaster/client/Assets/Vanguard/Runtime/Board3D/View/Pile3D.cs

150 lines
5.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
namespace Vanguard.Board3D
{
/// <summary>Колода, дроп или душа: стопка карт с подписью и коллайдером.</summary>
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<Pile3D>();
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<MeshRenderer>();
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<MeshFilter>();
topFilter.sharedMesh = BoardMeshLibrary.CardFace(width, height, front: true);
_top = topGo.AddComponent<MeshRenderer>();
_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<BoxCollider>();
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<Collider>();
if (collider == null)
return;
if (Application.isPlaying)
Destroy(collider);
else
DestroyImmediate(collider);
}
}
}