@pascal-app/editor 0.8.0 → 0.9.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 (350) hide show
  1. package/package.json +15 -13
  2. package/src/components/editor/alignment-3d-guide-layer.tsx +168 -0
  3. package/src/components/editor/bake-exporter.tsx +47 -0
  4. package/src/components/editor/custom-camera-controls.tsx +795 -28
  5. package/src/components/editor/editor-layout-mobile.tsx +8 -3
  6. package/src/components/editor/editor-layout-v2.tsx +76 -51
  7. package/src/components/editor/export-manager.tsx +69 -32
  8. package/src/components/editor/fence-tangent-lines-3d.tsx +87 -0
  9. package/src/components/editor/first-person/build-collider-world.test.ts +182 -0
  10. package/src/components/editor/first-person/build-collider-world.ts +228 -83
  11. package/src/components/editor/first-person-controls.tsx +943 -27
  12. package/src/components/editor/floating-action-menu.tsx +676 -208
  13. package/src/components/editor/floating-building-action-menu.tsx +2 -2
  14. package/src/components/editor/floorplan-background-selection.test.ts +58 -0
  15. package/src/components/editor/floorplan-background-selection.ts +3 -2
  16. package/src/components/editor/floorplan-panel.tsx +6916 -12137
  17. package/src/components/editor/grid.tsx +197 -36
  18. package/src/components/editor/group-actions.ts +457 -0
  19. package/src/components/editor/group-floating-action-menu.tsx +130 -0
  20. package/src/components/editor/group-move-3d.ts +397 -0
  21. package/src/components/editor/group-rotate-handle.tsx +420 -0
  22. package/src/components/editor/group-selection-box-3d.tsx +173 -0
  23. package/src/components/editor/group-transform-shared.test.ts +396 -0
  24. package/src/components/editor/group-transform-shared.ts +489 -0
  25. package/src/components/editor/handles/handle-arrow.tsx +581 -0
  26. package/src/components/editor/handles/use-handle-drag.ts +246 -0
  27. package/src/components/editor/index.tsx +412 -162
  28. package/src/components/editor/measurement-pill.tsx +115 -0
  29. package/src/components/editor/node-action-menu.tsx +14 -1
  30. package/src/components/editor/node-arrow-handles.tsx +1646 -0
  31. package/src/components/editor/opening-guides-3d-layer.tsx +144 -0
  32. package/src/components/editor/quick-measurement-card.tsx +70 -0
  33. package/src/components/editor/quick-measurement-hud.tsx +28 -0
  34. package/src/components/editor/riser-diagram-panel.tsx +137 -0
  35. package/src/components/editor/selection-manager.tsx +1106 -483
  36. package/src/components/editor/site-edge-labels.tsx +45 -21
  37. package/src/components/editor/slab-hole-highlights.tsx +474 -0
  38. package/src/components/editor/snapshot-capture-overlay.tsx +369 -155
  39. package/src/components/editor/three-context-bridge.ts +22 -0
  40. package/src/components/editor/thumbnail-generator.tsx +140 -41
  41. package/src/components/editor/use-floorplan-background-placement.ts +190 -35
  42. package/src/components/editor/use-floorplan-hit-testing.ts +24 -0
  43. package/src/components/editor/use-floorplan-scene-data.ts +19 -7
  44. package/src/components/editor/use-mesh-settle-epoch.ts +26 -0
  45. package/src/components/editor/wall-measurement-label.tsx +14 -19
  46. package/src/components/editor/wall-move-side-handles.tsx +870 -0
  47. package/src/components/editor/wall-opening-highlights.tsx +181 -0
  48. package/src/components/editor/wall-snap-beacon-layer.tsx +304 -0
  49. package/src/components/editor-2d/floorplan-action-menu-layer.tsx +15 -6
  50. package/src/components/editor-2d/floorplan-alignment-guide-layer.tsx +142 -0
  51. package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +5 -3
  52. package/src/components/editor-2d/floorplan-group-action-menu.tsx +87 -0
  53. package/src/components/editor-2d/floorplan-group-move.tsx +701 -0
  54. package/src/components/editor-2d/floorplan-measurement-tool-layer.test.ts +113 -0
  55. package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +1656 -0
  56. package/src/components/editor-2d/floorplan-quick-measure-layer.tsx +212 -0
  57. package/src/components/editor-2d/floorplan-registry-action-menu.tsx +392 -0
  58. package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +857 -0
  59. package/src/components/editor-2d/floorplan-render-context.tsx +62 -0
  60. package/src/components/editor-2d/floorplan-snap-beacon-layer.tsx +77 -0
  61. package/src/components/editor-2d/floorplan-wall-move-ghost-layer.tsx +47 -0
  62. package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +266 -0
  63. package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +15 -0
  64. package/src/components/editor-2d/renderers/floorplan-label-angle.ts +14 -0
  65. package/src/components/editor-2d/renderers/floorplan-measurements-layer.tsx +108 -66
  66. package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +62 -0
  67. package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +308 -0
  68. package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +3325 -0
  69. package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +24 -9
  70. package/src/components/editor-2d/renderers/floorplan-voronoi-layer.tsx +128 -0
  71. package/src/components/editor-2d/svg-paths.ts +10 -2
  72. package/src/components/systems/ceiling/ceiling-selection-affordance-system.tsx +439 -57
  73. package/src/components/systems/ceiling/ceiling-system.tsx +109 -12
  74. package/src/components/systems/roof/roof-edit-system.tsx +1851 -22
  75. package/src/components/systems/selection-affordance-manager.tsx +38 -0
  76. package/src/components/systems/stair/stair-edit-system.tsx +1 -1
  77. package/src/components/systems/zone/zone-label-editor-system.tsx +14 -1
  78. package/src/components/systems/zone/zone-system.tsx +42 -13
  79. package/src/components/tools/elevator/elevator-defaults.ts +8 -0
  80. package/src/components/tools/elevator/elevator-tool.tsx +375 -0
  81. package/src/components/tools/elevator/move-elevator-tool.tsx +263 -0
  82. package/src/components/tools/fence/fence-drafting.ts +141 -27
  83. package/src/components/tools/item/move-tool.tsx +45 -105
  84. package/src/components/tools/item/placement-math.test.ts +22 -0
  85. package/src/components/tools/item/placement-math.ts +59 -7
  86. package/src/components/tools/item/placement-strategies.ts +432 -16
  87. package/src/components/tools/item/placement-types.ts +22 -1
  88. package/src/components/tools/item/use-draft-node.ts +51 -2
  89. package/src/components/tools/item/use-placement-coordinator.tsx +1399 -256
  90. package/src/components/tools/registry/move-registry-node-tool.tsx +1064 -0
  91. package/src/components/tools/roof/roof-tool.tsx +350 -28
  92. package/src/components/tools/select/box-select-state.ts +88 -0
  93. package/src/components/tools/select/box-select-tool.tsx +442 -520
  94. package/src/components/tools/select/marquee-geometry.test.ts +161 -0
  95. package/src/components/tools/select/marquee-geometry.ts +155 -0
  96. package/src/components/tools/select/plane-box-select-tool.tsx +570 -0
  97. package/src/components/tools/select/screen-rectangle-selection.ts +84 -0
  98. package/src/components/tools/select/select-candidates.test.ts +109 -0
  99. package/src/components/tools/select/select-candidates.ts +85 -0
  100. package/src/components/tools/shared/affordance-dispatch.ts +30 -0
  101. package/src/components/tools/shared/cursor-sphere.tsx +62 -26
  102. package/src/components/tools/shared/drag-bounding-box.tsx +195 -0
  103. package/src/components/tools/shared/facing-indicator.tsx +87 -0
  104. package/src/components/tools/shared/facing-pose-indicator.tsx +54 -0
  105. package/src/components/tools/shared/floor-stack-preview.ts +25 -0
  106. package/src/components/tools/shared/fresh-placement-visibility.ts +61 -0
  107. package/src/components/tools/shared/placement-box-geometry.ts +123 -0
  108. package/src/components/tools/shared/placement-box.tsx +305 -0
  109. package/src/components/tools/shared/polygon-editor.tsx +866 -175
  110. package/src/components/tools/shared/segment-angle.ts +56 -0
  111. package/src/components/tools/site/site-boundary-editor.tsx +520 -16
  112. package/src/components/tools/site/site-flag-model.ts +18 -0
  113. package/src/components/tools/stair/stair-defaults.ts +2 -1
  114. package/src/components/tools/stair/stair-tool.tsx +342 -37
  115. package/src/components/tools/tool-manager.tsx +239 -62
  116. package/src/components/tools/wall/wall-drafting.test.ts +330 -0
  117. package/src/components/tools/wall/wall-drafting.ts +248 -171
  118. package/src/components/tools/wall/wall-snap-geometry.test.ts +123 -0
  119. package/src/components/tools/wall/wall-snap-geometry.ts +331 -0
  120. package/src/components/tools/zone/zone-boundary-editor.tsx +5 -1
  121. package/src/components/tools/zone/zone-tool.tsx +86 -82
  122. package/src/components/ui/action-menu/action-button.tsx +21 -1
  123. package/src/components/ui/action-menu/camera-actions.tsx +24 -17
  124. package/src/components/ui/action-menu/control-modes.tsx +40 -170
  125. package/src/components/ui/action-menu/furnish-tools.tsx +5 -5
  126. package/src/components/ui/action-menu/index.tsx +3 -117
  127. package/src/components/ui/action-menu/measurement-control.tsx +188 -0
  128. package/src/components/ui/action-menu/structure-tools.tsx +27 -93
  129. package/src/components/ui/action-menu/view-toggles.tsx +279 -90
  130. package/src/components/ui/command-palette/editor-commands.tsx +20 -15
  131. package/src/components/ui/command-palette/index.tsx +5 -3
  132. package/src/components/ui/controls/material-paint-panel.tsx +152 -0
  133. package/src/components/ui/controls/material-picker.tsx +87 -177
  134. package/src/components/ui/controls/material-properties-editor.tsx +108 -0
  135. package/src/components/ui/controls/metric-control.tsx +142 -46
  136. package/src/components/ui/controls/scene-material-list.tsx +247 -0
  137. package/src/components/ui/controls/slider-control.tsx +88 -38
  138. package/src/components/ui/floating-level-selector.tsx +47 -10
  139. package/src/components/ui/helpers/building-helper.tsx +10 -23
  140. package/src/components/ui/helpers/contextual-helper-panel.tsx +428 -0
  141. package/src/components/ui/helpers/helper-manager.tsx +235 -23
  142. package/src/components/ui/helpers/item-helper.tsx +28 -32
  143. package/src/components/ui/helpers/registered-tool-helper.tsx +59 -0
  144. package/src/components/ui/helpers/roof-helper.tsx +10 -12
  145. package/src/components/ui/icon-ref.tsx +47 -0
  146. package/src/components/ui/item-catalog/catalog-items.tsx +40 -1
  147. package/src/components/ui/item-catalog/item-catalog.tsx +16 -36
  148. package/src/components/ui/level-duplicate-dialog.tsx +2 -1
  149. package/src/components/ui/panels/node-display.ts +17 -16
  150. package/src/components/ui/panels/panel-manager.tsx +55 -58
  151. package/src/components/ui/panels/panel-wrapper.tsx +238 -12
  152. package/src/components/ui/panels/parametric-inspector.tsx +482 -0
  153. package/src/components/ui/panels/reference-panel.tsx +54 -19
  154. package/src/components/ui/primitives/dropdown-menu.tsx +12 -8
  155. package/src/components/ui/primitives/shortcut-token.tsx +39 -3
  156. package/src/components/ui/primitives/sidebar.tsx +1 -0
  157. package/src/components/ui/scene-loader.tsx +1 -3
  158. package/src/components/ui/sidebar/app-sidebar.tsx +5 -1
  159. package/src/components/ui/sidebar/icon-rail.tsx +50 -31
  160. package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +263 -0
  161. package/src/components/ui/sidebar/panels/items-panel/index.tsx +82 -8
  162. package/src/components/ui/sidebar/panels/plugins-panel.tsx +218 -0
  163. package/src/components/ui/sidebar/panels/settings-panel/index.tsx +122 -41
  164. package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +66 -7
  165. package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +267 -0
  166. package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +3 -1
  167. package/src/components/ui/sidebar/panels/site-panel/ceiling-tree-node.tsx +9 -5
  168. package/src/components/ui/sidebar/panels/site-panel/chimney-tree-node.tsx +86 -0
  169. package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +1 -1
  170. package/src/components/ui/sidebar/panels/site-panel/door-tree-node.tsx +7 -2
  171. package/src/components/ui/sidebar/panels/site-panel/dormer-tree-node.tsx +92 -0
  172. package/src/components/ui/sidebar/panels/site-panel/elevator-tree-node.tsx +75 -0
  173. package/src/components/ui/sidebar/panels/site-panel/fence-tree-node.tsx +3 -3
  174. package/src/components/ui/sidebar/panels/site-panel/gutter-tree-node.tsx +86 -0
  175. package/src/components/ui/sidebar/panels/site-panel/index.tsx +42 -21
  176. package/src/components/ui/sidebar/panels/site-panel/item-tree-node.tsx +31 -17
  177. package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +2 -1
  178. package/src/components/ui/sidebar/panels/site-panel/registry-tree-node.tsx +140 -0
  179. package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +48 -8
  180. package/src/components/ui/sidebar/panels/site-panel/shelf-tree-node.tsx +132 -0
  181. package/src/components/ui/sidebar/panels/site-panel/slab-tree-node.tsx +9 -5
  182. package/src/components/ui/sidebar/panels/site-panel/solar-panel-tree-node.tsx +86 -0
  183. package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +7 -1
  184. package/src/components/ui/sidebar/panels/site-panel/stair-tree-node.tsx +2 -2
  185. package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +112 -39
  186. package/src/components/ui/sidebar/panels/site-panel/tree-structure.ts +36 -0
  187. package/src/components/ui/sidebar/panels/site-panel/wall-tree-node.tsx +1 -1
  188. package/src/components/ui/sidebar/panels/site-panel/window-tree-node.tsx +7 -2
  189. package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +3 -3
  190. package/src/components/ui/sidebar/panels/zone-panel/index.tsx +51 -2
  191. package/src/components/ui/sidebar/tab-bar.tsx +75 -1
  192. package/src/components/ui/sidebar/use-plugin-panels.tsx +132 -0
  193. package/src/components/ui/snap-target-badge.test.tsx +40 -0
  194. package/src/components/ui/snap-target-badge.tsx +88 -0
  195. package/src/components/viewer-overlay.tsx +253 -61
  196. package/src/components/viewer-zone-system.tsx +7 -2
  197. package/src/hooks/use-auto-save.test.ts +14 -0
  198. package/src/hooks/use-auto-save.ts +64 -10
  199. package/src/hooks/use-ceiling-events.ts +176 -0
  200. package/src/hooks/use-drag-action.ts +127 -0
  201. package/src/hooks/use-keyboard.ts +493 -95
  202. package/src/hooks/use-selection.ts +64 -0
  203. package/src/index.tsx +451 -6
  204. package/src/lib/active-placement-surface.ts +35 -0
  205. package/src/lib/ceiling-plan-snap.ts +24 -0
  206. package/src/lib/constants.ts +6 -2
  207. package/src/lib/contextual-help.test.ts +112 -0
  208. package/src/lib/contextual-help.ts +144 -0
  209. package/src/lib/continuation.ts +64 -0
  210. package/src/lib/direct-manipulation.test.ts +192 -0
  211. package/src/lib/direct-manipulation.ts +109 -0
  212. package/src/lib/editor-api.ts +50 -0
  213. package/src/lib/elevator-support.ts +96 -0
  214. package/src/lib/floorplan/apply-alignment.test.ts +25 -0
  215. package/src/lib/floorplan/apply-alignment.ts +117 -0
  216. package/src/lib/floorplan/floorplan-export.tsx +364 -0
  217. package/src/lib/floorplan/geometry.ts +53 -0
  218. package/src/lib/floorplan/index.ts +10 -0
  219. package/src/lib/floorplan/items.ts +5 -2
  220. package/src/lib/floorplan/plan-coords.ts +21 -0
  221. package/src/lib/floorplan/selection-tool.ts +40 -0
  222. package/src/lib/floorplan/stairs.ts +12 -1
  223. package/src/lib/fresh-planar-placement.test.ts +339 -0
  224. package/src/lib/fresh-planar-placement.ts +130 -0
  225. package/src/lib/glb-export.test.ts +441 -0
  226. package/src/lib/glb-export.ts +874 -0
  227. package/src/lib/history.ts +11 -1
  228. package/src/lib/interaction/hot-set.test.ts +133 -0
  229. package/src/lib/interaction/hot-set.ts +67 -0
  230. package/src/lib/interaction/overlay-policy.test.ts +51 -0
  231. package/src/lib/interaction/overlay-policy.ts +59 -0
  232. package/src/lib/interaction/scope.ts +211 -0
  233. package/src/lib/level-duplication.ts +54 -42
  234. package/src/lib/level-selection.ts +2 -2
  235. package/src/lib/material-paint.ts +227 -48
  236. package/src/lib/measurement-kind.test.ts +30 -0
  237. package/src/lib/measurement-kind.ts +19 -0
  238. package/src/lib/measurement-label.test.ts +47 -0
  239. package/src/lib/measurement-label.ts +68 -0
  240. package/src/lib/measurement-parser.ts +116 -0
  241. package/src/lib/measurements.test.ts +183 -0
  242. package/src/lib/measurements.ts +199 -0
  243. package/src/lib/paint-scope.test.ts +454 -0
  244. package/src/lib/paint-scope.ts +461 -0
  245. package/src/lib/placement-drag-release.ts +23 -0
  246. package/src/lib/placement-metadata.ts +29 -0
  247. package/src/lib/planar-cursor-placement.test.ts +100 -0
  248. package/src/lib/planar-cursor-placement.ts +42 -0
  249. package/src/lib/plugin-panels.test.ts +19 -0
  250. package/src/lib/plugin-panels.ts +91 -0
  251. package/src/lib/quick-measurement.test.ts +77 -0
  252. package/src/lib/quick-measurement.ts +109 -0
  253. package/src/lib/roof-duplication.ts +7 -7
  254. package/src/lib/roof-hover-outline-proxy.ts +22 -0
  255. package/src/lib/roof-wall-hit.ts +164 -0
  256. package/src/lib/scene-clipboard.test.ts +196 -0
  257. package/src/lib/scene-clipboard.ts +332 -0
  258. package/src/lib/scene.ts +40 -8
  259. package/src/lib/selection-routing.test.ts +298 -0
  260. package/src/lib/selection-routing.ts +175 -0
  261. package/src/lib/sfx/index.ts +1 -0
  262. package/src/lib/sfx/movement-tick.test.ts +65 -0
  263. package/src/lib/sfx/movement-tick.ts +18 -0
  264. package/src/lib/sfx-bus.ts +69 -10
  265. package/src/lib/sfx-player.test.ts +124 -0
  266. package/src/lib/sfx-player.ts +148 -55
  267. package/src/lib/site-boundary.ts +1 -0
  268. package/src/lib/slab-plan-snap.test.ts +93 -0
  269. package/src/lib/slab-plan-snap.ts +108 -0
  270. package/src/lib/snapping-mode.test.ts +138 -0
  271. package/src/lib/snapping-mode.ts +179 -0
  272. package/src/lib/stair-duplication.ts +4 -4
  273. package/src/lib/stair-levels.test.ts +146 -0
  274. package/src/lib/stair-levels.ts +177 -0
  275. package/src/lib/surface-plan-snap.test.ts +71 -0
  276. package/src/lib/surface-plan-snap.ts +256 -0
  277. package/src/lib/use-linear-display.ts +40 -0
  278. package/src/lib/world-grid-snap.ts +231 -0
  279. package/src/lib/zone-content.ts +130 -0
  280. package/src/store/use-alignment-guides.ts +21 -0
  281. package/src/store/use-direct-manipulation-feedback.ts +20 -0
  282. package/src/store/use-editor.tsx +767 -114
  283. package/src/store/use-facing-pose.ts +44 -0
  284. package/src/store/use-fence-curve-draft.ts +21 -0
  285. package/src/store/use-floorplan-draft-preview.ts +101 -0
  286. package/src/store/use-floorplan-marquee.ts +50 -0
  287. package/src/store/use-interaction-scope.test.ts +186 -0
  288. package/src/store/use-interaction-scope.ts +132 -0
  289. package/src/store/use-measurement-draft.test.ts +530 -0
  290. package/src/store/use-measurement-draft.ts +543 -0
  291. package/src/store/use-opening-guides.ts +41 -0
  292. package/src/store/use-placement-preview.ts +39 -0
  293. package/src/store/use-quick-measurement-hud.test.ts +53 -0
  294. package/src/store/use-quick-measurement-hud.ts +77 -0
  295. package/src/store/use-segment-draft-chain.ts +28 -0
  296. package/src/store/use-stair-build-preview.ts +43 -0
  297. package/src/store/use-wall-move-ghosts.ts +36 -0
  298. package/src/store/use-wall-snap-indicator.ts +34 -0
  299. package/src/components/editor/first-person/bvh-ecctrl.tsx +0 -860
  300. package/src/components/editor/preset-thumbnail-generator.tsx +0 -125
  301. package/src/components/editor-2d/renderers/floorplan-roof-layer.tsx +0 -113
  302. package/src/components/tools/building/move-building-tool.tsx +0 -157
  303. package/src/components/tools/ceiling/ceiling-boundary-editor.tsx +0 -43
  304. package/src/components/tools/ceiling/ceiling-hole-editor.tsx +0 -49
  305. package/src/components/tools/ceiling/ceiling-tool.tsx +0 -465
  306. package/src/components/tools/ceiling/move-ceiling-tool.tsx +0 -264
  307. package/src/components/tools/column/column-tool.tsx +0 -97
  308. package/src/components/tools/column/move-column-tool.tsx +0 -105
  309. package/src/components/tools/door/door-math.ts +0 -110
  310. package/src/components/tools/door/door-tool.tsx +0 -324
  311. package/src/components/tools/door/move-door-tool.tsx +0 -412
  312. package/src/components/tools/fence/curve-fence-tool.tsx +0 -178
  313. package/src/components/tools/fence/fence-tool.tsx +0 -346
  314. package/src/components/tools/fence/move-fence-endpoint-tool.tsx +0 -441
  315. package/src/components/tools/fence/move-fence-tool.tsx +0 -302
  316. package/src/components/tools/item/item-tool.tsx +0 -26
  317. package/src/components/tools/roof/move-roof-tool.tsx +0 -364
  318. package/src/components/tools/slab/move-slab-tool.tsx +0 -182
  319. package/src/components/tools/slab/slab-boundary-editor.tsx +0 -43
  320. package/src/components/tools/slab/slab-hole-editor.tsx +0 -49
  321. package/src/components/tools/slab/slab-tool.tsx +0 -322
  322. package/src/components/tools/spawn/move-spawn-tool.tsx +0 -101
  323. package/src/components/tools/spawn/spawn-tool.tsx +0 -130
  324. package/src/components/tools/wall/curve-wall-tool.tsx +0 -178
  325. package/src/components/tools/wall/move-wall-endpoint-tool.tsx +0 -426
  326. package/src/components/tools/wall/move-wall-tool.tsx +0 -358
  327. package/src/components/tools/wall/wall-tool.tsx +0 -332
  328. package/src/components/tools/window/move-window-tool.tsx +0 -447
  329. package/src/components/tools/window/window-math.ts +0 -117
  330. package/src/components/tools/window/window-tool.tsx +0 -332
  331. package/src/components/ui/helpers/ceiling-helper.tsx +0 -20
  332. package/src/components/ui/helpers/slab-helper.tsx +0 -20
  333. package/src/components/ui/helpers/wall-helper.tsx +0 -20
  334. package/src/components/ui/panels/ceiling-panel.tsx +0 -249
  335. package/src/components/ui/panels/column-panel.tsx +0 -759
  336. package/src/components/ui/panels/door-panel.tsx +0 -1299
  337. package/src/components/ui/panels/fence-panel.tsx +0 -222
  338. package/src/components/ui/panels/item-panel.tsx +0 -306
  339. package/src/components/ui/panels/paint-panel.tsx +0 -163
  340. package/src/components/ui/panels/presets/presets-popover.tsx +0 -511
  341. package/src/components/ui/panels/roof-panel.tsx +0 -280
  342. package/src/components/ui/panels/roof-segment-panel.tsx +0 -311
  343. package/src/components/ui/panels/slab-panel.tsx +0 -250
  344. package/src/components/ui/panels/spawn-panel.tsx +0 -161
  345. package/src/components/ui/panels/stair-panel.tsx +0 -577
  346. package/src/components/ui/panels/stair-segment-panel.tsx +0 -325
  347. package/src/components/ui/panels/wall-panel.tsx +0 -273
  348. package/src/components/ui/panels/window-panel.tsx +0 -968
  349. package/src/contexts/presets-context.tsx +0 -121
  350. package/src/hooks/use-contextual-tools.ts +0 -61
