using System.Collections; using TMPro; using UnityEngine; [DisallowMultipleComponent] public class MemoryProgressPopupUI : MonoBehaviour { [Header("Panel")] [Tooltip("실제로 켜고 끌 팝업 패널입니다. 가능하면 이 스크립트는 항상 켜진 MemoryPopupController에 붙이고, 이 필드에 MemoryPopupPanel을 연결하세요.")] [SerializeField] private GameObject popupPanel; [SerializeField] private CanvasGroup popupCanvasGroup; [Tooltip("체크하면 팝업이 끝난 뒤 Popup Panel을 비활성화합니다. 단, Popup Panel이 이 스크립트 오브젝트와 같으면 자동으로 비활성화하지 않습니다.")] [SerializeField] private bool deactivatePanelAfterHide = true; [Header("Text")] [SerializeField] private TMP_Text titleText; [SerializeField] private TMP_Text countText; [SerializeField] private TMP_Text addedAmountText; [Header("Popup Visual Objects")] [Tooltip("팝업 안의 소켓 이미지입니다. 보통 항상 켜도 됩니다.")] [SerializeField] private GameObject popupCrystalSocket; [Tooltip("팝업 안의 파란 기억 조각 이미지입니다.")] [SerializeField] private GameObject popupCrystalIcon; [Tooltip("팝업 안의 정적 Glow 이미지입니다. 애니메이션 없이 ON/OFF만 합니다.")] [SerializeField] private GameObject popupGlowIcon; [Tooltip("팝업이 표시될 때 Glow를 켭니다.")] [SerializeField] private bool showPopupGlow = true; [Tooltip("체크하면 마지막 조각 획득으로 완료됐을 때만 Popup Glow를 켭니다.")] [SerializeField] private bool showPopupGlowOnlyWhenCompleted = false; [Header("Messages")] [SerializeField] private string message = "기억의 조각 획득!"; [SerializeField] private string completedMessage = "모든 기억의 조각을 모았습니다!"; [SerializeField] private bool useCompletedMessage = true; [Header("Added Amount")] [SerializeField] private string addedAmountFormat = "+{0}"; [SerializeField] private bool showCompletedTextWhenCompleted = true; [SerializeField] private string completedAddedAmountText = "완료"; [Header("Timing")] [Tooltip("팝업이 표시되는 시간입니다. 페이드 애니메이션은 제거했고, 이 시간 후 즉시 숨깁니다.")] [SerializeField] private float showTime = 1.5f; [SerializeField] private bool autoHide = true; [SerializeField] private bool useUnscaledTime = false; private Coroutine popupRoutine; private void Awake() { AutoFillReferencesIfNeeded(); HidePopup(); } private void OnDisable() { if (popupRoutine != null) { StopCoroutine(popupRoutine); popupRoutine = null; } } public void ShowPopup(int current, int max) { ShowPopupInternal(0, current, max, false); } public void ShowPieceAdded(int addedAmount, int current, int max) { if (addedAmount <= 0) return; ShowPopupInternal(addedAmount, current, max, true); } public void HidePopup() { if (popupRoutine != null) { StopCoroutine(popupRoutine); popupRoutine = null; } SetCanvasVisible(false); ApplyPopupObjects(false, false); if (ShouldDeactivatePanel() && popupPanel != null) popupPanel.SetActive(false); } private void ShowPopupInternal(int addedAmount, int current, int max, bool showAddedAmount) { AutoFillReferencesIfNeeded(); if (!gameObject.activeInHierarchy) { Debug.LogWarning("[MemoryProgressPopupUI] 스크립트 오브젝트가 비활성화되어 팝업을 표시할 수 없습니다. 항상 켜져 있는 MemoryPopupController 오브젝트에 붙이세요.", this); return; } if (popupRoutine != null) StopCoroutine(popupRoutine); ShowPopupNow(addedAmount, current, max, showAddedAmount); if (autoHide) popupRoutine = StartCoroutine(AutoHideRoutine()); } private void ShowPopupNow(int addedAmount, int current, int max, bool showAddedAmount) { bool completed = max > 0 && current >= max; if (popupPanel != null) popupPanel.SetActive(true); ApplyPopupObjects(true, completed); ApplyTexts(addedAmount, current, max, showAddedAmount, completed); SetCanvasVisible(true); } private IEnumerator AutoHideRoutine() { yield return Wait(showTime); HidePopup(); } private void ApplyTexts(int addedAmount, int current, int max, bool showAddedAmount, bool completed) { if (titleText != null) { if (completed && useCompletedMessage) titleText.text = completedMessage; else titleText.text = message; } if (countText != null) countText.text = $"{current} / {max}"; if (addedAmountText != null) { bool showText = showAddedAmount || (completed && showCompletedTextWhenCompleted); addedAmountText.gameObject.SetActive(showText); if (showText) { if (completed && showCompletedTextWhenCompleted) addedAmountText.text = completedAddedAmountText; else addedAmountText.text = SafeFormatAddedAmount(addedAmount); } } } private void ApplyPopupObjects(bool visible, bool completed) { if (popupCrystalSocket != null) popupCrystalSocket.SetActive(visible); if (popupCrystalIcon != null) popupCrystalIcon.SetActive(visible); if (popupGlowIcon != null) { bool glowVisible = visible && showPopupGlow && (!showPopupGlowOnlyWhenCompleted || completed); popupGlowIcon.SetActive(glowVisible); } } private string SafeFormatAddedAmount(int addedAmount) { try { return string.Format(addedAmountFormat, addedAmount); } catch { Debug.LogWarning("[MemoryProgressPopupUI] Added Amount Format이 잘못되어 기본 형식 '+{0}'을 사용합니다.", this); return $"+{addedAmount}"; } } private void AutoFillReferencesIfNeeded() { if (popupPanel == null) popupPanel = gameObject; if (popupCanvasGroup == null) { if (popupPanel != null) popupCanvasGroup = popupPanel.GetComponent(); if (popupCanvasGroup == null) popupCanvasGroup = GetComponent(); } } private bool ShouldDeactivatePanel() { if (!deactivatePanelAfterHide) return false; if (popupPanel == null) return false; return popupPanel != gameObject; } private void SetCanvasVisible(bool visible) { if (popupCanvasGroup == null) return; popupCanvasGroup.alpha = visible ? 1f : 0f; popupCanvasGroup.interactable = visible; popupCanvasGroup.blocksRaycasts = visible; } private IEnumerator Wait(float duration) { if (duration <= 0f) yield break; if (useUnscaledTime) yield return new WaitForSecondsRealtime(duration); else yield return new WaitForSeconds(duration); } #if UNITY_EDITOR private void OnValidate() { showTime = Mathf.Max(0f, showTime); } #endif }