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

@@ -1,40 +0,0 @@
/**
* Gizmo Plugin
* Gizmo 插件
*
* Registers gizmo support for built-in components
* 为内置组件注册 gizmo 支持
*/
import type { Core, ServiceContainer } from '@esengine/ecs-framework';
import type { IEditorPlugin } from '@esengine/editor-core';
import { EditorPluginCategory } from '@esengine/editor-core';
import { registerSpriteGizmo } from '../gizmos';
export class GizmoPlugin implements IEditorPlugin {
readonly name = '@esengine/gizmo-plugin';
readonly version = '1.0.0';
readonly category = EditorPluginCategory.Tool;
get displayName(): string {
return 'Gizmo System';
}
get description(): string {
return 'Provides gizmo support for editor components';
}
async install(_core: Core, _services: ServiceContainer): Promise<void> {
// Register gizmo support for SpriteComponent
// 为 SpriteComponent 注册 gizmo 支持
registerSpriteGizmo();
console.log('[GizmoPlugin] Installed - registered gizmo support for built-in components');
}
async uninstall(): Promise<void> {
console.log('[GizmoPlugin] Uninstalled');
}
}
export const gizmoPlugin = new GizmoPlugin();

View File

@@ -1,121 +0,0 @@
import type { Core, ServiceContainer } from '@esengine/ecs-framework';
import { IEditorPlugin, EditorPluginCategory, PanelPosition } from '@esengine/editor-core';
import type { MenuItem, ToolbarItem, PanelDescriptor, ISerializer } from '@esengine/editor-core';
/**
* Scene Inspector 插件
*
* 提供场景层级视图和实体检视功能
*/
export class SceneInspectorPlugin implements IEditorPlugin {
readonly name = '@esengine/scene-inspector';
readonly version = '1.0.0';
readonly displayName = 'Scene Inspector';
readonly category = EditorPluginCategory.Inspector;
readonly description = 'Scene hierarchy and entity inspector';
readonly icon = '🔍';
async install(_core: Core, _services: ServiceContainer): Promise<void> {
}
async uninstall(): Promise<void> {
}
registerMenuItems(): MenuItem[] {
return [
{
id: 'view-scene-inspector',
label: 'Scene Inspector',
parentId: 'view',
onClick: () => {
},
shortcut: 'Ctrl+Shift+I',
order: 100
},
{
id: 'scene-create-entity',
label: 'Create Entity',
parentId: 'scene',
onClick: () => {
},
shortcut: 'Ctrl+N',
order: 10
}
];
}
registerToolbar(): ToolbarItem[] {
return [
{
id: 'toolbar-create-entity',
label: 'New Entity',
groupId: 'entity-tools',
icon: '',
onClick: () => {
},
order: 10
},
{
id: 'toolbar-delete-entity',
label: 'Delete Entity',
groupId: 'entity-tools',
icon: '🗑️',
onClick: () => {
},
order: 20
}
];
}
registerPanels(): PanelDescriptor[] {
return [
{
id: 'panel-scene-hierarchy',
title: 'Scene Hierarchy',
position: PanelPosition.Left,
defaultSize: 250,
resizable: true,
closable: false,
icon: '📋',
order: 10
},
{
id: 'panel-entity-inspector',
title: 'Entity Inspector',
position: PanelPosition.Right,
defaultSize: 300,
resizable: true,
closable: false,
icon: '🔎',
order: 10
}
];
}
getSerializers(): ISerializer[] {
return [
{
serialize: (data: any) => {
const json = JSON.stringify(data);
const encoder = new TextEncoder();
return encoder.encode(json);
},
deserialize: (data: Uint8Array) => {
const decoder = new TextDecoder();
const json = decoder.decode(data);
return JSON.parse(json);
},
getSupportedType: () => 'scene'
}
];
}
async onEditorReady(): Promise<void> {
}
async onProjectOpen(projectPath: string): Promise<void> {
}
async onProjectClose(): Promise<void> {
}
}

View File

