import { AssetManager, Component, EventTarget, Prefab, Widget, _decorator, error, instantiate, js, path, warn } from 'cc'; import { DEBUG, DEV, EDITOR } from 'cc/env'; import Core from '../Core'; import { Logger } from '../lib/logger/logger'; const { ccclass } = _decorator; const UserManagerPath = 'UserManager'; const DontRewriteFuns = ['emit', 'on', 'once', 'off', 'targetOff']; const uuid = new class UUID { private index = 0; public create(): string { if (this.index++ > 10000000) { this.index = 0; } return `${Date.now()}-${this.index}`; } }; const loadBegin = Logger.create('log', '#32cd32', DEV ? '[BaseManager] 下载开始' : '[BaseManager] [下载开始]'); const loadFinish = Logger.create('log', '#00ae9d', DEV ? '[BaseManager] 下载完成' : '[BaseManager] [下载完成]'); const loadError = Logger.create('log', '#ff4757', DEV ? '[BaseManager] 下载失败' : '[BaseManager] [下载失败]'); const initBegin = Logger.create('log', '#3e4145', DEV ? '[BaseManager] 初始化开始' : '[BaseManager] [初始化开始]'); const initFinish = Logger.create('log', '#008080', DEV ? '[BaseManager] 初始化完成' : '[BaseManager] [初始化完成]'); @ccclass('BaseManager') export default class BaseManager extends Component { // 事件管理器 private _base_event: EventTarget = new EventTarget(); // manager名字 private _base_manager_name: string = js.getClassName(this); public get managerName() { return this._base_manager_name; } constructor() { super(); if (EDITOR) { DontRewriteFuns.forEach((funName) => { if (BaseManager.prototype[funName] !== this[funName]) { warn(`[${this._base_manager_name}] 不应该重写父类方法{${funName}}`); } }); } if (this._base_manager_name !== 'Manager' && this._base_manager_name.slice(-7) === 'Manager') { const managerName = this._base_manager_name.slice(0, - 7); Core.inst.Manager[managerName] = this.constructor; Core.inst.manager[managerName.toLowerCase()] = this; } else if (EDITOR) { error(`[${this._base_manager_name}] manager命名错误(应为 xxxxManager 以Manager结尾)`); } else if (DEBUG) { error(`[${this._base_manager_name}] manager命名错误(应为 xxxxManager 以Manager结尾)`); } } // 用来初始化组件或节点的一些属性,当该组件被第一次添加到节点上或用户点击了它的 Reset 菜单时调用。这个回调只会在编辑器下调用。 resetInEditor() { const widget = this.node.getComponent(Widget) || this.node.addComponent(Widget); widget.isAlignBottom = true; widget.isAlignLeft = true; widget.isAlignRight = true; widget.isAlignTop = true; widget.top = 0; widget.left = 0; widget.right = 0; widget.bottom = 0; widget.alignMode = Widget.AlignMode.ON_WINDOW_RESIZE; } /** * [无序] 自身初始化完成, init执行完毕后被调用 */ protected onInited() { } /** * [无序] 所有manager初始化完成 */ protected onFinished() { } /** * [无序] 初始化manager,在初始化完成后,调用finish方法 * @param {Function} finish */ protected init(finish?: Function) { finish && finish(); } protected createUUID() { return uuid.create(); } /**打印日志 */ protected get log() { if (DEV) { return window.console.log.bind(window.console, '%c %s %c %s ', 'background:#4169e1; padding: 2px; border-radius: 5px 0 0 5px; border: 1px solid #4169e1; color: #fff; font-weight: normal;', `[${this._base_manager_name}] LOG ${new Date().toLocaleString()}`, 'background:#ffffff ; padding: 2px; border-radius: 0 5px 5px 0; border: 1px solid #4169e1; color: #4169e1; font-weight: normal;' ); } return window.console.log.bind(window.console, `[${this._base_manager_name}] [LOG] [${new Date().toLocaleString()}]`, ); } /**打印警告 */ protected get warn() { if (DEV) { return window.console.warn.bind(window.console, '%c %s %c %s ', 'background:#ff7f50; padding: 2px; border-radius: 5px 0 0 5px; border: 1px solid #ff7f50; color: #fff; font-weight: normal;', `[${this._base_manager_name}] WARN ${new Date().toLocaleString()}`, 'background:#ffffff ; padding: 2px; border-radius: 0 5px 5px 0; border: 1px solid #ff7f50; color: #ff7f50; font-weight: normal;' ); } return window.console.warn.bind(window.console, `[${this._base_manager_name}] [WARN] [${new Date().toLocaleString()}]`, ); } /**打印错误 */ protected get error() { if (DEV) { return window.console.error.bind(window.console, '%c %s %c %s ', 'background:#ff4757; padding: 2px; border-radius: 5px 0 0 5px; border: 1px solid #ff4757; color: #fff; font-weight: normal;', `[${this._base_manager_name}] ERROR ${new Date().toLocaleString()}`, 'background:#ffffff ; padding: 2px; border-radius: 0 5px 5px 0; border: 1px solid #ff4757; color: #ff4757; font-weight: normal;' ); } return window.console.error.bind(window.console, `[${this._base_manager_name}] [ERROR] [${new Date().toLocaleString()}]`, ); } /** * [系统内置] 事件分发 */ public emit(event: string | number, ...data: any[]) { this._base_event.emit(event as any, ...data); } /** * [系统内置] 事件监听 */ public on(event: string | number, cb: (...any: any[]) => void, target?: any) { this._base_event.on(event as any, cb, target); } /** * [系统内置] 事件监听 */ public once(event: string | number, cb: (...any: any[]) => void, target?: any) { this._base_event.once(event as any, cb, target); } /** * [系统内置] 事件移除监听 */ public off(event: string | number, cb?: (...any: any[]) => void, target?: any) { this._base_event.off(event as any, cb, target); } /** * [系统内置] 事件移除监听 */ public targetOff(target: any) { this._base_event.targetOff(target); } /***********************************静态***********************************/ /** * 框架内置Manager的数量 * @private */ public static get sysMgrCount() { return 5; } /** * 获得初始化资源的数量(包括sysMgrCount) * @private */ public static getTotalAssetNum(bundle: AssetManager.Bundle) { let count = this.sysMgrCount; if (!bundle) return count; const array = bundle.getDirWithPath('/', Prefab) as { uuid: string, path: string, ctor: Function }[]; array.forEach(function (item) { if (item.path.endsWith('Manager')) { count++; } }); return count; } /** * 获得初始化资源的数量 * @private */ public static getUserAssetUrls(bundle: AssetManager.Bundle) { const pathArr: string[] = []; if (!bundle) return pathArr; const array = bundle.getDirWithPath('/', Prefab) as { uuid: string, path: string, ctor: Function }[]; array.forEach(function (item) { if (item.path.endsWith('Manager')) { pathArr.push(item.path); } }); return pathArr; } /** * 静态方法,初始化manager,该方法必须在场景初始化完毕之后调用 * @private */ public static init( bundle: AssetManager.Bundle, progress: (completeAsset: Number, totalAsset: Number) => any, complete: (totalAsset: Number) => any) { const urls = this.getUserAssetUrls(bundle); const totalAsset = urls.length + this.sysMgrCount; let completeAsset = 0; const onProgress = function (next: Function, manager: BaseManager) { if (DEBUG) { const startTime = window?.performance?.now ? performance.now() : Date.now(); initBegin(manager.managerName); return function () { manager.onInited(); if (DEBUG) { const endTime = window?.performance?.now ? performance.now() : Date.now(); initFinish(`${manager.managerName} 耗时:${(endTime - startTime).toFixed(6)} ms`); } progress && progress(++completeAsset, totalAsset); next(); }; } return function () { manager.onInited(); progress && progress(++completeAsset, totalAsset); next(); }; }; // 用户manager(动态添加) const userMgrList: BaseManager[] = []; // 系统manager(静态内置) const sysMgrList: BaseManager[] = [Core.inst.manager.event, Core.inst.manager.timer, Core.inst.manager.loader, Core.inst.manager.ui, Core.inst.manager.sound] as any as BaseManager[]; // 初始化系统manager const initSysMgrTask = Core.inst.lib.task.createASync(); sysMgrList.forEach(function (manager: BaseManager) { initSysMgrTask.add(function (next) { manager.init(onProgress(next, manager)); }); }); // 加载用户manager const loadUserMgrTask = Core.inst.lib.task.createASync(); const UserManagerRoot = Core.inst.manager.ui.root.getChildByPath(UserManagerPath); urls.forEach(function (url) { loadUserMgrTask.add(function (next, retry) { if (DEBUG) { const managerName = path.basename(url); const startTime = window?.performance?.now ? performance.now() : Date.now(); loadBegin(managerName); bundle.load(url, Prefab, function (err, prefab: Prefab) { if (err || !prefab) { loadError(managerName, '重试...'); retry(1); } else { const endTime = window?.performance?.now ? performance.now() : Date.now(); loadFinish(`${managerName} 耗时:${(endTime - startTime).toFixed(6)} ms`); const node = instantiate(prefab); node.parent = UserManagerRoot; node.active = true; userMgrList.push(node.getComponent(BaseManager)); next(); } }); return; } bundle.load(url, Prefab, function (err, prefab: Prefab) { if (err || !prefab) { loadError(path.basename(url), '重试...'); retry(1); } else { const node = instantiate(prefab); node.parent = UserManagerRoot; node.active = true; userMgrList.push(node.getComponent(BaseManager)); next(); } }); }); }); Core.inst.lib.task.createAny() .add([ next => initSysMgrTask.start(next), next => loadUserMgrTask.start(next), ]) .add(function (next) { Core.emit(Core.EventType.EVENT_SYS_MANAGER_INITED); next(); }) .add(function (next) { // 初始化用户manager const initUserMgrTask = Core.inst.lib.task.createASync(); userMgrList.forEach(manager => { initUserMgrTask.add(function (next) { manager.init(onProgress(next, manager)); }); }); initUserMgrTask.start(next); }) .add(function (next) { Core.emit(Core.EventType.EVENT_USER_MANAGER_INITED); Core.emit(Core.EventType.EVENT_MANAGER_INITED); next(); }) .add(function (next) { // 所有manager初始化完成后,触发回调 sysMgrList.forEach(function (manager) { manager.onFinished(); }); userMgrList.forEach(function (manager) { manager.onFinished(); }); next(); }) .start(function () { Core.emit(Core.EventType.EVENT_MANAGER_FINISHED); complete && complete(totalAsset); }); } }