Files
A-Fairytale-Gone-Bad-Briar-…/Assets/Scripts/UI/Menus/Components/SaveSlotUI.cs

171 lines
4.9 KiB
C#

using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace BriarQueen.UI.Menus.Components
{
/// <summary>
/// Save Slot UI:
/// - No Load button.
/// - Slot itself is clickable:
/// - Filled => click loads
/// - Empty => click creates (via SelectSaveWindow opening NewSaveWindow)
/// - Delete button remains for filled saves.
/// </summary>
public class SaveSlotUI : MonoBehaviour
{
[Header("Clickable Root")]
[SerializeField]
private Button _slotButton;
[Header("Labels")]
[SerializeField]
private TextMeshProUGUI _saveNameText;
[SerializeField]
private TextMeshProUGUI _saveDateText;
[Header("Delete")]
[SerializeField]
private Button _deleteButton;
[Header("Empty Visual")]
[SerializeField]
private Image _emptyImage;
private Action<SaveFileInfo> _onDeleteClick;
private Action _onEmptyClick;
private Action<SaveFileInfo> _onFilledClick;
public SaveFileInfo SaveInfo { get; private set; }
public bool IsEmpty { get; private set; }
private void Awake()
{
if (_slotButton != null)
{
_slotButton.onClick.RemoveAllListeners();
_slotButton.onClick.AddListener(HandleSlotClicked);
}
if (_deleteButton != null)
{
_deleteButton.onClick.RemoveAllListeners();
_deleteButton.onClick.AddListener(HandleDeleteClicked);
}
}
private void OnDestroy()
{
if (_slotButton != null) _slotButton.onClick.RemoveAllListeners();
if (_deleteButton != null) _deleteButton.onClick.RemoveAllListeners();
}
public GameObject GetSelectableGameObject()
{
return _slotButton != null ? _slotButton.gameObject : gameObject;
}
public void SetFilled(
SaveFileInfo saveInfo,
Action<SaveFileInfo> onClickFilled,
Action<SaveFileInfo> onDelete)
{
SaveInfo = saveInfo;
IsEmpty = false;
_onFilledClick = onClickFilled;
_onEmptyClick = null;
_onDeleteClick = onDelete;
if (_emptyImage != null) _emptyImage.gameObject.SetActive(false);
if (_saveNameText != null)
{
_saveNameText.gameObject.SetActive(true);
_saveNameText.text = saveInfo.FileName;
}
if (_saveDateText != null)
{
_saveDateText.gameObject.SetActive(true);
_saveDateText.text = saveInfo.LastModified.ToString("g");
}
if (_deleteButton != null)
{
_deleteButton.gameObject.SetActive(true);
_deleteButton.interactable = true;
}
if (_slotButton != null)
_slotButton.interactable = true;
}
public void SetEmpty(Action onClickEmpty)
{
SaveInfo = default;
IsEmpty = true;
_onFilledClick = null;
_onEmptyClick = onClickEmpty;
_onDeleteClick = null;
if (_saveNameText != null) _saveNameText.text = string.Empty;
if (_saveDateText != null) _saveDateText.text = string.Empty;
if (_emptyImage != null) _emptyImage.gameObject.SetActive(true);
if (_deleteButton != null)
{
_deleteButton.gameObject.SetActive(false);
_deleteButton.interactable = false;
}
if (_slotButton != null)
_slotButton.interactable = true; // empty slot is still clickable
}
public void SetInteractable(bool interactable)
{
// Slot click should still work even when empty; we fully disable during "busy" only.
if (_slotButton != null)
_slotButton.interactable = interactable;
// Delete only for filled saves.
if (_deleteButton != null)
_deleteButton.interactable = interactable && !IsEmpty;
}
private void HandleSlotClicked()
{
if (IsEmpty)
_onEmptyClick?.Invoke();
else if (!string.IsNullOrWhiteSpace(SaveInfo.FileName))
_onFilledClick?.Invoke(SaveInfo);
}
private void HandleDeleteClicked()
{
if (IsEmpty)
return;
if (!string.IsNullOrWhiteSpace(SaveInfo.FileName))
_onDeleteClick?.Invoke(SaveInfo);
}
}
public struct SaveFileInfo
{
public readonly string FileName;
public readonly DateTime LastModified;
public SaveFileInfo(string fileName, DateTime lastModified)
{
FileName = fileName;
LastModified = lastModified;
}
}
}