@3driseai/3drise-viewer 0.1.40 → 0.1.42

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 (303) hide show
  1. package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -1
  2. package/dist/animationsV2/ClipsRuntime.js +9 -5
  3. package/dist/animationsV2/clipUtils.d.ts +9 -0
  4. package/dist/animationsV2/clipUtils.d.ts.map +1 -1
  5. package/dist/animationsV2/clipUtils.js +11 -2
  6. package/dist/animationsV2/normalize.d.ts.map +1 -1
  7. package/dist/animationsV2/normalize.js +2 -0
  8. package/dist/animationsV2/types.d.ts +4 -0
  9. package/dist/animationsV2/types.d.ts.map +1 -1
  10. package/dist/api/sceneHandle.d.ts +40 -3
  11. package/dist/api/sceneHandle.d.ts.map +1 -1
  12. package/dist/api/sceneHandle.js +40 -0
  13. package/dist/components/GalleryObject.d.ts +13 -0
  14. package/dist/components/GalleryObject.d.ts.map +1 -0
  15. package/dist/components/GalleryObject.js +46 -0
  16. package/dist/components/ImageObject.d.ts +9 -0
  17. package/dist/components/ImageObject.d.ts.map +1 -0
  18. package/dist/components/ImageObject.js +26 -0
  19. package/dist/components/ObjectNode.d.ts.map +1 -1
  20. package/dist/components/ObjectNode.js +11 -5
  21. package/dist/components/ProjectLoader.d.ts +2 -0
  22. package/dist/components/ProjectLoader.d.ts.map +1 -1
  23. package/dist/components/ProjectLoader.js +2 -2
  24. package/dist/components/SceneBuilder.d.ts +10 -0
  25. package/dist/components/SceneBuilder.d.ts.map +1 -1
  26. package/dist/components/SceneBuilder.js +3 -2
  27. package/dist/components/gallery/BasicCarouselGallery.d.ts +18 -0
  28. package/dist/components/gallery/BasicCarouselGallery.d.ts.map +1 -0
  29. package/dist/components/gallery/BasicCarouselGallery.js +9 -0
  30. package/dist/components/gallery/ContourLinesGallery.d.ts +18 -0
  31. package/dist/components/gallery/ContourLinesGallery.d.ts.map +1 -0
  32. package/dist/components/gallery/ContourLinesGallery.js +9 -0
  33. package/dist/components/gallery/DepthLayersGallery.d.ts +18 -0
  34. package/dist/components/gallery/DepthLayersGallery.d.ts.map +1 -0
  35. package/dist/components/gallery/DepthLayersGallery.js +9 -0
  36. package/dist/components/gallery/EngravingGallery.d.ts +18 -0
  37. package/dist/components/gallery/EngravingGallery.d.ts.map +1 -0
  38. package/dist/components/gallery/EngravingGallery.js +9 -0
  39. package/dist/components/gallery/FlowLinesGallery.d.ts +18 -0
  40. package/dist/components/gallery/FlowLinesGallery.d.ts.map +1 -0
  41. package/dist/components/gallery/FlowLinesGallery.js +9 -0
  42. package/dist/components/gallery/FoldGallery.d.ts +18 -0
  43. package/dist/components/gallery/FoldGallery.d.ts.map +1 -0
  44. package/dist/components/gallery/FoldGallery.js +9 -0
  45. package/dist/components/gallery/GlassPanesGallery.d.ts +18 -0
  46. package/dist/components/gallery/GlassPanesGallery.d.ts.map +1 -0
  47. package/dist/components/gallery/GlassPanesGallery.js +9 -0
  48. package/dist/components/gallery/HaloGallery.d.ts +18 -0
  49. package/dist/components/gallery/HaloGallery.d.ts.map +1 -0
  50. package/dist/components/gallery/HaloGallery.js +9 -0
  51. package/dist/components/gallery/LightThreadsGallery.d.ts +18 -0
  52. package/dist/components/gallery/LightThreadsGallery.d.ts.map +1 -0
  53. package/dist/components/gallery/LightThreadsGallery.js +9 -0
  54. package/dist/components/gallery/LoomGallery.d.ts +18 -0
  55. package/dist/components/gallery/LoomGallery.d.ts.map +1 -0
  56. package/dist/components/gallery/LoomGallery.js +9 -0
  57. package/dist/components/gallery/PaperLanternsGallery.d.ts +18 -0
  58. package/dist/components/gallery/PaperLanternsGallery.d.ts.map +1 -0
  59. package/dist/components/gallery/PaperLanternsGallery.js +9 -0
  60. package/dist/components/gallery/ParticleShiftGallery.d.ts +18 -0
  61. package/dist/components/gallery/ParticleShiftGallery.d.ts.map +1 -0
  62. package/dist/components/gallery/ParticleShiftGallery.js +9 -0
  63. package/dist/components/gallery/PinscreenGallery.d.ts +18 -0
  64. package/dist/components/gallery/PinscreenGallery.d.ts.map +1 -0
  65. package/dist/components/gallery/PinscreenGallery.js +9 -0
  66. package/dist/components/gallery/PopUpGallery.d.ts +18 -0
  67. package/dist/components/gallery/PopUpGallery.d.ts.map +1 -0
  68. package/dist/components/gallery/PopUpGallery.js +9 -0
  69. package/dist/components/gallery/PrismSplitGallery.d.ts +18 -0
  70. package/dist/components/gallery/PrismSplitGallery.d.ts.map +1 -0
  71. package/dist/components/gallery/PrismSplitGallery.js +9 -0
  72. package/dist/components/gallery/RidgelinesGallery.d.ts +18 -0
  73. package/dist/components/gallery/RidgelinesGallery.d.ts.map +1 -0
  74. package/dist/components/gallery/RidgelinesGallery.js +9 -0
  75. package/dist/components/gallery/ShadowBoxGallery.d.ts +18 -0
  76. package/dist/components/gallery/ShadowBoxGallery.d.ts.map +1 -0
  77. package/dist/components/gallery/ShadowBoxGallery.js +9 -0
  78. package/dist/components/gallery/SilkGallery.d.ts +18 -0
  79. package/dist/components/gallery/SilkGallery.d.ts.map +1 -0
  80. package/dist/components/gallery/SilkGallery.js +9 -0
  81. package/dist/components/gallery/SlatsGallery.d.ts +18 -0
  82. package/dist/components/gallery/SlatsGallery.d.ts.map +1 -0
  83. package/dist/components/gallery/SlatsGallery.js +9 -0
  84. package/dist/components/gallery/StrataGallery.d.ts +18 -0
  85. package/dist/components/gallery/StrataGallery.d.ts.map +1 -0
  86. package/dist/components/gallery/StrataGallery.js +9 -0
  87. package/dist/components/gallery/TerracesGallery.d.ts +18 -0
  88. package/dist/components/gallery/TerracesGallery.d.ts.map +1 -0
  89. package/dist/components/gallery/TerracesGallery.js +9 -0
  90. package/dist/components/gallery/WireReliefGallery.d.ts +18 -0
  91. package/dist/components/gallery/WireReliefGallery.d.ts.map +1 -0
  92. package/dist/components/gallery/WireReliefGallery.js +9 -0
  93. package/dist/components/gallery/index.d.ts +46 -0
  94. package/dist/components/gallery/index.d.ts.map +1 -0
  95. package/dist/components/gallery/index.js +22 -0
  96. package/dist/components/gallery/kit/GalleryVariant.d.ts +68 -0
  97. package/dist/components/gallery/kit/GalleryVariant.d.ts.map +1 -0
  98. package/dist/components/gallery/kit/GalleryVariant.js +231 -0
  99. package/dist/components/gallery/kit/feeds.d.ts +7 -0
  100. package/dist/components/gallery/kit/feeds.d.ts.map +1 -0
  101. package/dist/components/gallery/kit/feeds.js +83 -0
  102. package/dist/components/gallery/kit/galleryKit.d.ts +118 -0
  103. package/dist/components/gallery/kit/galleryKit.d.ts.map +1 -0
  104. package/dist/components/gallery/kit/galleryKit.js +298 -0
  105. package/dist/components/gallery/kit/lookBase.d.ts +157 -0
  106. package/dist/components/gallery/kit/lookBase.d.ts.map +1 -0
  107. package/dist/components/gallery/kit/lookBase.js +211 -0
  108. package/dist/components/gallery/kit/pictures.d.ts +14 -0
  109. package/dist/components/gallery/kit/pictures.d.ts.map +1 -0
  110. package/dist/components/gallery/kit/pictures.js +81 -0
  111. package/dist/components/gallery/looks/basicCarousel.d.ts +177 -0
  112. package/dist/components/gallery/looks/basicCarousel.d.ts.map +1 -0
  113. package/dist/components/gallery/looks/basicCarousel.js +315 -0
  114. package/dist/components/gallery/looks/contourLines.d.ts +153 -0
  115. package/dist/components/gallery/looks/contourLines.d.ts.map +1 -0
  116. package/dist/components/gallery/looks/contourLines.js +91 -0
  117. package/dist/components/gallery/looks/depthLayers.d.ts +155 -0
  118. package/dist/components/gallery/looks/depthLayers.d.ts.map +1 -0
  119. package/dist/components/gallery/looks/depthLayers.js +87 -0
  120. package/dist/components/gallery/looks/engraving.d.ts +162 -0
  121. package/dist/components/gallery/looks/engraving.d.ts.map +1 -0
  122. package/dist/components/gallery/looks/engraving.js +96 -0
  123. package/dist/components/gallery/looks/flowLines.d.ts +180 -0
  124. package/dist/components/gallery/looks/flowLines.d.ts.map +1 -0
  125. package/dist/components/gallery/looks/flowLines.js +113 -0
  126. package/dist/components/gallery/looks/fold.d.ts +209 -0
  127. package/dist/components/gallery/looks/fold.d.ts.map +1 -0
  128. package/dist/components/gallery/looks/fold.js +155 -0
  129. package/dist/components/gallery/looks/glassPanes.d.ts +133 -0
  130. package/dist/components/gallery/looks/glassPanes.d.ts.map +1 -0
  131. package/dist/components/gallery/looks/glassPanes.js +208 -0
  132. package/dist/components/gallery/looks/halo.d.ts +100 -0
  133. package/dist/components/gallery/looks/halo.d.ts.map +1 -0
  134. package/dist/components/gallery/looks/halo.js +119 -0
  135. package/dist/components/gallery/looks/lightThreads.d.ts +199 -0
  136. package/dist/components/gallery/looks/lightThreads.d.ts.map +1 -0
  137. package/dist/components/gallery/looks/lightThreads.js +246 -0
  138. package/dist/components/gallery/looks/loom.d.ts +238 -0
  139. package/dist/components/gallery/looks/loom.d.ts.map +1 -0
  140. package/dist/components/gallery/looks/loom.js +256 -0
  141. package/dist/components/gallery/looks/paperLanterns.d.ts +181 -0
  142. package/dist/components/gallery/looks/paperLanterns.d.ts.map +1 -0
  143. package/dist/components/gallery/looks/paperLanterns.js +399 -0
  144. package/dist/components/gallery/looks/particleShift.d.ts +193 -0
  145. package/dist/components/gallery/looks/particleShift.d.ts.map +1 -0
  146. package/dist/components/gallery/looks/particleShift.js +282 -0
  147. package/dist/components/gallery/looks/pinscreen.d.ts +175 -0
  148. package/dist/components/gallery/looks/pinscreen.d.ts.map +1 -0
  149. package/dist/components/gallery/looks/pinscreen.js +96 -0
  150. package/dist/components/gallery/looks/popUp.d.ts +206 -0
  151. package/dist/components/gallery/looks/popUp.d.ts.map +1 -0
  152. package/dist/components/gallery/looks/popUp.js +132 -0
  153. package/dist/components/gallery/looks/prismSplit.d.ts +151 -0
  154. package/dist/components/gallery/looks/prismSplit.d.ts.map +1 -0
  155. package/dist/components/gallery/looks/prismSplit.js +84 -0
  156. package/dist/components/gallery/looks/ridgelines.d.ts +179 -0
  157. package/dist/components/gallery/looks/ridgelines.d.ts.map +1 -0
  158. package/dist/components/gallery/looks/ridgelines.js +111 -0
  159. package/dist/components/gallery/looks/shadowBox.d.ts +152 -0
  160. package/dist/components/gallery/looks/shadowBox.d.ts.map +1 -0
  161. package/dist/components/gallery/looks/shadowBox.js +82 -0
  162. package/dist/components/gallery/looks/silk.d.ts +140 -0
  163. package/dist/components/gallery/looks/silk.d.ts.map +1 -0
  164. package/dist/components/gallery/looks/silk.js +346 -0
  165. package/dist/components/gallery/looks/slats.d.ts +176 -0
  166. package/dist/components/gallery/looks/slats.d.ts.map +1 -0
  167. package/dist/components/gallery/looks/slats.js +93 -0
  168. package/dist/components/gallery/looks/strata.d.ts +172 -0
  169. package/dist/components/gallery/looks/strata.d.ts.map +1 -0
  170. package/dist/components/gallery/looks/strata.js +88 -0
  171. package/dist/components/gallery/looks/terraces.d.ts +168 -0
  172. package/dist/components/gallery/looks/terraces.d.ts.map +1 -0
  173. package/dist/components/gallery/looks/terraces.js +91 -0
  174. package/dist/components/gallery/looks/wireRelief.d.ts +153 -0
  175. package/dist/components/gallery/looks/wireRelief.d.ts.map +1 -0
  176. package/dist/components/gallery/looks/wireRelief.js +128 -0
  177. package/dist/components/image/ContourImage.d.ts +7 -0
  178. package/dist/components/image/ContourImage.d.ts.map +1 -0
  179. package/dist/components/image/ContourImage.js +6 -0
  180. package/dist/components/image/EngravingImage.d.ts +7 -0
  181. package/dist/components/image/EngravingImage.d.ts.map +1 -0
  182. package/dist/components/image/EngravingImage.js +6 -0
  183. package/dist/components/image/FrostImage.d.ts +7 -0
  184. package/dist/components/image/FrostImage.d.ts.map +1 -0
  185. package/dist/components/image/FrostImage.js +6 -0
  186. package/dist/components/image/LenticularImage.d.ts +7 -0
  187. package/dist/components/image/LenticularImage.d.ts.map +1 -0
  188. package/dist/components/image/LenticularImage.js +6 -0
  189. package/dist/components/image/PinscreenImage.d.ts +7 -0
  190. package/dist/components/image/PinscreenImage.d.ts.map +1 -0
  191. package/dist/components/image/PinscreenImage.js +6 -0
  192. package/dist/components/image/PrismImage.d.ts +7 -0
  193. package/dist/components/image/PrismImage.d.ts.map +1 -0
  194. package/dist/components/image/PrismImage.js +6 -0
  195. package/dist/components/image/ProjectorImage.d.ts +7 -0
  196. package/dist/components/image/ProjectorImage.d.ts.map +1 -0
  197. package/dist/components/image/ProjectorImage.js +6 -0
  198. package/dist/components/image/ReliefImage.d.ts +7 -0
  199. package/dist/components/image/ReliefImage.d.ts.map +1 -0
  200. package/dist/components/image/ReliefImage.js +6 -0
  201. package/dist/components/image/RollImage.d.ts +7 -0
  202. package/dist/components/image/RollImage.d.ts.map +1 -0
  203. package/dist/components/image/RollImage.js +6 -0
  204. package/dist/components/image/ShardsImage.d.ts +126 -0
  205. package/dist/components/image/ShardsImage.d.ts.map +1 -0
  206. package/dist/components/image/ShardsImage.js +470 -0
  207. package/dist/components/image/core/contour.d.ts +126 -0
  208. package/dist/components/image/core/contour.d.ts.map +1 -0
  209. package/dist/components/image/core/contour.js +123 -0
  210. package/dist/components/image/core/engraving.d.ts +135 -0
  211. package/dist/components/image/core/engraving.d.ts.map +1 -0
  212. package/dist/components/image/core/engraving.js +163 -0
  213. package/dist/components/image/core/frost.d.ts +126 -0
  214. package/dist/components/image/core/frost.d.ts.map +1 -0
  215. package/dist/components/image/core/frost.js +156 -0
  216. package/dist/components/image/core/imageCore.d.ts +110 -0
  217. package/dist/components/image/core/imageCore.d.ts.map +1 -0
  218. package/dist/components/image/core/imageCore.js +269 -0
  219. package/dist/components/image/core/lenticular.d.ts +129 -0
  220. package/dist/components/image/core/lenticular.d.ts.map +1 -0
  221. package/dist/components/image/core/lenticular.js +132 -0
  222. package/dist/components/image/core/pinscreen.d.ts +126 -0
  223. package/dist/components/image/core/pinscreen.d.ts.map +1 -0
  224. package/dist/components/image/core/pinscreen.js +147 -0
  225. package/dist/components/image/core/prism.d.ts +120 -0
  226. package/dist/components/image/core/prism.d.ts.map +1 -0
  227. package/dist/components/image/core/prism.js +164 -0
  228. package/dist/components/image/core/projector.d.ts +135 -0
  229. package/dist/components/image/core/projector.d.ts.map +1 -0
  230. package/dist/components/image/core/projector.js +225 -0
  231. package/dist/components/image/core/relief.d.ts +111 -0
  232. package/dist/components/image/core/relief.d.ts.map +1 -0
  233. package/dist/components/image/core/relief.js +94 -0
  234. package/dist/components/image/core/roll.d.ts +114 -0
  235. package/dist/components/image/core/roll.d.ts.map +1 -0
  236. package/dist/components/image/core/roll.js +116 -0
  237. package/dist/components/image/imageVariant.d.ts +46 -0
  238. package/dist/components/image/imageVariant.d.ts.map +1 -0
  239. package/dist/components/image/imageVariant.js +128 -0
  240. package/dist/components/image/index.d.ts +22 -0
  241. package/dist/components/image/index.d.ts.map +1 -0
  242. package/dist/components/image/index.js +10 -0
  243. package/dist/components/image/pictureCycle.d.ts +15 -0
  244. package/dist/components/image/pictureCycle.d.ts.map +1 -0
  245. package/dist/components/image/pictureCycle.js +82 -0
  246. package/dist/components/index.d.ts +4 -0
  247. package/dist/components/index.d.ts.map +1 -1
  248. package/dist/components/index.js +4 -0
  249. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +9 -7
  250. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
  251. package/dist/components/volumetricClouds/VolumetricCloudsPass.js +39 -27
  252. package/dist/constants.d.ts.map +1 -1
  253. package/dist/constants.js +2 -0
  254. package/dist/galleryRuntime.d.ts +57 -0
  255. package/dist/galleryRuntime.d.ts.map +1 -0
  256. package/dist/galleryRuntime.js +105 -0
  257. package/dist/hooks/useConfigLive.d.ts +1 -1
  258. package/dist/hooks/useConfigLive.d.ts.map +1 -1
  259. package/dist/index.d.ts +4 -1
  260. package/dist/index.d.ts.map +1 -1
  261. package/dist/index.js +4 -0
  262. package/dist/keyPad/KeyPadControls.d.ts +16 -0
  263. package/dist/keyPad/KeyPadControls.d.ts.map +1 -0
  264. package/dist/keyPad/KeyPadControls.js +176 -0
  265. package/dist/keyPad/index.d.ts +16 -0
  266. package/dist/keyPad/index.d.ts.map +1 -0
  267. package/dist/keyPad/index.js +8 -0
  268. package/dist/keyPad/keyBindings.d.ts +43 -0
  269. package/dist/keyPad/keyBindings.d.ts.map +1 -0
  270. package/dist/keyPad/keyBindings.js +92 -0
  271. package/dist/keyPad/keyPadAnimation.d.ts +28 -0
  272. package/dist/keyPad/keyPadAnimation.d.ts.map +1 -0
  273. package/dist/keyPad/keyPadAnimation.js +131 -0
  274. package/dist/keyPad/keyPadMotion.d.ts +68 -0
  275. package/dist/keyPad/keyPadMotion.d.ts.map +1 -0
  276. package/dist/keyPad/keyPadMotion.js +283 -0
  277. package/dist/keyPad/keyPadStore.d.ts +25 -0
  278. package/dist/keyPad/keyPadStore.d.ts.map +1 -0
  279. package/dist/keyPad/keyPadStore.js +63 -0
  280. package/dist/keyPad/types.d.ts +23 -0
  281. package/dist/keyPad/types.d.ts.map +1 -0
  282. package/dist/keyPad/types.js +9 -0
  283. package/dist/operations/catalogue/visibility.d.ts.map +1 -1
  284. package/dist/operations/catalogue/visibility.js +23 -1
  285. package/dist/shaders/clouds/CloudResolveMaterial.d.ts +2 -1
  286. package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -1
  287. package/dist/shaders/clouds/CloudResolveMaterial.js +37 -12
  288. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +4 -0
  289. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -1
  290. package/dist/shaders/clouds/CloudVolumeMaterial.js +15 -3
  291. package/dist/triggers/kinds/gallery.d.ts +2 -0
  292. package/dist/triggers/kinds/gallery.d.ts.map +1 -0
  293. package/dist/triggers/kinds/gallery.js +39 -0
  294. package/dist/triggers/kinds/index.d.ts +1 -0
  295. package/dist/triggers/kinds/index.d.ts.map +1 -1
  296. package/dist/triggers/kinds/index.js +1 -0
  297. package/dist/ui/UiLayers.d.ts +17 -1
  298. package/dist/ui/UiLayers.d.ts.map +1 -1
  299. package/dist/ui/UiLayers.js +76 -3
  300. package/dist/ui/index.d.ts +2 -2
  301. package/dist/ui/index.d.ts.map +1 -1
  302. package/dist/ui/index.js +1 -1
  303. package/package.json +2 -2
