219 lines
6.3 KiB
C#
219 lines
6.3 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using UnityEngine.Events;
|
|
using Sirenix.OdinInspector;
|
|
using Cysharp.Threading.Tasks;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Linq;
|
|
namespace BITKit.UX
|
|
{
|
|
public interface IWindowElement
|
|
{
|
|
string GetName();
|
|
UXElement Navigation { get; }
|
|
UXElement Window { get; }
|
|
UXWindowManager SubWindowManager { get; }
|
|
Task Open(CancellationToken cancellationToken = default);
|
|
Task Close(CancellationToken cancellationToken = default);
|
|
}
|
|
[System.Serializable]
|
|
public class UXWindowElement : IWindowElement
|
|
{
|
|
[SerializeField]
|
|
protected string name;
|
|
[SerializeField]
|
|
protected UXElement navigation;
|
|
[SerializeField]
|
|
protected UXElement window;
|
|
[SerializeField]
|
|
protected UXWindowManager subWindowManager;
|
|
[SerializeField]
|
|
protected bool enabled;
|
|
public UXElement Navigation => navigation;
|
|
public UXElement Window => window;
|
|
public UXWindowManager SubWindowManager => subWindowManager;
|
|
public async Task Close(CancellationToken cancellationToken = default)
|
|
{
|
|
try
|
|
{
|
|
await UniTask.SwitchToMainThread(cancellationToken);
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
await UniTask.Yield();
|
|
try
|
|
{
|
|
navigation.GetVisualElement().SetEnabled(true);
|
|
}
|
|
catch (System.Exception)
|
|
{
|
|
Debug.LogWarning($"Navgation:{name} 已丢失");
|
|
throw;
|
|
}
|
|
try
|
|
{
|
|
window.Set(false);
|
|
}
|
|
catch (System.Exception)
|
|
{
|
|
Debug.LogWarning($"Window:{name} 已丢失");
|
|
throw;
|
|
}
|
|
enabled = false;
|
|
}
|
|
catch (System.Exception)
|
|
{
|
|
Debug.LogWarning(name);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task Open(CancellationToken cancellationToken = default)
|
|
{
|
|
await UniTask.SwitchToMainThread(cancellationToken);
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
navigation.GetVisualElement().SetEnabled(false);
|
|
window.Set(true);
|
|
enabled = true;
|
|
}
|
|
public string GetName() => name;
|
|
|
|
|
|
}
|
|
public class UXWindowManager : MonoBehaviour, INextble
|
|
{
|
|
public enum WindowState
|
|
{
|
|
None,
|
|
Flex,
|
|
Hidden
|
|
}
|
|
[Header(Constant.Header.Components)]
|
|
[SerializeReference, SubclassSelector] public List<IWindowElement> windows = new();
|
|
public UXWindowManager subWindowManager;
|
|
[Header(Constant.Header.Settings)]
|
|
public UXElement startElement;
|
|
[SerializeField] bool hidden;
|
|
[Header(Constant.Header.Events)]
|
|
public UnityEvent<string> OnEntry = new();
|
|
public UnityEvent<string> OnExit = new();
|
|
[Header(Constant.Header.InternalVariables)]
|
|
List<IWindowElement> activeWindows = new();
|
|
IWindowElement activeWindow;
|
|
public int index { get; private set; }
|
|
CancellationTokenSource cts;
|
|
public async void Select(UXElement element)
|
|
{
|
|
cts.Cancel();
|
|
cts = new();
|
|
foreach (var activeWindow in activeWindows)
|
|
{
|
|
await activeWindow.Close(cts.Token);
|
|
OnExit.Invoke(activeWindow.GetName());
|
|
|
|
}
|
|
|
|
activeWindows.Clear();
|
|
var window = windows
|
|
.Find(x => x.GetName() == element.name || x.Navigation == element || x.Window == element);
|
|
index = windows.IndexOf(window);
|
|
activeWindows.Add(window);
|
|
activeWindow = window;
|
|
// currentWindow = window;
|
|
try
|
|
{
|
|
await window.Open();
|
|
}
|
|
catch (System.Exception)
|
|
{
|
|
Debug.LogWarning(name);
|
|
if (window is null)
|
|
{
|
|
Debug.Log("Window is Null");
|
|
}
|
|
throw;
|
|
}
|
|
|
|
OnEntry.Invoke(window.GetName());
|
|
}
|
|
public bool Next()
|
|
{
|
|
if (activeWindow is not null && activeWindow.SubWindowManager)
|
|
{
|
|
if (activeWindow.SubWindowManager.Next())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
if (windows.Count > index + 1)
|
|
{
|
|
var element = windows[index + 1].Navigation;
|
|
Select(element);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public bool Previous()
|
|
{
|
|
if (activeWindow is not null && activeWindow.SubWindowManager)
|
|
{
|
|
if (activeWindow.SubWindowManager.Previous())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
if (index - 1 >= 0)
|
|
{
|
|
var element = windows[index - 1].Navigation;
|
|
Select(element);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public bool Hidden
|
|
{
|
|
get => hidden;
|
|
set
|
|
{
|
|
if (hidden)
|
|
{
|
|
Exit();
|
|
}
|
|
else
|
|
{
|
|
Recovery();
|
|
}
|
|
}
|
|
}
|
|
public void Exit()
|
|
{
|
|
hidden = true;
|
|
activeWindow?.Close();
|
|
}
|
|
public void Recovery()
|
|
{
|
|
hidden = false;
|
|
activeWindow?.Open();
|
|
}
|
|
void Awake()
|
|
{
|
|
cts = new();
|
|
var ct = gameObject.GetCancellationTokenOnDestroy();
|
|
ct.Register(cts.Cancel);
|
|
}
|
|
async void Start()
|
|
{
|
|
await UniTask.Yield();
|
|
foreach (var window in windows)
|
|
{
|
|
await window.Close(cts.Token);
|
|
}
|
|
Select(startElement);
|
|
}
|
|
}
|
|
} |