@3driseai/3drise-viewer 0.1.29 → 0.1.31

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 (237) hide show
  1. package/dist/animationsV2/ClipPlayer.d.ts.map +1 -1
  2. package/dist/animationsV2/ClipPlayer.js +14 -12
  3. package/dist/animationsV2/ClipsRuntime.d.ts +13 -0
  4. package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -1
  5. package/dist/animationsV2/ClipsRuntime.js +115 -4
  6. package/dist/animationsV2/appliers.d.ts.map +1 -1
  7. package/dist/animationsV2/appliers.js +21 -2
  8. package/dist/animationsV2/clipUtils.d.ts.map +1 -1
  9. package/dist/animationsV2/clipUtils.js +5 -1
  10. package/dist/animationsV2/sequenceUtils.d.ts +5 -0
  11. package/dist/animationsV2/sequenceUtils.d.ts.map +1 -1
  12. package/dist/animationsV2/sequenceUtils.js +14 -5
  13. package/dist/animationsV2/sunSystemLive.d.ts +12 -0
  14. package/dist/animationsV2/sunSystemLive.d.ts.map +1 -0
  15. package/dist/animationsV2/sunSystemLive.js +8 -0
  16. package/dist/animationsV2/types.d.ts +6 -0
  17. package/dist/animationsV2/types.d.ts.map +1 -1
  18. package/dist/api/sceneHandle.d.ts +3 -1
  19. package/dist/api/sceneHandle.d.ts.map +1 -1
  20. package/dist/api/sceneHandle.js +2 -2
  21. package/dist/components/AdaptiveResolution.d.ts +9 -0
  22. package/dist/components/AdaptiveResolution.d.ts.map +1 -0
  23. package/dist/components/AdaptiveResolution.js +61 -0
  24. package/dist/components/CameraController.d.ts.map +1 -1
  25. package/dist/components/CameraController.js +24 -7
  26. package/dist/components/EffectsGenerator.d.ts.map +1 -1
  27. package/dist/components/EffectsGenerator.js +43 -38
  28. package/dist/components/GeometryShape.d.ts.map +1 -1
  29. package/dist/components/GeometryShape.js +22 -2
  30. package/dist/components/MoonDisc.d.ts.map +1 -1
  31. package/dist/components/MoonDisc.js +2 -1
  32. package/dist/components/ObjectNode.d.ts.map +1 -1
  33. package/dist/components/ObjectNode.js +6 -17
  34. package/dist/components/OceanBuilder.d.ts +4 -1
  35. package/dist/components/OceanBuilder.d.ts.map +1 -1
  36. package/dist/components/OceanBuilder.js +2 -1
  37. package/dist/components/ParticlesGenerator.d.ts.map +1 -1
  38. package/dist/components/ParticlesGenerator.js +46 -24
  39. package/dist/components/PickVolume.d.ts +17 -0
  40. package/dist/components/PickVolume.d.ts.map +1 -0
  41. package/dist/components/PickVolume.js +20 -0
  42. package/dist/components/SceneBuilder.d.ts.map +1 -1
  43. package/dist/components/SceneBuilder.js +5 -2
  44. package/dist/components/SkyStars.d.ts.map +1 -1
  45. package/dist/components/SkyStars.js +83 -2
  46. package/dist/components/Skybox.d.ts.map +1 -1
  47. package/dist/components/Skybox.js +2 -1
  48. package/dist/components/SunLight.d.ts.map +1 -1
  49. package/dist/components/SunLight.js +3 -2
  50. package/dist/components/TextGenerator.d.ts.map +1 -1
  51. package/dist/components/TextGenerator.js +3 -2
  52. package/dist/components/index.d.ts +2 -8
  53. package/dist/components/index.d.ts.map +1 -1
  54. package/dist/components/index.js +2 -4
  55. package/dist/components/lightBulb/LightBulb.d.ts.map +1 -1
  56. package/dist/components/lightBulb/LightBulb.js +7 -2
  57. package/dist/components/particles/BioluminescentWakeParticles.d.ts +5 -0
  58. package/dist/components/particles/BioluminescentWakeParticles.d.ts.map +1 -1
  59. package/dist/components/particles/BioluminescentWakeParticles.js +2 -1
  60. package/dist/components/particles/BrownianDustParticles.d.ts +5 -0
  61. package/dist/components/particles/BrownianDustParticles.d.ts.map +1 -1
  62. package/dist/components/particles/BrownianDustParticles.js +2 -0
  63. package/dist/components/particles/ChladniSandParticles.d.ts +5 -0
  64. package/dist/components/particles/ChladniSandParticles.d.ts.map +1 -1
  65. package/dist/components/particles/ChladniSandParticles.js +2 -1
  66. package/dist/components/particles/ElectronOrbitalsParticles.d.ts +5 -0
  67. package/dist/components/particles/ElectronOrbitalsParticles.d.ts.map +1 -1
  68. package/dist/components/particles/ElectronOrbitalsParticles.js +2 -1
  69. package/dist/components/particles/FaradayPowderParticles.d.ts +5 -0
  70. package/dist/components/particles/FaradayPowderParticles.d.ts.map +1 -1
  71. package/dist/components/particles/FaradayPowderParticles.js +2 -1
  72. package/dist/components/particles/FireworksParticles.d.ts +22 -0
  73. package/dist/components/particles/FireworksParticles.d.ts.map +1 -0
  74. package/dist/components/particles/FireworksParticles.js +1649 -0
  75. package/dist/components/particles/GrinderSparksParticles.d.ts +5 -0
  76. package/dist/components/particles/GrinderSparksParticles.d.ts.map +1 -1
  77. package/dist/components/particles/GrinderSparksParticles.js +2 -1
  78. package/dist/components/particles/MagneticBottleParticles.d.ts +5 -0
  79. package/dist/components/particles/MagneticBottleParticles.d.ts.map +1 -1
  80. package/dist/components/particles/MagneticBottleParticles.js +2 -1
  81. package/dist/components/particles/NeonRainParticles.d.ts +5 -0
  82. package/dist/components/particles/NeonRainParticles.d.ts.map +1 -1
  83. package/dist/components/particles/NeonRainParticles.js +2 -1
  84. package/dist/components/particles/ShapeBurstParticles.d.ts +5 -0
  85. package/dist/components/particles/ShapeBurstParticles.d.ts.map +1 -1
  86. package/dist/components/particles/ShapeBurstParticles.js +2 -1
  87. package/dist/components/particles/ShapeFlowParticles.d.ts +5 -0
  88. package/dist/components/particles/ShapeFlowParticles.d.ts.map +1 -1
  89. package/dist/components/particles/ShapeFlowParticles.js +2 -1
  90. package/dist/components/particles/TidalStreamParticles.d.ts +5 -0
  91. package/dist/components/particles/TidalStreamParticles.d.ts.map +1 -1
  92. package/dist/components/particles/TidalStreamParticles.js +2 -0
  93. package/dist/components/particles/index.d.ts +2 -0
  94. package/dist/components/particles/index.d.ts.map +1 -1
  95. package/dist/components/particles/index.js +1 -0
  96. package/dist/components/terrain/TerrainSurface.d.ts.map +1 -1
  97. package/dist/components/terrain/TerrainSurface.js +26 -4
  98. package/dist/components/text/PlainText.d.ts +15 -0
  99. package/dist/components/text/PlainText.d.ts.map +1 -0
  100. package/dist/components/text/PlainText.js +4 -0
  101. package/dist/components/text/TextObjectView.d.ts +3 -1
  102. package/dist/components/text/TextObjectView.d.ts.map +1 -1
  103. package/dist/components/text/TextObjectView.js +9 -3
  104. package/dist/components/text/engine/looks/index.d.ts.map +1 -1
  105. package/dist/components/text/engine/looks/index.js +2 -1
  106. package/dist/components/text/engine/looks/plain.d.ts +146 -0
  107. package/dist/components/text/engine/looks/plain.d.ts.map +1 -0
  108. package/dist/components/text/engine/looks/plain.js +104 -0
  109. package/dist/components/text/fonts/bebas-neue.outline.d.ts +3 -0
  110. package/dist/components/text/fonts/bebas-neue.outline.d.ts.map +1 -0
  111. package/dist/components/text/fonts/bebas-neue.outline.js +4 -0
  112. package/dist/components/text/fonts/bebas-neue.strokes.d.ts +3 -0
  113. package/dist/components/text/fonts/bebas-neue.strokes.d.ts.map +1 -0
  114. package/dist/components/text/fonts/bebas-neue.strokes.js +4 -0
  115. package/dist/components/text/fonts/index.d.ts +1 -1
  116. package/dist/components/text/fonts/index.d.ts.map +1 -1
  117. package/dist/components/text/fonts/index.js +15 -1
  118. package/dist/components/text/fonts/inter.outline.d.ts +3 -0
  119. package/dist/components/text/fonts/inter.outline.d.ts.map +1 -0
  120. package/dist/components/text/fonts/inter.outline.js +4 -0
  121. package/dist/components/text/fonts/inter.strokes.d.ts +3 -0
  122. package/dist/components/text/fonts/inter.strokes.d.ts.map +1 -0
  123. package/dist/components/text/fonts/inter.strokes.js +4 -0
  124. package/dist/components/text/fonts/lora.outline.d.ts +3 -0
  125. package/dist/components/text/fonts/lora.outline.d.ts.map +1 -0
  126. package/dist/components/text/fonts/lora.outline.js +4 -0
  127. package/dist/components/text/fonts/lora.strokes.d.ts +3 -0
  128. package/dist/components/text/fonts/lora.strokes.d.ts.map +1 -0
  129. package/dist/components/text/fonts/lora.strokes.js +4 -0
  130. package/dist/components/text/fonts/montserrat.outline.d.ts +3 -0
  131. package/dist/components/text/fonts/montserrat.outline.d.ts.map +1 -0
  132. package/dist/components/text/fonts/montserrat.outline.js +4 -0
  133. package/dist/components/text/fonts/montserrat.strokes.d.ts +3 -0
  134. package/dist/components/text/fonts/montserrat.strokes.d.ts.map +1 -0
  135. package/dist/components/text/fonts/montserrat.strokes.js +4 -0
  136. package/dist/components/text/fonts/oswald.outline.d.ts +3 -0
  137. package/dist/components/text/fonts/oswald.outline.d.ts.map +1 -0
  138. package/dist/components/text/fonts/oswald.outline.js +4 -0
  139. package/dist/components/text/fonts/oswald.strokes.d.ts +3 -0
  140. package/dist/components/text/fonts/oswald.strokes.d.ts.map +1 -0
  141. package/dist/components/text/fonts/oswald.strokes.js +4 -0
  142. package/dist/components/text/fonts/playfair-display.outline.d.ts +3 -0
  143. package/dist/components/text/fonts/playfair-display.outline.d.ts.map +1 -0
  144. package/dist/components/text/fonts/playfair-display.outline.js +4 -0
  145. package/dist/components/text/fonts/playfair-display.strokes.d.ts +3 -0
  146. package/dist/components/text/fonts/playfair-display.strokes.d.ts.map +1 -0
  147. package/dist/components/text/fonts/playfair-display.strokes.js +4 -0
  148. package/dist/components/text/fonts/roboto.outline.d.ts +3 -0
  149. package/dist/components/text/fonts/roboto.outline.d.ts.map +1 -0
  150. package/dist/components/text/fonts/roboto.outline.js +4 -0
  151. package/dist/components/text/fonts/roboto.strokes.d.ts +3 -0
  152. package/dist/components/text/fonts/roboto.strokes.d.ts.map +1 -0
  153. package/dist/components/text/fonts/roboto.strokes.js +4 -0
  154. package/dist/components/text/index.d.ts +2 -0
  155. package/dist/components/text/index.d.ts.map +1 -1
  156. package/dist/components/text/index.js +1 -0
  157. package/dist/components/text/useTextObject.d.ts +1 -0
  158. package/dist/components/text/useTextObject.d.ts.map +1 -1
  159. package/dist/components/text/useTextObject.js +23 -11
  160. package/dist/components/water/OceanSurface.d.ts.map +1 -1
  161. package/dist/components/water/OceanSurface.js +5 -1
  162. package/dist/components/water/types.d.ts +3 -1
  163. package/dist/components/water/types.d.ts.map +1 -1
  164. package/dist/constants.d.ts +1 -1
  165. package/dist/constants.d.ts.map +1 -1
  166. package/dist/constants.js +3 -1
  167. package/dist/hooks/useOceanMaterial.d.ts +6 -2
  168. package/dist/hooks/useOceanMaterial.d.ts.map +1 -1
  169. package/dist/hooks/useOceanMaterial.js +22 -2
  170. package/dist/hooks/useOrbitTargetFollow.d.ts +10 -0
  171. package/dist/hooks/useOrbitTargetFollow.d.ts.map +1 -0
  172. package/dist/hooks/useOrbitTargetFollow.js +194 -0
  173. package/dist/index.d.ts +2 -1
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +2 -1
  176. package/dist/operations/catalogue/flock.d.ts.map +1 -1
  177. package/dist/operations/catalogue/flock.js +44 -9
  178. package/dist/operations/catalogue/inkBloom.d.ts.map +1 -1
  179. package/dist/operations/catalogue/inkBloom.js +46 -9
  180. package/dist/operations/catalogue/liquidMetal.d.ts.map +1 -1
  181. package/dist/operations/catalogue/liquidMetal.js +41 -12
  182. package/dist/operations/catalogue/particleSwarm.d.ts.map +1 -1
  183. package/dist/operations/catalogue/particleSwarm.js +29 -9
  184. package/dist/operations/catalogue/petalPeel.d.ts.map +1 -1
  185. package/dist/operations/catalogue/petalPeel.js +33 -9
  186. package/dist/operations/catalogue/portal.d.ts.map +1 -1
  187. package/dist/operations/catalogue/portal.js +33 -11
  188. package/dist/operations/catalogue/sandErosion.d.ts.map +1 -1
  189. package/dist/operations/catalogue/sandErosion.js +36 -14
  190. package/dist/operations/catalogue/teleport.d.ts.map +1 -1
  191. package/dist/operations/catalogue/teleport.js +43 -12
  192. package/dist/operations/catalogue/unweave.d.ts.map +1 -1
  193. package/dist/operations/catalogue/unweave.js +34 -15
  194. package/dist/operations/catalogue/voxelize.d.ts.map +1 -1
  195. package/dist/operations/catalogue/voxelize.js +37 -10
  196. package/dist/shaders/glsl/terrainCore.glsl.d.ts +18 -3
  197. package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -1
  198. package/dist/shaders/glsl/terrainCore.glsl.js +42 -21
  199. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +36 -11
  200. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -1
  201. package/dist/shaders/ocean/OceanSurfaceMaterial.js +96 -5
  202. package/dist/triggers/engine.d.ts +1 -1
  203. package/dist/triggers/engine.d.ts.map +1 -1
  204. package/dist/triggers/engine.js +3 -0
  205. package/dist/triggers/hosts/actions.d.ts.map +1 -1
  206. package/dist/triggers/hosts/actions.js +3 -1
  207. package/dist/triggers/hosts/interactions.d.ts.map +1 -1
  208. package/dist/triggers/hosts/interactions.js +1 -1
  209. package/dist/triggers/hosts/timelineCues.js +1 -1
  210. package/dist/triggers/kinds/change.d.ts +4 -0
  211. package/dist/triggers/kinds/change.d.ts.map +1 -0
  212. package/dist/triggers/kinds/change.js +50 -0
  213. package/dist/triggers/kinds/index.d.ts +1 -0
  214. package/dist/triggers/kinds/index.d.ts.map +1 -1
  215. package/dist/triggers/kinds/index.js +1 -0
  216. package/dist/utils/CameraSingleton.d.ts +4 -0
  217. package/dist/utils/CameraSingleton.d.ts.map +1 -1
  218. package/dist/utils/CameraSingleton.js +4 -0
  219. package/dist/utils/deviceTier.d.ts +2 -0
  220. package/dist/utils/deviceTier.d.ts.map +1 -0
  221. package/dist/utils/deviceTier.js +16 -0
  222. package/dist/utils/environmentDrawOrder.d.ts +23 -0
  223. package/dist/utils/environmentDrawOrder.d.ts.map +1 -0
  224. package/dist/utils/environmentDrawOrder.js +22 -0
  225. package/dist/utils/pickProxy.d.ts +11 -0
  226. package/dist/utils/pickProxy.d.ts.map +1 -0
  227. package/dist/utils/pickProxy.js +36 -0
  228. package/dist/utils/shapes.d.ts +4 -0
  229. package/dist/utils/shapes.d.ts.map +1 -1
  230. package/dist/utils/shapes.js +4 -1
  231. package/dist/utils/terrainUniforms.d.ts +7 -0
  232. package/dist/utils/terrainUniforms.d.ts.map +1 -1
  233. package/dist/utils/terrainUniforms.js +15 -2
  234. package/dist/utils/textShape.d.ts +24 -0
  235. package/dist/utils/textShape.d.ts.map +1 -0
  236. package/dist/utils/textShape.js +102 -0
  237. package/package.json +2 -2
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
+ import { useThree } from '@react-three/fiber';
4
+ import { PerformanceMonitor } from '@react-three/drei';
5
+ import { isMobileDevice } from '../utils/deviceTier.js';
6
+ /**
7
+ * Render resolution that follows the frame rate. Mount inside <Canvas>.
8
+ *
9
+ * The terrain (and most of what makes the environment expensive) costs per PIXEL:
10
+ * textures and noise octaves in the fragment shader. Pixel ratio is therefore the
11
+ * biggest single lever — 1.5 is 2.25x the pixels of 1, and a phone's 3 is 9x.
12
+ *
13
+ * - Ceiling: the canvas's configured dpr, capped at MOBILE_MAX_DPR on phones and
14
+ * tablets, where the device ratio is 2-3 and the GPU is a fraction of a desktop's.
15
+ * - Under load: drei's PerformanceMonitor averages the frame rate and steps the
16
+ * ratio down while it stays under ~50 fps, and back up when there is room.
17
+ * After a few flip-flops it freezes where it is, so a scene sitting on the edge
18
+ * does not oscillate between sharp and soft.
19
+ * - Floor: half the ceiling, never below 0.6 — softer, never mush.
20
+ * - Warm-up: the monitor starts WARMUP_MS after mount. Loading a scene compiles
21
+ * shaders and packs textures, and those stalls used to burn the flip-flop
22
+ * budget in the first seconds, freezing the ratio below the ceiling for the
23
+ * whole session (seen in the studio: stuck at 1.42 of 1.5 at a steady 60 fps).
24
+ */
25
+ const WARMUP_MS = 4000;
26
+ export const MOBILE_MAX_DPR = 1.5;
27
+ const round2 = (v) => Math.round(v * 100) / 100;
28
+ const AdaptiveResolution = ({ max }) => {
29
+ const setDpr = useThree((s) => s.setDpr);
30
+ const ceiling = useMemo(() => {
31
+ const device = typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;
32
+ const configured = Array.isArray(max) ? max[1] : (max ?? device);
33
+ return isMobileDevice() ? Math.min(configured, MOBILE_MAX_DPR) : configured;
34
+ }, [max]);
35
+ const floor = Math.max(0.6, ceiling * 0.5);
36
+ const frozen = useRef(false);
37
+ const [watching, setWatching] = useState(false);
38
+ useEffect(() => {
39
+ frozen.current = false;
40
+ setDpr(ceiling);
41
+ setWatching(false);
42
+ const t = setTimeout(() => setWatching(true), WARMUP_MS);
43
+ return () => clearTimeout(t);
44
+ }, [ceiling, setDpr]);
45
+ if (!watching)
46
+ return null;
47
+ return (_jsx(PerformanceMonitor
48
+ // 60 Hz: below 45 fps step down, above 55 step up. Not tighter: the
49
+ // studio's own main-thread work makes a GPU-idle frame rate wander
50
+ // between 55 and 60, and a 58 threshold pinned the ratio low for good.
51
+ , {
52
+ // 60 Hz: below 45 fps step down, above 55 step up. Not tighter: the
53
+ // studio's own main-thread work makes a GPU-idle frame rate wander
54
+ // between 55 and 60, and a 58 threshold pinned the ratio low for good.
55
+ bounds: (refresh) => (refresh > 100 ? [70, 100] : [45, 55]), flipflops: 3, onChange: ({ factor }) => {
56
+ if (frozen.current)
57
+ return;
58
+ setDpr(round2(floor + (ceiling - floor) * factor));
59
+ }, onFallback: () => { frozen.current = true; } }));
60
+ };
61
+ export default AdaptiveResolution;
@@ -1 +1 @@
1
- {"version":3,"file":"CameraController.d.ts","sourceRoot":"","sources":["../../src/components/CameraController.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,UAAU,qBAAsB,SAAQ,gBAAgB;IACpD,QAAQ,EAAE,WAAW,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C;AAGD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA+G5D,CAAC;AACF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"CameraController.d.ts","sourceRoot":"","sources":["../../src/components/CameraController.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAQ7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,UAAU,qBAAsB,SAAQ,gBAAgB;IACpD,QAAQ,EAAE,WAAW,CAAC;IACtB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;IAC1C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,IAAI,CAAC;CAC/C;AAGD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA4H5D,CAAC;AACF,eAAe,gBAAgB,CAAC"}
@@ -7,6 +7,8 @@ import { cameraManager } from '../utils/CameraSingleton.js';
7
7
  import { usePathAnimation } from '../hooks/usePathAnimation.js';
8
8
  import { OrbitControls } from "@react-three/drei";
9
9
  import { useRuntimeSettings } from '../hooks/useRuntimeSettings.js';
10
+ import { orbitAngleLimits } from "@3driseai/3drise-core";
11
+ import { useOrbitTargetFollow } from '../hooks/useOrbitTargetFollow.js';
10
12
  export const CameraController = ({ enableAutoAnimation = true, animationDuration = 1, animationEase = "power2.out", settings, onObjectReady, onObjectDispose, onControlsReady, onControlsDispose, }) => {
11
13
  // Authored camera + any applied action patch ('camera').
12
14
  settings = useRuntimeSettings('camera', settings);
@@ -19,8 +21,11 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
19
21
  const controls = controlsRef.current;
20
22
  if (!controls)
21
23
  return;
24
+ cameraManager.setControls(controls);
22
25
  onControlsReady && onControlsReady(controls);
23
26
  return () => {
27
+ if (cameraManager.getControls() === controls)
28
+ cameraManager.setControls(null);
24
29
  onControlsDispose && onControlsDispose(controls);
25
30
  };
26
31
  }, [controlsRef.current]); // eslint-disable-line react-hooks/exhaustive-deps
@@ -59,15 +64,27 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
59
64
  }
