@3driseai/3drise-core 1.0.19 → 1.0.20

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 (131) hide show
  1. package/dist/animations/index.d.ts +2 -0
  2. package/dist/animations/index.d.ts.map +1 -0
  3. package/dist/animations/index.js +1 -0
  4. package/dist/animations/trackGenerators.d.ts +140 -0
  5. package/dist/animations/trackGenerators.d.ts.map +1 -0
  6. package/dist/animations/trackGenerators.js +443 -0
  7. package/dist/autoAnimate/bounds.d.ts +7 -0
  8. package/dist/autoAnimate/bounds.d.ts.map +1 -0
  9. package/dist/autoAnimate/bounds.js +23 -0
  10. package/dist/autoAnimate/composer.d.ts +30 -0
  11. package/dist/autoAnimate/composer.d.ts.map +1 -0
  12. package/dist/autoAnimate/composer.js +251 -0
  13. package/dist/autoAnimate/describeScene.d.ts +105 -0
  14. package/dist/autoAnimate/describeScene.d.ts.map +1 -0
  15. package/dist/autoAnimate/describeScene.js +165 -0
  16. package/dist/autoAnimate/draft.d.ts +59 -0
  17. package/dist/autoAnimate/draft.d.ts.map +1 -0
  18. package/dist/autoAnimate/draft.js +2 -0
  19. package/dist/autoAnimate/index.d.ts +14 -0
  20. package/dist/autoAnimate/index.d.ts.map +1 -0
  21. package/dist/autoAnimate/index.js +9 -0
  22. package/dist/autoAnimate/recipes.d.ts +87 -0
  23. package/dist/autoAnimate/recipes.d.ts.map +1 -0
  24. package/dist/autoAnimate/recipes.js +224 -0
  25. package/dist/autoAnimate/rng.d.ts +10 -0
  26. package/dist/autoAnimate/rng.d.ts.map +1 -0
  27. package/dist/autoAnimate/rng.js +16 -0
  28. package/dist/autoAnimate/sceneAnalyzer.d.ts +7 -0
  29. package/dist/autoAnimate/sceneAnalyzer.d.ts.map +1 -0
  30. package/dist/autoAnimate/sceneAnalyzer.js +291 -0
  31. package/dist/autoAnimate/types.d.ts +124 -0
  32. package/dist/autoAnimate/types.d.ts.map +1 -0
  33. package/dist/autoAnimate/types.js +1 -0
  34. package/dist/autoAnimate/validator.d.ts +10 -0
  35. package/dist/autoAnimate/validator.d.ts.map +1 -0
  36. package/dist/autoAnimate/validator.js +59 -0
  37. package/dist/data/effectsDefaults.d.ts +4 -0
  38. package/dist/data/effectsDefaults.d.ts.map +1 -1
  39. package/dist/data/effectsDefaults.js +393 -2
  40. package/dist/data/gridsDefaults.d.ts +5 -0
  41. package/dist/data/gridsDefaults.d.ts.map +1 -0
  42. package/dist/data/gridsDefaults.js +290 -0
  43. package/dist/data/index.d.ts +1 -0
  44. package/dist/data/index.d.ts.map +1 -1
  45. package/dist/data/index.js +1 -0
  46. package/dist/data/particlesDefaults.d.ts +3 -1
  47. package/dist/data/particlesDefaults.d.ts.map +1 -1
  48. package/dist/data/particlesDefaults.js +78 -0
  49. package/dist/environment/cloudConfigs.d.ts +313 -0
  50. package/dist/environment/cloudConfigs.d.ts.map +1 -0
  51. package/dist/environment/cloudConfigs.js +342 -0
  52. package/dist/environment/index.d.ts +5 -0
  53. package/dist/environment/index.d.ts.map +1 -0
  54. package/dist/environment/index.js +6 -0
  55. package/dist/environment/landscapeConfigs.d.ts +220 -0
  56. package/dist/environment/landscapeConfigs.d.ts.map +1 -0
  57. package/dist/environment/landscapeConfigs.js +256 -0
  58. package/dist/environment/oceanConfigs.d.ts +293 -0
  59. package/dist/environment/oceanConfigs.d.ts.map +1 -0
  60. package/dist/environment/oceanConfigs.js +380 -0
  61. package/dist/environment/terrainConfigs.d.ts +254 -0
  62. package/dist/environment/terrainConfigs.d.ts.map +1 -0
  63. package/dist/environment/terrainConfigs.js +292 -0
  64. package/dist/index.d.ts +4 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +4 -0
  67. package/dist/properties/index.d.ts +4 -0
  68. package/dist/properties/index.d.ts.map +1 -0
  69. package/dist/properties/index.js +3 -0
  70. package/dist/properties/registry.d.ts +44 -0
  71. package/dist/properties/registry.d.ts.map +1 -0
  72. package/dist/properties/registry.js +343 -0
  73. package/dist/properties/tables/effectsProperties.d.ts +40 -0
  74. package/dist/properties/tables/effectsProperties.d.ts.map +1 -0
  75. package/dist/properties/tables/effectsProperties.js +512 -0
  76. package/dist/properties/tables/geometryProperties.d.ts +38 -0
  77. package/dist/properties/tables/geometryProperties.d.ts.map +1 -0
  78. package/dist/properties/tables/geometryProperties.js +91 -0
  79. package/dist/properties/tables/getPropertyConfig.d.ts +3 -0
  80. package/dist/properties/tables/getPropertyConfig.d.ts.map +1 -0
  81. package/dist/properties/tables/getPropertyConfig.js +16 -0
  82. package/dist/properties/tables/gridProperties.d.ts +6 -0
  83. package/dist/properties/tables/gridProperties.d.ts.map +1 -0
  84. package/dist/properties/tables/gridProperties.js +121 -0
  85. package/dist/properties/tables/index.d.ts +9 -0
  86. package/dist/properties/tables/index.d.ts.map +1 -0
  87. package/dist/properties/tables/index.js +8 -0
  88. package/dist/properties/tables/lightProperties.d.ts +14 -0
  89. package/dist/properties/tables/lightProperties.d.ts.map +1 -0
  90. package/dist/properties/tables/lightProperties.js +263 -0
  91. package/dist/properties/tables/materialBounds.d.ts +33 -0
  92. package/dist/properties/tables/materialBounds.d.ts.map +1 -0
  93. package/dist/properties/tables/materialBounds.js +180 -0
  94. package/dist/properties/tables/optionalProperties.d.ts +83 -0
  95. package/dist/properties/tables/optionalProperties.d.ts.map +1 -0
  96. package/dist/properties/tables/optionalProperties.js +710 -0
  97. package/dist/properties/tables/particlesProperties.d.ts +17 -0
  98. package/dist/properties/tables/particlesProperties.d.ts.map +1 -0
  99. package/dist/properties/tables/particlesProperties.js +334 -0
  100. package/dist/properties/types.d.ts +43 -0
  101. package/dist/properties/types.d.ts.map +1 -0
  102. package/dist/properties/types.js +12 -0
  103. package/dist/services/ShadersLibrary.d.ts +1 -1
  104. package/dist/services/ShadersLibrary.d.ts.map +1 -1
  105. package/dist/shaders/WallpaperGridMaterial.d.ts.map +1 -1
  106. package/dist/shaders/WallpaperGridMaterial.js +6 -1
  107. package/dist/three/GalleryLayoutV.d.ts.map +1 -1
  108. package/dist/three/GalleryLayoutV.js +0 -10
  109. package/dist/three/SceneBuilderV.d.ts.map +1 -1
  110. package/dist/three/SceneBuilderV.js +1 -7
  111. package/dist/types/generativeEffects.d.ts +0 -4
  112. package/dist/types/generativeEffects.d.ts.map +1 -1
  113. package/dist/types/generativeParticles.d.ts +175 -2
  114. package/dist/types/generativeParticles.d.ts.map +1 -1
  115. package/dist/types/objectSettings.d.ts +45 -4
  116. package/dist/types/objectSettings.d.ts.map +1 -1
  117. package/dist/types/scene3d.d.ts +3 -3
  118. package/dist/types/scene3d.d.ts.map +1 -1
  119. package/dist/utils/generativeAnimatable.d.ts +1 -1
  120. package/dist/utils/generativeAnimatable.d.ts.map +1 -1
  121. package/dist/utils/generativeAnimatable.js +7 -1
  122. package/dist/utils/getAnimatableProperties.d.ts +12 -1
  123. package/dist/utils/getAnimatableProperties.d.ts.map +1 -1
  124. package/dist/utils/getAnimatableProperties.js +35 -138
  125. package/dist/utils/index.d.ts +1 -0
  126. package/dist/utils/index.d.ts.map +1 -1
  127. package/dist/utils/index.js +1 -0
  128. package/dist/utils/objectEffects.d.ts +6 -0
  129. package/dist/utils/objectEffects.d.ts.map +1 -0
  130. package/dist/utils/objectEffects.js +5 -0
  131. package/package.json +1 -1