@@ -0,0 +1,283 @@
1
+ // =============================================================================
2
+ // keyPadMotion — keyboard / KeyPad camera moves
3
+ // =============================================================================
4
+ //
5
+ // What the mouse does to OrbitControls, driven by held keys instead. Two camera
6
+ // styles; the control mode picks the default one and Alt switches to the other:
7
+ // orbit: arrows → orbit (left-drag)
8
+ // fly: ↑ / ↓ → walk the camera forward / back (camera and orbit point
9
+ // together — not a zoom)
10
+ // ← / → → turn in place: the orbit point swings around the camera
11
+ // pan + arrows → pan (right-drag / ctrl-drag), in either style
12
+ // zoomIn/zoomOut → dolly (wheel)
13
+ // zoom slider → sets the orbit distance directly, between the zoom limits
14
+ // home → main view
15
+ //
16
+ // Moves the live camera only — nothing is written to the store. Each move ends
17
+ // with OrbitControls.update(), so the camera's own limits still clamp it, and
18
+ // the controls' enableRotate / enablePan / enableZoom are respected like the
19
+ // mouse respects them.
20
+ //
21
+ import { Spherical, Vector3 } from 'three';
22
+ import { cameraManager } from '../utils/CameraSingleton.js';
23
+ export const CONTROL_MODES = [
24
+ { value: 'none', label: 'No keyboard' },
25
+ { value: 'orbit', label: 'Orbit first' },
26
+ { value: 'fly', label: 'Fly first' },
27
+ { value: 'animation', label: 'Animation control' },
28
+ ];
29
+ /** Fly style right now: the mode's default, flipped while Alt is held / latched. */
30
+ export const isFlying = (mode, held) => (mode === 'fly') !== held.has('alt');
31
+ /** Keys that move the camera while held (home is one-shot, pan is a modifier). */
32
+ export const HELD_MOVE_KEYS = ['up', 'down', 'left', 'right', 'zoomIn', 'zoomOut'];
33
+ /** Real keyboard → KeyPad key. Matched on KeyboardEvent.key. */
34
+ export const KEYBOARD_MAP = {
35
+ ArrowUp: 'up',
36
+ ArrowDown: 'down',
37
+ ArrowLeft: 'left',
38
+ ArrowRight: 'right',
39
+ '+': 'zoomIn',
40
+ '=': 'zoomIn',
41
+ '-': 'zoomOut',
42
+ '_': 'zoomOut',
43
+ Control: 'pan',
44
+ Alt: 'alt',
45
+ Home: 'home',
46
+ };
47
+ /** Shown on the KeyPad buttons' tooltips. */
48
+ export const KEY_HINTS = {
49
+ up: '↑',
50
+ down: '↓',
51
+ left: '←',
52
+ right: '→',
53
+ zoomIn: '+',
54
+ zoomOut: '−',
55
+ pan: 'Ctrl',
56
+ alt: 'Alt',
57
+ home: 'Home',
58
+ };
59
+ // Base rates at speed 1, per second.
60
+ const ORBIT_RAD_PER_SEC = Math.PI / 2; // 90° a second
61
+ const PAN_RADII_PER_SEC = 0.8; // fraction of the orbit distance
62
+ const ZOOM_PER_SEC = 1.6; // distance × e^(±1.6) a second
63
+ const _off = new Vector3();
64
+ const _sph = new Spherical();
65
+ const _right = new Vector3();
66
+ const _up = new Vector3();
67
+ const _worldUp = new Vector3(0, 1, 0);
68
+ const _orbitSph = new Spherical();
69
+ function liveRig() {
70
+ const cam = cameraManager.getCamera();
71
+ const oc = cameraManager.getControls();
72
+ return cam && oc && oc.enabled !== false ? { cam, oc } : null;
73
+ }
74
+ /** Orbit around the orbit point by (theta, phi) radians; the controls' limits clamp in update(). */
75
+ export function orbitBy(dTheta, dPhi) {
76
+ const rig = liveRig();
77
+ if (!rig)
78
+ return;
79
+ _orbitSph.setFromVector3(_off.copy(rig.cam.position).sub(rig.oc.target));
80
+ _orbitSph.theta += dTheta;
81
+ _orbitSph.phi += dPhi;
82
+ _orbitSph.makeSafe();
83
+ rig.cam.position.copy(rig.oc.target).add(_off.setFromSpherical(_orbitSph));
84
+ rig.cam.lookAt(rig.oc.target);
85
+ rig.oc.update?.();
86
+ }
87
+ /** Slide camera + orbit point together in the view plane (x right, y up), in metres. */
88
+ export function panBy(dx, dy) {
89
+ const rig = liveRig();
90
+ if (!rig || rig.oc.enablePan === false)
91
+ return;
92
+ rig.cam.updateMatrix();
93
+ _right.setFromMatrixColumn(rig.cam.matrix, 0).multiplyScalar(dx);
94
+ _up.setFromMatrixColumn(rig.cam.matrix, 1).multiplyScalar(dy);
95
+ _right.add(_up);
96
+ rig.cam.position.add(_right);
97
+ rig.oc.target.add(_right);
98
+ rig.oc.update?.();
99
+ }
100
+ /** Walk camera + orbit point along the view direction flattened onto the ground
101
+ * (height kept). Looking straight down, "forward" is the top of the screen. */
102
+ export function moveBy(d) {
103
+ const rig = liveRig();
104
+ if (!rig || rig.oc.enablePan === false)
105
+ return; // same rule as pan: it moves the orbit point
106
+ rig.cam.getWorldDirection(_right);
107
+ _right.y = 0;
108
+ if (_right.lengthSq() < 1e-8) {
109
+ rig.cam.updateMatrix();
110
+ _right.setFromMatrixColumn(rig.cam.matrix, 1);
111
+ _right.y = 0;
112
+ }
113
+ if (_right.lengthSq() < 1e-8)
114
+ return;
115
+ _right.normalize().multiplyScalar(d);
116
+ rig.cam.position.add(_right);
117
+ rig.oc.target.add(_right);
118
+ rig.oc.update?.();
119
+ }
120
+ // --- Zoom slider: distance ↔ 0…1 between the zoom limits --------------------------
121
+ //
122
+ // Log scale, like the wheel (each notch scales the distance), so the near end is
123
+ // as usable as the far end. t = 0 is the closest (minDistance), 1 the farthest.
124
+ /** maxDistance at / above this is the saved "no limit" (see CameraLimitsHelper). */
125
+ const NO_LIMIT = 1e6;
126
+ /** Far end of the slider when there is no max limit. */
127
+ const UNLIMITED_FAR = 1000;
128
+ const MIN_NEAR = 0.01;
129
+ export function zoomRange() {
130
+ const rig = liveRig();
131
+ if (!rig)
132
+ return null;
133
+ const distance = orbitDistance();
134
+ const near = Math.max(Number(rig.oc.minDistance) || 0, MIN_NEAR);
135
+ const maxD = Number(rig.oc.maxDistance);
136
+ let far = Number.isFinite(maxD) && maxD < NO_LIMIT ? maxD : Math.max(UNLIMITED_FAR, distance);
137
+ if (far <= near)
138
+ far = near * 1.0001;
139
+ return { near, far, distance, enabled: rig.oc.enableZoom !== false };
140
+ }
141
+ export function distanceToT(d, r) {
142
+ const t = (Math.log(d) - Math.log(r.near)) / (Math.log(r.far) - Math.log(r.near));
143
+ return Math.max(0, Math.min(1, t));
144
+ }
145
+ export function tToDistance(t, r) {
146
+ return Math.exp(Math.log(r.near) + Math.max(0, Math.min(1, t)) * (Math.log(r.far) - Math.log(r.near)));
147
+ }
148
+ /** Put the camera at `d` from the orbit point, same direction. Limits clamp in update(). */
149
+ export function setOrbitDistance(d) {
150
+ const rig = liveRig();
151
+ if (!rig || rig.oc.enableZoom === false)
152
+ return;
153
+ _off.copy(rig.cam.position).sub(rig.oc.target);
154
+ const len = _off.length();
155
+ if (len < 1e-9)
156
+ return;
157
+ rig.cam.position.copy(rig.oc.target).add(_off.multiplyScalar(d / len));
158
+ rig.oc.update?.();
159
+ }
160
+ /** Turn in place: swing the orbit point around the camera about world up (+ = right). */
161
+ export function turnBy(a) {
162
+ const rig = liveRig();
163
+ if (!rig || rig.oc.enablePan === false)
164
+ return; // same rule as move: it moves the orbit point
165
+ _off.copy(rig.oc.target).sub(rig.cam.position).applyAxisAngle(_worldUp, -a);
166
+ rig.oc.target.copy(rig.cam.position).add(_off);
167
+ rig.cam.lookAt(rig.oc.target);
168
+ rig.oc.update?.();
169
+ }
170
+ /** Scale the distance to the orbit point (<1 = closer). Limits clamp in update(). */
171
+ export function dollyBy(scale) {
172
+ const rig = liveRig();
173
+ if (!rig || rig.oc.enableZoom === false)
174
+ return;
175
+ _off.copy(rig.cam.position).sub(rig.oc.target);
176
+ _off.multiplyScalar(scale);
177
+ rig.cam.position.copy(rig.oc.target).add(_off);
178
+ rig.oc.update?.();
179
+ }
180
+ function orbitDistance() {
181
+ const rig = liveRig();
182
+ if (!rig)
183
+ return 0;
184
+ return _sph.setFromVector3(_off.copy(rig.cam.position).sub(rig.oc.target)).radius;
185
+ }
186
+ /**
187
+ * One frame of camera motion.
188
+ * @param held keys down (modifiers included, latched or held)
189
+ * @param zoom zoom rate -1 … 1 (±1 from the +/− keys)
190
+ * @param fly fly style (else orbit) — see isFlying
191
+ * @param arrows false: the arrows drive something else (animation mode); zoom only
192
+ */
193
+ export function stepKeyPad(held, zoom, dt, speed, fly, arrows = true) {
194
+ const rig = liveRig();
195
+ if (!rig)
196
+ return;
197
+ const x = arrows ? (held.has('right') ? 1 : 0) - (held.has('left') ? 1 : 0) : 0;
198
+ const y = arrows ? (held.has('up') ? 1 : 0) - (held.has('down') ? 1 : 0) : 0;
199
+ const z = zoom;
200
+ // Flying, the speed is the forward / back speed only: turn, pan and zoom keep
201
+ // their base rates. Orbiting, it scales everything.
202
+ const k = fly ? 1 : speed;
203
+ if (x || y) {
204
+ if (held.has('pan')) {
205
+ const d = orbitDistance() * PAN_RADII_PER_SEC * k * dt;
206
+ panBy(x * d, y * d);
207
+ }
208
+ else if (fly) {
209
+ // ↑ / ↓ walk, ← / → turn.
210
+ if (y)
211
+ moveBy(y * orbitDistance() * PAN_RADII_PER_SEC * speed * dt);
212
+ if (x)
213
+ turnBy(x * ORBIT_RAD_PER_SEC * dt);
214
+ }
215
+ else if (rig.oc.enableRotate !== false) {
216
+ // right → camera moves to its right around the orbit point (theta+),
217
+ // up → camera rises (phi−).
218
+ const a = ORBIT_RAD_PER_SEC * k * dt;
219
+ orbitBy(x * a, -y * a);
220
+ }
221
+ }
222
+ if (z)
223
+ dollyBy(Math.exp(-z * ZOOM_PER_SEC * k * dt));
224
+ }
225
+ /** The live camera as a view, or null before the camera is up. */
226
+ export function captureView() {
227
+ const cam = cameraManager.getCamera();
228
+ const oc = cameraManager.getControls();
229
+ if (!cam || !oc)
230
+ return null;
231
+ const r = (n) => Math.round(n * 1000) / 1000;
232
+ return {
233
+ position: [r(cam.position.x), r(cam.position.y), r(cam.position.z)],
234
+ target: [r(oc.target.x), r(oc.target.y), r(oc.target.z)],
235
+ };
236
+ }
237
+ let viewRaf = 0;
238
+ const _fromPos = new Vector3();
239
+ const _fromTarget = new Vector3();
240
+ const _toPos = new Vector3();
241
+ const _toTarget = new Vector3();
242
+ const easeInOut = (t) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2);
243
+ /** Glide camera and orbit point together to a view (a new glide replaces one in flight). */
244
+ export function glideToView(view, duration = 0.9) {
245
+ const cam = cameraManager.getCamera();
246
+ const oc = cameraManager.getControls();
247
+ if (!cam || !oc)
248
+ return;
249
+ cancelAnimationFrame(viewRaf);
250
+ _fromPos.copy(cam.position);
251
+ _fromTarget.copy(oc.target);
252
+ _toPos.set(...view.position);
253
+ _toTarget.set(...view.target);
254
+ const start = performance.now();
255
+ const step = () => {
256
+ const c = cameraManager.getCamera();
257
+ const o = cameraManager.getControls();
258
+ if (!c || !o)
259
+ return;
260
+ const t = Math.min((performance.now() - start) / (duration * 1000), 1);
261
+ const k = easeInOut(t);
262
+ c.position.lerpVectors(_fromPos, _toPos, k);
263
+ o.target.lerpVectors(_fromTarget, _toTarget, k);
264
+ c.lookAt(o.target);
265
+ o.update?.();
266
+ viewRaf = t < 1 ? requestAnimationFrame(step) : 0;
267
+ };
268
+ viewRaf = requestAnimationFrame(step);
269
+ }
270
+ /** Main view: glide the camera to the project's saved camera position. */
271
+ export function goToMainView(position) {
272
+ return cameraManager.animateCameraPosition(position);
273
+ }
274
+ /** Is this keyboard event aimed at a text field / editor, or already handled? */
275
+ export function isTypingTarget(e) {
276
+ if (e.defaultPrevented)
277
+ return true;
278
+ const el = e.target;
279
+ if (!el || !(el instanceof HTMLElement))
280
+ return false;
281
+ const tag = el.tagName;
282
+ return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || el.isContentEditable;
283
+ }
@@ -0,0 +1,25 @@
1
+ import type { KeyPadControlMode, KeyPadKey, KeyPadModifier } from './keyPadMotion';
2
+ export interface KeyPadLiveState {
3
+ pressed: readonly KeyPadKey[];
4
+ /** A modifier latched on by clicking its pad button (Ctrl / Alt on the keyboard are momentary). */
5
+ latched: KeyPadModifier | null;
6
+ /** A control mode switched to by a key binding — over the saved one until changed again. */
7
+ modeOverride: KeyPadControlMode | null;
8
+ }
9
+ export declare const keyPadStore: {
10
+ get: () => KeyPadLiveState;
11
+ subscribe(fn: () => void): () => void;
12
+ press(key: KeyPadKey): void;
13
+ release(key: KeyPadKey): void;
14
+ /** Click on a modifier button: latch it, or unlatch it if it is the latched one. */
15
+ toggleModifier(m: KeyPadModifier): void;
16
+ /** Every key up (window blur, unmount). Keeps a latched modifier. */
17
+ releaseAll(): void;
18
+ /** Keys up and modifier unlatched (control mode changed). Keeps the mode override. */
19
+ reset(): void;
20
+ setModeOverride(mode: KeyPadControlMode | null): void;
21
+ };
22
+ export declare function useKeyPadState(): KeyPadLiveState;
23
+ /** Held keys with the latched modifier folded in. */
24
+ export declare function useKeyPadHeld(): ReadonlySet<KeyPadKey>;
25
+ //# sourceMappingURL=keyPadStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyPadStore.d.ts","sourceRoot":"","sources":["../../src/keyPad/keyPadStore.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IAC9B,mGAAmG;IACnG,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,4FAA4F;IAC5F,YAAY,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC1C;AAYD,eAAO,MAAM,WAAW;eACX,eAAe;kBACV,MAAM,IAAI,GAAG,MAAM,IAAI;eAI1B,SAAS;iBAGP,SAAS;IAGtB,oFAAoF;sBAClE,cAAc;IAGhC,qEAAqE;;IAIrE,sFAAsF;;0BAEhE,iBAAiB,GAAG,IAAI;CAGjD,CAAC;AAEF,wBAAgB,cAAc,IAAI,eAAe,CAEhD;AAED,qDAAqD;AACrD,wBAAgB,aAAa,IAAI,WAAW,CAAC,SAAS,CAAC,CAOtD"}
@@ -0,0 +1,63 @@
1
+ // =============================================================================
2
+ // keyPadStore — which keys are held right now (live, never saved)
3
+ // =============================================================================
4
+ //
5
+ // One store for both sources: the real keyboard (KeyPadControls) and an on-screen
6
+ // pad (the studio's KeyPad) press / release the same keys here, so a key held on
7
+ // the keyboard lights its button and a button held on screen moves the camera
8
+ // exactly like its key. Outside React state on purpose: the published viewer has
9
+ // no Redux, and the studio and the viewer share this.
10
+ //
11
+ import { useMemo, useSyncExternalStore } from 'react';
12
+ const EMPTY = { pressed: [], latched: null, modeOverride: null };
13
+ let state = EMPTY;
14
+ const listeners = new Set();
15
+ function set(next) {
16
+ if (next === state)
17
+ return;
18
+ state = next;
19
+ listeners.forEach(fn => fn());
20
+ }
21
+ export const keyPadStore = {
22
+ get: () => state,
23
+ subscribe(fn) {
24
+ listeners.add(fn);
25
+ return () => { listeners.delete(fn); };
26
+ },
27
+ press(key) {
28
+ if (!state.pressed.includes(key))
29
+ set({ ...state, pressed: [...state.pressed, key] });
30
+ },
31
+ release(key) {
32
+ if (state.pressed.includes(key))
33
+ set({ ...state, pressed: state.pressed.filter(k => k !== key) });
34
+ },
35
+ /** Click on a modifier button: latch it, or unlatch it if it is the latched one. */
36
+ toggleModifier(m) {
37
+ set({ ...state, latched: state.latched === m ? null : m });
38
+ },
39
+ /** Every key up (window blur, unmount). Keeps a latched modifier. */
40
+ releaseAll() {
41
+ if (state.pressed.length)
42
+ set({ ...state, pressed: [] });
43
+ },
44
+ /** Keys up and modifier unlatched (control mode changed). Keeps the mode override. */
45
+ reset() { set({ ...EMPTY, modeOverride: state.modeOverride }); },
46
+ setModeOverride(mode) {
47
+ if (mode !== state.modeOverride)
48
+ set({ ...state, modeOverride: mode });
49
+ },
50
+ };
51
+ export function useKeyPadState() {
52
+ return useSyncExternalStore(keyPadStore.subscribe, keyPadStore.get, keyPadStore.get);
53
+ }
54
+ /** Held keys with the latched modifier folded in. */
55
+ export function useKeyPadHeld() {
56
+ const s = useKeyPadState();
57
+ return useMemo(() => {
58
+ const held = new Set(s.pressed);
59
+ if (s.latched)
60
+ held.add(s.latched);
61
+ return held;
62
+ }, [s]);
63
+ }
@@ -0,0 +1,23 @@
1
+ import type { KeyPadControlMode } from './keyPadMotion';
2
+ import type { KeyBinding } from './keyBindings';
3
+ /**
4
+ * A project's keyboard / KeyPad controller — saved as sceneSettings.keyPadSettings
5
+ * (scene_settings.key_pad_settings). Projects saved before it existed have none:
6
+ * read through resolveKeyPadSettings.
7
+ */
8
+ export interface KeyPadSettings {
9
+ /** The on-screen KeyPad is shown (studio toolbar). */
10
+ visible: boolean;
11
+ /** What the keyboard drives — see KeyPadControlMode. */
12
+ mode: KeyPadControlMode;
13
+ /** General speed, 1–10 (× the base rates). Orbit: orbit / pan / zoom. Fly: forward / back only. Animation: playback. */
14
+ speed: number;
15
+ /** Animation control mode: the animations / clips the arrows drive (`seq:<id>` / `clip:<id>`). */
16
+ animations: string[];
17
+ /** Keys that run things (play, apply, effects, camera views, mode switches) — see keyBindings. */
18
+ bindings: KeyBinding[];
19
+ }
20
+ export declare const DEFAULT_KEYPAD_SETTINGS: KeyPadSettings;
21
+ /** Saved settings (possibly missing / partial / null) over the defaults. */
22
+ export declare const resolveKeyPadSettings: (s?: Partial<KeyPadSettings> | null) => KeyPadSettings;
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/keyPad/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,wDAAwD;IACxD,IAAI,EAAE,iBAAiB,CAAC;IACxB,wHAAwH;IACxH,KAAK,EAAE,MAAM,CAAC;IACd,kGAAkG;IAClG,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kGAAkG;IAClG,QAAQ,EAAE,UAAU,EAAE,CAAC;CAC1B;AAED,eAAO,MAAM,uBAAuB,EAAE,cAMrC,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,GAAI,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI,KAAG,cACzB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export const DEFAULT_KEYPAD_SETTINGS = {
2
+ visible: false,
3
+ mode: 'orbit',
4
+ speed: 1,
5
+ animations: [],
6
+ bindings: [],
7
+ };
8
+ /** Saved settings (possibly missing / partial / null) over the defaults. */
9
+ export const resolveKeyPadSettings = (s) => ({ ...DEFAULT_KEYPAD_SETTINGS, ...(s ?? {}) });
@@ -1 +1 @@
1
- {"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/visibility.ts"],"names":[],"mappings":";AAIA,wBAoBG"}
1
+ {"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../src/operations/catalogue/visibility.ts"],"names":[],"mappings":";AAiBA,wBA4BG"}
@@ -1,9 +1,20 @@
1
+ import { SceneActions } from '@3driseai/3drise-core';
1
2
  import { defineOperation } from '../types.js';