@@ -1,465 +0,0 @@
1
- import { CeilingNode, emitter, type GridEvent, type LevelNode, useScene } from '@pascal-app/core'
2
- import { useViewer } from '@pascal-app/viewer'
3
- import { useEffect, useMemo, useRef, useState } from 'react'
4
- import { BufferGeometry, DoubleSide, type Group, type Line, Shape, Vector3 } from 'three'
5
- import { mix, positionLocal } from 'three/tsl'
6
- import { markToolCancelConsumed } from '../../../hooks/use-keyboard'
7
- import { EDITOR_LAYER } from '../../../lib/constants'
8
- import { sfxEmitter } from '../../../lib/sfx-bus'
9
- import { CursorSphere } from '../shared/cursor-sphere'
10
-
11
- const CEILING_HEIGHT = 2.52
12
- const GRID_OFFSET = 0.02
13
-
14
- /**
15
- * Snaps a point to the nearest axis-aligned or 45-degree diagonal from the last point
16
- */
17
- const calculateSnapPoint = (
18
- lastPoint: [number, number],
19
- currentPoint: [number, number],
20
- ): [number, number] => {
21
- const [x1, y1] = lastPoint
22
- const [x, y] = currentPoint
23
-
24
- const dx = x - x1
25
- const dy = y - y1
26
- const absDx = Math.abs(dx)
27
- const absDy = Math.abs(dy)
28
-
29
- // Calculate distances to horizontal, vertical, and diagonal lines
30
- const horizontalDist = absDy
31
- const verticalDist = absDx
32
- const diagonalDist = Math.abs(absDx - absDy)
33
-
34
- // Find the minimum distance to determine which axis to snap to
35
- const minDist = Math.min(horizontalDist, verticalDist, diagonalDist)
36
-
37
- if (minDist === diagonalDist) {
38
- // Snap to 45° diagonal
39
- const diagonalLength = Math.min(absDx, absDy)
40
- return [x1 + Math.sign(dx) * diagonalLength, y1 + Math.sign(dy) * diagonalLength]
41
- }
42
- if (minDist === horizontalDist) {
43
- // Snap to horizontal
44
- return [x, y1]
45
- }
46
- // Snap to vertical
47
- return [x1, y]
48
- }
49
-
50
- /**
51
- * Creates a ceiling with the given polygon points and returns its ID
52
- */
53
- const commitCeilingDrawing = (
54
- levelId: LevelNode['id'],
55
- points: Array<[number, number]>,
56
- ): string => {
57
- const { createNode, nodes } = useScene.getState()
58
-
59
- // Count existing ceilings for naming
60
- const ceilingCount = Object.values(nodes).filter((n) => n.type === 'ceiling').length
61
- const name = `Ceiling ${ceilingCount + 1}`
62
-
63
- const ceiling = CeilingNode.parse({
64
- name,
65
- polygon: points,
66
- })
67
-
68
- createNode(ceiling, levelId)
69
- sfxEmitter.emit('sfx:structure-build')
70
- return ceiling.id
71
- }
72
-
73
- export const CeilingTool: React.FC = () => {
74
- const cursorRef = useRef<Group>(null)
75
- const gridCursorRef = useRef<Group>(null)
76
- const mainLineRef = useRef<Line>(null!)
77
- const closingLineRef = useRef<Line>(null!)
78
- const groundMainLineRef = useRef<Line>(null!)
79
- const groundClosingLineRef = useRef<Line>(null!)
80
- const verticalLineRef = useRef<Line>(null!)
81
- const currentLevelId = useViewer((state) => state.selection.levelId)
82
- const setSelection = useViewer((state) => state.setSelection)
83
-
84
- const [points, setPoints] = useState<Array<[number, number]>>([])
85
- const [cursorPosition, setCursorPosition] = useState<[number, number]>([0, 0])
86
- const [snappedCursorPosition, setSnappedCursorPosition] = useState<[number, number]>([0, 0])
87
- const [levelY, setLevelY] = useState(0)
88
- const previousSnappedPointRef = useRef<[number, number] | null>(null)
89
- const shiftPressed = useRef(false)
90
-
91
- // Static geometry: local y goes 0 (grid) → H (ceiling), mesh is positioned at gridY
92
- const verticalGeo = useMemo(
93
- () =>
94
- new BufferGeometry().setFromPoints([
95
- new Vector3(0, 0, 0),
96
- new Vector3(0, CEILING_HEIGHT - GRID_OFFSET, 0),
97
- ]),
98
- [],
99
- )
100
-
101
- // opacityNode: positionLocal.y is 0 at grid, H at ceiling → fade from 0.6 to 0
102
- const gradientOpacityNode = useMemo(
103
- () => mix(0.6, 0.0, positionLocal.y.div(CEILING_HEIGHT - GRID_OFFSET).clamp()),
104
- [],
105
- )
106
-
107
- // Update cursor position and lines on grid move
108
- useEffect(() => {
109
- if (!currentLevelId) return
110
-
111
- const onGridMove = (event: GridEvent) => {
112
- if (!(cursorRef.current && gridCursorRef.current)) return
113
-
114
- const gridX = Math.round(event.localPosition[0] * 2) / 2
115
- const gridZ = Math.round(event.localPosition[2] * 2) / 2
116
- const gridPosition: [number, number] = [gridX, gridZ]
117
-
118
- setCursorPosition(gridPosition)
119
- setLevelY(event.localPosition[1])
120
-
121
- const ceilingY = event.localPosition[1] + CEILING_HEIGHT
122
- const gridY = event.localPosition[1] + GRID_OFFSET
123
-
124
- // Calculate snapped display position (bypass snap when Shift is held)
125
- const lastPoint = points[points.length - 1]
126
- const displayPoint =
127
- shiftPressed.current || !lastPoint
128
- ? gridPosition
129
- : calculateSnapPoint(lastPoint, gridPosition)
130
- setSnappedCursorPosition(displayPoint)
131
-
132
- // Play snap sound when the snapped position actually changes (only when drawing)
133
- if (
134
- points.length > 0 &&
135
- previousSnappedPointRef.current &&
136
- (displayPoint[0] !== previousSnappedPointRef.current[0] ||
137
- displayPoint[1] !== previousSnappedPointRef.current[1])
138
- ) {
139
- sfxEmitter.emit('sfx:grid-snap')
140
- }
141
-
142
- previousSnappedPointRef.current = displayPoint
143
- cursorRef.current.position.set(displayPoint[0], ceilingY, displayPoint[1])
144
- gridCursorRef.current.position.set(displayPoint[0], gridY, displayPoint[1])
145
-
146
- if (verticalLineRef.current) {
147
- verticalLineRef.current.position.set(displayPoint[0], gridY, displayPoint[1])
148
- }
149
- }
150
-
151
- const onGridClick = (_event: GridEvent) => {
152
- if (!currentLevelId) return
153
-
154
- // Use the last displayed snapped position (respects Shift state from onGridMove)
155
- const clickPoint = previousSnappedPointRef.current ?? cursorPosition
156
-
157
- // Check if clicking on the first point to close the shape
158
- const firstPoint = points[0]
159
- if (
160
- points.length >= 3 &&
161
- firstPoint &&
162
- Math.abs(clickPoint[0] - firstPoint[0]) < 0.25 &&
163
- Math.abs(clickPoint[1] - firstPoint[1]) < 0.25
164
- ) {
165
- // Create the ceiling and select it
166
- const ceilingId = commitCeilingDrawing(currentLevelId, points)
167
- setSelection({ selectedIds: [ceilingId] })
168
- setPoints([])
169
- } else {
170
- // Add point to polygon
171
- setPoints([...points, clickPoint])
172
- }
173
- }
174
-
175
- const onGridDoubleClick = (_event: GridEvent) => {
176
- if (!currentLevelId) return
177
-
178
- // Need at least 3 points to form a polygon
179
- if (points.length >= 3) {
180
- const ceilingId = commitCeilingDrawing(currentLevelId, points)
181
- setSelection({ selectedIds: [ceilingId] })
182
- setPoints([])
183
- }
184
- }
185
-
186
- const onCancel = () => {
187
- if (points.length > 0) markToolCancelConsumed()
188
- setPoints([])
189
- }
190
-
191
- const onKeyDown = (e: KeyboardEvent) => {
192
- if (e.key === 'Shift') shiftPressed.current = true
193
- }
194
- const onKeyUp = (e: KeyboardEvent) => {
195
- if (e.key === 'Shift') shiftPressed.current = false
196
- }
197
- document.addEventListener('keydown', onKeyDown)
198
- document.addEventListener('keyup', onKeyUp)
199
-
200
- emitter.on('grid:move', onGridMove)
201
- emitter.on('grid:click', onGridClick)
202
- emitter.on('grid:double-click', onGridDoubleClick)
203
- emitter.on('tool:cancel', onCancel)
204
-
205
- return () => {
206
- document.removeEventListener('keydown', onKeyDown)
207
- document.removeEventListener('keyup', onKeyUp)
208
- emitter.off('grid:move', onGridMove)
209
- emitter.off('grid:click', onGridClick)
210
- emitter.off('grid:double-click', onGridDoubleClick)
211
- emitter.off('tool:cancel', onCancel)
212
- }
213
- }, [currentLevelId, points, cursorPosition, setSelection])
214
-
215
- // Update line geometries when points change
216
- useEffect(() => {
217
- if (!(mainLineRef.current && closingLineRef.current)) return
218
-
219
- if (points.length === 0) {
220
- mainLineRef.current.visible = false
221
- closingLineRef.current.visible = false
222
- return
223
- }
224
-
225
- const ceilingY = levelY + CEILING_HEIGHT
226
- const snappedCursor = snappedCursorPosition
227
-
228
- // Build main line points
229
- const linePoints: Vector3[] = points.map(([x, z]) => new Vector3(x, ceilingY, z))
230
- linePoints.push(new Vector3(snappedCursor[0], ceilingY, snappedCursor[1]))
231
-
232
- const gridY = levelY + GRID_OFFSET
233
- const groundLinePoints: Vector3[] = points.map(([x, z]) => new Vector3(x, gridY, z))
234
- groundLinePoints.push(new Vector3(snappedCursor[0], gridY, snappedCursor[1]))
235
-
236
- // Update main line
237
- if (linePoints.length >= 2) {
238
- mainLineRef.current.geometry.dispose()
239
- mainLineRef.current.geometry = new BufferGeometry().setFromPoints(linePoints)
240
- mainLineRef.current.visible = true
241
-
242
- groundMainLineRef.current.geometry.dispose()
243
- groundMainLineRef.current.geometry = new BufferGeometry().setFromPoints(groundLinePoints)
244
- groundMainLineRef.current.visible = true
245
- } else {
246
- mainLineRef.current.visible = false
247
- groundMainLineRef.current.visible = false
248
- }
249
-
250
- // Update closing line (from cursor back to first point)
251
- const firstPoint = points[0]
252
- if (points.length >= 2 && firstPoint) {
253
- const closingPoints = [
254
- new Vector3(snappedCursor[0], ceilingY, snappedCursor[1]),
255
- new Vector3(firstPoint[0], ceilingY, firstPoint[1]),
256
- ]
257
- closingLineRef.current.geometry.dispose()
258
- closingLineRef.current.geometry = new BufferGeometry().setFromPoints(closingPoints)
259
- closingLineRef.current.visible = true
260
-
261
- const groundClosingPoints = [
262
- new Vector3(snappedCursor[0], gridY, snappedCursor[1]),
263
- new Vector3(firstPoint[0], gridY, firstPoint[1]),
264
- ]
265
- groundClosingLineRef.current.geometry.dispose()
266
- groundClosingLineRef.current.geometry = new BufferGeometry().setFromPoints(
267
- groundClosingPoints,
268
- )
269
- groundClosingLineRef.current.visible = true
270
- } else {
271
- closingLineRef.current.visible = false
272
- groundClosingLineRef.current.visible = false
273
- }
274
- }, [points, snappedCursorPosition, levelY])
275
-
276
- // Create preview shape when we have 3+ points
277
- const previewShape = useMemo(() => {
278
- if (points.length < 3) return null
279
-
280
- const snappedCursor = snappedCursorPosition
281
-
282
- const allPoints = [...points, snappedCursor]
283
-
284
- // THREE.Shape is in X-Y plane. After rotation of -PI/2 around X:
285
- // - Shape X -> World X
286
- // - Shape Y -> World -Z (so we negate Z to get correct orientation)
287
- const firstPt = allPoints[0]
288
- if (!firstPt) return null
289
-
290
- const shape = new Shape()
291
- shape.moveTo(firstPt[0], -firstPt[1])
292
-
293
- for (let i = 1; i < allPoints.length; i++) {
294
- const pt = allPoints[i]
295
- if (pt) {
296
- shape.lineTo(pt[0], -pt[1])
297
- }
298
- }
299
- shape.closePath()
300
-
301
- return shape
302
- }, [points, snappedCursorPosition])
303
-
304
- return (
305
- <group>
306
- {/* Cursor at ceiling height */}
307
- <CursorSphere ref={cursorRef} />
308
-
309
- {/* Grid-level cursor indicator */}
310
- <mesh
311
- layers={EDITOR_LAYER}
312
- ref={gridCursorRef}
313
- renderOrder={2}
314
- rotation={[-Math.PI / 2, 0, 0]}
315
- >
316
- <ringGeometry args={[0.15, 0.2, 32]} />
317
- <meshBasicMaterial
318
- color="#818cf8"
319
- depthTest={false}
320
- depthWrite={true}
321
- opacity={0.5}
322
- side={DoubleSide}
323
- transparent
324
- />
325
- </mesh>
326
-
327
- {/* Vertical connector: local y=0 at grid, y=H at ceiling; position.y set to gridY on move */}
328
- {/* @ts-ignore */}
329
- <line geometry={verticalGeo} layers={EDITOR_LAYER} ref={verticalLineRef} renderOrder={1}>
330
- <lineBasicNodeMaterial
331
- color="#818cf8"
332
- depthTest={false}
333
- depthWrite={false}
334
- opacityNode={gradientOpacityNode}
335
- transparent
336
- />
337
- </line>
338
-
339
- {/* Preview fill (Top) */}
340
- {previewShape && (
341
- <mesh
342
- frustumCulled={false}
343
- layers={EDITOR_LAYER}
344
- position={[0, levelY + CEILING_HEIGHT, 0]}
345
- rotation={[-Math.PI / 2, 0, 0]}
346
- >
347
- <shapeGeometry args={[previewShape]} />
348
- <meshBasicMaterial
349
- color="#818cf8"
350
- depthTest={false}
351
- opacity={0.15}
352
- side={DoubleSide}
353
- transparent
354
- />
355
- </mesh>
356
- )}
357
-
358
- {/* Preview fill (Ground) */}
359
- {previewShape && (
360
- <mesh
361
- frustumCulled={false}
362
- layers={EDITOR_LAYER}
363
- position={[0, levelY + GRID_OFFSET, 0]}
364
- rotation={[-Math.PI / 2, 0, 0]}
365
- >
366
- <shapeGeometry args={[previewShape]} />
367
- <meshBasicMaterial
368
- color="#818cf8"
369
- depthTest={false}
370
- opacity={0.1}
371
- side={DoubleSide}
372
- transparent
373
- />
374
- </mesh>
375
- )}
376
-
377
- {/* Main line */}
378
- {/* @ts-ignore */}
379
- <line
380
- frustumCulled={false}
381
- layers={EDITOR_LAYER}
382
- // @ts-expect-error
383
- ref={mainLineRef}
384
- renderOrder={1}
385
- visible={false}
386
- >
387
- <bufferGeometry />
388
- <lineBasicNodeMaterial color="#818cf8" depthTest={false} depthWrite={false} linewidth={3} />
389
- </line>
390
-
391
- {/* Closing line */}
392
- {/* @ts-ignore */}
393
- <line
394
- frustumCulled={false}
395
- layers={EDITOR_LAYER}
396
- // @ts-expect-error
397
- ref={closingLineRef}
398
- renderOrder={1}
399
- visible={false}
400
- >
401
- <bufferGeometry />
402
- <lineBasicNodeMaterial
403
- color="#818cf8"
404
- depthTest={false}
405
- depthWrite={false}
406
- linewidth={2}
407
- opacity={0.5}
408
- transparent
409
- />
410
- </line>
411
-
412
- {/* Ground main line */}
413
- {/* @ts-ignore */}
414
- <line
415
- frustumCulled={false}
416
- layers={EDITOR_LAYER}
417
- // @ts-expect-error
418
- ref={groundMainLineRef}
419
- renderOrder={1}
420
- visible={false}
421
- >
422
- <bufferGeometry />
423
- <lineBasicNodeMaterial
424
- color="#818cf8"
425
- depthTest={false}
426
- depthWrite={false}
427
- linewidth={3}
428
- opacity={0.3}
429
- transparent
430
- />
431
- </line>
432
-
433
- {/* Ground closing line */}
434
- {/* @ts-ignore */}
435
- <line
436
- frustumCulled={false}
437
- layers={EDITOR_LAYER}
438
- // @ts-expect-error
439
- ref={groundClosingLineRef}
440
- renderOrder={1}
441
- visible={false}
442
- >
443
- <bufferGeometry />
444
- <lineBasicNodeMaterial
445
- color="#818cf8"
446
- depthTest={false}
447
- depthWrite={false}
448
- linewidth={2}
449
- opacity={0.15}
450
- transparent
451
- />
452
- </line>
453
-
454
- {/* Point markers */}
455
- {points.map(([x, z], index) => (
456
- <CursorSphere
457
- color="#818cf8"
458
- key={index}
459
- position={[x, levelY + CEILING_HEIGHT + 0.01, z]}
460
- showTooltip={false}
461
- />
462
- ))}
463
- </group>
464
- )
465
- }