feat: 集成Rust WASM渲染引擎与TypeScript ECS框架 (#228)
* feat: 集成Rust WASM渲染引擎与TypeScript ECS框架 * feat: 增强编辑器UI功能与跨平台支持 * fix: 修复CI测试和类型检查问题 * fix: 修复CI问题并提高测试覆盖率 * fix: 修复CI问题并提高测试覆盖率
This commit is contained in:
235
packages/platform-wechat/src/EngineBridge.ts
Normal file
235
packages/platform-wechat/src/EngineBridge.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* Rust 引擎桥接层
|
||||
* 负责在微信小游戏环境中初始化和管理 Rust WASM 引擎
|
||||
*/
|
||||
|
||||
import type { IPlatformCanvas } from '@esengine/platform-common';
|
||||
import { WeChatAdapter } from './WeChatAdapter';
|
||||
|
||||
/**
|
||||
* 引擎配置
|
||||
*/
|
||||
export interface EngineBridgeConfig {
|
||||
wasmPath: string;
|
||||
canvasWidth?: number;
|
||||
canvasHeight?: number;
|
||||
enableWebGL2?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 引擎桥接层
|
||||
* 将微信平台能力桥接到 Rust WASM 引擎
|
||||
*/
|
||||
export class EngineBridge {
|
||||
private _adapter: WeChatAdapter;
|
||||
private _canvas: IPlatformCanvas;
|
||||
private _gl: WebGLRenderingContext | WebGL2RenderingContext | null = null;
|
||||
private _wasmInstance: any = null;
|
||||
private _config: EngineBridgeConfig;
|
||||
|
||||
constructor(adapter: WeChatAdapter, config: EngineBridgeConfig) {
|
||||
this._adapter = adapter;
|
||||
this._config = config;
|
||||
|
||||
// 创建主 Canvas
|
||||
const windowInfo = adapter.getSystemInfo();
|
||||
const width = config.canvasWidth ?? windowInfo.windowWidth;
|
||||
const height = config.canvasHeight ?? windowInfo.windowHeight;
|
||||
|
||||
this._canvas = adapter.canvas.createCanvas(width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化引擎
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
// 获取 WebGL 上下文
|
||||
this._gl = this._getWebGLContext();
|
||||
if (!this._gl) {
|
||||
throw new Error('无法获取 WebGL 上下文');
|
||||
}
|
||||
|
||||
// 加载 WASM 模块
|
||||
const imports = this._createWASMImports();
|
||||
this._wasmInstance = await this._adapter.wasm.instantiate(
|
||||
this._config.wasmPath,
|
||||
imports
|
||||
);
|
||||
|
||||
// 初始化引擎
|
||||
if (this._wasmInstance.exports.init) {
|
||||
this._wasmInstance.exports.init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 WebGL 上下文
|
||||
*/
|
||||
private _getWebGLContext(): WebGLRenderingContext | WebGL2RenderingContext | null {
|
||||
const contextType = this._config.enableWebGL2 ? 'webgl2' : 'webgl';
|
||||
const gl = this._canvas.getContext(contextType, {
|
||||
alpha: false,
|
||||
antialias: false,
|
||||
depth: false,
|
||||
stencil: false,
|
||||
premultipliedAlpha: true,
|
||||
preserveDrawingBuffer: false
|
||||
});
|
||||
|
||||
return gl as WebGLRenderingContext | WebGL2RenderingContext | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 WASM 导入对象
|
||||
*/
|
||||
private _createWASMImports(): Record<string, Record<string, any>> {
|
||||
return {
|
||||
env: {
|
||||
// 内存
|
||||
memory: this._adapter.wasm.createMemory(256, 16384),
|
||||
|
||||
// 平台桥接函数
|
||||
platform_log: (ptr: number, len: number) => {
|
||||
const message = this._readString(ptr, len);
|
||||
console.log('[Engine]', message);
|
||||
},
|
||||
|
||||
platform_error: (ptr: number, len: number) => {
|
||||
const message = this._readString(ptr, len);
|
||||
console.error('[Engine]', message);
|
||||
},
|
||||
|
||||
platform_now: () => {
|
||||
return performance.now();
|
||||
},
|
||||
|
||||
// WebGL 桥接
|
||||
gl_bindBuffer: (target: number, buffer: number) => {
|
||||
this._gl?.bindBuffer(target, this._getGLObject(buffer));
|
||||
},
|
||||
|
||||
gl_bufferData: (target: number, dataPtr: number, dataLen: number, usage: number) => {
|
||||
const data = this._readBuffer(dataPtr, dataLen);
|
||||
this._gl?.bufferData(target, data, usage);
|
||||
},
|
||||
|
||||
gl_clear: (mask: number) => {
|
||||
this._gl?.clear(mask);
|
||||
},
|
||||
|
||||
gl_clearColor: (r: number, g: number, b: number, a: number) => {
|
||||
this._gl?.clearColor(r, g, b, a);
|
||||
},
|
||||
|
||||
gl_drawArrays: (mode: number, first: number, count: number) => {
|
||||
this._gl?.drawArrays(mode, first, count);
|
||||
},
|
||||
|
||||
gl_drawElements: (mode: number, count: number, type: number, offset: number) => {
|
||||
this._gl?.drawElements(mode, count, type, offset);
|
||||
},
|
||||
|
||||
gl_enable: (cap: number) => {
|
||||
this._gl?.enable(cap);
|
||||
},
|
||||
|
||||
gl_disable: (cap: number) => {
|
||||
this._gl?.disable(cap);
|
||||
},
|
||||
|
||||
gl_viewport: (x: number, y: number, width: number, height: number) => {
|
||||
this._gl?.viewport(x, y, width, height);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 WASM 内存读取字符串
|
||||
*/
|
||||
private _readString(ptr: number, len: number): string {
|
||||
const memory = this._wasmInstance?.exports.memory as WebAssembly.Memory;
|
||||
if (!memory) return '';
|
||||
|
||||
const bytes = new Uint8Array(memory.buffer, ptr, len);
|
||||
return new TextDecoder().decode(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 WASM 内存读取缓冲区
|
||||
*/
|
||||
private _readBuffer(ptr: number, len: number): ArrayBuffer {
|
||||
const memory = this._wasmInstance?.exports.memory as WebAssembly.Memory;
|
||||
if (!memory) return new ArrayBuffer(0);
|
||||
|
||||
return memory.buffer.slice(ptr, ptr + len);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 WebGL 对象(暂时简化实现)
|
||||
*/
|
||||
private _getGLObject(_id: number): WebGLBuffer | null {
|
||||
// TODO: 实现 WebGL 对象管理
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Canvas
|
||||
*/
|
||||
get canvas(): IPlatformCanvas {
|
||||
return this._canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 WebGL 上下文
|
||||
*/
|
||||
get gl(): WebGLRenderingContext | WebGL2RenderingContext | null {
|
||||
return this._gl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 WASM 实例
|
||||
*/
|
||||
get wasmInstance(): any {
|
||||
return this._wasmInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清屏
|
||||
*/
|
||||
clear(r: number, g: number, b: number, a: number): void {
|
||||
if (this._gl) {
|
||||
this._gl.clearColor(r, g, b, a);
|
||||
this._gl.clear(this._gl.COLOR_BUFFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染一帧
|
||||
*/
|
||||
render(): void {
|
||||
if (this._wasmInstance?.exports.render) {
|
||||
this._wasmInstance.exports.render();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新逻辑
|
||||
*/
|
||||
update(deltaTime: number): void {
|
||||
if (this._wasmInstance?.exports.update) {
|
||||
this._wasmInstance.exports.update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁引擎
|
||||
*/
|
||||
dispose(): void {
|
||||
if (this._wasmInstance?.exports.dispose) {
|
||||
this._wasmInstance.exports.dispose();
|
||||
}
|
||||
this._wasmInstance = null;
|
||||
this._gl = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user