import UIBase from "./base/UIBase"; import { SysDefine, PanelType } from "./config/SysDefine"; import ResManager from "../res/ResManager"; import UIMaskMgr from "./UIMaskMgr"; import AdapterManager, { AdaptaterType } from "./AdapterManager"; const {ccclass, property} = cc._decorator; @ccclass export default class UIManager extends cc.Component { private _NoNormal: cc.Node = null; // 全屏显示的UI 挂载结点 private _NoFixed: cc.Node = null; // 固定显示的UI private _NoPopUp: cc.Node = null; // 弹出窗口 private _NoTips: cc.Node = null; // 独立窗体 private _StaCurrentUIPanels:Array = []; // 存储弹出的窗体 private _MapAllUIPanels: {[key: string]: UIBase} = cc.js.createMap(); // 所有的窗体 private _MapCurrentShowUIPanels: {[key: string]: UIBase} = cc.js.createMap(); // 正在显示的窗体(不包括弹窗) private _MapIndependentPanels: {[key: string]: UIBase} = cc.js.createMap(); // 独立窗体 独立于其他窗体, 不受其他窗体的影响 private _LoadingPanel: {[key: string]: boolean} = cc.js.createMap(); // 正在加载的Panel private _currWindowId = ''; public get currWindowId() { return this._currWindowId; } private _currScreenId = ''; public get currScreenId() { return this._currScreenId; } private static instance: UIManager = null; // 单例 public static getInstance(): UIManager { if(this.instance == null) { this.instance = cc.find(SysDefine.SYS_UIROOT_NAME).addComponent(this); cc.director.once(cc.Director.EVENT_AFTER_SCENE_LAUNCH, () => { this.instance = null; }); } return this.instance; } onLoad () { // 初始化结点 this._NoNormal = this.node.getChildByName(SysDefine.SYS_SCREEN_NODE); this._NoFixed = this.node.getChildByName(SysDefine.SYS_FIXEDUI_NODE); this._NoPopUp = this.node.getChildByName(SysDefine.SYS_POPUP_NODE); this._NoTips = this.node.getChildByName(SysDefine.SYS_TOPTIPS_NODE); } start() { } /** */ public getComponentByUid(uid: string) { return this._MapAllUIPanels[uid]; } /** * 重要方法 加载显示一个UIPanel * @param prefabPath * @param obj 初始化信息, 可以不要 */ public async openUIPanel(prefabPath: string, ...params: any) { if(prefabPath === "" || prefabPath == null) return ; if(this.checkUIPanelIsShowing(prefabPath) || this.checkUIPanelIsLoading(prefabPath)) { cc.warn(`${prefabPath}窗体已经在显示,或者正在加载中!`); return null; } let uiBase = await this.loadPanelsToAllUIPanelsCatch(prefabPath); if(uiBase == null) { cc.warn(`${prefabPath}未加载!`); return null; } switch(uiBase.panelType) { case PanelType.Screen: await this.enterUIPanelsAndHideOther(prefabPath, ...params); break; case PanelType.FixedUI: await this.loadUIToCurrentCache(prefabPath, ...params); break; case PanelType.PopUp: await this.pushUIPanelToStack(prefabPath, ...params); break; case PanelType.TopTips: // 独立显示 await this.loadUIPanelsToIndependent(prefabPath, ...params); break; } return uiBase; } /** * 重要方法 关闭一个UIPanel * @param prefabPath */ public async closeUIPanel(prefabPath: string) { if(prefabPath == "" || prefabPath == null) return ; let UIBase = this._MapAllUIPanels[prefabPath]; if(UIBase == null) return true; switch(UIBase.panelType) { case PanelType.Screen: await this.exitUIPanelsAndDisplayOther(prefabPath); break; case PanelType.FixedUI: // 普通模式显示 await this.exitUIPanels(prefabPath); break; case PanelType.PopUp: await this.popUIPanel(); break; case PanelType.TopTips: await this.exitIndependentPanels(prefabPath); break; } // 判断是否销毁该窗体 if(UIBase.canDestory) { this.destoryPanel(UIBase, prefabPath); } return true; } /** * 从全部的UI窗口中加载, 并挂载到结点上 */ private async loadPanelsToAllUIPanelsCatch(prefabPath: string) { let baseUIResult = this._MapAllUIPanels[prefabPath]; // 判断窗体不在mapAllUIPanels中, 也不再loadingPanels中 if (baseUIResult == null && !this._LoadingPanel[prefabPath]) { //加载指定名称的“UI窗体 this._LoadingPanel[prefabPath] = true; baseUIResult = await this.loadUIPanel(prefabPath); this._LoadingPanel[prefabPath] = false; delete this._LoadingPanel[prefabPath]; } return baseUIResult; } /** * 从resources中加载 * @param prefabPath */ //加载UI,自动添加的层级 private async loadUIPanel(PrefabPath: string,parent?:cc.Node) { if(PrefabPath == "" || PrefabPath == null){ return ; } let node = await ResManager.inst.loadPrefab(PrefabPath); if(!node) { return ; } // 初始化窗体名称 let baseUI = node.getComponent(UIBase); node.active = false; switch(baseUI.panelType) { case PanelType.Screen: UIManager.getInstance()._NoNormal.addChild(node); break; case PanelType.FixedUI: UIManager.getInstance()._NoFixed.addChild(node); break; case PanelType.PopUp: UIManager.getInstance()._NoPopUp.addChild(node); break; case PanelType.TopTips: UIManager.getInstance()._NoTips.addChild(node); break; default: ResManager.inst.destoryPrefab(baseUI) return; } this._MapAllUIPanels[PrefabPath] = baseUI; return baseUI } /** * 加载到缓存中, * @param prefabPath */ private async loadUIToCurrentCache(prefabPath: string, ...params: any) { let UIBase: UIBase = null; let UIBaseFromAllCache: UIBase = null; UIBase = this._MapCurrentShowUIPanels[prefabPath]; if(UIBase != null) return ; // 要加载的窗口正在显示 UIBaseFromAllCache = this._MapAllUIPanels[prefabPath]; if(UIBaseFromAllCache != null) { await UIBaseFromAllCache._preInit(); this._MapCurrentShowUIPanels[prefabPath] = UIBaseFromAllCache; UIBaseFromAllCache.onShow(...params); await this.showPanel(UIBaseFromAllCache); } } /** * 加载到栈中 * @param prefabPath */ private async pushUIPanelToStack(prefabPath: string, ...params: any) { if(this._StaCurrentUIPanels.length > 0) { let topUIPanel = this._StaCurrentUIPanels[this._StaCurrentUIPanels.length-1]; } let baseUI = this._MapAllUIPanels[prefabPath]; if(baseUI == null) return ; await baseUI._preInit(); // 加入栈中, 同时设置其zIndex 使得后进入的窗体总是显示在上面 this._StaCurrentUIPanels.push(baseUI); baseUI.node.zIndex = this._StaCurrentUIPanels.length; baseUI.onShow(...params); this._currWindowId = baseUI.uid; UIMaskMgr.inst.checkMaskWindow(this._StaCurrentUIPanels); await this.showPanel(baseUI); } /** * 加载时, 关闭其他窗口 */ private async enterUIPanelsAndHideOther(prefabPath: string, ...params: any) { let UIBase = this._MapCurrentShowUIPanels[prefabPath]; if(UIBase != null) return ; // 隐藏其他窗口 for(let key in this._MapCurrentShowUIPanels) { await this._MapCurrentShowUIPanels[key].closeUIPanel(); } this._StaCurrentUIPanels.forEach(async uiPanel => { await uiPanel.closeUIPanel(); }); let UIBaseFromAll = this._MapAllUIPanels[prefabPath]; if(UIBaseFromAll == null) return ; AdapterManager.inst.adapatByType(AdaptaterType.FullScreen, UIBaseFromAll.node); await UIBaseFromAll._preInit(); this._MapCurrentShowUIPanels[prefabPath] = UIBaseFromAll; UIBaseFromAll.onShow(...params); this._currScreenId = UIBaseFromAll.uid; await this.showPanel(UIBaseFromAll); } /** 加载到独立map中 */ private async loadUIPanelsToIndependent(prefabPath: string, ...params: any) { let UIBase = this._MapAllUIPanels[prefabPath]; if(UIBase == null) return ; await UIBase._preInit(); this._MapIndependentPanels[prefabPath] = UIBase; UIBase.onShow(...params); await this.showPanel(UIBase); } /** * --------------------------------- 关闭窗口 -------------------------- */ /** * 关闭一个UIPanel * @param prefabPath */ private async exitUIPanels(prefabPath: string) { let UIBase = this._MapAllUIPanels[prefabPath]; if(UIBase == null) return ; UIBase.onHide(); await this.hidePanel(UIBase); this._MapCurrentShowUIPanels[prefabPath] = null; delete this._MapCurrentShowUIPanels[prefabPath]; } private async popUIPanel() { if(this._StaCurrentUIPanels.length >= 1) { let topUIPanel = this._StaCurrentUIPanels.pop(); topUIPanel.onHide(); UIMaskMgr.inst.checkMaskWindow(this._StaCurrentUIPanels); await this.hidePanel(topUIPanel); this._currWindowId = this._StaCurrentUIPanels.length > 0 ? this._StaCurrentUIPanels[this._StaCurrentUIPanels.length-1].uid : ''; } } private async exitUIPanelsAndDisplayOther(prefabPath: string) { if(prefabPath == "" || prefabPath == null) return ; let UIBase = this._MapCurrentShowUIPanels[prefabPath]; if(UIBase == null) return ; UIBase.onHide(); await this.hidePanel(UIBase); this._MapCurrentShowUIPanels[prefabPath] = null; delete this._MapCurrentShowUIPanels[prefabPath]; } private async exitIndependentPanels(prefabPath: string) { let UIBase = this._MapAllUIPanels[prefabPath]; if(UIBase == null) return ; UIBase.onHide(); await this.hidePanel(UIBase); this._MapIndependentPanels[prefabPath] = null; delete this._MapIndependentPanels[prefabPath]; } private async showPanel(baseUI: UIBase) { baseUI.node.active = true; await baseUI.showAnimation(); } private async hidePanel(baseUI: UIBase) { await baseUI.hideAnimation(); baseUI.node.active = false; } /** 销毁 */ private destoryPanel(UIBase: UIBase, prefabPath: string) { UIBase.onRemove() ResManager.inst.destoryPrefab(UIBase) // 从allmap中删除 this._MapAllUIPanels[prefabPath] = null; delete this._MapAllUIPanels[prefabPath]; } /** 窗体是否正在显示 */ public checkUIPanelIsShowing(prefabPath: string) { let UIBases = this._MapAllUIPanels[prefabPath]; if (UIBases == null) { return false; } return UIBases.node.active; } /** 窗体是否正在加载 */ public checkUIPanelIsLoading(prefabPath: string) { let UIBase = this._LoadingPanel[prefabPath]; return !!UIBase; } }