@pascal-app/editor 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -5
- package/src/components/editor/bottom-sheet.tsx +149 -0
- package/src/components/editor/custom-camera-controls.tsx +75 -7
- package/src/components/editor/editor-layout-mobile.tsx +264 -0
- package/src/components/editor/editor-layout-v2.tsx +20 -0
- package/src/components/editor/first-person/build-collider-world.ts +365 -0
- package/src/components/editor/first-person/bvh-ecctrl.tsx +795 -0
- package/src/components/editor/first-person-controls.tsx +496 -143
- package/src/components/editor/floating-action-menu.tsx +32 -55
- package/src/components/editor/floorplan-background-selection.ts +113 -0
- package/src/components/editor/floorplan-panel.tsx +9855 -3298
- package/src/components/editor/index.tsx +269 -21
- package/src/components/editor/selection-manager.tsx +575 -13
- package/src/components/editor/thumbnail-generator.tsx +38 -7
- package/src/components/editor/use-floorplan-background-placement.ts +257 -0
- package/src/components/editor/use-floorplan-hit-testing.ts +171 -0
- package/src/components/editor/use-floorplan-scene-data.ts +189 -0
- package/src/components/editor/wall-measurement-label.tsx +267 -36
- package/src/components/editor-2d/floorplan-action-menu-layer.tsx +95 -0
- package/src/components/editor-2d/floorplan-cursor-indicator-overlay.tsx +160 -0
- package/src/components/editor-2d/floorplan-hotkey-handlers.tsx +92 -0
- package/src/components/editor-2d/renderers/floorplan-draft-layer.tsx +119 -0
- package/src/components/editor-2d/renderers/floorplan-marquee-layer.tsx +58 -0
- package/src/components/editor-2d/renderers/floorplan-measurements-layer.tsx +197 -0
- package/src/components/editor-2d/renderers/floorplan-roof-layer.tsx +113 -0
- package/src/components/editor-2d/renderers/floorplan-stair-layer.tsx +474 -0
- package/src/components/editor-2d/svg-paths.ts +119 -0
- package/src/components/tools/ceiling/ceiling-boundary-editor.tsx +1 -0
- package/src/components/tools/ceiling/ceiling-hole-editor.tsx +1 -0
- package/src/components/tools/ceiling/ceiling-tool.tsx +5 -5
- package/src/components/tools/column/column-tool.tsx +97 -0
- package/src/components/tools/column/move-column-tool.tsx +105 -0
- package/src/components/tools/door/door-tool.tsx +7 -0
- package/src/components/tools/door/move-door-tool.tsx +28 -8
- package/src/components/tools/fence/fence-drafting.ts +10 -3
- package/src/components/tools/fence/fence-tool.tsx +159 -3
- package/src/components/tools/fence/move-fence-endpoint-tool.tsx +129 -18
- package/src/components/tools/fence/move-fence-tool.tsx +101 -34
- package/src/components/tools/item/move-tool.tsx +10 -1
- package/src/components/tools/item/placement-math.ts +30 -1
- package/src/components/tools/item/placement-strategies.ts +109 -31
- package/src/components/tools/item/placement-types.ts +7 -0
- package/src/components/tools/item/use-draft-node.ts +2 -0
- package/src/components/tools/item/use-placement-coordinator.tsx +660 -52
- package/src/components/tools/roof/move-roof-tool.tsx +22 -15
- package/src/components/tools/shared/polygon-editor.tsx +153 -28
- package/src/components/tools/shared/segment-angle.ts +156 -0
- package/src/components/tools/slab/slab-boundary-editor.tsx +1 -0
- package/src/components/tools/slab/slab-hole-editor.tsx +1 -0
- package/src/components/tools/spawn/move-spawn-tool.tsx +101 -0
- package/src/components/tools/spawn/spawn-tool.tsx +130 -0
- package/src/components/tools/tool-manager.tsx +18 -3
- package/src/components/tools/wall/move-wall-endpoint-tool.tsx +121 -20
- package/src/components/tools/wall/wall-drafting.ts +18 -9
- package/src/components/tools/wall/wall-tool.tsx +134 -2
- package/src/components/tools/window/move-window-tool.tsx +18 -0
- package/src/components/tools/window/window-tool.tsx +5 -0
- package/src/components/ui/action-menu/camera-actions.tsx +37 -33
- package/src/components/ui/action-menu/control-modes.tsx +28 -1
- package/src/components/ui/action-menu/index.tsx +91 -1
- package/src/components/ui/action-menu/structure-tools.tsx +2 -0
- package/src/components/ui/action-menu/view-toggles.tsx +424 -35
- package/src/components/ui/command-palette/editor-commands.tsx +18 -1
- package/src/components/ui/controls/material-picker.tsx +152 -165
- package/src/components/ui/controls/slider-control.tsx +66 -18
- package/src/components/ui/floating-level-selector.tsx +286 -55
- package/src/components/ui/helpers/helper-manager.tsx +5 -0
- package/src/components/ui/item-catalog/catalog-items.tsx +1116 -1219
- package/src/components/ui/item-catalog/item-catalog.tsx +42 -175
- package/src/components/ui/level-duplicate-dialog.tsx +115 -0
- package/src/components/ui/panels/ceiling-panel.tsx +1 -25
- package/src/components/ui/panels/column-panel.tsx +715 -0
- package/src/components/ui/panels/door-panel.tsx +981 -289
- package/src/components/ui/panels/fence-panel.tsx +3 -45
- package/src/components/ui/panels/mobile-panel-sheet.tsx +108 -0
- package/src/components/ui/panels/mobile-selection-bar.tsx +100 -0
- package/src/components/ui/panels/node-display.ts +39 -0
- package/src/components/ui/panels/paint-panel.tsx +138 -0
- package/src/components/ui/panels/panel-manager.tsx +210 -1
- package/src/components/ui/panels/panel-wrapper.tsx +48 -39
- package/src/components/ui/panels/reference-panel.tsx +238 -5
- package/src/components/ui/panels/roof-panel.tsx +4 -105
- package/src/components/ui/panels/roof-segment-panel.tsx +0 -25
- package/src/components/ui/panels/slab-panel.tsx +4 -30
- package/src/components/ui/panels/spawn-panel.tsx +155 -0
- package/src/components/ui/panels/stair-panel.tsx +11 -117
- package/src/components/ui/panels/stair-segment-panel.tsx +0 -25
- package/src/components/ui/panels/wall-panel.tsx +1 -95
- package/src/components/ui/panels/window-panel.tsx +660 -139
- package/src/components/ui/sidebar/mobile-tab-bar.tsx +46 -0
- package/src/components/ui/sidebar/panels/settings-panel/keyboard-shortcuts-dialog.tsx +2 -2
- package/src/components/ui/sidebar/panels/site-panel/building-tree-node.tsx +2 -2
- package/src/components/ui/sidebar/panels/site-panel/column-tree-node.tsx +77 -0
- package/src/components/ui/sidebar/panels/site-panel/index.tsx +109 -24
- package/src/components/ui/sidebar/panels/site-panel/level-tree-node.tsx +2 -2
- package/src/components/ui/sidebar/panels/site-panel/spawn-tree-node.tsx +82 -0
- package/src/components/ui/sidebar/panels/site-panel/tree-node.tsx +9 -3
- package/src/components/ui/sidebar/panels/site-panel/zone-tree-node.tsx +8 -5
- package/src/components/ui/sidebar/tab-bar.tsx +3 -0
- package/src/components/ui/viewer-toolbar.tsx +42 -1
- package/src/hooks/use-auto-frame.ts +45 -0
- package/src/hooks/use-keyboard.ts +64 -7
- package/src/hooks/use-mobile.ts +12 -12
- package/src/lib/door-interaction.ts +88 -0
- package/src/lib/floorplan/geometry.ts +263 -0
- package/src/lib/floorplan/index.ts +38 -0
- package/src/lib/floorplan/items.ts +179 -0
- package/src/lib/floorplan/selection-tool.ts +231 -0
- package/src/lib/floorplan/stairs.ts +478 -0
- package/src/lib/floorplan/types.ts +57 -0
- package/src/lib/floorplan/walls.ts +23 -0
- package/src/lib/guide-events.ts +10 -0
- package/src/lib/level-duplication.test.ts +72 -0
- package/src/lib/level-duplication.ts +153 -0
- package/src/lib/local-guide-image.ts +42 -0
- package/src/lib/material-paint.ts +284 -0
- package/src/lib/roof-duplication.ts +214 -0
- package/src/lib/scene-bounds.test.ts +183 -0
- package/src/lib/scene-bounds.ts +169 -0
- package/src/lib/stair-duplication.ts +126 -0
- package/src/lib/window-interaction.ts +86 -0
- package/src/store/use-editor.tsx +164 -8
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
type AnyNode,
|
|
5
5
|
type AnyNodeId,
|
|
6
6
|
type AttachmentSide,
|
|
7
|
-
type MaterialSchema,
|
|
8
7
|
type StairSegmentNode,
|
|
9
8
|
StairSegmentNode as StairSegmentNodeSchema,
|
|
10
9
|
type StairSegmentType,
|
|
@@ -16,7 +15,6 @@ import { useCallback } from 'react'
|
|
|
16
15
|
import { sfxEmitter } from '../../../lib/sfx-bus'
|
|
17
16
|
import useEditor from '../../../store/use-editor'
|
|
18
17
|
import { ActionButton, ActionGroup } from '../controls/action-button'
|
|
19
|
-
import { MaterialPicker } from '../controls/material-picker'
|
|
20
18
|
import { PanelSection } from '../controls/panel-section'
|
|
21
19
|
import { SegmentedControl } from '../controls/segmented-control'
|
|
22
20
|
import { SliderControl } from '../controls/slider-control'
|
|
@@ -61,20 +59,6 @@ export function StairSegmentPanel() {
|
|
|
61
59
|
[selectedId, updateNode],
|
|
62
60
|
)
|
|
63
61
|
|
|
64
|
-
const handleMaterialChange = useCallback(
|
|
65
|
-
(material: MaterialSchema) => {
|
|
66
|
-
handleUpdate({ material, materialPreset: undefined })
|
|
67
|
-
},
|
|
68
|
-
[handleUpdate],
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
const handleMaterialPresetChange = useCallback(
|
|
72
|
-
(materialPreset: string) => {
|
|
73
|
-
handleUpdate({ materialPreset, material: undefined })
|
|
74
|
-
},
|
|
75
|
-
[handleUpdate],
|
|
76
|
-
)
|
|
77
|
-
|
|
78
62
|
const handleClose = useCallback(() => {
|
|
79
63
|
setSelection({ selectedIds: [] })
|
|
80
64
|
}, [setSelection])
|
|
@@ -336,15 +320,6 @@ export function StairSegmentPanel() {
|
|
|
336
320
|
/>
|
|
337
321
|
</ActionGroup>
|
|
338
322
|
</PanelSection>
|
|
339
|
-
<PanelSection title="Material">
|
|
340
|
-
<MaterialPicker
|
|
341
|
-
nodeType="stair-segment"
|
|
342
|
-
onChange={handleMaterialChange}
|
|
343
|
-
onSelectMaterialPreset={handleMaterialPresetChange}
|
|
344
|
-
selectedMaterialPreset={node.materialPreset}
|
|
345
|
-
value={node.material}
|
|
346
|
-
/>
|
|
347
|
-
</PanelSection>
|
|
348
323
|
</PanelWrapper>
|
|
349
324
|
)
|
|
350
325
|
}
|
|
@@ -3,61 +3,29 @@
|
|
|
3
3
|
import {
|
|
4
4
|
type AnyNode,
|
|
5
5
|
type AnyNodeId,
|
|
6
|
-
getEffectiveWallSurfaceMaterial,
|
|
7
6
|
getClampedWallCurveOffset,
|
|
8
7
|
getMaxWallCurveOffset,
|
|
9
8
|
getWallCurveLength,
|
|
10
|
-
getWallSurfaceMaterialSignature,
|
|
11
9
|
normalizeWallCurveOffset,
|
|
12
|
-
type MaterialSchema,
|
|
13
10
|
useScene,
|
|
14
|
-
type WallSurfaceSide,
|
|
15
11
|
type WallNode,
|
|
16
12
|
} from '@pascal-app/core'
|
|
17
13
|
import { useViewer } from '@pascal-app/viewer'
|
|
18
14
|
import { Move, Spline } from 'lucide-react'
|
|
19
|
-
import { useCallback
|
|
15
|
+
import { useCallback } from 'react'
|
|
20
16
|
import { sfxEmitter } from '../../../lib/sfx-bus'
|
|
21
17
|
import useEditor from '../../../store/use-editor'
|
|
22
18
|
import { ActionButton, ActionGroup } from '../controls/action-button'
|
|
23
|
-
import { MaterialPicker } from '../controls/material-picker'
|
|
24
19
|
import { PanelSection } from '../controls/panel-section'
|
|
25
20
|
import { SliderControl } from '../controls/slider-control'
|
|
26
21
|
import { PanelWrapper } from './panel-wrapper'
|
|
27
22
|
|
|
28
|
-
function buildWallSurfaceMaterialPatch(
|
|
29
|
-
node: WallNode,
|
|
30
|
-
targetSide: WallSurfaceSide | null,
|
|
31
|
-
material: MaterialSchema | undefined,
|
|
32
|
-
materialPreset: string | undefined,
|
|
33
|
-
): Partial<WallNode> {
|
|
34
|
-
const nextSurfaceMaterial = { material, materialPreset }
|
|
35
|
-
const nextInterior =
|
|
36
|
-
targetSide === null || targetSide === 'interior'
|
|
37
|
-
? nextSurfaceMaterial
|
|
38
|
-
: getEffectiveWallSurfaceMaterial(node, 'interior')
|
|
39
|
-
const nextExterior =
|
|
40
|
-
targetSide === null || targetSide === 'exterior'
|
|
41
|
-
? nextSurfaceMaterial
|
|
42
|
-
: getEffectiveWallSurfaceMaterial(node, 'exterior')
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
interiorMaterial: nextInterior.material,
|
|
46
|
-
interiorMaterialPreset: nextInterior.materialPreset,
|
|
47
|
-
exteriorMaterial: nextExterior.material,
|
|
48
|
-
exteriorMaterialPreset: nextExterior.materialPreset,
|
|
49
|
-
material: undefined,
|
|
50
|
-
materialPreset: undefined,
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
23
|
export function WallPanel() {
|
|
55
24
|
const selectedId = useViewer((s) => s.selection.selectedIds[0])
|
|
56
25
|
const setSelection = useViewer((s) => s.setSelection)
|
|
57
26
|
const updateNode = useScene((s) => s.updateNode)
|
|
58
27
|
const setMovingNode = useEditor((s) => s.setMovingNode)
|
|
59
28
|
const setCurvingWall = useEditor((s) => s.setCurvingWall)
|
|
60
|
-
const selectedMaterialTarget = useEditor((s) => s.selectedMaterialTarget)
|
|
61
29
|
|
|
62
30
|
const node = useScene((s) =>
|
|
63
31
|
selectedId ? (s.nodes[selectedId as AnyNode['id']] as WallNode | undefined) : undefined,
|
|
@@ -88,35 +56,6 @@ export function WallPanel() {
|
|
|
88
56
|
[selectedId, updateNode],
|
|
89
57
|
)
|
|
90
58
|
|
|
91
|
-
const effectiveInteriorMaterial = useMemo(
|
|
92
|
-
() => (node ? getEffectiveWallSurfaceMaterial(node, 'interior') : {}),
|
|
93
|
-
[node],
|
|
94
|
-
)
|
|
95
|
-
const effectiveExteriorMaterial = useMemo(
|
|
96
|
-
() => (node ? getEffectiveWallSurfaceMaterial(node, 'exterior') : {}),
|
|
97
|
-
[node],
|
|
98
|
-
)
|
|
99
|
-
const surfaceMaterialsMatch = useMemo(
|
|
100
|
-
() =>
|
|
101
|
-
getWallSurfaceMaterialSignature(effectiveInteriorMaterial) ===
|
|
102
|
-
getWallSurfaceMaterialSignature(effectiveExteriorMaterial),
|
|
103
|
-
[effectiveExteriorMaterial, effectiveInteriorMaterial],
|
|
104
|
-
)
|
|
105
|
-
const materialTargetSide =
|
|
106
|
-
selectedMaterialTarget &&
|
|
107
|
-
selectedMaterialTarget.nodeId === node?.id &&
|
|
108
|
-
(selectedMaterialTarget.role === 'interior' || selectedMaterialTarget.role === 'exterior')
|
|
109
|
-
? selectedMaterialTarget.role
|
|
110
|
-
: null
|
|
111
|
-
const materialPickerValue =
|
|
112
|
-
materialTargetSide === 'interior'
|
|
113
|
-
? effectiveInteriorMaterial
|
|
114
|
-
: materialTargetSide === 'exterior'
|
|
115
|
-
? effectiveExteriorMaterial
|
|
116
|
-
: surfaceMaterialsMatch
|
|
117
|
-
? effectiveInteriorMaterial
|
|
118
|
-
: {}
|
|
119
|
-
|
|
120
59
|
const handleUpdateLength = useCallback(
|
|
121
60
|
(newLength: number) => {
|
|
122
61
|
if (!node || newLength <= 0) return
|
|
@@ -140,22 +79,6 @@ export function WallPanel() {
|
|
|
140
79
|
[node, handleUpdate],
|
|
141
80
|
)
|
|
142
81
|
|
|
143
|
-
const handleMaterialPresetChange = useCallback(
|
|
144
|
-
(materialPreset: string) => {
|
|
145
|
-
if (!node || !materialTargetSide) return
|
|
146
|
-
handleUpdate(buildWallSurfaceMaterialPatch(node, materialTargetSide, undefined, materialPreset))
|
|
147
|
-
},
|
|
148
|
-
[handleUpdate, materialTargetSide, node],
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
const handleCustomMaterialChange = useCallback(
|
|
152
|
-
(material: MaterialSchema) => {
|
|
153
|
-
if (!node || !materialTargetSide) return
|
|
154
|
-
handleUpdate(buildWallSurfaceMaterialPatch(node, materialTargetSide, material, undefined))
|
|
155
|
-
},
|
|
156
|
-
[handleUpdate, materialTargetSide, node],
|
|
157
|
-
)
|
|
158
|
-
|
|
159
82
|
const handleClose = useCallback(() => {
|
|
160
83
|
setSelection({ selectedIds: [] })
|
|
161
84
|
}, [setSelection])
|
|
@@ -237,23 +160,6 @@ export function WallPanel() {
|
|
|
237
160
|
)}
|
|
238
161
|
</PanelSection>
|
|
239
162
|
|
|
240
|
-
<PanelSection title="Material">
|
|
241
|
-
{!materialTargetSide ? (
|
|
242
|
-
<div className="mb-3 rounded-lg border border-border/50 bg-[#2C2C2E] px-3 py-2 text-[11px] text-muted-foreground">
|
|
243
|
-
Click the wall face you want to edit. Materials now apply to one side at a time.
|
|
244
|
-
</div>
|
|
245
|
-
) : null}
|
|
246
|
-
<MaterialPicker
|
|
247
|
-
disabled={!materialTargetSide}
|
|
248
|
-
hideSideControl
|
|
249
|
-
nodeType="wall"
|
|
250
|
-
onChange={handleCustomMaterialChange}
|
|
251
|
-
onSelectMaterialPreset={handleMaterialPresetChange}
|
|
252
|
-
selectedMaterialPreset={materialPickerValue.materialPreset}
|
|
253
|
-
value={materialPickerValue.material}
|
|
254
|
-
/>
|
|
255
|
-
</PanelSection>
|
|
256
|
-
|
|
257
163
|
<PanelSection title="Actions">
|
|
258
164
|
<ActionGroup>
|
|
259
165
|
<ActionButton icon={<Move className="h-3.5 w-3.5" />} label="Move" onClick={handleMove} />
|