Files
WhaleAdventure_VR/Assets/My project/Memory Scripts/UI/MemoryProgressPopupUI.cs
2026-06-24 17:13:40 +09:00

240 lines
7.5 KiB
C#

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<CanvasGroup>();
if (popupCanvasGroup == null)
popupCanvasGroup = GetComponent<CanvasGroup>();
}
}
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
}