using JetBrains.Annotations; using NEG.UI.Area; using NEG.UI.Popup; using NEG.UI.Window; using System; using System.Collections.Generic; using UnityEngine; namespace NEG.UI { [PublicAPI] public abstract class UiManager { public static UiManager Instance { get; private set; } /// /// Current area shown on screen. /// public IArea CurrentArea { get => currentArea; set { currentArea?.SetEnabled(false); currentArea = value; currentArea?.SetEnabled(true); } } /// /// Current window that is considered main (focused, lastly opened). Can be null. /// public IWindow CurrentMainWindow { get; protected set; } public PopupData CurrentPopup => currentShownPopup.data; private IArea currentArea; private (PopupData data, int priority) currentShownPopup; protected IDefaultPopup currentDefaultPopup; private PriorityQueue popupsToShow = new(); //TODO: localize private string localizedYes = "Yes", localizedNo = "No", localizedOk = "Ok"; protected UiManager(IArea startArea) { if (Instance != null) { Debug.LogError("Only one instance od UiManager is allowed"); return; } Instance = this; CurrentArea = startArea; } /// /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. It will be closed after pressing ok button. /// /// popup title /// popup content /// text to show on ok button, empty for localized "Ok" /// additional action on ok pressed /// priority of popup (lower number -> show first) /// force show current popup only if currently shown has lower priority /// data for created popup, can be used to invalidate popup (will not show) public PopupData ShowOkPopup(string title, string content, string okText = null, Action okPressed = null, int priority = 0, bool forceShow = false) { var data = new DefaultPopupData(currentDefaultPopup, title, content, new List<(string, Action)>() { (okText ?? localizedOk, okPressed) }); ShowPopup(data, priority, forceShow); return data; } /// /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. It will be closed after pressing yes or no button. /// /// popup title /// popup content /// text to show on yes button, empty for localized "Yes" /// text to show on no button, empty for localized "No" /// additional action on yes pressed /// additional action on no pressed /// priority of popup (lower number -> show first) /// force show current popup only if currently shown has lower priority /// data for created popup, can be used to invalidate popup (will not show) public PopupData ShowYesNoPopup(string title, string content, string yesText = null, string noText = null, Action yesPressed = null, Action noPressed = null, int priority = 0, bool forceShow = false) { var data = new DefaultPopupData(currentDefaultPopup, title, content, new List<(string, Action)>() { (yesText ?? localizedYes, yesPressed), (noText ?? localizedNo, noPressed) }); ShowPopup(data, priority, forceShow); return data; } /// /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. It will be closed after pressing any button. /// /// popup title /// popup content /// list of actions /// priority of popup (lower number -> show first) /// force show current popup only if currently shown has lower priority /// data for created popup, can be used to invalidate popup (will not show) public PopupData ShowPopup(string title, string content, List<(string, Action)> actions, int priority = 0, bool forceShow = false) { var data = new DefaultPopupData(currentDefaultPopup, title, content, actions); ShowPopup(data, priority, forceShow); return data; } /// /// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later. /// /// popup data object /// priority of popup (lower number -> show first) /// force show current popup only if currently shown has lower priority public void ShowPopup(PopupData data, int priority = 0, bool forceShow = false) { popupsToShow.Enqueue(data, priority); UpdatePopupsState(forceShow, priority, data); } protected void PopupClosed(PopupData data) { if (currentShownPopup.data != data) { Debug.LogError("Popup was not shown"); return; } UpdatePopupsState(false); } protected void SetDefaultPopup(IDefaultPopup popup) => currentDefaultPopup = popup; private void UpdatePopupsState(bool forceShow, int priority = 0, PopupData data = null) { if (forceShow) { if(currentShownPopup.priority <= priority) return; popupsToShow.Enqueue(currentShownPopup.data, currentShownPopup.priority); ShowPopup(data, priority); return; } if(!popupsToShow.TryDequeue(out var d, out int p)) return; ShowPopup(d, p); } private void ShowPopup(PopupData data, int priority) { if (currentShownPopup.data != null) { currentShownPopup.data.PopupClosedEvent -= PopupClosed; currentShownPopup.data.Hide(); } currentShownPopup = (data, priority); data.Show(); data.PopupClosedEvent += PopupClosed; } } }