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:
@@ -3,6 +3,7 @@ import * as ReactDOM from 'react-dom';
|
||||
import * as ReactJSXRuntime from 'react/jsx-runtime';
|
||||
import { Core, createLogger, Scene } from '@esengine/ecs-framework';
|
||||
import * as ECSFramework from '@esengine/ecs-framework';
|
||||
import { getProfilerService } from './services/getService';
|
||||
|
||||
// 将 React 暴露到全局,供动态加载的插件使用
|
||||
// editor-runtime.js 将 React 设为 external,需要从全局获取
|
||||
@@ -207,14 +208,15 @@ function App() {
|
||||
}, [messageHub, showToast]);
|
||||
|
||||
// 监听远程连接状态
|
||||
// Monitor remote connection status
|
||||
useEffect(() => {
|
||||
const checkConnection = () => {
|
||||
const profilerService = (window as any).__PROFILER_SERVICE__;
|
||||
const connected = profilerService && profilerService.isConnected();
|
||||
const profilerService = getProfilerService();
|
||||
const connected = !!(profilerService && profilerService.isConnected());
|
||||
|
||||
setIsRemoteConnected((prevConnected) => {
|
||||
if (connected !== prevConnected) {
|
||||
// 状态发生变化
|
||||
// 状态发生变化 | State has changed
|
||||
if (connected) {
|
||||
setStatus(t('header.status.remoteConnected'));
|
||||
} else {
|
||||
@@ -246,7 +248,8 @@ function App() {
|
||||
initRef.current = true;
|
||||
|
||||
try {
|
||||
(window as any).__ECS_FRAMEWORK__ = ECSFramework;
|
||||
// ECS Framework 已通过 PluginSDKRegistry 暴露到全局
|
||||
// ECS Framework is exposed globally via PluginSDKRegistry
|
||||
|
||||
const editorScene = new Scene();
|
||||
Core.setScene(editorScene);
|
||||
@@ -775,7 +778,7 @@ function App() {
|
||||
const Component = panelDesc.component;
|
||||
return {
|
||||
id: panelDesc.id,
|
||||
title: (panelDesc as any).titleZh && locale === 'zh' ? (panelDesc as any).titleZh : panelDesc.title,
|
||||
title: panelDesc.titleZh && locale === 'zh' ? panelDesc.titleZh : panelDesc.title,
|
||||
content: <Component key={`${panelDesc.id}-${pluginUpdateTrigger}`} projectPath={currentProjectPath} />,
|
||||
closable: panelDesc.closable ?? true
|
||||
};
|
||||
@@ -791,7 +794,7 @@ function App() {
|
||||
const panelDesc = uiRegistry.getPanel(panelId)!;
|
||||
// 优先使用动态标题,否则使用默认标题
|
||||
const customTitle = dynamicPanelTitles.get(panelId);
|
||||
const defaultTitle = (panelDesc as any).titleZh && locale === 'zh' ? (panelDesc as any).titleZh : panelDesc.title;
|
||||
const defaultTitle = panelDesc.titleZh && locale === 'zh' ? panelDesc.titleZh : panelDesc.title;
|
||||
|
||||
// 支持 component 或 render 两种方式
|
||||
let content: React.ReactNode;
|
||||
|
||||
Reference in New Issue
Block a user