From 92e8ccbe9bfe21c54af0b9e067aab215da4ad0d9 Mon Sep 17 00:00:00 2001 From: dgflash Date: Wed, 10 Sep 2025 18:35:44 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84GUI=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=89=93=E5=BC=80=E7=95=8C=E9=9D=A2=E4=B8=8E=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E7=9A=84=E5=8F=82=E6=95=B0=EF=BC=8C=E6=96=B9?= =?UTF-8?q?=E4=BE=BF=E5=90=8E=E7=BB=AD=E6=89=A9=E5=B1=95=E6=96=B0=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E8=80=8C=E4=BF=9D=E6=8C=81=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E4=B8=8D=E5=8F=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/core/gui/layer/LayerDialog.ts | 73 +++++---- assets/core/gui/layer/LayerManager.ts | 101 +++++------- assets/core/gui/layer/LayerPopup.ts | 20 +-- assets/core/gui/layer/LayerUI.ts | 205 +++++++++++++----------- assets/core/gui/layer/LayerUIElement.ts | 90 +++++------ assets/core/gui/layer/UIConfig.ts | 2 +- assets/module/common/CCComp.ts | 7 +- assets/module/common/CCVMParentComp.ts | 7 +- assets/module/common/GameComponent.ts | 14 +- assets/module/common/ModuleUtil.ts | 134 +++------------- 10 files changed, 265 insertions(+), 388 deletions(-) diff --git a/assets/core/gui/layer/LayerDialog.ts b/assets/core/gui/layer/LayerDialog.ts index 60d0ee4..bc80767 100644 --- a/assets/core/gui/layer/LayerDialog.ts +++ b/assets/core/gui/layer/LayerDialog.ts @@ -4,9 +4,9 @@ * @LastEditors: dgflash * @LastEditTime: 2023-07-24 17:14:57 */ - +import { Node } from "cc"; import { LayerPopUp } from "./LayerPopup"; -import { UICallbacks, UIParams } from "./LayerUIElement"; +import { UIParam, UIState } from "./LayerUIElement"; import { UIConfig } from "./UIConfig"; /** 模式弹窗数据 */ @@ -16,9 +16,7 @@ type DialogParam = { /** 窗口配置 */ config: UIConfig; /** 窗口附加参数 */ - params?: any; - /** 窗口回调 */ - callbacks?: UICallbacks; + params?: UIParam; } /* @@ -27,54 +25,55 @@ type DialogParam = { export class LayerDialog extends LayerPopUp { /** 窗口调用参数队列 */ private params: Array = []; + /** 当前打开的界面 */ + private current: Node = null!; - add(uiid: string, config: UIConfig, params?: any, callbacks?: UICallbacks) { - // 控制同一时间只能显示一个模式窗口 - if (this.ui_nodes.size > 0) { - this.params.push({ - uiid: uiid, - config: config, - params: params, - callbacks: callbacks, - }); - return; - } - - this.show(uiid, config, params, callbacks); + /** + * 添加模式窗口 + * 1. 同时添加多个模式窗口时,第一个之后的窗口会先队列起来,在第一个关闭后在加载与显示第二个;同时方法返回节点保持只返回当前显示的界面节点 + */ + add(uiid: string, config: UIConfig, params?: UIParam): Promise { + return new Promise(async (resolve, reject) => { + // 控制同一时间只能显示一个模式窗口 + if (this.ui_nodes.size > 0) { + this.params.push({ + uiid: uiid, + config: config, + params: params + }); + resolve(this.current); + } + else { + this.current = await this.showDialog(uiid, config, params); + resolve(this.current); + } + }); } /** 显示模式弹窗 */ - private show(uiid: string, config: UIConfig, params?: any, callbacks?: UICallbacks) { - let uip = this.ui_cache.get(config.prefab); - if (uip == null) { - uip = new UIParams(); - uip.uiid = uiid; - uip.valid = true; - uip.config = config; - } - - uip.params = params || {}; - uip.callbacks = callbacks ?? {}; - this.ui_nodes.set(uip.config.prefab, uip); - - this.load(uip, config.bundle); + private showDialog(uiid: string, config: UIConfig, param?: UIParam): Promise { + return new Promise(async (resolve, reject) => { + let state = this.initUIConfig(uiid, config, param); + let node = await this.load(state, config.bundle); + resolve(node); + }); } - protected onCloseWindow(uip: UIParams) { - super.onCloseWindow(uip); + protected uiClose(state: UIState) { + super.uiClose(state); setTimeout(this.next.bind(this), 0); } - protected closeUI() { + protected closeBlack() { if (this.params.length == 0) { - super.closeUI(); + super.closeBlack(); } } private next() { if (this.params.length > 0) { let param = this.params.shift()!; - this.show(param.uiid, param.config, param.params, param.callbacks); + this.showDialog(param.uiid, param.config, param.params); } } } \ No newline at end of file diff --git a/assets/core/gui/layer/LayerManager.ts b/assets/core/gui/layer/LayerManager.ts index aa4ea04..3be745e 100644 --- a/assets/core/gui/layer/LayerManager.ts +++ b/assets/core/gui/layer/LayerManager.ts @@ -9,7 +9,7 @@ import { LayerHelper } from "./LayerHelper"; import { LayerNotify } from "./LayerNotify"; import { LayerPopUp } from "./LayerPopup"; import { LayerUI } from "./LayerUI"; -import { LayerUIElement, UICallbacks } from "./LayerUIElement"; +import { LayerUIElement, UIParam } from "./LayerUIElement"; import { UIConfig } from "./UIConfig"; /** 界面层级管理器 */ @@ -171,13 +171,13 @@ export class LayerManager { this.notify.waitClose(); } + /** 获取界面信息 */ private getInfo(uiid: Uiid): { key: string; config: UIConfig } { let key = ""; let config: UIConfig = null!; // 界面配置 if (typeof uiid === 'object') { - if (uiid.bundle == null) uiid.bundle = resLoader.defaultBundleName; key = uiid.bundle + "_" + uiid.prefab; config = gui.internal.getConfig(key); if (config == null) { @@ -205,8 +205,7 @@ export class LayerManager { /** * 同步打开一个窗口 * @param uiid 窗口唯一编号 - * @param uiArgs 窗口参数 - * @param callbacks 回调对象 + * @param param 窗口参数 * @example var uic: UICallbacks = { onAdded: (node: Node, params: any) => { @@ -218,50 +217,43 @@ export class LayerManager { }; oops.gui.open(UIID.Loading, null, uic); */ - open(uiid: Uiid, uiArgs: any = null, callbacks?: UICallbacks): void { + open(uiid: Uiid, param?: UIParam): Promise { + return new Promise(async (resolve, reject) => { + let info = this.getInfo(uiid); + let layer = this.uiLayers.get(info.config.layer); + if (layer) { + let node = await layer.add(info.key, info.config, param); + resolve(node); + } + else { + console.error(`打开编号为【${uiid}】的界面失败,界面层不存在`); + } + }); + } + + /** 显示指定界面 */ + show(uiid: Uiid) { let info = this.getInfo(uiid); let layer = this.uiLayers.get(info.config.layer); if (layer) { - layer.add(info.key, info.config, uiArgs, callbacks); + layer.show(info.config.prefab); } else { console.error(`打开编号为【${uiid}】的界面失败,界面层不存在`); } } - /** - * 异步打开一个窗口 - * @param uiid 窗口唯一编号 - * @param uiArgs 窗口参数 - * @example - * var node = await oops.gui.openAsync(UIID.Loading); - */ - async openAsync(uiid: Uiid, uiArgs: any = null): Promise { - return new Promise((resolve, reject) => { - const callbacks: UICallbacks = { - onAdded: (node: Node, params: any) => { - resolve(node); - }, - onLoadFailure: () => { - resolve(null); - } - }; - this.open(uiid, uiArgs, callbacks); - }); - } - /** * 移除指定标识的窗口 * @param uiid 窗口唯一标识 - * @param isDestroy 移除后是否释放(默认释放内存) * @example * oops.gui.remove(UIID.Loading); */ - remove(uiid: Uiid, isDestroy: boolean = true) { + remove(uiid: Uiid) { let info = this.getInfo(uiid); let layer = this.uiLayers.get(info.config.layer); if (layer) { - layer.remove(info.config.prefab, isDestroy); + layer.remove(info.config.prefab); } else { console.error(`移除编号为【${uiid}】的界面失败,界面层不存在`); @@ -271,25 +263,24 @@ export class LayerManager { /** * 通过界面节点移除 * @param node 窗口节点 - * @param isDestroy 移除后是否释放资源(默认释放内存) * @example * oops.gui.removeByNode(cc.Node); */ - removeByNode(node: Node, isDestroy: boolean = true) { + removeByNode(node: Node) { if (node instanceof Node) { let comp = node.getComponent(LayerUIElement); - if (comp && comp.params) { + if (comp && comp.state) { // 释放显示的界面 if (node.parent) { - let uiid = gui.internal.getConfig(comp.params.uiid); - this.remove(uiid, isDestroy); + let uiid = gui.internal.getConfig(comp.state.uiid); + this.remove(uiid); } // 释放缓存中的界面 - else if (isDestroy) { - let layer = this.uiLayers.get(comp.params.config.layer); + else { + let layer = this.uiLayers.get(comp.state.config.layer); if (layer) { // @ts-ignore 注:不对外使用 - layer.removeCache(comp.params.config.prefab); + layer.removeCache(comp.state.config.prefab); } } } @@ -303,34 +294,14 @@ export class LayerManager { /** * 场景替换 * @param removeUiId 移除场景编号 - * @param openUiId 新打开场景编号 - * @param uiArgs 新打开场景参数 + * @param openUiid 新打开场景编号 + * @param param 新打开场景参数 */ - replace(removeUiId: Uiid, openUiId: Uiid, uiArgs: any = null) { - const callbacks: UICallbacks = { - onAdded: (node: Node, params: any) => { - this.remove(removeUiId); - } - }; - this.open(openUiId, uiArgs, callbacks); - } - - /** - * 异步场景替换 - * @param removeUiId 移除场景编号 - * @param openUiId 新打开场景编号 - * @param uiArgs 新打开场景参数 - */ - replaceAsync(removeUiId: Uiid, openUiId: Uiid, uiArgs: any = null): Promise { - return new Promise(async (resolve, reject) => { - const node = await this.openAsync(openUiId, uiArgs); - if (node) { - this.remove(removeUiId); - resolve(node); - } - else { - resolve(null); - } + replace(removeUiId: Uiid, openUiid: Uiid, param?: UIParam): Promise { + return new Promise(async (resolve, reject) => { + let node = await this.open(openUiid, param); + this.remove(removeUiId); + resolve(node); }); } diff --git a/assets/core/gui/layer/LayerPopup.ts b/assets/core/gui/layer/LayerPopup.ts index 95d4d63..70c3479 100644 --- a/assets/core/gui/layer/LayerPopup.ts +++ b/assets/core/gui/layer/LayerPopup.ts @@ -7,7 +7,7 @@ import { BlockInputEvents, EventTouch, Node } from "cc"; import { ViewUtil } from "../../utils/ViewUtil"; import { PromptResType } from "../GuiEnum"; import { LayerUI } from "./LayerUI"; -import { UIParams } from "./LayerUIElement"; +import { UIState } from "./LayerUIElement"; import { UIConfig } from "./UIConfig"; /* 弹窗层,允许同时弹出多个窗口 */ @@ -32,12 +32,12 @@ export class LayerPopUp extends LayerUI { if (this.mask) this.mask.setSiblingIndex(this.children.length - 2); } - protected showUi(uip: UIParams): Promise { + protected uiInit(state: UIState): Promise { return new Promise(async (resolve) => { - const r = await super.showUi(uip); + const r = await super.uiInit(state); if (r) { // 界面加载完成显示时,启动触摸非窗口区域关闭 - this.openVacancyRemove(uip.config); + this.openVacancyRemove(state.config); // 界面加载完成显示时,层级事件阻挡 this.black.enabled = true; @@ -46,15 +46,15 @@ export class LayerPopUp extends LayerUI { }); } - protected onCloseWindow(uip: UIParams) { - super.onCloseWindow(uip); + protected uiClose(state: UIState) { + super.uiClose(state); // 界面关闭后,关闭触摸事件阻挡、关闭触摸非窗口区域关闭、关闭遮罩 - this.closeUI(); + this.closeBlack(); } /** 设置触摸事件阻挡 */ - protected closeUI() { + protected closeBlack() { // 所有弹窗关闭后,关闭事件阻挡功能 if (this.ui_nodes.size == 0) { if (this.black) this.black.enabled = false; @@ -120,13 +120,13 @@ export class LayerPopUp extends LayerUI { if (this.ui_nodes.size > 0) { let vp = this.ui_nodes.array[this.ui_nodes.size - 1]; if (vp.valid && vp.config.vacancy) { - this.remove(vp.config.prefab, vp.config.destroy); + this.remove(vp.config.prefab); } } } clear(isDestroy: boolean) { super.clear(isDestroy) - this.closeUI(); + this.closeBlack(); } } \ No newline at end of file diff --git a/assets/core/gui/layer/LayerUI.ts b/assets/core/gui/layer/LayerUI.ts index ebf9446..bb93ccb 100644 --- a/assets/core/gui/layer/LayerUI.ts +++ b/assets/core/gui/layer/LayerUI.ts @@ -1,19 +1,20 @@ import { instantiate, Node, Prefab, SafeArea } from "cc"; import { Collection } from "db://oops-framework/libs/collection/Collection"; +import { resLoader } from "../../common/loader/ResLoader"; import { oops } from "../../Oops"; import { Uiid } from "./LayerEnum"; import { LayerHelper } from "./LayerHelper"; -import { LayerUIElement, UICallbacks, UIParams } from "./LayerUIElement"; +import { LayerUIElement, UIParam, UIState } from "./LayerUIElement"; import { UIConfig } from "./UIConfig"; /** 界面层对象 */ export class LayerUI extends Node { - /** 全局窗口打开失败 */ + /** 全局窗口打开失败事件 */ onOpenFailure: Function = null!; /** 显示界面节点集合 */ - protected ui_nodes = new Collection(); + protected ui_nodes = new Collection(); /** 被移除的界面缓存数据 */ - protected ui_cache = new Map(); + protected ui_cache = new Map(); /** * UI基础层,允许添加多个预制件节点 @@ -28,71 +29,101 @@ export class LayerUI extends Node { * 添加一个预制件节点到层容器中,该方法将返回一个唯一`uuid`来标识该操作节点 * @param config 界面配置数据 * @param params 自定义参数 - * @param callbacks 回调函数对象,可选 * @returns ture为成功,false为失败 */ - add(uiid: Uiid, config: UIConfig, params?: any, callbacks?: UICallbacks) { - if (this.ui_nodes.has(config.prefab)) { - console.warn(`路径为【${config.prefab}】的预制重复加载`); - return; + add(uiid: Uiid, config: UIConfig, params?: UIParam): Promise { + return new Promise(async (resolve, reject) => { + if (this.ui_nodes.has(config.prefab)) { + console.warn(`路径为【${config.prefab}】的预制重复加载`); + return; + } + + // 检查缓存中是否存界面 + let state = this.initUIConfig(uiid, config, params); + await this.load(state, config.bundle); + resolve(state.node); + }); + } + + /** 初始化界面配置初始值 */ + protected initUIConfig(uiid: Uiid, config: UIConfig, params?: UIParam) { + let state = this.ui_cache.get(config.prefab); + if (state == null) { + if (config.bundle == null) config.bundle = resLoader.defaultBundleName; + if (config.destroy == null) config.destroy = true; + if (config.vacancy == null) config.vacancy = false; + if (config.mask == null) config.mask = false; + if (config.safeArea == null) config.safeArea = false; + + state = new UIState(); + state.uiid = uiid.toString(); + state.config = config; } - - // 检查缓存中是否存界面 - let uip = this.ui_cache.get(config.prefab); - if (uip == null) { - uip = new UIParams(); - uip.uiid = uiid.toString(); - uip.config = config; - } - this.ui_nodes.set(config.prefab, uip); - - uip.params = params ?? {}; - uip.callbacks = callbacks ?? {}; - uip.valid = true; - - this.load(uip, config.bundle) + state.params = params ?? {}; + state.valid = true; + this.ui_nodes.set(config.prefab, state); + return state; } /** * 加载界面资源 - * @param uip 显示参数 + * @param state 显示参数 * @param bundle 远程资源包名,如果为空就是默认本地资源包 */ - protected async load(uip: UIParams, bundle?: string) { - // 加载界面资源超时提示 - const timerId = setTimeout(this.onLoadingTimeoutGui, oops.config.game.loadingTimeoutGui); + protected async load(state: UIState, bundle: string = resLoader.defaultBundleName): Promise { + return new Promise(async (resolve, reject) => { + // 加载界面资源超时提示 + let timerId = setTimeout(this.onLoadingTimeoutGui, oops.config.game.loadingTimeoutGui); + if (state.node == null) { + // 优先加载配置的指定资源包中资源,如果没配置则加载默认资源包资源 + const res = await resLoader.loadAsync(bundle, state.config.prefab, Prefab); + if (res) { + state.node = instantiate(res); - if (uip && uip.node) { - await this.showUi(uip); - } - else { - // 优先加载配置的指定资源包中资源,如果没配置则加载默认资源包资源 - bundle = bundle || oops.res.defaultBundleName; - const res = await oops.res.loadAsync(bundle, uip.config.prefab, Prefab); - if (res) { - uip.node = instantiate(res); + // 是否启动真机安全区域显示 + if (state.config.safeArea) state.node.addComponent(SafeArea); - // 是否启动真机安全区域显示 - if (uip.config.safeArea) uip.node.addComponent(SafeArea); + // 窗口事件委托 + const comp = state.node.addComponent(LayerUIElement); + comp.state = state; + } + else { + console.warn(`路径为【${state.config.prefab}】的预制加载失败`); + this.failure(state); + } + } - // 窗口事件委托 - const dc = uip.node.addComponent(LayerUIElement); - dc.params = uip; - //@ts-ignore - dc.onCloseWindow = this.onCloseWindow.bind(this); + // 关闭界面资源超时提示 + oops.gui.waitClose(); + clearTimeout(timerId); - // 显示界面 - await this.showUi(uip); + await this.uiInit(state); + + resolve(state.node); + }); + } + + /** + * 创建界面节点 + * @param state 视图参数 + */ + protected uiInit(state: UIState): Promise { + return new Promise(async (resolve, reject) => { + const comp = state.node.getComponent(LayerUIElement)!; + const r: boolean = await comp.add(); + if (r) { + state.valid = true; // 标记界面为使用状态 + if (!state.params.preload) { + state.params.preload = false; + state.node.parent = this; + } } else { - console.warn(`路径为【${uip.config.prefab}】的预制加载失败`); - this.failure(uip); + console.warn(`路径为【${state.config.prefab}】的自定义预处理逻辑异常.检查预制上绑定的组件中 onAdded 方法,返回true才能正确完成窗口显示流程`); + this.failure(state); } - } - - // 关闭界面资源超时提示 - oops.gui.waitClose(); - clearTimeout(timerId); + resolve(r); + }); } /** 加载超时事件*/ @@ -101,74 +132,52 @@ export class LayerUI extends Node { } /** 窗口关闭事件 */ - protected onCloseWindow(vp: UIParams) { - this.ui_nodes.delete(vp.config.prefab); - } - - /** - * 创建界面节点 - * @param uip 视图参数 - */ - protected async showUi(uip: UIParams): Promise { - // 触发窗口添加事件 - const comp = uip.node.getComponent(LayerUIElement)!; - const r: boolean = await comp.add(); - if (r) { - uip.node.parent = this; - - // 标记界面为使用状态 - uip.valid = true; - } - else { - console.warn(`路径为【${uip.config.prefab}】的自定义预处理逻辑异常.检查预制上绑定的组件中 onAdded 方法,返回true才能正确完成窗口显示流程`); - this.failure(uip); - } - return r; + protected uiClose(state: UIState) { + this.ui_nodes.delete(state.config.prefab); } /** 打开窗口失败逻辑 */ - protected failure(uip: UIParams) { - this.onCloseWindow(uip); - uip.callbacks && uip.callbacks.onLoadFailure && uip.callbacks.onLoadFailure(); + protected failure(state: UIState) { + this.uiClose(state); this.onOpenFailure && this.onOpenFailure(); } /** * 根据预制件路径删除,预制件如在队列中也会被删除,如果该预制件存在多个也会一起删除 * @param prefabPath 预制路径 - * @param isDestroy 移除后是否释放 */ - remove(prefabPath: string, isDestroy?: boolean): void { - let release: any = undefined; - if (isDestroy !== undefined) release = isDestroy; + remove(prefabPath: string): void { + let release: boolean = true; // 界面移出舞台 - const uip = this.ui_nodes.get(prefabPath); - if (uip) { + const state = this.ui_nodes.get(prefabPath); + if (state) { // 优先使用参数中控制的释放条件,如果未传递参数则用配置中的释放条件,默认不缓存关闭的界面 - if (release === undefined) { - release = uip.config.destroy !== undefined ? uip.config.destroy : true; - } + release = state.config.destroy !== undefined ? state.config.destroy : true; // 不释放界面,缓存起来待下次使用 if (release === false) { - this.ui_cache.set(uip.config.prefab, uip); + this.ui_cache.set(state.config.prefab, state); } - const node = uip.node; + const node = state.node; const comp = node.getComponent(LayerUIElement)!; comp.remove(release); } - // 验证是否删除后台缓存界面 - if (release === true) this.removeCache(prefabPath); + // 清理界面缓存 + const cache = this.ui_cache.get(prefabPath); + if (cache) { + // 验证是否删除后台缓存界面 + if (release) this.removeCache(prefabPath); + } } /** 删除缓存的界面,当缓存界面被移除舞台时,可通过此方法删除缓存界面 */ private removeCache(prefabPath: string) { let vp = this.ui_cache.get(prefabPath); if (vp) { - this.onCloseWindow(vp); + this.uiClose(vp); this.ui_cache.delete(prefabPath); const node = vp.node; const comp = node.getComponent(LayerUIElement)!; @@ -177,6 +186,12 @@ export class LayerUI extends Node { } } + /** 显示界面 */ + show(prefabPath: string) { + const vp = this.ui_nodes.get(prefabPath); + if (vp) vp.node.parent = this; + } + /** * 根据预制路径获取已打开界面的节点对象 * @param prefabPath 预制路径 @@ -204,13 +219,13 @@ export class LayerUI extends Node { const length = this.ui_nodes.array.length - 1; for (let i = length; i >= 0; i--) { const uip = this.ui_nodes.array[i]; - this.remove(uip.config.prefab, isDestroy); + this.remove(uip.config.prefab); } this.ui_nodes.clear(); // 清除缓存中的界面 if (isDestroy) { - this.ui_cache.forEach((value: UIParams, prefabPath: string) => { + this.ui_cache.forEach((value: UIState, prefabPath: string) => { this.removeCache(prefabPath); }); } diff --git a/assets/core/gui/layer/LayerUIElement.ts b/assets/core/gui/layer/LayerUIElement.ts index 19e3131..f158fd8 100644 --- a/assets/core/gui/layer/LayerUIElement.ts +++ b/assets/core/gui/layer/LayerUIElement.ts @@ -18,11 +18,9 @@ const { ccclass } = _decorator; @ccclass('LayerUIElement') export class LayerUIElement extends Component { /** 视图参数 */ - params: UIParams = null!; + state: UIState = null!; /** 关闭窗口之前 */ - onCloseWindowBefore: Function = null!; - /** 界面关闭回调 - 包括关闭动画播放完(辅助框架内存业务流程使用) */ - private onCloseWindow: Function = null!; + onClose: Function = null!; /** 添加界面且界面设置到父节点之前 */ add(): Promise { @@ -32,7 +30,7 @@ export class LayerUIElement extends Component { const component: any = this.node.components[i]; const func = component[EventOnAdded]; if (func) { - if (await func.call(component, this.params.params) == false) { + if (await func.call(component, this.state.params.data) == false) { resolve(false); return; } @@ -40,8 +38,8 @@ export class LayerUIElement extends Component { } // 触发外部窗口显示前的事件(辅助实现自定义动画逻辑) - if (typeof this.params.callbacks.onAdded === "function") { - this.params.callbacks.onAdded(this.node, this.params.params); + if (typeof this.state.params.onAdded === "function") { + this.state.params.onAdded(this.node, this.state.params.data); } resolve(true); @@ -49,14 +47,14 @@ export class LayerUIElement extends Component { } /** 删除节点,该方法只能调用一次,将会触发onBeforeRemoved回调 */ - remove(isDestroy?: boolean) { - if (this.params.valid) { + remove(isDestroy: boolean) { + if (this.state.valid) { // 触发窗口移除舞台之前事件 - this.applyComponentsFunction(this.node, EventOnBeforeRemove, this.params.params); + this.applyComponentsFunction(this.node, EventOnBeforeRemove, this.state.params.data); // 通知外部对象窗口组件上移除之前的事件(关闭窗口前的关闭动画处理) - if (typeof this.params.callbacks.onBeforeRemove === "function") { - this.params.callbacks.onBeforeRemove(this.node, this.onBeforeRemoveNext.bind(this, isDestroy)); + if (typeof this.state.params.onBeforeRemove === "function") { + this.state.params.onBeforeRemove(this.node, this.onBeforeRemoveNext.bind(this, isDestroy)); } else { this.onBeforeRemoveNext(isDestroy); @@ -68,28 +66,26 @@ export class LayerUIElement extends Component { } /** 窗口关闭前动画处理完后的回调方法,主要用于释放资源 */ - private onBeforeRemoveNext(isDestroy?: boolean) { - this.onCloseWindowBefore && this.onCloseWindowBefore(); - this.removed(this.params, isDestroy); - } + private onBeforeRemoveNext(isDestroy: boolean) { + this.state.valid = false; - /** 窗口组件中触发移除事件与释放窗口对象 */ - private removed(uip: UIParams, isDestroy?: boolean) { - uip.valid = false; - - if (uip.callbacks && typeof uip.callbacks.onRemoved === "function") { - uip.callbacks.onRemoved(this.node, uip.params); + if (this.state.params && typeof this.state.params.onRemoved === "function") { + this.state.params.onRemoved(this.node, this.state.params.data); } - // 界面移除舞台事件 - this.onCloseWindow && this.onCloseWindow(uip); + // 关闭动画播放完后,界面移除舞台 + //@ts-ignore + this.node.parent.uiClose(this.state); + + // 关闭动画播放完后,界面移除舞台事件 + this.onClose && this.onClose(); if (isDestroy) { // 释放界面显示对象 this.node.destroy(); // 释放界面相关资源 - oops.res.release(uip.config.prefab, uip.config.bundle); + oops.res.release(this.state.config.prefab, this.state.config.bundle); // oops.log.logView(`【界面管理】释放【${uip.config.prefab}】界面资源`); } @@ -98,7 +94,7 @@ export class LayerUIElement extends Component { } // 触发窗口组件上窗口移除之后的事件 - this.applyComponentsFunction(this.node, EventOnRemoved, this.params.params); + this.applyComponentsFunction(this.node, EventOnRemoved, this.state.params.data); } private applyComponentsFunction(node: Node, funName: string, params: any) { @@ -112,38 +108,33 @@ export class LayerUIElement extends Component { } onDestroy() { - this.params = null!; - this.onCloseWindowBefore = null!; - this.onCloseWindow = null!; + this.state = null!; + this.onClose = null!; } } /** 本类型仅供gui模块内部使用,请勿在功能逻辑中使用 */ -export class UIParams { +export class UIState { /** 界面唯一编号 */ uiid: string = null!; /** 界面配置 */ config: UIConfig = null!; - /** 传递给打开界面的参数 */ - params: any = null!; /** 窗口事件 */ - callbacks: UICallbacks = null!; + params: UIParam = null!; /** 是否在使用状态 */ valid: boolean = true; /** 界面根节点 */ node: Node = null!; } -/** 界面关闭参数 */ -export interface UIRemove { - /** 关闭是否释放资源内存 */ - isDestroy?: boolean; - /** 界面动画播放完关闭事件 */ - onRemoved?: Function; -} +/*** 界面打开参数 */ +export interface UIParam { + /** 自定义传递参数 */ + data?: any; + + /** 是否开启预加载(默认不开启 - 开启后加载完不显示界面) */ + preload?: boolean; -/*** 界面回调参数对象定义 */ -export interface UICallbacks { /** * 节点添加到层级以后的回调 * @param node 当前界面节点 @@ -151,13 +142,6 @@ export interface UICallbacks { */ onAdded?: (node: Node, params: any) => void, - /** - * 窗口节点 destroy 之后回调 - * @param node 当前界面节点 - * @param params 外部传递参数 - */ - onRemoved?: (node: Node | null, params: any) => void, - /** * 如果指定onBeforeRemoved,则next必须调用,否则节点不会被正常删除。 * @@ -167,6 +151,10 @@ export interface UICallbacks { */ onBeforeRemove?: (node: Node, next: Function) => void, - /** 网络异常时,窗口加载失败回调 */ - onLoadFailure?: () => void; + /** + * 窗口节点 destroy 之后回调 + * @param node 当前界面节点 + * @param params 外部传递参数 + */ + onRemoved?: (node: Node, params: any) => void } \ No newline at end of file diff --git a/assets/core/gui/layer/UIConfig.ts b/assets/core/gui/layer/UIConfig.ts index 344c4d7..d736757 100644 --- a/assets/core/gui/layer/UIConfig.ts +++ b/assets/core/gui/layer/UIConfig.ts @@ -39,7 +39,7 @@ export interface UIConfig { vacancy?: boolean, /** 是否打开窗口后显示背景遮罩(默认关闭) */ mask?: boolean; - /** 是否启动真机安全区域显示 */ + /** 是否启动真机安全区域显示(默认关闭) */ safeArea?: boolean; /** 界面弹出时的节点排序索引 */ siblingIndex?: number; diff --git a/assets/module/common/CCComp.ts b/assets/module/common/CCComp.ts index e2738b5..3320319 100644 --- a/assets/module/common/CCComp.ts +++ b/assets/module/common/CCComp.ts @@ -5,7 +5,6 @@ * @LastEditTime: 2022-09-06 17:20:51 */ -import { UIRemove } from '../../core/gui/layer/LayerUIElement'; import { ecs } from '../../libs/ecs/ECS'; import { ECSModel } from '../../libs/ecs/ECSModel'; import { GameComponent } from './GameComponent'; @@ -43,13 +42,13 @@ export abstract class CCComp extends GameComponent implements ecs.IComp { tid: number = -1; /** 从父节点移除自己 */ - remove(params?: UIRemove) { + remove() { const cct = ECSModel.compCtors[this.tid]; if (this.ent) { - ModuleUtil.removeGui(this.ent, cct, params); + ModuleUtil.removeGui(this.ent, cct); } else { - console.error(`组件 ${this.name} 移除失败,实体不存在`); + console.error(`组件 ${this.name} 移除失败,组件未注册`); } } diff --git a/assets/module/common/CCVMParentComp.ts b/assets/module/common/CCVMParentComp.ts index e5557a1..fa9c9c2 100644 --- a/assets/module/common/CCVMParentComp.ts +++ b/assets/module/common/CCVMParentComp.ts @@ -5,7 +5,6 @@ * @LastEditTime: 2022-09-06 17:22:05 */ -import { UIRemove } from '../../core/gui/layer/LayerUIElement'; import { ecs } from '../../libs/ecs/ECS'; import { ECSModel } from '../../libs/ecs/ECSModel'; import VMParent from '../../libs/model-view/VMParent'; @@ -55,13 +54,13 @@ export abstract class CCVMParentComp extends VMParent implements ecs.IComp { tid: number = -1; /** 从父节点移除自己 */ - remove(params?: UIRemove) { + remove() { const cct = ECSModel.compCtors[this.tid]; if (this.ent) { - ModuleUtil.removeGui(this.ent, cct, params); + ModuleUtil.removeGui(this.ent, cct); } else { - console.error(`组件 ${this.name} 移除失败,实体不存在`); + console.error(`组件 ${this.name} 移除失败,组件未注册`); } } diff --git a/assets/module/common/GameComponent.ts b/assets/module/common/GameComponent.ts index 0b1a041..6f3410f 100644 --- a/assets/module/common/GameComponent.ts +++ b/assets/module/common/GameComponent.ts @@ -11,7 +11,7 @@ import { IAudioParams } from "../../core/common/audio/IAudio"; import { EventDispatcher } from "../../core/common/event/EventDispatcher"; import { EventMessage, ListenerFunc } from "../../core/common/event/EventMessage"; import { AssetType, CompleteCallback, Paths, ProgressCallback, resLoader } from "../../core/common/loader/ResLoader"; -import { LayerUIElement, UIRemove } from "../../core/gui/layer/LayerUIElement"; +import { LayerUIElement } from "../../core/gui/layer/LayerUIElement"; import { ViewUtil } from "../../core/utils/ViewUtil"; const { ccclass } = _decorator; @@ -483,18 +483,10 @@ export class GameComponent extends Component { //#endregion /** 移除自己 */ - remove(params?: UIRemove) { - if (params == null) { - params = { isDestroy: true }; - } - else { - if (params.isDestroy == null) params.isDestroy = true; - } - + remove() { const comp = this.node.getComponent(LayerUIElement); if (comp) { - if (params.onRemoved) comp.onCloseWindowBefore = params.onRemoved; - oops.gui.removeByNode(this.node, params.isDestroy); + oops.gui.removeByNode(this.node); } } diff --git a/assets/module/common/ModuleUtil.ts b/assets/module/common/ModuleUtil.ts index 187ed7c..c2dbc53 100644 --- a/assets/module/common/ModuleUtil.ts +++ b/assets/module/common/ModuleUtil.ts @@ -2,8 +2,7 @@ import { Node, __private } from "cc"; import { oops } from "../../core/Oops"; import { resLoader } from "../../core/common/loader/ResLoader"; import { gui } from "../../core/gui/Gui"; -import { Uiid } from "../../core/gui/layer/LayerEnum"; -import { LayerUIElement, UICallbacks, UIRemove } from "../../core/gui/layer/LayerUIElement"; +import { LayerUIElement, UIParam } from "../../core/gui/layer/LayerUIElement"; import { ViewUtil } from "../../core/utils/ViewUtil"; import { ecs } from "../../libs/ecs/ECS"; import { CompType } from "../../libs/ecs/ECSModel"; @@ -17,29 +16,26 @@ export class ModuleUtil { * 异步添加视图层组件 * @param ent 模块实体 * @param ctor 界面逻辑组件 - * @param uiArgs 界面参数 - * @param anim 界面打开与关闭动画 + * @param params 界面参数 * @returns 界面节点 */ - static addGui(ent: ecs.Entity, ctor: ECSCtor, uiArgs?: any, anim?: UICallbacks): Promise { - return new Promise((resolve, reject) => { - const uic: UICallbacks = { - onAdded: (node: Node, params: any) => { - const comp = node.getComponent(ctor) as ecs.Comp; - ent.add(comp); - if (anim && anim.onAdded) anim.onAdded(node, params); - resolve(node); - }, - onLoadFailure: () => { - if (anim && anim.onLoadFailure) anim.onLoadFailure(); - resolve(null); - } - }; - + static addGui(ent: ecs.Entity, ctor: ECSCtor, params?: UIParam): Promise { + return new Promise(async (resolve, reject) => { //@ts-ignore const key = ctor[gui.internal.GUI_KEY]; if (key) { - oops.gui.open(key, uiArgs, uic); + if (params == null) { + params = { preload: true }; + } + else { + params.preload = true; + } + + let node = await oops.gui.open(key, params); + const comp = node.getComponent(ctor) as ecs.Comp; + ent.add(comp); + oops.gui.show(key); + resolve(node); } else { console.error(`${key} 界面组件未使用 gui.register 注册`); @@ -49,18 +45,11 @@ export class ModuleUtil { /** * 业务实体上移除界面组件 - * @param ent 模块实体 - * @param ctor 界面逻辑组件 - * @param params 界面关闭参数 + * @param ent 模块实体 + * @param ctor 界面逻辑组件 + * @param params 界面关闭参数 */ - static removeGui(ent: ecs.Entity, ctor: CompType, params?: UIRemove) { - if (params == null) { - params = { isDestroy: true }; - } - else { - if (params.isDestroy == null) params.isDestroy = true; - } - + static removeGui(ent: ecs.Entity, ctor: CompType) { //@ts-ignore const key = ctor[gui.internal.GUI_KEY]; if (key) { @@ -72,16 +61,14 @@ export class ModuleUtil { const comp = node.getComponent(LayerUIElement); if (comp) { - comp.onCloseWindowBefore = () => { - if (params.isDestroy) ent.remove(ctor); - if (params.onRemoved) params.onRemoved(); + comp.onClose = () => { + if (comp.state.config.destroy) ent.remove(ctor); }; - oops.gui.remove(key, params.isDestroy); + oops.gui.remove(key); } } else { - if (params.isDestroy) ent.remove(ctor); - if (params.onRemoved) params.onRemoved(); + ent.remove(ctor); } } @@ -99,77 +86,4 @@ export class ModuleUtil { ent.add(comp); node.parent = parent; } - - //#region deprecated - /** - * 添加界面组件 - * @param ent 模块实体 - * @param ctor 界面逻辑组件 - * @param uiId 界面资源编号 - * @param uiArgs 界面参数 - * @deprecated 使用gui.register注册的界面组件,可使用add方法打开 - */ - static addViewUi(ent: ecs.Entity, ctor: ECSCtor, uiId: Uiid, uiArgs: any = null) { - const uic: UICallbacks = { - onAdded: (node: Node, params: any) => { - const comp = node.getComponent(ctor) as ecs.Comp; - //@ts-ignore - if (!ent.has(ctor)) ent.add(comp); - } - }; - oops.gui.open(uiId, uiArgs, uic); - } - - /** - * 异步添加视图层组件 - * @param ent 模块实体 - * @param ctor 界面逻辑组件 - * @param uiId 界面资源编号 - * @param uiArgs 界面参数 - * @returns 界面节点 - * @deprecated 使用gui.register注册的界面组件,可使用add方法打开 - */ - static addViewUiAsync(ent: ecs.Entity, ctor: ECSCtor, uiId: Uiid, uiArgs: any = null): Promise { - return new Promise((resolve, reject) => { - const uic: UICallbacks = { - onAdded: (node: Node, params: any) => { - const comp = node.getComponent(ctor) as ecs.Comp; - ent.add(comp); - resolve(node); - }, - onLoadFailure: () => { - resolve(null); - } - }; - oops.gui.open(uiId, uiArgs, uic); - }); - } - - /** - * 业务实体上移除界面组件 - * @param ent 模块实体 - * @param ctor 界面逻辑组件 - * @param uiId 界面资源编号 - * @param isDestroy 是否释放界面缓存(默认为释放界面缓存) - * @param onRemoved 窗口关闭完成事件 - * @deprecated 使用gui.register注册的界面组件,可使用remove方法移除 - */ - static removeViewUi(ent: ecs.Entity, ctor: CompType, uiId: Uiid, isDestroy: boolean = true, onRemoved?: Function) { - const node = oops.gui.get(uiId); - if (!node) { - if (onRemoved) onRemoved(); - return; - } - - const comp = node.getComponent(LayerUIElement); - if (comp) { - comp.onCloseWindowBefore = () => { - // 移除ECS显示组件 - if (isDestroy) ent.remove(ctor, isDestroy); - if (onRemoved) onRemoved(); - }; - oops.gui.remove(uiId, isDestroy); - } - } - //#endregion } \ No newline at end of file