1. 为 Gui.ts 添加完整类型注解

2.修复 CCBusiness 事件释放方法
3.提取 CCEntity 类型至统一模块,优化 addPrefab 方法
This commit is contained in:
dgflash
2026-02-23 11:53:30 +08:00
parent 2da486bd77
commit aec1a6567f
11 changed files with 158 additions and 52 deletions

View File

@@ -1,3 +1,4 @@
import type { GameComponentCtor, UICtor } from '../../module/types/Types';
import type { UIConfigMap } from './layer/LayerEnum';
import type { UIConfig } from './layer/UIConfig';
@@ -5,10 +6,9 @@ const configs: UIConfigMap = {};
export namespace gui {
/** 注册界面组件 */
export function register(key: string, config: UIConfig) {
return function (ctor: any) {
//@ts-ignore
ctor[gui.internal.GUI_KEY] = key;
export function register(key: string, config: UIConfig): (ctor: GameComponentCtor) => void {
return function (ctor: GameComponentCtor): void {
(ctor as any)[gui.internal.GUI_KEY] = key;
internal.setConfig(key, config);
};
}
@@ -19,28 +19,26 @@ export namespace gui {
export const GUI_KEY = 'OOPS_GUI_KEY';
/** 获取界面唯一关键字 */
export function getKey(ctor: any) {
return ctor[GUI_KEY];
export function getKey(ctor: UICtor): string {
return (ctor as any)[GUI_KEY];
}
/** 获取界面组件配置 */
export function getConfig(key: string) {
export function getConfig(key: string): UIConfig {
return configs[key];
}
/** 获取界面组件配置 */
export function setConfig(key: string, config: UIConfig) {
const c = getConfig(key);
if (c == null) {
configs[key] = config;
}
else {
/** 设置界面组件配置 */
export function setConfig(key: string, config: UIConfig): void {
if (configs[key] != null) {
console.error(`界面${key}重复注册`);
return;
}
configs[key] = config;
}
/** 初始化界面组件配置 */
export function initConfigs(uicm: UIConfigMap) {
export function initConfigs(uicm: UIConfigMap): void {
for (const key in uicm) {
configs[key] = uicm[key];
}

View File

@@ -21,7 +21,7 @@ export class CCBusiness<T extends CCEntity> {
destroy() {
// 释放消息对象
if (this._event) {
this._event.destroy();
this._event.clear();
this._event = null;
}

View File

@@ -1,37 +1,20 @@
import type { __private, Node } from 'cc';
import { resLoader } from '../../core/common/loader/ResLoader';
import type { Node } from 'cc';
import { oops } from '../../core/Oops';
import { gui } from '../../core/gui/Gui';
import type { UIParam } from '../../core/gui/layer/LayerUIElement';
import { LayerUIElement } from '../../core/gui/layer/LayerUIElement';
import { oops } from '../../core/Oops';
import { ViewUtil } from '../../core/utils/ViewUtil';
import { ecs } from '../../libs/ecs/ECS';
import type { ECSEntity } from '../../libs/ecs/ECSEntity';
import type { CompType } from '../../libs/ecs/ECSModel';
import type { BusinessCtor, EntityCtor, GUIView, UICtor, ViewCtor } from '../types/Types';
import type { CCBusiness } from './CCBusiness';
import type { CCView } from './CCView';
import { GameComponent } from './GameComponent';
/** ECS 组件构造函数类型(用于继承自 ecs.Comp 的组件) */
type ECSCtor<T extends ecs.Comp> =
| __private.__types_globals__Constructor<T>
| __private.__types_globals__AbstractedConstructor<T>;
/** UI 组件构造函数类型(用于继承自 GameComponent 并使用 gui.register 注册的组件) */
type UICtor<T extends GameComponent = GameComponent> =
| __private.__types_globals__Constructor<T>
| __private.__types_globals__AbstractedConstructor<T>;
/** ECS 游戏视图组件类型(继承自 CCView用于完整的 ECS 组件) */
export type ECSView = CCView<CCEntity>;
/** GUI 视图组件类型(继承自 GameComponent使用 @gui.register 装饰器注册的组件) */
export type GUIView = GameComponent;
/** ECS 实体构造函数类型 */
type EntityCtor<T extends CCEntity = CCEntity> = new (...args: any[]) => T;
/** ECS 业务逻辑组件构造函数类型 */
type BusinessCtor<T extends CCBusiness<CCEntity> = CCBusiness<CCEntity>> = new (...args: any[]) => T;
/** ECS 游戏模块实体 */
export abstract class CCEntity extends ecs.Entity {
//#region 子模块管理
/** 单例子实体集合key: 实体类构造函数value: 实体实例) */
private singletons: Map<EntityCtor, ECSEntity> = null!;
@@ -94,37 +77,40 @@ export abstract class CCEntity extends ecs.Entity {
//#region 游戏视图层管理
/**
* 通过资源内存中获取预制上的组件添加到ECS实体中
* @param ctor 界面逻辑组件
* @param ctor 界面逻辑组件(支持 ECSView 或使用 gui.register 注册的 GUIView
* @param parent 显示对象父级
* @param path 显示资源地址
* @param bundleName 资源包名称
* @param path 显示资源地址(可选,不传时使用 @game.prefab 装饰器注册的路径)
* @param bundleName 资源包名称(可选,不传时使用 @game.prefab 装饰器注册的包名)
*/
async addPrefab<T extends ECSView>(
ctor: ECSCtor<T>,
async addPrefab<T extends GUIView>(
ctor: ViewCtor<T>,
parent: Node | GameComponent,
path: string,
bundleName: string = resLoader.defaultBundleName
path?: string,
bundleName?: string
): Promise<Node> {
// 未传入路径时,从装饰器注册的数据中获取
if (path == null) {
path = (ctor as any).GAME_PREFAB_PATH;
bundleName = (ctor as any).GAME_PREFAB_BUNDLE;
if (path == null) {
throw new Error(`组件 ${(ctor as any).name} 未使用 @game.prefab 装饰器注册,请添加 @game.prefab('path/to/prefab') 装饰器或手动传入路径参数`);
}
}
let node: Node;
// 跟随父节点释放自动释放当前资源
if (parent instanceof GameComponent) {
node = await parent.createPrefabNode(path, bundleName);
const comp = node.getComponent(ctor);
if (!comp) {
throw new Error(`组件 ${ctor.name} 不存在于预制 ${path}`);
}
this.add(comp);
if (comp) this.add(comp as unknown as ecs.Comp);
node.parent = parent.node;
}
// 手动内存管理
else {
node = await ViewUtil.createPrefabNodeAsync(path, bundleName);
const comp = node.getComponent(ctor);
if (!comp) {
throw new Error(`组件 ${ctor.name} 不存在于预制 ${path}`);
}
this.add(comp);
if (comp) this.add(comp as unknown as ecs.Comp);
node.parent = parent;
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "72863800-5c5d-44f0-b86c-a5b0d0643d8f",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,32 @@
import { resLoader } from '../../core/common/loader/ResLoader';
import type { GameComponentCtor } from '../types/Types';
/**
* 游戏装饰器命名空间
*/
export namespace prefab {
/**
* Prefab 装饰器 - 用于标记组件的预制体路径
* @param path 预制体路径
* @param bundleName 资源包名称(可选,默认使用 resLoader.defaultBundleName
* @example
* ```typescript
* @ccclass('V_Backpack_Prop')
* @ecs.register('V_Backpack_Prop', false)
* @prefab.register('gui/backpack/prefab/V_Backpack_Prop')
* export class V_Backpack_Prop extends CCView<Backpack> {
* // ...
* }
*
* // 使用时
* await entity.addPrefab(V_Backpack_Prop, parentNode);
* ```
*/
export function register(path: string, bundleName?: string): (ctor: GameComponentCtor) => void {
return function (ctor: GameComponentCtor): void {
const bundle = bundleName || resLoader.defaultBundleName;
(ctor as any).GAME_PREFAB_PATH = path;
(ctor as any).GAME_PREFAB_BUNDLE = bundle;
};
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "7c1ef3cb-50c6-49d4-b17c-11b8d37535bf",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,8 @@
/**
* 游戏装饰器模块
* 提供各种装饰器用于简化开发
*/
export { prefab as game } from './GamePrefabDecorator';
export type { PrefabConfig as PrefabMetadata } from './GamePrefabDecorator';

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "7f85c52b-9f8e-4f0d-b749-7dca9fb8f57e",
"files": [],
"subMetas": {},
"userData": {}
}

9
assets/module/types.meta Normal file
View File

@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "050d0e85-32a0-4573-b0ef-d8911bf7f13d",
"files": [],
"subMetas": {},
"userData": {}
}

View File

@@ -0,0 +1,37 @@
import type { GameComponent } from 'db://oops-framework/module/common/GameComponent';
import type { ecs } from 'db://oops-framework/libs/ecs/ECS';
import type { CCView } from 'db://oops-framework/module/common/CCView';
import type { CCEntity } from 'db://oops-framework/module/common/CCEntity';
import type { CCBusiness } from 'db://oops-framework/module/common/CCBusiness';
// ==================== 通用构造函数类型 ====================
/** 通用构造函数类型 */
type Ctor<T = any> = new (...args: any[]) => T;
// ==================== 视图类型 ====================
/** GameComponent 及其子类的构造函数类型,用于类型安全的组件实例化 */
export type GameComponentCtor<T extends GameComponent = GameComponent> = Ctor<T>;
/** UI 组件构造函数类型(用于继承自 GameComponent 并使用 gui.register 注册的组件) */
export type UICtor<T extends GameComponent = GameComponent> = Ctor<T>;
/** 通用的视图组件构造函数类型(支持 ECSView 或 GUIView */
export type ViewCtor<T extends GameComponent | ecs.Comp = GameComponent | ecs.Comp> = Ctor<T>;
/** ECS 游戏视图组件类型(继承自 CCView用于完整的 ECS 组件) */
export type ECSView = CCView<CCEntity>;
/** GUI 视图组件类型(继承自 GameComponent使用 @gui.register 装饰器注册的组件) */
export type GUIView = GameComponent;
// ==================== 实体类型 ====================
/** ECS 实体构造函数类型 */
export type EntityCtor<T extends CCEntity = CCEntity> = Ctor<T>;
// ==================== 业务逻辑类型 ====================
/** ECS 业务逻辑组件构造函数类型 */
export type BusinessCtor<T extends CCBusiness<CCEntity> = CCBusiness<CCEntity>> = Ctor<T>;

View File

@@ -0,0 +1,9 @@
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "4d52b2a4-af0e-4ae4-b575-920ec36b6bcf",
"files": [],
"subMetas": {},
"userData": {}
}