Working popups
This commit is contained in:
parent
d14e2ca055
commit
7c4c98ede8
45
Debug.cs
Normal file
45
Debug.cs
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace NegUtils
|
||||
{
|
||||
public static class Debug
|
||||
{
|
||||
private const string LogDefine = "LOG_INFO";
|
||||
private const string WarningDefine = "LOG_WARNING";
|
||||
private const string ErrorDefine = "LOG_ERRORS";
|
||||
private const string AssertDefine = "UNITY_ASSERTIONS";
|
||||
private const string Editor = "UNITY_EDITOR";
|
||||
|
||||
[Conditional(LogDefine), Conditional(Editor)]
|
||||
public static void Log(object message) => UnityEngine.Debug.Log(message);
|
||||
[Conditional(LogDefine), Conditional(Editor)]
|
||||
public static void Log(object message, Object context) => UnityEngine.Debug.Log(message, context);
|
||||
|
||||
[Conditional(WarningDefine), Conditional(Editor)]
|
||||
public static void LogWarning(object message) => UnityEngine.Debug.LogWarning(message);
|
||||
[Conditional(WarningDefine), Conditional(Editor)]
|
||||
public static void LogWarning(object message, Object context) => UnityEngine.Debug.LogWarning(message, context);
|
||||
|
||||
[Conditional(ErrorDefine), Conditional(Editor)]
|
||||
public static void LogError(object message) => UnityEngine.Debug.LogError(message);
|
||||
[Conditional(ErrorDefine), Conditional(Editor)]
|
||||
public static void LogError(object message, Object context) => UnityEngine.Debug.LogError(message, context);
|
||||
|
||||
public static void LogException(Exception e) => UnityEngine.Debug.LogException(e);
|
||||
|
||||
|
||||
|
||||
[Conditional(AssertDefine)]
|
||||
public static void Assert(bool state) => UnityEngine.Debug.Assert(state);
|
||||
[Conditional(AssertDefine)]
|
||||
public static void Assert(bool state, Object context) => UnityEngine.Debug.Assert(state, context);
|
||||
[Conditional(AssertDefine)]
|
||||
public static void Assert(bool state, object message) => UnityEngine.Debug.Assert(state, message);
|
||||
[Conditional(AssertDefine)]
|
||||
public static void Assert(bool state, object message, Object context) => UnityEngine.Debug.Assert(state, message, context);
|
||||
|
||||
}
|
||||
}
|
||||
3
Debug.cs.meta
Normal file
3
Debug.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df1918e04df74ff8bc0e5aef1fce3437
|
||||
timeCreated: 1752327272
|
||||
11
NEG/UI/Abstraction.cs
Normal file
11
NEG/UI/Abstraction.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using NEG.UI.Popup;
|
||||
|
||||
namespace NegUtils.NEG.UI;
|
||||
|
||||
internal interface IPopupsHandler
|
||||
{
|
||||
internal static IPopupsHandler Instance => instance;
|
||||
protected static IPopupsHandler instance;
|
||||
|
||||
void RefreshPopups();
|
||||
}
|
||||
3
NEG/UI/Abstraction.cs.meta
Normal file
3
NEG/UI/Abstraction.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d28e117dd3d544a18cf1654c71e5bb00
|
||||
timeCreated: 1759328259
|
||||
@ -5,25 +5,14 @@ namespace NEG.UI.Popup
|
||||
{
|
||||
public class DefaultPopupData : PopupData
|
||||
{
|
||||
private readonly string content;
|
||||
private readonly IDefaultPopup defaultPopup;
|
||||
private readonly List<(string, Action)> options;
|
||||
public string Title;
|
||||
public string Content;
|
||||
public readonly List<(string, Action)> Options = new(5);
|
||||
|
||||
private readonly string title;
|
||||
|
||||
public DefaultPopupData(IDefaultPopup popup, string title, string content, List<(string, Action)> options) :
|
||||
base(popup)
|
||||
public override void OnRelease()
|
||||
{
|
||||
defaultPopup = popup;
|
||||
this.title = title;
|
||||
this.content = content;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
public override void Show()
|
||||
{
|
||||
defaultPopup.SetContent(title, content, options);
|
||||
base.Show();
|
||||
base.OnRelease();
|
||||
Options.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,54 +1,79 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.Design;
|
||||
using NEG.Utils;
|
||||
using NegUtils;
|
||||
using NegUtils.NEG.UI;
|
||||
|
||||
namespace NEG.UI.Popup
|
||||
{
|
||||
[PublicAPI]
|
||||
public class PopupData
|
||||
public struct PopupDataHook
|
||||
{
|
||||
private readonly IPopup popup;
|
||||
private uint version;
|
||||
private PopupData data;
|
||||
|
||||
/// <summary>
|
||||
/// PopupData constructor.
|
||||
/// </summary>
|
||||
/// <param name="popup">attached to this data, can be used by different data instances</param>
|
||||
public PopupData(IPopup popup)
|
||||
public bool IsValid => version == data.CurrentVersion;
|
||||
|
||||
public PopupDataHook(PopupData data)
|
||||
{
|
||||
this.popup = popup;
|
||||
IsValid = true;
|
||||
this.data = data;
|
||||
version = data.CurrentVersion;
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
if (!IsValid)
|
||||
return;
|
||||
data.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public class PopupData : IPoolable
|
||||
{
|
||||
private static readonly Dictionary<Type, Action<PopupData>> ReturnDelegates = new();
|
||||
|
||||
/// <summary>
|
||||
/// Is this data is still valid. If set to false, popup will not show.
|
||||
/// </summary>
|
||||
public bool IsValid { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event that is fired on closing popup.
|
||||
/// </summary>
|
||||
public event Action<PopupData> PopupClosedEvent
|
||||
{
|
||||
add => popup.OnPopupClosed += value;
|
||||
remove => popup.OnPopupClosed -= value;
|
||||
}
|
||||
internal uint CurrentVersion { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Show popup and pass needed data.
|
||||
/// </summary>
|
||||
public virtual void Show() => popup.Show(this);
|
||||
|
||||
/// <summary>
|
||||
/// Hide popup. Close visuals without firing events;
|
||||
/// </summary>
|
||||
public virtual void Hide() => popup.Close(true);
|
||||
|
||||
/// <summary>
|
||||
/// Invalidate popup, <see cref="UiManager" /> will automatically skip this popup
|
||||
/// </summary>
|
||||
public virtual void Invalidate()
|
||||
internal void Dispose()
|
||||
{
|
||||
IsValid = false;
|
||||
UiManager.Instance.RefreshPopups();
|
||||
IPopupsHandler.Instance.RefreshPopups();
|
||||
|
||||
var type = GetType();
|
||||
|
||||
if (!ReturnDelegates.TryGetValue(GetType(), out var returnDelegate))
|
||||
ReturnDelegates[type] = CreateReturnDelegate(type);
|
||||
|
||||
returnDelegate?.Invoke(this);
|
||||
}
|
||||
|
||||
|
||||
private static Action<PopupData> CreateReturnDelegate(Type type)
|
||||
{
|
||||
var returnMethod = typeof(NativePool<>)
|
||||
.MakeGenericType(type)
|
||||
.GetMethod(nameof(NativePool<PopupData>.Return), new[] { type });
|
||||
|
||||
return (Action<PopupData>)Delegate.CreateDelegate(
|
||||
typeof(Action<PopupData>),
|
||||
returnMethod);
|
||||
}
|
||||
|
||||
public virtual void OnGet()
|
||||
{
|
||||
IsValid = true;
|
||||
}
|
||||
|
||||
public virtual void OnRelease()
|
||||
{
|
||||
CurrentVersion++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,39 +6,17 @@ using NegUtils.NEG.UI;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using System.Runtime.CompilerServices;
|
||||
using NegUtils;
|
||||
using UnityEngine.Pool;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
namespace NEG.UI
|
||||
{
|
||||
[PublicAPI]
|
||||
public abstract class UiManager : IDisposable
|
||||
public abstract class UiManager<TWindow, TPopup> : IDisposable, IPopupsHandler where TWindow : Enum where TPopup : Enum
|
||||
{
|
||||
private IArea currentArea;
|
||||
protected IDefaultPopup currentDefaultPopup;
|
||||
private (PopupData data, int priority) currentShownPopup;
|
||||
|
||||
//TODO: localize
|
||||
private string localizedYes = "Yes", localizedNo = "No", localizedOk = "Ok";
|
||||
|
||||
private List<IWindow> mainWindows;
|
||||
|
||||
private PriorityQueue<PopupData, int> popupsToShow = new();
|
||||
|
||||
protected UiManager(IArea startArea)
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
Debug.LogError("Only one instance od UiManager is allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
|
||||
CurrentArea = startArea;
|
||||
mainWindows = new List<IWindow>();
|
||||
}
|
||||
|
||||
public static UiManager Instance { get; protected set; }
|
||||
public static UiManager<TWindow, TPopup> Instance { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current area shown on screen.
|
||||
@ -59,38 +37,69 @@ namespace NEG.UI
|
||||
/// <summary>
|
||||
/// Current window that is considered main (focused, lastly opened). Can be null.
|
||||
/// </summary>
|
||||
public IWindow CurrentMainWindow => mainWindows.LastOrDefault();
|
||||
// public IWindow CurrentMainWindow => mainWindows.LastOrDefault();
|
||||
|
||||
public PopupData CurrentPopup => currentShownPopup.data;
|
||||
// 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</param>
|
||||
/// <param name="content">popup content</param>
|
||||
/// <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 PopupData ShowOkPopup(string title, string content, string okText = null, Action okPressed = null,
|
||||
public PopupDataHook 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;
|
||||
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</param>
|
||||
/// <param name="content">popup content</param>
|
||||
/// <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>
|
||||
@ -98,126 +107,186 @@ namespace NEG.UI
|
||||
/// <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 PopupData ShowYesNoPopup(string title, string content, string yesText = null, string noText = null,
|
||||
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 = new DefaultPopupData(currentDefaultPopup, title, content,
|
||||
new List<(string, Action)>
|
||||
{
|
||||
(yesText ?? localizedYes, yesPressed), (noText ?? localizedNo, noPressed)
|
||||
});
|
||||
ShowPopup(data, priority, forceShow);
|
||||
return data;
|
||||
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</param>
|
||||
/// <param name="content">popup content</param>
|
||||
/// <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 PopupData ShowPopup(string title, string content, List<(string, Action)> actions, int priority = 0,
|
||||
bool forceShow = false)
|
||||
public PopupDataHook ShowPopup(string title, string content, ReadOnlySpan<(string, Action)> actions, int priority = 0, bool forceShow = false)
|
||||
{
|
||||
var data = new DefaultPopupData(currentDefaultPopup, title, content, actions);
|
||||
ShowPopup(data, priority, forceShow);
|
||||
return data;
|
||||
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 void ShowPopup(PopupData data, int priority = 0, bool forceShow = false)
|
||||
public PopupDataHook ShowPopup(TPopup popupType, PopupData data, int priority = 0, bool forceShow = false)
|
||||
{
|
||||
popupsToShow.Enqueue(data, priority);
|
||||
UpdatePopupsState(forceShow, priority, data);
|
||||
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)
|
||||
//CurrentMainWindow?.TryUseBack(ref backUsed);
|
||||
if(backUsed.Used)
|
||||
return;
|
||||
CurrentArea.TryUseBack(ref backUsed);
|
||||
}
|
||||
|
||||
#region Windows
|
||||
|
||||
public void RefreshPopups()
|
||||
{
|
||||
if (currentShownPopup.data is { IsValid: true })
|
||||
return;
|
||||
UpdatePopupsState(false);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected void SetDefaultPopup(IDefaultPopup popup) => currentDefaultPopup = popup;
|
||||
private Dictionary<TWindow, IWindow> registeredWindows = new();
|
||||
|
||||
|
||||
protected virtual void UpdatePopupsState(bool forceShow, int priority = 0, PopupData data = null)
|
||||
{
|
||||
if (forceShow)
|
||||
{
|
||||
if (currentShownPopup.data != null && currentShownPopup.priority >= priority)
|
||||
return;
|
||||
#endregion
|
||||
|
||||
popupsToShow.Enqueue(currentShownPopup.data, currentShownPopup.priority);
|
||||
ShowPopup(data, priority);
|
||||
return;
|
||||
}
|
||||
|
||||
while (popupsToShow.TryDequeue(out var d, out int p))
|
||||
{
|
||||
if (d == null)
|
||||
continue;
|
||||
if (!d.IsValid)
|
||||
continue;
|
||||
if (d == currentShownPopup.data)
|
||||
continue;
|
||||
ShowPopup(d, p);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentShownPopup.data == null)
|
||||
return;
|
||||
currentShownPopup.data.PopupClosedEvent -= PopupClosed;
|
||||
currentShownPopup.data.Hide();
|
||||
currentShownPopup.data = null;
|
||||
}
|
||||
// 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);
|
||||
// }
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,8 +10,8 @@ namespace NEG.UI.Area
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (UiManager.Instance.CurrentMainWindow == null)
|
||||
window.Open();
|
||||
// if (UiManager.Instance.CurrentMainWindow == null)
|
||||
// window.Open();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,9 +8,9 @@ namespace NEG.UI.Area
|
||||
{
|
||||
protected override void OnBackUsed(IControllable.BackUsed backUsed)
|
||||
{
|
||||
base.OnBackUsed(backUsed);
|
||||
UiManager.Instance.CurrentMainWindow?.Close();
|
||||
backUsed.Used = true;
|
||||
// base.OnBackUsed(backUsed);
|
||||
// UiManager.Instance.CurrentMainWindow?.Close();
|
||||
// backUsed.Used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,8 +17,8 @@ namespace NEG.UI.Area
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (setAsDefaultArea)
|
||||
UiManager.Instance.CurrentArea = this;
|
||||
// if (setAsDefaultArea)
|
||||
// UiManager.Instance.CurrentArea = this;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
@ -29,10 +29,10 @@ namespace NEG.UI.Area
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (UiManager.Instance == null)
|
||||
return;
|
||||
if (ReferenceEquals(UiManager.Instance.CurrentArea, this))
|
||||
UiManager.Instance.CurrentArea = null;
|
||||
// if (UiManager.Instance == null)
|
||||
// return;
|
||||
// if (ReferenceEquals(UiManager.Instance.CurrentArea, this))
|
||||
// UiManager.Instance.CurrentArea = null;
|
||||
}
|
||||
|
||||
public event Action<object> OnOpened;
|
||||
|
||||
@ -34,11 +34,11 @@ namespace NEG.UI.UnityUi.Buttons
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
button.onClick.AddListener(OnClicked);
|
||||
if (groupButtonSettings == null)
|
||||
MonoUiManager.Instance.DefaultUiSettings.Apply(this);
|
||||
else
|
||||
groupButtonSettings.Apply(this);
|
||||
// button.onClick.AddListener(OnClicked);
|
||||
// if (groupButtonSettings == null)
|
||||
// MonoUiManager.Instance.DefaultUiSettings.Apply(this);
|
||||
// else
|
||||
// groupButtonSettings.Apply(this);
|
||||
}
|
||||
|
||||
private void Start() => OnDeselect(null);
|
||||
@ -74,13 +74,13 @@ namespace NEG.UI.UnityUi.Buttons
|
||||
|
||||
public void AddOrOverrideSetting(SettingData data)
|
||||
{
|
||||
if (behaviours.TryGetValue(data.Key, out var setting))
|
||||
{
|
||||
setting.ChangeData(data);
|
||||
return;
|
||||
}
|
||||
|
||||
behaviours.Add(data.Key, MonoUiManager.Instance.BehavioursFactory.CreateInstance(data.Key, this, data));
|
||||
// if (behaviours.TryGetValue(data.Key, out var setting))
|
||||
// {
|
||||
// setting.ChangeData(data);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// behaviours.Add(data.Key, MonoUiManager.Instance.BehavioursFactory.CreateInstance(data.Key, this, data));
|
||||
}
|
||||
|
||||
public void RemoveSetting(string key)
|
||||
|
||||
@ -30,10 +30,10 @@ namespace NEG.UI.UnityUi.Buttons.Behaviours
|
||||
button.OnSelected -= OnButtonSelected;
|
||||
button.OnDeselected -= OnButtonDeselected;
|
||||
}
|
||||
|
||||
[FactoryRegistration]
|
||||
private static void RegisterInFactory() =>
|
||||
MonoUiManager.Instance.BehavioursFactory.Register("ChangeTextColor", typeof(ChangeTextColorBehaviour));
|
||||
//
|
||||
// [FactoryRegistration]
|
||||
// private static void RegisterInFactory() =>
|
||||
// MonoUiManager.Instance.BehavioursFactory.Register("ChangeTextColor", typeof(ChangeTextColorBehaviour));
|
||||
|
||||
private void OnButtonSelected(bool _) => button.Text.color = data.SelectedColor;
|
||||
private void OnButtonDeselected(bool _) => button.Text.color = data.DeselectedColor;
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
{
|
||||
public class CloseAllWindows : ButtonReaction
|
||||
{
|
||||
protected override void OnClicked() => UiManager.Instance.CurrentArea.CloseAllWindows();
|
||||
//protected override void OnClicked() => UiManager.Instance.CurrentArea.CloseAllWindows();
|
||||
protected override void OnClicked() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,10 @@ namespace NEG.UI.UnityUi.Buttons.Reactions
|
||||
{
|
||||
[SerializeField] private MonoWindow windowToOpen;
|
||||
|
||||
protected override void OnClicked() => UiManager.Instance.CurrentMainWindow.OpenAsChild(windowToOpen);
|
||||
// protected override void OnClicked() => UiManager.Instance.CurrentMainWindow.OpenAsChild(windowToOpen);
|
||||
protected override void OnClicked()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,12 +21,12 @@ namespace NEG.UI.UnityUi
|
||||
{
|
||||
public DefaultInputModule()
|
||||
{
|
||||
var defaultActions = new DefaultInputActions();
|
||||
InputActionReference.Create(defaultActions.UI.Navigate).action.performed +=
|
||||
ctx => OnSelectionChangeStarted();
|
||||
InputActionReference.Create(defaultActions.UI.Cancel).action.performed +=
|
||||
_ => UiManager.Instance.UseBack();
|
||||
defaultActions.Enable();
|
||||
// var defaultActions = new DefaultInputActions();
|
||||
// InputActionReference.Create(defaultActions.UI.Navigate).action.performed +=
|
||||
// ctx => OnSelectionChangeStarted();
|
||||
// InputActionReference.Create(defaultActions.UI.Cancel).action.performed +=
|
||||
// _ => UiManager.Instance.UseBack();
|
||||
// defaultActions.Enable();
|
||||
|
||||
if (Gamepad.current != null)
|
||||
SetDirectionInput();
|
||||
@ -60,28 +60,28 @@ namespace NEG.UI.UnityUi
|
||||
|
||||
private void SetDirectionInput()
|
||||
{
|
||||
if (EventSystem.current == null || MonoUiManager.Instance == null) return;
|
||||
CurrentSelectionSource = SelectionSource.Direction;
|
||||
Cursor.visible = false;
|
||||
if (EventSystem.current.currentSelectedGameObject == null &&
|
||||
MonoUiManager.Instance.CurrentMainWindow != null)
|
||||
{
|
||||
EventSystem.current.SetSelectedGameObject(((MonoWindow)MonoUiManager.Instance.CurrentMainWindow)
|
||||
.DefaultSelectedItem);
|
||||
return;
|
||||
}
|
||||
|
||||
var data = new PointerEventData(EventSystem.current);
|
||||
var currentSelected = EventSystem.current.currentSelectedGameObject;
|
||||
if (currentSelected != null)
|
||||
{
|
||||
for (var current = EventSystem.current.currentSelectedGameObject.transform;
|
||||
current != null;
|
||||
current = current.parent)
|
||||
ExecuteEvents.Execute(current.gameObject, data, ExecuteEvents.pointerExitHandler);
|
||||
}
|
||||
|
||||
EventSystem.current.SetSelectedGameObject(currentSelected);
|
||||
// if (EventSystem.current == null || MonoUiManager.Instance == null) return;
|
||||
// CurrentSelectionSource = SelectionSource.Direction;
|
||||
// Cursor.visible = false;
|
||||
// if (EventSystem.current.currentSelectedGameObject == null &&
|
||||
// MonoUiManager.Instance.CurrentMainWindow != null)
|
||||
// {
|
||||
// EventSystem.current.SetSelectedGameObject(((MonoWindow)MonoUiManager.Instance.CurrentMainWindow)
|
||||
// .DefaultSelectedItem);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var data = new PointerEventData(EventSystem.current);
|
||||
// var currentSelected = EventSystem.current.currentSelectedGameObject;
|
||||
// if (currentSelected != null)
|
||||
// {
|
||||
// for (var current = EventSystem.current.currentSelectedGameObject.transform;
|
||||
// current != null;
|
||||
// current = current.parent)
|
||||
// ExecuteEvents.Execute(current.gameObject, data, ExecuteEvents.pointerExitHandler);
|
||||
// }
|
||||
//
|
||||
// EventSystem.current.SetSelectedGameObject(currentSelected);
|
||||
}
|
||||
|
||||
private void SetPointerInput()
|
||||
|
||||
@ -24,7 +24,7 @@ namespace NEG.UI.UnityUi
|
||||
/// </para>
|
||||
/// NEG_UI_DISABLE_WARNING_DEFAULT_SELECTION
|
||||
/// </summary>
|
||||
public class MonoUiManager : UiManager, IDisposable
|
||||
public abstract class MonoUiManager<TWindow, TPopup> : UiManager<TWindow, TPopup>, IDisposable where TWindow : Enum where TPopup : Enum
|
||||
{
|
||||
private readonly GameObject canvasPrefab;
|
||||
|
||||
@ -51,9 +51,9 @@ namespace NEG.UI.UnityUi
|
||||
canvasPrefab = popupCanvas;
|
||||
defaultPopupPrefab = defaultPopup.GetComponent<MonoDefaultPopup>();
|
||||
|
||||
SpawnDefaultPopup();
|
||||
|
||||
SceneManager.activeSceneChanged += (_, _) => SpawnDefaultPopup();
|
||||
// SpawnDefaultPopup();
|
||||
//
|
||||
// SceneManager.activeSceneChanged += (_, _) => SpawnDefaultPopup();
|
||||
|
||||
BehavioursFactory = new KeyBasedFactory<string, ButtonElementBehaviour>();
|
||||
BehavioursFactory.FireRegistration();
|
||||
@ -64,7 +64,7 @@ namespace NEG.UI.UnityUi
|
||||
|
||||
//TODO: use default unity selection
|
||||
//TODO: window snaping to slots
|
||||
public static new MonoUiManager Instance { get; private set; }
|
||||
//public static new MonoUiManager<T, T1, T2> Instance { get; private set; }
|
||||
|
||||
public ButtonSettings DefaultUiSettings { get; }
|
||||
public KeyBasedFactory<string, ButtonElementBehaviour> BehavioursFactory { get; }
|
||||
@ -75,27 +75,27 @@ namespace NEG.UI.UnityUi
|
||||
Instance = null;
|
||||
}
|
||||
|
||||
protected override void UpdatePopupsState(bool forceShow, int priority = 0, PopupData data = null)
|
||||
{
|
||||
base.UpdatePopupsState(forceShow, priority, data);
|
||||
if (inputModule.CurrentSelectionSource != SelectionSource.Direction)
|
||||
return;
|
||||
// protected override void UpdatePopupsState(bool forceShow, int priority = 0, PopupData data = null)
|
||||
// {
|
||||
// base.UpdatePopupsState(forceShow, priority, data);
|
||||
// if (inputModule.CurrentSelectionSource != SelectionSource.Direction)
|
||||
// return;
|
||||
//
|
||||
// if (CurrentPopup == null && (EventSystem.current.currentSelectedGameObject == null ||
|
||||
// !EventSystem.current.currentSelectedGameObject.activeInHierarchy))
|
||||
// {
|
||||
// if (((MonoWindow)CurrentMainWindow).DefaultSelectedItem == null)
|
||||
// return;
|
||||
// EventSystem.current.SetSelectedGameObject(((MonoWindow)CurrentMainWindow).DefaultSelectedItem);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (CurrentPopup == null && (EventSystem.current.currentSelectedGameObject == null ||
|
||||
!EventSystem.current.currentSelectedGameObject.activeInHierarchy))
|
||||
{
|
||||
if (((MonoWindow)CurrentMainWindow).DefaultSelectedItem == null)
|
||||
return;
|
||||
EventSystem.current.SetSelectedGameObject(((MonoWindow)CurrentMainWindow).DefaultSelectedItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void SpawnDefaultPopup()
|
||||
{
|
||||
var canvas = Object.Instantiate(canvasPrefab);
|
||||
canvas.name = "DefaultPopupCanvas";
|
||||
SetDefaultPopup(Object.Instantiate(defaultPopupPrefab, canvas.transform));
|
||||
currentDefaultPopup.Close(true);
|
||||
}
|
||||
// private void SpawnDefaultPopup()
|
||||
// {
|
||||
// var canvas = Object.Instantiate(canvasPrefab);
|
||||
// canvas.name = "DefaultPopupCanvas";
|
||||
// SetDefaultPopup(Object.Instantiate(defaultPopupPrefab, canvas.transform));
|
||||
// currentDefaultPopup.Close(true);
|
||||
// }
|
||||
}
|
||||
}
|
||||
@ -27,10 +27,10 @@ namespace NEG.UI.UnityUi.Window
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (UiManager.Instance == null)
|
||||
return;
|
||||
if (IsOpened)
|
||||
UiManager.Instance.OnWindowClosed(this);
|
||||
// if (UiManager.Instance == null)
|
||||
// return;
|
||||
// if (IsOpened)
|
||||
// UiManager.Instance.OnWindowClosed(this);
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
@ -50,23 +50,23 @@ namespace NEG.UI.UnityUi.Window
|
||||
|
||||
public void SetOpenedState(IWindowSlot parentSlot, object data)
|
||||
{
|
||||
gameObject.SetActive(true);
|
||||
IsOpened = true;
|
||||
Parent = parentSlot;
|
||||
EventSystem.current.SetSelectedGameObject(defaultSelectedItem);
|
||||
if (parentSlot.OpenWindowAsMain)
|
||||
UiManager.Instance.SetMainWindow(this);
|
||||
OnOpened?.Invoke(data);
|
||||
// gameObject.SetActive(true);
|
||||
// IsOpened = true;
|
||||
// Parent = parentSlot;
|
||||
// EventSystem.current.SetSelectedGameObject(defaultSelectedItem);
|
||||
// if (parentSlot.OpenWindowAsMain)
|
||||
// UiManager.Instance.SetMainWindow(this);
|
||||
// OnOpened?.Invoke(data);
|
||||
}
|
||||
|
||||
public void SetClosedState()
|
||||
{
|
||||
gameObject.SetActive(false);
|
||||
IsOpened = false;
|
||||
Parent = null;
|
||||
((ISlotsHolder)this).CloseAllWindows();
|
||||
UiManager.Instance.OnWindowClosed(this);
|
||||
OnClosed?.Invoke();
|
||||
// gameObject.SetActive(false);
|
||||
// IsOpened = false;
|
||||
// Parent = null;
|
||||
// ((ISlotsHolder)this).CloseAllWindows();
|
||||
// UiManager.Instance.OnWindowClosed(this);
|
||||
// OnClosed?.Invoke();
|
||||
}
|
||||
|
||||
public void SetHiddenState() => gameObject.SetActive(false);
|
||||
|
||||
@ -25,9 +25,9 @@ namespace NEG.UI.WindowSlot
|
||||
|
||||
public override void DetachWindow(IWindow window)
|
||||
{
|
||||
if (UiManager.Instance.CurrentMainWindow == window)
|
||||
UiManager.Instance.MainWindowClosed(window);
|
||||
CurrentWindow = null;
|
||||
// if (UiManager.Instance.CurrentMainWindow == window)
|
||||
// UiManager.Instance.MainWindowClosed(window);
|
||||
// CurrentWindow = null;
|
||||
}
|
||||
|
||||
public override void CloseAllWindows() => CurrentWindow = null;
|
||||
|
||||
@ -38,16 +38,16 @@ namespace NegUtils.NEG.UI.UnityUi.WindowSlot
|
||||
|
||||
public override void DetachWindow(IWindow window)
|
||||
{
|
||||
if (window == null)
|
||||
return;
|
||||
window.SetClosedState();
|
||||
windowsHistory.Remove(window);
|
||||
if (window != currentWindow || windowsHistory.Count == 0) return;
|
||||
currentWindow = windowsHistory[^1];
|
||||
currentWindow.SeVisibleState();
|
||||
if (UiManager.Instance.CurrentMainWindow == window)
|
||||
UiManager.Instance.MainWindowClosed(window);
|
||||
EventSystem.current.SetSelectedGameObject(((MonoWindow)currentWindow).DefaultSelectedItem);
|
||||
// if (window == null)
|
||||
// return;
|
||||
// window.SetClosedState();
|
||||
// windowsHistory.Remove(window);
|
||||
// if (window != currentWindow || windowsHistory.Count == 0) return;
|
||||
// currentWindow = windowsHistory[^1];
|
||||
// currentWindow.SeVisibleState();
|
||||
// if (UiManager.Instance.CurrentMainWindow == window)
|
||||
// UiManager.Instance.MainWindowClosed(window);
|
||||
// EventSystem.current.SetSelectedGameObject(((MonoWindow)currentWindow).DefaultSelectedItem);
|
||||
}
|
||||
|
||||
public override void CloseAllWindows()
|
||||
|
||||
@ -51,7 +51,7 @@ namespace NEG.UI.Window
|
||||
return;
|
||||
}
|
||||
|
||||
UiManager.Instance.CurrentArea.OpenWindow(window, data);
|
||||
//UiManager.Instance.CurrentArea.OpenWindow(window, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -94,13 +94,13 @@ namespace NEG.UI.Window
|
||||
return;
|
||||
}
|
||||
|
||||
if (UiManager.Instance.CurrentMainWindow != null)
|
||||
{
|
||||
UiManager.Instance.CurrentMainWindow.OpenWindow(window, data);
|
||||
return;
|
||||
}
|
||||
|
||||
UiManager.Instance.CurrentArea.OpenWindow(window, data);
|
||||
// if (UiManager.Instance.CurrentMainWindow != null)
|
||||
// {
|
||||
// UiManager.Instance.CurrentMainWindow.OpenWindow(window, data);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// UiManager.Instance.CurrentArea.OpenWindow(window, data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
47
NativePool.cs
Normal file
47
NativePool.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Assertions;
|
||||
|
||||
namespace NegUtils;
|
||||
|
||||
public interface NativePool<T> where T : class, IPoolable
|
||||
{
|
||||
private static readonly List<T> Instances = new(10);
|
||||
|
||||
public static T Get()
|
||||
{
|
||||
T item;
|
||||
if (Instances.Count == 0)
|
||||
item = Activator.CreateInstance<T>();
|
||||
else
|
||||
{
|
||||
item = Instances[^1];
|
||||
Instances.RemoveAt(Instances.Count - 1);
|
||||
}
|
||||
item.OnGet();
|
||||
return item;
|
||||
}
|
||||
|
||||
public static void Return(T obj)
|
||||
{
|
||||
Assert.IsNotNull(obj);
|
||||
obj.OnRelease();
|
||||
|
||||
if(Instances.Count >= Capacity)
|
||||
return;
|
||||
|
||||
Instances.Add(obj);
|
||||
}
|
||||
|
||||
public static int Capacity
|
||||
{
|
||||
get => Instances.Count;
|
||||
set => Instances.Capacity = value;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IPoolable
|
||||
{
|
||||
void OnGet();
|
||||
void OnRelease();
|
||||
}
|
||||
3
NativePool.cs.meta
Normal file
3
NativePool.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 924ee76ac4a34cd6b60b4d9b93ff0ee5
|
||||
timeCreated: 1757278537
|
||||
Loading…
x
Reference in New Issue
Block a user