@terraware/web-components 5.0.27 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/components/AntSwitch/index.js +19 -22
  2. package/components/Autocomplete/Autocomplete.js +106 -130
  3. package/components/Badge/index.js +28 -29
  4. package/components/BusySpinner/index.js +40 -45
  5. package/components/Button/Button.js +41 -47
  6. package/components/Checkbox.js +64 -63
  7. package/components/Confirm/index.js +74 -83
  8. package/components/DatePicker/DatePicker.js +138 -141
  9. package/components/DialogBox/DialogBox.js +111 -118
  10. package/components/Divisor.js +18 -18
  11. package/components/Dropdown.js +66 -94
  12. package/components/EditableTable/index.js +211 -271
  13. package/components/ErrorBox/ErrorBox.js +47 -49
  14. package/components/FileChooser/index.js +117 -135
  15. package/components/FormBottomBar/index.js +75 -84
  16. package/components/Icon/Icon.js +12 -20
  17. package/components/Icon/icons/index.js +256 -256
  18. package/components/IconTooltip/index.js +49 -60
  19. package/components/Map/MapBox.js +545 -452
  20. package/components/Map/MapContainer.js +25 -29
  21. package/components/Map/MapDateSliderControl.js +64 -64
  22. package/components/Map/MapDrawer.js +41 -47
  23. package/components/Map/MapLegend.js +176 -172
  24. package/components/Map/MapViewStyleControl.js +59 -63
  25. package/components/Map/ReactMapboxWrapper.js +3 -2
  26. package/components/Map/index.js +161 -180
  27. package/components/Map/types.js +12 -17
  28. package/components/Map/useMaintainLayerOrder.js +16 -26
  29. package/components/Markdown/index.js +25 -26
  30. package/components/Message/Message.js +73 -76
  31. package/components/MultiSelect/index.js +112 -124
  32. package/components/Navbar/NavFooter.js +9 -13
  33. package/components/Navbar/NavItem.js +70 -76
  34. package/components/Navbar/NavSection.js +17 -19
  35. package/components/Navbar/Navbar.js +39 -46
  36. package/components/Navbar/SubNavbar.js +9 -13
  37. package/components/Note.js +18 -22
  38. package/components/OverlayModal/OverlayModal.js +56 -63
  39. package/components/PageForm/index.js +33 -41
  40. package/components/PhotoChooser/index.js +165 -173
  41. package/components/PhotosCarousel/PhotoSlide.js +32 -35
  42. package/components/PhotosCarousel/index.js +80 -85
  43. package/components/PhotosCarousel/usePhotosCarousel.js +69 -76
  44. package/components/Pill/index.js +41 -45
  45. package/components/PillList/index.js +17 -24
  46. package/components/PlacementWrapper/index.js +38 -59
  47. package/components/PopoverMenu/Popover.js +68 -85
  48. package/components/PopoverMenu/index.js +51 -56
  49. package/components/PopoverMultiSelect/index.js +52 -59
  50. package/components/ProgressCircle/ProgressCircle.js +28 -32
  51. package/components/RadioButton.js +17 -19
  52. package/components/Select/Select.js +13 -15
  53. package/components/Select/SelectT.js +235 -250
  54. package/components/Separator/index.js +14 -17
  55. package/components/Size.js +0 -1
  56. package/components/Slider/index.js +43 -56
  57. package/components/SummaryBox.js +70 -72
  58. package/components/Tabs/index.js +133 -135
  59. package/components/TextTruncated/index.js +117 -130
  60. package/components/Textfield/Textfield.js +158 -190
  61. package/components/Textfield/TruncatedTextArea.js +70 -84
  62. package/components/TimelineSlider/TimelineMarker.js +25 -30
  63. package/components/TimelineSlider/TimelineRail.js +8 -11
  64. package/components/TimelineSlider/index.js +64 -66
  65. package/components/TimelineSliderV2/ClusterBadge.js +25 -29
  66. package/components/TimelineSliderV2/TimelineDot.js +31 -35
  67. package/components/TimelineSliderV2/TimelineRail.js +8 -11
  68. package/components/TimelineSliderV2/index.js +121 -103
  69. package/components/TimelineSliderV2/layout.js +124 -147
  70. package/components/TimelineSliderV2/types.js +0 -1
  71. package/components/Tooltip/Tooltip.js +47 -56
  72. package/components/ViewPhotosDialog/index.js +28 -35
  73. package/components/VirtualWalkthrough/Annotation.js +163 -207
  74. package/components/VirtualWalkthrough/AnnotationEditPane.js +198 -184
  75. package/components/VirtualWalkthrough/AnnotationPanel.js +187 -199
  76. package/components/VirtualWalkthrough/Application.js +31 -34
  77. package/components/VirtualWalkthrough/AutoRotator.js +85 -223
  78. package/components/VirtualWalkthrough/BlockingSpinner.js +26 -28
  79. package/components/VirtualWalkthrough/BoundaryRing.js +30 -34
  80. package/components/VirtualWalkthrough/BoundaryWall.js +32 -36
  81. package/components/VirtualWalkthrough/CameraInfo.js +100 -89
  82. package/components/VirtualWalkthrough/ControlsInfoPane.js +254 -195
  83. package/components/VirtualWalkthrough/GradientSky.js +72 -73
  84. package/components/VirtualWalkthrough/SplatControls.js +209 -221
  85. package/components/VirtualWalkthrough/SplatCrop.js +21 -20
  86. package/components/VirtualWalkthrough/SplatFadeCrop.js +21 -20
  87. package/components/VirtualWalkthrough/SplatModel.js +65 -85
  88. package/components/VirtualWalkthrough/SplatRevealRain.js +41 -46
  89. package/components/VirtualWalkthrough/TfAnnotationManager.js +197 -379
  90. package/components/VirtualWalkthrough/TfXrNavigation.js +73 -162
  91. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.js +438 -431
  92. package/components/VirtualWalkthrough/VrAnnotationPanel.js +18 -22
  93. package/components/VirtualWalkthrough/XrAnnotationInteraction.js +14 -17
  94. package/components/VirtualWalkthrough/XrExitButton.js +14 -17
  95. package/components/VirtualWalkthrough/XrGazeDwell.js +14 -17
  96. package/components/VirtualWalkthrough/XrPointerRay.js +14 -17
  97. package/components/VirtualWalkthrough/XrStartPose.js +67 -121
  98. package/components/VirtualWalkthrough/boundary-ring.js +87 -117
  99. package/components/VirtualWalkthrough/boundary-wall.js +175 -258
  100. package/components/VirtualWalkthrough/camera-adoption.js +18 -64
  101. package/components/VirtualWalkthrough/groundPlane.js +32 -47
  102. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.js +35 -35
  103. package/components/VirtualWalkthrough/splatFormat.js +13 -47
  104. package/components/VirtualWalkthrough/useAdoptedCamera.js +23 -44
  105. package/components/VirtualWalkthrough/useRestartOnVr.js +26 -37
  106. package/components/VirtualWalkthrough/useXrRenderTuning.js +33 -54
  107. package/components/VirtualWalkthrough/vr-annotation-panel-layout.js +67 -99
  108. package/components/VirtualWalkthrough/vr-annotation-panel.js +403 -433
  109. package/components/VirtualWalkthrough/vr-annotation-scroll.js +10 -28
  110. package/components/VirtualWalkthrough/walkthrough-camera.js +204 -329
  111. package/components/VirtualWalkthrough/xr-annotation-candidate-buffer.js +39 -80
  112. package/components/VirtualWalkthrough/xr-annotation-candidates.js +6 -18
  113. package/components/VirtualWalkthrough/xr-annotation-interaction.js +31 -56
  114. package/components/VirtualWalkthrough/xr-annotation-targeting.js +22 -38
  115. package/components/VirtualWalkthrough/xr-button-arming.js +7 -17
  116. package/components/VirtualWalkthrough/xr-button-hold.js +22 -36
  117. package/components/VirtualWalkthrough/xr-exit-button-mask.js +22 -36
  118. package/components/VirtualWalkthrough/xr-exit-button.js +148 -207
  119. package/components/VirtualWalkthrough/xr-face-buttons.js +19 -29
  120. package/components/VirtualWalkthrough/xr-gaze-dwell-state.js +23 -34
  121. package/components/VirtualWalkthrough/xr-gaze-dwell.js +107 -144
  122. package/components/VirtualWalkthrough/xr-interactive-ui.js +12 -24
  123. package/components/VirtualWalkthrough/xr-pointer-ray.js +13 -20
  124. package/components/VirtualWalkthrough/xr-progress-pie-material.js +117 -88
  125. package/components/VirtualWalkthrough/xr-progress-pie.js +1 -10
  126. package/components/VirtualWalkthrough/xr-ray-quad.js +16 -30
  127. package/components/VirtualWalkthrough/xr-render-tuning.js +17 -48
  128. package/components/VirtualWalkthrough/xr-scene-bounds.js +21 -37
  129. package/components/VirtualWalkthrough/xr-start-pose.js +27 -73
  130. package/components/VirtualWalkthrough/xr-teleport-gesture.js +16 -42
  131. package/components/svg/BlobbyGrayIconImage.js +41 -39
  132. package/components/svg/BlobbyGrayIconImport.js +41 -39
  133. package/components/svg/BlobbyGrayIconUploadToTheCloud.js +41 -39
  134. package/components/svg/BlobbyIconCloudChecked.js +202 -164
  135. package/components/svg/BlobbyIconExportOrUploadPhoto.js +202 -164
  136. package/components/svg/BlobbyIconFolder.js +202 -164
  137. package/components/svg/BlobbyIconGraphReport.js +202 -164
  138. package/components/svg/BlobbyIconHappy.js +202 -164
  139. package/components/svg/BlobbyIconHeartMonitor.js +202 -164
  140. package/components/svg/BlobbyIconLeaf.js +202 -164
  141. package/components/svg/BlobbyIconLibrary.js +202 -164
  142. package/components/svg/BlobbyIconNursery.js +204 -166
  143. package/components/svg/BlobbyIconOrganization.js +202 -164
  144. package/components/svg/BlobbyIconParchment.js +202 -164
  145. package/components/svg/BlobbyIconPeople.js +202 -164
  146. package/components/svg/BlobbyIconSeedBank.js +202 -164
  147. package/components/svg/BlobbyIconSeedling.js +202 -164
  148. package/components/svg/BlobbyIconSeeds.js +202 -164
  149. package/components/svg/BlobbyIconSite.js +206 -167
  150. package/components/svg/BlobbyIconSparkles.js +202 -164
  151. package/components/svg/BlobbyIconWrench.js +202 -164
  152. package/components/svg/Bug.js +19 -21
  153. package/components/svg/Calendar.js +19 -21
  154. package/components/svg/CaretDown.js +19 -21
  155. package/components/svg/CaretLeft.js +19 -21
  156. package/components/svg/CaretRight.js +19 -21
  157. package/components/svg/CaretUp.js +19 -21
  158. package/components/svg/ChevronDown.js +19 -21
  159. package/components/svg/ChevronUp.js +19 -21
  160. package/components/svg/Close.js +19 -21
  161. package/components/svg/Critical.js +19 -21
  162. package/components/svg/Edit.js +202 -164
  163. package/components/svg/Error.js +19 -21
  164. package/components/svg/Filter.js +19 -21
  165. package/components/svg/Folder.js +19 -21
  166. package/components/svg/Help.js +19 -21
  167. package/components/svg/Home.js +19 -21
  168. package/components/svg/IconAdd.js +19 -21
  169. package/components/svg/IconArrowRight.js +21 -23
  170. package/components/svg/IconBusinessNetwork.js +19 -21
  171. package/components/svg/IconCalendar.js +19 -21
  172. package/components/svg/IconCancel.js +19 -21
  173. package/components/svg/IconChargingBattery.js +19 -21
  174. package/components/svg/IconChecklist.js +21 -23
  175. package/components/svg/IconCheckmark.js +19 -21
  176. package/components/svg/IconCoinInHand.js +19 -21
  177. package/components/svg/IconColumns.js +19 -21
  178. package/components/svg/IconComment.js +20 -22
  179. package/components/svg/IconDashboard.js +19 -21
  180. package/components/svg/IconDataMigration.js +19 -21
  181. package/components/svg/IconDocument.js +21 -23
  182. package/components/svg/IconDownloadFromTheCloud.js +21 -23
  183. package/components/svg/IconEdit.js +21 -23
  184. package/components/svg/IconExpand.js +21 -23
  185. package/components/svg/IconExport.js +19 -21
  186. package/components/svg/IconExternalLink.js +19 -21
  187. package/components/svg/IconEye.js +19 -21
  188. package/components/svg/IconEyeOff.js +19 -21
  189. package/components/svg/IconFile.js +19 -21
  190. package/components/svg/IconFolder.js +19 -21
  191. package/components/svg/IconFullScreen.js +20 -22
  192. package/components/svg/IconFutures.js +19 -21
  193. package/components/svg/IconGraphReport.js +19 -21
  194. package/components/svg/IconGrid.js +19 -21
  195. package/components/svg/IconHeartMonitor.js +19 -21
  196. package/components/svg/IconHelp.js +21 -23
  197. package/components/svg/IconHistory.js +19 -21
  198. package/components/svg/IconImport.js +19 -21
  199. package/components/svg/IconIndex.js +19 -21
  200. package/components/svg/IconLayers.js +19 -21
  201. package/components/svg/IconLibrary.js +20 -22
  202. package/components/svg/IconList.js +19 -21
  203. package/components/svg/IconLivePlant.js +19 -21
  204. package/components/svg/IconLocations.js +19 -21
  205. package/components/svg/IconMail.js +19 -21
  206. package/components/svg/IconManager.js +19 -21
  207. package/components/svg/IconMap.js +19 -21
  208. package/components/svg/IconMarker.js +19 -21
  209. package/components/svg/IconMenu.js +19 -21
  210. package/components/svg/IconMenuHorizontal.js +19 -21
  211. package/components/svg/IconModule.js +19 -21
  212. package/components/svg/IconMyLocation.js +19 -21
  213. package/components/svg/IconNote.js +21 -23
  214. package/components/svg/IconNursery.js +21 -23
  215. package/components/svg/IconOrg.js +19 -21
  216. package/components/svg/IconParchment.js +19 -21
  217. package/components/svg/IconPhoto.js +19 -21
  218. package/components/svg/IconPlantsFilled.js +19 -21
  219. package/components/svg/IconRedo.js +19 -21
  220. package/components/svg/IconRestorationSite.js +19 -21
  221. package/components/svg/IconSeedBank.js +19 -21
  222. package/components/svg/IconSeedling.js +19 -21
  223. package/components/svg/IconSettings.js +19 -21
  224. package/components/svg/IconSlice.js +19 -21
  225. package/components/svg/IconSubmit.js +19 -21
  226. package/components/svg/IconSubtract.js +21 -23
  227. package/components/svg/IconSynced.js +19 -21
  228. package/components/svg/IconTrashCan.js +19 -21
  229. package/components/svg/IconTreasureMap.js +19 -21
  230. package/components/svg/IconUnavailable.js +19 -21
  231. package/components/svg/IconUndo.js +19 -21
  232. package/components/svg/IconVariable.js +19 -21
  233. package/components/svg/IconVideo.js +30 -31
  234. package/components/svg/IconWifi.js +19 -21
  235. package/components/svg/Info.js +19 -21
  236. package/components/svg/Key.js +19 -21
  237. package/components/svg/Leaf.js +19 -21
  238. package/components/svg/Lock.js +19 -21
  239. package/components/svg/Logo.js +48 -43
  240. package/components/svg/MenuVertical.js +19 -21
  241. package/components/svg/Notification.js +19 -21
  242. package/components/svg/Person.js +19 -21
  243. package/components/svg/Plus.js +19 -21
  244. package/components/svg/RestorationSite.js +19 -21
  245. package/components/svg/Search.js +19 -21
  246. package/components/svg/Seeds.js +19 -21
  247. package/components/svg/Site.js +19 -21
  248. package/components/svg/Sparkles.js +19 -21
  249. package/components/svg/Species.js +19 -21
  250. package/components/svg/Species2.js +202 -164
  251. package/components/svg/Spinner.js +54 -48
  252. package/components/svg/Star.js +19 -21
  253. package/components/svg/Success.js +19 -21
  254. package/components/svg/SuccessFilled.js +19 -21
  255. package/components/svg/TerrawareLogoDesktop.js +55 -49
  256. package/components/svg/TerrawareLogoMobile.js +25 -26
  257. package/components/svg/Touchscreen.js +19 -21
  258. package/components/svg/UploadCloud.js +202 -164
  259. package/components/svg/Warning.js +19 -21
  260. package/components/svg/WelcomeClipboard.js +156 -133
  261. package/components/svg/index.js +129 -129
  262. package/components/table/EnhancedTableToolbar.js +68 -74
  263. package/components/table/EnhancedTableToolbarV2.js +31 -41
  264. package/components/table/TableCellRenderer.js +196 -231
  265. package/components/table/TableHeader.js +71 -73
  266. package/components/table/TableHeaderItem.js +97 -102
  267. package/components/table/density.js +18 -19
  268. package/components/table/index.js +350 -369
  269. package/components/table/sort.js +27 -52
  270. package/components/table/types.js +0 -1
  271. package/components/types/index.js +0 -1
  272. package/hooks/cameraEntityContext.js +2 -13
  273. package/hooks/useBoolean.js +17 -13
  274. package/hooks/useCameraPosition.js +56 -56
  275. package/hooks/useDevicePerformance.js +17 -17
  276. package/hooks/useXr.js +85 -87
  277. package/index.js +58 -58
  278. package/package.json +1 -1
  279. package/setupTests.js +0 -4
  280. package/strings/export.js +111 -170
  281. package/strings/index.js +25 -54
  282. package/strings/locales.js +21 -41
  283. package/strings/strings-en.js +49 -51
  284. package/strings/strings-es.js +49 -51
  285. package/strings/strings-fr.js +49 -51
  286. package/strings/strings-gx.js +49 -51
  287. package/style-dictionary-dist/TerrawareTheme.js +186 -186
  288. package/theme.js +74 -76
  289. package/utils/color.js +8 -15
  290. package/utils/date.js +42 -108
  291. package/utils/index.js +4 -4
  292. package/utils/preventDefaultEvent.js +3 -3
  293. package/utils/text.js +11 -11
  294. package/utils/useDeviceInfo.js +42 -79
  295. package/virtualWalkthrough.js +23 -23
