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>
This commit is contained in:
1 parent
1665576fb9
commit
3f12a77aea
10 files changed
+239
-4
No files matched your search
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* A sprite's preview in the inspector: magnified by whole device pixels with its corner on one, so
|
||||
* pixel art stays sharp; shrunk freely when it does not fit, and with room for a shader's padding.
|
||||
*/
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { previewFit } from '../../src/editor/inspector/previewFit';
|
||||
|
||||
const room = { w: 300, h: 140 };
|
||||
const options = { margin: 8, maxZoom: 8, ratio: 1 };
|
||||
|
||||
/** Whether `v` device pixels is a whole one, within float noise. */
|
||||
const whole = (v: number) => Math.abs(v - Math.round(v)) < 1e-9;
|
||||
|
||||
describe('previewFit', () => {
|
||||
it('magnifies a small sprite by a whole factor and centres it on whole pixels', () => {
|
||||
// 124 / 15 = 8.27 is capped at 8; the 120-px picture leaves 90 and 10 at the sides.
|
||||
const fit = previewFit(15, 15, room, options);
|
||||
expect(fit).toEqual({ zoom: 8, x: 90, y: 10 });
|
||||
});
|
||||
|
||||
it('rounds the zoom down to whole device pixels', () => {
|
||||
// 124 / 48 = 2.58: two pixels per unit, not a blur between two and three.
|
||||
expect(previewFit(48, 48, room, options).zoom).toBe(2);
|
||||
// At a device ratio of 1.5 the same room holds 3.875 device pixels per unit: three, = 2 panel px.
|
||||
const fit = previewFit(48, 48, room, { ...options, ratio: 1.5 });
|
||||
expect(fit.zoom).toBe(2);
|
||||
expect(whole(fit.x * 1.5) && whole(fit.y * 1.5)).toBe(true);
|
||||
});
|
||||
|
||||
it('puts the corner of an odd size on a whole device pixel', () => {
|
||||
const fit = previewFit(15, 9, room, { ...options, ratio: 1.25 });
|
||||
expect(whole(fit.zoom * 1.25)).toBe(true);
|
||||
expect(whole(fit.x * 1.25) && whole(fit.y * 1.25)).toBe(true);
|
||||
});
|
||||
|
||||
it('shrinks a sprite bigger than the room to fit, without rounding to nothing', () => {
|
||||
const fit = previewFit(800, 200, room, options);
|
||||
expect(fit.zoom).toBeCloseTo(284 / 800);
|
||||
expect(800 * fit.zoom).toBeLessThanOrEqual(room.w - 16);
|
||||
});
|
||||
|
||||
it("keeps room for a shader's padding", () => {
|
||||
// 10 % on each side: 124 / (15 * 1.2) = 6.9 → 6 rather than 8.
|
||||
expect(previewFit(15, 15, room, { ...options, pad: { u: 0.1, v: 0.1 } }).zoom).toBe(6);
|
||||
});
|
||||
});
|
||||
@@ -351,6 +351,7 @@ describe('the groups of the inspector', () => {
|
||||
'[TRANSFORM]',
|
||||
'[EDITOR OFFSET (SCENE VIEW ONLY)]',
|
||||
'[PROPERTIES]',
|
||||
'[PREVIEW]',
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user