refactor(arch): 改进 ServiceToken 设计,统一服务获取模式 (#300)
* refactor(arch): 移除全局变量,使用 ServiceToken 模式 - 创建 PluginServiceRegistry 类,提供类型安全的服务注册/获取 - 添加 ProfilerServiceToken 和 CollisionLayerConfigToken - 重构所有 __PROFILER_SERVICE__ 全局变量访问为 getProfilerService() - 重构 __PHYSICS_RAPIER2D__ 全局变量访问为 CollisionLayerConfigToken - 在 Core 类添加 pluginServices 静态属性 - 添加 getService.ts 辅助模块简化服务获取 这是 ServiceToken 模式重构的第一阶段,移除了最常用的两个全局变量。 后续可继续应用到其他模块(Camera/Audio 等)。 * refactor(arch): 改进 ServiceToken 设计,移除重复常量 - tokens.ts: 从 engine-core 导入 createServiceToken(符合规范) - tokens.ts: Token 使用接口 IProfilerService 而非具体类 - 移除 AssetPickerDialog 和 ContentBrowser 中重复的 MANAGED_ASSET_DIRECTORIES - 统一从 editor-core 导入 MANAGED_ASSET_DIRECTORIES * fix(type): 修复 IProfilerService 接口与实现类型不匹配 - 将 ProfilerData 等数据类型移到 tokens.ts 以避免循环依赖 - ProfilerService 显式实现 IProfilerService 接口 - 更新使用方使用 IProfilerService 接口类型而非具体类 * refactor(type): 移除类型重导出,改进类型安全 - 删除 ProfilerService.ts 中的类型重导出,消费方直接从 tokens.ts 导入 - PanelDescriptor 接口添加 titleZh 属性,移除 App.tsx 中的 as any - 改进 useDynamicIcon.ts 的类型安全,使用正确的 Record 类型 * refactor(arch): 为模块添加 ServiceToken 支持 - Material System: 创建 tokens.ts,定义 IMaterialManager 接口和 MaterialManagerToken - Audio: 创建预留 tokens.ts 文件,为未来 AudioManager 服务扩展做准备 - Camera: 创建预留 tokens.ts 文件,为未来 CameraManager 服务扩展做准备 遵循"谁定义接口,谁导出 Token"原则,统一服务访问模式
This commit is contained in:
@@ -1,29 +1,13 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { SettingsService } from './SettingsService';
|
||||
import { LogLevel } from '@esengine/ecs-framework';
|
||||
|
||||
export interface SystemPerformanceData {
|
||||
name: string;
|
||||
executionTime: number;
|
||||
entityCount: number;
|
||||
averageTime: number;
|
||||
percentage: number;
|
||||
}
|
||||
|
||||
export interface RemoteEntity {
|
||||
id: number;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
active: boolean;
|
||||
activeInHierarchy: boolean;
|
||||
componentCount: number;
|
||||
componentTypes: string[];
|
||||
parentId: number | null;
|
||||
childIds: number[];
|
||||
depth: number;
|
||||
tag: number;
|
||||
updateOrder: number;
|
||||
}
|
||||
import type {
|
||||
IProfilerService,
|
||||
ProfilerData,
|
||||
SystemPerformanceData,
|
||||
RemoteEntity,
|
||||
AdvancedProfilerDataPayload
|
||||
} from './tokens';
|
||||
|
||||
export interface RemoteComponentDetail {
|
||||
typeName: string;
|
||||
@@ -45,29 +29,10 @@ export interface RemoteEntityDetails {
|
||||
parentName: string | null;
|
||||
}
|
||||
|
||||
export interface ProfilerData {
|
||||
totalFrameTime: number;
|
||||
systems: SystemPerformanceData[];
|
||||
entityCount: number;
|
||||
componentCount: number;
|
||||
fps: number;
|
||||
entities?: RemoteEntity[];
|
||||
}
|
||||
|
||||
type ProfilerDataListener = (data: ProfilerData) => void;
|
||||
|
||||
/**
|
||||
* 高级性能数据结构(用于高级性能分析器)
|
||||
*/
|
||||
export interface AdvancedProfilerDataPayload {
|
||||
advancedProfiler?: any;
|
||||
performance?: any;
|
||||
systems?: any;
|
||||
}
|
||||
|
||||
type AdvancedProfilerDataListener = (data: AdvancedProfilerDataPayload) => void;
|
||||
|
||||
export class ProfilerService {
|
||||
export class ProfilerService implements IProfilerService {
|
||||
private ws: WebSocket | null = null;
|
||||
private isServerRunning = false;
|
||||
private wsPort: number;
|
||||
|
||||
36
packages/editor-app/src/services/getService.ts
Normal file
36
packages/editor-app/src/services/getService.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 服务获取辅助函数
|
||||
* Service getter helper functions
|
||||
*
|
||||
* 提供类型安全的服务获取,避免直接访问全局变量。
|
||||
* Provides type-safe service access, avoiding direct global variable access.
|
||||
*/
|
||||
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
import type { ServiceToken } from '@esengine/engine-core';
|
||||
import { ProfilerServiceToken, type IProfilerService } from './tokens';
|
||||
|
||||
/**
|
||||
* 安全获取插件服务
|
||||
* Safely get plugin service
|
||||
*
|
||||
* 在 Core 未初始化时返回 undefined 而非抛出异常。
|
||||
* Returns undefined instead of throwing when Core is not initialized.
|
||||
*/
|
||||
export function getPluginService<T>(token: ServiceToken<T>): T | undefined {
|
||||
try {
|
||||
return Core.pluginServices.get(token);
|
||||
} catch {
|
||||
// Core 可能还没有初始化
|
||||
// Core might not be initialized yet
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 ProfilerService 实例
|
||||
* Get ProfilerService instance
|
||||
*/
|
||||
export function getProfilerService(): IProfilerService | undefined {
|
||||
return getPluginService(ProfilerServiceToken);
|
||||
}
|
||||
114
packages/editor-app/src/services/tokens.ts
Normal file
114
packages/editor-app/src/services/tokens.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 编辑器服务令牌
|
||||
* Editor Service Tokens
|
||||
*
|
||||
* 遵循"谁定义接口,谁导出 Token"原则。
|
||||
* 这些服务定义在 editor-app 中,所以 Token 也在这里定义。
|
||||
*
|
||||
* Following "who defines interface, who exports Token" principle.
|
||||
* These services are defined in editor-app, so Tokens are also defined here.
|
||||
*/
|
||||
|
||||
import { createServiceToken } from '@esengine/engine-core';
|
||||
|
||||
// ============================================================================
|
||||
// Profiler Data Types (定义在这里以避免循环依赖)
|
||||
// ============================================================================
|
||||
|
||||
export interface SystemPerformanceData {
|
||||
name: string;
|
||||
executionTime: number;
|
||||
entityCount: number;
|
||||
averageTime: number;
|
||||
percentage: number;
|
||||
}
|
||||
|
||||
export interface RemoteEntity {
|
||||
id: number;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
active: boolean;
|
||||
activeInHierarchy: boolean;
|
||||
componentCount: number;
|
||||
componentTypes: string[];
|
||||
parentId: number | null;
|
||||
childIds: number[];
|
||||
depth: number;
|
||||
tag: number;
|
||||
updateOrder: number;
|
||||
}
|
||||
|
||||
export interface ProfilerData {
|
||||
totalFrameTime: number;
|
||||
systems: SystemPerformanceData[];
|
||||
entityCount: number;
|
||||
componentCount: number;
|
||||
fps: number;
|
||||
entities?: RemoteEntity[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 高级性能数据结构(用于高级性能分析器)
|
||||
* Advanced profiler data structure
|
||||
*/
|
||||
export interface AdvancedProfilerDataPayload {
|
||||
advancedProfiler?: any;
|
||||
performance?: any;
|
||||
systems?: any;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Profiler Service Token
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* ProfilerService 接口(用于类型检查)
|
||||
* ProfilerService interface (for type checking)
|
||||
*
|
||||
* 提供远程性能分析功能,包括:
|
||||
* - WebSocket 连接管理
|
||||
* - 性能数据收集和分发
|
||||
* - 远程日志接收
|
||||
*
|
||||
* Provides remote profiling capabilities including:
|
||||
* - WebSocket connection management
|
||||
* - Performance data collection and distribution
|
||||
* - Remote log reception
|
||||
*/
|
||||
export interface IProfilerService {
|
||||
/** 检查是否已连接 | Check if connected */
|
||||
isConnected(): boolean;
|
||||
|
||||
/** 检查服务器是否运行 | Check if server is running */
|
||||
isServerActive(): boolean;
|
||||
|
||||
/** 手动启动服务器 | Manually start server */
|
||||
manualStartServer(): Promise<void>;
|
||||
|
||||
/** 手动停止服务器 | Manually stop server */
|
||||
manualStopServer(): Promise<void>;
|
||||
|
||||
/** 订阅数据更新 | Subscribe to data updates */
|
||||
subscribe(callback: (data: ProfilerData) => void): () => void;
|
||||
|
||||
/** 订阅高级数据更新 | Subscribe to advanced data updates */
|
||||
subscribeAdvanced(callback: (data: AdvancedProfilerDataPayload) => void): () => void;
|
||||
|
||||
/** 请求实体详情 | Request entity details */
|
||||
requestEntityDetails(entityId: number): void;
|
||||
|
||||
/** 请求高级性能分析数据 | Request advanced profiler data */
|
||||
requestAdvancedProfilerData(): void;
|
||||
|
||||
/** 设置选中的函数 | Set selected function */
|
||||
setProfilerSelectedFunction(functionName: string | null): void;
|
||||
|
||||
/** 销毁服务 | Destroy service */
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* ProfilerService 的服务令牌
|
||||
* Service token for ProfilerService
|
||||
*/
|
||||
export const ProfilerServiceToken = createServiceToken<IProfilerService>('profilerService');
|
||||
Reference in New Issue
Block a user