fix(editor): fix build errors and refactor behavior-tree architecture (#394)
* docs: add editor-app README with setup instructions * docs: add separate EN/CN editor setup guides * fix(editor): fix build errors and refactor behavior-tree architecture - Fix fairygui-editor tsconfig extends path and add missing tsconfig.build.json - Refactor behavior-tree-editor to not depend on asset-system in runtime - Create local BehaviorTreeRuntimeModule for pure runtime logic - Move asset loader registration to editor module install() - Add BehaviorTreeLoader for asset system integration - Fix rapier2d WASM loader to not pass arguments to init() - Add WASM base64 loader config to rapier2d tsup.config - Update README documentation and simplify setup steps
This commit is contained in:
@@ -228,6 +228,7 @@ If you want a complete engine solution with rendering:
|
|||||||
A visual editor built with Tauri for scene management:
|
A visual editor built with Tauri for scene management:
|
||||||
|
|
||||||
- Download from [Releases](https://github.com/esengine/esengine/releases)
|
- Download from [Releases](https://github.com/esengine/esengine/releases)
|
||||||
|
- [Build from source](./packages/editor/editor-app/README.md)
|
||||||
- Supports behavior tree editing, tilemap painting, visual scripting
|
- Supports behavior tree editing, tilemap painting, visual scripting
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
@@ -281,6 +282,7 @@ pnpm test
|
|||||||
|
|
||||||
- [ECS Framework Guide](./packages/framework/core/README.md)
|
- [ECS Framework Guide](./packages/framework/core/README.md)
|
||||||
- [Behavior Tree Guide](./packages/framework/behavior-tree/README.md)
|
- [Behavior Tree Guide](./packages/framework/behavior-tree/README.md)
|
||||||
|
- [Editor Setup Guide](./packages/editor/editor-app/README.md) ([中文](./packages/editor/editor-app/README_CN.md))
|
||||||
- [API Reference](https://esengine.cn/api/README)
|
- [API Reference](https://esengine.cn/api/README)
|
||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ npm install @esengine/world-streaming # 世界流送
|
|||||||
基于 Tauri 构建的可视化编辑器:
|
基于 Tauri 构建的可视化编辑器:
|
||||||
|
|
||||||
- 从 [Releases](https://github.com/esengine/esengine/releases) 下载
|
- 从 [Releases](https://github.com/esengine/esengine/releases) 下载
|
||||||
|
- [从源码构建](./packages/editor/editor-app/README.md)
|
||||||
- 支持行为树编辑、Tilemap 绘制、可视化脚本
|
- 支持行为树编辑、Tilemap 绘制、可视化脚本
|
||||||
|
|
||||||
## 项目结构
|
## 项目结构
|
||||||
@@ -281,6 +282,7 @@ pnpm test
|
|||||||
|
|
||||||
- [ECS 框架指南](./packages/framework/core/README.md)
|
- [ECS 框架指南](./packages/framework/core/README.md)
|
||||||
- [行为树指南](./packages/framework/behavior-tree/README.md)
|
- [行为树指南](./packages/framework/behavior-tree/README.md)
|
||||||
|
- [编辑器启动指南](./packages/editor/editor-app/README_CN.md) ([English](./packages/editor/editor-app/README.md))
|
||||||
- [API 参考](https://esengine.cn/api/README)
|
- [API 参考](https://esengine.cn/api/README)
|
||||||
|
|
||||||
## 社区
|
## 社区
|
||||||
|
|||||||
86
packages/editor/editor-app/README.md
Normal file
86
packages/editor/editor-app/README.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# ESEngine Editor
|
||||||
|
|
||||||
|
A cross-platform desktop visual editor built with Tauri 2.x + React 18.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before running the editor, ensure you have the following installed:
|
||||||
|
|
||||||
|
- **Node.js** >= 18.x
|
||||||
|
- **pnpm** >= 10.x
|
||||||
|
- **Rust** >= 1.70 (for Tauri)
|
||||||
|
- **Platform-specific dependencies**:
|
||||||
|
- **Windows**: Microsoft Visual Studio C++ Build Tools
|
||||||
|
- **macOS**: Xcode Command Line Tools (`xcode-select --install`)
|
||||||
|
- **Linux**: See [Tauri prerequisites](https://tauri.app/v1/guides/getting-started/prerequisites)
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Clone and Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/esengine/esengine.git
|
||||||
|
cd esengine
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Build Dependencies
|
||||||
|
|
||||||
|
From the project root:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build:editor
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Run Editor
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd packages/editor/editor-app
|
||||||
|
pnpm tauri:dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
| Script | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `pnpm tauri:dev` | Run editor in development mode with hot-reload |
|
||||||
|
| `pnpm tauri:build` | Build production application |
|
||||||
|
| `pnpm build:sdk` | Build editor-runtime SDK |
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
editor-app/
|
||||||
|
├── src/ # React application source
|
||||||
|
│ ├── components/ # UI components
|
||||||
|
│ ├── panels/ # Editor panels
|
||||||
|
│ └── services/ # Core services
|
||||||
|
├── src-tauri/ # Tauri (Rust) backend
|
||||||
|
├── public/ # Static assets
|
||||||
|
└── scripts/ # Build scripts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Build Errors
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm clean
|
||||||
|
pnpm install
|
||||||
|
pnpm build:editor
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rust/Tauri Errors
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rustup update
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [ESEngine Documentation](https://esengine.cn/)
|
||||||
|
- [Tauri Documentation](https://tauri.app/)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License
|
||||||
86
packages/editor/editor-app/README_CN.md
Normal file
86
packages/editor/editor-app/README_CN.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# ESEngine 编辑器
|
||||||
|
|
||||||
|
基于 Tauri 2.x + React 18 构建的跨平台桌面可视化编辑器。
|
||||||
|
|
||||||
|
## 环境要求
|
||||||
|
|
||||||
|
运行编辑器前,请确保已安装以下环境:
|
||||||
|
|
||||||
|
- **Node.js** >= 18.x
|
||||||
|
- **pnpm** >= 10.x
|
||||||
|
- **Rust** >= 1.70 (Tauri 需要)
|
||||||
|
- **平台相关依赖**:
|
||||||
|
- **Windows**: Microsoft Visual Studio C++ Build Tools
|
||||||
|
- **macOS**: Xcode Command Line Tools (`xcode-select --install`)
|
||||||
|
- **Linux**: 参考 [Tauri 环境配置](https://tauri.app/v1/guides/getting-started/prerequisites)
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 克隆并安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/esengine/esengine.git
|
||||||
|
cd esengine
|
||||||
|
pnpm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 构建依赖
|
||||||
|
|
||||||
|
在项目根目录执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm build:editor
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 启动编辑器
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd packages/editor/editor-app
|
||||||
|
pnpm tauri:dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## 可用脚本
|
||||||
|
|
||||||
|
| 脚本 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `pnpm tauri:dev` | 开发模式运行编辑器(支持热重载)|
|
||||||
|
| `pnpm tauri:build` | 构建生产版本应用 |
|
||||||
|
| `pnpm build:sdk` | 构建 editor-runtime SDK |
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
editor-app/
|
||||||
|
├── src/ # React 应用源码
|
||||||
|
│ ├── components/ # UI 组件
|
||||||
|
│ ├── panels/ # 编辑器面板
|
||||||
|
│ └── services/ # 核心服务
|
||||||
|
├── src-tauri/ # Tauri (Rust) 后端
|
||||||
|
├── public/ # 静态资源
|
||||||
|
└── scripts/ # 构建脚本
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 构建错误
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm clean
|
||||||
|
pnpm install
|
||||||
|
pnpm build:editor
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rust/Tauri 错误
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rustup update
|
||||||
|
```
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
- [ESEngine 文档](https://esengine.cn/)
|
||||||
|
- [Tauri 文档](https://tauri.app/)
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT License
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"build": "npm run build:sdk && tsc && vite build",
|
"build": "npm run build:sdk && tsc && vite build",
|
||||||
"build:watch": "vite build --watch",
|
"build:watch": "vite build --watch",
|
||||||
"tauri": "tauri",
|
"tauri": "tauri",
|
||||||
"copy-modules": "node ../../scripts/copy-engine-modules.mjs",
|
"copy-modules": "node ../../../scripts/copy-engine-modules.mjs",
|
||||||
"tauri:dev": "npm run build:sdk && npm run copy-modules && tauri dev",
|
"tauri:dev": "npm run build:sdk && npm run copy-modules && tauri dev",
|
||||||
"bundle:runtime": "node scripts/bundle-runtime.mjs",
|
"bundle:runtime": "node scripts/bundle-runtime.mjs",
|
||||||
"tauri:build": "npm run build:sdk && npm run copy-modules && npm run bundle:runtime && tauri build",
|
"tauri:build": "npm run build:sdk && npm run copy-modules && npm run bundle:runtime && tauri build",
|
||||||
|
|||||||
1010
packages/editor/editor-app/src-tauri/Cargo.lock
generated
1010
packages/editor/editor-app/src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -10,16 +10,16 @@ name = "ecs_editor_lib"
|
|||||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { version = "2.0", features = [] }
|
tauri-build = { version = "2", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "2.0", features = ["protocol-asset"] }
|
tauri = { version = "2", features = ["protocol-asset"] }
|
||||||
tauri-plugin-shell = "2.0"
|
tauri-plugin-shell = "2"
|
||||||
tauri-plugin-dialog = "2.0"
|
tauri-plugin-dialog = "2"
|
||||||
tauri-plugin-fs = "2.0"
|
tauri-plugin-fs = "2"
|
||||||
tauri-plugin-updater = "2"
|
tauri-plugin-updater = "2"
|
||||||
tauri-plugin-http = "2.0"
|
tauri-plugin-http = "2"
|
||||||
tauri-plugin-cli = "2.0"
|
tauri-plugin-cli = "2"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@esengine/ecs-framework": "workspace:*",
|
"@esengine/ecs-framework": "workspace:*",
|
||||||
"@esengine/engine-core": "workspace:*",
|
"@esengine/engine-core": "workspace:*",
|
||||||
|
"@esengine/asset-system": "workspace:*",
|
||||||
"@esengine/editor-core": "workspace:*",
|
"@esengine/editor-core": "workspace:*",
|
||||||
"@esengine/editor-runtime": "workspace:*",
|
"@esengine/editor-runtime": "workspace:*",
|
||||||
"@esengine/node-editor": "workspace:*",
|
"@esengine/node-editor": "workspace:*",
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @zh ESEngine 行为树运行时模块
|
||||||
|
* @en ESEngine Behavior Tree Runtime Module
|
||||||
|
*
|
||||||
|
* @zh 纯运行时模块,不依赖 asset-system。资产加载由编辑器在 install 时注册。
|
||||||
|
* @en Pure runtime module, no asset-system dependency. Asset loading is registered by editor during install.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { IScene, ServiceContainer, IComponentRegistry } from '@esengine/ecs-framework';
|
||||||
|
import type { IRuntimeModule, SystemContext } from '@esengine/engine-core';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BehaviorTreeRuntimeComponent,
|
||||||
|
BehaviorTreeExecutionSystem,
|
||||||
|
BehaviorTreeAssetManager,
|
||||||
|
GlobalBlackboardService,
|
||||||
|
BehaviorTreeSystemToken
|
||||||
|
} from '@esengine/behavior-tree';
|
||||||
|
|
||||||
|
export class BehaviorTreeRuntimeModule implements IRuntimeModule {
|
||||||
|
registerComponents(registry: IComponentRegistry): void {
|
||||||
|
registry.register(BehaviorTreeRuntimeComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerServices(services: ServiceContainer): void {
|
||||||
|
if (!services.isRegistered(GlobalBlackboardService)) {
|
||||||
|
services.registerSingleton(GlobalBlackboardService);
|
||||||
|
}
|
||||||
|
if (!services.isRegistered(BehaviorTreeAssetManager)) {
|
||||||
|
services.registerSingleton(BehaviorTreeAssetManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createSystems(scene: IScene, context: SystemContext): void {
|
||||||
|
const ecsServices = (context as { ecsServices?: ServiceContainer }).ecsServices;
|
||||||
|
const behaviorTreeSystem = new BehaviorTreeExecutionSystem(ecsServices);
|
||||||
|
|
||||||
|
if (context.isEditor) {
|
||||||
|
behaviorTreeSystem.enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
scene.addSystem(behaviorTreeSystem);
|
||||||
|
context.services.register(BehaviorTreeSystemToken, behaviorTreeSystem);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,8 +30,11 @@ import {
|
|||||||
LocaleService,
|
LocaleService,
|
||||||
} from '@esengine/editor-runtime';
|
} from '@esengine/editor-runtime';
|
||||||
|
|
||||||
// Runtime imports from @esengine/behavior-tree package
|
// Runtime imports
|
||||||
import { BehaviorTreeRuntimeComponent, BehaviorTreeRuntimeModule } from '@esengine/behavior-tree';
|
import { BehaviorTreeRuntimeComponent, BehaviorTreeAssetType } from '@esengine/behavior-tree';
|
||||||
|
import { AssetManagerToken } from '@esengine/asset-system';
|
||||||
|
import { BehaviorTreeRuntimeModule } from './BehaviorTreeRuntimeModule';
|
||||||
|
import { BehaviorTreeLoader } from './runtime/BehaviorTreeLoader';
|
||||||
|
|
||||||
// Editor components and services
|
// Editor components and services
|
||||||
import { BehaviorTreeService } from './services/BehaviorTreeService';
|
import { BehaviorTreeService } from './services/BehaviorTreeService';
|
||||||
@@ -71,6 +74,10 @@ export class BehaviorTreeEditorModule implements IEditorModuleLoader {
|
|||||||
// 设置插件上下文
|
// 设置插件上下文
|
||||||
PluginContext.setServices(services);
|
PluginContext.setServices(services);
|
||||||
|
|
||||||
|
// 注册行为树资产加载器到 AssetManager
|
||||||
|
// Register behavior tree asset loader to AssetManager
|
||||||
|
this.registerAssetLoader();
|
||||||
|
|
||||||
// 注册服务
|
// 注册服务
|
||||||
this.registerServices(services);
|
this.registerServices(services);
|
||||||
|
|
||||||
@@ -92,6 +99,22 @@ export class BehaviorTreeEditorModule implements IEditorModuleLoader {
|
|||||||
logger.info('BehaviorTree editor module installed');
|
logger.info('BehaviorTree editor module installed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册行为树资产加载器
|
||||||
|
* Register behavior tree asset loader
|
||||||
|
*/
|
||||||
|
private registerAssetLoader(): void {
|
||||||
|
try {
|
||||||
|
const assetManager = PluginAPI.resolve(AssetManagerToken);
|
||||||
|
if (assetManager) {
|
||||||
|
assetManager.registerLoader(BehaviorTreeAssetType, new BehaviorTreeLoader());
|
||||||
|
logger.info('BehaviorTree asset loader registered');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn('Failed to register asset loader:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private registerAssetCreationMappings(services: ServiceContainer): void {
|
private registerAssetCreationMappings(services: ServiceContainer): void {
|
||||||
try {
|
try {
|
||||||
const fileActionRegistry = services.resolve<FileActionRegistry>(IFileActionRegistry);
|
const fileActionRegistry = services.resolve<FileActionRegistry>(IFileActionRegistry);
|
||||||
@@ -376,7 +399,7 @@ export const BehaviorTreePlugin: IEditorPlugin = {
|
|||||||
editorModule: new BehaviorTreeEditorModule(),
|
editorModule: new BehaviorTreeEditorModule(),
|
||||||
};
|
};
|
||||||
|
|
||||||
export { BehaviorTreeRuntimeModule };
|
// BehaviorTreeRuntimeModule is internal, not re-exported
|
||||||
|
|
||||||
// Re-exports for editor functionality
|
// Re-exports for editor functionality
|
||||||
export { PluginContext } from './PluginContext';
|
export { PluginContext } from './PluginContext';
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* @zh ESEngine 资产加载器
|
||||||
|
* @en ESEngine asset loader
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Core } from '@esengine/ecs-framework';
|
||||||
|
import {
|
||||||
|
BehaviorTreeAssetManager,
|
||||||
|
EditorToBehaviorTreeDataConverter,
|
||||||
|
BehaviorTreeAssetType,
|
||||||
|
type BehaviorTreeData
|
||||||
|
} from '@esengine/behavior-tree';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 行为树资产接口
|
||||||
|
* @en Behavior tree asset interface
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface IBehaviorTreeAsset {
|
||||||
|
data: BehaviorTreeData;
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 行为树加载器
|
||||||
|
* @en Behavior tree loader implementing IAssetLoader interface
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export class BehaviorTreeLoader {
|
||||||
|
readonly supportedType = BehaviorTreeAssetType;
|
||||||
|
readonly supportedExtensions = ['.btree'];
|
||||||
|
readonly contentType = 'text' as const;
|
||||||
|
|
||||||
|
async parse(content: { text?: string }, context: { metadata: { path: string } }): Promise<IBehaviorTreeAsset> {
|
||||||
|
if (!content.text) {
|
||||||
|
throw new Error('Behavior tree content is empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
const treeData = EditorToBehaviorTreeDataConverter.fromEditorJSON(content.text);
|
||||||
|
const assetPath = context.metadata.path;
|
||||||
|
treeData.id = assetPath;
|
||||||
|
|
||||||
|
const btAssetManager = Core.services.tryResolve(BehaviorTreeAssetManager);
|
||||||
|
if (btAssetManager) {
|
||||||
|
btAssetManager.loadAsset(treeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: treeData,
|
||||||
|
path: assetPath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(asset: IBehaviorTreeAsset): void {
|
||||||
|
const btAssetManager = Core.services.tryResolve(BehaviorTreeAssetManager);
|
||||||
|
if (btAssetManager && asset.data) {
|
||||||
|
btAssetManager.unloadAsset(asset.data.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,15 @@
|
|||||||
{
|
{
|
||||||
|
"extends": "../../../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2020",
|
"composite": false,
|
||||||
"module": "ES2020",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"lib": ["ES2020", "DOM"],
|
|
||||||
"outDir": "./dist",
|
|
||||||
"rootDir": "./src",
|
|
||||||
"strict": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"resolveJsonModule": true,
|
"skipLibCheck": true,
|
||||||
"experimentalDecorators": true,
|
"moduleResolution": "bundler"
|
||||||
"emitDecoratorMetadata": true
|
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
"exclude": ["node_modules", "dist"]
|
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ 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'
|
tsconfig: 'tsconfig.build.json'
|
||||||
});
|
});
|
||||||
|
|||||||
13
packages/editor/plugins/fairygui-editor/tsconfig.build.json
Normal file
13
packages/editor/plugins/fairygui-editor/tsconfig.build.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": false,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"jsx": "react-jsx"
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "../build-config/tsconfig.json",
|
"extends": "../../../../tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export default defineConfig({
|
|||||||
format: ['esm'],
|
format: ['esm'],
|
||||||
dts: true,
|
dts: true,
|
||||||
clean: true,
|
clean: true,
|
||||||
|
tsconfig: 'tsconfig.build.json',
|
||||||
external: [
|
external: [
|
||||||
'react',
|
'react',
|
||||||
'react-dom',
|
'react-dom',
|
||||||
|
|||||||
@@ -121,9 +121,9 @@ export class WeChatRapier2DLoader implements IWasmLibraryLoader<RapierModule> {
|
|||||||
// 导入 Rapier2D 标准版
|
// 导入 Rapier2D 标准版
|
||||||
const RAPIER = await import('@esengine/rapier2d');
|
const RAPIER = await import('@esengine/rapier2d');
|
||||||
|
|
||||||
// 初始化 WASM - 标准版需要提供 WASM 路径
|
// 初始化 WASM - WASM 已经作为 base64 嵌入到包中
|
||||||
const wasmPath = this._config.minigame?.wasmPath || 'wasm/rapier_wasm2d_bg.wasm';
|
// Initialize WASM - WASM is embedded as base64 in the package
|
||||||
await RAPIER.init(wasmPath);
|
await RAPIER.init();
|
||||||
|
|
||||||
return RAPIER;
|
return RAPIER;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -53,10 +53,9 @@ export class WebRapier2DLoader implements IWasmLibraryLoader<RapierModule> {
|
|||||||
// 动态导入标准版
|
// 动态导入标准版
|
||||||
const RAPIER = await import('@esengine/rapier2d');
|
const RAPIER = await import('@esengine/rapier2d');
|
||||||
|
|
||||||
// 初始化 WASM - 标准版需要提供 WASM 路径
|
// 初始化 WASM - WASM 已经作为 base64 嵌入到包中
|
||||||
// 构建时 WASM 文件会被复制到 wasm/ 目录
|
// Initialize WASM - WASM is embedded as base64 in the package
|
||||||
const wasmPath = this._config.web?.wasmPath || 'wasm/rapier_wasm2d_bg.wasm';
|
await RAPIER.init();
|
||||||
await RAPIER.init(wasmPath);
|
|
||||||
|
|
||||||
console.log(`[${this._config.name}] 加载完成`);
|
console.log(`[${this._config.name}] 加载完成`);
|
||||||
return RAPIER;
|
return RAPIER;
|
||||||
|
|||||||
@@ -19,11 +19,13 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"gen:src": "node scripts/gen-src.mjs",
|
"gen:src": "node scripts/gen-src.mjs",
|
||||||
"build": "pnpm gen:src && tsup",
|
"build": "tsup",
|
||||||
"clean": "rimraf dist src"
|
"build:regen": "pnpm gen:src && tsup",
|
||||||
|
"clean": "rimraf dist"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"base64-js": "^1.5.1",
|
||||||
"rimraf": "^5.0.0",
|
"rimraf": "^5.0.0",
|
||||||
"tsup": "^8.0.0",
|
"tsup": "^8.0.0",
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
|
|||||||
@@ -91,9 +91,8 @@ export class KinematicCharacterController {
|
|||||||
*/
|
*/
|
||||||
public setUp(vector: Vector) {
|
public setUp(vector: Vector) {
|
||||||
let rawVect = VectorOps.intoRaw(vector);
|
let rawVect = VectorOps.intoRaw(vector);
|
||||||
const result = this.raw.setUp(rawVect);
|
return this.raw.setUp(rawVect);
|
||||||
rawVect.free();
|
rawVect.free();
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public applyImpulsesToDynamicBodies(): boolean {
|
public applyImpulsesToDynamicBodies(): boolean {
|
||||||
|
|||||||
@@ -28,9 +28,6 @@ export class DynamicRayCastVehicleController {
|
|||||||
bodies: RigidBodySet,
|
bodies: RigidBodySet,
|
||||||
colliders: ColliderSet,
|
colliders: ColliderSet,
|
||||||
) {
|
) {
|
||||||
if (typeof RawDynamicRayCastVehicleController === 'undefined') {
|
|
||||||
throw new Error('DynamicRayCastVehicleController is not available in 2D mode');
|
|
||||||
}
|
|
||||||
this.raw = new RawDynamicRayCastVehicleController(chassis.handle);
|
this.raw = new RawDynamicRayCastVehicleController(chassis.handle);
|
||||||
this.broadPhase = broadPhase;
|
this.broadPhase = broadPhase;
|
||||||
this.narrowPhase = narrowPhase;
|
this.narrowPhase = narrowPhase;
|
||||||
|
|||||||
@@ -1,60 +1,12 @@
|
|||||||
/**
|
// @ts-ignore
|
||||||
* RAPIER initialization module with dynamic WASM loading support.
|
import wasmBase64 from "../pkg/rapier_wasm2d_bg.wasm";
|
||||||
* 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(input?: InitInput): Promise<void> {
|
export async function init() {
|
||||||
if (initialized) {
|
await wasmInit(base64.toByteArray(wasmBase64 as unknown as string).buffer);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await wasmInit(input);
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if RAPIER is already initialized.
|
|
||||||
* 检查 RAPIER 是否已初始化。
|
|
||||||
*/
|
|
||||||
export function isInitialized(): boolean {
|
|
||||||
return initialized;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export class VectorOps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: type ram: RawVector?
|
// FIXME: type ram: RawVector?
|
||||||
public static fromRaw(raw: RawVector): Vector | null {
|
public static fromRaw(raw: RawVector): Vector {
|
||||||
if (!raw) return null;
|
if (!raw) return null;
|
||||||
|
|
||||||
let res = VectorOps.new(raw.x, raw.y);
|
let res = VectorOps.new(raw.x, raw.y);
|
||||||
@@ -56,7 +56,7 @@ export class RotationOps {
|
|||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static fromRaw(raw: RawRotation): Rotation | null {
|
public static fromRaw(raw: RawRotation): Rotation {
|
||||||
if (!raw) return null;
|
if (!raw) return null;
|
||||||
|
|
||||||
let res = raw.angle;
|
let res = raw.angle;
|
||||||
|
|||||||
@@ -7,4 +7,7 @@ export default defineConfig({
|
|||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
clean: true,
|
clean: true,
|
||||||
external: ["../pkg/rapier_wasm2d.js"],
|
external: ["../pkg/rapier_wasm2d.js"],
|
||||||
|
loader: {
|
||||||
|
".wasm": "base64",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -569,6 +569,9 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../../framework/behavior-tree
|
version: link:../../../framework/behavior-tree
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@esengine/asset-system':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../../engine/asset-system
|
||||||
'@esengine/build-config':
|
'@esengine/build-config':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../../tools/build-config
|
version: link:../../../tools/build-config
|
||||||
@@ -1861,6 +1864,9 @@ importers:
|
|||||||
|
|
||||||
packages/physics/rapier2d:
|
packages/physics/rapier2d:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
base64-js:
|
||||||
|
specifier: ^1.5.1
|
||||||
|
version: 1.5.1
|
||||||
rimraf:
|
rimraf:
|
||||||
specifier: ^5.0.0
|
specifier: ^5.0.0
|
||||||
version: 5.0.10
|
version: 5.0.10
|
||||||
|
|||||||
Reference in New Issue
Block a user