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 专用于编辑器组件元数据 - 更新所有编辑器包使用新名称
This commit is contained in:
@@ -15,13 +15,13 @@ import type {
|
||||
import {
|
||||
EntityStoreService,
|
||||
MessageHub,
|
||||
ComponentRegistry
|
||||
EditorComponentRegistry
|
||||
} from '@esengine/editor-core';
|
||||
import { CameraComponent } from '@esengine/camera';
|
||||
|
||||
export class CameraEditorModule implements IEditorModuleLoader {
|
||||
async install(services: ServiceContainer): Promise<void> {
|
||||
const componentRegistry = services.resolve(ComponentRegistry);
|
||||
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||
if (componentRegistry) {
|
||||
componentRegistry.register({
|
||||
name: 'Camera',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { IComponentRegistry, IScene } from '@esengine/ecs-framework';
|
||||
import type { IRuntimeModule, IRuntimePlugin, ModuleManifest, SystemContext } from '@esengine/engine-core';
|
||||
import { EngineBridgeToken } from '@esengine/engine-core';
|
||||
import { RenderConfigServiceToken } from '@esengine/engine-core';
|
||||
import { CameraComponent } from './CameraComponent';
|
||||
import { CameraSystem } from './CameraSystem';
|
||||
|
||||
@@ -10,15 +10,15 @@ class CameraRuntimeModule implements IRuntimeModule {
|
||||
}
|
||||
|
||||
createSystems(scene: IScene, context: SystemContext): void {
|
||||
// 从服务注册表获取 EngineBridge | Get EngineBridge from service registry
|
||||
const bridge = context.services.get(EngineBridgeToken);
|
||||
if (!bridge) {
|
||||
console.warn('[CameraPlugin] EngineBridge not found, CameraSystem will not be created');
|
||||
// 从服务注册表获取渲染配置服务 | Get render config service from registry
|
||||
const renderConfig = context.services.get(RenderConfigServiceToken);
|
||||
if (!renderConfig) {
|
||||
console.warn('[CameraPlugin] RenderConfigService not found, CameraSystem will not be created');
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建并添加 CameraSystem | Create and add CameraSystem
|
||||
const cameraSystem = new CameraSystem(bridge);
|
||||
const cameraSystem = new CameraSystem(renderConfig);
|
||||
scene.addSystem(cameraSystem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
*/
|
||||
|
||||
import { EntitySystem, Matcher, Entity, ECSSystem } from '@esengine/ecs-framework';
|
||||
import type { IEngineBridge } from '@esengine/engine-core';
|
||||
import type { IRenderConfigService } from '@esengine/engine-core';
|
||||
import { CameraComponent } from './CameraComponent';
|
||||
|
||||
@ECSSystem('Camera', { updateOrder: -100 })
|
||||
export class CameraSystem extends EntitySystem {
|
||||
private bridge: IEngineBridge;
|
||||
private renderConfig: IRenderConfigService;
|
||||
private lastAppliedCameraId: number | null = null;
|
||||
|
||||
constructor(bridge: IEngineBridge) {
|
||||
constructor(renderConfig: IRenderConfigService) {
|
||||
// Match entities with CameraComponent
|
||||
super(Matcher.empty().all(CameraComponent));
|
||||
this.bridge = bridge;
|
||||
this.renderConfig = renderConfig;
|
||||
}
|
||||
|
||||
protected override onBegin(): void {
|
||||
@@ -47,6 +47,6 @@ export class CameraSystem extends EntitySystem {
|
||||
const r = parseInt(bgColor.slice(1, 3), 16) / 255;
|
||||
const g = parseInt(bgColor.slice(3, 5), 16) / 255;
|
||||
const b = parseInt(bgColor.slice(5, 7), 16) / 255;
|
||||
this.bridge.setClearColor(r, g, b, 1.0);
|
||||
this.renderConfig.setClearColor(r, g, b, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,11 @@ import type { Component } from '../../Component';
|
||||
/**
|
||||
* 组件类型定义
|
||||
* Component type definition
|
||||
*
|
||||
* 注意:构造函数参数使用 any[] 是必要的,因为组件可以有各种不同签名的构造函数
|
||||
* Note: Constructor args use any[] because components can have various constructor signatures
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ComponentType<T extends Component = Component> = new (...args: any[]) => T;
|
||||
|
||||
/**
|
||||
@@ -61,6 +65,51 @@ export interface ComponentEditorOptions {
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组件构造函数上的元数据接口
|
||||
* Metadata interface stored on component constructors
|
||||
*
|
||||
* 使用 Symbol 索引签名来类型安全地访问装饰器存储的元数据
|
||||
* Uses Symbol index signature to safely access decorator-stored metadata
|
||||
*/
|
||||
export interface ComponentTypeMetadata {
|
||||
readonly [COMPONENT_TYPE_NAME]?: string;
|
||||
readonly [COMPONENT_DEPENDENCIES]?: string[];
|
||||
readonly [COMPONENT_EDITOR_OPTIONS]?: ComponentEditorOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 可写的组件类型元数据(用于装饰器设置)
|
||||
* Writable component type metadata (for decorator setting)
|
||||
*/
|
||||
export interface WritableComponentTypeMetadata {
|
||||
[COMPONENT_TYPE_NAME]?: string;
|
||||
[COMPONENT_DEPENDENCIES]?: string[];
|
||||
[COMPONENT_EDITOR_OPTIONS]?: ComponentEditorOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取组件构造函数的元数据
|
||||
* Get metadata from component constructor
|
||||
*
|
||||
* @param componentType 组件构造函数
|
||||
* @returns 元数据对象
|
||||
*/
|
||||
export function getComponentTypeMetadata(componentType: ComponentType): ComponentTypeMetadata {
|
||||
return componentType as unknown as ComponentTypeMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可写的组件构造函数元数据(用于装饰器)
|
||||
* Get writable metadata from component constructor (for decorators)
|
||||
*
|
||||
* @param componentType 组件构造函数
|
||||
* @returns 可写的元数据对象
|
||||
*/
|
||||
export function getWritableComponentTypeMetadata(componentType: ComponentType): WritableComponentTypeMetadata {
|
||||
return componentType as unknown as WritableComponentTypeMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查组件是否使用了 @ECSComponent 装饰器
|
||||
* Check if component has @ECSComponent decorator
|
||||
@@ -69,7 +118,8 @@ export interface ComponentEditorOptions {
|
||||
* @returns 是否有装饰器
|
||||
*/
|
||||
export function hasECSComponentDecorator(componentType: ComponentType): boolean {
|
||||
return !!(componentType as any)[COMPONENT_TYPE_NAME];
|
||||
const metadata = getComponentTypeMetadata(componentType);
|
||||
return metadata[COMPONENT_TYPE_NAME] !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +132,8 @@ export function hasECSComponentDecorator(componentType: ComponentType): boolean
|
||||
export function getComponentTypeName(componentType: ComponentType): string {
|
||||
// 优先使用装饰器指定的名称
|
||||
// Prefer decorator-specified name
|
||||
const decoratorName = (componentType as any)[COMPONENT_TYPE_NAME];
|
||||
const metadata = getComponentTypeMetadata(componentType);
|
||||
const decoratorName = metadata[COMPONENT_TYPE_NAME];
|
||||
if (decoratorName) {
|
||||
return decoratorName;
|
||||
}
|
||||
@@ -111,7 +162,8 @@ export function getComponentInstanceTypeName(component: Component): string {
|
||||
* @returns 依赖的组件名称列表
|
||||
*/
|
||||
export function getComponentDependencies(componentType: ComponentType): string[] | undefined {
|
||||
return (componentType as any)[COMPONENT_DEPENDENCIES];
|
||||
const metadata = getComponentTypeMetadata(componentType);
|
||||
return metadata[COMPONENT_DEPENDENCIES];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +174,8 @@ export function getComponentDependencies(componentType: ComponentType): string[]
|
||||
* @returns 编辑器选项
|
||||
*/
|
||||
export function getComponentEditorOptions(componentType: ComponentType): ComponentEditorOptions | undefined {
|
||||
return (componentType as any)[COMPONENT_EDITOR_OPTIONS];
|
||||
const metadata = getComponentTypeMetadata(componentType);
|
||||
return metadata[COMPONENT_EDITOR_OPTIONS];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,9 @@ import {
|
||||
COMPONENT_TYPE_NAME,
|
||||
COMPONENT_DEPENDENCIES,
|
||||
COMPONENT_EDITOR_OPTIONS,
|
||||
type ComponentEditorOptions
|
||||
getWritableComponentTypeMetadata,
|
||||
type ComponentEditorOptions,
|
||||
type ComponentType
|
||||
} from '../Core/ComponentStorage/ComponentTypeUtils';
|
||||
|
||||
/**
|
||||
@@ -24,6 +26,50 @@ import {
|
||||
*/
|
||||
export const SYSTEM_TYPE_NAME = Symbol('SystemTypeName');
|
||||
|
||||
/**
|
||||
* 系统类型元数据接口
|
||||
* System type metadata interface
|
||||
*/
|
||||
export interface SystemTypeMetadata {
|
||||
readonly [SYSTEM_TYPE_NAME]?: string;
|
||||
readonly __systemMetadata__?: SystemMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 可写的系统类型元数据
|
||||
* Writable system type metadata
|
||||
*/
|
||||
interface WritableSystemTypeMetadata {
|
||||
[SYSTEM_TYPE_NAME]?: string;
|
||||
__systemMetadata__?: SystemMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统类型元数据
|
||||
* Get system type metadata
|
||||
*/
|
||||
function getSystemTypeMetadata(systemType: SystemConstructor): SystemTypeMetadata {
|
||||
return systemType as unknown as SystemTypeMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可写的系统类型元数据
|
||||
* Get writable system type metadata
|
||||
*/
|
||||
function getWritableSystemTypeMetadata(systemType: SystemConstructor): WritableSystemTypeMetadata {
|
||||
return systemType as unknown as WritableSystemTypeMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统构造函数类型
|
||||
* System constructor type
|
||||
*
|
||||
* 注意:构造函数参数使用 any[] 是必要的,因为系统可以有各种不同签名的构造函数
|
||||
* Note: Constructor args use any[] because systems can have various constructor signatures
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
type SystemConstructor<T extends EntitySystem = EntitySystem> = new (...args: any[]) => T;
|
||||
|
||||
/**
|
||||
* 组件装饰器配置选项
|
||||
* Component decorator options
|
||||
@@ -67,25 +113,29 @@ export interface ComponentOptions {
|
||||
* ```
|
||||
*/
|
||||
export function ECSComponent(typeName: string, options?: ComponentOptions) {
|
||||
return function <T extends new (...args: any[]) => Component>(target: T): T {
|
||||
return function <T extends ComponentType<Component>>(target: T): T {
|
||||
if (!typeName || typeof typeName !== 'string') {
|
||||
throw new Error('ECSComponent装饰器必须提供有效的类型名称');
|
||||
}
|
||||
|
||||
// 获取可写的元数据对象
|
||||
// Get writable metadata object
|
||||
const metadata = getWritableComponentTypeMetadata(target);
|
||||
|
||||
// 在构造函数上存储类型名称
|
||||
// Store type name on constructor
|
||||
(target as any)[COMPONENT_TYPE_NAME] = typeName;
|
||||
metadata[COMPONENT_TYPE_NAME] = typeName;
|
||||
|
||||
// 存储依赖关系
|
||||
// Store dependencies
|
||||
if (options?.requires) {
|
||||
(target as any)[COMPONENT_DEPENDENCIES] = options.requires;
|
||||
metadata[COMPONENT_DEPENDENCIES] = options.requires;
|
||||
}
|
||||
|
||||
// 存储编辑器选项
|
||||
// Store editor options
|
||||
if (options?.editor) {
|
||||
(target as any)[COMPONENT_EDITOR_OPTIONS] = options.editor;
|
||||
metadata[COMPONENT_EDITOR_OPTIONS] = options.editor;
|
||||
}
|
||||
|
||||
// 自动注册到全局 ComponentRegistry,使组件可以通过名称查找
|
||||
@@ -154,19 +204,23 @@ export interface SystemMetadata {
|
||||
* ```
|
||||
*/
|
||||
export function ECSSystem(typeName: string, metadata?: SystemMetadata) {
|
||||
return function <T extends new (...args: any[]) => EntitySystem>(target: T): T {
|
||||
return function <T extends SystemConstructor>(target: T): T {
|
||||
if (!typeName || typeof typeName !== 'string') {
|
||||
throw new Error('ECSSystem装饰器必须提供有效的类型名称');
|
||||
}
|
||||
|
||||
// 获取可写的元数据对象
|
||||
// Get writable metadata object
|
||||
const meta = getWritableSystemTypeMetadata(target);
|
||||
|
||||
// 在构造函数上存储类型名称
|
||||
// Store type name on constructor
|
||||
(target as any)[SYSTEM_TYPE_NAME] = typeName;
|
||||
meta[SYSTEM_TYPE_NAME] = typeName;
|
||||
|
||||
// 存储元数据
|
||||
// Store metadata
|
||||
if (metadata) {
|
||||
(target as any).__systemMetadata__ = metadata;
|
||||
meta.__systemMetadata__ = metadata;
|
||||
}
|
||||
|
||||
return target;
|
||||
@@ -177,8 +231,9 @@ export function ECSSystem(typeName: string, metadata?: SystemMetadata) {
|
||||
* 获取 System 的元数据
|
||||
* Get System metadata
|
||||
*/
|
||||
export function getSystemMetadata(systemType: new (...args: any[]) => EntitySystem): SystemMetadata | undefined {
|
||||
return (systemType as any).__systemMetadata__;
|
||||
export function getSystemMetadata(systemType: SystemConstructor): SystemMetadata | undefined {
|
||||
const meta = getSystemTypeMetadata(systemType);
|
||||
return meta.__systemMetadata__;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +244,7 @@ export function getSystemMetadata(systemType: new (...args: any[]) => EntitySyst
|
||||
* @returns 系统元数据 | System metadata
|
||||
*/
|
||||
export function getSystemInstanceMetadata(system: EntitySystem): SystemMetadata | undefined {
|
||||
return getSystemMetadata(system.constructor as new (...args: any[]) => EntitySystem);
|
||||
return getSystemMetadata(system.constructor as SystemConstructor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,9 +255,10 @@ export function getSystemInstanceMetadata(system: EntitySystem): SystemMetadata
|
||||
* @returns 系统类型名称 | System type name
|
||||
*/
|
||||
export function getSystemTypeName<T extends EntitySystem>(
|
||||
systemType: new (...args: any[]) => T
|
||||
systemType: SystemConstructor<T>
|
||||
): string {
|
||||
const decoratorName = (systemType as any)[SYSTEM_TYPE_NAME];
|
||||
const meta = getSystemTypeMetadata(systemType);
|
||||
const decoratorName = meta[SYSTEM_TYPE_NAME];
|
||||
if (decoratorName) {
|
||||
return decoratorName;
|
||||
}
|
||||
@@ -217,5 +273,5 @@ export function getSystemTypeName<T extends EntitySystem>(
|
||||
* @returns 系统类型名称 | System type name
|
||||
*/
|
||||
export function getSystemInstanceTypeName(system: EntitySystem): string {
|
||||
return getSystemTypeName(system.constructor as new (...args: any[]) => EntitySystem);
|
||||
return getSystemTypeName(system.constructor as SystemConstructor);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
import type { SpriteRenderData, TextureLoadRequest, EngineStats, CameraConfig } from '../types';
|
||||
import type { ITextureEngineBridge } from '@esengine/asset-system';
|
||||
import type { GameEngine } from '../wasm/es_engine';
|
||||
import type {
|
||||
ITextureService,
|
||||
IDynamicAtlasService,
|
||||
ICoordinateService,
|
||||
IRenderConfigService
|
||||
} from '@esengine/engine-core';
|
||||
|
||||
/**
|
||||
* Engine bridge configuration.
|
||||
@@ -43,7 +49,7 @@ export interface EngineBridgeConfig {
|
||||
* bridge.render();
|
||||
* ```
|
||||
*/
|
||||
export class EngineBridge implements ITextureEngineBridge {
|
||||
export class EngineBridge implements ITextureEngineBridge, ITextureService, IDynamicAtlasService, ICoordinateService, IRenderConfigService {
|
||||
private engine: GameEngine | null = null;
|
||||
private config: Required<EngineBridgeConfig>;
|
||||
private initialized = false;
|
||||
|
||||
@@ -8,12 +8,20 @@
|
||||
// Service tokens and interfaces (谁定义接口,谁导出 Token)
|
||||
export {
|
||||
RenderSystemToken,
|
||||
EngineBridgeToken,
|
||||
EngineIntegrationToken,
|
||||
// 新的单一职责服务令牌 | New single-responsibility service tokens
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken,
|
||||
// 接口类型 | Interface types
|
||||
type IRenderSystem,
|
||||
type IEngineBridge,
|
||||
type IEngineIntegration,
|
||||
type IRenderDataProvider
|
||||
type IRenderDataProvider,
|
||||
type ITextureService,
|
||||
type IDynamicAtlasService,
|
||||
type ICoordinateService,
|
||||
type IRenderConfigService
|
||||
} from './tokens';
|
||||
|
||||
export { EngineBridge } from './core/EngineBridge';
|
||||
|
||||
@@ -4,12 +4,31 @@
|
||||
*/
|
||||
|
||||
import { createServiceToken } from '@esengine/ecs-framework';
|
||||
import { EngineBridgeToken as CoreEngineBridgeToken, type IEngineBridge as CoreIEngineBridge } from '@esengine/engine-core';
|
||||
import {
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken,
|
||||
type ITextureService,
|
||||
type IDynamicAtlasService,
|
||||
type ICoordinateService,
|
||||
type IRenderConfigService
|
||||
} from '@esengine/engine-core';
|
||||
import type { IRenderDataProvider as InternalIRenderDataProvider } from './systems/EngineRenderSystem';
|
||||
|
||||
// 从 engine-core 重新导出 | Re-export from engine-core
|
||||
export { CoreEngineBridgeToken as EngineBridgeToken };
|
||||
export type { CoreIEngineBridge as IEngineBridge };
|
||||
export {
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken
|
||||
};
|
||||
export type {
|
||||
ITextureService,
|
||||
IDynamicAtlasService,
|
||||
ICoordinateService,
|
||||
IRenderConfigService
|
||||
};
|
||||
|
||||
export type IRenderDataProvider = InternalIRenderDataProvider;
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
UIRegistry,
|
||||
MessageHub,
|
||||
EntityStoreService,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
LocaleService,
|
||||
LogService,
|
||||
SettingsRegistry,
|
||||
@@ -394,7 +394,7 @@ function App() {
|
||||
setStatus(t('header.status.remoteConnected'));
|
||||
} else {
|
||||
if (projectLoaded) {
|
||||
const componentRegistry = Core.services.resolve(ComponentRegistry);
|
||||
const componentRegistry = Core.services.resolve(EditorComponentRegistry);
|
||||
const componentCount = componentRegistry?.getAllComponents().length || 0;
|
||||
setStatus(t('header.status.projectOpened') + (componentCount > 0 ? ` (${componentCount} components registered)` : ''));
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
IMessageHub,
|
||||
SerializerRegistry,
|
||||
EntityStoreService,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
ProjectService,
|
||||
ComponentDiscoveryService,
|
||||
PropertyMetadataService,
|
||||
@@ -90,7 +90,7 @@ export interface EditorServices {
|
||||
messageHub: MessageHub;
|
||||
serializerRegistry: SerializerRegistry;
|
||||
entityStore: EntityStoreService;
|
||||
componentRegistry: ComponentRegistry;
|
||||
componentRegistry: EditorComponentRegistry;
|
||||
projectService: ProjectService;
|
||||
componentDiscovery: ComponentDiscoveryService;
|
||||
propertyMetadata: PropertyMetadataService;
|
||||
@@ -121,7 +121,7 @@ export class ServiceRegistry {
|
||||
const messageHub = new MessageHub();
|
||||
const serializerRegistry = new SerializerRegistry();
|
||||
const entityStore = new EntityStoreService(messageHub);
|
||||
const componentRegistry = new ComponentRegistry();
|
||||
const componentRegistry = new EditorComponentRegistry();
|
||||
|
||||
// 注册标准组件到编辑器和核心注册表
|
||||
// Register to both editor registry (for UI) and core registry (for serialization)
|
||||
@@ -168,7 +168,7 @@ export class ServiceRegistry {
|
||||
Core.services.registerInstance(IMessageHub, messageHub); // Symbol 注册用于跨包插件访问
|
||||
Core.services.registerInstance(SerializerRegistry, serializerRegistry);
|
||||
Core.services.registerInstance(EntityStoreService, entityStore);
|
||||
Core.services.registerInstance(ComponentRegistry, componentRegistry);
|
||||
Core.services.registerInstance(EditorComponentRegistry, componentRegistry);
|
||||
Core.services.registerInstance(ProjectService, projectService);
|
||||
Core.services.registerInstance(ComponentDiscoveryService, componentDiscovery);
|
||||
Core.services.registerInstance(PropertyMetadataService, propertyMetadata);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Entity, Component, getComponentDependencies, getComponentTypeName } from '@esengine/ecs-framework';
|
||||
import { MessageHub, ComponentRegistry } from '@esengine/editor-core';
|
||||
import { MessageHub, EditorComponentRegistry } from '@esengine/editor-core';
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
import { BaseCommand } from '../BaseCommand';
|
||||
|
||||
@@ -55,7 +55,7 @@ export class AddComponentCommand extends BaseCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
const componentRegistry = Core.services.tryResolve(ComponentRegistry) as ComponentRegistry | null;
|
||||
const componentRegistry = Core.services.tryResolve(EditorComponentRegistry) as EditorComponentRegistry | null;
|
||||
if (!componentRegistry) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
import {
|
||||
MessageHub,
|
||||
CommandManager,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
ComponentActionRegistry,
|
||||
ComponentInspectorRegistry,
|
||||
PrefabService,
|
||||
@@ -147,7 +147,7 @@ export const EntityInspectorPanel: React.FC<EntityInspectorPanelProps> = ({
|
||||
|
||||
// ==================== 服务 | Services ====================
|
||||
|
||||
const componentRegistry = Core.services.resolve(ComponentRegistry);
|
||||
const componentRegistry = Core.services.resolve(EditorComponentRegistry);
|
||||
const componentActionRegistry = Core.services.resolve(ComponentActionRegistry);
|
||||
const componentInspectorRegistry = Core.services.resolve(ComponentInspectorRegistry);
|
||||
const prefabService = Core.services.tryResolve(PrefabService) as PrefabService | null;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
||||
import { Settings, ChevronDown, ChevronRight, X, Plus, Box, Search, Lock, Unlock } from 'lucide-react';
|
||||
import { Entity, Component, Core, getComponentDependencies, getComponentTypeName, getComponentInstanceTypeName, isComponentInstanceHiddenInInspector, PrefabInstanceComponent } from '@esengine/ecs-framework';
|
||||
import { MessageHub, CommandManager, ComponentRegistry, ComponentActionRegistry, ComponentInspectorRegistry, PrefabService } from '@esengine/editor-core';
|
||||
import { MessageHub, CommandManager, EditorComponentRegistry, ComponentActionRegistry, ComponentInspectorRegistry, PrefabService } from '@esengine/editor-core';
|
||||
import { PropertyInspector } from '../../PropertyInspector';
|
||||
import { NotificationService } from '../../../services/NotificationService';
|
||||
import { RemoveComponentCommand, UpdateComponentCommand, AddComponentCommand } from '../../../application/commands/component';
|
||||
@@ -11,7 +11,7 @@ import * as LucideIcons from 'lucide-react';
|
||||
|
||||
type CategoryFilter = 'all' | 'general' | 'transform' | 'rendering' | 'physics' | 'audio' | 'other';
|
||||
|
||||
// 从 ComponentRegistry category 到 CategoryFilter 的映射
|
||||
// 从 EditorComponentRegistry category 到 CategoryFilter 的映射
|
||||
const categoryKeyMap: Record<string, CategoryFilter> = {
|
||||
'components.category.core': 'general',
|
||||
'components.category.rendering': 'rendering',
|
||||
@@ -84,7 +84,7 @@ export function EntityInspector({
|
||||
const addButtonRef = useRef<HTMLButtonElement>(null);
|
||||
const searchInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const componentRegistry = Core.services.resolve(ComponentRegistry);
|
||||
const componentRegistry = Core.services.resolve(EditorComponentRegistry);
|
||||
const componentActionRegistry = Core.services.resolve(ComponentActionRegistry);
|
||||
const componentInspectorRegistry = Core.services.resolve(ComponentInspectorRegistry);
|
||||
const prefabService = Core.services.tryResolve(PrefabService) as PrefabService | null;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
import type { IPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import type { IEditorPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import { AssetRegistryService } from '@esengine/editor-core';
|
||||
|
||||
const logger = createLogger('AssetMetaPlugin');
|
||||
@@ -65,7 +65,7 @@ const manifest: ModuleManifest = {
|
||||
exports: {}
|
||||
};
|
||||
|
||||
export const AssetMetaPlugin: IPlugin = {
|
||||
export const AssetMetaPlugin: IEditorPlugin = {
|
||||
manifest,
|
||||
editorModule: new AssetMetaEditorModule()
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
import type { IPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import type { IEditorPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import { SettingsRegistry } from '@esengine/editor-core';
|
||||
import { SettingsService } from '../../services/SettingsService';
|
||||
|
||||
@@ -146,7 +146,7 @@ const manifest: ModuleManifest = {
|
||||
exports: {}
|
||||
};
|
||||
|
||||
export const EditorAppearancePlugin: IPlugin = {
|
||||
export const EditorAppearancePlugin: IEditorPlugin = {
|
||||
manifest,
|
||||
editorModule: new EditorAppearanceEditorModule()
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import type { IPlugin, IEditorModuleLoader, ModuleManifest, GizmoProviderRegistration } from '@esengine/editor-core';
|
||||
import type { IEditorPlugin, IEditorModuleLoader, ModuleManifest, GizmoProviderRegistration } from '@esengine/editor-core';
|
||||
import { registerSpriteGizmo } from '../../gizmos';
|
||||
|
||||
/**
|
||||
@@ -42,7 +42,7 @@ const manifest: ModuleManifest = {
|
||||
}
|
||||
};
|
||||
|
||||
export const GizmoPlugin: IPlugin = {
|
||||
export const GizmoPlugin: IEditorPlugin = {
|
||||
manifest,
|
||||
editorModule: new GizmoEditorModule()
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import { createLogger } from '@esengine/ecs-framework';
|
||||
import type { IPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import type { IEditorPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import { SettingsRegistry } from '@esengine/editor-core';
|
||||
|
||||
const logger = createLogger('PluginConfigPlugin');
|
||||
@@ -69,7 +69,7 @@ const manifest: ModuleManifest = {
|
||||
exports: {}
|
||||
};
|
||||
|
||||
export const PluginConfigPlugin: IPlugin = {
|
||||
export const PluginConfigPlugin: IEditorPlugin = {
|
||||
manifest,
|
||||
editorModule: new PluginConfigEditorModule()
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
import type {
|
||||
IPlugin,
|
||||
IEditorPlugin,
|
||||
IEditorModuleLoader,
|
||||
ModuleManifest,
|
||||
MenuItemDescriptor
|
||||
@@ -140,7 +140,7 @@ const manifest: ModuleManifest = {
|
||||
exports: {}
|
||||
};
|
||||
|
||||
export const ProfilerPlugin: IPlugin = {
|
||||
export const ProfilerPlugin: IEditorPlugin = {
|
||||
manifest,
|
||||
editorModule: new ProfilerEditorModule()
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import { createLogger, Core } from '@esengine/ecs-framework';
|
||||
import type { IPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import type { IEditorPlugin, IEditorModuleLoader, ModuleManifest } from '@esengine/editor-core';
|
||||
import { SettingsRegistry, ProjectService, moduleRegistry } from '@esengine/editor-core';
|
||||
import EngineService from '../../services/EngineService';
|
||||
|
||||
@@ -306,7 +306,7 @@ const manifest: ModuleManifest = {
|
||||
exports: {}
|
||||
};
|
||||
|
||||
export const ProjectSettingsPlugin: IPlugin = {
|
||||
export const ProjectSettingsPlugin: IEditorPlugin = {
|
||||
manifest,
|
||||
editorModule: new ProjectSettingsEditorModule()
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Core, Entity } from '@esengine/ecs-framework';
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
import type {
|
||||
IPlugin,
|
||||
IEditorPlugin,
|
||||
IEditorModuleLoader,
|
||||
ModuleManifest,
|
||||
PanelDescriptor,
|
||||
@@ -191,7 +191,7 @@ const manifest: ModuleManifest = {
|
||||
}
|
||||
};
|
||||
|
||||
export const SceneInspectorPlugin: IPlugin = {
|
||||
export const SceneInspectorPlugin: IEditorPlugin = {
|
||||
manifest,
|
||||
editorModule: new SceneInspectorEditorModule()
|
||||
};
|
||||
|
||||
@@ -8,7 +8,15 @@
|
||||
|
||||
import { GizmoRegistry, EntityStoreService, MessageHub, SceneManagerService, ProjectService, PluginManager, IPluginManager, AssetRegistryService, GizmoInteractionService, GizmoInteractionServiceToken, type SystemContext } from '@esengine/editor-core';
|
||||
import { Core, Scene, Entity, SceneSerializer, ProfilerSDK, createLogger, PluginServiceRegistry } from '@esengine/ecs-framework';
|
||||
import { CameraConfig, EngineBridgeToken, RenderSystemToken, EngineIntegrationToken } from '@esengine/ecs-engine-bindgen';
|
||||
import {
|
||||
CameraConfig,
|
||||
RenderSystemToken,
|
||||
EngineIntegrationToken,
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken
|
||||
} from '@esengine/ecs-engine-bindgen';
|
||||
import { TransformComponent, TransformTypeToken, CanvasElementToken } from '@esengine/engine-core';
|
||||
import { SpriteComponent, SpriteAnimatorComponent, SpriteAnimatorSystemToken } from '@esengine/sprite';
|
||||
import { ParticleSystemComponent } from '@esengine/particle';
|
||||
@@ -252,7 +260,11 @@ export class EngineService {
|
||||
// 创建服务注册表并注册核心服务
|
||||
// Create service registry and register core services
|
||||
const services = new PluginServiceRegistry();
|
||||
services.register(EngineBridgeToken, this._runtime.bridge);
|
||||
// 使用单一职责接口注册 EngineBridge | Register EngineBridge with single-responsibility interfaces
|
||||
services.register(TextureServiceToken, this._runtime.bridge);
|
||||
services.register(DynamicAtlasServiceToken, this._runtime.bridge);
|
||||
services.register(CoordinateServiceToken, this._runtime.bridge);
|
||||
services.register(RenderConfigServiceToken, this._runtime.bridge);
|
||||
services.register(RenderSystemToken, this._runtime.renderSystem);
|
||||
services.register(AssetManagerToken, this._assetManager);
|
||||
services.register(EngineIntegrationToken, this._engineIntegration);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { PluginManager, LocaleService, MessageHub, EditorConfig, getPluginsPath } from '@esengine/editor-core';
|
||||
import type { IPlugin, ModuleManifest } from '@esengine/editor-core';
|
||||
import type { IRuntimePlugin, ModuleManifest } from '@esengine/editor-core';
|
||||
import { Core } from '@esengine/ecs-framework';
|
||||
import { TauriAPI } from '../api/tauri';
|
||||
import { PluginSDKRegistry } from './PluginSDKRegistry';
|
||||
@@ -164,7 +164,7 @@ export class PluginLoader {
|
||||
code: string,
|
||||
pluginName: string,
|
||||
_pluginDirName: string
|
||||
): Promise<IPlugin | null> {
|
||||
): Promise<IRuntimePlugin | null> {
|
||||
const pluginKey = this.sanitizePluginKey(pluginName);
|
||||
|
||||
const pluginsContainer = (window as any)[PLUGINS_GLOBAL_NAME] as Record<string, any>;
|
||||
@@ -267,7 +267,7 @@ export class PluginLoader {
|
||||
/**
|
||||
* 查找模块中的插件
|
||||
*/
|
||||
private findPluginLoader(module: any): IPlugin | null {
|
||||
private findPluginLoader(module: any): IRuntimePlugin | null {
|
||||
// 优先检查 default 导出
|
||||
if (module.default && this.isPluginLoader(module.default)) {
|
||||
return module.default;
|
||||
@@ -287,12 +287,12 @@ export class PluginLoader {
|
||||
/**
|
||||
* 验证对象是否为有效的插件
|
||||
*/
|
||||
private isPluginLoader(obj: any): obj is IPlugin {
|
||||
private isPluginLoader(obj: any): obj is IRuntimePlugin {
|
||||
if (!obj || typeof obj !== 'object') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 新的 IPlugin 接口检查
|
||||
// IRuntimePlugin 接口检查
|
||||
if (obj.manifest && this.isModuleManifest(obj.manifest)) {
|
||||
return true;
|
||||
}
|
||||
@@ -315,7 +315,7 @@ export class PluginLoader {
|
||||
/**
|
||||
* 同步插件语言设置
|
||||
*/
|
||||
private syncPluginLocale(plugin: IPlugin, pluginName: string): void {
|
||||
private syncPluginLocale(plugin: IRuntimePlugin, pluginName: string): void {
|
||||
try {
|
||||
const localeService = Core.services.resolve(LocaleService);
|
||||
const currentLocale = localeService.getCurrentLocale();
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"@esengine/asset-system": "workspace:*",
|
||||
"@esengine/asset-system-editor": "workspace:*",
|
||||
"@esengine/engine-core": "workspace:*",
|
||||
"@esengine/plugin-types": "workspace:*",
|
||||
"@tauri-apps/api": "^2.2.0",
|
||||
"@babel/core": "^7.28.3",
|
||||
"@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
|
||||
|
||||
@@ -15,7 +15,7 @@ export type {
|
||||
LoadingPhase,
|
||||
SystemContext,
|
||||
IRuntimeModule,
|
||||
IPlugin,
|
||||
IRuntimePlugin,
|
||||
ModuleManifest,
|
||||
ModuleCategory,
|
||||
ModulePlatform,
|
||||
@@ -309,17 +309,17 @@ export interface IEditorModuleLoader extends IEditorModuleBase {
|
||||
// 编辑器插件类型 | Editor Plugin Type
|
||||
// ============================================================================
|
||||
|
||||
import type { IPlugin } from './PluginDescriptor';
|
||||
import type { IRuntimePlugin } from './PluginDescriptor';
|
||||
|
||||
/**
|
||||
* 编辑器插件类型
|
||||
* Editor plugin type
|
||||
*
|
||||
* 这是开发编辑器插件时应使用的类型。
|
||||
* 它是 IPlugin 的特化版本,editorModule 类型为 IEditorModuleLoader。
|
||||
* 它是 IRuntimePlugin 的特化版本,editorModule 类型为 IEditorModuleLoader。
|
||||
*
|
||||
* This is the type to use when developing editor plugins.
|
||||
* It's a specialized version of IPlugin with editorModule typed as IEditorModuleLoader.
|
||||
* It's a specialized version of IRuntimePlugin with editorModule typed as IEditorModuleLoader.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
@@ -337,4 +337,4 @@ import type { IPlugin } from './PluginDescriptor';
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
export type IEditorPlugin = IPlugin<IEditorModuleLoader>;
|
||||
export type IEditorPlugin = IRuntimePlugin<IEditorModuleLoader>;
|
||||
|
||||
@@ -6,10 +6,6 @@
|
||||
* Re-export base types from @esengine/engine-core.
|
||||
*/
|
||||
|
||||
// 从 engine-core 导入类型
|
||||
// Import types from engine-core
|
||||
import type { IRuntimePlugin as IRuntimePluginBase } from '@esengine/engine-core';
|
||||
|
||||
// 从 engine-core 重新导出所有类型
|
||||
// 包括 IEditorModuleBase(原来在 plugin-types 中定义,现在统一从 engine-core 导出)
|
||||
export type {
|
||||
@@ -24,9 +20,6 @@ export type {
|
||||
IEditorModuleBase
|
||||
} from '@esengine/engine-core';
|
||||
|
||||
/** @deprecated Use IRuntimePlugin instead */
|
||||
export type IPlugin<TEditorModule = unknown> = IRuntimePluginBase<TEditorModule>;
|
||||
|
||||
/**
|
||||
* 插件状态
|
||||
* Plugin state
|
||||
|
||||
@@ -7,7 +7,7 @@ import { createLogger, GlobalComponentRegistry } from '@esengine/ecs-framework';
|
||||
import type { IScene, ServiceContainer, IService } from '@esengine/ecs-framework';
|
||||
import type {
|
||||
ModuleManifest,
|
||||
IPlugin,
|
||||
IRuntimePlugin,
|
||||
ModuleCategory,
|
||||
PluginState
|
||||
} from './PluginDescriptor';
|
||||
@@ -22,7 +22,7 @@ import { UIRegistry } from '../Services/UIRegistry';
|
||||
import { MessageHub } from '../Services/MessageHub';
|
||||
import { moduleRegistry } from '../Services/Module/ModuleRegistry';
|
||||
import { SerializerRegistry } from '../Services/SerializerRegistry';
|
||||
import { ComponentRegistry as EditorComponentRegistry } from '../Services/ComponentRegistry';
|
||||
import { EditorComponentRegistry } from '../Services/ComponentRegistry';
|
||||
|
||||
const logger = createLogger('PluginManager');
|
||||
|
||||
@@ -64,7 +64,7 @@ export interface NormalizedManifest {
|
||||
*/
|
||||
export interface NormalizedPlugin {
|
||||
manifest: NormalizedManifest;
|
||||
runtimeModule?: IPlugin['runtimeModule'];
|
||||
runtimeModule?: IRuntimePlugin['runtimeModule'];
|
||||
editorModule?: IEditorModuleLoader;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ export class PluginManager implements IService {
|
||||
* 标准化模块清单,填充默认值
|
||||
* Normalize module manifest, fill in defaults
|
||||
*/
|
||||
private normalizePlugin(input: IPlugin): NormalizedPlugin {
|
||||
private normalizePlugin(input: IRuntimePlugin): NormalizedPlugin {
|
||||
const m = input.manifest;
|
||||
return {
|
||||
manifest: {
|
||||
@@ -229,10 +229,10 @@ export class PluginManager implements IService {
|
||||
* 注册插件
|
||||
* Register plugin
|
||||
*
|
||||
* 接受任何符合 IPlugin 接口的插件,内部会标准化所有字段。
|
||||
* Accepts any plugin conforming to IPlugin interface, normalizes all fields internally.
|
||||
* 接受任何符合 IRuntimePlugin 接口的插件,内部会标准化所有字段。
|
||||
* Accepts any plugin conforming to IRuntimePlugin interface, normalizes all fields internally.
|
||||
*/
|
||||
register(plugin: IPlugin): void {
|
||||
register(plugin: IRuntimePlugin): void {
|
||||
if (!plugin) {
|
||||
logger.error('Cannot register plugin: plugin is null or undefined');
|
||||
return;
|
||||
|
||||
@@ -14,10 +14,17 @@ export interface ComponentTypeInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理编辑器中可用的组件类型
|
||||
* 编辑器组件注册表
|
||||
* Editor Component Registry
|
||||
*
|
||||
* 管理编辑器中可用的组件类型元数据(名称、分类、图标等)。
|
||||
* 与 ECS 核心的 ComponentRegistry(管理组件位掩码)不同。
|
||||
*
|
||||
* Manages component type metadata (name, category, icon, etc.) for the editor.
|
||||
* Different from the ECS core ComponentRegistry (which manages component bitmasks).
|
||||
*/
|
||||
@Injectable()
|
||||
export class ComponentRegistry implements IService {
|
||||
export class EditorComponentRegistry implements IService {
|
||||
private components: Map<string, ComponentTypeInfo> = new Map();
|
||||
|
||||
public dispose(): void {
|
||||
|
||||
@@ -108,7 +108,7 @@ export type { IVector2, IVector3 } from '@esengine/ecs-framework-math';
|
||||
// Rename conflicting exports to avoid collision with ecs-framework
|
||||
// =============================================================================
|
||||
export {
|
||||
ComponentRegistry as EditorComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
} from '@esengine/editor-core';
|
||||
|
||||
export type {
|
||||
@@ -229,7 +229,7 @@ export type {
|
||||
ModuleCategory,
|
||||
ModulePlatform,
|
||||
ModuleExports,
|
||||
IPlugin,
|
||||
IRuntimePlugin,
|
||||
IRuntimeModule,
|
||||
SystemContext,
|
||||
ComponentInspectorProviderDef,
|
||||
|
||||
@@ -30,8 +30,7 @@
|
||||
"dependencies": {
|
||||
"@esengine/ecs-framework": "workspace:*",
|
||||
"@esengine/ecs-framework-math": "workspace:*",
|
||||
"@esengine/platform-common": "workspace:*",
|
||||
"@esengine/plugin-types": "workspace:*"
|
||||
"@esengine/platform-common": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@esengine/build-config": "workspace:*",
|
||||
|
||||
@@ -21,20 +21,93 @@ import type { ModuleManifest } from './ModuleManifest';
|
||||
import {
|
||||
TransformTypeToken,
|
||||
CanvasElementToken,
|
||||
EngineBridgeToken,
|
||||
type IEngineBridge
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken,
|
||||
type ITextureService,
|
||||
type IDynamicAtlasService,
|
||||
type ICoordinateService,
|
||||
type IRenderConfigService
|
||||
} from './PluginServiceRegistry';
|
||||
|
||||
// 导出 engine-core 特有的服务令牌 | Export engine-core specific service tokens
|
||||
export {
|
||||
TransformTypeToken,
|
||||
CanvasElementToken,
|
||||
EngineBridgeToken,
|
||||
type IEngineBridge
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken,
|
||||
type ITextureService,
|
||||
type IDynamicAtlasService,
|
||||
type ICoordinateService,
|
||||
type IRenderConfigService
|
||||
};
|
||||
|
||||
// 重新导出 IEditorModuleBase(供编辑器插件使用)| Re-export for editor plugins
|
||||
export type { IEditorModuleBase } from '@esengine/plugin-types';
|
||||
// ============================================================================
|
||||
// 编辑器模块基础接口 | Editor Module Base Interface
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 编辑器模块基础接口
|
||||
* Base editor module interface
|
||||
*
|
||||
* 定义编辑器模块的核心生命周期方法。
|
||||
* 完整的 IEditorModuleLoader 接口在 editor-core 中扩展此接口。
|
||||
*
|
||||
* Defines core lifecycle methods for editor modules.
|
||||
* Full IEditorModuleLoader interface extends this in editor-core.
|
||||
*/
|
||||
export interface IEditorModuleBase {
|
||||
/**
|
||||
* 安装编辑器模块
|
||||
* Install editor module
|
||||
*/
|
||||
install(services: ServiceContainer): Promise<void>;
|
||||
|
||||
/**
|
||||
* 卸载编辑器模块
|
||||
* Uninstall editor module
|
||||
*/
|
||||
uninstall?(): Promise<void>;
|
||||
|
||||
/**
|
||||
* 编辑器就绪回调
|
||||
* Editor ready callback
|
||||
*/
|
||||
onEditorReady?(): void | Promise<void>;
|
||||
|
||||
/**
|
||||
* 项目打开回调
|
||||
* Project open callback
|
||||
*/
|
||||
onProjectOpen?(projectPath: string): void | Promise<void>;
|
||||
|
||||
/**
|
||||
* 项目关闭回调
|
||||
* Project close callback
|
||||
*/
|
||||
onProjectClose?(): void | Promise<void>;
|
||||
|
||||
/**
|
||||
* 场景加载回调
|
||||
* Scene loaded callback
|
||||
*/
|
||||
onSceneLoaded?(scenePath: string): void;
|
||||
|
||||
/**
|
||||
* 场景保存前回调
|
||||
* Before scene save callback
|
||||
*/
|
||||
onSceneSaving?(scenePath: string): boolean | void;
|
||||
|
||||
/**
|
||||
* 设置语言
|
||||
* Set locale
|
||||
*/
|
||||
setLocale?(locale: string): void;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 加载阶段 | Loading Phase
|
||||
@@ -155,7 +228,7 @@ export interface IRuntimeModule {
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 纯运行时插件 | Pure runtime plugin
|
||||
* const MyPlugin: IPlugin = {
|
||||
* const MyPlugin: IRuntimePlugin = {
|
||||
* manifest,
|
||||
* runtimeModule: new MyRuntimeModule()
|
||||
* };
|
||||
@@ -184,9 +257,6 @@ export interface IRuntimePlugin<TEditorModule = unknown> {
|
||||
readonly editorModule?: TEditorModule;
|
||||
}
|
||||
|
||||
/** @deprecated Use IRuntimePlugin instead */
|
||||
export type IPlugin<TEditorModule = unknown> = IRuntimePlugin<TEditorModule>;
|
||||
|
||||
// ============================================================================
|
||||
// Engine Core 插件 | Engine Core Plugin
|
||||
// ============================================================================
|
||||
@@ -215,7 +285,7 @@ const manifest: ModuleManifest = {
|
||||
}
|
||||
};
|
||||
|
||||
export const EnginePlugin: IPlugin = {
|
||||
export const EnginePlugin: IRuntimePlugin = {
|
||||
manifest,
|
||||
runtimeModule: new EngineRuntimeModule()
|
||||
};
|
||||
|
||||
@@ -34,115 +34,46 @@ export const TransformTypeToken = createServiceToken<new (...args: any[]) => any
|
||||
export const CanvasElementToken = createServiceToken<HTMLCanvasElement>('canvasElement');
|
||||
|
||||
// ============================================================================
|
||||
// 引擎桥接接口 | Engine Bridge Interface
|
||||
// 渲染服务接口 | Render Service Interfaces
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 引擎桥接接口
|
||||
* Engine bridge interface
|
||||
* 纹理服务接口
|
||||
* Texture service interface
|
||||
*
|
||||
* 定义 WASM 引擎桥接的核心契约,供各模块使用。
|
||||
* Defines the core contract of WASM engine bridge for modules to use.
|
||||
* 负责纹理的加载、状态查询和管理。
|
||||
* Responsible for texture loading, state querying, and management.
|
||||
*/
|
||||
export interface IEngineBridge {
|
||||
export interface ITextureService {
|
||||
/** 加载纹理 | Load texture */
|
||||
loadTexture(id: number, url: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* 屏幕坐标转世界坐标
|
||||
* Screen to world coordinate conversion
|
||||
*/
|
||||
screenToWorld(screenX: number, screenY: number): { x: number; y: number };
|
||||
/** 获取纹理加载状态 | Get texture loading state */
|
||||
getTextureState(id: number): string;
|
||||
|
||||
/**
|
||||
* 世界坐标转屏幕坐标
|
||||
* World to screen coordinate conversion
|
||||
*/
|
||||
worldToScreen(worldX: number, worldY: number): { x: number; y: number };
|
||||
/** 检查纹理是否就绪 | Check if texture is ready */
|
||||
isTextureReady(id: number): boolean;
|
||||
|
||||
/**
|
||||
* 设置清除颜色
|
||||
* Set clear color
|
||||
*/
|
||||
setClearColor(r: number, g: number, b: number, a: number): void;
|
||||
/** 获取正在加载的纹理数量 | Get loading texture count */
|
||||
getTextureLoadingCount(): number;
|
||||
|
||||
// ===== Texture State API (Optional) =====
|
||||
// ===== 纹理状态 API(可选)=====
|
||||
/** 异步加载纹理(等待完成)| Load texture async (wait for completion) */
|
||||
loadTextureAsync(id: number, url: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* 获取纹理加载状态
|
||||
* Get texture loading state
|
||||
*
|
||||
* @param id 纹理 ID | Texture ID
|
||||
* @returns 状态字符串: 'loading', 'ready', 或 'failed:reason'
|
||||
* State string: 'loading', 'ready', or 'failed:reason'
|
||||
*/
|
||||
getTextureState?(id: number): string;
|
||||
/** 等待所有加载中的纹理完成 | Wait for all textures to load */
|
||||
waitForAllTextures(timeout?: number): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查纹理是否就绪
|
||||
* Check if texture is ready for rendering
|
||||
*
|
||||
* @param id 纹理 ID | Texture ID
|
||||
* @returns 纹理数据已加载则返回 true | true if texture data is loaded
|
||||
*/
|
||||
isTextureReady?(id: number): boolean;
|
||||
/**
|
||||
* 动态图集服务接口
|
||||
* Dynamic atlas service interface
|
||||
*/
|
||||
export interface IDynamicAtlasService {
|
||||
/** 创建空白纹理 | Create blank texture */
|
||||
createBlankTexture(width: number, height: number): number;
|
||||
|
||||
/**
|
||||
* 获取正在加载的纹理数量
|
||||
* Get count of textures currently loading
|
||||
*
|
||||
* @returns 处于加载状态的纹理数量 | Number of textures in loading state
|
||||
*/
|
||||
getTextureLoadingCount?(): number;
|
||||
|
||||
/**
|
||||
* 异步加载纹理(等待完成)
|
||||
* Load texture asynchronously (wait for completion)
|
||||
*
|
||||
* 与 loadTexture 不同,此方法会等待纹理实际加载完成。
|
||||
* Unlike loadTexture, this method waits until texture is actually loaded.
|
||||
*
|
||||
* @param id 纹理 ID | Texture ID
|
||||
* @param url 图片 URL | Image URL
|
||||
* @returns 纹理就绪时解析的 Promise | Promise that resolves when texture is ready
|
||||
*/
|
||||
loadTextureAsync?(id: number, url: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* 等待所有加载中的纹理完成
|
||||
* Wait for all loading textures to complete
|
||||
*
|
||||
* @param timeout 最大等待时间(毫秒,默认30000)| Max wait time in ms (default 30000)
|
||||
* @returns 所有纹理加载完成时解析 | Resolves when all textures are loaded
|
||||
*/
|
||||
waitForAllTextures?(timeout?: number): Promise<void>;
|
||||
|
||||
// ===== Dynamic Atlas API (Optional) =====
|
||||
// ===== 动态图集 API(可选)=====
|
||||
|
||||
/**
|
||||
* 创建空白纹理(用于动态图集)
|
||||
* Create blank texture (for dynamic atlas)
|
||||
*
|
||||
* @param width 宽度 | Width
|
||||
* @param height 高度 | Height
|
||||
* @returns 纹理 ID | Texture ID
|
||||
*/
|
||||
createBlankTexture?(width: number, height: number): number;
|
||||
|
||||
/**
|
||||
* 更新纹理区域
|
||||
* Update texture region
|
||||
*
|
||||
* @param id 纹理 ID | Texture ID
|
||||
* @param x X 坐标 | X coordinate
|
||||
* @param y Y 坐标 | Y coordinate
|
||||
* @param width 宽度 | Width
|
||||
* @param height 高度 | Height
|
||||
* @param pixels RGBA 像素数据 | RGBA pixel data
|
||||
*/
|
||||
updateTextureRegion?(
|
||||
/** 更新纹理区域 | Update texture region */
|
||||
updateTextureRegion(
|
||||
id: number,
|
||||
x: number,
|
||||
y: number,
|
||||
@@ -153,7 +84,38 @@ export interface IEngineBridge {
|
||||
}
|
||||
|
||||
/**
|
||||
* 引擎桥接服务令牌
|
||||
* Engine bridge service token
|
||||
* 坐标转换服务接口
|
||||
* Coordinate transform service interface
|
||||
*/
|
||||
export const EngineBridgeToken = createServiceToken<IEngineBridge>('engineBridge');
|
||||
export interface ICoordinateService {
|
||||
/** 屏幕坐标转世界坐标 | Screen to world */
|
||||
screenToWorld(screenX: number, screenY: number): { x: number; y: number };
|
||||
|
||||
/** 世界坐标转屏幕坐标 | World to screen */
|
||||
worldToScreen(worldX: number, worldY: number): { x: number; y: number };
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染配置服务接口
|
||||
* Render config service interface
|
||||
*/
|
||||
export interface IRenderConfigService {
|
||||
/** 设置清除颜色 | Set clear color */
|
||||
setClearColor(r: number, g: number, b: number, a: number): void;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 服务令牌 | Service Tokens
|
||||
// ============================================================================
|
||||
|
||||
/** 纹理服务令牌 | Texture service token */
|
||||
export const TextureServiceToken = createServiceToken<ITextureService>('textureService');
|
||||
|
||||
/** 动态图集服务令牌 | Dynamic atlas service token */
|
||||
export const DynamicAtlasServiceToken = createServiceToken<IDynamicAtlasService>('dynamicAtlasService');
|
||||
|
||||
/** 坐标转换服务令牌 | Coordinate service token */
|
||||
export const CoordinateServiceToken = createServiceToken<ICoordinateService>('coordinateService');
|
||||
|
||||
/** 渲染配置服务令牌 | Render config service token */
|
||||
export const RenderConfigServiceToken = createServiceToken<IRenderConfigService>('renderConfigService');
|
||||
|
||||
@@ -13,10 +13,16 @@ export {
|
||||
// Engine-specific service tokens
|
||||
TransformTypeToken,
|
||||
CanvasElementToken,
|
||||
EngineBridgeToken,
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken,
|
||||
// Types
|
||||
type IEditorModuleBase,
|
||||
type IEngineBridge
|
||||
type ITextureService,
|
||||
type IDynamicAtlasService,
|
||||
type ICoordinateService,
|
||||
type IRenderConfigService
|
||||
} from './EnginePlugin';
|
||||
|
||||
// Module Manifest types (unified module/plugin configuration)
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
InspectorRegistry,
|
||||
EntityStoreService,
|
||||
MessageHub,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
FileActionRegistry
|
||||
} from '@esengine/editor-core';
|
||||
import { TransformComponent } from '@esengine/engine-core';
|
||||
@@ -56,7 +56,7 @@ export class ParticleEditorModule implements IEditorModuleLoader {
|
||||
}
|
||||
|
||||
// 注册组件到编辑器组件注册表 | Register to editor component registry
|
||||
const componentRegistry = services.resolve(ComponentRegistry);
|
||||
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||
if (componentRegistry) {
|
||||
componentRegistry.register({
|
||||
name: 'ParticleSystem',
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { IComponentRegistry, IScene } from '@esengine/ecs-framework';
|
||||
import type { IRuntimeModule, IRuntimePlugin, ModuleManifest, SystemContext } from '@esengine/engine-core';
|
||||
import { TransformTypeToken, CanvasElementToken } from '@esengine/engine-core';
|
||||
import { AssetManagerToken } from '@esengine/asset-system';
|
||||
import { RenderSystemToken, EngineBridgeToken, EngineIntegrationToken } from '@esengine/ecs-engine-bindgen';
|
||||
import { RenderSystemToken, EngineIntegrationToken, TextureServiceToken, CoordinateServiceToken } from '@esengine/ecs-engine-bindgen';
|
||||
import { Physics2DQueryToken } from '@esengine/physics-rapier2d';
|
||||
import { ParticleSystemComponent } from './ParticleSystemComponent';
|
||||
import { ClickFxComponent } from './ClickFxComponent';
|
||||
@@ -30,7 +30,8 @@ class ParticleRuntimeModule implements IRuntimeModule {
|
||||
const assetManager = context.services.get(AssetManagerToken);
|
||||
const transformType = context.services.get(TransformTypeToken);
|
||||
const engineIntegration = context.services.get(EngineIntegrationToken);
|
||||
const engineBridge = context.services.get(EngineBridgeToken);
|
||||
const textureService = context.services.get(TextureServiceToken);
|
||||
const coordinateService = context.services.get(CoordinateServiceToken);
|
||||
const physics2DQuery = context.services.get(Physics2DQueryToken);
|
||||
const renderSystem = context.services.get(RenderSystemToken);
|
||||
|
||||
@@ -60,9 +61,9 @@ class ParticleRuntimeModule implements IRuntimeModule {
|
||||
this._updateSystem.setEngineIntegration(engineIntegration);
|
||||
}
|
||||
|
||||
// 设置引擎桥接(用于加载默认纹理)| Set engine bridge (for loading default texture)
|
||||
if (engineBridge) {
|
||||
this._updateSystem.setEngineBridge(engineBridge);
|
||||
// 设置纹理服务(用于加载默认纹理)| Set texture service (for loading default texture)
|
||||
if (textureService) {
|
||||
this._updateSystem.setTextureService(textureService);
|
||||
}
|
||||
|
||||
// 设置 2D 物理查询(用于粒子与场景碰撞)| Set 2D physics query (for particle-scene collision)
|
||||
@@ -77,10 +78,10 @@ class ParticleRuntimeModule implements IRuntimeModule {
|
||||
// ClickFxSystem no longer needs AssetManager, assets are loaded by ParticleUpdateSystem
|
||||
const clickFxSystem = new ClickFxSystem();
|
||||
|
||||
// 设置 EngineBridge(用于屏幕坐标转世界坐标)
|
||||
// Set EngineBridge (for screen to world coordinate conversion)
|
||||
if (engineBridge) {
|
||||
clickFxSystem.setEngineBridge(engineBridge);
|
||||
// 设置坐标服务(用于屏幕坐标转世界坐标)
|
||||
// Set coordinate service (for screen to world coordinate conversion)
|
||||
if (coordinateService) {
|
||||
clickFxSystem.setCoordinateService(coordinateService);
|
||||
}
|
||||
|
||||
// 从服务注册表获取 Canvas 元素(用于计算相对坐标)
|
||||
|
||||
@@ -11,23 +11,11 @@ import { Input, MouseButton, TransformComponent, SortingLayers } from '@esengine
|
||||
import { ClickFxComponent, ClickFxTriggerMode } from '../ClickFxComponent';
|
||||
import { ParticleSystemComponent, RenderSpace } from '../ParticleSystemComponent';
|
||||
|
||||
import { CoordinateServiceToken, type ICoordinateService } from '@esengine/ecs-engine-bindgen';
|
||||
|
||||
// ============================================================================
|
||||
// 本地服务令牌定义 | Local Service Token Definitions
|
||||
// ============================================================================
|
||||
// 使用 createServiceToken() 本地定义(与 runtime-core 相同策略)
|
||||
// createServiceToken() 使用 Symbol.for(),确保运行时与源模块令牌匹配
|
||||
//
|
||||
// Local token definitions using createServiceToken() (same strategy as runtime-core)
|
||||
// createServiceToken() uses Symbol.for(), ensuring runtime match with source module tokens
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* EngineBridge 接口(最小定义,用于坐标转换)
|
||||
* EngineBridge interface (minimal definition for coordinate conversion)
|
||||
*/
|
||||
interface IEngineBridge {
|
||||
screenToWorld(screenX: number, screenY: number): { x: number; y: number };
|
||||
}
|
||||
|
||||
/**
|
||||
* EngineRenderSystem 接口(最小定义,用于获取 UI Canvas 尺寸)
|
||||
@@ -37,10 +25,6 @@ interface IEngineRenderSystem {
|
||||
getUICanvasSize(): { width: number; height: number };
|
||||
}
|
||||
|
||||
// EngineBridge 令牌(与 engine-core 中的一致)
|
||||
// EngineBridge token (consistent with engine-core)
|
||||
const EngineBridgeToken = createServiceToken<IEngineBridge>('engineBridge');
|
||||
|
||||
// RenderSystem 令牌(与 ecs-engine-bindgen 中的一致)
|
||||
// RenderSystem token (consistent with ecs-engine-bindgen)
|
||||
const RenderSystemToken = createServiceToken<IEngineRenderSystem>('renderSystem');
|
||||
@@ -62,7 +46,7 @@ const RenderSystemToken = createServiceToken<IEngineRenderSystem>('renderSystem'
|
||||
*/
|
||||
@ECSSystem('ClickFx', { updateOrder: 100 })
|
||||
export class ClickFxSystem extends EntitySystem {
|
||||
private _engineBridge: IEngineBridge | null = null;
|
||||
private _coordinateService: ICoordinateService | null = null;
|
||||
private _renderSystem: IEngineRenderSystem | null = null;
|
||||
private _entitiesToDestroy: Entity[] = [];
|
||||
private _canvas: HTMLCanvasElement | null = null;
|
||||
@@ -72,20 +56,20 @@ export class ClickFxSystem extends EntitySystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置服务注册表(用于获取 EngineBridge 和 RenderSystem)
|
||||
* Set service registry (for getting EngineBridge and RenderSystem)
|
||||
* 设置服务注册表(用于获取 CoordinateService 和 RenderSystem)
|
||||
* Set service registry (for getting CoordinateService and RenderSystem)
|
||||
*/
|
||||
setServiceRegistry(services: PluginServiceRegistry): void {
|
||||
this._engineBridge = services.get(EngineBridgeToken) ?? null;
|
||||
this._coordinateService = services.get(CoordinateServiceToken) ?? null;
|
||||
this._renderSystem = services.get(RenderSystemToken) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 EngineBridge(直接注入)
|
||||
* Set EngineBridge (direct injection)
|
||||
* 设置坐标服务(直接注入)
|
||||
* Set coordinate service (direct injection)
|
||||
*/
|
||||
setEngineBridge(bridge: IEngineBridge): void {
|
||||
this._engineBridge = bridge;
|
||||
setCoordinateService(coordinateService: ICoordinateService): void {
|
||||
this._coordinateService = coordinateService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { EntitySystem, Matcher, ECSSystem, Time, Entity, type Component, type ComponentType } from '@esengine/ecs-framework';
|
||||
import type { IEngineIntegration, IEngineBridge } from '@esengine/ecs-engine-bindgen';
|
||||
import type { IEngineIntegration, ITextureService } from '@esengine/ecs-engine-bindgen';
|
||||
import type { IAssetManager } from '@esengine/asset-system';
|
||||
import { ParticleSystemComponent } from '../ParticleSystemComponent';
|
||||
import { ParticleRenderDataProvider } from '../rendering/ParticleRenderDataProvider';
|
||||
@@ -78,7 +78,7 @@ export class ParticleUpdateSystem extends EntitySystem {
|
||||
private _transformType: ComponentType<Component & ITransformComponent> | null = null;
|
||||
private _renderDataProvider: ParticleRenderDataProvider;
|
||||
private _engineIntegration: IEngineIntegration | null = null;
|
||||
private _engineBridge: IEngineBridge | null = null;
|
||||
private _textureService: ITextureService | null = null;
|
||||
private _physics2DQuery: IPhysics2DQuery | null = null;
|
||||
private _assetManager: IAssetManager | null = null;
|
||||
private _defaultTextureLoaded: boolean = false;
|
||||
@@ -114,11 +114,11 @@ export class ParticleUpdateSystem extends EntitySystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置引擎桥接(用于加载默认纹理)
|
||||
* Set engine bridge (for loading default texture)
|
||||
* 设置纹理服务(用于加载默认纹理)
|
||||
* Set texture service (for loading default texture)
|
||||
*/
|
||||
setEngineBridge(bridge: IEngineBridge): void {
|
||||
this._engineBridge = bridge;
|
||||
setTextureService(textureService: ITextureService): void {
|
||||
this._textureService = textureService;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -487,8 +487,8 @@ export class ParticleUpdateSystem extends EntitySystem {
|
||||
}
|
||||
|
||||
// 没有引擎桥接,无法加载 | No engine bridge, cannot load
|
||||
if (!this._engineBridge) {
|
||||
console.warn('[ParticleUpdateSystem] EngineBridge not set, cannot load default texture');
|
||||
if (!this._textureService) {
|
||||
console.warn('[ParticleUpdateSystem] TextureService not set, cannot load default texture');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -496,15 +496,9 @@ export class ParticleUpdateSystem extends EntitySystem {
|
||||
try {
|
||||
const dataUrl = generateDefaultParticleTextureDataURL();
|
||||
if (dataUrl) {
|
||||
// 优先使用 loadTextureAsync(等待纹理就绪)
|
||||
// Prefer loadTextureAsync (waits for texture ready)
|
||||
if (this._engineBridge.loadTextureAsync) {
|
||||
await this._engineBridge.loadTextureAsync(DEFAULT_PARTICLE_TEXTURE_ID, dataUrl);
|
||||
} else {
|
||||
// 回退到旧 API(可能显示灰色占位符)
|
||||
// Fallback to old API (may show gray placeholder)
|
||||
await this._engineBridge.loadTexture(DEFAULT_PARTICLE_TEXTURE_ID, dataUrl);
|
||||
}
|
||||
// 使用 loadTextureAsync(等待纹理就绪)
|
||||
// Use loadTextureAsync (waits for texture ready)
|
||||
await this._textureService.loadTextureAsync(DEFAULT_PARTICLE_TEXTURE_ID, dataUrl);
|
||||
this._defaultTextureLoaded = true;
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
import {
|
||||
EntityStoreService,
|
||||
MessageHub,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
SettingsRegistry
|
||||
} from '@esengine/editor-core';
|
||||
import { TransformComponent } from '@esengine/engine-core';
|
||||
@@ -48,7 +48,7 @@ export class Physics2DEditorModule implements IEditorModuleLoader {
|
||||
this.setupSettingsListener();
|
||||
|
||||
// 注册组件到编辑器组件注册表
|
||||
const componentRegistry = services.resolve(ComponentRegistry);
|
||||
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||
if (componentRegistry) {
|
||||
componentRegistry.register({
|
||||
name: 'Rigidbody2D',
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
BrowserFileSystemService,
|
||||
RuntimeSceneManager,
|
||||
RuntimeSceneManagerToken,
|
||||
type IPlugin,
|
||||
type IRuntimePlugin,
|
||||
type IRuntimeSceneManager
|
||||
} from '@esengine/runtime-core';
|
||||
import { isValidGUID, setGlobalAssetFileLoader, type IAssetManager, type IAssetFileLoader } from '@esengine/asset-system';
|
||||
@@ -75,7 +75,7 @@ export class BrowserRuntime {
|
||||
*
|
||||
* Call this before initialize() to register plugins.
|
||||
*/
|
||||
registerPlugin(plugin: IPlugin): void {
|
||||
registerPlugin(plugin: IRuntimePlugin): void {
|
||||
if (plugin) {
|
||||
runtimePluginManager.register(plugin);
|
||||
runtimePluginManager.enable(plugin.manifest.id);
|
||||
@@ -87,7 +87,7 @@ export class BrowserRuntime {
|
||||
* Register multiple plugins
|
||||
* 注册多个插件
|
||||
*/
|
||||
registerPlugins(plugins: IPlugin[]): void {
|
||||
registerPlugins(plugins: IRuntimePlugin[]): void {
|
||||
for (const plugin of plugins) {
|
||||
this.registerPlugin(plugin);
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"name": "@esengine/plugin-types",
|
||||
"version": "1.0.0",
|
||||
"description": "Plugin system type definitions for ES Engine",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"build:watch": "tsup --watch",
|
||||
"clean": "rimraf dist",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"keywords": [
|
||||
"ecs",
|
||||
"plugin",
|
||||
"types",
|
||||
"typescript"
|
||||
],
|
||||
"author": "yhh",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@esengine/ecs-framework": "workspace:*",
|
||||
"@esengine/build-config": "workspace:*",
|
||||
"rimraf": "^5.0.0",
|
||||
"tsup": "^8.0.0",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/esengine/esengine.git",
|
||||
"directory": "packages/plugin-types"
|
||||
}
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
/**
|
||||
* 插件系统基础类型定义
|
||||
* Plugin system base type definitions
|
||||
*
|
||||
* 这个包只提供用于打破循环依赖的基础接口。
|
||||
* 完整的类型定义在 engine-core 中。
|
||||
*
|
||||
* This package only provides base interfaces to break circular dependencies.
|
||||
* Complete type definitions are in engine-core.
|
||||
*
|
||||
* 导出内容 | Exports:
|
||||
* - ServiceToken / createServiceToken / PluginServiceRegistry: 服务令牌系统
|
||||
* - IEditorModuleBase: 编辑器模块基础接口(用于 IPlugin.editorModule 类型)
|
||||
*
|
||||
* 不导出(在 engine-core 中定义)| Not exported (defined in engine-core):
|
||||
* - IPlugin, IRuntimeModule, SystemContext: 完整的插件类型
|
||||
* - ModuleManifest: 完整的模块清单类型
|
||||
* - LoadingPhase: 加载阶段类型
|
||||
*/
|
||||
|
||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||
|
||||
// ============================================================================
|
||||
// 服务令牌 | Service Token
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 服务令牌接口
|
||||
* Service token interface
|
||||
*
|
||||
* 用于类型安全的服务注册和获取。
|
||||
* For type-safe service registration and retrieval.
|
||||
*
|
||||
* 注意:__phantom 是必需属性(使用 declare 避免运行时开销),
|
||||
* 这确保 TypeScript 在跨包类型解析时保留泛型类型信息。
|
||||
*
|
||||
* Note: __phantom is a required property (using declare to avoid runtime overhead),
|
||||
* which ensures TypeScript preserves generic type information across packages.
|
||||
*/
|
||||
export interface ServiceToken<T> {
|
||||
readonly id: symbol;
|
||||
readonly name: string;
|
||||
/**
|
||||
* Phantom type 标记(强制类型推断)
|
||||
* Phantom type marker (enforces type inference)
|
||||
*
|
||||
* 使用 declare 声明,不会在运行时占用内存。
|
||||
* Declared with 'declare', no runtime memory overhead.
|
||||
*/
|
||||
readonly __phantom: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建服务令牌
|
||||
* Create a service token
|
||||
*
|
||||
* @param name 令牌名称 | Token name
|
||||
* @returns 服务令牌 | Service token
|
||||
*/
|
||||
export function createServiceToken<T>(name: string): ServiceToken<T> {
|
||||
// __phantom 仅用于类型推断,不需要实际值
|
||||
// __phantom is only for type inference, no actual value needed
|
||||
return {
|
||||
id: Symbol(name),
|
||||
name
|
||||
} as ServiceToken<T>;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 插件服务注册表 | Plugin Service Registry
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 插件服务注册表
|
||||
* Plugin service registry
|
||||
*
|
||||
* 用于跨插件共享服务的类型安全注册表。
|
||||
* Type-safe registry for sharing services between plugins.
|
||||
*/
|
||||
export class PluginServiceRegistry {
|
||||
private _services = new Map<symbol, unknown>();
|
||||
|
||||
/**
|
||||
* 注册服务
|
||||
* Register a service
|
||||
*/
|
||||
register<T>(token: ServiceToken<T>, service: T): void {
|
||||
this._services.set(token.id, service);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务(可选)
|
||||
* Get a service (optional)
|
||||
*/
|
||||
get<T>(token: ServiceToken<T>): T | undefined {
|
||||
return this._services.get(token.id) as T | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务(必需)
|
||||
* Get a service (required)
|
||||
*
|
||||
* @throws 如果服务未注册 | If service is not registered
|
||||
*/
|
||||
require<T>(token: ServiceToken<T>): T {
|
||||
const service = this._services.get(token.id);
|
||||
if (service === undefined) {
|
||||
throw new Error(`Service not found: ${token.name}`);
|
||||
}
|
||||
return service as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查服务是否已注册
|
||||
* Check if a service is registered
|
||||
*/
|
||||
has<T>(token: ServiceToken<T>): boolean {
|
||||
return this._services.has(token.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销服务
|
||||
* Unregister a service
|
||||
*/
|
||||
unregister<T>(token: ServiceToken<T>): boolean {
|
||||
return this._services.delete(token.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有服务
|
||||
* Clear all services
|
||||
*/
|
||||
clear(): void {
|
||||
this._services.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 编辑器模块基础接口 | Editor Module Base Interface
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* 编辑器模块基础接口
|
||||
* Base editor module interface
|
||||
*
|
||||
* 定义编辑器模块的核心生命周期方法。
|
||||
* 这个接口用于 IPlugin.editorModule 的类型定义,避免 engine-core 依赖 editor-core。
|
||||
* 完整的 IEditorModuleLoader 接口在 editor-core 中扩展此接口。
|
||||
*
|
||||
* Defines core lifecycle methods for editor modules.
|
||||
* This interface is used for IPlugin.editorModule type to avoid engine-core depending on editor-core.
|
||||
* Full IEditorModuleLoader interface extends this in editor-core.
|
||||
*/
|
||||
export interface IEditorModuleBase {
|
||||
/**
|
||||
* 安装编辑器模块
|
||||
* Install editor module
|
||||
*/
|
||||
install(services: ServiceContainer): Promise<void>;
|
||||
|
||||
/**
|
||||
* 卸载编辑器模块
|
||||
* Uninstall editor module
|
||||
*/
|
||||
uninstall?(): Promise<void>;
|
||||
|
||||
/**
|
||||
* 编辑器就绪回调
|
||||
* Editor ready callback
|
||||
*/
|
||||
onEditorReady?(): void | Promise<void>;
|
||||
|
||||
/**
|
||||
* 项目打开回调
|
||||
* Project open callback
|
||||
*/
|
||||
onProjectOpen?(projectPath: string): void | Promise<void>;
|
||||
|
||||
/**
|
||||
* 项目关闭回调
|
||||
* Project close callback
|
||||
*/
|
||||
onProjectClose?(): void | Promise<void>;
|
||||
|
||||
/**
|
||||
* 场景加载回调
|
||||
* Scene loaded callback
|
||||
*/
|
||||
onSceneLoaded?(scenePath: string): void;
|
||||
|
||||
/**
|
||||
* 场景保存前回调
|
||||
* Before scene save callback
|
||||
*/
|
||||
onSceneSaving?(scenePath: string): boolean | void;
|
||||
|
||||
/**
|
||||
* 设置语言
|
||||
* Set locale
|
||||
*/
|
||||
setLocale?(locale: string): void;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"lib": ["ES2020", "DOM"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['esm'],
|
||||
dts: true,
|
||||
splitting: false,
|
||||
sourcemap: true,
|
||||
clean: true,
|
||||
tsconfig: 'tsconfig.build.json',
|
||||
external: [
|
||||
'@esengine/ecs-framework'
|
||||
]
|
||||
});
|
||||
@@ -10,9 +10,12 @@ import { Core, Scene, SceneSerializer, HierarchySystem, PluginServiceRegistry, c
|
||||
import {
|
||||
EngineBridge,
|
||||
EngineRenderSystem,
|
||||
EngineBridgeToken,
|
||||
RenderSystemToken,
|
||||
EngineIntegrationToken,
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken,
|
||||
type IUIRenderDataProvider
|
||||
} from '@esengine/ecs-engine-bindgen';
|
||||
import {
|
||||
@@ -360,7 +363,11 @@ export class GameRuntime {
|
||||
const services = new PluginServiceRegistry();
|
||||
|
||||
// 注册核心服务 | Register core services
|
||||
services.register(EngineBridgeToken, this._bridge);
|
||||
// 使用单一职责接口注册 EngineBridge | Register EngineBridge with single-responsibility interfaces
|
||||
services.register(TextureServiceToken, this._bridge);
|
||||
services.register(DynamicAtlasServiceToken, this._bridge);
|
||||
services.register(CoordinateServiceToken, this._bridge);
|
||||
services.register(RenderConfigServiceToken, this._bridge);
|
||||
services.register(RenderSystemToken, this._renderSystem);
|
||||
services.register(EngineIntegrationToken, this._engineIntegration);
|
||||
services.register(AssetManagerToken, this._assetManager);
|
||||
|
||||
@@ -7,9 +7,6 @@ export {
|
||||
type IRuntimePlugin
|
||||
} from './PluginManager';
|
||||
|
||||
/** @deprecated Use IRuntimePlugin instead */
|
||||
export type { IRuntimePlugin as IPlugin } from './PluginManager';
|
||||
|
||||
export {
|
||||
createPlugin,
|
||||
registerPlugin,
|
||||
@@ -123,13 +120,21 @@ export { TransformTypeToken } from '@esengine/engine-core';
|
||||
|
||||
// Re-export service tokens from their respective modules
|
||||
export {
|
||||
EngineBridgeToken,
|
||||
RenderSystemToken,
|
||||
EngineIntegrationToken,
|
||||
type IEngineBridge,
|
||||
// 新的单一职责服务令牌 | New single-responsibility service tokens
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
CoordinateServiceToken,
|
||||
RenderConfigServiceToken,
|
||||
// 类型 | Types
|
||||
type IRenderSystem,
|
||||
type IRenderDataProvider,
|
||||
type IEngineIntegration
|
||||
type IEngineIntegration,
|
||||
type ITextureService,
|
||||
type IDynamicAtlasService,
|
||||
type ICoordinateService,
|
||||
type IRenderConfigService
|
||||
} from '@esengine/ecs-engine-bindgen';
|
||||
|
||||
export {
|
||||
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
import {
|
||||
EntityStoreService,
|
||||
MessageHub,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
ComponentInspectorRegistry
|
||||
} from '@esengine/editor-core';
|
||||
import { TransformComponent } from '@esengine/engine-core';
|
||||
@@ -47,7 +47,7 @@ export class SpriteEditorModule implements IEditorModuleLoader {
|
||||
}
|
||||
|
||||
// 注册 Sprite 组件到编辑器组件注册表 | Register Sprite components to editor component registry
|
||||
const componentRegistry = services.resolve(ComponentRegistry);
|
||||
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||
if (componentRegistry) {
|
||||
const spriteComponents = [
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
InspectorRegistry,
|
||||
EntityStoreService,
|
||||
MessageHub,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
IDialogService,
|
||||
IFileSystemService,
|
||||
FileActionRegistry
|
||||
@@ -72,7 +72,7 @@ export class TilemapEditorModule implements IEditorModuleLoader {
|
||||
}
|
||||
|
||||
// 注册组件到编辑器组件注册表 | Register to editor component registry
|
||||
const componentRegistry = services.resolve(ComponentRegistry);
|
||||
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||
if (componentRegistry) {
|
||||
componentRegistry.register({
|
||||
name: 'Tilemap',
|
||||
|
||||
@@ -14,7 +14,7 @@ import type {
|
||||
import {
|
||||
EntityStoreService,
|
||||
MessageHub,
|
||||
ComponentRegistry,
|
||||
EditorComponentRegistry,
|
||||
ComponentInspectorRegistry
|
||||
} from '@esengine/editor-core';
|
||||
|
||||
@@ -47,7 +47,7 @@ export { registerUITransformGizmo, unregisterUITransformGizmo } from './gizmos';
|
||||
export class UIEditorModule implements IEditorModuleLoader {
|
||||
async install(services: ServiceContainer): Promise<void> {
|
||||
// 注册 UI 组件到编辑器组件注册表 | Register UI components to editor component registry
|
||||
const componentRegistry = services.resolve(ComponentRegistry);
|
||||
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||
if (componentRegistry) {
|
||||
const uiComponents = [
|
||||
{ name: 'UITransform', type: UITransformComponent, category: 'components.category.ui', description: 'UI element positioning and sizing', icon: 'Move' },
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import type { IScene, IComponentRegistry } from '@esengine/ecs-framework';
|
||||
import type { IRuntimeModule, IRuntimePlugin, ModuleManifest, SystemContext } from '@esengine/engine-core';
|
||||
import { EngineBridgeToken } from '@esengine/ecs-engine-bindgen';
|
||||
import {
|
||||
TextureServiceToken,
|
||||
DynamicAtlasServiceToken,
|
||||
type ITextureService,
|
||||
type IDynamicAtlasService
|
||||
} from '@esengine/ecs-engine-bindgen';
|
||||
import { EngineIntegration } from '@esengine/asset-system';
|
||||
|
||||
import { initializeDynamicAtlasService, registerTexturePathMapping, AtlasExpansionStrategy, type IAtlasEngineBridge } from './atlas';
|
||||
@@ -77,7 +82,8 @@ class UIRuntimeModule implements IRuntimeModule {
|
||||
|
||||
createSystems(scene: IScene, context: SystemContext): void {
|
||||
// 从服务注册表获取依赖 | Get dependencies from service registry
|
||||
const engineBridge = context.services.get(EngineBridgeToken);
|
||||
const textureService = context.services.get(TextureServiceToken);
|
||||
const dynamicAtlasService = context.services.get(DynamicAtlasServiceToken);
|
||||
|
||||
// Slider fill control system (runs before layout to modify anchors)
|
||||
// 滑块填充控制系统(在布局之前运行以修改锚点)
|
||||
@@ -133,34 +139,30 @@ class UIRuntimeModule implements IRuntimeModule {
|
||||
const textRenderSystem = new UITextRenderSystem();
|
||||
scene.addSystem(textRenderSystem);
|
||||
|
||||
if (engineBridge) {
|
||||
if (textureService) {
|
||||
// 设置文本渲染系统的纹理回调
|
||||
// Set texture callback for text render system
|
||||
textRenderSystem.setTextureCallback((id: number, dataUrl: string) => {
|
||||
engineBridge.loadTexture(id, dataUrl);
|
||||
textureService.loadTexture(id, dataUrl);
|
||||
});
|
||||
|
||||
// 设置纹理就绪检查回调,用于检测异步加载的纹理是否已就绪
|
||||
// Set texture ready checker callback to detect if async-loaded texture is ready
|
||||
if (engineBridge.isTextureReady) {
|
||||
textRenderSystem.setTextureReadyChecker((id: number) => {
|
||||
return engineBridge.isTextureReady!(id);
|
||||
});
|
||||
}
|
||||
textRenderSystem.setTextureReadyChecker((id: number) => {
|
||||
return textureService.isTextureReady(id);
|
||||
});
|
||||
|
||||
// 设置输入框渲染系统的纹理回调
|
||||
// Set texture callback for input field render system
|
||||
inputFieldRenderSystem.setTextureCallback((id: number, dataUrl: string) => {
|
||||
engineBridge.loadTexture(id, dataUrl);
|
||||
textureService.loadTexture(id, dataUrl);
|
||||
});
|
||||
|
||||
// 设置输入框渲染系统的纹理就绪检查回调
|
||||
// Set texture ready checker callback for input field render system
|
||||
if (engineBridge.isTextureReady) {
|
||||
inputFieldRenderSystem.setTextureReadyChecker((id: number) => {
|
||||
return engineBridge.isTextureReady!(id);
|
||||
});
|
||||
}
|
||||
inputFieldRenderSystem.setTextureReadyChecker((id: number) => {
|
||||
return textureService.isTextureReady(id);
|
||||
});
|
||||
}
|
||||
|
||||
const uiRenderProvider = new UIRenderDataProvider();
|
||||
@@ -175,17 +177,15 @@ class UIRuntimeModule implements IRuntimeModule {
|
||||
context.services.register(UITextRenderSystemToken, textRenderSystem);
|
||||
|
||||
// 初始化动态图集服务 | Initialize dynamic atlas service
|
||||
// 需要 engineBridge 支持 createBlankTexture 和 updateTextureRegion
|
||||
// Requires engineBridge to support createBlankTexture and updateTextureRegion
|
||||
console.log('[UIRuntimeModule] engineBridge available:', !!engineBridge);
|
||||
console.log('[UIRuntimeModule] createBlankTexture:', !!engineBridge?.createBlankTexture);
|
||||
console.log('[UIRuntimeModule] updateTextureRegion:', !!engineBridge?.updateTextureRegion);
|
||||
if (engineBridge?.createBlankTexture && engineBridge?.updateTextureRegion) {
|
||||
// 创建适配器将 EngineBridge 适配为 IAtlasEngineBridge
|
||||
// Create adapter to adapt EngineBridge to IAtlasEngineBridge
|
||||
// 需要 dynamicAtlasService 支持 createBlankTexture 和 updateTextureRegion
|
||||
// Requires dynamicAtlasService to support createBlankTexture and updateTextureRegion
|
||||
console.log('[UIRuntimeModule] dynamicAtlasService available:', !!dynamicAtlasService);
|
||||
if (dynamicAtlasService) {
|
||||
// 创建适配器将 IDynamicAtlasService 适配为 IAtlasEngineBridge
|
||||
// Create adapter to adapt IDynamicAtlasService to IAtlasEngineBridge
|
||||
const atlasBridge: IAtlasEngineBridge = {
|
||||
createBlankTexture: (width: number, height: number) => {
|
||||
return engineBridge.createBlankTexture!(width, height);
|
||||
return dynamicAtlasService.createBlankTexture(width, height);
|
||||
},
|
||||
updateTextureRegion: (
|
||||
id: number,
|
||||
@@ -195,7 +195,7 @@ class UIRuntimeModule implements IRuntimeModule {
|
||||
height: number,
|
||||
pixels: Uint8Array
|
||||
) => {
|
||||
engineBridge.updateTextureRegion!(id, x, y, width, height, pixels);
|
||||
dynamicAtlasService.updateTextureRegion(id, x, y, width, height, pixels);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -218,7 +218,7 @@ class UIRuntimeModule implements IRuntimeModule {
|
||||
registerTexturePathMapping(guid, path);
|
||||
});
|
||||
} else {
|
||||
console.warn('[UIRuntimeModule] Cannot initialize dynamic atlas service: engineBridge missing createBlankTexture or updateTextureRegion');
|
||||
console.warn('[UIRuntimeModule] Cannot initialize dynamic atlas service: dynamicAtlasService not available');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
InspectorRegistry,
|
||||
EntityStoreService,
|
||||
MessageHub,
|
||||
ComponentRegistry
|
||||
EditorComponentRegistry
|
||||
} from '@esengine/editor-core';
|
||||
import { TransformComponent } from '@esengine/engine-core';
|
||||
import {
|
||||
@@ -47,7 +47,7 @@ export class WorldStreamingEditorModule implements IEditorModuleLoader {
|
||||
inspectorRegistry.register(new StreamingAnchorInspectorProvider());
|
||||
}
|
||||
|
||||
const componentRegistry = services.resolve(ComponentRegistry);
|
||||
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||
if (componentRegistry) {
|
||||
componentRegistry.register({
|
||||
name: 'ChunkLoader',
|
||||
|
||||
Reference in New Issue
Block a user