123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- const { ccclass, property } = cc._decorator;
- /***
- * @en internal class, used for handling node event.
- * @zh 内部类,用于节点事件监听
- *
- * */
- export class __NodeEventAgent__ extends cc.Component {
- /***
- * @en recieve button click event and deliver them to the real handlers.
- * @zh 接受按钮事件,并转发给真正的处理函数
- * */
- onButtonClicked(evt: cc.Event.EventTouch, customEventData) {
- let btn = (evt.target as cc.Node).getComponent(cc.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: cc.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]);
- }
- }
- }
- }
- /**
- * @en manage event-handlers automatically, will remove all handlers when the ui destroyed.
- * @zh 自动管理事件,将在UI销毁时自动清理
- * */
- export class AutoEventHandler {
- private _handlers = [];
- on(event: string, cb: () => void, target?: any, once?: boolean) {
- this._handlers.push({
- event: event,
- cb: cb,
- target: target,
- once: once
- });
- cc.game.on(event, cb, target, once);
- }
- off(event: string, cb: () => void, target?: any, once?: boolean) {
- cc.game.off(event, cb, target);
- for (let i = 0; i < this._handlers.length; ++i) {
- let h = this._handlers[i];
- if (h.event == event && h.cb == cb && h.target == target && h.once == once) {
- this._handlers.splice(i, 1);
- return;
- }
- }
- }
- dispose() {
- for (let i = 0; i < this._handlers.length; ++i) {
- let h = this._handlers[i];
- cc.game.off(h.event, h.cb, h.target);
- }
- }
- }
- /**
- * @en base class of UI Panel
- * @zh 各类UI面板基类
- * */
- export class UIController extends cc.EventTarget {
- private static _idBase = 1000;
- private static _controllers: UIController[] = [];
- private _instId: number = 0;
- private _prefab: string | cc.Prefab;
- private _layer: number;
- private _layout: any;
- protected node: cc.Node;
- private _destroyed:boolean = false;
- constructor(prefab: string | cc.Prefab, layer: number, layoutCls: any) {
- super();
- this._prefab = prefab;
- this._layer = layer;
- this._layout = layoutCls;
- this._instId = UIController._idBase++;
- UIController._controllers.push(this);
- }
- /***
- * @en the instance id to indicate an unique ui panel.
- * @zh 实例ID,用于标记一个唯一面板实例
- * */
- public get instId(): number {
- return this._instId;
- }
- /***
- * @en url of the prefab used by this ui panel.
- * @zh 本UI使用prefab路径
- * */
- public get prefab(): string | cc.Prefab {
- return this._prefab;
- }
- /***
- * @en layer of this ui panel.
- * @zh 本UI所在的UI层级
- * */
- public get layer(): number {
- return this._layer;
- }
- /***
- * @en layout of this ui panel.
- * @zh 本UI所在的UI层级
- * */
- public get layout(): any {
- return this._layout;
- }
- /***
- * @en hide and destroy all ui panel.
- * @zh 隐藏并销毁所有UI面板
- * */
- public static hideAll() {
- while (this._controllers.length) {
- this._controllers[0].hide();
- }
- }
- //update all ui, called by UIMgr.
- public static updateAll() {
- for (let i = 0; i < this._controllers.length; ++i) {
- let ctrl = this._controllers[i];
- if (ctrl.node && cc.isValid(ctrl.node)) {
- this._controllers[i].onUpdate();
- }
- }
- }
- //setup this ui,called by UIMgr.
- public setup(node: cc.Node) {
- this.node = node;
- if (this._layout) {
- this._layout = this.node.getComponent(this._layout);
- }
- //notify sub class to handle something.
- //节点创建完毕,调用子类的处理函数。
- this.onCreated();
- //check whether it has been destroyed, if has, hide it.
- //检查是否为已销毁,如果已销毁,则走销毁流程
- if(this._destroyed){
- this.hide();
- }
- }
- /**
- * @en hide and destroy this ui panel.
- * @zh 隐藏并销毁此UI面板cc.Component.EventHandler
- * */
- public hide() {
- this._destroyed = true;
- if(!this.node){
- return;
- }
- this.node.removeFromParent();
- for (let i = 0; i < UIController._controllers.length; ++i) {
- if (UIController._controllers[i] == this) {
- UIController._controllers.splice(i, 1);
- break;
- }
- }
- this.onDispose();
- this.node.destroy();
- this.node = null;
- }
- /**
- * @en add button event handler
- * @zh 添加按钮事件
- * @param relativeNodePath to indicate a button node, can pass `string`|`cc.Node`|`cc.Button` here.
- * @param cb will be called when event emits. method format:(btn:cc.Button,args:any)=>void
- * @param target the `this` argument of `cb`
- * */
- onButtonEvent(relativeNodePath: string | cc.Node | cc.Button, cb: Function, target?: any, args?: any) {
- let buttonNode: cc.Node = null;
- if (relativeNodePath instanceof cc.Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof cc.Button) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = cc.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(cc.Button);
- let clickEvents = btn.clickEvents;
- let handler = new cc.Component.EventHandler();
- handler.target = this.node;
- handler.component = '__NodeEventAgent__';
- handler.handler = 'onButtonClicked';
- handler.customEventData = '' + UIController._idBase++;
- //附加额外信息 供事件转发使用
- 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`|`cc.Node`|`cc.Button` here.
- * @param cb will be called when event emits.
- * @param target the `this` argument of `cb`
- * */
- offButtonEvent(relativeNodePath: string | cc.Node | cc.Button, cb: Function, target: any) {
- let buttonNode: cc.Node = null;
- if (relativeNodePath instanceof cc.Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof cc.Button) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = cc.find(relativeNodePath, this.node);
- }
- if (!buttonNode) {
- return; ``
- }
- let agent = this.node.getComponent(__NodeEventAgent__);
- if (!agent) {
- return;
- }
- let btn = buttonNode.getComponent(cc.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`|`cc.Node`|`cc.Button` here.
- * @param cb will be called when event emits. method format:(btn:cc.Button,args:any)=>void
- * @param target the `this` argument of `cb`
- * */
- onToggleEvent(relativeNodePath: string | cc.Node | cc.Button | cc.ToggleContainer, cb: Function, target?: any, args?: any) {
- let buttonNode: cc.Node = null;
- if (relativeNodePath instanceof cc.Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof cc.Button) {
- buttonNode = relativeNodePath.node;
- }
- else if (relativeNodePath instanceof cc.ToggleContainer) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = cc.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(cc.Button) as any;
- if (!btn) {
- btn = buttonNode.getComponent(cc.ToggleContainer) as any;
- }
- let checkEvents = btn.checkEvents;
- let handler = new cc.Component.EventHandler();
- handler.target = this.node;
- handler.component = '__NodeEventAgent__';
- handler.handler = 'onToggleEvent';
- handler.customEventData = '' + UIController._idBase++;
- //附加额外信息 供事件转发使用
- 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`|`cc.Node`|`cc.Button` here.
- * @param cb will be called when event emits. method format:(btn:cc.Button,args:any)=>void
- * @param target the `this` argument of `cb`
- * */
- offToggleEvent(relativeNodePath: string | cc.Node | cc.Button | cc.ToggleContainer, cb: Function, target: any) {
- let buttonNode: cc.Node = null;
- if (relativeNodePath instanceof cc.Node) {
- buttonNode = relativeNodePath;
- }
- else if (relativeNodePath instanceof cc.Button) {
- buttonNode = relativeNodePath.node;
- }
- else if (relativeNodePath instanceof cc.ToggleContainer) {
- buttonNode = relativeNodePath.node;
- }
- else {
- buttonNode = cc.find(relativeNodePath, this.node);
- }
- if (!buttonNode) {
- return null;
- }
- //添加转发器
- let agent = this.node.getComponent(__NodeEventAgent__);
- if (!agent) {
- return;
- }
- let btn = buttonNode.getComponent(cc.Button) as any;
- if (!btn) {
- btn = buttonNode.getComponent(cc.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;
- }
- }
- }
- /***
- * @en the extra resource needed by this ui panel.the ui will not be created until these res loaded.
- * @zh 本UI使用的依赖资源.UI会等这些资源加载完成后才创建。
- * */
- public getRes(): [] {
- return [];
- }
- //子类的所有操作,需要在这个函数之后。
- protected onCreated() { }
- //销毁
- protected onDispose() { }
- //
- protected onUpdate() { }
- }
|