docs(editor): improve editor-app build documentation and add build:rapier2d script

- Add `pnpm build:rapier2d` command to automate Rapier2D WASM build process
- Fix gen-src.mjs path to correctly locate thirdparty/rapier.js
- Update init.ts to work with new wasm-pack web target (auto-initialization)
- Fix behavior-tree-editor build config for asset-system dependency
- Update README_CN.md and README.md with simplified build instructions
This commit is contained in:
yhh
2025-12-30 22:33:06 +08:00
parent f01ce1e320
commit b38fe5ebf4
8 changed files with 306 additions and 17 deletions

View File

@@ -74,6 +74,7 @@
"lint:fix": "turbo run lint:fix", "lint:fix": "turbo run lint:fix",
"build:wasm": "cd packages/rust/engine && wasm-pack build --dev --out-dir pkg", "build:wasm": "cd packages/rust/engine && wasm-pack build --dev --out-dir pkg",
"build:wasm:release": "cd packages/rust/engine && wasm-pack build --release --out-dir pkg", "build:wasm:release": "cd packages/rust/engine && wasm-pack build --release --out-dir pkg",
"build:rapier2d": "node scripts/build-rapier2d.mjs",
"copy-modules": "node scripts/copy-engine-modules.mjs" "copy-modules": "node scripts/copy-engine-modules.mjs"
}, },
"author": "yhh", "author": "yhh",

View File

