diff --git a/docs/superpowers/specs/2026-07-15-unity-menu-model-translator-design.md b/docs/superpowers/specs/2026-07-15-unity-menu-model-translator-design.md new file mode 100644 index 00000000..a5b58751 --- /dev/null +++ b/docs/superpowers/specs/2026-07-15-unity-menu-model-translator-design.md @@ -0,0 +1,85 @@ +# ModelTranslator Unity 菜单集成设计文档 + +日期:2026-07-15 +状态:已确认 +前置:[2026-07-15-model-translator-design.md](2026-07-15-model-translator-design.md)(CLI 工具本体) + +## 目标 + +在 Unity 编辑器中提供菜单入口,选择工程外的原始 FBX、设置参数(持久化保存)、 +点击确认即调用 `Tools/ModelTranslator/model_translator.py` 转换, +结果输出到 `Client/Assets/Res/[子目录/]<模型名>/` 并自动刷新、选中。 + +CLI 本体**零改动**(`-o` 输出根目录 + 自动建 `<模型名>/` 子目录的既有行为正好满足需求)。 + +## 文件 + +``` +Client/Assets/Editor/ModelTranslatorMenu.cs # 唯一新增文件 +``` + +- `namespace XGame.Editor`,跟随 `MiniGamePublishMenu.cs` 的既有模式 +- 菜单项:`XWorld/模型转换(XPbr)`,priority 803 + +## 窗口布局 + +``` +┌─ 模型转换(XPbr) ────────────────┐ +│ FBX 文件 [D:\...\well.fbx] [选择…] ← EditorUtility.OpenFilePanel,可选工程外文件 +│ 贴图最大尺寸 [2048 ▼] ← 512/1024/2048/4096 +│ 输出子目录 Assets/Res/[______] ← 留空 = 直接放 Res/<模型名> +│ Blender [D:\tools\...\blender.exe] [选择…] +│ Python [python] [选择…] ← 默认用 PATH 里的 python +│ ────────────────────────── +│ [ 转换 ] ← 校验不过/转换中 置灰 +│ (转换日志/警告滚动区,等宽字体) +└────────────────────────────┘ +``` + +## 参数持久化 + +`EditorPrefs`,key 前缀 `XWorld.ModelTranslator.*`: + +| key | 默认值 | +|---|---| +| `maxSize` | 2048 | +| `outSubDir` | ""(直接放 Res 下) | +| `blenderPath` | `D:\tools\blender-5.0.0-windows-x64\blender.exe` | +| `pythonPath` | `python` | +| `lastFbxDir` | 上次选文件的目录(文件对话框起始位置) | + +Blender/Python 路径每台机器不同,EditorPrefs(每用户每机器)正合适,不进版本库。 + +## 执行流程 + +1. **校验**(点转换前):FBX 存在;blender.exe 存在;python 可用。 + 不满足给明确中文提示(如"未找到 python,请安装 Python 3 或在面板中指定路径")。 +2. **启动**:`Process` 异步运行 + ` Tools/ModelTranslator/model_translator.py "" -o "Client/Assets/Res[/子目录]" --max-size N --blender ""`, + 工作目录 = 仓库根。路径全部加引号(中文/空格安全)。 +3. **转换中**:不阻塞编辑器;`EditorApplication.update` 轮询,stdout 实时追加到日志区; + 提供"取消"按钮(kill 进程);"转换"按钮置灰防并发。 +4. **成功**(退出码 0):`AssetDatabase.Refresh()` → `PingObject` 选中 + `Assets/Res/[子目录/]<模型名>/`;日志区显示 CLI 的材质/警告报告。 +5. **失败**(非零退出码):日志区显示 stdout+stderr 尾部,`DisplayDialog` 弹错误提示。 +6. **重复转换**:CLI 复用已有 `.meta` 的 GUID 直接覆盖,场景引用不丢(既有机制,无需处理)。 + +## 边界与错误处理 + +- 窗口关闭时进程还在跑 → kill +- stdout/stderr 用 UTF-8 读取(CLI 输出中文) +- `Assets/Res` 不存在时由 CLI 的 `os.makedirs` 自动创建,无需预建 +- 输出子目录做合法性清洗:剔除 `..`、绝对路径,只允许 Res 下的相对子路径 + +## 测试(手动验证清单) + +C# 编辑器脚本无自动化测试框架,按清单手动验证: + +1. 正常转换 `Tools/ModelTranslator/src/well.fbx` → `Assets/Res/well/` 出现且模型材质正确 +2. FBX 路径不存在 / blender 路径错 → 明确报错,不启动进程 +3. 转换中取消 → 进程被 kill,按钮恢复 +4. 同一模型二次转换 → GUID 不变(场景中已摆放的实例不丢材质) +5. 输出子目录填 `Scene/props` → 结果在 `Assets/Res/Scene/props/<模型名>/` +6. 关闭窗口再打开 → 参数记住上次的值 + +现有 Python 测试不受影响(CLI 未改)。