Nine-slice: borders and fill on a texture frame (#41)
1 parent
b0d0e016d3
commit
15f6f33b19
3 files changed
+38
-4
No files matched your search
+3
-3
@@ -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 # 945 editor checks, screenshots in /tmp/gm-e2e-*.png
|
||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 955 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
|
||||
@@ -64,7 +64,7 @@ The e2e run is a list of steps in `tools/e2e/` (hierarchy, inspector, play, asse
|
||||
graph, parenting, colliders, containers, text/enabled, menus, textures, frames, overflow, aspect,
|
||||
container tab, run-in-editor, pause, nested behaviors, key repeat, list tab, struct variable,
|
||||
variable nodes, property nodes, animations, state machines, console, shaders, transforms, fonts,
|
||||
particles, shared scope, render on change, sounds, load scene, graph groups) that build on each other's
|
||||
particles, shared scope, render on change, sounds, load scene, graph groups, nine-slice) that build on each other's
|
||||
scene state and share the CDP driver in `tools/lib/harness.mjs` — `press`, `undo`, `play`,
|
||||
`object(id)`, `world()`, `mutate(js)` and friends, so a check reads like the interaction it
|
||||
exercises.
|
||||
@@ -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 945 checks as here.
|
||||
WebGL 2.0, and the same 955 checks as here.
|
||||
+1
-1
@@ -14,7 +14,7 @@ Live: <https://nockal.com/game-maker/> · Widget playground: <https://nockal.com
|
||||
| [Scene editing](Scene-editing) | Placing by drag, editor symbols, z-order, hierarchy and parenting, the editor offset |
|
||||
| [Behaviors](Behaviors) | Node graphs: variables and properties, Variables assets, the node set, structs and lists, loops, behaviors as nodes, editing the graph, the live view |
|
||||
| [Colliders](Colliders) | Collider assets, collision events, blocking movement |
|
||||
| [Textures](Textures) | Getting images in, where they go, tinting, the filter, frames, upload limits |
|
||||
| [Textures](Textures) | Getting images in, where they go, tinting, the filter, frames, nine-slice, upload limits |
|
||||
| [Fonts](Fonts) | Uploading a typeface, what a text wears, what the editor falls back to |
|
||||
| [Sounds](Sounds) | Uploading a sound, what the asset says, `Play sound` and `Stop sound`, what a pause and a stop do to a voice |
|
||||
| [Animations](Animations) | Animation assets, the Animation tab, how they run |
|
||||
|
||||
+34
@@ -66,6 +66,40 @@ undo step. Deleting a frame leaves the sprites pointing at it: a dangling refere
|
||||
plain colour and comes back by itself on undo. Deleting the whole texture counts the sprites
|
||||
wearing *any* of its frames, not just the ones naming the texture directly.
|
||||
|
||||
## Nine-slice — a frame that keeps its corners
|
||||
|
||||
A frame carries four **borders** and a **fill**, and a sprite wearing it is drawn as nine parts
|
||||
instead of one: the four corners keep their own pixel size however big the box gets, the four edges
|
||||
grow along one axis, and the middle grows along both. That is what makes one 24 x 24 picture serve
|
||||
every button, panel and dialog in a game without the rounded corner smearing.
|
||||
|
||||
The borders live on **the frame**, not on the sprite — set them once on the picture and all ten
|
||||
buttons wearing it are sliced the same way, and a new version of the artwork is nudged in one
|
||||
place. The price is that a sprite cannot decide to ignore them: a picture that should sometimes be
|
||||
stretched whole wants a second frame without borders.
|
||||
|
||||
Set them in the **Texture tab**: the selected frame shows four dashed lines, one per border, and
|
||||
dragging one moves that border alone; the inspector has the same four numbers next to the frame's
|
||||
rectangle. The lines are tested *after* the frame's own eight resize handles and *before* its body,
|
||||
so a border still sitting on the frame's edge cannot steal the grip that resizes the frame, and the
|
||||
whole inside of a frame does not swallow the lines it holds. **All four at zero means the frame is
|
||||
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
|
||||
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
|
||||
same trap the frame cut-outs exist to avoid. Above 64 tiles along an axis the part stretches
|
||||
instead; that is a guard against a buffer that grows with the sprite, not a design.
|
||||
|
||||
Two sizes have an answer of their own. A sprite **narrower than its two borders** does not draw
|
||||
them over each other: both are scaled down together until the middle is exactly zero and the
|
||||
corners meet at a seam. And a frame can never be given borders that leave *no* middle — they are
|
||||
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.
|
||||
|
||||
**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
|
||||
|
||||
Reference in new issue
Block a user