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
|
@@ -5,15 +5,30 @@ license: MIT
|
|
|
5
5
|
compatibility: [Cursor, Claude Code, Windsurf, Codex]
|
|
6
6
|
category: animation
|
|
7
7
|
user-invocable: false
|
|
8
|
-
allowed-tools: Read Grep summer_search_assets summer_inspect_resource
|
|
8
|
+
allowed-tools: Read Grep summer_search_assets summer_inspect_resource summer_generate_motion summer_get_scene_tree summer_set_resource_property summer_save_scene
|
|
9
9
|
paths: ["**/*.tscn", "**/*.tres"]
|
|
10
10
|
---
|
|
11
11
|
|
|
12
12
|
# Retarget Motion — One Library, Many Characters
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## There is no retarget MCP tool. Read this before promising one.
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Summer ships **no** `summer_retarget_motion` tool, and no other MCP tool that
|
|
17
|
+
re-projects an existing animation asset onto a second rig. Verify it yourself:
|
|
18
|
+
`grep -rn 'summer_' tools/summer-cli/src/mcp/tools/*.ts` lists every registered
|
|
19
|
+
tool and there is no retarget entry. Never call one — the MCP server rejects
|
|
20
|
+
unknown tool names outright, and inventing a cost table for it ("$0.05 a clip")
|
|
21
|
+
is worse than saying nothing.
|
|
22
|
+
|
|
23
|
+
Two real paths exist. Pick by whether the target rig is Meshy-rigged.
|
|
24
|
+
|
|
25
|
+
| Situation | Path |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Target is Meshy-rigged and the clip name is on the curated list | Re-run `summer_generate_motion` against the target's `rigAssetId`. Same clip, ~$0.10, ~30s. |
|
|
28
|
+
| Target is not Meshy-rigged, or the clip is hand-authored / Mixamo / bought | In-engine retargeting: `BoneMap` + `SkeletonProfileHumanoid` + `RetargetModifier3D`. No credits, no network, but you configure the bone mapping. |
|
|
29
|
+
|
|
30
|
+
The rest of this skill covers both. The cost math that used to live here assumed a
|
|
31
|
+
retarget API that does not exist; the honest math is below.
|
|
17
32
|
|
|
18
33
|
## When to use this skill
|
|
19
34
|
|
|
@@ -24,149 +39,182 @@ The Meshy retarget pipeline takes a source `animationAssetId` and a target `rigA
|
|
|
24
39
|
|
|
25
40
|
## When NOT to use this skill
|
|
26
41
|
|
|
27
|
-
-
|
|
28
|
-
- Target is a quadruped or non-humanoid (wings-only, mech, blob). Meshy retarget is humanoid-skeleton-locked. Hand-author or regenerate.
|
|
29
|
-
- The user wants ONE new clip on ONE character — just call `summer:animation/generate-motion`. Retarget is for fan-out.
|
|
42
|
+
- The user wants ONE new clip on ONE character — just call `summer:animation/generate-motion`.
|
|
30
43
|
- The user wants to retime, edit, or layer the animation — that's `summer:animation/animation-tree` and the `summer:animation/procedural-animation` additive layers.
|
|
44
|
+
- Target is a quadruped or non-humanoid (wings-only, mech, blob). The curated Meshy
|
|
45
|
+
library is humanoid-only and `SkeletonProfileHumanoid` is a humanoid profile.
|
|
46
|
+
Hand-author instead.
|
|
31
47
|
|
|
32
|
-
##
|
|
33
|
-
|
|
34
|
-
The dominant failure mode is retargeting between rigs that look humanoid but have different bone counts, names, or hierarchies. Meshy auto-rigs use a fixed 52-bone humanoid skeleton — every Meshy rig is interchangeable. Mixamo / VRoid / hand-rigged FBX imports are NOT — even if they're "humanoid", the bone names differ and the retarget call rejects them.
|
|
35
|
-
|
|
36
|
-
Before calling `summer_retarget_motion`, verify:
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
summer_inspect_resource(<source_rigAssetId>)
|
|
40
|
-
summer_inspect_resource(<target_rigAssetId>)
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
Both responses should include `rig_provider: "meshy"` and `bone_count: 52`. If either is missing those fields or shows a different provider, **stop**. Tell the user: "Target rig isn't Meshy-rigged — retarget will fail. Either re-rig the target via `summer_generate_3d({ kind: \"image-to-3d\", imageUrl: \"...\", options: { rig: true } })` or regenerate motion directly on it via `summer:animation/generate-motion`. Which?"
|
|
44
|
-
|
|
45
|
-
If both are Meshy-rigged but the target's mesh has wildly different proportions (e.g., source is a 1.8m human, target is a 2.5m ogre with arms-down-to-knees), retarget will succeed but the *result* will look wrong — clipping, foot-floating, or limb-twisting. Warn the user before spending: "Proportions differ a lot — retarget will run but you'll likely need procedural foot IK on the result. Continue?" Hand off to `summer:animation/procedural-animation` after.
|
|
48
|
+
## Path A — regenerate on the target rig (Meshy-rigged targets)
|
|
46
49
|
|
|
47
|
-
|
|
50
|
+
This is the path for the common case: several characters that all came out of
|
|
51
|
+
`summer_generate_3d(... rig: true)`.
|
|
48
52
|
|
|
49
|
-
### 1. Find the source
|
|
53
|
+
### 1. Find the source clip names
|
|
50
54
|
|
|
51
55
|
```
|
|
52
|
-
summer_search_assets(query: "<source character>",
|
|
56
|
+
summer_search_assets(query: "<source character>", assetType: "animation", source: "my_assets")
|
|
53
57
|
```
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
You want the *names* (`idle`, `walk`, `run`, ...), not the asset IDs — the IDs
|
|
60
|
+
belong to the source rig and cannot be transplanted.
|
|
56
61
|
|
|
57
62
|
### 2. Find the target rig
|
|
58
63
|
|
|
59
64
|
```
|
|
60
|
-
summer_search_assets(query: "<target character>",
|
|
65
|
+
summer_search_assets(query: "<target character>", assetType: "3d_model", source: "my_assets")
|
|
61
66
|
```
|
|
62
67
|
|
|
63
|
-
Confirm `rigAssetId` is present
|
|
68
|
+
Confirm a `rigAssetId` is present. If it is null the model was never rigged —
|
|
69
|
+
stop and propose `summer_generate_3d({ kind: "image-to-3d", imageUrl: "...", options: { rig: true } })`
|
|
70
|
+
first, or route to `summer:asset-pipeline/asset-strategy`.
|
|
64
71
|
|
|
65
72
|
### 3. Confirm with user before spending
|
|
66
73
|
|
|
67
|
-
|
|
74
|
+
Regeneration is a real generation per clip per character. Say the total.
|
|
68
75
|
|
|
69
|
-
> I'm about to
|
|
76
|
+
> I'm about to generate 12 clips (idle, walk, run, attack, ...) on `orc_rigged` —
|
|
77
|
+
> 12 × ~$0.10 = ~$1.20, a few minutes total. OK?
|
|
70
78
|
|
|
71
|
-
### 4. Loop the
|
|
79
|
+
### 4. Loop the generation calls
|
|
72
80
|
|
|
73
81
|
```
|
|
74
|
-
for
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
for name in source_clip_names:
|
|
83
|
+
summer_generate_motion(
|
|
84
|
+
rigAssetId: "<target_rigAssetId>",
|
|
85
|
+
backend: "meshy-library",
|
|
86
|
+
motionName: name // exact curated name — see generate-motion's list
|
|
79
87
|
)
|
|
80
|
-
// returns
|
|
88
|
+
// returns animationAssetId in the job result
|
|
81
89
|
```
|
|
82
90
|
|
|
83
91
|
Save the returned IDs as a map `{ name: animationAssetId }` for the target.
|
|
84
92
|
|
|
85
93
|
### 5. Attach to the target's AnimationPlayer
|
|
86
94
|
|
|
87
|
-
|
|
95
|
+
`summer_set_resource_property` requires the target scene path — it is not optional.
|
|
88
96
|
|
|
89
97
|
```
|
|
90
98
|
summer_set_resource_property(
|
|
99
|
+
scenePath: "res://main.tscn",
|
|
91
100
|
nodePath: "./World/Orc/AnimationPlayer",
|
|
92
101
|
resourceProperty: "libraries/default",
|
|
93
102
|
subProperty: "<clip_name>",
|
|
94
|
-
value: "<
|
|
103
|
+
value: "<animationAssetId>"
|
|
95
104
|
)
|
|
96
105
|
```
|
|
97
106
|
|
|
98
|
-
`summer_save_scene` once at the end, not per clip.
|
|
107
|
+
`summer_save_scene(scenePath: "res://main.tscn")` once at the end, not per clip.
|
|
108
|
+
|
|
109
|
+
## Path B — in-engine retargeting (non-Meshy rigs, bought or hand-authored clips)
|
|
110
|
+
|
|
111
|
+
The current Summer Engine build ships the retargeting stack that the MCP layer
|
|
112
|
+
does not wrap. Verified
|
|
113
|
+
instantiable on the shipped binary: `BoneMap`, `SkeletonProfileHumanoid`
|
|
114
|
+
(56 bones), `RetargetModifier3D`.
|
|
115
|
+
|
|
116
|
+
The shape:
|
|
117
|
+
|
|
118
|
+
1. Create a `BoneMap` resource per rig, with `profile` set to a
|
|
119
|
+
`SkeletonProfileHumanoid`. Map each profile bone name to that rig's actual
|
|
120
|
+
bone name. Save as `.tres` — one per distinct skeleton, reused forever.
|
|
121
|
+
2. On import, set the source `.glb`'s import options to use the source rig's
|
|
122
|
+
`BoneMap` so its animation tracks are expressed against the humanoid profile.
|
|
123
|
+
3. On the target character, add a `RetargetModifier3D` under the `Skeleton3D`
|
|
124
|
+
and set its `profile` to the same `SkeletonProfileHumanoid`. It re-projects
|
|
125
|
+
the profile-space pose onto the target's bones each frame.
|
|
126
|
+
|
|
127
|
+
This costs no credits and works with any humanoid skeleton, including Mixamo and
|
|
128
|
+
hand-rigged FBX. The cost is the bone-mapping pass: a few minutes per distinct
|
|
129
|
+
skeleton, once.
|
|
99
130
|
|
|
100
131
|
## Confirmation gates
|
|
101
132
|
|
|
102
|
-
- **Before any
|
|
103
|
-
- **After the first
|
|
133
|
+
- **Before any generation call:** show the full clip list and total cost.
|
|
134
|
+
- **After the first clip:** preview the result. If it looks wrong, stop the loop
|
|
135
|
+
and re-evaluate (proportions, T-pose, missing bones).
|
|
104
136
|
- **Before saving the scene:** confirm the AnimationPlayer additions you're about to write.
|
|
105
137
|
|
|
106
138
|
## Reference card
|
|
107
139
|
|
|
108
|
-
### When retarget fails — the 5 common causes
|
|
109
|
-
|
|
110
|
-
| Symptom | Cause | Fix |
|
|
111
|
-
|---|---|---|
|
|
112
|
-
| API returns `incompatible_rig` | Target isn't Meshy-rigged | Re-rig target via `summer_generate_3d({ kind: "image-to-3d", options: { rig: true } })` |
|
|
113
|
-
| API returns `bone_mismatch` | Source rigged with custom bones (extra wings, etc.) | Strip extras or regenerate motion natively on target |
|
|
114
|
-
| Clip plays but limbs twist 180° | T-pose vs A-pose mismatch | Re-rig source from T-pose reference |
|
|
115
|
-
| Feet float / clip into ground | Target is much taller/shorter | Apply foot IK — see `summer:animation/procedural-animation` |
|
|
116
|
-
| Root motion drifts | Source had baked root translation, target scale differs | Strip root track in AnimationPlayer or scale `playback_speed` |
|
|
117
|
-
|
|
118
140
|
### Cost math (decision rule)
|
|
119
141
|
|
|
120
|
-
|
|
142
|
+
There is no cheaper "retarget" rate to compare against, so the real decision is
|
|
143
|
+
generate-per-character versus spend the time on a `BoneMap`.
|
|
144
|
+
|
|
145
|
+
| Scenario | Regenerate (Path A) | In-engine BoneMap (Path B) |
|
|
121
146
|
|---|---|---|
|
|
122
|
-
| 1 character,
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
| 30 NPCs, same 8-clip set | $24.00 | $6.40 ($0.80 + 29 × $0.40) |
|
|
147
|
+
| 1 character, 12 clips | ~$1.20 | n/a — nothing to share yet |
|
|
148
|
+
| 5 characters, same 12 clips | ~$6.00 | $0, plus ~1 bone-map pass per distinct skeleton |
|
|
149
|
+
| 30 NPCs sharing one skeleton | ~$36.00 | $0 — same rig, so the clips already play on all of them |
|
|
126
150
|
|
|
127
|
-
|
|
151
|
+
Note the case that makes most of this moot: **NPCs that share one rig share one
|
|
152
|
+
animation library already.** If the user's 30 enemies are 30 instances of the
|
|
153
|
+
same rigged `.glb`, nothing needs retargeting — instance the scene.
|
|
128
154
|
|
|
129
155
|
### Pitfalls
|
|
130
156
|
|
|
131
|
-
- **
|
|
132
|
-
|
|
133
|
-
- **
|
|
134
|
-
|
|
135
|
-
|
|
157
|
+
- **Assuming a retarget tool exists.** It does not. Check the tool list before
|
|
158
|
+
promising a capability; a hallucinated tool name fails the call outright.
|
|
159
|
+
- **Reusing the source `animationAssetId` on the target.** Animation assets are
|
|
160
|
+
bound to the rig they were generated against. Generate against the target's own
|
|
161
|
+
`rigAssetId` (Path A) or go through a `BoneMap` (Path B).
|
|
162
|
+
- **Omitting `scenePath`.** `summer_set_resource_property`, `summer_save_scene`,
|
|
163
|
+
`summer_add_node`, and `summer_set_prop` all take a required `scenePath`.
|
|
164
|
+
- **Mixing Meshy and Mixamo libraries on one character without a BoneMap.** The
|
|
165
|
+
bone-naming conventions differ; the AnimationPlayer plays tracks against bones
|
|
166
|
+
that don't exist. One rig provider per character, or map both through the
|
|
167
|
+
humanoid profile.
|
|
168
|
+
- **Proportion mismatch.** A library authored on a 1.8m humanoid on a 2.5m ogre
|
|
169
|
+
runs, but you get foot-float and limb-twist. Layer foot IK afterwards — see
|
|
170
|
+
`summer:animation/procedural-animation`.
|
|
136
171
|
|
|
137
172
|
### Quality bar
|
|
138
173
|
|
|
139
|
-
- Library
|
|
140
|
-
- Target
|
|
141
|
-
- Target
|
|
174
|
+
- Library authored on a 1.8m humanoid → target between 1.5m and 2.2m: production-ready.
|
|
175
|
+
- Target 2.2m–3m: expect foot-clipping; layer foot IK.
|
|
176
|
+
- Target < 1.5m or cartoon proportions (big head, short limbs): expect limb-pop.
|
|
142
177
|
|
|
143
178
|
## Anti-patterns
|
|
144
179
|
|
|
145
|
-
- Calling `summer_retarget_motion`
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
|
|
180
|
+
- Calling a `summer_retarget_motion` / `summer_retarget_*` tool. None exists.
|
|
181
|
+
- Quoting a retarget price. There is no retarget SKU to price.
|
|
182
|
+
- Passing an asset ID to `summer_inspect_resource`. That tool takes a `res://`
|
|
183
|
+
**path** to a resource in the project, not a cloud asset ID. Use
|
|
184
|
+
`summer_get_asset(assetId: ...)` for asset metadata.
|
|
185
|
+
- Generating motion on each enemy separately when they are instances of the same
|
|
186
|
+
rig. Instance the scene; the library comes with it.
|
|
149
187
|
|
|
150
188
|
## Edge cases
|
|
151
189
|
|
|
152
|
-
- **Source
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
- **
|
|
190
|
+
- **Source has facial blendshape tracks.** Skeleton retargeting only handles
|
|
191
|
+
bones. Facial tracks do not transfer. Hand off to `summer:animation/facial-and-lipsync`
|
|
192
|
+
to re-author per character.
|
|
193
|
+
- **Target rig is a different Meshy skeleton generation.** Symptom: bone-count
|
|
194
|
+
mismatch even though both are Meshy. Re-rig the target with a fresh
|
|
195
|
+
`summer_generate_3d({ kind: "image-to-3d", options: { rig: true } })` call.
|
|
196
|
+
- **The clip the user wants is not on the curated list.** Path A cannot produce
|
|
197
|
+
it. Either hand-author it, or import a Mixamo clip and take Path B.
|
|
156
198
|
|
|
157
199
|
## Fallback (no MCP)
|
|
158
200
|
|
|
159
|
-
|
|
201
|
+
Path B is the fallback and does not need MCP at all. In Summer Engine: select
|
|
202
|
+
the source `.glb` in the FileSystem dock, open the Import tab, create/assign a
|
|
203
|
+
`BoneMap` with a `SkeletonProfileHumanoid` profile, re-import. On the target
|
|
204
|
+
character add a `RetargetModifier3D` under `Skeleton3D` with the same profile.
|
|
205
|
+
Documented in the Godot 4.x "Retargeting 3D Skeletons" docs.
|
|
160
206
|
|
|
161
207
|
## Handoff
|
|
162
208
|
|
|
163
|
-
- After
|
|
164
|
-
|
|
209
|
+
- After the clips are on the target, the wiring is identical to a freshly-generated
|
|
210
|
+
clip — hand off to `summer:animation/animation-tree` for state-machine integration.
|
|
211
|
+
- If the result shows foot-clipping or hand-pen-through-prop issues, hand off to
|
|
212
|
+
`summer:animation/procedural-animation` for IK correction.
|
|
165
213
|
- For NPC behavior driving these clips, hand off to `summer:ai-and-npcs/design-npc`.
|
|
166
214
|
|
|
167
215
|
## See also
|
|
168
216
|
|
|
169
|
-
- `summer:animation/generate-motion` —
|
|
170
|
-
- `summer:asset-pipeline/asset-strategy` —
|
|
171
|
-
- `summer:animation/animation-tree` — wire the
|
|
172
|
-
- `summer:animation/procedural-animation` — fix proportional mismatches with foot IK
|
|
217
|
+
- `summer:animation/generate-motion` — the tool that actually produces clips, and the curated name list.
|
|
218
|
+
- `summer:asset-pipeline/asset-strategy` — getting characters rigged in the first place.
|
|
219
|
+
- `summer:animation/animation-tree` — wire the clips into a state machine.
|
|
220
|
+
- `summer:animation/procedural-animation` — fix proportional mismatches with foot IK.
|
|
@@ -56,7 +56,7 @@ For 90% of indie games, **horizontal sequencing** is correct. It's cheaper to au
|
|
|
56
56
|
### 3. Confirm stems exist (or generate them)
|
|
57
57
|
|
|
58
58
|
```
|
|
59
|
-
summer_search_assets(query="music",
|
|
59
|
+
summer_search_assets(query="music", assetType="music", source="all")
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
You need (typical case):
|
|
@@ -100,25 +100,27 @@ For ducking, add a sidechain compressor on the `Music` bus with the `Voice` bus
|
|
|
100
100
|
For horizontal sequencing, instantiate one `AudioStreamPlayer` per state, all on the Music bus, all autoplay, all looping, all starting at `-60 dB` except the active state:
|
|
101
101
|
|
|
102
102
|
```
|
|
103
|
-
summer_add_node(
|
|
104
|
-
summer_set_prop(path="
|
|
105
|
-
summer_set_prop(path="
|
|
106
|
-
summer_set_prop(path="
|
|
107
|
-
summer_set_prop(path="
|
|
108
|
-
|
|
109
|
-
summer_add_node(
|
|
110
|
-
summer_set_prop(path="
|
|
111
|
-
summer_set_prop(path="
|
|
112
|
-
summer_set_prop(path="
|
|
113
|
-
summer_set_prop(path="
|
|
114
|
-
|
|
115
|
-
summer_add_node(
|
|
116
|
-
summer_set_prop(path="
|
|
117
|
-
summer_set_prop(path="
|
|
118
|
-
summer_set_prop(path="
|
|
119
|
-
summer_set_prop(path="
|
|
103
|
+
summer_add_node(scenePath="res://main.tscn", parent="./Music", type="AudioStreamPlayer", name="Calm")
|
|
104
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="stream", value="res://audio/music/calm.mp3")
|
|
105
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="bus", value="Music")
|
|
106
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="volume_db", value=0.0)
|
|
107
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Calm", key="autoplay", value=true)
|
|
108
|
+
|
|
109
|
+
summer_add_node(scenePath="res://main.tscn", parent="./Music", type="AudioStreamPlayer", name="Tension")
|
|
110
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="stream", value="res://audio/music/tension.mp3")
|
|
111
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="bus", value="Music")
|
|
112
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="volume_db", value=-60.0)
|
|
113
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Tension", key="autoplay", value=true)
|
|
114
|
+
|
|
115
|
+
summer_add_node(scenePath="res://main.tscn", parent="./Music", type="AudioStreamPlayer", name="Combat")
|
|
116
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="stream", value="res://audio/music/combat.mp3")
|
|
117
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="bus", value="Music")
|
|
118
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="volume_db", value=-60.0)
|
|
119
|
+
summer_set_prop(scenePath="res://main.tscn", path="./Music/Combat", key="autoplay", value=true)
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
+
Every scene-mutating tool takes an explicit `scenePath`; node paths are relative to that scene's root (`./`), not absolute `/root/...` runtime paths; and the property argument is named `key`, not `property`.
|
|
123
|
+
|
|
122
124
|
All three play simultaneously, in sync, but only one is audible. State transitions tween volumes — the music never restarts, only fades.
|
|
123
125
|
|
|
124
126
|
This is why same BPM / same key / same bar length matter: all three are at the same playhead at all times.
|
|
@@ -309,7 +311,8 @@ Master
|
|
|
309
311
|
|
|
310
312
|
## Fallback (no MCP)
|
|
311
313
|
|
|
312
|
-
Print the bus layout,
|
|
314
|
+
Print the bus layout, node tree, and GDScript. The user constructs it manually
|
|
315
|
+
in Summer Engine.
|
|
313
316
|
|
|
314
317
|
## Handoff
|
|
315
318
|
|
|
@@ -323,4 +326,5 @@ Print the bus layout, the node tree, and the GDScript. User constructs in the Go
|
|
|
323
326
|
- `audio/audio-direction` — defines the dynamic music plan and bus layout
|
|
324
327
|
- `audio/music-track` — generates the stems
|
|
325
328
|
- `audio/voice-line` — the voice bus that triggers ducking
|
|
326
|
-
-
|
|
329
|
+
- `../../../references/godot-version.md` — Summer compatibility for AudioServer
|
|
330
|
+
and Tween APIs
|
|
@@ -17,7 +17,8 @@ An ambient bed is the *air* of a place. Forest at dawn, dungeon corridor, spaces
|
|
|
17
17
|
|
|
18
18
|
This is **not** music. Use `summer_generate_audio({capability: 'sound_effects'})`, not `{capability: 'music'}`. SFX renders textures; Music renders melody. You want texture.
|
|
19
19
|
|
|
20
|
-
Generated at 15–22 seconds (the SFX duration ceiling) and looped
|
|
20
|
+
Generated at 15–22 seconds (the SFX duration ceiling) and looped with a Summer
|
|
21
|
+
Engine import loop point and optional crossfade.
|
|
21
22
|
|
|
22
23
|
## When to use
|
|
23
24
|
|
|
@@ -102,38 +103,43 @@ If the user wants a busier bed (market, party), still prevent foreground events:
|
|
|
102
103
|
```
|
|
103
104
|
summer_generate_audio(
|
|
104
105
|
capability: "sound_effects",
|
|
105
|
-
|
|
106
|
+
text: "forest at dawn, gentle wind through leaves, distant bird calls every 6 seconds, soft creaking branches, no music, no human sound, 22s seamless loop",
|
|
106
107
|
durationSeconds: 22
|
|
107
108
|
)
|
|
108
|
-
// Result: { asset: { fileUrl, ... } }
|
|
109
109
|
// Then: summer_import_from_url(url: "<fileUrl>", path: "res://audio/ambient/forest_dawn.wav")
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
`sound_effects` reads from **`text`**, not `prompt` — passing `prompt` is a 400 `text_required`. (`prompt` is the `music` capability's field.) The clip comes back as WAV, so a `.wav` target path is correct.
|
|
113
|
+
|
|
112
114
|
22s is the SFX ceiling. Always generate at the ceiling for ambient — longer cycle means less recognized repetition.
|
|
113
115
|
|
|
114
116
|
If the model returns a clip with a loud event near the start or end (a sudden bird right at 0:00), regenerate. That kills loop seamlessness.
|
|
115
117
|
|
|
116
|
-
### 6. Mark the seamless loop in
|
|
118
|
+
### 6. Mark the seamless loop in Summer Engine's Import dock
|
|
117
119
|
|
|
118
120
|
This step is what makes the bed sound like a place rather than a 22-second sample.
|
|
119
121
|
|
|
120
|
-
|
|
122
|
+
WAV and MP3 use **different importers with different option names** — do not copy the MP3 block from `audio/music-track` here. The WAV importer has no `loop` / `loop_offset`; it has an `edit/loop_mode` enum plus sample-frame bounds.
|
|
123
|
+
|
|
124
|
+
In Summer Engine, select the `.wav` and open the Import dock:
|
|
121
125
|
|
|
122
126
|
| Setting | Value |
|
|
123
127
|
|---|---|
|
|
124
|
-
| Loop |
|
|
125
|
-
| Loop
|
|
126
|
-
| Loop
|
|
128
|
+
| Edit > Loop Mode | Forward |
|
|
129
|
+
| Edit > Loop Begin | 0 |
|
|
130
|
+
| Edit > Loop End | -1 (end of file) |
|
|
127
131
|
|
|
128
132
|
The `.import` file:
|
|
129
133
|
|
|
130
134
|
```
|
|
131
135
|
[params]
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
edit/loop_mode = 2
|
|
137
|
+
edit/loop_begin = 0
|
|
138
|
+
edit/loop_end = -1
|
|
135
139
|
```
|
|
136
140
|
|
|
141
|
+
`edit/loop_mode` is `0 = Detect From WAV, 1 = Disabled, 2 = Forward, 3 = Ping-Pong, 4 = Backward` — Forward is **2**, not 1. `edit/loop_begin` / `edit/loop_end` are integer sample frames, not seconds; to skip a 0.5 s fade-in artifact at 44.1 kHz set `edit/loop_begin = 22050`.
|
|
142
|
+
|
|
137
143
|
After changing, click `Reimport`.
|
|
138
144
|
|
|
139
145
|
### 7. Crossfade-loop pattern for seamlessness
|
|
@@ -190,11 +196,11 @@ This eliminates the click and adds variation through phase-overlap (the loop ove
|
|
|
190
196
|
For most beds, non-positional is correct (the player is *in* the place; the bed isn't an emitter):
|
|
191
197
|
|
|
192
198
|
```
|
|
193
|
-
summer_add_node(
|
|
194
|
-
summer_set_prop(path="
|
|
195
|
-
summer_set_prop(path="
|
|
196
|
-
summer_set_prop(path="
|
|
197
|
-
summer_set_prop(path="
|
|
199
|
+
summer_add_node(scenePath="res://levels/level_01.tscn", parent="./Level", type="AudioStreamPlayer", name="AmbientBed")
|
|
200
|
+
summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="stream", value="res://audio/ambient/forest_dawn.wav")
|
|
201
|
+
summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="bus", value="Ambient")
|
|
202
|
+
summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="volume_db", value=-12.0)
|
|
203
|
+
summer_set_prop(scenePath="res://levels/level_01.tscn", path="./Level/AmbientBed", key="autoplay", value=true)
|
|
198
204
|
```
|
|
199
205
|
|
|
200
206
|
Or attach the script in step 7 to a Node, set its `stream` to the imported audio, and skip the `AudioStreamPlayer` node — the script provides its own.
|
|
@@ -139,7 +139,8 @@ Rules:
|
|
|
139
139
|
|
|
140
140
|
### 8. Configure the audio bus layout
|
|
141
141
|
|
|
142
|
-
Real audio in
|
|
142
|
+
Real audio in Summer Engine needs a bus layout. A new project starts with only
|
|
143
|
+
the Master bus, so configure the remaining buses now.
|
|
143
144
|
|
|
144
145
|
**Preferred (Summer MCP):** Buses are typically in `default_bus_layout.tres`. Modify project setting:
|
|
145
146
|
|
|
@@ -151,7 +152,8 @@ Ask the user:
|
|
|
151
152
|
|
|
152
153
|
> May I create `audio/default_bus_layout.tres` with these buses: Master / Music / SFX / UI / Voice / Ambient / Reverb_Small / Reverb_Large / Reverb_Outdoor?
|
|
153
154
|
|
|
154
|
-
On yes, write the `.tres` directly via `Write` (it
|
|
155
|
+
On yes, write the `.tres` directly via `Write` (it is the engine's plain-text
|
|
156
|
+
resource format):
|
|
155
157
|
|
|
156
158
|
```
|
|
157
159
|
Write audio/default_bus_layout.tres
|
|
@@ -204,11 +206,13 @@ Ask:
|
|
|
204
206
|
If the user wants to start generating, propose 3-5 SFX seeds aligned with the vocabulary. These are starting points, not finals.
|
|
205
207
|
|
|
206
208
|
```
|
|
207
|
-
summer_generate_audio(
|
|
208
|
-
summer_generate_audio(
|
|
209
|
-
summer_generate_audio(
|
|
209
|
+
summer_generate_audio(capability="sound_effects", text="soft woody UI click, 80ms, no reverb, neutral pitch", durationSeconds=0.5)
|
|
210
|
+
summer_generate_audio(capability="sound_effects", text="warm major-third coin pickup, 300ms, light reverb", durationSeconds=0.5)
|
|
211
|
+
summer_generate_audio(capability="sound_effects", text="punchy low-mid player damage hit, slight detune, 200ms, no tail", durationSeconds=0.5)
|
|
210
212
|
```
|
|
211
213
|
|
|
214
|
+
`capability` is required; `sound_effects` reads from `text` (not `prompt`), and the length argument is `durationSeconds` (not `duration`) with a floor of 0.5 s. Ask for the character you want inside the text and let the player only use the front of the clip — you cannot request 80 ms.
|
|
215
|
+
|
|
212
216
|
Ask first:
|
|
213
217
|
|
|
214
218
|
> May I generate first-pass SFX seeds for UI, pickup, and damage classes? They're starting points, not finals.
|
|
@@ -235,11 +239,11 @@ End with:
|
|
|
235
239
|
| Pure sine "ding" for pickup | Reads as cheap mobile game. Use a major-third interval with character. |
|
|
236
240
|
| Same footstep sample for all surfaces | Material-aware footsteps are 80% of the perceived audio quality. |
|
|
237
241
|
| No master ceiling / true peak | Audio clips on console builds without `-1 dBTP` ceiling. Always set it. |
|
|
238
|
-
| Calling SetResourceProperty on inline sub_resources | Silent fail. See
|
|
242
|
+
| Calling SetResourceProperty on inline sub_resources | Silent fail. See `../../../references/mcp-tools-reference.md` § Trap. |
|
|
239
243
|
|
|
240
244
|
## Collaborative protocol
|
|
241
245
|
|
|
242
|
-
This skill writes one bible (`.summer/audio-bible.md`), creates a bus layout (`audio/default_bus_layout.tres`), modifies `project.godot`, and may generate audio (metered). Always ask before writing or generating. See
|
|
246
|
+
This skill writes one bible (`.summer/audio-bible.md`), creates a bus layout (`audio/default_bus_layout.tres`), modifies `project.godot`, and may generate audio (metered). Always ask before writing or generating. See `../../../references/collaborative-protocol.md`.
|
|
243
247
|
|
|
244
248
|
## Want a working starter?
|
|
245
249
|
|
|
@@ -247,9 +251,10 @@ No template — this is a workflow that produces the bible the rest of the proje
|
|
|
247
251
|
|
|
248
252
|
## See also
|
|
249
253
|
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
254
|
+
- `../../../references/collaborative-protocol.md`
|
|
255
|
+
- `../../../references/godot-version.md` — Summer compatibility and
|
|
256
|
+
version-sensitive audio API notes
|
|
257
|
+
- `../../../references/mcp-tools-reference.md`
|
|
253
258
|
- `scene-and-project/brainstorm-game/SKILL.md` — produces the brief that anchors the bible
|
|
254
259
|
- `rendering-and-lighting/art-direction/SKILL.md` — the visual counterpart; audio must rhyme with it
|
|
255
260
|
- `audio/audio-bus-setup/SKILL.md` (NEXT) — implements the bus layout in detail
|
|
@@ -13,7 +13,7 @@ paths: ["audio/music/**", "scripts/**", "**/*.tscn"]
|
|
|
13
13
|
|
|
14
14
|
## Overview
|
|
15
15
|
|
|
16
|
-
ElevenLabs Music renders
|
|
16
|
+
ElevenLabs Music renders a track from a prompt. Summer clamps the requested length to **3–600 seconds** before sending it, so anything outside that range is silently pulled to the nearest bound. The output quality depends entirely on prompt specificity: tempo (BPM), key, instrumentation, mood, structural cue. "Epic orchestral" returns generic stock music. "85 BPM, D minor, solo cello and detuned upright piano, sparse, melancholic, no drums, 4/4" returns a usable score for a melancholic exploration scene.
|
|
17
17
|
|
|
18
18
|
This skill produces one track aligned with the audio bible's music style and dynamic music plan, then wires it as an `AudioStreamPlayer` on the `Music` bus with a marked loop point if it's a loop, or as a linear cinematic stream if it's a one-shot.
|
|
19
19
|
|
|
@@ -126,21 +126,26 @@ Show the prompt:
|
|
|
126
126
|
> `85 BPM, D minor, 4/4, solo cello and detuned upright piano, sparse, melancholic exploration loop, no drums, gentle reverb, 60s loop`
|
|
127
127
|
> Duration 60s. Cost: ~12 credits. Generate?
|
|
128
128
|
|
|
129
|
+
The `music` capability reads the description from **`prompt`**, not `text` — the mirror image of `sound_effects`. Passing `text` here is a 400 `prompt_required`.
|
|
130
|
+
|
|
129
131
|
```
|
|
130
132
|
summer_generate_audio(
|
|
131
133
|
capability: "music",
|
|
132
134
|
prompt: "85 BPM, D minor, 4/4, solo cello and detuned upright piano, sparse, melancholic exploration loop, no drums, gentle reverb, 60s loop",
|
|
133
135
|
durationSeconds: 60
|
|
134
136
|
)
|
|
135
|
-
// Result: { asset: { fileUrl, ... } }
|
|
136
137
|
// Then: summer_import_from_url(url: "<fileUrl>", path: "res://audio/music/calm_exploration.mp3")
|
|
137
138
|
```
|
|
138
139
|
|
|
139
|
-
`durationSeconds`
|
|
140
|
+
`durationSeconds` is clamped to 3–600. Music comes back as MP3 (`audio/mpeg`), so a `.mp3` target path is correct.
|
|
141
|
+
|
|
142
|
+
### 7. Mark the loop point in Summer Engine
|
|
140
143
|
|
|
141
|
-
|
|
144
|
+
ElevenLabs Music does not return a loop-clean cut. You must mark the loop point
|
|
145
|
+
in Summer Engine's Import dock so playback returns to the loop point on
|
|
146
|
+
completion, not to 0:00.
|
|
142
147
|
|
|
143
|
-
|
|
148
|
+
The MP3 importer exposes exactly five options — `loop`, `loop_offset`, `bpm`, `beat_count`, `bar_beats`. There is **no `loop_mode`** on MP3 or OGG; `loop_mode` belongs to the WAV importer, where it is spelled `edit/loop_mode`.
|
|
144
149
|
|
|
145
150
|
In `audio/music/calm_exploration.mp3.import`:
|
|
146
151
|
|
|
@@ -148,21 +153,22 @@ In `audio/music/calm_exploration.mp3.import`:
|
|
|
148
153
|
[params]
|
|
149
154
|
loop = true
|
|
150
155
|
loop_offset = 0.0
|
|
151
|
-
loop_mode = 0 # 0=disabled, 1=forward, 2=ping-pong, 3=backward
|
|
152
156
|
```
|
|
153
157
|
|
|
154
|
-
If the start has a fade-in but the body is loopable, set `loop_offset = 4.0` (4 seconds of intro skipped on loop, plays full track first time).
|
|
158
|
+
If the start has a fade-in but the body is loopable, set `loop_offset = 4.0` (4 seconds of intro skipped on loop, plays full track first time). `bpm` + `beat_count` + `bar_beats` are what you set if you want beat-synced transitions later — see `audio/adaptive-music`.
|
|
155
159
|
|
|
156
160
|
For seamless looping, the cleaner option is to ask the model to generate a cell (one bar / one phrase) and concatenate; or generate at 60s and trust the model's structural cue. Crossfade looping in code is the practical fallback (see step 9).
|
|
157
161
|
|
|
158
162
|
### 8. Wire it as `AudioStreamPlayer` on the `Music` bus
|
|
159
163
|
|
|
164
|
+
Every scene-mutating tool takes an explicit `scenePath`, node paths are relative to the scene root (`./`), and the property argument is named `key`, not `property`:
|
|
165
|
+
|
|
160
166
|
```
|
|
161
|
-
summer_add_node(
|
|
162
|
-
summer_set_prop(path="
|
|
163
|
-
summer_set_prop(path="
|
|
164
|
-
summer_set_prop(path="
|
|
165
|
-
summer_set_prop(path="
|
|
167
|
+
summer_add_node(scenePath="res://main.tscn", parent=".", type="AudioStreamPlayer", name="MusicCalm")
|
|
168
|
+
summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="stream", value="res://audio/music/calm_exploration.mp3")
|
|
169
|
+
summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="bus", value="Music")
|
|
170
|
+
summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="volume_db", value=-8.0)
|
|
171
|
+
summer_set_prop(scenePath="res://main.tscn", path="./MusicCalm", key="autoplay", value=true)
|
|
166
172
|
```
|
|
167
173
|
|
|
168
174
|
Music is `AudioStreamPlayer` (not 2D / 3D) — non-positional. The bible's `Music -8 dB` mix sits the music behind SFX where it belongs.
|