@inweb/viewer-three 25.11.2 → 25.12.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.
@@ -57,6 +57,9 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
57
57
  * model reference files from the Open Cloud Server. For a standalone viewer instance use
58
58
  * {@link openGltfFile | openGltfFile()}.
59
59
  *
60
+ * If there was an active dragger before opening the file, it will be deactivated. After
61
+ * opening the file, you must manually activate the required dragger.
62
+ *
60
63
  * Fires:
61
64
  *
62
65
  * - {@link OpenEvent | open}
@@ -76,6 +79,9 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
76
79
  /**
77
80
  * Loads a `glTF` file into the viewer.
78
81
  *
82
+ * If there was an active dragger before opening the file, it will be deactivated. After
83
+ * opening the file, you must manually activate the required dragger.
84
+ *
79
85
  * Fires:
80
86
  *
81
87
  * - {@link OpenEvent | open}
@@ -1,7 +1,14 @@
1
- import { Camera, EventDispatcher, Vector2 } from "three";
2
- export declare class WalkControls extends EventDispatcher {
3
- camera: Camera;
4
- canvas: HTMLElement;
1
+ import { Camera, Controls, Vector2 } from "three";
2
+ interface WalkControlsEventMap {
3
+ change: {
4
+ type: "change";
5
+ };
6
+ walkspeedchange: {
7
+ type: "walkspeedchange";
8
+ data: number;
9
+ };
10
+ }
11
+ export declare class WalkControls extends Controls<WalkControlsEventMap> {
5
12
  movementSpeed: number;
6
13
  lookSpeed: number;
7
14
  multiplier: number;
@@ -24,3 +31,4 @@ export declare class WalkControls extends EventDispatcher {
24
31
  update(): void;
25
32
  rotateCamera(delta: Vector2): void;
26
33
  }
34
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { Viewer } from "../Viewer";
2
+ import { OrbitDragger } from "./OrbitDragger";
3
+ export declare class MeasureLineDragger extends OrbitDragger {
4
+ private overlay;
5
+ private line;
6
+ private snapper;
7
+ constructor(viewer: Viewer);
8
+ dispose(): void;
9
+ onPointerDown: (event: PointerEvent) => void;
10
+ onPointerMove: (event: PointerEvent) => void;
11
+ onPointerUp: (event: PointerEvent) => void;
12
+ onPointerCancel: (event: PointerEvent) => void;
13
+ onPointerLeave: () => void;
14
+ renderOverlay: () => void;
15
+ updateSnapper: () => void;
16
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inweb/viewer-three",
3
- "version": "25.11.2",
3
+ "version": "25.12.0",
4
4
  "description": "JavaScript library for rendering CAD and BIM files in a browser using Three.js",
5
5
  "homepage": "https://cloud.opendesign.com/docs/index.html",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -28,17 +28,17 @@
28
28
  "docs": "typedoc"
29
29
  },
30
30
  "dependencies": {
31
- "@inweb/client": "~25.11.2",
32
- "@inweb/eventemitter2": "~25.11.2",
33
- "@inweb/markup": "~25.11.2",
34
- "@inweb/viewer-core": "~25.11.2"
31
+ "@inweb/client": "~25.12.0",
32
+ "@inweb/eventemitter2": "~25.12.0",
33
+ "@inweb/markup": "~25.12.0",
34
+ "@inweb/viewer-core": "~25.12.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@types/three": "^0.152.1",
38
- "three": "^0.153.0"
37
+ "@types/three": "^0.169.0",
38
+ "three": "^0.170.0"
39
39
  },
40
40
  "peerDependencies": {
41
- "@types/three": "^0.152.1",
42
- "three": "^0.153.0"
41
+ "@types/three": "^0.169.0",
42
+ "three": "^0.170.0"
43
43
  }
44
44
  }
@@ -52,6 +52,7 @@ import { WalkDragger } from "./draggers/WalkDragger";
52
52
  import { CuttingPlaneXAxisDragger } from "./draggers/CuttingPlaneXAxis";
53
53
  import { CuttingPlaneYAxisDragger } from "./draggers/CuttingPlaneYAxis";
54
54
  import { CuttingPlaneZAxisDragger } from "./draggers/CuttingPlaneZAxis";
55
+ import { MeasureLineDragger } from "./draggers/MeasureLineDragger";
55
56
 
56
57
  import { IDisposable } from "./IDisposable";
57
58
  import { ExtentsComponent } from "./components/ExtentsComponent";
@@ -125,6 +126,7 @@ export class Viewer
125
126
  CuttingPlaneXAxis: CuttingPlaneXAxisDragger,
126
127
  CuttingPlaneYAxis: CuttingPlaneYAxisDragger,
127
128
  CuttingPlaneZAxis: CuttingPlaneZAxisDragger,
129
+ MeasureLine: MeasureLineDragger,
128
130
  };
129
131
  this._activeDragger = null;
130
132
 
@@ -284,6 +286,9 @@ export class Viewer
284
286
  * model reference files from the Open Cloud Server. For a standalone viewer instance use
285
287
  * {@link openGltfFile | openGltfFile()}.
286
288
  *
289
+ * If there was an active dragger before opening the file, it will be deactivated. After
290
+ * opening the file, you must manually activate the required dragger.
291
+ *
287
292
  * Fires:
288
293
  *
289
294
  * - {@link OpenEvent | open}
@@ -333,6 +338,9 @@ export class Viewer
333
338
  /**
334
339
  * Loads a `glTF` file into the viewer.
335
340
  *
341
+ * If there was an active dragger before opening the file, it will be deactivated. After
342
+ * opening the file, you must manually activate the required dragger.
343
+ *
336
344
  * Fires:
337
345
  *
338
346
  * - {@link OpenEvent | open}
@@ -479,6 +487,7 @@ export class Viewer
479
487
  this.setActiveDragger();
480
488
  this.clearSlices();
481
489
  this.clearOverlay();
490
+ this.clearSelected();
482
491
 
483
492
  this.helpers.traverse(disposeObject);
484
493
  this.helpers.clear();
@@ -33,11 +33,7 @@ function zoomToObjects(viewer: Viewer, handles: string[] = []): void {
33
33
  if (handleSet.has(child.userData?.handle)) objects.push(child);
34
34
  });
35
35
 
36
- const extents = objects.reduce((result, object) => {
37
- const objectExtents = new Box3().setFromObject(object);
38
- return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
39
- }, new Box3());
40
-
36
+ const extents = objects.reduce((result: Box3, object) => result.expandByObject(object), new Box3());
41
37
  const center = extents.getCenter(new Vector3());
42
38
  const distance = extents.getBoundingSphere(new Sphere()).radius;
43
39
 
@@ -27,10 +27,7 @@ import { commands } from "@inweb/viewer-core";
27
27
  import type { Viewer } from "../Viewer";
28
28
 
29
29
  function zoomToSelected(viewer: Viewer): void {
30
- const extents = viewer.selected.reduce((result, object) => {
31
- const objectExtents = new Box3().setFromObject(object);
32
- return result.isEmpty() ? result.copy(objectExtents) : result.union(objectExtents);
33
- }, new Box3());
30
+ const extents = viewer.selected.reduce((result: Box3, object) => result.expandByObject(object), new Box3());
34
31
 
35
32
  if (extents.isEmpty()) extents.copy(viewer.extents);
36
33
 
@@ -43,10 +43,7 @@ export class ExtentsComponent implements IDisposable {
43
43
  }
44
44
 
45
45
  syncExtents = () => {
46
- const extents = this.viewer.models.reduce((result, gltf) => {
47
- const modelExtents = new Box3().setFromObject(gltf.scene);
48
- return result.isEmpty() ? result.copy(modelExtents) : result.union(modelExtents);
49
- }, new Box3());
46
+ const extents = this.viewer.models.reduce((result: Box3, gltf) => result.expandByObject(gltf.scene), new Box3());
50
47
 
51
48
  this.viewer.extents.copy(extents);
52
49
  this.viewer.target.copy(extents.getCenter(new Vector3()));
@@ -100,6 +100,15 @@ export class SelectionComponent implements IDisposable {
100
100
  const objects = [];
101
101
  this.viewer.scene.traverseVisible((child) => objects.push(child));
102
102
 
103
+ this.raycaster.params = this.raycaster.params = {
104
+ Mesh: {},
105
+ Line: { threshold: 0.25 },
106
+ Line2: { threshold: 0.25 },
107
+ LOD: {},
108
+ Points: { threshold: 0.1 },
109
+ Sprite: {},
110
+ };
111
+
103
112
  return this.raycaster.intersectObjects(objects, false);
104
113
  }
105
114
 
@@ -41,6 +41,9 @@ export class WCSHelperComponent implements IDisposable {
41
41
  }
42
42
 
43
43
  viewerRender = () => {
44
- if (!this.viewer.extents.isEmpty()) this.wcsHelper.render(this.viewer.renderer);
44
+ if (!this.viewer.options.showWCS) return;
45
+ if (this.viewer.extents.isEmpty()) return;
46
+
47
+ this.wcsHelper.render(this.viewer.renderer);
45
48
  };
46
49
  }
@@ -21,14 +21,14 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { Clock, Camera, EventDispatcher, Quaternion, Vector2, Vector3 } from "three";
24
+ import { Clock, Camera, Controls, Quaternion, Vector2, Vector3 } from "three";
25
25
 
26
- const _changeEvent = { type: "change" };
27
-
28
- export class WalkControls extends EventDispatcher {
29
- public camera: Camera;
30
- public canvas: HTMLElement;
26
+ interface WalkControlsEventMap {
27
+ change: { type: "change" };
28
+ walkspeedchange: { type: "walkspeedchange"; data: number };
29
+ }
31
30
 
31
+ export class WalkControls extends Controls<WalkControlsEventMap> {
32
32
  public movementSpeed = 0.2;
33
33
  public lookSpeed = 5;
34
34
  public multiplier = 5;
@@ -43,10 +43,7 @@ export class WalkControls extends EventDispatcher {
43
43
  public rotateDelta: Vector2;
44
44
 
45
45
  constructor(camera: Camera, canvas: HTMLElement) {
46
- super();
47
-
48
- this.camera = camera;
49
- this.canvas = canvas;
46
+ super(camera, canvas);
50
47
 
51
48
  this.moveKeys = new Set();
52
49
  this.moveClock = new Clock();
@@ -55,56 +52,56 @@ export class WalkControls extends EventDispatcher {
55
52
  this.downPosition = new Vector2(0, 0);
56
53
  this.rotateDelta = new Vector2(0, 0);
57
54
 
58
- this.canvas.addEventListener("pointerdown", this.onPointerDown);
59
- this.canvas.addEventListener("pointermove", this.onPointerMove);
60
- this.canvas.addEventListener("pointerup", this.onPointerUp);
61
- this.canvas.addEventListener("pointercancel", this.onPointerCancel);
62
- this.canvas.addEventListener("wheel", this.onWheel);
55
+ this.domElement.addEventListener("pointerdown", this.onPointerDown);
56
+ this.domElement.addEventListener("pointermove", this.onPointerMove);
57
+ this.domElement.addEventListener("pointerup", this.onPointerUp);
58
+ this.domElement.addEventListener("pointercancel", this.onPointerCancel);
59
+ this.domElement.addEventListener("wheel", this.onWheel);
63
60
 
64
61
  window.addEventListener("keydown", this.onKeyDown);
65
62
  window.addEventListener("keyup", this.onKeyUp);
66
63
  }
67
64
 
68
- dispose() {
69
- this.canvas.removeEventListener("pointerdown", this.onPointerDown);
70
- this.canvas.removeEventListener("pointermove", this.onPointerMove);
71
- this.canvas.removeEventListener("pointerup", this.onPointerUp);
72
- this.canvas.removeEventListener("pointercancel", this.onPointerCancel);
73
- this.canvas.removeEventListener("wheel", this.onWheel);
65
+ override dispose() {
66
+ this.domElement.removeEventListener("pointerdown", this.onPointerDown);
67
+ this.domElement.removeEventListener("pointermove", this.onPointerMove);
68
+ this.domElement.removeEventListener("pointerup", this.onPointerUp);
69
+ this.domElement.removeEventListener("pointercancel", this.onPointerCancel);
70
+ this.domElement.removeEventListener("wheel", this.onWheel);
74
71
 
75
72
  window.removeEventListener("keydown", this.onKeyDown);
76
73
  window.removeEventListener("keyup", this.onKeyUp);
74
+
75
+ super.dispose();
77
76
  }
78
77
 
79
78
  onPointerDown = (event: PointerEvent) => {
80
- if (!event.isPrimary || event.button !== 0) return;
79
+ if (event.button !== 0) return;
81
80
 
82
- this.canvas.setPointerCapture(event.pointerId);
81
+ this.domElement.setPointerCapture(event.pointerId);
83
82
  this.downPosition.set(event.clientX, event.clientY);
84
- this.quaternion.copy(this.camera.quaternion);
83
+ this.quaternion.copy(this.object.quaternion);
85
84
  this.mouseDragOn = true;
86
85
  };
87
86
 
88
87
  onPointerMove = (event: PointerEvent) => {
89
- if (!event.isPrimary || !this.mouseDragOn) return;
88
+ if (!this.mouseDragOn) return;
90
89
 
91
90
  const movePosition = new Vector2(event.clientX, event.clientY);
92
91
  if (this.downPosition.distanceTo(movePosition) === 0) return;
93
92
 
94
93
  this.rotateDelta.copy(this.downPosition).sub(movePosition);
95
94
  this.rotateCamera(this.rotateDelta);
96
- this.dispatchEvent(_changeEvent);
95
+ this.dispatchEvent({ type: "change" });
97
96
  };
98
97
 
99
98
  onPointerUp = (event: PointerEvent) => {
100
- if (!event.isPrimary || event.button !== 0) return;
101
-
102
- this.canvas.releasePointerCapture(event.pointerId);
99
+ this.domElement.releasePointerCapture(event.pointerId);
103
100
  this.mouseDragOn = false;
104
101
  };
105
102
 
106
103
  onPointerCancel = (event: PointerEvent) => {
107
- this.canvas.dispatchEvent(new PointerEvent("pointerup", event));
104
+ this.domElement.dispatchEvent(new PointerEvent("pointerup", event));
108
105
  };
109
106
 
110
107
  onWheel = (event: WheelEvent) => {
@@ -147,36 +144,22 @@ export class WalkControls extends EventDispatcher {
147
144
  };
148
145
 
149
146
  onKeyUp = (event: KeyboardEvent) => {
150
- switch (event.code) {
151
- case "ArrowLeft":
152
- case "ArrowRight":
153
- case "ArrowUp":
154
- case "ArrowDown":
155
- case "KeyW":
156
- case "KeyS":
157
- case "KeyA":
158
- case "KeyD":
159
- case "KeyQ":
160
- case "KeyE":
161
- this.moveKeys.delete(event.code);
162
- this.update();
163
- break;
164
- }
147
+ if (this.moveKeys.delete(event.code)) this.update();
165
148
  };
166
149
 
167
- update() {
150
+ override update() {
168
151
  if (this.moveKeys.size > 0) {
169
152
  const timeDelta = this.moveClock.getDelta();
170
153
  const moveDelta = timeDelta * this.movementSpeed * this.multiplier;
171
154
 
172
- if (this.moveKeys.has("KeyW")) this.camera.translateZ(-moveDelta);
173
- if (this.moveKeys.has("KeyS")) this.camera.translateZ(moveDelta);
155
+ if (this.moveKeys.has("KeyW")) this.object.translateZ(-moveDelta);
156
+ if (this.moveKeys.has("KeyS")) this.object.translateZ(moveDelta);
174
157
 
175
- if (this.moveKeys.has("KeyA")) this.camera.translateX(-moveDelta);
176
- if (this.moveKeys.has("KeyD")) this.camera.translateX(moveDelta);
158
+ if (this.moveKeys.has("KeyA")) this.object.translateX(-moveDelta);
159
+ if (this.moveKeys.has("KeyD")) this.object.translateX(moveDelta);
177
160
 
178
- if (this.moveKeys.has("KeyQ")) this.camera.translateY(moveDelta);
179
- if (this.moveKeys.has("KeyE")) this.camera.translateY(-moveDelta);
161
+ if (this.moveKeys.has("KeyQ")) this.object.translateY(moveDelta);
162
+ if (this.moveKeys.has("KeyE")) this.object.translateY(-moveDelta);
180
163
 
181
164
  const lookDelta = this.lookSpeed + (this.multiplier - 1);
182
165
 
@@ -187,15 +170,15 @@ export class WalkControls extends EventDispatcher {
187
170
  if (this.moveKeys.has("ArrowRight")) this.rotateCamera(this.rotateDelta.add(new Vector2(-lookDelta, 0)));
188
171
 
189
172
  this.moveWheel = 0;
190
- this.dispatchEvent(_changeEvent);
173
+ this.dispatchEvent({ type: "change" });
191
174
  }
192
175
 
193
176
  if (this.moveWheel !== 0) {
194
177
  const moveDelta = this.moveWheel * 0.0001 * this.movementSpeed * this.multiplier;
195
178
 
196
- this.camera.translateZ(-moveDelta);
179
+ this.object.translateZ(-moveDelta);
197
180
  this.moveWheel += -1 * Math.sign(this.moveWheel);
198
- this.dispatchEvent(_changeEvent);
181
+ this.dispatchEvent({ type: "change" });
199
182
  }
200
183
 
201
184
  if (this.moveKeys.size === 0 && this.moveWheel === 0) {
@@ -205,11 +188,11 @@ export class WalkControls extends EventDispatcher {
205
188
  }
206
189
 
207
190
  rotateCamera(delta: Vector2) {
208
- const rotateX = (Math.PI * delta.x) / this.canvas.clientWidth;
209
- const rotateY = (Math.PI * delta.y) / this.canvas.clientHeight;
191
+ const rotateX = (Math.PI * delta.x) / this.domElement.clientWidth;
192
+ const rotateY = (Math.PI * delta.y) / this.domElement.clientHeight;
210
193
 
211
194
  const xRotation = new Quaternion();
212
- xRotation.setFromAxisAngle(this.camera.up, rotateX);
195
+ xRotation.setFromAxisAngle(this.object.up, rotateX);
213
196
 
214
197
  const yRotation = new Quaternion();
215
198
  yRotation.setFromAxisAngle(new Vector3(1, 0, 0), rotateY);
@@ -217,6 +200,6 @@ export class WalkControls extends EventDispatcher {
217
200
  const quaternion = this.quaternion.clone();
218
201
  quaternion.premultiply(xRotation).multiply(yRotation).normalize();
219
202
 
220
- this.camera.setRotationFromQuaternion(quaternion);
203
+ this.object.setRotationFromQuaternion(quaternion);
221
204
  }
222
205
  }
@@ -60,7 +60,7 @@ export class CuttingPlaneDragger extends OrbitDragger {
60
60
  this.transform.attach(this.planeCenter);
61
61
  this.transform.addEventListener("change", this.transformChange);
62
62
  this.transform.addEventListener("dragging-changed", this.transformDrag);
63
- this.viewer.helpers.add(this.transform);
63
+ this.viewer.helpers.add(this.transform.getHelper());
64
64
 
65
65
  this.viewer.on("explode", this.viewerExplode);
66
66
  this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
@@ -73,7 +73,8 @@ export class CuttingPlaneDragger extends OrbitDragger {
73
73
 
74
74
  this.transform.removeEventListener("change", this.transformChange);
75
75
  this.transform.removeEventListener("dragging-changed", this.transformDrag);
76
- this.transform.removeFromParent();
76
+ this.transform.getHelper().removeFromParent();
77
+ this.transform.detach();
77
78
  this.transform.dispose();
78
79
 
79
80
  this.planeHelper.removeFromParent();