Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions assets/theme-v2/css/gamefoundrystudio.css
Original file line number Diff line number Diff line change
Expand Up @@ -1164,21 +1164,24 @@ body.tool-focus-mode .tool-column:last-of-type {
}

.sprite-canvas-grid {
--sprite-grid-size: 16;
box-sizing: border-box;
display: grid;
grid-template-columns: repeat(var(--sprite-grid-size), minmax(0, 1fr));
gap: 0;
width: min(100%, 520px);
aspect-ratio: 1;
overflow: hidden;
border: 1px solid var(--line);
background: var(--panel)
}

.sprite-canvas-grid[data-sprites-grid-size="16"] {
--sprite-grid-size: 16
grid-template-columns: repeat(16, minmax(0, 1fr));
grid-template-rows: repeat(16, minmax(0, 1fr))
}

.sprite-canvas-grid[data-sprites-grid-size="32"] {
--sprite-grid-size: 32
grid-template-columns: repeat(32, minmax(0, 1fr));
grid-template-rows: repeat(32, minmax(0, 1fr))
}

.sprite-canvas-shell[data-sprites-zoom-level="2"] .sprite-canvas-grid {
Expand All @@ -1190,6 +1193,7 @@ body.tool-focus-mode .tool-column:last-of-type {
}

.sprite-canvas-cell {
box-sizing: border-box;
min-width: 0;
min-height: 0;
padding: 0;
Expand Down
74 changes: 74 additions & 0 deletions dev/tests/playwright/tools/SpritesToolShell.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,52 @@ async function expectCenterAndPreviewEmpty(page, row, column) {
expect(await previewCellHasPaint(page, row, column)).toBe(false);
}

async function gridDimensionMetrics(page) {
return page.locator("[data-sprites-pixel-grid]").evaluate((grid) => {
const cells = Array.from(grid.querySelectorAll("[role='gridcell']"));
const gridRect = grid.getBoundingClientRect();
let maxRight = 0;
let maxBottom = 0;
const styles = getComputedStyle(grid);
const templateTrackCount = (value) => value.split(" ").filter(Boolean).length;

for (const cell of cells) {
const rect = cell.getBoundingClientRect();
maxRight = Math.max(maxRight, rect.right);
maxBottom = Math.max(maxBottom, rect.bottom);
}

const lastRowCells = cells.slice(-Number(grid.dataset.spritesGridSize || 0));
return {
cellCount: cells.length,
columnCount: templateTrackCount(styles.gridTemplateColumns),
heightDelta: Math.abs(maxBottom - gridRect.bottom),
lastCellColumn: cells.at(-1)?.dataset.spritePixelColumn || "",
lastCellRow: cells.at(-1)?.dataset.spritePixelRow || "",
lastRowCellCount: lastRowCells.length,
lastRowColumns: lastRowCells.map((cell) => cell.dataset.spritePixelColumn),
lastRowRows: lastRowCells.map((cell) => cell.dataset.spritePixelRow),
rowCount: templateTrackCount(styles.gridTemplateRows),
widthDelta: Math.abs(maxRight - gridRect.right),
};
});
}

async function expectExactGridDimensions(page, expectedSize) {
await expect(page.locator("[data-sprites-pixel-grid] [role='gridcell']")).toHaveCount(expectedSize * expectedSize);
const metrics = await gridDimensionMetrics(page);
expect(metrics.cellCount).toBe(expectedSize * expectedSize);
expect(metrics.columnCount).toBe(expectedSize);
expect(metrics.rowCount).toBe(expectedSize);
expect(metrics.lastRowCellCount).toBe(expectedSize);
expect(metrics.lastCellRow).toBe(String(expectedSize));
expect(metrics.lastCellColumn).toBe(String(expectedSize));
expect(metrics.lastRowRows.every((row) => row === String(expectedSize))).toBe(true);
expect(metrics.lastRowColumns).toEqual(Array.from({ length: expectedSize }, (_, index) => String(index + 1)));
expect(metrics.widthDelta).toBeLessThanOrEqual(1);
expect(metrics.heightDelta).toBeLessThanOrEqual(1);
}

test("Sprite Creator shell loads with visible tool, canvas, details, and status regions", async ({ page }) => {
const server = await startSpriteShellTestServer();
const failures = collectPageFailures(page);
Expand Down Expand Up @@ -418,6 +464,34 @@ test("Sprite Creator shell loads with visible tool, canvas, details, and status
}
});

test("Sprite Creator canvas grid dimensions stay exact across modes and zoom", async ({ page }) => {
const server = await startSpriteShellTestServer();
const failures = collectPageFailures(page);

try {
await page.goto(`${server.baseUrl}/toolbox/sprites/index.html`, { waitUntil: "networkidle" });

await expectExactGridDimensions(page, 16);
for (const zoomLabel of ["200%", "400%", "100%"]) {
await page.getByRole("button", { name: zoomLabel }).click();
await expectExactGridDimensions(page, 16);
}

await page.getByRole("button", { name: "32x32" }).click();
await expectExactGridDimensions(page, 32);
for (const zoomLabel of ["200%", "400%", "100%"]) {
await page.getByRole("button", { name: zoomLabel }).click();
await expectExactGridDimensions(page, 32);
}

expect(failures.failedRequests).toEqual([]);
expect(failures.pageErrors).toEqual([]);
expect(failures.consoleErrors).toEqual([]);
} finally {
await server.close();
}
});

test("Sprite Creator keeps center canvas and right preview in sync", async ({ page }) => {
const server = await startSpriteShellTestServer();
const failures = collectPageFailures(page);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# PR_26179_CHARLIE_038-sprites-grid-dimension-fix

Team: CHARLIE

Mode: Batch governance stacked bug-fix workflow

Base branch: PR_26179_CHARLIE_037-sprites-animation-export

Branch: PR_26179_CHARLIE_038-sprites-grid-dimension-fix

## Summary

Fixed Sprite Creator center canvas grid dimensions. The Sprite Creator page now loads the shared `gamefoundrystudio.css` stylesheet that owns the canvas styles, and the canvas grid uses explicit 16x16 and 32x32 CSS row/column templates instead of an invalid custom-property repeat count. This prevents orphan or partial rows/columns and keeps zoom display controls from changing logical grid dimensions.

## Branch Validation

PASS

- Built from `PR_26179_CHARLIE_037-sprites-animation-export`.
- Scope stayed limited to Sprite Creator grid dimensions and regression coverage.
- No DB/API/schema changes.
- No browser-owned authoritative product data added.
- No start_of_day files changed.
- ZIP package created at the requested path.

## Requirement Checklist

PASS - 16x16 mode renders exactly 16 columns and 16 rows.

PASS - 32x32 mode renders exactly 32 columns and 32 rows.

PASS - Prevents orphan or extra cells at bottom/right edge.

PASS - Zoom levels 100%, 200%, and 400% do not change row/column count.

PASS - Preview/export behavior unchanged.

PASS - No DB/API/schema changes.

PASS - No browser-owned authoritative product data.

PASS - No start_of_day changes.

PASS - Targeted Playwright coverage added.

## Validation Lane

PASS - `node --check dev/tests/playwright/tools/SpritesToolShell.spec.mjs`

PASS - `git diff --check -- toolbox/sprites/index.html assets/theme-v2/css/gamefoundrystudio.css dev/tests/playwright/tools/SpritesToolShell.spec.mjs`

PASS - Runtime guard scan found no prohibited inline style/script/event-handler or stale placeholder text in touched runtime files.

PASS - `npx playwright test dev/tests/playwright/tools/SpritesToolShell.spec.mjs --workers=1 --reporter=list`

## Manual Validation Notes

1. Open `toolbox/sprites/index.html`.
2. Confirm the 16x16 canvas shows a complete square with 16 rows and 16 columns.
3. Switch to 32x32 and confirm a complete 32-row, 32-column grid.
4. Switch through 100%, 200%, and 400% zoom and confirm the cell count and rows/columns do not change.
5. Confirm no partial trailing row or right-edge orphan cells are visible.

## ZIP

`dev/workspace/zip/PR_26179_CHARLIE_038-sprites-grid-dimension-fix_delta.zip`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Put the delta ZIP under tmp

For this BUILD handoff, the repo AGENTS.md Packaging section requires the delta ZIP at <project folder>/tmp/<TASK_NAME>_delta.zip, but the report records dev/workspace/zip/... instead. Automation or reviewers following the documented contract will look in tmp/ and miss the artifact for this task, so please generate/report the ZIP at tmp/PR_26179_CHARLIE_038-sprites-grid-dimension-fix_delta.zip while keeping it untracked.

Useful? React with 👍 / 👎.

4 changes: 2 additions & 2 deletions docs_build/dev/reports/codex_changed_files.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
assets/toolbox/sprites/js/index.js
assets/theme-v2/css/gamefoundrystudio.css
dev/tests/playwright/tools/SpritesToolShell.spec.mjs
docs_build/dev/reports/PR_26179_CHARLIE_037-sprites-animation-export.md
docs_build/dev/reports/PR_26179_CHARLIE_038-sprites-grid-dimension-fix.md
docs_build/dev/reports/codex_changed_files.txt
docs_build/dev/reports/codex_review.diff
toolbox/sprites/index.html
Loading
Loading