Files
feuerwerk/src/editor/inspector/previewFit.ts
T
adminandClaude Opus 5.5 3f12a77aea Preview a sprite at the end of its inspector, placed or as an asset
A sprite's inspector listed its rows but never showed what they add up
to. The picture, its frame, nine-slice, tint and shader could only be
judged in the scene, often far from the object being edited.

- SpritePreview draws the sprite through syncSpriteMesh, the function
  the scene draws it with. Slices, padding, tint and shader come out
  the same without a second path. syncSpriteMesh now takes only the
  three fields of a DrawItem it reads.
- The subject is resolved by previewPicture from the Shader tab, so a
  placed sprite shows its own overrides.
- previewFit is the rule for size and place: whole device pixels per
  unit from 1 on, at most 8, and the corner on a whole device pixel.
  Pixel art stays sharp. A sprite larger than the group shrinks freely.
- A shader with a Time node keeps the preview redrawing once a frame
  while it is on screen. A folded group or a hidden panel stops it.
- New test hook __gm.inspectorSpritePreview().

Finding: the preview redrew on a model change in a microtask at first.
A drawn picture whose revision moved on is retried once, in a
microtask queued by the scene's synchronous redraw. That retry ran
before the preview had let go, and the old pixel art sheet stayed
waiting (e2e 48l-iii read waiting [1,1,1]). The preview now redraws
at once on a model change, as the scene does.

Tests:
- unit: 238 files, 3592 tests (+5 in preview-fit.test.ts), and the
  group list of a placed sprite in sections.test.ts ends in PREVIEW
- e2e 48: ALL PASSED, 47 checks (+2: 48l-i asset preview with
  the frame, 48l-iii placed preview with its shader values)
- counter-checks: without whole-pixel zoom 2 unit tests fail; with
  the microtask redraw 48l-iii fails with waiting [1,1,1]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 14:27:35 +02:00

25 lines
1.1 KiB
TypeScript
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.
/**
* How big a picture of `w`×`h` units is drawn in a preview of `room` and where its top left lands.
* `pad` is the room a worn shader asks for around it, as a share of each side (see `quadPadding`).
* From one device pixel per unit on the zoom is whole device pixels, and the corner sits on one, so
* pixel art stays sharp; below that the picture only shrinks to fit. `ratio` is device pixels per
* panel pixel.
*/
export function previewFit(
w: number,
h: number,
room: { w: number; h: number },
options: { margin: number; maxZoom: number; ratio: number; pad?: { u: number; v: number } | null },
): { zoom: number; x: number; y: number } {
const { margin, maxZoom, ratio, pad } = options;
const fits = Math.min(
(room.w - 2 * margin) / (w * (1 + 2 * (pad?.u ?? 0))),
(room.h - 2 * margin) / (h * (1 + 2 * (pad?.v ?? 0))),
maxZoom,
);
const device = fits * ratio;
const zoom = Math.max(0, device >= 1 ? Math.floor(device) / ratio : fits);
const corner = (space: number, size: number) => Math.round(((space - size * zoom) / 2) * ratio) / ratio;
return { zoom, x: corner(room.w, w), y: corner(room.h, h) };
}