@call-me-sensei/toonlab 0.2.0 → 0.3.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/AGENTS.md +127 -4
- package/ATTRIBUTION.md +41 -3
- package/README.md +234 -34
- package/docs/characters.md +144 -0
- package/docs/debug-panel.md +126 -0
- package/docs/docs.css +589 -0
- package/docs/environment.md +186 -0
- package/docs/getting-started.md +180 -0
- package/docs/index.html +14 -0
- package/docs/lab-architecture.md +100 -0
- package/docs/lighting.md +825 -0
- package/docs/main.jsx +739 -0
- package/docs/mcp.md +97 -0
- package/docs/post-processing.md +98 -0
- package/docs/settings-reference.md +1878 -0
- package/docs/shader-constants.md +77 -0
- package/docs/sky.md +182 -0
- package/docs/style-labs.md +309 -0
- package/docs/texture-lab.md +135 -0
- package/docs/toon-shading.md +183 -0
- package/docs/tsl-conventions.md +167 -0
- package/docs/vegetation-sky.md +275 -0
- package/docs/water.md +430 -0
- package/docs/weather.md +200 -0
- package/docs/world-scale.md +111 -0
- package/mcp/server.mjs +610 -0
- package/mcp/style-lab-tools.mjs +371 -0
- package/mcp/vite-plugin.mjs +174 -0
- package/mcp/workspace.mjs +397 -0
- package/package.json +64 -5
- package/src/ambientfx/INTEGRATION.md +164 -0
- package/src/ambientfx/ambientFxPresets.js +83 -0
- package/src/ambientfx/ambientFxSettings.js +368 -0
- package/src/ambientfx/emitters.js +169 -0
- package/src/ambientfx/index.js +5 -0
- package/src/ambientfx/particleBackbone.js +493 -0
- package/src/ambientfx/stylizedAmbientFx.js +450 -0
- package/src/assetlib/ambientcg.js +117 -0
- package/src/assetlib/assetRef.js +91 -0
- package/src/assetlib/importedEntry.js +40 -0
- package/src/assetlib/index.js +23 -0
- package/src/assetlib/kaykit.js +192 -0
- package/src/assetlib/kaykitStaticIndex.js +700 -0
- package/src/assetlib/loadImported.js +143 -0
- package/src/assetlib/opensource3d.js +113 -0
- package/src/assetlib/polyhaven.js +182 -0
- package/src/assetlib/polypizza.js +115 -0
- package/src/assetlib/smithsonian.js +214 -0
- package/src/assetlib/sources.js +279 -0
- package/src/assetlib/zip.js +58 -0
- package/src/biome/biomeGenerator.js +385 -0
- package/src/biome/biomeRuntime.js +299 -0
- package/src/biome/index.js +2 -0
- package/src/buildinggen/buildingAsset.js +44 -0
- package/src/buildinggen/buildingGrammar.js +311 -0
- package/src/buildinggen/buildingMesh.js +451 -0
- package/src/buildinggen/buildingPresets.js +46 -0
- package/src/buildinggen/buildingRecipe.js +100 -0
- package/src/buildinggen/buildingSettings.js +238 -0
- package/src/buildinggen/index.js +6 -0
- package/src/camera/cameraDirector.js +157 -0
- package/src/camera/cameraGenerator.js +367 -0
- package/src/camera/cameraRig.js +570 -0
- package/src/camera/cameraSettings.js +236 -0
- package/src/camera/index.js +7 -0
- package/src/catalog/builtinEntries.js +245 -0
- package/src/catalog/catalog.js +210 -0
- package/src/catalog/index.js +3 -0
- package/src/catalog/manifest.js +84 -0
- package/src/core/generation.js +529 -0
- package/src/environment/environmentRigs.js +21 -1
- package/src/environment/environmentSettings.js +4 -0
- package/src/environment/environmentSunShadowPass.js +8 -0
- package/src/fauna/INTEGRATION.md +174 -0
- package/src/fauna/boids.js +861 -0
- package/src/fauna/faunaBodies.js +492 -0
- package/src/fauna/faunaPresets.js +52 -0
- package/src/fauna/faunaSettings.js +525 -0
- package/src/fauna/index.js +5 -0
- package/src/fauna/stylizedFauna.js +395 -0
- package/src/game-feel/gameFeelGenerator.js +402 -0
- package/src/game-feel/gameFeelRuntime.js +549 -0
- package/src/game-feel/index.js +2 -0
- package/src/index.js +17 -6
- package/src/lighting/colorIntensity.js +177 -0
- package/src/lighting/index.js +161 -0
- package/src/lighting/lightDescriptors.js +249 -0
- package/src/lighting/lightingCapabilities.js +79 -0
- package/src/lighting/lightingDocuments.js +247 -0
- package/src/lighting/lightingFixtures.js +446 -0
- package/src/lighting/lightingGenerator.js +449 -0
- package/src/lighting/lightingPresets.js +319 -0
- package/src/lighting/lightingRuntime.js +723 -0
- package/src/lighting/lightingStyle.js +386 -0
- package/src/lighting/lightingSystem.js +774 -0
- package/src/lighting/unrealExport.js +186 -0
- package/src/lighting/utils.js +87 -0
- package/src/motion/index.js +5 -0
- package/src/motion/motionClip.js +441 -0
- package/src/motion/motionController.js +628 -0
- package/src/motion/motionDocuments.js +225 -0
- package/src/motion/motionGraph.js +307 -0
- package/src/motion/motionSettings.js +222 -0
- package/src/pathgen/index.js +7 -0
- package/src/pathgen/pathBridge.js +232 -0
- package/src/pathgen/pathPresets.js +35 -0
- package/src/pathgen/pathRibbon.js +410 -0
- package/src/pathgen/pathRouter.js +380 -0
- package/src/pathgen/pathSettings.js +335 -0
- package/src/pathgen/pathTextures.js +123 -0
- package/src/pathgen/stylizedPaths.js +453 -0
- package/src/post/index.js +1 -0
- package/src/post/postGenerator.js +177 -0
- package/src/post/postProcessing.js +41 -0
- package/src/propgen/generatorsWave1.js +379 -0
- package/src/propgen/generatorsWave2.js +462 -0
- package/src/propgen/index.js +5 -0
- package/src/propgen/propAsset.js +323 -0
- package/src/propgen/propParts.js +170 -0
- package/src/propgen/propPlacement.js +459 -0
- package/src/propgen/propPresets.js +82 -0
- package/src/propgen/propSettings.js +395 -0
- package/src/shaders-tsl/chunks/projected-water-caustics.js +242 -0
- package/src/shaders-tsl/chunks/vegetation-style.js +360 -0
- package/src/shaders-tsl/chunks/water-shore-state.js +31 -0
- package/src/shaders-tsl/chunks/water-waves.js +90 -11
- package/src/shaders-tsl/environment.js +15 -1
- package/src/shaders-tsl/flower.js +279 -30
- package/src/shaders-tsl/grass.js +60 -33
- package/src/shaders-tsl/sky.js +125 -31
- package/src/shaders-tsl/tree-leaf.js +61 -25
- package/src/shaders-tsl/water-breaker.js +7 -4
- package/src/shaders-tsl/water-shore-state-simulation.js +523 -0
- package/src/shaders-tsl/water.js +439 -49
- package/src/shaders-tsl/woody-surface.js +154 -0
- package/src/sky/sceneOverrideLayers.js +10 -0
- package/src/sky/skyQuality.js +26 -0
- package/src/sky/stylizedSky.js +753 -45
- package/src/soundscape/index.js +4 -0
- package/src/soundscape/soundscapeGenerator.js +179 -0
- package/src/soundscape/soundscapeRuntime.js +806 -0
- package/src/soundscape/soundscapeSettings.js +292 -0
- package/src/styles/index.js +13 -0
- package/src/styles/styleBundle.js +325 -0
- package/src/stylizedTerrain.js +32 -2
- package/src/stylizedWorld.js +423 -20
- package/src/texgen/evaluateTexture.js +675 -0
- package/src/texgen/index.js +60 -0
- package/src/texgen/noise2.js +210 -0
- package/src/texgen/textureAi.js +436 -0
- package/src/texgen/textureGenerators.js +516 -0
- package/src/texgen/texturePresets.js +490 -0
- package/src/texgen/textureSettings.js +342 -0
- package/src/texgen/textureThree.js +59 -0
- package/src/vegetation/flowerSpecies.js +15 -3
- package/src/vegetation/grassPalettes.js +153 -0
- package/src/vegetation/index.js +6 -0
- package/src/vegetation/stylizedBush.js +2 -0
- package/src/vegetation/stylizedFlower.js +82 -0
- package/src/vegetation/stylizedFlowers.js +48 -7
- package/src/vegetation/stylizedForest.js +29 -1
- package/src/vegetation/stylizedGrass.js +291 -56
- package/src/vegetation/stylizedTree.js +38 -2
- package/src/vegetation/stylizedTreeFoliage.js +2 -1
- package/src/vegetation/vegetationShaders.js +1110 -0
- package/src/vfxgen/INTEGRATION.md +145 -0
- package/src/vfxgen/core/burstBackbone.js +380 -0
- package/src/vfxgen/core/projectileCore.js +92 -0
- package/src/vfxgen/core/spriteShapes.js +98 -0
- package/src/vfxgen/core/trailRibbon.js +272 -0
- package/src/vfxgen/core/vfxRandom.js +29 -0
- package/src/vfxgen/effects/emitHelpers.js +37 -0
- package/src/vfxgen/effects/magicEffects.js +162 -0
- package/src/vfxgen/effects/movementEffects.js +87 -0
- package/src/vfxgen/effects/weaponEffects.js +118 -0
- package/src/vfxgen/index.js +18 -0
- package/src/vfxgen/moves/moveController.js +146 -0
- package/src/vfxgen/moves/moveLibrary.js +335 -0
- package/src/vfxgen/vfxPresets.js +98 -0
- package/src/vfxgen/vfxSettings.js +384 -0
- package/src/vfxgen/vfxSystem.js +449 -0
- package/src/vfxgen/weapons/stylizedWeapons.js +137 -0
- package/src/villagegen/index.js +4 -0
- package/src/villagegen/stylizedVillage.js +490 -0
- package/src/villagegen/villageArchetypes.js +160 -0
- package/src/villagegen/villageNames.js +40 -0
- package/src/villagegen/villageSites.js +105 -0
- package/src/water/sceneOverrideLayers.js +23 -0
- package/src/water/water.js +5 -0
- package/src/water/waterBreakerSystem.js +15 -1
- package/src/water/waterCurrentField.js +447 -0
- package/src/water/waterMaterial.js +12 -0
- package/src/water/waterNearshorePhase.js +320 -0
- package/src/water/waterScenePasses.js +83 -30
- package/src/water/waterSettings.js +325 -13
- package/src/water/waterShoreMaterial.js +322 -0
- package/src/water/waterShoreStateField.js +605 -0
- package/src/water/waterSurface.js +797 -28
- package/src/weather/index.js +6 -0
- package/src/weather/weatherPrecipitation.js +221 -0
- package/src/weather/weatherPresets.js +258 -0
- package/src/weather/weatherSettings.js +269 -0
- package/src/weather/weatherSystem.js +871 -0
- package/src/worldMinimap.js +62 -0
- package/src/worldPresets.js +4 -1
package/docs/main.jsx
ADDED
|
@@ -0,0 +1,739 @@
|
|
|
1
|
+
// OSS documentation pages. Everything documented here works offline with the
|
|
2
|
+
// open-source package; hosted-only features are explicitly badged "Pro" and
|
|
3
|
+
// link to toonlab.io. The settings reference renders the generated
|
|
4
|
+
// settings-reference.md from this folder.
|
|
5
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
6
|
+
import { createRoot } from 'react-dom/client';
|
|
7
|
+
import { marked } from 'marked';
|
|
8
|
+
import {
|
|
9
|
+
BookOpenText,
|
|
10
|
+
Bot,
|
|
11
|
+
Check,
|
|
12
|
+
Copy,
|
|
13
|
+
Crown,
|
|
14
|
+
Lightbulb,
|
|
15
|
+
Plug,
|
|
16
|
+
Sparkles,
|
|
17
|
+
TerminalSquare,
|
|
18
|
+
} from 'lucide-react';
|
|
19
|
+
import settingsReferenceRaw from './settings-reference.md?raw';
|
|
20
|
+
import './docs.css';
|
|
21
|
+
|
|
22
|
+
const GITHUB = 'https://github.com/call-me-sensei/toonlab';
|
|
23
|
+
|
|
24
|
+
function CopyButton({ value }) {
|
|
25
|
+
const [copied, setCopied] = useState(false);
|
|
26
|
+
return (
|
|
27
|
+
<button
|
|
28
|
+
type="button"
|
|
29
|
+
className="docs-codeblock-copy"
|
|
30
|
+
onClick={async () => {
|
|
31
|
+
await navigator.clipboard.writeText(value);
|
|
32
|
+
setCopied(true);
|
|
33
|
+
setTimeout(() => setCopied(false), 1600);
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
{copied ? <Check size={13} aria-hidden /> : <Copy size={13} aria-hidden />}
|
|
37
|
+
{copied ? 'Copied' : 'Copy'}
|
|
38
|
+
</button>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function CodeBlock({ code, label }) {
|
|
43
|
+
return (
|
|
44
|
+
<div className="docs-codeblock">
|
|
45
|
+
{label && <div className="docs-codeblock-label">{label}</div>}
|
|
46
|
+
<pre><code>{code}</code></pre>
|
|
47
|
+
<CopyButton value={code} />
|
|
48
|
+
</div>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function PromptBlock({ title, prompt, note, pro }) {
|
|
53
|
+
return (
|
|
54
|
+
<div className="docs-promptblock">
|
|
55
|
+
<span className="docs-promptblock-title">
|
|
56
|
+
{title}
|
|
57
|
+
{pro && <span className="docs-pro">Pro</span>}
|
|
58
|
+
</span>
|
|
59
|
+
<CodeBlock code={prompt} />
|
|
60
|
+
{note && <p className="docs-promptblock-note">{note}</p>}
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function ProBadge() {
|
|
66
|
+
return <span className="docs-pro">Pro</span>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* ---------------------------------------------------------------- overview */
|
|
70
|
+
|
|
71
|
+
function Overview() {
|
|
72
|
+
return (
|
|
73
|
+
<article>
|
|
74
|
+
<div className="docs-eyebrow">Documentation</div>
|
|
75
|
+
<h1>Build games with ToonLab and your AI coding agent</h1>
|
|
76
|
+
<p className="docs-lede">
|
|
77
|
+
ToonLab is an open-source anime-style runtime for Three.js plus browser labs for authoring
|
|
78
|
+
shaders, assets, and world systems. Everything on this page runs from this repo or the npm
|
|
79
|
+
package — no account, no service. The optimal workflow adds an AI coding agent driving it
|
|
80
|
+
all through skills and MCP.
|
|
81
|
+
</p>
|
|
82
|
+
|
|
83
|
+
<h2>The pieces</h2>
|
|
84
|
+
<ul>
|
|
85
|
+
<li>
|
|
86
|
+
<strong>The runtime library</strong> —{' '}
|
|
87
|
+
<a href="https://www.npmjs.com/package/@call-me-sensei/toonlab" target="_blank" rel="noreferrer">
|
|
88
|
+
<code>@call-me-sensei/toonlab</code>
|
|
89
|
+
</a>
|
|
90
|
+
: toon and environment shading, water, sky, weather, vegetation, lighting, post, camera,
|
|
91
|
+
game feel, and seeded generators for rocks, props, buildings, paths, and villages.
|
|
92
|
+
MIT-licensed, WebGPU-first with a WebGL2 fallback, zero bundled textures.
|
|
93
|
+
</li>
|
|
94
|
+
<li>
|
|
95
|
+
<strong>The labs</strong> — visual editors served by <code>npm run dev</code> (or hosted
|
|
96
|
+
at <a href="https://toonlab.io" target="_blank" rel="noreferrer">toonlab.io</a>). Every
|
|
97
|
+
lab exports a portable preset document the runtime loads.
|
|
98
|
+
</li>
|
|
99
|
+
<li>
|
|
100
|
+
<strong>The local MCP server</strong> — bundled with the package: your coding agent
|
|
101
|
+
searches the procedural catalog and public CC0 sources, reads and saves presets, and
|
|
102
|
+
imports assets into an on-disk <code>.toonlab/</code> workspace. Stdio, no OAuth.
|
|
103
|
+
</li>
|
|
104
|
+
<li>
|
|
105
|
+
<strong>Hosted generation and library</strong> <ProBadge /> — toonlab.io adds a remote
|
|
106
|
+
MCP server with AI generation (concept art, seamless textures, image→3D), stored
|
|
107
|
+
characters, a cloud library, and the public gallery.
|
|
108
|
+
</li>
|
|
109
|
+
</ul>
|
|
110
|
+
|
|
111
|
+
<h2>The optimal workflow</h2>
|
|
112
|
+
<p>
|
|
113
|
+
<span className="docs-step-label">01</span>
|
|
114
|
+
<strong>Install the runtime and the agent skills.</strong> <code>npm install
|
|
115
|
+
@call-me-sensei/toonlab</code>, then copy the feature skills from{' '}
|
|
116
|
+
<a href={`${GITHUB}/tree/main/agents`} target="_blank" rel="noreferrer"><code>agents/</code></a>{' '}
|
|
117
|
+
into your project — they teach the agent the assembly order, the frame-loop contract, and
|
|
118
|
+
each subsystem's API. Start with <code>game-dev</code>.
|
|
119
|
+
</p>
|
|
120
|
+
<p>
|
|
121
|
+
<span className="docs-step-label">02</span>
|
|
122
|
+
<strong>Connect the local MCP server.</strong> See <a href="#/mcp">Connect via MCP</a> —
|
|
123
|
+
one JSON block, no account. Your agent can now find or import assets and share presets
|
|
124
|
+
with the labs through <code>.toonlab/</code>.
|
|
125
|
+
</p>
|
|
126
|
+
<p>
|
|
127
|
+
<span className="docs-step-label">03</span>
|
|
128
|
+
<strong>Author looks visually, apply them from code.</strong> Tune shaders and world
|
|
129
|
+
systems in the labs, export presets, and load them in your game — or fetch a published{' '}
|
|
130
|
+
<a href="https://toonlab.io/styles" target="_blank" rel="noreferrer">style bundle</a> with{' '}
|
|
131
|
+
<code>fetchStyleBundle</code>.
|
|
132
|
+
</p>
|
|
133
|
+
<p>
|
|
134
|
+
<span className="docs-step-label">04</span>
|
|
135
|
+
<strong>Prompt, run, iterate.</strong> Start from a goal prompt with a verifiable outcome
|
|
136
|
+
and let the agent check its own work — the <a href="#/prompts">prompt cookbook</a> has
|
|
137
|
+
ready-to-paste recipes.
|
|
138
|
+
</p>
|
|
139
|
+
|
|
140
|
+
<h2>Start here</h2>
|
|
141
|
+
<div className="docs-cards">
|
|
142
|
+
<a className="docs-card" href="#/library">
|
|
143
|
+
<BookOpenText size={18} aria-hidden />
|
|
144
|
+
<strong>Using the library</strong>
|
|
145
|
+
<span>Bootstrap a world, customize shaders, author assets, share your work.</span>
|
|
146
|
+
</a>
|
|
147
|
+
<a className="docs-card" href="#/mcp">
|
|
148
|
+
<Plug size={18} aria-hidden />
|
|
149
|
+
<strong>Connect via MCP</strong>
|
|
150
|
+
<span>The local server, its tool reference, and the optional Pro remote server.</span>
|
|
151
|
+
</a>
|
|
152
|
+
<a className="docs-card" href="#/prompts">
|
|
153
|
+
<Sparkles size={18} aria-hidden />
|
|
154
|
+
<strong>Prompt cookbook</strong>
|
|
155
|
+
<span>The first prompt to start a game, and recipes for the common jobs.</span>
|
|
156
|
+
</a>
|
|
157
|
+
<a className="docs-card" href="#/reference">
|
|
158
|
+
<TerminalSquare size={18} aria-hidden />
|
|
159
|
+
<strong>Settings reference</strong>
|
|
160
|
+
<span>Every tunable field with types, defaults, and ranges — generated from the schemas.</span>
|
|
161
|
+
</a>
|
|
162
|
+
</div>
|
|
163
|
+
</article>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* ----------------------------------------------------------------- library */
|
|
168
|
+
|
|
169
|
+
const WORLD_SNIPPET = `import * as THREE from 'three';
|
|
170
|
+
import { createStylizedTerrain, createStylizedWorld } from '@call-me-sensei/toonlab';
|
|
171
|
+
|
|
172
|
+
// Seeded terrain — any seed is a valid, playable world.
|
|
173
|
+
const terrain = createStylizedTerrain({ seed: 42, size: 1000, archetype: 'terracedKarst' });
|
|
174
|
+
const terrainRoot = new THREE.Group();
|
|
175
|
+
terrainRoot.add(terrain.root);
|
|
176
|
+
scene.add(terrainRoot);
|
|
177
|
+
|
|
178
|
+
// Environment shading, sun + shadows, sky, water, LOD forests, grass,
|
|
179
|
+
// fog, and collision — all on by default.
|
|
180
|
+
const world = await createStylizedWorld({
|
|
181
|
+
renderer, scene, camera,
|
|
182
|
+
terrain: { heightAt: terrain.heightAt, root: terrainRoot, size: terrain.meshExtent },
|
|
183
|
+
water: { level: terrain.waterLevel },
|
|
184
|
+
weather: { preset: 'call_me_sensei' },
|
|
185
|
+
followTarget: character, // optional: splashes, wakes, grass push
|
|
186
|
+
});
|
|
187
|
+
character.position.copy(terrain.spawn);
|
|
188
|
+
|
|
189
|
+
const clock = new THREE.Clock();
|
|
190
|
+
renderer.setAnimationLoop(() => {
|
|
191
|
+
world.update(clock.getDelta());
|
|
192
|
+
renderer.render(scene, camera);
|
|
193
|
+
});`;
|
|
194
|
+
|
|
195
|
+
const TOON_SNIPPET = `import { applyToonShader, createToonSettings } from '@call-me-sensei/toonlab/toon';
|
|
196
|
+
|
|
197
|
+
// Every field ships a sensible default; override only what defines your look.
|
|
198
|
+
// 23 groups, 298 fields — see the Settings reference for all of them.
|
|
199
|
+
const settings = createToonSettings({
|
|
200
|
+
preset: 'default',
|
|
201
|
+
rimLight: { intensity: 0.35, mode: 'depth' },
|
|
202
|
+
outline: { thickness: 1.6 },
|
|
203
|
+
skinTone: { skinShadowBrightness: 0.94 },
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
applyToonShader(characterRoot, { settings });`;
|
|
207
|
+
|
|
208
|
+
const ASSET_SNIPPET = `import { createCatalog } from '@call-me-sensei/toonlab/catalog';
|
|
209
|
+
import { propAssetFromObject } from '@call-me-sensei/toonlab/propgen';
|
|
210
|
+
|
|
211
|
+
// Procedural catalog: every recipe/preset as a searchable manifest.
|
|
212
|
+
const catalog = createCatalog();
|
|
213
|
+
const lantern = catalog.spawn('prop/lantern/stone-toro', { seed: 7 }); // grounded, collided, LOD'd
|
|
214
|
+
|
|
215
|
+
// Any imported GLB (e.g. a CC0 model imported through the local MCP server)
|
|
216
|
+
// joins the same placement pipeline:
|
|
217
|
+
const shrine = propAssetFromObject(importedGltf.scene);`;
|
|
218
|
+
|
|
219
|
+
const TEXGEN_SNIPPET = `import {
|
|
220
|
+
createTextureSettings, evaluateTextureMaps,
|
|
221
|
+
findTexturePreset, syncTextureMapTextures,
|
|
222
|
+
} from '@call-me-sensei/toonlab/texgen';
|
|
223
|
+
|
|
224
|
+
// 25 tileable generators, layered overlays (moss, rust, grime), a
|
|
225
|
+
// cel-capable color ramp, and derived normal/AO/roughness/ORM maps —
|
|
226
|
+
// all CPU-baked from a 60+ preset library. No texture assets shipped.
|
|
227
|
+
const settings = createTextureSettings(findTexturePreset('mossy-bricks').settings);
|
|
228
|
+
const maps = await evaluateTextureMaps(settings, { size: 1024 });
|
|
229
|
+
const textures = syncTextureMapTextures(maps); // THREE.DataTexture per map
|
|
230
|
+
material.map = textures.albedo;
|
|
231
|
+
material.normalMap = textures.normal;`;
|
|
232
|
+
|
|
233
|
+
const BUNDLE_SNIPPET = `import { fetchStyleBundle } from '@call-me-sensei/toonlab/styles';
|
|
234
|
+
|
|
235
|
+
// One published document that styles many systems at once. Fetching public
|
|
236
|
+
// bundles needs no account; authoring them happens on toonlab.io (Pro).
|
|
237
|
+
const { settings } = await fetchStyleBundle('sakura-dusk'); // slug or full URL
|
|
238
|
+
|
|
239
|
+
applyToonShader(characterRoot, { settings: settings.toon });
|
|
240
|
+
sky.applySettings(settings.sky);
|
|
241
|
+
water.applySettings(settings.water);
|
|
242
|
+
// Other slots: environment, weather, grass, flowers, vegetationShader,
|
|
243
|
+
// tree, lighting, post — apply each through its system's runtime.`;
|
|
244
|
+
|
|
245
|
+
function Library() {
|
|
246
|
+
return (
|
|
247
|
+
<article>
|
|
248
|
+
<div className="docs-eyebrow">Runtime library</div>
|
|
249
|
+
<h1>Using the npm package</h1>
|
|
250
|
+
<p className="docs-lede">
|
|
251
|
+
<code>@call-me-sensei/toonlab</code> is a runtime library — your app owns the renderer and
|
|
252
|
+
the frame loop; ToonLab systems accept your objects. It is WebGPU-first (TSL /
|
|
253
|
+
NodeMaterial) with a WebGL2 fallback through the same path.
|
|
254
|
+
</p>
|
|
255
|
+
|
|
256
|
+
<CodeBlock label="Install" code={'npm install @call-me-sensei/toonlab'} />
|
|
257
|
+
|
|
258
|
+
<div className="docs-callout">
|
|
259
|
+
<Bot size={16} aria-hidden />
|
|
260
|
+
<span>
|
|
261
|
+
For every tunable field with types, defaults, and ranges, see the{' '}
|
|
262
|
+
<a href="#/reference">Settings reference</a> — generated from the same schemas that
|
|
263
|
+
drive the labs and the debug panel.
|
|
264
|
+
</span>
|
|
265
|
+
</div>
|
|
266
|
+
|
|
267
|
+
<h2>A complete open world</h2>
|
|
268
|
+
<p>
|
|
269
|
+
<code>createStylizedWorld</code> composes environment shading, an aligned sun with real
|
|
270
|
+
shadows, sky, water, LOD forests, follow-window grass, unified fog, weather, and collision
|
|
271
|
+
in one call. Terrain is a pure contract — <code>heightAt(x, z)</code> in meters plus a
|
|
272
|
+
displaced mesh — so you can use the seeded generator or bring your own.
|
|
273
|
+
</p>
|
|
274
|
+
<CodeBlock label="main.js" code={WORLD_SNIPPET} />
|
|
275
|
+
<p>
|
|
276
|
+
Archetypes: <code>terracedKarst</code>, <code>lakeland</code>, <code>alpine</code>,{' '}
|
|
277
|
+
<code>rollingPlains</code>, <code>archipelago</code>. Add solid props with{' '}
|
|
278
|
+
<code>world.collision.addCircles(...)</code> and a clickable minimap with{' '}
|
|
279
|
+
<code>createWorldMinimap</code>. The{' '}
|
|
280
|
+
<a href="/examples/outdoor-world/" target="_blank" rel="noreferrer">outdoor-world example</a>{' '}
|
|
281
|
+
is the reference project layout.
|
|
282
|
+
</p>
|
|
283
|
+
|
|
284
|
+
<h2>What each import gives you</h2>
|
|
285
|
+
<div className="docs-table-wrap">
|
|
286
|
+
<table className="docs-table">
|
|
287
|
+
<thead>
|
|
288
|
+
<tr>
|
|
289
|
+
<th>Import</th>
|
|
290
|
+
<th>What you get</th>
|
|
291
|
+
</tr>
|
|
292
|
+
</thead>
|
|
293
|
+
<tbody>
|
|
294
|
+
<tr><td>/toon</td><td>Anime character shader: cel bands, face lighting, rim, hair highlights, outlines — 23 preset-serializable settings groups.</td></tr>
|
|
295
|
+
<tr><td>/environment</td><td>Scene shader for texture packs and glTF: material-role classification, wrapped lighting, time-of-day, fog, cloud shadows.</td></tr>
|
|
296
|
+
<tr><td>/water</td><td>Gerstner-wave water with a calm→storm dial, breakers, foam, caustics, ripples, and a CPU spectrum mirror for buoyancy.</td></tr>
|
|
297
|
+
<tr><td>/sky</td><td>Gradient/sun/painterly-cloud/star system — 46 portable art fields per preset.</td></tr>
|
|
298
|
+
<tr><td>/weather</td><td>Cross-system coordinator: 22 presets, GPU precipitation, lightning; drives sky, water, wind, vegetation, and fog.</td></tr>
|
|
299
|
+
<tr><td>/vegetation</td><td>Instanced grass and flower fields, procedural trees, palettes, masks, and scatter helpers.</td></tr>
|
|
300
|
+
<tr><td>/lighting</td><td>Versioned light recipes, budgets, runtime realization, and a data-only UE5 handoff.</td></tr>
|
|
301
|
+
<tr><td>/post, /camera, /game-feel</td><td>Compositor pipeline, camera operator stack + director, and hit-stop/punch/flash game feel.</td></tr>
|
|
302
|
+
<tr><td>/texgen</td><td>Seamless CPU-baked PBR texture generator with 60+ presets and a natural-language recipe mapper.</td></tr>
|
|
303
|
+
<tr><td>/rockgen, /propgen, /buildinggen, /pathgen, /villagegen</td><td>Seeded generators for rocks, 12 prop families, building exteriors, road networks, and settlements.</td></tr>
|
|
304
|
+
<tr><td>/vfxgen, /ambientfx, /fauna</td><td>Gameplay VFX (trails, impacts, weapons), ambient particles (petals, fireflies), and GPU-animated creatures.</td></tr>
|
|
305
|
+
<tr><td>/catalog, /loaders, /debug</td><td>Searchable asset manifest with <code>catalog.spawn</code>, model loaders (GLB/VRM/PMX/FBX), and the schema-driven tuning panel.</td></tr>
|
|
306
|
+
</tbody>
|
|
307
|
+
</table>
|
|
308
|
+
</div>
|
|
309
|
+
<p>
|
|
310
|
+
The full cluster table with per-system deep dives is in the{' '}
|
|
311
|
+
<a href={`${GITHUB}#whats-inside`} target="_blank" rel="noreferrer">README</a> and{' '}
|
|
312
|
+
<a href={`${GITHUB}/tree/main/docs`} target="_blank" rel="noreferrer"><code>docs/</code></a>.
|
|
313
|
+
</p>
|
|
314
|
+
|
|
315
|
+
<h2>Customize a shader</h2>
|
|
316
|
+
<p>
|
|
317
|
+
Every ToonLab shader is driven by a settings object created from a schema — you never
|
|
318
|
+
write GLSL/TSL to get a custom look. The same schemas power the labs, so anything you can
|
|
319
|
+
click there is a field you can set in code.
|
|
320
|
+
</p>
|
|
321
|
+
<CodeBlock label="Custom character shader" code={TOON_SNIPPET} />
|
|
322
|
+
<p>
|
|
323
|
+
The intended workflow for a signature look: tune it visually in the{' '}
|
|
324
|
+
<a href="/shader-lab/" target="_blank" rel="noreferrer">Character Shader Lab</a>, export
|
|
325
|
+
the preset document, and load it in your game (<code>serializeToonPreset</code> /{' '}
|
|
326
|
+
<code>registerToonPreset</code>). For looks beyond the schema, the shaders are open-source
|
|
327
|
+
TSL modules — fork the cluster and keep the preset contract.
|
|
328
|
+
</p>
|
|
329
|
+
|
|
330
|
+
<h2>Create assets</h2>
|
|
331
|
+
<p>
|
|
332
|
+
Assets come from seeded procedural generators, the texture generator, and anything you
|
|
333
|
+
import — including CC0 assets your agent pulls in through the{' '}
|
|
334
|
+
<a href="#/mcp">local MCP server</a>. All of them end up in the same placement pipeline:
|
|
335
|
+
grounded, collided, instanced, with true-3D-distance LODs.
|
|
336
|
+
</p>
|
|
337
|
+
<CodeBlock label="Procedural + imported assets" code={ASSET_SNIPPET} />
|
|
338
|
+
<CodeBlock label="Procedural textures" code={TEXGEN_SNIPPET} />
|
|
339
|
+
|
|
340
|
+
<h2>Apply a style bundle</h2>
|
|
341
|
+
<CodeBlock label="Style bundle in the runtime" code={BUNDLE_SNIPPET} />
|
|
342
|
+
<p>
|
|
343
|
+
Bundles resolve through <code>GET https://toonlab.io/api/v1/bundles/:slug</code> — public,
|
|
344
|
+
no API key. Pass a full URL to use a self-hosted bundle document instead. Authoring and
|
|
345
|
+
publishing bundles happens in the{' '}
|
|
346
|
+
<a href="https://toonlab.io/styles" target="_blank" rel="noreferrer">bundle builder</a>{' '}
|
|
347
|
+
<ProBadge />.
|
|
348
|
+
</p>
|
|
349
|
+
|
|
350
|
+
<h2>Share your work</h2>
|
|
351
|
+
<p>
|
|
352
|
+
Locally, everything you author lives in portable JSON documents: labs save into the
|
|
353
|
+
disk-backed <code>.toonlab/</code> workspace (shared with the MCP server), and every lab
|
|
354
|
+
can export preset files you can commit to your repo or hand to anyone.
|
|
355
|
+
</p>
|
|
356
|
+
<p>
|
|
357
|
+
Publishing to the public <a href="https://toonlab.io/gallery" target="_blank" rel="noreferrer">gallery</a>{' '}
|
|
358
|
+
<ProBadge /> works through a toonlab.io account: save a creation to your cloud library,
|
|
359
|
+
set its visibility to public, and it gets a permanent page and appears in gallery search —
|
|
360
|
+
loadable by anyone, including by reference from style bundles.
|
|
361
|
+
</p>
|
|
362
|
+
</article>
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* --------------------------------------------------------------------- mcp */
|
|
367
|
+
|
|
368
|
+
const LOCAL_CONFIG = `{
|
|
369
|
+
"mcpServers": {
|
|
370
|
+
"toonlab-local": {
|
|
371
|
+
"command": "npx",
|
|
372
|
+
"args": ["-y", "@call-me-sensei/toonlab@latest", "--workspace", "/absolute/path/to/your-game/.toonlab"]
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}`;
|
|
376
|
+
|
|
377
|
+
const LOCAL_TOOLS = [
|
|
378
|
+
['get_workspace_info', 'Workspace path, migration status, and item counts.'],
|
|
379
|
+
['search_assets', 'Search built-in procedural assets, saved library entries, lab presets, and files on disk.'],
|
|
380
|
+
['get_asset', 'Complete asset, recipe, preset, library entry, or workspace file descriptor by id.'],
|
|
381
|
+
['list_my_creations', 'List the disk-backed library, saved lab documents, presets, imports, and exports.'],
|
|
382
|
+
['get_my_creation', 'Read a saved creation or small workspace file (binary as base64 with a direct path).'],
|
|
383
|
+
['save_creation', 'Save a JSON or text creation into .toonlab/creations so labs and agents share it.'],
|
|
384
|
+
['generate_asset', 'Generate a deterministic, editable asset recipe from a built-in catalog entry (seeded — no credits, no AI).'],
|
|
385
|
+
['search_cc0_assets', 'Search CC0 models, textures, and HDRIs from Poly Haven and ambientCG.'],
|
|
386
|
+
['get_cc0_asset', 'Source, attribution, and download metadata for one CC0 asset.'],
|
|
387
|
+
['import_cc0_asset', 'Download a CC0 asset plus attribution manifest into .toonlab/imports.'],
|
|
388
|
+
['get_generation_capabilities', 'Explains what generation the local server offers (procedural recipes only).'],
|
|
389
|
+
['list_style_labs', 'List the style-domain recipe systems the workspace understands.'],
|
|
390
|
+
['create_style_recipe', 'Author a style-domain recipe document (post, camera, game feel, …).'],
|
|
391
|
+
['generate_style_presets', 'Generate seeded preset variations for a style domain.'],
|
|
392
|
+
['validate_style_document', 'Validate a style recipe/preset document against its schema.'],
|
|
393
|
+
];
|
|
394
|
+
|
|
395
|
+
function Mcp() {
|
|
396
|
+
return (
|
|
397
|
+
<article>
|
|
398
|
+
<div className="docs-eyebrow">Model Context Protocol</div>
|
|
399
|
+
<h1>Connect your AI coding agent</h1>
|
|
400
|
+
<p className="docs-lede">
|
|
401
|
+
The open-source package bundles a local MCP server: stdio transport, no account, no OAuth,
|
|
402
|
+
everything on disk. It shares the <code>.toonlab/</code> workspace with the browser labs,
|
|
403
|
+
so what your agent saves, the labs see — and vice versa.
|
|
404
|
+
</p>
|
|
405
|
+
|
|
406
|
+
<h2>Setup</h2>
|
|
407
|
+
<p>
|
|
408
|
+
With the labs running (<code>npm run dev</code>), open{' '}
|
|
409
|
+
<a href="/settings/" target="_blank" rel="noreferrer">/settings/</a> for a ready-made,
|
|
410
|
+
checkout-specific config to paste into your client. Or configure it directly from npm:
|
|
411
|
+
</p>
|
|
412
|
+
<CodeBlock label="MCP client config" code={LOCAL_CONFIG} />
|
|
413
|
+
<p>
|
|
414
|
+
The workspace directory is created on first use and is ignored by Git by default. See{' '}
|
|
415
|
+
<a href={`${GITHUB}/blob/main/docs/mcp.md`} target="_blank" rel="noreferrer">
|
|
416
|
+
Local MCP and workspace
|
|
417
|
+
</a>{' '}
|
|
418
|
+
for the full layout.
|
|
419
|
+
</p>
|
|
420
|
+
|
|
421
|
+
<h2>Tool reference (local server)</h2>
|
|
422
|
+
<div className="docs-table-wrap">
|
|
423
|
+
<table className="docs-table">
|
|
424
|
+
<thead>
|
|
425
|
+
<tr>
|
|
426
|
+
<th>Tool</th>
|
|
427
|
+
<th>What it does</th>
|
|
428
|
+
</tr>
|
|
429
|
+
</thead>
|
|
430
|
+
<tbody>
|
|
431
|
+
{LOCAL_TOOLS.map(([name, what]) => (
|
|
432
|
+
<tr key={name}>
|
|
433
|
+
<td>{name}</td>
|
|
434
|
+
<td>{what}</td>
|
|
435
|
+
</tr>
|
|
436
|
+
))}
|
|
437
|
+
</tbody>
|
|
438
|
+
</table>
|
|
439
|
+
</div>
|
|
440
|
+
<p>
|
|
441
|
+
Note the boundary: the local <code>generate_asset</code> produces <strong>seeded
|
|
442
|
+
procedural recipes</strong> from the built-in catalog — deterministic and free. AI
|
|
443
|
+
generation (diffusion images, textures, 3D models) is a hosted Pro feature.
|
|
444
|
+
</p>
|
|
445
|
+
|
|
446
|
+
<h2>
|
|
447
|
+
The remote Pro server <ProBadge />
|
|
448
|
+
</h2>
|
|
449
|
+
<div className="docs-callout docs-callout--pro">
|
|
450
|
+
<Crown size={16} aria-hidden />
|
|
451
|
+
<span>
|
|
452
|
+
<a href="https://toonlab.io" target="_blank" rel="noreferrer">toonlab.io</a> hosts a
|
|
453
|
+
remote MCP server at <code>https://toonlab.io/mcp</code> (OAuth, Pro/Team plans) that
|
|
454
|
+
adds an indexed CC0 search with styled previews, AI generation on credits — concept art,
|
|
455
|
+
seamless textures, image→3D chaining — stored characters with reference-image
|
|
456
|
+
consistency, and your cloud library. It composes with the local server; run both. Setup
|
|
457
|
+
and its tool reference:{' '}
|
|
458
|
+
<a href="https://toonlab.io/docs/mcp" target="_blank" rel="noreferrer">
|
|
459
|
+
toonlab.io/docs/mcp
|
|
460
|
+
</a>.
|
|
461
|
+
</span>
|
|
462
|
+
</div>
|
|
463
|
+
</article>
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/* ----------------------------------------------------------------- prompts */
|
|
468
|
+
|
|
469
|
+
function Prompts() {
|
|
470
|
+
return (
|
|
471
|
+
<article>
|
|
472
|
+
<div className="docs-eyebrow">Prompt cookbook</div>
|
|
473
|
+
<h1>Prompts that build games</h1>
|
|
474
|
+
<p className="docs-lede">
|
|
475
|
+
These prompts assume the recommended setup — the runtime installed, the{' '}
|
|
476
|
+
<a href={`${GITHUB}/tree/main/agents`} target="_blank" rel="noreferrer">ToonLab skills</a>{' '}
|
|
477
|
+
copied into your project, and the <a href="#/mcp">local MCP server</a> connected. Recipes
|
|
478
|
+
that need the hosted service are badged <span className="docs-pro">Pro</span>.
|
|
479
|
+
</p>
|
|
480
|
+
|
|
481
|
+
<div className="docs-callout">
|
|
482
|
+
<Lightbulb size={16} aria-hidden />
|
|
483
|
+
<span>
|
|
484
|
+
Pattern: <strong>goal → constraints → definition of done.</strong> Let the agent choose
|
|
485
|
+
APIs (that is what the skills are for), but always give it something observable to
|
|
486
|
+
verify — "until I can walk to the shoreline" beats "set up a world".
|
|
487
|
+
</span>
|
|
488
|
+
</div>
|
|
489
|
+
|
|
490
|
+
<h2>Start a game</h2>
|
|
491
|
+
<PromptBlock
|
|
492
|
+
title="The first prompt"
|
|
493
|
+
prompt={`Using the ToonLab game-dev skill, set up a new Three.js + Vite project with
|
|
494
|
+
@call-me-sensei/toonlab. Build a 1 km seeded open world (archetype "lakeland")
|
|
495
|
+
with the bundled toon-shaded mannequin as the playable character, water, sky,
|
|
496
|
+
the "call_me_sensei" weather preset, post-processing, and a follow camera with
|
|
497
|
+
game feel. Follow the skill's assembly order and frame-loop contract, then run
|
|
498
|
+
the dev server and fix issues until I can walk from spawn to the shoreline
|
|
499
|
+
and swim.`}
|
|
500
|
+
note="The game-dev skill carries the assembly order and the frame-loop contract, so the agent wires update order and render ownership correctly on the first try."
|
|
501
|
+
/>
|
|
502
|
+
|
|
503
|
+
<h2>Dress the world with assets</h2>
|
|
504
|
+
<PromptBlock
|
|
505
|
+
title="CC0 import via the local server"
|
|
506
|
+
prompt={`Use the toonlab-local MCP server to furnish the fishing village: search
|
|
507
|
+
CC0 sources for lanterns, crates, barrels, and a pier (search_cc0_assets),
|
|
508
|
+
import the best fits with import_cc0_asset, and place them with the propgen
|
|
509
|
+
placement pipeline so they are grounded, collided, and LOD'd. Show me what
|
|
510
|
+
came from where with attribution.`}
|
|
511
|
+
note="import_cc0_asset writes the files and an attribution manifest into .toonlab/imports for direct use by the project."
|
|
512
|
+
/>
|
|
513
|
+
<PromptBlock
|
|
514
|
+
title="Procedural set dressing"
|
|
515
|
+
prompt={`Using the ToonLab outdoor-world and rockgen skills, scatter cliff rocks along
|
|
516
|
+
the north ridge and add a stepped stone path from the village to the shrine
|
|
517
|
+
with an arched plank bridge over the river. Keep everything walkable — the
|
|
518
|
+
path should flatten heightAt and register collision.`}
|
|
519
|
+
/>
|
|
520
|
+
<PromptBlock
|
|
521
|
+
title="Seeded recipes from the catalog"
|
|
522
|
+
prompt={`With the toonlab-local MCP server, generate three lantern recipe variations
|
|
523
|
+
(generate_asset from the catalog entry, different seeds), save them as
|
|
524
|
+
creations, and spawn them along the pier so I can compare them in the game.`}
|
|
525
|
+
/>
|
|
526
|
+
|
|
527
|
+
<h2>Textures and style</h2>
|
|
528
|
+
<PromptBlock
|
|
529
|
+
title="Procedural texture with texgen"
|
|
530
|
+
prompt={`Using the ToonLab texture skill, build a mossy stone texture for the shrine
|
|
531
|
+
path with texgen (start from the mossy-bricks preset), tune the ramp toward a
|
|
532
|
+
hand-painted five-stop cel look, and derive normal + AO maps.`}
|
|
533
|
+
/>
|
|
534
|
+
<PromptBlock
|
|
535
|
+
title="AI-generated seamless texture"
|
|
536
|
+
pro
|
|
537
|
+
prompt={`Generate a 2k seamless mossy stone texture through the toonlab remote MCP
|
|
538
|
+
server (kind texture_image) and apply it to the shrine walls. Before
|
|
539
|
+
generating, call get_generation_capabilities and tell me the credit cost.`}
|
|
540
|
+
note="AI generation runs on toonlab.io (Pro plan + credits). The local texgen recipe above is the free procedural alternative."
|
|
541
|
+
/>
|
|
542
|
+
<PromptBlock
|
|
543
|
+
title="Apply a style bundle"
|
|
544
|
+
prompt={`Fetch the public "sakura-dusk" style bundle (fetchStyleBundle in
|
|
545
|
+
@call-me-sensei/toonlab/styles) and apply every filled slot — toon shading,
|
|
546
|
+
sky, water, environment, post — so the whole game matches it. Wire it behind
|
|
547
|
+
a setStyle() function so I can swap bundles later.`}
|
|
548
|
+
/>
|
|
549
|
+
|
|
550
|
+
<h2>Atmosphere and feel</h2>
|
|
551
|
+
<PromptBlock
|
|
552
|
+
title="Weather as drama"
|
|
553
|
+
prompt={`Using the ToonLab weather and lighting skills, add a day/night cycle and a
|
|
554
|
+
thunderstorm that rolls in at dusk: wind ramps in the grass and trees, rain
|
|
555
|
+
streaks and ripples the water, lightning drives the sky flash and the light
|
|
556
|
+
rig, and the storm clears to fireflies at night.`}
|
|
557
|
+
/>
|
|
558
|
+
<PromptBlock
|
|
559
|
+
title="Anime combat feedback"
|
|
560
|
+
prompt={`Using the ToonLab game-feel and vfxgen skills, make the sword swing feel
|
|
561
|
+
anime: 60 ms hit-stop on contact, a camera punch, a trail ribbon that follows
|
|
562
|
+
the blade, impact sparks, and a one-frame white flash on the target. Keep it
|
|
563
|
+
all through the game-feel runtime so time scaling stays consistent.`}
|
|
564
|
+
/>
|
|
565
|
+
|
|
566
|
+
<h2>
|
|
567
|
+
Characters <ProBadge />
|
|
568
|
+
</h2>
|
|
569
|
+
<PromptBlock
|
|
570
|
+
title="Consistent character art"
|
|
571
|
+
pro
|
|
572
|
+
prompt={`Using my stored ToonLab character Yuki (list_characters first to see her
|
|
573
|
+
options), generate a concept of her in the travel cloak, lantern in hand, on
|
|
574
|
+
the pier at dusk. Pass character: { ref: "Yuki", outfit: "travel cloak" } —
|
|
575
|
+
do not re-describe her appearance in the prompt.`}
|
|
576
|
+
note="Stored character profiles with reference-image consistency live on toonlab.io — the server composes appearance, art style, and references automatically."
|
|
577
|
+
/>
|
|
578
|
+
|
|
579
|
+
<h2>Ship the loop</h2>
|
|
580
|
+
<PromptBlock
|
|
581
|
+
title="Iterate with verification"
|
|
582
|
+
prompt={`Play through the current build: spawn, walk to the village, buy the lantern,
|
|
583
|
+
sail past the reef in the storm. Fix anything that breaks the loop — falling
|
|
584
|
+
through terrain, unlit props at night, water clipping in the boat — and rerun
|
|
585
|
+
until the whole sequence works. List what you changed.`}
|
|
586
|
+
/>
|
|
587
|
+
|
|
588
|
+
<p>
|
|
589
|
+
The extended cookbook — including the full Pro generation and character workflows — is at{' '}
|
|
590
|
+
<a href="https://toonlab.io/docs/prompts" target="_blank" rel="noreferrer">
|
|
591
|
+
toonlab.io/docs/prompts
|
|
592
|
+
</a>.
|
|
593
|
+
</p>
|
|
594
|
+
</article>
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/* --------------------------------------------------------------- reference */
|
|
599
|
+
|
|
600
|
+
function slugify(text) {
|
|
601
|
+
return text
|
|
602
|
+
.toLowerCase()
|
|
603
|
+
.replace(/&[a-z]+;|&#\d+;/g, '')
|
|
604
|
+
.replace(/[^\w\s-]/g, '')
|
|
605
|
+
.trim()
|
|
606
|
+
.replace(/\s+/g, '-');
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
let referenceHtmlCache = null;
|
|
610
|
+
|
|
611
|
+
function referenceHtml() {
|
|
612
|
+
if (referenceHtmlCache) return referenceHtmlCache;
|
|
613
|
+
let html = marked.parse(settingsReferenceRaw, { async: false });
|
|
614
|
+
html = html.replace(
|
|
615
|
+
/<h([123])>([^<]+)<\/h\1>/g,
|
|
616
|
+
(_m, level, text) => `<h${level} id="${slugify(text)}">${text}</h${level}>`,
|
|
617
|
+
);
|
|
618
|
+
html = html.replace(/<h1[^>]*>[\s\S]*?<\/h1>/, '');
|
|
619
|
+
html = html.replace(
|
|
620
|
+
/href="([\w-]+\.md)"/g,
|
|
621
|
+
`href="${GITHUB}/blob/main/docs/$1" target="_blank" rel="noreferrer"`,
|
|
622
|
+
);
|
|
623
|
+
referenceHtmlCache = html;
|
|
624
|
+
return html;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
function Reference() {
|
|
628
|
+
const html = useMemo(referenceHtml, []);
|
|
629
|
+
return (
|
|
630
|
+
<article>
|
|
631
|
+
<div className="docs-eyebrow">Generated reference</div>
|
|
632
|
+
<h1>Settings reference</h1>
|
|
633
|
+
<p className="docs-lede">
|
|
634
|
+
Every tunable field in <code>@call-me-sensei/toonlab</code>, generated straight from the
|
|
635
|
+
settings schemas that drive the labs and the debug panel — with type, default, range or
|
|
636
|
+
options, and whether the field is portable (saved in preset documents) or scene/runtime
|
|
637
|
+
state.
|
|
638
|
+
</p>
|
|
639
|
+
<div className="docs-callout">
|
|
640
|
+
<Bot size={16} aria-hidden />
|
|
641
|
+
<span>
|
|
642
|
+
<strong>Using a coding agent?</strong> Point it at the raw markdown source of this page:{' '}
|
|
643
|
+
<code>docs/settings-reference.md</code> in the repo (regenerate with{' '}
|
|
644
|
+
<code>node scripts/generate-settings-reference.mjs</code>), or fetch it from{' '}
|
|
645
|
+
<a href="https://toonlab.io/docs/reference.md" target="_blank" rel="noreferrer">
|
|
646
|
+
toonlab.io/docs/reference.md
|
|
647
|
+
</a>.
|
|
648
|
+
</span>
|
|
649
|
+
</div>
|
|
650
|
+
<div className="docs-md" dangerouslySetInnerHTML={{ __html: html }} />
|
|
651
|
+
</article>
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/* --------------------------------------------------------------------- app */
|
|
656
|
+
|
|
657
|
+
const SECTIONS = [
|
|
658
|
+
{ hash: '', label: 'Overview', component: Overview },
|
|
659
|
+
{ hash: '#/library', label: 'Using the library', component: Library },
|
|
660
|
+
{ hash: '#/mcp', label: 'Connect via MCP', component: Mcp },
|
|
661
|
+
{ hash: '#/prompts', label: 'Prompt cookbook', component: Prompts },
|
|
662
|
+
{ hash: '#/reference', label: 'Settings reference', component: Reference },
|
|
663
|
+
];
|
|
664
|
+
|
|
665
|
+
function activeSection() {
|
|
666
|
+
const hash = window.location.hash;
|
|
667
|
+
return SECTIONS.find((section) => section.hash && hash.startsWith(section.hash)) ?? SECTIONS[0];
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function App() {
|
|
671
|
+
const [section, setSection] = useState(activeSection);
|
|
672
|
+
|
|
673
|
+
useEffect(() => {
|
|
674
|
+
const onHashChange = () => {
|
|
675
|
+
const next = activeSection();
|
|
676
|
+
setSection((prev) => {
|
|
677
|
+
if (prev !== next) window.scrollTo(0, 0);
|
|
678
|
+
return next;
|
|
679
|
+
});
|
|
680
|
+
};
|
|
681
|
+
window.addEventListener('hashchange', onHashChange);
|
|
682
|
+
return () => window.removeEventListener('hashchange', onHashChange);
|
|
683
|
+
}, []);
|
|
684
|
+
|
|
685
|
+
const Body = section.component;
|
|
686
|
+
|
|
687
|
+
return (
|
|
688
|
+
<>
|
|
689
|
+
<header className="docs-header">
|
|
690
|
+
<a className="docs-brand" href="/">
|
|
691
|
+
<span className="docs-brand-mark">ト</span>
|
|
692
|
+
<span className="docs-brand-word">TOONLAB</span>
|
|
693
|
+
<span className="docs-brand-tag">Open Source</span>
|
|
694
|
+
</a>
|
|
695
|
+
<nav className="docs-topnav">
|
|
696
|
+
<a href="/">Labs</a>
|
|
697
|
+
<a href="/gallery/">Gallery</a>
|
|
698
|
+
<a href="/docs/" aria-current="page">Docs</a>
|
|
699
|
+
<a href="/settings/">Settings</a>
|
|
700
|
+
<a href={GITHUB} target="_blank" rel="noreferrer">GitHub</a>
|
|
701
|
+
</nav>
|
|
702
|
+
</header>
|
|
703
|
+
<div className="docs-frame">
|
|
704
|
+
<aside className="docs-side">
|
|
705
|
+
<div className="docs-side-label">Documentation</div>
|
|
706
|
+
<nav className="docs-nav">
|
|
707
|
+
{SECTIONS.map((item) => (
|
|
708
|
+
<a
|
|
709
|
+
key={item.label}
|
|
710
|
+
href={item.hash || '#'}
|
|
711
|
+
className={item === section ? 'active' : undefined}
|
|
712
|
+
onClick={(event) => {
|
|
713
|
+
if (!item.hash) {
|
|
714
|
+
event.preventDefault();
|
|
715
|
+
history.pushState(null, '', window.location.pathname);
|
|
716
|
+
setSection(SECTIONS[0]);
|
|
717
|
+
window.scrollTo(0, 0);
|
|
718
|
+
}
|
|
719
|
+
}}
|
|
720
|
+
>
|
|
721
|
+
{item.label}
|
|
722
|
+
</a>
|
|
723
|
+
))}
|
|
724
|
+
</nav>
|
|
725
|
+
<div className="docs-side-foot">
|
|
726
|
+
<a href={GITHUB} target="_blank" rel="noreferrer">GitHub</a>
|
|
727
|
+
<a href="https://www.npmjs.com/package/@call-me-sensei/toonlab" target="_blank" rel="noreferrer">npm</a>
|
|
728
|
+
<a href="https://toonlab.io/docs" target="_blank" rel="noreferrer">Pro docs</a>
|
|
729
|
+
</div>
|
|
730
|
+
</aside>
|
|
731
|
+
<main className="docs-main">
|
|
732
|
+
<Body />
|
|
733
|
+
</main>
|
|
734
|
+
</div>
|
|
735
|
+
</>
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
createRoot(document.getElementById('app')).render(<App />);
|