@terraware/web-components 5.0.26 → 5.0.27-rc.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,438 +1,445 @@
1
- import { useState, useCallback, useRef, useEffect, useMemo } from 'react';
2
- import { useTheme } from '@mui/material';
3
- import { Entity } from '@playcanvas/react';
4
- import { Script, Camera } from '@playcanvas/react/components';
5
- import { useApp } from '@playcanvas/react/hooks';
6
- import { Vec3, Color } from 'playcanvas';
7
- import { XrControllers } from 'playcanvas/scripts/esm/xr/xr-controllers.mjs';
8
- import { CameraEntityContext } from '../../hooks/cameraEntityContext.js';
9
- import { useCameraPosition } from '../../hooks/useCameraPosition.js';
10
- import { useDevicePerformance } from '../../hooks/useDevicePerformance.js';
11
- import useXr from '../../hooks/useXr.js';
12
- import Annotation from './Annotation.js';
13
- import AnnotationPanel from './AnnotationPanel.js';
14
- import { AutoRotator } from './AutoRotator.js';
15
- import BoundaryRing from './BoundaryRing.js';
16
- import BoundaryWall from './BoundaryWall.js';
17
- import GradientSky from './GradientSky.js';
18
- import SplatControls from './SplatControls.js';
19
- import SplatModel from './SplatModel.js';
20
- import { TfAnnotationManager } from './TfAnnotationManager.js';
21
- import { TfXrNavigation } from './TfXrNavigation.js';
22
- import VrAnnotationPanel from './VrAnnotationPanel.js';
23
- import XrAnnotationInteraction from './XrAnnotationInteraction.js';
24
- import XrExitButton from './XrExitButton.js';
25
- import XrGazeDwell from './XrGazeDwell.js';
26
- import XrPointerRay from './XrPointerRay.js';
27
- import { XrStartPose } from './XrStartPose.js';
28
- import useAdoptedCamera from './useAdoptedCamera.js';
29
- import useXrRenderTuning from './useXrRenderTuning.js';
30
- import { WalkthroughCamera } from './walkthrough-camera.js';
31
- import { rayHitsInteractiveUi } from './xr-interactive-ui.js';
32
- import { jsx, jsxs } from 'react/jsx-runtime';
33
-
34
- const DEFAULT_FOCUS_POINT = [0, 0.1, 0];
35
- const DEFAULT_POSITION = [1, 0.1, 0];
36
-
37
- // How far outside the clamp radius the boundary wall stands. Without it the wall would be coplanar
38
- // with the surface the head is clamped to, so a pinned user would have it in their face and through
39
- // their near clip plane.
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { useTheme } from "@mui/material";
4
+ import { Entity } from "@playcanvas/react";
5
+ import { Camera, Script } from "@playcanvas/react/components";
6
+ import { useApp } from "@playcanvas/react/hooks";
7
+ import { Color, Vec3 } from "playcanvas";
8
+ import { XrControllers } from "playcanvas/scripts/esm/xr/xr-controllers.mjs";
9
+ import { CameraEntityContext } from "../../hooks/cameraEntityContext.js";
10
+ import { useCameraPosition } from "../../hooks/useCameraPosition.js";
11
+ import { useDevicePerformance } from "../../hooks/useDevicePerformance.js";
12
+ import { useXr } from "../../hooks/useXr.js";
13
+ import Annotation from "./Annotation.js";
14
+ import AnnotationPanel from "./AnnotationPanel.js";
15
+ import { AutoRotator } from "./AutoRotator.js";
16
+ import BoundaryRing from "./BoundaryRing.js";
17
+ import BoundaryWall from "./BoundaryWall.js";
18
+ import GradientSky from "./GradientSky.js";
19
+ import SplatControls from "./SplatControls.js";
20
+ import SplatModel from "./SplatModel.js";
21
+ import { TfAnnotationManager } from "./TfAnnotationManager.js";
22
+ import { TfXrNavigation } from "./TfXrNavigation.js";
23
+ import VrAnnotationPanel from "./VrAnnotationPanel.js";
24
+ import XrAnnotationInteraction from "./XrAnnotationInteraction.js";
25
+ import XrExitButton from "./XrExitButton.js";
26
+ import XrGazeDwell from "./XrGazeDwell.js";
27
+ import XrPointerRay from "./XrPointerRay.js";
28
+ import { XrStartPose } from "./XrStartPose.js";
29
+ import { useAdoptedCamera } from "./useAdoptedCamera.js";
30
+ import { useXrRenderTuning } from "./useXrRenderTuning.js";
31
+ import { WalkthroughCamera } from "./walkthrough-camera.js";
32
+ import { rayHitsInteractiveUi } from "./xr-interactive-ui.js";
33
+ const DEFAULT_FOCUS_POINT = [
34
+ 0,
35
+ 0.1,
36
+ 0
37
+ ];
38
+ const DEFAULT_POSITION = [
39
+ 1,
40
+ 0.1,
41
+ 0
42
+ ];
40
43
  const WALL_INSET = 0.25;
41
-
42
- /**
43
- * Largest world size (metres) a hotspot is allowed to reach as the camera approaches it, so it
44
- * stops growing rather than filling the view from close up.
45
- */
46
44
  const MAX_HOTSPOT_WORLD_SIZE = 0.75;
