From f54f0762ef8b8994311df471da85db97b9023a47 Mon Sep 17 00:00:00 2001 From: furao Date: Sun, 7 Jun 2026 19:00:47 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20fix-borders=20=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E6=94=B9=E5=90=8D=E4=B8=BA=20fix-meta=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20trim=20=E7=A0=B4=E5=9D=8F=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 改名 fix-borders → fix-meta(CLI 子命令 fix-meta;MCP tool meta_fix),名字更通用 - 新增第三类噪音识别:trimType 从 none 被 Cocos 改成自动裁剪(连带 width/height/ offset/顶点全变)→ 还原该 frame 到 git(恢复不裁剪)。保守:只还原 git=none 的 明确破坏,不碰 git 本就 auto 的(分不清破坏 vs 真改) - 三类统一处理:① 纯顺序/格式噪音 ② 九宫格 border 重置 ③ trim 强改 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../{fix-borders-cmd.js => fix-meta-cmd.js} | 32 +++++----- cli/src/cli/main.js | 8 +-- .../editor/{fix-borders.js => fix-meta.js} | 63 ++++++++++++------- main.js | 6 +- server/tools.js | 6 +- 5 files changed, 66 insertions(+), 49 deletions(-) rename cli/src/cli/{fix-borders-cmd.js => fix-meta-cmd.js} (53%) rename cli/src/editor/{fix-borders.js => fix-meta.js} (58%) diff --git a/cli/src/cli/fix-borders-cmd.js b/cli/src/cli/fix-meta-cmd.js similarity index 53% rename from cli/src/cli/fix-borders-cmd.js rename to cli/src/cli/fix-meta-cmd.js index 3c2e2c2..e2b244a 100644 --- a/cli/src/cli/fix-borders-cmd.js +++ b/cli/src/cli/fix-meta-cmd.js @@ -1,22 +1,23 @@ // ============================================================ -// cli/fix-borders-cmd.js — fix-borders 子命令 +// cli/fix-meta-cmd.js — fix-meta 子命令 // // 用法: -// cocos-mcp-cli fix-borders [--project ] [--dry-run] +// cocos-mcp-cli fix-meta [--project ] [--dry-run] // -// 修复 Cocos 重启把图片九宫格 border(subMetas.*.userData.border*)重置成 0 的 meta: -// 扫 git 改动的 .meta,把「git 里有值、工作区被清 0」的 border 还原成 git 的值。 -// 只动 border 字段、保留 meta 其它改动。 +// 清理 Cocos 重启造成的图片 meta 噪音(保守,只还原能确认是破坏的): +// 1) 纯 key 顺序/格式变化(值没变)→ 还原成 git 原文 +// 2) 九宫格 border 被重置成 0 → 用 git 的值精准还原 +// 3) trimType 从 none 被改成自动裁剪 → 还原该 frame 到 git(恢复不裁剪) // --dry-run 只预览不写;--project 指定项目路径(默认当前目录)。 // ============================================================ 'use strict'; -const { fixResetBorders } = require('../editor/fix-borders.js'); +const { fixMeta } = require('../editor/fix-meta.js'); function die(msg) { process.stderr.write('Error: ' + msg + '\n'); process.exit(1); } -function cmdFixBorders(argv) { +function cmdFixMeta(argv) { let project = process.cwd(); let dryRun = false; @@ -28,12 +29,13 @@ function cmdFixBorders(argv) { project = argv[++i]; } else if (a === '--help' || a === '-h') { process.stdout.write( - 'cocos-mcp-cli fix-borders — 清理 Cocos 重启造成的图片 meta 噪音\n\n' + + 'cocos-mcp-cli fix-meta — 清理 Cocos 重启造成的图片 meta 噪音\n\n' + ' --project, -p 项目路径(git 仓库或其子目录,默认当前目录)\n' + ' --dry-run 只预览将还原哪些,不写文件\n\n' + - '处理两类噪音(都靠 git 对比,正确处理中文路径):\n' + + '处理三类(都靠 git 对比,正确处理中文路径,保守只还原能确认的):\n' + ' 1) 纯 key 顺序/格式变化(值没变)→ 还原成 git 原文\n' + - ' 2) 九宫格 border 被重置成 0 → 用 git 的值精准还原\n'); + ' 2) 九宫格 border 被重置成 0 → 用 git 的值精准还原\n' + + ' 3) trimType 从 none 被改成自动裁剪 → 还原该 frame 到 git(恢复不裁剪)\n'); return; } else { die('未知参数 "' + a + '"'); @@ -42,20 +44,20 @@ function cmdFixBorders(argv) { let r; try { - r = fixResetBorders(project, { dryRun: dryRun }); + r = fixMeta(project, { dryRun: dryRun }); } catch (e) { die(e.message); } process.stdout.write( (dryRun ? '[dry-run] ' : '') + - '扫描 ' + r.scanned + ' 个改动 meta:顺序噪音还原 ' + r.reorderFiles + - ' 个,border 还原 ' + r.borderFiles + ' 个 meta / ' + r.borderFrames + ' frame\n'); + '扫描 ' + r.scanned + ' 个改动 meta:顺序还原 ' + r.reorderFiles + + ' 个,值修复 ' + r.fixedFiles + ' 个 meta(border ' + r.borderFrames + ' frame / trim ' + r.trimFrames + ' frame)\n'); if (r.details.length) { process.stdout.write(r.details.slice(0, 50).join('\n') + '\n'); - if (r.details.length > 50) process.stdout.write('...(共 ' + r.details.length + ' 处,此处只列前 50)\n'); + if (r.details.length > 50) process.stdout.write('...(共 ' + r.details.length + ' 处,只列前 50)\n'); } } -module.exports = { cmdFixBorders }; +module.exports = { cmdFixMeta }; diff --git a/cli/src/cli/main.js b/cli/src/cli/main.js index 13c5d99..0763236 100644 --- a/cli/src/cli/main.js +++ b/cli/src/cli/main.js @@ -20,7 +20,7 @@ const { cmdExtractPrefab } = require('./extract-cmd.js'); const { cmdCompactPrefab } = require('./compact-cmd.js'); const { cmdEnsureMeta } = require('./ensure-meta-cmd.js'); const { cmdBuild } = require('./build-cmd.js'); -const { cmdFixBorders } = require('./fix-borders-cmd.js'); +const { cmdFixMeta } = require('./fix-meta-cmd.js'); function die(msg) { process.stderr.write('Error: ' + msg + '\n'); @@ -56,10 +56,10 @@ function main(argv) { cmdEnsureMeta(rest); } else if (cmd === 'build') { cmdBuild(rest); - } else if (cmd === 'fix-borders') { - cmdFixBorders(rest); + } else if (cmd === 'fix-meta') { + cmdFixMeta(rest); } else { - die(`未知子命令 "${cmd}",可用: query / set / batch / anim / diff / create-prefab / extract-prefab / compact-prefab / ensure-meta / build / fix-borders`); + die(`未知子命令 "${cmd}",可用: query / set / batch / anim / diff / create-prefab / extract-prefab / compact-prefab / ensure-meta / build / fix-meta`); } } diff --git a/cli/src/editor/fix-borders.js b/cli/src/editor/fix-meta.js similarity index 58% rename from cli/src/editor/fix-borders.js rename to cli/src/editor/fix-meta.js index 61960ba..f8a1ee3 100644 --- a/cli/src/editor/fix-borders.js +++ b/cli/src/editor/fix-meta.js @@ -1,20 +1,26 @@ // ============================================================ -// editor/fix-borders.js — 清理 Cocos 重启/重新导入造成的图片 meta 噪音 +// editor/fix-meta.js — 清理 Cocos 重启/重新导入造成的图片 meta 噪音 // -// 现象(Cocos 重启/重新导入有时发生): -// 1) 纯 key 顺序/格式变化:如 userData 里 trimType/atlasUuid 等字段被重排位置, +// Cocos 重启/重新导入有时会改坏图片 .meta,常见三类: +// 1) 纯 key 顺序/格式变化:如 userData 里 trimType/atlasUuid 等被重排位置, // 值没变,只产生 git diff 噪音。 // 2) 九宫格 border 被重置:subMetas..userData.{borderTop,Bottom,Left,Right} -// 被清成 0(九宫格丢失,数据真丢)。 +// 被清成 0(九宫格丢失)。 +// 3) trim 裁剪被强改:用户设 trimType="none"(不裁剪)的图,被改成 "auto"(自动裁剪), +// 连带 width/height/offset/trimX-Y/顶点全变。 // -// 修复:扫 git 工作区改动的 .meta,逐个对比 git 版本: -// - 值深度相等(只 key 顺序/格式不同)→ 直接还原成 git 原文,消噪音; -// - 值不等但只是九宫格 border 被重置成 0 → 用 git 的值精准还原 border; -// 还原后若整体已等于 git(差异仅 border + 顺序)也直接写 git 原文,否则只改 border -// 字段、保留 meta 其它真实改动。 +// 修复(保守,只还原能确认是 Cocos 破坏的,不碰分不清的):扫 git 工作区改动的 .meta, +// 逐个对比 git 版本: +// - 值深度相等(只 key 顺序/格式不同)→ 还原成 git 原文; +// - border 被重置成 0(git 有值)→ 用 git 的值精准还原 border; +// - trimType 从 none 被改成裁剪 → 还原该 frame 的 userData 到 git(恢复不裁剪); +// - 还原后若整体已等于 git → 直接写 git 原文,否则只改动过的字段、保留 meta 其它真实改动。 +// +// 不处理:git 本来就 trimType="auto" 的图(auto→auto 值变分不清破坏 vs 真改)、 +// 以及其它无明确破坏特征的值变化。 // // 靠 git 对比拿正确值;git 调用统一带 core.quotePath=false,正确处理中文路径。 -// 纯 Node + git,跨平台。供 CLI(fix-borders-cmd)和 MCP tool 共用。 +// 纯 Node + git,跨平台。供 CLI(fix-meta-cmd)和 MCP tool 共用。 // ============================================================ 'use strict'; @@ -39,14 +45,15 @@ function norm(o) { return o; } function valueEqual(a, b) { return JSON.stringify(norm(a)) === JSON.stringify(norm(b)); } +function deepClone(o) { return JSON.parse(JSON.stringify(o)); } /** - * 清理被 Cocos 重启搞乱的 .meta(顺序噪音 + 九宫格 border 重置)。 + * 清理被 Cocos 重启搞坏的 .meta(顺序噪音 / 九宫格 border 重置 / trim 被强改)。 * @param {string} projectOrRoot 项目路径(git 仓库或其子目录均可) * @param {{dryRun?:boolean}} [opts] - * @returns {{gitRoot, scanned, reorderFiles, borderFiles, borderFrames, details:string[]}} + * @returns {{gitRoot, scanned, reorderFiles, fixedFiles, borderFrames, trimFrames, details:string[]}} */ -function fixResetBorders(projectOrRoot, opts) { +function fixMeta(projectOrRoot, opts) { opts = opts || {}; var dryRun = !!opts.dryRun; @@ -63,7 +70,7 @@ function fixResetBorders(projectOrRoot, opts) { var changed = git(gitRoot, ['diff', '--name-only', '--', '*.meta']) .split('\n').map(function (s) { return s.trim(); }).filter(Boolean); - var reorderFiles = 0, borderFiles = 0, borderFrames = 0; + var reorderFiles = 0, fixedFiles = 0, borderFrames = 0, trimFrames = 0; var details = []; for (var i = 0; i < changed.length; i++) { @@ -83,7 +90,7 @@ function fixResetBorders(projectOrRoot, opts) { continue; } - // 2) 值不等 → 检查九宫格 border 是否被重置成 0,精准还原 + // 2) 值不等 → 逐 frame 识别 trim 破坏 / border 重置 var wSubs = work && work.subMetas; var hSubs = head && head.subMetas; if (!wSubs || !hSubs || typeof wSubs !== 'object' || typeof hSubs !== 'object') continue; @@ -95,21 +102,28 @@ function fixResetBorders(projectOrRoot, opts) { var wud = wSubs[key] && wSubs[key].userData; var hud = hSubs[key] && hSubs[key].userData; if (!wud || !hud) continue; - if (!BORDER_KEYS.some(function (b) { return b in wud; })) continue; - if (allZero(wud) && anyNonZero(hud)) { + + // trim 破坏:git trimType=none、工作区被改成裁剪(none→非none)→ 还原整个 frame userData + if (hud.trimType === 'none' && wud.trimType && wud.trimType !== 'none') { + wSubs[key].userData = deepClone(hud); + metaChanged = true; trimFrames++; + details.push('[trim] ' + rel + ' [' + key + '] ' + wud.trimType + '→none(还原不裁剪)'); + continue; + } + + // border 重置:工作区 border 全 0、git 有非 0 → 精准还原 border 四字段 + if (BORDER_KEYS.some(function (b) { return b in wud; }) && allZero(wud) && anyNonZero(hud)) { for (var b = 0; b < BORDER_KEYS.length; b++) wud[BORDER_KEYS[b]] = hud[BORDER_KEYS[b]]; - metaChanged = true; - borderFrames++; + metaChanged = true; borderFrames++; details.push('[border] ' + rel + ' [' + key + '] → T' + hud.borderTop + '/B' + hud.borderBottom + '/L' + hud.borderLeft + '/R' + hud.borderRight); } } if (metaChanged) { - borderFiles++; + fixedFiles++; if (!dryRun) { - // 还原 border 后若整体已等于 git(差异仅 border + 顺序)→ 直接写 git 原文,最干净; - // 否则只改了 border 字段、保留其它真实改动 → 按 work 写回(Cocos 标准格式) + // 还原后若整体已等于 git → 直接写 git 原文(连带消顺序噪音);否则按 work 写回、保留其它真实改动 if (valueEqual(work, head)) fs.writeFileSync(abs, headStr, 'utf8'); else fs.writeFileSync(abs, JSON.stringify(work, null, 2) + '\n', 'utf8'); } @@ -118,9 +132,10 @@ function fixResetBorders(projectOrRoot, opts) { return { gitRoot: gitRoot, scanned: changed.length, - reorderFiles: reorderFiles, borderFiles: borderFiles, borderFrames: borderFrames, + reorderFiles: reorderFiles, fixedFiles: fixedFiles, + borderFrames: borderFrames, trimFrames: trimFrames, details: details, }; } -module.exports = { fixResetBorders: fixResetBorders }; +module.exports = { fixMeta: fixMeta }; diff --git a/main.js b/main.js index 4cb636a..701c619 100644 --- a/main.js +++ b/main.js @@ -488,9 +488,9 @@ function buildToolCtx() { cleanDevDir: function () { return exports.methods.cleanDevDir(); }, getStatus: function () { return exports.methods.getStatus(); }, reloadPackage: doRestartSelf, - fixResetBorders: function (opts) { - var mod = require('./cli/src/editor/fix-borders.js'); - return mod.fixResetBorders(Editor.Project.path, opts || {}); + fixMeta: function (opts) { + var mod = require('./cli/src/editor/fix-meta.js'); + return mod.fixMeta(Editor.Project.path, opts || {}); }, }, }; diff --git a/server/tools.js b/server/tools.js index 02d34be..b63b56e 100644 --- a/server/tools.js +++ b/server/tools.js @@ -309,14 +309,14 @@ function defineTools(ctx) { }, }, { - name: 'meta_fix_reset_border', - description: '清理 Cocos 重启造成的图片 meta 噪音:① 纯 key 顺序/格式变化(值没变只 git diff 噪音)还原成 git 原文;② 九宫格 border(subMetas.*.userData.border*)被重置成 0 的精准还原 git 的值。靠 git 对比、正确处理中文路径。dryRun=true 只预览不写。', + name: 'meta_fix', + description: '清理 Cocos 重启造成的图片 meta 噪音(保守,只还原能确认是破坏的):① 纯 key 顺序/格式变化还原 git 原文;② 九宫格 border 被重置成 0 精准还原;③ trimType 从 none 被改成自动裁剪还原该 frame 到 git。靠 git 对比、正确处理中文路径。dryRun=true 只预览不写。', inputSchema: { type: 'object', properties: { dryRun: { type: 'boolean', description: 'true=只预览不写文件,列出将还原的 meta' } }, }, handler: async function (args) { - return local.fixResetBorders({ dryRun: !!(args && args.dryRun) }); + return local.fixMeta({ dryRun: !!(args && args.dryRun) }); }, }, ];