Files
youle_cocos/.pnpm-store/v11/projects/f47659282495706053836086ad375b3e/scripts/convert-ui.mjs
T
2026-09-05 00:12:11 +08:00

94 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
import { readFileSync, writeFileSync, mkdirSync, rmSync, existsSync, copyFileSync } from 'node:fs';
import { join } from 'node:path';
import { pathToFileURL } from 'node:url';
import { ROOT, HOST_PROJECT, frameworkUiDirOf } from './lib/paths.mjs';
import { loadSource } from './ui-migration/gameabc-source.mjs';
import { imageBuckets } from './ui-migration/buckets.mjs';
import { convertAll } from './ui-migration/convert.mjs';
import { splitSheet } from './ui-migration/frame-io.mjs';
import { frameNames } from './ui-migration/frames.mjs';
// 与 verify-frames.mjs 一致:相对 ROOT 推导,不硬编码绝对路径。
const DEFAULT_SOURCE = join(ROOT, '..', 'projects', 'Game_Surface_3');
/**
* 全量转换:产出中间描述 + 切好的散图。
* 幂等:每次先清空产出目录(spec §4.4),避免残留帧文件混进图集。
* 清空对象包括中间描述目录,以及本次实际会写入的每个 atlas-{bucket} 目录
* (按 bucket 惰性清空一次,防止在同一次运行中被同 bucket 的后续图片覆盖式清掉)。
*/
export function runConvert(opts = {}) {
const projectDir = opts.projectDir ?? DEFAULT_SOURCE;
const intermediateDir = opts.intermediateDir ?? join(ROOT, 'ui-migration', 'intermediate');
const uiDir = opts.uiDir ?? frameworkUiDirOf(HOST_PROJECT);
const source = loadSource(join(projectDir, 'output'));
const bucketMap = imageBuckets(source);
const { layers, manifest, warnings } = convertAll(source);
// 1) 中间描述
rmSync(intermediateDir, { recursive: true, force: true });
mkdirSync(intermediateDir, { recursive: true });
writeFileSync(join(intermediateDir, 'manifest.json'), `${JSON.stringify(manifest, null, 2)}\n`);
writeFileSync(join(intermediateDir, 'warnings.json'), `${JSON.stringify(warnings, null, 2)}\n`);
for (const doc of layers) {
const entry = manifest.layers.find((l) => l.layerId === doc.layerId);
writeFileSync(join(intermediateDir, entry.file), `${JSON.stringify(doc, null, 2)}\n`);
}
// 2) 散图:多帧图切分,单帧图直拷
let frameCount = 0;
const cleanedBuckets = new Set();
for (const image of source.images.values()) {
const bucket = bucketMap.get(image.id) ?? 'unassigned';
const outDir = join(uiDir, `atlas-${bucket}`);
if (!cleanedBuckets.has(bucket)) {
rmSync(outDir, { recursive: true, force: true });
mkdirSync(outDir, { recursive: true });
cleanedBuckets.add(bucket);
}
const src = join(projectDir, 'assets', 'bmp', image.bmp);
if (!existsSync(src)) {
throw new Error(`图片文件不存在: ${src}(图 id=${image.id})`);
}
if (image.frame_all <= 1) {
copyFileSync(src, join(outDir, image.bmp));
frameCount++;
continue;
}
const names = frameNames(image);
splitSheet(readFileSync(src), image).forEach((buf, i) => {
writeFileSync(join(outDir, names[i]), buf);
frameCount++;
});
}
const unassigned = layers.filter((l) => l.bucket === 'unassigned').map((l) => l.name);
return {
layerCount: layers.length,
nodeCount: layers.reduce((s, l) => s + l.nodes.length, 0),
imageCount: source.images.size,
frameCount,
unassigned,
warningCount: warnings.length,
};
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
const r = runConvert();
console.log(`界面 ${r.layerCount} 个 / 节点 ${r.nodeCount} 个`);
console.log(`图片 ${r.imageCount} 张 → 散图 ${r.frameCount} 张`);
if (r.unassigned.length) {
console.warn(`\n⚠️ ${r.unassigned.length} 个层的 bucket 未定,资源已落入 atlas-unassigned,需人工归位:`);
for (const n of r.unassigned) console.warn(` ${n}`);
}
if (r.warningCount > 0) {
console.warn(
`\n⚠️ ${r.warningCount} 条已知的源数据遗留问题(FrameIndex 超出图帧数,已回退为帧 1),`
+ '详情见 ui-migration/intermediate/warnings.json',
);
}
}