47
-
48
- /**
49
- * Every coordinate, distance and size in this component is world-space, in the metres an XR
50
- * headset imposes on the scene: `scaleFactor` converts the splat's own arbitrary units to them,
51
- * and is applied to nothing but the splat itself.
52
- */
53
-
54
- const VirtualWalkthroughViewer = ({
55
- splatSrc,
56
- splatFormat,
57
- camera = /*#__PURE__*/jsx(Camera, {
45
+ const VirtualWalkthroughViewer = ({ splatSrc, splatFormat, camera = /*#__PURE__*/ jsx(Camera, {
58
46
  clearColor: "#EAF8FF",
59
47
  fov: 60
60
- }),
61
- origin = DEFAULT_FOCUS_POINT,
62
- cameraPosition = DEFAULT_POSITION,
63
- sceneBounds,
64
- groundPlane: groundPlaneProp,
65
- skyColor,
66
- groundColor,
67
- averageCameraHeight = 0,
68
- scaleFactor = 1,
69
- splatModelProps,
70
- autoStartVr = false,
71
- onXrExit,
72
- onXrClose,
73
- annotations,
74
- onSaveAnnotations,
75
- editable = false,
76
- showFreeFly = false,
77
- isFullScreen = false,
78
- onToggleFullScreen,
79
- maxImagesPerAnnotation
80
- }) => {
81
- const theme = useTheme();
82
- // Held as state so the effects and hooks that address these entities re-run once they
83
- // exist. Addressed directly: a viewer mounted into a host's scene shares the graph
84
- // with the host's entities, so the camera can be found by component type.
85
- const [cameraRoot, setCameraRoot] = useState(null);
86
- const [cameraEntity, setCameraEntity] = useState(null);
87
- const adoptedCamera = useAdoptedCamera(cameraRoot, cameraEntity);
88
- // The entity carrying the live camera component: the viewer's own, or the host's while adopted.
89
- // Everything that poses the camera or projects through it addresses this rather than the entity
90
- // the viewer mounts a camera of its own on, which holds nothing while a camera is adopted.
91
- const activeCamera = adoptedCamera ?? cameraEntity;
92
- const {
93
- setCamera
94
- } = useCameraPosition(activeCamera);
95
- const {
96
- isHighPerformance
97
- } = useDevicePerformance();
98
- const app = useApp();
99
- const [showAnnotations, setShowAnnotations] = useState(true);
100
- const [autoRotate, setAutoRotate] = useState(true);
101
- const [isEdit, setIsEdit] = useState(false);
102
- const [isFreeFly, setIsFreeFly] = useState(false);
103
- const [selectedAnnotationIndex, setSelectedAnnotationIndex] = useState(-1);
104
- const [localAnnotations, setLocalAnnotations] = useState(annotations);
105
- const [isTextFieldFocused, setIsTextFieldFocused] = useState(false);
106
- const [viewingAnnotation, setViewingAnnotation] = useState(null);
107
- const [viewingAnnotationIndex, setViewingAnnotationIndex] = useState(-1);
108
- const [viewedScreenPos, setViewedScreenPos] = useState(null);
109
- const reportXrError = useCallback(error => {
110
- console.warn(error.message, error);
111
- onXrExit?.(error);
112
- }, [onXrExit]);
113
- const {
114
- isCurrentlyInXr,
115
- isCurrentlyInVr,
116
- isCurrentlyInAr,
117
- isXrAvailable,
118
- startXr
119
- } = useXr({
120
- onError: reportXrError
121
- });
122
- useXrRenderTuning();
123
- const autoStartRequested = useRef(false);
124
-
125
- // Edge-triggered so that ending a session doesn't pull the user straight back into one. The ref
126
- // is written before the early returns, so lowering the prop re-arms the next rising edge.
127
- useEffect(() => {
128
- const isRisingEdge = autoStartVr && !autoStartRequested.current;
129
- autoStartRequested.current = autoStartVr;
130
- if (!isRisingEdge || isCurrentlyInXr) {
131
- return;
132
- }
133
- if (!isXrAvailable('VR')) {
134
- reportXrError(new Error('A VR session was requested, but this device reports no immersive VR support'));
135
- return;
136
- }
137
- startXr('VR');
138
- }, [autoStartVr, isCurrentlyInXr, isXrAvailable, startXr, reportXrError]);
139
- const wasInXr = useRef(false);
140
-
141
- // Edge-detected rather than reported whenever the viewer is out of XR, which would fire on mount
142
- // and tell a caller a session had ended before one ever began.
143
- useEffect(() => {
144
- if (wasInXr.current && !isCurrentlyInXr) {
145
- onXrExit?.();
146
- }
147
- wasInXr.current = isCurrentlyInXr;
148
- }, [isCurrentlyInXr, onXrExit]);
149
- const sceneBoundsRadius = useMemo(() => {
150
- if (sceneBounds?.m !== undefined) {
151
- return sceneBounds.m;
152
- }
153
- const dx = cameraPosition[0] - origin[0];
154
- const dy = cameraPosition[1] - origin[1];
155
- const dz = cameraPosition[2] - origin[2];
156
- return Math.sqrt(dx * dx + dy * dy + dz * dz);
157
- }, [cameraPosition, sceneBounds, origin]);
158
- const sceneBoundsCenter = useMemo(() => sceneBounds ? new Vec3(sceneBounds.x, sceneBounds.y, sceneBounds.z) : new Vec3(origin[0], cameraPosition[1], origin[2]), [sceneBounds, origin, cameraPosition]);
159
- const groundPlane = useMemo(() => groundPlaneProp?.length === 3 ? groundPlaneProp.map(p => new Vec3(p[0], p[1], p[2])) : [], [groundPlaneProp]);
160
-
161
- // Also runs when a session ends. WalkthroughCamera is unmounted for the duration of a session, so
162
- // the camera entity is left holding the last head pose — an eye height above wherever in the rig
163
- // the user was standing — which is neither where nor how high the walkthrough left off.
164
- useEffect(() => {
165
- if (isCurrentlyInXr) {
166
- return;
167
- }
168
- setCamera(origin, cameraPosition);
169
- }, [origin, cameraPosition, setCamera, isCurrentlyInXr]);
170
-
171
- // Re-applied when a session ends for the same reason: the script that comes back is a new
172
- // instance, and without the ground plane it walks the camera at the bounds centre's height
173
- // instead of an eye height above the ground.
174
- useEffect(() => {
175
- if (!groundPlane.length || isCurrentlyInXr) {
176
- return;
177
- }
178
- // @ts-expect-error - scripts are added dynamically to the entity
179
- const walkthroughCam = cameraRoot?.script?.walkthroughCamera;
180
- if (walkthroughCam) {
181
- // Should be changed to a react prop if shallowEquals in playcanvas/react is fixed (see https://github.com/playcanvas/react/pull/298)
182
- walkthroughCam.groundPlane = groundPlane;
183
- }
184
- }, [groundPlane, cameraRoot, isCurrentlyInXr]);
185
- useEffect(() => {
186
- // Set imperatively for the same reason as BoundaryRing: boundsCenter is a Vec3, and the
187
- // @playcanvas/react memo() comparator stops at the first prop with an .equals() method.
188
- // @ts-expect-error - scripts are added dynamically to the entity
189
- const navigation = cameraRoot?.script?.tfXrNavigation;
190
- if (navigation) {
191
- navigation.boundsCenter = sceneBoundsCenter;
192
- navigation.boundsRadius = sceneBoundsRadius;
193
- }
194
- }, [cameraRoot, sceneBoundsCenter, sceneBoundsRadius]);
195
- const handleToggleFreeFly = useCallback(() => {
196
- const newFreeFly = !isFreeFly;
197
- // @ts-expect-error - scripts are added dynamically to the entity
198
- const walkthroughCam = cameraRoot?.script?.walkthroughCamera;
199
- if (walkthroughCam) {
200
- walkthroughCam.freeFly = newFreeFly;
201
- }
202
- if (!newFreeFly) {
203
- setCamera(origin, cameraPosition);
204
- }
205
- setIsFreeFly(newFreeFly);
206
- }, [isFreeFly, cameraRoot, setCamera, origin, cameraPosition]);
207
- useEffect(() => {
208
- setLocalAnnotations(annotations);
209
- }, [annotations]);
210
- useEffect(() => {
211
- if (!isEdit) {
212
- setSelectedAnnotationIndex(-1);
213
- }
214
- }, [isEdit]);
215
- const handleAnnotationPositionChange = useCallback(position => {
216
- setLocalAnnotations(prev => {
217
- if (selectedAnnotationIndex === -1) {
218
- return prev;
219
- }
220
- const updated = [...prev];
221
- updated[selectedAnnotationIndex] = {
222
- ...updated[selectedAnnotationIndex],
223
- position
224
- };
225
- return updated;
48
+ }), origin = DEFAULT_FOCUS_POINT, cameraPosition = DEFAULT_POSITION, sceneBounds, groundPlane: groundPlaneProp, skyColor, groundColor, averageCameraHeight = 0, scaleFactor = 1, splatModelProps, autoStartVr = false, onXrExit, onXrClose, annotations, onSaveAnnotations, editable = false, showFreeFly = false, isFullScreen = false, onToggleFullScreen, maxImagesPerAnnotation })=>{
49
+ const theme = useTheme();
50
+ const [cameraRoot, setCameraRoot] = useState(null);
51
+ const [cameraEntity, setCameraEntity] = useState(null);
52
+ const adoptedCamera = useAdoptedCamera(cameraRoot, cameraEntity);
53
+ const activeCamera = adoptedCamera ?? cameraEntity;
54
+ const { setCamera } = useCameraPosition(activeCamera);
55
+ const { isHighPerformance } = useDevicePerformance();
56
+ const app = useApp();
57
+ const [showAnnotations, setShowAnnotations] = useState(true);
58
+ const [autoRotate, setAutoRotate] = useState(true);
59
+ const [isEdit, setIsEdit] = useState(false);
60
+ const [isFreeFly, setIsFreeFly] = useState(false);
61
+ const [selectedAnnotationIndex, setSelectedAnnotationIndex] = useState(-1);
62
+ const [localAnnotations, setLocalAnnotations] = useState(annotations);
63
+ const [isTextFieldFocused, setIsTextFieldFocused] = useState(false);
64
+ const [viewingAnnotation, setViewingAnnotation] = useState(null);
65
+ const [viewingAnnotationIndex, setViewingAnnotationIndex] = useState(-1);
66
+ const [viewedScreenPos, setViewedScreenPos] = useState(null);
67
+ const reportXrError = useCallback((error)=>{
68
+ console.warn(error.message, error);
69
+ onXrExit?.(error);
70
+ }, [
71
+ onXrExit
72
+ ]);
73
+ const { isCurrentlyInXr, isCurrentlyInVr, isCurrentlyInAr, isXrAvailable, startXr } = useXr({
74
+ onError: reportXrError
226
75
  });
227
- }, [selectedAnnotationIndex]);
228
- const handleSave = useCallback(() => {
229
- const saveAndClose = async () => {
230
- await onSaveAnnotations(localAnnotations);
231
- setIsEdit(false);
232
- setSelectedAnnotationIndex(-1);
233
- };
234
- void saveAndClose();
235
- }, [onSaveAnnotations, localAnnotations]);
236
- const handleCancel = useCallback(() => {
237
- setLocalAnnotations(annotations);
238
- setIsEdit(false);
239
- setSelectedAnnotationIndex(-1);
240
- }, [annotations]);
241
- const handleAddAnnotation = useCallback(() => {
242
- const newAnnotation = {
243
- position: origin,
244
- title: ''
245
- };
246
- setLocalAnnotations(prev => [...prev, newAnnotation]);
247
- setSelectedAnnotationIndex(localAnnotations.length);
248
- }, [origin, localAnnotations]);
249
- const handleDeleteAnnotation = useCallback(() => {
250
- if (selectedAnnotationIndex === -1) {
251
- return;
252
- }
253
- setLocalAnnotations(prev => prev.filter((_, index) => index !== selectedAnnotationIndex));
254
- setSelectedAnnotationIndex(-1);
255
- }, [selectedAnnotationIndex]);
256
- const handleDeselectAnnotation = useCallback(() => {
257
- setSelectedAnnotationIndex(-1);
258
- }, []);
259
- const handleAnnotationView = useCallback(
260
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
261
- (annotation, annotationIndex, screenX, screenY) => {
262
- setViewingAnnotation(annotation);
263
- setViewingAnnotationIndex(annotationIndex);
264
- // Cleared so the connector line waits for the hotspot's post-aim position
265
- // rather than briefly pointing at its old spot.
266
- setViewedScreenPos(null);
267
- }, []);
268
- const handleAnnotationScreenPositionUpdate = useCallback((_index, screenX, screenY, size) => {
269
- if (isCurrentlyInXr) {
270
- return;
271
- }
272
- // The scene is frozen while the panel is open, so guard against redundant
273
- // updates from the per-frame callback to avoid needless re-renders.
274
- setViewedScreenPos(prev => prev && prev.x === screenX && prev.y === screenY && prev.size === size ? prev : {
275
- x: screenX,
276
- y: screenY,
277
- size
76
+ useXrRenderTuning();
77
+ const autoStartRequested = useRef(false);
78
+ useEffect(()=>{
79
+ const isRisingEdge = autoStartVr && !autoStartRequested.current;
80
+ autoStartRequested.current = autoStartVr;
81
+ if (!isRisingEdge || isCurrentlyInXr) return;
82
+ if (!isXrAvailable('VR')) return void reportXrError(new Error('A VR session was requested, but this device reports no immersive VR support'));
83
+ startXr('VR');
84
+ }, [
85
+ autoStartVr,
86
+ isCurrentlyInXr,
87
+ isXrAvailable,
88
+ startXr,
89
+ reportXrError
90
+ ]);
91
+ const wasInXr = useRef(false);
92
+ useEffect(()=>{
93
+ if (wasInXr.current && !isCurrentlyInXr) onXrExit?.();
94
+ wasInXr.current = isCurrentlyInXr;
95
+ }, [
96
+ isCurrentlyInXr,
97
+ onXrExit
98
+ ]);
99
+ const sceneBoundsRadius = useMemo(()=>{
100
+ if (sceneBounds?.m !== void 0) return sceneBounds.m;
101
+ const dx = cameraPosition[0] - origin[0];
102
+ const dy = cameraPosition[1] - origin[1];
103
+ const dz = cameraPosition[2] - origin[2];
104
+ return Math.sqrt(dx * dx + dy * dy + dz * dz);
105
+ }, [
106
+ cameraPosition,
107
+ sceneBounds,
108
+ origin
109
+ ]);
110
+ const sceneBoundsCenter = useMemo(()=>sceneBounds ? new Vec3(sceneBounds.x, sceneBounds.y, sceneBounds.z) : new Vec3(origin[0], cameraPosition[1], origin[2]), [
111
+ sceneBounds,
112
+ origin,
113
+ cameraPosition
114
+ ]);
115
+ const groundPlane = useMemo(()=>groundPlaneProp?.length === 3 ? groundPlaneProp.map((p)=>new Vec3(p[0], p[1], p[2])) : [], [
116
+ groundPlaneProp
117
+ ]);
118
+ useEffect(()=>{
119
+ if (isCurrentlyInXr) return;
120
+ setCamera(origin, cameraPosition);
121
+ }, [
122
+ origin,
123
+ cameraPosition,
124
+ setCamera,
125
+ isCurrentlyInXr
126
+ ]);
127
+ useEffect(()=>{
128
+ if (!groundPlane.length || isCurrentlyInXr) return;
129
+ const walkthroughCam = cameraRoot?.script?.walkthroughCamera;
130
+ if (walkthroughCam) walkthroughCam.groundPlane = groundPlane;
131
+ }, [
132
+ groundPlane,
133
+ cameraRoot,
134
+ isCurrentlyInXr
135
+ ]);
136
+ useEffect(()=>{
137
+ const navigation = cameraRoot?.script?.tfXrNavigation;
138
+ if (navigation) {
139
+ navigation.boundsCenter = sceneBoundsCenter;
140
+ navigation.boundsRadius = sceneBoundsRadius;
141
+ }
142
+ }, [
143
+ cameraRoot,
144
+ sceneBoundsCenter,
145
+ sceneBoundsRadius
146
+ ]);
147
+ const handleToggleFreeFly = useCallback(()=>{
148
+ const newFreeFly = !isFreeFly;
149
+ const walkthroughCam = cameraRoot?.script?.walkthroughCamera;
150
+ if (walkthroughCam) walkthroughCam.freeFly = newFreeFly;
151
+ if (!newFreeFly) setCamera(origin, cameraPosition);
152
+ setIsFreeFly(newFreeFly);
153
+ }, [
154
+ isFreeFly,
155
+ cameraRoot,
156
+ setCamera,
157
+ origin,
158
+ cameraPosition
159
+ ]);
160
+ useEffect(()=>{
161
+ setLocalAnnotations(annotations);
162
+ }, [
163
+ annotations
164
+ ]);
165
+ useEffect(()=>{
166
+ if (!isEdit) setSelectedAnnotationIndex(-1);
167
+ }, [
168
+ isEdit
169
+ ]);
170
+ const handleAnnotationPositionChange = useCallback((position)=>{
171
+ setLocalAnnotations((prev)=>{
172
+ if (-1 === selectedAnnotationIndex) return prev;
173
+ const updated = [
174
+ ...prev
175
+ ];
176
+ updated[selectedAnnotationIndex] = {
177
+ ...updated[selectedAnnotationIndex],
178
+ position
179
+ };
180
+ return updated;
181
+ });
182
+ }, [
183
+ selectedAnnotationIndex
184
+ ]);
185
+ const handleSave = useCallback(()=>{
186
+ const saveAndClose = async ()=>{
187
+ await onSaveAnnotations(localAnnotations);
188
+ setIsEdit(false);
189
+ setSelectedAnnotationIndex(-1);
190
+ };
191
+ saveAndClose();
192
+ }, [
193
+ onSaveAnnotations,
194
+ localAnnotations
195
+ ]);
196
+ const handleCancel = useCallback(()=>{
197
+ setLocalAnnotations(annotations);
198
+ setIsEdit(false);
199
+ setSelectedAnnotationIndex(-1);
200
+ }, [
201
+ annotations
202
+ ]);
203
+ const handleAddAnnotation = useCallback(()=>{
204
+ const newAnnotation = {
205
+ position: origin,
206
+ title: ''
207
+ };
208
+ setLocalAnnotations((prev)=>[
209
+ ...prev,
210
+ newAnnotation
211
+ ]);
212
+ setSelectedAnnotationIndex(localAnnotations.length);
213
+ }, [
214
+ origin,
215
+ localAnnotations
216
+ ]);
217
+ const handleDeleteAnnotation = useCallback(()=>{
218
+ if (-1 === selectedAnnotationIndex) return;
219
+ setLocalAnnotations((prev)=>prev.filter((_, index)=>index !== selectedAnnotationIndex));
220
+ setSelectedAnnotationIndex(-1);
221
+ }, [
222
+ selectedAnnotationIndex
223
+ ]);
224
+ const handleDeselectAnnotation = useCallback(()=>{
225
+ setSelectedAnnotationIndex(-1);
226
+ }, []);
227
+ const handleAnnotationView = useCallback((annotation, annotationIndex, screenX, screenY)=>{
228
+ setViewingAnnotation(annotation);
229
+ setViewingAnnotationIndex(annotationIndex);
230
+ setViewedScreenPos(null);
231
+ }, []);
232
+ const handleAnnotationScreenPositionUpdate = useCallback((_index, screenX, screenY, size)=>{
233
+ if (isCurrentlyInXr) return;
234
+ setViewedScreenPos((prev)=>prev && prev.x === screenX && prev.y === screenY && prev.size === size ? prev : {
235
+ x: screenX,
236
+ y: screenY,
237
+ size
238
+ });
239
+ }, [
240
+ isCurrentlyInXr
241
+ ]);
242
+ const handleCloseAnnotation = useCallback(()=>{
243
+ setViewingAnnotation(null);
244
+ setViewingAnnotationIndex(-1);
245
+ setViewedScreenPos(null);
246
+ }, []);
247
+ const isTeleportBlocked = useCallback((inputSource)=>rayHitsInteractiveUi(app, inputSource.getOrigin(), inputSource.getDirection()), [
248
+ app
249
+ ]);
250
+ useEffect(()=>{
251
+ if (!isCurrentlyInXr) handleCloseAnnotation();
252
+ }, [
253
+ isCurrentlyInXr,
254
+ handleCloseAnnotation
255
+ ]);
256
+ const handleAnnotationUpdate = useCallback((updates)=>{
257
+ if (-1 === selectedAnnotationIndex) return;
258
+ setLocalAnnotations((prev)=>{
259
+ const updated = [
260
+ ...prev
261
+ ];
262
+ updated[selectedAnnotationIndex] = {
263
+ ...updated[selectedAnnotationIndex],
264
+ ...updates
265
+ };
266
+ return updated;
267
+ });
268
+ }, [
269
+ selectedAnnotationIndex
270
+ ]);
271
+ const handleImagesChange = useCallback((files)=>handleAnnotationUpdate({
272
+ images: files
273
+ }), [
274
+ handleAnnotationUpdate
275
+ ]);
276
+ const canSave = useMemo(()=>localAnnotations.every((annotation)=>annotation.title && '' !== annotation.title.trim()), [
277
+ localAnnotations
278
+ ]);
279
+ const splatModel = useMemo(()=>/*#__PURE__*/ jsx(SplatModel, {
280
+ ...splatModelProps,
281
+ splatSrc: splatSrc,
282
+ splatFormat: splatFormat,
283
+ rotation: [
284
+ -180,
285
+ 0,
286
+ 0
287
+ ],
288
+ scaleFactor: scaleFactor,
289
+ revealRain: isHighPerformance
290
+ }, "splat"), [
291
+ isHighPerformance,
292
+ splatSrc,
293
+ splatFormat,
294
+ scaleFactor,
295
+ splatModelProps
296
+ ]);
297
+ return /*#__PURE__*/ jsxs(CameraEntityContext.Provider, {
298
+ value: activeCamera,
299
+ children: [
300
+ /*#__PURE__*/ jsx(GradientSky, {
301
+ topColor: skyColor || '#FFFFFF',
302
+ horizonColor: skyColor || '#EAF8FF',
303
+ groundColor: groundColor || '#C3BDB7'
304
+ }),
305
+ /*#__PURE__*/ jsxs(Entity, {
306
+ name: "camera-root",
307
+ ref: setCameraRoot,
308
+ children: [
309
+ /*#__PURE__*/ jsx(Entity, {
310
+ name: "camera",
311
+ ref: setCameraEntity,
312
+ children: camera
313
+ }),
314
+ !isCurrentlyInXr && /*#__PURE__*/ jsx(Script, {
315
+ script: WalkthroughCamera,
316
+ boundsCenter: sceneBoundsCenter,
317
+ boundsRadius: sceneBoundsRadius,
318
+ enableFly: !isTextFieldFocused,
319
+ averageCameraHeight: averageCameraHeight
320
+ }),
321
+ /*#__PURE__*/ jsx(XrExitButton, {
322
+ onClose: onXrClose
323
+ }),
324
+ /*#__PURE__*/ jsx(Script, {
325
+ script: XrControllers,
326
+ enabled: !isEdit
327
+ }),
328
+ /*#__PURE__*/ jsx(XrAnnotationInteraction, {
329
+ onDismiss: handleCloseAnnotation
330
+ }),
331
+ /*#__PURE__*/ jsx(XrPointerRay, {}),
332
+ isCurrentlyInVr && viewingAnnotation && /*#__PURE__*/ jsx(VrAnnotationPanel, {
333
+ annotation: viewingAnnotation,
334
+ annotationIndex: viewingAnnotationIndex
335
+ }, viewingAnnotationIndex),
336
+ /*#__PURE__*/ jsx(XrGazeDwell, {
337
+ activeIndex: viewingAnnotationIndex
338
+ }),
339
+ /*#__PURE__*/ jsx(Script, {
340
+ script: XrStartPose,
341
+ targetX: cameraPosition[0],
342
+ targetZ: cameraPosition[2],
343
+ focusX: origin[0],
344
+ focusZ: origin[2]
345
+ }),
346
+ /*#__PURE__*/ jsx(Script, {
347
+ script: TfXrNavigation,
348
+ enabled: !isEdit,
349
+ enableTeleport: !isCurrentlyInAr && !viewingAnnotation,
350
+ enableSnapVertical: false,
351
+ isTeleportBlocked: isTeleportBlocked
352
+ }),
353
+ !isCurrentlyInXr && /*#__PURE__*/ jsx(Script, {
354
+ script: AutoRotator,
355
+ enabled: !isEdit && autoRotate && !viewingAnnotation,
356
+ startDelay: 0.5,
357
+ restartDelay: 3,
358
+ startFadeInTime: 0.5
359
+ })
360
+ ]
361
+ }),
362
+ /*#__PURE__*/ jsxs(Entity, {
363
+ name: "content-root",
364
+ children: [
365
+ splatModel,
366
+ sceneBounds?.m !== void 0 && 3 === groundPlane.length && /*#__PURE__*/ jsx(BoundaryRing, {
367
+ center: sceneBoundsCenter,
368
+ radius: sceneBoundsRadius,
369
+ groundPlane: groundPlane
370
+ }),
371
+ localAnnotations.length > 0 && /*#__PURE__*/ jsxs(Entity, {
372
+ name: "annotations-root",
373
+ children: [
374
+ /*#__PURE__*/ jsx(Script, {
375
+ script: TfAnnotationManager,
376
+ enabled: true,
377
+ hotspotSize: 30,
378
+ maxWorldSize: MAX_HOTSPOT_WORLD_SIZE,
379
+ opacity: 1,
380
+ hotspotColor: new Color().fromString(theme.palette.TwClrIcnBrand),
381
+ hoverColor: new Color().fromString('#ffffff'),
382
+ hotspotBackgroundColor: theme.palette.TwClrBaseWhite
383
+ }),
384
+ localAnnotations.map((annotation, index)=>/*#__PURE__*/ jsx(Annotation, {
385
+ ...annotation,
386
+ index: index,
387
+ visible: showAnnotations,
388
+ isEdit: isEdit,
389
+ isSelected: selectedAnnotationIndex === index,
390
+ isViewed: viewingAnnotationIndex === index,
391
+ onSelect: ()=>setSelectedAnnotationIndex(index),
392
+ onPositionChange: handleAnnotationPositionChange,
393
+ onView: (anno, screenX, screenY)=>handleAnnotationView(anno, index, screenX, screenY),
394
+ onScreenPositionUpdate: handleAnnotationScreenPositionUpdate
395
+ }, `annotation-${index}`))
396
+ ]
397
+ })
398
+ ]
399
+ }),
400
+ isCurrentlyInXr && sceneBoundsRadius > 0 && /*#__PURE__*/ jsx(BoundaryWall, {
401
+ center: sceneBoundsCenter,
402
+ radius: sceneBoundsRadius + WALL_INSET,
403
+ groundPlane: groundPlane,
404
+ baseY: 0
405
+ }),
406
+ /*#__PURE__*/ jsx(SplatControls, {
407
+ defaultCameraFocus: origin,
408
+ defaultCameraPosition: cameraPosition,
409
+ showAnnotations: showAnnotations,
410
+ onToggleAnnotations: setShowAnnotations,
411
+ autoRotate: autoRotate,
412
+ onToggleAutoRotate: setAutoRotate,
413
+ isEdit: isEdit,
414
+ onToggleEdit: setIsEdit,
415
+ onSave: handleSave,
416
+ onCancel: handleCancel,
417
+ onAddAnnotation: handleAddAnnotation,
418
+ onDeleteAnnotation: handleDeleteAnnotation,
419
+ onDeselectAnnotation: handleDeselectAnnotation,
420
+ hasSelectedAnnotation: selectedAnnotationIndex >= 0,
421
+ selectedAnnotation: selectedAnnotationIndex >= 0 ? localAnnotations[selectedAnnotationIndex] : null,
422
+ selectedAnnotationIndex: selectedAnnotationIndex,
423
+ onAnnotationUpdate: handleAnnotationUpdate,
424
+ onImagesChange: handleImagesChange,
425
+ maxImagesPerAnnotation: maxImagesPerAnnotation,
426
+ onTextFieldFocus: setIsTextFieldFocused,
427
+ canSave: canSave,
428
+ editable: editable,
429
+ isFullScreen: isFullScreen,
430
+ onToggleFullScreen: onToggleFullScreen,
431
+ isFreeFly: isFreeFly,
432
+ onToggleFreeFly: handleToggleFreeFly,
433
+ showFreeFly: showFreeFly,
434
+ onError: reportXrError
435
+ }),
436
+ /*#__PURE__*/ jsx(AnnotationPanel, {
437
+ annotation: viewingAnnotation,
438
+ hotspotPosition: viewedScreenPos,
439
+ onClose: handleCloseAnnotation
440
+ })
441
+ ]
278
442
  });
279
- }, [isCurrentlyInXr]);
280
- const handleCloseAnnotation = useCallback(() => {
281
- setViewingAnnotation(null);
282
- setViewingAnnotationIndex(-1);
283
- setViewedScreenPos(null);
284
- }, []);
285
- const isTeleportBlocked = useCallback(inputSource => rayHitsInteractiveUi(app, inputSource.getOrigin(), inputSource.getDirection()), [app]);
286
- useEffect(() => {
287
- if (!isCurrentlyInXr) {
288
- handleCloseAnnotation();
289
- }
290
- }, [isCurrentlyInXr, handleCloseAnnotation]);
291
- const handleAnnotationUpdate = useCallback(updates => {
292
- if (selectedAnnotationIndex === -1) {
293
- return;
294
- }
295
- setLocalAnnotations(prev => {
296
- const updated = [...prev];
297
- updated[selectedAnnotationIndex] = {
298
- ...updated[selectedAnnotationIndex],
299
- ...updates
300
- };
301
- return updated;
302
- });
303
- }, [selectedAnnotationIndex]);
304
- const handleImagesChange = useCallback(files => handleAnnotationUpdate({
305
- images: files
306
- }), [handleAnnotationUpdate]);
307
- const canSave = useMemo(() => localAnnotations.every(annotation => annotation.title && annotation.title.trim() !== ''), [localAnnotations]);
308
- const splatModel = useMemo(() => /*#__PURE__*/jsx(SplatModel, {
309
- ...splatModelProps,
310
- splatSrc: splatSrc,
311
- splatFormat: splatFormat,
312
- rotation: [-180, 0, 0],
313
- scaleFactor: scaleFactor,
314
- revealRain: isHighPerformance
315
- }, 'splat'), [isHighPerformance, splatSrc, splatFormat, scaleFactor, splatModelProps]);
316
- return /*#__PURE__*/jsxs(CameraEntityContext.Provider, {
317
- value: activeCamera,
318
- children: [/*#__PURE__*/jsx(GradientSky, {
319
- topColor: skyColor || '#FFFFFF',
320
- horizonColor: skyColor || '#EAF8FF',
321
- groundColor: groundColor || '#C3BDB7'
322
- }), /*#__PURE__*/jsxs(Entity, {
323
- name: "camera-root",
324
- ref: setCameraRoot,
325
- children: [/*#__PURE__*/jsx(Entity, {
326
- name: "camera",
327
- ref: setCameraEntity,
328
- children: camera
329
- }), !isCurrentlyInXr && /*#__PURE__*/jsx(Script, {
330
- script: WalkthroughCamera,
331
- boundsCenter: sceneBoundsCenter,
332
- boundsRadius: sceneBoundsRadius,
333
- enableFly: !isTextFieldFocused,
334
- averageCameraHeight: averageCameraHeight
335
- }), /*#__PURE__*/jsx(XrExitButton, {
336
- onClose: onXrClose
337
- }), /*#__PURE__*/jsx(Script, {
338
- script: XrControllers,
339
- enabled: !isEdit
340
- }), /*#__PURE__*/jsx(XrAnnotationInteraction, {
341
- onDismiss: handleCloseAnnotation
342
- }), /*#__PURE__*/jsx(XrPointerRay, {}), isCurrentlyInVr && viewingAnnotation && /*#__PURE__*/jsx(VrAnnotationPanel, {
343
- annotation: viewingAnnotation,
344
- annotationIndex: viewingAnnotationIndex
345
- }, viewingAnnotationIndex), /*#__PURE__*/jsx(XrGazeDwell, {
346
- activeIndex: viewingAnnotationIndex
347
- }), /*#__PURE__*/jsx(Script, {
348
- script: XrStartPose,
349
- targetX: cameraPosition[0],
350
- targetZ: cameraPosition[2],
351
- focusX: origin[0],
352
- focusZ: origin[2]
353
- }), /*#__PURE__*/jsx(Script, {
354
- script: TfXrNavigation,
355
- enabled: !isEdit,
356
- enableTeleport: !isCurrentlyInAr && !viewingAnnotation,
357
- enableSnapVertical: false,
358
- isTeleportBlocked: isTeleportBlocked
359
- }), !isCurrentlyInXr && /*#__PURE__*/jsx(Script, {
360
- script: AutoRotator,
361
- enabled: !isEdit && autoRotate && !viewingAnnotation,
362
- startDelay: 0.5,
363
- restartDelay: 3,
364
- startFadeInTime: 0.5
365
- })]
366
- }), /*#__PURE__*/jsxs(Entity, {
367
- name: "content-root",
368
- children: [splatModel, sceneBounds?.m !== undefined && groundPlane.length === 3 && /*#__PURE__*/jsx(BoundaryRing, {
369
- center: sceneBoundsCenter,
370
- radius: sceneBoundsRadius,
371
- groundPlane: groundPlane
372
- }), localAnnotations.length > 0 && /*#__PURE__*/jsxs(Entity, {
373
- name: "annotations-root",
374
- children: [/*#__PURE__*/jsx(Script, {
375
- script: TfAnnotationManager,
376
- enabled: true,
377
- hotspotSize: 30,
378
- maxWorldSize: MAX_HOTSPOT_WORLD_SIZE,
379
- opacity: 1,
380
- hotspotColor: new Color().fromString(theme.palette.TwClrIcnBrand),
381
- hoverColor: new Color().fromString('#ffffff'),
382
- hotspotBackgroundColor: theme.palette.TwClrBaseWhite
383
- }), localAnnotations.map((annotation, index) => /*#__PURE__*/jsx(Annotation, {
384
- ...annotation,
385
- index: index,
386
- visible: showAnnotations,
387
- isEdit: isEdit,
388
- isSelected: selectedAnnotationIndex === index,
389
- isViewed: viewingAnnotationIndex === index,
390
- onSelect: () => setSelectedAnnotationIndex(index),
391
- onPositionChange: handleAnnotationPositionChange,
392
- onView: (anno, screenX, screenY) => handleAnnotationView(anno, index, screenX, screenY),
393
- onScreenPositionUpdate: handleAnnotationScreenPositionUpdate
394
- }, `annotation-${index}`))]
395
- })]
396
- }), isCurrentlyInXr && sceneBoundsRadius > 0 && /*#__PURE__*/jsx(BoundaryWall, {
397
- center: sceneBoundsCenter,
398
- radius: sceneBoundsRadius + WALL_INSET,
399
- groundPlane: groundPlane,
400
- baseY: 0
401
- }), /*#__PURE__*/jsx(SplatControls, {
402
- defaultCameraFocus: origin,
403
- defaultCameraPosition: cameraPosition,
404
- showAnnotations: showAnnotations,
405
- onToggleAnnotations: setShowAnnotations,
406
- autoRotate: autoRotate,
407
- onToggleAutoRotate: setAutoRotate,
408
- isEdit: isEdit,
409
- onToggleEdit: setIsEdit,
410
- onSave: handleSave,
411
- onCancel: handleCancel,
412
- onAddAnnotation: handleAddAnnotation,
413
- onDeleteAnnotation: handleDeleteAnnotation,
414
- onDeselectAnnotation: handleDeselectAnnotation,
415
- hasSelectedAnnotation: selectedAnnotationIndex >= 0,
416
- selectedAnnotation: selectedAnnotationIndex >= 0 ? localAnnotations[selectedAnnotationIndex] : null,
417
- selectedAnnotationIndex: selectedAnnotationIndex,
418
- onAnnotationUpdate: handleAnnotationUpdate,
419
- onImagesChange: handleImagesChange,
420
- maxImagesPerAnnotation: maxImagesPerAnnotation,
421
- onTextFieldFocus: setIsTextFieldFocused,
422
- canSave: canSave,
423
- editable: editable,
424
- isFullScreen: isFullScreen,
425
- onToggleFullScreen: onToggleFullScreen,
426
- isFreeFly: isFreeFly,
427
- onToggleFreeFly: handleToggleFreeFly,
428
- showFreeFly: showFreeFly,
429
- onError: reportXrError
430
- }), /*#__PURE__*/jsx(AnnotationPanel, {
431
- annotation: viewingAnnotation,
432
- hotspotPosition: viewedScreenPos,
433
- onClose: handleCloseAnnotation
434
- })]
435
- });
436
443
  };
437
-
438
- export { VirtualWalkthroughViewer as default };
444
+ const VirtualWalkthrough_VirtualWalkthroughViewer = VirtualWalkthroughViewer;
445
+ export default VirtualWalkthrough_VirtualWalkthroughViewer;