@@ -0,0 +1,710 @@
1
+ // The sky panel's own ranges (SkyControllerUi renders from these). Elevation goes
2
+ // below the horizon for dusk / night; azimuth is signed around north.
3
+ export const skyOptionalProperties = [
4
+ { name: 'turbidity', label: 'Turbidity', description: 'Atmospheric haze, affects sky color and sun intensity', type: 'number', min: 0, max: 20, step: 0.1 },
5
+ { name: 'rayleigh', label: 'Rayleigh', description: 'Rayleigh scattering coefficient for blue light', type: 'number', min: 0, max: 4, step: 0.1 },
6
+ { name: 'mieCoefficient', label: 'Mie Coefficient', description: 'Mie scattering coefficient for particles in atmosphere', type: 'number', min: 0, max: 0.1, step: 0.001 },
7
+ { name: 'mieDirectionalG', label: 'Mie Directional G', description: 'Directional intensity of Mie scattering', type: 'number', min: 0, max: 1, step: 0.01 },
8
+ { name: 'elevation', label: 'Elevation', description: 'Height of the sun above the horizon (negative = below it)', type: 'number', min: -90, max: 90, step: 1, unit: '°' },
9
+ { name: 'azimuth', label: 'Azimuth', description: 'Compass direction of the sun', type: 'number', min: -180, max: 180, step: 1, unit: '°' },
10
+ ];
11
+ export const oceanOptionalProperties = [
12
+ {
13
+ name: 'sunColor',
14
+ description: 'Color of the sun reflection on water',
15
+ type: 'color',
16
+ },
17
+ {
18
+ name: 'waterColor',
19
+ description: 'Base color of the water',
20
+ type: 'color',
21
+ },
22
+ {
23
+ name: 'distortionScale',
24
+ description: 'Intensity of water surface distortion',
25
+ type: 'number',
26
+ min: 0,
27
+ max: 20,
28
+ step: 0.1,
29
+ },
30
+ {
31
+ name: 'waveHeight',
32
+ description: 'Height of the water waves',
33
+ type: 'number',
34
+ min: 0,
35
+ max: 10,
36
+ step: 0.1,
37
+ },
38
+ {
39
+ name: 'speed',
40
+ description: 'Speed of water movement animation',
41
+ type: 'number',
42
+ min: 0,
43
+ max: 2,
44
+ step: 0.01,
45
+ }
46
+ ];
47
+ // Procedural terrain. Built from the renderer's schema the same way the cloud rows
48
+ // are, so a knob added to the shader shows up in the panel with its bounds and its
49
+ // description without anything here being touched.
50
+ import { TERRAIN_SCHEMA, TERRAIN_QUALITY_SCHEMA, OCEAN_SCHEMA, OCEAN_QUALITY_SCHEMA, LANDSCAPE_SCHEMA, LANDSCAPE_AUTOSPLAT_SCHEMA, LANDSCAPE_QUALITY_SCHEMA, } from '../../environment/index.js';
51
+ function toTerrainOptional(schema, type) {
52
+ return schema
53
+ .filter((p) => !p.advanced)
54
+ // A property scoped to a landform is not merely hidden elsewhere - the shader
55
+ // gates it on the type, so it would do nothing.
56
+ .filter((p) => !p.types || !type || p.types.includes(type))
57
+ .map((p) => ({
58
+ name: p.key,
59
+ description: p.unit ? `${p.description} (${p.unit})` : p.description,
60
+ type: 'number',
61
+ min: p.min,
62
+ max: p.max,
63
+ step: p.step,
64
+ ...(p.animatable === false ? { animatable: false } : {}),
65
+ ...(p.unit ? { unit: p.unit } : {}),
66
+ }));
67
+ }
68
+ // The on/off switch is UI state rather than a shader parameter, so it is not in the
69
+ // schema; BaseControllerUi renders a listed boolean as a toggle and persists it
70
+ // immediately, which is the right behaviour for a switch.
71
+ const terrainEnabled = {
72
+ name: 'enabled',
73
+ description: 'Render the terrain',
74
+ type: 'boolean',
75
+ };
76
+ /** Terrain properties for a given landform. Strata, plateau, incision and the dune
77
+ * terms only appear on the types whose shader branch reads them. */
78
+ export const terrainOptionalProperties = (type) => [
79
+ terrainEnabled,
80
+ ...toTerrainOptional(TERRAIN_SCHEMA, type),
81
+ ];
82
+ /**
83
+ * Ocean rows from the renderer's schema.
84
+ *
85
+ * Same mapping as the terrain's with two extra filters, because the ocean has
86
+ * two hosts and a property that is meaningless on one of them is worse than
87
+ * hidden — a row that does nothing reads as a bug in the renderer. The world
88
+ * ocean has no size and no rim; a placed pool has no sea level of its own beyond
89
+ * its transform.
90
+ */
91
+ function toOceanOptional(schema, type, host) {
92
+ return schema
93
+ .filter((p) => !p.advanced)
94
+ .filter((p) => !p.types || !type || p.types.includes(type))
95
+ .filter((p) => !p.hosts || !host || p.hosts.includes(host))
96
+ // Only ranged numbers and colours have a row. `size` is a vector2 the
97
+ // Transform tab already owns for a placed body.
98
+ .filter((p) => !p.kind || p.kind === 'number' || p.kind === 'color' || p.kind === 'boolean')
99
+ .map((p) => ({
100
+ name: p.key,
101
+ description: p.unit ? `${p.description} (${p.unit})` : p.description,
102
+ type: (p.kind ?? 'number'),
103
+ min: p.min,
104
+ max: p.max,
105
+ step: p.step,
106
+ options: p.options,
107
+ ...(p.animatable === false ? { animatable: false } : {}),
108
+ ...(p.unit ? { unit: p.unit } : {}),
109
+ }));
110
+ }
111
+ // The on/off switch is UI state rather than a shader parameter, so it is not in
112
+ // the schema; BaseControllerUi renders a listed boolean as a toggle and persists
113
+ // it immediately, which is the right behaviour for a switch.
114
+ const oceanEnabled = {
115
+ name: 'enabled',
116
+ description: 'Render the water',
117
+ type: 'boolean',
118
+ };
119
+ /** Ocean properties for a given water type and host. */
120
+ export const oceanSurfaceOptionalProperties = (type, host) => [
121
+ oceanEnabled,
122
+ ...toOceanOptional(OCEAN_SCHEMA, type, host),
123
+ ];
124
+ export const oceanQualityOptionalProperties = [
125
+ {
126
+ name: 'receiveShadows',
127
+ description: 'Receive the scene shadow map, so objects cast onto the water',
128
+ type: 'boolean',
129
+ },
130
+ {
131
+ name: 'wireframe',
132
+ description: 'Draw the water surface as wireframe',
133
+ type: 'boolean',
134
+ },
135
+ ...toOceanOptional(OCEAN_QUALITY_SCHEMA),
136
+ ];
137
+ export const terrainQualityOptionalProperties = [
138
+ {
139
+ name: 'receiveShadows',
140
+ description: 'Receive the scene shadow map, so objects cast onto the ground. Terrain-on-terrain shadowing is analytic and unaffected by this',
141
+ type: 'boolean',
142
+ },
143
+ {
144
+ name: 'wireframe',
145
+ description: 'Draw the clipmap rings as wireframe',
146
+ type: 'boolean',
147
+ },
148
+ ...toTerrainOptional(TERRAIN_QUALITY_SCHEMA),
149
+ ];
150
+ // Landscape rows, from the renderer's schema like everything else here. The
151
+ // surface LIST is not in the schema and cannot be: it is an array of objects with
152
+ // their own texture slots, which BaseControllerUi's flat whitelist has no shape
153
+ // for. LandscapeSurfaceList renders it and uses landscapeSurfaceOptionalProperties
154
+ // for the rows inside one surface.
155
+ function toLandscapeOptional(schema, host) {
156
+ return schema
157
+ .filter((p) => !p.advanced)
158
+ .filter((p) => !p.hosts || !host || p.hosts.includes(host))
159
+ .map((p) => ({
160
+ name: p.key,
161
+ description: p.unit ? `${p.description} (${p.unit})` : p.description,
162
+ type: (p.type ?? 'number'),
163
+ min: p.min,
164
+ max: p.max,
165
+ step: p.step,
166
+ options: p.options,
167
+ ...(p.animatable === false ? { animatable: false } : {}),
168
+ ...(p.unit ? { unit: p.unit } : {}),
169
+ }));
170
+ }
171
+ const landscapeEnabled = {
172
+ name: 'enabled',
173
+ description: 'Render the landscape',
174
+ type: 'boolean',
175
+ };
176
+ export const landscapeOptionalProperties = (host) => [
177
+ landscapeEnabled,
178
+ ...toLandscapeOptional(LANDSCAPE_SCHEMA, host),
179
+ ];
180
+ /** Height and slope rules for a generated splat. Only shown when splatSource is
181
+ * 'auto' — with authored maps they would do nothing, and a row that does nothing
182
+ * reads as a bug in the renderer. */
183
+ export const landscapeAutoSplatOptionalProperties = toLandscapeOptional(LANDSCAPE_AUTOSPLAT_SCHEMA);
184
+ export const landscapeQualityOptionalProperties = toLandscapeOptional(LANDSCAPE_QUALITY_SCHEMA);
185
+ /** One surface's rows. Hand-written rather than schema-driven because a surface
186
+ * is not a shader parameter block — it is a material, and its texture slots are
187
+ * rendered by the surface list itself. */
188
+ export const landscapeSurfaceOptionalProperties = [
189
+ { name: 'repeat', description: 'How many times this texture tiles across the whole landscape. The single knob that decides whether the ground reads at the right scale.', type: 'number', min: 1, max: 2000, step: 1 },
190
+ { name: 'normalStrength', description: 'Normal map strength.', type: 'number', min: 0, max: 2, step: 0.01 },
191
+ { name: 'roughness', description: 'Per-surface roughness. Wet mud and dry rock are not the same material.', type: 'number', min: 0.04, max: 1, step: 0.01 },
192
+ { name: 'metalness', description: 'Almost always 0 for ground; wet rock is the exception.', type: 'number', min: 0, max: 1, step: 0.01 },
193
+ { name: 'saturation', description: 'A luma lerp: 0 is greyscale, 1 leaves the texture alone, above 1 pushes.', type: 'number', min: 0, max: 2, step: 0.01 },
194
+ { name: 'heightBlend', description: 'How hard this surface pushes through its neighbours at a transition, using its own height map. 0 cross-fades; 1 lets the texture\u2019s own grain decide.', type: 'number', min: 0, max: 1, step: 0.01 },
195
+ { name: 'tint', description: 'Multiplied into the albedo.', type: 'color' },
196
+ { name: 'aperiodic', description: 'Stochastic tiling: breaks the repeat grid at three fetches instead of one. Worth it on anything the camera gets close to.', type: 'boolean' },
197
+ { name: 'triplanar', description: 'Project on world axes instead of the tile UV, so a vertical face is not a smear. Doubles the fetches for this surface \u2014 cliffs and rock only.', type: 'boolean' },
198
+ { name: 'flipNormalY', description: 'Flip the normal map green channel (DirectX vs OpenGL).', type: 'boolean' },
199
+ ];
200
+ export const textOptionalProperties = [
201
+ {
202
+ name: 'text',
203
+ description: 'Text content to display',
204
+ type: 'string',
205
+ },
206
+ {
207
+ name: 'height',
208
+ description: 'Extrusion depth of the 3D text',
209
+ type: 'number',
210
+ min: 0,
211
+ max: 1,
212
+ step: 0.01,
213
+ },
214
+ {
215
+ name: 'position',
216
+ description: 'Position of the text in 3D space',
217
+ type: 'vector3',
218
+ },
219
+ {
220
+ name: 'scale',
221
+ description: 'Scale of the text object',
222
+ type: 'vector3',
223
+ },
224
+ {
225
+ name: 'bevelSize',
226
+ description: 'Size of the text bevel',
227
+ type: 'number',
228
+ min: 0,
229
+ max: 10,
230
+ step: 0.1,
231
+ },
232
+ {
233
+ name: 'bevelSegments',
234
+ description: 'Number of bevel segments for smoother edges',
235
+ type: 'number',
236
+ min: 1,
237
+ max: 20,
238
+ step: 1,
239
+ },
240
+ {
241
+ name: 'curveSegments',
242
+ description: 'Number of segments for text curves',
243
+ type: 'number',
244
+ min: 1,
245
+ max: 256,
246
+ step: 1,
247
+ },
248
+ {
249
+ name: 'bevelThickness',
250
+ description: 'Thickness of the text bevel',
251
+ type: 'number',
252
+ min: 0,
253
+ max: 0.1,
254
+ step: 0.001,
255
+ },
256
+ {
257
+ name: 'letterSpacing',
258
+ description: 'Spacing between letters',
259
+ type: 'number',
260
+ min: 0,
261
+ max: 1,
262
+ step: 0.01,
263
+ }
264
+ ];
265
+ export const plainOptionalProperties = [
266
+ {
267
+ name: 'materialType',
268
+ description: 'Type of material for the plane',
269
+ type: 'select',
270
+ options: ['reflector', 'refraction', 'transmission', 'wobble', 'distort', 'standard', 'physical', 'basic', 'lambert', 'phong', 'toon', 'normal', 'matcap'],
271
+ },
272
+ {
273
+ name: 'position',
274
+ description: 'Position of the plane in 3D space',
275
+ type: 'vector3',
276
+ },
277
+ {
278
+ name: 'rotation',
279
+ description: 'Rotation of the plane',
280
+ type: 'vector3',
281
+ },
282
+ {
283
+ name: 'scale',
284
+ description: 'Scale of the plane',
285
+ type: 'vector3',
286
+ },
287
+ {
288
+ name: 'size',
289
+ description: 'Width and height of the plane',
290
+ type: 'vector2',
291
+ },
292
+ {
293
+ name: 'color',
294
+ description: 'Base color of the plane',
295
+ type: 'color',
296
+ },
297
+ {
298
+ name: 'blur',
299
+ description: 'Blur amount for reflective materials',
300
+ type: 'vector2',
301
+ },
302
+ {
303
+ name: 'resolution',
304
+ description: 'Resolution for reflective materials',
305
+ type: 'number',
306
+ min: 256,
307
+ max: 4096,
308
+ step: 256,
309
+ },
310
+ {
311
+ name: 'mixBlur',
312
+ description: 'Mix factor for blur effect',
313
+ type: 'number',
314
+ min: 0,
315
+ max: 10,
316
+ step: 0.1,
317
+ },
318
+ {
319
+ name: 'mixStrength',
320
+ description: 'Strength of the reflection mix',
321
+ type: 'number',
322
+ min: 0,
323
+ max: 100,
324
+ step: 1,
325
+ },
326
+ {
327
+ name: 'roughness',
328
+ description: 'Surface roughness of the material',
329
+ type: 'number',
330
+ min: 0,
331
+ max: 1,
332
+ step: 0.01,
333
+ },
334
+ {
335
+ name: 'metalness',
336
+ description: 'Metallic property of the material',
337
+ type: 'number',
338
+ min: 0,
339
+ max: 1,
340
+ step: 0.01,
341
+ },
342
+ {
343
+ name: 'depthScale',
344
+ description: 'Scale factor for depth-based effects',
345
+ type: 'number',
346
+ min: 0,
347
+ max: 5,
348
+ step: 0.1,
349
+ },
350
+ {
351
+ name: 'minDepthThreshold',
352
+ description: 'Minimum depth threshold for effects',
353
+ type: 'number',
354
+ min: 0,
355
+ max: 1,
356
+ step: 0.01,
357
+ },
358
+ {
359
+ name: 'maxDepthThreshold',
360
+ description: 'Maximum depth threshold for effects',
361
+ type: 'number',
362
+ min: 0,
363
+ max: 5,
364
+ step: 0.01,
365
+ }
366
+ ];
367
+ export const meshOptionalProperties = [
368
+ {
369
+ name: 'position',
370
+ description: 'Position of the mesh in 3D space',
371
+ type: 'vector3',
372
+ },
373
+ {
374
+ name: 'rotation',
375
+ description: 'Rotation of the mesh in radians',
376
+ type: 'vector3',
377
+ },
378
+ {
379
+ name: 'scale',
380
+ description: 'Scale factor for each axis',
381
+ type: 'vector3',
382
+ },
383
+ {
384
+ name: 'color',
385
+ description: 'Base color of the mesh material',
386
+ type: 'color',
387
+ },
388
+ {
389
+ name: 'opacity',
390
+ description: 'Transparency of the mesh material',
391
+ type: 'number',
392
+ min: 0,
393
+ max: 1,
394
+ step: 0.01,
395
+ }
396
+ ];
397
+ // The rain panel's knobs (RainControllerUi renders from these).
398
+ export const rainOptionalProperties = [
399
+ { name: 'color', label: 'Color', description: 'Color of rain particles', type: 'color' },
400
+ { name: 'size', label: 'Size', description: 'Size of individual rain particles', type: 'number', min: 0.01, max: 1, step: 0.01 },
401
+ { name: 'opacity', label: 'Opacity', description: 'Transparency of rain particles', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },
402
+ { name: 'speed', label: 'Speed', description: 'Speed of falling rain', type: 'number', min: 0.1, max: 5, step: 0.1, unit: 'x', default: 1 },
403
+ { name: 'density', label: 'Density', description: 'Number of rain particles', type: 'number', min: 1, max: 200, step: 1, default: 100 },
404
+ { name: 'windStrength', label: 'Wind Strength', description: 'How hard the wind pushes the drops sideways', type: 'number', min: 0, max: 1, step: 0.01, default: 0 },
405
+ { name: 'windDirection', label: 'Wind Direction', description: 'Compass direction the wind blows toward', type: 'number', min: 0, max: 360, step: 1, unit: '°', default: 0 },
406
+ { name: 'turbulence', label: 'Turbulence', description: 'Random sway of the drops', type: 'number', min: 0, max: 1, step: 0.01, default: 0 },
407
+ ];
408
+ // A path object's knobs (PathControllerUi renders from these). Structural: they rebuild the line.
409
+ export const pathOptionalProperties = [
410
+ { name: 'pointSize', label: 'Point Size', description: 'Size of the path points', type: 'number', min: 0.05, max: 1, step: 0.05, default: 0.1 },
411
+ { name: 'lineWidth', label: 'Line Width', description: 'Width of the path line', type: 'number', min: 1, max: 10, step: 0.5, default: 2 },
412
+ { name: 'curve', label: 'Curve Smoothness', description: 'Samples per segment of the curve', type: 'number', min: 1, max: 100, step: 1, default: 1 },
413
+ { name: 'smoothCorners', label: 'Smooth Corners', description: 'How much the corners are rounded', type: 'number', min: 0, max: 100, step: 1, default: 0 },
414
+ ];
415
+ // An object's edges (EdgesControllerUi). Tube radius / cube size are in world units
416
+ // (the panel shows millimetres) and rebuild the edge geometry, so they are structural.
417
+ export const edgesOptionalProperties = [
418
+ { name: 'enabled', label: 'Enable Edges', description: 'Draw the object\'s edges', type: 'boolean', default: false },
419
+ { name: 'type', label: 'Type', description: 'How the edges are drawn', type: 'select', options: ['line', 'tube', 'cube', 'particles'], optionLabels: ['Line', 'Tube', 'Cube', 'Particles'], default: 'line' },
420
+ { name: 'tubeRadius', label: 'Tube Radius', description: 'Radius of the edge tubes (type tube)', type: 'number', min: 0.001, max: 0.1, step: 0.001, unit: 'm', default: 0.01 },
421
+ { name: 'cubeSize', label: 'Cube Size', description: 'Size of the edge cubes (type cube)', type: 'number', min: 0.001, max: 0.1, step: 0.001, unit: 'm', default: 0.02 },
422
+ ];
423
+ export const fogOptionalProperties = [
424
+ {
425
+ name: 'color',
426
+ description: 'Color of the fog',
427
+ type: 'color',
428
+ },
429
+ {
430
+ name: 'near',
431
+ description: 'Distance where fog starts to appear',
432
+ type: 'number',
433
+ min: 0.1,
434
+ max: 100,
435
+ step: 0.1,
436
+ },
437
+ {
438
+ name: 'far',
439
+ description: 'Distance where fog reaches maximum density',
440
+ type: 'number',
441
+ min: 1,
442
+ max: 1000,
443
+ step: 1,
444
+ }
445
+ ];
446
+ export const starsOptionalProperties = [
447
+ {
448
+ name: 'rotateSpeed',
449
+ description: 'Speed of stars rotation',
450
+ type: 'number',
451
+ min: 0,
452
+ max: 2,
453
+ step: 0.01,
454
+ },
455
+ {
456
+ name: 'count',
457
+ description: 'Number of stars to display',
458
+ type: 'number',
459
+ min: 10,
460
+ max: 1000,
461
+ step: 10,
462
+ },
463
+ {
464
+ name: 'sep',
465
+ description: 'Separation distance between stars',
466
+ type: 'number',
467
+ min: 1,
468
+ max: 20,
469
+ step: 0.1,
470
+ },
471
+ {
472
+ name: 'color',
473
+ description: 'Color of the stars',
474
+ type: 'color',
475
+ },
476
+ {
477
+ name: 'size',
478
+ description: 'Size of individual stars',
479
+ type: 'number',
480
+ min: 0.01,
481
+ max: 1,
482
+ step: 0.01,
483
+ }
484
+ ];
485
+ export const shootingStarsOptionalProperties = [
486
+ {
487
+ name: 'count',
488
+ description: 'Number of shooting stars active at once',
489
+ type: 'number',
490
+ min: 1,
491
+ max: 50,
492
+ step: 1,
493
+ },
494
+ {
495
+ name: 'speedRange',
496
+ description: 'Min and max speed of shooting stars',
497
+ type: 'vector2',
498
+ min: 0,
499
+ max: 1,
500
+ step: 0.01,
501
+ },
502
+ {
503
+ name: 'lengthRange',
504
+ description: 'Min and max length of shooting star trails',
505
+ type: 'vector2',
506
+ min: 1,
507
+ max: 500,
508
+ step: 1,
509
+ },
510
+ {
511
+ name: 'intervalRange',
512
+ description: 'Min and max seconds between new shooting stars',
513
+ type: 'vector2',
514
+ min: 0.1,
515
+ max: 30,
516
+ step: 0.1,
517
+ },
518
+ {
519
+ name: 'trailLengthRange',
520
+ description: 'Min and max trail fade length',
521
+ type: 'vector2',
522
+ min: 1,
523
+ max: 300,
524
+ step: 1,
525
+ },
526
+ {
527
+ name: 'followMouse',
528
+ description: 'Shooting stars aim toward mouse cursor',
529
+ type: 'boolean',
530
+ },
531
+ ];
532
+ export const hdrOptionalProperties = [
533
+ {
534
+ name: 'name',
535
+ description: 'HDR environment name',
536
+ type: 'select',
537
+ options: ['apartment', 'city', 'forest', 'dawn', 'lobby', 'night', 'park', 'studio', 'sunset', 'warehouse'],
538
+ },
539
+ {
540
+ name: 'url',
541
+ description: 'Custom HDR environment URL',
542
+ type: 'string',
543
+ }
544
+ ];
545
+ export const cloudsOptionalProperties = [
546
+ {
547
+ name: 'cloudColor',
548
+ description: 'Color of the clouds',
549
+ type: 'color',
550
+ },
551
+ {
552
+ name: 'lightColor',
553
+ description: 'Color of the lightning',
554
+ type: 'color',
555
+ },
556
+ {
557
+ name: 'speed',
558
+ description: 'Speed of cloud movement',
559
+ type: 'number',
560
+ },
561
+ {
562
+ name: 'scroll',
563
+ description: 'Scroll factor for cloud texture',
564
+ type: 'number',
565
+ }
566
+ ];
567
+ // =============================================================================
568
+ // Volumetric clouds
569
+ // =============================================================================
570
+ //
571
+ // Derived, not re-typed. The ranges and descriptions live next to the shader in
572
+ // @3driseai/3drise-viewer, so a knob added to the renderer reaches this panel and
573
+ // the AI agent's context without either being edited here. Advanced entries are
574
+ // dropped: they are per-octave scattering constants that are not useful to drag.
575
+ import { CIRRUS_SCHEMA, CLOUD_DECK_SCHEMA, CLOUD_QUALITY_SCHEMA, THUNDER_SCHEMA, } from '../../environment/index.js';
576
+ function toOptional(schema, deckType) {
577
+ return schema
578
+ .filter((p) => !p.advanced)
579
+ // A property scoped to a type is not merely hidden elsewhere — the shader
580
+ // gates it on the vertical profile, so it would do nothing.
581
+ .filter((p) => !p.types || !deckType || p.types.includes(deckType))
582
+ .map((p) => ({
583
+ name: p.key,
584
+ description: p.unit ? `${p.description} (${p.unit})` : p.description,
585
+ type: (p.valueType ?? 'number'),
586
+ min: p.min,
587
+ max: p.max,
588
+ step: p.step,
589
+ ...(p.animatable === false ? { animatable: false } : {}),
590
+ ...(p.unit ? { unit: p.unit } : {}),
591
+ }));
592
+ }
593
+ // The on/off switches are UI state rather than shader parameters, so they are not in
594
+ // the schema; BaseControllerUi renders a listed boolean as a toggle and persists it
595
+ // immediately, which is the right behaviour for a switch.
596
+ const deckEnabled = {
597
+ name: 'enabled',
598
+ description: 'Show the main cloud layer',
599
+ type: 'boolean',
600
+ };
601
+ /** Deck properties for a given type. Anvil and precipitation only appear on a storm. */
602
+ export const cloudDeckOptionalProperties = (deckType) => [
603
+ deckEnabled,
604
+ ...toOptional(CLOUD_DECK_SCHEMA, deckType),
605
+ ];
606
+ export const cirrusOptionalProperties = [
607
+ { name: 'enabled', description: 'Show the high wispy ice layer', type: 'boolean' },
608
+ ...toOptional(CIRRUS_SCHEMA),
609
+ ];
610
+ export const thunderOptionalProperties = [
611
+ { name: 'enabled', description: 'Turn lightning on', type: 'boolean' },
612
+ ...toOptional(THUNDER_SCHEMA),
613
+ ];
614
+ export const cloudQualityOptionalProperties = [
615
+ {
616
+ name: 'tonemap',
617
+ description: 'Let the clouds handle their own final colour balance. Turn this off if you are using post-processing effects, or the image gets processed twice and looks washed out',
618
+ type: 'boolean',
619
+ },
620
+ ...toOptional(CLOUD_QUALITY_SCHEMA),
621
+ ];
622
+ // =============================================================================
623
+ // Gallery layout
624
+ // =============================================================================
625
+ //
626
+ // createdObject.config for a 'gallery' object is one flat GalleryLayoutSettings
627
+ // bag that every layout algorithm in GalleryCreator.ts can read from, but each
628
+ // layout only reads a handful of its fields (see GALLERY_LAYOUT_CONFIGS in
629
+ // GalleryLayouts.ts). A row for a field the active layout ignores does nothing,
630
+ // so the whitelist is built per-layout from that same config.
631
+ import { getLayoutSettingsFields } from '../../utils/GalleryLayouts.js';
632
+ const GALLERY_FIELD_DEFS = {
633
+ columns: { name: 'columns', description: 'Number of columns in the grid', type: 'number', min: 1, max: 12, step: 1 },
634
+ spacing: { name: 'spacing', description: 'Distance between adjacent frames', type: 'number', min: 0.5, max: 10, step: 0.1 },
635
+ startX: { name: 'startX', description: 'Horizontal offset of the first frame', type: 'number', min: -20, max: 20, step: 0.5 },
636
+ startY: { name: 'startY', description: 'Vertical offset of the first frame', type: 'number', min: -20, max: 20, step: 0.5 },
637
+ radius: { name: 'radius', description: 'Radius of the layout', type: 'number', min: 0.5, max: 30, step: 0.5 },
638
+ size: { name: 'size', description: 'Half-size of the box the frames are placed on', type: 'number', min: 1, max: 20, step: 0.5 },
639
+ rotations: { name: 'rotations', description: 'Number of full turns the layout makes', type: 'number', min: 1, max: 10, step: 1 },
640
+ heightIncrement: { name: 'heightIncrement', description: 'Vertical rise per image', type: 'number', min: 0, max: 2, step: 0.05 },
641
+ arcAngle: { name: 'arcAngle', description: 'Total arc the frames are spread across, in radians', type: 'number', min: 0, max: Math.PI * 2, step: 0.05 },
642
+ amplitude: { name: 'amplitude', description: 'Height of the wave motion', type: 'number', min: 0, max: 10, step: 0.1 },
643
+ frequency: { name: 'frequency', description: 'Number of wave oscillations across the gallery', type: 'number', min: 0.1, max: 10, step: 0.1 },
644
+ layers: { name: 'layers', description: 'Number of stacked layers', type: 'number', min: 1, max: 10, step: 1 },
645
+ depth: { name: 'depth', description: 'Total distance the layout recedes into the screen', type: 'number', min: 1, max: 60, step: 1 },
646
+ scaleFactor: { name: 'scaleFactor', description: 'Per-frame shrink factor going into the tunnel', type: 'number', min: 0.1, max: 1, step: 0.01 },
647
+ bounds: { name: 'bounds', description: 'Half-extent of the random placement volume', type: 'number', min: 1, max: 30, step: 0.5 },
648
+ seed: { name: 'seed', description: 'Change to reshuffle the random layout', type: 'number', min: 1, max: 999, step: 1 },
649
+ };
650
+ /** Defaults mirror getInitialLayoutSettings, so a row left blank by a previous
651
+ * layout still shows a sane starting value instead of disappearing. */
652
+ export const GALLERY_FIELD_DEFAULTS = {
653
+ columns: 3,
654
+ width: 1,
655
+ height: 1,
656
+ spacing: 3.5,
657
+ startX: 0,
658
+ startY: 0,
659
+ radius: 5,
660
+ size: 5,
661
+ rotations: 2,
662
+ heightIncrement: 0.5,
663
+ arcAngle: Math.PI,
664
+ amplitude: 2,
665
+ frequency: 2,
666
+ layers: 3,
667
+ depth: 20,
668
+ scaleFactor: 0.8,
669
+ bounds: 8,
670
+ seed: 1,
671
+ outerFrameScale: 1,
672
+ numImages: 20,
673
+ };
674
+ export const galleryCommonProperties = [
675
+ { name: 'outerFrameScale', description: 'Scale of the frame relative to the image', type: 'number', min: 0.1, max: 3, step: 0.05 },
676
+ { name: 'width', description: 'Frame width', type: 'number', min: 0.1, max: 10, step: 0.1 },
677
+ { name: 'height', description: 'Frame height', type: 'number', min: 0.1, max: 10, step: 0.1 },
678
+ { name: 'numImages', description: 'Placeholder image count used only while no images are assigned', type: 'number', min: 1, max: 100, step: 1 },
679
+ ];
680
+ /** Only the layout-math fields the given layout actually reads (LayoutCreator). */
681
+ export const layoutFieldOptionalProperties = (layout) => [
682
+ ...getLayoutSettingsFields(layout)
683
+ .map((field) => GALLERY_FIELD_DEFS[field])
684
+ .filter((def) => !!def),
685
+ ...(layout === 'random' ? [GALLERY_FIELD_DEFS.seed] : []),
686
+ ];
687
+ /** Only the fields GalleryCreator.generateGallery actually reads for this layout. */
688
+ export const galleryLayoutOptionalProperties = (layout) => [
689
+ ...galleryCommonProperties,
690
+ ...layoutFieldOptionalProperties(layout),
691
+ ];
692
+ /** meshSettings.layout — the rows above the per-layout fields in the Transform tab. */
693
+ export const objectLayoutCommonProperties = [
694
+ { name: 'enabled', description: 'Repeat this object across the selected layout', type: 'boolean' },
695
+ { name: 'count', description: 'Number of copies', type: 'number', min: 1, max: 100, step: 1 },
696
+ ];
697
+ // Export all optional properties as a collection for easy access
698
+ export const environmentOptionalProperties = {
699
+ sky: skyOptionalProperties,
700
+ ocean: oceanOptionalProperties,
701
+ terrain: terrainOptionalProperties(),
702
+ text: textOptionalProperties,
703
+ plain: plainOptionalProperties,
704
+ mesh: meshOptionalProperties,
705
+ rain: rainOptionalProperties,
706
+ fog: fogOptionalProperties,
707
+ stars: starsOptionalProperties,
708
+ hdr: hdrOptionalProperties,
709
+ clouds: cloudsOptionalProperties
710
+ };