@@ -1,24 +1,21 @@
import type { Core, ServiceContainer } from '@esengine/ecs-framework';
/**
* Editor Appearance Plugin
*
*/
import type { ServiceContainer } from '@esengine/ecs-framework';
import { createLogger } from '@esengine/ecs-framework';
import { IEditorPlugin, EditorPluginCategory, SettingsRegistry } from '@esengine/editor-core';
import { SettingsService } from '../services/SettingsService';
import type { IPluginLoader, IEditorModuleLoader, PluginDescriptor } from '@esengine/editor-core';
import { SettingsRegistry } from '@esengine/editor-core';
import { SettingsService } from '../../services/SettingsService';
const logger = createLogger('EditorAppearancePlugin');
/**
* Editor Appearance Plugin
*
* Manages editor appearance settings like font size
* Editor Appearance
*/
export class EditorAppearancePlugin implements IEditorPlugin {
readonly name = '@esengine/editor-appearance';
readonly version = '1.0.0';
readonly displayName = 'Editor Appearance';
readonly category = EditorPluginCategory.System;
readonly description = 'Configure editor appearance settings';
readonly icon = '🎨';
async install(_core: Core, services: ServiceContainer): Promise<void> {
class EditorAppearanceEditorModule implements IEditorModuleLoader {
async install(services: ServiceContainer): Promise<void> {
const settingsRegistry = services.resolve(SettingsRegistry);
settingsRegistry.registerCategory({
@@ -77,9 +74,6 @@ export class EditorAppearancePlugin implements IEditorPlugin {
logger.info('Editor is ready');
}
/**
* Apply font settings from settings
*/
private applyFontSettings(): void {
const settings = SettingsService.getInstance();
const baseFontSize = settings.get<number>('editor.fontSize', 13);
@@ -87,8 +81,6 @@ export class EditorAppearancePlugin implements IEditorPlugin {
logger.info(`Applying font size: ${baseFontSize}px`);
const root = document.documentElement;
// Apply font sizes
root.style.setProperty('--font-size-xs', `${baseFontSize - 2}px`);
root.style.setProperty('--font-size-sm', `${baseFontSize - 1}px`);
root.style.setProperty('--font-size-base', `${baseFontSize}px`);
@@ -97,9 +89,6 @@ export class EditorAppearancePlugin implements IEditorPlugin {
root.style.setProperty('--font-size-xl', `${baseFontSize + 5}px`);
}
/**
* Listen for settings changes
*/
private setupSettingsListener(): void {
window.addEventListener('settings:changed', ((event: CustomEvent) => {
const changedSettings = event.detail;
@@ -112,3 +101,28 @@ export class EditorAppearancePlugin implements IEditorPlugin {
}) as EventListener);
}
}
const descriptor: PluginDescriptor = {
id: '@esengine/editor-appearance',
name: 'Editor Appearance',
version: '1.0.0',
description: 'Configure editor appearance settings',
category: 'tools',
icon: 'Palette',
enabledByDefault: true,
canContainContent: false,
isEnginePlugin: true,
isCore: true,
modules: [
{
name: 'EditorAppearanceEditor',
type: 'editor',
loadingPhase: 'earliest'
}
]
};
export const EditorAppearancePlugin: IPluginLoader = {
descriptor,
editorModule: new EditorAppearanceEditorModule()
};

View File

@@ -0,0 +1,50 @@
/**
* Gizmo Plugin
* Gizmo 插件
*/
import type { ServiceContainer } from '@esengine/ecs-framework';
import type { IPluginLoader, IEditorModuleLoader, PluginDescriptor, GizmoProviderRegistration } from '@esengine/editor-core';
import { registerSpriteGizmo } from '../../gizmos';
/**
* Gizmo 编辑器模块
*/
class GizmoEditorModule implements IEditorModuleLoader {
async install(_services: ServiceContainer): Promise<void> {
registerSpriteGizmo();
}
async uninstall(): Promise<void> {
// Uninstalled
}
getGizmoProviders(): GizmoProviderRegistration[] {
return [];
}
}
const descriptor: PluginDescriptor = {
id: '@esengine/gizmo',
name: 'Gizmo System',
version: '1.0.0',
description: 'Provides gizmo support for editor components',
category: 'tools',
icon: 'Move',
enabledByDefault: true,
canContainContent: false,
isEnginePlugin: true,
isCore: true,
modules: [
{
name: 'GizmoEditor',
type: 'editor',
loadingPhase: 'preDefault'
}
]
};
export const GizmoPlugin: IPluginLoader = {
descriptor,
editorModule: new GizmoEditorModule()
};

View File

@@ -0,0 +1,77 @@
/**
* Plugin Config Plugin
* 插件配置插件
*/
import type { ServiceContainer } from '@esengine/ecs-framework';
import { createLogger } from '@esengine/ecs-framework';
import type { IPluginLoader, IEditorModuleLoader, PluginDescriptor } from '@esengine/editor-core';
import { SettingsRegistry } from '@esengine/editor-core';
const logger = createLogger('PluginConfigPlugin');
/**
* Plugin Config 编辑器模块
*/
class PluginConfigEditorModule implements IEditorModuleLoader {
async install(services: ServiceContainer): Promise<void> {
const settingsRegistry = services.resolve(SettingsRegistry);
settingsRegistry.registerCategory({
id: 'plugins',
title: '插件',
description: '管理项目使用的插件',
sections: [
{
id: 'engine-plugins',
title: '插件管理',
description: '启用或禁用项目需要的插件。禁用不需要的插件可以减少打包体积。',
settings: [
{
key: 'project.enabledPlugins',
label: '',
type: 'pluginList',
defaultValue: [],
description: ''
}
]
}
]
});
logger.info('Installed');
}
async uninstall(): Promise<void> {
logger.info('Uninstalled');
}
async onEditorReady(): Promise<void> {
logger.info('Editor is ready');
}
}
const descriptor: PluginDescriptor = {
id: '@esengine/plugin-config',
name: 'Plugin Config',
version: '1.0.0',
description: 'Configure engine plugins',
category: 'tools',
icon: 'Package',
enabledByDefault: true,
canContainContent: false,
isEnginePlugin: true,
isCore: true,
modules: [
{
name: 'PluginConfigEditor',
type: 'editor',
loadingPhase: 'postDefault'
}
]
};
export const PluginConfigPlugin: IPluginLoader = {
descriptor,
editorModule: new PluginConfigEditorModule()
};

View File

@@ -1,28 +1,30 @@
import type { Core, ServiceContainer } from '@esengine/ecs-framework';
import { IEditorPlugin, EditorPluginCategory, MenuItem, MessageHub, PanelDescriptor, SettingsRegistry } from '@esengine/editor-core';
import { ProfilerDockPanel } from '../components/ProfilerDockPanel';
import { ProfilerService } from '../services/ProfilerService';
/**
* Profiler Plugin
*
* Displays real-time performance metrics for ECS systems
*
*/
export class ProfilerPlugin implements IEditorPlugin {
readonly name = '@esengine/profiler';
readonly version = '1.0.0';
readonly displayName = 'Performance Profiler';
readonly category = EditorPluginCategory.Tool;
readonly description = 'Real-time performance monitoring for ECS systems';
readonly icon = '📊';
import type { ServiceContainer } from '@esengine/ecs-framework';
import type {
IPluginLoader,
IEditorModuleLoader,
PluginDescriptor,
PanelDescriptor,
MenuItemDescriptor
} from '@esengine/editor-core';
import { MessageHub, SettingsRegistry, PanelPosition } from '@esengine/editor-core';
import { ProfilerDockPanel } from '../../components/ProfilerDockPanel';
import { ProfilerService } from '../../services/ProfilerService';
/**
* Profiler
*/
class ProfilerEditorModule implements IEditorModuleLoader {
private messageHub: MessageHub | null = null;
private profilerService: ProfilerService | null = null;
async install(_core: Core, services: ServiceContainer): Promise<void> {
async install(services: ServiceContainer): Promise<void> {
this.messageHub = services.resolve(MessageHub);
// 注册设置
const settingsRegistry = services.resolve(SettingsRegistry);
settingsRegistry.registerCategory({
id: 'profiler',
@@ -86,51 +88,68 @@ export class ProfilerPlugin implements IEditorPlugin {
]
});
// 创建并启动 ProfilerService
this.profilerService = new ProfilerService();
// 将服务实例存储到全局,供组件访问
(window as any).__PROFILER_SERVICE__ = this.profilerService;
}
async uninstall(): Promise<void> {
// 清理 ProfilerService
if (this.profilerService) {
this.profilerService.destroy();
this.profilerService = null;
}
delete (window as any).__PROFILER_SERVICE__;
}
async onEditorReady(): Promise<void> {
}
registerMenuItems(): MenuItem[] {
const items = [
{
id: 'window.profiler',
label: 'Profiler',
parentId: 'window',
order: 100,
onClick: () => {
this.messageHub?.publish('ui:openWindow', { windowId: 'profiler' });
}
}
];
return items;
}
registerPanels(): PanelDescriptor[] {
getPanels(): PanelDescriptor[] {
return [
{
id: 'profiler-monitor',
title: 'Performance Monitor',
position: 'center' as any,
position: PanelPosition.Center,
closable: false,
component: ProfilerDockPanel,
order: 200
}
];
}
getMenuItems(): MenuItemDescriptor[] {
return [
{
id: 'window.profiler',
label: 'Profiler',
parentId: 'window',
execute: () => {
this.messageHub?.publish('ui:openWindow', { windowId: 'profiler' });
}
}
];
}
async onEditorReady(): Promise<void> {}
}
const descriptor: PluginDescriptor = {
id: '@esengine/profiler',
name: 'Performance Profiler',
version: '1.0.0',
description: 'Real-time performance monitoring for ECS systems',
category: 'tools',
icon: 'BarChart3',
enabledByDefault: true,
canContainContent: false,
isEnginePlugin: true,
modules: [
{
name: 'ProfilerEditor',
type: 'editor',
loadingPhase: 'postDefault',
panels: ['profiler-monitor']
}
]
};
export const ProfilerPlugin: IPluginLoader = {
descriptor,
editorModule: new ProfilerEditorModule()
};

View File

@@ -0,0 +1,173 @@
/**
* Project Settings Plugin
* 项目设置插件
*
* Registers project-level settings like UI design resolution.
* 注册项目级别的设置,如 UI 设计分辨率。
*/
import type { ServiceContainer } from '@esengine/ecs-framework';
import { createLogger, Core } from '@esengine/ecs-framework';
import type { IPluginLoader, IEditorModuleLoader, PluginDescriptor } from '@esengine/editor-core';
import { SettingsRegistry, ProjectService } from '@esengine/editor-core';
import EngineService from '../../services/EngineService';
const logger = createLogger('ProjectSettingsPlugin');
/**
* Common UI design resolution presets
* 常见的 UI 设计分辨率预设
*/
export const UI_RESOLUTION_PRESETS = [
{ label: '1920 x 1080 (Full HD)', value: { width: 1920, height: 1080 } },
{ label: '1280 x 720 (HD)', value: { width: 1280, height: 720 } },
{ label: '1366 x 768 (HD+)', value: { width: 1366, height: 768 } },
{ label: '2560 x 1440 (2K)', value: { width: 2560, height: 1440 } },
{ label: '3840 x 2160 (4K)', value: { width: 3840, height: 2160 } },
{ label: '750 x 1334 (iPhone 6/7/8)', value: { width: 750, height: 1334 } },
{ label: '1125 x 2436 (iPhone X/11/12)', value: { width: 1125, height: 2436 } },
{ label: '1080 x 1920 (Mobile Portrait)', value: { width: 1080, height: 1920 } },
{ label: '800 x 600 (SVGA)', value: { width: 800, height: 600 } },
{ label: '1024 x 768 (XGA)', value: { width: 1024, height: 768 } },
];
/**
* Project Settings 编辑器模块
*/
class ProjectSettingsEditorModule implements IEditorModuleLoader {
private settingsListener: ((event: Event) => void) | null = null;
async install(services: ServiceContainer): Promise<void> {
const settingsRegistry = services.resolve(SettingsRegistry);
// Setup listener for UI design resolution changes
this.setupSettingsListener();
settingsRegistry.registerCategory({
id: 'project',
title: '项目',
description: '项目级别的配置',
sections: [
{
id: 'ui-settings',
title: 'UI 设置',
description: '配置 UI 系统的基础参数',
settings: [
{
key: 'project.uiDesignResolution.width',
label: '设计宽度',
type: 'number',
defaultValue: 1920,
description: 'UI 画布的设计宽度(像素)',
min: 320,
max: 7680,
step: 1
},
{
key: 'project.uiDesignResolution.height',
label: '设计高度',
type: 'number',
defaultValue: 1080,
description: 'UI 画布的设计高度(像素)',
min: 240,
max: 4320,
step: 1
},
{
key: 'project.uiDesignResolution.preset',
label: '分辨率预设',
type: 'select',
defaultValue: '1920x1080',
description: '选择常见的分辨率预设',
options: UI_RESOLUTION_PRESETS.map(p => ({
label: p.label,
value: `${p.value.width}x${p.value.height}`
}))
}
]
}
]
});
logger.info('Installed');
}
async uninstall(): Promise<void> {
// Remove settings listener
if (this.settingsListener) {
window.removeEventListener('settings:changed', this.settingsListener);
this.settingsListener = null;
}
logger.info('Uninstalled');
}
async onEditorReady(): Promise<void> {
logger.info('Editor is ready');
}
/**
* Setup listener for settings changes
* 设置设置变化监听器
*/
private setupSettingsListener(): void {
this.settingsListener = ((event: CustomEvent) => {
const changedSettings = event.detail;
// Check if UI design resolution changed
if ('project.uiDesignResolution.width' in changedSettings ||
'project.uiDesignResolution.height' in changedSettings ||
'project.uiDesignResolution.preset' in changedSettings) {
logger.info('UI design resolution changed, applying...');
this.applyUIDesignResolution();
}
}) as EventListener;
window.addEventListener('settings:changed', this.settingsListener);
}
/**
* Apply UI design resolution from ProjectService
* 从 ProjectService 应用 UI 设计分辨率
*/
private applyUIDesignResolution(): void {
const projectService = Core.services.tryResolve<ProjectService>(ProjectService);
if (!projectService) {
logger.warn('ProjectService not available');
return;
}
const resolution = projectService.getUIDesignResolution();
const engineService = EngineService.getInstance();
if (engineService.isInitialized()) {
engineService.setUICanvasSize(resolution.width, resolution.height);
logger.info(`Applied UI design resolution: ${resolution.width}x${resolution.height}`);
}
}
}
const descriptor: PluginDescriptor = {
id: '@esengine/project-settings',
name: 'Project Settings',
version: '1.0.0',
description: 'Configure project-level settings',
category: 'tools',
icon: 'Settings',
enabledByDefault: true,
canContainContent: false,
isEnginePlugin: true,
isCore: true,
modules: [
{
name: 'ProjectSettingsEditor',
type: 'editor',
loadingPhase: 'postDefault'
}
]
};
export const ProjectSettingsPlugin: IPluginLoader = {
descriptor,
editorModule: new ProjectSettingsEditorModule()
};

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

View File

@@ -0,0 +1,11 @@
/**
* 内置插件
* Built-in plugins
*/
export { GizmoPlugin } from './GizmoPlugin';
export { SceneInspectorPlugin } from './SceneInspectorPlugin';
export { ProfilerPlugin } from './ProfilerPlugin';
export { EditorAppearancePlugin } from './EditorAppearancePlugin';
export { PluginConfigPlugin } from './PluginConfigPlugin';
export { ProjectSettingsPlugin } from './ProjectSettingsPlugin';