feat: 集成Rust WASM渲染引擎与TypeScript ECS框架 (#228)

* feat: 集成Rust WASM渲染引擎与TypeScript ECS框架

* feat: 增强编辑器UI功能与跨平台支持

* fix: 修复CI测试和类型检查问题

* fix: 修复CI问题并提高测试覆盖率

* fix: 修复CI问题并提高测试覆盖率
This commit is contained in:
YHH
2025-11-21 10:03:18 +08:00
committed by GitHub
parent 8b9616837d
commit a768b890fd
107 changed files with 10221 additions and 477 deletions

View File

@@ -0,0 +1,254 @@
/**
* Engine service for managing Rust engine lifecycle.
* 管理Rust引擎生命周期的服务。
*/
import { EngineBridge, SpriteComponent, EngineRenderSystem, ITransformComponent } from '@esengine/ecs-engine-bindgen';
import { Core, Scene, Entity, Component, ECSComponent } from '@esengine/ecs-framework';
import * as esEngine from '@esengine/engine';
/**
* Transform component for editor entities.
* 编辑器实体的变换组件。
*/
@ECSComponent('Transform')
export class TransformComponent extends Component implements ITransformComponent {
position = { x: 0, y: 0 };
rotation = 0;
scale = { x: 1, y: 1 };
}
/**
* Engine service singleton for editor integration.
* 用于编辑器集成的引擎服务单例。
*/
export class EngineService {
private static instance: EngineService | null = null;
private bridge: EngineBridge | null = null;
private scene: Scene | null = null;
private renderSystem: EngineRenderSystem | null = null;
private initialized = false;
private running = false;
private animationFrameId: number | null = null;
private lastTime = 0;
private constructor() {}
/**
* Get singleton instance.
* 获取单例实例。
*/
static getInstance(): EngineService {
if (!EngineService.instance) {
EngineService.instance = new EngineService();
}
return EngineService.instance;
}
/**
* Initialize the engine with canvas.
* 使用canvas初始化引擎。
*/
async initialize(canvasId: string): Promise<void> {
if (this.initialized) {
return;
}
try {
// Create engine bridge | 创建引擎桥接
this.bridge = new EngineBridge({
canvasId
});
// Initialize WASM with pre-imported module | 使用预导入模块初始化WASM
await this.bridge.initializeWithModule(esEngine);
// Initialize Core if not already | 初始化Core如果尚未初始化
if (!Core.scene) {
Core.create({ debug: false });
}
// Create ECS scene and set it via Core | 通过Core创建并设置ECS场景
this.scene = new Scene({ name: 'EditorScene' });
// Add render system | 添加渲染系统
this.renderSystem = new EngineRenderSystem(this.bridge, TransformComponent);
this.scene.addSystem(this.renderSystem);
// Set scene via Core | 通过Core设置场景
Core.setScene(this.scene);
this.initialized = true;
console.log('EngineService initialized | 引擎服务初始化完成');
} catch (error) {
console.error('Failed to initialize engine | 引擎初始化失败:', error);
throw error;
}
}
/**
* Check if engine is initialized.
* 检查引擎是否已初始化。
*/
isInitialized(): boolean {
return this.initialized;
}
/**
* Check if engine is running.
* 检查引擎是否正在运行。
*/
isRunning(): boolean {
return this.running;
}
/**
* Start the game loop.
* 启动游戏循环。
*/
start(): void {
if (!this.initialized || this.running) {
return;
}
this.running = true;
this.lastTime = performance.now();
this.gameLoop();
}
/**
* Stop the game loop.
* 停止游戏循环。
*/
stop(): void {
this.running = false;
if (this.animationFrameId !== null) {
cancelAnimationFrame(this.animationFrameId);
this.animationFrameId = null;
}
}
/**
* Main game loop.
* 主游戏循环。
*/
private gameLoop = (): void => {
if (!this.running) {
return;
}
const currentTime = performance.now();
const deltaTime = (currentTime - this.lastTime) / 1000;
this.lastTime = currentTime;
// Update via Core | 通过Core更新
Core.update(deltaTime);
this.animationFrameId = requestAnimationFrame(this.gameLoop);
};
/**
* Create entity with sprite and transform.
* 创建带精灵和变换的实体。
*/
createSpriteEntity(name: string, options?: {
x?: number;
y?: number;
textureId?: number;
width?: number;
height?: number;
}): Entity | null {
if (!this.scene) {
return null;
}
const entity = this.scene.createEntity(name);
// Add transform | 添加变换组件
const transform = new TransformComponent();
if (options) {
transform.position.x = options.x ?? 0;
transform.position.y = options.y ?? 0;
}
entity.addComponent(transform);
// Add sprite | 添加精灵组件
const sprite = new SpriteComponent();
if (options) {
sprite.textureId = options.textureId ?? 0;
sprite.width = options.width ?? 64;
sprite.height = options.height ?? 64;
}
entity.addComponent(sprite);
return entity;
}
/**
* Load texture.
* 加载纹理。
*/
loadTexture(id: number, url: string): void {
if (this.renderSystem) {
this.renderSystem.loadTexture(id, url);
}
}
/**
* Get engine statistics.
* 获取引擎统计信息。
*/
getStats(): { fps: number; drawCalls: number; spriteCount: number } {
if (!this.renderSystem) {
return { fps: 0, drawCalls: 0, spriteCount: 0 };
}
const engineStats = this.renderSystem.getStats();
return {
fps: engineStats?.fps ?? 0,
drawCalls: engineStats?.drawCalls ?? 0,
spriteCount: this.renderSystem.spriteCount
};
}
/**
* Get the ECS scene.
* 获取ECS场景。
*/
getScene(): Scene | null {
return this.scene;
}
/**
* Resize the engine viewport.
* 调整引擎视口大小。
*/
resize(width: number, height: number): void {
if (this.bridge) {
this.bridge.resize(width, height);
}
}
/**
* Dispose engine resources.
* 释放引擎资源。
*/
dispose(): void {
this.stop();
// Scene doesn't have a destroy method, just clear reference
// 场景没有destroy方法只需清除引用
this.scene = null;
if (this.bridge) {
this.bridge.dispose();
this.bridge = null;
}
this.renderSystem = null;
this.initialized = false;
}
}
export default EngineService;