Files
esengine/packages/editor-app/src/plugins/builtin/SceneInspectorPlugin.ts
YHH e24c850568 refactor: 类型安全与接口清理 (#311)
* refactor: 分解 IEngineBridge 为单一职责接口

- 新增 ITextureService, IDynamicAtlasService, ICoordinateService, IRenderConfigService
- 移除 EngineBridgeToken,改用具体服务 Token
- 更新 camera, ui, particle 等模块使用新接口
- 优化装饰器类型安全,使用 Symbol-based metadata 访问模式

* refactor: 删除 plugin-types 包,统一 createServiceToken 实现

- 移动 IEditorModuleBase 接口到 engine-core
- 移除 engine-core 和 editor-core 对 plugin-types 的依赖
- 删除冗余的 plugin-types 包
- 统一使用 core 中基于 Symbol.for() 的 createServiceToken

* refactor: 统一 IPlugin 接口,移除 deprecated 别名

- 移除 engine-core、editor-core、runtime-core 中的 IPlugin 别名
- 模块插件统一使用 IRuntimePlugin(运行时)或 IEditorPlugin(编辑器)
- 保留 core 包中的 IPlugin 作为 ECS 核心插件接口(不同概念)
- 更新所有消费方使用正确的类型

* refactor: 重命名 editor-core ComponentRegistry 为 EditorComponentRegistry

- 消除与 core 包 ComponentRegistry(ECS 位掩码管理)的命名歧义
- editor-core 的 EditorComponentRegistry 专用于编辑器组件元数据
- 更新所有编辑器包使用新名称
2025-12-19 17:48:18 +08:00

198 lines
5.9 KiB
TypeScript

/**
* Scene Inspector Plugin
* 场景检视器插件
*/
import { Core, Entity } from '@esengine/ecs-framework';
import type { ServiceContainer } from '@esengine/ecs-framework';
import type {
IEditorPlugin,
IEditorModuleLoader,
ModuleManifest,
PanelDescriptor,
MenuItemDescriptor,
ToolbarItemDescriptor,
EntityCreationTemplate
} from '@esengine/editor-core';
import { PanelPosition, EntityStoreService, MessageHub } from '@esengine/editor-core';
import { TransformComponent } from '@esengine/engine-core';
import { SpriteComponent, SpriteAnimatorComponent } from '@esengine/sprite';
import { CameraComponent } from '@esengine/camera';
/**
* Scene Inspector 编辑器模块
*/
class SceneInspectorEditorModule implements IEditorModuleLoader {
async install(_services: ServiceContainer): Promise<void> {
// Installed
}
async uninstall(): Promise<void> {
// Uninstalled
}
getPanels(): PanelDescriptor[] {
return [
{
id: 'panel-scene-hierarchy',
title: 'Scene Hierarchy',
position: PanelPosition.Left,
defaultSize: 250,
resizable: true,
closable: false,
icon: 'List',
order: 10
},
{
id: 'panel-entity-inspector',
title: 'Entity Inspector',
position: PanelPosition.Right,
defaultSize: 300,
resizable: true,
closable: false,
icon: 'Search',
order: 10
}
];
}
getMenuItems(): MenuItemDescriptor[] {
return [
{
id: 'view-scene-inspector',
label: 'Scene Inspector',
parentId: 'view',
shortcut: 'Ctrl+Shift+I'
},
{
id: 'scene-create-entity',
label: 'Create Entity',
parentId: 'scene',
shortcut: 'Ctrl+N'
}
];
}
getToolbarItems(): ToolbarItemDescriptor[] {
return [
{
id: 'toolbar-create-entity',
label: 'New Entity',
icon: 'Plus',
tooltip: 'Create new entity',
execute: () => {}
},
{
id: 'toolbar-delete-entity',
label: 'Delete Entity',
icon: 'Trash2',
tooltip: 'Delete selected entity',
execute: () => {}
}
];
}
getEntityCreationTemplates(): EntityCreationTemplate[] {
return [
// Sprite
{
id: 'create-sprite-entity',
label: 'Sprite',
icon: 'Image',
category: 'rendering',
order: 10,
create: (): number => {
return this.createEntity('Sprite', (entity) => {
entity.addComponent(new TransformComponent());
entity.addComponent(new SpriteComponent());
});
}
},
// Animated Sprite
{
id: 'create-animated-sprite-entity',
label: '动画 Sprite',
icon: 'Film',
category: 'rendering',
order: 11,
create: (): number => {
return this.createEntity('AnimatedSprite', (entity) => {
entity.addComponent(new TransformComponent());
entity.addComponent(new SpriteAnimatorComponent());
});
}
},
// Camera
{
id: 'create-camera-entity',
label: '相机',
icon: 'Camera',
category: 'rendering',
order: 12,
create: (): number => {
return this.createEntity('Camera', (entity) => {
entity.addComponent(new TransformComponent());
entity.addComponent(new CameraComponent());
});
}
}
];
}
private createEntity(baseName: string, setupFn: (entity: Entity) => void): number {
const scene = Core.scene;
if (!scene) {
throw new Error('Scene not available');
}
const entityStore = Core.services.resolve(EntityStoreService);
const messageHub = Core.services.resolve(MessageHub);
if (!entityStore || !messageHub) {
throw new Error('EntityStoreService or MessageHub not available');
}
// 计数已有同类实体
const count = entityStore.getAllEntities()
.filter((e: Entity) => e.name.startsWith(`${baseName} `)).length;
const entityName = `${baseName} ${count + 1}`;
const entity = scene.createEntity(entityName);
setupFn(entity);
entityStore.addEntity(entity);
messageHub.publish('entity:added', { entity });
messageHub.publish('scene:modified', {});
entityStore.selectEntity(entity);
return entity.id;
}
async onEditorReady(): Promise<void> {}
async onProjectOpen(_projectPath: string): Promise<void> {}
async onProjectClose(): Promise<void> {}
}
const manifest: ModuleManifest = {
id: '@esengine/scene-inspector',
name: '@esengine/scene-inspector',
displayName: 'Scene Inspector',
version: '1.0.0',
description: 'Scene hierarchy and entity inspector',
category: 'Other',
icon: 'Search',
isCore: true,
defaultEnabled: true,
isEngineModule: true,
canContainContent: false,
dependencies: ['engine-core'],
exports: {
other: ['SceneHierarchy', 'EntityInspector']
}
};
export const SceneInspectorPlugin: IEditorPlugin = {
manifest,
editorModule: new SceneInspectorEditorModule()
};