123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
- using YooAsset;
- namespace UniFramework.Window
- {
- public static class UniWindow
- {
- public struct WindowInfo
- {
- public string WindowName;
- public int WindowLayer;
- public bool IsLoadDone;
- }
- private static bool _isInitialize = false;
- private static GameObject _driver = null;
- private static readonly List<UIWindow> _stack = new List<UIWindow>(100);
- internal static GameObject Desktop { private set; get; }
- /// <summary>
- /// 初始化界面系统
- /// </summary>
- public static void Initalize(GameObject desktop)
- {
- if (_isInitialize)
- throw new Exception($"{nameof(UniWindow)} is initialized !");
- if (desktop == null)
- throw new ArgumentNullException();
- if (_isInitialize == false)
- {
- // 创建驱动器
- _isInitialize = true;
- _driver = new UnityEngine.GameObject($"[{nameof(UniWindow)}]");
- _driver.AddComponent<UniWindowDriver>();
- UnityEngine.Object.DontDestroyOnLoad(_driver);
- UniLogger.Log($"{nameof(UniWindow)} initalize !");
- Desktop = desktop;
- }
- }
- /// <summary>
- /// 销毁界面系统
- /// </summary>
- public static void Destroy()
- {
- if (_isInitialize)
- {
- CloseAll();
- _isInitialize = false;
- if (_driver != null)
- GameObject.Destroy(_driver);
- UniLogger.Log($"{nameof(UniWindow)} destroy all !");
- }
- }
- /// <summary>
- /// 更新界面系统
- /// </summary>
- internal static void Update()
- {
- if (_isInitialize)
- {
- int count = _stack.Count;
- for (int i = 0; i < _stack.Count; i++)
- {
- if (_stack.Count != count)
- break;
- var window = _stack[i];
- window.InternalUpdate();
- }
- }
- }
- /// <summary>
- /// 设置屏幕安全区域(异形屏支持)
- /// </summary>
- /// <param name="safeRect">安全区域</param>
- public static void ApplyScreenSafeRect(Rect safeRect)
- {
- CanvasScaler scaler = Desktop.GetComponentInParent<CanvasScaler>();
- if (scaler == null)
- {
- UniLogger.Error($"Not found {nameof(CanvasScaler)} !");
- return;
- }
- // Convert safe area rectangle from absolute pixels to UGUI coordinates
- float rateX = scaler.referenceResolution.x / Screen.width;
- float rateY = scaler.referenceResolution.y / Screen.height;
- float posX = (int)(safeRect.position.x * rateX);
- float posY = (int)(safeRect.position.y * rateY);
- float width = (int)(safeRect.size.x * rateX);
- float height = (int)(safeRect.size.y * rateY);
- float offsetMaxX = scaler.referenceResolution.x - width - posX;
- float offsetMaxY = scaler.referenceResolution.y - height - posY;
- // 注意:安全区坐标系的原点为左下角
- var rectTrans = Desktop.transform as RectTransform;
- rectTrans.offsetMin = new Vector2(posX, posY); //锚框状态下的屏幕左下角偏移向量
- rectTrans.offsetMax = new Vector2(-offsetMaxX, -offsetMaxY); //锚框状态下的屏幕右上角偏移向量
- }
- /// <summary>
- /// 模拟IPhoneX异形屏
- /// </summary>
- public static void SimulateIPhoneXNotchScreen()
- {
- Rect rect;
- if (Screen.height > Screen.width)
- {
- // 竖屏Portrait
- float deviceWidth = 1125;
- float deviceHeight = 2436;
- rect = new Rect(0f / deviceWidth, 102f / deviceHeight, 1125f / deviceWidth, 2202f / deviceHeight);
- }
- else
- {
- // 横屏Landscape
- float deviceWidth = 2436;
- float deviceHeight = 1125;
- rect = new Rect(132f / deviceWidth, 63f / deviceHeight, 2172f / deviceWidth, 1062f / deviceHeight);
- }
- Rect safeArea = new Rect(Screen.width * rect.x, Screen.height * rect.y, Screen.width * rect.width, Screen.height * rect.height);
- ApplyScreenSafeRect(safeArea);
- }
- /// <summary>
- /// 获取窗口堆栈信息
- /// </summary>
- public static void GetWindowInfos(List<WindowInfo> output)
- {
- if (output == null)
- output = new List<WindowInfo>();
- else
- output.Clear();
- for (int i = 0; i < _stack.Count; i++)
- {
- var window = _stack[i];
- WindowInfo info = new WindowInfo();
- info.WindowName = window.WindowName;
- info.WindowLayer = window.WindowLayer;
- info.IsLoadDone = window.IsLoadDone;
- output.Add(info);
- }
- }
- /// <summary>
- /// 获取所有层级下顶部的窗口名称
- /// </summary>
- public static string GetTopWindow()
- {
- if (_stack.Count == 0)
- return string.Empty;
- UIWindow topWindow = _stack[_stack.Count - 1];
- return topWindow.WindowName;
- }
- /// <summary>
- /// 获取指定层级下顶部的窗口名称
- /// </summary>
- public static string GetTopWindow(int layer)
- {
- UIWindow lastOne = null;
- for (int i = 0; i < _stack.Count; i++)
- {
- if (_stack[i].WindowLayer == layer)
- lastOne = _stack[i];
- }
- if (lastOne == null)
- return string.Empty;
- return lastOne.WindowName;
- }
- /// <summary>
- /// 是否有任意窗口正在加载
- /// </summary>
- public static bool IsAnyLoading()
- {
- for (int i = 0; i < _stack.Count; i++)
- {
- var window = _stack[i];
- if (window.IsLoadDone == false)
- return true;
- }
- return false;
- }
- /// <summary>
- /// 查询窗口是否存在
- /// </summary>
- public static bool HasWindow<T>()
- {
- return HasWindow(typeof(T));
- }
- public static bool HasWindow(Type type)
- {
- return IsContains(type.FullName);
- }
- /// <summary>
- /// 异步打开窗口
- /// </summary>
- /// <param name="location">资源定位地址</param>
- /// <param name="userDatas">用户自定义数据</param>
- public static OpenWindowOperation OpenWindowAsync<T>(string location, params System.Object[] userDatas) where T : UIWindow
- {
- return OpenWindowAsync(typeof(T), location, userDatas);
- }
- public static OpenWindowOperation OpenWindowAsync(Type type, string location, params System.Object[] userDatas)
- {
- string windowName = type.FullName;
- // 如果窗口已经存在
- if (IsContains(windowName))
- {
- UIWindow window = GetWindow(windowName);
- Pop(window); //弹出窗口
- Push(window); //重新压入
- window.TryInvoke(OnWindowPrepare, userDatas);
- var operation = new OpenWindowOperation(window.Handle);
- YooAssets.StartOperation(operation);
- return operation;
- }
- else
- {
- UIWindow window = CreateInstance(type);
- Push(window); //首次压入
- window.InternalLoad(location, OnWindowPrepare, userDatas);
- var operation = new OpenWindowOperation(window.Handle);
- YooAssets.StartOperation(operation);
- return operation;
- }
- }
- /// <summary>
- /// 同步打开窗口
- /// </summary>
- /// <typeparam name="T">窗口类</typeparam>
- /// <param name="location">资源定位地址</param>
- /// <param name="userDatas">用户自定义数据</param>
- public static OpenWindowOperation OpenWindowSync<T>(string location, params System.Object[] userDatas) where T : UIWindow
- {
- var operation = OpenWindowAsync(typeof(T), location, userDatas);
- operation.WaitForAsyncComplete();
- return operation;
- }
- public static OpenWindowOperation OpenWindowSync(Type type, string location, params System.Object[] userDatas)
- {
- var operation = OpenWindowAsync(type, location, userDatas);
- operation.WaitForAsyncComplete();
- return operation;
- }
- /// <summary>
- /// 关闭窗口
- /// </summary>
- public static void CloseWindow<T>() where T : UIWindow
- {
- CloseWindow(typeof(T));
- }
- public static void CloseWindow(Type type)
- {
- string windowName = type.FullName;
- UIWindow window = GetWindow(windowName);
- if (window == null)
- return;
- window.InternalDestroy();
- Pop(window);
- OnSortWindowDepth(window.WindowLayer);
- OnSetWindowVisible();
- }
- /// <summary>
- /// 关闭所有窗口
- /// </summary>
- public static void CloseAll()
- {
- for (int i = 0; i < _stack.Count; i++)
- {
- UIWindow window = _stack[i];
- window.InternalDestroy();
- }
- _stack.Clear();
- }
- private static void OnWindowPrepare(UIWindow window)
- {
- OnSortWindowDepth(window.WindowLayer);
- window.InternalCreate();
- window.InternalRefresh();
- OnSetWindowVisible();
- }
- private static void OnSortWindowDepth(int layer)
- {
- int depth = layer;
- for (int i = 0; i < _stack.Count; i++)
- {
- if (_stack[i].WindowLayer == layer)
- {
- _stack[i].Depth = depth;
- depth += 100; //注意:每次递增100深度
- }
- }
- }
- private static void OnSetWindowVisible()
- {
- bool isHideNext = false;
- for (int i = _stack.Count - 1; i >= 0; i--)
- {
- UIWindow window = _stack[i];
- if (isHideNext == false)
- {
- window.Visible = true;
- if (window.IsPrepare && window.FullScreen)
- isHideNext = true;
- }
- else
- {
- window.Visible = false;
- }
- }
- }
- private static UIWindow CreateInstance(Type type)
- {
- UIWindow window = Activator.CreateInstance(type) as UIWindow;
- WindowAttribute attribute = Attribute.GetCustomAttribute(type, typeof(WindowAttribute)) as WindowAttribute;
- if (window == null)
- throw new Exception($"Window {type.FullName} create instance failed.");
- if (attribute == null)
- throw new Exception($"Window {type.FullName} not found {nameof(WindowAttribute)} attribute.");
- window.Init(type.FullName, attribute.WindowLayer, attribute.FullScreen);
- return window;
- }
- private static UIWindow GetWindow(string name)
- {
- for (int i = 0; i < _stack.Count; i++)
- {
- UIWindow window = _stack[i];
- if (window.WindowName == name)
- return window;
- }
- return null;
- }
- private static bool IsContains(string name)
- {
- for (int i = 0; i < _stack.Count; i++)
- {
- UIWindow window = _stack[i];
- if (window.WindowName == name)
- return true;
- }
- return false;
- }
- private static void Push(UIWindow window)
- {
- // 如果已经存在
- if (IsContains(window.WindowName))
- throw new System.Exception($"Window {window.WindowName} is exist.");
- // 获取插入到所属层级的位置
- int insertIndex = -1;
- for (int i = 0; i < _stack.Count; i++)
- {
- if (window.WindowLayer == _stack[i].WindowLayer)
- insertIndex = i + 1;
- }
- // 如果没有所属层级,找到相邻层级
- if (insertIndex == -1)
- {
- for (int i = 0; i < _stack.Count; i++)
- {
- if (window.WindowLayer > _stack[i].WindowLayer)
- insertIndex = i + 1;
- }
- }
- // 如果是空栈或没有找到插入位置
- if (insertIndex == -1)
- {
- insertIndex = 0;
- }
- // 最后插入到堆栈
- _stack.Insert(insertIndex, window);
- }
- private static void Pop(UIWindow window)
- {
- // 从堆栈里移除
- _stack.Remove(window);
- }
- }
- }
|