@pascal-app/editor 1.1.0 → 1.1.1

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 (260) 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/panels/collections/collections-popover.tsx +2 -2
  84. package/src/components/ui/panels/floor-foundation-panel.tsx +2 -2
  85. package/src/components/ui/panels/floor-opening-panel.tsx +4 -4
  86. package/src/components/ui/panels/node-display.ts +1 -1
  87. package/src/components/ui/panels/panel-manager.tsx +1 -1
  88. package/src/components/ui/panels/panel-wrapper.tsx +1 -1
  89. package/src/components/ui/panels/parametric-inspector.tsx +1 -1
  90. package/src/components/ui/panels/room-construction-rows.tsx +6 -6
  91. package/src/components/ui/panels/room-name-options.ts +1 -5
  92. package/src/components/ui/panels/room-panel.tsx +6 -8
  93. package/src/components/ui/primitives/color-dot.tsx +2 -2
  94. package/src/components/ui/primitives/opacity-control.tsx +2 -2
  95. package/src/components/ui/primitives/sidebar.tsx +3 -3
  96. package/src/components/ui/right-stack.tsx +1 -1
  97. package/src/components/ui/sidebar/icon-rail.tsx +1 -1
  98. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +1 -1
  99. package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +2 -2
  100. package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.tsx +1 -1
  101. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +2 -2
  102. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +1 -1
  103. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +1 -1
  104. package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +1 -1
  105. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +1 -1
  106. package/src/components/ui/sidebar/panels/site-panel/index.tsx +2 -2
  107. package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +1 -1
  108. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +1 -1
  109. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +46 -7
  110. package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +1 -1
  111. package/src/components/ui/sidebar/panels/site-panel/tree-node-drag.tsx +14 -5
  112. package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -2
  113. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +3 -3
  114. package/src/components/ui/sidebar/tab-bar.tsx +1 -1
  115. package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +1 -1
  116. package/src/components/ui/wall-type/wall-type-menu.tsx +1 -1
  117. package/src/components/viewer-overlay.tsx +1 -2
  118. package/src/hooks/use-auto-frame.ts +1 -2
  119. package/src/hooks/use-keyboard.ts +1 -2
  120. package/src/hooks/use-selected-room.ts +5 -7
  121. package/src/i18n/floor-footprint-name.ts +1 -1
  122. package/src/i18n/locales/en/messages.po +180 -182
  123. package/src/i18n/locales/es/messages.po +180 -182
  124. package/src/i18n/locales/fr/messages.po +180 -182
  125. package/src/i18n/locales/ja/messages.po +180 -182
  126. package/src/i18n/locales/zh-CN/messages.po +180 -182
  127. package/src/i18n/locales.test.ts +1 -1
  128. package/src/index.tsx +109 -131
  129. package/src/lib/below-grade.test.tsx +4 -4
  130. package/src/lib/camera-facing.test.ts +1 -1
  131. package/src/lib/camera-facing.ts +2 -3
  132. package/src/lib/editor-level-display.ts +1 -1
  133. package/src/lib/floor-footprints.test.ts +2 -2
  134. package/src/lib/floor-opening-draft.ts +1 -1
  135. package/src/lib/floorplan/annotation-visibility.test.ts +1 -1
  136. package/src/lib/floorplan/annotation-visibility.ts +1 -1
  137. package/src/lib/floorplan/floorplan-export.test.ts +1 -1
  138. package/src/lib/floorplan/floorplan-export.tsx +8 -11
  139. package/src/lib/floorplan/floorplan-extension.ts +4 -157
  140. package/src/lib/floorplan/floorplan-mode.ts +2 -1
  141. package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +1 -1
  142. package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +8 -6
  143. package/src/lib/floorplan/floorplan-plugin-install.test.tsx +3 -4
  144. package/src/lib/floorplan/geometry.ts +2 -112
  145. package/src/lib/floorplan/index.ts +0 -9
  146. package/src/lib/floorplan/items.ts +2 -1
  147. package/src/lib/floorplan/schedules.ts +6 -3
  148. package/src/lib/floorplan/sheet-export.ts +7 -3
  149. package/src/lib/floorplan/site-plan/site-parts.ts +7 -1
  150. package/src/lib/floorplan/site-plan/site-plan-layer.tsx +1 -1
  151. package/src/lib/follow-pascal-presentation.ts +1 -1
  152. package/src/lib/glb-export.ts +1 -1
  153. package/src/lib/material-paint.ts +1 -1
  154. package/src/lib/measurements.test.ts +2 -1
  155. package/src/lib/mezzanine-selection.test.ts +1 -1
  156. package/src/lib/paint-region-mode.ts +1 -1
  157. package/src/lib/point-ask/session.ts +1 -2
  158. package/src/lib/roof-duplication.test.ts +100 -0
  159. package/src/lib/roof-duplication.ts +30 -5
  160. package/src/lib/room-handle-drag.ts +2 -12
  161. package/src/lib/room-name-catalog.test.ts +2 -1
  162. package/src/lib/room-name-messages.test.ts +2 -1
  163. package/src/lib/room-name-messages.ts +1 -118
  164. package/src/lib/room-name-storage.test.ts +2 -1
  165. package/src/lib/room-selection-commands.ts +2 -2
  166. package/src/lib/room-selection.test.ts +6 -6
  167. package/src/lib/room-transform-session.ts +1 -2
  168. package/src/lib/room-zone-routing.ts +2 -2
  169. package/src/lib/selection-routing.test.ts +0 -28
  170. package/src/lib/selection-routing.ts +1 -40
  171. package/src/lib/sfx-bus.ts +8 -32
  172. package/src/lib/sfx-player.test.ts +72 -1
  173. package/src/lib/sfx-player.ts +49 -337
  174. package/src/lib/viewer-selection.test.ts +38 -10
  175. package/src/lib/wall-pull.test.ts +1 -1
  176. package/src/lib/wall-pull.ts +1 -27
  177. package/src/store/use-editor.tsx +17 -26
  178. package/src/store/use-floorplan-annotation-visibility.ts +5 -5
  179. package/src/store/use-wall-region-handles-selection.ts +1 -2
  180. package/src/components/editor/__bench__/room-label-placement.bench.ts +0 -108
  181. package/src/components/editor/first-person/build-collider-world.test.ts +0 -596
  182. package/src/components/editor/first-person/build-collider-world.ts +0 -549
  183. package/src/components/editor/first-person/ground-holes.test.ts +0 -128
  184. package/src/components/editor/first-person/ground-holes.ts +0 -130
  185. package/src/components/editor/first-person/mechanism-targets.test.ts +0 -162
  186. package/src/components/editor/first-person/mechanism-targets.ts +0 -88
  187. package/src/components/editor/first-person/terrain-collider.test.ts +0 -132
  188. package/src/components/editor/first-person/terrain-collider.ts +0 -212
  189. package/src/components/editor/floorplan-camera-sync.test.ts +0 -249
  190. package/src/components/editor/floorplan-camera-sync.ts +0 -213
  191. package/src/components/editor/localized-html.tsx +0 -22
  192. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.test.tsx +0 -236
  193. package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +0 -708
  194. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.test.tsx +0 -385
  195. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +0 -670
  196. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +0 -89
  197. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +0 -106
  198. package/src/components/editor-2d/svg-paths.ts +0 -124
  199. package/src/components/ui/action-menu/action-button.tsx +0 -89
  200. package/src/components/ui/action-menu/follow-pascal-toggle.tsx +0 -42
  201. package/src/components/ui/primitives/button.tsx +0 -69
  202. package/src/components/ui/primitives/dropdown-menu.tsx +0 -232
  203. package/src/components/ui/primitives/popover.tsx +0 -42
  204. package/src/components/ui/primitives/switch.tsx +0 -29
  205. package/src/components/ui/primitives/tooltip.tsx +0 -57
  206. package/src/components/ui/scene-loader.tsx +0 -73
  207. package/src/components/viewer/floorplan-compass-button.tsx +0 -67
  208. package/src/components/viewer/floorplan-preview-geometry.test.ts +0 -107
  209. package/src/components/viewer/floorplan-preview-geometry.ts +0 -281
  210. package/src/components/viewer/floorplan-preview-navigation.test.ts +0 -43
  211. package/src/components/viewer/floorplan-preview-navigation.ts +0 -62
  212. package/src/components/viewer/floorplan-preview-visibility.test.ts +0 -35
  213. package/src/components/viewer/floorplan-preview-visibility.ts +0 -19
  214. package/src/components/viewer/floorplan-preview.tsx +0 -1065
  215. package/src/components/viewer/render-settings-menu.tsx +0 -294
  216. package/src/components/viewer/sky-control.tsx +0 -710
  217. package/src/components/viewer/use-viewer-camera-navigation-sync.ts +0 -140
  218. package/src/components/viewer/use-viewer-ui-sounds.test.ts +0 -15
  219. package/src/components/viewer/use-viewer-ui-sounds.ts +0 -46
  220. package/src/components/viewer/viewer-controls-bar.tsx +0 -496
  221. package/src/components/viewer/viewer-hover-label.tsx +0 -42
  222. package/src/components/viewer/viewer-rooms.tsx +0 -248
  223. package/src/components/viewer/viewer-scene-header.tsx +0 -286
  224. package/src/components/viewer/viewer-selection-manager.tsx +0 -124
  225. package/src/components/viewer/viewer-stage-modes.test.ts +0 -38
  226. package/src/components/viewer/viewer-stage-modes.ts +0 -49
  227. package/src/components/viewer/viewer-stage-switcher.tsx +0 -97
  228. package/src/components/viewer/viewer-stage.test.tsx +0 -47
  229. package/src/components/viewer/viewer-stage.tsx +0 -221
  230. package/src/components/walkthrough-hud.tsx +0 -193
  231. package/src/hooks/use-mobile.ts +0 -19
  232. package/src/i18n/level-name.ts +0 -39
  233. package/src/i18n/scene-theme-name.ts +0 -16
  234. package/src/lib/below-grade.ts +0 -133
  235. package/src/lib/camera-pose.test.ts +0 -237
  236. package/src/lib/camera-pose.ts +0 -172
  237. package/src/lib/floorplan/floorplan-extension.test.ts +0 -42
  238. package/src/lib/floorplan/floorplan-readonly.test.ts +0 -47
  239. package/src/lib/floorplan/floorplan-readonly.ts +0 -95
  240. package/src/lib/floorplan/marks.test.ts +0 -213
  241. package/src/lib/floorplan/marks.ts +0 -238
  242. package/src/lib/measurements.ts +0 -8
  243. package/src/lib/node-display-label.ts +0 -37
  244. package/src/lib/room-assembly-overlay.test.ts +0 -275
  245. package/src/lib/room-assembly-overlay.ts +0 -265
  246. package/src/lib/room-selection.ts +0 -417
  247. package/src/lib/scene-bounds.test.ts +0 -327
  248. package/src/lib/scene-bounds.ts +0 -233
  249. package/src/lib/typing-target.ts +0 -9
  250. package/src/lib/viewer-selection.ts +0 -595
  251. package/src/lib/zone-content.ts +0 -133
  252. package/src/store/camera-pose-store.test.ts +0 -29
  253. package/src/store/camera-pose-store.ts +0 -27
  254. package/src/store/navigation-sync-pose-store.test.ts +0 -34
  255. package/src/store/navigation-sync-pose-store.ts +0 -27
  256. package/src/store/use-audio.test.ts +0 -146
  257. package/src/store/use-audio.tsx +0 -169
  258. package/src/store/use-first-person-hud.ts +0 -40
  259. package/src/store/use-follow-pascal.test.ts +0 -62
  260. package/src/store/use-follow-pascal.ts +0 -53
