using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Sirenix.OdinInspector; using UnityEngine; namespace DDD { [CreateAssetMenu(fileName = "PopupUiState", menuName = "GameUi/PopupUiState")] public class PopupUiState : SerializedScriptableObject, IEventHandler, IEventHandler { public Dictionary> FlowToPopupUiMapping = new(); [Title("디버그")] [ReadOnly, ShowInInspector] private readonly Dictionary _popupUis = new(); [ReadOnly, ShowInInspector] private readonly Stack _popupUiStack = new(); [ReadOnly, SerializeField] private InputActionMaps _previousActionMap = InputActionMaps.None; private void OnDisable() { EventBus.Unregister(this); EventBus.Unregister(this); } public void Initialize() { EventBus.Register(this); EventBus.Register(this); _popupUis.Clear(); _popupUiStack.Clear(); } public void RegisterPopupUI(BasePopupUi ui) { var type = ui.GetType(); _popupUis.TryAdd(type, ui); } public void UnregisterPopupUI(BasePopupUi ui) { var type = ui.GetType(); if (_popupUis.TryGetValue(type, out var registered) && registered == ui) { _popupUis.Remove(type); } } public void Invoke(OpenPopupUiEvent evt) { if (_popupUis.TryGetValue(evt.UiType, out var popup)) { if (!popup.IsOpen) { PushPopup(popup); popup.Open(evt); if (popup.IsBlockingTime) { var timeScaleChangeEvent = GameEvents.RequestTimeScaleChangeEvent; timeScaleChangeEvent.Requester = popup; timeScaleChangeEvent.NewTimeScale = 0f; EventBus.Broadcast(timeScaleChangeEvent); } } } } public void Invoke(ClosePopupUiEvent evt) { if (_popupUis.TryGetValue(evt.UiType, out var popup)) { if (popup.IsOpen) { popup.ClosePanel(); PopPopup(popup); if (popup.IsBlockingTime) { var timeScaleChangeEvent = GameEvents.RequestTimeScaleChangeEvent; timeScaleChangeEvent.Requester = popup; timeScaleChangeEvent.NewTimeScale = 1f; EventBus.Broadcast(timeScaleChangeEvent); } } } } public void CreatePopup(BasePopupUi popup, Transform parent) { if (_popupUis.TryGetValue(popup.GetType(), out var registered) && registered == popup) return; var instance = Instantiate(popup, parent); instance.name = popup.name; } public void DestroyPopup(BasePopupUi popup) { if (_popupUis.TryGetValue(popup.GetType(), out var registered) == false || registered != popup) return; Destroy(popup.gameObject); } public List GetMatchingPopupUis(GameFlowState flowState) { return FlowToPopupUiMapping .Where(keyValuePair => (keyValuePair.Key & flowState) != 0) .SelectMany(keyValuePair => keyValuePair.Value) .ToList(); } public bool HasMatchingPopupUis(GameFlowState flowState) { return FlowToPopupUiMapping.Any(keyValuePair => (keyValuePair.Key & flowState) != 0); } public void CreateMatchingPopupUis(GameFlowState flowState, Transform parent) { var matchingPopupUis = GetMatchingPopupUis(flowState); foreach (var popupUi in matchingPopupUis) { CreatePopup(popupUi, parent); } } public void DestroyMatchingPopupUis(GameFlowState flowState) { var matchingPopupUis = GetMatchingPopupUis(flowState); foreach (var popupUi in matchingPopupUis) { DestroyPopup(popupUi); } } public bool IsTopPopup(BasePopupUi popup) { return _popupUiStack.Count > 0 && _popupUiStack.Peek() == popup; } public void PushPopup(BasePopupUi popup) { if (_popupUiStack.Contains(popup)) return; if (_popupUiStack.Count == 0) { _previousActionMap = InputManager.Instance.GetCurrentActionMap(); } _popupUiStack.Push(popup); UpdatePopupCanvasGroups(); } public void PopPopup(BasePopupUi popup) { if (_popupUiStack.Count == 0) return; if (_popupUiStack.Peek() == popup) { _popupUiStack.Pop(); } else { var temp = _popupUiStack.Reverse().Where(p => p != popup).Reverse().ToList(); _popupUiStack.Clear(); foreach (var p in temp) { _popupUiStack.Push(p); } } if (_popupUiStack.TryPeek(out var topPopup) && topPopup.IsOpen) { InputManager.Instance.SwitchCurrentActionMap(topPopup.InputActionMaps); } else { InputManager.Instance.SwitchCurrentActionMap(_previousActionMap); } UpdatePopupCanvasGroups(); } private void UpdatePopupCanvasGroups() { if (_popupUiStack.Count == 0) return; foreach (var popupUi in _popupUiStack) { bool isTop = IsTopPopup(popupUi); popupUi.SetUiInteractable(isTop); } } } }