60
65
  }
61
66
  }, [position, orientation]);
67
+ // The stored orbit point is applied only when it (or the object choice) changes: a
68
+ // followed object or a pan moves the live point, and an unrelated edit (a speed, a
69
+ // limit) must not snap it back.
70
+ const appliedTarget = useRef('');
62
71
  // Sync controls config changes imperatively via ref (after initial mount)
63
72
  useEffect(() => {
64
73
  const orbitControls = controlsRef.current;
65
74
  if (!orbitControls)
66
75
  return;
67
76
  orbitControls.enabled = controls.enabled;
68
- orbitControls.target.set(controls.target[0], controls.target[1], controls.target[2]);
69
- orbitControls.enablePan = controls.enablePan;
77
+ // Orbiting an object: the follow hook owns the target, and panning is off
78
+ // (a pan would pull the orbit point off the object).
79
+ const lookingAtObject = !!controls.targetObject?.id;
80
+ const targetKey = `${controls.target?.join(',')}|${controls.targetObject?.id ?? ''}|${controls.targetObject?.node ?? ''}`;
81
+ if (!lookingAtObject && targetKey !== appliedTarget.current)
82
+ orbitControls.target.set(controls.target[0], controls.target[1], controls.target[2]);
83
+ appliedTarget.current = targetKey;
84
+ orbitControls.enablePan = lookingAtObject ? false : controls.enablePan;
70
85
  orbitControls.enableRotate = controls.enableRotate;
86
+ // ClipPlayer holds zoom off while a wheel-driven sequence runs (it re-asserts every frame).
87
+ orbitControls.enableZoom = controls.enableZoom !== false;
71
88
  orbitControls.autoRotate = controls.autoRotate;
72
89
  orbitControls.autoRotateSpeed = controls.autoRotateSpeed;
73
90
  orbitControls.zoomSpeed = controls.zoomSpeed;
@@ -75,11 +92,11 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
75
92
  orbitControls.rotateSpeed = controls.rotateSpeed;
76
93
  orbitControls.minDistance = controls.minDistance;
77
94
  orbitControls.maxDistance = controls.maxDistance;
78
- orbitControls.minPolarAngle = controls.minPolarAngle ?? -Infinity;
79
- orbitControls.maxPolarAngle = controls.maxPolarAngle ?? Infinity;
80
- orbitControls.minAzimuthAngle = controls.minAzimuthAngle ?? -Infinity;
81
- orbitControls.maxAzimuthAngle = controls.maxAzimuthAngle ?? Infinity;
95
+ // Saved limits may be null (once ±Infinity): the full range then.
96
+ Object.assign(orbitControls, orbitAngleLimits(controls));
82
97
  }, [controls]);
