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