172 lines
5.4 KiB
C#
172 lines
5.4 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;
|
|
gameObject.name = $"bt_{x}_{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)
|
|
{
|
|
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)
|
|
{
|
|
SetActiveIfChanged(contentImage.gameObject, showFlag || (showMine && !showMineAsText));
|
|
if (showFlag)
|
|
{
|
|
SetSpriteIfChanged(contentImage, config.FlagSprite);
|
|
}
|
|
else if (showMine)
|
|
{
|
|
SetSpriteIfChanged(contentImage, config.MineSprite);
|
|
}
|
|
|
|
contentImage.color = Color.white;
|
|
}
|
|
|
|
if (label != null)
|
|
{
|
|
SetActiveIfChanged(label.gameObject, showNumber || showMineAsText);
|
|
SetTextIfChanged(label, showMineAsText ? "M" : showNumber ? cell.NeighborMines.ToString() : string.Empty);
|
|
label.color = config.GetNumberTextColor(cell.NeighborMines);
|
|
}
|
|
}
|
|
|
|
private static void SetActiveIfChanged(GameObject target, bool active)
|
|
{
|
|
if (target.activeSelf != active)
|
|
{
|
|
target.SetActive(active);
|
|
}
|
|
}
|
|
|
|
private static void SetSpriteIfChanged(Image image, Sprite sprite)
|
|
{
|
|
if (image.sprite != sprite)
|
|
{
|
|
image.sprite = sprite;
|
|
}
|
|
}
|
|
|
|
private static void SetTextIfChanged(TMP_Text text, string value)
|
|
{
|
|
if (text.text != value)
|
|
{
|
|
text.text = value;
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
}
|