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,171 @@
/**
* Engine render system for ECS.
* 用于ECS的引擎渲染系统。
*/
import { EntitySystem, Matcher, Entity, ComponentType, ECSSystem, Component } from '@esengine/ecs-framework';
import type { EngineBridge } from '../core/EngineBridge';
import { RenderBatcher } from '../core/RenderBatcher';
import { SpriteComponent } from '../components/SpriteComponent';
import type { SpriteRenderData } from '../types';
import type { ITransformComponent } from '../core/SpriteRenderHelper';
/**
* Type for transform component constructor.
* 变换组件构造函数类型。
*/
export type TransformComponentType = ComponentType & (new (...args: any[]) => Component & ITransformComponent);
/**
* ECS System for rendering sprites using the Rust engine.
* 使用Rust引擎渲染精灵的ECS系统。
*
* This system extends EntitySystem and integrates with the ECS lifecycle.
* 此系统扩展EntitySystem并与ECS生命周期集成。
*
* @example
* ```typescript
* // Create transform component | 创建变换组件
* @ECSComponent('Transform')
* class Transform extends Component implements ITransformComponent {
* position = { x: 0, y: 0 };
* rotation = 0;
* scale = { x: 1, y: 1 };
* }
*
* // Initialize bridge | 初始化桥接
* const bridge = new EngineBridge({ canvasId: 'canvas' });
* await bridge.initialize();
*
* // Add system to scene | 将系统添加到场景
* const renderSystem = new EngineRenderSystem(bridge, Transform);
* scene.addSystem(renderSystem);
* ```
*/
@ECSSystem('EngineRender', { updateOrder: 1000 }) // Render system executes last | 渲染系统最后执行
export class EngineRenderSystem extends EntitySystem {
private bridge: EngineBridge;
private batcher: RenderBatcher;
private transformType: TransformComponentType;
/**
* Create a new engine render system.
* 创建新的引擎渲染系统。
*
* @param bridge - Engine bridge instance | 引擎桥接实例
* @param transformType - Transform component class (must implement ITransformComponent) | 变换组件类必须实现ITransformComponent
*/
constructor(bridge: EngineBridge, transformType: TransformComponentType) {
// Match entities with both Sprite and Transform components
// 匹配同时具有Sprite和Transform组件的实体
super(Matcher.empty().all(SpriteComponent, transformType));
this.bridge = bridge;
this.batcher = new RenderBatcher();
this.transformType = transformType;
}
/**
* Called when system is initialized.
* 系统初始化时调用。
*/
public override initialize(): void {
super.initialize();
this.logger.info('EngineRenderSystem initialized | 引擎渲染系统初始化完成');
}
/**
* Called before processing entities.
* 处理实体之前调用。
*/
protected begin(): void {
// Clear the batch | 清空批处理
this.batcher.clear();
// Clear screen | 清屏
this.bridge.clear(0, 0, 0, 1);
// Update input | 更新输入
this.bridge.updateInput();
}
/**
* Process all matched entities.
* 处理所有匹配的实体。
*
* @param entities - Entities to process | 要处理的实体
*/
protected process(entities: readonly Entity[]): void {
for (const entity of entities) {
const sprite = entity.getComponent(SpriteComponent);
const transform = entity.getComponent(this.transformType) as unknown as ITransformComponent | null;
if (!sprite || !transform || !sprite.visible) {
continue;
}
// Calculate UV with flip | 计算带翻转的UV
let uv = sprite.uv;
if (sprite.flipX || sprite.flipY) {
uv = [...sprite.uv] as [number, number, number, number];
if (sprite.flipX) {
[uv[0], uv[2]] = [uv[2], uv[0]];
}
if (sprite.flipY) {
[uv[1], uv[3]] = [uv[3], uv[1]];
}
}
const renderData: SpriteRenderData = {
x: transform.position.x,
y: transform.position.y,
rotation: transform.rotation,
scaleX: transform.scale.x,
scaleY: transform.scale.y,
originX: sprite.originX,
originY: sprite.originY,
textureId: sprite.textureId,
uv,
color: sprite.color
};
this.batcher.addSprite(renderData);
}
}
/**
* Called after processing entities.
* 处理实体之后调用。
*/
protected end(): void {
// Submit batch and render | 提交批处理并渲染
if (!this.batcher.isEmpty) {
this.bridge.submitSprites(this.batcher.getSprites());
}
this.bridge.render();
}
/**
* Get the number of sprites rendered.
* 获取渲染的精灵数量。
*/
get spriteCount(): number {
return this.batcher.count;
}
/**
* Get engine statistics.
* 获取引擎统计信息。
*/
getStats() {
return this.bridge.getStats();
}
/**
* Load a texture.
* 加载纹理。
*/
loadTexture(id: number, url: string): void {
this.bridge.loadTexture(id, url);
}
}