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 { fileURLToPath } from 'node:url';
|
||||
import { DOMParser } from '@xmldom/xmldom';
|
||||
@@ -176,3 +176,84 @@ export function mapSpiritTypeToComponent(type) {
|
||||
}
|
||||
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