/** @format */ import {Log} from '../utils/LogUtils' import {Delegate} from './Delegate' export class EventManager { // 同一type包含多个caller多个func private mListenerMap = new Map>() public has(type: string, caller: any, listener: Function): boolean { return this.find(type, caller, listener) !== null } public trigger(type: string, ...argArray: any[]): boolean { if (!type) { Log.error('Listener type is null!') return false } const delegateList: Delegate[] = [] const callerList: any[] = [] const listenerMap = this.mListenerMap.get(type) if (listenerMap) { listenerMap.forEach((listenerList, caller) => { for (const delegate of listenerList) { let insertIndex = delegateList.findIndex(obj => obj.priority < delegate.priority) if (insertIndex === -1) { insertIndex = delegateList.length } delegateList.splice(insertIndex, 0, delegate) callerList.splice(insertIndex, 0, caller) } for (let index = listenerList.length - 1; index >= 0; index -= 1) { if (listenerList[index].isOnce) { listenerList.splice(index, 1) } } if (listenerList.length <= 0 || !cc.isValid(caller)) { listenerMap.delete(caller) } }) if (listenerMap.size <= 0) { this.mListenerMap.delete(type) } } const {length} = delegateList for (let index = 0; index < length; index++) { const delegate: Delegate = delegateList[index] if (delegate.argArray.length > 0 && delegate.argArray[0].length == 0) { delegate.listener.call(callerList[index], ...argArray) } else { delegate.listener.call(callerList[index], ...delegate.argArray, ...argArray) } } return length > 0 } public add(type: string, caller: any, listener: Function, ...argArray: any[]): void { this.addListener(type, caller, listener, false, 0, ...argArray) } public addOnce(type: string, caller: any, listener: Function, ...argArray: any[]): void { this.addListener(type, caller, listener, true, 0, ...argArray) } public addTop(type: string, caller: any, listener: Function, ...argArray: any[]): void { this.addListener(type, caller, listener, false, 1, ...argArray) } public remove(type: string, caller: any, listener: Function, onceOnly?: boolean): void { this.removeBy((listenerType, listenerCaller, delegate) => { if (type && type !== listenerType) { return false } if (caller && caller !== listenerCaller) { return false } if (listener && listener !== delegate.listener) { return false } if (onceOnly && !delegate.isOnce) { return false } return true }) } public removeAll(caller: any): void { this.mListenerMap.forEach((listenerMap, type) => { listenerMap.delete(caller) if (listenerMap.size <= 0) { this.mListenerMap.delete(type) } }) } /** * 游戏重启时调用,防止重复注册监听 */ public reset() { this.mListenerMap.forEach((listenerMap, type) => { this.mListenerMap.delete(type) }) } private addListener( type: string, caller: any, listener: Function, isOnce: boolean, priority: number, ...argArray: any[] ): void { let delegate = this.find(type, caller, listener) if (delegate) { delegate.isOnce = isOnce delegate.priority = priority Log.error('Listener is already exist!', type) } else { delegate = new Delegate(listener, argArray, isOnce, priority) this.mListenerMap.get(type).get(caller).push(delegate) } } private removeBy(predicate: (type: string, caller: any, delegate: Delegate) => boolean): void { if (!predicate) { return } for (const [type, listenerMap] of Array.from(this.mListenerMap.entries())) { for (const [caller, listenerList] of Array.from(listenerMap.entries())) { for (let index = listenerList.length - 1; index >= 0; --index) { const delegate = listenerList[index] if (predicate(type, caller, delegate)) { listenerList.splice(index, 1) } } if (listenerList.length <= 0) { listenerMap.delete(caller) } } if (listenerMap.size <= 0) { this.mListenerMap.delete(type) } } } private find(type: string, caller: any, listener: Function): Delegate { if (!type) { Log.error('Listener type is null!') return undefined } if (!caller) { Log.error('Caller type is null!') return undefined } if (!listener) { Log.error('Listener is null!') return undefined } let listenerMap: Map if (this.mListenerMap.has(type)) { listenerMap = this.mListenerMap.get(type) } else { listenerMap = new Map() this.mListenerMap.set(type, listenerMap) } let listenerList: Delegate[] if (listenerMap.has(caller)) { listenerList = listenerMap.get(caller) } else { listenerList = [] listenerMap.set(caller, listenerList) } for (const delegate of listenerList) { if (delegate.mListener === listener) { return delegate } } return undefined } }