2025-12-19 14:44:14 +08:00
|
|
|
|
using System;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
2023-11-21 13:31:06 +08:00
|
|
|
|
using System.Linq;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
|
|
using Framework;
|
2025-10-23 15:43:50 +08:00
|
|
|
|
using Obfuz;
|
2023-10-19 15:00:19 +08:00
|
|
|
|
using PhxhSDK;
|
2025-06-17 13:54:47 +08:00
|
|
|
|
using PhxhSDK.AOT.Aspect;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
2025-10-23 15:43:50 +08:00
|
|
|
|
[ObfuzIgnore]
|
2024-01-26 16:06:42 +08:00
|
|
|
|
public partial class UIManager : Singlenton<UIManager>, IInitable, IUpdatable
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2025-04-02 15:49:57 +08:00
|
|
|
|
public const string UI_PREFAB_PATH = "Assets/Art_Out/UI/Prefab/{0}.prefab";
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
|
|
|
|
|
public Dictionary<string, UIWindow> mMemoryWindows = new Dictionary<string, UIWindow>();
|
|
|
|
|
|
|
2025-12-19 16:15:25 +08:00
|
|
|
|
// ✅ 使用独立的层级管理器
|
|
|
|
|
|
private UICanvasLayerManager LayerManager => UICanvasLayerManager.Instance;
|
|
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
private ScreenOrientation _currentOrientation;
|
|
|
|
|
|
private Dictionary<string, string> _openingWindows = new Dictionary<string, string>();
|
|
|
|
|
|
|
2023-12-29 15:09:18 +08:00
|
|
|
|
private List<UIWindow> _hideCache = new List<UIWindow>();
|
2024-01-24 15:42:01 +08:00
|
|
|
|
private UIWindow _curFullScreen;
|
2023-12-29 15:09:18 +08:00
|
|
|
|
|
2024-03-29 12:05:14 +08:00
|
|
|
|
private Dictionary<GameObject, UIWindow> _uiWindowObjDic = new Dictionary<GameObject, UIWindow>();
|
|
|
|
|
|
public Dictionary<GameObject, UIWindow> UIWindowObjDic => _uiWindowObjDic;
|
2024-12-10 15:13:03 +08:00
|
|
|
|
|
|
|
|
|
|
public Vector2 Size;
|
2025-06-25 17:37:22 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// UI和主相机屏幕缩放
|
|
|
|
|
|
/// </summary>
|
2025-06-25 17:52:18 +08:00
|
|
|
|
public Vector2 UIAndMainScreenScale;
|
2025-06-25 17:37:22 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// UI和UI屏幕缩放
|
|
|
|
|
|
/// </summary>
|
2025-06-25 17:52:18 +08:00
|
|
|
|
public Vector2 UIAndUIScreenScale;
|
2024-07-05 20:28:35 +08:00
|
|
|
|
/// <summary>
|
2025-08-01 19:03:25 +08:00
|
|
|
|
/// 禁用返回键计数
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private int disableBackCount;
|
|
|
|
|
|
/// <summary>
|
2024-07-05 20:28:35 +08:00
|
|
|
|
/// 是否响应返回键
|
|
|
|
|
|
/// </summary>
|
2025-08-01 19:03:25 +08:00
|
|
|
|
public bool IsEnableBack
|
|
|
|
|
|
{
|
|
|
|
|
|
get { return disableBackCount <= 0; }
|
|
|
|
|
|
set
|
|
|
|
|
|
{
|
|
|
|
|
|
if (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (disableBackCount > 0)
|
|
|
|
|
|
--disableBackCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
++disableBackCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-03-29 12:05:14 +08:00
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
public void Init()
|
|
|
|
|
|
{
|
2024-07-05 20:28:35 +08:00
|
|
|
|
IsEnableBack = true;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
_AllWindowMeta();
|
2025-12-19 14:44:14 +08:00
|
|
|
|
|
2025-12-19 16:15:25 +08:00
|
|
|
|
// 初始化层级管理器
|
|
|
|
|
|
LayerManager.Initialize(UIRoot.Instance.GetAllLayerRoots());
|
2025-12-19 14:44:14 +08:00
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
if (DeviceHelper.IsFullScreenIOS())
|
|
|
|
|
|
{
|
|
|
|
|
|
SetFullScreenIOS();
|
|
|
|
|
|
}
|
2023-12-08 18:41:26 +08:00
|
|
|
|
|
|
|
|
|
|
EventManager.Instance.Register(EventManager.EventName.Android_Click_Back, _OnAndroidClickBack);
|
2024-12-10 15:13:03 +08:00
|
|
|
|
|
2025-06-17 13:54:47 +08:00
|
|
|
|
OnScreenSizeChange();
|
|
|
|
|
|
|
|
|
|
|
|
AspectManager.Instance.ScreenSizeChange += OnScreenSizeChange;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Release()
|
|
|
|
|
|
{
|
2025-12-19 16:15:25 +08:00
|
|
|
|
LayerManager.Clear();
|
2025-06-17 13:54:47 +08:00
|
|
|
|
AspectManager.Instance.ScreenSizeChange -= OnScreenSizeChange;
|
2023-12-08 18:41:26 +08:00
|
|
|
|
EventManager.Instance.Unregister(EventManager.EventName.Android_Click_Back, _OnAndroidClickBack);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-07 14:28:33 +08:00
|
|
|
|
public bool disableUILogic = false;
|
|
|
|
|
|
|
2024-01-26 16:06:42 +08:00
|
|
|
|
public void Update(float dt)
|
|
|
|
|
|
{
|
2025-08-07 14:28:33 +08:00
|
|
|
|
if (disableUILogic) return;
|
2024-01-26 16:06:42 +08:00
|
|
|
|
foreach (var winKv in mMemoryWindows)
|
|
|
|
|
|
{
|
|
|
|
|
|
var window = winKv.Value;
|
2025-12-30 15:48:15 +08:00
|
|
|
|
if (window != null
|
|
|
|
|
|
&& window.gameObject
|
|
|
|
|
|
&& window.IsCreated()
|
2026-01-06 16:45:21 +08:00
|
|
|
|
&& window.IsActive() // 改为 IsActive():只更新活跃窗口(显示且未暂停)
|
2025-12-30 15:48:15 +08:00
|
|
|
|
&& !window.IsClosing)
|
2024-01-26 16:06:42 +08:00
|
|
|
|
{
|
2025-12-30 15:48:15 +08:00
|
|
|
|
window.Update(dt);
|
2024-01-26 16:06:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-08-28 19:07:32 +08:00
|
|
|
|
|
2025-09-12 15:18:50 +08:00
|
|
|
|
_UpdateInputBlockTimer(dt);
|
2024-01-26 16:06:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#region UIWindow Manager
|
|
|
|
|
|
|
|
|
|
|
|
public static void BindWindowObj(UIWindow window, GameObject uiObj)
|
|
|
|
|
|
{
|
2025-10-22 19:46:14 +08:00
|
|
|
|
if (window == null || uiObj == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (window == null)
|
|
|
|
|
|
DebugUtil.LogError("window is null");
|
|
|
|
|
|
if (uiObj == null)
|
|
|
|
|
|
DebugUtil.LogError("uiObj is null");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-01-26 16:06:42 +08:00
|
|
|
|
window.gameObject = uiObj.gameObject;
|
|
|
|
|
|
window.transform = uiObj.transform;
|
|
|
|
|
|
window.name = uiObj.name;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-01-24 15:42:01 +08:00
|
|
|
|
#region OpenWindowAPI
|
2023-08-22 19:08:45 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 打开一个UI
|
|
|
|
|
|
/// UIManager.Instance.OpenWindow("Common/GameUI")
|
|
|
|
|
|
/// </summary>
|
2023-11-15 12:55:00 +08:00
|
|
|
|
|
2025-12-22 19:31:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建并打开窗口
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="path">窗口路径</param>
|
|
|
|
|
|
/// <param name="data">传递的数据</param>
|
2025-12-25 20:26:05 +08:00
|
|
|
|
public async UniTask<UIWindow> CreateAndOpenWindow(string path, object data = null)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2024-10-24 17:03:31 +08:00
|
|
|
|
DebugUtil.LogP($"打开窗口:{path}");
|
2024-10-17 15:36:14 +08:00
|
|
|
|
if (mMemoryWindows.ContainsKey(path))
|
|
|
|
|
|
{
|
2024-10-24 17:03:31 +08:00
|
|
|
|
DebugUtil.LogG($"窗口已打开!!!{path}");
|
2024-10-18 15:06:46 +08:00
|
|
|
|
//return null;
|
2024-10-17 15:36:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 15:01:35 +08:00
|
|
|
|
var window = await _LoadWindow(path, false);
|
2024-01-26 16:06:42 +08:00
|
|
|
|
if (window != null)
|
2023-10-19 15:00:19 +08:00
|
|
|
|
{
|
2025-09-10 16:05:21 +08:00
|
|
|
|
window.ShowWindow(data);
|
2023-10-19 15:00:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
return window;
|
|
|
|
|
|
}
|
2024-01-24 15:42:01 +08:00
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
public bool Back()
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-21 13:31:06 +08:00
|
|
|
|
public bool RemoveWindow(string wName)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
|
|
|
|
|
string windowName = wName;
|
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
UIWindow window;
|
|
|
|
|
|
if (mMemoryWindows.TryGetValue(windowName, out window))
|
|
|
|
|
|
{
|
2025-12-19 16:15:25 +08:00
|
|
|
|
LayerManager.RemoveWindow(window);
|
2023-11-21 13:31:06 +08:00
|
|
|
|
mMemoryWindows.Remove(windowName);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
result = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
2025-09-11 21:06:09 +08:00
|
|
|
|
|
2025-12-23 19:28:45 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 关闭窗口
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="wName">窗口名称</param>
|
|
|
|
|
|
/// <param name="destroy">是否销毁窗口</param>
|
|
|
|
|
|
public void CloseWindow(string wName, bool destroy)
|
2025-09-12 15:18:50 +08:00
|
|
|
|
{
|
2025-12-30 14:36:01 +08:00
|
|
|
|
var window = GetLoadedWindowByPath<UIWindow>(wName);
|
2025-09-12 15:18:50 +08:00
|
|
|
|
if (window != null)
|
|
|
|
|
|
{
|
2025-12-23 19:28:45 +08:00
|
|
|
|
window.CloseWindow(destroy);
|
2025-09-12 15:18:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-22 19:31:07 +08:00
|
|
|
|
|
2025-12-30 14:36:01 +08:00
|
|
|
|
|
2025-12-22 19:31:07 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 打开已加载的窗口(通过路径)
|
|
|
|
|
|
/// </summary>
|
2025-12-25 20:26:05 +08:00
|
|
|
|
public void OpenLoadedWindow(string path, object data = null)
|
2025-12-22 19:31:07 +08:00
|
|
|
|
{
|
2025-12-30 14:36:01 +08:00
|
|
|
|
var window = GetLoadedWindowByPath(path);
|
2025-12-22 19:31:07 +08:00
|
|
|
|
if (window != null)
|
|
|
|
|
|
{
|
2025-12-30 14:36:01 +08:00
|
|
|
|
window.ShowWindow(data);
|
2025-12-22 19:31:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError($"OpenLoadedWindow: window not found: {path}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-21 13:31:06 +08:00
|
|
|
|
|
2025-12-30 14:36:01 +08:00
|
|
|
|
public T GetLoadedWindowByPath<T>(string uipath) where T : UIWindow
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2025-12-30 14:36:01 +08:00
|
|
|
|
var window = GetLoadedWindowByPath(uipath) as T;
|
2024-07-05 16:04:26 +08:00
|
|
|
|
//return window.gameObject.activeSelf ? window : null;
|
|
|
|
|
|
return window;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-30 14:36:01 +08:00
|
|
|
|
public UIWindow GetLoadedWindowByPath(string uipath)
|
2024-07-05 16:04:26 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(uipath))
|
|
|
|
|
|
{
|
|
|
|
|
|
DebugUtil.LogError("UIManager.GetOpenedWindowByPath, uipath is null or empty");
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
if (mMemoryWindows.ContainsKey(uipath))
|
|
|
|
|
|
{
|
2024-01-23 13:58:40 +08:00
|
|
|
|
//return window.gameObject.activeSelf ? window : null;
|
2024-07-05 16:04:26 +08:00
|
|
|
|
return mMemoryWindows[uipath];
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
2024-07-05 16:04:26 +08:00
|
|
|
|
|
|
|
|
|
|
return null;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-19 14:44:14 +08:00
|
|
|
|
public bool GetTopWindow(out UIWindow window, out UICanvasLayer layer, int banLayerMask)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2025-12-19 16:15:25 +08:00
|
|
|
|
return LayerManager.GetTopWindow(out window, out layer, banLayerMask);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-19 14:44:14 +08:00
|
|
|
|
public int LayerMask(UICanvasLayer layer)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2025-12-19 16:15:25 +08:00
|
|
|
|
return LayerManager.GetLayerMask(layer);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async void SetFullScreenIOS()
|
|
|
|
|
|
{
|
|
|
|
|
|
await UniTask.Delay(670);
|
|
|
|
|
|
// while (true)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var screenOrientation = DragonNativeBridge.GetScreenOrientation();
|
|
|
|
|
|
// if (screenOrientation != _currentOrientation)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// _currentOrientation = screenOrientation;
|
|
|
|
|
|
// EventDispatcher.Instance.DispatchEvent(new ScreenOrientationChangedEvent(_currentOrientation));
|
|
|
|
|
|
// }
|
|
|
|
|
|
// yield return wait;
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-22 19:31:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 加载窗口(不显示)
|
|
|
|
|
|
/// 用于预加载场景
|
|
|
|
|
|
/// </summary>
|
2025-12-19 14:44:14 +08:00
|
|
|
|
public async UniTask<UIWindow> LoadWindow(string path)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2025-12-29 18:41:38 +08:00
|
|
|
|
return await _LoadWindow(path, true);
|
2023-11-16 15:32:40 +08:00
|
|
|
|
}
|
2025-12-29 18:41:38 +08:00
|
|
|
|
private async UniTask<UIWindow> _LoadWindow(string path, bool forceHide)
|
2023-11-16 15:32:40 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
string uipath = path;
|
|
|
|
|
|
UIWindow window = null;
|
2023-11-16 15:32:40 +08:00
|
|
|
|
|
2023-08-22 19:08:45 +08:00
|
|
|
|
WindowInfo wInfo;
|
|
|
|
|
|
if (!_windowsInfo.ContainsKey(uipath))
|
|
|
|
|
|
{
|
|
|
|
|
|
//if (_windowsInfo.TryGetValue(uipath, out wInfo))
|
|
|
|
|
|
{
|
2023-10-19 15:00:19 +08:00
|
|
|
|
DebugUtil.LogError("Create ui fail: {0}, no windows info inited", uipath);
|
2023-11-16 15:32:40 +08:00
|
|
|
|
return window;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
wInfo = _windowsInfo[uipath];
|
|
|
|
|
|
var uiWindowLayer = wInfo.windowLayer;
|
|
|
|
|
|
|
|
|
|
|
|
if (!mMemoryWindows.TryGetValue(uipath, out window))
|
|
|
|
|
|
{
|
2023-11-16 15:32:40 +08:00
|
|
|
|
if (_openingWindows.ContainsKey(uipath))
|
|
|
|
|
|
{
|
|
|
|
|
|
return window;
|
|
|
|
|
|
}
|
|
|
|
|
|
_openingWindows.Add(uipath, uipath);
|
2025-12-19 14:44:14 +08:00
|
|
|
|
window = await UIRoot.Instance.CreateWindow(uipath, uiWindowLayer);
|
2023-11-16 15:32:40 +08:00
|
|
|
|
_openingWindows.Remove(uipath);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
if (window != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
mMemoryWindows[uipath] = window;
|
|
|
|
|
|
window.WindowName = uipath;
|
|
|
|
|
|
window.uiWindowLayer = uiWindowLayer;
|
2025-12-30 14:36:01 +08:00
|
|
|
|
window.Init();
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2023-10-19 15:00:19 +08:00
|
|
|
|
DebugUtil.LogError("Create ui fail: {0}", uipath);
|
2023-11-16 15:32:40 +08:00
|
|
|
|
return window;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-19 16:15:25 +08:00
|
|
|
|
LayerManager.AddWindow(window);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2024-01-26 16:06:42 +08:00
|
|
|
|
if (window == null)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2023-10-19 15:00:19 +08:00
|
|
|
|
DebugUtil.LogError("Create ui fail: {0}", uipath);
|
2023-11-16 15:32:40 +08:00
|
|
|
|
return null;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-29 18:41:38 +08:00
|
|
|
|
if (forceHide)
|
2023-08-22 19:08:45 +08:00
|
|
|
|
{
|
2023-11-16 15:32:40 +08:00
|
|
|
|
window.gameObject.SetActive(false);
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
2023-11-16 15:32:40 +08:00
|
|
|
|
|
2024-03-29 12:05:14 +08:00
|
|
|
|
_uiWindowObjDic.TryAdd(window.gameObject, window);
|
2023-11-16 15:32:40 +08:00
|
|
|
|
return window;
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|
2023-11-16 15:32:40 +08:00
|
|
|
|
|
2024-08-15 14:56:28 +08:00
|
|
|
|
|
2024-01-09 18:11:00 +08:00
|
|
|
|
public void ForeachUI(Action<UIWindow> action)
|
|
|
|
|
|
{
|
|
|
|
|
|
var windowList = mMemoryWindows.ToList();
|
|
|
|
|
|
foreach (var kv in windowList)
|
|
|
|
|
|
{
|
|
|
|
|
|
var window = kv.Value;
|
|
|
|
|
|
if (window != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
action?.Invoke(kv.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-25 16:37:51 +08:00
|
|
|
|
public void CloseAllUIExcept(string path)
|
|
|
|
|
|
{
|
|
|
|
|
|
var windowList = mMemoryWindows.ToList();
|
|
|
|
|
|
foreach (var kv in windowList)
|
|
|
|
|
|
{
|
|
|
|
|
|
var window = kv.Value;
|
|
|
|
|
|
if(window.WindowName != path)
|
|
|
|
|
|
{
|
2025-12-23 19:28:45 +08:00
|
|
|
|
window.CloseWindow(destroy: true);
|
2025-02-25 16:37:51 +08:00
|
|
|
|
mMemoryWindows.Remove(window.WindowName);
|
2025-12-19 16:15:25 +08:00
|
|
|
|
LayerManager.RemoveWindow(window);
|
2025-02-25 16:37:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-24 15:42:01 +08:00
|
|
|
|
#endregion
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2024-05-09 14:37:29 +08:00
|
|
|
|
#region ShowAndHide
|
|
|
|
|
|
|
2025-12-19 14:44:14 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 隐藏指定层级及以下的所有UI
|
|
|
|
|
|
/// 和 ShowAllUI 成对调用
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="maxLayer">最大层级(包含该层级及以下的所有UI都会被隐藏)</param>
|
|
|
|
|
|
/// <param name="exceptions">不隐藏的UI窗口名称列表</param>
|
|
|
|
|
|
public void HideAllUI(UICanvasLayer maxLayer, params string[] exceptions)
|
2023-12-29 15:03:59 +08:00
|
|
|
|
{
|
2025-12-19 16:15:25 +08:00
|
|
|
|
var hiddenWindows = LayerManager.HideWindowsUpToLayer(maxLayer, exceptions);
|
|
|
|
|
|
_hideCache.AddRange(hiddenWindows);
|
2025-12-19 14:44:14 +08:00
|
|
|
|
}
|
2025-12-25 20:26:05 +08:00
|
|
|
|
|
2024-05-17 18:28:31 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 和HideAllUI成对调用
|
|
|
|
|
|
/// </summary>
|
2023-12-29 15:03:59 +08:00
|
|
|
|
public void ShowAllUI()
|
|
|
|
|
|
{
|
2023-12-29 15:09:18 +08:00
|
|
|
|
foreach (var v in _hideCache)
|
2023-12-29 15:03:59 +08:00
|
|
|
|
{
|
2023-12-29 15:09:18 +08:00
|
|
|
|
var window = v;
|
2024-01-03 17:25:13 +08:00
|
|
|
|
if (window != null)
|
|
|
|
|
|
window.ShowWindow();
|
2023-12-29 15:03:59 +08:00
|
|
|
|
}
|
2023-12-29 15:09:18 +08:00
|
|
|
|
_hideCache.Clear();
|
2023-12-29 15:03:59 +08:00
|
|
|
|
}
|
2025-12-30 16:20:28 +08:00
|
|
|
|
|
2024-05-09 14:37:29 +08:00
|
|
|
|
#endregion
|
2023-08-22 19:08:45 +08:00
|
|
|
|
|
2023-11-21 13:24:42 +08:00
|
|
|
|
//根据路径判断UI界面是否打开
|
2023-08-22 19:08:45 +08:00
|
|
|
|
public bool IsWindowOpening(string uiPath)
|
|
|
|
|
|
{
|
|
|
|
|
|
string windowName;
|
|
|
|
|
|
if (_openingWindows.TryGetValue(uiPath, out windowName))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (windowName != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2024-03-08 12:59:24 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-12-25 20:26:05 +08:00
|
|
|
|
/// 关闭指定层级的所有窗口(支持单个或多个层级)
|
2024-03-08 12:59:24 +08:00
|
|
|
|
/// </summary>
|
2025-12-25 20:26:05 +08:00
|
|
|
|
/// <param name="layers">要关闭的层级列表</param>
|
|
|
|
|
|
public void CloseAllInLayer(params UICanvasLayer[] layers)
|
2023-11-21 13:24:42 +08:00
|
|
|
|
{
|
2025-12-25 20:26:05 +08:00
|
|
|
|
CloseAllInLayer(layers, null);
|
2023-11-21 13:24:42 +08:00
|
|
|
|
}
|
2025-07-29 17:58:30 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-12-25 20:26:05 +08:00
|
|
|
|
/// 关闭指定层级的所有窗口,可排除指定窗口(支持单个或多个层级)
|
2025-07-29 17:58:30 +08:00
|
|
|
|
/// </summary>
|
2025-12-25 20:26:05 +08:00
|
|
|
|
/// <param name="layers">要关闭的层级列表</param>
|
|
|
|
|
|
/// <param name="exceptions">不关闭的窗口名称列表</param>
|
|
|
|
|
|
public void CloseAllInLayer(UICanvasLayer[] layers, params string[] exceptions)
|
2025-03-21 12:55:24 +08:00
|
|
|
|
{
|
2025-12-25 20:26:05 +08:00
|
|
|
|
if (layers == null || layers.Length == 0)
|
2025-03-21 12:55:24 +08:00
|
|
|
|
{
|
2025-12-25 20:26:05 +08:00
|
|
|
|
DebugUtil.LogWarning("[CloseAllInLayer] No layers specified");
|
|
|
|
|
|
return;
|
2025-03-21 12:55:24 +08:00
|
|
|
|
}
|
2023-11-21 13:24:42 +08:00
|
|
|
|
|
2025-12-25 20:26:05 +08:00
|
|
|
|
int totalClosed = 0;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var layer in layers)
|
2025-07-29 17:58:30 +08:00
|
|
|
|
{
|
2025-12-25 20:26:05 +08:00
|
|
|
|
var windowsInLayer = LayerManager.GetWindowsInLayer(layer);
|
|
|
|
|
|
|
|
|
|
|
|
if (windowsInLayer.Count == 0)
|
2025-07-29 17:58:30 +08:00
|
|
|
|
{
|
2025-12-25 20:26:05 +08:00
|
|
|
|
DebugUtil.Log($"[CloseAllInLayer] No windows in layer: {layer}");
|
|
|
|
|
|
continue;
|
2025-07-29 17:58:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 20:26:05 +08:00
|
|
|
|
List<UIWindow> toBeRemoved = new List<UIWindow>();
|
|
|
|
|
|
|
|
|
|
|
|
var node = windowsInLayer.First;
|
2025-07-29 17:58:30 +08:00
|
|
|
|
while (node != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var window = node.Value;
|
2025-12-25 20:26:05 +08:00
|
|
|
|
bool shouldClose = true;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否在例外列表中
|
|
|
|
|
|
if (exceptions != null && exceptions.Length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var exception in exceptions)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (window.WindowName == exception)
|
|
|
|
|
|
{
|
|
|
|
|
|
shouldClose = false;
|
|
|
|
|
|
DebugUtil.Log($"[CloseAllInLayer] Skipping window: {window.WindowName} (in exception list)");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (shouldClose)
|
2025-07-29 17:58:30 +08:00
|
|
|
|
{
|
|
|
|
|
|
toBeRemoved.Add(window);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 20:26:05 +08:00
|
|
|
|
if (node == windowsInLayer.Last)
|
2025-07-29 17:58:30 +08:00
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-12-25 20:26:05 +08:00
|
|
|
|
|
2025-07-29 17:58:30 +08:00
|
|
|
|
node = node.Next;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 20:26:05 +08:00
|
|
|
|
// 关闭窗口
|
|
|
|
|
|
foreach (var window in toBeRemoved)
|
2025-07-29 17:58:30 +08:00
|
|
|
|
{
|
2025-12-25 20:26:05 +08:00
|
|
|
|
DebugUtil.Log($"[CloseAllInLayer] Closing window: {window.WindowName} in layer {layer}");
|
|
|
|
|
|
window.CloseWindow(destroy: true);
|
2025-07-29 17:58:30 +08:00
|
|
|
|
}
|
2025-12-25 20:26:05 +08:00
|
|
|
|
|
|
|
|
|
|
totalClosed += toBeRemoved.Count;
|
2025-07-29 17:58:30 +08:00
|
|
|
|
}
|
2025-12-25 20:26:05 +08:00
|
|
|
|
|
|
|
|
|
|
if (layers.Length == 1)
|
|
|
|
|
|
DebugUtil.Log($"[CloseAllInLayer] Closed {totalClosed} windows in layer {layers[0]}");
|
|
|
|
|
|
else
|
|
|
|
|
|
DebugUtil.Log($"[CloseAllInLayer] Closed {totalClosed} windows in {layers.Length} layers");
|
2025-07-29 17:58:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-12-08 18:41:26 +08:00
|
|
|
|
private async void _OnAndroidClickBack()
|
2023-11-21 13:24:42 +08:00
|
|
|
|
{
|
2024-07-05 20:28:35 +08:00
|
|
|
|
if (!IsEnableBack)
|
|
|
|
|
|
return;
|
2024-03-27 17:07:43 +08:00
|
|
|
|
|
2025-12-25 20:26:05 +08:00
|
|
|
|
// 获取所有可见窗口(从上到下)
|
|
|
|
|
|
var visibleWindows = LayerManager.GetAllVisibleWindows();
|
|
|
|
|
|
|
|
|
|
|
|
DebugUtil.Log($"[AndroidBack] Found {visibleWindows.Count} visible windows");
|
|
|
|
|
|
|
|
|
|
|
|
// 从上到下遍历,找到第一个处理返回键的窗口
|
|
|
|
|
|
foreach (var window in visibleWindows)
|
2023-12-08 18:41:26 +08:00
|
|
|
|
{
|
2025-12-25 20:26:05 +08:00
|
|
|
|
DebugUtil.Log($"[AndroidBack] Trying window: {window.WindowName} (Layer: {window.uiWindowLayer})");
|
|
|
|
|
|
|
2025-12-26 12:16:37 +08:00
|
|
|
|
if (await window.Back())
|
2025-12-25 20:26:05 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 窗口处理了返回键,结束遍历
|
|
|
|
|
|
DebugUtil.Log($"[AndroidBack] Handled by: {window.WindowName}");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-11-21 13:24:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-25 20:26:05 +08:00
|
|
|
|
// 没有窗口处理返回键,显示退出确认
|
|
|
|
|
|
DebugUtil.Log("[AndroidBack] No window handled, showing exit confirmation");
|
2024-08-22 15:09:18 +08:00
|
|
|
|
if (!CheckWindowCreated(UINameConst.UIBackReturn))
|
|
|
|
|
|
{
|
|
|
|
|
|
await CreateAndOpenWindow(UINameConst.UIBackReturn);
|
|
|
|
|
|
}
|
2023-11-21 13:24:42 +08:00
|
|
|
|
}
|
2025-09-10 16:05:21 +08:00
|
|
|
|
|
2024-05-16 12:40:15 +08:00
|
|
|
|
public bool CheckWindowCreated(string uiPath)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (mMemoryWindows.TryGetValue(uiPath, out var window))
|
|
|
|
|
|
{
|
|
|
|
|
|
return window.IsCreated();
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2025-06-17 13:54:47 +08:00
|
|
|
|
|
|
|
|
|
|
private async void OnScreenSizeChange()
|
|
|
|
|
|
{
|
|
|
|
|
|
await UniTask.NextFrame(); // 必须等待一帧,等RectTransform大小刷新后获取
|
|
|
|
|
|
|
|
|
|
|
|
RectTransform rectTrans = UIRoot.Instance.Root.GetComponent<RectTransform>();
|
|
|
|
|
|
|
|
|
|
|
|
Size = new(rectTrans.sizeDelta.x, rectTrans.sizeDelta.y);
|
2025-06-25 17:37:22 +08:00
|
|
|
|
UIAndMainScreenScale = new Vector3(Size.x / Screen.width, Size.y / Screen.height);
|
2025-06-25 17:52:18 +08:00
|
|
|
|
UIAndUIScreenScale = new Vector3(Size.x / AspectManager.Instance.ScreenSize.x, Size.y / AspectManager.Instance.ScreenSize.y);
|
2025-06-17 13:54:47 +08:00
|
|
|
|
}
|
2023-08-22 19:08:45 +08:00
|
|
|
|
}
|