| 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);
 
- 		}
 
- 	}
 
- }
 
 
  |