using System; using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UnityEngine; namespace DDD { public class UiState : SerializedScriptableObject, IEventHandler, IEventHandler { private readonly Dictionary _uis = new(); private readonly Dictionary _popupUis = new(); private readonly Stack _popupUiStack = new(); private InputActionMaps _previousActionMap = InputActionMaps.None; private UiData _uiData => GameData.Instance.UiData; public void OnEnable() { EventBus.Register(this); EventBus.Register(this); _uis.Clear(); _popupUis.Clear(); _popupUiStack.Clear(); } private void OnDisable() { EventBus.Unregister(this); EventBus.Unregister(this); } public void RegisterUI(BaseUi ui) { var type = ui.GetType(); _uis.TryAdd(type, ui); } public void UnregisterUI(BaseUi ui) { var type = ui.GetType(); if (_uis.TryGetValue(type, out var registered) && registered == ui) { _uis.Remove(type); } } 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 bool HasMatchingPopupUis(GameFlowState flowState) { return _uiData.FlowToUiMapping.Any(keyValuePair => (keyValuePair.Key & flowState) != 0); } public void CreateUi(BaseUi ui, Transform parent) { if (_uis.TryGetValue(ui.GetType(), out var registered) && registered == ui) return; var instance = Instantiate(ui, parent); instance.name = ui.name; instance.CreateInitialize(); } public void DestroyUi(BaseUi ui) { if (_uis.TryGetValue(ui.GetType(), out var registered) && registered == ui) return; Destroy(ui.gameObject); } 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); } } } }