Files
oops-plugin-framework/assets/module/common/CCEntity.ts
dgflash dfc0690dd2 优化
2025-10-26 21:34:40 +08:00

219 lines
6.9 KiB
TypeScript
Raw 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 { __private, Node } from "cc";
import { resLoader } from "../../core/common/loader/ResLoader";
import { gui } from "../../core/gui/Gui";
import { LayerUIElement, UIParam } from "../../core/gui/layer/LayerUIElement";
import { oops } from "../../core/Oops";
import { ViewUtil } from "../../core/utils/ViewUtil";
import { ecs } from "../../libs/ecs/ECS";
import { ECSEntity } from "../../libs/ecs/ECSEntity";
import { CompType } from "../../libs/ecs/ECSModel";
import { CCBusiness } from "./CCBusiness";
import { CCView } from "./CCView";
import { CCViewVM } from "./CCViewVM";
import { GameComponent } from "./GameComponent";
export type ECSCtor<T extends ecs.Comp> = __private.__types_globals__Constructor<T> | __private.__types_globals__AbstractedConstructor<T>;
export type ECSView = CCViewVM<CCEntity> | CCView<CCEntity>;
/** ECS 游戏模块实体 */
export abstract class CCEntity extends ecs.Entity {
//#region 子模块管理
/** 单例子实体 */
private singletons: Map<any, ECSEntity> = null!;
/**
* 批量添加单例子实体
* @param clss 单例子实体类数组
*/
addChildSingletons<T extends CCEntity>(...clss: any[]) {
for (let ctor of clss) {
this.addChildSingleton<T>(ctor);
}
}
/**
* 添加单例子实体
* @param cls 单例子实体类
* @returns 单例子实体
*/
addChildSingleton<T extends CCEntity>(cls: any): T {
if (this.singletons == null) this.singletons = new Map();
if (this.singletons.has(cls)) {
console.error(`${cls.name} 单例子实体已存在`);
return null!;
}
let entity = ecs.getEntity<T>(cls);
this.singletons.set(cls, entity);
this.addChild(entity);
return entity as T;
}
/**
* 获取单例子实体
* @param cls 单例子实体类
* @returns 单例子实体
*/
getChildSingleton<T extends CCEntity>(cls: any): T {
return this.singletons.get(cls) as T;
}
/** 移除单例子实体 */
removeChildSingleton(cls: any) {
let entity = this.singletons.get(cls);
if (entity) {
this.singletons.delete(cls);
this.removeChild(entity);
}
}
//#endregion
//#region 游戏视图层管理
/**
* 通过资源内存中获取预制上的组件添加到ECS实体中
* @param ctor 界面逻辑组件
* @param parent 显示对象父级
* @param path 显示资源地址
* @param bundleName 资源包名称
*/
addPrefab<T extends ECSView>(ctor: ECSCtor<T>, parent: Node | GameComponent, path: string, bundleName: string = resLoader.defaultBundleName): Promise<Node> {
return new Promise(async (resolve, reject) => {
let node: Node = null!;
// 跟随父节点施放自动释放当前资源
if (parent instanceof GameComponent) {
node = await parent.createPrefabNode(path, bundleName);
const comp = node.getComponent(ctor)!;
this.add(comp);
node.parent = parent.node;
}
// 手动内存管理
else {
node = await ViewUtil.createPrefabNodeAsync(path, bundleName);
const comp = node.getComponent(ctor)!;
this.add(comp);
node.parent = parent;
}
resolve(node);
});
}
/**
* 添加视图层组件
* @param ctor 界面逻辑组件
* @param params 界面参数
* @returns 界面节点
*/
addUi<T extends ECSView>(ctor: ECSCtor<T>, params?: UIParam): Promise<Node> {
return new Promise<Node>(async (resolve, reject) => {
const key = gui.internal.getKey(ctor);
if (key) {
if (params == null) {
params = { preload: true };
}
else {
params.preload = true;
}
const node = await oops.gui.open(key, params);
const comp = node.getComponent(ctor) as ecs.Comp;
this.add(comp);
oops.gui.show(key);
resolve(node);
}
else {
console.error(`${ctor.name} 界面组件未使用 gui.register 注册`);
}
});
}
/**
* 移除视图层组件
* @param ctor 界面逻辑组件
*/
removeUi(ctor: CompType<ecs.IComp>) {
const key = gui.internal.getKey(ctor);
if (key) {
const node = oops.gui.get(key);
if (node == null) {
console.error(`${key} 界面重复关闭`);
return;
}
const comp = node.getComponent(LayerUIElement);
if (comp) {
// 处理界面关闭动画播放完成后移除ECS组件避免使用到组件实体数据还在动画播放时在使用导致的空对象问题
comp.onClose = this.remove.bind(this, ctor);
oops.gui.remove(key);
}
}
else {
this.remove(ctor);
}
}
//#endregion
//#region 游戏业务层管理
/** 模块业务逻辑组件 */
private businesss: Map<any, CCBusiness<CCEntity>> = null!;
/**
* 批量添加组件
* @param ctors 组件类
* @returns
*/
addBusinesss<T extends CCBusiness<CCEntity>>(...clss: any[]) {
for (let ctor of clss) {
this.addBusiness<T>(ctor);
}
}
/**
* 添加业务逻辑组件
* @param cls 业务逻辑组件类
* @returns 业务逻辑组件实例
*/
addBusiness<T extends CCBusiness<CCEntity>>(cls: any): T {
if (this.businesss == null) this.businesss = new Map();
if (this.businesss.has(cls)) {
console.error(`${cls.name} 业务逻辑组件已存在`);
return null!;
}
let business = new cls();
business.ent = this;
business.init();
this.businesss.set(cls, business);
return business as T;
}
/**
* 获取业务逻辑组件
* @param cls 业务逻辑组件类
* @returns 业务逻辑组件实例
*/
getBusiness<T extends CCBusiness<CCEntity>>(cls: any): T {
return this.businesss.get(cls) as T;
}
/**
* 移除业务逻辑组件
* @param cls 业务逻辑组件类
*/
removeBusiness(cls: any) {
let business = this.businesss.get(cls);
if (business) this.businesss.delete(cls);
}
//#endregion
destroy(): void {
if (this.singletons) {
this.singletons.clear();
this.singletons = null!;
}
if (this.businesss) {
this.businesss.forEach(business => business.destroy());
this.businesss.clear();
this.businesss = null!;
}
super.destroy();
}
}