196 lines
6.1 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
} |