Skip to main content
use-widget-asset is a skill from the Summer skill library: a guide your AI agent reads when the task matches, so it builds the good version on the first try. Wire a widget slice from an asset pack (panel, button, bar, toggle) into NinePatchRect or TextureRect.

When your agent uses it

  • Consuming a widget slice (panel, button, slider, progress bar, toggle pair) from a create-asset-sheet pack so it behaves like a real UI control
  • Turning a panel, button, slider, or bar slice from a generated UI kit into a working NinePatchRect or TextureProgressBar

Install

summer setup installs every skill for your agent. To add only this one:
Swap claude-code for your agent, such as codex or cursor. See Skills for every option.

The skill

When the create-asset-sheet wizard sees a stretchable UI element (a panel, a slider, a progress bar, a toggle), it returns more than a flat PNG. It returns geometry: 9-slice frame margins for stretchable rectangles, and a fill rect for value-driven widgets. It also pairs ON/OFF toggle slices via pairWith. This skill is the runtime side: how to read that metadata and wire the asset into the right Summer Engine node. If a slice has no widget metadata, treat it as a static texture (TextureRect) and skip this skill.

Shape support (read first)

The single rule that governs everything below:
9-slice for any AABB-fitting stretchable widget. Static texture for everything else.
Concrete: The wizard’s vision detector only emits widget metadata for the 5 kinds it knows how to slice (slider, progress_bar, toggle, panel, button). Anything else lands as a static category: ui slice with no widget field — fall through to “render as TextureRect” and skip the rest of this skill.

What the pack hands you

The wizard saves the pack as a single ArtAsset with:
widget looks like:
Margins and rect are percentages of the SLICE’s own pixel dimensions (not the source sheet). Convert to pixels with Math.round(pct * sliceWidth / 100) before applying to a Summer Engine node.

Decision tree

Recipes

1. Panel — NinePatchRect

When the NinePatchRect is sized larger than the source, corners stay fixed, edges stretch on one axis, center stretches both. This is exactly the behavior the wizard’s widget detection assumes.

2. Progress bar — TextureProgressBar (fill_mode = FILL_LEFT_TO_RIGHT)

Set value from 0 to 100 to drive the bar.

3. Slider — HSlider with TextureRect overlays

Slider in Summer Engine is a behavioral node (drag input + value range); it does not ship visuals on its own. Combine it with two TextureRects underneath: one for the track and one for the knob. Simplest wiring: NinePatchRect for the track using frameMargins, an HSlider on top with flat = true and theme_override_styles/grabber_area = null, and a child TextureRect for the knob positioned via slider.ratio.

4. Toggle — TextureRect that swaps texture via pairWith

In the pack, find the pair: sliceMeta[currentIndex].pairWith gives the other slice’s index; look it up in packFiles[pairIndex].url.

Cut-offs and re-renders

If the detected frameMargins are obviously wrong (the dashed overlay in the wizard’s lightbox shows the center area clipping into a corner ornament), the user should hit Recreate (HD) on that slice. It regenerates cleanly — but the margins themselves don’t get re-detected after upscale. Margins live on the original detection. The user can also manually edit them in code via the patch_margin_* properties after instantiating.

Composite panels with sub-elements

When a slice has parentSliceIndex set, it came from a Break-down pass — the parent is a composite (settings panel, card frame) and this slice is one of its sub-elements (Apply button, slider, toggle). Use either:
  • The whole parent as a single NinePatchRect for the frame, OR
  • Instantiate each sub-element individually positioned where the original panel had them (the parent’s sliceBboxes[parentSliceIndex] gives the source-sheet rect; each sub-slice’s relative position within it is recoverable from its own bbox).
Pick based on whether your game needs the panel to stretch as one unit or whether each control needs independent interaction. See Composite Panels (Sliced Further) below for the fields the wizard emits (isComposite, zOrder) and the consume recipe.

Composite Panels (Sliced Further)

The wizard’s Break-down pass adds per-slice fields the runtime must understand: The table above lists every field this skill reads; treat any other field in the pack manifest as opaque.

Consume recipe

  1. Filter out composite parents. Drop any slice with isComposite: true unless the caller specifically asked for the flat preview.
  2. Group by parentSliceIndex. Slices that share a parentSliceIndex belong to the same composite group. Slices without it are standalone.
  3. Sort each group by zOrder ascending. Lower values render behind higher values. This determines paint order.
  4. Spawn Node2D parent + Sprite2D children. Name the parent after the original composite parent’s slice name. For each child:
    • name = child.name
    • texture = imported res:// path
    • z_index = child.zOrder
    • position = Vector2(child.bbox.x - parent.bbox.x, child.bbox.y - parent.bbox.y) — offset relative to the parent’s source-sheet rect.
  5. Apply widget post-processing. If any child has a widget field, wrap or replace its Sprite2D with the appropriate Control node per the recipes above (panel → NinePatchRect, progress_bar → TextureProgressBar, etc.).
For the full instantiation flow (op JSON, examples), use instantiate-asset-pack.

Legacy compatibility

Older packs use different field names. Always fall back:
packFileIndex is the slice’s iteration position in packFiles[] (the loop counter, not a persisted field). On packs with no zOrder and no layerIndex at all, iteration order is the only signal you get — accept it and move on. Check metadata.schemaVersion on the pack: null (or absent) = legacy, 1 = current. New packs from the wizard always set it.

What this skill does NOT cover

  • Auto-tiling terrain (Wang / 47-tile). Different format entirely — see tileable-texture.
  • Animated UI (button press-down sprites, hover glow). The wizard captures static frames; for animation see sprite-sheet.
  • Non-AABB widgets in the 9-slice path. See the Shape support table at the top — for circles, hexagons, organic shapes, fall through to TextureRect and skip 9-slice entirely.

From a shell

No Summer MCP tools in this session? Run each one as a command; when summer --version is missing or below 4.0, use npx -y summer-engine@latest in place of summer. Fields are flags in kebab-case (--scene-path res://main.tscn) or one --input '<json>', and summer ops describe <op> prints the exact input. The summer-cli skill has the rest.
  • create-asset-sheet: Generate a pack of 2D assets from one prompt (tile sheet, UI kit, character pack, biome), sliced.
  • instantiate-asset-pack: Lay out a whole create-asset-sheet pack in the scene: composites, paint order, Sprite2D and NinePatch.
  • sprite-sheet: Generate animated 2D character sprite sheets (walk, attack, idle, death) for AnimatedSprite2D.
  • tileable-texture: Generate a seamless tileable texture for walls, floors or terrain, wired as a StandardMaterial3D albedo.

Source: library/skills/use-widget-asset/SKILL.md, rendered from summer-engine@4.3.0 on npm.