@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.
Files changed (205) hide show
  1. package/AGENTS.md +127 -4
  2. package/ATTRIBUTION.md +41 -3
  3. package/README.md +234 -34
  4. package/docs/characters.md +144 -0
  5. package/docs/debug-panel.md +126 -0
  6. package/docs/docs.css +589 -0
  7. package/docs/environment.md +186 -0
  8. package/docs/getting-started.md +180 -0
  9. package/docs/index.html +14 -0
  10. package/docs/lab-architecture.md +100 -0
  11. package/docs/lighting.md +825 -0
  12. package/docs/main.jsx +739 -0
  13. package/docs/mcp.md +97 -0
  14. package/docs/post-processing.md +98 -0
  15. package/docs/settings-reference.md +1878 -0
  16. package/docs/shader-constants.md +77 -0
  17. package/docs/sky.md +182 -0
  18. package/docs/style-labs.md +309 -0
  19. package/docs/texture-lab.md +135 -0
  20. package/docs/toon-shading.md +183 -0
  21. package/docs/tsl-conventions.md +167 -0
  22. package/docs/vegetation-sky.md +275 -0
  23. package/docs/water.md +430 -0
  24. package/docs/weather.md +200 -0
  25. package/docs/world-scale.md +111 -0
  26. package/mcp/server.mjs +610 -0
  27. package/mcp/style-lab-tools.mjs +371 -0
  28. package/mcp/vite-plugin.mjs +174 -0
  29. package/mcp/workspace.mjs +397 -0
  30. package/package.json +64 -5
  31. package/src/ambientfx/INTEGRATION.md +164 -0
  32. package/src/ambientfx/ambientFxPresets.js +83 -0
  33. package/src/ambientfx/ambientFxSettings.js +368 -0
  34. package/src/ambientfx/emitters.js +169 -0
  35. package/src/ambientfx/index.js +5 -0
  36. package/src/ambientfx/particleBackbone.js +493 -0
  37. package/src/ambientfx/stylizedAmbientFx.js +450 -0
  38. package/src/assetlib/ambientcg.js +117 -0
  39. package/src/assetlib/assetRef.js +91 -0
  40. package/src/assetlib/importedEntry.js +40 -0
  41. package/src/assetlib/index.js +23 -0
  42. package/src/assetlib/kaykit.js +192 -0
  43. package/src/assetlib/kaykitStaticIndex.js +700 -0
  44. package/src/assetlib/loadImported.js +143 -0
  45. package/src/assetlib/opensource3d.js +113 -0
  46. package/src/assetlib/polyhaven.js +182 -0
  47. package/src/assetlib/polypizza.js +115 -0
  48. package/src/assetlib/smithsonian.js +214 -0
  49. package/src/assetlib/sources.js +279 -0
  50. package/src/assetlib/zip.js +58 -0
  51. package/src/biome/biomeGenerator.js +385 -0
  52. package/src/biome/biomeRuntime.js +299 -0
  53. package/src/biome/index.js +2 -0
  54. package/src/buildinggen/buildingAsset.js +44 -0
  55. package/src/buildinggen/buildingGrammar.js +311 -0
  56. package/src/buildinggen/buildingMesh.js +451 -0
  57. package/src/buildinggen/buildingPresets.js +46 -0
  58. package/src/buildinggen/buildingRecipe.js +100 -0
  59. package/src/buildinggen/buildingSettings.js +238 -0
  60. package/src/buildinggen/index.js +6 -0
  61. package/src/camera/cameraDirector.js +157 -0
  62. package/src/camera/cameraGenerator.js +367 -0
  63. package/src/camera/cameraRig.js +570 -0
  64. package/src/camera/cameraSettings.js +236 -0
  65. package/src/camera/index.js +7 -0
  66. package/src/catalog/builtinEntries.js +245 -0
  67. package/src/catalog/catalog.js +210 -0
  68. package/src/catalog/index.js +3 -0
  69. package/src/catalog/manifest.js +84 -0
  70. package/src/core/generation.js +529 -0
  71. package/src/environment/environmentRigs.js +21 -1
  72. package/src/environment/environmentSettings.js +4 -0
  73. package/src/environment/environmentSunShadowPass.js +8 -0
  74. package/src/fauna/INTEGRATION.md +174 -0
  75. package/src/fauna/boids.js +861 -0
  76. package/src/fauna/faunaBodies.js +492 -0
  77. package/src/fauna/faunaPresets.js +52 -0
  78. package/src/fauna/faunaSettings.js +525 -0
  79. package/src/fauna/index.js +5 -0
  80. package/src/fauna/stylizedFauna.js +395 -0
  81. package/src/game-feel/gameFeelGenerator.js +402 -0
  82. package/src/game-feel/gameFeelRuntime.js +549 -0
  83. package/src/game-feel/index.js +2 -0
  84. package/src/index.js +17 -6
  85. package/src/lighting/colorIntensity.js +177 -0
  86. package/src/lighting/index.js +161 -0
  87. package/src/lighting/lightDescriptors.js +249 -0
  88. package/src/lighting/lightingCapabilities.js +79 -0
  89. package/src/lighting/lightingDocuments.js +247 -0
  90. package/src/lighting/lightingFixtures.js +446 -0
  91. package/src/lighting/lightingGenerator.js +449 -0
  92. package/src/lighting/lightingPresets.js +319 -0
  93. package/src/lighting/lightingRuntime.js +723 -0
  94. package/src/lighting/lightingStyle.js +386 -0
  95. package/src/lighting/lightingSystem.js +774 -0
  96. package/src/lighting/unrealExport.js +186 -0
  97. package/src/lighting/utils.js +87 -0
  98. package/src/motion/index.js +5 -0
  99. package/src/motion/motionClip.js +441 -0
  100. package/src/motion/motionController.js +628 -0
  101. package/src/motion/motionDocuments.js +225 -0
  102. package/src/motion/motionGraph.js +307 -0
  103. package/src/motion/motionSettings.js +222 -0
  104. package/src/pathgen/index.js +7 -0
  105. package/src/pathgen/pathBridge.js +232 -0
  106. package/src/pathgen/pathPresets.js +35 -0
  107. package/src/pathgen/pathRibbon.js +410 -0
  108. package/src/pathgen/pathRouter.js +380 -0
  109. package/src/pathgen/pathSettings.js +335 -0
  110. package/src/pathgen/pathTextures.js +123 -0
  111. package/src/pathgen/stylizedPaths.js +453 -0
  112. package/src/post/index.js +1 -0
  113. package/src/post/postGenerator.js +177 -0
  114. package/src/post/postProcessing.js +41 -0
  115. package/src/propgen/generatorsWave1.js +379 -0
  116. package/src/propgen/generatorsWave2.js +462 -0
  117. package/src/propgen/index.js +5 -0
  118. package/src/propgen/propAsset.js +323 -0
  119. package/src/propgen/propParts.js +170 -0
  120. package/src/propgen/propPlacement.js +459 -0
  121. package/src/propgen/propPresets.js +82 -0
  122. package/src/propgen/propSettings.js +395 -0
  123. package/src/shaders-tsl/chunks/projected-water-caustics.js +242 -0
  124. package/src/shaders-tsl/chunks/vegetation-style.js +360 -0
  125. package/src/shaders-tsl/chunks/water-shore-state.js +31 -0
  126. package/src/shaders-tsl/chunks/water-waves.js +90 -11
  127. package/src/shaders-tsl/environment.js +15 -1
  128. package/src/shaders-tsl/flower.js +279 -30
  129. package/src/shaders-tsl/grass.js +60 -33
  130. package/src/shaders-tsl/sky.js +125 -31
  131. package/src/shaders-tsl/tree-leaf.js +61 -25
  132. package/src/shaders-tsl/water-breaker.js +7 -4
  133. package/src/shaders-tsl/water-shore-state-simulation.js +523 -0
  134. package/src/shaders-tsl/water.js +439 -49
  135. package/src/shaders-tsl/woody-surface.js +154 -0
  136. package/src/sky/sceneOverrideLayers.js +10 -0
  137. package/src/sky/skyQuality.js +26 -0
  138. package/src/sky/stylizedSky.js +753 -45
  139. package/src/soundscape/index.js +4 -0
  140. package/src/soundscape/soundscapeGenerator.js +179 -0
  141. package/src/soundscape/soundscapeRuntime.js +806 -0
  142. package/src/soundscape/soundscapeSettings.js +292 -0
  143. package/src/styles/index.js +13 -0
  144. package/src/styles/styleBundle.js +325 -0
  145. package/src/stylizedTerrain.js +32 -2
  146. package/src/stylizedWorld.js +423 -20
  147. package/src/texgen/evaluateTexture.js +675 -0
  148. package/src/texgen/index.js +60 -0
  149. package/src/texgen/noise2.js +210 -0
  150. package/src/texgen/textureAi.js +436 -0
  151. package/src/texgen/textureGenerators.js +516 -0
  152. package/src/texgen/texturePresets.js +490 -0
  153. package/src/texgen/textureSettings.js +342 -0
  154. package/src/texgen/textureThree.js +59 -0
  155. package/src/vegetation/flowerSpecies.js +15 -3
  156. package/src/vegetation/grassPalettes.js +153 -0
  157. package/src/vegetation/index.js +6 -0
  158. package/src/vegetation/stylizedBush.js +2 -0
  159. package/src/vegetation/stylizedFlower.js +82 -0
  160. package/src/vegetation/stylizedFlowers.js +48 -7
  161. package/src/vegetation/stylizedForest.js +29 -1
  162. package/src/vegetation/stylizedGrass.js +291 -56
  163. package/src/vegetation/stylizedTree.js +38 -2
  164. package/src/vegetation/stylizedTreeFoliage.js +2 -1
  165. package/src/vegetation/vegetationShaders.js +1110 -0
  166. package/src/vfxgen/INTEGRATION.md +145 -0
  167. package/src/vfxgen/core/burstBackbone.js +380 -0
  168. package/src/vfxgen/core/projectileCore.js +92 -0
  169. package/src/vfxgen/core/spriteShapes.js +98 -0
  170. package/src/vfxgen/core/trailRibbon.js +272 -0
  171. package/src/vfxgen/core/vfxRandom.js +29 -0
  172. package/src/vfxgen/effects/emitHelpers.js +37 -0
  173. package/src/vfxgen/effects/magicEffects.js +162 -0
  174. package/src/vfxgen/effects/movementEffects.js +87 -0
  175. package/src/vfxgen/effects/weaponEffects.js +118 -0
  176. package/src/vfxgen/index.js +18 -0
  177. package/src/vfxgen/moves/moveController.js +146 -0
  178. package/src/vfxgen/moves/moveLibrary.js +335 -0
  179. package/src/vfxgen/vfxPresets.js +98 -0
  180. package/src/vfxgen/vfxSettings.js +384 -0
  181. package/src/vfxgen/vfxSystem.js +449 -0
  182. package/src/vfxgen/weapons/stylizedWeapons.js +137 -0
  183. package/src/villagegen/index.js +4 -0
  184. package/src/villagegen/stylizedVillage.js +490 -0
  185. package/src/villagegen/villageArchetypes.js +160 -0
  186. package/src/villagegen/villageNames.js +40 -0
  187. package/src/villagegen/villageSites.js +105 -0
  188. package/src/water/sceneOverrideLayers.js +23 -0
  189. package/src/water/water.js +5 -0
  190. package/src/water/waterBreakerSystem.js +15 -1
  191. package/src/water/waterCurrentField.js +447 -0
  192. package/src/water/waterMaterial.js +12 -0
  193. package/src/water/waterNearshorePhase.js +320 -0
  194. package/src/water/waterScenePasses.js +83 -30
  195. package/src/water/waterSettings.js +325 -13
  196. package/src/water/waterShoreMaterial.js +322 -0
  197. package/src/water/waterShoreStateField.js +605 -0
  198. package/src/water/waterSurface.js +797 -28
  199. package/src/weather/index.js +6 -0
  200. package/src/weather/weatherPrecipitation.js +221 -0
  201. package/src/weather/weatherPresets.js +258 -0
  202. package/src/weather/weatherSettings.js +269 -0
  203. package/src/weather/weatherSystem.js +871 -0
  204. package/src/worldMinimap.js +62 -0
  205. package/src/worldPresets.js +4 -1