@@ -19,13 +19,13 @@
19
19
 
20
20
  import {
21
21
  type AnyNodeId,
22
- getWallCurveFrameAt,
23
22
  getWallThickness,
24
23
  useScene,
25
24
  WALL_CONSTRUCTION_FIELDS,
26
25
  type WallNode,
27
26
  type WallPlanPoint,
28
27
  wallFollowsStorey,
28
+ wallPullSeed,
29
29
  } from '@pascal-app/core'
30
30
  import { useViewer } from '@pascal-app/viewer'
31
31
  import { create } from 'zustand'
@@ -34,15 +34,6 @@ import type { ContinuationMode } from './continuation'
34
34
  import { getWallDrawVariant, selectWallDrawVariant } from './wall-draw-variant'
35
35
  import { publishWallRunFeedback } from './wall-run-snap'
36
36
 
37
- /** The floor plan's affordance id for a wall end's pull grip (a `move-arrow`, variant `pull`). */
38
- export const WALL_PULL_AFFORDANCE = 'wall-pull'
39
-
40
- /** What a pull grip carries: the wall, and which of its ends it pulls from. */
41
- export type WallPullGripPayload = { wallId: string; endpoint: 'start' | 'end' }
42
-
43
- /** The grip's tooltip, in both views. */
44
- export const WALL_PULL_GRIP_TITLE = 'Drag to draw the next wall'
45
-
46
37
  export type WallPullRun = {
47
38
  /** Bumped per pull, so each view seeds its draft from it once. */
48
39
  seq: number
@@ -93,23 +84,6 @@ export function wallPullTypePatch(wall: WallNode, storeyHeight: number | null):
93
84
  return patch as Partial<WallNode>
94
85
  }
