292 lines
11 KiB
C#
292 lines
11 KiB
C#
using JetBrains.Annotations;
|
|
using NEG.UI.Area;
|
|
using NEG.UI.Popup;
|
|
using NEG.UI.Window;
|
|
using NegUtils.NEG.UI;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using NegUtils;
|
|
using UnityEngine.Pool;
|
|
using Debug = UnityEngine.Debug;
|
|
|
|
namespace NEG.UI
|
|
{
|
|
[PublicAPI]
|
|
public abstract class UiManager<TWindow, TPopup> : IDisposable, IPopupsHandler where TWindow : Enum where TPopup : Enum
|
|
{
|
|
public static UiManager<TWindow, TPopup> Instance { get; protected set; }
|
|
|
|
/// <summary>
|
|
/// Current area shown on screen.
|
|
/// </summary>
|
|
public IArea CurrentArea
|
|
{
|
|
get => currentArea;
|
|
set
|
|
{
|
|
currentArea?.Close();
|
|
|
|
currentArea = value;
|
|
|
|
currentArea?.Open();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Current window that is considered main (focused, lastly opened). Can be null.
|
|
/// </summary>
|
|
// public IWindow CurrentMainWindow => mainWindows.LastOrDefault();
|
|
|
|
// public PopupData CurrentPopup => currentShownPopup.Data;
|
|
|
|
private IArea currentArea;
|
|
private PopupDataExtended currentShownPopupData;
|
|
private IPopup currentShownPopup;
|
|
|
|
private readonly List<PopupDataExtended> popupsToShow = new();
|
|
|
|
protected abstract string OkLocalizationKey { get; }
|
|
protected abstract string YesLocalizationKey { get; }
|
|
protected abstract string NoLocalizationKey { get; }
|
|
|
|
protected abstract TPopup DefaultPopup { get; }
|
|
|
|
protected UiManager(IArea startArea)
|
|
{
|
|
if (Instance != null)
|
|
{
|
|
Debug.LogError("Only one instance od UiManager is allowed");
|
|
return;
|
|
}
|
|
|
|
Instance = this;
|
|
IPopupsHandler.instance = this;
|
|
CurrentArea = startArea;
|
|
}
|
|
|
|
public virtual void Dispose() => Instance = null;
|
|
|
|
#region Popups
|
|
|
|
private Dictionary<TPopup, IPopup> registeredPopups = new();
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="title">popup title key</param>
|
|
/// <param name="content">popup content key</param>
|
|
/// <param name="okText">text to show on ok button, empty for localized "Ok"</param>
|
|
/// <param name="okPressed">additional action on ok pressed</param>
|
|
/// <param name="priority">priority of popup (lower number -> show first)</param>
|
|
/// <param name="forceShow">force show current popup only if currently shown has lower priority</param>
|
|
/// <returns>data for created popup, can be used to invalidate popup (will not show)</returns>
|
|
public PopupDataHook ShowOkPopup(string title, string content, string okText = null, Action okPressed = null,
|
|
int priority = 0, bool forceShow = false)
|
|
{
|
|
var data = NativePool<DefaultPopupData>.Get();
|
|
data.Title = title;
|
|
data.Content = content;
|
|
data.Options.Add((okText ?? OkLocalizationKey, okPressed));
|
|
|
|
return ShowPopup(DefaultPopup, data, priority, forceShow);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="title">popup title key</param>
|
|
/// <param name="content">popup content key</param>
|
|
/// <param name="yesText">text to show on yes button, empty for localized "Yes"</param>
|
|
/// <param name="noText">text to show on no button, empty for localized "No"</param>
|
|
/// <param name="yesPressed">additional action on yes pressed</param>
|
|
/// <param name="noPressed">additional action on no pressed</param>
|
|
/// <param name="priority">priority of popup (lower number -> show first)</param>
|
|
/// <param name="forceShow">force show current popup only if currently shown has lower priority</param>
|
|
/// <returns>data for created popup, can be used to invalidate popup (will not show)</returns>
|
|
public PopupDataHook 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 = NativePool<DefaultPopupData>.Get();
|
|
data.Title = title;
|
|
data.Content = content;
|
|
data.Options.Add((yesText ?? YesLocalizationKey, yesPressed));
|
|
data.Options.Add((noText ?? NoLocalizationKey, noPressed));
|
|
return ShowPopup(DefaultPopup, data, priority, forceShow);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
/// <param name="title">popup title key</param>
|
|
/// <param name="content">popup content key</param>
|
|
/// <param name="actions">list of actions</param>
|
|
/// <param name="priority">priority of popup (lower number -> show first)</param>
|
|
/// <param name="forceShow">force show current popup only if currently shown has lower priority</param>
|
|
/// <returns>data for created popup, can be used to invalidate popup (will not show)</returns>
|
|
public PopupDataHook ShowPopup(string title, string content, ReadOnlySpan<(string, Action)> actions, int priority = 0, bool forceShow = false)
|
|
{
|
|
var data = NativePool<DefaultPopupData>.Get();
|
|
data.Title = title;
|
|
data.Content = content;
|
|
foreach (var action in actions)
|
|
{
|
|
data.Options.Add(action);
|
|
}
|
|
return ShowPopup(DefaultPopup, data, priority, forceShow);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Show popup if there is non other currently shown. Otherwise add current popup to ordered queue and show it later.
|
|
/// </summary>
|
|
/// <param name="popupType">popup type to show</param>
|
|
/// <param name="data">popup data object</param>
|
|
/// <param name="priority">priority of popup (lower number -> show first)</param>
|
|
/// <param name="forceShow">force show current popup only if currently shown has lower priority</param>
|
|
public PopupDataHook ShowPopup(TPopup popupType, PopupData data, int priority = 0, bool forceShow = false)
|
|
{
|
|
var dataExtended = new PopupDataExtended(priority, popupType, data);
|
|
|
|
if (forceShow)
|
|
{
|
|
if (currentShownPopupData.Data != null && currentShownPopupData.Priority >= priority)
|
|
{
|
|
EnqueuePopup(dataExtended);
|
|
return new PopupDataHook(data);
|
|
}
|
|
|
|
if (currentShownPopupData.Data != null)
|
|
EnqueuePopup(currentShownPopupData, false);
|
|
|
|
ShowPopup(dataExtended);
|
|
return new PopupDataHook(data);
|
|
}
|
|
|
|
popupsToShow.Add(dataExtended);
|
|
RefreshPopups();
|
|
return new PopupDataHook(data);
|
|
}
|
|
|
|
public void RegisterPopup(TPopup popupType, IPopup popup)
|
|
{
|
|
registeredPopups.Add(popupType, popup);
|
|
}
|
|
|
|
public void RefreshPopups()
|
|
{
|
|
for (int i = popupsToShow.Count - 1; i >= 0; i--)
|
|
{
|
|
if(!popupsToShow[i].Data.IsValid)
|
|
popupsToShow.RemoveAt(i);
|
|
}
|
|
|
|
if(currentShownPopupData.Data?.IsValid == true)
|
|
return;
|
|
|
|
ClosePopupSilently();
|
|
|
|
if (popupsToShow.Count == 0)
|
|
return;
|
|
|
|
var data = popupsToShow[0];
|
|
popupsToShow.RemoveAt(0);
|
|
ShowPopup(data);
|
|
}
|
|
|
|
private void ShowPopup(PopupDataExtended data)
|
|
{
|
|
if (currentShownPopup != null)
|
|
ClosePopupSilently();
|
|
|
|
if (!registeredPopups.TryGetValue(data.PopupType, out var popup))
|
|
{
|
|
Debug.LogError($"Popup {data.PopupType} does not exist");
|
|
data.Data.Dispose();
|
|
return;
|
|
}
|
|
|
|
popup.Show(data.Data);
|
|
currentShownPopup = popup;
|
|
currentShownPopupData = data;
|
|
}
|
|
|
|
private void ClosePopupSilently()
|
|
{
|
|
currentShownPopup?.Close(true);
|
|
currentShownPopupData = default;
|
|
currentShownPopup = null;
|
|
}
|
|
|
|
private void EnqueuePopup(PopupDataExtended data, bool asLast = true)
|
|
{
|
|
for (int i = 0; i < popupsToShow.Count; i++)
|
|
{
|
|
var popup = popupsToShow[i];
|
|
if(popup.Priority > data.Priority || (asLast && popup.Priority == data.Priority))
|
|
continue;
|
|
popupsToShow.Insert(i, data);
|
|
return;
|
|
}
|
|
popupsToShow.Add(data);
|
|
}
|
|
|
|
private readonly struct PopupDataExtended
|
|
{
|
|
public readonly int Priority;
|
|
public readonly TPopup PopupType;
|
|
public readonly PopupData Data;
|
|
|
|
public PopupDataExtended(int priority, TPopup popupType, PopupData data)
|
|
{
|
|
Priority = priority;
|
|
PopupType = popupType;
|
|
Data = data;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
public void UseBack()
|
|
{
|
|
//Remove this ugly alocation
|
|
IControllable.BackUsed backUsed = new();
|
|
|
|
//CurrentMainWindow?.TryUseBack(ref backUsed);
|
|
if(backUsed.Used)
|
|
return;
|
|
CurrentArea.TryUseBack(ref backUsed);
|
|
}
|
|
|
|
#region Windows
|
|
|
|
private Dictionary<TWindow, IWindow> registeredWindows = new();
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
// public void SetMainWindow(IWindow window) => mainWindows.Add(window);
|
|
//
|
|
// public void MainWindowClosed(IWindow window) => mainWindows.Remove(window);
|
|
//
|
|
// public void OnWindowClosed(IWindow window) => MainWindowClosed(window);
|
|
|
|
// //TODO: select new main window
|
|
// protected void PopupClosed(PopupData data)
|
|
// {
|
|
// if (currentShownPopup.data != data)
|
|
// {
|
|
// //Debug.LogError("Popup was not shown");
|
|
// return;
|
|
// }
|
|
// UpdatePopupsState(false);
|
|
// }
|
|
|
|
|
|
}
|
|
} |