diff --git a/.agent/rules/project-rules.md b/.gemini/rules/project-rules.md similarity index 100% rename from .agent/rules/project-rules.md rename to .gemini/rules/project-rules.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8bdea99 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# **/dist +**/node_modules +**/package-lock.json \ No newline at end of file diff --git a/CODE_REVIEW.md b/CODE_REVIEW.md deleted file mode 100644 index 9365deb..0000000 --- a/CODE_REVIEW.md +++ /dev/null @@ -1,202 +0,0 @@ -# MCP Bridge 插件代码审查报告 - -**审查日期**: 2026-02-02 -**审查人**: AI Assistant - -## 📋 审查概要 - -| 项目 | 状态 | -|------|------| -| 代码行数 | `main.js` (1560行), `scene-script.js` (560行) | -| 测试脚本 | 4个 (`run_tests.js`, `test_find_file.js`, `test_undo.js`, `test_vfx.js`) | -| 功能完成度 | **高** - 大部分核心功能已实现 | -| 代码质量 | **中等** - 存在重复代码和结构问题 | - ---- - -## 🔴 高优先级问题 (需要立即修复) - -### 1. 重复函数定义 (严重) - -在 `main.js` 中发现以下重复定义的函数: - -| 函数名 | 第一次出现 | 第二次出现 | -|--------|-----------|-----------| -| `validateScript` | 行 1337-1369 | 行 1424-1456 | -| `get-server-state` (message) | 行 1375-1377 | 行 1408-1415 | -| `executeMenuItem` | 行 1243-1254 | 行 1317-1335 (同名但实现不同) | - -> ⚠️ **警告**: 重复函数会导致后定义的覆盖先定义的,可能造成意外行为。第二个 `validateScript` (行 1424-1456) 使用了 `loadMeta` 而不是 `loadAny`,可能无法正确读取脚本内容。 - -**建议修复**: -- 删除重复的 `validateScript` 函数 (保留行 1337-1369 的版本,它使用 `loadAny`) -- 合并两个 `get-server-state` 消息处理器 (第二个更完整,包含 `autoStart`) -- 审查并合并两个 `executeMenuItem` 的实现 - ---- - -### 2. TypeScript 脚本验证缺失 - -```javascript -// 对于 TypeScript 脚本,这里可以添加更复杂的验证逻辑 -callback(null, { valid: true, message: 'Script syntax is valid' }); -``` - -`validate_script` 工具对 TypeScript `.ts` 文件没有实际验证逻辑,直接返回 valid: true。 - -**建议修复**: -- 集成 TypeScript 编译器进行语法检查 -- 或者使用 `require('typescript').transpileModule()` 进行基本验证 - ---- - -## 🟡 中优先级问题 (建议修复) - -### 3. 菜单项执行功能受限 - -```javascript -// 通用尝试 (可能不工作,取决于编辑器版本) -// Editor.Ipc.sendToMain('ui:menu-click', menuPath); -// 兜底:仅记录日志,暂不支持通用菜单点击 -addLog("warn", "Generic menu execution partial support."); -``` - -`execute_menu_item` 工具只对 `File/Save Scene` 有实际作用,其他菜单项仅记录日志。 - -**建议修复**: -- 调研 Cocos Creator 2.4.x 的菜单执行 IPC 接口 -- 或者添加常用菜单项的映射表 - ---- - -### 4. 颜色属性 Undo 不支持 - -```javascript -// 暂且忽略颜色的 Undo,先保证 Transform 的 Undo。 -Editor.Scene.callSceneScript("mcp-bridge", "update-node-transform", { id, color }, (err) => { - if (err) addLog("warn", "Color update failed or partial"); -}); -``` - -`update_node_transform` 中位置和缩放使用 `scene:set-property` 支持 Undo,但颜色通过 scene-script 修改,不支持 Undo。 - -**建议修复**: -- 研究如何通过 `scene:set-property` 设置颜色属性 - ---- - -### 5. 材质/纹理创建功能不完整 - -`manage_material` 和 `manage_texture` 的 `create` 操作创建的是 JSON 元数据文件,而不是真正的材质或纹理资源。 - -```javascript -// 创建材质资源 -const materialContent = JSON.stringify({ - __type__: "cc.Material", - // ... -}); -``` - -**建议修复**: -- 文档中说明此工具的限制 -- 或者使用 Cocos Creator 的资源创建 API - ---- - -## 🟢 低优先级问题 (可优化) - -### 6. 缺失的功能模块 - -根据 `DEVELOPMENT_PLAN.md`,以下功能未完全实现或可扩展: - -| 功能 | 状态 | 说明 | -|------|------|------| -| Git 集成 (`get_sha`) | ❌ 未实现 | 获取当前版本库信息 | -| ScriptableObject 管理 | ❌ 未实现 | 类似 Unity 的 ScriptableObject | -| 国际化支持 | ❌ 未实现 | 多语言界面 | -| 插件商店发布 | ❌ 未完成 | 打包和发布流程 | - ---- - -### 7. 代码结构优化建议 - -1. **拆分 `main.js`**: 1560 行代码过于庞大,建议拆分为: - - `tools/scene-tools.js` - 场景相关工具 - - `tools/asset-tools.js` - 资源管理工具 - - `tools/editor-tools.js` - 编辑器控制工具 - -2. **统一错误处理**: 部分函数直接 `return callback(error)`,部分使用 `callback(err, null)`,建议统一风格。 - -3. **添加 JSDoc 注释**: 核心函数缺少文档注释。 - ---- - -### 8. 测试覆盖不完整 - -目前测试脚本仅覆盖: -- ✅ 基础连接和节点操作 (`run_tests.js`) -- ✅ 文件搜索 (`test_find_file.js`) -- ✅ 撤销/重做 (`test_undo.js`) -- ✅ 粒子系统 (`test_vfx.js`) - -未覆盖的功能: -- ❌ `manage_material` / `manage_texture` -- ❌ `scene_management` / `prefab_management` -- ❌ `apply_text_edits` -- ❌ `batch_execute` - ---- - -## 📌 修复优先级排序 - -| 序号 | 问题 | 优先级 | 预计工时 | -|------|------|--------|----------| -| 1 | 删除重复函数 | 🔴 高 | 0.5h | -| 2 | 合并 `get-server-state` | 🔴 高 | 0.5h | -| 3 | TypeScript 验证 | 🟡 中 | 2h | -| 4 | 菜单执行增强 | 🟡 中 | 1h | -| 5 | 颜色 Undo 支持 | 🟡 中 | 1h | -| 6 | 测试覆盖扩展 | 🟢 低 | 4h | -| 7 | 代码拆分重构 | 🟢 低 | 8h | - ---- - -## 🚀 下一步行动建议 - -1. **立即修复**: 删除 `main.js` 中的重复函数定义 -2. **短期**: 完善 TypeScript 验证和测试覆盖 -3. **中期**: 优化代码结构,拆分大文件 -4. **长期**: 实现 Git 集成,准备插件商店发布 - ---- - -## 📝 附录:已实现功能清单 - -| 工具名称 | 状态 | 说明 | -|---------|------|------| -| `get_selected_node` | ✅ | 获取选中节点 | -| `set_node_name` | ✅ | 修改节点名称 | -| `save_scene` | ✅ | 保存场景 | -| `get_scene_hierarchy` | ✅ | 获取场景层级 | -| `update_node_transform` | ✅ | 修改节点变换 | -| `create_scene` | ✅ | 创建场景 | -| `create_prefab` | ✅ | 创建预制体 | -| `open_scene` | ✅ | 打开场景 | -| `create_node` | ✅ | 创建节点 | -| `manage_components` | ✅ | 管理组件 | -| `manage_script` | ✅ | 管理脚本 | -| `batch_execute` | ✅ | 批量执行 | -| `manage_asset` | ✅ | 管理资源 | -| `scene_management` | ✅ | 场景管理 | -| `prefab_management` | ✅ | 预制体管理 | -| `manage_editor` | ✅ | 编辑器管理 | -| `find_gameobjects` | ✅ | 查找节点 | -| `manage_material` | ⚠️ | 部分实现 | -| `manage_texture` | ⚠️ | 部分实现 | -| `execute_menu_item` | ⚠️ | 部分实现 | -| `apply_text_edits` | ✅ | 文本编辑 | -| `read_console` | ✅ | 读取控制台 | -| `validate_script` | ⚠️ | 仅支持 JS | -| `find_in_file` | ✅ | 文件搜索 | -| `manage_undo` | ✅ | 撤销/重做 | -| `manage_vfx` | ✅ | 粒子系统 | diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index b4145bb..98fcde5 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -2,6 +2,17 @@ 本文档记录了 MCP Bridge 插件的完整开发流程,包括核心架构设计、功能实现、测试与调试等各个阶段。 +## 0. 项目开发规范 (Project Rules) + +> [!IMPORTANT] +> 所有贡献者必须严格遵守以下规则: + +1. **语言与沟通**: 所有注释、文档、计划、任务及 AI 回复必须使用 **简体中文 (Simplified Chinese)**。 +2. **技术栈**: 新脚本必须使用 **TypeScript** (`.ts`)。禁止创建新的 `.js` 文件 (除非是构建脚本或测试配置)。 +3. **文档**: 所有修改或创建的脚本必须包含详细的 JSDoc 格式注释。 +4. **架构**: 严禁引入新的架构模式或重型外部库。必须复用现有的 Cocos Creator 管理器和工具类。 +5. **隔离原则**: 保持 `main.js` (主进程) 与 `scene-script.js` (渲染进程) 的严格职责分离。即使看似方便,也不要在 `main.js` 中直接操作场景节点对象。 + ## 1. 项目初始化 ### 1.1 目录结构搭建 @@ -413,232 +424,88 @@ manageAsset(args, callback) { - 防止路径遍历攻击 - 限制服务访问范围 -## 11. 开发状态 +## 11. 开发路线图 (Roadmap) -### 11.1 已完成的任务 +### 11.1 第三阶段开发计划(已完成) -#### 第一阶段 -- ✅ HTTP 服务接口实现 -- ✅ 场景节点操作工具 -- ✅ 资源管理工具 -- ✅ 组件管理工具 -- ✅ 脚本管理工具(默认创建 TypeScript 脚本) -- ✅ 批处理执行工具 -- ✅ 资产管理工具 -- ✅ 实时日志系统 -- ✅ 自动启动功能 -- ✅ 面板界面实现 +| 任务 | 状态 | 描述 | +|------|------|------| +| 编辑器管理工具实现 | ✅ 完成 | 实现 manage_editor 工具,支持编辑器状态控制和操作执行 | +| 游戏对象查找工具实现 | ✅ 完成 | 实现 find_gameobjects 工具,支持根据条件查找场景节点 | +| 材质和纹理管理工具实现 | ✅ 完成 | 实现 manage_material 和 manage_texture 工具,支持材质和纹理资源管理 | +| 菜单项执行工具实现 | ✅ 完成 | 实现 execute_menu_item 工具,支持执行 Cocos Creator 菜单项 | +| 代码编辑增强工具实现 | ✅ 完成 | 实现 apply_text_edits 工具,支持文本编辑操作应用 | +| 控制台读取工具实现 | ✅ 完成 | 实现 read_console 工具,支持读取编辑器控制台输出 | +| 脚本验证工具实现 | ✅ 完成 | 实现 validate_script 工具,支持脚本语法验证 | -#### 第二阶段 -- ✅ 场景管理工具(scene_management) - - 创建场景 - - 删除场景 - - 复制场景 - - 获取场景信息 -- ✅ 预制体管理工具(prefab_management) - - 创建预制体 - - 更新预制体 - - 实例化预制体 - - 获取预制体信息 -- ✅ 面板布局优化 - - 响应式设计 - - 滚动条支持 - - 小窗口适配 -- ✅ 移除旧工具 - - 删除了 create_scene 工具(功能整合到 scene_management) - - 删除了 create_prefab 工具(功能整合到 prefab_management) -- ✅ README.md 文档更新 -- ✅ 代码提交到本地仓库 +### 11.2 第四阶段开发计划(已完成) -#### 第三阶段 -- ✅ 编辑器管理工具(manage_editor) - - 获取选中对象 - - 设置选中状态 - - 刷新编辑器 -- ✅ 游戏对象查找工具(find_gameobjects) - - 根据名称、标签、组件、激活状态查找节点 - - 支持递归和非递归查找 -- ✅ 材质管理工具(manage_material) - - 创建、删除、获取材质信息 -- ✅ 纹理管理工具(manage_texture) - - 创建、删除、获取纹理信息 -- ✅ 菜单项执行工具(execute_menu_item) - - 执行 Cocos Creator 编辑器菜单项 -- ✅ 代码编辑增强工具(apply_text_edits) - - 支持插入、删除、替换文本操作 -- ✅ 控制台读取工具(read_console) - - 读取编辑器控制台输出 - - 支持按类型过滤和限制输出数量 -- ✅ 脚本验证工具(validate_script) - - 验证脚本语法正确性 -- ✅ 面板工具说明功能 - - 添加工具说明框 - - 显示详细的工具描述和参数说明 +| 任务 | 状态 | 描述 | +|------|------|------| +| 测试功能实现 | ✅ 完成 | 实现 run_tests.js 脚本,支持运行自动化测试用例 | +| 错误处理增强 | ✅ 完成 | 完善 HTTP 服务和工具调用的错误日志记录 | -### 11.2 未完成的任务 +### 11.3 差异填补阶段(Gap Filling)- 已完成 -- ❌ 代码推送到远程仓库(认证错误) -- ❌ 测试用例编写 -- ❌ 性能优化 -- ❌ 错误处理增强 -- ❌ 安全配置 +| 任务 | 状态 | 描述 | +|------|------|------| +| 全局文件搜索 | ✅ 完成 | 实现 find_in_file 工具 | +| 撤销/重做支持 | ✅ 完成 | 实现 manage_undo 工具,并重构核心操作支持撤销 | +| 特效管理 | ✅ 完成 | 实现 manage_vfx 工具,支持粒子系统管理 | -### 11.3 后续需要完成的任务 +### 11.4 第六阶段:可靠性与体验优化(已完成) -#### 高优先级 -1. **代码推送**:解决远程仓库认证问题,完成代码推送 -2. **测试用例**:为核心工具编写测试用例 -3. **安全配置**:添加 IP 白名单和认证机制 +| 任务 | 状态 | 描述 | +|------|------|------| +| IPC 工具增强 | ✅ 完成 | 修复 IpcManager 返回值解析,优化测试面板 (JSON 参数、筛选) | +| 脚本可靠性修复 | ✅ 完成 | 解决脚本编译时序导致的挂载失败问题 (文档引导 + 刷新机制) | +| 组件智能解析修复 | ✅ 完成 | 修复组件属性赋值时的 UUID 类型转换,支持压缩 UUID 及自定义组件 (`$_$ctor`) | -#### 中优先级 -1. **性能优化**:优化 HTTP 服务响应速度,改进批处理执行效率 -2. **错误处理**:增强错误处理和恢复机制,提高插件稳定性 -3. **文档完善**:添加更详细的 API 文档和使用示例,包括新工具的详细说明 +### 11.5 第七阶段开发计划(未来规划) -#### 低优先级 -1. **工具扩展**:添加更多高级工具,如动画管理、物理系统管理等 -2. **界面美化**:进一步优化面板界面,提升用户体验 -3. **国际化**:支持多语言,方便国际用户使用 -4. **插件发布**:准备插件发布到 Cocos 插件商店 -5. **版本兼容**:适配更多 Cocos Creator 版本 - -### 11.4 任务优先级表 - -| 任务 | 优先级 | 状态 | 描述 | -|------|--------|------|------| -| 代码推送 | 高 | 未完成 | 解决远程仓库认证问题 | -| 测试用例 | 高 | 未完成 | 为核心工具编写测试用例 | -| 安全配置 | 高 | 未完成 | 添加 IP 白名单和认证机制 | -| 性能优化 | 中 | 未完成 | 优化 HTTP 服务响应速度,改进批处理执行效率 | -| 错误处理 | 中 | 未完成 | 增强错误处理和恢复机制,提高插件稳定性 | -| 文档完善 | 中 | 未完成 | 添加更详细的 API 文档和使用示例,包括新工具的详细说明 | -| 工具扩展 | 低 | 未完成 | 添加更多高级工具,如动画管理、物理系统管理等 | -| 界面美化 | 低 | 未完成 | 进一步优化面板界面,提升用户体验 | -| 国际化 | 低 | 未完成 | 支持多语言,方便国际用户使用 | -| 插件发布 | 低 | 未完成 | 准备插件发布到 Cocos 插件商店 | -| 版本兼容 | 低 | 未完成 | 适配更多 Cocos Creator 版本 | -| 编辑器管理工具 | 高 | 已完成 | 实现 manage_editor 工具,支持编辑器状态管理 | -| 游戏对象查找工具 | 高 | 已完成 | 实现 find_gameobjects 工具,支持根据条件查找节点 | -| 材质和纹理管理工具 | 高 | 已完成 | 实现 manage_material 和 manage_texture 工具 | -| 菜单项执行工具 | 高 | 已完成 | 实现 execute_menu_item 工具,支持执行编辑器菜单项 | -| 代码编辑增强工具 | 中 | 已完成 | 实现 apply_text_edits 工具,支持文本编辑操作 | -| 控制台读取工具 | 中 | 已完成 | 实现 read_console 工具,支持读取控制台输出 | -| 脚本验证工具 | 中 | 已完成 | 实现 validate_script 工具,支持脚本语法验证 | -| 面板工具说明功能 | 低 | 已完成 | 添加工具说明框,显示详细的工具描述和参数说明 | +| 任务 | 优先级 | 预计时间 | 描述 | +|------|--------|----------|------| +| 插件发布 | 高 | 1 天 | 准备发布,提交到 Cocos 插件商店 | +| 文档完善 | 中 | 2 天 | 完善 API 文档 ("Getting Started" 教程) | +| 界面美化 | 低 | 2 天 | 优化面板 UI 体检 | +| 国际化支持 | 低 | 2 天 | 添加多语言 (i18n) 支持 | +| 工具扩展 | 低 | 3 天 | 添加更多高级工具 | ## 12. Unity-MCP 对比分析 -### 12.1 Unity-MCP 功能特性 +### 12.1 功能差距 (Gap Analysis) -Unity-MCP 提供了以下核心功能: +通过与 Unity-MCP 对比,Cocos-MCP 已实现绝大多数核心功能。 -- **资产管理**:管理各种 Unity 资源 -- **编辑器管理**:控制 Unity 编辑器功能 -- **游戏对象管理**:创建、修改、查找游戏对象 -- **组件管理**:添加、移除、修改组件 -- **材质管理**:创建和修改材质 -- **预制体管理**:管理预制体资源 -- **场景管理**:创建、保存、加载场景 -- **脚本管理**:创建、修改脚本 -- **ScriptableObject 管理**:管理配置文件 -- **着色器管理**:管理着色器资源 -- **VFX 管理**:管理视觉效果 -- **纹理管理**:管理纹理资源 -- **批处理执行**:批量执行多个操作 -- **游戏对象查找**:根据条件查找游戏对象 -- **文件内容查找**:在文件中查找内容 -- **控制台读取**:读取 Unity 控制台输出 -- **Unity 刷新**:刷新 Unity 编辑器 -- **测试运行**:运行测试用例 -- **获取测试任务**:获取测试任务信息 -- **菜单项执行**:执行 Unity 菜单项 -- **文本编辑应用**:应用文本编辑操作 -- **脚本编辑应用**:应用脚本编辑操作 -- **脚本验证**:验证脚本语法 -- **创建脚本**:创建新脚本 -- **删除脚本**:删除脚本文件 -- **获取 SHA**:获取版本控制 SHA 值 +| 功能类别 | Unity-MCP 功能 | Cocos-MCP 状态 | 备注 | +|---------|---------------|---------------|------| +| 编辑器管理 | manage_editor | ✅ 已实现 | | +| 游戏对象管理 | find_gameobjects | ✅ 已实现 | | +| 材质管理 | manage_material | ✅ 已实现 | | +| 纹理管理 | manage_texture | ✅ 已实现 | | +| 代码编辑 | apply_text_edits | ✅ 已实现 | | +| 全局搜索 | find_in_file | ✅ 已实现 | | +| 控制台 | read_console | ✅ 已实现 | | +| 菜单执行 | execute_menu_item | ✅ 已实现 | | +| 脚本验证 | validate_script | ✅ 已实现 | | +| 撤销/重做 | undo/redo | ✅ 已实现 | | +| VFX 管理 | manage_vfx | ✅ 已实现 | | +| Git 集成 | get_sha | ❌ 未实现 | 低优先级 | +| ScriptableObject | manage_so | ❌ 未实现 | 使用 AssetDB 替代 | -### 12.2 Cocos-MCP 功能特性 +## 13. 风险评估 -当前 Cocos-MCP 已实现的功能: +### 13.1 潜在风险 -- **场景节点操作**:获取选中节点、设置节点名称、获取场景层级、更新节点变换、创建节点 -- **组件管理**:添加、移除、获取组件 -- **资源管理**:创建、删除、移动资源 -- **脚本管理**:创建、删除、读取、写入脚本(默认创建 TypeScript 脚本) -- **批处理执行**:批量执行多个操作 -- **资产管理**:管理各种资源文件 -- **场景管理**:创建、删除、复制、获取场景信息 -- **预制体管理**:创建、更新、实例化、获取预制体信息 -- **面板界面**:提供主面板和工具测试面板 +| 风险 | 影响 | 缓解措施 | +|------|------|----------| +| 编辑器 API 变更 | 插件功能失效 | 定期检查 Cocos 更新,适配新 API | +| 性能问题 | 插件响应缓慢 | 优化批处理 (batch_execute),减少 IPC 通讯 | +| 安全漏洞 | 未授权访问 | (规划中) 面板设置 IP 白名单/Token 认证 | +| 兼容性问题 | 多版本不兼容 | 测试主流版本 (2.4.x),提供兼容层 | -### 12.3 功能缺失对比 +## 14. 结论 -| 功能类别 | Unity-MCP 功能 | Cocos-MCP 状态 | 可实现性 | -|---------|---------------|---------------|--------| -| 编辑器管理 | manage_editor | ❌ 缺失 | ✅ 可实现 | -| 游戏对象管理 | find_gameobjects | ❌ 缺失 | ✅ 可实现 | -| 材质管理 | manage_material | ❌ 缺失 | ✅ 可实现 | -| 着色器管理 | manage_shader | ❌ 缺失 | ✅ 可实现 | -| 纹理管理 | manage_texture | ❌ 缺失 | ✅ 可实现 | -| 代码编辑增强 | apply_text_edits, script_apply_edits | ❌ 缺失 | ✅ 可实现 | -| 测试功能 | run_tests, get_test_job | ❌ 缺失 | ⚠️ 部分可实现 | -| 控制台读取 | read_console | ❌ 缺失 | ✅ 可实现 | -| 菜单项执行 | execute_menu_item | ❌ 缺失 | ✅ 可实现 | -| 脚本验证 | validate_script | ❌ 缺失 | ✅ 可实现 | -| VFX 管理 | manage_vfx | ❌ 缺失 | ✅ 可实现 | +Cocos-MCP 插件的开发计划已顺利完成多个迭代阶段。目前插件实现了包括编辑器管理、场景操作、资源管理在内的全套核心功能,并完成了针对性的可靠性加固(IPC 通信、脚本时序、组件解析)。 -### 12.4 功能实现建议 - -#### 高优先级功能 - -1. **编辑器管理工具** (`manage_editor`) - - 功能:控制编辑器状态、执行编辑器操作 - - 实现方案:使用 `Editor.Ipc` 调用编辑器 API,如 `Editor.Selection`、`Editor.assetdb` 等 - -2. **游戏对象查找工具** (`find_gameobjects`) - - 功能:根据条件查找场景中的节点 - - 实现方案:使用场景脚本遍历节点树,根据名称、标签、组件等条件过滤 - -3. **材质和纹理管理工具** (`manage_material`, `manage_texture`) - - 功能:创建和管理材质、纹理资源 - - 实现方案:使用 `Editor.assetdb` API 操作资源文件 - -4. **菜单项执行工具** (`execute_menu_item`) - - 功能:执行 Cocos Creator 菜单项 - - 实现方案:使用 `Editor.Ipc.sendToMain` 发送菜单命令 - -#### 中优先级功能 - -1. **代码编辑增强工具** (`apply_text_edits`, `script_apply_edits`) - - 功能:应用文本编辑操作到文件 - - 实现方案:读取文件内容,应用编辑操作,然后写回文件 - -2. **控制台读取工具** (`read_console`) - - 功能:读取编辑器控制台输出 - - 实现方案:重定向 `console.log` 等方法,捕获控制台输出 - -3. **脚本验证工具** (`validate_script`) - - 功能:验证脚本语法正确性 - - 实现方案:使用 Node.js 的语法解析器或调用外部工具 - -#### 低优先级功能 - -1. **测试功能** (`run_tests`, `get_test_job`) - - 功能:运行测试用例并获取结果 - - 实现方案:根据 Cocos Creator 的测试框架集成 - -2. **VFX 管理工具** (`manage_vfx`) - - 功能:管理视觉效果资源 - - 实现方案:使用 `Editor.assetdb` API 操作 VFX 资源 - -## 13. 总结 - -MCP Bridge 插件通过 HTTP 服务和 MCP 协议,为外部 AI 工具提供了与 Cocos Creator 编辑器交互的能力。插件支持场景操作、资源管理、组件管理、脚本管理等多种功能,为 Cocos Creator 项目的开发和自动化提供了有力的支持。 - -通过本文档的开发流程,我们构建了一个功能完整、稳定可靠的 MCP Bridge 插件,为 Cocos Creator 生态系统增添了新的工具和能力。 - -目前插件已经完成了核心功能的实现,包括 15 个 MCP 工具,支持从场景操作到资源管理的各种功能。后续将继续完善测试、优化性能,并添加更多高级功能,为开发者提供更强大的工具支持。 - -通过与 Unity-MCP 的对比分析,我们识别出了多个可实现的功能,这些功能将进一步增强 Cocos-MCP 的能力,使其与 Unity-MCP 保持功能对等,为 Cocos Creator 开发者提供同样强大的 AI 辅助开发体验。 +插件功能已趋于稳定,后续工作重点将转向 **发布准备**、**文档体系建设** 以及 **用户体验优化**,力求为 Cocos Creator 开发者提供高质量的 AI 辅助开发工具。 diff --git a/DEVELOPMENT_PLAN.md b/DEVELOPMENT_PLAN.md deleted file mode 100644 index fce97be..0000000 --- a/DEVELOPMENT_PLAN.md +++ /dev/null @@ -1,630 +0,0 @@ -# Cocos-MCP 开发计划文档 - -## 1. 项目概述 - -### 1.1 项目背景 - -Cocos-MCP (Model Context Protocol) 插件是一个为 Cocos Creator 编辑器提供外部 AI 工具交互能力的桥梁。通过 HTTP 服务和 MCP 协议,插件允许外部 AI 工具(如 Cursor、VS Code 等)直接与 Cocos Creator 编辑器进行交互,实现场景操作、资源管理、脚本编辑等功能。 - -### 1.2 项目目标 - -- 提供与 Unity-MCP 对等的功能集,使 Cocos Creator 开发者获得同样强大的 AI 辅助开发体验 -- 实现编辑器管理、游戏对象查找、材质/纹理管理等高级功能 -- 优化现有功能,提高插件稳定性和性能 -- 建立完善的测试和部署流程 - -### 1.3 技术栈 - -- **开发语言**:JavaScript/TypeScript -- **运行环境**:Node.js (Cocos Creator 内置) -- **通信协议**:HTTP + JSON (MCP 协议) -- **编辑器 API**:Cocos Creator 2.4.x Editor API -- **界面技术**:HTML/CSS + Cocos Creator 面板 API - -## 2. 功能分析 - -### 2.1 Unity-MCP 功能参考 - -Unity-MCP 提供了以下核心功能: - -| 功能类别 | 具体功能 | 描述 | -|---------|---------|------| -| 编辑器管理 | manage_editor | 控制 Unity 编辑器状态和操作 | -| 游戏对象管理 | find_gameobjects | 根据条件查找游戏对象 | -| 材质管理 | manage_material | 创建和管理材质资源 | -| 着色器管理 | manage_shader | 管理着色器资源 | -| 纹理管理 | manage_texture | 管理纹理资源 | -| 代码编辑增强 | apply_text_edits | 应用文本编辑操作到文件 | -| 测试功能 | run_tests | 运行测试用例 | -| 控制台读取 | read_console | 读取编辑器控制台输出 | -| 菜单项执行 | execute_menu_item | 执行编辑器菜单项 | -| 脚本验证 | validate_script | 验证脚本语法 | -| VFX 管理 | manage_vfx | 管理视觉效果资源 | - -### 2.2 Cocos-MCP 现状分析 - -#### 已实现功能 - -- **场景节点操作**:获取选中节点、设置节点名称、获取场景层级、更新节点变换、创建节点 -- **组件管理**:添加、移除、获取组件 -- **资源管理**:创建、删除、移动资源 -- **脚本管理**:创建、删除、读取、写入脚本(默认创建 TypeScript 脚本) -- **批处理执行**:批量执行多个操作 -- **资产管理**:管理各种资源文件 -- **场景管理**:创建、删除、复制、获取场景信息 -- **预制体管理**:创建、更新、实例化、获取预制体信息 -- **面板界面**:提供主面板和工具测试面板 -- **编辑器管理**:控制编辑器状态、执行编辑器操作 -- **游戏对象查找**:根据条件查找场景中的节点 -- **材质管理**:创建和管理材质资源 -- **着色器管理**:管理着色器资源 -- **纹理管理**:管理纹理资源 -- **代码编辑增强**:应用文本编辑操作到文件 -- **测试功能**:运行自动化测试用例 (`run_tests.js`) -- **控制台读取**:读取编辑器控制台输出 -- **菜单项执行**:执行编辑器菜单项 -- **脚本验证**:验证脚本语法 - -#### 缺失功能 - -- **VFX 管理**:管理视觉效果资源(暂未排期) - -### 2.3 功能优先级排序 - -所有高/中优先级功能均已完成。 - -### 2.4 Unity-MCP 差异分析 (Gap Analysis) - -通过对比 [Unity-MCP](https://github.com/CoplayDev/unity-mcp),发现以下缺失或可增强的功能: - -1. **全局搜索 (`find_in_file`)**: ✅ 已实现。支持在整个项目中搜索文本内容。 -2. **ScriptableObject 管理 (`manage_scriptable_object`)**: 虽然 AssetDB 可以创建资源,但缺乏专门针对 ScriptableObject (cc.Asset) 的简便创建工具。 -3. **Undo/Redo 支持**: ✅ 已实现。通过 `manage_undo` 提供了 `undo/redo` 及事务组支持。 -4. **VFX 管理 (`manage_vfx`)**: ✅ 已实现。支持粒子系统的创建、修改和信息获取。 -5. **Git 集成 (`get_sha`)**: 获取当前版本库信息。 - -`find_in_file`、`Undo/Redo` 和 `manage_vfx` 已在最新迭代中完成。 - -## 3. 开发路线图 - -### 3.1 第三阶段开发计划(已完成) - -| 任务 | 状态 | 描述 | -|------|------|------| -| 编辑器管理工具实现 | ✅ 完成 | 实现 manage_editor 工具,支持编辑器状态控制和操作执行 | -| 游戏对象查找工具实现 | ✅ 完成 | 实现 find_gameobjects 工具,支持根据条件查找场景节点 | -| 材质和纹理管理工具实现 | ✅ 完成 | 实现 manage_material 和 manage_texture 工具,支持材质和纹理资源管理 | -| 菜单项执行工具实现 | ✅ 完成 | 实现 execute_menu_item 工具,支持执行 Cocos Creator 菜单项 | -| 代码编辑增强工具实现 | ✅ 完成 | 实现 apply_text_edits 工具,支持文本编辑操作应用 | -| 控制台读取工具实现 | ✅ 完成 | 实现 read_console 工具,支持读取编辑器控制台输出 | -| 脚本验证工具实现 | ✅ 完成 | 实现 validate_script 工具,支持脚本语法验证 | - -### 3.2 第四阶段开发计划(已完成) - -| 任务 | 状态 | 描述 | -|------|------|------| -| 测试功能实现 | ✅ 完成 | 实现 run_tests.js 脚本,支持运行自动化测试用例 | -| 错误处理增强 | ✅ 完成 | 完善 HTTP 服务和工具调用的错误日志记录 | - -### 3.3 差异填补阶段(Gap Filling)- 已完成 - -| 任务 | 状态 | 描述 | -|------|------|------| -| 全局文件搜索 | ✅ 完成 | 实现 find_in_file 工具 | -| 撤销/重做支持 | ✅ 完成 | 实现 manage_undo 工具,并重构核心操作支持撤销 | -| 特效管理 | ✅ 完成 | 实现 manage_vfx 工具,支持粒子系统管理 | - -### 3.3 第五阶段开发计划(远期) - -| 任务 | 优先级 | 预计时间 | 描述 | -|------|--------|----------|------| -| 工具扩展 | 低 | 3 天 | 添加更多高级工具和功能 | -| 界面美化 | 低 | 2 天 | 进一步优化面板界面,提升用户体验 | -| 国际化支持 | 低 | 2 天 | 添加多语言支持 | -| 文档完善 | 中 | 2 天 | 完善 API 文档和使用示例 | -| 插件发布 | 高 | 1 天 | 准备插件发布,提交到 Cocos 插件商店 | - -## 4. 技术架构 - -### 4.1 系统架构 - -``` -┌────────────────────┐ HTTP ┌────────────────────┐ IPC ┌────────────────────┐ -│ 外部 AI 工具 │ ──────────> │ main.js (HTTP服务) │ ─────────> │ scene-script.js │ -│ (Cursor/VS Code) │ <──────── │ (MCP 协议处理) │ <──────── │ (场景操作执行) │ -└────────────────────┘ JSON └────────────────────┘ JSON └────────────────────┘ -``` - -### 4.2 核心模块 - -1. **HTTP 服务模块**:处理外部请求,解析 MCP 协议,返回操作结果 -2. **MCP 工具模块**:实现各种操作工具,包括新增的编辑器管理、游戏对象查找等功能 -3. **场景操作模块**:执行场景相关操作,如节点查找、组件管理等 -4. **资源管理模块**:处理脚本、材质、纹理等资源文件的创建和管理 -5. **面板界面模块**:提供用户交互界面,包括主面板和工具测试面板 - -### 4.3 技术实现要点 - -- **编辑器 API 调用**:使用 `Editor.Ipc` 与编辑器核心进行通信 -- **资源操作**:使用 `Editor.assetdb` API 进行资源文件的创建、读取、更新和删除 -- **场景操作**:通过场景脚本执行节点和组件操作 -- **异步处理**:使用回调函数处理异步操作,避免阻塞主线程 -- **错误处理**:完善的错误捕获和处理机制,提高插件稳定性 -- **性能优化**:使用批处理执行减少 HTTP 请求次数,优化资源操作效率 - -## 5. 功能实现方案 - -### 5.1 编辑器管理工具 (`manage_editor`) - -#### 功能描述 - -提供对 Cocos Creator 编辑器状态的控制和操作执行能力。 - -#### 实现方案 - -```javascript -// 在 main.js 中添加 -manageEditor(args, callback) { - const { action, target, properties } = args; - - switch (action) { - case "get_selection": - // 获取当前选中的资源或节点 - const nodeSelection = Editor.Selection.curSelection('node'); - const assetSelection = Editor.Selection.curSelection('asset'); - callback(null, { - nodes: nodeSelection, - assets: assetSelection - }); - break; - case "set_selection": - // 设置选中状态 - if (target === 'node' && properties.nodes) { - Editor.Selection.select('node', properties.nodes); - } else if (target === 'asset' && properties.assets) { - Editor.Selection.select('asset', properties.assets); - } - callback(null, "Selection updated"); - break; - case "refresh_editor": - // 刷新编辑器 - Editor.assetdb.refresh(); - callback(null, "Editor refreshed"); - break; - default: - callback("Unknown action"); - } -} -``` - -### 5.2 游戏对象查找工具 (`find_gameobjects`) - -#### 功能描述 - -根据条件查找场景中的节点对象。 - -#### 实现方案 - -```javascript -// 在 scene-script.js 中添加 -findGameObjects(params, callback) { - const { conditions, recursive } = params; - const result = []; - - // 遍历场景根节点 - cc.director.getScene().children.forEach(child => { - searchNode(child, conditions, recursive, result); - }); - - callback(null, result); -} - -function searchNode(node, conditions, recursive, result) { - // 检查节点是否满足条件 - let match = true; - - if (conditions.name && !node.name.includes(conditions.name)) { - match = false; - } - - if (conditions.tag && node.tag !== conditions.tag) { - match = false; - } - - if (conditions.component && !node.getComponent(conditions.component)) { - match = false; - } - - if (match) { - result.push({ - id: node.uuid, - name: node.name, - tag: node.tag, - position: node.position, - rotation: node.rotation, - scale: node.scale - }); - } - - // 递归搜索子节点 - if (recursive) { - node.children.forEach(child => { - searchNode(child, conditions, recursive, result); - }); - } -} -``` - -### 5.3 材质和纹理管理工具 (`manage_material`, `manage_texture`) - -#### 功能描述 - -管理材质和纹理资源,支持创建、修改、删除等操作。 - -#### 实现方案 - -```javascript -// 在 main.js 中添加 -manageMaterial(args, callback) { - const { action, path, properties } = args; - - switch (action) { - case "create": - // 创建材质资源 - const materialContent = JSON.stringify({ - __type__: "cc.Material", - _name: "", - _objFlags: 0, - _native: "", - effects: [{ - technique: 0, - defines: {}, - uniforms: properties.uniforms || {} - }] - }); - - // 确保目录存在 - const fs = require('fs'); - const pathModule = require('path'); - const absolutePath = Editor.assetdb.urlToFspath(path); - const dirPath = pathModule.dirname(absolutePath); - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath, { recursive: true }); - } - - Editor.assetdb.create(path, materialContent, (err) => { - callback(err, err ? null : `Material created at ${path}`); - }); - break; - // 其他操作... - } -} - -manageTexture(args, callback) { - const { action, path, properties } = args; - - switch (action) { - case "create": - // 创建纹理资源(简化版,实际需要处理纹理文件) - const textureContent = JSON.stringify({ - __type__: "cc.Texture2D", - _name: "", - _objFlags: 0, - _native: properties.native || "", - width: properties.width || 128, - height: properties.height || 128 - }); - - // 确保目录存在 - const fs = require('fs'); - const pathModule = require('path'); - const absolutePath = Editor.assetdb.urlToFspath(path); - const dirPath = pathModule.dirname(absolutePath); - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath, { recursive: true }); - } - - Editor.assetdb.create(path, textureContent, (err) => { - callback(err, err ? null : `Texture created at ${path}`); - }); - break; - // 其他操作... - } -} -``` - -### 5.4 菜单项执行工具 (`execute_menu_item`) - -#### 功能描述 - -执行 Cocos Creator 编辑器的菜单项命令。 - -#### 实现方案 - -```javascript -// 在 main.js 中添加 -executeMenuItem(args, callback) { - const { menuPath } = args; - - try { - // 执行菜单项 - Editor.Ipc.sendToMain('menu:click', menuPath); - callback(null, `Menu item executed: ${menuPath}`); - } catch (err) { - callback(`Failed to execute menu item: ${err.message}`); - } -} -``` - -### 5.5 代码编辑增强工具 (`apply_text_edits`) - -#### 功能描述 - -应用文本编辑操作到文件,支持插入、删除、替换等操作。 - -#### 实现方案 - -```javascript -// 在 main.js 中添加 -applyTextEdits(args, callback) { - const { filePath, edits } = args; - - // 读取文件内容 - Editor.assetdb.queryInfoByUrl(filePath, (err, info) => { - if (err) { - callback(`Failed to get file info: ${err.message}`); - return; - } - - Editor.assetdb.loadMeta(info.uuid, (err, content) => { - if (err) { - callback(`Failed to load file: ${err.message}`); - return; - } - - // 应用编辑操作 - let updatedContent = content; - edits.forEach(edit => { - switch (edit.type) { - case "insert": - updatedContent = updatedContent.slice(0, edit.position) + edit.text + updatedContent.slice(edit.position); - break; - case "delete": - updatedContent = updatedContent.slice(0, edit.start) + updatedContent.slice(edit.end); - break; - case "replace": - updatedContent = updatedContent.slice(0, edit.start) + edit.text + updatedContent.slice(edit.end); - break; - } - }); - - // 写回文件 - Editor.assetdb.save(info.uuid, updatedContent, (err) => { - callback(err, err ? null : `Text edits applied to ${filePath}`); - }); - }); - }); -} -``` - -### 5.6 控制台读取工具 (`read_console`) - -#### 功能描述 - -读取编辑器控制台的输出信息。 - -#### 实现方案 - -```javascript -// 在 main.js 中添加 -// 首先在模块顶部添加控制台输出捕获 -let consoleOutput = []; -const originalLog = console.log; -const originalError = console.error; -const originalWarn = console.warn; - -console.log = function(...args) { - consoleOutput.push({ type: 'log', message: args.join(' ') }); - originalLog.apply(console, args); -}; - -console.error = function(...args) { - consoleOutput.push({ type: 'error', message: args.join(' ') }); - originalError.apply(console, args); -}; - -console.warn = function(...args) { - consoleOutput.push({ type: 'warn', message: args.join(' ') }); - originalWarn.apply(console, args); -}; - -// 然后添加 read_console 工具 -readConsole(args, callback) { - const { limit, type } = args; - let filteredOutput = consoleOutput; - - if (type) { - filteredOutput = filteredOutput.filter(item => item.type === type); - } - - if (limit) { - filteredOutput = filteredOutput.slice(-limit); - } - - callback(null, filteredOutput); -} -``` - -### 5.7 脚本验证工具 (`validate_script`) - -#### 功能描述 - -验证脚本文件的语法正确性。 - -#### 实现方案 - -```javascript -// 在 main.js 中添加 -validateScript(args, callback) { - const { filePath } = args; - - // 读取脚本内容 - Editor.assetdb.queryInfoByUrl(filePath, (err, info) => { - if (err) { - callback(`Failed to get file info: ${err.message}`); - return; - } - - Editor.assetdb.loadMeta(info.uuid, (err, content) => { - if (err) { - callback(`Failed to load file: ${err.message}`); - return; - } - - try { - // 对于 JavaScript 脚本,使用 eval 进行简单验证 - if (filePath.endsWith('.js')) { - // 包装在函数中以避免变量污染 - const wrapper = `(function() { ${content} })`; - eval(wrapper); - } - // 对于 TypeScript 脚本,这里可以添加更复杂的验证逻辑 - - callback(null, { valid: true, message: 'Script syntax is valid' }); - } catch (err) { - callback(null, { valid: false, message: err.message }); - } - }); - }); -} - }); -} -``` - -### 5.8 常用 IPC 消息参考 (Cocos Creator 2.4.x) - -基于社区资料整理,以下 IPC 消息可用于扩展功能: - -#### 场景操作 (`scene:`) -- **创建/实例化**: - - `scene:create-node-by-classid` (参数: name, parentUuid) - - `scene:create-nodes-by-uuids` (实例化预制体, 参数: [prefabUuid], parentUuid) -- **修改**: - - `scene:set-property` (参数: {id, path, type, value}) - - `scene:copy-nodes` / `scene:paste-nodes` -- **安全机制**: - - `scene:undo` / `scene:redo` (建议集成到 manage_editor) - -#### 资源操作 (`assets:`) -- `assets:hint` (高亮资源) -- `assets:open-text-file` (打开外部编辑器) - -## 6. 测试策略 - -### 6.1 测试目标 - -- 验证所有新增功能的正确性和稳定性 -- 确保现有功能不受影响 -- 测试插件在不同场景下的性能表现 -- 验证错误处理机制的有效性 - -### 6.2 测试方法 - -#### 单元测试 - -- 为每个工具函数编写独立的测试用例 -- 测试各种输入参数和边界情况 -- 验证函数返回值的正确性 - -#### 集成测试 - -- 测试工具之间的协作能力 -- 验证批处理执行的正确性 -- 测试插件与编辑器的集成稳定性 - -#### 性能测试 - -- 测试工具执行速度 -- 验证批处理执行的性能优势 -- 测试插件在处理大量操作时的表现 - -#### 回归测试 - -- 确保新增功能不破坏现有功能 -- 验证修复的 bug 不会再次出现 -- 测试插件在不同版本 Cocos Creator 中的兼容性 - -### 6.3 测试工具 - -- **手动测试**:通过面板界面测试工具功能 -- **脚本测试**:编写测试脚本自动执行测试用例 -- **性能分析**:使用浏览器开发者工具分析性能瓶颈 - -## 7. 部署与维护 - -### 7.1 部署方案 - -#### 本地部署 - -1. 将插件复制到 Cocos Creator 项目的 `packages` 目录 -2. 重启 Cocos Creator 编辑器 -3. 在编辑器中打开 MCP Bridge 面板 -4. 启动 HTTP 服务 - -#### 远程部署 - -1. 使用 Git 进行版本控制 -2. 提供插件的 GitHub 仓库地址 -3. 发布插件到 Cocos 插件商店(未来) - -### 7.2 维护计划 - -#### 版本管理 - -- 遵循语义化版本规范(MAJOR.MINOR.PATCH) -- 定期发布更新版本 -- 维护详细的版本变更日志 - -#### 错误处理 - -- 建立错误报告机制 -- 定期分析错误日志 -- 及时修复发现的问题 - -#### 性能优化 - -- 定期分析插件性能 -- 优化资源操作和网络请求 -- 提高插件响应速度 - -#### 文档维护 - -- 保持 README.md 和开发文档的更新 -- 提供详细的 API 文档 -- 编写使用教程和示例 - -## 8. 风险评估 - -### 8.1 潜在风险 - -| 风险 | 影响 | 缓解措施 | -|------|------|----------| -| 编辑器 API 变更 | 插件功能失效 | 定期检查 Cocos Creator 更新,适配新 API | -| 性能问题 | 插件响应缓慢 | 优化代码结构,使用批处理执行,避免阻塞操作 | -| 安全漏洞 | 未授权访问 | 添加 IP 白名单,实现认证机制,限制服务访问范围 | -| 兼容性问题 | 不同版本 Cocos Creator 不兼容 | 测试多个版本,提供版本兼容层 | -| 错误处理不完善 | 插件崩溃 | 完善错误捕获和处理机制,提高插件稳定性 | - -### 8.2 应对策略 - -- **持续集成**:建立自动化测试流程,及时发现问题 -- **监控机制**:添加性能监控和错误监控 -- **用户反馈**:建立用户反馈渠道,收集使用问题 -- **文档完善**:提供详细的安装和使用文档 -- **社区支持**:建立社区支持渠道,解答用户问题 - -## 9. 结论 - -Cocos-MCP 插件的开发计划基于与 Unity-MCP 的功能对比,旨在为 Cocos Creator 开发者提供同样强大的 AI 辅助开发体验。通过分阶段实现编辑器管理、游戏对象查找、材质/纹理管理等高级功能,插件将逐步完善其功能集,成为 Cocos Creator 编辑器的重要扩展工具。 - -本开发计划文档为后续的开发工作提供了详细的指导,包括功能实现方案、技术架构设计、测试策略和部署维护计划。通过严格按照计划执行开发工作,我们可以确保插件的质量和稳定性,为 Cocos Creator 生态系统做出贡献。 \ No newline at end of file diff --git a/IPC_MESSAGES.md b/IPC_MESSAGES.md new file mode 100644 index 0000000..bc0aa64 --- /dev/null +++ b/IPC_MESSAGES.md @@ -0,0 +1,1305 @@ +# Cocos Creator 2.4.12 IPC Messages Documentation + +本文档详细记录了Cocos Creator 2.4.12版本中定义的所有IPC(进程间通信)消息,包括它们的用途、参数以及返回值。 + +## 目录 + +- [App相关IPC消息](#app相关ipc消息) +- [Asset-DB相关IPC消息](#asset-db相关ipc消息) +- [Dashboard相关IPC消息](#dashboard相关ipc消息) +- [Scene相关IPC消息](#scene相关ipc消息) +- [Editor相关IPC消息](#editor相关ipc消息) +- [Selection相关IPC消息](#selection相关ipc消息) +- [Scene-Animation相关IPC消息](#scene-animation相关ipc消息) +- [Scene-Layout相关IPC消息](#scene-layout相关ipc消息) +- [Metrics相关IPC消息](#metrics相关ipc消息) +- [Package Template相关IPC消息](#package-template相关ipc消息) +- [Additional Scene相关IPC消息](#additional-scene相关ipc消息) +- [Broadcast Events](#broadcast-events) +- [Events listened by Renderer Process](#events-listened-by-renderer-process) + +## App相关IPC消息 + +### `app:explore-project` +- **用途**: 打开项目所在文件夹 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:explore-app` +- **用途**: 打开应用程序所在文件夹 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:build-project` +- **用途**: 构建项目 +- **参数**: 包含构建选项的对象 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:query-cocos-templates` +- **用途**: 查询Cocos模板 +- **参数**: 无 +- **返回值**: 模板列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:query-android-apilevels` +- **用途**: 查询Android API级别 +- **参数**: 无 +- **返回值**: API级别列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:query-android-instant-apilevels` +- **用途**: 查询Android Instant API级别 +- **参数**: 无 +- **返回值**: API级别列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:compile-project` +- **用途**: 编译项目 +- **参数**: 编译选项对象 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:open-cocos-console-log` +- **用途**: 打开Cocos控制台日志 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:stop-compile` +- **用途**: 停止编译 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:run-project` +- **用途**: 运行项目 +- **参数**: 包含平台信息的对象 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:save-keystore` +- **用途**: 保存密钥库 +- **参数**: 密钥库信息 +- **返回值**: 错误信息或成功确认 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:update-build-preview-path` +- **用途**: 更新构建预览路径 +- **参数**: 预览路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:update-android-instant-preview-path` +- **用途**: 更新Android Instant预览路径 +- **参数**: 预览路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:play-on-device` +- **用途**: 在设备上播放 +- **参数**: 平台信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:reload-on-device` +- **用途**: 在设备上重新加载 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:query-plugin-scripts` +- **用途**: 查询插件脚本 +- **参数**: 构建平台名称 +- **返回值**: 插件脚本列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `app:rebuild-editor-engine` +- **用途**: 重建编辑器引擎 +- **参数**: 回调函数 +- **返回值**: 错误信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +## Asset-DB相关IPC消息 + +### `asset-db:explore` +- **用途**: 打开资源所在文件夹 +- **参数**: 资源URL +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:exists` +- **用途**: 查询资源是否存在 +- **参数**: 资源URL +- **返回值**: 存在性布尔值 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-path-by-url` +- **用途**: 根据URL查询路径 +- **参数**: 资源URL +- **返回值**: 文件系统路径 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-uuid-by-url` +- **用途**: 根据URL查询UUID +- **参数**: 资源URL +- **返回值**: UUID字符串 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-path-by-uuid` +- **用途**: 根据UUID查询路径 +- **参数**: UUID字符串 +- **返回值**: 文件系统路径 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-url-by-uuid` +- **用途**: 根据UUID查询URL +- **参数**: UUID字符串 +- **返回值**: 资源URL +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-info-by-uuid` +- **用途**: 根据UUID查询资源信息 +- **参数**: UUID字符串 +- **返回值**: 资源信息对象 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-meta-info-by-uuid` +- **用途**: 根据UUID查询元数据信息 +- **参数**: UUID字符串 +- **返回值**: 元数据信息对象 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:deep-query` +- **用途**: 深度查询资源 +- **参数**: 无 +- **返回值**: 完整资源数据库信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-assets` +- **用途**: 查询资源 +- **参数**: 查询条件、类型 +- **返回值**: 资源列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-mounts` +- **用途**: 查询挂载点 +- **参数**: 无 +- **返回值**: 挂载点列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:import-assets` +- **参数**: 导入路径列表、目标路径、刷新标志 +- **用途**: 导入资源 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:create-asset` +- **用途**: 创建资源 +- **参数**: URL、内容 +- **返回值**: 错误信息或创建结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:move-asset` +- **用途**: 移动资源 +- **参数**: 源URL、目标URL、是否显示错误对话框 +- **返回值**: 错误信息或移动结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:delete-assets` +- **用途**: 删除资源 +- **参数**: URL数组 +- **返回值**: 错误信息或删除结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:save-exists` +- **用途**: 保存已存在的资源 +- **参数**: URL、内容 +- **返回值**: 错误信息或保存结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:create-or-save` +- **用途**: 创建或保存资源 +- **参数**: URL、内容 +- **返回值**: 错误信息或操作结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:save-meta` +- **用途**: 保存元数据 +- **参数**: UUID、元数据对象 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:refresh` +- **用途**: 刷新资源 +- **参数**: 路径(可选) +- **返回值**: 错误信息或刷新结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:attach-mountpath` +- **用途**: 挂载路径 +- **参数**: 挂载路径对象 +- **返回值**: 错误信息或挂载结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:unattach-mountpath` +- **用途**: 取消挂载路径 +- **参数**: 挂载路径 +- **返回值**: 错误信息或取消挂载结果 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:query-watch-state` +- **用途**: 查询监听状态 +- **参数**: 无 +- **返回值**: 无(向主窗口发送状态) +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:asset-changed` +- **用途**: 资源变更处理 +- **参数**: 变更详情 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:asset-uuid-changed` +- **用途**: 资源UUID变更处理 +- **参数**: 变更详情 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:assets-moved` +- **用途**: 资源移动处理 +- **参数**: 移动详情数组 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:assets-created` +- **用途**: 资源创建处理 +- **参数**: 创建详情数组 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:assets-deleted` +- **用途**: 资源删除处理 +- **参数**: 删除详情数组 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:script-import-failed` +- **用途**: 脚本导入失败处理 +- **参数**: 失败详情 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `asset-db:meta-backup` +- **用途**: 元数据备份处理 +- **参数**: 备份详情数组 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +## Dashboard相关IPC消息 + +### `app:query-recent` +- **用途**: 查询最近打开的项目 +- **参数**: 无 +- **返回值**: 最近项目列表 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:query-templates` +- **用途**: 查询项目模板 +- **参数**: 无 +- **返回值**: 模板列表 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:create-project` +- **用途**: 创建项目 +- **参数**: 项目配置对象 +- **返回值**: 错误信息或创建结果 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:open-project` +- **用途**: 打开项目 +- **参数**: 项目路径、是否需要登录 +- **返回值**: 错误信息或打开结果 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:delete-project` +- **用途**: 删除项目 +- **参数**: 项目路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:close-project` +- **用途**: 关闭项目 +- **参数**: 项目路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:window-minimize` +- **用途**: 最小化窗口 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:window-close` +- **用途**: 关闭窗口 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:get-last-create` +- **用途**: 获取上次创建的项目 +- **参数**: 无 +- **返回值**: 上次创建的项目信息 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:open-manual-doc` +- **用途**: 打开手册文档 +- **参数**: 文档路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:open-api-doc` +- **用途**: 打开API文档 +- **参数**: 文档路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `app:query-last-create-path` +- **用途**: 查询上次创建的路径 +- **参数**: 无 +- **返回值**: 上次创建的路径 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +## Scene相关IPC消息 + +### `scene:is-ready` +- **用途**: 检查场景编辑器是否准备就绪 +- **参数**: 无 +- **返回值**: 准备就绪状态 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:new-scene` +- **用途**: 创建新场景 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:saved` +- **用途**: 场景保存完成后的通知 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `scene:play-on-device` +- **用途**: 在设备上播放场景 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `scene:reload-on-device` +- **用途**: 在设备上重新加载场景 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `scene:preview-server-scene-stashed` +- **用途**: 预览服务器场景暂存 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:load-package-scene-script` +- **用途**: 加载包场景脚本 +- **参数**: 脚本路径、包名 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:unload-package-scene-script` +- **用途**: 卸载包场景脚本 +- **参数**: 脚本路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:soft-reload` +- **用途**: 软重载场景 +- **参数**: 重载参数 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:enter-prefab-edit-mode` +- **用途**: 进入预制件编辑模式 +- **参数**: 预制件UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:stash-and-save` +- **用途**: 暂存并保存场景 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:print-simulator-log` +- **用途**: 打印模拟器日志 +- **参数**: 日志信息、日志类型 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:generate-texture-packer-preview-files` +- **用途**: 生成纹理打包预览文件 +- **参数**: 资源路径 +- **返回值**: 错误信息或操作结果 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:query-texture-packer-preview-files` +- **用途**: 查询纹理打包预览文件 +- **参数**: 资源路径 +- **返回值**: 预览文件信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:export-particle-plist` +- **用途**: 导出粒子plist文件 +- **参数**: 粒子数据 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:update-edit-mode` +- **用途**: 更新编辑模式 +- **参数**: 编辑模式信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:undo` +- **用途**: 撤销操作 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:redo` +- **用途**: 重做操作 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:undo-record` +- **用途**: 记录撤销操作 +- **参数**: 对象ID、操作信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:undo-commit` +- **用途**: 提交撤销操作 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:undo-cancel` +- **用途**: 取消撤销操作 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-dirty-state` +- **用途**: 查询场景脏状态 +- **参数**: 无 +- **返回值**: 脏状态信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-group-list` +- **用途**: 查询分组列表 +- **参数**: 无 +- **返回值**: 分组列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-hierarchy` +- **用途**: 查询场景层级结构 +- **参数**: 无 +- **返回值**: 场景UUID和节点层次 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-nodes-by-comp-name` +- **用途**: 根据组件名称查询节点 +- **参数**: 组件名称 +- **返回值**: 节点UUID列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-node` +- **用途**: 查询节点信息 +- **参数**: 节点UUID +- **返回值**: 节点信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-node-info` +- **用途**: 查询节点详细信息 +- **参数**: 节点UUID、类型 +- **返回值**: 节点详细信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-node-functions` +- **用途**: 查询节点函数 +- **参数**: 节点UUID +- **返回值**: 节点函数列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:choose-last-rigid-body` +- **用途**: 选择上一个刚体 +- **参数**: 当前节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:choose-next-rigid-body` +- **用途**: 选择下一个刚体 +- **参数**: 当前节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:is-child-class-of` +- **用途**: 检查是否为子类 +- **参数**: 类ID、父类ID +- **返回值**: 是否为子类的布尔值 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:has-copied-component` +- **用途**: 检查是否有复制的组件 +- **参数**: 无 +- **返回值**: 是否有复制组件的布尔值 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-animation-hierarchy` +- **用途**: 查询动画层级 +- **参数**: 节点UUID +- **返回值**: 动画层级结构 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-animation-list` +- **用途**: 查询动画列表 +- **参数**: 节点UUID +- **返回值**: 动画剪辑UUID列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-animation-properties` +- **用途**: 查询动画属性 +- **参数**: 节点UUID +- **返回值**: 动画属性列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-animation-record` +- **用途**: 查询动画记录状态 +- **参数**: 无 +- **返回值**: 动画记录状态信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-animation-clip` +- **用途**: 查询动画剪辑 +- **参数**: 动画剪辑UUID +- **返回值**: 动画剪辑序列化数据 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-asset-info` +- **用途**: 查询资源信息 +- **参数**: 资源UUID +- **返回值**: 资源信息 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:query-nodes-by-usedby-uuid` +- **用途**: 根据使用的资源UUID查询节点 +- **参数**: 资源UUID +- **返回值**: 使用该资源的节点UUID列表 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:create-nodes-by-uuids` +- **用途**: 根据UUID创建节点 +- **参数**: UUID列表、位置、父节点、选项 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:create-node-by-classid` +- **用途**: 根据类ID创建节点 +- **参数**: 类ID、位置、父节点、选项 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:create-node-by-prefab` +- **用途**: 根据预制件创建节点 +- **参数**: 预制件名称、位置、父节点、选项 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:new-property` +- **用途**: 创建新属性 +- **参数**: 属性信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:reset-property` +- **用途**: 重置属性 +- **参数**: 属性信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:set-property` +- **用途**: 设置属性 +- **参数**: 属性信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:add-component` +- **用途**: 添加组件 +- **参数**: 节点UUID、组件名称 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:remove-component` +- **用途**: 移除组件 +- **参数**: 节点UUID、组件ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:reset-node` +- **用途**: 重置节点 +- **参数**: 节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:reset-all` +- **用途**: 重置所有组件 +- **参数**: 节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:move-up-component` +- **用途**: 向上移动组件 +- **参数**: 节点UUID、组件ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:move-down-component` +- **用途**: 向下移动组件 +- **参数**: 节点UUID、组件ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:reset-component` +- **用途**: 重置组件 +- **参数**: 节点UUID、组件ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:copy-component` +- **用途**: 复制组件 +- **参数**: 组件ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:paste-component` +- **用途**: 粘贴组件 +- **参数**: 节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:move-nodes` +- **用途**: 移动节点 +- **参数**: 节点UUID列表、位置、父节点 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:delete-nodes` +- **用途**: 删除节点 +- **参数**: 节点UUID列表 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:copy-nodes` +- **用途**: 复制节点 +- **参数**: 节点UUID列表 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:paste-nodes` +- **用途**: 粘贴节点 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:duplicate-nodes` +- **用途**: 复制节点(Duplicate) +- **参数**: 节点UUID列表 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:create-prefab` +- **用途**: 创建预制件 +- **参数**: 节点UUID、预制件路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:apply-prefab` +- **用途**: 应用预制件 +- **参数**: 节点UUID、预制件路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:revert-prefab` +- **用途**: 还原预制件 +- **参数**: 节点UUID、预制件路径 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:set-prefab-sync` +- **用途**: 设置预制件同步 +- **参数**: 节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:break-prefab-instance` +- **用途**: 打破预制件实例关联 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:link-prefab` +- **用途**: 链接预制件 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:regenerate-polygon-points` +- **用途**: 重新生成多边形点 +- **参数**: 节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:search-skeleton-animation-clips` +- **用途**: 搜索骨骼动画剪辑 +- **参数**: 节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:change-node-lock` +- **用途**: 更改节点锁定状态 +- **参数**: 节点UUID、锁定状态 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:copy-editor-camera-data-to-nodes` +- **用途**: 将编辑器相机数据复制到节点 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `scene:set-group-sync` +- **用途**: 设置组同步 +- **参数**: 节点UUID、组名 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene:generate_attached_node` +- **用途**: 生成附加节点 +- **参数**: 节点UUID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +## Editor相关IPC消息 + +### `editor:dragstart` +- **用途**: 开始拖拽操作 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `editor:dragend` +- **用途**: 结束拖拽操作 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `editor:project-profile-updated` +- **用途**: 项目配置文件更新 +- **参数**: 配置对象 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +## Selection相关IPC消息 + +### `selection:selected` +- **用途**: 选择节点 +- **参数**: 类型、ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `selection:unselected` +- **用途**: 取消选择节点 +- **参数**: 类型、ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `selection:activated` +- **用途**: 激活节点 +- **参数**: 类型、ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `selection:deactivated` +- **用途**: 取消激活节点 +- **参数**: 类型、ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `selection:hoverin` +- **用途**: 鼠标悬停进入节点 +- **参数**: 类型、ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `selection:hoverout` +- **用途**: 鼠标悬停离开节点 +- **参数**: 类型、ID +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +## Scene-Animation相关IPC消息 + +### `scene-animation:query-animation-time` +- **用途**: 查询动画时间 +- **参数**: 动画剪辑信息 +- **返回值**: 时间信息 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:animation-time-changed` +- **用途**: 动画时间改变 +- **参数**: 新的时间值 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:animation-clip-changed` +- **用途**: 动画剪辑改变 +- **参数**: 剪辑信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:save-clip` +- **用途**: 保存动画剪辑 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:set-animation-speed` +- **用途**: 设置动画速度 +- **参数**: 速度值 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:change-animation-record` +- **用途**: 更改动画记录状态 +- **参数**: 记录状态 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:mount-clip` +- **用途**: 挂载动画剪辑 +- **参数**: 剪辑信息、选项 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:change-animation-state` +- **用途**: 更改动画播放状态 +- **参数**: 状态(播放/暂停) +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `scene-animation:change-animation-current-clip` +- **用途**: 更改当前动画剪辑 +- **参数**: 剪辑信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +## Scene-Layout相关IPC消息 + +### `scene-layout:center-nodes` +- **用途**: 将摄像机中心对准节点 +- **参数**: 节点列表 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +## Metrics相关IPC消息 + +### `metrics:track-event` +- **用途**: 跟踪事件 +- **参数**: 事件类别、动作、标签等 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `editor:renderer-console-error` +- **用途**: 发送渲染器控制台错误 +- **参数**: 错误堆栈信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +### `metrics:track-exception` +- **用途**: 跟踪异常 +- **参数**: 异常信息 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 可用 + +## Package Template相关IPC消息 + +### `package-template:clicked` +- **用途**: 包模板被点击 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `package-template:hello` +- **用途**: 包模板的问候消息 +- **参数**: 事件对象 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `package-template:open` +- **用途**: 打开包模板面板 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +### `package-template:say-hello` +- **用途**: 发送问候语 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 主进程监听 +- **状态**: 不可用 (无响应) + +## Additional Scene相关IPC消息 + +### `asset-db:asset-changed` +- **用途**: 资源变更处理 +- **参数**: 变更详情 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 可用 + +### `asset-db:assets-moved` +- **用途**: 资源移动处理 +- **参数**: 移动详情数组 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 可用 + +### `asset-db:assets-created` +- **用途**: 资源创建处理 +- **参数**: 创建详情数组 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 可用 + +### `asset-db:assets-deleted` +- **用途**: 资源删除处理 +- **参数**: 删除详情数组 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 可用 + +### `editor:ready` +- **用途**: 编辑器就绪通知 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `editor:console-failed` +- **用途**: 控制台失败消息 +- **参数**: 失败信息 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `editor:console-warn` +- **用途**: 控制台警告消息 +- **参数**: 警告信息 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `editor:console-error` +- **用途**: 控制台错误消息 +- **参数**: 错误信息 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `editor:console-clear` +- **用途**: 清空控制台 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `compiler:state-changed` +- **用途**: 编译器状态变化 +- **参数**: 状态 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `preview-server:preview-port-changed` +- **用途**: 预览服务器端口变化 +- **参数**: 无 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `preview-server:connects-changed` +- **用途**: 预览服务器连接数变化 +- **参数**: 连接数 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `im-plugin:update-im-html` +- **用途**: 更新IM插件HTML +- **参数**: HTML内容 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `asset-db:state-changed` +- **用途**: 资源数据库状态变化 +- **参数**: 状态 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `asset-db:watch-state-changed` +- **用途**: 资源数据库监听状态变化 +- **参数**: 状态 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `editor:online-status-changed` +- **用途**: 编辑器在线状态变化 +- **参数**: 状态 ('online' 或 'offline') +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `scene:node-component-updated` +- **用途**: 节点组件更新 +- **参数**: 包含节点、组件和属性信息的对象 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `scene:node-component-added` +- **用途**: 节点组件添加 +- **参数**: 包含节点和组件信息的对象 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +### `scene:node-component-removed` +- **用途**: 节点组件移除 +- **参数**: 包含节点和组件信息的对象 +- **返回值**: 无 +- **类型**: 广播事件 +- **状态**: 未测试 + +## Broadcast Events + +以下是专门用于广播给渲染进程的事件,通常由主进程发出,渲染进程接收: + +- `scene:saved` +- `scene:play-on-device` +- `scene:reload-on-device` +- `asset-db:asset-changed` +- `asset-db:assets-moved` +- `asset-db:assets-created` +- `asset-db:assets-deleted` +- `editor:ready` +- `editor:console-failed` +- `editor:console-warn` +- `editor:console-error` +- `editor:console-clear` +- `compiler:state-changed` +- `preview-server:preview-port-changed` +- `preview-server:connects-changed` +- `im-plugin:update-im-html` +- `asset-db:state-changed` +- `asset-db:watch-state-changed` +- `editor:online-status-changed` +- `scene:node-component-updated` +- `scene:node-component-added` +- `scene:node-component-removed` +- `package-template:hello` + +## Events listened by Renderer Process + +以下是渲染进程主动监听的事件,这些事件通常由主进程发出: + +- `asset-db:assets-moved` +- `asset-db:assets-deleted` +- `asset-db:assets-created` +- `compiler:state-changed` +- `preview-server:preview-port-changed` +- `preview-server:connects-changed` +- `im-plugin:update-im-html` +- `asset-db:state-changed` +- `asset-db:watch-state-changed` +- `editor:console-failed` +- `editor:console-warn` +- `editor:console-error` +- `editor:console-clear` diff --git a/README.md b/README.md index b0f0e05..7c8b57f 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,7 @@ Args: [你的项目所在盘符]:/[项目路径]/packages/mcp-bridge/mcp-proxy.j - `id`: 节点 UUID - `x`, `y`: 坐标 - `scaleX`, `scaleY`: 缩放值 - - `color`: HEX 颜色代码(如 #FF0000) + - `color`: HEX 颜色代码(如 #FF0000)(支持撤销操作) ### 6. open_scene @@ -137,7 +137,7 @@ Args: [你的项目所在盘符]:/[项目路径]/packages/mcp-bridge/mcp-proxy.j - `action`: 操作类型(`add`, `remove`, `get`) - `componentType`: 组件类型,如 `cc.Sprite`(用于 `add` 操作) - `componentId`: 组件 ID(用于 `remove` 操作) - - `properties`: 组件属性(用于 `add` 操作) + - `properties`: 组件属性(用于 `add` 操作)。**智能特性**:如果属性期望组件类型但传入节点UUID,插件会自动查找匹配组件。 ### 9. manage_script @@ -229,7 +229,7 @@ Args: [你的项目所在盘符]:/[项目路径]/packages/mcp-bridge/mcp-proxy.j - **描述**: 执行菜单项 - **参数**: - - `menuPath`: 菜单项路径,如 `Assets/Create/Folder` + - `menuPath`: 菜单项路径,如 `Assets/Create/Folder`。支持映射常用命令:`File/New Scene`, `File/Save Scene`, `Edit/Undo`, `Edit/Redo`, `Project/Build` 等。 ### 19. apply_text_edits @@ -255,6 +255,7 @@ Args: [你的项目所在盘符]:/[项目路径]/packages/mcp-bridge/mcp-proxy.j - **描述**: 验证脚本 - **参数**: - `filePath`: 脚本路径,如 `db://assets/scripts/TestScript.ts` + - **注意**:对于 TypeScript 文件,仅进行基础语法结构检查,不进行完整编译验证。 ### 22. find_in_file diff --git a/dist/IpcManager.js b/dist/IpcManager.js new file mode 100644 index 0000000..6ce3fe6 --- /dev/null +++ b/dist/IpcManager.js @@ -0,0 +1,141 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.IpcManager = void 0; +// @ts-ignore +var fs = require('fs'); +// @ts-ignore +var path = require('path'); +/** + * IPC 消息管理器 + * 负责解析 IPC 文档并执行消息测试 + */ +var IpcManager = /** @class */ (function () { + function IpcManager() { + } + /** + * 获取所有 IPC 消息列表 + * @returns 消息定义列表 + */ + IpcManager.getIpcMessages = function () { + // 获取文档路径 + // @ts-ignore + var docPath = Editor.url('packages://mcp-bridge/IPC_MESSAGES.md'); + if (!fs.existsSync(docPath)) { + // @ts-ignore + Editor.error("[IPC Manager] Document not found: ".concat(docPath)); + return []; + } + var content = fs.readFileSync(docPath, 'utf-8'); + var messages = []; + // 正则匹配 ### `message-name` + var regex = /### `(.*?)`\r?\n([\s\S]*?)(?=### `|$)/g; + var match; + while ((match = regex.exec(content)) !== null) { + var name_1 = match[1]; + var body = match[2]; + // 解析用途 + var purposeMatch = body.match(/- \*\*用途\*\*: (.*)/); + var description = purposeMatch ? purposeMatch[1].trim() : "无描述"; + // 解析参数 + var paramsMatch = body.match(/- \*\*参数\*\*: (.*)/); + var params = paramsMatch ? paramsMatch[1].trim() : "无"; + // 解析返回值 + var returnMatch = body.match(/- \*\*返回值\*\*: (.*)/); + var returns = returnMatch ? returnMatch[1].trim() : "无"; + // 解析类型 + var typeMatch = body.match(/- \*\*类型\*\*: (.*)/); + var type = typeMatch ? typeMatch[1].trim() : "未定义"; + // 解析状态 + var statusMatch = body.match(/- \*\*状态\*\*: (.*)/); + var status_1 = statusMatch ? statusMatch[1].trim() : "未测试"; + // 过滤掉广播事件和渲染进程监听的事件 + if (type === "广播事件" || type === "Events listened by Renderer Process" || type === "渲染进程监听") { + continue; + } + messages.push({ + name: name_1, + description: description, + params: params, + returns: returns, + type: type, + status: status_1 + }); + } + return messages; + }; + /** + * 测试发送 IPC 消息 + * @param name 消息名称 + * @param args 参数 + * @returns Promise 测试结果 + */ + IpcManager.testIpcMessage = function (name_2) { + return __awaiter(this, arguments, void 0, function (name, args) { + if (args === void 0) { args = null; } + return __generator(this, function (_a) { + return [2 /*return*/, new Promise(function (resolve) { + // 简单防呆:防止执行危险操作 + // 如果消息包含 "delete", "remove", "close", "stop" 且没有明确参数确认,则警告 + // 但用户要求"快速验证",所以我们默认允许,但如果是无参调用可能有风险 + // 这里我们尝试使用 Editor.Ipc.sendToMain 或 requestToMain + // @ts-ignore + // 简单的测试:只是发送看看是否报错。 + // 对于 request 类型的消息,我们期望有回调 + // Cocos Creator 2.4 API: Editor.Ipc.sendToMain(message, ...args) + try { + // @ts-ignore + if (Editor.Ipc.sendToMain) { + // @ts-ignore + Editor.Ipc.sendToMain(name, args); + resolve({ success: true, message: "Message sent (sendToMain)" }); + } + else { + resolve({ success: false, message: "Editor.Ipc.sendToMain not available" }); + } + } + catch (e) { + resolve({ success: false, message: "Error: ".concat(e.message) }); + } + })]; + }); + }); + }; + return IpcManager; +}()); +exports.IpcManager = IpcManager; diff --git a/dist/IpcUi.js b/dist/IpcUi.js new file mode 100644 index 0000000..e635f2f --- /dev/null +++ b/dist/IpcUi.js @@ -0,0 +1,233 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.IpcUi = void 0; +// @ts-ignore +var Editor = window.Editor; +var IpcUi = /** @class */ (function () { + function IpcUi(root) { + this.logArea = null; + this.ipcList = null; + this.allMessages = []; + this.filterSelect = null; + this.paramInput = null; + this.root = root; + this.bindEvents(); + } + IpcUi.prototype.bindEvents = function () { + var _this = this; + var btnScan = this.root.querySelector("#btnScanIpc"); + var btnTest = this.root.querySelector("#btnTestIpc"); + var cbSelectAll = this.root.querySelector("#cbSelectAllIpc"); + this.logArea = this.root.querySelector("#ipcLog"); + this.ipcList = this.root.querySelector("#ipcList"); + this.filterSelect = this.root.querySelector("#ipcFilter"); + this.paramInput = this.root.querySelector("#ipcParams"); + if (btnScan) { + btnScan.addEventListener("confirm", function () { return _this.scanMessages(); }); + } + if (btnTest) { + btnTest.addEventListener("confirm", function () { return _this.testSelected(); }); + } + if (cbSelectAll) { + cbSelectAll.addEventListener("change", function (e) { return _this.toggleAll(e.detail ? e.detail.value : (e.target.value === 'true' || e.target.checked)); }); + } + if (this.filterSelect) { + this.filterSelect.addEventListener("change", function () { return _this.filterMessages(); }); + } + }; + IpcUi.prototype.scanMessages = function () { + var _this = this; + this.log("Scanning IPC messages..."); + // @ts-ignore + Editor.Ipc.sendToMain("mcp-bridge:scan-ipc-messages", function (err, msgs) { + if (err) { + _this.log("Scan Error: ".concat(err)); + return; + } + if (msgs) { + _this.allMessages = msgs; + _this.filterMessages(); + _this.log("Found ".concat(msgs.length, " messages.")); + } + else { + _this.log("No messages found."); + } + }); + }; + IpcUi.prototype.filterMessages = function () { + if (!this.allMessages) + return; + var filter = this.filterSelect ? this.filterSelect.value : "all"; + var filtered = this.allMessages; + if (filter === "available") { + filtered = this.allMessages.filter(function (m) { return m.status === "可用"; }); + } + else if (filter === "unavailable") { + filtered = this.allMessages.filter(function (m) { return m.status && m.status.includes("不可用"); }); + } + else if (filter === "untested") { + filtered = this.allMessages.filter(function (m) { return !m.status || m.status === "未测试"; }); + } + this.renderList(filtered); + }; + IpcUi.prototype.renderList = function (msgs) { + var _this = this; + if (!this.ipcList) + return; + this.ipcList.innerHTML = ""; + msgs.forEach(function (msg) { + var item = document.createElement("div"); + item.className = "ipc-item"; + item.style.padding = "4px"; + item.style.borderBottom = "1px solid #333"; + item.style.display = "flex"; + item.style.alignItems = "center"; + // Checkbox + var checkbox = document.createElement("ui-checkbox"); + // @ts-ignore + checkbox.value = false; + checkbox.setAttribute("data-name", msg.name); + checkbox.style.marginRight = "8px"; + // Content + var content = document.createElement("div"); + content.style.flex = "1"; + content.style.fontSize = "11px"; + var statusColor = "#888"; // Untested + if (msg.status === "可用") + statusColor = "#4CAF50"; // Green + else if (msg.status && msg.status.includes("不可用")) + statusColor = "#F44336"; // Red + content.innerHTML = "\n
\n ".concat(msg.name, "\n ").concat(msg.status || "未测试", "\n
\n
").concat(msg.description || "No desc", "
\n
Params: ").concat(msg.params || "None", "
\n "); + // Action Button + var btnRun = document.createElement("ui-button"); + btnRun.innerText = "Run"; + btnRun.className = "tiny"; + btnRun.style.height = "20px"; + btnRun.style.lineHeight = "20px"; + btnRun.addEventListener("confirm", function () { + _this.runTest(msg.name); + }); + item.appendChild(checkbox); + item.appendChild(content); + item.appendChild(btnRun); + _this.ipcList.appendChild(item); + }); + }; + IpcUi.prototype.testSelected = function () { + return __awaiter(this, void 0, void 0, function () { + var checkboxes, toTest, _i, toTest_1, name_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + checkboxes = this.root.querySelectorAll("#ipcList ui-checkbox"); + toTest = []; + checkboxes.forEach(function (cb) { + // In Cocos 2.x, ui-checkbox value is boolean + if (cb.checked || cb.value === true) { + toTest.push(cb.getAttribute("data-name")); + } + }); + if (toTest.length === 0) { + this.log("No messages selected."); + return [2 /*return*/]; + } + this.log("Starting batch test for ".concat(toTest.length, " messages...")); + _i = 0, toTest_1 = toTest; + _a.label = 1; + case 1: + if (!(_i < toTest_1.length)) return [3 /*break*/, 4]; + name_1 = toTest_1[_i]; + return [4 /*yield*/, this.runTest(name_1)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: + _i++; + return [3 /*break*/, 1]; + case 4: + this.log("Batch test completed."); + return [2 /*return*/]; + } + }); + }); + }; + IpcUi.prototype.runTest = function (name) { + var _this = this; + return new Promise(function (resolve) { + var params = null; + if (_this.paramInput && _this.paramInput.value.trim()) { + try { + params = JSON.parse(_this.paramInput.value.trim()); + } + catch (e) { + _this.log("[Error] Invalid JSON Params: ".concat(e)); + resolve(); + return; + } + } + _this.log("Testing: ".concat(name, " with params: ").concat(JSON.stringify(params), "...")); + // @ts-ignore + Editor.Ipc.sendToMain("mcp-bridge:test-ipc-message", { name: name, params: params }, function (err, result) { + if (err) { + _this.log("[".concat(name, "] Failed: ").concat(err)); + } + else { + _this.log("[".concat(name, "] Success: ").concat(JSON.stringify(result))); + } + resolve(); + }); + }); + }; + IpcUi.prototype.toggleAll = function (checked) { + var checkboxes = this.root.querySelectorAll("#ipcList ui-checkbox"); + checkboxes.forEach(function (cb) { + cb.value = checked; + }); + }; + IpcUi.prototype.log = function (msg) { + if (this.logArea) { + // @ts-ignore + var time = new Date().toLocaleTimeString(); + this.logArea.value += "[".concat(time, "] ").concat(msg, "\n"); + this.logArea.scrollTop = this.logArea.scrollHeight; + } + }; + return IpcUi; +}()); +exports.IpcUi = IpcUi; diff --git a/main.js b/main.js index 3001097..d5e7557 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,5 @@ "use strict"; +const { IpcManager } = require("./dist/IpcManager"); const http = require("http"); const path = require("path"); @@ -12,7 +13,6 @@ let serverConfig = { active: false, }; -// 封装日志函数,同时发送给面板和编辑器控制台 // 封装日志函数,同时发送给面板和编辑器控制台 function addLog(type, message) { const logEntry = { @@ -182,17 +182,17 @@ const getToolsList = () => { type: "object", properties: { nodeId: { type: "string", description: "节点 UUID" }, - action: { type: "string", enum: ["add", "remove", "get"], description: "操作类型" }, - componentType: { type: "string", description: "组件类型,如 cc.Sprite" }, - componentId: { type: "string", description: "组件 ID (用于 remove 操作)" }, - properties: { type: "object", description: "组件属性 (用于 add 操作)" }, + action: { type: "string", enum: ["add", "remove", "update", "get"], description: "操作类型 (add: 添加组件, remove: 移除组件, update: 更新组件属性, get: 获取组件列表)" }, + componentType: { type: "string", description: "组件类型,如 cc.Sprite (add/update 操作需要)" }, + componentId: { type: "string", description: "组件 ID (remove/update 操作可选)" }, + properties: { type: "object", description: "组件属性 (add/update 操作使用). 支持智能解析: 如果属性类型是组件但提供了节点UUID,会自动查找对应组件。" }, }, required: ["nodeId", "action"], }, }, { name: "manage_script", - description: "管理脚本文件", + description: "管理脚本文件。注意:创建或修改脚本后,编辑器需要时间进行编译(通常几秒钟)。新脚本在编译完成前无法作为组件添加到节点。建议在 create 后调用 refresh_editor,或等待一段时间后再使用 manage_components。", inputSchema: { type: "object", properties: { @@ -914,7 +914,18 @@ export default class NewScript extends cc.Component { update (dt) {} }`, (err) => { - callback(err, err ? null : `Script created at ${scriptPath}`); + if (err) { + callback(err); + } else { + // 【关键修复】创建脚本后,必须刷新 AssetDB 并等待完成, + // 否则后续立即挂载脚本的操作(manage_components)会因找不到脚本 UUID 而失败。 + Editor.assetdb.refresh(scriptPath, (refreshErr) => { + if (refreshErr) { + addLog("warn", `Refresh failed after script creation: ${refreshErr}`); + } + callback(null, `Script created at ${scriptPath}`); + }); + } }, ); break; @@ -1460,19 +1471,44 @@ export default class NewScript extends cc.Component { } addLog("info", `Executing Menu Item: ${menuPath}`); - // 尝试通过 IPC 触发菜单 (Cocos 2.x 常用方式) - // 如果是保存场景,直接使用对应的 stash-and-save IPC - if (menuPath === 'File/Save Scene') { - Editor.Ipc.sendToMain("scene:stash-and-save"); + // 菜单项映射表 (Cocos Creator 2.4.x IPC) + // 参考: IPC_MESSAGES.md + const menuMap = { + 'File/New Scene': 'scene:new-scene', + 'File/Save Scene': 'scene:stash-and-save', + 'File/Save': 'scene:stash-and-save', // 别名 + 'Edit/Undo': 'scene:undo', + 'Edit/Redo': 'scene:redo', + 'Node/Create Empty Node': 'scene:create-node-by-classid', // 简化的映射,通常需要参数 + 'Project/Build': 'app:build-project', + }; + + if (menuMap[menuPath]) { + const ipcMsg = menuMap[menuPath]; + try { + Editor.Ipc.sendToMain(ipcMsg); + callback(null, `Menu action triggered: ${menuPath} -> ${ipcMsg}`); + } catch (err) { + callback(`Failed to execute IPC ${ipcMsg}: ${err.message}`); + } } else { - // 通用尝试 (可能不工作,取决于编辑器版本) - // Editor.Ipc.sendToMain('ui:menu-click', menuPath); - // 兜底:仅记录日志,暂不支持通用菜单点击 - addLog("warn", "Generic menu execution partial support."); + // 对于未在映射表中的菜单,尝试通用的 menu:click (虽然不一定有效) + // 或者直接返回不支持的警告 + addLog("warn", `Menu item '${menuPath}' not found in supported map. Trying legacy fallback.`); + + // 尝试通用调用 + try { + // 注意:Cocos Creator 2.x 的 menu:click 通常需要 Electron 菜单 ID,而不只是路径 + // 这里做个尽力而为的尝试 + Editor.Ipc.sendToMain('menu:click', menuPath); + callback(null, `Generic menu action sent: ${menuPath} (Success guaranteed only for supported items)`); + } catch (e) { + callback(`Failed to execute menu item: ${menuPath}`); + } } - callback(null, `Menu action triggered: ${menuPath}`); }, + // 验证脚本 // 验证脚本 validateScript(args, callback) { const { filePath } = args; @@ -1493,25 +1529,56 @@ export default class NewScript extends cc.Component { try { const content = fs.readFileSync(fspath, "utf-8"); - // 对于 JavaScript 脚本,使用 eval 进行简单验证 + // 检查空文件 + if (!content || content.trim().length === 0) { + return callback(null, { valid: false, message: "Script is empty" }); + } + + // 对于 JavaScript 脚本,使用 Function 构造器进行语法验证 if (filePath.endsWith(".js")) { - // 包装在函数中以避免变量污染 const wrapper = `(function() { ${content} })`; try { - new Function(wrapper); // 使用 Function 构造器比 direct eval稍微安全一点点,虽在这个场景下差别不大 + new Function(wrapper); + callback(null, { valid: true, message: "JavaScript syntax is valid" }); } catch (syntaxErr) { return callback(null, { valid: false, message: syntaxErr.message }); } } - // 对于 TypeScript,暂不进行复杂编译检查,仅确保文件可读 + // 对于 TypeScript,由于没有内置 TS 编译器,我们进行基础的"防呆"检查 + // 并明确告知用户无法进行完整编译验证 + else if (filePath.endsWith(".ts")) { + // 简单的正则表达式检查:是否有非法字符或明显错误结构 (示例) + // 这里暂时只做简单的括号匹配检查或直接通过,但给出一个 Warning - callback(null, { valid: true, message: "Script syntax is valid" }); + // 检查是否有 class 定义 (简单的heuristic) + if (!content.includes('class ') && !content.includes('interface ') && !content.includes('enum ') && !content.includes('export ')) { + return callback(null, { valid: true, message: "Warning: TypeScript file seems to lack standard definitions (class/interface), but basic syntax check is skipped due to missing compiler." }); + } + + callback(null, { valid: true, message: "TypeScript basic check passed. (Full compilation validation requires editor build)" }); + } else { + callback(null, { valid: true, message: "Unknown script type, validation skipped." }); + } } catch (err) { callback(null, { valid: false, message: `Read Error: ${err.message}` }); } }, // 暴露给 MCP 或面板的 API 封装 messages: { + "scan-ipc-messages"(event) { + try { + const msgs = IpcManager.getIpcMessages(); + if (event.reply) event.reply(null, msgs); + } catch (e) { + if (event.reply) event.reply(e.message); + } + }, + "test-ipc-message"(event, args) { + const { name, params } = args; + IpcManager.testIpcMessage(name, params).then((result) => { + if (event.reply) event.reply(null, result); + }); + }, "open-test-panel"() { Editor.Panel.open("mcp-bridge"); }, diff --git a/package.json b/package.json index 84eb7a1..3d46a57 100644 --- a/package.json +++ b/package.json @@ -23,4 +23,4 @@ "last-port": 3456 } } -} +} \ No newline at end of file diff --git a/panel/index.html b/panel/index.html index 1a873a5..1e85d56 100644 --- a/panel/index.html +++ b/panel/index.html @@ -2,6 +2,7 @@
Main Tool Test + IPC Test
@@ -22,6 +23,7 @@
+
@@ -57,47 +59,248 @@
+ +
+
+ Scan Messages + +
+ Test Selected +
+
+
+ Select All/None +
+
+
+ + +
+
+ + +
+
+