2
3
  const KEY = '__opVisible';
4
+ /**
5
+ * A whole scene object (a CreatedObject root) is shown / hidden through its settings, the
6
+ * same way an action's `visible` change is: a runtime patch layer (no store write). Its
7
+ * visibility-linked effects then play in and out (usePresentedVisibility) — writing
8
+ * Object3D.visible here would cut them. A model part has no effects: set directly.
9
+ */
10
+ const objectIdOf = (target) => target?.userData?.id && target.userData.objectType ? String(target.userData.id) : null;
11
+ const layerOf = (id) => `op:visibility:${id}`;
12
+ /** Objects shown / hidden through a layer, by id — not on the Object3D: hiding can re-render it. */
13
+ const laid = new Set();
3
14
  export default defineOperation({
4
15
  value: 'visibility',
5
16
  label: 'Show / hide',
6
- description: 'Hide (or show) the targets instantly',
17
+ description: 'Hide (or show) the targets instantly — an object with visibility-linked effects plays them in / out',
7
18
  channel: 'visual',
8
19
  multi: true,
9
20
  toggles: true,
@@ -12,11 +23,22 @@ export default defineOperation({
12
23
  mode: { type: 'select', label: 'Make it', default: 'hide', options: [{ value: 'hide', label: 'Hidden' }, { value: 'show', label: 'Visible' }] },
13
24
  },
14
25
  apply(target, p) {
26
+ const id = objectIdOf(target);
27
+ if (id) {
28
+ laid.add(id);
29
+ SceneActions.setLayer(layerOf(id), { [id]: { meshSettings: { visible: p.mode === 'show' } } });
30
+ return;
31
+ }
15
32
  if (target.userData[KEY] === undefined)
16
33
  target.userData[KEY] = target.visible;
17
34
  target.visible = p.mode === 'show';
18
35
  },
19
36
  revert(target) {
37
+ const id = objectIdOf(target);
38
+ if (id && laid.delete(id)) {
39
+ SceneActions.setLayer(layerOf(id), null);
40
+ return;
41
+ }
20
42
  if (target.userData[KEY] === undefined)
21
43
  return;
22
44
  target.visible = target.userData[KEY];
@@ -7,7 +7,8 @@ export declare const CloudResolveMaterial: import("@react-three/fiber").Construc
7
7
  u_invProj: THREE.Matrix4;
8
8
  u_camWorld: THREE.Matrix4;
9
9
  u_camPos: THREE.Vector3;
10
- u_texel: THREE.Vector2;
10
+ u_curSize: THREE.Vector2;
11
+ u_offset: THREE.Vector2;
11
12
  u_blend: number;
12
13
  u_proxyHeight: number;
13
14
  u_valid: number;
@@ -1 +1 @@
1
- {"version":3,"file":"CloudResolveMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudResolveMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAkE9D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;CAehC,CAAA;AAID,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAa;QACrB,oBAAoB,EAAE,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAA;KAChE;CACF"}
1
+ {"version":3,"file":"CloudResolveMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudResolveMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AA0F9D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;CAgBhC,CAAA;AAID,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAa;QACrB,oBAAoB,EAAE,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAA;KAChE;CACF"}
@@ -2,9 +2,20 @@ import * as THREE from 'three';
2
2
  import { shaderMaterial } from '@react-three/drei';
3
3
  import { extend } from '@react-three/fiber';
4
4
  /**
5
- * Temporal resolve for the layer path. Blends this frame's half-resolution march with a
6
- * reprojected history buffer, so 96 march steps at quarter the pixel count converge to
7
- * something close to a full-resolution result over ~4 frames.
5
+ * Temporal reconstruction for the layer path.
6
+ *
7
+ * The march runs at a quarter of the cloud buffer's pixels: each frame, every march
8
+ * texel traces ONE of the four buffer pixels under it, cycling through all four over
9
+ * four frames. This pass rebuilds the full buffer from that:
10
+ *
11
+ * - the pixel traced this frame takes the fresh sample, blended with its history
12
+ * to average out the march's per-frame step jitter;
13
+ * - the other three take their reprojected history, clamped to the neighbourhood
14
+ * of this frame's samples so a stale value cannot ghost far.
15
+ *
16
+ * So every pixel is re-traced every fourth frame, and the march costs a quarter of
17
+ * what it did — the same scheme production volumetric clouds use, at a milder ratio
18
+ * (they trace one in sixteen).
8
19
  *
9
20
  * Reprojection runs against a proxy surface at the layer's mid-height rather than a
10
21
  * per-pixel cloud depth. That avoids a second render target for depth, and for a layer
@@ -20,18 +31,28 @@ precision highp float;
20
31
  in vec2 vUv;
21
32
  out vec4 outColor;
22
33
 
23
- uniform sampler2D u_current;
24
- uniform sampler2D u_history;
34
+ uniform sampler2D u_current; // the march, a quarter of this pass's pixels
35
+ uniform sampler2D u_history; // last frame's output, this pass's size
25
36
  uniform mat4 u_prevViewProj;
26
37
  uniform mat4 u_invProj, u_camWorld;
27
38
  uniform vec3 u_camPos;
28
- uniform vec2 u_texel;
29
- uniform float u_blend;
39
+ uniform vec2 u_curSize; // march buffer size in texels
40
+ uniform vec2 u_offset; // which of the 2x2 pixels was traced this frame (0 or 1 each)
41
+ uniform float u_blend; // history weight on the freshly traced pixel
30
42
  uniform float u_proxyHeight;
31
43
  uniform float u_valid;
32
44
 
33
45
  void main(){
34
- vec4 cur = texture(u_current, vUv);
46
+ ivec2 p = ivec2(gl_FragCoord.xy);
47
+ ivec2 q = p / 2;
48
+ ivec2 qMax = ivec2(u_curSize) - 1;
49
+ bool fresh = (p - q * 2) == ivec2(u_offset);
50
+
51
+ // This frame's samples sit on the centres of the traced pixels, so in march texel
52
+ // space this pixel's centre is at (p - offset) / 2 + 0.5. Bilinear there is an exact
53
+ // fetch for the traced pixel and an interpolation for the other three.
54
+ vec2 cUv = ((vec2(p) - u_offset) * 0.5 + 0.5) / u_curSize;
55
+ vec4 cur = texture(u_current, cUv);
35
56
 
36
57
  if (u_valid < 0.5){ outColor = cur; return; }
37
58
 
@@ -53,13 +74,16 @@ void main(){
53
74
 
54
75
  vec4 hist = texture(u_history, pUv);
55
76
 
56
- vec4 lo = cur, hi = cur;
77
+ // Neighbourhood of this frame's samples: the 3x3 march texels around the nearest one.
78
+ ivec2 n = clamp(ivec2(cUv * u_curSize), ivec2(0), qMax);
79
+ vec4 lo = vec4(1e9), hi = vec4(-1e9);
57
80
  for (int y = -1; y <= 1; y++)
58
81
  for (int x = -1; x <= 1; x++){
59
- vec4 s = texture(u_current, vUv + vec2(float(x), float(y)) * u_texel);
82
+ vec4 s = texelFetch(u_current, clamp(n + ivec2(x, y), ivec2(0), qMax), 0);
60
83
  lo = min(lo, s); hi = max(hi, s);
61
84
  }
62
- outColor = mix(cur, clamp(hist, lo, hi), u_blend);
85
+ vec4 h = clamp(hist, lo, hi);
86
+ outColor = fresh ? mix(cur, h, u_blend) : h;
63
87
  }
64
88
  `;
65
89
  export const CloudResolveMaterial = shaderMaterial({
@@ -69,7 +93,8 @@ export const CloudResolveMaterial = shaderMaterial({
69
93
  u_invProj: new THREE.Matrix4(),
70
94
  u_camWorld: new THREE.Matrix4(),
71
95
  u_camPos: new THREE.Vector3(),
72
- u_texel: new THREE.Vector2(1, 1),
96
+ u_curSize: new THREE.Vector2(1, 1),
97
+ u_offset: new THREE.Vector2(0, 0),
73
98
  u_blend: 0.9,
74
99
  u_proxyHeight: 2400,
75
100
  u_valid: 0
@@ -72,6 +72,8 @@ export declare const cloudVolumeDefaults: {
72
72
  u_far: number;
73
73
  u_resolution: THREE.Vector2;
74
74
  u_screenSpace: number;
75
+ u_uvOffset: THREE.Vector2;
76
+ u_minStep: number;
75
77
  };
76
78
  export declare const CloudVolumeMaterial: import("@react-three/fiber").ConstructorRepresentation<THREE.ShaderMaterial & {
77
79
  u_base: any;
@@ -142,6 +144,8 @@ export declare const CloudVolumeMaterial: import("@react-three/fiber").Construct
142
144
  u_far: number;
143
145
  u_resolution: THREE.Vector2;
144
146
  u_screenSpace: number;
147
+ u_uvOffset: THREE.Vector2;
148
+ u_minStep: number;
145
149
  }> & {
146
150
  key: string;
147
151
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CloudVolumeMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudVolumeMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAuN9D,MAAM,WAAW,0BAA0B;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6E/B,CAAA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAwD,CAAA;AAIxF,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAa;QACrB,mBAAmB,EAAE,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAA;KAC9D;CACF"}
1
+ {"version":3,"file":"CloudVolumeMaterial.d.ts","sourceRoot":"","sources":["../../../src/shaders/clouds/CloudVolumeMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAiO9D,MAAM,WAAW,0BAA0B;IACzC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+E/B,CAAA;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAwD,CAAA;AAIxF,OAAO,QAAQ,oBAAoB,CAAC;IAClC,UAAU,aAAa;QACrB,mBAAmB,EAAE,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAA;KAC9D;CACF"}
@@ -40,6 +40,12 @@ uniform vec2 u_resolution;
40
40
  uniform int u_steps;
41
41
  uniform float u_stepGrowth, u_maxSpan, u_fogDensity, u_detailFade;
42
42
  uniform float u_screenSpace;
43
+ // Layer path only. The march runs at a quarter of the cloud buffer's pixels and each
44
+ // frame picks one of the four half-res pixels under every march texel; this shifts the
45
+ // ray onto that pixel's centre. The resolve pass rebuilds the full buffer from it.
46
+ uniform vec2 u_uvOffset;
47
+ // Floor on the fine step, in metres, from the detail noise size (see applyDeckUniforms).
48
+ uniform float u_minStep;
43
49
 
44
50
  // Lightning. Declared here rather than in the shared cloudUniforms chunk so the
45
51
  // exported cloudField, which host apps pull into their own surface materials for
@@ -59,7 +65,7 @@ float ign(vec2 p){
59
65
  }
60
66
 
61
67
  void main(){
62
- vec2 uv = (u_screenSpace > 0.5) ? vUv : (gl_FragCoord.xy / u_resolution);
68
+ vec2 uv = (u_screenSpace > 0.5) ? (vUv + u_uvOffset) : (gl_FragCoord.xy / u_resolution);
63
69
  vec2 ndc = uv * 2.0 - 1.0;
64
70
 
65
71
  vec4 vp = u_invProj * vec4(ndc, -1.0, 1.0);
@@ -98,7 +104,11 @@ void main(){
98
104
  // spans 100 km; dividing that by the step budget gives kilometre steps and every
99
105
  // feature dissolves into fog. Empty space is skipped 2.8x coarser, and the step
100
106
  // grows with distance to hold screen-space error roughly constant.
101
- float dt0 = min(thick * 2.0 / float(u_steps), span / 8.0);
107
+ //
108
+ // The floor is the other half: a step much finer than the detail noise samples
109
+ // the same erosion feature many times over. On a shallow deck the depth-derived
110
+ // step can be a fraction of that, which costs samples and buys nothing visible.
111
+ float dt0 = min(max(thick * 2.0 / float(u_steps), u_minStep), span / 8.0);
102
112
  dt0 = max(dt0, thick * 0.004);
103
113
  float big = dt0 * 2.8;
104
114
 
@@ -279,7 +289,9 @@ export const cloudVolumeDefaults = {
279
289
  u_near: 1,
280
290
  u_far: 100000,
281
291
  u_resolution: new THREE.Vector2(1, 1),
282
- u_screenSpace: 0
292
+ u_screenSpace: 0,
293
+ u_uvOffset: new THREE.Vector2(0, 0),
294
+ u_minStep: 0
283
295
  };
284
296
  export const CloudVolumeMaterial = shaderMaterial(cloudVolumeDefaults, vertex, fragment);
285
297
  extend({ CloudVolumeMaterial });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gallery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../../../src/triggers/kinds/gallery.ts"],"names":[],"mappings":""}