@inweb/viewer-three 26.6.5 → 26.6.7

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 (75) hide show
  1. package/dist/plugins/components/AxesHelperComponent.js +5 -5
  2. package/dist/plugins/components/AxesHelperComponent.js.map +1 -1
  3. package/dist/plugins/components/AxesHelperComponent.min.js +1 -1
  4. package/dist/plugins/components/AxesHelperComponent.module.js +5 -5
  5. package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -1
  6. package/dist/plugins/components/ExtentsHelperComponent.js +15 -7
  7. package/dist/plugins/components/ExtentsHelperComponent.js.map +1 -1
  8. package/dist/plugins/components/ExtentsHelperComponent.min.js +1 -1
  9. package/dist/plugins/components/ExtentsHelperComponent.module.js +15 -7
  10. package/dist/plugins/components/ExtentsHelperComponent.module.js.map +1 -1
  11. package/dist/plugins/components/LightHelperComponent.js +5 -5
  12. package/dist/plugins/components/LightHelperComponent.js.map +1 -1
  13. package/dist/plugins/components/LightHelperComponent.min.js +1 -1
  14. package/dist/plugins/components/LightHelperComponent.module.js +5 -5
  15. package/dist/plugins/components/LightHelperComponent.module.js.map +1 -1
  16. package/dist/plugins/loaders/GLTFCloudLoader.js +4840 -0
  17. package/dist/plugins/loaders/GLTFCloudLoader.js.map +1 -0
  18. package/dist/plugins/loaders/GLTFCloudLoader.min.js +1 -0
  19. package/dist/plugins/loaders/GLTFCloudLoader.module.js +49 -0
  20. package/dist/plugins/loaders/GLTFCloudLoader.module.js.map +1 -0
  21. package/dist/plugins/loaders/IFCXLoader.js +12 -6
  22. package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
  23. package/dist/plugins/loaders/IFCXLoader.min.js +1 -1
  24. package/dist/plugins/loaders/IFCXLoader.module.js +13 -7
  25. package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
  26. package/dist/viewer-three.js +3131 -459
  27. package/dist/viewer-three.js.map +1 -1
  28. package/dist/viewer-three.min.js +2 -2
  29. package/dist/viewer-three.module.js +2326 -264
  30. package/dist/viewer-three.module.js.map +1 -1
  31. package/lib/Viewer/Viewer.d.ts +6 -5
  32. package/lib/Viewer/components/HighlighterComponent.d.ts +4 -3
  33. package/lib/Viewer/components/SelectionComponent.d.ts +8 -5
  34. package/lib/Viewer/draggers/CuttingPlaneDragger.d.ts +1 -1
  35. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +20 -0
  36. package/lib/Viewer/loaders/GLTFCloudDynamicLoader.d.ts +15 -0
  37. package/lib/Viewer/model/IModelImpl.d.ts +27 -0
  38. package/lib/Viewer/model/ModelImpl.d.ts +30 -0
  39. package/lib/Viewer/model/index.d.ts +2 -0
  40. package/lib/index.d.ts +1 -0
  41. package/package.json +11 -7
  42. package/plugins/components/AxesHelperComponent.ts +5 -5
  43. package/plugins/components/ExtentsHelperComponent.ts +15 -7
  44. package/plugins/components/LightHelperComponent.ts +5 -5
  45. package/{src/Viewer/loaders/GLTFCloudModelLoader.ts → plugins/loaders/GLTFCloudLoader.ts} +15 -12
  46. package/plugins/loaders/{IFCXCloudFileLoader.ts → IFCXCloudLoader.ts} +8 -4
  47. package/plugins/loaders/IFCXFileLoader.ts +7 -3
  48. package/plugins/loaders/IFCXLoader.ts +2 -2
  49. package/src/Viewer/Viewer.ts +32 -36
  50. package/src/Viewer/commands/ClearSelected.ts +2 -3
  51. package/src/Viewer/commands/Explode.ts +1 -47
  52. package/src/Viewer/commands/GetModels.ts +1 -1
  53. package/src/Viewer/commands/GetSelected.ts +3 -1
  54. package/src/Viewer/commands/HideSelected.ts +3 -4
  55. package/src/Viewer/commands/IsolateSelected.ts +1 -7
  56. package/src/Viewer/commands/SelectModel.ts +9 -1
  57. package/src/Viewer/commands/SetSelected.ts +8 -10
  58. package/src/Viewer/commands/ShowAll.ts +1 -1
  59. package/src/Viewer/components/BackgroundComponent.ts +1 -0
  60. package/src/Viewer/components/ExtentsComponent.ts +5 -3
  61. package/src/Viewer/components/HighlighterComponent.ts +79 -48
  62. package/src/Viewer/components/SelectionComponent.ts +67 -21
  63. package/src/Viewer/draggers/CuttingPlaneDragger.ts +7 -3
  64. package/src/Viewer/draggers/MeasureLineDragger.ts +2 -0
  65. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +1628 -0
  66. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +102 -0
  67. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +450 -0
  68. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +145 -0
  69. package/src/Viewer/loaders/GLTFFileLoader.ts +7 -2
  70. package/src/Viewer/loaders/index.ts +2 -2
  71. package/src/Viewer/model/IModelImpl.ts +67 -0
  72. package/src/Viewer/model/ModelImpl.ts +215 -0
  73. package/src/Viewer/model/index.ts +25 -0
  74. package/src/index.ts +1 -0
  75. package/lib/Viewer/loaders/GLTFCloudModelLoader.d.ts +0 -8
