@ifc-lite/viewer 1.16.0 → 1.17.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/.turbo/turbo-build.log +46 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +15 -0
- package/dist/assets/{Arrow.dom--gdrQd-q.js → Arrow.dom-CcoDLP6E.js} +1 -1
- package/dist/assets/{basketViewActivator-CI3y6VYQ.js → basketViewActivator-FtbS__bG.js} +1 -1
- package/dist/assets/{browser-vWDubxDI.js → browser-CXd3z0DO.js} +1 -1
- package/dist/assets/ifc-lite-TI3u_Zyw.js +7 -0
- package/dist/assets/ifc-lite_bg-DeZrXTKQ.wasm +0 -0
- package/dist/assets/index-Ba4eoTe7.css +1 -0
- package/dist/assets/{index-BImINgzG.js → index-D99fzcwI.js} +28962 -26947
- package/dist/assets/{index-RXIK18da.js → index-DqNiuQep.js} +4 -4
- package/dist/assets/{native-bridge-4rLidc3f.js → native-bridge-DjDj2M6p.js} +1 -1
- package/dist/assets/{wasm-bridge-BkfXfw8O.js → wasm-bridge-CDTF4ZQc.js} +1 -1
- package/dist/assets/workerHelpers-G7llXNMi.js +36 -0
- package/dist/index.html +2 -2
- package/package.json +15 -14
- package/src/components/viewer/BCFPanel.tsx +12 -0
- package/src/components/viewer/BulkPropertyEditor.tsx +315 -154
- package/src/components/viewer/CommandPalette.tsx +0 -6
- package/src/components/viewer/DataConnector.tsx +489 -284
- package/src/components/viewer/ExportDialog.tsx +66 -6
- package/src/components/viewer/KeyboardShortcutsDialog.tsx +44 -1
- package/src/components/viewer/MainToolbar.tsx +1 -5
- package/src/components/viewer/Viewport.tsx +42 -56
- package/src/components/viewer/ViewportContainer.tsx +3 -0
- package/src/components/viewer/ViewportOverlays.tsx +12 -10
- package/src/components/viewer/bcf/BCFOverlay.tsx +254 -0
- package/src/components/viewer/lists/ListPanel.tsx +0 -21
- package/src/components/viewer/lists/ListResultsTable.tsx +93 -5
- package/src/components/viewer/measureHandlers.ts +558 -0
- package/src/components/viewer/mouseHandlerTypes.ts +108 -0
- package/src/components/viewer/selectionHandlers.ts +86 -0
- package/src/components/viewer/useAnimationLoop.ts +116 -44
- package/src/components/viewer/useGeometryStreaming.ts +155 -367
- package/src/components/viewer/useKeyboardControls.ts +30 -46
- package/src/components/viewer/useMouseControls.ts +169 -695
- package/src/components/viewer/useRenderUpdates.ts +9 -59
- package/src/components/viewer/useTouchControls.ts +55 -40
- package/src/hooks/bcfIdLookup.ts +70 -0
- package/src/hooks/useBCF.ts +12 -31
- package/src/hooks/useIfcCache.ts +2 -20
- package/src/hooks/useIfcFederation.ts +5 -11
- package/src/hooks/useIfcLoader.ts +47 -56
- package/src/hooks/useIfcServer.ts +9 -1
- package/src/hooks/useKeyboardShortcuts.ts +0 -10
- package/src/hooks/useLatestRef.ts +24 -0
- package/src/sdk/adapters/export-adapter.ts +2 -2
- package/src/sdk/adapters/model-adapter.ts +1 -0
- package/src/sdk/local-backend.ts +2 -0
- package/src/store/basketVisibleSet.ts +12 -0
- package/src/store/slices/bcfSlice.ts +9 -0
- package/src/utils/loadingUtils.ts +46 -0
- package/src/utils/serverDataModel.ts +4 -3
- package/dist/assets/ifc-lite_bg-CyWQTvp5.wasm +0 -0
- package/dist/assets/index-ax1X2WPd.css +0 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Keyboard controls hook for the 3D viewport
|
|
7
|
-
* Handles keyboard shortcuts,
|
|
7
|
+
* Handles keyboard shortcuts, walk mode, continuous movement
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEffect, type MutableRefObject } from 'react';
|
|
@@ -37,6 +37,12 @@ export interface UseKeyboardControlsParams {
|
|
|
37
37
|
calculateScale: () => void;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/** Keys that trigger continuous movement (arrow keys + WASD + shift for sprint) */
|
|
41
|
+
const MOVEMENT_KEYS = new Set([
|
|
42
|
+
'arrowup', 'arrowdown', 'arrowleft', 'arrowright',
|
|
43
|
+
'w', 's', 'a', 'd', 'shift',
|
|
44
|
+
]);
|
|
45
|
+
|
|
40
46
|
export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
41
47
|
const {
|
|
42
48
|
rendererRef,
|
|
@@ -69,6 +75,10 @@ export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
|
69
75
|
let moveLoopRunning = false;
|
|
70
76
|
let moveFrameId: number | null = null;
|
|
71
77
|
|
|
78
|
+
const renderScene = () => {
|
|
79
|
+
renderer.requestRender();
|
|
80
|
+
};
|
|
81
|
+
|
|
72
82
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
73
83
|
const target = e.target as HTMLElement;
|
|
74
84
|
if (
|
|
@@ -82,8 +92,7 @@ export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
|
82
92
|
keyState[e.key.toLowerCase()] = true;
|
|
83
93
|
|
|
84
94
|
// Start movement loop when a movement key is pressed
|
|
85
|
-
|
|
86
|
-
if (isMovementKey && !moveLoopRunning) {
|
|
95
|
+
if (MOVEMENT_KEYS.has(e.key.toLowerCase()) && !moveLoopRunning) {
|
|
87
96
|
moveLoopRunning = true;
|
|
88
97
|
keyboardMove();
|
|
89
98
|
}
|
|
@@ -92,18 +101,7 @@ export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
|
92
101
|
const setViewAndRender = (view: 'top' | 'bottom' | 'front' | 'back' | 'left' | 'right') => {
|
|
93
102
|
const rotation = coordinateInfoRef.current?.buildingRotation;
|
|
94
103
|
camera.setPresetView(view, geometryBoundsRef.current, rotation);
|
|
95
|
-
|
|
96
|
-
hiddenIds: hiddenEntitiesRef.current,
|
|
97
|
-
isolatedIds: isolatedEntitiesRef.current,
|
|
98
|
-
selectedId: selectedEntityIdRef.current,
|
|
99
|
-
selectedModelIndex: selectedModelIndexRef.current,
|
|
100
|
-
clearColor: clearColorRef.current,
|
|
101
|
-
sectionPlane: activeToolRef.current === 'section' ? {
|
|
102
|
-
...sectionPlaneRef.current,
|
|
103
|
-
min: sectionRangeRef.current?.min,
|
|
104
|
-
max: sectionRangeRef.current?.max,
|
|
105
|
-
} : undefined,
|
|
106
|
-
});
|
|
104
|
+
renderScene();
|
|
107
105
|
updateCameraRotationRealtime(camera.getRotation());
|
|
108
106
|
calculateScale();
|
|
109
107
|
};
|
|
@@ -119,13 +117,11 @@ export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
|
119
117
|
if (e.key === 'f' || e.key === 'F') {
|
|
120
118
|
const selectedId = selectedEntityIdRef.current;
|
|
121
119
|
if (selectedId !== null) {
|
|
122
|
-
// Frame selection - zoom to fit selected element
|
|
123
120
|
const bounds = getEntityBounds(geometryRef.current, selectedId);
|
|
124
121
|
if (bounds) {
|
|
125
122
|
camera.frameBounds(bounds.min, bounds.max, 300);
|
|
126
123
|
}
|
|
127
124
|
} else {
|
|
128
|
-
// No selection - fit all
|
|
129
125
|
camera.zoomExtent(geometryBoundsRef.current.min, geometryBoundsRef.current.max, 300);
|
|
130
126
|
}
|
|
131
127
|
calculateScale();
|
|
@@ -141,20 +137,14 @@ export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
|
141
137
|
camera.zoomExtent(geometryBoundsRef.current.min, geometryBoundsRef.current.max, 300);
|
|
142
138
|
calculateScale();
|
|
143
139
|
}
|
|
144
|
-
|
|
145
|
-
// Toggle first-person mode
|
|
146
|
-
if (e.key === 'c' || e.key === 'C') {
|
|
147
|
-
firstPersonModeRef.current = !firstPersonModeRef.current;
|
|
148
|
-
camera.enableFirstPersonMode(firstPersonModeRef.current);
|
|
149
|
-
}
|
|
150
140
|
};
|
|
151
141
|
|
|
152
142
|
const handleKeyUp = (e: KeyboardEvent) => {
|
|
153
143
|
keyState[e.key.toLowerCase()] = false;
|
|
154
144
|
|
|
155
145
|
// Stop movement loop when no movement keys are held
|
|
156
|
-
const
|
|
157
|
-
if (!
|
|
146
|
+
const anyHeld = Array.from(MOVEMENT_KEYS).some(k => keyState[k]);
|
|
147
|
+
if (!anyHeld && moveLoopRunning) {
|
|
158
148
|
moveLoopRunning = false;
|
|
159
149
|
if (moveFrameId !== null) {
|
|
160
150
|
cancelAnimationFrame(moveFrameId);
|
|
@@ -170,16 +160,21 @@ export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
|
170
160
|
if (aborted || !moveLoopRunning) return;
|
|
171
161
|
|
|
172
162
|
let moved = false;
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
if (
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (
|
|
163
|
+
const isWalkMode = activeToolRef.current === 'walk';
|
|
164
|
+
|
|
165
|
+
if (isWalkMode) {
|
|
166
|
+
// Walk mode: arrow keys + WASD move on horizontal plane
|
|
167
|
+
// Up/W = forward, Down/S = backward, Left/A = strafe left, Right/D = strafe right
|
|
168
|
+
const fwd = (keyState['arrowup'] || keyState['w'] ? 1 : 0) + (keyState['arrowdown'] || keyState['s'] ? -1 : 0);
|
|
169
|
+
const strafe = (keyState['arrowleft'] || keyState['a'] ? -1 : 0) + (keyState['arrowright'] || keyState['d'] ? 1 : 0);
|
|
170
|
+
if (fwd !== 0 || strafe !== 0) {
|
|
171
|
+
const sprint = keyState['shift'] ? 2 : 1;
|
|
172
|
+
camera.moveFirstPerson(fwd * sprint, strafe * sprint, 0);
|
|
173
|
+
moved = true;
|
|
174
|
+
}
|
|
181
175
|
} else {
|
|
182
|
-
//
|
|
176
|
+
// Normal mode: arrow keys pan the view
|
|
177
|
+
const panSpeed = 5;
|
|
183
178
|
if (keyState['arrowup']) { camera.pan(0, -panSpeed, false); moved = true; }
|
|
184
179
|
if (keyState['arrowdown']) { camera.pan(0, panSpeed, false); moved = true; }
|
|
185
180
|
if (keyState['arrowleft']) { camera.pan(panSpeed, 0, false); moved = true; }
|
|
@@ -187,18 +182,7 @@ export function useKeyboardControls(params: UseKeyboardControlsParams): void {
|
|
|
187
182
|
}
|
|
188
183
|
|
|
189
184
|
if (moved) {
|
|
190
|
-
|
|
191
|
-
hiddenIds: hiddenEntitiesRef.current,
|
|
192
|
-
isolatedIds: isolatedEntitiesRef.current,
|
|
193
|
-
selectedId: selectedEntityIdRef.current,
|
|
194
|
-
selectedModelIndex: selectedModelIndexRef.current,
|
|
195
|
-
clearColor: clearColorRef.current,
|
|
196
|
-
sectionPlane: activeToolRef.current === 'section' ? {
|
|
197
|
-
...sectionPlaneRef.current,
|
|
198
|
-
min: sectionRangeRef.current?.min,
|
|
199
|
-
max: sectionRangeRef.current?.max,
|
|
200
|
-
} : undefined,
|
|
201
|
-
});
|
|
185
|
+
renderScene();
|
|
202
186
|
}
|
|
203
187
|
moveFrameId = requestAnimationFrame(keyboardMove);
|
|
204
188
|
};
|