@pascal-app/editor 1.1.0 → 1.1.2

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 (262) hide show
  1. package/package.json +9 -15
  2. package/src/components/editor/action-menu-button.tsx +1 -1
  3. package/src/components/editor/alignment-3d-guide-layer.tsx +1 -1
  4. package/src/components/editor/custom-camera-controls.tsx +11 -11
  5. package/src/components/editor/editor-layout-v2.tsx +1 -1
  6. package/src/components/editor/elevation-3d-guide-layer.tsx +1 -1
  7. package/src/components/editor/first-person-controls.tsx +20 -1981
  8. package/src/components/editor/floating-action-menu.tsx +1 -1
  9. package/src/components/editor/floating-building-action-menu.tsx +1 -1
  10. package/src/components/editor/floor-region-controls.tsx +6 -2
  11. package/src/components/editor/floorplan-navigation-presentation.test.ts +0 -40
  12. package/src/components/editor/floorplan-navigation-presentation.ts +0 -66
  13. package/src/components/editor/floorplan-panel.tsx +26 -22
  14. package/src/components/editor/floorplan-wall-typing-keys.ts +1 -1
  15. package/src/components/editor/follow-pascal.test.tsx +1 -2
  16. package/src/components/editor/follow-pascal.tsx +1 -1
  17. package/src/components/editor/footprint-height-handle.tsx +1 -1
  18. package/src/components/editor/group-actions.ts +1 -2
  19. package/src/components/editor/group-floating-action-menu.tsx +1 -1
  20. package/src/components/editor/group-move-3d.ts +1 -2
  21. package/src/components/editor/group-rotate-handle.tsx +1 -2
  22. package/src/components/editor/handles/use-handle-drag.ts +1 -2
  23. package/src/components/editor/index.tsx +24 -14
  24. package/src/components/editor/inspector-extension-actions.tsx +1 -1
  25. package/src/components/editor/node-arrow-handles.tsx +1 -1
  26. package/src/components/editor/open-wall-ends-3d-layer.tsx +1 -1
  27. package/src/components/editor/opening-guides-3d-layer.tsx +1 -1
  28. package/src/components/editor/room-controls.tsx +7 -4
  29. package/src/components/editor/room-handles-2d.tsx +2 -3
  30. package/src/components/editor/room-handles.tsx +1 -2
  31. package/src/components/editor/room-highlight.tsx +6 -105
  32. package/src/components/editor/room-labels.test.ts +8 -822
  33. package/src/components/editor/room-labels.tsx +40 -1671
  34. package/src/components/editor/room-webgpu-materials.test.ts +1 -1
  35. package/src/components/editor/selection-manager.tsx +5 -3
  36. package/src/components/editor/site-edge-labels.tsx +1 -1
  37. package/src/components/editor/snapshot-capture-overlay.tsx +2 -5
  38. package/src/components/editor/use-floorplan-background-placement.ts +2 -1
  39. package/src/components/editor/views/plugins-view.tsx +1 -1
  40. package/src/components/editor/views/view-bar.tsx +9 -9
  41. package/src/components/editor/wall-measurement-label.tsx +1 -1
  42. package/src/components/editor/wall-move-side-handles.tsx +1 -1
  43. package/src/components/editor/wall-pull-grip.tsx +2 -2
  44. package/src/components/editor-2d/floorplan-group-move.tsx +2 -3
  45. package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +1 -1
  46. package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +1 -1
  47. package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +1 -2
  48. package/src/components/editor-2d/renderers/floorplan-annotation-layout.test.ts +0 -37
  49. package/src/components/editor-2d/renderers/floorplan-annotation-layout.ts +0 -30
  50. package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +13 -3
  51. package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +1 -2
  52. package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +8 -10
  53. package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +25 -33
  54. package/src/components/systems/roof/roof-edit-system.tsx +4 -3
  55. package/src/components/tools/distribution/distribution-run-tool.tsx +1 -1
  56. package/src/components/tools/item/placement-history.test.tsx +1 -1
  57. package/src/components/tools/item/use-placement-coordinator.tsx +2 -3
  58. package/src/components/tools/paint-region/wall-paint-region-tool.tsx +6 -2
  59. package/src/components/tools/registry/move-registry-node-tool.tsx +1 -2
  60. package/src/components/tools/shared/cursor-sphere.tsx +1 -1
  61. package/src/components/tools/shared/draft-measurement-label.tsx +1 -1
  62. package/src/components/tools/shared/placement-box.tsx +1 -1
  63. package/src/components/tools/shared/placement-dimension-guides.tsx +1 -1
  64. package/src/components/tools/site/terrain-brush-cursor.tsx +1 -1
  65. package/src/components/ui/action-menu/camera-actions.tsx +2 -2
  66. package/src/components/ui/action-menu/control-modes.tsx +1 -1
  67. package/src/components/ui/action-menu/follow-pascal-pill.tsx +1 -1
  68. package/src/components/ui/action-menu/index.tsx +3 -3
  69. package/src/components/ui/action-menu/measurement-control.tsx +3 -3
  70. package/src/components/ui/action-menu/placement.ts +0 -18
  71. package/src/components/ui/action-menu/point-ask-button.tsx +1 -1
  72. package/src/components/ui/action-menu/view-toggles.tsx +5 -5
  73. package/src/components/ui/controls/finish-swatch.tsx +1 -1
  74. package/src/components/ui/controls/material-paint-panel.tsx +2 -2
  75. package/src/components/ui/controls/scene-material-list.tsx +2 -2
  76. package/src/components/ui/controls/select-control.tsx +1 -1
  77. package/src/components/ui/controls/terrain-sculpt-panel.tsx +1 -1
  78. package/src/components/ui/floating-level-selector.tsx +3 -3
  79. package/src/components/ui/helpers/contextual-helper-panel.tsx +1 -1
  80. package/src/components/ui/helpers/helper-manager.test.tsx +1 -1
  81. package/src/components/ui/helpers/helper-manager.tsx +1 -1
  82. package/src/components/ui/level-duplicate-dialog.tsx +1 -1
  83. package/src/components/ui/node-icon-image.test.tsx +46 -0
  84. package/src/components/ui/node-icon-image.tsx +33 -1
  85. package/src/components/ui/panels/collections/collections-popover.tsx +2 -2
  86. package/src/components/ui/panels/floor-foundation-panel.tsx +2 -2
  87. package/src/components/ui/panels/floor-opening-panel.tsx +4 -4
  88. package/src/components/ui/panels/node-display.ts +1 -1
  89. package/src/components/ui/panels/panel-manager.tsx +1 -1
  90. package/src/components/ui/panels/panel-wrapper.tsx +1 -1
  91. package/src/components/ui/panels/parametric-inspector.tsx +1 -1
  92. package/src/components/ui/panels/room-construction-rows.tsx +6 -6
  93. package/src/components/ui/panels/room-name-options.ts +1 -5
  94. package/src/components/ui/panels/room-panel.tsx +6 -8
  95. package/src/components/ui/primitives/color-dot.tsx +2 -2
  96. package/src/components/ui/primitives/opacity-control.tsx +2 -2
  97. package/src/components/ui/primitives/sidebar.tsx +3 -3
  98. package/src/components/ui/right-stack.tsx +1 -1
  99. package/src/components/ui/sidebar/icon-rail.tsx +1 -1
  100. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +1 -1
  101. package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +2 -2
  102. package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.tsx +1 -1
  103. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +2 -2
  104. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +1 -1
  105. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +1 -1
  106. package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +1 -1
  107. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +1 -1
  108. package/src/components/ui/sidebar/panels/site-panel/index.tsx +2 -2
  109. package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +1 -1
  110. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +1 -1
  111. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +46 -7
  112. package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +1 -1
  113. package/src/components/ui/sidebar/panels/site-panel/tree-node-drag.tsx +14 -5
  114. package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -2
  115. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +3 -3
  116. package/src/components/ui/sidebar/tab-bar.tsx +1 -1
  117. package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +1 -1
  118. package/src/components/ui/wall-type/wall-type-menu.tsx +1 -1
  119. package/src/components/viewer-overlay.tsx +1 -2
  120. package/src/hooks/use-auto-frame.ts +1 -2
  121. package/src/hooks/use-keyboard.ts +1 -2
  122. package/src/hooks/use-selected-room.ts +5 -7
  123. package/src/i18n/floor-footprint-name.ts +1 -1
  124. package/src/i18n/locales/en/messages.po +180 -182
  125. package/src/i18n/locales/es/messages.po +180 -182
  126. package/src/i18n/locales/fr/messages.po +180 -182
  127. package/src/i18n/locales/ja/messages.po +180 -182
  128. package/src/i18n/locales/zh-CN/messages.po +180 -182
  129. package/src/i18n/locales.test.ts +1 -1
  130. package/src/index.tsx +109 -131
  131. package/src/lib/below-grade.test.tsx +4 -4
  132. package/src/lib/camera-facing.test.ts +1 -1
  133. package/src/lib/camera-facing.ts +2 -3
  134. package/src/lib/editor-level-display.ts +1 -1
  135. package/src/lib/floor-footprints.test.ts +2 -2
  136. package/src/lib/floor-opening-draft.ts +1 -1
  137. package/src/lib/floorplan/annotation-visibility.test.ts +1 -1
  138. package/src/lib/floorplan/annotation-visibility.ts +1 -1
  139. package/src/lib/floorplan/floorplan-export.test.ts +1 -1
  140. package/src/lib/floorplan/floorplan-export.tsx +8 -11
  141. package/src/lib/floorplan/floorplan-extension.ts +4 -157
  142. package/src/lib/floorplan/floorplan-mode.ts +2 -1
  143. package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +1 -1
  144. package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +8 -6
  145. package/src/lib/floorplan/floorplan-plugin-install.test.tsx +3 -4
  146. package/src/lib/floorplan/geometry.ts +2 -112
  147. package/src/lib/floorplan/index.ts +0 -9
  148. package/src/lib/floorplan/items.ts +2 -1
  149. package/src/lib/floorplan/schedules.ts +6 -3
  150. package/src/lib/floorplan/sheet-export.ts +7 -3
  151. package/src/lib/floorplan/site-plan/site-parts.ts +7 -1
  152. package/src/lib/floorplan/site-plan/site-plan-layer.tsx +1 -1
  153. package/src/lib/follow-pascal-presentation.ts +1 -1
  154. package/src/lib/glb-export.ts +1 -1
  155. package/src/lib/material-paint.ts +1 -1
  156. package/src/lib/measurements.test.ts +2 -1
  157. package/src/lib/mezzanine-selection.test.ts +1 -1
  158. package/src/lib/paint-region-mode.ts +1 -1
  159. package/src/lib/point-ask/session.ts +1 -2
  160. package/src/lib/roof-duplication.test.ts +100 -0
  161. package/src/lib/roof-duplication.ts +30 -5
  162. package/src/lib/room-handle-drag.ts +2 -12
  163. package/src/lib/room-name-catalog.test.ts +2 -1
  164. package/src/lib/room-name-messages.test.ts +2 -1
  165. package/src/lib/room-name-messages.ts +1 -118
  166. package/src/lib/room-name-storage.test.ts +2 -1
  167. package/src/lib/room-selection-commands.ts +2 -2
  168. package/src/lib/room-selection.test.ts +6 -6
  169. package/src/lib/room-transform-session.ts +1 -2
  170. package/src/lib/room-zone-routing.ts +2 -2
  171. package/src/lib/selection-routing.test.ts +0 -28
  172. package/src/lib/selection-routing.ts +1 -40
  173. package/src/lib/sfx-bus.ts +8 -32
  174. package/src/lib/sfx-player.test.ts +72 -1
  175. package/src/lib/sfx-player.ts +49 -337
  176. package/src/lib/viewer-selection.test.ts +38 -10
  177. package/src/lib/wall-pull.test.ts +1 -1
  178. package/src/lib/wall-pull.ts +1 -27
  179. package/src/store/use-editor.tsx +17 -26
  180. package/src/store/use-floorplan-annotation-visibility.ts +5 -5
  181. package/src/store/use-wall-region-handles-selection.ts +1 -2
  182. package/src/components/editor/__bench__/room-label-placement.bench.ts +0 -108
  183. package/src/components/editor/first-person/build-collider-world.test.ts +0 -596
  184. package/src/components/editor/first-person/build-collider-world.ts +0 -549
  185. package/src/components/editor/first-person/ground-holes.test.ts +0 -128
  186. package/src/components/editor/first-person/ground-holes.ts +0 -130
  187. package/src/components/editor/first-person/mechanism-targets.test.ts +0 -162
  188. package/src/components/editor/first-person/mechanism-targets.ts +0 -88
  189. package/src/components/editor/first-person/terrain-collider.test.ts +0 -132
  190. package/src/components/editor/first-person/terrain-collider.ts +0 -212
  191. package/src/components/editor/floorplan-camera-sync.test.ts +0 -249
  192. package/src/components/editor/floorplan-camera-sync.ts +0 -213
  193. package/src/components/editor/localized-html.tsx +0 -22
  194. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.test.tsx +0 -236
  195. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +0 -708
  196. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.test.tsx +0 -385
  197. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +0 -670
  198. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +0 -89
  199. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +0 -106
  200. package/src/components/editor-2d/svg-paths.ts +0 -124
  201. package/src/components/ui/action-menu/action-button.tsx +0 -89
  202. package/src/components/ui/action-menu/follow-pascal-toggle.tsx +0 -42
  203. package/src/components/ui/primitives/button.tsx +0 -69
  204. package/src/components/ui/primitives/dropdown-menu.tsx +0 -232
  205. package/src/components/ui/primitives/popover.tsx +0 -42
  206. package/src/components/ui/primitives/switch.tsx +0 -29
  207. package/src/components/ui/primitives/tooltip.tsx +0 -57
  208. package/src/components/ui/scene-loader.tsx +0 -73
  209. package/src/components/viewer/floorplan-compass-button.tsx +0 -67
  210. package/src/components/viewer/floorplan-preview-geometry.test.ts +0 -107
  211. package/src/components/viewer/floorplan-preview-geometry.ts +0 -281
  212. package/src/components/viewer/floorplan-preview-navigation.test.ts +0 -43
  213. package/src/components/viewer/floorplan-preview-navigation.ts +0 -62
  214. package/src/components/viewer/floorplan-preview-visibility.test.ts +0 -35
  215. package/src/components/viewer/floorplan-preview-visibility.ts +0 -19
  216. package/src/components/viewer/floorplan-preview.tsx +0 -1065
  217. package/src/components/viewer/render-settings-menu.tsx +0 -294
  218. package/src/components/viewer/sky-control.tsx +0 -710
  219. package/src/components/viewer/use-viewer-camera-navigation-sync.ts +0 -140
  220. package/src/components/viewer/use-viewer-ui-sounds.test.ts +0 -15
  221. package/src/components/viewer/use-viewer-ui-sounds.ts +0 -46
  222. package/src/components/viewer/viewer-controls-bar.tsx +0 -496
  223. package/src/components/viewer/viewer-hover-label.tsx +0 -42
  224. package/src/components/viewer/viewer-rooms.tsx +0 -248
  225. package/src/components/viewer/viewer-scene-header.tsx +0 -286
  226. package/src/components/viewer/viewer-selection-manager.tsx +0 -124
  227. package/src/components/viewer/viewer-stage-modes.test.ts +0 -38
  228. package/src/components/viewer/viewer-stage-modes.ts +0 -49
  229. package/src/components/viewer/viewer-stage-switcher.tsx +0 -97
  230. package/src/components/viewer/viewer-stage.test.tsx +0 -47
  231. package/src/components/viewer/viewer-stage.tsx +0 -221
  232. package/src/components/walkthrough-hud.tsx +0 -193
  233. package/src/hooks/use-mobile.ts +0 -19
  234. package/src/i18n/level-name.ts +0 -39
  235. package/src/i18n/scene-theme-name.ts +0 -16
  236. package/src/lib/below-grade.ts +0 -133
  237. package/src/lib/camera-pose.test.ts +0 -237
  238. package/src/lib/camera-pose.ts +0 -172
  239. package/src/lib/floorplan/floorplan-extension.test.ts +0 -42
  240. package/src/lib/floorplan/floorplan-readonly.test.ts +0 -47
  241. package/src/lib/floorplan/floorplan-readonly.ts +0 -95
  242. package/src/lib/floorplan/marks.test.ts +0 -213
  243. package/src/lib/floorplan/marks.ts +0 -238
  244. package/src/lib/measurements.ts +0 -8
  245. package/src/lib/node-display-label.ts +0 -37
  246. package/src/lib/room-assembly-overlay.test.ts +0 -275
  247. package/src/lib/room-assembly-overlay.ts +0 -265
  248. package/src/lib/room-selection.ts +0 -417
  249. package/src/lib/scene-bounds.test.ts +0 -327
  250. package/src/lib/scene-bounds.ts +0 -233
  251. package/src/lib/typing-target.ts +0 -9
  252. package/src/lib/viewer-selection.ts +0 -595
  253. package/src/lib/zone-content.ts +0 -133
  254. package/src/store/camera-pose-store.test.ts +0 -29
  255. package/src/store/camera-pose-store.ts +0 -27
  256. package/src/store/navigation-sync-pose-store.test.ts +0 -34
  257. package/src/store/navigation-sync-pose-store.ts +0 -27
  258. package/src/store/use-audio.test.ts +0 -146
  259. package/src/store/use-audio.tsx +0 -169
  260. package/src/store/use-first-person-hud.ts +0 -40
  261. package/src/store/use-follow-pascal.test.ts +0 -62
  262. package/src/store/use-follow-pascal.ts +0 -53