@@ -21,56 +21,10 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { Box3, Vector3 } from "three";
25
24
  import type { Viewer } from "../Viewer";
26
25
 
27
- function calcExplodeDepth(object, depth: number): number {
28
- let res = depth;
29
- object.children.forEach((x) => {
30
- const objectDepth = calcExplodeDepth(x, depth + 1);
31
- if (res < objectDepth) res = objectDepth;
32
- });
33
-
34
- object.originalPosition = object.position.clone();
35
- object.originalCenter = new Box3().setFromObject(object).getCenter(new Vector3());
36
- object.isExplodeLocked = depth > 2 && object.children.length === 0;
37
-
38
- return res;
39
- }
40
-
41
- function explodeModel(scene, scale = 0, coeff = 4) {
42
- scale /= 100;
43
-
44
- if (!scene.explodeDepth) scene.explodeDepth = calcExplodeDepth(scene, 1);
45
- const maxDepth = scene.explodeDepth;
46
-
47
- const scaledExplodeDepth = scale * maxDepth + 1;
48
- const explodeDepth = 0 | scaledExplodeDepth;
49
- const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
50
-
51
- function explodeObject(object, depth: number) {
52
- object.position.copy(object.originalPosition);
53
-
54
- if (depth > 0 && depth <= explodeDepth && !object.isExplodeLocked) {
55
- let objectScale = scale * coeff;
56
- if (depth === explodeDepth) objectScale *= currentSegmentFraction;
57
-
58
- const parentCenter = object.parent.originalCenter;
59
- const objectCenter = object.originalCenter;
60
- const objectOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
61
-
62
- object.position.add(objectOffset);
63
- }
64
-
65
- object.children.forEach((x) => explodeObject(x, depth + 1));
66
- }
67
-
68
- explodeObject(scene, 0);
69
- }
70
-
71
26
  export function explode(viewer: Viewer, index = 0): void {
72
- viewer.models.forEach((model) => explodeModel(model, index));
73
- viewer.scene.updateMatrixWorld();
27
+ viewer.models.forEach((model) => model.explode(index));
74
28
 
75
29
  viewer.update();
76
30
  viewer.emitEvent({ type: "explode", data: index });
@@ -24,5 +24,5 @@
24
24
  import type { Viewer } from "../Viewer";
25
25
 
26
26
  export function getModels(viewer: Viewer): string[] {
27
- return viewer.models.map((model) => model.userData?.handle || "").filter((handle) => handle);
27
+ return viewer.models.map((model) => model.handle);
28
28
  }
@@ -24,5 +24,7 @@
24
24
  import type { Viewer } from "../Viewer";
25
25
 
26
26
  export function getSelected(viewer: Viewer): string[] {
27
- return viewer.selected.map((object) => object.userData?.handle).filter((handle) => handle);
27
+ const handles = [];
28
+ viewer.models.forEach((model) => handles.push(...model.getHandlesByObjects(viewer.selected)));
29
+ return handles;
28
30
  }
@@ -22,14 +22,13 @@
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
24
  import type { Viewer } from "../Viewer";
25
- import { SelectionComponent } from "../components/SelectionComponent";
25
+ import type { SelectionComponent } from "../components/SelectionComponent";
26
26
 
27
27
  export function hideSelected(viewer: Viewer): void {
28
- viewer.selected.forEach((object) => (object.visible = false));
28
+ viewer.models.forEach((model) => model.hideObjects(viewer.selected));
29
29
 
30
- const selection = new SelectionComponent(viewer);
30
+ const selection = viewer.getComponent("SelectionComponent") as SelectionComponent;
31
31
  selection.clearSelection();
32
- selection.dispose();
33
32
 
34
33
  viewer.update();
35
34
  viewer.emitEvent({ type: "hide" });
@@ -24,13 +24,7 @@
24
24
  import type { Viewer } from "../Viewer";
25
25
 
26
26
  export function isolateSelected(viewer: Viewer): void {
27
- const visibleSet = new Set();
28
- viewer.selected.forEach((object) => {
29
- visibleSet.add(object);
30
- object.traverseAncestors((object2) => visibleSet.add(object2));
31
- });
32
-
33
- viewer.scene.traverse((object) => (object.visible = visibleSet.has(object)));
27
+ viewer.models.forEach((model) => model.isolateObjects(viewer.selected));
34
28
 
35
29
  viewer.update();
36
30
  viewer.emitEvent({ type: "isolate" });
@@ -22,8 +22,16 @@
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
24
  import type { Viewer } from "../Viewer";
25
+ import type { SelectionComponent } from "../components/SelectionComponent";
25
26
 
26
27
  export function selectModel(viewer: Viewer, handle: string): void {
27
- console.warn("selectModel not implemented");
28
+ const selection = viewer.getComponent("SelectionComponent") as SelectionComponent;
29
+ selection.clearSelection();
30
+
31
+ viewer.models
32
+ .filter((model) => model.handle === handle)
33
+ .forEach((model) => selection.select(model.getObjects(), model));
34
+
35
+ viewer.update();
28
36
  viewer.emit({ type: "select", data: [] });
29
37
  }
@@ -22,20 +22,18 @@
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
24
  import type { Viewer } from "../Viewer";
25
+ import type { SelectionComponent } from "../components/SelectionComponent";
25
26
 
26
27
  export function setSelected(viewer: Viewer, handles: string[] = []): void {
27
- const handleSet = new Set(handles);
28
- const objects = [];
29
- viewer.scene.traverseVisible((child) => {
30
- if (handleSet.has(child.userData?.handle)) objects.push(child);
31
- });
32
-
33
- const selection: any = viewer.getComponent("SelectionComponent");
34
- if (!selection) return;
35
-
28
+ const selection = viewer.getComponent("SelectionComponent") as SelectionComponent;
36
29
  selection.clearSelection();
37
- objects.forEach((object) => selection.select(object));
30
+
31
+ viewer.models.forEach((model) => {
32
+ const objects = model.getObjectsByHandles(handles);
33
+ selection.select(objects, model);
34
+ });
38
35
 
39
36
  viewer.update();
37
+ viewer.emitEvent({ type: "show" });
40
38
  viewer.emitEvent({ type: "select", data: undefined, handles });
41
39
  }
@@ -24,7 +24,7 @@
24
24
  import type { Viewer } from "../Viewer";
25
25
 
26
26
  export function showAll(viewer: Viewer): void {
27
- viewer.scene.traverse((object) => (object.visible = true));
27
+ viewer.models.forEach((model) => model.showAllObjects());
28
28
 
29
29
  viewer.update();
30
30
  viewer.emitEvent({ type: "showall" });
@@ -47,5 +47,6 @@ export class BackgroundComponent implements IComponent {
47
47
 
48
48
  syncOptions = () => {
49
49
  this.backgroundColor.setHex(0xffffff);
50
+ this.viewer.renderer.setClearColor(this.backgroundColor);
50
51
  };
51
52
  }
@@ -34,8 +34,9 @@ export class ExtentsComponent implements IComponent {
34
34
  this.viewer.addEventListener("databasechunk", this.syncExtents);
35
35
  this.viewer.addEventListener("clear", this.syncExtents);
36
36
  this.viewer.on("explode", this.syncExtents);
37
- this.viewer.on("isolate", this.syncExtents);
38
37
  this.viewer.on("hide", this.syncExtents);
38
+ this.viewer.on("isolate", this.syncExtents);
39
+ this.viewer.on("show", this.syncExtents);
39
40
  this.viewer.on("showall", this.syncExtents);
40
41
  }
41
42
 
@@ -43,14 +44,15 @@ export class ExtentsComponent implements IComponent {
43
44
  this.viewer.removeEventListener("databasechunk", this.syncExtents);
44
45
  this.viewer.removeEventListener("clear", this.syncExtents);
45
46
  this.viewer.off("explode", this.syncExtents);
46
- this.viewer.off("isolate", this.syncExtents);
47
47
  this.viewer.off("hide", this.syncExtents);
48
+ this.viewer.off("isolate", this.syncExtents);
49
+ this.viewer.off("show", this.syncExtents);
48
50
  this.viewer.off("showall", this.syncExtents);
49
51
  }
50
52
 
51
53
  syncExtents = () => {
52
54
  const extents = new Box3();
53
- this.viewer.scene.traverseVisible((object) => !object.children.length && extents.expandByObject(object));
55
+ this.viewer.models.forEach((model) => model.getExtents(extents));
54
56
 
55
57
  this.viewer.extents.copy(extents);
56
58
  };
@@ -21,7 +21,17 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { Color, EdgesGeometry, LineBasicMaterial, MeshBasicMaterial, Vector2 } from "three";
24
+ import {
25
+ Color,
26
+ EdgesGeometry,
27
+ LineBasicMaterial,
28
+ MeshBasicMaterial,
29
+ Object3D,
30
+ RGBAFormat,
31
+ UnsignedByteType,
32
+ Vector2,
33
+ WebGLRenderTarget,
34
+ } from "three";
25
35
  import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeometry.js";
26
36
  import { Wireframe } from "three/examples/jsm/lines/Wireframe.js";
27
37
  import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
@@ -32,6 +42,7 @@ import { HighlighterUtils } from "./HighlighterUtils";
32
42
 
33
43
  export class HighlighterComponent implements IComponent {
34
44
  protected viewer: Viewer;
45
+ public renderTarget: WebGLRenderTarget;
35
46
  public highlightMaterial: MeshBasicMaterial;
36
47
  public outlineMaterial: LineMaterial;
37
48
  public highlightLineMaterial: LineBasicMaterial;
@@ -40,6 +51,17 @@ export class HighlighterComponent implements IComponent {
40
51
  constructor(viewer: Viewer) {
41
52
  this.viewer = viewer;
42
53
 
54
+ const gl2 = viewer.canvas.getContext("webgl2");
55
+ if (gl2) {
56
+ const size = viewer.renderer.getSize(new Vector2());
57
+ this.renderTarget = new WebGLRenderTarget(size.x, size.y, {
58
+ format: RGBAFormat,
59
+ stencilBuffer: false,
60
+ samples: 4,
61
+ type: UnsignedByteType,
62
+ });
63
+ }
64
+
43
65
  this.viewer.addEventListener("databasechunk", this.geometryEnd);
44
66
  this.viewer.addEventListener("optionschange", this.optionsChange);
45
67
  this.viewer.addEventListener("resize", this.viewerResize);
@@ -53,54 +75,64 @@ export class HighlighterComponent implements IComponent {
53
75
  this.viewer.removeEventListener("resize", this.viewerResize);
54
76
  }
55
77
 
56
- highlight(object: any) {
57
- if (object.isHighlighted) return;
58
-
59
- if (object.isLine || object.isLineSegments) {
60
- const positions = object.geometry.attributes.position.array;
61
- const indices = object.geometry.index ? object.geometry.index.array : null;
62
- const lineGeometry = indices
63
- ? HighlighterUtils.fromIndexedLine(positions, indices)
64
- : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
65
-
66
- const wireframe = new Wireframe(lineGeometry, this.highlightLineGlowMaterial);
67
- wireframe.position.copy(object.position);
68
- wireframe.rotation.copy(object.rotation);
69
- wireframe.scale.copy(object.scale);
70
-
71
- object.parent.add(wireframe);
72
-
73
- object.userData.highlightwireframe = wireframe;
74
- object.userData.originalMaterial = object.material;
75
- object.material = this.highlightLineMaterial;
76
- object.isHighlighted = true;
77
- } else if (object.isMesh) {
78
- const edgesGeometry = new EdgesGeometry(object.geometry, 30);
79
- const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
80
-
81
- const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
82
- wireframe.position.copy(object.position);
83
- wireframe.rotation.copy(object.rotation);
84
- wireframe.scale.copy(object.scale);
85
-
86
- object.parent.add(wireframe);
87
-
88
- object.userData.highlightwireframe = wireframe;
89
- object.userData.originalMaterial = object.material;
90
- object.material = this.highlightMaterial;
91
- object.isHighlighted = true;
92
- }
78
+ highlight(objects: Object3D | Object3D[]) {
79
+ if (!Array.isArray(objects)) objects = [objects];
80
+ if (!objects.length) return;
81
+
82
+ objects.forEach((object: any) => {
83
+ if (object.isHighlighted) return;
84
+
85
+ if (object.isLine || object.isLineSegments) {
86
+ const positions = object.geometry.attributes.position.array;
87
+ const indices = object.geometry.index ? object.geometry.index.array : null;
88
+ const lineGeometry = indices
89
+ ? HighlighterUtils.fromIndexedLine(positions, indices)
90
+ : HighlighterUtils.fromNonIndexedLine(positions, object.isLineSegments);
91
+
92
+ const wireframe = new Wireframe(lineGeometry, this.highlightLineGlowMaterial);
93
+ wireframe.position.copy(object.position);
94
+ wireframe.rotation.copy(object.rotation);
95
+ wireframe.scale.copy(object.scale);
96
+
97
+ object.parent.add(wireframe);
98
+
99
+ object.userData.highlightwireframe = wireframe;
100
+ object.userData.originalMaterial = object.material;
101
+ object.material = this.highlightLineMaterial;
102
+ object.isHighlighted = true;
103
+ } else if (object.isMesh) {
104
+ const edgesGeometry = new EdgesGeometry(object.geometry, 30);
105
+ const lineGeometry = new LineSegmentsGeometry().fromEdgesGeometry(edgesGeometry);
106
+
107
+ const wireframe = new Wireframe(lineGeometry, this.outlineMaterial);
108
+ wireframe.position.copy(object.position);
109
+ wireframe.rotation.copy(object.rotation);
110
+ wireframe.scale.copy(object.scale);
111
+
112
+ object.parent.add(wireframe);
113
+
114
+ object.userData.highlightwireframe = wireframe;
115
+ object.userData.originalMaterial = object.material;
116
+ object.material = this.highlightMaterial;
117
+ object.isHighlighted = true;
118
+ }
119
+ });
93
120
  }
94
121
 
95
- unhighlight(object: any) {
96
- if (!object.isHighlighted) return;
122
+ unhighlight(objects: Object3D | Object3D[]) {
123
+ if (!Array.isArray(objects)) objects = [objects];
124
+ if (!objects.length) return;
97
125
 
98
- object.isHighlighted = false;
99
- object.material = object.userData.originalMaterial;
100
- object.userData.highlightwireframe.removeFromParent();
126
+ objects.forEach((object: any) => {
127
+ if (!object.isHighlighted) return;
101
128
 
102
- delete object.userData.originalMaterial;
103
- delete object.userData.highlightwireframe;
129
+ object.isHighlighted = false;
130
+ object.material = object.userData.originalMaterial;
131
+ object.userData.highlightwireframe.removeFromParent();
132
+
133
+ delete object.userData.originalMaterial;
134
+ delete object.userData.highlightwireframe;
135
+ });
104
136
  }
105
137
 
106
138
  geometryEnd = () => {
@@ -152,8 +184,7 @@ export class HighlighterComponent implements IComponent {
152
184
  };
153
185
 
154
186
  viewerResize(event: ResizeEvent) {
155
- if (!this.outlineMaterial) return;
156
-
157
- this.outlineMaterial.resolution.set(event.width, event.height);
187
+ this.renderTarget?.setSize(event.width, event.height);
188
+ this.outlineMaterial?.resolution.set(event.width, event.height);
158
189
  }
159
190
  }
@@ -23,9 +23,10 @@
23
23
 
24
24
  import { Intersection, Object3D, Raycaster, Vector2 } from "three";
25
25
 
26
- import { IComponent } from "@inweb/viewer-core";
27
- import { Viewer } from "../Viewer";
28
- import { HighlighterComponent } from "./HighlighterComponent";
26
+ import type { IComponent } from "@inweb/viewer-core";
27
+ import type { Viewer } from "../Viewer";
28
+ import type { IModelImpl } from "../model";
29
+ import type { HighlighterComponent } from "./HighlighterComponent";
29
30
 
30
31
  export class SelectionComponent implements IComponent {
31
32
  protected viewer: Viewer;
@@ -61,12 +62,26 @@ export class SelectionComponent implements IComponent {
61
62
  if (!event.isPrimary) return;
62
63
 
63
64
  const upPosition = this.getMousePosition(event, new Vector2());
64
- if (this.downPosition.distanceTo(upPosition) !== 0) return;
65
+ if (upPosition.distanceTo(this.downPosition) !== 0) return;
65
66
 
66
- const intersects = this.getPointerIntersects(upPosition);
67
+ let intersections = [];
68
+ this.viewer.models.forEach((model) => {
69
+ const objects = model.getVisibleObjects();
70
+ const intersects = this.getPointerIntersects(upPosition, objects);
71
+ intersections.push(...intersects.map((x) => ({ ...x, model })));
72
+ });
73
+ intersections = intersections.sort((a, b) => a.distance - b.distance);
74
+
75
+ if (!event.shiftKey) this.clearSelection();
67
76
 
68
- this.clearSelection();
69
- if (intersects.length > 0) this.select(intersects[0].object);
77
+ if (intersections.length > 0) {
78
+ const model = intersections[0].model;
79
+ const handles = model.getHandlesByObjects(intersections[0].object);
80
+ const objects = model.getObjectsByHandles(handles);
81
+
82
+ if (!event.shiftKey) this.select(objects, model);
83
+ else this.toggleSelection(objects, model);
84
+ }
70
85
 
71
86
  this.viewer.update();
72
87
  this.viewer.emitEvent({ type: "select", data: undefined, handles: this.viewer.getSelected() });
@@ -82,7 +97,7 @@ export class SelectionComponent implements IComponent {
82
97
  return target.set(event.clientX, event.clientY);
83
98
  }
84
99
 
85
- getPointerIntersects(mouse: Vector2): Array<Intersection<Object3D>> {
100
+ getPointerIntersects(mouse: Vector2, objects: Object3D[]): Array<Intersection<Object3D>> {
86
101
  const rect = this.viewer.canvas.getBoundingClientRect();
87
102
  const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
88
103
  const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
@@ -90,9 +105,6 @@ export class SelectionComponent implements IComponent {
90
105
  const coords = new Vector2(x, y);
91
106
  this.raycaster.setFromCamera(coords, this.viewer.camera);
92
107
 
93
- const objects = [];
94
- this.viewer.scene.traverseVisible((child) => objects.push(child));
95
-
96
108
  this.raycaster.params = this.raycaster.params = {
97
109
  Mesh: {},
98
110
  Line: { threshold: 0.25 },
@@ -105,24 +117,58 @@ export class SelectionComponent implements IComponent {
105
117
  return this.raycaster.intersectObjects(objects, false);
106
118
  }
107
119
 
108
- select(object: any) {
109
- if (object.isSelected) return;
120
+ select(objects: Object3D | Object3D[], model?: IModelImpl) {
121
+ if (!model) {
122
+ this.viewer.models.forEach((model) => this.select(objects, model));
123
+ return;
124
+ }
125
+
126
+ if (!Array.isArray(objects)) objects = [objects];
127
+ if (!objects.length) return;
128
+
129
+ model.showObjects(objects);
130
+ model.showOriginalObjects(objects);
131
+ this.highlighter.highlight(objects);
132
+
133
+ objects.forEach((object: any) => this.viewer.selected.push(object));
134
+ objects.forEach((object: any) => (object.isSelected = true));
135
+ }
136
+
137
+ deselect(objects: Object3D | Object3D[], model?: IModelImpl) {
138
+ if (!model) {
139
+ this.viewer.models.forEach((model) => this.select(objects, model));
140
+ return;
141
+ }
142
+
143
+ if (!Array.isArray(objects)) objects = [objects];
144
+ if (!objects.length) return;
145
+
146
+ this.highlighter.unhighlight(objects);
147
+ model.hideOriginalObjects(objects);
148
+
149
+ this.viewer.selected = this.viewer.selected.filter((x) => !objects.includes(x));
150
+ objects.forEach((object: any) => (object.isSelected = false));
151
+ }
110
152
 
111
- object.isSelected = true;
112
- this.highlighter.highlight(object);
153
+ toggleSelection(objects: Object3D | Object3D[], model?: IModelImpl) {
154
+ if (!Array.isArray(objects)) objects = [objects];
155
+ if (!objects.length) return;
113
156
 
114
- this.viewer.selected.push(object);
157
+ if ((objects[0] as any).isSelected) this.deselect(objects, model);
158
+ else this.select(objects, model);
115
159
  }
116
160
 
117
161
  clearSelection() {
118
- this.viewer.selected.forEach((object: any) => {
119
- object.isSelected = false;
120
- this.highlighter.unhighlight(object);
121
- });
162
+ if (!this.viewer.selected.length) return;
163
+
164
+ this.highlighter.unhighlight(this.viewer.selected);
165
+ this.viewer.models.forEach((model) => model.hideOriginalObjects(this.viewer.selected));
166
+
167
+ this.viewer.selected.forEach((object: any) => (object.isSelected = false));
122
168
  this.viewer.selected.length = 0;
123
169
  }
124
170
 
125
171
  initHighlighter = () => {
126
- this.highlighter = this.viewer.getComponent("HighlighterComponent") as any;
172
+ this.highlighter = this.viewer.getComponent("HighlighterComponent") as HighlighterComponent;
127
173
  };
128
174
  }
@@ -62,13 +62,17 @@ export class CuttingPlaneDragger extends OrbitDragger {
62
62
  this.transform.addEventListener("dragging-changed", this.transformDrag);
63
63
  this.viewer.helpers.add(this.transform.getHelper());
64
64
 
65
- this.viewer.on("explode", this.viewerExplode);
65
+ this.viewer.on("explode", this.updatePlaneSize);
66
+ this.viewer.on("show", this.updatePlaneSize);
67
+ this.viewer.on("showall", this.updatePlaneSize);
66
68
  this.viewer.canvas.addEventListener("dblclick", this.onDoubleClick, true);
67
69
  this.viewer.update();
68
70
  }
69
71
 
70
72
  override dispose() {
71
- this.viewer.off("explode", this.viewerExplode);
73
+ this.viewer.off("explode", this.updatePlaneSize);
74
+ this.viewer.off("show", this.updatePlaneSize);
75
+ this.viewer.off("showAll", this.updatePlaneSize);
72
76
  this.viewer.canvas.removeEventListener("dblclick", this.onDoubleClick, true);
73
77
 
74
78
  this.transform.removeEventListener("change", this.transformChange);
@@ -97,7 +101,7 @@ export class CuttingPlaneDragger extends OrbitDragger {
97
101
  this.orbit.enabled = !event.value;
98
102
  };
99
103
 
100
- viewerExplode = () => {
104
+ updatePlaneSize = () => {
101
105
  this.planeHelper.size = this.viewer.extents.getSize(new Vector3()).length();
102
106
  this.viewer.update();
103
107
  };
@@ -54,6 +54,7 @@ export class MeasureLineDragger extends OrbitDragger {
54
54
  this.viewer.addEventListener("render", this.renderOverlay);
55
55
  this.viewer.addEventListener("hide", this.updateSnapper);
56
56
  this.viewer.addEventListener("isolate", this.updateSnapper);
57
+ this.viewer.addEventListener("show", this.updateSnapper);
57
58
  this.viewer.addEventListener("showall", this.updateSnapper);
58
59
  }
59
60
 
@@ -67,6 +68,7 @@ export class MeasureLineDragger extends OrbitDragger {
67
68
  this.viewer.removeEventListener("render", this.renderOverlay);
68
69
  this.viewer.removeEventListener("hide", this.updateSnapper);
69
70
  this.viewer.removeEventListener("isolate", this.updateSnapper);
71
+ this.viewer.removeEventListener("show", this.updateSnapper);
70
72
  this.viewer.removeEventListener("showall", this.updateSnapper);
71
73
 
72
74
  this.overlay.detach();