From c6982970116a1dbd6f777db99de52dd7d89cb19f Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Wed, 16 Sep 2026 18:13:12 +0200 Subject: [PATCH] Textures: nine-slice scale per texture (#96); Repeat is the default fill Co-Authored-By: Claude Opus 5 --- Development.md | 4 ++-- Textures.md | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Development.md b/Development.md index 94d5853..4ec1996 100644 --- a/Development.md +++ b/Development.md @@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs # code is lost (tail's is reported), so a red run reads as green npm run build # writes dist/ and regenerates index.html ./build.sh # the same under `set -o pipefail`, for callers that pipe the output -node tools/seed-e2e.mjs && node tools/e2e.mjs # 958 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 960 editor checks, screenshots in /tmp/gm-e2e-*.png GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step ./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh status # live progress, or the last run's result @@ -232,4 +232,4 @@ widths to find click points. The **render device is not in this repo** — `/dev and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`, -WebGL 2.0, and the same 958 checks as here. +WebGL 2.0, and the same 960 checks as here. diff --git a/Textures.md b/Textures.md index 2f39e74..f2c125c 100644 --- a/Textures.md +++ b/Textures.md @@ -86,8 +86,9 @@ whole inside of a frame does not swallow the lines it holds. **All four at zero not sliced at all** — it is drawn over the whole box, exactly as every sprite was before #41, and a frame nobody sliced carries no border keys in the saved document. -**Fill** says how the parts *between* the corners fill their space: `Stretch` pulls them, `Repeat` -tiles them. One setting for the edges and the middle together, because a brick pattern that tiles +**Fill** says how the parts *between* the corners fill their space: `Repeat` tiles them, `Stretch` +pulls them. `Repeat` is the default, so only a `Stretch` is written into the saved document. +One setting for the edges and the middle together, because a brick pattern that tiles along the top and stretches in the centre reads as a mistake. A tiled part is built as one quad per tile, each with the frame's own UVs and the last one cut off where the space ends — sampling past 1 with a repeating address mode would pull in the *neighbouring cell of the sheet*, which is the @@ -100,6 +101,15 @@ corners meet at a seam. And a frame can never be given borders that leave *no* m squeezed to leave at least one pixel, because a middle of no pixels has nothing to draw the space between the corners with, and that would show as a hole rather than as an error. +**Nine-slice scale** is a property of **the texture**, not of a frame: it says how many sprite units +one border pixel is drawn with, for every sliced frame the texture has. The default 1 draws a 16 px +border 16 units wide; at 2 the same border is 32 units, at 0.5 it is 8. The pixels a corner shows +stay the same — only its size on screen changes — so a pixel-art button can have chunky corners +without redrawing the sheet at twice the size. With `Repeat` the tiles scale along, because a border +drawn twice as big beside a pattern at its old size reads as two different pictures. The rule for a +sprite narrower than its borders applies to the scaled size: two 32-unit borders on a 20-unit box +become two of 10. + **Fitting the sprite to the picture.** The *Width* and *Height* rows of a sprite carry a ↔ / ↕ button offering two things: **Fit to 64 x 48** sets that one side from the other and the picture's proportions — the frame's rectangle when it wears a frame, the whole image otherwise — and **Set