Files
FreewayGamesTest/Assets/Scripts/Presentation/Views/CellView.cs
T
2026-06-07 00:30:10 +07:00

148 lines
4.8 KiB
C#

using System;
using Minesweeper.Core;
using Minesweeper.Config;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Minesweeper.Presentation.Views
{
public sealed class CellView : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler
{
[SerializeField] private Button button;
[SerializeField] private Image backgroundImage;
[SerializeField] private RectTransform contentRoot;
[SerializeField] private Image contentImage;
[SerializeField] private TMP_Text label;
private int x;
private int y;
private bool inputEnabled = true;
private bool isOpened;
public event Action<int, int> OpenRequested;
public event Action<int, int> FlagRequested;
public event Action PressStarted;
public event Action PressEnded;
public void Bind(Button button, Image backgroundImage, RectTransform contentRoot, Image contentImage, TMP_Text label)
{
this.button = button;
this.backgroundImage = backgroundImage;
this.contentRoot = contentRoot;
this.contentImage = contentImage;
this.label = label;
}
public void Initialize(int x, int y)
{
this.x = x;
this.y = y;
}
public void SetInputEnabled(bool enabled)
{
inputEnabled = enabled;
if (button != null)
{
button.interactable = enabled && !isOpened;
}
}
public void Render(BoardCellData cell, MinesweeperUiConfig config, float pixelsPerUnitMultiplier, float contentPadding, bool revealUnflaggedMines)
{
gameObject.name = $"bt_{cell.X}_{cell.Y}_{cell.DisplayValue}";
isOpened = cell.IsOpened;
var revealMine = revealUnflaggedMines && cell.IsMine && !cell.IsFlagged;
if (contentRoot != null)
{
contentRoot.offsetMin = new Vector2(contentPadding, contentPadding);
contentRoot.offsetMax = new Vector2(-contentPadding, -contentPadding);
}
if (backgroundImage != null)
{
backgroundImage.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier;
backgroundImage.color = cell.IsOpened || revealMine ? config.OpenedCellColor : config.ClosedCellColor;
}
if (contentImage != null)
{
contentImage.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier;
}
RenderContent(cell, config, revealMine);
if (button != null)
{
button.interactable = inputEnabled && !cell.IsOpened;
}
}
private void RenderContent(BoardCellData cell, MinesweeperUiConfig config, bool revealMine)
{
var showFlag = cell.IsFlagged && !cell.IsOpened;
var showMine = (cell.IsOpened && cell.IsMine) || revealMine;
var showMineAsText = showMine && config.MineSprite == null;
var showNumber = cell.IsOpened && !cell.IsMine && cell.NeighborMines > 0;
if (contentImage != null)
{
contentImage.gameObject.SetActive(showFlag || (showMine && !showMineAsText));
if (showFlag)
{
contentImage.sprite = config.FlagSprite;
}
else if (showMine)
{
contentImage.sprite = config.MineSprite;
}
contentImage.color = Color.white;
}
if (label != null)
{
label.gameObject.SetActive(showNumber || showMineAsText);
label.text = showMineAsText ? "M" : showNumber ? cell.NeighborMines.ToString() : string.Empty;
label.color = config.GetNumberTextColor(cell.NeighborMines);
}
}
public void OnPointerClick(PointerEventData eventData)
{
if (!inputEnabled)
{
return;
}
if (eventData.button == PointerEventData.InputButton.Left)
{
OpenRequested?.Invoke(x, y);
}
else if (eventData.button == PointerEventData.InputButton.Right)
{
FlagRequested?.Invoke(x, y);
}
}
public void OnPointerDown(PointerEventData eventData)
{
if (inputEnabled && eventData.button == PointerEventData.InputButton.Left)
{
PressStarted?.Invoke();
}
}
public void OnPointerUp(PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Left)
{
PressEnded?.Invoke();
}
}
}
}