feat(scripts): resolveSpriteFrameUuid - ImgResID → SpriteFrame 真 UUID
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
|||||||
|
import { test } from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { resolveSpriteFrameUuid } from '../../scripts/legacy-layer-to-cocos-prefab.mjs';
|
||||||
|
|
||||||
|
// 数据源权威: gameabc_Image.json id=20 -> bmp="00020.png" 位于 atlas-login/,
|
||||||
|
// 该 .meta 的 subMetas.f9941.uuid 为 e36acab8-e623-4bfb-af05-3c6fd2fddfb4@f9941
|
||||||
|
// (SpriteFrame 真 UUID, 含 sub-asset 后缀).
|
||||||
|
|
||||||
|
test('resolveSpriteFrameUuid("20") 返回 atlas-login/00020.png 的 SpriteFrame 真 UUID', () => {
|
||||||
|
const uuid = resolveSpriteFrameUuid('20');
|
||||||
|
assert.equal(uuid, 'e36acab8-e623-4bfb-af05-3c6fd2fddfb4@f9941');
|
||||||
|
assert.match(uuid, /@f9941$/, '必须含 SpriteFrame sub-asset 后缀 @f9941');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('未知 imgResId → throw(不静默兜底)', () => {
|
||||||
|
// 数据源权威唯一、下游不兜底: ImgResID 不在 gameabc_Image.json 时必须显式报错.
|
||||||
|
assert.throws(
|
||||||
|
() => resolveSpriteFrameUuid('99999999'),
|
||||||
|
/ImgResID .* not in gameabc_Image\.json/
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { readFileSync } from 'node:fs';
|
import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';
|
||||||
import { dirname, join } from 'node:path';
|
import { dirname, join } from 'node:path';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import { DOMParser } from '@xmldom/xmldom';
|
import { DOMParser } from '@xmldom/xmldom';
|
||||||
@@ -176,3 +176,84 @@ export function mapSpiritTypeToComponent(type) {
|
|||||||
}
|
}
|
||||||
return entry.component;
|
return entry.component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImgResID (XML) → SpriteFrame 真 UUID. 数据源: fixtures/gameabc_Image.json + YouleNexus
|
||||||
|
// `atlas-*` 目录下的 .meta (含 subMetas.f9941.uuid). 下游不兜底: imgResId 不存在 / 对应
|
||||||
|
// bmp 不在任何 `atlas-*` 下 / .meta 缺 f9941 → 全部 throw.
|
||||||
|
const IMAGE_MAP_PATH = join(
|
||||||
|
__dirname,
|
||||||
|
'../framework-tests/legacy-layer-migration/fixtures/gameabc_Image.json'
|
||||||
|
);
|
||||||
|
|
||||||
|
let _imageMap = null;
|
||||||
|
function loadImageMap() {
|
||||||
|
if (!_imageMap) _imageMap = JSON.parse(readFileSync(IMAGE_MAP_PATH, 'utf8'));
|
||||||
|
return _imageMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ATLAS_ROOT = join(
|
||||||
|
__dirname,
|
||||||
|
'../YouleNexus/assets/framework/ui'
|
||||||
|
);
|
||||||
|
|
||||||
|
let _bmpToMetaPath = null;
|
||||||
|
function loadBmpToMetaPath() {
|
||||||
|
if (_bmpToMetaPath) return _bmpToMetaPath;
|
||||||
|
const map = new Map();
|
||||||
|
if (existsSync(ATLAS_ROOT)) {
|
||||||
|
for (const entry of readdirSync(ATLAS_ROOT)) {
|
||||||
|
if (!entry.startsWith('atlas-')) continue;
|
||||||
|
const dir = join(ATLAS_ROOT, entry);
|
||||||
|
if (!statSync(dir).isDirectory()) continue;
|
||||||
|
for (const file of readdirSync(dir)) {
|
||||||
|
if (!file.endsWith('.png.meta')) continue;
|
||||||
|
const bmpName = file.replace(/\.meta$/, '');
|
||||||
|
// 同一 bmp 出现在多个 atlas 时, 取首次发现 (字典序);
|
||||||
|
// YouleNexus 实际数据中无重复, 此为防御性 fallback.
|
||||||
|
if (!map.has(bmpName)) map.set(bmpName, join(dir, file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_bmpToMetaPath = map;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 XML 中的 ImgResID 字符串解析为 SpriteFrame 真 UUID (含 @f9941 sub-asset 后缀).
|
||||||
|
*
|
||||||
|
* 流程: gameabc_Image.json[id].bmp → `atlas-*`/<bmp>.meta → subMetas.f9941.uuid.
|
||||||
|
*
|
||||||
|
* 数据源权威唯一、下游不兜底:
|
||||||
|
* - imgResId 不在 gameabc_Image.json → throw
|
||||||
|
* - 对应 bmp 不在任何 `atlas-*` 下 → throw
|
||||||
|
* - .meta 缺 subMetas.f9941 → throw (说明该资源未走 sprite-frame 导入)
|
||||||
|
*
|
||||||
|
* @param {string} imgResId - XML ImgResID 字符串 (如 "20", "21", "25")
|
||||||
|
* @returns {string} SpriteFrame 真 UUID, 形如 "<uuid>@f9941"
|
||||||
|
*/
|
||||||
|
export function resolveSpriteFrameUuid(imgResId) {
|
||||||
|
const imageMap = loadImageMap();
|
||||||
|
const list = imageMap.ImageFileList;
|
||||||
|
if (!Array.isArray(list)) {
|
||||||
|
throw new Error('gameabc_Image.json missing ImageFileList array');
|
||||||
|
}
|
||||||
|
const entry = list.find(e => e && e.id != null && (e.id === Number(imgResId) || String(e.id) === imgResId));
|
||||||
|
if (!entry || !entry.bmp) {
|
||||||
|
const known = list.filter(e => e && e.id != null).slice(0, 5).map(e => e.id).join(', ');
|
||||||
|
throw new Error(`ImgResID "${imgResId}" not in gameabc_Image.json (known ids sample: ${known}...)`);
|
||||||
|
}
|
||||||
|
const bmpName = entry.bmp;
|
||||||
|
|
||||||
|
const bmpToMeta = loadBmpToMetaPath();
|
||||||
|
const metaPath = bmpToMeta.get(bmpName);
|
||||||
|
if (!metaPath) {
|
||||||
|
throw new Error(`bmp "${bmpName}" (ImgResID ${imgResId}) not found under 'atlas-*' in ${ATLAS_ROOT}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const meta = JSON.parse(readFileSync(metaPath, 'utf8'));
|
||||||
|
const spriteFrame = meta.subMetas && meta.subMetas.f9941;
|
||||||
|
if (!spriteFrame || !spriteFrame.uuid) {
|
||||||
|
throw new Error(`${bmpName}.meta missing subMetas.f9941.uuid (importer not sprite-frame?)`);
|
||||||
|
}
|
||||||
|
return spriteFrame.uuid;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user