using System.Collections; using System.Collections.Generic; using UnityEngine; using System; namespace vnxbqy.UI { public class WindowCenter : SingletonMonobehaviour { public event Action windowBeforeOpenEvent; public event Action windowAfterOpenEvent; public event Action windowBeforeCloseEvent; public event Action windowAfterCloseEvent; public event Action jumpWindowCloseEvent; UIRoot m_UIRoot; public UIRoot uiRoot { get { if (m_UIRoot == null) { var prefab = BuiltInLoader.LoadPrefab("UIRoot"); var instance = GameObject.Instantiate(prefab, Vector3.zero, Quaternion.identity); instance.name = "UIRoot"; m_UIRoot = instance.GetComponent(); if (Application.isPlaying) { GameObject.DontDestroyOnLoad(instance); } } return m_UIRoot; } } WindowAsyncLoad m_AnyncLoad; public WindowAsyncLoad asyncLoad { get { if (m_AnyncLoad == null) { var gameObject = new GameObject("WindowAnyncLoad"); m_AnyncLoad = gameObject.AddMissingComponent(); GameObject.DontDestroyOnLoad(gameObject); } return m_AnyncLoad; } } Windows windows = new Windows(); List openCommands = new List(); List closeCommands = new List(); public T Get() where T : Window { T win = null; if (TryGetWindow(out win)) { return win; } else { DebugEx.LogFormat("没有找到窗口:{0}", typeof(T).Name); return null; } } public Window Get(string name) { WindowTrim(name); if (windows.ContainsKey(name)) { return windows[name]; } else { return null; } } public WindowType GetWindowType(string name) { return windows.GetWindowType(name); } public void OpenFromLocal(int functionOrder = 0) where T : Window { var command = new OpenCommand() { name = typeof(T).Name, sync = true, playAnimatioin = false, fromBuiltIn = true, functionOrder = functionOrder }; PushOpenCommand(command); } public void OpenFromLocal(string name) { var command = new OpenCommand() { name = name, sync = true, playAnimatioin = false, fromBuiltIn = true, functionOrder = 0 }; PushOpenCommand(command); } public void Open(bool forceSync = false, int functionOrder = 0, string fixParentName = "") where T : Window { var command = new OpenCommand() { name = typeof(T).Name, sync = forceSync, playAnimatioin = true, fromBuiltIn = false, functionOrder = functionOrder, fixParentName = fixParentName }; PushOpenCommand(command); } public void Open(string name, bool forceSync = false, int functionOrder = 0, string fixParentName = "") { var command = new OpenCommand() { name = name, sync = forceSync, playAnimatioin = true, fromBuiltIn = false, functionOrder = functionOrder, fixParentName = fixParentName }; PushOpenCommand(command); } #if UNITY_EDITOR public Dictionary openWinNames = new Dictionary(); #endif private void PushOpenCommand(OpenCommand command) { #if UNITY_EDITOR //用于工具导出打开的界面的图片 openWinNames[command.name] = command.fromBuiltIn; #endif DebugEx.LogFormat("打开窗口:{0} ", command.name); var name = command.name; var index = closeCommands.FindIndex((x) => { return x.name == name; }); if (index != -1) { closeCommands.RemoveAt(index); } var exist = openCommands.Exists((x) => { return x.name == name; }); if (!exist) { openCommands.Add(command); } } public void Close() where T : Window { PushCloseCommand(new CloseCommand() { name = typeof(T).Name, }); } public void Close(string name) { if (WindowConfig.IsChildWindow(name)) { CloseImmediately(name); } else { PushCloseCommand(new CloseCommand() { name = name, }); } } public void CloseImmediately(string name) { Window window; if (windows.TryGetValue(name, out window)) { if (window.windowState != Window.WindowState.Closed) { window.CloseImmediately(); } } } private void PushCloseCommand(CloseCommand command) { var name = command.name; var index = openCommands.FindIndex((x) => { return x.name == name; }); if (index != -1) { openCommands.RemoveAt(index); } var exist = closeCommands.Exists((x) => { return x.name == name; }); if (!exist) { closeCommands.Add(command); } } public List GetAll() { return new List(windows.Keys); } public void CloseAll(CloseAllIgnoreType ignoreType = CloseAllIgnoreType.BaseAndCustom) { for (var i = windows.Keys.Count - 1; i >= 0; i--) { var name = windows.Keys[i]; var window = windows[name]; if (window == null) { continue; } var isIgnore = false; switch (ignoreType) { case CloseAllIgnoreType.Base: isIgnore = window.windowInfo.windowType <= WindowType.Base; break; case CloseAllIgnoreType.BaseAndCustom: isIgnore = window.windowInfo.windowType <= WindowType.Base || CloseAllIgnoreWindowConfig.IsIgnore(name); break; case CloseAllIgnoreType.System: isIgnore = window.windowInfo.windowType >= WindowType.System; break; case CloseAllIgnoreType.Custom: isIgnore = CloseAllIgnoreWindowConfig.IsIgnore(name); break; case CloseAllIgnoreType.SystemAndCustom: isIgnore = window.windowInfo.windowType >= WindowType.System || CloseAllIgnoreWindowConfig.IsIgnore(name); break; } isIgnore = isIgnore || WindowConfig.IsChildWindow(name); if (!isIgnore) { if (window.windowState == Window.WindowState.Opened || window.windowState == Window.WindowState.Opening) { Close(name); } } } asyncLoad.StopAllTasks(); } public void CloseOthers() where T : Window { for (var i = windows.Keys.Count - 1; i >= 0; i--) { var name = windows.Keys[i]; var window = windows[name]; if (window == null || window is T) { continue; } var isIgnore = WindowConfig.IsChildWindow(name); if (isIgnore) { continue; } if (window != null) { if (window.windowState == Window.WindowState.Opened || window.windowState == Window.WindowState.Opening) { Close(name); } } } asyncLoad.StopAllTasks(); } public void CloseOthers(List windowNames, CloseAllIgnoreType ignoreType) { for (var i = windows.Keys.Count - 1; i >= 0; i--) { var name = windows.Keys[i]; var window = windows[name]; if (window == null) { continue; } var isIgnore = false; switch (ignoreType) { case CloseAllIgnoreType.Base: isIgnore = windowNames.Contains(name) || window.windowInfo.windowType <= WindowType.Base; break; case CloseAllIgnoreType.BaseAndCustom: isIgnore = windowNames.Contains(name) || window.windowInfo.windowType <= WindowType.Base || CloseAllIgnoreWindowConfig.IsIgnore(name); break; case CloseAllIgnoreType.System: isIgnore = windowNames.Contains(name) || window.windowInfo.windowType >= WindowType.System; break; case CloseAllIgnoreType.Custom: isIgnore = windowNames.Contains(name) || CloseAllIgnoreWindowConfig.IsIgnore(name); break; case CloseAllIgnoreType.SystemAndCustom: isIgnore = windowNames.Contains(name) || window.windowInfo.windowType >= WindowType.System || CloseAllIgnoreWindowConfig.IsIgnore(name); break; } isIgnore = isIgnore || WindowConfig.IsChildWindow(name); if (!isIgnore) { if (window.windowState == Window.WindowState.Opened || window.windowState == Window.WindowState.Opening) { Close(name); } } } asyncLoad.StopAllTasks(); } public void DestoryWinsByStage(WindowStage windowStage) { switch (windowStage) { case WindowStage.Launch: DestroyWin(); DestroyWin(); DestroyWin(); if (!AssetSource.uiFromEditor) { AssetBundleUtility.Instance.UnloadAssetBundle("builtin/prefabs", true, false); } break; case WindowStage.Login: DestroyWin(); DestroyWin(); UILoader.UnLoadPriorityWindow("LoginWin"); break; case WindowStage.SelectRole: DestroyWin(); DestroyWin(); UILoader.UnLoadPriorityWindow("CreateRoleWin"); UILoader.UnLoadPriorityWindow("SelectRoleWin"); UILoader.UnLoadPriorityWindow("LaunchBackGroundWin"); break; default: break; } UnLoadAssetBundle(windowStage); } public void DestroyWin() where T : Window { DestroyWin(typeof(T).Name); } public void DestroyWin(string name) { if (windows.ContainsKey(name)) { var win = windows[name]; win.CloseImmediately(); GameObject.Destroy(win.gameObject, 0.3f); MonoBehaviour.Destroy(win, 0.3f); windows[name] = null; windows.Remove(name); } else { DebugEx.LogFormat("{0} 窗口无法获得!", name); } } public void UnLoadAssetBundle(WindowStage windowStage) { if (!AssetSource.uiFromEditor) { switch (windowStage) { case WindowStage.Launch: break; case WindowStage.Login: AssetBundleUtility.Instance.UnloadAsset("ui/prioritywindow", "LoginWin"); AssetBundleUtility.Instance.UnloadAsset("ui/prioritywindow", "ServerListWin"); break; case WindowStage.SelectRole: AssetBundleUtility.Instance.UnloadAsset("ui/prioritywindow", "CreateRoleWin"); AssetBundleUtility.Instance.UnloadAsset("ui/prioritywindow", "SelectRoleWin"); break; default: break; } } } public bool IsOpen() where T : Window { T win = null; if (TryGetWindow(out win)) { var open = win.windowState == Window.WindowState.Opened || win.windowState == Window.WindowState.Opening; return open; } else { return false; } } public bool IsOpen(string name) { if (windows.ContainsKey(name) && windows[name] != null) { var window = windows[name]; return window.windowState == Window.WindowState.Opened || window.windowState == Window.WindowState.Opening; } else { return false; } } public bool ExistAnyFullScreenOrMaskWin() { var exist = false; foreach (var name in windows.Keys) { var window = windows[name]; if (window.windowInfo.needMask || window.windowInfo.fullScreen) { if (window.windowState == Window.WindowState.Opened || window.windowState == Window.WindowState.Opening) { exist = true; break; } } } return exist; } /// /// 是否存在大于或等于这个层级的全屏或有模糊背景的界面 /// /// /// public bool ExistAnyFullScreenOrMaskWinLEqual(WindowType windowType) { var exist = false; foreach (var name in windows.Keys) { var window = windows[name]; if ((window.windowInfo.needMask || window.windowInfo.fullScreen) && window.windowInfo.windowType >= windowType) { if (window.windowState == Window.WindowState.Opened || window.windowState == Window.WindowState.Opening) { exist = true; break; } } } return exist; } internal void NotifyBeforeOpen(T window) where T : Window { //if (ConfigInitiator.done && window is not MainInterfaceWin && !WindowJumpMgr.Instance.IsJumpState) // CalcMainInterfaceWin(); if (windowBeforeOpenEvent != null) { windowBeforeOpenEvent(window); } } internal void NotifyAfterOpen(T window) where T : Window { if (windowAfterOpenEvent != null) { windowAfterOpenEvent(window); } } internal void NotifyBeforeClose(T window) where T : Window { if (windowBeforeCloseEvent != null) { windowBeforeCloseEvent(window); } } internal void NotifyAfterClose(T window) where T : Window { if (windowAfterCloseEvent != null) { windowAfterCloseEvent(window); } } internal void JumpNotifyAfterClose(T window) where T : Window { //if (ConfigInitiator.done && window is not MainInterfaceWin && !WindowJumpMgr.Instance.IsJumpState) // CalcMainInterfaceWin(); checkMainWin = true; if (jumpWindowCloseEvent != null) { jumpWindowCloseEvent(window); } } private bool TryGetWindow(out T win) where T : Window { var name = typeof(T).Name; Window window = null; if (TryGetWindow(name, out window)) { win = windows[name] as T; return win != null; } else { win = null; return false; } } private bool TryGetWindow(string name, out Window win) { WindowTrim(name); if (windows.ContainsKey(name)) { win = windows[name]; return win != null; } else { win = null; return false; } } private void WindowTrim(string name) { if (windows.ContainsKey(name)) { if (windows[name] == null || windows[name].gameObject == null) { windows.Remove(name); } } } float checkTimer = 0f; private void LateUpdate() { var checkMainWinImmedidately = closeCommands.Count + openCommands.Count > 0; if (checkMainWin) { checkMainWinImmedidately = true; checkMainWin = false; } while (closeCommands.Count > 0) { var command = closeCommands[0]; closeCommands.RemoveAt(0); Window window = null; if (windows.TryGetValue(command.name, out window)) { if (window.windowState != Window.WindowState.Closed) { window.CloseImmediately(); } } asyncLoad.StopTask(command.name); } while (openCommands.Count > 0) { var command = openCommands[0]; openCommands.RemoveAt(0); Window window = null; if (windows.TryGetValue(command.name, out window)) { if (window.windowState == Window.WindowState.Closed) { window.playAnimation = command.playAnimatioin; window.functionOrder = command.functionOrder; window.fixParentName = command.fixParentName; window.Open(); } else { DebugEx.LogFormat("{0} 窗口已经打开!", command.name); } } else { ExecuteFirstOpen(command); } } checkTimer += checkMainWinImmedidately ? 1f : Time.deltaTime; if (checkTimer > 0.2f) { checkTimer = 0f; CalcMainInterfaceWin(); } } bool checkMainWin = false; //主界面的开关默认处理 public void CalcMainInterfaceWin() { if (!StageLoad.Instance.isLoading) { var exceptOpen = StageLoad.Instance.stageType == Stage.E_StageType.Dungeon && !ExistAnyFullScreenOrMaskWinLEqual(WindowType.Base) && !IsOpen("DefaultDialogueBoxWin") && !IsOpen("DialogueDuidanceWin") && !IsOpen("TaskBoxBGMWin") && !IsOpen("WelcomeWin") && !IsOpen("HazyRegionDialogueWin") && !IsOpen("NormalDialogueWin") && !IsOpen("GuideDialogueWin"); if (exceptOpen != IsOpen("MainInterfaceWin") && windows.ContainsKey("MainInterfaceWin")) { if (exceptOpen) { windows["MainInterfaceWin"].Open(); } else { windows["MainInterfaceWin"].CloseImmediately(); } } } } private void ExecuteFirstOpen(OpenCommand command) { GetWindowPrefab(command, (bool ok, GameObject prefab) => { if (ok) { CreateWindowInstance(command, prefab); Window window = null; if (windows.TryGetValue(command.name, out window)) { window.playAnimation = command.playAnimatioin; window.functionOrder = command.functionOrder; window.fixParentName = command.fixParentName; window.Open(); } } }); } private void GetWindowPrefab(OpenCommand command, Action callBack) { if (command.sync) { var name = command.name; var fromBuiltIn = command.fromBuiltIn; var prefab = fromBuiltIn ? BuiltInLoader.LoadPrefab(name) : UILoader.LoadWindow(name); if (callBack != null) { callBack(prefab != null, prefab); } } else { var name = command.name; var task = new WindowAsyncLoad.Task(name, (bool ok, UnityEngine.Object @object) => { var prefab = @object as GameObject; if (callBack != null) { callBack(prefab != null, prefab); } }); asyncLoad.PushTask(task); } } private void CreateWindowInstance(OpenCommand command, GameObject prefab) { var name = command.name; Window window = null; if (!windows.ContainsKey(name)) { prefab.SetActive(false); var instance = GameObject.Instantiate(prefab); if (AssetSource.uiFromEditor) { prefab.SetActive(true); } if (command.fromBuiltIn) { BuiltInLoader.UnLoadPrefab(name); } else { UILoader.UnLoadWindowAsset(name); } window = instance.GetComponent(); instance.name = name; if (window != null) { windows[name] = window; } else { Debug.LogFormat("无法获得 {0} 的资源!", name); } } } public struct OpenCommand { public string name; public bool sync; public int functionOrder; public bool playAnimatioin; public bool fromBuiltIn; public string fixParentName; } public struct CloseCommand { public string name; } public enum WindowStage { Launch, Login, SelectRole, Other, } public enum CloseAllIgnoreType { Base = 1, System = 2, Custom = 3, BaseAndCustom = 4, SystemAndCustom = 5, } class Windows { Dictionary windows = new Dictionary(); List windowKeys = new List(); public Window this[string key] { get { return windows[key]; } set { windows[key] = value; if (!windowKeys.Contains(key)) { windowKeys.Add(key); } } } public List Keys { get { return windowKeys; } } public bool ContainsKey(string key) { return windowKeys.Contains(key); } public bool TryGetValue(string key, out Window window) { return windows.TryGetValue(key, out window); } public void Remove(string key) { windows.Remove(key); windowKeys.Remove(key); } public WindowType GetWindowType(string key) { if (windows.ContainsKey(key)) { return windows[key].windowInfo.windowType; } else { return WindowType.Flag; } } } } }