@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.
- package/package.json +9 -15
- package/src/components/editor/action-menu-button.tsx +1 -1
- package/src/components/editor/alignment-3d-guide-layer.tsx +1 -1
- package/src/components/editor/custom-camera-controls.tsx +11 -11
- package/src/components/editor/editor-layout-v2.tsx +1 -1
- package/src/components/editor/elevation-3d-guide-layer.tsx +1 -1
- package/src/components/editor/first-person-controls.tsx +20 -1981
- package/src/components/editor/floating-action-menu.tsx +1 -1
- package/src/components/editor/floating-building-action-menu.tsx +1 -1
- package/src/components/editor/floor-region-controls.tsx +6 -2
- package/src/components/editor/floorplan-navigation-presentation.test.ts +0 -40
- package/src/components/editor/floorplan-navigation-presentation.ts +0 -66
- package/src/components/editor/floorplan-panel.tsx +26 -22
- package/src/components/editor/floorplan-wall-typing-keys.ts +1 -1
- package/src/components/editor/follow-pascal.test.tsx +1 -2
- package/src/components/editor/follow-pascal.tsx +1 -1
- package/src/components/editor/footprint-height-handle.tsx +1 -1
- package/src/components/editor/group-actions.ts +1 -2
- package/src/components/editor/group-floating-action-menu.tsx +1 -1
- package/src/components/editor/group-move-3d.ts +1 -2
- package/src/components/editor/group-rotate-handle.tsx +1 -2
- package/src/components/editor/handles/use-handle-drag.ts +1 -2
- package/src/components/editor/index.tsx +24 -14
- package/src/components/editor/inspector-extension-actions.tsx +1 -1
- package/src/components/editor/node-arrow-handles.tsx +1 -1
- package/src/components/editor/open-wall-ends-3d-layer.tsx +1 -1
- package/src/components/editor/opening-guides-3d-layer.tsx +1 -1
- package/src/components/editor/room-controls.tsx +7 -4
- package/src/components/editor/room-handles-2d.tsx +2 -3
- package/src/components/editor/room-handles.tsx +1 -2
- package/src/components/editor/room-highlight.tsx +6 -105
- package/src/components/editor/room-labels.test.ts +8 -822
- package/src/components/editor/room-labels.tsx +40 -1671
- package/src/components/editor/room-webgpu-materials.test.ts +1 -1
- package/src/components/editor/selection-manager.tsx +5 -3
- package/src/components/editor/site-edge-labels.tsx +1 -1
- package/src/components/editor/snapshot-capture-overlay.tsx +2 -5
- package/src/components/editor/use-floorplan-background-placement.ts +2 -1
- package/src/components/editor/views/plugins-view.tsx +1 -1
- package/src/components/editor/views/view-bar.tsx +9 -9
- package/src/components/editor/wall-measurement-label.tsx +1 -1
- package/src/components/editor/wall-move-side-handles.tsx +1 -1
- package/src/components/editor/wall-pull-grip.tsx +2 -2
- package/src/components/editor-2d/floorplan-group-move.tsx +2 -3
- package/src/components/editor-2d/floorplan-measurement-tool-layer.tsx +1 -1
- package/src/components/editor-2d/floorplan-open-wall-ends-layer.tsx +1 -1
- package/src/components/editor-2d/floorplan-registry-move-overlay.tsx +1 -2
- package/src/components/editor-2d/renderers/floorplan-annotation-layout.test.ts +0 -37
- package/src/components/editor-2d/renderers/floorplan-annotation-layout.ts +0 -30
- package/src/components/editor-2d/renderers/floorplan-dimension-edit-overlay.tsx +13 -3
- package/src/components/editor-2d/renderers/floorplan-placement-preview-layer.tsx +1 -2
- package/src/components/editor-2d/renderers/floorplan-registry-layer.test.ts +8 -10
- package/src/components/editor-2d/renderers/floorplan-registry-layer.tsx +25 -33
- package/src/components/systems/roof/roof-edit-system.tsx +4 -3
- package/src/components/tools/distribution/distribution-run-tool.tsx +1 -1
- package/src/components/tools/item/placement-history.test.tsx +1 -1
- package/src/components/tools/item/use-placement-coordinator.tsx +2 -3
- package/src/components/tools/paint-region/wall-paint-region-tool.tsx +6 -2
- package/src/components/tools/registry/move-registry-node-tool.tsx +1 -2
- package/src/components/tools/shared/cursor-sphere.tsx +1 -1
- package/src/components/tools/shared/draft-measurement-label.tsx +1 -1
- package/src/components/tools/shared/placement-box.tsx +1 -1
- package/src/components/tools/shared/placement-dimension-guides.tsx +1 -1
- package/src/components/tools/site/terrain-brush-cursor.tsx +1 -1
- package/src/components/ui/action-menu/camera-actions.tsx +2 -2
- package/src/components/ui/action-menu/control-modes.tsx +1 -1
- package/src/components/ui/action-menu/follow-pascal-pill.tsx +1 -1
- package/src/components/ui/action-menu/index.tsx +3 -3
- package/src/components/ui/action-menu/measurement-control.tsx +3 -3
- package/src/components/ui/action-menu/placement.ts +0 -18
- package/src/components/ui/action-menu/point-ask-button.tsx +1 -1
- package/src/components/ui/action-menu/view-toggles.tsx +5 -5
- package/src/components/ui/controls/finish-swatch.tsx +1 -1
- package/src/components/ui/controls/material-paint-panel.tsx +2 -2
- package/src/components/ui/controls/scene-material-list.tsx +2 -2
- package/src/components/ui/controls/select-control.tsx +1 -1
- package/src/components/ui/controls/terrain-sculpt-panel.tsx +1 -1
- package/src/components/ui/floating-level-selector.tsx +3 -3
- package/src/components/ui/helpers/contextual-helper-panel.tsx +1 -1
- package/src/components/ui/helpers/helper-manager.test.tsx +1 -1
- package/src/components/ui/helpers/helper-manager.tsx +1 -1
- package/src/components/ui/level-duplicate-dialog.tsx +1 -1
- package/src/components/ui/node-icon-image.test.tsx +46 -0
- package/src/components/ui/node-icon-image.tsx +33 -1
- package/src/components/ui/panels/collections/collections-popover.tsx +2 -2
- package/src/components/ui/panels/floor-foundation-panel.tsx +2 -2
- package/src/components/ui/panels/floor-opening-panel.tsx +4 -4
- package/src/components/ui/panels/node-display.ts +1 -1
- package/src/components/ui/panels/panel-manager.tsx +1 -1
- package/src/components/ui/panels/panel-wrapper.tsx +1 -1
- package/src/components/ui/panels/parametric-inspector.tsx +1 -1
- package/src/components/ui/panels/room-construction-rows.tsx +6 -6
- package/src/components/ui/panels/room-name-options.ts +1 -5
- package/src/components/ui/panels/room-panel.tsx +6 -8
- package/src/components/ui/primitives/color-dot.tsx +2 -2
- package/src/components/ui/primitives/opacity-control.tsx +2 -2
- package/src/components/ui/primitives/sidebar.tsx +3 -3
- package/src/components/ui/right-stack.tsx +1 -1
- package/src/components/ui/sidebar/icon-rail.tsx +1 -1
- package/src/components/ui/sidebar/panels/items-panel/function-tree-panel.tsx +1 -1
- package/src/components/ui/sidebar/panels/settings-panel/audio-settings-dialog.tsx +2 -2
- package/src/components/ui/sidebar/panels/settings-panel/construction-animation-setting.tsx +1 -1
- package/src/components/ui/sidebar/panels/settings-panel/index.tsx +2 -2
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +1 -1
- package/src/components/ui/sidebar/panels/settings-panel/load-build-dialog.tsx +1 -1
- package/src/components/ui/sidebar/panels/settings-panel/print-export-button.tsx +1 -1
- package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +1 -1
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +2 -2
- package/src/components/ui/sidebar/panels/site-panel/inline-rename-input.tsx +1 -1
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +1 -1
- package/src/components/ui/sidebar/panels/site-panel/roof-tree-node.tsx +46 -7
- package/src/components/ui/sidebar/panels/site-panel/tree-node-actions.tsx +1 -1
- package/src/components/ui/sidebar/panels/site-panel/tree-node-drag.tsx +14 -5
- package/src/components/ui/sidebar/panels/site-panel/unit-tree-node.tsx +2 -2
- package/src/components/ui/sidebar/panels/zone-panel/index.tsx +3 -3
- package/src/components/ui/sidebar/tab-bar.tsx +1 -1
- package/src/components/ui/wall-type/wall-type-editor-dialog.tsx +1 -1
- package/src/components/ui/wall-type/wall-type-menu.tsx +1 -1
- package/src/components/viewer-overlay.tsx +1 -2
- package/src/hooks/use-auto-frame.ts +1 -2
- package/src/hooks/use-keyboard.ts +1 -2
- package/src/hooks/use-selected-room.ts +5 -7
- package/src/i18n/floor-footprint-name.ts +1 -1
- package/src/i18n/locales/en/messages.po +180 -182
- package/src/i18n/locales/es/messages.po +180 -182
- package/src/i18n/locales/fr/messages.po +180 -182
- package/src/i18n/locales/ja/messages.po +180 -182
- package/src/i18n/locales/zh-CN/messages.po +180 -182
- package/src/i18n/locales.test.ts +1 -1
- package/src/index.tsx +109 -131
- package/src/lib/below-grade.test.tsx +4 -4
- package/src/lib/camera-facing.test.ts +1 -1
- package/src/lib/camera-facing.ts +2 -3
- package/src/lib/editor-level-display.ts +1 -1
- package/src/lib/floor-footprints.test.ts +2 -2
- package/src/lib/floor-opening-draft.ts +1 -1
- package/src/lib/floorplan/annotation-visibility.test.ts +1 -1
- package/src/lib/floorplan/annotation-visibility.ts +1 -1
- package/src/lib/floorplan/floorplan-export.test.ts +1 -1
- package/src/lib/floorplan/floorplan-export.tsx +8 -11
- package/src/lib/floorplan/floorplan-extension.ts +4 -157
- package/src/lib/floorplan/floorplan-mode.ts +2 -1
- package/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts +1 -1
- package/src/lib/floorplan/floorplan-pdfkit-renderer.ts +8 -6
- package/src/lib/floorplan/floorplan-plugin-install.test.tsx +3 -4
- package/src/lib/floorplan/geometry.ts +2 -112
- package/src/lib/floorplan/index.ts +0 -9
- package/src/lib/floorplan/items.ts +2 -1
- package/src/lib/floorplan/schedules.ts +6 -3
- package/src/lib/floorplan/sheet-export.ts +7 -3
- package/src/lib/floorplan/site-plan/site-parts.ts +7 -1
- package/src/lib/floorplan/site-plan/site-plan-layer.tsx +1 -1
- package/src/lib/follow-pascal-presentation.ts +1 -1
- package/src/lib/glb-export.ts +1 -1
- package/src/lib/material-paint.ts +1 -1
- package/src/lib/measurements.test.ts +2 -1
- package/src/lib/mezzanine-selection.test.ts +1 -1
- package/src/lib/paint-region-mode.ts +1 -1
- package/src/lib/point-ask/session.ts +1 -2
- package/src/lib/roof-duplication.test.ts +100 -0
- package/src/lib/roof-duplication.ts +30 -5
- package/src/lib/room-handle-drag.ts +2 -12
- package/src/lib/room-name-catalog.test.ts +2 -1
- package/src/lib/room-name-messages.test.ts +2 -1
- package/src/lib/room-name-messages.ts +1 -118
- package/src/lib/room-name-storage.test.ts +2 -1
- package/src/lib/room-selection-commands.ts +2 -2
- package/src/lib/room-selection.test.ts +6 -6
- package/src/lib/room-transform-session.ts +1 -2
- package/src/lib/room-zone-routing.ts +2 -2
- package/src/lib/selection-routing.test.ts +0 -28
- package/src/lib/selection-routing.ts +1 -40
- package/src/lib/sfx-bus.ts +8 -32
- package/src/lib/sfx-player.test.ts +72 -1
- package/src/lib/sfx-player.ts +49 -337
- package/src/lib/viewer-selection.test.ts +38 -10
- package/src/lib/wall-pull.test.ts +1 -1
- package/src/lib/wall-pull.ts +1 -27
- package/src/store/use-editor.tsx +17 -26
- package/src/store/use-floorplan-annotation-visibility.ts +5 -5
- package/src/store/use-wall-region-handles-selection.ts +1 -2
- package/src/components/editor/__bench__/room-label-placement.bench.ts +0 -108
- package/src/components/editor/first-person/build-collider-world.test.ts +0 -596
- package/src/components/editor/first-person/build-collider-world.ts +0 -549
- package/src/components/editor/first-person/ground-holes.test.ts +0 -128
- package/src/components/editor/first-person/ground-holes.ts +0 -130
- package/src/components/editor/first-person/mechanism-targets.test.ts +0 -162
- package/src/components/editor/first-person/mechanism-targets.ts +0 -88
- package/src/components/editor/first-person/terrain-collider.test.ts +0 -132
- package/src/components/editor/first-person/terrain-collider.ts +0 -212
- package/src/components/editor/floorplan-camera-sync.test.ts +0 -249
- package/src/components/editor/floorplan-camera-sync.ts +0 -213
- package/src/components/editor/localized-html.tsx +0 -22
- package/src/components/editor-2d/renderers/floorplan-dimension-renderer.test.tsx +0 -236
- package/src/components/editor-2d/renderers/floorplan-dimension-renderer.tsx +0 -708
- package/src/components/editor-2d/renderers/floorplan-geometry-renderer.test.tsx +0 -385
- package/src/components/editor-2d/renderers/floorplan-geometry-renderer.tsx +0 -670
- package/src/components/editor-2d/renderers/floorplan-label-angle.test.ts +0 -89
- package/src/components/editor-2d/renderers/floorplan-label-angle.ts +0 -106
- package/src/components/editor-2d/svg-paths.ts +0 -124
- package/src/components/ui/action-menu/action-button.tsx +0 -89
- package/src/components/ui/action-menu/follow-pascal-toggle.tsx +0 -42
- package/src/components/ui/primitives/button.tsx +0 -69
- package/src/components/ui/primitives/dropdown-menu.tsx +0 -232
- package/src/components/ui/primitives/popover.tsx +0 -42
- package/src/components/ui/primitives/switch.tsx +0 -29
- package/src/components/ui/primitives/tooltip.tsx +0 -57
- package/src/components/ui/scene-loader.tsx +0 -73
- package/src/components/viewer/floorplan-compass-button.tsx +0 -67
- package/src/components/viewer/floorplan-preview-geometry.test.ts +0 -107
- package/src/components/viewer/floorplan-preview-geometry.ts +0 -281
- package/src/components/viewer/floorplan-preview-navigation.test.ts +0 -43
- package/src/components/viewer/floorplan-preview-navigation.ts +0 -62
- package/src/components/viewer/floorplan-preview-visibility.test.ts +0 -35
- package/src/components/viewer/floorplan-preview-visibility.ts +0 -19
- package/src/components/viewer/floorplan-preview.tsx +0 -1065
- package/src/components/viewer/render-settings-menu.tsx +0 -294
- package/src/components/viewer/sky-control.tsx +0 -710
- package/src/components/viewer/use-viewer-camera-navigation-sync.ts +0 -140
- package/src/components/viewer/use-viewer-ui-sounds.test.ts +0 -15
- package/src/components/viewer/use-viewer-ui-sounds.ts +0 -46
- package/src/components/viewer/viewer-controls-bar.tsx +0 -496
- package/src/components/viewer/viewer-hover-label.tsx +0 -42
- package/src/components/viewer/viewer-rooms.tsx +0 -248
- package/src/components/viewer/viewer-scene-header.tsx +0 -286
- package/src/components/viewer/viewer-selection-manager.tsx +0 -124
- package/src/components/viewer/viewer-stage-modes.test.ts +0 -38
- package/src/components/viewer/viewer-stage-modes.ts +0 -49
- package/src/components/viewer/viewer-stage-switcher.tsx +0 -97
- package/src/components/viewer/viewer-stage.test.tsx +0 -47
- package/src/components/viewer/viewer-stage.tsx +0 -221
- package/src/components/walkthrough-hud.tsx +0 -193
- package/src/hooks/use-mobile.ts +0 -19
- package/src/i18n/level-name.ts +0 -39
- package/src/i18n/scene-theme-name.ts +0 -16
- package/src/lib/below-grade.ts +0 -133
- package/src/lib/camera-pose.test.ts +0 -237
- package/src/lib/camera-pose.ts +0 -172
- package/src/lib/floorplan/floorplan-extension.test.ts +0 -42
- package/src/lib/floorplan/floorplan-readonly.test.ts +0 -47
- package/src/lib/floorplan/floorplan-readonly.ts +0 -95
- package/src/lib/floorplan/marks.test.ts +0 -213
- package/src/lib/floorplan/marks.ts +0 -238
- package/src/lib/measurements.ts +0 -8
- package/src/lib/node-display-label.ts +0 -37
- package/src/lib/room-assembly-overlay.test.ts +0 -275
- package/src/lib/room-assembly-overlay.ts +0 -265
- package/src/lib/room-selection.ts +0 -417
- package/src/lib/scene-bounds.test.ts +0 -327
- package/src/lib/scene-bounds.ts +0 -233
- package/src/lib/typing-target.ts +0 -9
- package/src/lib/viewer-selection.ts +0 -595
- package/src/lib/zone-content.ts +0 -133
- package/src/store/camera-pose-store.test.ts +0 -29
- package/src/store/camera-pose-store.ts +0 -27
- package/src/store/navigation-sync-pose-store.test.ts +0 -34
- package/src/store/navigation-sync-pose-store.ts +0 -27
- package/src/store/use-audio.test.ts +0 -146
- package/src/store/use-audio.tsx +0 -169
- package/src/store/use-first-person-hud.ts +0 -40
- package/src/store/use-follow-pascal.test.ts +0 -62
- package/src/store/use-follow-pascal.ts +0 -53
|
@@ -2,7 +2,11 @@ import type {
|
|
|
2
2
|
AnyNode,
|
|
3
3
|
AnyNodeId,
|
|
4
4
|
ConstructionDrawingType,
|
|
5
|
+
FloorplanAnnotationRole,
|
|
5
6
|
FloorplanGeometry,
|
|
7
|
+
FloorplanMetricNotation,
|
|
8
|
+
FloorplanSchedule,
|
|
9
|
+
FloorplanWallDimensionFaces,
|
|
6
10
|
GeometryContext,
|
|
7
11
|
NodeDefinition,
|
|
8
12
|
SceneApi,
|
|
@@ -11,57 +15,8 @@ import type { ComponentType } from 'react'
|
|
|
11
15
|
import type { WallSelectionDimension } from '../room-push-dimensions'
|
|
12
16
|
|
|
13
17
|
export const FLOORPLAN_NODE_EXTENSION_KEY = 'pascal:editor/floorplan'
|
|
14
|
-
export const FLOORPLAN_GEOMETRY_METADATA_KEY = 'pascal:editor/floorplan'
|
|
15
|
-
export const FLOORPLAN_CONTEXT_EXTENSION_KEY = 'pascal:editor/floorplan'
|
|
16
18
|
|
|
17
|
-
export type FloorplanRenderPurpose = 'edit' | 'document'
|
|
18
|
-
export type FloorplanMetricNotation = 'meters' | 'millimeters'
|
|
19
19
|
export type FloorplanToolMode = 'default' | 'expert'
|
|
20
|
-
/**
|
|
21
|
-
* Display → Measure walls: which finished faces wall dimensions measure to —
|
|
22
|
-
* the interior faces (ID, the room sizes), the exterior faces (OD, the
|
|
23
|
-
* outside size) or both. Read by a selected wall's temporary dimensions in 2D
|
|
24
|
-
* and 3D and by the Expert plan's automatic dimension strings.
|
|
25
|
-
*/
|
|
26
|
-
export type FloorplanWallDimensionFaces = 'interior' | 'exterior' | 'both'
|
|
27
|
-
export const DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES: FloorplanWallDimensionFaces = 'both'
|
|
28
|
-
|
|
29
|
-
export function normalizeFloorplanWallDimensionFaces(value: unknown): FloorplanWallDimensionFaces {
|
|
30
|
-
return value === 'interior' || value === 'exterior'
|
|
31
|
-
? value
|
|
32
|
-
: DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES
|
|
33
|
-
}
|
|
34
|
-
export type FloorplanAnnotationRole =
|
|
35
|
-
| 'automatic-dimension'
|
|
36
|
-
| 'contextual-dimension'
|
|
37
|
-
| 'manual-dimension'
|
|
38
|
-
| 'measurement'
|
|
39
|
-
| 'opening-mark'
|
|
40
|
-
| 'structural-grid'
|
|
41
|
-
| 'column-center'
|
|
42
|
-
| 'room-label'
|
|
43
|
-
/** A room's finish / ceiling-height lines — detail under the name, off in the clean plan. */
|
|
44
|
-
| 'room-detail'
|
|
45
|
-
/** The roof plan proper: outline, ridges, hips, slope arrows. Off over a floor plan unless asked. */
|
|
46
|
-
| 'roof-plan'
|
|
47
|
-
| 'roof-pitch'
|
|
48
|
-
| 'stair-annotation'
|
|
49
|
-
|
|
50
|
-
export type FloorplanSchedule = {
|
|
51
|
-
id: string
|
|
52
|
-
title: string
|
|
53
|
-
columns: ReadonlyArray<{
|
|
54
|
-
key: string
|
|
55
|
-
label: string
|
|
56
|
-
weight?: number
|
|
57
|
-
}>
|
|
58
|
-
rows: ReadonlyArray<{
|
|
59
|
-
id: string
|
|
60
|
-
cells: Readonly<Record<string, string>>
|
|
61
|
-
}>
|
|
62
|
-
issues?: readonly string[]
|
|
63
|
-
}
|
|
64
|
-
|
|
65
20
|
export type FloorplanToolContext = {
|
|
66
21
|
sceneApi: SceneApi
|
|
67
22
|
activeLevelId: AnyNodeId | null
|
|
@@ -124,7 +79,6 @@ export type FloorplanNodeExtension<N extends AnyNode = AnyNode> = {
|
|
|
124
79
|
/** A drafted sheet's schedule: marks match the sheet's tags. */
|
|
125
80
|
drafting?: boolean
|
|
126
81
|
}) => FloorplanSchedule | null
|
|
127
|
-
linkedLevelIds?: (node: N) => readonly AnyNodeId[]
|
|
128
82
|
resolveForDrawing?: (args: {
|
|
129
83
|
node: N
|
|
130
84
|
nodes: Record<string, AnyNode>
|
|
@@ -132,38 +86,6 @@ export type FloorplanNodeExtension<N extends AnyNode = AnyNode> = {
|
|
|
132
86
|
}) => AnyNode | null
|
|
133
87
|
}
|
|
134
88
|
|
|
135
|
-
type FloorplanGeometryMetadata = {
|
|
136
|
-
annotationRole?: FloorplanAnnotationRole
|
|
137
|
-
annotationObstacle?: 'bounds' | 'outline'
|
|
138
|
-
renderPass?: 'overlay'
|
|
139
|
-
/**
|
|
140
|
-
* Annotation text only: the size to print at, in paper points, instead of
|
|
141
|
-
* the size its role implies. Lets a sheet set a room tag's name larger than
|
|
142
|
-
* its number without inventing a role per size.
|
|
143
|
-
*/
|
|
144
|
-
textSizePt?: number
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
type FloorplanContextExtension = {
|
|
148
|
-
automaticDimensions: boolean
|
|
149
|
-
purpose: FloorplanRenderPurpose
|
|
150
|
-
/**
|
|
151
|
-
* Sheet drafting (the Sheets plan viewports): kinds draw the permit-set
|
|
152
|
-
* convention — fixtures as labelled linework, furniture as light outlines,
|
|
153
|
-
* no raster sprites. Only `collectSheetGeometry` sets it; the editor and the
|
|
154
|
-
* read-only viewer never do, so their plans keep today's look.
|
|
155
|
-
*/
|
|
156
|
-
drafting: boolean
|
|
157
|
-
/**
|
|
158
|
-
* The editor canvas draws room labels as screen pills over the plan
|
|
159
|
-
* (`RoomLabels2D`), so zones skip their drawn tags and wash there. Exports,
|
|
160
|
-
* sheets and the read-only viewer keep the drawn tags.
|
|
161
|
-
*/
|
|
162
|
-
roomLabelOverlay: boolean
|
|
163
|
-
metricNotation: FloorplanMetricNotation
|
|
164
|
-
wallDimensionFaces: FloorplanWallDimensionFaces
|
|
165
|
-
}
|
|
166
|
-
|
|
167
89
|
export function getFloorplanNodeExtension(
|
|
168
90
|
definition: NodeDefinition<any> | undefined,
|
|
169
91
|
): FloorplanNodeExtension | undefined {
|
|
@@ -171,78 +93,3 @@ export function getFloorplanNodeExtension(
|
|
|
171
93
|
| FloorplanNodeExtension
|
|
172
94
|
| undefined
|
|
173
95
|
}
|
|
174
|
-
|
|
175
|
-
export function floorplanGeometryMetadata(
|
|
176
|
-
values: FloorplanGeometryMetadata,
|
|
177
|
-
): Readonly<Record<string, unknown>> {
|
|
178
|
-
return { [FLOORPLAN_GEOMETRY_METADATA_KEY]: values }
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export function withFloorplanGeometryMetadata<T extends FloorplanGeometry | null>(
|
|
182
|
-
geometry: T,
|
|
183
|
-
values: FloorplanGeometryMetadata,
|
|
184
|
-
): T {
|
|
185
|
-
if (!geometry) return geometry
|
|
186
|
-
const existing = readFloorplanGeometryMetadata(geometry)
|
|
187
|
-
return {
|
|
188
|
-
...geometry,
|
|
189
|
-
metadata: floorplanGeometryMetadata({ ...existing, ...values }),
|
|
190
|
-
} as T
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function readFloorplanGeometryMetadata(geometry: unknown): FloorplanGeometryMetadata {
|
|
194
|
-
const metadata = (geometry as { metadata?: Readonly<Record<string, unknown>> } | null)?.metadata
|
|
195
|
-
const value = metadata?.[FLOORPLAN_GEOMETRY_METADATA_KEY]
|
|
196
|
-
return value && typeof value === 'object' && !Array.isArray(value)
|
|
197
|
-
? (value as FloorplanGeometryMetadata)
|
|
198
|
-
: {}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export function createFloorplanContextExtensions(
|
|
202
|
-
values: Partial<FloorplanContextExtension>,
|
|
203
|
-
): Readonly<Record<string, unknown>> {
|
|
204
|
-
return {
|
|
205
|
-
[FLOORPLAN_CONTEXT_EXTENSION_KEY]: {
|
|
206
|
-
automaticDimensions: values.automaticDimensions !== false,
|
|
207
|
-
purpose: values.purpose === 'document' ? 'document' : 'edit',
|
|
208
|
-
drafting: values.drafting === true,
|
|
209
|
-
roomLabelOverlay: values.roomLabelOverlay === true,
|
|
210
|
-
metricNotation: values.metricNotation === 'millimeters' ? 'millimeters' : 'meters',
|
|
211
|
-
wallDimensionFaces: normalizeFloorplanWallDimensionFaces(values.wallDimensionFaces),
|
|
212
|
-
} satisfies FloorplanContextExtension,
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export function readFloorplanContext(ctx: GeometryContext): FloorplanContextExtension {
|
|
217
|
-
const value = ctx.extensions?.[FLOORPLAN_CONTEXT_EXTENSION_KEY]
|
|
218
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
219
|
-
const extension = value as Partial<FloorplanContextExtension>
|
|
220
|
-
return {
|
|
221
|
-
automaticDimensions: extension.automaticDimensions !== false,
|
|
222
|
-
purpose: extension.purpose === 'document' ? 'document' : 'edit',
|
|
223
|
-
drafting: extension.drafting === true,
|
|
224
|
-
roomLabelOverlay: extension.roomLabelOverlay === true,
|
|
225
|
-
metricNotation: extension.metricNotation === 'millimeters' ? 'millimeters' : 'meters',
|
|
226
|
-
wallDimensionFaces: normalizeFloorplanWallDimensionFaces(extension.wallDimensionFaces),
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return {
|
|
230
|
-
automaticDimensions: true,
|
|
231
|
-
purpose: 'edit',
|
|
232
|
-
drafting: false,
|
|
233
|
-
roomLabelOverlay: false,
|
|
234
|
-
metricNotation: 'meters',
|
|
235
|
-
wallDimensionFaces: DEFAULT_FLOORPLAN_WALL_DIMENSION_FACES,
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
export function readFloorplanMetricNotationOverride(
|
|
240
|
-
ctx: GeometryContext,
|
|
241
|
-
): FloorplanMetricNotation | undefined {
|
|
242
|
-
const value = ctx.extensions?.[FLOORPLAN_CONTEXT_EXTENSION_KEY]
|
|
243
|
-
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined
|
|
244
|
-
const metricNotation = (value as { metricNotation?: unknown }).metricNotation
|
|
245
|
-
return metricNotation === 'meters' || metricNotation === 'millimeters'
|
|
246
|
-
? metricNotation
|
|
247
|
-
: undefined
|
|
248
|
-
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { FloorplanAnnotationRole } from '@pascal-app/core'
|
|
1
2
|
import {
|
|
2
3
|
type FloorplanAnnotationVisibility,
|
|
3
4
|
revealFloorplanAnnotationRole,
|
|
4
5
|
} from './annotation-visibility'
|
|
5
|
-
import type {
|
|
6
|
+
import type { FloorplanToolMode } from './floorplan-extension'
|
|
6
7
|
|
|
7
8
|
export const FLOORPLAN_MODES = ['default', 'expert'] as const
|
|
8
9
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test'
|
|
2
2
|
import type { FloorplanGeometry } from '@pascal-app/core'
|
|
3
|
+
import { floorplanGeometryMetadata } from '@pascal-app/core'
|
|
3
4
|
import PDFDocument from 'pdfkit'
|
|
4
|
-
import { floorplanGeometryMetadata } from './floorplan-extension'
|
|
5
5
|
import { FloorplanPdfDocument, loadFloorplanPdfFonts } from './floorplan-pdfkit-document'
|
|
6
6
|
import { renderFloorplanGeometryToPdfKit } from './floorplan-pdfkit-renderer'
|
|
7
7
|
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type FloorplanGeometry,
|
|
3
|
+
type FloorplanPoint,
|
|
4
|
+
loadAssetUrl,
|
|
5
|
+
readFloorplanGeometryMetadata,
|
|
6
|
+
} from '@pascal-app/core'
|
|
2
7
|
import {
|
|
3
8
|
type ArchitecturalDimensionLayout,
|
|
4
9
|
computeArchitecturalDimensionLayout,
|
|
5
|
-
} from '../../components/editor-2d/renderers/floorplan-dimension-renderer'
|
|
6
|
-
import {
|
|
7
10
|
documentCircleGeometryAttrs,
|
|
8
11
|
documentRectGeometryAttrs,
|
|
9
12
|
resolveDocumentAnnotationGroupChildren,
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
resolveFloorplanLabelAngle,
|
|
14
|
+
} from '@pascal-app/viewer/ui'
|
|
12
15
|
import type { FloorplanExportBounds } from './floorplan-export'
|
|
13
|
-
import { readFloorplanGeometryMetadata } from './floorplan-extension'
|
|
14
16
|
import type { FloorplanPdfBaseline, FloorplanPdfDocument } from './floorplan-pdfkit-document'
|
|
15
17
|
|
|
16
18
|
const DIMENSION_LINE_WIDTH_PT = 0.5
|
|
@@ -6,12 +6,11 @@ import {
|
|
|
6
6
|
loadPlugin,
|
|
7
7
|
nodeRegistry,
|
|
8
8
|
} from '@pascal-app/core'
|
|
9
|
+
import { FloorplanPreview } from '@pascal-app/viewer/ui'
|
|
9
10
|
import { renderToStaticMarkup } from 'react-dom/server'
|
|
10
11
|
import { z } from 'zod'
|
|
11
|
-
import { FloorplanPreview } from '../../components/viewer/floorplan-preview'
|
|
12
12
|
import { DEFAULT_FLOORPLAN_ANNOTATION_VISIBILITY } from './annotation-visibility'
|
|
13
13
|
import { collectFloorplanGeometry, floorplanExportInstalledPlugins } from './floorplan-export'
|
|
14
|
-
import { FLOORPLAN_NODE_EXTENSION_KEY } from './floorplan-extension'
|
|
15
14
|
|
|
16
15
|
// Plugin API v1, no-install case: a plugin kind's floor-plan output appears in
|
|
17
16
|
// the read-only preview and the PDF export only while the project has the
|
|
@@ -31,7 +30,7 @@ const bed = {
|
|
|
31
30
|
visible: true,
|
|
32
31
|
metadata: {},
|
|
33
32
|
} as unknown as AnyNode
|
|
34
|
-
// Lives on the upper level but draws on this one through `
|
|
33
|
+
// Lives on the upper level but draws on this one through `floorplanLinkedLevelIds`.
|
|
35
34
|
const upper = LevelNode.parse({ id: 'level_plugin_upper', level: 1, children: ['fxshaft_plan'] })
|
|
36
35
|
const shaft = {
|
|
37
36
|
object: 'node',
|
|
@@ -70,7 +69,7 @@ beforeEach(async () => {
|
|
|
70
69
|
category: 'structure',
|
|
71
70
|
defaults: () => ({}),
|
|
72
71
|
capabilities: {},
|
|
73
|
-
|
|
72
|
+
floorplanLinkedLevelIds: () => [level.id],
|
|
74
73
|
floorplan: () => ({ kind: 'rect', x: 3, y: 0, width: 1, height: 1 }),
|
|
75
74
|
} as unknown as AnyNodeDefinition,
|
|
76
75
|
],
|
|
@@ -1,68 +1,5 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import {
|
|
3
|
-
import type { FloorplanLineSegment, FloorplanSelectionBounds } from './types'
|
|
4
|
-
|
|
5
|
-
// Baseline rotation (deg) that orients the plan-local scene "north up" on
|
|
6
|
-
// screen. The on-screen floor-plan scene `<g>` is rotated by
|
|
7
|
-
// `FLOORPLAN_VIEW_ROTATION_DEG + userRotation - buildingRotation`; PDF export
|
|
8
|
-
// uses the same user rotation so its orientation matches the live plan.
|
|
9
|
-
//
|
|
10
|
-
// North is world −Z: with a 0 baseline a rotation-0 reference image (top =
|
|
11
|
-
// −Z) reads upright in the north-aligned view, and "align north" maps to a
|
|
12
|
-
// 3D camera azimuth of 0. The old 90° baseline made north world −X, so
|
|
13
|
-
// north-up floorplan scans displayed sideways whenever the compass claimed
|
|
14
|
-
// the view was aligned.
|
|
15
|
-
export const FLOORPLAN_VIEW_ROTATION_DEG = 0
|
|
16
|
-
|
|
17
|
-
export function clampPlanValue(value: number, min: number, max: number) {
|
|
18
|
-
return Math.min(Math.max(value, min), max)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function rotatePlanVector(x: number, y: number, rotation: number): [number, number] {
|
|
22
|
-
const cos = Math.cos(rotation)
|
|
23
|
-
const sin = Math.sin(rotation)
|
|
24
|
-
return [x * cos + y * sin, -x * sin + y * cos]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Converts a world X/Z point into the floor-plan-local (building-local)
|
|
28
|
-
// frame used by the SVG scene `<g>` and every stored node position. The
|
|
29
|
-
// inverse of `floorplanLocalToWorldPoint`. Shared so the floor-plan panel
|
|
30
|
-
// and the 2D move overlay resolve the same frame — feeding a world-space
|
|
31
|
-
// `original` into a local-space cursor solver lands the drop off by the
|
|
32
|
-
// building's world X/Z (worse for an off-origin building).
|
|
33
|
-
export function worldToFloorplanLocalPoint(
|
|
34
|
-
worldX: number,
|
|
35
|
-
worldZ: number,
|
|
36
|
-
buildingPosition: readonly [number, number, number],
|
|
37
|
-
buildingRotationY: number,
|
|
38
|
-
): Point2D {
|
|
39
|
-
const dx = worldX - buildingPosition[0]
|
|
40
|
-
const dz = worldZ - buildingPosition[2]
|
|
41
|
-
const cos = Math.cos(buildingRotationY)
|
|
42
|
-
const sin = Math.sin(buildingRotationY)
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
x: dx * cos - dz * sin,
|
|
46
|
-
y: dx * sin + dz * cos,
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Inverse of `worldToFloorplanLocalPoint`: floor-plan-local X/Y → world X/Z.
|
|
51
|
-
export function floorplanLocalToWorldPoint(
|
|
52
|
-
point: Point2D | [number, number],
|
|
53
|
-
buildingPosition: readonly [number, number, number],
|
|
54
|
-
buildingRotationY: number,
|
|
55
|
-
): { x: number; z: number } {
|
|
56
|
-
const localX = Array.isArray(point) ? point[0] : point.x
|
|
57
|
-
const localY = Array.isArray(point) ? point[1] : point.y
|
|
58
|
-
const cos = Math.cos(buildingRotationY)
|
|
59
|
-
const sin = Math.sin(buildingRotationY)
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
x: buildingPosition[0] + localX * cos + localY * sin,
|
|
63
|
-
z: buildingPosition[2] - localX * sin + localY * cos,
|
|
64
|
-
}
|
|
65
|
-
}
|
|
1
|
+
import { clampPlanValue, type Point2D, rotatePlanVector } from '@pascal-app/core'
|
|
2
|
+
import type { FloorplanSelectionBounds } from './types'
|
|
66
3
|
|
|
67
4
|
export function getRotatedRectanglePolygon(
|
|
68
5
|
center: Point2D,
|
|
@@ -88,53 +25,6 @@ export function getRotatedRectanglePolygon(
|
|
|
88
25
|
})
|
|
89
26
|
}
|
|
90
27
|
|
|
91
|
-
export function interpolatePlanPoint(start: Point2D, end: Point2D, t: number): Point2D {
|
|
92
|
-
return {
|
|
93
|
-
x: start.x + (end.x - start.x) * t,
|
|
94
|
-
y: start.y + (end.y - start.y) * t,
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export function getPlanPointDistance(start: Point2D, end: Point2D): number {
|
|
99
|
-
return Math.hypot(end.x - start.x, end.y - start.y)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function movePlanPointTowards(start: Point2D, end: Point2D, distance: number): Point2D {
|
|
103
|
-
const totalDistance = getPlanPointDistance(start, end)
|
|
104
|
-
if (totalDistance <= Number.EPSILON || distance <= 0) {
|
|
105
|
-
return start
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
return interpolatePlanPoint(start, end, Math.min(1, distance / totalDistance))
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function getThickPlanLinePolygon(
|
|
112
|
-
line: FloorplanLineSegment,
|
|
113
|
-
thickness: number,
|
|
114
|
-
justification?: WallJustification,
|
|
115
|
-
): Point2D[] {
|
|
116
|
-
const dx = line.end.x - line.start.x
|
|
117
|
-
const dy = line.end.y - line.start.y
|
|
118
|
-
const length = Math.hypot(dx, dy)
|
|
119
|
-
|
|
120
|
-
if (length <= Number.EPSILON || thickness <= 0) {
|
|
121
|
-
return [line.start, line.end, line.end, line.start]
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const { a, b } = getWallFaceOffsets({ thickness, justification })
|
|
125
|
-
const normalX = (-dy / length) * a
|
|
126
|
-
const normalY = (dx / length) * a
|
|
127
|
-
|
|
128
|
-
const backX = (-dy / length) * -b
|
|
129
|
-
const backY = (dx / length) * -b
|
|
130
|
-
return [
|
|
131
|
-
{ x: line.start.x + normalX, y: line.start.y + normalY },
|
|
132
|
-
{ x: line.end.x + normalX, y: line.end.y + normalY },
|
|
133
|
-
{ x: line.end.x - backX, y: line.end.y - backY },
|
|
134
|
-
{ x: line.start.x - backX, y: line.start.y - backY },
|
|
135
|
-
]
|
|
136
|
-
}
|
|
137
|
-
|
|
138
28
|
export function getFloorplanSelectionBounds(
|
|
139
29
|
start: [number, number],
|
|
140
30
|
end: [number, number],
|
|
@@ -6,23 +6,14 @@ export {
|
|
|
6
6
|
type FloorplanAlignmentResult,
|
|
7
7
|
} from './apply-alignment'
|
|
8
8
|
export {
|
|
9
|
-
clampPlanValue,
|
|
10
9
|
doesPolygonIntersectSelectionBounds,
|
|
11
|
-
FLOORPLAN_VIEW_ROTATION_DEG,
|
|
12
|
-
floorplanLocalToWorldPoint,
|
|
13
10
|
getDistanceToWallSegment,
|
|
14
11
|
getFloorplanSelectionBounds,
|
|
15
|
-
getPlanPointDistance,
|
|
16
12
|
getRotatedRectanglePolygon,
|
|
17
|
-
getThickPlanLinePolygon,
|
|
18
|
-
interpolatePlanPoint,
|
|
19
13
|
isPointInsidePolygon,
|
|
20
14
|
isPointInsidePolygonWithHoles,
|
|
21
15
|
isPointInsideSelectionBounds,
|
|
22
|
-
movePlanPointTowards,
|
|
23
16
|
pointMatchesWallPlanPoint,
|
|
24
|
-
rotatePlanVector,
|
|
25
|
-
worldToFloorplanLocalPoint,
|
|
26
17
|
} from './geometry'
|
|
27
18
|
export {
|
|
28
19
|
buildFloorplanItemEntry,
|
|
@@ -6,9 +6,10 @@ import {
|
|
|
6
6
|
getWallLocalFaceZ,
|
|
7
7
|
type ItemNode,
|
|
8
8
|
type LevelNode,
|
|
9
|
+
rotatePlanVector,
|
|
9
10
|
useLiveTransforms,
|
|
10
11
|
} from '@pascal-app/core'
|
|
11
|
-
import { getRotatedRectanglePolygon
|
|
12
|
+
import { getRotatedRectanglePolygon } from './geometry'
|
|
12
13
|
import type { FloorplanItemEntry, FloorplanNodeTransform, LevelDescendantMap } from './types'
|
|
13
14
|
|
|
14
15
|
export function collectLevelDescendants(
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { AnyNode, AnyNodeId, DoorNode, WallNode, WindowNode, ZoneNode } from '@pascal-app/core'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
deriveZoneQuantityReport,
|
|
4
|
+
type FloorplanSchedule,
|
|
5
|
+
resolveHostedOpeningFrameDepth,
|
|
6
|
+
resolveMarkDetail,
|
|
7
|
+
} from '@pascal-app/core'
|
|
3
8
|
import { collectFloorplanSchedules } from './floorplan-export'
|
|
4
|
-
import type { FloorplanSchedule } from './floorplan-extension'
|
|
5
|
-
import { resolveMarkDetail } from './marks'
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Construction-document schedule DATA — WS3.
|
|
@@ -30,7 +30,11 @@ import type {
|
|
|
30
30
|
FloorplanGeometry,
|
|
31
31
|
LiveNodeOverrides,
|
|
32
32
|
} from '@pascal-app/core'
|
|
33
|
-
import {
|
|
33
|
+
import {
|
|
34
|
+
type FloorplanMetricNotation,
|
|
35
|
+
nodeRegistry,
|
|
36
|
+
resolveBuildingForLevel,
|
|
37
|
+
} from '@pascal-app/core'
|
|
34
38
|
import {
|
|
35
39
|
buildContext,
|
|
36
40
|
collectFloorplanLinkedLevelNodes,
|
|
@@ -52,14 +56,12 @@ import {
|
|
|
52
56
|
resolveFloorplanExportRotationDeg,
|
|
53
57
|
resolveFloorplanExportViewState,
|
|
54
58
|
} from './floorplan-export'
|
|
55
|
-
import type { FloorplanMetricNotation } from './floorplan-extension'
|
|
56
59
|
import { createFloorplanPdfDocument } from './floorplan-pdfkit-document'
|
|
57
60
|
import { renderFloorplanGeometryToPdfKit } from './floorplan-pdfkit-renderer'
|
|
58
61
|
|
|
59
62
|
/** PDF user-space units per inch. */
|
|
60
63
|
export const POINTS_PER_INCH = 72
|
|
61
64
|
|
|
62
|
-
export type { FloorplanSchedule } from './floorplan-extension'
|
|
63
65
|
/**
|
|
64
66
|
* The schedules the kinds on a level contribute
|
|
65
67
|
* (`def.extensions['pascal:editor/floorplan'].schedule`). Re-exported here so
|
|
@@ -316,3 +318,5 @@ async function drawPlate(
|
|
|
316
318
|
},
|
|
317
319
|
)
|
|
318
320
|
}
|
|
321
|
+
|
|
322
|
+
export type { FloorplanSchedule } from '@pascal-app/core'
|
|
@@ -15,7 +15,9 @@ import {
|
|
|
15
15
|
isOutdoorRoomType,
|
|
16
16
|
type LevelNode,
|
|
17
17
|
migrateSiteMetadata,
|
|
18
|
+
type RoofNode,
|
|
18
19
|
type RoofSegmentNode,
|
|
20
|
+
roofFaceShapes,
|
|
19
21
|
type SceneSnapshot,
|
|
20
22
|
type SiteNode,
|
|
21
23
|
siteFrame,
|
|
@@ -75,7 +77,8 @@ export function findLowestLevel(
|
|
|
75
77
|
/**
|
|
76
78
|
* The roof's outline on the lot — every roof segment's plan rectangle out to
|
|
77
79
|
* its deck's reach at its eaves and rakes, through the segment's, the roof's
|
|
78
|
-
* and the building's turns,
|
|
80
|
+
* and the building's turns, and every face of another kind (`capabilities.roofs`)
|
|
81
|
+
* by its own outline, unioned into the outer ring(s). Dashed on the site plan: what the eye sees
|
|
79
82
|
* from above is the roof, and the setback is measured to the wall under it.
|
|
80
83
|
*/
|
|
81
84
|
export function roofOutlineRings(
|
|
@@ -93,6 +96,9 @@ export function roofOutlineRings(
|
|
|
93
96
|
}
|
|
94
97
|
if (roofs.size === 0) return []
|
|
95
98
|
const rects: Pt[][] = []
|
|
99
|
+
for (const roof of roofs.values())
|
|
100
|
+
for (const face of roofFaceShapes(roof as RoofNode, scene.nodes))
|
|
101
|
+
rects.push(face.outline.map(([x, z]) => toSite(x, z)))
|
|
96
102
|
for (const node of Object.values(scene.nodes)) {
|
|
97
103
|
if (node.type !== 'roof-segment') continue
|
|
98
104
|
const roof = roofs.get(String((node as { parentId?: unknown }).parentId))
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
resumeSceneHistory,
|
|
8
8
|
useScene,
|
|
9
9
|
} from '@pascal-app/core'
|
|
10
|
+
import { FloorplanGeometryRenderer } from '@pascal-app/viewer/ui'
|
|
10
11
|
import { type PointerEvent as ReactPointerEvent, useCallback, useMemo, useRef } from 'react'
|
|
11
|
-
import { FloorplanGeometryRenderer } from '../../../components/editor-2d/renderers/floorplan-geometry-renderer'
|
|
12
12
|
import { clientToPlan } from '../plan-coords'
|
|
13
13
|
import { buildSitePlanDrawing } from './build-site-plan-drawing'
|
|
14
14
|
|
package/src/lib/glb-export.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
type ViewerPresentationContribution,
|
|
33
33
|
viewerPresentationRegistry,
|
|
34
34
|
} from '@pascal-app/viewer'
|
|
35
|
+
import { nodeDisplayLabel } from '@pascal-app/viewer/ui'
|
|
35
36
|
import type { Object3D } from 'three'
|
|
36
37
|
import * as THREE from 'three'
|
|
37
38
|
import {
|
|
@@ -42,7 +43,6 @@ import {
|
|
|
42
43
|
import { createExportTextureUtils, type ExportTextureUtils } from './export-texture-utils'
|
|
43
44
|
import { cloneExportUserData } from './export-user-data'
|
|
44
45
|
import { isIfcRolePart } from './ifc-parts'
|
|
45
|
-
import { nodeDisplayLabel } from './node-display-label'
|
|
46
46
|
import {
|
|
47
47
|
type CompressedTextureDecompressor,
|
|
48
48
|
decompressCanonicalNormalMaps,
|
|
@@ -309,7 +309,7 @@ export function resolveActivePaintMaterialFromSelection(params: {
|
|
|
309
309
|
) {
|
|
310
310
|
const roofNode = selectedNode as RoofNode
|
|
311
311
|
const fallbackSegment = (roofNode.children ?? [])
|
|
312
|
-
.map((id
|
|
312
|
+
.map((id) => nodes[id as AnyNodeId] as RoofSegmentNode | undefined)
|
|
313
313
|
.find(
|
|
314
314
|
(segment: RoofSegmentNode | undefined) =>
|
|
315
315
|
segment?.type === 'roof-segment' &&
|
|
@@ -17,11 +17,12 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
MEASUREMENT_ACTIVE_COLOR,
|
|
19
19
|
MEASUREMENT_DANGLING_COLOR,
|
|
20
|
+
MEASUREMENT_FLOORPLAN_COLOR,
|
|
20
21
|
MEASUREMENT_PERSISTENT_COLOR,
|
|
22
|
+
measurementFloorplanPresentationColor,
|
|
21
23
|
measurementPresentationColor,
|
|
22
24
|
} from '@pascal-app/viewer'
|
|
23
25
|
import { measurementHint, parseMeasurement } from '../index'
|
|
24
|
-
import { MEASUREMENT_FLOORPLAN_COLOR, measurementFloorplanPresentationColor } from './measurements'
|
|
25
26
|
|
|
26
27
|
describe('measurement presentation', () => {
|
|
27
28
|
test('uses black at rest, indigo while active, and red for dangling references', () => {
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
type ZoneNode,
|
|
16
16
|
} from '@pascal-app/core'
|
|
17
17
|
import { useViewer } from '@pascal-app/viewer'
|
|
18
|
+
import { RoomSelectionIndex, resolveRoomHit } from '@pascal-app/viewer/ui'
|
|
18
19
|
import { deleteConfirmationContent } from '../components/editor/delete-confirmation-dialog'
|
|
19
20
|
import { resolveFloorRegionRoom } from '../components/editor/floor-region-controls'
|
|
20
21
|
import { MEZZANINE_GESTURE_HINTS, mezzanineGesture } from '../components/ui/helpers/helper-manager'
|
|
@@ -23,7 +24,6 @@ import {
|
|
|
23
24
|
mezzanineElevationBounds,
|
|
24
25
|
ROOM_ELEVATION_DRAG_LABEL,
|
|
25
26
|
} from './room-handle-drag'
|
|
26
|
-
import { RoomSelectionIndex, resolveRoomHit } from './room-selection'
|
|
27
27
|
import { applyRoomPlan } from './room-structure-commands'
|
|
28
28
|
import { ROOM_MOVE_DRAG_LABEL } from './room-transform-session'
|
|
29
29
|
import { zoneAtLevelPoint } from './units'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { isTypingTarget } from '@pascal-app/viewer'
|
|
1
2
|
import { create } from 'zustand'
|
|
2
3
|
import type { ActivePaintMaterial } from './material-paint'
|
|
3
|
-
import { isTypingTarget } from './typing-target'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* What a paint click does: paint the whole surface under it, draw part of a
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from '@pascal-app/core'
|
|
19
19
|
import { sceneViewBounds, sceneViewPose } from '@pascal-app/core/agent-operations'
|
|
20
20
|
import { retractNodes, useViewer } from '@pascal-app/viewer'
|
|
21
|
+
import { cameraPoseStore, useFollowPascal } from '@pascal-app/viewer/ui'
|
|
21
22
|
import { type Object3D, Vector2, Vector3 } from 'three'
|
|
22
23
|
import {
|
|
23
24
|
resolveRoofSegmentSelectionTarget,
|
|
@@ -25,9 +26,7 @@ import {
|
|
|
25
26
|
} from '../../components/editor/selection-manager'
|
|
26
27
|
import { getEditorThreeContext } from '../../components/editor/three-context-bridge'
|
|
27
28
|
import { resolveEditorRoomHit } from '../../hooks/use-selected-room'
|
|
28
|
-
import { cameraPoseStore } from '../../store/camera-pose-store'
|
|
29
29
|
import useEditor, { getActiveContinuationContext } from '../../store/use-editor'
|
|
30
|
-
import useFollowPascal from '../../store/use-follow-pascal'
|
|
31
30
|
import useInteractionScope from '../../store/use-interaction-scope'
|
|
32
31
|
import {
|
|
33
32
|
type BubbleTarget,
|