using System; using TMPro; using UnityEngine; using UnityEngine.UI; namespace BriarQueen.UI.Menus.Components { /// /// 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. /// 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 _onDeleteClick; private Action _onEmptyClick; private Action _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 onClickFilled, Action 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; } } }