98
+ // Look at a scene object (orbit target) and / or travel with one (follow).
99
+ useOrbitTargetFollow(controlsRef, controls.targetObject, controls.followObject, () => isInAnimatedTransition.current || isAnimating() || isPathAnimating(), controls.enabled !== false, controls);
83
100
  // Sync camera projection settings from state
84
101
  useEffect(() => {
85
102
  const cam = cameraRef.current;
@@ -117,6 +134,6 @@ export const CameraController = ({ enableAutoAnimation = true, animationDuration
117
134
  const ic = initialControls.current;
118
135
  return _jsx(OrbitControls, { ref: controlsRef, makeDefault: true, enabled: ic.enabled,
119
136
  // target={new Vector3(...ic.target)}
120
- enablePan: ic.enablePan, enableRotate: ic.enableRotate, autoRotate: ic.autoRotate, autoRotateSpeed: ic.autoRotateSpeed, zoomSpeed: ic.zoomSpeed, panSpeed: ic.panSpeed, rotateSpeed: ic.rotateSpeed, minDistance: ic.minDistance, maxDistance: ic.maxDistance, minPolarAngle: ic.minPolarAngle ?? -Infinity, maxPolarAngle: ic.maxPolarAngle ?? Infinity, minAzimuthAngle: ic.minAzimuthAngle ?? -Infinity, maxAzimuthAngle: ic.maxAzimuthAngle ?? Infinity });
137
+ enablePan: ic.targetObject?.id ? false : ic.enablePan, enableRotate: ic.enableRotate, enableZoom: ic.enableZoom !== false, autoRotate: ic.autoRotate, autoRotateSpeed: ic.autoRotateSpeed, zoomSpeed: ic.zoomSpeed, panSpeed: ic.panSpeed, rotateSpeed: ic.rotateSpeed, minDistance: ic.minDistance, maxDistance: ic.maxDistance, ...orbitAngleLimits(ic) });
121
138
  };
122
139
  export default CameraController;
@@ -1 +1 @@
1
- {"version":3,"file":"EffectsGenerator.d.ts","sourceRoot":"","sources":["../../src/components/EffectsGenerator.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAqCtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,QAAQ,EAAE,wBAAwB,CAAC;IACnC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB,mGAAmG;IACnG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0FAA0F;IAC1F,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,qFAAqF;IACrF,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAGD,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAuDrD,CAAC;AACF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"EffectsGenerator.d.ts","sourceRoot":"","sources":["../../src/components/EffectsGenerator.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAsCtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACzG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC3D,QAAQ,EAAE,wBAAwB,CAAC;IACnC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB,mGAAmG;IACnG,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0FAA0F;IAC1F,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,qFAAqF;IACrF,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAGD,QAAA,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA2DrD,CAAC;AACF,eAAe,gBAAgB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useMemo } from 'react';
3
3
  import { Box3, Sphere } from 'three';
4
+ import PickVolume from './PickVolume.js';
4
5
  import MoleculesEffect from './effects/MoleculesEffect.js';
5
6
  import ShockwaveEffect from './effects/ShockwaveEffect.js';
6
7
  import AuraEffect from './effects/AuraEffect.js';
@@ -52,44 +53,48 @@ const EffectsGenerator = ({ settings, object, id, keyframes, mouseMove, onObject
52
53
  const ready = { onObjectReady, onObjectDispose };
53
54
  // Every effect takes the domain drivers: live drag, keyframes and pointer bindings.
54
55
  const driven = { id, keyframes, mouseMove };
55
- switch (config.type) {
56
- case 'molecules': return _jsx(MoleculesEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
57
- case 'shockwave': return _jsx(ShockwaveEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
58
- case 'aura': return _jsx(AuraEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
59
- case 'dataStream': return _jsx(DataStreamEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
60
- case 'constellation': return _jsx(ConstellationEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
61
- case 'hologram': return _jsx(HologramEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
62
- case 'portal': return _jsx(PortalEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
63
- case 'dnaHelix': return _jsx(DnaHelixEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
64
- case 'orb': return _jsx(OrbEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
65
- case 'lightning': return _jsx(LightningEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
66
- case 'aurora': return _jsx(AuroraEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
67
- case 'forcefield': return _jsx(ForcefieldEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
68
- case 'neuralNetwork': return _jsx(NeuralNetworkEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
69
- case 'blackHole': return _jsx(BlackHoleEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
70
- case 'iceCrystals': return _jsx(IceCrystalsEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
71
- case 'smokePlume': return _jsx(SmokePlumeEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
72
- case 'volumetricFog': return _jsx(VolumetricFogEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
73
- case 'smokeRing': return _jsx(SmokeRingEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
74
- case 'fire': return _jsx(Fire, { hostRef: object, config: config, ...driven, ...ready });
75
- case 'flares': return _jsx(Flares, { hostRef: object, boundingRadius: boundingRadius, config: config, ...driven, ...ready });
76
- case 'sparklesBurst': return _jsx(SparklesBurst, { boundingRadius: boundingRadius, config: config, ...driven });
77
- case 'bubbles': return _jsx(Bubbles, { boundingRadius: boundingRadius, config: config, ...driven });
78
- case 'glyphs': return _jsx(Glyphs, { boundingRadius: boundingRadius, config: config, ...driven });
79
- case 'smokeRibbon': return _jsx(SmokeRibbon, { config: config, boundingRadius: boundingRadius, ...driven, ...ready });
80
- case 'fieldLines': return _jsx(FieldLinesEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
81
- case 'strangeAttractor': return _jsx(StrangeAttractorEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
82
- case 'harmonicShell': return _jsx(HarmonicShellEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
83
- case 'galaxy': return _jsx(GalaxyEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
84
- case 'fireflySwarm': return _jsx(FireflySwarmEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
85
- case 'murmuration': return _jsx(MurmurationEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
86
- case 'planetaryRings': return _jsx(PlanetaryRingsEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
87
- case 'waterCaustics': return _jsx(WaterCausticsEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
88
- case 'iceHalo': return _jsx(IceHaloEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
89
- case 'fallingLeaves': return _jsx(FallingLeavesEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
90
- case 'lichtenberg': return _jsx(LichtenbergEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
91
- case 'dandelionSeeds': return _jsx(DandelionSeedsEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
92
- default: return null;
56
+ // A standalone effect is hit on its unit sphere (boundingRadius 1), never on its sparse points; a hosted one is hit through its host.
57
+ return object ? effect() : _jsx(PickVolume, { radius: boundingRadius * 1.05, children: effect() });
58
+ function effect() {
59
+ switch (config.type) {
60
+ case 'molecules': return _jsx(MoleculesEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
61
+ case 'shockwave': return _jsx(ShockwaveEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
62
+ case 'aura': return _jsx(AuraEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
63
+ case 'dataStream': return _jsx(DataStreamEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
64
+ case 'constellation': return _jsx(ConstellationEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
65
+ case 'hologram': return _jsx(HologramEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
66
+ case 'portal': return _jsx(PortalEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
67
+ case 'dnaHelix': return _jsx(DnaHelixEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
68
+ case 'orb': return _jsx(OrbEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
69
+ case 'lightning': return _jsx(LightningEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
70
+ case 'aurora': return _jsx(AuroraEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
71
+ case 'forcefield': return _jsx(ForcefieldEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
72
+ case 'neuralNetwork': return _jsx(NeuralNetworkEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
73
+ case 'blackHole': return _jsx(BlackHoleEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
74
+ case 'iceCrystals': return _jsx(IceCrystalsEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
75
+ case 'smokePlume': return _jsx(SmokePlumeEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
76
+ case 'volumetricFog': return _jsx(VolumetricFogEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
77
+ case 'smokeRing': return _jsx(SmokeRingEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
78
+ case 'fire': return _jsx(Fire, { hostRef: object, config: config, ...driven, ...ready });
79
+ case 'flares': return _jsx(Flares, { hostRef: object, boundingRadius: boundingRadius, config: config, ...driven, ...ready });
80
+ case 'sparklesBurst': return _jsx(SparklesBurst, { boundingRadius: boundingRadius, config: config, ...driven });
81
+ case 'bubbles': return _jsx(Bubbles, { boundingRadius: boundingRadius, config: config, ...driven });
82
+ case 'glyphs': return _jsx(Glyphs, { boundingRadius: boundingRadius, config: config, ...driven });
83
+ case 'smokeRibbon': return _jsx(SmokeRibbon, { config: config, boundingRadius: boundingRadius, ...driven, ...ready });
84
+ case 'fieldLines': return _jsx(FieldLinesEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
85
+ case 'strangeAttractor': return _jsx(StrangeAttractorEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
86
+ case 'harmonicShell': return _jsx(HarmonicShellEffect, { boundingRadius: boundingRadius, config: config, ...driven, ...ready });
87
+ case 'galaxy': return _jsx(GalaxyEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
88
+ case 'fireflySwarm': return _jsx(FireflySwarmEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
89
+ case 'murmuration': return _jsx(MurmurationEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
90
+ case 'planetaryRings': return _jsx(PlanetaryRingsEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
91
+ case 'waterCaustics': return _jsx(WaterCausticsEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
92
+ case 'iceHalo': return _jsx(IceHaloEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
93
+ case 'fallingLeaves': return _jsx(FallingLeavesEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
94
+ case 'lichtenberg': return _jsx(LichtenbergEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
95
+ case 'dandelionSeeds': return _jsx(DandelionSeedsEffect, { boundingRadius: boundingRadius, config: config, hasHost: !!object, ...driven, ...ready });
96
+ default: return null;
97
+ }
93
98
  }
94
99
  };
95
100
  export default EffectsGenerator;
@@ -1 +1 @@
1
- {"version":3,"file":"GeometryShape.d.ts","sourceRoot":"","sources":["../../src/components/GeometryShape.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GeometryShape.d.ts","sourceRoot":"","sources":["../../src/components/GeometryShape.tsx"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useMemo, useRef } from 'react';
2
+ import { useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { useObjectReady } from '../hooks/useObjectReady.js';
4
4
  import { EdgesGeometry, WireframeGeometry, Mesh, MeshBasicMaterial, Raycaster, Vector3, DoubleSide, } from 'three';
5
5
  import { buildSegmentQuadGeometry } from '@3driseai/3drise-core';
6
6
  import { shapeGenerators } from '../utils/shapes.js';
7
+ import { DEFAULT_TEXT_SHAPE_FONT, loadOutlineFont } from '../utils/textShape.js';
7
8
  import PointCloud from './PointCloud.js';
8
9
  /**
9
10
  * World-space half-thickness of a line ribbon at `lineWidth: 1`. Line modes are
@@ -34,13 +35,32 @@ function normalizeModeConfig(config) {
34
35
  ...(config || {}),
35
36
  };
36
37
  }
38
+ /**
39
+ * The text shape's font loads lazily: bumps once per font when it has landed, so the geometry rebuilds. Always
40
+ * waits on the load (an inlined font can land in the microtask between the render that started it and this
41
+ * effect, so "already loaded" here does not mean the geometry above was built with it).
42
+ */
43
+ function useTextShapeFont(cfg) {
44
+ const font = cfg.type === 'text' ? (cfg.font ?? DEFAULT_TEXT_SHAPE_FONT) : null;
45
+ const [tick, setTick] = useState(0);
46
+ useEffect(() => {
47
+ if (font === null)
48
+ return;
49
+ let dead = false;
50
+ loadOutlineFont(font).then(() => { if (!dead)
51
+ setTick((t) => t + 1); });
52
+ return () => { dead = true; };
53
+ }, [font]);
54
+ return font === null ? 0 : tick;
55
+ }
37
56
  export function useShapeGeometry(options) {
38
57
  const safeOptions = useMemo(() => normalizeShapeConfig(options), [options]);
39
58
  const key = JSON.stringify(safeOptions);
59
+ const fontTick = useTextShapeFont(safeOptions);
40
60
  const geometry = useMemo(() => {
41
61
  const generator = shapeGenerators[safeOptions.type] ?? shapeGenerators.box;
42
62
  return generator(safeOptions);
43
- }, [safeOptions.type, key]); // eslint-disable-line react-hooks/exhaustive-deps
63
+ }, [safeOptions.type, key, fontTick]); // eslint-disable-line react-hooks/exhaustive-deps
44
64
  useEffect(() => () => geometry.dispose(), [geometry]);
45
65
  return geometry;
46
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MoonDisc.d.ts","sourceRoot":"","sources":["../../src/components/MoonDisc.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAIvE,MAAM,WAAW,aAAa;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AA+ED,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAoDrC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"MoonDisc.d.ts","sourceRoot":"","sources":["../../src/components/MoonDisc.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAG1D,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAKvE,MAAM,WAAW,aAAa;IAC1B,YAAY,EAAE,YAAY,CAAC;IAC3B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AA+ED,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAoDrC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -4,6 +4,7 @@ import * as THREE from 'three';
4
4
  import { useFrame } from '@react-three/fiber';
5
5
  import { useCloudSun } from '../hooks/useCloudSun.js';
6
6
  import { resolveMoon } from '../utils/skyMoon.js';
7
+ import { sunSystemLive } from '../animationsV2/sunSystemLive.js';
7
8
  /**
8
9
  * The moon in the sky, for either sky renderer.
9
10
  *
@@ -114,7 +115,7 @@ const MoonDisc = ({ timeSettings, skySettings, size = 1 }) => {
114
115
  const dist = far * 0.9;
115
116
  mesh.position.copy(camera.position).addScaledVector(m.direction, dist);
116
117
  mesh.quaternion.copy(camera.quaternion);
117
- const radius = dist * Math.tan(THREE.MathUtils.degToRad(MOON_ANGULAR_DIAMETER_DEG * size) / 2);
118
+ const radius = dist * Math.tan(THREE.MathUtils.degToRad(MOON_ANGULAR_DIAMETER_DEG * (sunSystemLive.moonSize ?? size)) / 2);
118
119
  mesh.scale.setScalar(radius * SPAN);
119
120
  // Sun direction in the quad's frame, so the disc is lit from where the sun is.
120
121
  scratch.q.copy(camera.quaternion).invert();
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAA2C,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACzI,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAiBrD,KAAK,eAAe,GAAG,gBAAgB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAoBF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAqJzC,CAAC;AACF,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ObjectNode.d.ts","sourceRoot":"","sources":["../../src/components/ObjectNode.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,KAAK,EAAe,qBAAqB,EAA2C,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACzI,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAiBrD,KAAK,eAAe,GAAG,gBAAgB,GAAG;IACtC,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;CAC7G,CAAC;AAkBF,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA8IzC,CAAC;AACF,eAAe,UAAU,CAAC"}
@@ -1,9 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useMemo } from "react";
3
3
  import CustomPrimitive from "./CustomPrimitive.js";
4
4
  import CreatedObject from "./CreatedObject.js";
5
- import Text3D from './Text3D.js';
6
- import Text2D from './Text2D.js';
7
5
  import PathRenderer from './PathRenderer.js';
8
6
  import GalleryLayout from './GalleryLayout.js';
9
7
  import EffectsGenerator from './EffectsGenerator.js';
@@ -20,7 +18,7 @@ import LayoutInstances from "./LayoutInstances.js";
20
18
  import { useRuntimeSettings } from "../hooks/useRuntimeSettings.js";
21
19
  import { usePresentedVisibility } from "../operations/usePresentedVisibility.js";
22
20
  import { SELF_MANAGED_MATERIAL } from "../constants.js";
23
- import { LAYOUT_CAPABLE_TYPES, getObjectLayoutSupport, normalizeObjectLayout, isGenerativeParticlesConfig, isTextObjectConfig } from "@3driseai/3drise-core";
21
+ import { LAYOUT_CAPABLE_TYPES, getObjectLayoutSupport, normalizeObjectLayout, isGenerativeParticlesConfig } from "@3driseai/3drise-core";
24
22
  // Slots after the first render with no ready callbacks: one object reports once.
25
23
  const NO_READY = {};
26
24
  // A point light's shadow is six extra renders; only slot 0 keeps it. Cached per settings
@@ -47,9 +45,7 @@ const GroupWithChildren = ({ createdObject, children, onObjectReady, onObjectDis
47
45
  const isGroup = createdObject.type === 'group';
48
46
  // Generative particle objects own their shaders, like effects do.
49
47
  const selfManagedMaterial = SELF_MANAGED_MATERIAL.has(createdObject.type)
50
- || (createdObject.type === 'particles' && isGenerativeParticlesConfig(createdObject.config))
51
- // The animated text looks own their shaders; the legacy 2d / 3d text (same object type) keeps its material.
52
- || (createdObject.type === 'text' && isTextObjectConfig(createdObject.config));
48
+ || (createdObject.type === 'particles' && isGenerativeParticlesConfig(createdObject.config));
53
49
  return (_jsxs(CreatedObject, { createdObject: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick, shouldApply3driseMaterial: !isGroup && !selfManagedMaterial, children: [!isGroup && renderObject(createdObject, handleObjectClick), children.map(childNode => (_jsx(ObjectNode, { node: childNode, handleObjectClick: handleObjectClick, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }, childNode.objectId)))] }, createdObject.id));
54
50
  };
55
51
  const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick }) => {
@@ -95,15 +91,8 @@ const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick })
95
91
  // handleObjectClick={handleObjectClick}
96
92
  // />
97
93
  // ),
98
- text: (obj, onObjectReady) => {
99
- // The animated looks (config.type) render through TextGenerator; the legacy 2d / 3d text keeps its own path.
100
- if (isTextObjectConfig(obj.config))
101
- return (_jsx(TextGenerator, { createdObject: obj, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose }));
102
- const renderMode = obj.config?.renderMode ?? 'bitmap';
103
- return (_jsx(_Fragment, { children: renderMode === 'text3d'
104
- ? _jsx(Text3D, { textSettings: obj, ...relabel(obj) })
105
- : _jsx(Text2D, { textSettings: obj, ...relabel(obj) }) }));
106
- },
94
+ // Text looks (config.type: plain, handwriting, neonTube, …) render through TextGenerator.
95
+ text: (obj, onObjectReady) => (_jsx(TextGenerator, { createdObject: obj, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose })),
107
96
  particles: (obj, onObjectReady) => {
108
97
  // Generative particle objects (config.type) render through ParticlesGenerator;
109
98
  // the legacy shape particles keep their own path.
@@ -180,7 +169,7 @@ const ObjectNode = ({ node, onObjectReady, onObjectDispose, handleObjectClick })
180
169
  const shouldRenderAsGroup = hasChildren || createdObject.type === 'group' || createdObject.type === 'effect';
181
170
  const renderedObject = shouldRenderAsGroup
182
171
  ? _jsx(GroupWithChildren, { createdObject: createdObject, children: children, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick, renderObject: renderObject })
183
- : _jsx(CreatedObject, { createdObject: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick, shouldApply3driseMaterial: !(SELF_MANAGED_MATERIAL.has(createdObject.type) || (createdObject.type === 'text' && isTextObjectConfig(createdObject.config))), children: renderObject(createdObject) }, createdObject.id);
172
+ : _jsx(CreatedObject, { createdObject: createdObject, onObjectReady: onObjectReady, onObjectDispose: onObjectDispose, handleObjectClick: handleObjectClick, shouldApply3driseMaterial: !SELF_MANAGED_MATERIAL.has(createdObject.type), children: renderObject(createdObject) }, createdObject.id);
184
173
  // createdObject.effects
185
174
  // ? <>
186
175
  // {renderObject(createdObject)}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { SkySettings, TimeSettings } from '@3driseai/3drise-core';
2
+ import type { SkySettings, TerrainConfig, TimeSettings } from '@3driseai/3drise-core';
3
3
  import type { ObjectReadyProps } from '../types/objectReady';
4
4
  import type { OceanWaterSettings } from '@3driseai/3drise-core';
5
5
  export interface OceanBuilderProps extends ObjectReadyProps {
@@ -11,6 +11,9 @@ export interface OceanBuilderProps extends ObjectReadyProps {
11
11
  timeSettings?: TimeSettings;
12
12
  /** Matches SkySystem's sunIntensity, so water brightens with the scene. */
13
13
  sunIntensity?: number;
14
+ /** The environment terrain's config: the world ocean's shoreline and the
15
+ * terrain's shadow on the water. Omit (or disabled) for open water. */
16
+ terrain?: TerrainConfig | null;
14
17
  }
15
18
  /**
16
19
  * Picks the water body for the scene.
@@ -1 +1 @@
1
- {"version":3,"file":"OceanBuilder.d.ts","sourceRoot":"","sources":["../../src/components/OceanBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAOhE,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACvD;;uEAEmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAqC7C,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"OceanBuilder.d.ts","sourceRoot":"","sources":["../../src/components/OceanBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAOhE,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACvD;;uEAEmE;IACnE,QAAQ,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;4EACwE;IACxE,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAuC7C,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -23,7 +23,7 @@ import Shore from './water/Shore.js';
23
23
  * the nearest type, its plane size onto the host, its Y onto the sea level. See
24
24
  * `normalizeOcean`.
25
25
  */
26
- const OceanBuilder = ({ settings, skySettings, timeSettings, sunIntensity, onObjectReady, onObjectDispose, }) => {
26
+ const OceanBuilder = ({ settings, skySettings, timeSettings, sunIntensity, terrain, onObjectReady, onObjectDispose, }) => {
27
27
  // Each block against its own source. Merging them through one object would
28
28
  // hand the renderer a new config every time a quality slider moved, which
29
29
  // rebuilds every clipmap ring.
@@ -41,6 +41,7 @@ const OceanBuilder = ({ settings, skySettings, timeSettings, sunIntensity, onObj
41
41
  meshSettings: settings?.meshSettings,
42
42
  animations: settings?.animations,
43
43
  mouseMove: settings?.mouseMove,
44
+ terrain,
44
45
  onObjectReady,
45
46
  onObjectDispose,
46
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ParticlesGenerator.d.ts","sourceRoot":"","sources":["../../src/components/ParticlesGenerator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAa7D,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC7D,QAAQ,EAAE,2BAA2B,CAAC;IACtC,uFAAuF;IACvF,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,0FAA0F;AAC1F,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAmBzD,CAAC;AACF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"ParticlesGenerator.d.ts","sourceRoot":"","sources":["../../src/components/ParticlesGenerator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AA+B7D,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC7D,QAAQ,EAAE,2BAA2B,CAAC;IACtC,uFAAuF;IACvF,SAAS,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,0FAA0F;AAC1F,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAyBzD,CAAC;AACF,eAAe,kBAAkB,CAAC"}
@@ -1,15 +1,31 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import TidalStreamParticles from './particles/TidalStreamParticles.js';
3
- import BrownianDustParticles from './particles/BrownianDustParticles.js';
4
- import BioluminescentWakeParticles from './particles/BioluminescentWakeParticles.js';
5
- import ElectronOrbitalsParticles from './particles/ElectronOrbitalsParticles.js';
6
- import GrinderSparksParticles from './particles/GrinderSparksParticles.js';
7
- import ChladniSandParticles from './particles/ChladniSandParticles.js';
8
- import FaradayPowderParticles from './particles/FaradayPowderParticles.js';
9
- import NeonRainParticles from './particles/NeonRainParticles.js';
10
- import MagneticBottleParticles from './particles/MagneticBottleParticles.js';
11
- import ShapeBurstParticles from './particles/ShapeBurstParticles.js';
12
- import ShapeFlowParticles from './particles/ShapeFlowParticles.js';
2
+ import PickVolume from './PickVolume.js';
3
+ import TidalStreamParticles, { BOUNDS as TIDALSTREAM_BOUNDS } from './particles/TidalStreamParticles.js';
4
+ import BrownianDustParticles, { BOUNDS as BROWNIANDUST_BOUNDS } from './particles/BrownianDustParticles.js';
5
+ import BioluminescentWakeParticles, { BOUNDS as BIOLUMINESCENTWAKE_BOUNDS } from './particles/BioluminescentWakeParticles.js';
6
+ import ElectronOrbitalsParticles, { BOUNDS as ELECTRONORBITALS_BOUNDS } from './particles/ElectronOrbitalsParticles.js';
7
+ import GrinderSparksParticles, { BOUNDS as GRINDERSPARKS_BOUNDS } from './particles/GrinderSparksParticles.js';
8
+ import ChladniSandParticles, { BOUNDS as CHLADNISAND_BOUNDS } from './particles/ChladniSandParticles.js';
9
+ import FaradayPowderParticles, { BOUNDS as FARADAYPOWDER_BOUNDS } from './particles/FaradayPowderParticles.js';
10
+ import NeonRainParticles, { BOUNDS as NEONRAIN_BOUNDS } from './particles/NeonRainParticles.js';
11
+ import MagneticBottleParticles, { BOUNDS as MAGNETICBOTTLE_BOUNDS } from './particles/MagneticBottleParticles.js';
12
+ import ShapeBurstParticles, { BOUNDS as SHAPEBURST_BOUNDS } from './particles/ShapeBurstParticles.js';
13
+ import ShapeFlowParticles, { BOUNDS as SHAPEFLOW_BOUNDS } from './particles/ShapeFlowParticles.js';
14
+ import FireworksParticles from './particles/FireworksParticles.js';
15
+ /** Each variant's pick volume (sim units, × size): the same sphere it culls itself with. */
16
+ const PICK_BOUNDS = {
17
+ tidalStream: TIDALSTREAM_BOUNDS,
18
+ brownianDust: BROWNIANDUST_BOUNDS,
19
+ bioluminescentWake: BIOLUMINESCENTWAKE_BOUNDS,
20
+ electronOrbitals: ELECTRONORBITALS_BOUNDS,
21
+ grinderSparks: GRINDERSPARKS_BOUNDS,
22
+ chladniSand: CHLADNISAND_BOUNDS,
23
+ faradayPowder: FARADAYPOWDER_BOUNDS,
24
+ neonRain: NEONRAIN_BOUNDS,
25
+ magneticBottle: MAGNETICBOTTLE_BOUNDS,
26
+ shapeBurst: SHAPEBURST_BOUNDS,
27
+ shapeFlow: SHAPEFLOW_BOUNDS,
28
+ };
13
29
  /** Standalone generative particle objects (type 'particles'), switched on config.type. */
14
30
  const ParticlesGenerator = ({ settings, mouseMove, onObjectReady, onObjectDispose }) => {
15
31
  const { config, animations } = settings;
@@ -17,19 +33,25 @@ const ParticlesGenerator = ({ settings, mouseMove, onObjectReady, onObjectDispos
17
33
  return null;
18
34
  const size = config.size ?? 1;
19
35
  const ready = { onObjectReady, onObjectDispose, mouseMove };
20
- switch (config.type) {
21
- case 'tidalStream': return _jsx(TidalStreamParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
22
- case 'brownianDust': return _jsx(BrownianDustParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
23
- case 'bioluminescentWake': return _jsx(BioluminescentWakeParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
24
- case 'electronOrbitals': return _jsx(ElectronOrbitalsParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
25
- case 'grinderSparks': return _jsx(GrinderSparksParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
26
- case 'chladniSand': return _jsx(ChladniSandParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
27
- case 'faradayPowder': return _jsx(FaradayPowderParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
28
- case 'neonRain': return _jsx(NeonRainParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
29
- case 'magneticBottle': return _jsx(MagneticBottleParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
30
- case 'shapeBurst': return _jsx(ShapeBurstParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
31
- case 'shapeFlow': return _jsx(ShapeFlowParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
32
- default: return null;
36
+ // Hover / click hit the system's volume (its own culling sphere, × size), never a sprite.
37
+ const b = PICK_BOUNDS[config.type] ?? { center: [0, 0, 0], radius: 1.3 };
38
+ return _jsx(PickVolume, { center: [b.center[0] * size, b.center[1] * size, b.center[2] * size], radius: b.radius * size * 1.05, children: variant() });
39
+ function variant() {
40
+ switch (config.type) {
41
+ case 'tidalStream': return _jsx(TidalStreamParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
42
+ case 'brownianDust': return _jsx(BrownianDustParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
43
+ case 'bioluminescentWake': return _jsx(BioluminescentWakeParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
44
+ case 'electronOrbitals': return _jsx(ElectronOrbitalsParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
45
+ case 'grinderSparks': return _jsx(GrinderSparksParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
46
+ case 'chladniSand': return _jsx(ChladniSandParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
47
+ case 'faradayPowder': return _jsx(FaradayPowderParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
48
+ case 'neonRain': return _jsx(NeonRainParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
49
+ case 'magneticBottle': return _jsx(MagneticBottleParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
50
+ case 'shapeBurst': return _jsx(ShapeBurstParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
51
+ case 'shapeFlow': return _jsx(ShapeFlowParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
52
+ case 'fireworks': return _jsx(FireworksParticles, { id: settings.id, size: size, config: config, animations: animations, ...ready });
53
+ default: return null;
54
+ }
33
55
  }
34
56
  };
35
57
  export default ParticlesGenerator;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ export interface PickVolumeProps {
3
+ /** Sphere centre and radius in world units of the parent (already multiplied by the object's size). */
4
+ center?: [number, number, number];
5
+ radius: number;
6
+ children: React.ReactNode;
7
+ }
8
+ /**
9
+ * Hover / click land on one invisible sphere over a generative object's volume, never on what it draws: the
10
+ * sprites of a particle system live on the GPU (the CPU attributes are seeds, not positions), an effect's points
11
+ * are sparse, and a user who clicks a cloud means the cloud. The children are taken out of raycasting as they
12
+ * appear (a build can add meshes after mount), so the sphere is the only hit target. Its geometry also gives the
13
+ * selection gizmo a true bounding box.
14
+ */
15
+ declare const PickVolume: React.FC<PickVolumeProps>;
16
+ export default PickVolume;
17
+ //# sourceMappingURL=PickVolume.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PickVolume.d.ts","sourceRoot":"","sources":["../../src/components/PickVolume.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAK1D,MAAM,WAAW,eAAe;IAC5B,uGAAuG;IACvG,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,QAAA,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAWzC,CAAC;AACF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef } from 'react';
3
+ import { useFrame } from '@react-three/fiber';
4
+ import { pickSphere, stopRaycast } from '../utils/pickProxy.js';
5
+ /**
6
+ * Hover / click land on one invisible sphere over a generative object's volume, never on what it draws: the
7
+ * sprites of a particle system live on the GPU (the CPU attributes are seeds, not positions), an effect's points
8
+ * are sparse, and a user who clicks a cloud means the cloud. The children are taken out of raycasting as they
9
+ * appear (a build can add meshes after mount), so the sphere is the only hit target. Its geometry also gives the
10
+ * selection gizmo a true bounding box.
11
+ */
12
+ const PickVolume = ({ center = [0, 0, 0], radius, children }) => {
13
+ const inner = useRef(null);
14
+ const proxy = useMemo(() => pickSphere(), []);
15
+ useEffect(() => () => { proxy.geometry.dispose(); proxy.material.dispose(); }, [proxy]);
16
+ useFrame(() => { if (inner.current)
17
+ stopRaycast(inner.current); });
18
+ return (_jsxs("group", { children: [_jsx("primitive", { object: proxy, position: center, scale: [radius, radius, radius] }), _jsx("group", { ref: inner, children: children })] }));
19
+ };
20
+ export default PickVolume;
@@ -1 +1 @@
1
- {"version":3,"file":"SceneBuilder.d.ts","sourceRoot":"","sources":["../../src/components/SceneBuilder.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AAGjG,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAWxE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,gBAAgB,GAAG;IACzE;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC5C,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,oEAAoE;IACpE,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,qFAAqF;IACrF,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,YAAY;IAfd;;;OAGG;mBACY,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI;IAC3C,mFAAmF;uBAChE,KAAK,CAAC,SAAS;IAClC,oEAAoE;SAC/D,OAAO;IACZ,qFAAqF;eAC1E,OAAO,EAAE;IACpB,2EAA2E;eAChE,MAAM;qCA0LnB,CAAC;AAIH,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"SceneBuilder.d.ts","sourceRoot":"","sources":["../../src/components/SceneBuilder.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAqB,KAAK,WAAW,EAA0B,MAAM,oBAAoB,CAAC;AAGjG,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAWxE,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAM7D,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,GAAG,gBAAgB,GAAG;IACzE;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC5C,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,oEAAoE;IACpE,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,qFAAqF;IACrF,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,YAAY;IAfd;;;OAGG;mBACY,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI;IAC3C,mFAAmF;uBAChE,KAAK,CAAC,SAAS;IAClC,oEAAoE;SAC/D,OAAO;IACZ,qFAAqF;eAC1E,OAAO,EAAE;IACpB,2EAA2E;eAChE,MAAM;qCA4LnB,CAAC;AAIH,eAAe,YAAY,CAAC"}