@@ -1,140 +0,0 @@
1
- 'use client'
2
-
3
- import { type CameraPose, emitter } from '@pascal-app/core'
4
- import { useViewer } from '@pascal-app/viewer'
5
- import type { CameraControlsImpl } from '@react-three/drei'
6
- import { useThree } from '@react-three/fiber'
7
- import { type RefObject, useCallback, useEffect, useRef } from 'react'
8
- import type { Camera, OrthographicCamera, PerspectiveCamera } from 'three'
9
- import { Vector3 } from 'three'
10
- import { normalizeCameraPose } from '../../lib/camera-pose'
11
- import { publishCameraPose } from '../../store/camera-pose-store'
12
-
13
- const position = new Vector3()
14
- const target = new Vector3()
15
-
16
- function isPerspectiveCamera(camera: Camera): camera is PerspectiveCamera {
17
- return (camera as PerspectiveCamera).isPerspectiveCamera === true
18
- }
19
-
20
- function isOrthographicCamera(camera: Camera): camera is OrthographicCamera {
21
- return (camera as OrthographicCamera).isOrthographicCamera === true
22
- }
23
-
24
- function cameraViewWidth(camera: Camera, distance: number, width: number, height: number) {
25
- if (isPerspectiveCamera(camera)) {
26
- const fov = (camera.getEffectiveFOV() * Math.PI) / 180
27
- return Math.max(0.001, 2 * distance * Math.tan(fov / 2) * (width / Math.max(height, 1)))
28
- }
29
- if (isOrthographicCamera(camera)) {
30
- return Math.max(0.001, (camera.right - camera.left) / camera.zoom)
31
- }
32
- return Math.max(0.001, distance)
33
- }
34
-
35
- function applyViewWidth(
36
- controls: CameraControlsImpl,
37
- camera: Camera,
38
- viewWidth: number,
39
- width: number,
40
- height: number,
41
- ) {
42
- if (isPerspectiveCamera(camera)) {
43
- const fov = (camera.getEffectiveFOV() * Math.PI) / 180
44
- const denominator = 2 * Math.tan(fov / 2) * (width / Math.max(height, 1))
45
- if (denominator > 0) controls.dollyTo(Math.max(0.001, viewWidth / denominator), false)
46
- return
47
- }
48
- if (isOrthographicCamera(camera) && viewWidth > 0) {
49
- controls.zoomTo(Math.max(0.001, (camera.right - camera.left) / viewWidth), false)
50
- }
51
- }
52
-
53
- export function useViewerCameraNavigationSync(controls: RefObject<CameraControlsImpl | null>) {
54
- const camera = useThree((state) => state.camera)
55
- const size = useThree((state) => state.size)
56
- const suppressPublish = useRef(false)
57
- const pendingPose = useRef<CameraPose | null>(null)
58
-
59
- const publishCurrentPose = useCallback(() => {
60
- const control = controls.current
61
- if (!control || suppressPublish.current) return
62
- control.getPosition(position, false)
63
- control.getTarget(target, false)
64
- const projection = isPerspectiveCamera(camera)
65
- ? 'perspective'
66
- : isOrthographicCamera(camera)
67
- ? 'orthographic'
68
- : null
69
- if (!projection) return
70
- const pose = normalizeCameraPose({
71
- position: [position.x, position.y, position.z],
72
- target: [target.x, target.y, target.z],
73
- projection,
74
- viewWidth: cameraViewWidth(camera, position.distanceTo(target), size.width, size.height),
75
- ...(isPerspectiveCamera(camera) ? { fov: camera.fov } : {}),
76
- })
77
- if (pose) publishCameraPose(pose)
78
- }, [camera, controls, size.height, size.width])
79
-
80
- const applyPendingPose = useCallback(() => {
81
- const control = controls.current
82
- const pose = pendingPose.current
83
- if (!(control && pose)) return
84
- const projectionMatches =
85
- (pose.projection === 'perspective' && isPerspectiveCamera(camera)) ||
86
- (pose.projection === 'orthographic' && isOrthographicCamera(camera))
87
- if (!projectionMatches) return
88
-
89
- pendingPose.current = null
90
- suppressPublish.current = true
91
- try {
92
- if (pose.fov !== undefined && isPerspectiveCamera(camera)) {
93
- camera.fov = pose.fov
94
- camera.updateProjectionMatrix()
95
- }
96
- control.setLookAt(
97
- pose.position[0],
98
- pose.position[1],
99
- pose.position[2],
100
- pose.target[0],
101
- pose.target[1],
102
- pose.target[2],
103
- false,
104
- )
105
- if (pose.viewWidth !== undefined) {
106
- applyViewWidth(control, camera, pose.viewWidth, size.width, size.height)
107
- }
108
- control.update(0)
109
- } finally {
110
- suppressPublish.current = false
111
- publishCurrentPose()
112
- }
113
- }, [camera, controls, publishCurrentPose, size.height, size.width])
114
-
115
- useEffect(() => {
116
- applyPendingPose()
117
- }, [applyPendingPose])
118
-
119
- useEffect(() => {
120
- const applyPose = (value: CameraPose) => {
121
- const pose = normalizeCameraPose(value)
122
- if (!pose) return
123
- pendingPose.current = pose
124
- if (useViewer.getState().cameraMode !== pose.projection) {
125
- useViewer.getState().setCameraMode(pose.projection)
126
- return
127
- }
128
- applyPendingPose()
129
- }
130
- emitter.on('camera-controls:apply-pose', applyPose)
131
- return () => emitter.off('camera-controls:apply-pose', applyPose)
132
- }, [applyPendingPose])
133
-
134
- useEffect(() => {
135
- const frame = requestAnimationFrame(publishCurrentPose)
136
- return () => cancelAnimationFrame(frame)
137
- }, [publishCurrentPose])
138
-
139
- return publishCurrentPose
140
- }
@@ -1,15 +0,0 @@
1
- import { expect, test } from 'bun:test'
2
- import { selectionCue } from './use-viewer-ui-sounds'
3
-
4
- type Selection = Parameters<typeof selectionCue>[0]
5
- const selection = (over: Partial<Record<keyof Selection, unknown>> = {}) =>
6
- ({ buildingId: null, levelId: 'level_a', zoneId: null, selectedIds: [], ...over }) as Selection
7
-
8
- test('picking a room or an element selects; letting it go deselects', () => {
9
- expect(selectionCue(selection(), selection({ zoneId: 'zone_a' }))).toBe('viewerSelect')
10
- expect(
11
- selectionCue(selection({ zoneId: 'zone_a' }), selection({ selectedIds: ['door_a'] })),
12
- ).toBe('viewerSelect')
13
- expect(selectionCue(selection({ selectedIds: ['door_a'] }), selection())).toBe('viewerDeselect')
14
- expect(selectionCue(selection(), selection())).toBe(null)
15
- })
@@ -1,46 +0,0 @@
1
- 'use client'
2
-
3
- import { useViewer } from '@pascal-app/viewer'
4
- import { useEffect } from 'react'
5
- import { playSFX } from '../../lib/sfx-player'
6
-
7
- type Selection = ReturnType<typeof useViewer.getState>['selection']
8
-
9
- /** Which tick a selection change plays: anything newly picked selects, anything let go deselects. */
10
- export function selectionCue(
11
- previous: Selection,
12
- next: Selection,
13
- ): 'viewerSelect' | 'viewerDeselect' | null {
14
- const picked =
15
- (next.levelId && next.levelId !== previous.levelId) ||
16
- (next.zoneId && next.zoneId !== previous.zoneId) ||
17
- next.selectedIds.some((id) => !previous.selectedIds.includes(id))
18
- if (picked) return 'viewerSelect'
19
- const released =
20
- (previous.levelId && !next.levelId) ||
21
- (previous.zoneId && !next.zoneId) ||
22
- previous.selectedIds.some((id) => !next.selectedIds.includes(id))
23
- return released ? 'viewerDeselect' : null
24
- }
25
-
26
- /**
27
- * The viewer's pointer ticks, as on the marketing house: a faint one when the
28
- * pointer finds something new, one on select and a softer one on deselect.
29
- * Silent in walkthrough, and until the person has interacted with the page, so
30
- * loading a scene with a default selection makes no sound.
31
- */
32
- export function useViewerUiSounds() {
33
- useEffect(
34
- () =>
35
- useViewer.subscribe((state, previous) => {
36
- if (state.walkthroughMode || !navigator.userActivation?.hasBeenActive) return
37
- if (state.selection !== previous.selection) {
38
- const cue = selectionCue(previous.selection, state.selection)
39
- if (cue) playSFX(cue)
40
- }
41
- if (state.hoveredId && state.hoveredId !== previous.hoveredId && !state.cameraDragging)
42
- playSFX('viewerHover')
43
- }),
44
- [],
45
- )
46
- }