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 {
|
import {
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
ComponentRegistry
|
EditorComponentRegistry
|
||||||
} from '@esengine/editor-core';
|
} from '@esengine/editor-core';
|
||||||
import { CameraComponent } from '@esengine/camera';
|
import { CameraComponent } from '@esengine/camera';
|
||||||
|
|
||||||
export class CameraEditorModule implements IEditorModuleLoader {
|
export class CameraEditorModule implements IEditorModuleLoader {
|
||||||
async install(services: ServiceContainer): Promise<void> {
|
async install(services: ServiceContainer): Promise<void> {
|
||||||
const componentRegistry = services.resolve(ComponentRegistry);
|
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||||
if (componentRegistry) {
|
if (componentRegistry) {
|
||||||
componentRegistry.register({
|
componentRegistry.register({
|
||||||
name: 'Camera',
|
name: 'Camera',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { IComponentRegistry, IScene } from '@esengine/ecs-framework';
|
import type { IComponentRegistry, IScene } from '@esengine/ecs-framework';
|
||||||
import type { IRuntimeModule, IRuntimePlugin, ModuleManifest, SystemContext } from '@esengine/engine-core';
|
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 { CameraComponent } from './CameraComponent';
|
||||||
import { CameraSystem } from './CameraSystem';
|
import { CameraSystem } from './CameraSystem';
|
||||||
|
|
||||||
@@ -10,15 +10,15 @@ class CameraRuntimeModule implements IRuntimeModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createSystems(scene: IScene, context: SystemContext): void {
|
createSystems(scene: IScene, context: SystemContext): void {
|
||||||
// 从服务注册表获取 EngineBridge | Get EngineBridge from service registry
|
// 从服务注册表获取渲染配置服务 | Get render config service from registry
|
||||||
const bridge = context.services.get(EngineBridgeToken);
|
const renderConfig = context.services.get(RenderConfigServiceToken);
|
||||||
if (!bridge) {
|
if (!renderConfig) {
|
||||||
console.warn('[CameraPlugin] EngineBridge not found, CameraSystem will not be created');
|
console.warn('[CameraPlugin] RenderConfigService not found, CameraSystem will not be created');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建并添加 CameraSystem | Create and add CameraSystem
|
// 创建并添加 CameraSystem | Create and add CameraSystem
|
||||||
const cameraSystem = new CameraSystem(bridge);
|
const cameraSystem = new CameraSystem(renderConfig);
|
||||||
scene.addSystem(cameraSystem);
|
scene.addSystem(cameraSystem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,18 +4,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { EntitySystem, Matcher, Entity, ECSSystem } from '@esengine/ecs-framework';
|
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';
|
import { CameraComponent } from './CameraComponent';
|
||||||
|
|
||||||
@ECSSystem('Camera', { updateOrder: -100 })
|
@ECSSystem('Camera', { updateOrder: -100 })
|
||||||
export class CameraSystem extends EntitySystem {
|
export class CameraSystem extends EntitySystem {
|
||||||
private bridge: IEngineBridge;
|
private renderConfig: IRenderConfigService;
|
||||||
private lastAppliedCameraId: number | null = null;
|
private lastAppliedCameraId: number | null = null;
|
||||||
|
|
||||||
constructor(bridge: IEngineBridge) {
|
constructor(renderConfig: IRenderConfigService) {
|
||||||
// Match entities with CameraComponent
|
// Match entities with CameraComponent
|
||||||
super(Matcher.empty().all(CameraComponent));
|
super(Matcher.empty().all(CameraComponent));
|
||||||
this.bridge = bridge;
|
this.renderConfig = renderConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override onBegin(): void {
|
protected override onBegin(): void {
|
||||||
@@ -47,6 +47,6 @@ export class CameraSystem extends EntitySystem {
|
|||||||
const r = parseInt(bgColor.slice(1, 3), 16) / 255;
|
const r = parseInt(bgColor.slice(1, 3), 16) / 255;
|
||||||
const g = parseInt(bgColor.slice(3, 5), 16) / 255;
|
const g = parseInt(bgColor.slice(3, 5), 16) / 255;
|
||||||
const b = parseInt(bgColor.slice(5, 7), 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
|
* 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;
|
export type ComponentType<T extends Component = Component> = new (...args: any[]) => T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,6 +65,51 @@ export interface ComponentEditorOptions {
|
|||||||
icon?: string;
|
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 装饰器
|
* 检查组件是否使用了 @ECSComponent 装饰器
|
||||||
* Check if component has @ECSComponent decorator
|
* Check if component has @ECSComponent decorator
|
||||||
@@ -69,7 +118,8 @@ export interface ComponentEditorOptions {
|
|||||||
* @returns 是否有装饰器
|
* @returns 是否有装饰器
|
||||||
*/
|
*/
|
||||||
export function hasECSComponentDecorator(componentType: ComponentType): boolean {
|
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 {
|
export function getComponentTypeName(componentType: ComponentType): string {
|
||||||
// 优先使用装饰器指定的名称
|
// 优先使用装饰器指定的名称
|
||||||
// Prefer decorator-specified name
|
// Prefer decorator-specified name
|
||||||
const decoratorName = (componentType as any)[COMPONENT_TYPE_NAME];
|
const metadata = getComponentTypeMetadata(componentType);
|
||||||
|
const decoratorName = metadata[COMPONENT_TYPE_NAME];
|
||||||
if (decoratorName) {
|
if (decoratorName) {
|
||||||
return decoratorName;
|
return decoratorName;
|
||||||
}
|
}
|
||||||
@@ -111,7 +162,8 @@ export function getComponentInstanceTypeName(component: Component): string {
|
|||||||
* @returns 依赖的组件名称列表
|
* @returns 依赖的组件名称列表
|
||||||
*/
|
*/
|
||||||
export function getComponentDependencies(componentType: ComponentType): string[] | undefined {
|
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 编辑器选项
|
* @returns 编辑器选项
|
||||||
*/
|
*/
|
||||||
export function getComponentEditorOptions(componentType: ComponentType): ComponentEditorOptions | undefined {
|
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_TYPE_NAME,
|
||||||
COMPONENT_DEPENDENCIES,
|
COMPONENT_DEPENDENCIES,
|
||||||
COMPONENT_EDITOR_OPTIONS,
|
COMPONENT_EDITOR_OPTIONS,
|
||||||
type ComponentEditorOptions
|
getWritableComponentTypeMetadata,
|
||||||
|
type ComponentEditorOptions,
|
||||||
|
type ComponentType
|
||||||
} from '../Core/ComponentStorage/ComponentTypeUtils';
|
} from '../Core/ComponentStorage/ComponentTypeUtils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,6 +26,50 @@ import {
|
|||||||
*/
|
*/
|
||||||
export const SYSTEM_TYPE_NAME = Symbol('SystemTypeName');
|
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
|
* Component decorator options
|
||||||
@@ -67,25 +113,29 @@ export interface ComponentOptions {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function ECSComponent(typeName: string, options?: 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') {
|
if (!typeName || typeof typeName !== 'string') {
|
||||||
throw new Error('ECSComponent装饰器必须提供有效的类型名称');
|
throw new Error('ECSComponent装饰器必须提供有效的类型名称');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取可写的元数据对象
|
||||||
|
// Get writable metadata object
|
||||||
|
const metadata = getWritableComponentTypeMetadata(target);
|
||||||
|
|
||||||
// 在构造函数上存储类型名称
|
// 在构造函数上存储类型名称
|
||||||
// Store type name on constructor
|
// Store type name on constructor
|
||||||
(target as any)[COMPONENT_TYPE_NAME] = typeName;
|
metadata[COMPONENT_TYPE_NAME] = typeName;
|
||||||
|
|
||||||
// 存储依赖关系
|
// 存储依赖关系
|
||||||
// Store dependencies
|
// Store dependencies
|
||||||
if (options?.requires) {
|
if (options?.requires) {
|
||||||
(target as any)[COMPONENT_DEPENDENCIES] = options.requires;
|
metadata[COMPONENT_DEPENDENCIES] = options.requires;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 存储编辑器选项
|
// 存储编辑器选项
|
||||||
// Store editor options
|
// Store editor options
|
||||||
if (options?.editor) {
|
if (options?.editor) {
|
||||||
(target as any)[COMPONENT_EDITOR_OPTIONS] = options.editor;
|
metadata[COMPONENT_EDITOR_OPTIONS] = options.editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自动注册到全局 ComponentRegistry,使组件可以通过名称查找
|
// 自动注册到全局 ComponentRegistry,使组件可以通过名称查找
|
||||||
@@ -154,19 +204,23 @@ export interface SystemMetadata {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function ECSSystem(typeName: string, metadata?: 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') {
|
if (!typeName || typeof typeName !== 'string') {
|
||||||
throw new Error('ECSSystem装饰器必须提供有效的类型名称');
|
throw new Error('ECSSystem装饰器必须提供有效的类型名称');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取可写的元数据对象
|
||||||
|
// Get writable metadata object
|
||||||
|
const meta = getWritableSystemTypeMetadata(target);
|
||||||
|
|
||||||
// 在构造函数上存储类型名称
|
// 在构造函数上存储类型名称
|
||||||
// Store type name on constructor
|
// Store type name on constructor
|
||||||
(target as any)[SYSTEM_TYPE_NAME] = typeName;
|
meta[SYSTEM_TYPE_NAME] = typeName;
|
||||||
|
|
||||||
// 存储元数据
|
// 存储元数据
|
||||||
// Store metadata
|
// Store metadata
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
(target as any).__systemMetadata__ = metadata;
|
meta.__systemMetadata__ = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
@@ -177,8 +231,9 @@ export function ECSSystem(typeName: string, metadata?: SystemMetadata) {
|
|||||||
* 获取 System 的元数据
|
* 获取 System 的元数据
|
||||||
* Get System metadata
|
* Get System metadata
|
||||||
*/
|
*/
|
||||||
export function getSystemMetadata(systemType: new (...args: any[]) => EntitySystem): SystemMetadata | undefined {
|
export function getSystemMetadata(systemType: SystemConstructor): SystemMetadata | undefined {
|
||||||
return (systemType as any).__systemMetadata__;
|
const meta = getSystemTypeMetadata(systemType);
|
||||||
|
return meta.__systemMetadata__;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,7 +244,7 @@ export function getSystemMetadata(systemType: new (...args: any[]) => EntitySyst
|
|||||||
* @returns 系统元数据 | System metadata
|
* @returns 系统元数据 | System metadata
|
||||||
*/
|
*/
|
||||||
export function getSystemInstanceMetadata(system: EntitySystem): SystemMetadata | undefined {
|
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
|
* @returns 系统类型名称 | System type name
|
||||||
*/
|
*/
|
||||||
export function getSystemTypeName<T extends EntitySystem>(
|
export function getSystemTypeName<T extends EntitySystem>(
|
||||||
systemType: new (...args: any[]) => T
|
systemType: SystemConstructor<T>
|
||||||
): string {
|
): string {
|
||||||
const decoratorName = (systemType as any)[SYSTEM_TYPE_NAME];
|
const meta = getSystemTypeMetadata(systemType);
|
||||||
|
const decoratorName = meta[SYSTEM_TYPE_NAME];
|
||||||
if (decoratorName) {
|
if (decoratorName) {
|
||||||
return decoratorName;
|
return decoratorName;
|
||||||
}
|
}
|
||||||
@@ -217,5 +273,5 @@ export function getSystemTypeName<T extends EntitySystem>(
|
|||||||
* @returns 系统类型名称 | System type name
|
* @returns 系统类型名称 | System type name
|
||||||
*/
|
*/
|
||||||
export function getSystemInstanceTypeName(system: EntitySystem): string {
|
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 { SpriteRenderData, TextureLoadRequest, EngineStats, CameraConfig } from '../types';
|
||||||
import type { ITextureEngineBridge } from '@esengine/asset-system';
|
import type { ITextureEngineBridge } from '@esengine/asset-system';
|
||||||
import type { GameEngine } from '../wasm/es_engine';
|
import type { GameEngine } from '../wasm/es_engine';
|
||||||
|
import type {
|
||||||
|
ITextureService,
|
||||||
|
IDynamicAtlasService,
|
||||||
|
ICoordinateService,
|
||||||
|
IRenderConfigService
|
||||||
|
} from '@esengine/engine-core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Engine bridge configuration.
|
* Engine bridge configuration.
|
||||||
@@ -43,7 +49,7 @@ export interface EngineBridgeConfig {
|
|||||||
* bridge.render();
|
* bridge.render();
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export class EngineBridge implements ITextureEngineBridge {
|
export class EngineBridge implements ITextureEngineBridge, ITextureService, IDynamicAtlasService, ICoordinateService, IRenderConfigService {
|
||||||
private engine: GameEngine | null = null;
|
private engine: GameEngine | null = null;
|
||||||
private config: Required<EngineBridgeConfig>;
|
private config: Required<EngineBridgeConfig>;
|
||||||
private initialized = false;
|
private initialized = false;
|
||||||
|
|||||||
@@ -8,12 +8,20 @@
|
|||||||
// Service tokens and interfaces (谁定义接口,谁导出 Token)
|
// Service tokens and interfaces (谁定义接口,谁导出 Token)
|
||||||
export {
|
export {
|
||||||
RenderSystemToken,
|
RenderSystemToken,
|
||||||
EngineBridgeToken,
|
|
||||||
EngineIntegrationToken,
|
EngineIntegrationToken,
|
||||||
|
// 新的单一职责服务令牌 | New single-responsibility service tokens
|
||||||
|
TextureServiceToken,
|
||||||
|
DynamicAtlasServiceToken,
|
||||||
|
CoordinateServiceToken,
|
||||||
|
RenderConfigServiceToken,
|
||||||
|
// 接口类型 | Interface types
|
||||||
type IRenderSystem,
|
type IRenderSystem,
|
||||||
type IEngineBridge,
|
|
||||||
type IEngineIntegration,
|
type IEngineIntegration,
|
||||||
type IRenderDataProvider
|
type IRenderDataProvider,
|
||||||
|
type ITextureService,
|
||||||
|
type IDynamicAtlasService,
|
||||||
|
type ICoordinateService,
|
||||||
|
type IRenderConfigService
|
||||||
} from './tokens';
|
} from './tokens';
|
||||||
|
|
||||||
export { EngineBridge } from './core/EngineBridge';
|
export { EngineBridge } from './core/EngineBridge';
|
||||||
|
|||||||
@@ -4,12 +4,31 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { createServiceToken } from '@esengine/ecs-framework';
|
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';
|
import type { IRenderDataProvider as InternalIRenderDataProvider } from './systems/EngineRenderSystem';
|
||||||
|
|
||||||
// 从 engine-core 重新导出 | Re-export from engine-core
|
// 从 engine-core 重新导出 | Re-export from engine-core
|
||||||
export { CoreEngineBridgeToken as EngineBridgeToken };
|
export {
|
||||||
export type { CoreIEngineBridge as IEngineBridge };
|
TextureServiceToken,
|
||||||
|
DynamicAtlasServiceToken,
|
||||||
|
CoordinateServiceToken,
|
||||||
|
RenderConfigServiceToken
|
||||||
|
};
|
||||||
|
export type {
|
||||||
|
ITextureService,
|
||||||
|
IDynamicAtlasService,
|
||||||
|
ICoordinateService,
|
||||||
|
IRenderConfigService
|
||||||
|
};
|
||||||
|
|
||||||
export type IRenderDataProvider = InternalIRenderDataProvider;
|
export type IRenderDataProvider = InternalIRenderDataProvider;
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
UIRegistry,
|
UIRegistry,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
LocaleService,
|
LocaleService,
|
||||||
LogService,
|
LogService,
|
||||||
SettingsRegistry,
|
SettingsRegistry,
|
||||||
@@ -394,7 +394,7 @@ function App() {
|
|||||||
setStatus(t('header.status.remoteConnected'));
|
setStatus(t('header.status.remoteConnected'));
|
||||||
} else {
|
} else {
|
||||||
if (projectLoaded) {
|
if (projectLoaded) {
|
||||||
const componentRegistry = Core.services.resolve(ComponentRegistry);
|
const componentRegistry = Core.services.resolve(EditorComponentRegistry);
|
||||||
const componentCount = componentRegistry?.getAllComponents().length || 0;
|
const componentCount = componentRegistry?.getAllComponents().length || 0;
|
||||||
setStatus(t('header.status.projectOpened') + (componentCount > 0 ? ` (${componentCount} components registered)` : ''));
|
setStatus(t('header.status.projectOpened') + (componentCount > 0 ? ` (${componentCount} components registered)` : ''));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
IMessageHub,
|
IMessageHub,
|
||||||
SerializerRegistry,
|
SerializerRegistry,
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
ProjectService,
|
ProjectService,
|
||||||
ComponentDiscoveryService,
|
ComponentDiscoveryService,
|
||||||
PropertyMetadataService,
|
PropertyMetadataService,
|
||||||
@@ -90,7 +90,7 @@ export interface EditorServices {
|
|||||||
messageHub: MessageHub;
|
messageHub: MessageHub;
|
||||||
serializerRegistry: SerializerRegistry;
|
serializerRegistry: SerializerRegistry;
|
||||||
entityStore: EntityStoreService;
|
entityStore: EntityStoreService;
|
||||||
componentRegistry: ComponentRegistry;
|
componentRegistry: EditorComponentRegistry;
|
||||||
projectService: ProjectService;
|
projectService: ProjectService;
|
||||||
componentDiscovery: ComponentDiscoveryService;
|
componentDiscovery: ComponentDiscoveryService;
|
||||||
propertyMetadata: PropertyMetadataService;
|
propertyMetadata: PropertyMetadataService;
|
||||||
@@ -121,7 +121,7 @@ export class ServiceRegistry {
|
|||||||
const messageHub = new MessageHub();
|
const messageHub = new MessageHub();
|
||||||
const serializerRegistry = new SerializerRegistry();
|
const serializerRegistry = new SerializerRegistry();
|
||||||
const entityStore = new EntityStoreService(messageHub);
|
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)
|
// 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(IMessageHub, messageHub); // Symbol 注册用于跨包插件访问
|
||||||
Core.services.registerInstance(SerializerRegistry, serializerRegistry);
|
Core.services.registerInstance(SerializerRegistry, serializerRegistry);
|
||||||
Core.services.registerInstance(EntityStoreService, entityStore);
|
Core.services.registerInstance(EntityStoreService, entityStore);
|
||||||
Core.services.registerInstance(ComponentRegistry, componentRegistry);
|
Core.services.registerInstance(EditorComponentRegistry, componentRegistry);
|
||||||
Core.services.registerInstance(ProjectService, projectService);
|
Core.services.registerInstance(ProjectService, projectService);
|
||||||
Core.services.registerInstance(ComponentDiscoveryService, componentDiscovery);
|
Core.services.registerInstance(ComponentDiscoveryService, componentDiscovery);
|
||||||
Core.services.registerInstance(PropertyMetadataService, propertyMetadata);
|
Core.services.registerInstance(PropertyMetadataService, propertyMetadata);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Entity, Component, getComponentDependencies, getComponentTypeName } from '@esengine/ecs-framework';
|
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 { Core } from '@esengine/ecs-framework';
|
||||||
import { BaseCommand } from '../BaseCommand';
|
import { BaseCommand } from '../BaseCommand';
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ export class AddComponentCommand extends BaseCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentRegistry = Core.services.tryResolve(ComponentRegistry) as ComponentRegistry | null;
|
const componentRegistry = Core.services.tryResolve(EditorComponentRegistry) as EditorComponentRegistry | null;
|
||||||
if (!componentRegistry) {
|
if (!componentRegistry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
MessageHub,
|
MessageHub,
|
||||||
CommandManager,
|
CommandManager,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
ComponentActionRegistry,
|
ComponentActionRegistry,
|
||||||
ComponentInspectorRegistry,
|
ComponentInspectorRegistry,
|
||||||
PrefabService,
|
PrefabService,
|
||||||
@@ -147,7 +147,7 @@ export const EntityInspectorPanel: React.FC<EntityInspectorPanelProps> = ({
|
|||||||
|
|
||||||
// ==================== 服务 | Services ====================
|
// ==================== 服务 | Services ====================
|
||||||
|
|
||||||
const componentRegistry = Core.services.resolve(ComponentRegistry);
|
const componentRegistry = Core.services.resolve(EditorComponentRegistry);
|
||||||
const componentActionRegistry = Core.services.resolve(ComponentActionRegistry);
|
const componentActionRegistry = Core.services.resolve(ComponentActionRegistry);
|
||||||
const componentInspectorRegistry = Core.services.resolve(ComponentInspectorRegistry);
|
const componentInspectorRegistry = Core.services.resolve(ComponentInspectorRegistry);
|
||||||
const prefabService = Core.services.tryResolve(PrefabService) as PrefabService | null;
|
const prefabService = Core.services.tryResolve(PrefabService) as PrefabService | null;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
|
||||||
import { Settings, ChevronDown, ChevronRight, X, Plus, Box, Search, Lock, Unlock } from 'lucide-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 { 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 { PropertyInspector } from '../../PropertyInspector';
|
||||||
import { NotificationService } from '../../../services/NotificationService';
|
import { NotificationService } from '../../../services/NotificationService';
|
||||||
import { RemoveComponentCommand, UpdateComponentCommand, AddComponentCommand } from '../../../application/commands/component';
|
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';
|
type CategoryFilter = 'all' | 'general' | 'transform' | 'rendering' | 'physics' | 'audio' | 'other';
|
||||||
|
|
||||||
// 从 ComponentRegistry category 到 CategoryFilter 的映射
|
// 从 EditorComponentRegistry category 到 CategoryFilter 的映射
|
||||||
const categoryKeyMap: Record<string, CategoryFilter> = {
|
const categoryKeyMap: Record<string, CategoryFilter> = {
|
||||||
'components.category.core': 'general',
|
'components.category.core': 'general',
|
||||||
'components.category.rendering': 'rendering',
|
'components.category.rendering': 'rendering',
|
||||||
@@ -84,7 +84,7 @@ export function EntityInspector({
|
|||||||
const addButtonRef = useRef<HTMLButtonElement>(null);
|
const addButtonRef = useRef<HTMLButtonElement>(null);
|
||||||
const searchInputRef = useRef<HTMLInputElement>(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 componentActionRegistry = Core.services.resolve(ComponentActionRegistry);
|
||||||
const componentInspectorRegistry = Core.services.resolve(ComponentInspectorRegistry);
|
const componentInspectorRegistry = Core.services.resolve(ComponentInspectorRegistry);
|
||||||
const prefabService = Core.services.tryResolve(PrefabService) as PrefabService | null;
|
const prefabService = Core.services.tryResolve(PrefabService) as PrefabService | null;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||||
import { createLogger } 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';
|
import { AssetRegistryService } from '@esengine/editor-core';
|
||||||
|
|
||||||
const logger = createLogger('AssetMetaPlugin');
|
const logger = createLogger('AssetMetaPlugin');
|
||||||
@@ -65,7 +65,7 @@ const manifest: ModuleManifest = {
|
|||||||
exports: {}
|
exports: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AssetMetaPlugin: IPlugin = {
|
export const AssetMetaPlugin: IEditorPlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
editorModule: new AssetMetaEditorModule()
|
editorModule: new AssetMetaEditorModule()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||||
import { createLogger } 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 { SettingsRegistry } from '@esengine/editor-core';
|
||||||
import { SettingsService } from '../../services/SettingsService';
|
import { SettingsService } from '../../services/SettingsService';
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ const manifest: ModuleManifest = {
|
|||||||
exports: {}
|
exports: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EditorAppearancePlugin: IPlugin = {
|
export const EditorAppearancePlugin: IEditorPlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
editorModule: new EditorAppearanceEditorModule()
|
editorModule: new EditorAppearanceEditorModule()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
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';
|
import { registerSpriteGizmo } from '../../gizmos';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +42,7 @@ const manifest: ModuleManifest = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GizmoPlugin: IPlugin = {
|
export const GizmoPlugin: IEditorPlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
editorModule: new GizmoEditorModule()
|
editorModule: new GizmoEditorModule()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||||
import { createLogger } 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 { SettingsRegistry } from '@esengine/editor-core';
|
||||||
|
|
||||||
const logger = createLogger('PluginConfigPlugin');
|
const logger = createLogger('PluginConfigPlugin');
|
||||||
@@ -69,7 +69,7 @@ const manifest: ModuleManifest = {
|
|||||||
exports: {}
|
exports: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PluginConfigPlugin: IPlugin = {
|
export const PluginConfigPlugin: IEditorPlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
editorModule: new PluginConfigEditorModule()
|
editorModule: new PluginConfigEditorModule()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||||
import { Core } from '@esengine/ecs-framework';
|
import { Core } from '@esengine/ecs-framework';
|
||||||
import type {
|
import type {
|
||||||
IPlugin,
|
IEditorPlugin,
|
||||||
IEditorModuleLoader,
|
IEditorModuleLoader,
|
||||||
ModuleManifest,
|
ModuleManifest,
|
||||||
MenuItemDescriptor
|
MenuItemDescriptor
|
||||||
@@ -140,7 +140,7 @@ const manifest: ModuleManifest = {
|
|||||||
exports: {}
|
exports: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProfilerPlugin: IPlugin = {
|
export const ProfilerPlugin: IEditorPlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
editorModule: new ProfilerEditorModule()
|
editorModule: new ProfilerEditorModule()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||||
import { createLogger, Core } 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 { SettingsRegistry, ProjectService, moduleRegistry } from '@esengine/editor-core';
|
||||||
import EngineService from '../../services/EngineService';
|
import EngineService from '../../services/EngineService';
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@ const manifest: ModuleManifest = {
|
|||||||
exports: {}
|
exports: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ProjectSettingsPlugin: IPlugin = {
|
export const ProjectSettingsPlugin: IEditorPlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
editorModule: new ProjectSettingsEditorModule()
|
editorModule: new ProjectSettingsEditorModule()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { Core, Entity } from '@esengine/ecs-framework';
|
import { Core, Entity } from '@esengine/ecs-framework';
|
||||||
import type { ServiceContainer } from '@esengine/ecs-framework';
|
import type { ServiceContainer } from '@esengine/ecs-framework';
|
||||||
import type {
|
import type {
|
||||||
IPlugin,
|
IEditorPlugin,
|
||||||
IEditorModuleLoader,
|
IEditorModuleLoader,
|
||||||
ModuleManifest,
|
ModuleManifest,
|
||||||
PanelDescriptor,
|
PanelDescriptor,
|
||||||
@@ -191,7 +191,7 @@ const manifest: ModuleManifest = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SceneInspectorPlugin: IPlugin = {
|
export const SceneInspectorPlugin: IEditorPlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
editorModule: new SceneInspectorEditorModule()
|
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 { 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 { 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 { TransformComponent, TransformTypeToken, CanvasElementToken } from '@esengine/engine-core';
|
||||||
import { SpriteComponent, SpriteAnimatorComponent, SpriteAnimatorSystemToken } from '@esengine/sprite';
|
import { SpriteComponent, SpriteAnimatorComponent, SpriteAnimatorSystemToken } from '@esengine/sprite';
|
||||||
import { ParticleSystemComponent } from '@esengine/particle';
|
import { ParticleSystemComponent } from '@esengine/particle';
|
||||||
@@ -252,7 +260,11 @@ export class EngineService {
|
|||||||
// 创建服务注册表并注册核心服务
|
// 创建服务注册表并注册核心服务
|
||||||
// Create service registry and register core services
|
// Create service registry and register core services
|
||||||
const services = new PluginServiceRegistry();
|
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(RenderSystemToken, this._runtime.renderSystem);
|
||||||
services.register(AssetManagerToken, this._assetManager);
|
services.register(AssetManagerToken, this._assetManager);
|
||||||
services.register(EngineIntegrationToken, this._engineIntegration);
|
services.register(EngineIntegrationToken, this._engineIntegration);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { PluginManager, LocaleService, MessageHub, EditorConfig, getPluginsPath } from '@esengine/editor-core';
|
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 { Core } from '@esengine/ecs-framework';
|
||||||
import { TauriAPI } from '../api/tauri';
|
import { TauriAPI } from '../api/tauri';
|
||||||
import { PluginSDKRegistry } from './PluginSDKRegistry';
|
import { PluginSDKRegistry } from './PluginSDKRegistry';
|
||||||
@@ -164,7 +164,7 @@ export class PluginLoader {
|
|||||||
code: string,
|
code: string,
|
||||||
pluginName: string,
|
pluginName: string,
|
||||||
_pluginDirName: string
|
_pluginDirName: string
|
||||||
): Promise<IPlugin | null> {
|
): Promise<IRuntimePlugin | null> {
|
||||||
const pluginKey = this.sanitizePluginKey(pluginName);
|
const pluginKey = this.sanitizePluginKey(pluginName);
|
||||||
|
|
||||||
const pluginsContainer = (window as any)[PLUGINS_GLOBAL_NAME] as Record<string, any>;
|
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 导出
|
// 优先检查 default 导出
|
||||||
if (module.default && this.isPluginLoader(module.default)) {
|
if (module.default && this.isPluginLoader(module.default)) {
|
||||||
return 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') {
|
if (!obj || typeof obj !== 'object') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新的 IPlugin 接口检查
|
// IRuntimePlugin 接口检查
|
||||||
if (obj.manifest && this.isModuleManifest(obj.manifest)) {
|
if (obj.manifest && this.isModuleManifest(obj.manifest)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ export class PluginLoader {
|
|||||||
/**
|
/**
|
||||||
* 同步插件语言设置
|
* 同步插件语言设置
|
||||||
*/
|
*/
|
||||||
private syncPluginLocale(plugin: IPlugin, pluginName: string): void {
|
private syncPluginLocale(plugin: IRuntimePlugin, pluginName: string): void {
|
||||||
try {
|
try {
|
||||||
const localeService = Core.services.resolve(LocaleService);
|
const localeService = Core.services.resolve(LocaleService);
|
||||||
const currentLocale = localeService.getCurrentLocale();
|
const currentLocale = localeService.getCurrentLocale();
|
||||||
|
|||||||
@@ -43,7 +43,6 @@
|
|||||||
"@esengine/asset-system": "workspace:*",
|
"@esengine/asset-system": "workspace:*",
|
||||||
"@esengine/asset-system-editor": "workspace:*",
|
"@esengine/asset-system-editor": "workspace:*",
|
||||||
"@esengine/engine-core": "workspace:*",
|
"@esengine/engine-core": "workspace:*",
|
||||||
"@esengine/plugin-types": "workspace:*",
|
|
||||||
"@tauri-apps/api": "^2.2.0",
|
"@tauri-apps/api": "^2.2.0",
|
||||||
"@babel/core": "^7.28.3",
|
"@babel/core": "^7.28.3",
|
||||||
"@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
|
"@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export type {
|
|||||||
LoadingPhase,
|
LoadingPhase,
|
||||||
SystemContext,
|
SystemContext,
|
||||||
IRuntimeModule,
|
IRuntimeModule,
|
||||||
IPlugin,
|
IRuntimePlugin,
|
||||||
ModuleManifest,
|
ModuleManifest,
|
||||||
ModuleCategory,
|
ModuleCategory,
|
||||||
ModulePlatform,
|
ModulePlatform,
|
||||||
@@ -309,17 +309,17 @@ export interface IEditorModuleLoader extends IEditorModuleBase {
|
|||||||
// 编辑器插件类型 | Editor Plugin Type
|
// 编辑器插件类型 | Editor Plugin Type
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
import type { IPlugin } from './PluginDescriptor';
|
import type { IRuntimePlugin } from './PluginDescriptor';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编辑器插件类型
|
* 编辑器插件类型
|
||||||
* Editor plugin type
|
* Editor plugin type
|
||||||
*
|
*
|
||||||
* 这是开发编辑器插件时应使用的类型。
|
* 这是开发编辑器插件时应使用的类型。
|
||||||
* 它是 IPlugin 的特化版本,editorModule 类型为 IEditorModuleLoader。
|
* 它是 IRuntimePlugin 的特化版本,editorModule 类型为 IEditorModuleLoader。
|
||||||
*
|
*
|
||||||
* This is the type to use when developing editor plugins.
|
* 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
|
* @example
|
||||||
* ```typescript
|
* ```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.
|
* 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 重新导出所有类型
|
// 从 engine-core 重新导出所有类型
|
||||||
// 包括 IEditorModuleBase(原来在 plugin-types 中定义,现在统一从 engine-core 导出)
|
// 包括 IEditorModuleBase(原来在 plugin-types 中定义,现在统一从 engine-core 导出)
|
||||||
export type {
|
export type {
|
||||||
@@ -24,9 +20,6 @@ export type {
|
|||||||
IEditorModuleBase
|
IEditorModuleBase
|
||||||
} from '@esengine/engine-core';
|
} from '@esengine/engine-core';
|
||||||
|
|
||||||
/** @deprecated Use IRuntimePlugin instead */
|
|
||||||
export type IPlugin<TEditorModule = unknown> = IRuntimePluginBase<TEditorModule>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件状态
|
* 插件状态
|
||||||
* Plugin state
|
* Plugin state
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { createLogger, GlobalComponentRegistry } from '@esengine/ecs-framework';
|
|||||||
import type { IScene, ServiceContainer, IService } from '@esengine/ecs-framework';
|
import type { IScene, ServiceContainer, IService } from '@esengine/ecs-framework';
|
||||||
import type {
|
import type {
|
||||||
ModuleManifest,
|
ModuleManifest,
|
||||||
IPlugin,
|
IRuntimePlugin,
|
||||||
ModuleCategory,
|
ModuleCategory,
|
||||||
PluginState
|
PluginState
|
||||||
} from './PluginDescriptor';
|
} from './PluginDescriptor';
|
||||||
@@ -22,7 +22,7 @@ import { UIRegistry } from '../Services/UIRegistry';
|
|||||||
import { MessageHub } from '../Services/MessageHub';
|
import { MessageHub } from '../Services/MessageHub';
|
||||||
import { moduleRegistry } from '../Services/Module/ModuleRegistry';
|
import { moduleRegistry } from '../Services/Module/ModuleRegistry';
|
||||||
import { SerializerRegistry } from '../Services/SerializerRegistry';
|
import { SerializerRegistry } from '../Services/SerializerRegistry';
|
||||||
import { ComponentRegistry as EditorComponentRegistry } from '../Services/ComponentRegistry';
|
import { EditorComponentRegistry } from '../Services/ComponentRegistry';
|
||||||
|
|
||||||
const logger = createLogger('PluginManager');
|
const logger = createLogger('PluginManager');
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export interface NormalizedManifest {
|
|||||||
*/
|
*/
|
||||||
export interface NormalizedPlugin {
|
export interface NormalizedPlugin {
|
||||||
manifest: NormalizedManifest;
|
manifest: NormalizedManifest;
|
||||||
runtimeModule?: IPlugin['runtimeModule'];
|
runtimeModule?: IRuntimePlugin['runtimeModule'];
|
||||||
editorModule?: IEditorModuleLoader;
|
editorModule?: IEditorModuleLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ export class PluginManager implements IService {
|
|||||||
* 标准化模块清单,填充默认值
|
* 标准化模块清单,填充默认值
|
||||||
* Normalize module manifest, fill in defaults
|
* Normalize module manifest, fill in defaults
|
||||||
*/
|
*/
|
||||||
private normalizePlugin(input: IPlugin): NormalizedPlugin {
|
private normalizePlugin(input: IRuntimePlugin): NormalizedPlugin {
|
||||||
const m = input.manifest;
|
const m = input.manifest;
|
||||||
return {
|
return {
|
||||||
manifest: {
|
manifest: {
|
||||||
@@ -229,10 +229,10 @@ export class PluginManager implements IService {
|
|||||||
* 注册插件
|
* 注册插件
|
||||||
* Register plugin
|
* Register plugin
|
||||||
*
|
*
|
||||||
* 接受任何符合 IPlugin 接口的插件,内部会标准化所有字段。
|
* 接受任何符合 IRuntimePlugin 接口的插件,内部会标准化所有字段。
|
||||||
* Accepts any plugin conforming to IPlugin interface, normalizes all fields internally.
|
* Accepts any plugin conforming to IRuntimePlugin interface, normalizes all fields internally.
|
||||||
*/
|
*/
|
||||||
register(plugin: IPlugin): void {
|
register(plugin: IRuntimePlugin): void {
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
logger.error('Cannot register plugin: plugin is null or undefined');
|
logger.error('Cannot register plugin: plugin is null or undefined');
|
||||||
return;
|
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()
|
@Injectable()
|
||||||
export class ComponentRegistry implements IService {
|
export class EditorComponentRegistry implements IService {
|
||||||
private components: Map<string, ComponentTypeInfo> = new Map();
|
private components: Map<string, ComponentTypeInfo> = new Map();
|
||||||
|
|
||||||
public dispose(): void {
|
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
|
// Rename conflicting exports to avoid collision with ecs-framework
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
export {
|
export {
|
||||||
ComponentRegistry as EditorComponentRegistry,
|
EditorComponentRegistry,
|
||||||
} from '@esengine/editor-core';
|
} from '@esengine/editor-core';
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
@@ -229,7 +229,7 @@ export type {
|
|||||||
ModuleCategory,
|
ModuleCategory,
|
||||||
ModulePlatform,
|
ModulePlatform,
|
||||||
ModuleExports,
|
ModuleExports,
|
||||||
IPlugin,
|
IRuntimePlugin,
|
||||||
IRuntimeModule,
|
IRuntimeModule,
|
||||||
SystemContext,
|
SystemContext,
|
||||||
ComponentInspectorProviderDef,
|
ComponentInspectorProviderDef,
|
||||||
|
|||||||
@@ -30,8 +30,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@esengine/ecs-framework": "workspace:*",
|
"@esengine/ecs-framework": "workspace:*",
|
||||||
"@esengine/ecs-framework-math": "workspace:*",
|
"@esengine/ecs-framework-math": "workspace:*",
|
||||||
"@esengine/platform-common": "workspace:*",
|
"@esengine/platform-common": "workspace:*"
|
||||||
"@esengine/plugin-types": "workspace:*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@esengine/build-config": "workspace:*",
|
"@esengine/build-config": "workspace:*",
|
||||||
|
|||||||
@@ -21,20 +21,93 @@ import type { ModuleManifest } from './ModuleManifest';
|
|||||||
import {
|
import {
|
||||||
TransformTypeToken,
|
TransformTypeToken,
|
||||||
CanvasElementToken,
|
CanvasElementToken,
|
||||||
EngineBridgeToken,
|
TextureServiceToken,
|
||||||
type IEngineBridge
|
DynamicAtlasServiceToken,
|
||||||
|
CoordinateServiceToken,
|
||||||
|
RenderConfigServiceToken,
|
||||||
|
type ITextureService,
|
||||||
|
type IDynamicAtlasService,
|
||||||
|
type ICoordinateService,
|
||||||
|
type IRenderConfigService
|
||||||
} from './PluginServiceRegistry';
|
} from './PluginServiceRegistry';
|
||||||
|
|
||||||
// 导出 engine-core 特有的服务令牌 | Export engine-core specific service tokens
|
// 导出 engine-core 特有的服务令牌 | Export engine-core specific service tokens
|
||||||
export {
|
export {
|
||||||
TransformTypeToken,
|
TransformTypeToken,
|
||||||
CanvasElementToken,
|
CanvasElementToken,
|
||||||
EngineBridgeToken,
|
TextureServiceToken,
|
||||||
type IEngineBridge
|
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
|
// 加载阶段 | Loading Phase
|
||||||
@@ -155,7 +228,7 @@ export interface IRuntimeModule {
|
|||||||
* @example
|
* @example
|
||||||
* ```typescript
|
* ```typescript
|
||||||
* // 纯运行时插件 | Pure runtime plugin
|
* // 纯运行时插件 | Pure runtime plugin
|
||||||
* const MyPlugin: IPlugin = {
|
* const MyPlugin: IRuntimePlugin = {
|
||||||
* manifest,
|
* manifest,
|
||||||
* runtimeModule: new MyRuntimeModule()
|
* runtimeModule: new MyRuntimeModule()
|
||||||
* };
|
* };
|
||||||
@@ -184,9 +257,6 @@ export interface IRuntimePlugin<TEditorModule = unknown> {
|
|||||||
readonly editorModule?: TEditorModule;
|
readonly editorModule?: TEditorModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @deprecated Use IRuntimePlugin instead */
|
|
||||||
export type IPlugin<TEditorModule = unknown> = IRuntimePlugin<TEditorModule>;
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Engine Core 插件 | Engine Core Plugin
|
// Engine Core 插件 | Engine Core Plugin
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -215,7 +285,7 @@ const manifest: ModuleManifest = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EnginePlugin: IPlugin = {
|
export const EnginePlugin: IRuntimePlugin = {
|
||||||
manifest,
|
manifest,
|
||||||
runtimeModule: new EngineRuntimeModule()
|
runtimeModule: new EngineRuntimeModule()
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,115 +34,46 @@ export const TransformTypeToken = createServiceToken<new (...args: any[]) => any
|
|||||||
export const CanvasElementToken = createServiceToken<HTMLCanvasElement>('canvasElement');
|
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 */
|
/** 加载纹理 | Load texture */
|
||||||
loadTexture(id: number, url: string): Promise<void>;
|
loadTexture(id: number, url: string): Promise<void>;
|
||||||
|
|
||||||
/**
|
/** 获取纹理加载状态 | Get texture loading state */
|
||||||
* 屏幕坐标转世界坐标
|
getTextureState(id: number): string;
|
||||||
* Screen to world coordinate conversion
|
|
||||||
*/
|
|
||||||
screenToWorld(screenX: number, screenY: number): { x: number; y: number };
|
|
||||||
|
|
||||||
/**
|
/** 检查纹理是否就绪 | Check if texture is ready */
|
||||||
* 世界坐标转屏幕坐标
|
isTextureReady(id: number): boolean;
|
||||||
* World to screen coordinate conversion
|
|
||||||
*/
|
|
||||||
worldToScreen(worldX: number, worldY: number): { x: number; y: number };
|
|
||||||
|
|
||||||
/**
|
/** 获取正在加载的纹理数量 | Get loading texture count */
|
||||||
* 设置清除颜色
|
getTextureLoadingCount(): number;
|
||||||
* Set clear color
|
|
||||||
*/
|
|
||||||
setClearColor(r: number, g: number, b: number, a: number): void;
|
|
||||||
|
|
||||||
// ===== Texture State API (Optional) =====
|
/** 异步加载纹理(等待完成)| Load texture async (wait for completion) */
|
||||||
// ===== 纹理状态 API(可选)=====
|
loadTextureAsync(id: number, url: string): Promise<void>;
|
||||||
|
|
||||||
/**
|
/** 等待所有加载中的纹理完成 | Wait for all textures to load */
|
||||||
* 获取纹理加载状态
|
waitForAllTextures(timeout?: number): 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查纹理是否就绪
|
* 动态图集服务接口
|
||||||
* Check if texture is ready for rendering
|
* Dynamic atlas service interface
|
||||||
*
|
*/
|
||||||
* @param id 纹理 ID | Texture ID
|
export interface IDynamicAtlasService {
|
||||||
* @returns 纹理数据已加载则返回 true | true if texture data is loaded
|
/** 创建空白纹理 | Create blank texture */
|
||||||
*/
|
createBlankTexture(width: number, height: number): number;
|
||||||
isTextureReady?(id: number): boolean;
|
|
||||||
|
|
||||||
/**
|
/** 更新纹理区域 | Update texture region */
|
||||||
* 获取正在加载的纹理数量
|
updateTextureRegion(
|
||||||
* 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?(
|
|
||||||
id: number,
|
id: number,
|
||||||
x: number,
|
x: number,
|
||||||
y: 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
|
// Engine-specific service tokens
|
||||||
TransformTypeToken,
|
TransformTypeToken,
|
||||||
CanvasElementToken,
|
CanvasElementToken,
|
||||||
EngineBridgeToken,
|
TextureServiceToken,
|
||||||
|
DynamicAtlasServiceToken,
|
||||||
|
CoordinateServiceToken,
|
||||||
|
RenderConfigServiceToken,
|
||||||
// Types
|
// Types
|
||||||
type IEditorModuleBase,
|
type IEditorModuleBase,
|
||||||
type IEngineBridge
|
type ITextureService,
|
||||||
|
type IDynamicAtlasService,
|
||||||
|
type ICoordinateService,
|
||||||
|
type IRenderConfigService
|
||||||
} from './EnginePlugin';
|
} from './EnginePlugin';
|
||||||
|
|
||||||
// Module Manifest types (unified module/plugin configuration)
|
// Module Manifest types (unified module/plugin configuration)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
InspectorRegistry,
|
InspectorRegistry,
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
FileActionRegistry
|
FileActionRegistry
|
||||||
} from '@esengine/editor-core';
|
} from '@esengine/editor-core';
|
||||||
import { TransformComponent } from '@esengine/engine-core';
|
import { TransformComponent } from '@esengine/engine-core';
|
||||||
@@ -56,7 +56,7 @@ export class ParticleEditorModule implements IEditorModuleLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 注册组件到编辑器组件注册表 | Register to editor component registry
|
// 注册组件到编辑器组件注册表 | Register to editor component registry
|
||||||
const componentRegistry = services.resolve(ComponentRegistry);
|
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||||
if (componentRegistry) {
|
if (componentRegistry) {
|
||||||
componentRegistry.register({
|
componentRegistry.register({
|
||||||
name: 'ParticleSystem',
|
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 type { IRuntimeModule, IRuntimePlugin, ModuleManifest, SystemContext } from '@esengine/engine-core';
|
||||||
import { TransformTypeToken, CanvasElementToken } from '@esengine/engine-core';
|
import { TransformTypeToken, CanvasElementToken } from '@esengine/engine-core';
|
||||||
import { AssetManagerToken } from '@esengine/asset-system';
|
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 { Physics2DQueryToken } from '@esengine/physics-rapier2d';
|
||||||
import { ParticleSystemComponent } from './ParticleSystemComponent';
|
import { ParticleSystemComponent } from './ParticleSystemComponent';
|
||||||
import { ClickFxComponent } from './ClickFxComponent';
|
import { ClickFxComponent } from './ClickFxComponent';
|
||||||
@@ -30,7 +30,8 @@ class ParticleRuntimeModule implements IRuntimeModule {
|
|||||||
const assetManager = context.services.get(AssetManagerToken);
|
const assetManager = context.services.get(AssetManagerToken);
|
||||||
const transformType = context.services.get(TransformTypeToken);
|
const transformType = context.services.get(TransformTypeToken);
|
||||||
const engineIntegration = context.services.get(EngineIntegrationToken);
|
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 physics2DQuery = context.services.get(Physics2DQueryToken);
|
||||||
const renderSystem = context.services.get(RenderSystemToken);
|
const renderSystem = context.services.get(RenderSystemToken);
|
||||||
|
|
||||||
@@ -60,9 +61,9 @@ class ParticleRuntimeModule implements IRuntimeModule {
|
|||||||
this._updateSystem.setEngineIntegration(engineIntegration);
|
this._updateSystem.setEngineIntegration(engineIntegration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置引擎桥接(用于加载默认纹理)| Set engine bridge (for loading default texture)
|
// 设置纹理服务(用于加载默认纹理)| Set texture service (for loading default texture)
|
||||||
if (engineBridge) {
|
if (textureService) {
|
||||||
this._updateSystem.setEngineBridge(engineBridge);
|
this._updateSystem.setTextureService(textureService);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置 2D 物理查询(用于粒子与场景碰撞)| Set 2D physics query (for particle-scene collision)
|
// 设置 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
|
// ClickFxSystem no longer needs AssetManager, assets are loaded by ParticleUpdateSystem
|
||||||
const clickFxSystem = new ClickFxSystem();
|
const clickFxSystem = new ClickFxSystem();
|
||||||
|
|
||||||
// 设置 EngineBridge(用于屏幕坐标转世界坐标)
|
// 设置坐标服务(用于屏幕坐标转世界坐标)
|
||||||
// Set EngineBridge (for screen to world coordinate conversion)
|
// Set coordinate service (for screen to world coordinate conversion)
|
||||||
if (engineBridge) {
|
if (coordinateService) {
|
||||||
clickFxSystem.setEngineBridge(engineBridge);
|
clickFxSystem.setCoordinateService(coordinateService);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从服务注册表获取 Canvas 元素(用于计算相对坐标)
|
// 从服务注册表获取 Canvas 元素(用于计算相对坐标)
|
||||||
|
|||||||
@@ -11,23 +11,11 @@ import { Input, MouseButton, TransformComponent, SortingLayers } from '@esengine
|
|||||||
import { ClickFxComponent, ClickFxTriggerMode } from '../ClickFxComponent';
|
import { ClickFxComponent, ClickFxTriggerMode } from '../ClickFxComponent';
|
||||||
import { ParticleSystemComponent, RenderSpace } from '../ParticleSystemComponent';
|
import { ParticleSystemComponent, RenderSpace } from '../ParticleSystemComponent';
|
||||||
|
|
||||||
|
import { CoordinateServiceToken, type ICoordinateService } from '@esengine/ecs-engine-bindgen';
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 本地服务令牌定义 | Local Service Token Definitions
|
// 本地服务令牌定义 | 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 尺寸)
|
* EngineRenderSystem 接口(最小定义,用于获取 UI Canvas 尺寸)
|
||||||
@@ -37,10 +25,6 @@ interface IEngineRenderSystem {
|
|||||||
getUICanvasSize(): { width: number; height: number };
|
getUICanvasSize(): { width: number; height: number };
|
||||||
}
|
}
|
||||||
|
|
||||||
// EngineBridge 令牌(与 engine-core 中的一致)
|
|
||||||
// EngineBridge token (consistent with engine-core)
|
|
||||||
const EngineBridgeToken = createServiceToken<IEngineBridge>('engineBridge');
|
|
||||||
|
|
||||||
// RenderSystem 令牌(与 ecs-engine-bindgen 中的一致)
|
// RenderSystem 令牌(与 ecs-engine-bindgen 中的一致)
|
||||||
// RenderSystem token (consistent with ecs-engine-bindgen)
|
// RenderSystem token (consistent with ecs-engine-bindgen)
|
||||||
const RenderSystemToken = createServiceToken<IEngineRenderSystem>('renderSystem');
|
const RenderSystemToken = createServiceToken<IEngineRenderSystem>('renderSystem');
|
||||||
@@ -62,7 +46,7 @@ const RenderSystemToken = createServiceToken<IEngineRenderSystem>('renderSystem'
|
|||||||
*/
|
*/
|
||||||
@ECSSystem('ClickFx', { updateOrder: 100 })
|
@ECSSystem('ClickFx', { updateOrder: 100 })
|
||||||
export class ClickFxSystem extends EntitySystem {
|
export class ClickFxSystem extends EntitySystem {
|
||||||
private _engineBridge: IEngineBridge | null = null;
|
private _coordinateService: ICoordinateService | null = null;
|
||||||
private _renderSystem: IEngineRenderSystem | null = null;
|
private _renderSystem: IEngineRenderSystem | null = null;
|
||||||
private _entitiesToDestroy: Entity[] = [];
|
private _entitiesToDestroy: Entity[] = [];
|
||||||
private _canvas: HTMLCanvasElement | null = null;
|
private _canvas: HTMLCanvasElement | null = null;
|
||||||
@@ -72,20 +56,20 @@ export class ClickFxSystem extends EntitySystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置服务注册表(用于获取 EngineBridge 和 RenderSystem)
|
* 设置服务注册表(用于获取 CoordinateService 和 RenderSystem)
|
||||||
* Set service registry (for getting EngineBridge and RenderSystem)
|
* Set service registry (for getting CoordinateService and RenderSystem)
|
||||||
*/
|
*/
|
||||||
setServiceRegistry(services: PluginServiceRegistry): void {
|
setServiceRegistry(services: PluginServiceRegistry): void {
|
||||||
this._engineBridge = services.get(EngineBridgeToken) ?? null;
|
this._coordinateService = services.get(CoordinateServiceToken) ?? null;
|
||||||
this._renderSystem = services.get(RenderSystemToken) ?? null;
|
this._renderSystem = services.get(RenderSystemToken) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置 EngineBridge(直接注入)
|
* 设置坐标服务(直接注入)
|
||||||
* Set EngineBridge (direct injection)
|
* Set coordinate service (direct injection)
|
||||||
*/
|
*/
|
||||||
setEngineBridge(bridge: IEngineBridge): void {
|
setCoordinateService(coordinateService: ICoordinateService): void {
|
||||||
this._engineBridge = bridge;
|
this._coordinateService = coordinateService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { EntitySystem, Matcher, ECSSystem, Time, Entity, type Component, type ComponentType } from '@esengine/ecs-framework';
|
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 type { IAssetManager } from '@esengine/asset-system';
|
||||||
import { ParticleSystemComponent } from '../ParticleSystemComponent';
|
import { ParticleSystemComponent } from '../ParticleSystemComponent';
|
||||||
import { ParticleRenderDataProvider } from '../rendering/ParticleRenderDataProvider';
|
import { ParticleRenderDataProvider } from '../rendering/ParticleRenderDataProvider';
|
||||||
@@ -78,7 +78,7 @@ export class ParticleUpdateSystem extends EntitySystem {
|
|||||||
private _transformType: ComponentType<Component & ITransformComponent> | null = null;
|
private _transformType: ComponentType<Component & ITransformComponent> | null = null;
|
||||||
private _renderDataProvider: ParticleRenderDataProvider;
|
private _renderDataProvider: ParticleRenderDataProvider;
|
||||||
private _engineIntegration: IEngineIntegration | null = null;
|
private _engineIntegration: IEngineIntegration | null = null;
|
||||||
private _engineBridge: IEngineBridge | null = null;
|
private _textureService: ITextureService | null = null;
|
||||||
private _physics2DQuery: IPhysics2DQuery | null = null;
|
private _physics2DQuery: IPhysics2DQuery | null = null;
|
||||||
private _assetManager: IAssetManager | null = null;
|
private _assetManager: IAssetManager | null = null;
|
||||||
private _defaultTextureLoaded: boolean = false;
|
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 {
|
setTextureService(textureService: ITextureService): void {
|
||||||
this._engineBridge = bridge;
|
this._textureService = textureService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -487,8 +487,8 @@ export class ParticleUpdateSystem extends EntitySystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 没有引擎桥接,无法加载 | No engine bridge, cannot load
|
// 没有引擎桥接,无法加载 | No engine bridge, cannot load
|
||||||
if (!this._engineBridge) {
|
if (!this._textureService) {
|
||||||
console.warn('[ParticleUpdateSystem] EngineBridge not set, cannot load default texture');
|
console.warn('[ParticleUpdateSystem] TextureService not set, cannot load default texture');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,15 +496,9 @@ export class ParticleUpdateSystem extends EntitySystem {
|
|||||||
try {
|
try {
|
||||||
const dataUrl = generateDefaultParticleTextureDataURL();
|
const dataUrl = generateDefaultParticleTextureDataURL();
|
||||||
if (dataUrl) {
|
if (dataUrl) {
|
||||||
// 优先使用 loadTextureAsync(等待纹理就绪)
|
// 使用 loadTextureAsync(等待纹理就绪)
|
||||||
// Prefer loadTextureAsync (waits for texture ready)
|
// Use loadTextureAsync (waits for texture ready)
|
||||||
if (this._engineBridge.loadTextureAsync) {
|
await this._textureService.loadTextureAsync(DEFAULT_PARTICLE_TEXTURE_ID, dataUrl);
|
||||||
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);
|
|
||||||
}
|
|
||||||
this._defaultTextureLoaded = true;
|
this._defaultTextureLoaded = true;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import type {
|
|||||||
import {
|
import {
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
SettingsRegistry
|
SettingsRegistry
|
||||||
} from '@esengine/editor-core';
|
} from '@esengine/editor-core';
|
||||||
import { TransformComponent } from '@esengine/engine-core';
|
import { TransformComponent } from '@esengine/engine-core';
|
||||||
@@ -48,7 +48,7 @@ export class Physics2DEditorModule implements IEditorModuleLoader {
|
|||||||
this.setupSettingsListener();
|
this.setupSettingsListener();
|
||||||
|
|
||||||
// 注册组件到编辑器组件注册表
|
// 注册组件到编辑器组件注册表
|
||||||
const componentRegistry = services.resolve(ComponentRegistry);
|
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||||
if (componentRegistry) {
|
if (componentRegistry) {
|
||||||
componentRegistry.register({
|
componentRegistry.register({
|
||||||
name: 'Rigidbody2D',
|
name: 'Rigidbody2D',
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
BrowserFileSystemService,
|
BrowserFileSystemService,
|
||||||
RuntimeSceneManager,
|
RuntimeSceneManager,
|
||||||
RuntimeSceneManagerToken,
|
RuntimeSceneManagerToken,
|
||||||
type IPlugin,
|
type IRuntimePlugin,
|
||||||
type IRuntimeSceneManager
|
type IRuntimeSceneManager
|
||||||
} from '@esengine/runtime-core';
|
} from '@esengine/runtime-core';
|
||||||
import { isValidGUID, setGlobalAssetFileLoader, type IAssetManager, type IAssetFileLoader } from '@esengine/asset-system';
|
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.
|
* Call this before initialize() to register plugins.
|
||||||
*/
|
*/
|
||||||
registerPlugin(plugin: IPlugin): void {
|
registerPlugin(plugin: IRuntimePlugin): void {
|
||||||
if (plugin) {
|
if (plugin) {
|
||||||
runtimePluginManager.register(plugin);
|
runtimePluginManager.register(plugin);
|
||||||
runtimePluginManager.enable(plugin.manifest.id);
|
runtimePluginManager.enable(plugin.manifest.id);
|
||||||
@@ -87,7 +87,7 @@ export class BrowserRuntime {
|
|||||||
* Register multiple plugins
|
* Register multiple plugins
|
||||||
* 注册多个插件
|
* 注册多个插件
|
||||||
*/
|
*/
|
||||||
registerPlugins(plugins: IPlugin[]): void {
|
registerPlugins(plugins: IRuntimePlugin[]): void {
|
||||||
for (const plugin of plugins) {
|
for (const plugin of plugins) {
|
||||||
this.registerPlugin(plugin);
|
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 {
|
import {
|
||||||
EngineBridge,
|
EngineBridge,
|
||||||
EngineRenderSystem,
|
EngineRenderSystem,
|
||||||
EngineBridgeToken,
|
|
||||||
RenderSystemToken,
|
RenderSystemToken,
|
||||||
EngineIntegrationToken,
|
EngineIntegrationToken,
|
||||||
|
TextureServiceToken,
|
||||||
|
DynamicAtlasServiceToken,
|
||||||
|
CoordinateServiceToken,
|
||||||
|
RenderConfigServiceToken,
|
||||||
type IUIRenderDataProvider
|
type IUIRenderDataProvider
|
||||||
} from '@esengine/ecs-engine-bindgen';
|
} from '@esengine/ecs-engine-bindgen';
|
||||||
import {
|
import {
|
||||||
@@ -360,7 +363,11 @@ export class GameRuntime {
|
|||||||
const services = new PluginServiceRegistry();
|
const services = new PluginServiceRegistry();
|
||||||
|
|
||||||
// 注册核心服务 | Register core services
|
// 注册核心服务 | 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(RenderSystemToken, this._renderSystem);
|
||||||
services.register(EngineIntegrationToken, this._engineIntegration);
|
services.register(EngineIntegrationToken, this._engineIntegration);
|
||||||
services.register(AssetManagerToken, this._assetManager);
|
services.register(AssetManagerToken, this._assetManager);
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ export {
|
|||||||
type IRuntimePlugin
|
type IRuntimePlugin
|
||||||
} from './PluginManager';
|
} from './PluginManager';
|
||||||
|
|
||||||
/** @deprecated Use IRuntimePlugin instead */
|
|
||||||
export type { IRuntimePlugin as IPlugin } from './PluginManager';
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
createPlugin,
|
createPlugin,
|
||||||
registerPlugin,
|
registerPlugin,
|
||||||
@@ -123,13 +120,21 @@ export { TransformTypeToken } from '@esengine/engine-core';
|
|||||||
|
|
||||||
// Re-export service tokens from their respective modules
|
// Re-export service tokens from their respective modules
|
||||||
export {
|
export {
|
||||||
EngineBridgeToken,
|
|
||||||
RenderSystemToken,
|
RenderSystemToken,
|
||||||
EngineIntegrationToken,
|
EngineIntegrationToken,
|
||||||
type IEngineBridge,
|
// 新的单一职责服务令牌 | New single-responsibility service tokens
|
||||||
|
TextureServiceToken,
|
||||||
|
DynamicAtlasServiceToken,
|
||||||
|
CoordinateServiceToken,
|
||||||
|
RenderConfigServiceToken,
|
||||||
|
// 类型 | Types
|
||||||
type IRenderSystem,
|
type IRenderSystem,
|
||||||
type IRenderDataProvider,
|
type IRenderDataProvider,
|
||||||
type IEngineIntegration
|
type IEngineIntegration,
|
||||||
|
type ITextureService,
|
||||||
|
type IDynamicAtlasService,
|
||||||
|
type ICoordinateService,
|
||||||
|
type IRenderConfigService
|
||||||
} from '@esengine/ecs-engine-bindgen';
|
} from '@esengine/ecs-engine-bindgen';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import type {
|
|||||||
import {
|
import {
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
ComponentInspectorRegistry
|
ComponentInspectorRegistry
|
||||||
} from '@esengine/editor-core';
|
} from '@esengine/editor-core';
|
||||||
import { TransformComponent } from '@esengine/engine-core';
|
import { TransformComponent } from '@esengine/engine-core';
|
||||||
@@ -47,7 +47,7 @@ export class SpriteEditorModule implements IEditorModuleLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 注册 Sprite 组件到编辑器组件注册表 | Register Sprite components to editor component registry
|
// 注册 Sprite 组件到编辑器组件注册表 | Register Sprite components to editor component registry
|
||||||
const componentRegistry = services.resolve(ComponentRegistry);
|
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||||
if (componentRegistry) {
|
if (componentRegistry) {
|
||||||
const spriteComponents = [
|
const spriteComponents = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
InspectorRegistry,
|
InspectorRegistry,
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
IDialogService,
|
IDialogService,
|
||||||
IFileSystemService,
|
IFileSystemService,
|
||||||
FileActionRegistry
|
FileActionRegistry
|
||||||
@@ -72,7 +72,7 @@ export class TilemapEditorModule implements IEditorModuleLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 注册组件到编辑器组件注册表 | Register to editor component registry
|
// 注册组件到编辑器组件注册表 | Register to editor component registry
|
||||||
const componentRegistry = services.resolve(ComponentRegistry);
|
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||||
if (componentRegistry) {
|
if (componentRegistry) {
|
||||||
componentRegistry.register({
|
componentRegistry.register({
|
||||||
name: 'Tilemap',
|
name: 'Tilemap',
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import type {
|
|||||||
import {
|
import {
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
ComponentRegistry,
|
EditorComponentRegistry,
|
||||||
ComponentInspectorRegistry
|
ComponentInspectorRegistry
|
||||||
} from '@esengine/editor-core';
|
} from '@esengine/editor-core';
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ export { registerUITransformGizmo, unregisterUITransformGizmo } from './gizmos';
|
|||||||
export class UIEditorModule implements IEditorModuleLoader {
|
export class UIEditorModule implements IEditorModuleLoader {
|
||||||
async install(services: ServiceContainer): Promise<void> {
|
async install(services: ServiceContainer): Promise<void> {
|
||||||
// 注册 UI 组件到编辑器组件注册表 | Register UI components to editor component registry
|
// 注册 UI 组件到编辑器组件注册表 | Register UI components to editor component registry
|
||||||
const componentRegistry = services.resolve(ComponentRegistry);
|
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||||
if (componentRegistry) {
|
if (componentRegistry) {
|
||||||
const uiComponents = [
|
const uiComponents = [
|
||||||
{ name: 'UITransform', type: UITransformComponent, category: 'components.category.ui', description: 'UI element positioning and sizing', icon: 'Move' },
|
{ 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 { IScene, IComponentRegistry } from '@esengine/ecs-framework';
|
||||||
import type { IRuntimeModule, IRuntimePlugin, ModuleManifest, SystemContext } from '@esengine/engine-core';
|
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 { EngineIntegration } from '@esengine/asset-system';
|
||||||
|
|
||||||
import { initializeDynamicAtlasService, registerTexturePathMapping, AtlasExpansionStrategy, type IAtlasEngineBridge } from './atlas';
|
import { initializeDynamicAtlasService, registerTexturePathMapping, AtlasExpansionStrategy, type IAtlasEngineBridge } from './atlas';
|
||||||
@@ -77,7 +82,8 @@ class UIRuntimeModule implements IRuntimeModule {
|
|||||||
|
|
||||||
createSystems(scene: IScene, context: SystemContext): void {
|
createSystems(scene: IScene, context: SystemContext): void {
|
||||||
// 从服务注册表获取依赖 | Get dependencies from service registry
|
// 从服务注册表获取依赖 | 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)
|
// Slider fill control system (runs before layout to modify anchors)
|
||||||
// 滑块填充控制系统(在布局之前运行以修改锚点)
|
// 滑块填充控制系统(在布局之前运行以修改锚点)
|
||||||
@@ -133,34 +139,30 @@ class UIRuntimeModule implements IRuntimeModule {
|
|||||||
const textRenderSystem = new UITextRenderSystem();
|
const textRenderSystem = new UITextRenderSystem();
|
||||||
scene.addSystem(textRenderSystem);
|
scene.addSystem(textRenderSystem);
|
||||||
|
|
||||||
if (engineBridge) {
|
if (textureService) {
|
||||||
// 设置文本渲染系统的纹理回调
|
// 设置文本渲染系统的纹理回调
|
||||||
// Set texture callback for text render system
|
// Set texture callback for text render system
|
||||||
textRenderSystem.setTextureCallback((id: number, dataUrl: string) => {
|
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
|
// Set texture ready checker callback to detect if async-loaded texture is ready
|
||||||
if (engineBridge.isTextureReady) {
|
textRenderSystem.setTextureReadyChecker((id: number) => {
|
||||||
textRenderSystem.setTextureReadyChecker((id: number) => {
|
return textureService.isTextureReady(id);
|
||||||
return engineBridge.isTextureReady!(id);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置输入框渲染系统的纹理回调
|
// 设置输入框渲染系统的纹理回调
|
||||||
// Set texture callback for input field render system
|
// Set texture callback for input field render system
|
||||||
inputFieldRenderSystem.setTextureCallback((id: number, dataUrl: string) => {
|
inputFieldRenderSystem.setTextureCallback((id: number, dataUrl: string) => {
|
||||||
engineBridge.loadTexture(id, dataUrl);
|
textureService.loadTexture(id, dataUrl);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 设置输入框渲染系统的纹理就绪检查回调
|
// 设置输入框渲染系统的纹理就绪检查回调
|
||||||
// Set texture ready checker callback for input field render system
|
// Set texture ready checker callback for input field render system
|
||||||
if (engineBridge.isTextureReady) {
|
inputFieldRenderSystem.setTextureReadyChecker((id: number) => {
|
||||||
inputFieldRenderSystem.setTextureReadyChecker((id: number) => {
|
return textureService.isTextureReady(id);
|
||||||
return engineBridge.isTextureReady!(id);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const uiRenderProvider = new UIRenderDataProvider();
|
const uiRenderProvider = new UIRenderDataProvider();
|
||||||
@@ -175,17 +177,15 @@ class UIRuntimeModule implements IRuntimeModule {
|
|||||||
context.services.register(UITextRenderSystemToken, textRenderSystem);
|
context.services.register(UITextRenderSystemToken, textRenderSystem);
|
||||||
|
|
||||||
// 初始化动态图集服务 | Initialize dynamic atlas service
|
// 初始化动态图集服务 | Initialize dynamic atlas service
|
||||||
// 需要 engineBridge 支持 createBlankTexture 和 updateTextureRegion
|
// 需要 dynamicAtlasService 支持 createBlankTexture 和 updateTextureRegion
|
||||||
// Requires engineBridge to support createBlankTexture and updateTextureRegion
|
// Requires dynamicAtlasService to support createBlankTexture and updateTextureRegion
|
||||||
console.log('[UIRuntimeModule] engineBridge available:', !!engineBridge);
|
console.log('[UIRuntimeModule] dynamicAtlasService available:', !!dynamicAtlasService);
|
||||||
console.log('[UIRuntimeModule] createBlankTexture:', !!engineBridge?.createBlankTexture);
|
if (dynamicAtlasService) {
|
||||||
console.log('[UIRuntimeModule] updateTextureRegion:', !!engineBridge?.updateTextureRegion);
|
// 创建适配器将 IDynamicAtlasService 适配为 IAtlasEngineBridge
|
||||||
if (engineBridge?.createBlankTexture && engineBridge?.updateTextureRegion) {
|
// Create adapter to adapt IDynamicAtlasService to IAtlasEngineBridge
|
||||||
// 创建适配器将 EngineBridge 适配为 IAtlasEngineBridge
|
|
||||||
// Create adapter to adapt EngineBridge to IAtlasEngineBridge
|
|
||||||
const atlasBridge: IAtlasEngineBridge = {
|
const atlasBridge: IAtlasEngineBridge = {
|
||||||
createBlankTexture: (width: number, height: number) => {
|
createBlankTexture: (width: number, height: number) => {
|
||||||
return engineBridge.createBlankTexture!(width, height);
|
return dynamicAtlasService.createBlankTexture(width, height);
|
||||||
},
|
},
|
||||||
updateTextureRegion: (
|
updateTextureRegion: (
|
||||||
id: number,
|
id: number,
|
||||||
@@ -195,7 +195,7 @@ class UIRuntimeModule implements IRuntimeModule {
|
|||||||
height: number,
|
height: number,
|
||||||
pixels: Uint8Array
|
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);
|
registerTexturePathMapping(guid, path);
|
||||||
});
|
});
|
||||||
} else {
|
} 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,
|
InspectorRegistry,
|
||||||
EntityStoreService,
|
EntityStoreService,
|
||||||
MessageHub,
|
MessageHub,
|
||||||
ComponentRegistry
|
EditorComponentRegistry
|
||||||
} from '@esengine/editor-core';
|
} from '@esengine/editor-core';
|
||||||
import { TransformComponent } from '@esengine/engine-core';
|
import { TransformComponent } from '@esengine/engine-core';
|
||||||
import {
|
import {
|
||||||
@@ -47,7 +47,7 @@ export class WorldStreamingEditorModule implements IEditorModuleLoader {
|
|||||||
inspectorRegistry.register(new StreamingAnchorInspectorProvider());
|
inspectorRegistry.register(new StreamingAnchorInspectorProvider());
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentRegistry = services.resolve(ComponentRegistry);
|
const componentRegistry = services.resolve(EditorComponentRegistry);
|
||||||
if (componentRegistry) {
|
if (componentRegistry) {
|
||||||
componentRegistry.register({
|
componentRegistry.register({
|
||||||
name: 'ChunkLoader',
|
name: 'ChunkLoader',
|
||||||
|
|||||||
24
pnpm-lock.yaml
generated
24
pnpm-lock.yaml
generated
@@ -777,9 +777,6 @@ importers:
|
|||||||
'@esengine/engine-core':
|
'@esengine/engine-core':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../engine-core
|
version: link:../engine-core
|
||||||
'@esengine/plugin-types':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../plugin-types
|
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.37.0
|
specifier: ^9.37.0
|
||||||
version: 9.39.1
|
version: 9.39.1
|
||||||
@@ -925,9 +922,6 @@ importers:
|
|||||||
'@esengine/platform-common':
|
'@esengine/platform-common':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../platform-common
|
version: link:../platform-common
|
||||||
'@esengine/plugin-types':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../plugin-types
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@esengine/build-config':
|
'@esengine/build-config':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
@@ -1331,24 +1325,6 @@ importers:
|
|||||||
specifier: ^5.8.3
|
specifier: ^5.8.3
|
||||||
version: 5.9.3
|
version: 5.9.3
|
||||||
|
|
||||||
packages/plugin-types:
|
|
||||||
devDependencies:
|
|
||||||
'@esengine/build-config':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../build-config
|
|
||||||
'@esengine/ecs-framework':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../core
|
|
||||||
rimraf:
|
|
||||||
specifier: ^5.0.0
|
|
||||||
version: 5.0.10
|
|
||||||
tsup:
|
|
||||||
specifier: ^8.0.0
|
|
||||||
version: 8.5.1(@microsoft/api-extractor@7.55.1(@types/node@20.19.25))(@swc/core@1.15.3)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.1)
|
|
||||||
typescript:
|
|
||||||
specifier: ^5.8.3
|
|
||||||
version: 5.9.3
|
|
||||||
|
|
||||||
packages/rapier2d:
|
packages/rapier2d:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
rimraf:
|
rimraf:
|
||||||
|
|||||||
Reference in New Issue
Block a user