Files
Genarrative/src/services/match3dSpritesheetParser.test.ts
高物 ae014ac881 Switch to VectorEngine gpt-image-2 and edits
Replace uses of the legacy `gpt-image-2-all` model with `gpt-image-2` and standardize image workflows: no-reference generation uses POST /v1/images/generations, any-reference flows use POST /v1/images/edits with multipart `image` parts. Update SKILLs, generation scripts, decision logs, and docs to reflect the contract change and edits-vs-generations guidance. Apply corresponding changes across backend (api-server match3d/puzzle modules, openai image adapter, mappers, telemetry, spacetime client/module), frontend components and services (Match3D, Puzzle, CreativeImageInputPanel, runtime shells), and add new spritesheet/parser files and tests. Also add media/logo.png. These changes align repository code and documentation with the VectorEngine image API contract and update generation/upload handling (green-screen -> alpha processing, spritesheet handling, and related tests).
2026-05-22 03:06:41 +08:00

99 lines
2.6 KiB
TypeScript

import { describe, expect, test } from 'vitest';
import {
buildMatch3DItemSpritesheetViewRegions,
detectMatch3DSpritesheetRegions,
} from './match3dSpritesheetParser';
describe('match3dSpritesheetParser', () => {
test('按透明像素连通域检测素材并按从上到下从左到右排序', () => {
const width = 12;
const height = 10;
const alpha = new Uint8ClampedArray(width * height);
const paint = (x0: number, y0: number, x1: number, y1: number) => {
for (let y = y0; y <= y1; y += 1) {
for (let x = x0; x <= x1; x += 1) {
alpha[y * width + x] = 255;
}
}
};
paint(8, 1, 10, 3);
paint(1, 1, 3, 2);
paint(5, 6, 7, 8);
const regions = detectMatch3DSpritesheetRegions({
alpha,
width,
height,
labels: ['返回', '设置', '移出'],
});
expect(regions).toEqual([
{ height: 2, label: '返回', width: 3, x: 1, y: 1 },
{ height: 3, label: '设置', width: 3, x: 8, y: 1 },
{ height: 3, label: '移出', width: 3, x: 5, y: 6 },
]);
});
test('忽略小噪点,只返回可用矩形素材', () => {
const width = 8;
const height = 8;
const alpha = new Uint8ClampedArray(width * height);
alpha[0] = 255;
for (let y = 2; y <= 5; y += 1) {
for (let x = 2; x <= 5; x += 1) {
alpha[y * width + x] = 255;
}
}
const regions = detectMatch3DSpritesheetRegions({
alpha,
width,
height,
labels: ['方格'],
minArea: 4,
});
expect(regions).toEqual([
{ height: 4, label: '方格', width: 4, x: 2, y: 2 },
]);
});
test('按10行10列图集顺序把每行两种物品拆成五视角', () => {
const regions = Array.from({ length: 100 }, (_, index) => ({
label: `素材${index + 1}`,
x: (index % 10) * 10,
y: Math.floor(index / 10) * 10,
width: 8,
height: 8,
}));
const grouped = buildMatch3DItemSpritesheetViewRegions(regions, [
'草莓',
'苹果',
'毛肚',
]);
expect(grouped).toHaveLength(20);
expect(grouped[0]).toEqual({
itemIndex: 0,
itemName: '草莓',
regions: regions.slice(0, 5).map((region, index) => ({
...region,
label: `草莓-形态${index + 1}`,
})),
});
expect(grouped[1]).toEqual({
itemIndex: 1,
itemName: '苹果',
regions: regions.slice(5, 10).map((region, index) => ({
...region,
label: `苹果-形态${index + 1}`,
})),
});
expect(grouped[2]?.itemName).toBe('毛肚');
expect(grouped[19]?.regions).toHaveLength(5);
});
});