From d601ec809022dead56a3f9af9e2c3e37511b236d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=81=AB=E7=84=B0=E5=BA=93=E6=8B=89?= <820449643@qq.com> Date: Thu, 26 Feb 2026 15:45:41 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DSpriteFrame=E8=B5=8B?= =?UTF-8?q?=E5=80=BC=E6=9C=AA=E8=8E=B7=E5=8F=96=E7=9C=9F=E5=AE=9EUUID?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=8F=8A=E9=9D=A2=E6=9D=BF=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E8=A2=AB=E6=88=AA=E6=96=AD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UPDATE_LOG.md | 14 ++++++++++++++ main.js | 39 +++++++++++++++++++++++++++++++++------ package.json | 12 ++++++++++++ scene-script.js | 26 ++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 6 deletions(-) diff --git a/UPDATE_LOG.md b/UPDATE_LOG.md index 5094c75..b5c5bd1 100644 --- a/UPDATE_LOG.md +++ b/UPDATE_LOG.md @@ -207,3 +207,17 @@ - **问题**: AI 偶尔会幻觉以为 `prefab_management`/`manage_script`/`manage_material`/`manage_texture`/`manage_shader` 的更新动作为 `save`,而不是标准定义的 `update` 或 `write`,导致抛出“未知的管理操作”报错。 - **修复**: 在 `main.js` 所有这些管理工具的核心路由表中,为 `update` 和 `write` 操作均显式添加了 `case "save":` 作为后备兼容,极大地增强了不同大模型在不同提示词上下文环境下的操作容错率。 + +--- + +## 素材库与面板工具优化 (2026-02-26) + +### 1. 材质与 SpriteFrame 赋值增强 + +- **问题**: 虽然支持了加载 Texture2D,但如果 AI 传给 `Sprite.spriteFrame` 属性的是原生贴图 UUID,在 `scene-script.js` 层面直接强转为 `new cc.SpriteFrame(asset)` 容易丢掉原图片配置信息,例如九宫格参数。 +- **重构**: 新增底层 IPC 消息 `query-spriteframe-uuid`。现在当场景脚本识别到目标属性为精灵材质时,会通过跨进程向主进程查询目标 UUID 关联物理文件所属的 `.meta`。提取真实的 `subMetas` 内 SpriteFrame 的长 UUID 并返回。之后再基于该长 UUID 调用标准的 `loadAsset`。彻底保证资源结构的稳定性。 + +### 2. 测试面板输出全量解析 + +- **问题**: 为了防止大体积结构传递给 AI 时引发 OOM 截断崩溃,`main.js` 后台强行限制了所有日志向 Webview 输出的边界值 (默认不超过 100~500 字符),导致人类开发者从面板查看时无法追溯长内容如 Base64 和完整序列化返回值。 +- **修复**: 拆分了拦截逻辑。剔除 `argsPreview` 与 `preview` 针对主面板渲染视图输出 `addLog` 时的预备阶段的 `substring` 剪裁。如今编辑器 UI 内将能看到完整、原生的调用参数和回调结果,而对于通过 HTTP 接口返还给 AI 的载荷依然安全拦截。 diff --git a/main.js b/main.js index 53032cd..07b92b7 100644 --- a/main.js +++ b/main.js @@ -695,6 +695,37 @@ const getToolsList = () => { module.exports = { "scene-script": "scene-script.js", + openTestPanel() { + Editor.Panel.open("mcp-bridge"); + }, + querySpriteFrameUuid(event, uuid) { + const fs = require("fs"); + try { + const url = Editor.assetdb.uuidToUrl(uuid); + if (!url) { + return event.reply && event.reply(null, null); + } + const fspath = Editor.assetdb.urlToFspath(url); + if (!fspath) { + return event.reply && event.reply(null, null); + } + const metaPath = fspath + ".meta"; + if (fs.existsSync(metaPath)) { + const meta = JSON.parse(fs.readFileSync(metaPath, "utf8")); + if (meta && meta.subMetas) { + const subKeys = Object.keys(meta.subMetas); + for (let k of subKeys) { + if (meta.subMetas[k].uuid) { + return event.reply && event.reply(null, meta.subMetas[k].uuid); + } + } + } + } + return event.reply && event.reply(null, null); + } catch (e) { + return event.reply && event.reply(null, null); + } + }, /** * 插件加载时的回调 */ @@ -840,9 +871,6 @@ module.exports = { if (args) { try { argsPreview = typeof args === "object" ? JSON.stringify(args) : String(args); - if (argsPreview.length > 500) { - argsPreview = argsPreview.substring(0, 500) + "...[Truncated]"; - } } catch (e) { argsPreview = "[无法序列化的参数]"; } @@ -868,11 +896,10 @@ module.exports = { } else { let preview = ""; if (typeof result === "string") { - preview = result.length > 100 ? result.substring(0, 100) + "..." : result; + preview = result; } else if (typeof result === "object") { try { - const jsonStr = JSON.stringify(result); - preview = jsonStr.length > 100 ? jsonStr.substring(0, 100) + "..." : jsonStr; + preview = JSON.stringify(result); } catch (e) { preview = "Object (Circular/Unserializable)"; } diff --git a/package.json b/package.json index 85ddd51..44e2752 100644 --- a/package.json +++ b/package.json @@ -22,5 +22,17 @@ "auto-start": false, "last-port": 3456 } + }, + "messages": { + "open-test-panel": { + "methods": [ + "openTestPanel" + ] + }, + "query-spriteframe-uuid": { + "methods": [ + "querySpriteFrameUuid" + ] + } } } diff --git a/scene-script.js b/scene-script.js index 67e3356..ff55868 100644 --- a/scene-script.js +++ b/scene-script.js @@ -447,9 +447,35 @@ module.exports = { loadedCount++; return; } + + // 从主进程查询是否这个 UUID 其实是一个纹理,而我们真正需要的是它的 SpriteFrame 子资源 + if (propertyType === cc.SpriteFrame || key.toLowerCase().includes("sprite")) { + try { + const sfUuid = Editor.Ipc.sendToMainSync( + "mcp-bridge:query-spriteframe-uuid", + uuid, + ); + if (sfUuid && sfUuid !== uuid) { + uuid = sfUuid; + Editor.log( + `[scene-script] 识别到材质类型为 SpriteFrame,已将纹理 UUID 自动纠正为 SpriteFrame UUID: ${uuid}`, + ); + } + } catch (e) { + // 忽略 + } + } + cc.AssetLibrary.loadAsset(uuid, (err, asset) => { loadedCount++; if (!err && asset) { + // 自动处理 Texture2D 到 SpriteFrame 的转换,防止由于传错了图片 UUID 导致赋值失效 + if ( + asset instanceof cc.Texture2D && + (propertyType === cc.SpriteFrame || key.toLowerCase().includes("sprite")) + ) { + asset = new cc.SpriteFrame(asset); + } loadedAssets[idx] = asset; Editor.log(`[scene-script] 成功为 ${key}[${idx}] 加载资源: ${asset.name}`); } else {