@@ -0,0 +1,4 @@
1
+ export * from './soundscapeSettings.js';
2
+ export * from './soundscapeGenerator.js';
3
+ export * from './soundscapeRuntime.js';
4
+
@@ -0,0 +1,179 @@
1
+ import {
2
+ createGeneratorRecipeDocument,
3
+ deepMerge,
4
+ parseGeneratorRecipeDocument,
5
+ resolveGeneratorRecipe,
6
+ serializeGeneratorRecipeDocument,
7
+ validateGeneratorRecipeDocument,
8
+ } from '../core/generation.js';
9
+ import {
10
+ createSoundscapePresetDocument,
11
+ createSoundscapeSettings,
12
+ sanitizeSoundscapeSettings,
13
+ } from './soundscapeSettings.js';
14
+
15
+ export const SOUNDSCAPE_GENERATOR_DOMAIN = 'soundscape';
16
+
17
+ const range = (min, max, step = 0.01, extra = {}) => Object.freeze({ $type: 'range', max, min, step, ...extra });
18
+ const chance = (probability) => Object.freeze({ $type: 'boolean', probability });
19
+ const choice = (...options) => Object.freeze({ $type: 'choice', options });
20
+
21
+ export const DEFAULT_SOUNDSCAPE_GENERATOR_DOMAINS = Object.freeze({
22
+ adaptive: Object.freeze({
23
+ smoothing: range(0.08, 1.4, 0.01, { distribution: 'log' }),
24
+ values: Object.freeze({
25
+ intensity: range(0.15, 0.78, 0.01),
26
+ tension: range(0, 0.42, 0.01),
27
+ weather: range(0, 0.72, 0.01),
28
+ }),
29
+ }),
30
+ buses: Object.freeze({
31
+ ambience: Object.freeze({ gain: range(0.52, 1.05, 0.01) }),
32
+ detail: Object.freeze({ gain: range(0.24, 0.92, 0.01) }),
33
+ music: Object.freeze({ gain: range(0.12, 0.72, 0.01) }),
34
+ }),
35
+ layers: Object.freeze({
36
+ air: Object.freeze({
37
+ enabled: chance(0.96),
38
+ gain: range(0.12, 0.46, 0.005, { distribution: 'normal', mean: 0.26, deviation: 0.08 }),
39
+ pan: range(-0.32, 0.22, 0.01),
40
+ params: Object.freeze({
41
+ color: choice({ value: 'brown', weight: 3 }, { value: 'pink', weight: 2 }, 'white'),
42
+ highpass: range(38, 220, 1, { distribution: 'log' }),
43
+ lowpass: range(1200, 5200, 10, { distribution: 'log' }),
44
+ movement: range(0.03, 0.48, 0.01),
45
+ }),
46
+ }),
47
+ drone: Object.freeze({
48
+ enabled: chance(0.78),
49
+ gain: range(0.015, 0.18, 0.002, { distribution: 'normal', mean: 0.07, deviation: 0.045 }),
50
+ pan: range(-0.26, 0.26, 0.01),
51
+ params: Object.freeze({
52
+ detune: range(-18, 18, 1),
53
+ frequency: range(48, 196, 0.1, { distribution: 'log' }),
54
+ movement: range(0, 0.24, 0.01),
55
+ waveform: choice({ value: 'sine', weight: 4 }, { value: 'triangle', weight: 2 }, 'sawtooth'),
56
+ }),
57
+ }),
58
+ rustle: Object.freeze({
59
+ enabled: chance(0.82),
60
+ gain: range(0.025, 0.26, 0.005),
61
+ pan: range(-0.64, 0.64, 0.01),
62
+ params: Object.freeze({
63
+ color: choice('pink', 'white', { value: 'brown', weight: 0.5 }),
64
+ highpass: range(420, 2400, 10, { distribution: 'log' }),
65
+ lowpass: range(2800, 11000, 10, { distribution: 'log' }),
66
+ movement: range(0.16, 1.1, 0.01),
67
+ }),
68
+ }),
69
+ wildlife: Object.freeze({
70
+ enabled: chance(0.9),
71
+ gain: range(0.035, 0.28, 0.005),
72
+ pan: range(-0.78, 0.78, 0.01),
73
+ params: Object.freeze({
74
+ density: range(0.035, 0.72, 0.005, { distribution: 'log' }),
75
+ duration: range(0.055, 0.48, 0.005),
76
+ frequency: range(680, 4200, 1, { distribution: 'log' }),
77
+ pitchSpread: range(0.05, 0.72, 0.01),
78
+ waveform: choice({ value: 'sine', weight: 3 }, 'triangle', 'square'),
79
+ }),
80
+ voiceLimit: range(2, 8, 1, { integer: true }),
81
+ }),
82
+ }),
83
+ master: Object.freeze({
84
+ gain: range(0.45, 0.92, 0.01, { distribution: 'normal', mean: 0.69, deviation: 0.1 }),
85
+ limiter: chance(0.94),
86
+ transitionSeconds: range(0.35, 4.8, 0.05, { distribution: 'log' }),
87
+ }),
88
+ transport: Object.freeze({ bpm: range(54, 142, 1, { integer: true }) }),
89
+ });
90
+
91
+ const FAMILIES = new Map([
92
+ ['living-landscape', {
93
+ basePreset: 'living-landscape',
94
+ description: 'Layered procedural air, foliage, wildlife and subtle tonal movement.',
95
+ domains: DEFAULT_SOUNDSCAPE_GENERATOR_DOMAINS,
96
+ label: 'Living Landscape',
97
+ }],
98
+ ['quiet-focus', {
99
+ basePreset: 'minimal-focus',
100
+ description: 'Sparse low-distraction beds for dialogue, building and exploration.',
101
+ domains: deepMerge(DEFAULT_SOUNDSCAPE_GENERATOR_DOMAINS, {
102
+ buses: { detail: { gain: range(0.08, 0.46, 0.01) }, music: { gain: range(0.04, 0.32, 0.01) } },
103
+ layers: {
104
+ drone: { gain: range(0.008, 0.07, 0.001) },
105
+ rustle: { enabled: chance(0.28) },
106
+ wildlife: { gain: range(0.008, 0.09, 0.002), params: { density: range(0.01, 0.18, 0.005) } },
107
+ },
108
+ }),
109
+ label: 'Quiet Focus',
110
+ }],
111
+ ]);
112
+
113
+ export function registerSoundscapeGeneratorFamily(id, definition = {}, { overwrite = false } = {}) {
114
+ const key = String(id ?? '').trim();
115
+ if (!key) throw new Error('Soundscape generator family id is required.');
116
+ if (!overwrite && FAMILIES.has(key)) throw new Error(`Soundscape generator family "${key}" already exists.`);
117
+ FAMILIES.set(key, deepMerge(definition));
118
+ return key;
119
+ }
120
+
121
+ export function getSoundscapeGeneratorFamilyOptions() {
122
+ return [...FAMILIES.entries()].map(([id, definition]) => ({
123
+ description: definition.description ?? '', id, label: definition.label ?? id,
124
+ }));
125
+ }
126
+
127
+ export function createSoundscapeGeneratorRecipe(id = 'generated-soundscape', definition = {}) {
128
+ const family = FAMILIES.get(definition.family ?? 'living-landscape') ?? {};
129
+ const basePreset = definition.basePreset ?? family.basePreset ?? 'living-landscape';
130
+ const baseSettings = createSoundscapeSettings({ preset: basePreset });
131
+ return createGeneratorRecipeDocument(SOUNDSCAPE_GENERATOR_DOMAIN, id, {
132
+ basePreset,
133
+ configuration: deepMerge(baseSettings, family.configuration, definition.configuration),
134
+ description: definition.description ?? family.description ?? '',
135
+ domains: deepMerge(family.domains ?? DEFAULT_SOUNDSCAPE_GENERATOR_DOMAINS, definition.domains),
136
+ label: definition.label ?? id,
137
+ locks: definition.locks ?? [],
138
+ seed: definition.seed ?? 1,
139
+ });
140
+ }
141
+
142
+ export function validateSoundscapeGeneratorRecipe(input) {
143
+ return validateGeneratorRecipeDocument(input, { domain: SOUNDSCAPE_GENERATOR_DOMAIN });
144
+ }
145
+
146
+ export function parseSoundscapeGeneratorRecipe(input) {
147
+ return parseGeneratorRecipeDocument(input, { domain: SOUNDSCAPE_GENERATOR_DOMAIN });
148
+ }
149
+
150
+ export function serializeSoundscapeGeneratorRecipe(idOrDocument, definition = {}, { pretty = true } = {}) {
151
+ return serializeGeneratorRecipeDocument(SOUNDSCAPE_GENERATOR_DOMAIN, idOrDocument, definition, { pretty });
152
+ }
153
+
154
+ export function resolveSoundscapeGeneratorRecipe(recipeInput, { budget, quality = 'balanced' } = {}) {
155
+ const recipe = recipeInput?.type
156
+ ? validateSoundscapeGeneratorRecipe(recipeInput).value
157
+ : createSoundscapeGeneratorRecipe('generated-soundscape', recipeInput);
158
+ if (!recipe) throw new Error('Invalid soundscape generator recipe.');
159
+ const baseSettings = recipe.basePreset == null
160
+ ? sanitizeSoundscapeSettings({})
161
+ : createSoundscapeSettings({ preset: recipe.basePreset });
162
+ return resolveGeneratorRecipe(recipe, {
163
+ baseSettings,
164
+ sanitizeSettings: (settings) => sanitizeSoundscapeSettings(settings, { budget, quality }),
165
+ });
166
+ }
167
+
168
+ export function createGeneratedSoundscapePresetDocument(recipeInput, {
169
+ budget,
170
+ id = recipeInput?.id ? `${recipeInput.id}-resolved` : 'generated-soundscape-resolved',
171
+ label = recipeInput?.label ? `${recipeInput.label} · resolved` : 'Generated Soundscape · resolved',
172
+ quality = 'balanced',
173
+ } = {}) {
174
+ return createSoundscapePresetDocument(id, {
175
+ description: `Resolved from generator seed ${recipeInput?.seed ?? 1}.`,
176
+ label,
177
+ settings: resolveSoundscapeGeneratorRecipe(recipeInput, { budget, quality }),
178
+ });
179
+ }