diff --git a/Assets/_DDD/_Scripts/GameUi/BaseUi.cs b/Assets/_DDD/_Scripts/GameUi/BaseUi.cs new file mode 100644 index 000000000..da48fc1dd --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/BaseUi.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +namespace DDD +{ + public abstract class BaseUi : MonoBehaviour + { + public virtual bool IsBlockingTime => false; + public virtual bool IsOpen => gameObject.activeSelf; + + protected virtual void Start() + { + TryRegister(); + } + + protected virtual void OnDestroy() + { + TryUnregister(); + } + + protected virtual void TryRegister() { } + protected virtual void TryUnregister() { } + + public virtual void Open() => gameObject.SetActive(true); + public virtual void Close() => gameObject.SetActive(false); + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/GameUi/FadeUi.cs b/Assets/_DDD/_Scripts/GameUi/FadeUi.cs new file mode 100644 index 000000000..4469828d9 --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/FadeUi.cs @@ -0,0 +1,51 @@ +using DG.Tweening; +using UnityEngine; + +namespace DDD +{ + public class FadeUi : MonoBehaviour, IEventHandler, IEventHandler + { + private CanvasGroup _canvasGroup; + + private void Awake() + { + _canvasGroup = GetComponent(); + + _canvasGroup.alpha = 0f; + _canvasGroup.gameObject.SetActive(false); + + EventBus.Register(this); + EventBus.Register(this); + } + + private void OnDestroy() + { + EventBus.Unregister(this); + EventBus.Unregister(this); + } + + public async void Invoke(FadeInEvent evt) + { + await _canvasGroup.DOFade(0f, evt.Duration) + .SetUpdate(true) + .AsyncWaitForCompletion(); + + _canvasGroup.blocksRaycasts = false; + _canvasGroup.gameObject.SetActive(false); + + evt.CompletionSource.SetResult(true); + } + + public async void Invoke(FadeOutEvent evt) + { + _canvasGroup.gameObject.SetActive(true); + _canvasGroup.blocksRaycasts = true; + + await _canvasGroup.DOFade(1f, evt.Duration) + .SetUpdate(true) + .AsyncWaitForCompletion(); + + evt.CompletionSource.SetResult(true); + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/GameUi/GlobalMessageUi.cs b/Assets/_DDD/_Scripts/GameUi/GlobalMessageUi.cs new file mode 100644 index 000000000..7d08b9621 --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/GlobalMessageUi.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using DG.Tweening; +using TMPro; +using UnityEngine; + +namespace DDD +{ + public class GlobalMessageUi : BaseUi, IEventHandler + { + private CanvasGroup _canvasGroup; + private TextMeshProUGUI _messageText; + private Tween _fadeTween; + + private readonly Queue _messageQueue = new(); + private bool _isDisplayingMessage = false; + + private void Awake() + { + _canvasGroup = GetComponent(); + _messageText = GetComponentInChildren(); + + _canvasGroup.alpha = 0; + _messageText.text = null; + + EventBus.Register(this); + } + + protected override void OnDestroy() + { + base.OnDestroy(); + + EventBus.Unregister(this); + _fadeTween?.Kill(); + } + + public void Invoke(ShowGlobalMessageEvent evt) + { + _messageQueue.Enqueue(evt); + TryDisplayNext(); + } + + private void TryDisplayNext() + { + if (_isDisplayingMessage || _messageQueue.Count == 0) return; + + var evt = _messageQueue.Dequeue(); + _isDisplayingMessage = true; + + _messageText.text = LocalizationManager.GetString(TableName.Global_Message, evt.NewMessageKey); + Open(); + + _fadeTween?.Kill(); + _fadeTween = DOTween.Sequence() + .Append(_canvasGroup.DOFade(1f, evt.FadeDuration)) + .AppendInterval(evt.ShowDuration) + .Append(_canvasGroup.DOFade(0f, evt.FadeDuration)) + .OnComplete(() => + { + Close(); + _fadeTween = null; + _isDisplayingMessage = false; + + // 다음 메시지 처리 + TryDisplayNext(); + }); + } + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/GameUi/PopupUi.cs b/Assets/_DDD/_Scripts/GameUi/PopupUi.cs new file mode 100644 index 000000000..830988d16 --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/PopupUi.cs @@ -0,0 +1,7 @@ +namespace DDD +{ + public class PopupUi : BaseUi + { + + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/GameUi/ScreenUi.cs b/Assets/_DDD/_Scripts/GameUi/ScreenUi.cs new file mode 100644 index 000000000..c4ab9b222 --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/ScreenUi.cs @@ -0,0 +1,7 @@ +namespace DDD +{ + public class ScreenUi : BaseUi + { + + } +} \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/GameUi/UiManager.cs b/Assets/_DDD/_Scripts/GameUi/UiManager.cs new file mode 100644 index 000000000..6867b93d2 --- /dev/null +++ b/Assets/_DDD/_Scripts/GameUi/UiManager.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace DDD +{ + public class UiManager : Singleton, IManager, IEventHandler, IEventHandler, + IEventHandler, IEventHandler + { + private readonly Dictionary _screenUIs = new(); + private readonly Dictionary _popupUIs = new(); + + private readonly object _uiPauseRequester = new(); + + public void PreInit() + { + EventBus.Register(this); + EventBus.Register(this); + EventBus.Register(this); + EventBus.Register(this); + } + + public Task Init() + { + return Task.CompletedTask; + } + + public void PostInit() + { + + } + + private void OnDestroy() + { + EventBus.Unregister(this); + EventBus.Unregister(this); + EventBus.Unregister(this); + EventBus.Unregister(this); + } + + public void RegisterScreenUI(ScreenUi ui) + { + var type = ui.GetType(); + _screenUIs.TryAdd(type, ui); + } + + public void UnregisterScreenUI(ScreenUi ui) + { + var type = ui.GetType(); + if (_screenUIs.TryGetValue(type, out var value) && value == ui) + { + _screenUIs.Remove(type); + } + } + + public void RegisterPopupUI(PopupUi ui) + { + var type = ui.GetType(); + _popupUIs.TryAdd(type, ui); + } + + public void UnregisterPopupUI(PopupUi ui) + { + var type = ui.GetType(); + if (_popupUIs.TryGetValue(type, out var registered) && registered == ui) + { + _popupUIs.Remove(type); + } + } + + private void CloseAllScreenUIs() + { + foreach (var screen in _screenUIs.Values) + { + if (screen.IsOpen) + { + screen.Close(); + + if (screen.IsBlockingTime) + { + EventBus.Broadcast(new TimeScaleChangeEvent(_uiPauseRequester, 1f)); + } + } + } + } + + public void Invoke(OpenScreenUiEvent evt) + { + if (_screenUIs.TryGetValue(evt.UiType, out var screen)) + { + CloseAllScreenUIs(); + screen.Open(); + + if (screen.IsBlockingTime) + { + EventBus.Broadcast(new TimeScaleChangeEvent(screen, 0f)); + } + } + } + + public void Invoke(CloseScreenUiEvent evt) + { + if (_screenUIs.TryGetValue(evt.UiType, out var screen)) + { + screen.Close(); + + if (screen.IsBlockingTime) + { + EventBus.Broadcast(new TimeScaleChangeEvent(screen, 1f)); + } + } + } + + public void Invoke(OpenPopupUiEvent evt) + { + if (_popupUIs.TryGetValue(evt.UiType, out var popup)) + { + popup.Open(); + + if (popup.IsBlockingTime) + { + EventBus.Broadcast(new TimeScaleChangeEvent(popup, 0f)); + } + } + } + + public void Invoke(ClosePopupUiEvent evt) + { + if (_screenUIs.TryGetValue(evt.UiType, out var popUp)) + { + popUp.Close(); + + if (popUp.IsBlockingTime) + { + EventBus.Broadcast(new TimeScaleChangeEvent(popUp, 1f)); + } + } + } + } +} \ No newline at end of file