Feature/runtime cdn and plugin loader (#240)
* feat(ui): 完善 UI 布局系统和编辑器可视化工具 * refactor: 移除 ModuleRegistry,统一使用 PluginManager 插件系统 * fix: 修复 CodeQL 警告并提升测试覆盖率 * refactor: 分离运行时入口点,解决 runtime bundle 包含 React 的问题 * fix(ci): 添加 editor-core 和 editor-runtime 到 CI 依赖构建步骤 * docs: 完善 ServiceContainer 文档,新增 Symbol.for 模式和 @InjectProperty 说明 * fix(ci): 修复 type-check 失败问题 * fix(ci): 修复类型检查失败问题 * fix(ci): 修复类型检查失败问题 * fix(ci): behavior-tree 构建添加 @tauri-apps 外部依赖 * fix(ci): behavior-tree 添加 @tauri-apps/plugin-fs 类型依赖 * fix(ci): platform-web 添加缺失的 behavior-tree 依赖 * fix(lint): 移除正则表达式中不必要的转义字符
This commit is contained in:
199
packages/editor-app/src/plugins/builtin/SceneInspectorPlugin.ts
Normal file
199
packages/editor-app/src/plugins/builtin/SceneInspectorPlugin.ts
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Scene Inspector Plugin
|
||||
* 场景检视器插件
|
||||
*/
|
||||
|
||||
import { Core, Entity } from '@esengine/ecs-framework';
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import type {
|
||||
IPluginLoader,
|
||||
IEditorModuleLoader,
|
||||
PluginDescriptor,
|
||||
PanelDescriptor,
|
||||
MenuItemDescriptor,
|
||||
ToolbarItemDescriptor,
|
||||
EntityCreationTemplate
|
||||
} from '@esengine/editor-core';
|
||||
import { PanelPosition, EntityStoreService, MessageHub } from '@esengine/editor-core';
|
||||
import { TransformComponent, SpriteComponent, SpriteAnimatorComponent, CameraComponent } from '@esengine/ecs-components';
|
||||
|
||||
/**
|
||||
* 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 descriptor: PluginDescriptor = {
|
||||
id: '@esengine/scene-inspector',
|
||||
name: 'Scene Inspector',
|
||||
version: '1.0.0',
|
||||
description: 'Scene hierarchy and entity inspector',
|
||||
category: 'tools',
|
||||
icon: 'Search',
|
||||
enabledByDefault: true,
|
||||
canContainContent: false,
|
||||
isEnginePlugin: true,
|
||||
isCore: true,
|
||||
modules: [
|
||||
{
|
||||
name: 'SceneInspectorEditor',
|
||||
type: 'editor',
|
||||
loadingPhase: 'default',
|
||||
panels: ['panel-scene-hierarchy', 'panel-entity-inspector'],
|
||||
inspectors: ['EntityInspector']
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const SceneInspectorPlugin: IPluginLoader = {
|
||||
descriptor,
|
||||
editorModule: new SceneInspectorEditorModule()
|
||||
};
|
||||
Reference in New Issue
Block a user