@@ -1,7 +1,6 @@
1
- import { Vec3 } from 'playcanvas';
2
- import { GSplatShaderEffect } from 'playcanvas/scripts/esm/gsplat/gsplat-shader-effect.mjs';
3
-
4
- const shaderGLSL = /* glsl */`
1
+ import { Vec3 } from "playcanvas";
2
+ import { GSplatShaderEffect } from "playcanvas/scripts/esm/gsplat/gsplat-shader-effect.mjs";
3
+ const shaderGLSL = `
5
4
  uniform vec3 uAabbMin;
6
5
  uniform vec3 uAabbMax;
7
6
  uniform float uFadeDistance;
@@ -44,7 +43,7 @@ void modifySplatColor(vec3 center, inout vec4 color) {
44
43
  // No color modification needed
45
44
  }
46
45
  `;
47
- const shaderWGSL = /* wgsl */`
46
+ const shaderWGSL = `
48
47
  uniform uAabbMin: vec3f;
49
48
  uniform uAabbMax: vec3f;
50
49
  uniform uFadeDistance: f32;
@@ -87,36 +86,37 @@ fn modifySplatColor(center: vec3f, color: ptr<function, vec4f>) {
87
86
  // No color modification needed
88
87
  }
89
88
  `;
90
-
91
- /**
92
- * Fade crop shader effect for gaussian splats.
93
- * Applies a smooth fade to splats outside the AABB based on distance.
94
- * Splats at the AABB edge are fully visible, and fade to invisible at fadeDistance away.
95
- */
96
89
  class GsplatFadeCropShaderEffect extends GSplatShaderEffect {
97
- static scriptName = 'gsplatFadeCropShaderEffect';
98
- _aabbMinArray = [0, 0, 0];
99
- _aabbMaxArray = [0, 0, 0];
100
- aabbMin = new Vec3(-0.5, -0.5, -0.5);
101
- aabbMax = new Vec3(0.5, 0.5, 0.5);
102
- fadeDistance = 0.5;
103
- getShaderGLSL() {
104
- return shaderGLSL;
105
- }
106
- getShaderWGSL() {
107
- return shaderWGSL;
108
- }
109
- updateEffect() {
110
- this._aabbMinArray[0] = this.aabbMin.x;
111
- this._aabbMinArray[1] = this.aabbMin.y;
112
- this._aabbMinArray[2] = this.aabbMin.z;
113
- this.setUniform('uAabbMin', this._aabbMinArray);
114
- this._aabbMaxArray[0] = this.aabbMax.x;
115
- this._aabbMaxArray[1] = this.aabbMax.y;
116
- this._aabbMaxArray[2] = this.aabbMax.z;
117
- this.setUniform('uAabbMax', this._aabbMaxArray);
118
- this.setUniform('uFadeDistance', this.fadeDistance);
119
- }
90
+ static scriptName = 'gsplatFadeCropShaderEffect';
91
+ _aabbMinArray = [
92
+ 0,
93
+ 0,
94
+ 0
95
+ ];
96
+ _aabbMaxArray = [
97
+ 0,
98
+ 0,
99
+ 0
100
+ ];
101
+ aabbMin = new Vec3(-0.5, -0.5, -0.5);
102
+ aabbMax = new Vec3(0.5, 0.5, 0.5);
103
+ fadeDistance = 0.5;
104
+ getShaderGLSL() {
105
+ return shaderGLSL;
106
+ }
107
+ getShaderWGSL() {
108
+ return shaderWGSL;
109
+ }
110
+ updateEffect() {
111
+ this._aabbMinArray[0] = this.aabbMin.x;
112
+ this._aabbMinArray[1] = this.aabbMin.y;
113
+ this._aabbMinArray[2] = this.aabbMin.z;
114
+ this.setUniform('uAabbMin', this._aabbMinArray);
115
+ this._aabbMaxArray[0] = this.aabbMax.x;
116
+ this._aabbMaxArray[1] = this.aabbMax.y;
117
+ this._aabbMaxArray[2] = this.aabbMax.z;
118
+ this.setUniform('uAabbMax', this._aabbMaxArray);
119
+ this.setUniform('uFadeDistance', this.fadeDistance);
120
+ }
120
121
  }
