feat(rendering): add nine-slice support for sprites#520
Open
stormmuller wants to merge 2 commits into
Open
Conversation
Adds `NineSliceOptions` (border insets plus stretch/tile modes for edges and center) to `SpriteEcsComponent` and `createImageSprite`. The render system expands a sliced sprite into up to nine batched render commands instead of one, reusing the existing sprite shader and Renderable unchanged, so corner artwork keeps its size while the edges/center stretch or tile as the sprite is resized. Closes #471.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #471.
NineSliceOptions(left/right/top/bottomborder insets, plus independentedgeMode/centerModeof'stretch'(default) or'tile') as an optionalslicesfield onSpriteEcsComponent, and as an option oncreateImageSprite.computeNineSliceRegionsis a new pure utility that turns a sprite's current size/pivot/UV rect +NineSliceOptionsinto up to nine region descriptors (four fixed-size corners, four stretch/tile edges, one stretch/tile center), correctly clamping oversized borders and anchoring UV fractions to anativeWidth/nativeHeightreference so resizing a sliced sprite never distorts its corners.createRenderEcsSystemexpands a sliced sprite into oneRenderCommandper region (still batched into a single instanced draw call alongside every other sprite sharing the sameRenderable) instead of writing a new shader/geometry path — the existing generic sprite shader already supports arbitrary per-instance size/position/UV, so no shader or geometry changes were needed. Region offsets correctly compose with the entity's rotation, scale, and flip.'tile'uses "round" repeat semantics (evenly-sized tiles, no cropped partial tile at the seam), the same tradeoff as CSS'sborder-image-repeat: round.Note on
SpriteOptionsThe issue links to the
SpriteOptionsAPI page (src/rendering/sprite.ts'sSpriteclass). That class predates the ECS component-factory refactor and has zero references anywhere insrc, the demos, or the docs — the actual render pipeline (createRenderEcsSystem) only ever readsSpriteEcsComponent. This PR adds slicing to the liveSpriteEcsComponent/createImageSpritepath instead of extending the deadSpriteclass.Test plan
npm run check-typesnpm test(989 tests, including new unit tests forcomputeNineSliceRegionsand newcreateRenderEcsSystemnine-slice cases)npm run lintnpm run cspellnpm run check-exportsdocumentation-site/docs/docs/renderingdocumentation-site:npm run build+npm run typecheckpass; loaded theecsandstress-testdemos in a browser to confirm no rendering regression (both demos don't use slicing yet, but exercise the samecreateRenderEcsSystemcode path)Generated by Claude Code