feat: 添加跨平台运行时、资产系统和UI适配功能 (#256)
* feat(platform-common): 添加WASM加载器和环境检测API * feat(rapier2d): 新增Rapier2D WASM绑定包 * feat(physics-rapier2d): 添加跨平台WASM加载器 * feat(asset-system): 添加运行时资产目录和bundle格式 * feat(asset-system-editor): 新增编辑器资产管理包 * feat(editor-core): 添加构建系统和模块管理 * feat(editor-app): 重构浏览器预览使用import maps * feat(platform-web): 添加BrowserRuntime和资产读取 * feat(engine): 添加材质系统和着色器管理 * feat(material): 新增材质系统和着色器编辑器 * feat(tilemap): 增强tilemap编辑器和动画系统 * feat(modules): 添加module.json配置 * feat(core): 添加module.json和类型定义更新 * chore: 更新依赖和构建配置 * refactor(plugins): 更新插件模板使用ModuleManifest * chore: 添加第三方依赖库 * chore: 移除BehaviourTree-ai和ecs-astar子模块 * docs: 更新README和文档主题样式 * fix: 修复Rust文档测试和添加rapier2d WASM绑定 * fix(tilemap-editor): 修复画布高DPI屏幕分辨率适配问题 * feat(ui): 添加UI屏幕适配系统(CanvasScaler/SafeArea) * fix(ecs-engine-bindgen): 添加缺失的ecs-framework-math依赖 * fix: 添加缺失的包依赖修复CI构建 * fix: 修复CodeQL检测到的代码问题 * fix: 修复构建错误和缺失依赖 * fix: 修复类型检查错误 * fix(material-system): 修复tsconfig配置支持TypeScript项目引用 * fix(editor-core): 修复Rollup构建配置添加tauri external * fix: 修复CodeQL检测到的代码问题 * fix: 修复CodeQL检测到的代码问题
This commit is contained in:
175
packages/editor-app/src-tauri/src/commands/modules.rs
Normal file
175
packages/editor-app/src-tauri/src/commands/modules.rs
Normal file
@@ -0,0 +1,175 @@
|
||||
//! Engine Module Commands
|
||||
//! 引擎模块命令
|
||||
//!
|
||||
//! Commands for reading engine module configurations.
|
||||
//! 用于读取引擎模块配置的命令。
|
||||
|
||||
use std::path::PathBuf;
|
||||
use tauri::{command, AppHandle};
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
use tauri::Manager;
|
||||
|
||||
/// Module index structure.
|
||||
/// 模块索引结构。
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct ModuleIndex {
|
||||
pub version: String,
|
||||
#[serde(rename = "generatedAt")]
|
||||
pub generated_at: String,
|
||||
pub modules: Vec<ModuleIndexEntry>,
|
||||
}
|
||||
|
||||
/// Module index entry.
|
||||
/// 模块索引条目。
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct ModuleIndexEntry {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
#[serde(rename = "displayName")]
|
||||
pub display_name: String,
|
||||
#[serde(rename = "hasRuntime")]
|
||||
pub has_runtime: bool,
|
||||
#[serde(rename = "editorPackage")]
|
||||
pub editor_package: Option<String>,
|
||||
#[serde(rename = "isCore")]
|
||||
pub is_core: bool,
|
||||
pub category: String,
|
||||
/// JS bundle size in bytes | JS 包大小(字节)
|
||||
#[serde(rename = "jsSize")]
|
||||
pub js_size: Option<u64>,
|
||||
/// Whether this module requires WASM | 是否需要 WASM
|
||||
#[serde(rename = "requiresWasm")]
|
||||
pub requires_wasm: Option<bool>,
|
||||
/// WASM file size in bytes | WASM 文件大小(字节)
|
||||
#[serde(rename = "wasmSize")]
|
||||
pub wasm_size: Option<u64>,
|
||||
}
|
||||
|
||||
/// Get the engine modules directory path.
|
||||
/// 获取引擎模块目录路径。
|
||||
///
|
||||
/// Uses compile-time CARGO_MANIFEST_DIR in dev mode to locate dist/engine.
|
||||
/// 在开发模式下使用编译时的 CARGO_MANIFEST_DIR 来定位 dist/engine。
|
||||
#[allow(unused_variables)]
|
||||
fn get_engine_modules_path(app: &AppHandle) -> Result<PathBuf, String> {
|
||||
// In development mode, use compile-time path
|
||||
// 在开发模式下,使用编译时路径
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
// CARGO_MANIFEST_DIR is set at compile time, pointing to src-tauri
|
||||
// CARGO_MANIFEST_DIR 在编译时设置,指向 src-tauri
|
||||
let dev_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.parent()
|
||||
.map(|p| p.join("dist/engine"))
|
||||
.unwrap_or_else(|| PathBuf::from("dist/engine"));
|
||||
|
||||
if dev_path.exists() {
|
||||
println!("[modules] Using dev path: {:?}", dev_path);
|
||||
return Ok(dev_path);
|
||||
}
|
||||
|
||||
// Fallback: try current working directory
|
||||
// 回退:尝试当前工作目录
|
||||
let cwd_path = std::env::current_dir()
|
||||
.map(|p| p.join("dist/engine"))
|
||||
.unwrap_or_else(|_| PathBuf::from("dist/engine"));
|
||||
|
||||
if cwd_path.exists() {
|
||||
println!("[modules] Using cwd path: {:?}", cwd_path);
|
||||
return Ok(cwd_path);
|
||||
}
|
||||
|
||||
return Err(format!(
|
||||
"Engine modules directory not found in dev mode. Tried: {:?}, {:?}. Run 'pnpm copy-modules' first.",
|
||||
dev_path, cwd_path
|
||||
));
|
||||
}
|
||||
|
||||
// Production: use resource directory
|
||||
// 生产环境:使用资源目录
|
||||
#[cfg(not(debug_assertions))]
|
||||
{
|
||||
let resource_path = app
|
||||
.path()
|
||||
.resource_dir()
|
||||
.map_err(|e| format!("Failed to get resource dir: {}", e))?;
|
||||
|
||||
let prod_path = resource_path.join("engine");
|
||||
|
||||
if prod_path.exists() {
|
||||
return Ok(prod_path);
|
||||
}
|
||||
|
||||
// Fallback: try exe directory
|
||||
// 回退:尝试可执行文件目录
|
||||
let exe_path = std::env::current_exe()
|
||||
.map_err(|e| format!("Failed to get exe path: {}", e))?;
|
||||
let exe_dir = exe_path.parent()
|
||||
.ok_or("Failed to get exe directory")?;
|
||||
|
||||
let exe_engine_path = exe_dir.join("engine");
|
||||
if exe_engine_path.exists() {
|
||||
return Ok(exe_engine_path);
|
||||
}
|
||||
|
||||
Err(format!(
|
||||
"Engine modules directory not found. Tried: {:?}, {:?}",
|
||||
prod_path, exe_engine_path
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the engine modules index.
|
||||
/// 读取引擎模块索引。
|
||||
#[command]
|
||||
pub async fn read_engine_modules_index(app: AppHandle) -> Result<ModuleIndex, String> {
|
||||
println!("[modules] read_engine_modules_index called");
|
||||
let engine_path = get_engine_modules_path(&app)?;
|
||||
println!("[modules] engine_path: {:?}", engine_path);
|
||||
let index_path = engine_path.join("index.json");
|
||||
|
||||
if !index_path.exists() {
|
||||
return Err(format!(
|
||||
"Module index not found at {:?}. Run 'pnpm copy-modules' first.",
|
||||
index_path
|
||||
));
|
||||
}
|
||||
|
||||
let content = std::fs::read_to_string(&index_path)
|
||||
.map_err(|e| format!("Failed to read index.json: {}", e))?;
|
||||
|
||||
serde_json::from_str(&content)
|
||||
.map_err(|e| format!("Failed to parse index.json: {}", e))
|
||||
}
|
||||
|
||||
/// Read a specific module's manifest.
|
||||
/// 读取特定模块的清单。
|
||||
#[command]
|
||||
pub async fn read_module_manifest(app: AppHandle, module_id: String) -> Result<serde_json::Value, String> {
|
||||
let engine_path = get_engine_modules_path(&app)?;
|
||||
let manifest_path = engine_path.join(&module_id).join("module.json");
|
||||
|
||||
if !manifest_path.exists() {
|
||||
return Err(format!(
|
||||
"Module manifest not found for '{}' at {:?}",
|
||||
module_id, manifest_path
|
||||
));
|
||||
}
|
||||
|
||||
let content = std::fs::read_to_string(&manifest_path)
|
||||
.map_err(|e| format!("Failed to read module.json for {}: {}", module_id, e))?;
|
||||
|
||||
serde_json::from_str(&content)
|
||||
.map_err(|e| format!("Failed to parse module.json for {}: {}", module_id, e))
|
||||
}
|
||||
|
||||
/// Get the base path to engine modules directory.
|
||||
/// 获取引擎模块目录的基础路径。
|
||||
#[command]
|
||||
pub async fn get_engine_modules_base_path(app: AppHandle) -> Result<String, String> {
|
||||
let path = get_engine_modules_path(&app)?;
|
||||
path.to_str()
|
||||
.map(|s| s.to_string())
|
||||
.ok_or_else(|| "Failed to convert path to string".to_string())
|
||||
}
|
||||
Reference in New Issue
Block a user