ProjectDDD/Assets/_DDD/_Scripts/GameUi/PopupUi/PopupUiState.cs
2025-08-18 13:26:18 +09:00

196 lines
6.1 KiB
C#

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<OpenPopupUiEvent>, IEventHandler<ClosePopupUiEvent>
{
public Dictionary<GameFlowState, List<BasePopupUi>> FlowToPopupUiMapping = new();
[Title("디버그")]
[ReadOnly, ShowInInspector] private readonly Dictionary<Type, BasePopupUi> _popupUis = new();
[ReadOnly, ShowInInspector] private readonly Stack<BasePopupUi> _popupUiStack = new();
[ReadOnly, SerializeField] private InputActionMaps _previousActionMap = InputActionMaps.None;
private void OnDisable()
{
EventBus.Unregister<OpenPopupUiEvent>(this);
EventBus.Unregister<ClosePopupUiEvent>(this);
}
public void Initialize()
{
EventBus.Register<OpenPopupUiEvent>(this);
EventBus.Register<ClosePopupUiEvent>(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<BasePopupUi> 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);
}
}
}
}