import { Animation, Canvas, find, instantiate, Node, Prefab, Sprite, Widget } from 'cc'; import { PREVIEW } from 'cc/env'; import { FrameworkConf } from '../config/FrameworkConf'; import { EventMgr } from '../event/EventManager'; import { resLoader } from '../res/ResLoader'; import { StringUtil } from '../util/StringUtil'; import { TimeUtil } from '../util/TimeUtil'; import { BaseView, UIShowType } from './BaseView'; import { LayerConf, LayerInfo } from './LayerManager'; import { UserData } from '../../game/data/UserData'; export class BaseLayer extends Node { private _layer_queue: LayerInfo[] = []; //UI队列 private _layer_conf: { [key: number]: LayerConf } = {}; //UI配置 private _layer_opening: boolean = false; //是否正在打开UI private _layer_cache: LayerInfo[] = []; //UI缓存 private _layer_manage = false; //是否启用层级管理 private _bottom_layer = 0; //底层UI数量(通常位于UI栈底部,不受UI切换影响) constructor(name: string, conf: any, manage: boolean = false) { super(name); this._layer_conf = conf; let widget = this.addComponent(Widget); widget.isAlignLeft = widget.isAlignRight = widget.isAlignTop = widget.isAlignBottom = true; widget.left = widget.right = widget.top = widget.bottom = 0; widget.alignMode = 2; widget.enabled = true; this._layer_queue = []; this._layer_cache = []; this._layer_opening = false; this._layer_manage = manage; } /** * 打开UI * @param id UIID * @param args 打开UI的可传参数 * @param callback UI打开成功过后的回调 */ open(id: number, callback: Function = null, args: any[]) { let conf = this._layer_conf[id]; if (conf) { let info: LayerInfo = { id: id, args: args, view: null, res: null, callback: callback, active: true, bLoading: true }; if (this._layer_opening) { //队列里不能有相同的UI for (let ui of this._layer_queue) { if (ui.id === id) { return false; } } //插入待打开队列 this._layer_queue.push(info); return false; } //开同一UI 则刷新 let curView = this.getUIView(id); if (curView) { //let conf = this._layer_conf[id]; if (conf.reset) { console.log("页面存在,直接刷新") //传递自定义参数 curView.onOpen(...info.args); //回调 info.callback && info.callback(); return true } else{ console.log("页面存在,不刷新") return false; } } this._layer_opening = true; this._layer_cache.push(info); let __time = TimeUtil.getTime(); let self = this /** * 加载失败 * @param bRes 资源已加载 */ let funError = function(bRes){ if(bRes){ resLoader.release(conf.url, conf.bundle); } for (let i = self._layer_cache.length - 1; i >= 0; --i) { if (self._layer_cache[i] == info) { self._layer_cache.splice(i, 1); break; } } //处理待打开队列中的UI self._layer_opening = false; self._open_next(); } //加载资源 resLoader.load(conf.bundle, conf.url, Prefab, (error: Error, prefab: Prefab) => { if (error) { console.error("载入资源失败:" + conf.url); funError(false) return false } else { if(!info.bLoading){ console.error("资源已不需要了:" + conf.url); funError(true) return false } info.bLoading = false; (!conf.cache) && (info.res = prefab); let node = instantiate(prefab); node.active = true; console.log(`复制预制体:${conf.url}`) if (!node) { console.error("初始化Node失败"); funError(true) return false; } let view = node.getComponent(BaseView); if (!view) { console.error("UI未找到UIView组件"); funError(true) return false; } prefab.addRef(); view.enabled = true; info.view = view; view.view_id = id; this.addChild(node); //统计底层UI数量 (conf.bottom) && ++this._bottom_layer; this._play_anim(id, node, "ui_open", () => { //刷新UI this._updateUI(); //传递自定义参数 view.onOpen(...info.args); //发送打开事件 EventMgr.fireEvent(FrameworkConf.Event.OPEND_UI, info.id); //回调 info.callback && info.callback(); //处理待打开队列中的UI this._layer_opening = false; this._open_next(); }); (PREVIEW) && console.log(StringUtil.format("UI[{0}]加载耗时:{1}毫秒", info.id, TimeUtil.getTime() - __time)); } }); return true; } return false; } private _open_next() { let info = this._layer_queue.shift(); info && this.open(info.id, info.callback, info.args); } private _play_anim(id: number, node: Node, name: string, callback: Function,) { //是否播放动画 let conf = this._layer_conf[id]; if (conf.anim) { let anim = node.getComponent(Animation); if (anim) { anim.on(Animation.EventType.FINISHED, () => { callback && callback(); callback = null; }, this); anim.play(name); return; } console.error("ui:" + id + "缺少Animation组件"); } else { callback && callback(); callback = null; } } private _updateUI() { if (this._layer_manage) { let show_idx = this._layer_cache.length - 1, hide_idx = 0;; for (; show_idx >= 0; --show_idx) { if (this._layer_cache[show_idx].active) { this._layer_cache[show_idx].view?.onShow(); let mode = this._layer_cache[show_idx].view?.show_type; if (mode == UIShowType.Single) { for (let i = 0; i < this._bottom_layer; ++i) { this._layer_cache[i] && this._layer_cache[i].view?.onShow(); } hide_idx = this._bottom_layer; break; } else if (mode == UIShowType.FullScreen) { break; } } } for (let i = hide_idx; i < show_idx; ++i) { this._layer_cache[i].view?.onHide(); } let find = false; for (let cache of this._layer_cache) { if (cache.active) { if (cache.view?.show_type == UIShowType.FullScreen) { find = true; //如果有全屏隐藏底层UI for (let i = 0; i < this._bottom_layer; ++i) { this._layer_cache[i] && this._layer_cache[i].view?.onHide(); } break; } } } EventMgr.fireEvent("_Framewrok_Show_GameLayer", !find); } } /** * 关闭UI * @param ui 该值可为UIID也可为this */ close(ui: number | BaseView) { let view = (typeof ui === "number") ? this.getUIView(ui) : ui; if (view) { let info: LayerInfo = null; for (let i = 0; i < this._layer_cache.length; ++i) { info = this._layer_cache[i]; if (info.view == view) { this._layer_cache.splice(i, 1); //刷新UI let pre_info = (this._layer_cache.length >= 1) ? this._layer_cache[this._layer_cache.length - 1] : null; if (pre_info) { if (!pre_info.active) { pre_info = (this._layer_cache.length >= 2) ? this._layer_cache[this._layer_cache.length - 2] : null; } } this._updateUI(); this._play_anim(info.view.view_id, info.view.node, "ui_close", () => { //显示最后一个UI if (pre_info && pre_info.view) { pre_info.view.onShow(); } this._clearUI(info); }); break; } } } else{ let info: LayerInfo = null; for (let i = 0; i < this._layer_cache.length; ++i) { info = this._layer_cache[i]; if(info.id == ui){ info.bLoading = false; console.log("closeUI with out view:", info.id); } } } } ShowUI(UI, state, callback: Function = null, args: any[]) { let nohave = true; let exist = [] for (let i in this._layer_cache) { if (this._layer_cache[i].id === UI) { nohave = false if (this._layer_cache[i] && this._layer_cache[i].view) { if (state) { for (let existUI of exist) { existUI.view.onHide(); } this._layer_cache[i].view.onShow(); this._layer_cache[i].active = true; } else { for (let existUI of exist) { existUI.view.onShow(); } this._layer_cache[i].view.onHide(); this._layer_cache[i].active = false; } callback && callback(); } return; } exist.push(this._layer_cache[i]) } if (nohave) { this.open(UI, callback, args); } } /** * 获取UI对应的UIView * @param id UIID */ getUIView(id: number) { for (let ui of this._layer_cache) { if (ui.id === id) { if (ui.active) { return ui.view; } } } return null; } /** * 关闭当前层的所有UI */ closeAll(withoutID: number = -1) { for (let index = this._layer_cache.length - 1; index >= 0; index--) { let info = this._layer_cache[index]; if (info.id !== withoutID) { this.close(info.id); let conf = this._layer_conf[info.id]; (!conf.special) && this._clearUI(info); } } this._layer_queue = []; } private _clearUI(info: LayerInfo) { if (info && info.view) { let conf = this._layer_conf[info.id]; (conf && conf.bottom) && --this._bottom_layer; info.view.onClose(); //发送打开事件 EventMgr.fireEvent(FrameworkConf.Event.CLOSE_UI, info.id); info.view.unscheduleAllCallbacks(); info.view.node.removeFromParent(); info.view.release(); EventMgr.removeEvent(info.view); info.view.node.destroyAllChildren(); info.view.node.destroy(); info.res && (info.res.decRef()); info.res = null; info.view = null; info = null; } } showLayerUI(show: boolean) { for (let cache of this._layer_cache) { if (show) { cache.active && cache.view?.onShow(); } else { cache.view?.onHide(); } } } }