95
86
 
96
- /**
97
- * The pulled end of `wall` and the direction out of it: along the wall for a
98
- * straight one, along its tangent for a curved one.
99
- */
100
- export function wallPullSeed(
101
- wall: Pick<WallNode, 'start' | 'end' | 'curveOffset'>,
102
- endpoint: 'start' | 'end',
103
- ): { start: WallPlanPoint; reference: WallPlanPoint } | null {
104
- const start: WallPlanPoint =
105
- endpoint === 'start' ? [wall.start[0], wall.start[1]] : [wall.end[0], wall.end[1]]
106
- const tangent = getWallCurveFrameAt(wall as WallNode, endpoint === 'start' ? 0 : 1).tangent
107
- const sign = endpoint === 'start' ? -1 : 1
108
- const length = Math.hypot(tangent.x, tangent.y)
109
- if (!(length > 1e-9)) return null
110
- return { start, reference: [(tangent.x / length) * sign, (tangent.y / length) * sign] }
111
- }
112
-
113
87
  // What the pull changed for its run, put back when it ends.
114
88
  let restore: { shape: ContinuationMode; toolDefaults: Record<string, unknown> | null } | null = null
115
89
  let stopWatching: (() => void) | null = null
@@ -21,6 +21,15 @@ import {
21
21
  type WallSurfaceSide,
22
22
  } from '@pascal-app/core'