121
-
122
122
  export { GsplatFadeCropShaderEffect };
@@ -1,52 +1,18 @@
1
- /*
2
- * The playcanvas gsplat loader picks its parser from the asset's `filename`, not from the URL it
3
- * actually downloads, because a splat is frequently served from a signed or extensionless URL. Each
4
- * supported format therefore maps to a canonical filename whose extension/basename routes the asset
5
- * to the matching engine parser:
6
- *
7
- * model.sog -> SogBundleParser sog packed into a single zip archive
8
- * meta.json -> SogParser the same sog data left unpacked as separate files
9
- * lod-meta.json -> GSplatOctreeParser sog with LOD levels, streamed in as the camera moves
10
- * model.ply -> PlyParser
11
- *
12
- * `sog` and `sogUnbundled` are two packagings of one format, not two formats: both parsers build a
13
- * GSplatSogData/GSplatSogResource and both await every texture before the resource exists. Only
14
- * `sogStreamed` streams — playcanvas.d.ts on GSplatOctreeResource#numSplats: "Not all of these are
15
- * resident at runtime: the LOD streaming system selects a subset per node based on view distance and
16
- * the configured splat budget."
17
- *
18
- * Only the filename is faked; the textures an unbundled or streamed sog references are still
19
- * resolved relative to the real URL, so no rewriting of splatSrc is needed.
20
- */
21
1
  const LOADER_FILENAMES = {
22
- sog: 'model.sog',
23
- sogUnbundled: 'meta.json',
24
- sogStreamed: 'lod-meta.json',
25
- ply: 'model.ply'
2
+ sog: 'model.sog',
3
+ sogUnbundled: 'meta.json',
4
+ sogStreamed: 'lod-meta.json',
5
+ ply: 'model.ply'
26
6
  };
