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:
YHH
2025-11-27 20:42:46 +08:00
committed by GitHub
parent 71869b1a58
commit 107439d70c
367 changed files with 10661 additions and 12473 deletions

View 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()
};