23
23
  import { useViewer } from '@pascal-app/viewer'
24
+ import {
25
+ cameraPoseStore,
26
+ type NavigationSyncPose,
27
+ type NavigationSyncPoseInput,
28
+ publishNavigationSyncPose,
29
+ type RoomKey,
30
+ sameRoom,
31
+ subscribeNavigationSyncPose,
32
+ } from '@pascal-app/viewer/ui'
24
33
  import { create } from 'zustand'
25
34
  import { persist } from 'zustand/middleware'
26
35
  import {
@@ -56,7 +65,6 @@ import {
56
65
  type PaintHoverInfo,
57
66
  type PaintScope,
58
67
  } from '../lib/paint-scope'
59
- import { type RoomKey, sameRoom } from '../lib/room-selection'
60
68
  import {
61
69
  cycleSnappingModeIn,
62
70
  defaultSnappingModeFor,
@@ -66,8 +74,6 @@ import {
66
74
  snapContextOf,
67
75
  snappingModesFor,
68
76
  } from '../lib/snapping-mode'
69
- import { cameraPoseStore } from './camera-pose-store'
70
- import { publishNavigationSyncPoseToStore } from './navigation-sync-pose-store'
71
77
  import useInteractionScope from './use-interaction-scope'
72
78
  import {
73
79
  clampViewPaneRatio,
@@ -233,18 +239,6 @@ export type CatalogCategory =
233
239
  export type FloorplanSelectionTool = 'click' | 'marquee'
234
240
  export type GridSnapStep = 0.5 | 0.25 | 0.1 | 0.05
235
241
 
236
- export type NavigationSyncSource = '2d' | '3d'
237
-
238
- export type NavigationSyncPose = {
239
- source: NavigationSyncSource
240
- revision: number
241
- target: [number, number, number]
242
- azimuth: number
243
- viewWidth: number
244
- }
245
-
246
- export type NavigationSyncPoseInput = Omit<NavigationSyncPose, 'revision'>
247
-
248
242
  // Combined tool type. Known literals keep autocomplete; the `(string & {})`
249
243
  // arm lets plugin-contributed tool ids (e.g. `'trees:tree'`) typecheck without
250
244
  // the host enumerating every plugin kind. The runtime dispatch is already
@@ -490,12 +484,13 @@ type EditorState = {
490
484
  setViewPinned: (viewId: string, pinned: boolean) => void
491
485
  isFloorplanHovered: boolean
492
486
  setFloorplanHovered: (hovered: boolean) => void
487
+ /** Mirror of viewer/ui's navigation sync store, kept for plugins that read it here. */
488
+ navigationSyncPose: NavigationSyncPose | null
489
+ publishNavigationSyncPose: (pose: NavigationSyncPoseInput) => void
493
490
  // Toggleable DWV riser-diagram (plumbing isometric) overlay.
494
491
  isRiserOpen: boolean
495
492
  setRiserOpen: (open: boolean) => void
496
493
  toggleRiserOpen: () => void
497
- navigationSyncPose: NavigationSyncPose | null
498
- publishNavigationSyncPose: (pose: NavigationSyncPoseInput) => void
499
494
  floorplanSelectionTool: FloorplanSelectionTool
500
495
  setFloorplanSelectionTool: (tool: FloorplanSelectionTool) => void
501
496
  gridSnapStep: GridSnapStep
@@ -1538,18 +1533,11 @@ const useEditor = create<EditorState>()(
1538
1533
  set((state) => ({ pinnedViews: { ...state.pinnedViews, [viewId]: pinned } })),
1539
1534
  isFloorplanHovered: false,
1540
1535
  setFloorplanHovered: (hovered) => set({ isFloorplanHovered: hovered }),
1536
+ navigationSyncPose: null,
1537
+ publishNavigationSyncPose,
1541
1538
  isRiserOpen: false,
1542
1539
  setRiserOpen: (open) => set({ isRiserOpen: open }),
1543
1540
  toggleRiserOpen: () => set((state) => ({ isRiserOpen: !state.isRiserOpen })),
1544
- navigationSyncPose: null,
1545
- publishNavigationSyncPose: (pose) => {
1546
- const navigationSyncPose = {
1547
- ...pose,
1548
- revision: (get().navigationSyncPose?.revision ?? 0) + 1,
1549
- }
1550
- publishNavigationSyncPoseToStore(navigationSyncPose)
1551
- set({ navigationSyncPose })
1552
- },
1553
1541
  floorplanSelectionTool: 'click' as FloorplanSelectionTool,
1554
1542
  setFloorplanSelectionTool: (tool) => set({ floorplanSelectionTool: tool }),
1555
1543
  gridSnapStep: DEFAULT_PERSISTED_EDITOR_LAYOUT_STATE.gridSnapStep,
@@ -1863,4 +1851,7 @@ usePaintRegionMode.subscribe((state) => {
1863
1851
  if (useEditor.getState().paintEraser !== paintEraser) useEditor.setState({ paintEraser })
1864
1852
  })
1865
1853
 
1854
+ // Published plugins read the 2D/3D navigation pose from the editor store; the shared store owns it.
1855
+ subscribeNavigationSyncPose((navigationSyncPose) => useEditor.setState({ navigationSyncPose }))
1856
+
1866
1857
  export default useEditor
@@ -1,5 +1,10 @@
1
1
  'use client'
2
2
 
3
+ import {
4
+ DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES,
5
+ type FloorplanWallDimensionFaces,
6
+ normalizeFloorplanWallDimensionFaces,
7
+ } from '@pascal-app/core'
3
8
  import { create } from 'zustand'
4
9
  import { persist } from 'zustand/middleware'
5
10
  import {
@@ -8,11 +13,6 @@ import {
8
13
  type FloorplanAnnotationVisibility,
9
14
  normalizeFloorplanAnnotationVisibility,
10
15
  } from '../lib/floorplan/annotation-visibility'
11
- import {
12
- DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES,
13
- type FloorplanWallDimensionFaces,
14
- normalizeFloorplanWallDimensionFaces,
15
- } from '../lib/floorplan/floorplan-extension'
16
16
 
17
17
  type PersistedFloorplanAnnotationState = {
18
18
  visibility: FloorplanAnnotationVisibility
@@ -1,10 +1,9 @@
1
1
  import { type AnyNodeId, useScene } from '@pascal-app/core'
2
- import { useViewer } from '@pascal-app/viewer'
2
+ import { isTypingTarget, useViewer } from '@pascal-app/viewer'
3
3
  import { create } from 'zustand'
4
4
  import { hasLiveGestures } from '../lib/gesture-lifecycle'
5
5
  import { removeWallRegion } from '../lib/paint-regions'
6
6
  import { sfxEmitter } from '../lib/sfx-bus'
7
- import { isTypingTarget } from '../lib/typing-target'
8
7
  import useDeleteConfirmation from './use-delete-confirmation'
9
8
  import useInteractionScope from './use-interaction-scope'
10
9
 
@@ -1,108 +0,0 @@
1
- import type { Polygon } from '@pascal-app/core'
2
- import {
3
- type PillCandidate,
4
- placePills,
5
- type RoomHit,
6
- type RoomLabelEntry,
7
- roomAt,
8
- } from '../room-labels'
9
-
10
- // One room-label placement pass and one pointer pick, for a 900 × 600 px house of 31, 60 and 120
11
- // rooms (every third an L), printed as JSON medians in ms. Run with `bun run <this file>`.
12
- let seed = 11
13
- const random = () => {
14
- seed = (seed * 1_103_515_245 + 12_345) % 2 ** 31
15
- return seed / 2 ** 31
16
- }
17
-
18
- function house(count: number) {
19
- const columns = Math.ceil(Math.sqrt(count * 1.5))
20
- const rows = Math.ceil(count / columns)
21
- const width = 900 / columns
22
- const depth = 600 / rows
23
- return Array.from({ length: count }, (_, i) => {
24
- const left = 270 + (i % columns) * width
25
- const top = 150 + Math.floor(i / columns) * depth
26
- const right = left + width
27
- const bottom = top + depth
28
- const outer: [number, number][] =
29
- i % 3 === 0
30
- ? [
31
- [left, top],
32
- [right, top],
33
- [right, top + depth / 2],
34
- [left + width / 2, top + depth / 2],
35
- [left + width / 2, bottom],
36
- [left, bottom],
37
- ]
38
- : [
39
- [left, top],
40
- [right, top],
41
- [right, bottom],
42
- [left, bottom],
43
- ]
44
- const outline: Polygon = { outer, holes: [] }
45
- const pill = 60 + random() * 110
46
- const candidate: PillCandidate = {
47
- id: `room_${i}`,
48
- x: left + width / 4,
49
- y: top + depth / 4,
50
- size: [pill, 24, pill * 0.6],
51
- area: width * depth * (i % 3 === 0 ? 0.75 : 1),
52
- outline,
53
- }
54
- const entry: RoomLabelEntry = {
55
- zoneId: candidate.id,
56
- polygon: outer,
57
- holes: [],
58
- area: candidate.area,
59
- }
60
- return { candidate, entry }
61
- })
62
- }
63
-
64
- const median = (samples: number[]) => samples.sort((a, b) => a - b)[samples.length >> 1]!
65
-
66
- const pane = { width: 1440, height: 900 }
67
- const results: Record<string, unknown> = {}
68
- for (const count of [31, 60, 120]) {
69
- const rooms = house(count)
70
- const candidates = rooms.map((room) => room.candidate)
71
- const entries = rooms.map((room) => room.entry)
72
- for (let i = 0; i < 20; i++) placePills(candidates, pane)
73
- const cold: number[] = []
74
- const warm: number[] = []
75
- let previous = placePills(candidates, pane)
76
- for (let i = 0; i < 100; i++) {
77
- let started = performance.now()
78
- placePills(candidates, pane)
79
- cold.push(performance.now() - started)
80
- started = performance.now()
81
- previous = placePills(candidates, pane, previous)
82
- warm.push(performance.now() - started)
83
- }
84
- const points = Array.from(
85
- { length: 1000 },
86
- (): RoomHit => [270 + random() * 900, 150 + random() * 600, 0],
87
- )
88
- for (const point of points) roomAt(entries, () => point)
89
- const picks: number[] = []
90
- for (let i = 0; i < 20; i++) {
91
- const started = performance.now()
92
- for (const point of points) roomAt(entries, () => point)
93
- picks.push((performance.now() - started) / points.length)
94
- }
95
- const tiers = Object.fromEntries(
96
- ['full', 'name', 'dot', 'hidden'].map((tier) => [
97
- tier,
98
- [...previous.values()].filter((placement) => placement.tier === tier).length,
99
- ]),
100
- )
101
- results[count] = {
102
- placeMs: median(cold),
103
- placeWithPreviousMs: median(warm),
104
- pickMs: median(picks),
105
- tiers,
106
- }
107
- }
108
- console.log(JSON.stringify(results, null, 2))