@@ -8,12 +8,23 @@ Before running the editor, ensure you have the following installed:
- **Node.js** >= 18.x - **Node.js** >= 18.x
- **pnpm** >= 10.x - **pnpm** >= 10.x
- **Rust** >= 1.70 (for Tauri) - **Rust** >= 1.70 (for Tauri and WASM builds)
- **wasm-pack** (for building Rapier2D physics engine)
- **Platform-specific dependencies**: - **Platform-specific dependencies**:
- **Windows**: Microsoft Visual Studio C++ Build Tools - **Windows**: Microsoft Visual Studio C++ Build Tools
- **macOS**: Xcode Command Line Tools (`xcode-select --install`) - **macOS**: Xcode Command Line Tools (`xcode-select --install`)
- **Linux**: See [Tauri prerequisites](https://tauri.app/v1/guides/getting-started/prerequisites) - **Linux**: See [Tauri prerequisites](https://tauri.app/v1/guides/getting-started/prerequisites)
### Installing wasm-pack
```bash
# Using cargo
cargo install wasm-pack
# Or using the official installer script (Linux/macOS)
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
```
## Quick Start ## Quick Start
### 1. Clone and Install ### 1. Clone and Install
@@ -24,7 +35,23 @@ cd esengine
pnpm install pnpm install
``` ```
### 2. Build Dependencies ### 2. Build Rapier2D WASM
The editor depends on Rapier2D physics engine WASM artifacts. First-time setup only requires one command:
```bash
pnpm build:rapier2d
```
This command automatically:
1. Prepares the Rust project
2. Builds WASM
3. Copies artifacts to `packages/physics/rapier2d/pkg`
4. Generates TypeScript source code
> **Note**: Requires Rust and wasm-pack to be installed.
### 3. Build Editor
From the project root: From the project root:
@@ -32,7 +59,7 @@ From the project root:
pnpm build:editor pnpm build:editor
``` ```
### 3. Run Editor ### 4. Run Editor
```bash ```bash
cd packages/editor/editor-app cd packages/editor/editor-app
@@ -43,6 +70,8 @@ pnpm tauri:dev
| Script | Description | | Script | Description |
|--------|-------------| |--------|-------------|
| `pnpm build:rapier2d` | Build Rapier2D WASM (required for first-time setup) |
| `pnpm build:editor` | Build editor and all dependencies |
| `pnpm tauri:dev` | Run editor in development mode with hot-reload | | `pnpm tauri:dev` | Run editor in development mode with hot-reload |
| `pnpm tauri:build` | Build production application | | `pnpm tauri:build` | Build production application |
| `pnpm build:sdk` | Build editor-runtime SDK | | `pnpm build:sdk` | Build editor-runtime SDK |
@@ -62,6 +91,17 @@ editor-app/
## Troubleshooting ## Troubleshooting
### Rapier2D WASM Build Failed
**Error**: `Could not resolve "../pkg/rapier_wasm2d"`
**Cause**: Missing Rapier2D WASM artifacts.
**Solution**:
1. Ensure `wasm-pack` is installed: `cargo install wasm-pack`
2. Run `pnpm build:rapier2d`
3. Verify `packages/physics/rapier2d/pkg/` directory exists and contains `rapier_wasm2d_bg.wasm` file
### Build Errors ### Build Errors
```bash ```bash
@@ -76,6 +116,12 @@ pnpm build:editor
rustup update rustup update
``` ```
### Windows Users Building WASM
The `pnpm build:rapier2d` script works directly on Windows. If you encounter issues:
1. Use Git Bash or WSL
2. Or download pre-built WASM artifacts from [Releases](https://github.com/esengine/esengine/releases)
## Documentation ## Documentation
- [ESEngine Documentation](https://esengine.cn/) - [ESEngine Documentation](https://esengine.cn/)

View File

@@ -8,12 +8,23 @@
- **Node.js** >= 18.x - **Node.js** >= 18.x
- **pnpm** >= 10.x - **pnpm** >= 10.x
- **Rust** >= 1.70 (Tauri 需要) - **Rust** >= 1.70 (Tauri 和 WASM 构建需要)
- **wasm-pack** (构建 Rapier2D 物理引擎需要)
- **平台相关依赖** - **平台相关依赖**
- **Windows**: Microsoft Visual Studio C++ Build Tools - **Windows**: Microsoft Visual Studio C++ Build Tools
- **macOS**: Xcode Command Line Tools (`xcode-select --install`) - **macOS**: Xcode Command Line Tools (`xcode-select --install`)
- **Linux**: 参考 [Tauri 环境配置](https://tauri.app/v1/guides/getting-started/prerequisites) - **Linux**: 参考 [Tauri 环境配置](https://tauri.app/v1/guides/getting-started/prerequisites)
### 安装 wasm-pack
```bash
# 使用 cargo 安装
cargo install wasm-pack
# 或使用官方安装脚本 (Linux/macOS)
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
```
## 快速开始 ## 快速开始
### 1. 克隆并安装 ### 1. 克隆并安装
@@ -24,7 +35,23 @@ cd esengine
pnpm install pnpm install
``` ```
### 2. 构建依赖 ### 2. 构建 Rapier2D WASM
编辑器依赖 Rapier2D 物理引擎的 WASM 产物。首次构建只需执行一条命令:
```bash
pnpm build:rapier2d
```
该命令会自动完成以下步骤:
1. 准备 Rust 项目
2. 构建 WASM
3. 复制产物到 `packages/physics/rapier2d/pkg`
4. 生成 TypeScript 源码
> **注意**:需要已安装 Rust 和 wasm-pack。
### 3. 构建编辑器
在项目根目录执行: 在项目根目录执行:
@@ -32,7 +59,7 @@ pnpm install
pnpm build:editor pnpm build:editor
``` ```
### 3. 启动编辑器 ### 4. 启动编辑器
```bash ```bash
cd packages/editor/editor-app cd packages/editor/editor-app
@@ -43,6 +70,8 @@ pnpm tauri:dev
| 脚本 | 说明 | | 脚本 | 说明 |
|------|------| |------|------|
| `pnpm build:rapier2d` | 构建 Rapier2D WASM首次构建必须执行|
| `pnpm build:editor` | 构建编辑器及所有依赖 |
| `pnpm tauri:dev` | 开发模式运行编辑器(支持热重载)| | `pnpm tauri:dev` | 开发模式运行编辑器(支持热重载)|
| `pnpm tauri:build` | 构建生产版本应用 | | `pnpm tauri:build` | 构建生产版本应用 |
| `pnpm build:sdk` | 构建 editor-runtime SDK | | `pnpm build:sdk` | 构建 editor-runtime SDK |
@@ -62,6 +91,17 @@ editor-app/
## 常见问题 ## 常见问题
### Rapier2D WASM 构建失败
**错误**: `Could not resolve "../pkg/rapier_wasm2d"`
**原因**: 缺少 Rapier2D 的 WASM 产物。
**解决方案**:
1. 确保已安装 `wasm-pack``cargo install wasm-pack`
2. 执行 `pnpm build:rapier2d`
3. 确认 `packages/physics/rapier2d/pkg/` 目录存在且包含 `rapier_wasm2d_bg.wasm` 文件
### 构建错误 ### 构建错误
```bash ```bash
@@ -76,6 +116,12 @@ pnpm build:editor
rustup update rustup update
``` ```
### Windows 用户构建 WASM
`pnpm build:rapier2d` 脚本在 Windows 上可以直接运行。如果遇到问题:
1. 使用 Git Bash 或 WSL
2. 或从 [Releases](https://github.com/esengine/esengine/releases) 下载预编译的 WASM 产物
## 文档 ## 文档
- [ESEngine 文档](https://esengine.cn/) - [ESEngine 文档](https://esengine.cn/)

View File

@@ -8,7 +8,10 @@
"rootDir": "./src", "rootDir": "./src",
"jsx": "react-jsx", "jsx": "react-jsx",
"skipLibCheck": true, "skipLibCheck": true,
"moduleResolution": "bundler" "moduleResolution": "bundler",
"paths": {
"@esengine/asset-system": ["../../../engine/asset-system/src"]
}
}, },
"include": ["src/**/*"], "include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"] "exclude": ["node_modules", "dist", "**/*.test.ts"]

View File

@@ -2,8 +2,7 @@ import { defineConfig } from 'tsup';
import { editorOnlyPreset } from '../../../tools/build-config/src/presets/plugin-tsup'; import { editorOnlyPreset } from '../../../tools/build-config/src/presets/plugin-tsup';
export default defineConfig({ export default defineConfig({
...editorOnlyPreset({ ...editorOnlyPreset({}),
external: ['@esengine/asset-system'] tsconfig: 'tsconfig.build.json',
}), noExternal: ['@esengine/asset-system']
tsconfig: 'tsconfig.build.json'
}); });

View File

@@ -14,7 +14,7 @@ import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url)); const __dirname = dirname(fileURLToPath(import.meta.url));
const packageRoot = join(__dirname, '..'); const packageRoot = join(__dirname, '..');
const rapierRoot = join(packageRoot, '..', '..', 'thirdparty', 'rapier.js'); const rapierRoot = join(packageRoot, '..', '..', '..', 'thirdparty', 'rapier.js');
const srcTsDir = join(rapierRoot, 'src.ts'); const srcTsDir = join(rapierRoot, 'src.ts');
const src2dDir = join(rapierRoot, 'rapier-compat', 'src2d'); const src2dDir = join(rapierRoot, 'rapier-compat', 'src2d');
const outputDir = join(packageRoot, 'src'); const outputDir = join(packageRoot, 'src');

View File

@@ -1,12 +1,60 @@
// @ts-ignore /**
import wasmBase64 from "../pkg/rapier_wasm2d_bg.wasm"; * RAPIER initialization module with dynamic WASM loading support.
* RAPIER 初始化模块,支持动态 WASM 加载。
*/
import wasmInit from "../pkg/rapier_wasm2d"; import wasmInit from "../pkg/rapier_wasm2d";
import base64 from "base64-js";
/**
* Input types for WASM initialization.
* WASM 初始化的输入类型。
*/
export type InitInput =
| RequestInfo // URL string or Request object
| URL // URL object
| Response // Fetch Response object
| BufferSource // ArrayBuffer or TypedArray
| WebAssembly.Module; // Pre-compiled module
let initialized = false;
/** /**
* Initializes RAPIER. * Initializes RAPIER.
* Has to be called and awaited before using any library methods. * Has to be called and awaited before using any library methods.
*
* 初始化 RAPIER。
* 必须在使用任何库方法之前调用并等待。
*
* @param input - WASM source (required). Can be URL, Response, ArrayBuffer, etc.
* WASM 源(必需)。可以是 URL、Response、ArrayBuffer 等。
*
* @example
* // Load from URL | 从 URL 加载
* await RAPIER.init('wasm/rapier_wasm2d_bg.wasm');
*
* @example
* // Load from fetch response | 从 fetch 响应加载
* const response = await fetch('wasm/rapier_wasm2d_bg.wasm');
* await RAPIER.init(response);
*
* @example
* // Load from ArrayBuffer | 从 ArrayBuffer 加载
* const buffer = await fetch('wasm/rapier_wasm2d_bg.wasm').then(r => r.arrayBuffer());
* await RAPIER.init(buffer);
*/ */
export async function init() { export async function init(input?: InitInput): Promise<void> {
await wasmInit(base64.toByteArray(wasmBase64 as unknown as string).buffer); if (initialized) {
return;
}
await wasmInit(input);
initialized = true;
}
/**
* Check if RAPIER is already initialized.
* 检查 RAPIER 是否已初始化。
*/
export function isInitialized(): boolean {
return initialized;
} }

146
scripts/build-rapier2d.mjs Normal file
View File

@@ -0,0 +1,146 @@
#!/usr/bin/env node
/**
* Build Rapier2D WASM artifacts
* 构建 Rapier2D WASM 产物
*
* This script automates the entire Rapier2D WASM build process:
* 此脚本自动化整个 Rapier2D WASM 构建流程:
*
* 1. Prepare Rust project from thirdparty/rapier.js
* 2. Build WASM using wasm-pack
* 3. Copy artifacts to packages/physics/rapier2d/pkg
* 4. Generate TypeScript source code
*/
import { execSync, spawn } from 'child_process';
import { existsSync, cpSync, rmSync, mkdirSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const rootDir = join(__dirname, '..');
const rapierJsDir = join(rootDir, 'thirdparty', 'rapier.js');
const rapier2dBuildDir = join(rapierJsDir, 'builds', 'rapier2d');
const rapier2dPkgSrc = join(rapier2dBuildDir, 'pkg');
const rapier2dPkgDest = join(rootDir, 'packages', 'physics', 'rapier2d', 'pkg');
/**
* Run a command and stream output
*/
function runCommand(command, cwd, description) {
console.log(`\n📦 ${description}...`);
console.log(` Running: ${command}`);
console.log(` In: ${cwd}\n`);
try {
execSync(command, {
cwd,
stdio: 'inherit',
shell: true
});
return true;
} catch (error) {
console.error(`❌ Failed: ${description}`);
return false;
}
}
/**
* Main build function
*/
async function build() {
console.log('🚀 Building Rapier2D WASM...\n');
// Check if rapier.js exists
if (!existsSync(rapierJsDir)) {
console.error('❌ Error: thirdparty/rapier.js not found!');
console.error(' Please clone it first:');
console.error(' git clone https://github.com/esengine/rapier.js.git thirdparty/rapier.js');
process.exit(1);
}
// Check if Rust/Cargo is installed
try {
execSync('cargo --version', { stdio: 'pipe' });
} catch {
console.error('❌ Error: Rust/Cargo not found!');
console.error(' Please install Rust: https://rustup.rs/');
process.exit(1);
}
// Check if wasm-pack is installed
try {
execSync('wasm-pack --version', { stdio: 'pipe' });
} catch {
console.error('❌ Error: wasm-pack not found!');
console.error(' Please install it: cargo install wasm-pack');
process.exit(1);
}
// Step 1: Prepare Rust project
if (!runCommand(
'cargo run -p prepare_builds -- -d dim2 -f non-deterministic',
rapierJsDir,
'Step 1/4: Preparing Rust project'
)) {
process.exit(1);
}
// Step 2: Install npm dependencies for rapier2d build
if (!runCommand(
'npm install',
rapier2dBuildDir,
'Step 2/4: Installing npm dependencies'
)) {
process.exit(1);
}
// Step 3: Build WASM
if (!runCommand(
'npm run build',
rapier2dBuildDir,
'Step 3/4: Building WASM'
)) {
process.exit(1);
}
// Step 4: Copy pkg to packages/physics/rapier2d/pkg
console.log('\n📦 Step 4/4: Copying WASM artifacts...');
console.log(` From: ${rapier2dPkgSrc}`);
console.log(` To: ${rapier2dPkgDest}\n`);
if (!existsSync(rapier2dPkgSrc)) {
console.error('❌ Error: Build output not found at', rapier2dPkgSrc);
process.exit(1);
}
// Remove old pkg if exists
if (existsSync(rapier2dPkgDest)) {
rmSync(rapier2dPkgDest, { recursive: true });
}
// Copy new pkg
cpSync(rapier2dPkgSrc, rapier2dPkgDest, { recursive: true });
console.log(' ✅ Copied successfully!\n');
// Step 5: Generate TypeScript source
if (!runCommand(
'pnpm --filter @esengine/rapier2d gen:src',
rootDir,
'Bonus: Generating TypeScript source'
)) {
console.warn('⚠️ Warning: Failed to generate TypeScript source.');
console.warn(' You can run it manually: pnpm --filter @esengine/rapier2d gen:src');
}
console.log('\n✅ Rapier2D WASM build completed successfully!');
console.log('\nNext steps:');
console.log(' 1. Run: pnpm build:editor');
console.log(' 2. Start editor: cd packages/editor/editor-app && pnpm tauri:dev\n');
}
build().catch(error => {
console.error('❌ Build failed:', error);
process.exit(1);
});