@3driseai/3drise-core 1.0.21 → 1.0.23

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 (179) hide show
  1. package/dist/autoAnimate/composer.d.ts +6 -0
  2. package/dist/autoAnimate/composer.d.ts.map +1 -1
  3. package/dist/autoAnimate/composer.js +4 -3
  4. package/dist/autoAnimate/describeScene.js +1 -1
  5. package/dist/catalog/catalogInfo.d.ts +22 -0
  6. package/dist/catalog/catalogInfo.d.ts.map +1 -0
  7. package/dist/catalog/catalogInfo.js +204 -0
  8. package/dist/catalog/index.d.ts +3 -0
  9. package/dist/catalog/index.d.ts.map +1 -0
  10. package/dist/catalog/index.js +2 -0
  11. package/dist/catalog/objectCatalog.d.ts +33 -0
  12. package/dist/catalog/objectCatalog.d.ts.map +1 -0
  13. package/dist/catalog/objectCatalog.js +94 -0
  14. package/dist/data/allMaterials.js +2 -2
  15. package/dist/data/defaults.d.ts +0 -12
  16. package/dist/data/defaults.d.ts.map +1 -1
  17. package/dist/data/defaults.js +0 -12
  18. package/dist/data/environmentDefaults.d.ts +10 -0
  19. package/dist/data/environmentDefaults.d.ts.map +1 -0
  20. package/dist/data/environmentDefaults.js +126 -0
  21. package/dist/data/gridsDefaults.d.ts +2 -0
  22. package/dist/data/gridsDefaults.d.ts.map +1 -1
  23. package/dist/data/gridsDefaults.js +57 -0
  24. package/dist/data/index.d.ts +4 -0
  25. package/dist/data/index.d.ts.map +1 -1
  26. package/dist/data/index.js +4 -0
  27. package/dist/data/landDefaults.d.ts +26 -0
  28. package/dist/data/landDefaults.d.ts.map +1 -0
  29. package/dist/data/landDefaults.js +76 -0
  30. package/dist/data/spaceDefaults.d.ts +10 -0
  31. package/dist/data/spaceDefaults.d.ts.map +1 -0
  32. package/dist/data/spaceDefaults.js +46 -0
  33. package/dist/data/textDefaults.d.ts +16 -0
  34. package/dist/data/textDefaults.d.ts.map +1 -0
  35. package/dist/data/textDefaults.js +219 -0
  36. package/dist/environment/oceanConfigs.d.ts +5 -4
  37. package/dist/environment/oceanConfigs.d.ts.map +1 -1
  38. package/dist/environment/oceanConfigs.js +2 -2
  39. package/dist/environment/terrainConfigs.d.ts +78 -0
  40. package/dist/environment/terrainConfigs.d.ts.map +1 -1
  41. package/dist/environment/terrainConfigs.js +72 -2
  42. package/dist/index.d.ts +3 -1
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +3 -1
  45. package/dist/properties/registry.d.ts +15 -1
  46. package/dist/properties/registry.d.ts.map +1 -1
  47. package/dist/properties/registry.js +99 -13
  48. package/dist/properties/tables/environmentProperties.d.ts +9 -0
  49. package/dist/properties/tables/environmentProperties.d.ts.map +1 -0
  50. package/dist/properties/tables/environmentProperties.js +127 -0
  51. package/dist/properties/tables/geometryProperties.d.ts +7 -0
  52. package/dist/properties/tables/geometryProperties.d.ts.map +1 -1
  53. package/dist/properties/tables/geometryProperties.js +9 -1
  54. package/dist/properties/tables/gridProperties.d.ts.map +1 -1
  55. package/dist/properties/tables/gridProperties.js +117 -93
  56. package/dist/properties/tables/index.d.ts +4 -0
  57. package/dist/properties/tables/index.d.ts.map +1 -1
  58. package/dist/properties/tables/index.js +4 -0
  59. package/dist/properties/tables/landProperties.d.ts +5 -0
  60. package/dist/properties/tables/landProperties.d.ts.map +1 -0
  61. package/dist/properties/tables/landProperties.js +24 -0
  62. package/dist/properties/tables/optionalProperties.d.ts +1 -2
  63. package/dist/properties/tables/optionalProperties.d.ts.map +1 -1
  64. package/dist/properties/tables/optionalProperties.js +22 -0
  65. package/dist/properties/tables/spaceProperties.d.ts +8 -0
  66. package/dist/properties/tables/spaceProperties.d.ts.map +1 -0
  67. package/dist/properties/tables/spaceProperties.js +42 -0
  68. package/dist/properties/tables/textProperties.d.ts +4 -0
  69. package/dist/properties/tables/textProperties.d.ts.map +1 -0
  70. package/dist/properties/tables/textProperties.js +387 -0
  71. package/dist/properties/types.d.ts +1 -1
  72. package/dist/properties/types.d.ts.map +1 -1
  73. package/dist/services/MaterialRegistry.d.ts.map +1 -1
  74. package/dist/services/MaterialRegistry.js +2 -0
  75. package/dist/services/SceneActions.d.ts +9 -0
  76. package/dist/services/SceneActions.d.ts.map +1 -1
  77. package/dist/services/SceneActions.js +30 -0
  78. package/dist/services/SkySystemManager.d.ts +22 -0
  79. package/dist/services/SkySystemManager.d.ts.map +1 -1
  80. package/dist/services/SkySystemManager.js +50 -18
  81. package/dist/services/TextureResolver.d.ts.map +1 -1
  82. package/dist/services/TextureResolver.js +22 -0
  83. package/dist/services/index.d.ts +1 -1
  84. package/dist/services/index.d.ts.map +1 -1
  85. package/dist/services/index.js +1 -1
  86. package/dist/shaders/SkyboxMaterial.js +3 -3
  87. package/dist/shaders/StarsMaterial.d.ts +5 -0
  88. package/dist/shaders/StarsMaterial.d.ts.map +1 -1
  89. package/dist/shaders/StarsMaterial.js +59 -57
  90. package/dist/three/LetterV.d.ts +7 -1
  91. package/dist/three/LetterV.d.ts.map +1 -1
  92. package/dist/three/Text2DV.d.ts +7 -1
  93. package/dist/three/Text2DV.d.ts.map +1 -1
  94. package/dist/three/Text3DV.d.ts +7 -1
  95. package/dist/three/Text3DV.d.ts.map +1 -1
  96. package/dist/types/actions.d.ts +6 -6
  97. package/dist/types/actions.d.ts.map +1 -1
  98. package/dist/types/commands.d.ts +61 -0
  99. package/dist/types/commands.d.ts.map +1 -0
  100. package/dist/types/commands.js +1 -0
  101. package/dist/types/environment.d.ts +34 -1
  102. package/dist/types/environment.d.ts.map +1 -1
  103. package/dist/types/environment.js +15 -0
  104. package/dist/types/environmentObjects.d.ts +152 -0
  105. package/dist/types/environmentObjects.d.ts.map +1 -0
  106. package/dist/types/environmentObjects.js +10 -0
  107. package/dist/types/index.d.ts +5 -2
  108. package/dist/types/index.d.ts.map +1 -1
  109. package/dist/types/landObjects.d.ts +15 -0
  110. package/dist/types/landObjects.d.ts.map +1 -0
  111. package/dist/types/landObjects.js +1 -0
  112. package/dist/types/objectSettings.d.ts +189 -16
  113. package/dist/types/objectSettings.d.ts.map +1 -1
  114. package/dist/types/objectsConfigs.d.ts +0 -3
  115. package/dist/types/objectsConfigs.d.ts.map +1 -1
  116. package/dist/types/scene3d.d.ts +12 -5
  117. package/dist/types/scene3d.d.ts.map +1 -1
  118. package/dist/types/spaceObjects.d.ts +65 -0
  119. package/dist/types/spaceObjects.d.ts.map +1 -0
  120. package/dist/types/spaceObjects.js +11 -0
  121. package/dist/types/textObjects.d.ts +371 -0
  122. package/dist/types/textObjects.d.ts.map +1 -0
  123. package/dist/types/textObjects.js +14 -0
  124. package/dist/types/types.d.ts +3 -6
  125. package/dist/types/types.d.ts.map +1 -1
  126. package/dist/types/users.d.ts +3 -1
  127. package/dist/types/users.d.ts.map +1 -1
  128. package/dist/types/users.js +2 -0
  129. package/dist/ui/index.d.ts +5 -0
  130. package/dist/ui/index.d.ts.map +1 -0
  131. package/dist/ui/index.js +4 -0
  132. package/dist/ui/uiBindings.d.ts +45 -0
  133. package/dist/ui/uiBindings.d.ts.map +1 -0
  134. package/dist/ui/uiBindings.js +172 -0
  135. package/dist/ui/uiKeys.d.ts +14 -0
  136. package/dist/ui/uiKeys.d.ts.map +1 -0
  137. package/dist/ui/uiKeys.js +22 -0
  138. package/dist/ui/uiSanitize.d.ts +18 -0
  139. package/dist/ui/uiSanitize.d.ts.map +1 -0
  140. package/dist/ui/uiSanitize.js +251 -0
  141. package/dist/ui/uiSpec.d.ts +116 -0
  142. package/dist/ui/uiSpec.d.ts.map +1 -0
  143. package/dist/ui/uiSpec.js +173 -0
  144. package/dist/utils/dataUtils.d.ts.map +1 -1
  145. package/dist/utils/dataUtils.js +0 -6
  146. package/dist/utils/environmentMigration.d.ts +3 -0
  147. package/dist/utils/environmentMigration.d.ts.map +1 -0
  148. package/dist/utils/environmentMigration.js +50 -0
  149. package/dist/utils/generativeAnimatable.d.ts +1 -1
  150. package/dist/utils/generativeAnimatable.d.ts.map +1 -1
  151. package/dist/utils/generativeAnimatable.js +12 -0
  152. package/dist/utils/getAnimatableProperties.d.ts +1 -1
  153. package/dist/utils/getAnimatableProperties.d.ts.map +1 -1
  154. package/dist/utils/getAnimatableProperties.js +1 -1
  155. package/dist/utils/gridMigration.d.ts +3 -0
  156. package/dist/utils/gridMigration.d.ts.map +1 -0
  157. package/dist/utils/gridMigration.js +34 -0
  158. package/dist/utils/index.d.ts +6 -0
  159. package/dist/utils/index.d.ts.map +1 -1
  160. package/dist/utils/index.js +6 -0
  161. package/dist/utils/objectEffects.d.ts +24 -2
  162. package/dist/utils/objectEffects.d.ts.map +1 -1
  163. package/dist/utils/objectEffects.js +28 -2
  164. package/dist/utils/objectMigration.d.ts +9 -0
  165. package/dist/utils/objectMigration.d.ts.map +1 -0
  166. package/dist/utils/objectMigration.js +13 -0
  167. package/dist/utils/skyPhase.d.ts +61 -0
  168. package/dist/utils/skyPhase.d.ts.map +1 -0
  169. package/dist/utils/skyPhase.js +93 -0
  170. package/dist/utils/spaceMigration.d.ts +3 -0
  171. package/dist/utils/spaceMigration.d.ts.map +1 -0
  172. package/dist/utils/spaceMigration.js +46 -0
  173. package/dist/utils/sunUtils.d.ts +26 -1
  174. package/dist/utils/sunUtils.d.ts.map +1 -1
  175. package/dist/utils/sunUtils.js +37 -6
  176. package/dist/utils/textMigration.d.ts +3 -0
  177. package/dist/utils/textMigration.d.ts.map +1 -0
  178. package/dist/utils/textMigration.js +56 -0
  179. package/package.json +1 -1