27
- /**
28
- * Format assumed when a URL is too opaque to tell us anything. Kept as the bundled `.sog` archive so
29
- * that existing extensionless splat URLs keep loading the way they did before the other formats were
30
- * supported.
31
- */
32
7
  const DEFAULT_SPLAT_FORMAT = 'sog';
33
- const splatLoaderFilename = format => LOADER_FILENAMES[format];
34
- const detectSplatFormat = splatSrc => {
35
- const path = splatSrc.split(/[?#]/)[0];
36
- const basename = path.slice(path.lastIndexOf('/') + 1).toLowerCase();
37
- if (basename === 'lod-meta.json') {
38
- return 'sogStreamed';
39
- }
40
- if (basename === 'meta.json') {
41
- return 'sogUnbundled';
42
- }
43
- if (basename.endsWith('.ply')) {
44
- return 'ply';
45
- }
46
- if (basename.endsWith('.sog')) {
47
- return 'sog';
48
- }
49
- return DEFAULT_SPLAT_FORMAT;
8
+ const splatLoaderFilename = (format)=>LOADER_FILENAMES[format];
9
+ const detectSplatFormat = (splatSrc)=>{
10
+ const path = splatSrc.split(/[?#]/)[0];
11
+ const basename = path.slice(path.lastIndexOf('/') + 1).toLowerCase();
12
+ if ('lod-meta.json' === basename) return 'sogStreamed';
13
+ if ('meta.json' === basename) return 'sogUnbundled';
14
+ if (basename.endsWith('.ply')) return 'ply';
15
+ if (basename.endsWith('.sog')) return 'sog';
16
+ return DEFAULT_SPLAT_FORMAT;
50
17
  };
51
-
52
18
  export { DEFAULT_SPLAT_FORMAT, detectSplatFormat, splatLoaderFilename };
@@ -1,45 +1,24 @@
1
- import { useState, useLayoutEffect } from 'react';
2
- import { useApp } from '@playcanvas/react/hooks';
3
- import { adoptSceneCamera } from './camera-adoption.js';
4
-
5
- /**
6
- * Keeps the walkthrough's rig holding a camera for as long as the viewer is mounted, adopting the
7
- * scene's own when the viewer wasn't given one. See {@link adoptSceneCamera} for why.
8
- *
9
- * @param rig - The `camera-root` entity, or null before it exists.
10
- * @param ownCamera - The entity the viewer mounts its own camera on, or null before it exists.
11
- * @returns The adopted camera, or null when the viewer brought one of its own. Held as state so the
12
- * viewer re-renders and re-points everything that addresses the camera at the entity now carrying
13
- * it.
14
- */
15
- const useAdoptedCamera = (rig, ownCamera) => {
16
- const app = useApp();
17
- const [adopted, setAdopted] = useState(null);
18
-
19
- // A layout effect, so that the camera is handed back before the rig it was parented into is
20
- // destroyed. `@playcanvas/react`'s Entity destroys its entity in a layout effect's teardown, and
21
- // destroying an entity destroys its children — so a release deferred to a passive effect runs
22
- // after the host's camera has already been destroyed along with the walkthrough, leaving the host
23
- // scene with no camera to render through at all.
24
- //
25
- // The rig is a child of the viewer, and React tears an unmounting tree's layout effects down from
26
- // the top, so this runs first.
27
- useLayoutEffect(() => {
28
- if (!rig || !ownCamera) {
29
- return;
30
- }
31
-
32
- // Both entities are state set from refs, so this runs a commit after the child that mounts the
33
- // camera component: a viewer that was given a camera is recognised as owning one rather than
34
- // adopted on top of.
35
- const adoption = adoptSceneCamera(app.root, rig, ownCamera);
36
- setAdopted(adoption?.camera ?? null);
37
- return () => {
38
- adoption?.release();
39
- setAdopted(null);
40
- };
41
- }, [app, rig, ownCamera]);
42
- return adopted;
1
+ import { useLayoutEffect, useState } from "react";
2
+ import { useApp } from "@playcanvas/react/hooks";
3
+ import { adoptSceneCamera } from "./camera-adoption.js";
4
+ const useAdoptedCamera = (rig, ownCamera)=>{
5
+ const app = useApp();
6
+ const [adopted, setAdopted] = useState(null);
7
+ useLayoutEffect(()=>{
8
+ if (!rig || !ownCamera) return;
9
+ const adoption = adoptSceneCamera(app.root, rig, ownCamera);
10
+ setAdopted(adoption?.camera ?? null);
11
+ return ()=>{
12
+ adoption?.release();
13
+ setAdopted(null);
14
+ };
15
+ }, [
16
+ app,
17
+ rig,
18
+ ownCamera
19
+ ]);
20
+ return adopted;
43
21
  };
44
-
45
- export { useAdoptedCamera as default, useAdoptedCamera };
22
+ const VirtualWalkthrough_useAdoptedCamera = useAdoptedCamera;
23
+ export default VirtualWalkthrough_useAdoptedCamera;
24
+ export { useAdoptedCamera };
@@ -1,38 +1,27 @@
1
- import { useEffect } from 'react';
2
- import { useApp } from '@playcanvas/react/hooks';
3
- import { XRTYPE_VR } from 'playcanvas';
4
-
5
- /**
6
- * Replays a one-shot script effect at the start of every VR session.
7
- *
8
- * `GSplatShaderEffect` zeroes its timeline on the script's `enable` event and switches itself off
9
- * once the animation has played out, so re-enabling a finished effect runs it again. The `enabled`
10
- * setter only fires the event on a change of state, which is why an effect still mid-play is taken
11
- * back through disabled first.
12
- *
13
- * @param scriptRef - The script instance to replay, as handed back by `Script`'s ref.
14
- * @param enabled - Whether the effect is in use at all. No session is watched while false.
15
- */
16
- const useRestartOnVr = (scriptRef, enabled) => {
17
- const app = useApp();
18
- useEffect(() => {
19
- const xr = app?.xr;
20
- if (!xr || !enabled) {
21
- return;
22
- }
23
- const restart = () => {
24
- const script = scriptRef.current;
25
- if (!script || xr.type !== XRTYPE_VR) {
26
- return;
27
- }
28
- script.enabled = false;
29
- script.enabled = true;
30
- };
31
- xr.on('start', restart);
32
- return () => {
33
- xr.off('start', restart);
34
- };
35
- }, [app, enabled, scriptRef]);
1
+ import { useEffect } from "react";
2
+ import { useApp } from "@playcanvas/react/hooks";
3
+ import { XRTYPE_VR } from "playcanvas";
4
+ const useRestartOnVr = (scriptRef, enabled)=>{
5
+ const app = useApp();
6
+ useEffect(()=>{
7
+ const xr = app?.xr;
8
+ if (!xr || !enabled) return;
9
+ const restart = ()=>{
10
+ const script = scriptRef.current;
11
+ if (!script || xr.type !== XRTYPE_VR) return;
12
+ script.enabled = false;
13
+ script.enabled = true;
14
+ };
15
+ xr.on('start', restart);
16
+ return ()=>{
17
+ xr.off('start', restart);
18
+ };
19
+ }, [
20
+ app,
21
+ enabled,
22
+ scriptRef
23
+ ]);
36
24
  };
37
-
38
- export { useRestartOnVr as default, useRestartOnVr };
25
+ const VirtualWalkthrough_useRestartOnVr = useRestartOnVr;
26
+ export default VirtualWalkthrough_useRestartOnVr;
27
+ export { useRestartOnVr };
@@ -1,55 +1,34 @@
1
- import { useEffect } from 'react';
2
- import { useApp } from '@playcanvas/react/hooks';
3
- import { applyGsplatTuning, XR_FIXED_FOVEATION, restoreGsplatTuning } from './xr-render-tuning.js';
4
-
5
- /**
6
- * Holds the XR render settings in place for the duration of a session, including one that is
7
- * already running when this mounts.
8
- *
9
- * Call this once per application. The gsplat settings it writes are scene-global, so a second
10
- * caller would capture the first caller's tuned values as the state to restore, and the scene would
11
- * come out of the session still tuned.
12
- */
13
- const useXrRenderTuning = () => {
14
- const app = useApp();
15
- useEffect(() => {
16
- const xr = app.xr;
17
- if (!xr) {
18
- return;
19
- }
20
- let previous = null;
21
- const restore = () => {
22
- if (previous) {
23
- restoreGsplatTuning(app.scene.gsplat, previous);
24
- previous = null;
25
- }
26
- };
27
- const handleStart = () => {
28
- // Guards against capturing already-tuned values as the restore target if `start` ever
29
- // fires again before a matching `end`.
30
- if (!previous) {
31
- previous = applyGsplatTuning(app.scene.gsplat);
32
- }
33
- // Only settable on an active session, so it cannot go in the start options alongside
34
- // framebufferScaleFactor. A no-op when the presentation layer doesn't support it.
35
- xr.fixedFoveation = XR_FIXED_FOVEATION;
36
- };
37
- xr.on('start', handleStart);
38
- xr.on('end', restore);
39
-
40
- // A viewer can be mounted into a scene that is already in a headset, in which case `start`
41
- // fired before this hook existed and waiting for it would leave the whole session rendering
42
- // with the desktop settings. `handleStart` is idempotent, so a session that goes on to fire
43
- // `start` anyway does not capture the tuned values as the ones to restore.
44
- if (xr.active) {
45
- handleStart();
46
- }
47
- return () => {
48
- xr.off('start', handleStart);
49
- xr.off('end', restore);
50
- restore();
51
- };
52
- }, [app]);
1
+ import { useEffect } from "react";
2
+ import { useApp } from "@playcanvas/react/hooks";
3
+ import { XR_FIXED_FOVEATION, applyGsplatTuning, restoreGsplatTuning } from "./xr-render-tuning.js";
4
+ const useXrRenderTuning = ()=>{
5
+ const app = useApp();
6
+ useEffect(()=>{
7
+ const xr = app.xr;
8
+ if (!xr) return;
9
+ let previous = null;
10
+ const restore = ()=>{
11
+ if (previous) {
12
+ restoreGsplatTuning(app.scene.gsplat, previous);
13
+ previous = null;
14
+ }
15
+ };
16
+ const handleStart = ()=>{
17
+ if (!previous) previous = applyGsplatTuning(app.scene.gsplat);
18
+ xr.fixedFoveation = XR_FIXED_FOVEATION;
19
+ };
20
+ xr.on('start', handleStart);
21
+ xr.on('end', restore);
22
+ if (xr.active) handleStart();
23
+ return ()=>{
24
+ xr.off('start', handleStart);
25
+ xr.off('end', restore);
26
+ restore();
27
+ };
28
+ }, [
29
+ app
30
+ ]);
53
31
  };
54
-
55
- export { useXrRenderTuning as default, useXrRenderTuning };
32
+ const VirtualWalkthrough_useXrRenderTuning = useXrRenderTuning;
33
+ export default VirtualWalkthrough_useXrRenderTuning;
34
+ export { useXrRenderTuning };
@@ -1,29 +1,20 @@
1
- /**
2
- * Greedily wraps `text` into lines no wider than `maxWidth`, using `measure` to size
3
- * each candidate line. A single word wider than `maxWidth` still gets its own line.
4
- */
5
- const wrapText = (text, maxWidth, measure) => {
6
- const words = text.split(/\s+/).filter(Boolean);
7
- const lines = [];
8
- let current = '';
9
- words.forEach(word => {
10
- const candidate = current ? `${current} ${word}` : word;
11
- if (!current || measure(candidate) <= maxWidth) {
12
- current = candidate;
13
- } else {
14
- lines.push(current);
15
- current = word;
16
- }
17
- });
18
- if (current) {
19
- lines.push(current);
20
- }
21
- return lines;
1
+ const wrapText = (text, maxWidth, measure)=>{
2
+ const words = text.split(/\s+/).filter(Boolean);
3
+ const lines = [];
4
+ let current = '';
5
+ words.forEach((word)=>{
6
+ const candidate = current ? `${current} ${word}` : word;
7
+ if (!current || measure(candidate) <= maxWidth) current = candidate;
8
+ else {
9
+ lines.push(current);
10
+ current = word;
11
+ }
12
+ });
13
+ if (current) lines.push(current);
14
+ return lines;
22
15
  };
23
16
  const PANEL_CANVAS_WIDTH = 1024;
24
- /** Tallest the panel can grow; also the canvas the content is painted into. */
25
17
  const PANEL_MAX_HEIGHT = 768;
26
- /** Shortest the panel can shrink, so a bare title still reads as a panel rather than a sliver. */
27
18
  const PANEL_MIN_HEIGHT = 200;
28
19
  const PANEL_PAD_X = 48;
29
20
  const PANEL_PAD_Y = 40;
@@ -37,86 +28,63 @@ const CHIP_GAP = 24;
37
28
  const TITLE_LINE_HEIGHT = 56;
38
29
  const TITLE_GAP = 16;
39
30
  const BODY_LINE_HEIGHT = 40;
40
-
41
- /**
42
- * Tallest canvas the body text is rasterised into. The body scrolls as a window onto this canvas,
43
- * so it bounds how much text an annotation can show — far more than the panel itself holds.
44
- */
45
31
  const TEXT_CANVAS_MAX_HEIGHT = 2048;
46
32
  const PANEL_FONTS = {
47
- label: '600 28px sans-serif',
48
- title: '700 48px sans-serif',
49
- body: '400 32px sans-serif'
33
+ label: '600 28px sans-serif',
34
+ title: '700 48px sans-serif',
35
+ body: '400 32px sans-serif'
50
36
  };
51
- /** Keeps the lines whose full line box fits above the bottom padding. */
52
- const fitLines = (lines, y, lineHeight) => {
53
- const room = Math.max(0, Math.floor((PANEL_MAX_HEIGHT - PANEL_PAD_Y - y) / lineHeight));
54
- return lines.slice(0, room);
37
+ const fitLines = (lines, y, lineHeight)=>{
38
+ const room = Math.max(0, Math.floor((PANEL_MAX_HEIGHT - PANEL_PAD_Y - y) / lineHeight));
39
+ return lines.slice(0, room);
55
40
  };
56
-
57
- /**
58
- * Lays the panel's blocks out top-to-bottom and reports the height they need, so the quad
59
- * can be sized to the content instead of a fixed aspect. Everything above the body is a header
60
- * that has to fit within `PANEL_MAX_HEIGHT`; the body instead scrolls within whatever height
61
- * the header leaves it.
62
- */
63
- const layoutPanel = ({
64
- title,
65
- label,
66
- bodyText,
67
- imageCount,
68
- contentWidth,
69
- measure
70
- }) => {
71
- let y = PANEL_PAD_Y;
72
- const image = imageCount > 0 ? {
73
- y,
74
- height: IMAGE_BAND_HEIGHT
75
- } : null;
76
- let dotsY = null;
77
- if (image) {
78
- y += IMAGE_BAND_HEIGHT + IMAGE_GAP;
79
- if (imageCount > 1) {
80
- dotsY = y + DOTS_CENTER_OFFSET;
81
- y += DOTS_BLOCK_HEIGHT;
82
- }
83
- y += IMAGE_GAP;
84
- }
85
- const chip = label ? {
86
- y,
87
- width: measure(label, 'label') + CHIP_PAD_X * 2,
88
- height: CHIP_HEIGHT
89
- } : null;
90
- if (chip) {
91
- y += CHIP_HEIGHT + CHIP_GAP;
92
- }
93
- const titleLines = wrapText(title, contentWidth, segment => measure(segment, 'title'));
94
- const fittedTitle = fitLines(titleLines, y, TITLE_LINE_HEIGHT);
95
- const titleY = y;
96
- y += fittedTitle.length * TITLE_LINE_HEIGHT + TITLE_GAP;
97
- const bodyLines = bodyText ? wrapText(bodyText, contentWidth, segment => measure(segment, 'body')) : [];
98
- const fittedBody = bodyLines.slice(0, Math.floor(TEXT_CANVAS_MAX_HEIGHT / BODY_LINE_HEIGHT));
99
- const bodyY = y;
100
- const contentHeight = fittedBody.length * BODY_LINE_HEIGHT;
101
- const viewportHeight = Math.min(contentHeight, Math.max(0, PANEL_MAX_HEIGHT - PANEL_PAD_Y - bodyY));
102
- const height = Math.max(PANEL_MIN_HEIGHT, Math.min(PANEL_MAX_HEIGHT, bodyY + viewportHeight + PANEL_PAD_Y));
103
- return {
104
- height,
105
- image,
106
- dotsY,
107
- chip,
108
- title: {
109
- y: titleY,
110
- lines: fittedTitle
111
- },
112
- body: {
113
- y: bodyY,
114
- lines: fittedBody,
115
- contentHeight,
116
- viewportHeight,
117
- scrollable: viewportHeight > 0 && contentHeight > viewportHeight
41
+ const layoutPanel = ({ title, label, bodyText, imageCount, contentWidth, measure })=>{
42
+ let y = PANEL_PAD_Y;
43
+ const image = imageCount > 0 ? {
44
+ y,
45
+ height: IMAGE_BAND_HEIGHT
46
+ } : null;
47
+ let dotsY = null;
48
+ if (image) {
49
+ y += IMAGE_BAND_HEIGHT + IMAGE_GAP;
50
+ if (imageCount > 1) {
51
+ dotsY = y + DOTS_CENTER_OFFSET;
52
+ y += DOTS_BLOCK_HEIGHT;
53
+ }
54
+ y += IMAGE_GAP;
118
55
  }
119
- };
56
+ const chip = label ? {
57
+ y,
58
+ width: measure(label, 'label') + 2 * CHIP_PAD_X,
59
+ height: CHIP_HEIGHT
60
+ } : null;
61
+ if (chip) y += CHIP_HEIGHT + CHIP_GAP;
62
+ const titleLines = wrapText(title, contentWidth, (segment)=>measure(segment, 'title'));
63
+ const fittedTitle = fitLines(titleLines, y, TITLE_LINE_HEIGHT);
64
+ const titleY = y;
65
+ y += fittedTitle.length * TITLE_LINE_HEIGHT + TITLE_GAP;
66
+ const bodyLines = bodyText ? wrapText(bodyText, contentWidth, (segment)=>measure(segment, 'body')) : [];
67
+ const fittedBody = bodyLines.slice(0, Math.floor(TEXT_CANVAS_MAX_HEIGHT / BODY_LINE_HEIGHT));
68
+ const bodyY = y;
69
+ const contentHeight = fittedBody.length * BODY_LINE_HEIGHT;
70
+ const viewportHeight = Math.min(contentHeight, Math.max(0, PANEL_MAX_HEIGHT - PANEL_PAD_Y - bodyY));
71
+ const height = Math.max(PANEL_MIN_HEIGHT, Math.min(PANEL_MAX_HEIGHT, bodyY + viewportHeight + PANEL_PAD_Y));
72
+ return {
73
+ height,
74
+ image,
75
+ dotsY,
76
+ chip,
77
+ title: {
78
+ y: titleY,
79
+ lines: fittedTitle
80
+ },
81
+ body: {
82
+ y: bodyY,
83
+ lines: fittedBody,
84
+ contentHeight,
85
+ viewportHeight,
86
+ scrollable: viewportHeight > 0 && contentHeight > viewportHeight
87
+ }
88
+ };
120
89
  };
121
-
122
90
  export { BODY_LINE_HEIGHT, CHIP_HEIGHT, IMAGE_BAND_HEIGHT, PANEL_CANVAS_WIDTH, PANEL_FONTS, PANEL_MAX_HEIGHT, PANEL_MIN_HEIGHT, PANEL_PAD_X, PANEL_PAD_Y, TEXT_CANVAS_MAX_HEIGHT, TITLE_LINE_HEIGHT, layoutPanel, wrapText };