summer-engine 2.6.6 → 2.8.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +4 -1
- package/.codex-plugin/plugin.json +6 -2
- package/.cursor-plugin/plugin.json +5 -1
- package/.opencode/INSTALL.md +1 -1
- package/.opencode/plugins/summer.js +2 -2
- package/AGENTS.md +11 -7
- package/CHANGELOG.md +40 -0
- package/GEMINI.md +9 -7
- package/README.md +63 -21
- package/_persona/summer/SKILL.md +1 -0
- package/assets/autopilot/README.md +51 -0
- package/assets/autopilot/autopilot.gd +222 -0
- package/assets/autopilot/probe_base.gd +262 -0
- package/assets/autopilot/run.sh +78 -0
- package/commands/gameskill.md +11 -2
- package/commands/summer.md +13 -0
- package/dist/bin/summer.js +12 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +53 -0
- package/dist/commands/create.d.ts +1 -0
- package/dist/commands/create.js +38 -6
- package/dist/commands/debug.d.ts +2 -0
- package/dist/commands/debug.js +44 -0
- package/dist/commands/doctor.js +112 -8
- package/dist/commands/list.js +1 -1
- package/dist/commands/login.d.ts +19 -0
- package/dist/commands/login.js +123 -36
- package/dist/commands/logout.js +3 -16
- package/dist/commands/logs.d.ts +2 -0
- package/dist/commands/logs.js +19 -0
- package/dist/commands/mcp.js +7 -2
- package/dist/commands/open.js +1 -1
- package/dist/commands/publish.d.ts +2 -0
- package/dist/commands/publish.js +20 -0
- package/dist/commands/releases.d.ts +2 -0
- package/dist/commands/releases.js +20 -0
- package/dist/commands/run.js +1 -1
- package/dist/commands/skills.js +1 -1
- package/dist/lib/api-client.d.ts +15 -4
- package/dist/lib/api-client.js +138 -13
- package/dist/lib/async-op-lifecycle.d.ts +7 -2
- package/dist/lib/async-op-lifecycle.js +32 -9
- package/dist/lib/auth.d.ts +40 -12
- package/dist/lib/auth.js +173 -37
- package/dist/lib/cloud/engine-bridge.d.ts +17 -4
- package/dist/lib/cloud/engine-bridge.js +32 -6
- package/dist/lib/config.d.ts +20 -0
- package/dist/lib/config.js +142 -0
- package/dist/lib/creator.d.ts +93 -0
- package/dist/lib/creator.js +393 -0
- package/dist/lib/debug-report.d.ts +50 -0
- package/dist/lib/debug-report.js +308 -0
- package/dist/lib/engine.d.ts +35 -2
- package/dist/lib/engine.js +240 -6
- package/dist/lib/game-task-plan.js +4 -4
- package/dist/lib/mcp-boot-notice.d.ts +3 -0
- package/dist/lib/mcp-boot-notice.js +7 -0
- package/dist/lib/mcp-log.d.ts +3 -0
- package/dist/lib/mcp-log.js +72 -0
- package/dist/lib/public-surface-paths.d.ts +13 -0
- package/dist/lib/public-surface-paths.js +42 -0
- package/dist/lib/skills-registry.d.ts +33 -1
- package/dist/lib/skills-registry.js +55 -0
- package/dist/lib/store.d.ts +14 -0
- package/dist/lib/store.js +145 -0
- package/dist/lib/summer-compatibility.d.ts +6 -0
- package/dist/lib/summer-compatibility.js +22 -0
- package/dist/mcp/server.d.ts +10 -3
- package/dist/mcp/server.js +104 -11
- package/dist/mcp/tools/asset-tools.js +33 -12
- package/dist/mcp/tools/cloud-tools.js +15 -15
- package/dist/mcp/tools/creator-tools.d.ts +2 -0
- package/dist/mcp/tools/creator-tools.js +105 -0
- package/dist/mcp/tools/debug-tools.js +44 -1
- package/dist/mcp/tools/file-tools.d.ts +2 -0
- package/dist/mcp/tools/file-tools.js +154 -0
- package/dist/mcp/tools/generate-tools.js +159 -11
- package/dist/mcp/tools/project-tools.js +37 -27
- package/dist/mcp/tools/scene-tools.js +106 -29
- package/dist/mcp/tools/visual-tools.js +4 -3
- package/dist/mcp/tools/with-engine.js +4 -4
- package/hooks/session-start.sh +5 -5
- package/package.json +3 -1
- package/references/collaborative-protocol.md +50 -0
- package/references/gd-style.md +121 -0
- package/references/godot-version.md +51 -0
- package/references/mcp-tools-reference.md +199 -0
- package/references/public-surface-language.md +30 -0
- package/references/summer-folder.md +90 -0
- package/references/template-registry.md +73 -0
- package/skills/2d-assets/character-portrait/SKILL.md +17 -12
- package/skills/2d-assets/concept-art/SKILL.md +10 -9
- package/skills/2d-assets/create-asset-sheet/SKILL.md +17 -15
- package/skills/2d-assets/pixel-art/SKILL.md +36 -20
- package/skills/2d-assets/skybox-panorama/SKILL.md +32 -37
- package/skills/2d-assets/sprite-sheet/SKILL.md +40 -35
- package/skills/2d-assets/tileable-texture/SKILL.md +28 -22
- package/skills/2d-assets/ui-graphics/SKILL.md +46 -32
- package/skills/2d-assets/use-widget-asset/SKILL.md +8 -6
- package/skills/3d-assets/character-model/SKILL.md +34 -19
- package/skills/3d-assets/environment-kit/SKILL.md +11 -5
- package/skills/3d-assets/organic-model/SKILL.md +8 -5
- package/skills/3d-assets/prop-model/SKILL.md +9 -3
- package/skills/3d-assets/vehicle-model/SKILL.md +32 -19
- package/skills/README.md +1 -1
- package/skills/ai-and-npcs/design-npc/SKILL.md +31 -13
- package/skills/animation/animation-tree/SKILL.md +39 -15
- package/skills/animation/facial-and-lipsync/SKILL.md +25 -8
- package/skills/animation/generate-motion/SKILL.md +47 -15
- package/skills/animation/procedural-animation/SKILL.md +31 -13
- package/skills/animation/retarget/SKILL.md +127 -79
- package/skills/audio/adaptive-music/SKILL.md +24 -20
- package/skills/audio/ambient-bed/SKILL.md +22 -16
- package/skills/audio/audio-direction/SKILL.md +15 -10
- package/skills/audio/music-track/SKILL.md +18 -12
- package/skills/audio/sound-effect/SKILL.md +17 -12
- package/skills/audio/voice-line/SKILL.md +42 -42
- package/skills/character-controllers/fps-controller/SKILL.md +26 -16
- package/skills/debugging/debug/SKILL.md +74 -20
- package/skills/deployment/export-and-ship/SKILL.md +105 -38
- package/skills/deployment/remote-deploy/SKILL.md +140 -0
- package/skills/gameplay-mechanics/auto-fire-targeting/SKILL.md +26 -1
- package/skills/gameplay-mechanics/design-mechanic/SKILL.md +23 -15
- package/skills/level-design/design-level/SKILL.md +22 -8
- package/skills/level-design/scene-to-level/SKILL.md +13 -7
- package/skills/multiplayer-and-networking/host-authoritative-state/SKILL.md +8 -8
- package/skills/multiplayer-and-networking/peer-to-peer-multiplayer/SKILL.md +2 -7
- package/skills/multiplayer-and-networking/setup-multiplayer/SKILL.md +26 -18
- package/skills/performance/tune-performance/SKILL.md +51 -32
- package/skills/rendering-and-lighting/3d-lighting/SKILL.md +34 -5
- package/skills/rendering-and-lighting/art-direction/SKILL.md +6 -8
- package/skills/scene-and-project/brainstorm-game/SKILL.md +7 -9
- package/skills/scene-and-project/make-game/SKILL.md +2 -1
- package/skills/scene-and-project/play/SKILL.md +10 -4
- package/skills/scene-and-project/scene-composition/SKILL.md +21 -8
- package/skills/scene-and-project/summer-cloud/SKILL.md +92 -0
- package/skills/scripting-patterns/gdscript-patterns/SKILL.md +1 -1
- package/skills/ui-and-ux/ui-basics/SKILL.md +16 -7
- package/skills/video/animated-loop/SKILL.md +63 -39
- package/skills/video/cinematic-cutscene/SKILL.md +66 -30
- package/skills/video/trailer-shot/SKILL.md +30 -21
- package/skills/visual-effects/_building-blocks/additive-billboard-particles.md +25 -16
- package/skills/visual-effects/_building-blocks/trauma-shake-snippet.md +5 -3
- package/skills/visual-effects/game-feel/SKILL.md +51 -33
- package/skills/visual-effects/recipes/dissolve/SKILL.md +51 -9
- package/skills/visual-effects/recipes/fire/SKILL.md +136 -49
- package/skills/visual-effects/recipes/hit-spark/SKILL.md +45 -8
- package/skills/visual-effects/recipes/lightning/SKILL.md +59 -27
- package/skills/visual-effects/recipes/magic-glow/SKILL.md +59 -26
- package/skills/visual-effects/recipes/muzzle-flash/SKILL.md +68 -25
- package/skills/visual-effects/recipes/smoke/SKILL.md +89 -28
- package/skills/visual-effects/recipes/water-ripple/SKILL.md +83 -23
- package/skills/workflow/brainstorming/SKILL.md +1 -1
- package/skills/workflow/debugging-game-feel/SKILL.md +29 -9
- package/skills/workflow/diagnosing-perf-regressions/SKILL.md +46 -21
- package/skills/workflow/gameskill/SKILL.md +11 -2
- package/skills/workflow/headless-scripting/SKILL.md +407 -0
- package/skills/workflow/investigating-bugs/SKILL.md +4 -2
- package/skills/workflow/mcpupdate/SKILL.md +9 -9
- package/skills/workflow/playtesting-a-feature/SKILL.md +94 -21
- package/skills/workflow/skill-create/SKILL.md +7 -7
- package/skills/workflow/skill-test/SKILL.md +3 -3
- package/skills/workflow/using-summer/SKILL.md +32 -3
- package/skills/workflow/verification-before-completion/SKILL.md +2 -0
- package/skills/workflow/writing-plans/SKILL.md +7 -7
- package/skills/workflow/writing-skills/SKILL.md +7 -5
- package/skills/workflow/writing-skills/testing-skills-with-subagents.md +1 -1
|
@@ -13,7 +13,15 @@ paths: ["assets/**", "art/pixel/**", "sprites/**"]
|
|
|
13
13
|
|
|
14
14
|
This skill generates pixel-art assets — sprites, items, tiles, icons, portraits — at a target resolution (32×32, 64×64, 128×128, etc.). Pixel art has hard constraints (grid alignment, limited palette, no anti-aliased edges) that diffusion models violate by default. This skill encodes the prompt patterns and post-processing discipline that makes the output actually look like pixel art and not "blurry small image."
|
|
15
15
|
|
|
16
|
-
**Backing tool:** `summer_generate_image` with
|
|
16
|
+
**Backing tool:** `summer_generate_image` with an explicit pixel-art prompt.
|
|
17
|
+
|
|
18
|
+
Two things about that tool you have to know before writing a call, because both silently do nothing:
|
|
19
|
+
|
|
20
|
+
- **There is no `"pixel"` style preset.** `style` accepts exactly `realistic`, `cartoon`, `anime`, `none`; anything else is coerced to `none`. Only `cartoon` and `anime` do anything at all (they append a short suffix); `realistic` and `none` append nothing. So `style: "pixel"` is identical to `style: "none"` — the pixel look has to come entirely from the prompt. Use `style: "none"` and say so honestly.
|
|
21
|
+
- **`options` is not a general passthrough.** The MCP tool forwards `options` to the server, which only recognizes Nano Banana provider keys: `seed`, `outputFormat`, `safetyTolerance`, `syncMode`, `systemPrompt`, `limitGenerations`, `thinkingLevel`. `image_size` and `negative_prompt` are not among them and are dropped without an error. There is no size or aspect-ratio argument on this tool at all — MCP images come back at the server's 1:1 default. Put framing and exclusions in the prompt text instead.
|
|
22
|
+
|
|
23
|
+
Pixel-perfect output is enforced in Summer Engine with Nearest texture filtering
|
|
24
|
+
and by downscaling to the target resolution after generation.
|
|
17
25
|
|
|
18
26
|
## When to use
|
|
19
27
|
|
|
@@ -54,7 +62,7 @@ shading: 3-tone (light, mid, shadow), no gradients, no AA
|
|
|
54
62
|
### 2. Search for existing assets
|
|
55
63
|
|
|
56
64
|
```
|
|
57
|
-
summer_search_assets(query="<subject> pixel",
|
|
65
|
+
summer_search_assets(query="<subject> pixel", assetType="2d_image", source="all")
|
|
58
66
|
```
|
|
59
67
|
|
|
60
68
|
### 3. Build the prompt
|
|
@@ -71,17 +79,17 @@ The model can't actually generate at 32×32 — it generates at 1024×1024 with
|
|
|
71
79
|
|
|
72
80
|
```
|
|
73
81
|
summer_generate_image(
|
|
74
|
-
prompt="pixel art slime monster, 32x32 sprite, PICO-8 palette, hard 1px outline in palette's darkest color, 3-tone shading, no anti-aliasing, no blur, sharp pixel edges,
|
|
82
|
+
prompt="pixel art slime monster, 32x32 sprite, PICO-8 palette, hard 1px outline in palette's darkest color, 3-tone shading, no anti-aliasing, no blur, sharp pixel edges, front-facing. Not blurry, no smooth gradients, no soft edges, not photorealistic, no 3D render.",
|
|
75
83
|
model="nano-banana-2",
|
|
76
|
-
style="
|
|
77
|
-
options={
|
|
78
|
-
image_size: "square_hd",
|
|
79
|
-
negative_prompt: "blurry, smooth gradients, anti-aliasing, photorealistic, 3D render, soft edges"
|
|
80
|
-
}
|
|
84
|
+
style="none",
|
|
85
|
+
options={ removeBackground: true }
|
|
81
86
|
)
|
|
82
87
|
```
|
|
83
88
|
|
|
84
|
-
|
|
89
|
+
Two deliberate choices there:
|
|
90
|
+
|
|
91
|
+
- **The negations live in the prompt.** There is no `negative_prompt` argument — putting one in `options` is dropped silently. Diffusion models honor in-prompt negations less reliably than a real negative-prompt field, so state them as plain sentences at the end and expect to regenerate more often than you would on a provider UI that exposes the field.
|
|
92
|
+
- **`options.removeBackground: true` is real** and is the only `options` key in this skill that does anything: it runs a real background-removal pass after generation and returns a PNG with true alpha. Prefer it over asking for "transparent background" in the prompt, which is what makes models paint a literal checkerboard.
|
|
85
93
|
|
|
86
94
|
### 5. Downscale to target resolution
|
|
87
95
|
|
|
@@ -89,7 +97,9 @@ The generated image is 1024×1024 pixel-style. To get true crisp pixels at 32×3
|
|
|
89
97
|
|
|
90
98
|
- Import to the engine, then in the import dock set `Filter: Nearest` (no smoothing).
|
|
91
99
|
- For a true 32×32 atlas/icon, downscale in an external editor (Aseprite, GIMP "nearest neighbor") to 32×32 before importing. Aseprite's "Sprite > Sprite Size" with Nearest gives the cleanest result.
|
|
92
|
-
- In
|
|
100
|
+
- In Summer Engine, set `Project Settings → Rendering → Textures → Default
|
|
101
|
+
Texture Filter: Nearest` if the entire game is pixel art. This disables
|
|
102
|
+
bilinear smoothing project-wide.
|
|
93
103
|
|
|
94
104
|
### 6. Import and wire
|
|
95
105
|
|
|
@@ -100,13 +110,16 @@ summer_import_from_url(url="<fileUrl>", path="res://sprites/slime.png")
|
|
|
100
110
|
For a `Sprite2D`:
|
|
101
111
|
|
|
102
112
|
```
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
summer_set_prop(
|
|
114
|
+
scenePath="res://main.tscn",
|
|
115
|
+
path="./Slime/Sprite2D",
|
|
116
|
+
key="texture",
|
|
106
117
|
value="res://sprites/slime.png"
|
|
107
118
|
)
|
|
108
119
|
```
|
|
109
120
|
|
|
121
|
+
`texture` is a property **on the node**, so it is `summer_set_prop`. `summer_set_resource_property` is for reaching *inside* a resource the node already holds (mesh size, material albedo) and needs all five of `scenePath`, `nodePath`, `resourceProperty`, `subProperty`, `value` — there is no two-argument form.
|
|
122
|
+
|
|
110
123
|
Confirm `Filter: Nearest` is set in the import dock OR project-wide.
|
|
111
124
|
|
|
112
125
|
## Prompt patterns
|
|
@@ -126,15 +139,16 @@ Confirm `Filter: Nearest` is set in the import dock OR project-wide.
|
|
|
126
139
|
|---|---|
|
|
127
140
|
| `8-bit sword` | "8-bit" is interpreted loosely. Returns a smooth render of a sword with vague pixel feel. Specify resolution + palette + "no AA" explicitly. |
|
|
128
141
|
| `pixel art knight, photorealistic` | Conflicting directives. Model averages and gives you neither. |
|
|
129
|
-
| `pixel art at 32x32`
|
|
142
|
+
| `pixel art at 32x32` with no negations | Model adds soft edges and gradient shading. Always spell out "no anti-aliasing, no blur, no smooth gradients" in the prompt itself — there is no negative-prompt argument to fall back on. |
|
|
130
143
|
| `pixel sprite walk cycle` | Walk cycles need consistent frames — single-prompt sprite sheets fail. Route to `summer:2d-assets/sprite-sheet`. |
|
|
131
144
|
| `cute pixel art` | "Cute" without subject is undefined. Specify what. |
|
|
132
145
|
|
|
133
146
|
## Anti-patterns
|
|
134
147
|
|
|
135
148
|
- **Skipping the downscale.** The model returns a 1024×1024 pixel-style image. If you import that as a 1024 texture, the "pixels" are actually 32-pixel blocks of soft color. Downscale to true target resolution OR set `Filter: Nearest` so the up-rendering doesn't smooth.
|
|
136
|
-
- **No `Filter: Nearest`.**
|
|
137
|
-
|
|
149
|
+
- **No `Filter: Nearest`.** The default texture filtering is bilinear. Set
|
|
150
|
+
Nearest on import or project-wide for pixel art.
|
|
151
|
+
- **Reaching for `negative_prompt` or `image_size`.** Neither exists on this tool; both are dropped without an error, so the call looks like it worked and the output is off-style. Negations go in the prompt text; size is fixed.
|
|
138
152
|
- **Inconsistent palette across the cast.** Pick a named palette (PICO-8, NES, custom hex list) and re-use across every asset in the project. Different palettes = the project doesn't read as one game.
|
|
139
153
|
- **Generating walk-cycle frames as one image.** Sprite sheets via single-prompt are unreliable. Route to `summer:2d-assets/sprite-sheet`.
|
|
140
154
|
|
|
@@ -152,13 +166,15 @@ Print the call:
|
|
|
152
166
|
|
|
153
167
|
```
|
|
154
168
|
summer_generate_image(
|
|
155
|
-
prompt="<pixel art prompt with full anchor
|
|
169
|
+
prompt="<pixel art prompt with full anchor>. Not blurry, no smooth gradients, no anti-aliasing.",
|
|
156
170
|
model="nano-banana-2",
|
|
157
|
-
style="
|
|
158
|
-
options={
|
|
171
|
+
style="none",
|
|
172
|
+
options={ removeBackground: true }
|
|
159
173
|
)
|
|
160
174
|
```
|
|
161
175
|
|
|
176
|
+
The Summer dashboard *does* expose size and negative-prompt controls that the MCP tool does not — if the user is running it there, tell them to set square + a real negative prompt.
|
|
177
|
+
|
|
162
178
|
Tell the user to run via the Summer dashboard, downscale in Aseprite/GIMP to true target resolution with nearest-neighbor, then `summer_import_from_url` (or drop into `res://sprites/`) and set `Filter: Nearest`.
|
|
163
179
|
|
|
164
180
|
If MCP is offline entirely: open Aseprite or Piskel and hand-author the asset. For pixel art at small resolutions, hand-authoring is often faster than fixing a generation.
|
|
@@ -177,4 +193,4 @@ After the asset is wired:
|
|
|
177
193
|
- `summer:2d-assets/sprite-sheet` — animated pixel frames.
|
|
178
194
|
- `summer:2d-assets/character-portrait` — high-res counterpart.
|
|
179
195
|
- `summer:asset-pipeline/asset-strategy` — meta-router.
|
|
180
|
-
-
|
|
196
|
+
- `../../../references/mcp-tools-reference.md` — `summer_generate_image` schema.
|
|
@@ -11,7 +11,10 @@ paths: ["assets/**", "art/sky/**", "environments/**"]
|
|
|
11
11
|
|
|
12
12
|
# skybox-panorama — 360° Sky for WorldEnvironment
|
|
13
13
|
|
|
14
|
-
This skill generates a single equirectangular panoramic image (2:1 aspect,
|
|
14
|
+
This skill generates a single equirectangular panoramic image (2:1 aspect,
|
|
15
|
+
e.g. 2048×1024 or 4096×2048) suitable for Summer Engine's
|
|
16
|
+
`PanoramaSkyMaterial`. It wires the image into a `Sky` resource on a
|
|
17
|
+
`WorldEnvironment` node so the sky is visible from every camera angle.
|
|
15
18
|
|
|
16
19
|
The single biggest failure mode is **non-equirectangular output**. Diffusion models default to flat 2D scenes; if you don't explicitly demand "equirectangular projection," the result looks fine in a thumbnail but distorts brutally when wrapped onto a sphere — horizon bows, zenith pinches, the sun stretches into a smear. This skill encodes the prompt suffix and the import discipline that produces a usable sky on the first or second try.
|
|
17
20
|
|
|
@@ -35,7 +38,7 @@ The single biggest failure mode is **non-equirectangular output**. Diffusion mod
|
|
|
35
38
|
### 1. Search for an existing sky
|
|
36
39
|
|
|
37
40
|
```
|
|
38
|
-
summer_search_assets(query="<vibe> sky panorama",
|
|
41
|
+
summer_search_assets(query="<vibe> sky panorama", assetType="2d_image", source="all")
|
|
39
42
|
```
|
|
40
43
|
|
|
41
44
|
Polyhaven (`polyhaven.com/hdris`) hosts hundreds of free CC0 HDRIs that beat AI generation for realism and provide IBL data. For realistic exterior scenes, prefer Polyhaven; for stylized / fantasy / sci-fi, AI generation wins.
|
|
@@ -55,22 +58,25 @@ Load-bearing phrases:
|
|
|
55
58
|
- **`no foreground objects, no ground horizon line`** — skies show only sky. If you include a horizon, it warps weirdly when sphere-mapped and kills the illusion that the sky is at infinite distance.
|
|
56
59
|
- **`distortion-correct for sphere mapping`** — reminds the model that the top/bottom of the image map to the zenith/nadir.
|
|
57
60
|
|
|
58
|
-
### 3. Generate
|
|
61
|
+
### 3. Generate, then fix the aspect yourself
|
|
62
|
+
|
|
63
|
+
Equirectangular MUST be 2:1 (width = 2× height). **`summer_generate_image` cannot give you that.** The tool takes only `prompt`, `model`, `style`, `referenceImageUrl`, and `options` — there is no aspect or size argument, so every MCP image comes back at the server's 1:1 default. `aspectRatio` and `image_size` inside `options` are not recognized and are dropped without an error; the underlying provider does support 2:1-class aspect ratios, but nothing on this surface lets you request one.
|
|
59
64
|
|
|
60
65
|
```
|
|
61
66
|
summer_generate_image(
|
|
62
|
-
prompt="dramatic fantasy sky, golden hour, large purple-orange clouds, distant mountains silhouetted at very bottom, soft god-rays, 360 degree panoramic equirectangular projection, seamless horizontal wrap, no visible seam, no foreground objects, sky only",
|
|
67
|
+
prompt="dramatic fantasy sky, golden hour, large purple-orange clouds, distant mountains silhouetted at very bottom, soft god-rays, 360 degree panoramic equirectangular projection, wide 2:1 panoramic framing, seamless horizontal wrap, no visible seam, no foreground objects, sky only. No vertical seam, no ground objects, no horizon-level detail, not distorted or warped, no characters, no buildings.",
|
|
63
68
|
model="nano-banana-2",
|
|
64
|
-
style="realistic"
|
|
65
|
-
options={
|
|
66
|
-
aspectRatio: "2:1",
|
|
67
|
-
image_size: "landscape_16_9",
|
|
68
|
-
negative_prompt: "vertical seam, ground objects, horizon-level details, distorted, warped, characters, buildings"
|
|
69
|
-
}
|
|
69
|
+
style="realistic"
|
|
70
70
|
)
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
Asking for "2:1 panoramic framing" in the prompt biases the composition; it does not change the returned pixel dimensions. So one of these has to happen before the image is usable as a panorama:
|
|
74
|
+
|
|
75
|
+
- **Generate in the Summer dashboard instead**, which does expose aspect ratio, and bring the 2:1 result back with `summer_import_from_url`. This is the right path when the sky matters.
|
|
76
|
+
- **Or crop the 1:1 result to 2:1** in any image editor before importing. You lose the top and bottom, which is usually acceptable for sky-only content — the zenith and nadir are the least informative regions — but it will clip a sun placed high in frame.
|
|
77
|
+
- **Or use a Polyhaven HDRI**, already 2:1 and better for realistic exteriors.
|
|
78
|
+
|
|
79
|
+
Do not import a 1:1 image as a `PanoramaSkyMaterial` panorama and call it done — it wraps with obvious horizontal compression.
|
|
74
80
|
|
|
75
81
|
### 4. Verify the seam and projection
|
|
76
82
|
|
|
@@ -97,38 +103,28 @@ In the import dock:
|
|
|
97
103
|
|
|
98
104
|
### 6. Wire into WorldEnvironment (3 lines)
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
summer_add_node(parentPath="/root/Game", type="WorldEnvironment", name="WorldEnvironment")
|
|
106
|
+
This is not three tool calls. `summer_set_resource_property` reaches exactly **one** level into a resource — it takes `scenePath`, `nodePath`, `resourceProperty`, `subProperty`, `value`, and there is no `"a:b:c"` colon-path form for walking Environment → Sky → SkyMaterial. Write the `Environment` (with its `Sky` and `PanoramaSkyMaterial` as sub-resources) as a `.tres`, then attach it in one property set:
|
|
102
107
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
```
|
|
109
|
+
summer_write_file(
|
|
110
|
+
path="res://environments/fantasy_sunset.tres",
|
|
111
|
+
content="<Environment .tres: background_mode = 2 (BG_SKY), sky = Sky with a PanoramaSkyMaterial whose panorama is res://art/sky/fantasy_sunset.png, ambient_light_source = 3 (AMBIENT_SOURCE_SKY) if you want IBL>",
|
|
112
|
+
create_only=true
|
|
107
113
|
)
|
|
108
114
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
value="<new PanoramaSkyMaterial with panorama: res://art/sky/fantasy_sunset.png>"
|
|
113
|
-
)
|
|
115
|
+
summer_add_node(scenePath="res://main.tscn", parent=".", type="WorldEnvironment", name="WorldEnvironment")
|
|
116
|
+
summer_set_prop(scenePath="res://main.tscn", path="./WorldEnvironment", key="environment", value="res://environments/fantasy_sunset.tres")
|
|
117
|
+
summer_save_scene(scenePath="res://main.tscn")
|
|
114
118
|
```
|
|
115
119
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
```
|
|
119
|
-
summer_set_resource_property(
|
|
120
|
-
nodePath="/root/Game/WorldEnvironment",
|
|
121
|
-
resourceProperty="environment:ambient_light_source",
|
|
122
|
-
value=3 # AMBIENT_SOURCE_SKY
|
|
123
|
-
)
|
|
124
|
-
```
|
|
120
|
+
Every scene-mutating tool takes an explicit `scenePath`; node paths are relative to that scene's root (`./`), not absolute `/root/...` runtime paths.
|
|
125
121
|
|
|
126
122
|
Note: AI-generated panoramas are LDR (8-bit per channel). For physically-correct IBL with bright suns, the lighting is muted compared to true HDRI. Mention this to the user if they expect strong IBL.
|
|
127
123
|
|
|
128
124
|
### 7. Verify in scene
|
|
129
125
|
|
|
130
126
|
```
|
|
131
|
-
summer_inspect_node(path="
|
|
127
|
+
summer_inspect_node(path="WorldEnvironment")
|
|
132
128
|
```
|
|
133
129
|
|
|
134
130
|
Then `summer_play` and look around. Sun in the right place? Seam invisible? Top/bottom okay?
|
|
@@ -158,7 +154,7 @@ Then `summer_play` and look around. Sun in the right place? Seam invisible? Top/
|
|
|
158
154
|
## Anti-patterns
|
|
159
155
|
|
|
160
156
|
- **Including foreground or horizon.** Mountains, trees, buildings at horizon level warp weirdly when sphere-mapped (the "swimming horizon" effect). Skies show ONLY sky. If the level needs distant mountains, model them as low-poly meshes in the scene, not in the sky texture.
|
|
161
|
-
- **
|
|
157
|
+
- **Assuming `options.aspectRatio` gave you 2:1.** It is silently ignored — the call succeeds and hands you a square image. A 1:1 or 16:9 panorama wrapped equirectangular has obvious horizontal compression. Crop it, or generate in the dashboard where the control exists.
|
|
162
158
|
- **Tight features at zenith/nadir.** Anything in the top or bottom 10% of the image gets pinched. Bias toward soft, diffuse features there.
|
|
163
159
|
- **Expecting HDR / IBL quality.** AI panoramas are 8-bit. If the user needs realistic environment lighting from the sky, point them at Polyhaven HDRIs (CC0). AI is for visual sky, not for lighting.
|
|
164
160
|
- **Forgetting `Repeat: Disabled` on import.** Panoramas wrap once via the material; if `Repeat` is on, you can get duplicate-tile artifacts at the seam.
|
|
@@ -180,12 +176,11 @@ Print the call:
|
|
|
180
176
|
summer_generate_image(
|
|
181
177
|
prompt="<sky> 360 degree panoramic equirectangular projection, seamless horizontal wrap, no visible seam, no foreground objects, sky only",
|
|
182
178
|
model="nano-banana-2",
|
|
183
|
-
style="realistic"
|
|
184
|
-
options={ aspectRatio: "2:1", negative_prompt: "vertical seam, foreground, distorted, warped, characters, buildings" }
|
|
179
|
+
style="realistic"
|
|
185
180
|
)
|
|
186
181
|
```
|
|
187
182
|
|
|
188
|
-
|
|
183
|
+
The dashboard is actually the *better* surface for this skill, not just the fallback: it exposes aspect ratio and a real negative prompt, which MCP does not. Tell the user to set 2:1 and a negative of `vertical seam, foreground, distorted, warped, characters, buildings`, then `summer_import_from_url` to `res://art/sky/<name>.png`, set `Repeat: Disabled`, and wire the WorldEnvironment.
|
|
189
184
|
|
|
190
185
|
If MCP is offline entirely: Polyhaven (`polyhaven.com/hdris`) has hundreds of free CC0 HDRIs ready to drop into `PanoramaSkyMaterial`. Often a better choice than AI for realistic exteriors anyway.
|
|
191
186
|
|
|
@@ -204,4 +199,4 @@ After the sky is wired:
|
|
|
204
199
|
- `summer:2d-assets/tileable-texture` — ground/floor counterpart.
|
|
205
200
|
- `summer:scene-composition` — WorldEnvironment placement and configuration.
|
|
206
201
|
- `summer:asset-pipeline/asset-strategy` — meta-router.
|
|
207
|
-
-
|
|
202
|
+
- `../../../references/mcp-tools-reference.md` — `summer_generate_image` schema.
|
|
@@ -5,7 +5,7 @@ license: MIT
|
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: 2d-assets
|
|
7
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
|
|
8
|
+
allowed-tools: Read Grep Glob Write Edit summer_generate_image summer_slice_asset_sheet summer_get_studio_workflow summer_search_assets summer_import_from_url summer_import_asset_by_id summer_set_resource_property summer_add_node summer_set_prop
|
|
9
9
|
paths: ["assets/**", "sprites/**", "art/sprites/**"]
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -18,10 +18,12 @@ This skill produces a grid of animation frames for a 2D character — walk cycle
|
|
|
18
18
|
This skill therefore offers **three paths**, ranked by reliability:
|
|
19
19
|
|
|
20
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
|
|
21
|
+
2. **Single-call sheet + auto-slice** (fast; sheet coherence is the gamble, not the cutting) — one prompt asks for the grid, then `summer_slice_asset_sheet` cuts it into individual frame assets server-side. Worth trying once for short cycles (4 frames or fewer) before falling back to (1).
|
|
22
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
23
|
|
|
24
|
-
There is no
|
|
24
|
+
There is no single "generate a sprite sheet" tool, but there **is** a shared two-tool sheet pipeline, and it is the same one Studio's Guided "sprite-sheet" workflow runs: `summer_generate_image` produces one sheet, then `summer_slice_asset_sheet({ assetId })` runs the server-side vision slicer that removes the background, detects each frame's bounding box, crops, and uploads every frame as its own asset. Call `summer_get_studio_workflow({ workflowId: "sprite-sheet" })` for the current ordered recipe and its stated limitations. Only Studio's frame-preview and visual timing-review UI is unreachable from MCP — the generation and the slicing both are reachable.
|
|
25
|
+
|
|
26
|
+
So do not tell the user to cut a generated sheet by hand or in ImageMagick. The cutting is automated; what is unreliable is inter-frame *consistency* inside the generated sheet.
|
|
25
27
|
|
|
26
28
|
## When to use
|
|
27
29
|
|
|
@@ -68,33 +70,44 @@ Generate frame 1 (or use existing base). For each subsequent frame, prompt the p
|
|
|
68
70
|
|
|
69
71
|
```
|
|
70
72
|
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,
|
|
73
|
+
prompt="goblin warrior, walk cycle frame 2 of 6, right leg forward, slight bob upward, identical character, same costume, same palette. Not a different character, not a different costume, no scene background.",
|
|
72
74
|
referenceImageUrl="<frame 1 fileUrl>",
|
|
73
75
|
model="nano-banana-2",
|
|
74
76
|
style="<same as base>",
|
|
75
|
-
options={
|
|
77
|
+
options={ removeBackground: true }
|
|
76
78
|
)
|
|
77
79
|
```
|
|
78
80
|
|
|
79
|
-
|
|
81
|
+
`summer_generate_image` has no `image_size` and no `negative_prompt` — put negations in the prompt text; there is no size argument at all. `options.removeBackground: true` is real and gives you true alpha instead of a prompted "transparent background" the model may paint as a literal checkerboard. `referenceImageUrl` only works on edit-capable models (`nano-banana-2`, `seedream-5-pro`, `nano-banana-lite`, `gpt-image-2`, `gemini-flash`, `flux-2`); `grok-imagine` has no edit endpoint and returns `edit_not_supported`.
|
|
80
82
|
|
|
81
|
-
|
|
83
|
+
Repeat for each frame. Save each as `goblin_walk_01.png`, `goblin_walk_02.png`, etc.
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
After all frames return, wire each as a separate frame in a `SpriteFrames`
|
|
86
|
+
resource. Summer Engine treats them as a sequence; there is no need to
|
|
87
|
+
composite them into one sheet image.
|
|
85
88
|
|
|
86
|
-
### 3b. Path 2 — Single-call sheet
|
|
89
|
+
### 3b. Path 2 — Single-call sheet, then auto-slice
|
|
87
90
|
|
|
88
91
|
```
|
|
89
92
|
summer_generate_image(
|
|
90
|
-
prompt="goblin warrior walk cycle, sprite sheet, 6 frames in a horizontal row, identical character across frames, side view,
|
|
93
|
+
prompt="goblin warrior walk cycle, sprite sheet, 6 frames in a horizontal row, identical character across frames, side view, frames clearly separated with empty space between them, consistent lighting, consistent palette. No scene background, no varying lighting, not a different character per frame.",
|
|
91
94
|
model="nano-banana-2",
|
|
92
|
-
style="
|
|
93
|
-
options={
|
|
95
|
+
style="none",
|
|
96
|
+
options={ removeBackground: true }
|
|
94
97
|
)
|
|
95
98
|
```
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
There is no `"pixel"` style preset (`style` is `realistic | cartoon | anime | none`; anything else is coerced to `none`), no `image_size`, and no `negative_prompt` — the layout and the negations have to be in the prompt.
|
|
101
|
+
|
|
102
|
+
Then cut it with the same server-side slicer Studio uses, passing the asset id the generation returned:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
summer_slice_asset_sheet(assetId="<generated sheet assetId>")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
It returns the source dimensions plus per-slice URLs, names, categories, and bounding boxes. Import the frames you want by id with `summer_import_asset_by_id`.
|
|
109
|
+
|
|
110
|
+
Inspect the result. If the frames are coherent and the count matches, proceed. If anatomy morphs across the row, or the slicer returns one giant box (items touching / no gaps), fall back to Path 1 or Path 3 — re-prompting with more separation between frames is the first thing to try.
|
|
98
111
|
|
|
99
112
|
### 3c. Path 3 — Aseprite manual fallback
|
|
100
113
|
|
|
@@ -104,7 +117,7 @@ Tell the user:
|
|
|
104
117
|
|
|
105
118
|
If yes, generate the static base via `summer:2d-assets/pixel-art` and stop here. The user takes it to Aseprite.
|
|
106
119
|
|
|
107
|
-
### 4. Import frames into
|
|
120
|
+
### 4. Import frames into Summer Engine
|
|
108
121
|
|
|
109
122
|
For per-frame import (Path 1):
|
|
110
123
|
|
|
@@ -125,30 +138,21 @@ Set `Filter: Nearest` on import for pixel art, `Linear` for high-res.
|
|
|
125
138
|
### 5. Wire as AnimatedSprite2D
|
|
126
139
|
|
|
127
140
|
```
|
|
128
|
-
summer_add_node(
|
|
141
|
+
summer_add_node(scenePath="res://main.tscn", parent="./Goblin", type="AnimatedSprite2D", name="Sprite")
|
|
129
142
|
```
|
|
130
143
|
|
|
131
|
-
|
|
144
|
+
Every scene-mutating tool takes an explicit `scenePath`, and node paths are relative to that scene's root (`./`), not absolute `/root/...` runtime paths.
|
|
145
|
+
|
|
146
|
+
Building the `SpriteFrames` itself is **not** an MCP job. `summer_set_resource_property` takes five flat arguments (`scenePath`, `nodePath`, `resourceProperty`, `subProperty`, `value`) and its `value` is restricted to a single string, number, or boolean — it cannot take a frame array, and there is no `"a:b/c"` colon-path form for reaching nested sub-resources. Author the `SpriteFrames` as a `.tres` with `summer_write_file` and then point the node at it:
|
|
132
147
|
|
|
133
148
|
```
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
+
summer_write_file(path="res://sprites/goblin/goblin_frames.tres", content="<SpriteFrames .tres with the walk animation, its frames, speed and loop>", create_only=true)
|
|
150
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Goblin/Sprite", key="sprite_frames", value="res://sprites/goblin/goblin_frames.tres")
|
|
151
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Goblin/Sprite", key="animation", value="walk")
|
|
152
|
+
summer_save_scene(scenePath="res://main.tscn")
|
|
149
153
|
```
|
|
150
154
|
|
|
151
|
-
For sheet-based (Path 2):
|
|
155
|
+
For sheet-based (Path 2): the slicer already returns individual frame images, so import those and list them as frames. If you would rather keep one packed sheet, declare `AtlasTexture` sub-resources with one region per frame inside the same `.tres`.
|
|
152
156
|
|
|
153
157
|
### 6. Trigger from code
|
|
154
158
|
|
|
@@ -198,6 +202,7 @@ func _physics_process(delta):
|
|
|
198
202
|
- **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
203
|
- **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
204
|
- **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.
|
|
205
|
+
- **Sending the user to ImageMagick or Aseprite to *cut* a generated sheet.** `summer_slice_asset_sheet` does that server-side. Hand off the creative work, not the mechanical work.
|
|
201
206
|
|
|
202
207
|
## Edge cases
|
|
203
208
|
|
|
@@ -212,7 +217,7 @@ func _physics_process(delta):
|
|
|
212
217
|
Print the per-frame call sequence:
|
|
213
218
|
|
|
214
219
|
```
|
|
215
|
-
Frame 1: summer_generate_image(prompt="<base>", model="nano-banana-2", style="
|
|
220
|
+
Frame 1: summer_generate_image(prompt="<base>", model="nano-banana-2", style="none", ...)
|
|
216
221
|
Frame 2: summer_generate_image(prompt="<base + delta>", referenceImageUrl="<frame 1>", ...)
|
|
217
222
|
Frame 3: summer_generate_image(prompt="<base + delta>", referenceImageUrl="<frame 2>", ...)
|
|
218
223
|
...
|
|
@@ -236,4 +241,4 @@ After the animation is wired:
|
|
|
236
241
|
- `summer:2d-assets/character-portrait` — base portrait for higher-res characters.
|
|
237
242
|
- `summer:animation/generate-motion` — 3D-skeletal counterpart.
|
|
238
243
|
- `summer:audio/sound-effect` — frame-synced SFX.
|
|
239
|
-
-
|
|
244
|
+
- `../../../references/mcp-tools-reference.md` — `summer_generate_image` schema.
|
|
@@ -35,7 +35,7 @@ The hard part is "seamless." Most diffusion models violate edge continuity by de
|
|
|
35
35
|
### 1. Search for an existing texture
|
|
36
36
|
|
|
37
37
|
```
|
|
38
|
-
summer_search_assets(query="<material> tileable",
|
|
38
|
+
summer_search_assets(query="<material> tileable", assetType="2d_image", source="all")
|
|
39
39
|
```
|
|
40
40
|
|
|
41
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.
|
|
@@ -60,17 +60,16 @@ The load-bearing phrases are:
|
|
|
60
60
|
|
|
61
61
|
```
|
|
62
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",
|
|
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. No vanishing point, no directional shadow, no vignette, no single standout feature, no scene context, no sky, no sun.",
|
|
64
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
|
-
}
|
|
65
|
+
style="realistic"
|
|
70
66
|
)
|
|
71
67
|
```
|
|
72
68
|
|
|
73
|
-
|
|
69
|
+
Two things about the arguments:
|
|
70
|
+
|
|
71
|
+
- **There is no `image_size` and no `negative_prompt`.** `summer_generate_image` takes only `prompt`, `model`, `style`, `referenceImageUrl`, and `options`, and `options` only recognizes Nano Banana provider keys (`seed`, `outputFormat`, `safetyTolerance`, `syncMode`, `systemPrompt`, `limitGenerations`, `thinkingLevel`) plus `removeBackground`. Anything else is dropped without an error, so the call looks like it worked. Put the negations in the prompt text. Square is what you get regardless — MCP images come back at the server's 1:1 default, which is exactly what a tileable texture wants.
|
|
72
|
+
- **`style: "realistic"` is a no-op.** Only `cartoon` and `anime` append anything to the prompt; `realistic` and `none` append nothing, and any other value is coerced to `none`. The photographic look has to come from the prompt (`photographic detail`). Switching to `"none"` for stylized work likewise changes nothing on its own — change the prompt.
|
|
74
73
|
|
|
75
74
|
### 4. Import to project
|
|
76
75
|
|
|
@@ -97,27 +96,35 @@ If you see hard horizontal/vertical seams, the edges don't match — regenerate
|
|
|
97
96
|
|
|
98
97
|
**On a PlaneMesh (floor/ceiling):**
|
|
99
98
|
|
|
99
|
+
Every scene-mutating tool takes an explicit `scenePath`; node paths are relative to that scene's root (`./`); `summer_set_prop`'s property argument is named `key`; and `summer_set_resource_property` needs all five of `scenePath`, `nodePath`, `resourceProperty`, `subProperty`, `value` (there is no two-argument form and no `"mesh:size"` colon-path form).
|
|
100
|
+
|
|
101
|
+
Assigning a bare class name to a resource property auto-instantiates it, so the mesh comes first:
|
|
102
|
+
|
|
100
103
|
```
|
|
101
|
-
summer_add_node(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
summer_add_node(scenePath="res://levels/level_01.tscn", parent="./Level", type="MeshInstance3D", name="Floor")
|
|
105
|
+
summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/Floor", key="mesh", value="PlaneMesh")
|
|
106
|
+
summer_set_resource_property(scenePath="res://levels/level_01.tscn", nodePath="./Level/Floor", resourceProperty="mesh", subProperty="size", value="Vector2(20, 20)")
|
|
104
107
|
```
|
|
105
108
|
|
|
106
|
-
Then
|
|
109
|
+
Then the material. `material_override` is a `Material`, and `StandardMaterial3D` is the class name that auto-instantiates:
|
|
107
110
|
|
|
108
111
|
```
|
|
112
|
+
summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/Floor", key="material_override", value="StandardMaterial3D")
|
|
109
113
|
summer_set_resource_property(
|
|
110
|
-
|
|
114
|
+
scenePath="res://levels/level_01.tscn",
|
|
115
|
+
nodePath="./Level/Floor",
|
|
111
116
|
resourceProperty="material_override",
|
|
112
117
|
subProperty="albedo_texture",
|
|
113
118
|
value="res://art/textures/brick_red.png"
|
|
114
119
|
)
|
|
115
120
|
summer_set_resource_property(
|
|
116
|
-
|
|
121
|
+
scenePath="res://levels/level_01.tscn",
|
|
122
|
+
nodePath="./Level/Floor",
|
|
117
123
|
resourceProperty="material_override",
|
|
118
124
|
subProperty="uv1_scale",
|
|
119
125
|
value="Vector3(20, 20, 1)"
|
|
120
126
|
)
|
|
127
|
+
summer_save_scene(scenePath="res://levels/level_01.tscn")
|
|
121
128
|
```
|
|
122
129
|
|
|
123
130
|
`uv1_scale = (20, 20, 1)` on a 20m plane means the texture tiles 20× across — each tile covers 1m².
|
|
@@ -125,8 +132,8 @@ summer_set_resource_property(
|
|
|
125
132
|
**On a CSGBox3D (walls):**
|
|
126
133
|
|
|
127
134
|
```
|
|
128
|
-
summer_add_node(
|
|
129
|
-
summer_set_prop(path="
|
|
135
|
+
summer_add_node(scenePath="res://levels/level_01.tscn", parent="./Level", type="CSGBox3D", name="WallNorth")
|
|
136
|
+
summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/WallNorth", key="size", value="Vector3(10, 3, 0.3)")
|
|
130
137
|
```
|
|
131
138
|
|
|
132
139
|
Then attach the same material with `uv1_scale` tuned to wall dimensions.
|
|
@@ -141,7 +148,7 @@ Then attach the same material with `uv1_scale` tuned to wall dimensions.
|
|
|
141
148
|
| Stone tiles | `cobblestone path, seamless tileable, top-down, uniform lighting, no shadows, no moss patches, square, photographic` | "No moss patches" kills hotspot |
|
|
142
149
|
| 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
150
|
| 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`
|
|
151
|
+
| Stylized painterly grass | `stylized painterly grass, Studio Ghibli, seamless tileable, top-down, uniform lighting, no specific blades emphasized, square` | The painterly direction has to be in the prompt; no `style` value produces it |
|
|
145
152
|
| 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
153
|
|
|
147
154
|
### Bad prompts (and why)
|
|
@@ -167,7 +174,7 @@ Then attach the same material with `uv1_scale` tuned to wall dimensions.
|
|
|
167
174
|
|
|
168
175
|
- **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
176
|
- **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).**
|
|
177
|
+
- **Texture must read at very low resolution (mobile, distant LOD).** You cannot request a generation size over MCP anyway — take the default and downscale on import (`Compress: VRAM Compressed`, or set a smaller size in the import dock).
|
|
171
178
|
- **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
179
|
- **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
180
|
|
|
@@ -177,10 +184,9 @@ Print the call:
|
|
|
177
184
|
|
|
178
185
|
```
|
|
179
186
|
summer_generate_image(
|
|
180
|
-
prompt="<material> seamless tileable texture, top-down view, uniform lighting, no perspective, no shadows, no specific objects, square",
|
|
187
|
+
prompt="<material> seamless tileable texture, top-down view, uniform lighting, no perspective, no shadows, no specific objects, square. No directional shadow, no single standout feature, no scene context.",
|
|
181
188
|
model="nano-banana-2",
|
|
182
|
-
style="realistic"
|
|
183
|
-
options={ image_size: "square_hd", negative_prompt: "perspective, directional shadow, single feature, scene context" }
|
|
189
|
+
style="realistic"
|
|
184
190
|
)
|
|
185
191
|
```
|
|
186
192
|
|
|
@@ -202,4 +208,4 @@ After the texture is wired:
|
|
|
202
208
|
- `summer:asset-pipeline/asset-strategy` — meta-router and 3D pipeline.
|
|
203
209
|
- `summer:2d-assets/skybox-panorama` — sky/environment counterpart.
|
|
204
210
|
- `summer:scene-composition` — applying textures to CSG and MeshInstance3D.
|
|
205
|
-
-
|
|
211
|
+
- `../../../references/mcp-tools-reference.md` — `summer_generate_image` schema.
|