summer-engine 1.5.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{marketplace.json → .claude-plugin/marketplace.json} +3 -3
- package/.claude-plugin/plugin.json +52 -11
- package/.codex-plugin/plugin.json +69 -8
- package/.cursor-plugin/plugin.json +53 -12
- package/.factory-plugin/plugin.json +20 -0
- package/.opencode/INSTALL.md +75 -0
- package/.opencode/plugins/summer.js +9 -6
- package/AGENTS.md +51 -0
- package/CHANGELOG.md +31 -1
- package/CLAUDE.md +5 -0
- package/GEMINI.md +56 -0
- package/README.md +409 -80
- package/_persona/summer/SKILL.md +113 -0
- package/dist/bin/summer.js +0 -0
- package/dist/commands/assets.d.ts +2 -0
- package/dist/commands/assets.js +189 -0
- package/dist/commands/create.js +55 -17
- package/dist/commands/debug.d.ts +2 -0
- package/dist/commands/debug.js +127 -0
- package/dist/commands/install.js +2 -2
- package/dist/commands/list.js +24 -5
- package/dist/commands/project.d.ts +2 -0
- package/dist/commands/project.js +170 -0
- package/dist/commands/scene.d.ts +2 -0
- package/dist/commands/scene.js +290 -0
- package/dist/lib/banner.js +2 -2
- package/dist/lib/log-filters.d.ts +53 -0
- package/dist/lib/log-filters.js +130 -0
- package/dist/lib/plugin-manifests.test.d.ts +1 -0
- package/dist/lib/plugin-manifests.test.js +134 -0
- package/dist/lib/remote-templates.d.ts +25 -0
- package/dist/lib/remote-templates.js +86 -0
- package/dist/lib/skills-registry.d.ts +283 -3
- package/dist/lib/skills-registry.js +522 -2
- package/dist/lib/telemetry.d.ts +13 -0
- package/dist/lib/telemetry.js +63 -0
- package/dist/lib/with-engine.d.ts +14 -0
- package/dist/lib/with-engine.js +109 -0
- package/dist/mcp/tools/asset-tools.js +12 -13
- package/dist/mcp/tools/debug-tools.js +32 -9
- package/dist/mcp/tools/generate-tools.js +101 -0
- package/dist/mcp/tools/with-engine.js +4 -0
- package/gemini-extension.json +2 -2
- package/hooks/pre-commit-doctor.sh +0 -0
- package/hooks/run-hook.cmd +0 -0
- package/hooks/session-start.sh +0 -0
- package/package.json +11 -5
- package/skills/2d-assets/character-portrait/SKILL.md +196 -0
- package/skills/2d-assets/concept-art/SKILL.md +152 -0
- package/skills/2d-assets/pixel-art/SKILL.md +180 -0
- package/skills/2d-assets/skybox-panorama/SKILL.md +207 -0
- package/skills/2d-assets/sprite-sheet/SKILL.md +239 -0
- package/skills/2d-assets/tileable-texture/SKILL.md +205 -0
- package/skills/2d-assets/ui-graphics/SKILL.md +210 -0
- package/skills/3d-assets/character-model/SKILL.md +225 -0
- package/skills/3d-assets/environment-kit/SKILL.md +164 -0
- package/skills/3d-assets/organic-model/SKILL.md +192 -0
- package/skills/3d-assets/prop-model/SKILL.md +133 -0
- package/skills/3d-assets/vehicle-model/SKILL.md +202 -0
- package/skills/README.md +1 -1
- package/skills/_meta/skill-create/SKILL.md +1 -1
- package/skills/_meta/skill-improve/SKILL.md +1 -1
- package/skills/_meta/skill-test/SKILL.md +1 -1
- package/skills/_meta/using-summer/SKILL.md +130 -0
- package/skills/ai-and-npcs/design-npc/SKILL.md +3 -1
- package/skills/animation/animation-tree/SKILL.md +260 -0
- package/skills/animation/facial-and-lipsync/SKILL.md +282 -0
- package/skills/animation/generate-motion/SKILL.md +129 -0
- package/skills/animation/procedural-animation/SKILL.md +234 -0
- package/skills/animation/retarget/SKILL.md +172 -0
- package/skills/asset-pipeline/asset-strategy/SKILL.md +102 -212
- package/skills/audio/adaptive-music/SKILL.md +326 -0
- package/skills/audio/ambient-bed/SKILL.md +278 -0
- package/skills/audio/music-track/SKILL.md +268 -0
- package/skills/audio/sound-effect/SKILL.md +237 -0
- package/skills/audio/voice-line/SKILL.md +253 -0
- package/skills/catalog.yaml +266 -5
- package/skills/character-controllers/fps-controller/SKILL.md +1 -1
- package/skills/debugging/debug/SKILL.md +102 -82
- package/skills/rendering-and-lighting/3d-lighting/SKILL.md +1 -1
- package/skills/scene-and-project/browse-templates/SKILL.md +105 -0
- package/skills/scene-and-project/make-game/SKILL.md +159 -346
- package/skills/scene-and-project/new-project/SKILL.md +106 -0
- package/skills/scene-and-project/scene-composition/SKILL.md +1 -1
- package/skills/scripting-patterns/gdscript-patterns/SKILL.md +1 -1
- package/skills/ui-and-ux/ui-basics/SKILL.md +1 -1
- package/skills/video/animated-loop/SKILL.md +200 -0
- package/skills/video/cinematic-cutscene/SKILL.md +204 -0
- package/skills/video/trailer-shot/SKILL.md +203 -0
- package/skills/visual-effects/_building-blocks/additive-billboard-particles.md +28 -0
- package/skills/visual-effects/_building-blocks/noise-3d-fbm.gdshaderinc +45 -0
- package/skills/visual-effects/_building-blocks/trauma-shake-snippet.md +51 -0
- package/skills/visual-effects/{vfx → game-feel}/SKILL.md +1 -1
- package/skills/visual-effects/recipes/dissolve/SKILL.md +349 -0
- package/skills/visual-effects/recipes/fire/SKILL.md +387 -0
- package/skills/visual-effects/recipes/hit-spark/SKILL.md +330 -0
- package/skills/visual-effects/recipes/lightning/SKILL.md +372 -0
- package/skills/visual-effects/recipes/magic-glow/SKILL.md +377 -0
- package/skills/visual-effects/recipes/muzzle-flash/SKILL.md +326 -0
- package/skills/visual-effects/recipes/smoke/SKILL.md +381 -0
- package/skills/visual-effects/recipes/water-ripple/SKILL.md +340 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sprite-sheet
|
|
3
|
+
description: Use when generating animated 2D character sprites laid out as a sprite sheet (grid of frames) — walk cycle, attack frames, idle bob, death sequence. Wires into AnimatedSprite2D / SpriteFrames. Trigger on "sprite sheet", "walk cycle", "attack frames", "animated sprite", "frame-by-frame animation", "2D character animation".
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
|
+
category: 2d-assets
|
|
7
|
+
user-invocable: true
|
|
8
|
+
allowed-tools: Read Grep Glob Write Edit summer_generate_image summer_search_assets summer_import_from_url summer_set_resource_property summer_add_node summer_set_prop
|
|
9
|
+
paths: ["assets/**", "sprites/**", "art/sprites/**"]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# sprite-sheet — Frame-by-Frame 2D Animation
|
|
13
|
+
|
|
14
|
+
This skill produces a grid of animation frames for a 2D character — walk cycle, idle bob, attack swing, death sequence — and wires the result into an `AnimatedSprite2D` via a `SpriteFrames` resource.
|
|
15
|
+
|
|
16
|
+
**Up-front honesty:** sprite-sheet generation from a single text-to-image call is **unreliable**. Models can render "a sprite sheet of a knight walking" and produce 8 frames, but the inter-frame consistency (same anatomy, same costume, same lighting) is poor. Limbs morph between frames. Pixel sprites get extra fingers in frame 3. The result usually looks worse than the static sprite did.
|
|
17
|
+
|
|
18
|
+
This skill therefore offers **three paths**, ranked by reliability:
|
|
19
|
+
|
|
20
|
+
1. **Per-frame img2img** (most reliable) — generate the base pose, then generate each subsequent frame via `referenceImageUrl` with a small pose delta. Composite the frames into a sheet externally or wire each as a separate `SpriteFrames` entry.
|
|
21
|
+
2. **Single-call sheet generation** (fast, unreliable) — one prompt asks for the grid. Works ~30% of the time. Worth trying once for short cycles (4 frames or fewer) before falling back to (1).
|
|
22
|
+
3. **Manual authoring** (most reliable, slowest) — hand-author in **Aseprite** or **Piskel**. For pixel art at 32×32, this is often faster than fixing AI generations.
|
|
23
|
+
|
|
24
|
+
There is no dedicated sprite-sheet generation tool. Recommended path: per-frame `summer_generate_image` with `referenceImageUrl` (img2img) at consistent angle/lighting, OR external tools (Aseprite/Piskel).
|
|
25
|
+
|
|
26
|
+
## When to use
|
|
27
|
+
|
|
28
|
+
- "Generate a walk cycle for the goblin sprite."
|
|
29
|
+
- "I need 4 attack frames for the player character."
|
|
30
|
+
- "Make a death animation — 6 frames of the enemy collapsing."
|
|
31
|
+
- "Create an idle bob, 2-frame loop."
|
|
32
|
+
- The character exists as a static sprite and needs animation.
|
|
33
|
+
|
|
34
|
+
## When NOT to use
|
|
35
|
+
|
|
36
|
+
- The character is 3D — use `summer:animation/generate-motion` for skeletal animation.
|
|
37
|
+
- The user wants a single static sprite → `summer:2d-assets/pixel-art` or `summer:2d-assets/character-portrait`.
|
|
38
|
+
- The user wants UI animation (loading spinner, button hover) — animate via `AnimationPlayer` rotating/tweening a static texture instead. Don't sprite-sheet UI.
|
|
39
|
+
- The user has 12+ frames per animation and 4+ animations — that's hundreds of generations at $0.02 each. Pause and discuss budget.
|
|
40
|
+
|
|
41
|
+
## Steps
|
|
42
|
+
|
|
43
|
+
### 1. Anchor the base sprite
|
|
44
|
+
|
|
45
|
+
You need a stable reference. Either:
|
|
46
|
+
|
|
47
|
+
- The user has a static sprite already (`res://sprites/goblin.png`) — use it as `referenceImageUrl`.
|
|
48
|
+
- Generate a base sprite via `summer:2d-assets/pixel-art` or `summer:2d-assets/character-portrait` first, then return here.
|
|
49
|
+
|
|
50
|
+
Without a base, every frame drifts.
|
|
51
|
+
|
|
52
|
+
### 2. Pick the path
|
|
53
|
+
|
|
54
|
+
Ask the user (or decide based on context):
|
|
55
|
+
|
|
56
|
+
| Signal | Path |
|
|
57
|
+
|---|---|
|
|
58
|
+
| Short cycle (≤4 frames), willing to accept some drift | Try **single-call sheet** first; fall back if bad |
|
|
59
|
+
| Pixel art at small resolution | **Aseprite manual** is often fastest |
|
|
60
|
+
| Higher-res character (128px+), 6-12 frames | **Per-frame img2img** |
|
|
61
|
+
| User wants exact-pixel consistency | **Aseprite manual** — AI cannot deliver exact pixels |
|
|
62
|
+
|
|
63
|
+
State the path before starting: "I'll do per-frame img2img — 6 generations, ~$0.12. The first frame is the base; each next frame uses the previous as reference. OK?"
|
|
64
|
+
|
|
65
|
+
### 3a. Path 1 — Per-frame img2img
|
|
66
|
+
|
|
67
|
+
Generate frame 1 (or use existing base). For each subsequent frame, prompt the pose delta and pass the previous frame as `referenceImageUrl`:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
summer_generate_image(
|
|
71
|
+
prompt="goblin warrior, walk cycle frame 2 of 6, right leg forward, slight bob upward, identical character, same costume, same palette, transparent background",
|
|
72
|
+
referenceImageUrl="<frame 1 fileUrl>",
|
|
73
|
+
model="nano-banana-2",
|
|
74
|
+
style="<same as base>",
|
|
75
|
+
options={ image_size: "square_hd", negative_prompt: "different character, different costume, scene background" }
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Repeat for each frame. Save each as `goblin_walk_01.png`, `goblin_walk_02.png`, etc.
|
|
80
|
+
|
|
81
|
+
After all frames return, either:
|
|
82
|
+
|
|
83
|
+
- Wire each as a separate frame in a `SpriteFrames` resource (Godot will treat them as a sequence — no need to composite into a single sheet image).
|
|
84
|
+
- Composite into a single sheet image via Aseprite (`File → Import Sprite Sheet`) or ImageMagick (`montage frame_*.png -tile 6x1 -geometry +0+0 sheet.png`).
|
|
85
|
+
|
|
86
|
+
### 3b. Path 2 — Single-call sheet (try once)
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
summer_generate_image(
|
|
90
|
+
prompt="goblin warrior walk cycle, sprite sheet, 6 frames in a horizontal row, identical character across frames, side view, transparent background, frames clearly separated, consistent lighting, consistent palette",
|
|
91
|
+
model="nano-banana-2",
|
|
92
|
+
style="pixel",
|
|
93
|
+
options={ image_size: "landscape_16_9", negative_prompt: "different character per frame, scene background, varying lighting" }
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Inspect the result. If frames are coherent and the count matches, proceed. If anatomy morphs or count is wrong, fall back to Path 1 or Path 3.
|
|
98
|
+
|
|
99
|
+
### 3c. Path 3 — Aseprite manual fallback
|
|
100
|
+
|
|
101
|
+
Tell the user:
|
|
102
|
+
|
|
103
|
+
> AI sprite-sheet generation is unreliable — best path for clean pixel animation is to hand-author in Aseprite (or Piskel for free in-browser). Onion-skin frame-by-frame; ~10 minutes for a 4-frame walk cycle. Want me to generate a base reference image you can trace?
|
|
104
|
+
|
|
105
|
+
If yes, generate the static base via `summer:2d-assets/pixel-art` and stop here. The user takes it to Aseprite.
|
|
106
|
+
|
|
107
|
+
### 4. Import frames into Godot
|
|
108
|
+
|
|
109
|
+
For per-frame import (Path 1):
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
summer_import_from_url(url="<frame 1>", path="res://sprites/goblin/walk_01.png")
|
|
113
|
+
summer_import_from_url(url="<frame 2>", path="res://sprites/goblin/walk_02.png")
|
|
114
|
+
...
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
For a composited sheet (Path 2 or external composite):
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
summer_import_from_url(url="<sheet>", path="res://sprites/goblin/walk_sheet.png")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Set `Filter: Nearest` on import for pixel art, `Linear` for high-res.
|
|
124
|
+
|
|
125
|
+
### 5. Wire as AnimatedSprite2D
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
summer_add_node(parentPath="/root/Game/Goblin", type="AnimatedSprite2D", name="Sprite")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Create a `SpriteFrames` resource and add an animation named `walk`. For per-frame textures:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
summer_set_resource_property(
|
|
135
|
+
nodePath="/root/Game/Goblin/Sprite",
|
|
136
|
+
resourceProperty="sprite_frames:animations/walk/frames",
|
|
137
|
+
value=["res://sprites/goblin/walk_01.png", "res://sprites/goblin/walk_02.png", ...]
|
|
138
|
+
)
|
|
139
|
+
summer_set_resource_property(
|
|
140
|
+
nodePath="/root/Game/Goblin/Sprite",
|
|
141
|
+
resourceProperty="sprite_frames:animations/walk/speed",
|
|
142
|
+
value=8.0
|
|
143
|
+
)
|
|
144
|
+
summer_set_resource_property(
|
|
145
|
+
nodePath="/root/Game/Goblin/Sprite",
|
|
146
|
+
resourceProperty="sprite_frames:animations/walk/loop",
|
|
147
|
+
value=true
|
|
148
|
+
)
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
For sheet-based (Path 2): use `AtlasTexture` with one region per frame, then add each AtlasTexture as a frame.
|
|
152
|
+
|
|
153
|
+
### 6. Trigger from code
|
|
154
|
+
|
|
155
|
+
```gdscript
|
|
156
|
+
@onready var sprite: AnimatedSprite2D = $Sprite
|
|
157
|
+
|
|
158
|
+
func _physics_process(delta):
|
|
159
|
+
if velocity.length() > 0.1:
|
|
160
|
+
sprite.play("walk")
|
|
161
|
+
else:
|
|
162
|
+
sprite.play("idle")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Prompt patterns
|
|
166
|
+
|
|
167
|
+
### Per-frame img2img (Path 1)
|
|
168
|
+
|
|
169
|
+
| Goal | Frame 1 (base) | Frame N prompt skeleton (with `referenceImageUrl: <frame N-1>`) |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| Walk cycle (6 frames, side view) | `<character>, side view, idle stance, transparent bg` | `<character>, walk cycle frame N of 6, <leg position description>, identical character, same costume, transparent bg` |
|
|
172
|
+
| Attack swing (4 frames) | `<character>, side view, weapon raised over head` | `<character>, attack frame N, <weapon position: descending / impact / recovery>, identical character, transparent bg` |
|
|
173
|
+
| Idle bob (2 frames, loop) | `<character>, neutral stance, slightly compressed` | `<character>, idle bob upper position, slightly extended upward, identical character, transparent bg` |
|
|
174
|
+
| Death (6 frames) | `<character>, hit react, leaning back` | `<character>, death frame N, <position: stumbling / kneeling / falling / collapsed>, identical character, transparent bg` |
|
|
175
|
+
| Jump (3 frames) | `<character>, crouched ready to jump` | `<character>, jump frame N, <apex extended / falling tucked / land impact>, identical character, transparent bg` |
|
|
176
|
+
|
|
177
|
+
### Single-call sheet (Path 2)
|
|
178
|
+
|
|
179
|
+
| Goal | Prompt that sometimes works |
|
|
180
|
+
|---|---|
|
|
181
|
+
| 4-frame walk cycle | `<character> walk cycle, sprite sheet, 4 frames in horizontal row, side view, identical character, transparent background, clear frame separation, consistent lighting` |
|
|
182
|
+
| 2-frame idle | `<character> idle bob, sprite sheet, 2 frames horizontal, identical character, slight up-down delta, transparent background` |
|
|
183
|
+
|
|
184
|
+
### Bad prompts (and why)
|
|
185
|
+
|
|
186
|
+
| Bad | Failure mode |
|
|
187
|
+
|---|---|
|
|
188
|
+
| `goblin walking` | Returns one image of a walking goblin. Not a sheet, not multiple frames. |
|
|
189
|
+
| `12-frame walk cycle in one image` | Frame count too high for single-call. Anatomy morphs across the row. |
|
|
190
|
+
| `walk cycle for any character` | No character anchor. Frames have different characters. |
|
|
191
|
+
| Per-frame without `referenceImageUrl` | Each frame is a different goblin. |
|
|
192
|
+
| `sprite sheet, photorealistic` | Photoreal characters in tight frames lose identity coherence fast. Stay stylized. |
|
|
193
|
+
|
|
194
|
+
## Anti-patterns
|
|
195
|
+
|
|
196
|
+
- **Skipping the base anchor.** Without a stable reference (existing sprite or generated base), every frame drifts. Anchor first.
|
|
197
|
+
- **Generating walk cycles at high frame counts (12+) via single call.** Will fail. Use per-frame img2img or split into chunks.
|
|
198
|
+
- **Wiring an inconsistent sheet anyway** because you don't want to regenerate. Ship the inconsistency and the player notices the morphing limbs immediately. Cut the frame count or hand-author instead.
|
|
199
|
+
- **Sprite-sheeting things that don't need to be sprite-sheeted.** UI animation, simple bobs, fades — use `AnimationPlayer` to tween a static texture instead. Sprite sheets are for character animation specifically.
|
|
200
|
+
- **Pretending Aseprite is a failure.** Hand-authoring 4 pixel-art frames takes 10 minutes and looks better than 8 AI generations. Don't oversell AI here.
|
|
201
|
+
|
|
202
|
+
## Edge cases
|
|
203
|
+
|
|
204
|
+
- **Pixel art at low resolution.** AI per-frame img2img at 16×16 or 32×32 is ~impossible — the model can't preserve exact pixel positions. Aseprite or Piskel manual is the only reliable path. Generate a high-res reference and trace it down.
|
|
205
|
+
- **Character with cloth / cape physics.** Cloth animation is hard for any AI. Use a base sprite and add cloth as a separate `AnimationPlayer`-tweened layer (`Sprite2D` for the cape, sin-wave-tweened rotation).
|
|
206
|
+
- **8-direction sprite (top-down RPG with N/NE/E/SE/S/SW/W/NW).** Generate one direction's full cycle, then for each other direction generate the FIRST FRAME via img2img with a "rotated to face X" prompt and use it as the new base for that direction's per-frame work. Multiplies generation count by 8 — pause for budget confirmation.
|
|
207
|
+
- **User wants a turn-around (rotating in place over 8 frames).** Same as 8-direction; generate single-frame per angle as anchor, accept that AI rotation won't be perfectly consistent.
|
|
208
|
+
- **Animation needs to loop seamlessly.** Make frame N+1 explicitly bridge back to frame 1 in your prompt. Or generate one extra "bridge" frame and drop it.
|
|
209
|
+
|
|
210
|
+
## Fallback (no MCP)
|
|
211
|
+
|
|
212
|
+
Print the per-frame call sequence:
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
Frame 1: summer_generate_image(prompt="<base>", model="nano-banana-2", style="pixel", ...)
|
|
216
|
+
Frame 2: summer_generate_image(prompt="<base + delta>", referenceImageUrl="<frame 1>", ...)
|
|
217
|
+
Frame 3: summer_generate_image(prompt="<base + delta>", referenceImageUrl="<frame 2>", ...)
|
|
218
|
+
...
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Tell the user to run via the Summer dashboard. Or recommend Aseprite (paid, $20) / Piskel (free in-browser) for hand-authoring — for pixel art under 64×64, it is the faster path even with MCP available.
|
|
222
|
+
|
|
223
|
+
## Handoff
|
|
224
|
+
|
|
225
|
+
After the animation is wired:
|
|
226
|
+
|
|
227
|
+
- **More animations on the same character** (idle, attack, death) → re-invoke this skill with the same base anchor, vary the delta.
|
|
228
|
+
- **Sound effects synced to animation frames** → `summer:audio/sound-effect`, then wire via `Call Method Track` in `AnimationPlayer`.
|
|
229
|
+
- **Multi-direction sprites** → re-invoke per direction (budget warning).
|
|
230
|
+
- **Pixel-art static base if not yet generated** → `summer:2d-assets/pixel-art` first.
|
|
231
|
+
- **3D character animation instead** → `summer:animation/generate-motion`.
|
|
232
|
+
|
|
233
|
+
## See also
|
|
234
|
+
|
|
235
|
+
- `summer:2d-assets/pixel-art` — base sprite generation.
|
|
236
|
+
- `summer:2d-assets/character-portrait` — base portrait for higher-res characters.
|
|
237
|
+
- `summer:animation/generate-motion` — 3D-skeletal counterpart.
|
|
238
|
+
- `summer:audio/sound-effect` — frame-synced SFX.
|
|
239
|
+
- `_shared/mcp-tools-reference.md` — `summer_generate_image` schema.
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tileable-texture
|
|
3
|
+
description: Use when generating a seamless tileable texture for walls, floors, terrain, ceilings — square tile that repeats cleanly on all four edges. Wires onto PlaneMesh / CSGBox3D / MeshInstance3D as a StandardMaterial3D albedo. Trigger on "tileable texture", "seamless texture", "wall texture", "floor texture", "ground texture", "terrain texture", "tiled material".
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
|
+
category: 2d-assets
|
|
7
|
+
user-invocable: true
|
|
8
|
+
allowed-tools: Read Grep Glob Write Edit summer_generate_image summer_search_assets summer_import_from_url summer_set_resource_property summer_add_node summer_set_prop summer_inspect_node
|
|
9
|
+
paths: ["assets/**", "art/textures/**", "materials/**"]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# tileable-texture — Seamless Square That Repeats Cleanly
|
|
13
|
+
|
|
14
|
+
This skill generates a seamless square texture (typically 1024×1024) that tiles cleanly on all four edges with no visible seams. Output goes onto a `PlaneMesh`, `CSGBox3D`, or `MeshInstance3D` as a `StandardMaterial3D` albedo, often with `uv_scale` cranked up so a single tile covers a small area and the surface repeats it across a wall or floor.
|
|
15
|
+
|
|
16
|
+
The hard part is "seamless." Most diffusion models violate edge continuity by default — generate a brick wall and the bricks stop mid-row at the edge. This skill encodes the prompt suffix and the post-import verification that catches seams before they ship.
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
- "Generate a brick wall texture for this room."
|
|
21
|
+
- "I need a grass ground texture for the level."
|
|
22
|
+
- "Tileable wood-floor texture, 1024×1024."
|
|
23
|
+
- "Stone tile texture for the dungeon."
|
|
24
|
+
- "Sand / dirt / metal-panel — seamless."
|
|
25
|
+
|
|
26
|
+
## When NOT to use
|
|
27
|
+
|
|
28
|
+
- The user wants a 3D-modeled wall with geometric brick relief → `summer:asset-pipeline/asset-strategy` (image-to-3D).
|
|
29
|
+
- The user wants a unique mural / non-tiling artwork → `summer:2d-assets/concept-art` or `summer:2d-assets/character-portrait`.
|
|
30
|
+
- The user wants a skybox / 360° environment → `summer:2d-assets/skybox-panorama`.
|
|
31
|
+
- The user wants a normal map / PBR material set — generation today is albedo-only. Normals must be derived (`MaterialMaker`, `NormalMap-Online`) or hand-authored.
|
|
32
|
+
|
|
33
|
+
## Steps
|
|
34
|
+
|
|
35
|
+
### 1. Search for an existing texture
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
summer_search_assets(query="<material> tileable", filter={ kind: "image" })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Texture libraries (AmbientCG, Polyhaven) often have free PBR sets that beat AI generation for realism. If the user wants photorealistic tiling, pause and suggest those.
|
|
42
|
+
|
|
43
|
+
### 2. Build the prompt — material + the seamless suffix
|
|
44
|
+
|
|
45
|
+
Pattern:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
<material description>, seamless tileable texture, top-down view, uniform lighting, no perspective, no shadows, no edges, square format, no specific objects in frame
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The load-bearing phrases are:
|
|
52
|
+
|
|
53
|
+
- **`seamless tileable texture`** — primes the model.
|
|
54
|
+
- **`top-down view`** — kills perspective convergence (which is the #1 source of visible seams).
|
|
55
|
+
- **`uniform lighting`** — kills directional shadows that bake into the tile and stripe across the surface when it repeats.
|
|
56
|
+
- **`no perspective, no shadows, no edges`** — explicit negation of common failure modes.
|
|
57
|
+
- **`no specific objects in frame`** — kills "interest" features the model adds (a single bright leaf, a chip in one brick) that scream "this is a repeating tile."
|
|
58
|
+
|
|
59
|
+
### 3. Generate
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
summer_generate_image(
|
|
63
|
+
prompt="weathered red brick wall, seamless tileable texture, top-down view, uniform lighting, no perspective, no shadows, no specific objects, square format, photographic detail",
|
|
64
|
+
model="nano-banana-2",
|
|
65
|
+
style="realistic",
|
|
66
|
+
options={
|
|
67
|
+
image_size: "square_hd",
|
|
68
|
+
negative_prompt: "perspective, vanishing point, directional shadow, vignette, single feature, scene context, sky, sun"
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`style: "realistic"` is the right default for textures (most are aiming for photographic surface). Switch to `"none"` for stylized/painterly.
|
|
74
|
+
|
|
75
|
+
### 4. Import to project
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
summer_import_from_url(url="<fileUrl>", path="res://art/textures/brick_red.png")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
In the import dock, set:
|
|
82
|
+
|
|
83
|
+
- `Repeat: Enabled` (REQUIRED for tiling).
|
|
84
|
+
- `Filter: Linear with mipmaps` (smoother at distance).
|
|
85
|
+
- `Mipmaps: Enabled` (textures viewed at angle need mipmaps).
|
|
86
|
+
- `Compress: VRAM Compressed` for ship; `Lossless` while iterating.
|
|
87
|
+
|
|
88
|
+
### 5. Verify the seam
|
|
89
|
+
|
|
90
|
+
Before wiring into a scene, view the texture tiled. Quick check: in the editor's filesystem dock, right-click the texture → preview → set repeat 4×4 mentally. Or apply to a `PlaneMesh` with `uv_scale = (4, 4)` and look from above.
|
|
91
|
+
|
|
92
|
+
If you see a grid of identical "interest features" (a chip, a stain, a bright pixel) repeating, the tile has a hotspot — regenerate with stronger negative on "single feature."
|
|
93
|
+
|
|
94
|
+
If you see hard horizontal/vertical seams, the edges don't match — regenerate with extra emphasis on `seamless` or run the texture through a seamless-tile filter (Photoshop "Offset" + heal, GIMP "Make Seamless", or Aseprite's Tiled Mode).
|
|
95
|
+
|
|
96
|
+
### 6. Wire onto geometry
|
|
97
|
+
|
|
98
|
+
**On a PlaneMesh (floor/ceiling):**
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
summer_add_node(parentPath="/root/Level", type="MeshInstance3D", name="Floor")
|
|
102
|
+
summer_set_resource_property(nodePath="/root/Level/Floor", resourceProperty="mesh", value="<new PlaneMesh resource>")
|
|
103
|
+
summer_set_prop(path="/root/Level/Floor", property="mesh:size", value="Vector2(20, 20)")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Then create a `StandardMaterial3D`, set `albedo_texture` to the imported texture, and crank `uv1_scale` so each tile covers ~1m of world space:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
summer_set_resource_property(
|
|
110
|
+
nodePath="/root/Level/Floor",
|
|
111
|
+
resourceProperty="material_override",
|
|
112
|
+
subProperty="albedo_texture",
|
|
113
|
+
value="res://art/textures/brick_red.png"
|
|
114
|
+
)
|
|
115
|
+
summer_set_resource_property(
|
|
116
|
+
nodePath="/root/Level/Floor",
|
|
117
|
+
resourceProperty="material_override",
|
|
118
|
+
subProperty="uv1_scale",
|
|
119
|
+
value="Vector3(20, 20, 1)"
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`uv1_scale = (20, 20, 1)` on a 20m plane means the texture tiles 20× across — each tile covers 1m².
|
|
124
|
+
|
|
125
|
+
**On a CSGBox3D (walls):**
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
summer_add_node(parentPath="/root/Level", type="CSGBox3D", name="WallNorth")
|
|
129
|
+
summer_set_prop(path="/root/Level/WallNorth", property="size", value="Vector3(10, 3, 0.3)")
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Then attach the same material with `uv1_scale` tuned to wall dimensions.
|
|
133
|
+
|
|
134
|
+
## Prompt patterns
|
|
135
|
+
|
|
136
|
+
| Goal | Prompt that works | Why |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| Brick wall | `weathered red brick wall, seamless tileable texture, top-down view, uniform lighting, no perspective, no shadows, no specific objects, square, photographic` | Top-down + uniform lighting kill perspective seams |
|
|
139
|
+
| Grass ground | `dense fresh grass, seamless tileable texture, top-down view, uniform lighting, no shadows, no flowers, no patches, square` | "No flowers, no patches" kills hotspot features |
|
|
140
|
+
| Wood floor | `oak wood floor planks, seamless tileable, top-down view, uniform lighting, no perspective, no nails, no knots emphasized, square` | "No knots emphasized" kills the ONE bright knot per tile |
|
|
141
|
+
| Stone tiles | `cobblestone path, seamless tileable, top-down, uniform lighting, no shadows, no moss patches, square, photographic` | "No moss patches" kills hotspot |
|
|
142
|
+
| Metal panel | `industrial metal floor panel, seamless tileable, top-down, uniform lighting, no rust hotspots, no scratches concentrated, square` | Diffuse rust spreads across the tile instead of clumping |
|
|
143
|
+
| Sand / dirt | `dry desert sand, seamless tileable, top-down view, uniform soft lighting, no footprints, no rocks, no shadows, square` | Negative space is ideal for tiling |
|
|
144
|
+
| Stylized painterly grass | `stylized painterly grass, Studio Ghibli, seamless tileable, top-down, uniform lighting, no specific blades emphasized, square` (style: "none") | Style preset would fight the painterly direction |
|
|
145
|
+
| Sci-fi panel | `sci-fi metal floor panel with subtle glowing seams, seamless tileable, top-down, uniform lighting, square, the glowing seams form a regular grid that aligns with tile edges` | Make the seams part of the design |
|
|
146
|
+
|
|
147
|
+
### Bad prompts (and why)
|
|
148
|
+
|
|
149
|
+
| Bad | Failure mode |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `brick wall` | No "seamless," no "top-down." Returns a 3D-photographed wall with perspective and a corner. Useless for tiling. |
|
|
152
|
+
| `seamless brick wall in a dungeon at night` | Scene context bakes shadows and ambience that won't tile. |
|
|
153
|
+
| `tileable grass with flowers and rocks` | Hotspot features. Each tile has the SAME flower. Visible repeat. |
|
|
154
|
+
| `seamless wood floor (not specifying square / top-down)` | Often returns floor-from-eye-level with perspective. |
|
|
155
|
+
| `pbr wood floor texture` | "PBR" implies a material set (albedo + normal + roughness). The model only outputs albedo. Generate albedo, derive maps separately. |
|
|
156
|
+
|
|
157
|
+
## Anti-patterns
|
|
158
|
+
|
|
159
|
+
- **Skipping `Repeat: Enabled` on import.** Default is `Repeat: Disabled`. The texture stretches across the whole surface instead of tiling. Looks blurry at distance.
|
|
160
|
+
- **Not tuning `uv1_scale`.** Default scale of (1, 1, 1) on a 20m floor means the 1m-real texture is stretched to 20m. Always scale to physical sizing.
|
|
161
|
+
- **Hotspot features** that scream "repeated tile." Regenerate with stronger negative on single-feature words.
|
|
162
|
+
- **Generating PBR sets with one image.** Diffusion outputs albedo only. For normals/roughness, use a derivation tool or hand-author. Don't claim it's PBR-ready when it's not.
|
|
163
|
+
- **Forgetting mipmaps.** Tileable textures viewed at distance need mipmaps; without them, you get shimmering moire.
|
|
164
|
+
- **Using textures with directional shadow** baked in. Even subtle shadow stripes when tiled. Always demand "uniform lighting."
|
|
165
|
+
|
|
166
|
+
## Edge cases
|
|
167
|
+
|
|
168
|
+
- **User wants normal map / roughness / AO too.** Generation today produces albedo only. Use `Materialize` (free) or `MaterialMaker` (open source) to derive a normal from the albedo. Hand-paint roughness if the surface is heterogeneous (wood = low roughness on knots, high on grain). Set the user's expectation: AI gives albedo; PBR is a follow-up step.
|
|
169
|
+
- **Texture must tile in only one direction (e.g., a brick wall that runs horizontally but not vertically).** Generate 1024×1024 seamless, then crop to your actual aspect; the horizontal tile remains seamless. Or: prompt `tileable horizontally only, distinct top and bottom edges` for ceiling-to-floor walls.
|
|
170
|
+
- **Texture must read at very low resolution (mobile, distant LOD).** Generate at `square_hd`, downscale on import via `Compress: VRAM Compressed`. Avoid generating at low resolution — model quality drops.
|
|
171
|
+
- **User wants animated water / lava texture.** Generate a still tileable texture and use a `ShaderMaterial` with UV scrolling to animate. Don't try to generate frames.
|
|
172
|
+
- **Visible seam after generation.** Run through GIMP `Filters → Map → Make Seamless` or open in Aseprite, set Tiled mode, paint over the seam manually. AI-generated tileables often need a 5-minute touch-up.
|
|
173
|
+
|
|
174
|
+
## Fallback (no MCP)
|
|
175
|
+
|
|
176
|
+
Print the call:
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
summer_generate_image(
|
|
180
|
+
prompt="<material> seamless tileable texture, top-down view, uniform lighting, no perspective, no shadows, no specific objects, square",
|
|
181
|
+
model="nano-banana-2",
|
|
182
|
+
style="realistic",
|
|
183
|
+
options={ image_size: "square_hd", negative_prompt: "perspective, directional shadow, single feature, scene context" }
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Tell the user to run via the Summer dashboard, then `summer_import_from_url` to `res://art/textures/<name>.png`, set `Repeat: Enabled`, and tune `uv1_scale` to physical size.
|
|
188
|
+
|
|
189
|
+
If MCP is offline entirely: AmbientCG and Polyhaven offer free CC0 PBR texture sets that often beat AI for realism. For stylized, hand-author in Aseprite/Krita with tile-mode preview.
|
|
190
|
+
|
|
191
|
+
## Handoff
|
|
192
|
+
|
|
193
|
+
After the texture is wired:
|
|
194
|
+
|
|
195
|
+
- **More textures in the same biome** → re-invoke this skill, hold style/lighting consistent.
|
|
196
|
+
- **Apply to a procedurally-built level** → `summer:scene-composition` for CSG and modular wall kits.
|
|
197
|
+
- **PBR set with normals/roughness** → out of MCP scope today; user runs derivation in MaterialMaker.
|
|
198
|
+
- **Skybox for the level's environment** → `summer:2d-assets/skybox-panorama`.
|
|
199
|
+
|
|
200
|
+
## See also
|
|
201
|
+
|
|
202
|
+
- `summer:asset-pipeline/asset-strategy` — meta-router and 3D pipeline.
|
|
203
|
+
- `summer:2d-assets/skybox-panorama` — sky/environment counterpart.
|
|
204
|
+
- `summer:scene-composition` — applying textures to CSG and MeshInstance3D.
|
|
205
|
+
- `_shared/mcp-tools-reference.md` — `summer_generate_image` schema.
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ui-graphics
|
|
3
|
+
description: Use when generating UI elements — icons, buttons, panels, frames, HUD widgets, badges. Flat-design, transparent-background, game-UI style. Wires the result via TextureRect / NinePatchRect / AtlasTexture. Trigger on "UI icon", "button graphic", "HUD element", "panel frame", "menu background", "inventory slot", "ability icon", "badge".
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
|
+
category: 2d-assets
|
|
7
|
+
user-invocable: true
|
|
8
|
+
allowed-tools: Read Grep Glob Write Edit summer_generate_image summer_search_assets summer_import_from_url summer_set_resource_property summer_add_node summer_set_prop
|
|
9
|
+
paths: ["assets/**", "ui/**", "art/ui/**"]
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# ui-graphics — Icons, Buttons, Panels, HUD
|
|
13
|
+
|
|
14
|
+
This skill generates flat, game-UI-style graphics: icons (skill / item / status), buttons (idle / hover / pressed states), panels and frames (NinePatch-friendly), HUD widgets (health frames, minimaps, badges). Output is **transparent PNG** by default and wires via Godot's `TextureRect`, `NinePatchRect`, or `AtlasTexture`.
|
|
15
|
+
|
|
16
|
+
UI graphics succeed or fail on **two specific things**: a clean transparent background (no checkerboard residue) and a consistent visual language across the set (all icons share line weight, color treatment, lighting). This skill encodes both.
|
|
17
|
+
|
|
18
|
+
## When to use
|
|
19
|
+
|
|
20
|
+
- "Generate a fire-spell icon for the ability bar."
|
|
21
|
+
- "I need a parchment panel background for the inventory."
|
|
22
|
+
- "Make a set of 8 status-effect icons (poison, burn, freeze, stun, ...)."
|
|
23
|
+
- "Create a button frame I can NinePatch."
|
|
24
|
+
- "HUD frame for the health bar."
|
|
25
|
+
|
|
26
|
+
## When NOT to use
|
|
27
|
+
|
|
28
|
+
- The user wants a character portrait → `summer:2d-assets/character-portrait`.
|
|
29
|
+
- The user wants pixel-art UI → `summer:2d-assets/pixel-art` (UI in pixel style needs a different prompt pattern).
|
|
30
|
+
- The user wants a 3D HUD element → that's a 3D mesh job; route to `summer:asset-pipeline/asset-strategy`.
|
|
31
|
+
- The user wants a font → fonts aren't generated; use a `.ttf`/`.otf` and import via `FontFile`.
|
|
32
|
+
|
|
33
|
+
## Steps
|
|
34
|
+
|
|
35
|
+
### 1. Lock the UI style anchor
|
|
36
|
+
|
|
37
|
+
Check `.summer/ui-anchor.md`. If it doesn't exist, define it on the first UI asset and re-use:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
## UI anchor
|
|
41
|
+
|
|
42
|
+
style: flat design with subtle gradient, soft inner shadow
|
|
43
|
+
line: 2px outline in deep navy (#1a2332)
|
|
44
|
+
fill palette: gold (#d4a24c), parchment (#f5e6c4), dark teal accent (#2c5f5d)
|
|
45
|
+
shape language: rounded rectangles, no sharp 90deg corners
|
|
46
|
+
mood: warm fantasy, slightly weathered
|
|
47
|
+
background: transparent PNG
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Every icon / button / panel re-uses this anchor verbatim. Skipping this step produces the most common UI failure: 12 icons that all look like they came from 12 different games.
|
|
51
|
+
|
|
52
|
+
### 2. Search before generating
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
summer_search_assets(query="<subject> icon", filter={ kind: "image" })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. Pick the right pattern (icon vs button vs panel)
|
|
59
|
+
|
|
60
|
+
| Asset class | Image size | Wiring node | Notes |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| Icon (ability, item, status) | `square_hd` | `TextureRect` (or `AtlasTexture` if part of an icon sheet) | Centered subject, generous padding |
|
|
63
|
+
| Button (idle / hover / pressed) | `landscape_4_3` | `Button` with custom theme OR `TextureButton` | Generate 3 variants of the same shape |
|
|
64
|
+
| Panel / frame (NinePatch-friendly) | `square_hd` | `NinePatchRect` | Border + center MUST be visually separable for 9-slicing |
|
|
65
|
+
| HUD bar frame | `landscape_16_9` | `NinePatchRect` over `ProgressBar` | Frame only — bar fill is a separate gradient texture |
|
|
66
|
+
| Badge / emblem | `square_hd` | `TextureRect` | Symmetric, centered, no text |
|
|
67
|
+
|
|
68
|
+
### 4. Build the prompt — subject + anchor + transparent
|
|
69
|
+
|
|
70
|
+
Pattern:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
<asset class> of <subject>, game UI, <anchor style>, flat design, clean edges, transparent background, centered, isolated
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`transparent background` and `isolated` are the load-bearing words. Without them, you get a square card with a textured background that defeats the purpose.
|
|
77
|
+
|
|
78
|
+
### 5. Generate
|
|
79
|
+
|
|
80
|
+
**Icon example:**
|
|
81
|
+
```
|
|
82
|
+
summer_generate_image(
|
|
83
|
+
prompt="ability icon for a fire spell, glowing flame in cupped hand, game UI, flat design with subtle gradient and soft inner shadow, 2px deep navy outline, gold and parchment palette, rounded square frame, transparent background, centered, isolated",
|
|
84
|
+
model="nano-banana-2",
|
|
85
|
+
style="none",
|
|
86
|
+
options={ image_size: "square_hd", negative_prompt: "photorealistic, 3D render, scene background, busy, multiple objects" }
|
|
87
|
+
)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Button (3 states in 3 calls):**
|
|
91
|
+
```
|
|
92
|
+
summer_generate_image(prompt="<subject>, idle state, ...")
|
|
93
|
+
summer_generate_image(prompt="<subject>, hover state, slightly brighter glow, ...")
|
|
94
|
+
summer_generate_image(prompt="<subject>, pressed state, darker, slight inset shadow, ...")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Panel for NinePatch:**
|
|
98
|
+
```
|
|
99
|
+
summer_generate_image(
|
|
100
|
+
prompt="parchment scroll panel frame, ornate gold border, weathered tan center, clear distinction between border and center area, game UI, fantasy, transparent background, square format, centered",
|
|
101
|
+
...
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The "clear distinction between border and center" is the NinePatch hint — without it, the border bleeds into the center and 9-slicing produces artifacts.
|
|
106
|
+
|
|
107
|
+
### 6. Import with transparency preserved
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
summer_import_from_url(url="<fileUrl>", path="res://ui/icons/fire_spell.png")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Verify in the import dock: `Mipmaps: off` (UI shouldn't mipmap), `Filter: Linear` for high-res UI (or `Nearest` if pixel-style).
|
|
114
|
+
|
|
115
|
+
### 7. Wire into the scene
|
|
116
|
+
|
|
117
|
+
**Icon as TextureRect:**
|
|
118
|
+
```
|
|
119
|
+
summer_add_node(parentPath="/root/UI/AbilityBar", type="TextureRect", name="FireSpellIcon")
|
|
120
|
+
summer_set_prop(path="/root/UI/AbilityBar/FireSpellIcon", property="texture", value="res://ui/icons/fire_spell.png")
|
|
121
|
+
summer_set_prop(path="/root/UI/AbilityBar/FireSpellIcon", property="expand_mode", value=1) # KEEP_SIZE → 1 = STRETCH
|
|
122
|
+
summer_set_prop(path="/root/UI/AbilityBar/FireSpellIcon", property="stretch_mode", value=5) # KEEP_ASPECT_CENTERED
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Panel as NinePatchRect:**
|
|
126
|
+
```
|
|
127
|
+
summer_add_node(parentPath="/root/UI", type="NinePatchRect", name="InventoryPanel")
|
|
128
|
+
summer_set_prop(path="/root/UI/InventoryPanel", property="texture", value="res://ui/panels/parchment.png")
|
|
129
|
+
summer_set_prop(path="/root/UI/InventoryPanel", property="patch_margin_left", value=24)
|
|
130
|
+
summer_set_prop(path="/root/UI/InventoryPanel", property="patch_margin_right", value=24)
|
|
131
|
+
summer_set_prop(path="/root/UI/InventoryPanel", property="patch_margin_top", value=24)
|
|
132
|
+
summer_set_prop(path="/root/UI/InventoryPanel", property="patch_margin_bottom", value=24)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Tune patch margins to match the actual border width in the generated texture. Open the texture in the editor's NinePatch preview to verify.
|
|
136
|
+
|
|
137
|
+
**Multiple icons as AtlasTexture:**
|
|
138
|
+
|
|
139
|
+
If you generate a 4×4 grid of icons in one image, each icon becomes an `AtlasTexture` referencing the same source. Saves draw calls. Use a `Region` rect per icon.
|
|
140
|
+
|
|
141
|
+
## Prompt patterns
|
|
142
|
+
|
|
143
|
+
| Goal | Prompt that works | Why |
|
|
144
|
+
|---|---|---|
|
|
145
|
+
| Ability icon | `ability icon for <effect>, <visual metaphor>, game UI, flat design, 2px outline, <palette>, rounded square frame, transparent background, centered, isolated` | Visual metaphor (cupped hand, swirling vortex) reads better than abstract |
|
|
146
|
+
| Item icon (potion) | `inventory icon of red health potion, glass bottle with red liquid, cork stopper, game UI, flat design, soft inner shadow, transparent background, centered, isolated, three-quarter view` | Three-quarter beats pure front for items |
|
|
147
|
+
| Status icon (poison) | `status effect icon, green skull with dripping liquid, game UI, flat, bold silhouette readable at 32px, 2px outline, transparent background` | "Readable at 32px" forces bold silhouette |
|
|
148
|
+
| Button frame | `wooden button frame, ornate corners, slight bevel, game UI fantasy, transparent background, no text, no icon inside, just the empty frame` | "No text, no icon" prevents the model adding fake labels |
|
|
149
|
+
| NinePatch panel | `parchment panel frame, ornate gold border, weathered tan center, clear border-vs-center distinction, transparent background, square` | "Clear border-vs-center" enables 9-slicing |
|
|
150
|
+
| Badge / rank emblem | `gold rank emblem, laurel wreath, central star, symmetric, game UI heraldry style, transparent background, centered` | Symmetry + centered is critical for emblems |
|
|
151
|
+
| HUD health frame | `decorative frame for a horizontal health bar, ornate metal border, hollow center for the bar to show through, transparent background, landscape format` | "Hollow center" is the key for frame-over-bar |
|
|
152
|
+
|
|
153
|
+
### Bad prompts (and why)
|
|
154
|
+
|
|
155
|
+
| Bad | Failure mode |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `cool button` | No subject, no anchor. Returns a generic button on a card background. |
|
|
158
|
+
| `transparent button with icon` (no negative prompt) | Model often renders a checkerboard "transparent" pattern as the actual fill. Add `no checkerboard pattern` to negative. |
|
|
159
|
+
| `8 ability icons in one image` | Inconsistent style across the 8. Generate one at a time with the same anchor. |
|
|
160
|
+
| `realistic 3D rendered button` | Conflicts with flat-UI. Stay flat. |
|
|
161
|
+
| `button with the word "Play"` on it | Models render text badly. Add text in Godot via a `Label` over the button, not in the texture. |
|
|
162
|
+
|
|
163
|
+
## Anti-patterns
|
|
164
|
+
|
|
165
|
+
- **Skipping the anchor.** A 12-icon ability bar with no anchor looks like 12 unrelated games. Define the anchor on icon #1.
|
|
166
|
+
- **Letting the model render text.** Diffusion models can't render reliable text. Always overlay text in Godot via a `Label` node. The button texture is the frame; the label is the word.
|
|
167
|
+
- **Forgetting `transparent background` in the prompt.** Default is opaque. Without the keyword, you import an icon with a 200×200 white square around the actual icon.
|
|
168
|
+
- **Using `style: "realistic"` for UI.** UI is flat. `style: "none"` lets the prompt's "flat design" land cleanly.
|
|
169
|
+
- **NinePatch with no border-vs-center distinction.** The 9-slice scaling smears the border into the center.
|
|
170
|
+
- **Mipmaps on UI.** UI textures shouldn't mipmap — they're displayed at 1:1 or near it. Mipmaps waste memory and blur sharp edges.
|
|
171
|
+
|
|
172
|
+
## Edge cases
|
|
173
|
+
|
|
174
|
+
- **User wants the same icon at multiple sizes (32, 64, 128).** Generate once at high res. Godot's `TextureRect` with `STRETCH_KEEP_ASPECT_CENTERED` scales it down cleanly. Don't generate three sizes.
|
|
175
|
+
- **User wants pixel-style UI.** Route to `summer:2d-assets/pixel-art` — different prompt pattern, different filter, different anchor.
|
|
176
|
+
- **User wants animated UI (spinning loading icon).** Generate the static frame here. Animate via `AnimationPlayer` rotating the `TextureRect`, not as a sprite sheet.
|
|
177
|
+
- **Transparency comes back as a checkerboard pattern in the image.** The model rendered the checkerboard literally. Regenerate with `no checkerboard pattern, true alpha transparency` in the negative prompt.
|
|
178
|
+
- **Icons need to read at very small size (16-24px in a packed bar).** Bias prompts toward bold silhouette + minimal interior detail. Ornate detail is invisible at 16px and adds noise.
|
|
179
|
+
|
|
180
|
+
## Fallback (no MCP)
|
|
181
|
+
|
|
182
|
+
Print the call:
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
summer_generate_image(
|
|
186
|
+
prompt="<asset + anchor + transparent>",
|
|
187
|
+
model="nano-banana-2",
|
|
188
|
+
style="none",
|
|
189
|
+
options={ image_size: "square_hd", negative_prompt: "scene background, photorealistic, 3D, busy" }
|
|
190
|
+
)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
User runs via the Summer dashboard, then `summer_import_from_url` to `res://ui/icons/<name>.png` and wires manually.
|
|
194
|
+
|
|
195
|
+
## Handoff
|
|
196
|
+
|
|
197
|
+
After the UI graphic is wired:
|
|
198
|
+
|
|
199
|
+
- **More icons in the same set** → re-invoke this skill with the same anchor.
|
|
200
|
+
- **Button states (hover/pressed)** → re-invoke for each state.
|
|
201
|
+
- **Theme assembly (combining icons + panels into a Godot Theme resource)** → `summer:scene-composition` for the Theme resource wiring.
|
|
202
|
+
- **Pixel-art UI** → `summer:2d-assets/pixel-art`.
|
|
203
|
+
- **Dialogue UI with portraits** → `summer:2d-assets/character-portrait` for the portrait, then back here for the surrounding panel.
|
|
204
|
+
|
|
205
|
+
## See also
|
|
206
|
+
|
|
207
|
+
- `summer:2d-assets/character-portrait` — for in-UI character images.
|
|
208
|
+
- `summer:2d-assets/pixel-art` — pixel-style UI.
|
|
209
|
+
- `summer:scene-composition` — Theme and Control hierarchy.
|
|
210
|
+
- `_shared/mcp-tools-reference.md` — `summer_generate_image` schema.
|