diff --git a/cocoscreator_projects/framework-tests/legacy-layer-migration/group-builder.test.mjs b/cocoscreator_projects/framework-tests/legacy-layer-migration/group-builder.test.mjs new file mode 100644 index 0000000..8671c8b --- /dev/null +++ b/cocoscreator_projects/framework-tests/legacy-layer-migration/group-builder.test.mjs @@ -0,0 +1,47 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { buildGroupParents } from '../../scripts/legacy-layer-to-cocos-prefab.mjs'; + +test('buildGroupParents 把同 group Spirit 归类', () => { + const spirits = [ + { id: '1', group: '2', indexOfLayer: '1' }, + { id: '405', group: '2', indexOfLayer: '2' }, + { id: '285', group: '2', indexOfLayer: '3' }, + ]; + const result = buildGroupParents(spirits); + assert.equal(result.groupParents.length, 1, '只有一个 group=2'); + assert.equal(result.groupParents[0].name, 'group-2'); + assert.deepEqual(result.groupParents[0].childSpiritIds, ['1', '405', '285']); + assert.equal(result.rootChildSpiritIds.length, 0); +}); + +test('buildGroupParents 多 group 按 ID 升序', () => { + const spirits = [ + { id: '1', group: '32', indexOfLayer: '1' }, + { id: '2', group: '1', indexOfLayer: '2' }, + { id: '3', group: '1', indexOfLayer: '3' }, + ]; + const result = buildGroupParents(spirits); + assert.deepEqual(result.groupParents.map(g => g.name), ['group-1', 'group-32']); +}); + +test('buildGroupParents group=0 Spirit 直挂 Layer 根', () => { + const spirits = [ + { id: '10', group: '0', indexOfLayer: '1' }, + { id: '20', group: '0', indexOfLayer: '2' }, + { id: '30', group: '2', indexOfLayer: '3' }, + ]; + const result = buildGroupParents(spirits); + assert.equal(result.groupParents.length, 1); + assert.deepEqual(result.rootChildSpiritIds, ['10', '20']); +}); + +test('buildGroupParents 按 IndexOfLayer 排序子节点', () => { + const spirits = [ + { id: 'c', group: '1', indexOfLayer: '3' }, + { id: 'a', group: '1', indexOfLayer: '1' }, + { id: 'b', group: '1', indexOfLayer: '2' }, + ]; + const result = buildGroupParents(spirits); + assert.deepEqual(result.groupParents[0].childSpiritIds, ['a', 'b', 'c']); +}); \ No newline at end of file diff --git a/cocoscreator_projects/scripts/legacy-layer-to-cocos-prefab.mjs b/cocoscreator_projects/scripts/legacy-layer-to-cocos-prefab.mjs index 1d64032..ba30514 100644 --- a/cocoscreator_projects/scripts/legacy-layer-to-cocos-prefab.mjs +++ b/cocoscreator_projects/scripts/legacy-layer-to-cocos-prefab.mjs @@ -96,3 +96,44 @@ export function computeContentSize(spirit) { height: parseFloat(spirit.h || '0'), }; } + +/** + * 将 Spirit 记录按 BelongGroupID 归类, 生成 group-X 父节点集合 + Layer 根直挂子节点. + * + * 规则: + * - BelongGroupID === '0' (或缺失) → 直挂 Layer 根, 不进任何 group 父节点 + * - BelongGroupID > 0 → 归入对应 group- 父节点 + * - group 父节点按 ID 升序排列; 同 group 内子节点按 IndexOfLayer 升序 + * - 命名保留原 BelongGroupID 值, 不重排 + * + * 数据源权威: IndexOfLayer 缺失视作 0 (XML 中该字段由 readLayerXml 提供, 必有值). + * + * @param {Array<{ id?: string, group?: string, indexOfLayer?: string }>} spirits + * @returns {{ groupParents: Array<{ name: string, childSpiritIds: string[] }>, rootChildSpiritIds: string[] }} + */ +export function buildGroupParents(spirits) { + const groupMap = new Map(); // group_id -> [{ spiritId, index }] + const rootSpirits = []; + + for (const s of spirits) { + if (s.group === '0' || !s.group) { + rootSpirits.push({ spiritId: s.id, index: parseInt(s.indexOfLayer || '0', 10) }); + } else { + if (!groupMap.has(s.group)) groupMap.set(s.group, []); + groupMap.get(s.group).push({ spiritId: s.id, index: parseInt(s.indexOfLayer || '0', 10) }); + } + } + + const groupParents = Array.from(groupMap.entries()) + .sort(([a], [b]) => parseInt(a, 10) - parseInt(b, 10)) + .map(([gid, items]) => ({ + name: `group-${gid}`, + childSpiritIds: items.sort((a, b) => a.index - b.index).map(x => x.spiritId), + })); + + const rootChildSpiritIds = rootSpirits + .sort((a, b) => a.index - b.index) + .map(x => x.spiritId); + + return { groupParents, rootChildSpiritIds }; +}