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:
@@ -15,22 +15,25 @@
|
||||
"dist/**/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"build": "tsc && vite build",
|
||||
"build:watch": "vite build --watch",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@esengine/ecs-framework": "workspace:*",
|
||||
"@esengine/editor-core": "workspace:*",
|
||||
"@tauri-apps/api": "^2.2.0",
|
||||
"@tauri-apps/plugin-dialog": "^2.4.0",
|
||||
"@tauri-apps/plugin-fs": "^2.4.2",
|
||||
"tsyringe": "^4.10.0",
|
||||
"reflect-metadata": "^0.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@esengine/ecs-framework": "workspace:*",
|
||||
"@esengine/editor-core": "workspace:*",
|
||||
"@esengine/ui": "workspace:*",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"zustand": "^5.0.8",
|
||||
"lucide-react": "^0.545.0",
|
||||
"tsyringe": "^4.10.0",
|
||||
"reflect-metadata": "^0.2.2"
|
||||
"lucide-react": "^0.545.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.12",
|
||||
|
||||
109
packages/editor-runtime/src/PluginAPI.ts
Normal file
109
packages/editor-runtime/src/PluginAPI.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* Plugin API - 为插件提供简洁的访问接口
|
||||
*
|
||||
* 使用方式:
|
||||
* ```typescript
|
||||
* import { PluginAPI } from '@esengine/editor-runtime';
|
||||
*
|
||||
* const scene = PluginAPI.scene;
|
||||
* const entityStore = PluginAPI.entityStore;
|
||||
* const messageHub = PluginAPI.messageHub;
|
||||
* ```
|
||||
*
|
||||
* 这个 API 会自动从全局 __ESENGINE__ 获取正确的实例,
|
||||
* 避免模块实例不一致的问题。
|
||||
*/
|
||||
|
||||
import type { EntityStoreService, MessageHub } from '@esengine/editor-core';
|
||||
import type { Scene, ServiceContainer } from '@esengine/ecs-framework';
|
||||
|
||||
// 内部 API 接口定义
|
||||
interface IPluginAPIInternal {
|
||||
getScene(): Scene | null;
|
||||
getEntityStore(): EntityStoreService;
|
||||
getMessageHub(): MessageHub;
|
||||
resolveService<T>(serviceType: any): T;
|
||||
getCore(): any;
|
||||
}
|
||||
|
||||
// 声明全局类型
|
||||
declare global {
|
||||
interface Window {
|
||||
__ESENGINE__?: {
|
||||
api?: IPluginAPIInternal;
|
||||
[key: string]: any;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取内部 API
|
||||
*/
|
||||
function getInternalAPI(): IPluginAPIInternal {
|
||||
const api = window.__ESENGINE__?.api;
|
||||
if (!api) {
|
||||
throw new Error('[PluginAPI] 插件 API 未初始化,请确保编辑器已正确启动');
|
||||
}
|
||||
return api;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件 API
|
||||
* 提供简洁的属性访问方式,避免模块实例不一致问题
|
||||
*/
|
||||
export const PluginAPI = {
|
||||
/**
|
||||
* 获取当前场景
|
||||
* @throws 如果场景未初始化
|
||||
*/
|
||||
get scene(): Scene {
|
||||
const scene = getInternalAPI().getScene();
|
||||
if (!scene) {
|
||||
throw new Error('[PluginAPI] 场景未初始化,请先打开或创建一个场景');
|
||||
}
|
||||
return scene;
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取当前场景(可能为 null)
|
||||
*/
|
||||
get sceneOrNull(): Scene | null {
|
||||
return getInternalAPI().getScene();
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取 EntityStoreService
|
||||
*/
|
||||
get entityStore(): EntityStoreService {
|
||||
return getInternalAPI().getEntityStore();
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取 MessageHub
|
||||
*/
|
||||
get messageHub(): MessageHub {
|
||||
return getInternalAPI().getMessageHub();
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取服务容器
|
||||
*/
|
||||
get services(): ServiceContainer {
|
||||
return getInternalAPI().getCore().services;
|
||||
},
|
||||
|
||||
/**
|
||||
* 解析服务
|
||||
* @param serviceType 服务类型
|
||||
*/
|
||||
resolve<T>(serviceType: any): T {
|
||||
return getInternalAPI().resolveService<T>(serviceType);
|
||||
},
|
||||
|
||||
/**
|
||||
* 检查 API 是否可用
|
||||
*/
|
||||
get isAvailable(): boolean {
|
||||
return !!window.__ESENGINE__?.api;
|
||||
},
|
||||
};
|
||||
@@ -94,14 +94,10 @@ export type {
|
||||
// Runtime exports from editor-core
|
||||
export {
|
||||
// Enums
|
||||
EditorPluginCategory,
|
||||
PanelPosition,
|
||||
UIExtensionType,
|
||||
|
||||
// Classes
|
||||
EditorPluginManager,
|
||||
PluginRegistry,
|
||||
pluginRegistry,
|
||||
UIRegistry,
|
||||
MessageHub,
|
||||
SerializerRegistry,
|
||||
@@ -123,6 +119,9 @@ export {
|
||||
BaseCommand,
|
||||
PropertyMetadataService,
|
||||
|
||||
// Plugin system
|
||||
PluginManager,
|
||||
|
||||
// Gizmo exports
|
||||
GizmoRegistry,
|
||||
GizmoColors,
|
||||
@@ -141,22 +140,17 @@ export {
|
||||
// Type-only exports from editor-core
|
||||
export type {
|
||||
// Plugin types
|
||||
IEditorPlugin,
|
||||
IEditorPluginMetadata,
|
||||
ISerializer,
|
||||
FileContextMenuItem,
|
||||
FileCreationTemplate,
|
||||
FileActionHandler,
|
||||
EditorPluginDefinition,
|
||||
RegisteredPlugin,
|
||||
MenuTreeNode,
|
||||
ComponentRegistration,
|
||||
MenuItemRegistration,
|
||||
PanelRegistration,
|
||||
ToolbarItemRegistration,
|
||||
EntityTemplateRegistration,
|
||||
AssetHandlerRegistration,
|
||||
ComponentActionDefinition,
|
||||
PluginConfig,
|
||||
PluginCategory,
|
||||
LoadingPhase,
|
||||
ModuleType,
|
||||
ModuleDescriptor,
|
||||
PluginDependency,
|
||||
PluginState,
|
||||
|
||||
// Service interfaces
|
||||
IFileSystem,
|
||||
@@ -191,6 +185,7 @@ export type {
|
||||
IGizmoRenderData,
|
||||
IGizmoProvider,
|
||||
GizmoProviderFn,
|
||||
GizmoProviderRegistration,
|
||||
|
||||
// UI types
|
||||
MenuItem,
|
||||
@@ -199,6 +194,17 @@ export type {
|
||||
EntityCreationTemplate,
|
||||
IFileAPI,
|
||||
PropertyMetadata,
|
||||
MenuItemDescriptor,
|
||||
ToolbarItemDescriptor,
|
||||
ComponentAction,
|
||||
|
||||
// Plugin system types
|
||||
IPluginLoader,
|
||||
IRuntimeModuleLoader,
|
||||
IEditorModuleLoader,
|
||||
PluginDescriptor,
|
||||
SystemContext,
|
||||
ComponentInspectorProviderDef,
|
||||
} from '@esengine/editor-core';
|
||||
|
||||
|
||||
@@ -225,6 +231,95 @@ import * as Icons from 'lucide-react';
|
||||
export { Icons };
|
||||
export type { LucideIcon } from 'lucide-react';
|
||||
|
||||
// =============================================================================
|
||||
// Plugin API
|
||||
// =============================================================================
|
||||
export { PluginAPI } from './PluginAPI';
|
||||
|
||||
// =============================================================================
|
||||
// UI System
|
||||
// =============================================================================
|
||||
export {
|
||||
// Components - Core
|
||||
UITransformComponent,
|
||||
AnchorPreset,
|
||||
UIRenderComponent,
|
||||
UIRenderType,
|
||||
UIInteractableComponent,
|
||||
UITextComponent,
|
||||
UILayoutComponent,
|
||||
UILayoutType,
|
||||
UIJustifyContent,
|
||||
UIAlignItems,
|
||||
// Components - Widgets
|
||||
UIButtonComponent,
|
||||
UIProgressBarComponent,
|
||||
UIProgressDirection,
|
||||
UIProgressFillMode,
|
||||
UISliderComponent,
|
||||
UISliderOrientation,
|
||||
UIScrollViewComponent,
|
||||
UIScrollbarVisibility,
|
||||
// Systems - Core
|
||||
UILayoutSystem,
|
||||
UIInputSystem,
|
||||
MouseButton,
|
||||
UIAnimationSystem,
|
||||
Easing,
|
||||
UIRenderDataProvider,
|
||||
// Systems - Render
|
||||
UIRenderCollector,
|
||||
getUIRenderCollector,
|
||||
resetUIRenderCollector,
|
||||
invalidateUIRenderCaches,
|
||||
UIRenderBeginSystem,
|
||||
UIRectRenderSystem,
|
||||
UITextRenderSystem,
|
||||
UIButtonRenderSystem,
|
||||
UIProgressBarRenderSystem,
|
||||
UISliderRenderSystem,
|
||||
UIScrollViewRenderSystem,
|
||||
// Rendering
|
||||
WebGLUIRenderer,
|
||||
TextRenderer,
|
||||
// Builder API
|
||||
UIBuilder,
|
||||
// Plugin
|
||||
UIPlugin,
|
||||
UIRuntimeModule,
|
||||
} from '@esengine/ui';
|
||||
|
||||
export type {
|
||||
// Types from UI
|
||||
UIBorderStyle,
|
||||
UIShadowStyle,
|
||||
UICursorType,
|
||||
UITextAlign,
|
||||
UITextVerticalAlign,
|
||||
UITextOverflow,
|
||||
UIFontWeight,
|
||||
UIPadding,
|
||||
UIButtonStyle,
|
||||
UIButtonDisplayMode,
|
||||
UIInputEvent,
|
||||
EasingFunction,
|
||||
EasingName,
|
||||
UIRenderPrimitive,
|
||||
ProviderRenderData as UIProviderRenderData,
|
||||
IRenderDataProvider as UIIRenderDataProvider,
|
||||
IUIRenderDataProvider,
|
||||
TextMeasurement,
|
||||
TextRenderOptions,
|
||||
UIBaseConfig,
|
||||
UIButtonConfig,
|
||||
UITextConfig,
|
||||
UIImageConfig,
|
||||
UIProgressBarConfig,
|
||||
UISliderConfig,
|
||||
UIPanelConfig,
|
||||
UIScrollViewConfig,
|
||||
} from '@esengine/ui';
|
||||
|
||||
// =============================================================================
|
||||
// SDK Metadata
|
||||
// =============================================================================
|
||||
|
||||
@@ -5,15 +5,17 @@
|
||||
"moduleResolution": "bundler",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "react-jsx",
|
||||
"composite": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
@@ -21,6 +23,6 @@
|
||||
"references": [
|
||||
{ "path": "../core" },
|
||||
{ "path": "../editor-core" },
|
||||
{ "path": "../behavior-tree" }
|
||||
{ "path": "../ui" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ export default defineConfig({
|
||||
dts({
|
||||
include: ['src'],
|
||||
outDir: 'dist',
|
||||
rollupTypes: true
|
||||
rollupTypes: false,
|
||||
tsconfigPath: './tsconfig.json'
|
||||
})
|
||||
],
|
||||
define: {
|
||||
@@ -24,8 +25,21 @@ export default defineConfig({
|
||||
fileName: () => 'editor-runtime.js'
|
||||
},
|
||||
rollupOptions: {
|
||||
// 将 React 设为外部依赖,使用主应用提供的 React
|
||||
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
||||
// 将 React 和核心 ECS 框架设为外部依赖
|
||||
// 这确保整个应用使用同一个 ComponentRegistry 实例
|
||||
external: [
|
||||
'react',
|
||||
'react-dom',
|
||||
'react/jsx-runtime',
|
||||
'@esengine/ecs-framework',
|
||||
'@esengine/ecs-components',
|
||||
'@esengine/tilemap',
|
||||
'@esengine/ui',
|
||||
'@esengine/behavior-tree',
|
||||
'@esengine/platform-web',
|
||||
'@esengine/ecs-engine-bindgen',
|
||||
'@esengine/asset-system',
|
||||
],
|
||||
output: {
|
||||
exports: 'named',
|
||||
inlineDynamicImports: true,
|
||||
|
||||
Reference in New Issue
Block a user