fix(catalog): resolve namespaced Nitro frames and empty scale declarations
This commit is contained in:
1 parent
cd75361b9f
commit
dcb5f46eed
4 files changed
+77
-7
No files matched your search
@@ -69,3 +69,20 @@ it("does not invent sprites from visualization metadata alone", () => {
|
||||
.state,
|
||||
).toBe("issues");
|
||||
});
|
||||
it("resolves namespaced atlas frames and mirrored aliases", () => {
|
||||
const metadata = {
|
||||
name: "chair",
|
||||
assets: {
|
||||
chair_64_a_0_0: {},
|
||||
chair_64_a_2_0: { source: "chair_64_a_0_0", flipH: true },
|
||||
},
|
||||
spritesheet: {
|
||||
frames: { chair_chair_64_a_0_0: { frame: { x: 0, y: 0, w: 4, h: 6 } } },
|
||||
},
|
||||
};
|
||||
expect(resolveNitroFrame(metadata, "chair_64_a_2_0")).toMatchObject({
|
||||
name: "chair_chair_64_a_0_0",
|
||||
flipH: true,
|
||||
frame: { frame: { w: 4, h: 6 } },
|
||||
});
|
||||
});
|
||||
@@ -44,10 +44,15 @@ export function resolveNitroFrame(
|
||||
current = asset.source;
|
||||
continue;
|
||||
}
|
||||
const frame = object(frames[current]);
|
||||
const frameName = Object.hasOwn(frames, current)
|
||||
? current
|
||||
: typeof metadata.name === "string"
|
||||
? `${metadata.name}_${current}`
|
||||
: current;
|
||||
const frame = object(frames[frameName]);
|
||||
if (Object.keys(frame).length)
|
||||
return {
|
||||
name: current,
|
||||
name: frameName,
|
||||
asset: object(assets[name]),
|
||||
frame,
|
||||
flipH,
|
||||
|
||||
@@ -177,3 +177,37 @@ it("unrotates atlas artwork before generating the smaller frame", async () => {
|
||||
).metadata();
|
||||
expect([size.width, size.height]).toEqual([3, 1]);
|
||||
});
|
||||
it("fills an empty scale declaration and retains namespaced frame naming", async () => {
|
||||
const m = metadata();
|
||||
const originalFrames = m.spritesheet.frames;
|
||||
const source = createNitroBundle(
|
||||
{
|
||||
...m,
|
||||
visualizations: [
|
||||
{ size: 32, layerCount: 1, angle: 45, directions: { 0: {}, 2: {} } },
|
||||
...m.visualizations,
|
||||
],
|
||||
spritesheet: {
|
||||
...m.spritesheet,
|
||||
frames: { chair_chair_64_a_0_0: originalFrames.chair_64_a_0_0 },
|
||||
},
|
||||
},
|
||||
await sharp({
|
||||
create: { width: 6, height: 8, channels: 4, background: "#ff0000" },
|
||||
})
|
||||
.png()
|
||||
.toBuffer(),
|
||||
"chair",
|
||||
);
|
||||
const result = parseNitroBundle((await generateScale32(source)).bundle);
|
||||
|
||||
expect(
|
||||
(result.json.visualizations as { size: number }[]).filter(
|
||||
(v) => v.size === 32,
|
||||
),
|
||||
).toHaveLength(1);
|
||||
expect(
|
||||
(result.json.spritesheet as { frames: Record<string, unknown> }).frames
|
||||
.chair_chair_32_a_0_0,
|
||||
).toBeDefined();
|
||||
});
|
||||
@@ -22,6 +22,18 @@ function halfOffsets(value: unknown): unknown {
|
||||
]),
|
||||
);
|
||||
}
|
||||
function emptyScaleDeclaration(viz: Record<string, unknown>): boolean {
|
||||
return Object.entries(viz).every(([key, value]) => {
|
||||
if (["size", "layerCount", "angle"].includes(key)) return true;
|
||||
if (key === "directions")
|
||||
return Object.values(object(value)).every(
|
||||
(direction) => Object.keys(object(direction)).length === 0,
|
||||
);
|
||||
return (
|
||||
value && typeof value === "object" && Object.keys(value).length === 0
|
||||
);
|
||||
});
|
||||
}
|
||||
export async function generateScale32(
|
||||
input: Buffer,
|
||||
): Promise<{ bundle: Buffer; before: string; after: string; count: number }> {
|
||||
@@ -35,7 +47,9 @@ export async function generateScale32(
|
||||
if (
|
||||
Object.keys(assets).some((n) => isScale(n, 32)) ||
|
||||
Object.keys(frames).some((n) => isScale(n, 32)) ||
|
||||
visualizations.some((v) => object(v).size === 32)
|
||||
visualizations.some(
|
||||
(v) => object(v).size === 32 && !emptyScaleDeclaration(object(v)),
|
||||
)
|
||||
)
|
||||
throw Error("Scale 32 already exists; original artwork is preserved");
|
||||
const viz = visualizations.find((v) => object(v).size === 64);
|
||||
@@ -62,13 +76,13 @@ export async function generateScale32(
|
||||
(typeof asset[key] !== "number" || !Number.isFinite(asset[key]))
|
||||
)
|
||||
throw Error("Invalid sprite offset");
|
||||
resolveNitroFrame(json, name);
|
||||
const resolved = resolveNitroFrame(json, name);
|
||||
if (typeof asset.source === "string" && asset.source !== name) {
|
||||
if (!names.includes(asset.source))
|
||||
throw Error("A sprite references artwork outside scale 64");
|
||||
continue;
|
||||
}
|
||||
const frame = object(frames[name]),
|
||||
const frame = resolved.frame,
|
||||
rect = object(frame.frame);
|
||||
let sprite = await sharp(png)
|
||||
.extract({
|
||||
@@ -105,7 +119,7 @@ export async function generateScale32(
|
||||
if (!before) before = `data:image/png;base64,${sprite.toString("base64")}`;
|
||||
images.push({
|
||||
id: images.length,
|
||||
name: scaleName(name),
|
||||
name: scaleName(resolved.name),
|
||||
width,
|
||||
height,
|
||||
pixels: await sharp(sprite)
|
||||
@@ -152,7 +166,7 @@ export async function generateScale32(
|
||||
}
|
||||
json.assets = assets;
|
||||
json.visualizations = [
|
||||
...visualizations,
|
||||
...visualizations.filter((v) => object(v).size !== 32),
|
||||
{ ...object(halfOffsets(viz)), size: 32 },
|
||||
];
|
||||
json.spritesheet = {
|
||||
|
||||
Reference in new issue
Block a user