Help us improve
Share bugs, ideas, or general feedback.
From summer
Spawns an entire multi-slice asset pack as a correctly-grouped, paint-ordered node tree in the current scene.
npx claudepluginhub summerengine/summer-engine-agent --plugin summerHow this skill is triggered — by the user, by Claude, or both
Slash command
/summer:instantiate-asset-packassets/**art/**ui/**scenes/**This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
A pack ArtAsset (produced by `summer:2d-assets/create-asset-sheet`) is a bundle of cropped slice PNGs with per-slice metadata. This skill is the runtime side: given a pack, lay its slices into the current scene as a correctly-grouped, correctly-layered set of nodes.
Explains how to wire 9-slice widget metadata from create-asset-sheet packs into NinePatchRect and other Godot nodes for stretchable UI panels, buttons, sliders, progress bars, and toggles.
Defines import, slicing, atlas packing, and naming rules for 2D sprite assets to ensure consistency, performance, and replaceability across a project.
Guides importing and managing assets in Godot 4.3+ — image compression, 3D scene import, audio formats, and import configuration.
Share bugs, ideas, or general feedback.
A pack ArtAsset (produced by summer:2d-assets/create-asset-sheet) is a bundle of cropped slice PNGs with per-slice metadata. This skill is the runtime side: given a pack, lay its slices into the current scene as a correctly-grouped, correctly-layered set of nodes.
For wiring individual widget slices (9-slice panels, progress bars, toggles), this skill delegates to summer:2d-assets/use-widget-asset. This skill handles the pack-level layout: grouping composites, paint order, spatial offset, naming.
Sprite2D (or summer:2d-assets/use-widget-asset if it's a UI widget).summer:2d-assets/create-asset-sheet.asset_pipeline.json.Full schema: publicsummerengine/public/knowledge/asset_pack_schema.json.
The per-slice fields this skill cares about:
| Field | Used for |
|---|---|
name | Node name |
url | Texture path (after summer_import_from_url) |
bbox | Spatial offset of composite children relative to parent |
zOrder | z_index on the Sprite2D; sort children by this ascending |
isComposite | Filter out parent slices (flat previews, not runtime assets) |
parentSliceIndex | Group children to their composite parent |
pairWith | Toggle ON/OFF pair link |
widget | Wrap in NinePatchRect / TextureProgressBar via use-widget-asset |
category | Decide wrapper type — ui → Control tree, else Node2D/Sprite2D |
Legacy fallback: slice.zOrder ?? slice.layerIndex ?? packFileIndex, slice.isComposite ?? slice.isReference ?? false. packFileIndex is the iteration counter when looping packFiles[], not a stored field.
A standalone slice has no parentSliceIndex and isn't a composite parent. Spawn as a single Sprite2D:
summer_import_from_url to get a res:// path.summer_add_node — type Sprite2D, name slice.name.summer_set_prop — texture = res://....slice.zOrder is set, summer_set_prop — z_index = slice.zOrder.If the slice has a widget field, hand off to summer:2d-assets/use-widget-asset after step 1.
A composite parent (isComposite: true) is the flat preview the wizard made of the assembled panel. Do not spawn it. Its children — slices whose parentSliceIndex points back at it — are the real runtime assets.
Recipe:
isComposite: true slices unless the user asked for the flat preview.parentSliceIndex matches this parent's index.zOrder ascending. Lower zOrder renders behind. Use the legacy fallback chain.Node2D parent named after the composite parent's name (e.g. settings_panel).child.url → res:// path.summer_add_node Sprite2D under the Node2D, name = child.name.summer_set_prop — texture = res://....summer_set_prop — z_index = child.zOrder.summer_set_prop — position = Vector2(child.bbox.x - parent.bbox.x, child.bbox.y - parent.bbox.y).widget field — see next section.When a child slice has widget.kind set, the bare Sprite2D is not the right node. Replace or wrap it per the widget mapping:
| widget.kind | Node | Mapping |
|---|---|---|
panel, button | NinePatchRect | frameMargins[0..3] → patch_margin_left/top/right/bottom |
progress_bar | TextureProgressBar | fillRect → stretch_margin_*; orientation → fill_mode |
slider | HSlider/VSlider + NinePatchRect track | track uses frameMargins; slider sits on top |
toggle | TextureRect | Swap texture between this slice and packFiles[pairWith].url |
Delegate the actual wiring (percentage-to-pixel conversion, node-specific props) to summer:2d-assets/use-widget-asset. This skill places the node; that skill configures the geometry.
slice.name is canonical. The wizard's classifier produces snake_case names (play_button, health_bar_fill, settings_panel). Use as the node name verbatim.hud_"), prepend: hud_play_button.name becomes the Node2D wrapper name._1, _2, etc. Do not silently overwrite.Pack has one non-composite slice, crate_wooden, no widget metadata. Place it at scene origin:
{
"ops": [
{
"op": "AddNode",
"parent": ".",
"type": "Sprite2D",
"name": "crate_wooden"
},
{
"op": "SetProp",
"path": "./crate_wooden",
"key": "texture",
"value": "res://assets/images/crate_wooden.png"
},
{
"op": "SetProp",
"path": "./crate_wooden",
"key": "position",
"value": "Vector2(0, 0)"
},
{ "op": "SaveScene" }
]
}
Pack has a composite parent settings_panel (filtered out) plus three children:
panel_bg — zOrder 0, bbox offset (0, 0), widget.kind = panel, frameMargins presentapply_button — zOrder 1, bbox offset (40, 120), widget.kind = button, frameMargins presentclose_icon — zOrder 2, bbox offset (220, 8), no widget{
"ops": [
{
"op": "AddNode",
"parent": ".",
"type": "Node2D",
"name": "settings_panel"
},
{
"op": "AddNode",
"parent": "./settings_panel",
"type": "NinePatchRect",
"name": "panel_bg"
},
{
"op": "SetProp",
"path": "./settings_panel/panel_bg",
"key": "texture",
"value": "res://assets/images/panel_bg.png"
},
{
"op": "SetProp",
"path": "./settings_panel/panel_bg",
"key": "z_index",
"value": 0
},
{
"op": "SetProp",
"path": "./settings_panel/panel_bg",
"key": "position",
"value": "Vector2(0, 0)"
},
{
"op": "AddNode",
"parent": "./settings_panel",
"type": "NinePatchRect",
"name": "apply_button"
},
{
"op": "SetProp",
"path": "./settings_panel/apply_button",
"key": "texture",
"value": "res://assets/images/apply_button.png"
},
{
"op": "SetProp",
"path": "./settings_panel/apply_button",
"key": "z_index",
"value": 1
},
{
"op": "SetProp",
"path": "./settings_panel/apply_button",
"key": "position",
"value": "Vector2(40, 120)"
},
{
"op": "AddNode",
"parent": "./settings_panel",
"type": "Sprite2D",
"name": "close_icon"
},
{
"op": "SetProp",
"path": "./settings_panel/close_icon",
"key": "texture",
"value": "res://assets/images/close_icon.png"
},
{
"op": "SetProp",
"path": "./settings_panel/close_icon",
"key": "z_index",
"value": 2
},
{
"op": "SetProp",
"path": "./settings_panel/close_icon",
"key": "position",
"value": "Vector2(220, 8)"
},
{ "op": "SaveScene" }
]
}
After this, hand panel_bg and apply_button to summer:2d-assets/use-widget-asset to set patch_margin_* from their widget.frameMargins.
Note the ops format: position is the Godot string "Vector2(0, 0)", not a JSON object. z_index is a bare integer. This is the format Summer Engine expects — see the publicsummerengine CLAUDE.md.
zOrder. Fall back to slice.zOrder ?? slice.layerIndex ?? packFileIndex. packFileIndex is the iteration counter when looping packFiles[] (not a persisted field). If even layerIndex is missing (very old pack), iteration order is the only signal — accept it.isComposite. Fall back to slice.isComposite ?? slice.isReference ?? false. If both are missing on every slice, treat the whole pack as standalone — no compositing, every slice spawns at origin as its own Sprite2D.Vector2(0, 0) with its own zOrder.frameMargins. The vision detector said kind: 'panel' but didn't emit margins. Render as TextureRect (or Sprite2D if outside a Control tree) and skip 9-slice. Do not invent margins._1, _2, etc. Never overwrite an existing node.summer_import_from_url returns an error — skip that slice, log a warning, continue with the rest. Do not abort the whole pack.summer:2d-assets/create-asset-sheet — production side; how the pack was made.summer:2d-assets/use-widget-asset — wiring an individual widget slice (NinePatchRect, TextureProgressBar geometry).asset_pipeline.json — broader find-or-generate -> import -> apply flow.