Let a texture frame set where a sprite stands for Y sorting (#228)
A sprite sorted by Y stood on the bottom of its box. With a shadow or empty rows under the feet that is too low, so a figure slipped in front of a tree it should stand behind. The line belongs to the frame, not the texture, because one texture can hold several sprite sheets. - New field `sortLine` on a frame: whole image pixels up from the frame's bottom edge, 0 to the frame height. 0 is stored as nothing, so old projects stay the same. Shrinking a frame keeps the line inside it. - `feetOf` in drawOrder.ts lifts a sprite by the same share of its box. Scene view, game view, play and picking all use it. In an animation the line of the frame shown right now counts. - The texture tab draws the selected frame's line dashed in yellow with a knob left of the frame. At 0 the line shares the bottom edge with the nine-slice border and a resize handle, so the knob is tested first. A line inside the frame can be dragged directly, tested after the nine-slice lines. - The inspector has a new "Sorting" section with a "Sort line" field. Dragging or typing is one undo step each. Limit: frames of one walk cycle need the same value, set by hand. Otherwise the figure changes its place in the order while walking. Tests: - ./check.sh: 160 files, 2356 tests, CHECK EXIT 0 (before 2350). - 6 new unit tests in tests/viewport/sort-by-y.test.ts. - e2e 37 and 39-43: ALL PASSED, 162 checks. New check 37b-ii drags the knob up 6 px and undoes it, plus the inspector row. - Counter checks: if feetOf ignores the line, exactly the 3 order tests fail. If the knob cannot be grabbed, 37b-ii fails. - The e2e sum in the README is 1380, counted, not yet seen in CI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
50854389bb
commit
89048413f1
11 files changed
+334
-11
No files matched your search
@@ -3,6 +3,7 @@ import {
|
||||
RenameFrameCommand,
|
||||
SetFrameRectCommand,
|
||||
SetFrameSliceCommand,
|
||||
SetFrameSortLineCommand,
|
||||
} from '../../core/commands/frameCommands';
|
||||
import type { FrameBorders, TextureAsset, TextureFrame } from '../../core/model/Asset';
|
||||
import { type PropertyValue, textOf } from '../../core/model/Properties';
|
||||
@@ -15,9 +16,12 @@ import {
|
||||
type FrameRect,
|
||||
frameSlice,
|
||||
type FrameSlice,
|
||||
frameSortLine,
|
||||
normalizeFrameRect,
|
||||
normalizeSortLine,
|
||||
setFrameRect,
|
||||
setFrameSlice,
|
||||
setFrameSortLine,
|
||||
} from '../../core/model/texture';
|
||||
import { Button } from '../../ui';
|
||||
import { createFieldRow, type FieldHandlers } from './fieldFactory';
|
||||
@@ -70,6 +74,10 @@ export function buildFrameSection(host: InspectorHost, assetId: string, frameId:
|
||||
fillRow(host, assetId, frameId);
|
||||
addNote(host, 'All four at zero: the picture is drawn over the whole box, as it always was.');
|
||||
|
||||
addTitle(host, 'SORTING (IMAGE PIXELS)');
|
||||
sortLineRow(host, assetId, frameId);
|
||||
addNote(host, 'Where a sprite of this frame stands on a layer sorted by Y, up from the bottom edge.');
|
||||
|
||||
addGap(host);
|
||||
host.body.add(
|
||||
new Button('Delete frame', {
|
||||
@@ -89,9 +97,28 @@ export function refreshFrameSection(host: InspectorHost, assetId: string, frameI
|
||||
for (const component of BORDER_COMPONENTS)
|
||||
host.fields.get(`border-${component.key}`)?.setValue(border[component.key]);
|
||||
host.fields.get('fill')?.setValue(frameFill(frame));
|
||||
host.fields.get('sortLine')?.setValue(frameSortLine(frame));
|
||||
return true;
|
||||
}
|
||||
|
||||
function sortLineRow(host: InspectorHost, assetId: string, frameId: string): void {
|
||||
const frame = currentFrame(host.state.project, assetId, frameId);
|
||||
const row = createFieldRow(
|
||||
host,
|
||||
{ key: 'sortLine', label: 'Sort line', kind: 'number', default: 0, min: 0, step: 1, decimals: 0 },
|
||||
frame ? frameSortLine(frame) : 0,
|
||||
previewingHandlers<TextureFrame, number>(host, {
|
||||
target: () => currentFrame(host.state.project, assetId, frameId),
|
||||
read: frameSortLine,
|
||||
write: setFrameSortLine,
|
||||
toModel: (input, frame) => normalizeSortLine(Number(input), frame.h),
|
||||
commit: (line) => new SetFrameSortLineCommand(assetId, frameId, line),
|
||||
}),
|
||||
);
|
||||
host.fields.set('sortLine', row);
|
||||
host.body.add(row.row);
|
||||
}
|
||||
|
||||
/**
|
||||
* One border of the nine-slice, in pixels of the frame. The row keeps the other three and the fill
|
||||
* as they are at that moment, so two rows edited one after the other do not undo each other.
|
||||
|
||||
Reference in new issue
Block a user