123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- import { _decorator, assetManager, Button, Component, EventHandler, EventTouch, find, isValid, Node, Prefab, Toggle, ToggleContainer } from 'cc';
- const { ccclass, property } = _decorator;
- /***
- * @en internal class, used for handling node event.
- * @zh 内部类,用于节点事件监听
- *
- * */
- @ccclass('tgxNodeEventAgent')
- class __NodeEventAgent__ extends Component {
- /***
- * @en recieve button click event and deliver them to the real handlers.
- * @zh 接受按钮事件,并转发给真正的处理函数
- * */
- onButtonClicked(evt: EventTouch, customEventData) {
- let btn = (evt.target as Node).getComponent(Button);
- let clickEvents = btn.clickEvents;
- for (let i = 0; i < clickEvents.length; ++i) {
- let h = clickEvents[i];
- if (h.customEventData == customEventData) {
- let cb = h['$cb$'];
- let target = h['$target$']
- let args = h['$args$'];
- cb.apply(target, [btn, args]);
- }
- }
- }
- /***
- * @en recieve toggle event and deliver them to the real handlers.
- * @zh 接受Toggle事件,并转发给真正的处理函数
- * */
- onToggleEvent(toggle: Toggle, customEventData) {
- let checkEvents = toggle.checkEvents;
- //if (toggle['_toggleContainer']) {
- // checkEvents = toggle['_toggleContainer'].checkEvents;
- //}
- for (let i = 0; i < checkEvents.length; ++i) {
- let h = checkEvents[i];
- if (h.customEventData == customEventData) {
- let cb = h['$cb$'];
- let target = h['$target$']
- let args = h['$args$'];
- cb.apply(target, [toggle, args]);
- }
- }
- }
- }
- let _id:number=0;
- export default class ui_base {
- private static _clss:Set<any>=new Set();
- private static _uis: ui_base[] = [];
- /***
- * @en hide and destroy all ui panel.
- * @zh 隐藏并销毁所有UI面板
- * */
- public static closeAll() {
- while (this._uis.length) {
- this._uis[0].close();
- }
- this._clss.clear();
- }
- //
- public static closeAndReleaseAll(){
- while (this._uis.length) {
- this._uis[0].closeAndRelease();
- }
- this._clss.clear();
- }
- //update all ui, called by UI.
- public static updateAll(dt:number) {
- for (let i = 0; i < this._uis.length; ++i) {
- let ctrl = this._uis[i];
- if (ctrl.node && isValid(ctrl.node)) {
- this._uis[i].onUpdate(dt);
- }
- }
- }
- private static _addCls(cls:any):void{
- if(!cls) return;this._clss.add(cls);
- }
- private static _removeCls(cls:any):void{
- if(!cls) return;this._clss.delete(cls);
- }
- private static _hasCls(cls:any):boolean{
- return this._clss.has(cls);
- }
- private _id: number = 0;
- private _bundle:string;
- private _prefab: string;
- private _layer: number;
- private _layout: any;
- private _cls:any;
- protected node: Node;
- private _destroyed:boolean = false;
- /***
- * @en the instance id to indicate an unique ui panel.
- * @zh 实例ID,用于标记一个唯一面板实例
- * */
- public get id(): number {return this._id;}
- /***
- * @en url of the prefab used by this ui panel.
- * @zh 本UI使用prefab路径
- * */
- public get prefab(): string {return this._prefab;}
- public get bundle():string{return this._bundle;}
- /***
- * @en layer of this ui panel.
- * @zh 本UI所在的UI层级
- * */
- public get layer(): number {return this._layer;}
- /***
- * @en layout of this ui panel.
- * @zh 本UI组件
- * */
- public get layout(): Component { return this._layout;}
- public getLayout<T extends Component>():T{ return this._layout as T;}
- constructor(bundle:string,prefab: string, layer: number, layoutCls: any) {
- this._cls = null;
- this._bundle=bundle;
- this._prefab = prefab;
- this._layer = layer;
- this._layout = layoutCls;
- this._id = _id++;
- }
- //setup this ui,called by UIMgr.
- private _setup(cls:any,node: Node,...data: any[]) {
- ui_base._uis.push(this);
- this._cls=cls;
- (ui_base as any)._addCls(this._cls);
- this.node = node;
- if (this._layout) this._layout = this.node.getComponent(this._layout);
- //notify sub class to handle something.
- //节点创建完毕,调用子类的处理函数。
- this.onCreated(...data);
- //check whether it has been destroyed, if has, hide it.
- //检查是否为已销毁,如果已销毁,则走销毁流程
- if(this._destroyed) this.close();
- }
- /**
- * @en hide and destroy this ui panel.
- * @zh 隐藏并销毁此UI面板
- * */
- public close(){
- this._resolve_close?.();
- this._resolve_close=null;
- this._destroyed = true;
- if(!this.node) return;
- this.node.removeFromParent();
- for (let i = 0; i < ui_base._uis.length; ++i) {
- if (ui_base._uis[i] == this) {
- ui_base._uis.splice(i, 1);
- break;
- }
- }
- this.onDispose();
- this.node.destroy();
- this.node = null;
- (ui_base as any)._removeCls(this._cls);
- this._cls=null;
- }
- public closeAndRelease(){
- this.close();
- assetManager.getBundle(this._bundle)?.release(this._prefab);
- }
- private _resolve_close: (() => void) | null = null;
- /**等待此ui关闭*/
- public wait_close():Promise<void>{
- if(this._resolve_close) return;
- return new Promise((resolve) => {this._resolve_close = resolve;});
- }
- /**
- * @en add button event handler
- * @zh 添加按钮事件
- * @param relativeNodePath to indicate a button node, can pass `string`|`Node`|`Button` here.
- * @param cb will be called when event emits. method format:(btn:Button,args:any)=>void
- * @param target the `this` argument of `cb`
- * */
- onButtonEvent(relativeNodePath: string | Node | Button, cb: Function, target?: any, args?: any) {
- let buttonNode: Node = null;
- if (relativeNodePath instanceof Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof Button) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = find(relativeNodePath, this.node);
- }
- if (!buttonNode) {
- return null;
- }
- //添加转发器
- let agent = this.node.getComponent(__NodeEventAgent__);
- if (!agent) {
- agent = this.node.addComponent(__NodeEventAgent__);
- }
- let btn = buttonNode.getComponent(Button);
- let clickEvents = btn.clickEvents;
- let handler = new EventHandler();
- handler.target = this.node;
- handler.component = 'tgxNodeEventAgent';
- handler.handler = 'onButtonClicked';
- handler.customEventData = '' + _id++;
- //附加额外信息 供事件转发使用
- handler['$cb$'] = cb;
- handler['$target$'] = target;
- handler['$args$'] = args;
- clickEvents.push(handler);
- btn.clickEvents = clickEvents;
- }
- /**
- * @en remove button event handler
- * @zh 移除按钮事件
- * @param relativeNodePath to indicate a button node, can pass `string`|`Node`|`Button` here.
- * @param cb will be called when event emits.
- * @param target the `this` argument of `cb`
- * */
- offButtonEvent(relativeNodePath: string | Node | Button, cb: Function, target: any) {
- let buttonNode: Node = null;
- if (relativeNodePath instanceof Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof Button) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = find(relativeNodePath, this.node);
- }
- if (!buttonNode) {
- return; ``
- }
- let agent = this.node.getComponent(__NodeEventAgent__);
- if (!agent) {
- return;
- }
- let btn = buttonNode.getComponent(Button);
- if (!btn) {
- return;
- }
- let clickEvents = btn.clickEvents;
- for (let i = 0; i < clickEvents.length; ++i) {
- let h = clickEvents[i];
- if (h['$cb$'] == cb && h['$target$'] == target) {
- clickEvents.splice(i, 1);
- btn.clickEvents = clickEvents;
- break;
- }
- }
- }
- /**
- * @en add toggle event handler
- * @zh 添加Toggle事件
- * @param relativeNodePath to indicate a button node, can pass `string`|`Node`|`Button` here.
- * @param cb will be called when event emits. method format:(btn:Toggle,args:any)=>void
- * @param target the `this` argument of `cb`
- */
- onToggleEvent(relativeNodePath: string | Node | Toggle | ToggleContainer, cb: Function, target?: any, args?: any) {
- let buttonNode: Node = null;
- if (relativeNodePath instanceof Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof Toggle) {
- buttonNode = relativeNodePath.node;
- }
- else if (relativeNodePath instanceof ToggleContainer) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = find(relativeNodePath, this.node);
- }
- if (!buttonNode) {
- return null;
- }
- //添加转发器
- let agent = this.node.getComponent(__NodeEventAgent__);
- if (!agent) agent = this.node.addComponent(__NodeEventAgent__);
- let btn = buttonNode.getComponent(Toggle) as any;
- if (!btn) btn = buttonNode.getComponent(ToggleContainer) as any;
- let checkEvents = btn.checkEvents;
- let handler = new EventHandler();
- handler.target = this.node;
- handler.component = 'tgxNodeEventAgent';
- handler.handler = 'onToggleEvent';
- handler.customEventData = '' + _id++;
- //附加额外信息 供事件转发使用
- handler['$cb$'] = cb;
- handler['$target$'] = target;
- handler['$args$'] = args;
- checkEvents.push(handler);
- btn.checkEvents = checkEvents;
- }
- /**
- * @en remove toggle event handler
- * @zh 移除Toggle事件
- * @param relativeNodePath to indicate a button node, can pass `string`|`Node`|`Button` here.
- * @param cb will be called when event emits. method format:(btn:Toggle,args:any)=>void
- * @param target the `this` argument of `cb`
- * */
- offToggleEvent(relativeNodePath: string | Node | Toggle | ToggleContainer, cb: Function, target: any) {
- let buttonNode: Node = null;
- if (relativeNodePath instanceof Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof Toggle) {
- buttonNode = relativeNodePath.node;
- }
- else if (relativeNodePath instanceof ToggleContainer) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = find(relativeNodePath, this.node);
- }
- if (!buttonNode) {
- return null;
- }
- //添加转发器
- let agent = this.node.getComponent(__NodeEventAgent__);
- if (!agent) {
- return;
- }
- let btn = buttonNode.getComponent(Toggle) as any;
- if (!btn) {
- btn = buttonNode.getComponent(ToggleContainer) as any;
- }
- let checkEvents = btn.checkEvents;
- for (let i = 0; i < checkEvents.length; ++i) {
- let h = checkEvents[i];
- if (h['$cb$'] == cb && h['$target$'] == target) {
- checkEvents.splice(i, 1);
- btn.checkEvents = checkEvents;
- break;
- }
- }
- }
- //子类的所有操作,需要在这个函数之后。
- protected onCreated(...data: any[]){}
- //当界面销毁时调用
- protected onDispose(){}
- //
- protected onUpdate(dt?:number) { }
- }
|