feat(i18n): 统一国际化系统架构,支持插件独立翻译 (#301)
* feat(i18n): 统一国际化系统架构,支持插件独立翻译 ## 主要改动 ### 核心架构 - 增强 LocaleService,支持插件命名空间翻译扩展 - 新增 editor-runtime/i18n 模块,提供 createPluginLocale/createPluginTranslator - 新增 editor-core/tokens.ts,定义 LocaleServiceToken 等服务令牌 - 改进 PluginAPI 类型安全,使用 ServiceToken<T> 替代 any ### 编辑器本地化 - 扩展 en.ts/zh.ts 翻译文件,覆盖所有 UI 组件 - 新增 es.ts 西班牙语支持 - 重构 40+ 组件使用 useLocale() hook ### 插件本地化系统 - behavior-tree-editor: 新增 locales/ 和 useBTLocale hook - material-editor: 新增 locales/ 和 useMaterialLocale hook - particle-editor: 新增 locales/ 和 useParticleLocale hook - tilemap-editor: 新增 locales/ 和 useTilemapLocale hook - ui-editor: 新增 locales/ 和 useUILocale hook ### 类型安全改进 - 修复 Debug 工具使用公共接口替代 as any - 修复 ChunkStreamingSystem 添加 forEachChunk 公共方法 - 修复 blueprint-editor 移除不必要的向后兼容代码 * fix(behavior-tree-editor): 使用 ServiceToken 模式修复服务解析 - 创建 BehaviorTreeServiceToken 遵循"谁定义接口,谁导出Token"原则 - 使用 ServiceToken.id (symbol) 注册服务到 ServiceContainer - 更新 PluginSDKRegistry.resolveService 支持 ServiceToken 检测 - BehaviorTreeEditorPanel 现在使用类型安全的 PluginAPI.resolve * fix(behavior-tree-editor): 使用 ServiceContainer.resolve 获取类注册的服务 * fix: 修复多个包的依赖和类型问题 - core: EntityDataCollector.getEntityDetails 使用 HierarchySystem 获取父实体 - ui-editor: 添加 @esengine/editor-runtime 依赖 - tilemap-editor: 添加 @esengine/editor-runtime 依赖 - particle-editor: 添加 @esengine/editor-runtime 依赖
This commit is contained in:
@@ -22,7 +22,7 @@ export class ComponentDataCollector {
|
||||
};
|
||||
}
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityList = scene.entities;
|
||||
if (!entityList?.buffer) {
|
||||
return {
|
||||
componentTypes: 0,
|
||||
@@ -98,7 +98,7 @@ export class ComponentDataCollector {
|
||||
|
||||
if (!scene) return 64;
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityList = scene.entities;
|
||||
if (!entityList?.buffer) return 64;
|
||||
|
||||
let calculatedSize = 64;
|
||||
@@ -174,7 +174,7 @@ export class ComponentDataCollector {
|
||||
public calculateDetailedComponentMemory(typeName: string, scene?: IScene | null): number {
|
||||
if (!scene) return this.getEstimatedComponentSize(typeName, scene);
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityList = scene.entities;
|
||||
if (!entityList?.buffer) return this.getEstimatedComponentSize(typeName, scene);
|
||||
|
||||
try {
|
||||
|
||||
@@ -8,18 +8,25 @@ import { HierarchySystem } from '../../ECS/Systems/HierarchySystem';
|
||||
|
||||
/**
|
||||
* 实体数据收集器
|
||||
* Entity data collector
|
||||
*
|
||||
* 收集实体的调试信息,通过公共接口访问数据。
|
||||
* Collects entity debug information through public interfaces.
|
||||
*/
|
||||
export class EntityDataCollector {
|
||||
/**
|
||||
* 收集实体数据
|
||||
* @param scene 场景实例
|
||||
* Collect entity data
|
||||
*
|
||||
* @param scene 场景实例 | Scene instance
|
||||
*/
|
||||
public collectEntityData(scene?: IScene | null): IEntityDebugData {
|
||||
if (!scene) {
|
||||
return this.getEmptyEntityDebugData();
|
||||
}
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
// 使用公共接口 | Use public interface
|
||||
const entityList = scene.entities;
|
||||
if (!entityList) {
|
||||
return this.getEmptyEntityDebugData();
|
||||
}
|
||||
@@ -56,7 +63,9 @@ export class EntityDataCollector {
|
||||
|
||||
/**
|
||||
* 获取原始实体列表
|
||||
* @param scene 场景实例
|
||||
* Get raw entity list
|
||||
*
|
||||
* @param scene 场景实例 | Scene instance
|
||||
*/
|
||||
public getRawEntityList(scene?: IScene | null): Array<{
|
||||
id: number;
|
||||
@@ -74,7 +83,8 @@ export class EntityDataCollector {
|
||||
}> {
|
||||
if (!scene) return [];
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
// 使用公共接口 | Use public interface
|
||||
const entityList = scene.entities;
|
||||
if (!entityList?.buffer) return [];
|
||||
|
||||
const hierarchySystem = scene.getSystem(HierarchySystem);
|
||||
@@ -110,15 +120,21 @@ export class EntityDataCollector {
|
||||
try {
|
||||
if (!scene) return null;
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityList = scene.entities;
|
||||
if (!entityList?.buffer) return null;
|
||||
|
||||
const entity = entityList.buffer.find((e: any) => e.id === entityId);
|
||||
if (!entity) return null;
|
||||
|
||||
// 使用 HierarchySystem 获取父实体
|
||||
// Use HierarchySystem to get parent entity
|
||||
const hierarchySystem = scene.getSystem(HierarchySystem);
|
||||
const parent = hierarchySystem?.getParent(entity);
|
||||
const parentName = parent?.name ?? null;
|
||||
|
||||
const baseDebugInfo = entity.getDebugInfo
|
||||
? entity.getDebugInfo()
|
||||
: this.buildFallbackEntityInfo(entity, scene);
|
||||
: this.buildFallbackEntityInfo(entity, scene, hierarchySystem);
|
||||
|
||||
const componentDetails = this.extractComponentDetails(entity.components);
|
||||
|
||||
@@ -129,7 +145,7 @@ export class EntityDataCollector {
|
||||
scene: sceneInfo.name,
|
||||
sceneName: sceneInfo.name,
|
||||
sceneType: sceneInfo.type,
|
||||
parentName: entity.parent?.name || null,
|
||||
parentName,
|
||||
components: componentDetails || [],
|
||||
componentCount: entity.components?.length || 0,
|
||||
componentTypes: entity.components?.map((comp: any) => getComponentInstanceTypeName(comp)) || []
|
||||
@@ -180,7 +196,7 @@ export class EntityDataCollector {
|
||||
return this.getEmptyEntityDebugData();
|
||||
}
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityList = scene.entities;
|
||||
if (!entityList) {
|
||||
return this.getEmptyEntityDebugData();
|
||||
}
|
||||
@@ -769,13 +785,14 @@ export class EntityDataCollector {
|
||||
try {
|
||||
if (!scene) return {};
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityList = scene.entities;
|
||||
if (!entityList?.buffer) return {};
|
||||
|
||||
const entity = entityList.buffer.find((e: any) => e.id === entityId);
|
||||
if (!entity || componentIndex >= entity.components.length) return {};
|
||||
|
||||
const component = entity.components[componentIndex];
|
||||
if (!component) return {};
|
||||
const properties: Record<string, any> = {};
|
||||
|
||||
const propertyKeys = Object.keys(component);
|
||||
@@ -970,7 +987,7 @@ export class EntityDataCollector {
|
||||
try {
|
||||
if (!scene) return null;
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityList = scene.entities;
|
||||
if (!entityList?.buffer) return null;
|
||||
|
||||
// 找到对应的实体
|
||||
|
||||
@@ -3,13 +3,19 @@ import { IScene } from '../../ECS/IScene';
|
||||
|
||||
/**
|
||||
* 场景数据收集器
|
||||
* Scene data collector
|
||||
*
|
||||
* 收集场景的调试信息,通过公共接口访问数据。
|
||||
* Collects scene debug information through public interfaces.
|
||||
*/
|
||||
export class SceneDataCollector {
|
||||
private sceneStartTime: number = Date.now();
|
||||
|
||||
/**
|
||||
* 收集场景数据
|
||||
* @param scene 场景实例
|
||||
* Collect scene data
|
||||
*
|
||||
* @param scene 场景实例 | Scene instance
|
||||
*/
|
||||
public collectSceneData(scene?: IScene | null): ISceneDebugData {
|
||||
if (!scene) {
|
||||
@@ -26,15 +32,15 @@ export class SceneDataCollector {
|
||||
const currentTime = Date.now();
|
||||
const runTime = (currentTime - this.sceneStartTime) / 1000;
|
||||
|
||||
const entityList = (scene as any).entities;
|
||||
const entityProcessors = (scene as any).entityProcessors;
|
||||
// 使用公共接口获取数据 | Use public interface to get data
|
||||
const stats = scene.getStats();
|
||||
|
||||
return {
|
||||
currentSceneName: (scene as any).name || 'Unnamed Scene',
|
||||
isInitialized: (scene as any)._didSceneBegin || false,
|
||||
currentSceneName: scene.name || 'Unnamed Scene',
|
||||
isInitialized: true, // 如果 scene 存在,则认为已初始化 | If scene exists, consider initialized
|
||||
sceneRunTime: runTime,
|
||||
sceneEntityCount: entityList?.buffer?.length || 0,
|
||||
sceneSystemCount: entityProcessors?.processors?.length || 0,
|
||||
sceneEntityCount: stats.entityCount,
|
||||
sceneSystemCount: stats.processorCount,
|
||||
sceneUptime: runTime
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,12 +4,18 @@ import { IScene } from '../../ECS/IScene';
|
||||
|
||||
/**
|
||||
* 系统数据收集器
|
||||
* System data collector
|
||||
*
|
||||
* 收集系统的调试信息,通过公共接口访问数据。
|
||||
* Collects system debug information through public interfaces.
|
||||
*/
|
||||
export class SystemDataCollector {
|
||||
/**
|
||||
* 收集系统数据
|
||||
* @param performanceMonitor 性能监视器实例
|
||||
* @param scene 场景实例
|
||||
* Collect system data
|
||||
*
|
||||
* @param performanceMonitor 性能监视器实例 | Performance monitor instance
|
||||
* @param scene 场景实例 | Scene instance
|
||||
*/
|
||||
public collectSystemData(performanceMonitor: any, scene?: IScene | null): ISystemDebugData {
|
||||
if (!scene) {
|
||||
@@ -19,15 +25,8 @@ export class SystemDataCollector {
|
||||
};
|
||||
}
|
||||
|
||||
const entityProcessors = (scene as any).entityProcessors;
|
||||
if (!entityProcessors) {
|
||||
return {
|
||||
totalSystems: 0,
|
||||
systemsInfo: []
|
||||
};
|
||||
}
|
||||
|
||||
const systems = entityProcessors.processors || [];
|
||||
// 使用公共接口 | Use public interface
|
||||
const systems = scene.systems || [];
|
||||
|
||||
// 获取性能监控数据
|
||||
let systemStats: Map<string, any> = new Map();
|
||||
|
||||
Reference in New Issue
Block a user