Files
RedPacketRain/extensions/app/assets/base/BaseManager.ts
2026-03-04 11:30:40 +08:00

359 lines
13 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
});
}
}