import { _decorator, Component, Constructor, find, Node, Prefab, instantiate, EventHandler, game } from "cc"; import { ResourcesUtils } from "../../resourceManager/ResourcesUtils"; import { Utils } from "../../utils/Utils"; import { Tips } from "./Tips"; import { Window } from "./Window"; import { WindowOpenMode } from "./WindowOpenMode"; const { ccclass, property } = _decorator; /** * 窗口系统,负责管理窗口,底层运行时自动创建,无需在编辑器中绑定 * @author 袁浩 */ @ccclass('WindowSystem') export class WindowSystem extends Component { @property({ tooltip: "Canvas节点名称" }) public canvasName = "Canvas"; public windowList: Window[] = []; private static thisObject: WindowSystem; start() { game.addPersistRootNode(this.node);//常驻节点 WindowSystem.thisObject = this; } public onWindowOpen(_window: Window) { this.windowList.push(_window); } public onWindowClose(_window: Window) { Utils.removeArrayItem(this.windowList, _window); } public static onWindowOpen(_window: Window) { this.thisObject.onWindowOpen(_window); } /** * 最近打开的窗口 */ public get currentWindow(): Window { return this.windowList[this.windowList.length - 1]; } public destroyWindow(_window: Window) { for (let i = 0; i < _window.openWindowOnClosing.length; i++) { _window.openWindowOnClosing[i].emit([_window]); } if (_window.onClosing.length) { for (let i = 0; i < _window.onClosing.length; i++) { _window.onClosing[i].emit([() => { _window.node.destroy(); Utils.removeArrayItem(this.windowList, _window); }]); } } else { _window.node.destroy(); Utils.removeArrayItem(this.windowList, _window); } } private isLoadding: boolean = false; /** * 打开窗口 * @param prefabPath 预制体路径 * @param openMode 窗口打开模式 * @param params 给窗口传递的参数 * @returns */ public async open(prefabPath: string, openMode: WindowOpenMode, params: any[], onOpening: EventHandler[] = [], onClosing: EventHandler[] = []) { var _window: Window; switch (openMode) { case WindowOpenMode.NotCloseAndAdd: _window = await this.doOpen(prefabPath, params, onOpening, onClosing); break; case WindowOpenMode.NotCloseAndCover: if (this.currentWindow && prefabPath == this.currentWindow.prefabPath) { this.currentWindow.setParams(params); _window = this.currentWindow; } else { _window = await this.doOpen(prefabPath, params, onOpening, onClosing); } break; case WindowOpenMode.CloseAndAdd: this.close(); _window = await this.doOpen(prefabPath, params, onOpening, onClosing); break; case WindowOpenMode.CloseAndCover: if (this.currentWindow && prefabPath == this.currentWindow.prefabPath) { this.currentWindow.setParams(params); _window = this.currentWindow; } else { this.close(); _window = await this.doOpen(prefabPath, params, onOpening, onClosing); } break; default: break; } return _window; } private async doOpen(prefabPath: string, params: any[], onOpening: EventHandler[] = [], onClosing: EventHandler[] = []) { if (this.isLoadding) { return null; } this.isLoadding = true; var prefab = await ResourcesUtils.load(prefabPath, null, this.node); var windowNode = instantiate(prefab); var _window = windowNode.getComponent(Window) || windowNode.addComponent(Window); _window.node.parent = find(this.canvasName); _window.setParams(params); _window.prefabPath = prefabPath; onClosing && (_window.openWindowOnClosing = onClosing); for (let i = 0; i < onOpening.length; i++) { onOpening[i].emit([_window]); } this.isLoadding = false; return _window; } public async showTips(message: string, prefabPath: string = "prefabs/ui/tips") { var _window = await this.open(prefabPath, WindowOpenMode.NotCloseAndAdd, [message]); if (_window) { _window.getComponent(Tips) || _window.addComponent(Tips); } } /** * 关闭窗口 * @param type 指定窗口类型,如果不传则关闭最近打开的窗口 */ public close(type: ui_window | Window | Node = null): void { if (!this.currentWindow) { return; } if (type) { var windowList = this.windowList.concat(); for (let i = 0; i < windowList.length; i++) { const _window = windowList[i]; if (type instanceof Window) { if (type == _window) { this.destroyWindow(_window); } } else if (type instanceof Node) { if (type == _window.node) { this.destroyWindow(_window); } } else if (_window instanceof type) { this.destroyWindow(_window); } } } else { var _window = this.windowList[this.windowList.length - 1]; this.destroyWindow(_window); } } /** * 关闭指定路径的窗口 * @param path 路径,例:Canvas/XXWindow */ public closeByPath(path: string): void { if (!this.currentWindow) { return; } var _windowNode = find(path); _windowNode && this.destroyWindow(_windowNode.getComponent(Window)); } /** * 关闭所有窗口 */ public closeAll() { while (this.windowList.length) { var _window = this.windowList.shift(); this.destroyWindow(_window); } } /** * 最近打开的窗口 */ public static get currentWindow(): Window { return this.thisObject.currentWindow; } /** * 打开窗口 * @param prefabPath 预制体路径 * @param openMode 窗口打开模式 * @param params 给窗口传递的参数 * @returns */ public static async open(prefabPath: string, openMode: WindowOpenMode, params: any[] = [], onOpening: EventHandler[] = [], onClosing: EventHandler[] = []) { return this.thisObject.open(prefabPath, openMode, params, onOpening, onClosing); } /** * 关闭窗口 * @param type 指定窗口类型,如果不传则关闭最近打开的窗口 */ public static close(type: ui_window | Window | Node = null): void { this.thisObject.close(type); } /** * 关闭指定路径的窗口 * @param path 路径,例:Canvas/XXWindow */ public static closeByPath(path: string): void { this.thisObject.closeByPath(path); } /** * 关闭所有窗口 */ public static closeAll() { this.thisObject.closeAll(); } /** * 显示小提示 * @param message */ public static showTips(message: string, prefabPath: string = "prefabs/ui/tips") { this.thisObject.showTips(message, prefabPath); } public static getWindowList(): Window[] { return this.thisObject.windowList.concat(); } public static onWindowClose(_window: Window) { this.thisObject.onWindowClose(_window); } } export type ui_window = Constructor;