@@ -7,6 +7,11 @@ export declare const RAIN_ANIMATABLE_KEYS: readonly ["color", "size", "opacity",
7
7
  * renderer, so they have no material properties. They animate through config.
8
8
  */
9
9
  export declare const SELF_MANAGED_MATERIAL_TYPES: Set<string>;
10
+ /** True when the object draws with its own shaders (the object types above): it gets no material specs. */
11
+ export declare const selfManagesMaterial: (obj: {
12
+ type?: string;
13
+ config?: unknown;
14
+ } | null | undefined) => boolean;
10
15
  /** camelCase → "Title Case" (same as toAnimatableLabel). */
11
16
  export declare const propertyLabel: (key: string) => string;
12
17
  export declare function getSettingAtPath(obj: unknown, path: string): unknown;
@@ -29,13 +34,22 @@ export declare function isPropertyLive(element: PropertyElement, spec: PropertyS
29
34
  export declare function getAnimatableSpecs(element: PropertyElement, settings: any): PropertySpec[];
30
35
  /**
31
36
  * Object config families the animation timeline keys. The V2 applier drives
32
- * `config.*` through the object's live config handle, which these four register;
37
+ * `config.*` through the object's live config handle, which these seven register;
33
38
  * rain and the legacy cloud object have per-frame knobs for the keyframe /
34
39
  * mouse-move systems only.
35
40
  */
36
41
  export declare const TRACK_CONFIG_DOMAINS: ReadonlySet<PropertyDomain>;
37
42
  /** What an animation clip can key on this element (timeline track picker, AI clips). */
38
43
  export declare function getTrackSpecs(element: PropertyElement, settings: any): PropertySpec[];
44
+ /**
45
+ * Structural properties a clip can key as DISCRETE tracks (timeline): not writable per
46
+ * frame, so the clip sets them at its keys — the runtime lays the values at the playhead
47
+ * over the element's settings through the SceneActions patch layer, like an action, and
48
+ * the element re-renders. Every domain qualifies (it goes through the settings path, not
49
+ * a live handle); textures don't (no key editor for them). Not filtered by
50
+ * isPropertyLive: the switch that turns a layer on is itself one of these.
51
+ */
52
+ export declare function getDiscreteTrackSpecs(element: PropertyElement, settings: any): PropertySpec[];
39
53
  export declare function getPropertySpec(element: PropertyElement, settings: any, key: string): PropertySpec | undefined;
40
54
  /** Specs with the element's current values. */
41
55
  export declare function describeProperties(element: PropertyElement, settings: any): DescribedProperty[];
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/properties/registry.ts"],"names":[],"mappings":"AA8CA,OAAO,EACH,KAAK,gBAAgB,EAMxB,MAAM,6BAA6B,CAAC;AAOrC,OAAO,KAAK,EACR,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAkB,YAAY,EACjG,MAAM,SAAS,CAAC;AAMjB,0CAA0C;AAC1C,eAAO,MAAM,oBAAoB,+FAAgG,CAAC;AAUlI;;;GAGG;AACH,eAAO,MAAM,2BAA2B,aAAoD,CAAC;AAmB7F,4DAA4D;AAC5D,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MACiC,CAAC;AAE9E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOpE;AAID,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAaxE;AAgCD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,MAAM,SAAK,EAAE,MAAM,GAAE,cAAyB,GAAG,YAAY,EAAE,CAExH;AAuLD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,EAAE,CAIxF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAInG;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,EAAE,CAE1F;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,cAAc,CAAqE,CAAC;AAEnI,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,EAAE,CAIrF;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE9G;AAED,+CAA+C;AAC/C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,iBAAiB,EAAE,CAE/F;AAED,wHAAwH;AACxH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,eAC+E,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/properties/registry.ts"],"names":[],"mappings":"AAuDA,OAAO,EACH,KAAK,gBAAgB,EAMxB,MAAM,6BAA6B,CAAC;AAWrC,OAAO,KAAK,EACR,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,YAAY,EAAkB,YAAY,EACjG,MAAM,SAAS,CAAC;AAMjB,0CAA0C;AAC1C,eAAO,MAAM,oBAAoB,+FAAgG,CAAC;AAUlI;;;GAGG;AACH,eAAO,MAAM,2BAA2B,aAA4F,CAAC;AAErI,2GAA2G;AAC3G,eAAO,MAAM,mBAAmB,GAAI,KAAK;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,KAAG,OAClC,CAAC;AAmBjE,4DAA4D;AAC5D,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MACiC,CAAC;AAE9E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOpE;AAID,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAaxE;AAgCD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,MAAM,SAAK,EAAE,MAAM,GAAE,cAAyB,GAAG,YAAY,EAAE,CAExH;AAkOD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,EAAE,CAIxF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,GAAG,OAAO,CAUnG;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,EAAE,CAE1F;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,CAAC,cAAc,CAA6G,CAAC;AAE3K,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,EAAE,CAIrF;AAgBD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,EAAE,CAG7F;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAE9G;AAED,+CAA+C;AAC/C,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,GAAG,GAAG,iBAAiB,EAAE,CAE/F;AAED,wHAAwH;AACxH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,eAC+E,CAAC"}
@@ -2,13 +2,21 @@ import { LIGHTS_ANIMATABLE } from '../data/lightsDefaults.js';
2
2
  import { GENERATIVE_PARTICLES_ANIMATABLE } from '../data/particlesDefaults.js';
3
3
  import { EFFECTS_ANIMATABLE } from '../data/effectsDefaults.js';
4
4
  import { GRIDS_ANIMATABLE } from '../data/gridsDefaults.js';
5
+ import { ENVIRONMENT_OBJECTS_ANIMATABLE } from '../data/environmentDefaults.js';
6
+ import { LAND_OBJECTS_ANIMATABLE } from '../data/landDefaults.js';
7
+ import { SPACE_OBJECTS_ANIMATABLE } from '../data/spaceDefaults.js';
8
+ import { TEXT_OBJECTS_ANIMATABLE } from '../data/textDefaults.js';
5
9
  import { CLOUD_ANIMATABLE_PROPERTIES } from '../environment/cloudConfigs.js';
6
- import { skyOptionalProperties, cloudDeckOptionalProperties, cirrusOptionalProperties, oceanSurfaceOptionalProperties, terrainOptionalProperties, rainOptionalProperties, cloudsOptionalProperties, textOptionalProperties, plainOptionalProperties, pathOptionalProperties, edgesOptionalProperties, } from './tables/optionalProperties.js';
10
+ import { skyOptionalProperties, skyStarsOptionalProperties, cloudDeckOptionalProperties, cirrusOptionalProperties, thunderOptionalProperties, oceanSurfaceOptionalProperties, terrainOptionalProperties, rainOptionalProperties, cloudsOptionalProperties, plainOptionalProperties, pathOptionalProperties, edgesOptionalProperties, } from './tables/optionalProperties.js';
7
11
  import { SHAPE_CONTROLS, MODE_CONTROLS } from './tables/geometryProperties.js';
8
12
  import { LIGHT_PROPERTIES, SHADOW_PROPERTIES } from './tables/lightProperties.js';
9
13
  import { PARTICLES_PROPERTIES } from './tables/particlesProperties.js';
10
14
  import { EFFECT_PROPERTIES } from './tables/effectsProperties.js';
11
15
  import { GRID_PROPERTIES } from './tables/gridProperties.js';
16
+ import { ENVIRONMENT_PROPERTIES } from './tables/environmentProperties.js';
17
+ import { LAND_PROPERTIES } from './tables/landProperties.js';
18
+ import { SPACE_PROPERTIES } from './tables/spaceProperties.js';
19
+ import { TEXT_PROPERTIES } from './tables/textProperties.js';
12
20
  import { MATERIAL_PROPERTY_BOUNDS } from './tables/materialBounds.js';
13
21
  // =============================================================================
14
22
  // Data owned here (was inline in getAnimatableProperties / the timeline)
@@ -26,7 +34,9 @@ const MATERIAL_STRUCTURAL = new Set([
26
34
  * Objects that own their shader: their materialSettings (if any) never reach the
27
35
  * renderer, so they have no material properties. They animate through config.
28
36
  */
29
- export const SELF_MANAGED_MATERIAL_TYPES = new Set(['effect', 'grid', 'light', 'particles']);
37
+ export const SELF_MANAGED_MATERIAL_TYPES = new Set(['effect', 'grid', 'light', 'particles', 'environment', 'space', 'land', 'text']);
38
+ /** True when the object draws with its own shaders (the object types above): it gets no material specs. */
39
+ export const selfManagesMaterial = (obj) => !!obj && SELF_MANAGED_MATERIAL_TYPES.has(obj.type);
30
40
  const CAMERA_SPECS = [
31
41
  { key: 'position', name: 'position', label: 'Position', kind: 'vec3', domain: 'camera', animatable: true },
32
42
  { key: 'controls.target', name: 'target', label: 'Target', kind: 'vec3', domain: 'camera', animatable: true },
@@ -178,6 +188,8 @@ function controlSpecs(controls, prefix, group) {
178
188
  animatable: false,
179
189
  default: c.default,
180
190
  };
191
+ if (c.type === 'select')
192
+ spec.options = c.options.map((value, i) => (c.optionLabels?.[i] ? { value, label: c.optionLabels[i] } : { value }));
181
193
  if (c.type === 'range') {
182
194
  spec.min = c.min;
183
195
  spec.max = c.max;
@@ -188,6 +200,13 @@ function controlSpecs(controls, prefix, group) {
188
200
  return spec;
189
201
  });
190
202
  }
203
+ /** Environment families animate by the environment rule (numbers and colours unless the schema opts out). */
204
+ const envFamily = (domain, list, prefix) => ({
205
+ domain,
206
+ list,
207
+ prefix,
208
+ animatable: new Map(list.filter(envAnimatable).map(p => [p.name, p.label ?? propertyLabel(p.name)])),
209
+ });
191
210
  const tableOf = (rows) => new Map((rows ?? []).map(r => [r.value, r.label]));
192
211
  /** The config family of an object: by object type, else by config.type (as getAnimatableProperties does). */
193
212
  function familyOf(obj) {
@@ -197,6 +216,19 @@ function familyOf(obj) {
197
216
  const particles = () => ({ domain: 'particles', list: PARTICLES_PROPERTIES[t] ?? [], animatable: tableOf(GENERATIVE_PARTICLES_ANIMATABLE[t]) });
198
217
  const effect = () => ({ domain: 'effect', list: EFFECT_PROPERTIES[t] ?? [], animatable: tableOf(EFFECTS_ANIMATABLE[t]) });
199
218
  const grid = () => ({ domain: 'grid', list: GRID_PROPERTIES[t] ?? [], animatable: tableOf(GRIDS_ANIMATABLE[t]) });
219
+ const environment = () => ({ domain: 'environment', list: ENVIRONMENT_PROPERTIES[t] ?? [], animatable: tableOf(ENVIRONMENT_OBJECTS_ANIMATABLE[t]) });
220
+ const space = () => ({ domain: 'space', list: SPACE_PROPERTIES[t] ?? [], animatable: tableOf(SPACE_OBJECTS_ANIMATABLE[t]) });
221
+ const land = () => ({ domain: 'land', list: LAND_PROPERTIES[t] ?? [], animatable: tableOf(LAND_OBJECTS_ANIMATABLE[t]) });
222
+ const text = () => ({ domain: 'text', list: TEXT_PROPERTIES[t] ?? [], animatable: tableOf(TEXT_OBJECTS_ANIMATABLE[t]) });
223
+ // Environment elements seen through the object view, so the Animation and
224
+ // MouseMove panels (getAnimatableProperties) work on them like on any object.
225
+ // The sky is flat — no config block — so it is keyed before the config.type gate.
226
+ if (type === 'sky')
227
+ return envFamily('sky', skyOptionalProperties, '');
228
+ if (type === 'ocean' && obj?.config)
229
+ return envFamily('ocean', oceanSurfaceOptionalProperties(obj.config.waterType, obj.config.host), 'config.');
230
+ if (type === 'terrain' && obj?.config)
231
+ return envFamily('terrain', terrainOptionalProperties(obj.config.terrainType), 'config.');
200
232
  if (t) {
201
233
  if (type === 'light')
202
234
  return light();
@@ -206,6 +238,18 @@ function familyOf(obj) {
206
238
  return effect();
207
239
  if (type === 'grid')
208
240
  return grid();
241
+ // Before the rain branch: the rain *object* is a family member; the branch below is the scene-level rain element.
242
+ if (type === 'environment' && ENVIRONMENT_OBJECTS_ANIMATABLE[t])
243
+ return environment();
244
+ // Space objects only under their own object type: their keys ('stars', 'earth'…) are too generic to match by config.type alone.
245
+ if (type === 'space' && SPACE_OBJECTS_ANIMATABLE[t])
246
+ return space();
247
+ // Land objects only under their own object type: their keys are landform names ('hills'…).
248
+ if (type === 'land' && LAND_OBJECTS_ANIMATABLE[t])
249
+ return land();
250
+ // Text looks only under the text object type (plain, handwriting, …).
251
+ if (type === 'text' && TEXT_OBJECTS_ANIMATABLE[t])
252
+ return text();
209
253
  if (t === 'rain')
210
254
  return { domain: 'rain', list: rainOptionalProperties, animatable: new Map(RAIN_ANIMATABLE_KEYS.map(k => [k, propertyLabel(k)])) };
211
255
  if (t === 'clouds')
@@ -220,8 +264,6 @@ function familyOf(obj) {
220
264
  if (GENERATIVE_PARTICLES_ANIMATABLE[t])
221
265
  return particles();
222
266
  }
223
- if (type === 'text')
224
- return { domain: 'config', list: textOptionalProperties, animatable: null };
225
267
  if (type === 'plain')
226
268
  return { domain: 'config', list: plainOptionalProperties, animatable: null };
227
269
  if (type === 'path')
@@ -239,11 +281,11 @@ function configSpecs(obj) {
239
281
  const family = familyOf(obj);
240
282
  if (!family)
241
283
  return [];
242
- const { domain, list, animatable } = family;
284
+ const { domain, list, animatable, prefix = 'config.' } = family;
243
285
  const out = [];
244
286
  const seen = new Set();
245
287
  for (const p of list) {
246
- const spec = fromOptional(p, 'config.', domain, !!animatable?.has(p.name));
288
+ const spec = fromOptional(p, prefix, domain, !!animatable?.has(p.name));
247
289
  out.push(spec);
248
290
  seen.add(p.name);
249
291
  }
@@ -252,7 +294,16 @@ function configSpecs(obj) {
252
294
  if (seen.has(name))
253
295
  continue;
254
296
  const kind = kindOfValue(name, obj?.config?.[name]) ?? 'number';
255
- out.push({ key: `config.${name}`, name, label: label || propertyLabel(name), kind, domain, animatable: true });
297
+ out.push({ key: `${prefix}${name}`, name, label: label || propertyLabel(name), kind, domain, animatable: true });
298
+ }
299
+ // Text's draw / erase trigger (config.shown: on plays the draw animation, off the erase).
300
+ // Its controller shows it as the Shown button; the per-look tables don't list it.
301
+ if (domain === 'text' && !seen.has('shown')) {
302
+ out.push({
303
+ key: `${prefix}shown`, name: 'shown', label: 'Shown',
304
+ description: 'The draw / erase trigger: switching it on plays the draw animation, off plays the erase animation (the text then stays hidden)',
305
+ kind: 'boolean', domain, animatable: false, default: true,
306
+ });
256
307
  }
257
308
  if (domain === 'light') {
258
309
  for (const p of SHADOW_PROPERTIES[obj.config.type] ?? []) {
@@ -264,7 +315,7 @@ function configSpecs(obj) {
264
315
  function objectSpecs(obj) {
265
316
  if (!obj)
266
317
  return [];
267
- const ownsMaterial = !SELF_MANAGED_MATERIAL_TYPES.has(obj.type);
318
+ const ownsMaterial = !selfManagesMaterial(obj);
268
319
  return [
269
320
  ...TRANSFORM_SPECS,
270
321
  ...(ownsMaterial ? materialSpecs(obj.materialSettings, 'materialSettings.', 'material') : []),
@@ -278,11 +329,15 @@ function objectSpecs(obj) {
278
329
  function environmentSpecs(element, settings) {
279
330
  switch (element) {
280
331
  case 'sky':
281
- return envSpecs(skyOptionalProperties, '', 'sky');
332
+ return [
333
+ ...envSpecs(skyOptionalProperties, '', 'sky'),
334
+ ...envSpecs(skyStarsOptionalProperties, 'stars.', 'stars'),
335
+ ];
282
336
  case 'clouds':
283
337
  return [
284
338
  ...envSpecs(cloudDeckOptionalProperties(settings?.config?.deckType), 'config.', 'clouds'),
285
339
  ...envSpecs(cirrusOptionalProperties, 'cirrus.', 'cirrus'),
340
+ ...envSpecs(thunderOptionalProperties, 'thunder.', 'thunder'),
286
341
  ];
287
342
  case 'ocean':
288
343
  return envSpecs(oceanSurfaceOptionalProperties(settings?.config?.waterType, settings?.config?.host), 'config.', 'ocean');
@@ -310,8 +365,16 @@ export function getPropertySpecs(element, settings) {
310
365
  export function isPropertyLive(element, spec, settings) {
311
366
  if (spec.domain === 'edges')
312
367
  return settings?.edgesSettings?.enabled !== false;
313
- if (element === 'clouds')
314
- return spec.domain === 'cirrus' ? !!settings?.cirrus?.enabled : !!settings?.config?.enabled;
368
+ if (element === 'clouds') {
369
+ if (spec.domain === 'cirrus')
370
+ return !!settings?.cirrus?.enabled;
371
+ // Lightning needs cloud to strike in: the deck, and the thunder block itself.
372
+ if (spec.domain === 'thunder')
373
+ return !!settings?.config?.enabled && (spec.name === 'enabled' || !!settings?.thunder?.enabled);
374
+ return !!settings?.config?.enabled;
375
+ }
376
+ if (spec.domain === 'stars')
377
+ return settings?.stars?.visible !== false;
315
378
  return true;
316
379
  }
317
380
  /** Properties that can be driven per frame on this element right now. */
@@ -320,11 +383,11 @@ export function getAnimatableSpecs(element, settings) {
320
383
  }
321
384
  /**
322
385
  * Object config families the animation timeline keys. The V2 applier drives
323
- * `config.*` through the object's live config handle, which these four register;
386
+ * `config.*` through the object's live config handle, which these seven register;
324
387
  * rain and the legacy cloud object have per-frame knobs for the keyframe /
325
388
  * mouse-move systems only.
326
389
  */
327
- export const TRACK_CONFIG_DOMAINS = new Set(['light', 'particles', 'effect', 'grid']);
390
+ export const TRACK_CONFIG_DOMAINS = new Set(['light', 'particles', 'effect', 'grid', 'environment', 'space', 'land', 'text']);
328
391
  /** What an animation clip can key on this element (timeline track picker, AI clips). */
329
392
  export function getTrackSpecs(element, settings) {
330
393
  const specs = getAnimatableSpecs(element, settings);
@@ -332,6 +395,29 @@ export function getTrackSpecs(element, settings) {
332
395
  return specs;
333
396
  return specs.filter(s => s.domain === 'transform' || s.domain === 'material' || s.domain === 'edges' || TRACK_CONFIG_DOMAINS.has(s.domain));
334
397
  }
398
+ /**
399
+ * Text settings that configure HOW it draws / erases / replays — read only when a draw or
400
+ * erase starts, so keying them changes nothing you'd see. The timeline drives text with
401
+ * Shown (config.enabled) instead; these stay panel settings.
402
+ */
403
+ const TEXT_LIFECYCLE = new Set([
404
+ 'drawMethod', 'drawDuration', 'drawEase', 'drawStagger', 'drawAngle',
405
+ 'eraseMethod', 'eraseDuration', 'eraseEase', 'eraseStagger', 'eraseAngle',
406
+ 'autoPlay', 'loop', 'yoyo', 'holdTime', 'hiddenTime',
407
+ ]);
408
+ /** Kinds a structural (discrete) track can hold: a key value the timeline can edit. */
409
+ const DISCRETE_KINDS = new Set(['number', 'boolean', 'string', 'select', 'color', 'vec3', 'vec2']);
410
+ /**
411
+ * Structural properties a clip can key as DISCRETE tracks (timeline): not writable per
412
+ * frame, so the clip sets them at its keys — the runtime lays the values at the playhead
413
+ * over the element's settings through the SceneActions patch layer, like an action, and
414
+ * the element re-renders. Every domain qualifies (it goes through the settings path, not
415
+ * a live handle); textures don't (no key editor for them). Not filtered by
416
+ * isPropertyLive: the switch that turns a layer on is itself one of these.
417
+ */
418
+ export function getDiscreteTrackSpecs(element, settings) {
419
+ return getPropertySpecs(element, settings).filter(s => !s.animatable && DISCRETE_KINDS.has(s.kind) && !(s.domain === 'text' && TEXT_LIFECYCLE.has(s.name)));
420
+ }
335
421
  export function getPropertySpec(element, settings, key) {
336
422
  return getPropertySpecs(element, settings).find(s => s.key === key);
337
423
  }
@@ -0,0 +1,9 @@
1
+ import type { OptionalProperty } from './optionalProperties';
2
+ import type { EnvironmentObjectType } from '../../types/environmentObjects';
3
+ export declare const snowEnvironmentProperties: OptionalProperty[];
4
+ export declare const sandstormEnvironmentProperties: OptionalProperty[];
5
+ export declare const rainbowEnvironmentProperties: OptionalProperty[];
6
+ export declare const tornadoEnvironmentProperties: OptionalProperty[];
7
+ export declare const thunderstormEnvironmentProperties: OptionalProperty[];
8
+ export declare const ENVIRONMENT_PROPERTIES: Record<EnvironmentObjectType, OptionalProperty[]>;
9
+ //# sourceMappingURL=environmentProperties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"environmentProperties.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/environmentProperties.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAO5E,eAAO,MAAM,yBAAyB,EAAE,gBAAgB,EAuBvD,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,gBAAgB,EAsB5D,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,gBAAgB,EAU1D,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,gBAAgB,EAyB1D,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,gBAAgB,EAqB/D,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,qBAAqB,EAAE,gBAAgB,EAAE,CAgBpF,CAAC"}
@@ -0,0 +1,127 @@
1
+ // =============================================================================
2
+ // ENVIRONMENT OBJECTS OPTIONAL PROPERTIES (generated: gen_family.mjs)
3
+ // Order: selects, base, variant, wind, colours, pointer (pointer* -> Pointer tab).
4
+ // =============================================================================
5
+ export const snowEnvironmentProperties = [
6
+ { name: 'quality', description: 'Detail level: scales the number of flakes (rebuilds)', type: 'select', options: ['low', 'medium', 'high'], optionLabels: ['Low', 'Medium', 'High'] },
7
+ { name: 'intensity', description: 'Overall brightness of the snow', type: 'number', min: 0, max: 2, step: 0.01 },
8
+ { name: 'speed', description: 'Time scale of the whole fall: flakes, gusts and eddies', type: 'number', min: 0, max: 3, step: 0.01 },
9
+ { name: 'opacity', description: 'Overall opacity', type: 'number', min: 0, max: 1, step: 0.01 },
10
+ { name: 'density', description: 'How heavily it snows (rebuilds)', type: 'number', min: 0.1, max: 3, step: 0.05 },
11
+ { name: 'flakeSize', description: 'Mean flake diameter; bigger flakes fall faster', type: 'number', min: 0.01, max: 0.12, step: 0.001, unit: 'm' },
12
+ { name: 'flutter', description: 'Side-to-side spiral of the falling flakes', type: 'number', min: 0, max: 1, step: 0.01 },
13
+ { name: 'tumble', description: 'How much the crystals rock and flip as they fall', type: 'number', min: 0, max: 1, step: 0.01 },
14
+ { name: 'glint', description: 'Sparkle of sunlight off the tumbling crystals', type: 'number', min: 0, max: 2, step: 0.01 },
15
+ { name: 'windStrength', description: 'Mean wind (1 = 8 m/s)', type: 'number', min: 0, max: 1, step: 0.01 },
16
+ { name: 'windDirection', description: 'Compass direction the wind blows toward', type: 'number', min: 0, max: 360, step: 1, unit: '°' },
17
+ { name: 'turbulence', description: 'Swirling eddies on top of the wind', type: 'number', min: 0, max: 1, step: 0.01 },
18
+ { name: 'gustiness', description: 'Strength of the gust waves that sweep downwind', type: 'number', min: 0, max: 1, step: 0.01 },
19
+ { name: 'bands', description: 'How strongly the gusts gather the snow into sweeping curtains', type: 'number', min: 0, max: 1, step: 0.01 },
20
+ { name: 'seed', description: 'Random layout of the flakes (rebuilds)', type: 'number', min: 1, max: 999, step: 1 },
21
+ { name: 'followCamera', description: 'Keep snowing around the camera wherever it goes, ignoring the sides of the volume', type: 'boolean' },
22
+ { name: 'color', description: 'Colour of the snow, lit by the sun and the sky', type: 'color' },
23
+ { name: 'shadeColor', description: 'Sky-lit shade on the side away from the sun', type: 'color' },
24
+ { name: 'pointerMode', description: 'What the cursor is: off, a gust of air, a shelter the snow slides off, or a warm hand that melts it', type: 'select', options: ['none', 'gust', 'shelter', 'warmth'], optionLabels: ['Off', 'Gust', 'Shelter', 'Warmth'] },
25
+ { name: 'pointerStrength', description: 'Force of the gust, width of the clearing, heat of the hand', type: 'number', min: 0, max: 3, step: 0.01 },
26
+ { name: 'pointerRadius', description: 'Reach of the cursor (1 = 2 m)', type: 'number', min: 0.2, max: 3, step: 0.01 },
27
+ { name: 'pointerColor', description: 'Warm glow of the melting droplets (Warmth)', type: 'color' },
28
+ ];
29
+ export const sandstormEnvironmentProperties = [
30
+ { name: 'quality', description: 'Detail level: scales the counts and the volume samples (rebuilds)', type: 'select', options: ['low', 'medium', 'high'], optionLabels: ['Low', 'Medium', 'High'] },
31
+ { name: 'intensity', description: 'Overall brightness', type: 'number', min: 0, max: 2, step: 0.01 },
32
+ { name: 'speed', description: 'Time scale of the storm: billows, gust fronts and grains', type: 'number', min: 0, max: 3, step: 0.01 },
33
+ { name: 'opacity', description: 'Overall opacity', type: 'number', min: 0, max: 1, step: 0.01 },
34
+ { name: 'density', description: 'How thick the dust is (rebuilds)', type: 'number', min: 0.1, max: 3, step: 0.05 },
35
+ { name: 'height', description: 'Scale height of the dust, as a share of the volume height', type: 'number', min: 0.05, max: 1, step: 0.01 },
36
+ { name: 'walls', description: 'Strength of the gust fronts: towering walls of dust rolling downwind', type: 'number', min: 0, max: 1, step: 0.01 },
37
+ { name: 'haze', description: 'Fine dust hanging everywhere between the walls', type: 'number', min: 0, max: 1, step: 0.01 },
38
+ { name: 'grains', description: 'Sand grains hopping along the ground', type: 'number', min: 0, max: 2, step: 0.01 },
39
+ { name: 'grainSize', description: 'Size and hop length of the grains', type: 'number', min: 0.3, max: 3, step: 0.01 },
40
+ { name: 'windStrength', description: 'Mean wind (1 = 8 m/s)', type: 'number', min: 0, max: 1, step: 0.01 },
41
+ { name: 'windDirection', description: 'Compass direction the wind blows toward', type: 'number', min: 0, max: 360, step: 1, unit: '°' },
42
+ { name: 'turbulence', description: 'How strongly the billows are warped and torn', type: 'number', min: 0, max: 1, step: 0.01 },
43
+ { name: 'seed', description: 'Random layout (rebuilds)', type: 'number', min: 1, max: 999, step: 1 },
44
+ { name: 'followCamera', description: 'Keep the weather around the camera wherever it goes, ignoring the sides of the volume', type: 'boolean' },
45
+ { name: 'color', description: 'Colour of the dust (its albedo: thick dust tints everything behind it)', type: 'color' },
46
+ { name: 'shadeColor', description: 'Sky-lit colour of the dust in shadow', type: 'color' },
47
+ { name: 'pointerMode', description: 'What the cursor is: off, a windbreak with still air behind it, a dust devil, or a gust', type: 'select', options: ['none', 'windbreak', 'devil', 'gust'], optionLabels: ['Off', 'Windbreak', 'Dust devil', 'Gust'] },
48
+ { name: 'pointerStrength', description: 'How still the lee, how strong the devil, how hard the gust', type: 'number', min: 0, max: 3, step: 0.01 },
49
+ { name: 'pointerRadius', description: 'Reach of the cursor (1 = 3 m)', type: 'number', min: 0.2, max: 3, step: 0.01 },
50
+ { name: 'pointerColor', description: 'Glow of the dust lifted by the dust devil', type: 'color' },
51
+ ];
52
+ export const rainbowEnvironmentProperties = [
53
+ { name: 'intensity', description: 'Brightness of the bow', type: 'number', min: 0, max: 2, step: 0.01 },
54
+ { name: 'opacity', description: 'Overall opacity', type: 'number', min: 0, max: 1, step: 0.01 },
55
+ { name: 'dropSize', description: 'Raindrop diameter: big drops give a narrow, vivid bow; small ones pale fringes inside it; fog drops a white fogbow', type: 'number', min: 0.03, max: 3, step: 0.01, unit: 'mm' },
56
+ { name: 'secondary', description: 'Strength of the secondary bow outside the primary (reversed colours, ~51°); 0 = a single rainbow', type: 'number', min: 0, max: 1, step: 0.01 },
57
+ { name: 'color', description: 'Tint of the bow (white = the pure spectrum)', type: 'color' },
58
+ { name: 'pointerMode', description: 'What the cursor is: off, a mist spray that brightens the bow, a clearing that wipes it, or a polarising filter that fades it as it turns', type: 'select', options: ['none', 'spray', 'clear', 'polarizer'], optionLabels: ['Off', 'Mist spray', 'Clearing', 'Polarising filter'] },
59
+ { name: 'pointerStrength', description: 'Brightness of the sprayed stretch, depth of the clearing, strength of the filter', type: 'number', min: 0, max: 3, step: 0.01 },
60
+ { name: 'pointerRadius', description: 'Reach of the spray or clearing (1 = 6 m)', type: 'number', min: 0.2, max: 3, step: 0.01 },
61
+ { name: 'pointerColor', description: 'Tint of the bow in the sprayed mist', type: 'color' },
62
+ ];
63
+ export const tornadoEnvironmentProperties = [
64
+ { name: 'quality', description: 'Detail level: scales the counts and the volume samples (rebuilds)', type: 'select', options: ['low', 'medium', 'high'], optionLabels: ['Low', 'Medium', 'High'] },
65
+ { name: 'intensity', description: 'Overall brightness', type: 'number', min: 0, max: 2, step: 0.01 },
66
+ { name: 'speed', description: 'Time scale of the whole vortex', type: 'number', min: 0, max: 3, step: 0.01 },
67
+ { name: 'opacity', description: 'Overall opacity', type: 'number', min: 0, max: 1, step: 0.01 },
68
+ { name: 'density', description: 'How opaque the funnel and dust are (rebuilds)', type: 'number', min: 0.1, max: 3, step: 0.05 },
69
+ { name: 'rotation', description: 'Spin rate of the vortex', type: 'number', min: 0, max: 3, step: 0.01 },
70
+ { name: 'coreRadius', description: 'Radius of the core, and so the width of the funnel', type: 'number', min: 0.3, max: 3, step: 0.01 },
71
+ { name: 'reach', description: 'How far down the condensation funnel reaches (1 = touchdown)', type: 'number', min: 0, max: 1, step: 0.01 },
72
+ { name: 'wander', description: 'How much the axis wanders and bends like a rope', type: 'number', min: 0, max: 1, step: 0.01 },
73
+ { name: 'lift', description: 'Updraft: how fast the streaks and dust climb', type: 'number', min: 0, max: 3, step: 0.01 },
74
+ { name: 'dust', description: 'Ground dust drawn in and swirled up around the funnel', type: 'number', min: 0, max: 2, step: 0.01 },
75
+ { name: 'dustSpread', description: 'How far out the dust swirls', type: 'number', min: 0.2, max: 3, step: 0.01 },
76
+ { name: 'windStrength', description: 'Mean wind (1 = 8 m/s)', type: 'number', min: 0, max: 1, step: 0.01 },
77
+ { name: 'windDirection', description: 'Compass direction the wind blows toward', type: 'number', min: 0, max: 360, step: 1, unit: '°' },
78
+ { name: 'turbulence', description: 'Raggedness of the flow', type: 'number', min: 0, max: 1, step: 0.01 },
79
+ { name: 'seed', description: 'Random layout (rebuilds)', type: 'number', min: 1, max: 999, step: 1 },
80
+ { name: 'followCamera', description: 'Keep the volume centred on the camera horizontally', type: 'boolean' },
81
+ { name: 'color', description: 'Colour of the condensation funnel', type: 'color' },
82
+ { name: 'shadeColor', description: 'Storm-light colour in shadow', type: 'color' },
83
+ { name: 'dustColor', description: 'Colour of the swirling dust', type: 'color' },
84
+ { name: 'pointerMode', description: 'What the cursor does: off, steers the foot of the tornado, feeds its inflow, or bends it with a gust', type: 'select', options: ['none', 'steer', 'feed', 'gust'], optionLabels: ['Off', 'Steer', 'Feed', 'Gust'] },
85
+ { name: 'pointerStrength', description: 'How far it steers, how much it feeds, how hard it bends', type: 'number', min: 0, max: 3, step: 0.01 },
86
+ { name: 'pointerRadius', description: 'Height span of the bend (Gust)', type: 'number', min: 0.2, max: 3, step: 0.01 },
87
+ { name: 'pointerColor', description: 'Colour of the dust the cursor feeds in', type: 'color' },
88
+ ];
89
+ export const thunderstormEnvironmentProperties = [
90
+ { name: 'quality', description: 'Detail level: scales the counts and the volume samples (rebuilds)', type: 'select', options: ['low', 'medium', 'high'], optionLabels: ['Low', 'Medium', 'High'] },
91
+ { name: 'intensity', description: 'Overall brightness', type: 'number', min: 0, max: 2, step: 0.01 },
92
+ { name: 'speed', description: 'Time scale of the drifting curtains and the flashes', type: 'number', min: 0, max: 3, step: 0.01 },
93
+ { name: 'opacity', description: 'Overall opacity', type: 'number', min: 0, max: 1, step: 0.01 },
94
+ { name: 'density', description: 'How thick the storm curtains are (rebuilds)', type: 'number', min: 0.1, max: 3, step: 0.05 },
95
+ { name: 'shafts', description: 'Visibility of the dark storm curtains', type: 'number', min: 0, max: 1, step: 0.01 },
96
+ { name: 'flashRate', description: 'Lightning flashes per minute (random intervals)', type: 'number', min: 0, max: 30, step: 0.1 },
97
+ { name: 'flashIntensity', description: 'Brightness of a flash, on the curtains and on the scene', type: 'number', min: 0, max: 3, step: 0.01 },
98
+ { name: 'windStrength', description: 'Mean wind (1 = 8 m/s)', type: 'number', min: 0, max: 1, step: 0.01 },
99
+ { name: 'windDirection', description: 'Compass direction the wind blows toward', type: 'number', min: 0, max: 360, step: 1, unit: '°' },
100
+ { name: 'turbulence', description: 'How ragged the curtains are', type: 'number', min: 0, max: 1, step: 0.01 },
101
+ { name: 'seed', description: 'Random layout (rebuilds)', type: 'number', min: 1, max: 999, step: 1 },
102
+ { name: 'followCamera', description: 'Keep the weather around the camera wherever it goes, ignoring the sides of the volume', type: 'boolean' },
103
+ { name: 'color', description: 'Colour of the curtains in the light', type: 'color' },
104
+ { name: 'shadeColor', description: 'Storm-dark tint of the curtains', type: 'color' },
105
+ { name: 'flashColor', description: 'Colour of the lightning', type: 'color' },
106
+ { name: 'pointerMode', description: 'What the cursor is: off, calls a strike where you sweep, or a clearing swept through the murk', type: 'select', options: ['none', 'strike', 'clear'], optionLabels: ['Off', 'Call a strike', 'Clearing'] },
107
+ { name: 'pointerStrength', description: 'How easily a sweep calls a strike, how deep the clearing', type: 'number', min: 0, max: 3, step: 0.01 },
108
+ { name: 'pointerRadius', description: 'Reach of the clearing (1 = 2 m)', type: 'number', min: 0.2, max: 3, step: 0.01 },
109
+ { name: 'pointerColor', description: 'Colour of the strikes the cursor calls', type: 'color' },
110
+ ];
111
+ export const ENVIRONMENT_PROPERTIES = {
112
+ snow: snowEnvironmentProperties,
113
+ sandstorm: sandstormEnvironmentProperties,
114
+ rainbow: rainbowEnvironmentProperties,
115
+ tornado: tornadoEnvironmentProperties,
116
+ thunderstorm: thunderstormEnvironmentProperties,
117
+ rain: [
118
+ { name: 'color', description: 'Colour of the drops', type: 'color' },
119
+ { name: 'size', description: 'Streak size', type: 'number', min: 0.01, max: 1, step: 0.01 },
120
+ { name: 'opacity', description: 'Opacity of the drops', type: 'number', min: 0, max: 1, step: 0.01 },
121
+ { name: 'speed', description: 'Fall speed', type: 'number', min: 0.1, max: 5, step: 0.1, unit: 'x' },
122
+ { name: 'density', description: 'How many drops fill the volume (rebuilds)', type: 'number', min: 1, max: 200, step: 1 },
123
+ { name: 'windStrength', description: 'How hard the wind pushes the drops sideways', type: 'number', min: 0, max: 1, step: 0.01 },
124
+ { name: 'windDirection', description: 'Compass direction the wind blows toward', type: 'number', min: 0, max: 360, step: 1, unit: '°' },
125
+ { name: 'turbulence', description: 'Random sway of the drops', type: 'number', min: 0, max: 1, step: 0.01 },
126
+ ],
127
+ };
@@ -20,6 +20,13 @@ export type ControlOf<K extends string> = {
20
20
  key: K;
21
21
  label: string;
22
22
  default: string;
23
+ } | {
24
+ type: 'select';
25
+ key: K;
26
+ label: string;
27
+ options: string[];
28
+ optionLabels?: string[];
29
+ default: string;
23
30
  };
24
31
  type OptKey = keyof GeometryShapeConfig & string;
25
32
  export declare const SHAPE_CONTROLS: Record<ShapeName, ControlOf<OptKey>[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"geometryProperties.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/geometryProperties.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE9G,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAClC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GACjK;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAU7D,KAAK,MAAM,GAAG,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAGjD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAuCjE,CAAC;AAEF,eAAO,MAAM,UAAU,EAAkC,SAAS,EAAE,CAAC;AAErE,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,SAAmB,GAAG,mBAAmB,CAIlF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,SAAmB,GAAG,mBAAmB,CAEjF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,WAAqB,GAAG,UAAU,CAEzE;AAED,KAAK,MAAM,GAAG,MAAM,UAAU,GAAG,MAAM,CAAC;AAIxC,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAYlE,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,WAAW,EAAE,CAAA;CAAE,EAInE,CAAC;AAGF,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAYlD,CAAC"}
1
+ {"version":3,"file":"geometryProperties.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/geometryProperties.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAG9G,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,MAAM,IAClC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;CAAE,GACjK;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAY3G,KAAK,MAAM,GAAG,MAAM,mBAAmB,GAAG,MAAM,CAAC;AAGjD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CA4CjE,CAAC;AAEF,eAAO,MAAM,UAAU,EAAkC,SAAS,EAAE,CAAC;AAErE,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,SAAmB,GAAG,mBAAmB,CAIlF;AAED,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,SAAmB,GAAG,mBAAmB,CAEjF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,WAAqB,GAAG,UAAU,CAEzE;AAED,KAAK,MAAM,GAAG,MAAM,UAAU,GAAG,MAAM,CAAC;AAIxC,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAYlE,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,WAAW,EAAE,CAAA;CAAE,EAInE,CAAC;AAGF,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAYlD,CAAC"}
@@ -1,7 +1,10 @@
1
+ import { TEXT_FONTS } from '../../data/textDefaults.js';
1
2
  const int = (key, label, min, max, def) => ({ type: 'range', key, label, min, max, step: 1, default: def });
2
3
  const num = (key, label, min, max, step, def) => ({ type: 'range', key, label, min, max, step, default: def, digits: 2 });
3
4
  const ang = (key, label, def) => ({ type: 'range', key, label, min: 0, max: Math.PI * 2, step: 0.05, default: def, digits: 2, unit: 'rad' });
4
5
  const str = (key, label, def) => ({ type: 'text', key, label, default: def });
6
+ const sel = (key, label, options, optionLabels, def) => ({ type: 'select', key, label, options, optionLabels, default: def });
7
+ const tog = (key, label, def) => ({ type: 'toggle', key, label, default: def });
5
8
  const CURVE = int('curveSegments', 'Curve detail', 6, 160, 64);
6
9
  export const SHAPE_CONTROLS = {
7
10
  heart: [CURVE],
@@ -39,7 +42,12 @@ export const SHAPE_CONTROLS = {
39
42
  arcPlane: [num('radius', 'Radius', 0.2, 3, 0.01, 1), num('width', 'Band width', 0.02, 1, 0.01, 0.2), ang('startAngle', 'Start angle', 0), ang('endAngle', 'End angle', Math.PI), int('segments', 'Segments', 3, 128, 32)],
40
43
  bentPlane: [num('radius', 'Radius', 0.2, 5, 0.01, 2), num('height', 'Height', 0.1, 3, 0.01, 1), ang('arc', 'Arc', Math.PI / 2), int('widthSegments', 'Width segments', 1, 64, 32), int('heightSegments', 'Height segments', 1, 64, 1)],
41
44
  bentPlaneInverse: [num('radius', 'Radius', 0.2, 5, 0.01, 2), num('height', 'Height', 0.1, 3, 0.01, 1), ang('arc', 'Arc', Math.PI / 2), int('widthSegments', 'Width segments', 1, 64, 32), int('heightSegments', 'Height segments', 1, 64, 1)],
42
- text: [str('text', 'Text', 'Hello'), num('size', 'Size', 0.2, 3, 0.01, 1), num('height', 'Depth', 0.05, 1, 0.01, 0.2)],
45
+ // the string extruded into a solid from the packed outline fonts (the text looks' font list)
46
+ text: [
47
+ str('text', 'Text', 'Hello'), sel('font', 'Font', TEXT_FONTS.map((f) => f.id), TEXT_FONTS.map((f) => f.label), 'inter'),
48
+ num('size', 'Size', 0.2, 3, 0.01, 1), num('height', 'Depth', 0.02, 1, 0.01, 0.2), num('letterSpacing', 'Letter spacing', -0.1, 0.5, 0.005, 0),
49
+ tog('bevelEnabled', 'Bevel', true), num('bevelThickness', 'Bevel depth', 0, 0.1, 0.002, 0.02), num('bevelSize', 'Bevel size', 0, 0.1, 0.002, 0.015), int('bevelSegments', 'Bevel segments', 1, 8, 3),
50
+ ],
43
51
  point: [num('size', 'Size', 0.02, 0.5, 0.01, 0.1)],
44
52
  custom: [],
45
53
  };
@@ -1 +1 @@
1
- {"version":3,"file":"gridProperties.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/gridProperties.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiB7D,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAwBrD,CAAC;AAiKF,sFAAsF;AACtF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAE9D,CAAC"}
1
+ {"version":3,"file":"gridProperties.d.ts","sourceRoot":"","sources":["../../../src/properties/tables/gridProperties.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAiB7D,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAsBrD,CAAC;AA8LF,sFAAsF;AACtF,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAE9D,CAAC"}