@inweb/viewer-three 26.10.6 → 26.11.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.
Files changed (143) hide show
  1. package/README.md +7 -4
  2. package/dist/{plugins → extensions}/components/AxesHelperComponent.js +23 -1
  3. package/dist/extensions/components/AxesHelperComponent.js.map +1 -0
  4. package/dist/extensions/components/AxesHelperComponent.min.js +24 -0
  5. package/dist/{plugins → extensions}/components/AxesHelperComponent.module.js +24 -2
  6. package/dist/extensions/components/AxesHelperComponent.module.js.map +1 -0
  7. package/dist/{plugins → extensions}/components/ExtentsHelperComponent.js +18 -0
  8. package/dist/extensions/components/ExtentsHelperComponent.js.map +1 -0
  9. package/dist/{plugins/components/AxesHelperComponent.min.js → extensions/components/ExtentsHelperComponent.min.js} +1 -1
  10. package/dist/{plugins → extensions}/components/ExtentsHelperComponent.module.js +19 -1
  11. package/dist/extensions/components/ExtentsHelperComponent.module.js.map +1 -0
  12. package/dist/extensions/components/GridHelperComponent.js.map +1 -0
  13. package/dist/extensions/components/GridHelperComponent.module.js.map +1 -0
  14. package/dist/extensions/components/LightHelperComponent.js.map +1 -0
  15. package/dist/extensions/components/LightHelperComponent.module.js.map +1 -0
  16. package/dist/extensions/components/RoomEnvironmentComponent.js.map +1 -0
  17. package/dist/extensions/components/RoomEnvironmentComponent.module.js.map +1 -0
  18. package/dist/extensions/components/StatsPanelComponent.js.map +1 -0
  19. package/dist/extensions/components/StatsPanelComponent.module.js.map +1 -0
  20. package/dist/{plugins → extensions}/loaders/GLTFCloudLoader.js +2 -3
  21. package/dist/extensions/loaders/GLTFCloudLoader.js.map +1 -0
  22. package/dist/{plugins → extensions}/loaders/GLTFCloudLoader.min.js +1 -1
  23. package/dist/{plugins → extensions}/loaders/GLTFCloudLoader.module.js +2 -3
  24. package/dist/extensions/loaders/GLTFCloudLoader.module.js.map +1 -0
  25. package/dist/extensions/loaders/GLTFFileLoader.js +2499 -0
  26. package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -0
  27. package/dist/extensions/loaders/GLTFFileLoader.min.js +24 -0
  28. package/dist/extensions/loaders/GLTFFileLoader.module.js +74 -0
  29. package/dist/extensions/loaders/GLTFFileLoader.module.js.map +1 -0
  30. package/dist/{plugins → extensions}/loaders/IFCXLoader.js +5 -7
  31. package/dist/extensions/loaders/IFCXLoader.js.map +1 -0
  32. package/dist/{plugins → extensions}/loaders/IFCXLoader.min.js +1 -1
  33. package/dist/{plugins → extensions}/loaders/IFCXLoader.module.js +5 -7
  34. package/dist/extensions/loaders/IFCXLoader.module.js.map +1 -0
  35. package/dist/{plugins → extensions}/loaders/PotreeLoader.js +1 -2
  36. package/dist/extensions/loaders/PotreeLoader.js.map +1 -0
  37. package/dist/{plugins → extensions}/loaders/PotreeLoader.min.js +1 -1
  38. package/dist/{plugins → extensions}/loaders/PotreeLoader.module.js +1 -2
  39. package/dist/extensions/loaders/PotreeLoader.module.js.map +1 -0
  40. package/dist/viewer-three.js +1015 -2926
  41. package/dist/viewer-three.js.map +1 -1
  42. package/dist/viewer-three.min.js +3 -3
  43. package/dist/viewer-three.module.js +847 -356
  44. package/dist/viewer-three.module.js.map +1 -1
  45. package/{plugins → extensions}/components/AxesHelperComponent.ts +31 -2
  46. package/{plugins → extensions}/components/ExtentsHelperComponent.ts +25 -0
  47. package/{plugins → extensions}/loaders/GLTFCloudLoader.ts +2 -3
  48. package/{src/Viewer → extensions}/loaders/GLTFFileLoader.ts +21 -12
  49. package/{plugins → extensions}/loaders/IFCX/IFCXCloudLoader.ts +5 -5
  50. package/{plugins → extensions}/loaders/IFCX/IFCXFileLoader.ts +3 -4
  51. package/{plugins → extensions}/loaders/Potree/PotreeFileLoader.ts +3 -4
  52. package/lib/Viewer/Viewer.d.ts +27 -20
  53. package/lib/Viewer/commands/GetSelected2.d.ts +2 -0
  54. package/lib/Viewer/commands/SelectModel.d.ts +1 -1
  55. package/lib/Viewer/commands/SetSelected2.d.ts +2 -0
  56. package/lib/Viewer/components/SelectionComponent.d.ts +1 -3
  57. package/lib/Viewer/components/index.d.ts +6 -6
  58. package/lib/Viewer/draggers/MeasureLineDragger.d.ts +7 -1
  59. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +0 -1
  60. package/lib/Viewer/loaders/GLTFBinaryExtension.d.ts +5 -0
  61. package/lib/Viewer/loaders/GLTFCloudDynamicLoader.d.ts +2 -2
  62. package/lib/Viewer/loaders/{GLTFFileLoader.d.ts → GLTFFileDynamicLoader.d.ts} +7 -1
  63. package/lib/Viewer/loaders/GLTFLoadingManager.d.ts +4 -3
  64. package/lib/Viewer/loaders/RangesLoader.d.ts +15 -0
  65. package/lib/Viewer/loaders/index.d.ts +22 -14
  66. package/lib/Viewer/measurement/Snapper.d.ts +15 -0
  67. package/lib/Viewer/measurement/UnitConverter.d.ts +63 -0
  68. package/lib/Viewer/measurement/UnitFormatter.d.ts +4 -0
  69. package/lib/Viewer/models/IModelImpl.d.ts +10 -8
  70. package/lib/Viewer/models/ModelImpl.d.ts +7 -5
  71. package/package.json +11 -11
  72. package/src/Viewer/Viewer.ts +120 -88
  73. package/src/Viewer/commands/ClearSelected.ts +3 -1
  74. package/src/Viewer/commands/GetModels.ts +1 -1
  75. package/src/Viewer/commands/GetSelected.ts +2 -2
  76. package/src/Viewer/commands/GetSelected2.ts +34 -0
  77. package/src/Viewer/commands/HideSelected.ts +3 -1
  78. package/src/Viewer/commands/SelectModel.ts +5 -5
  79. package/src/Viewer/commands/SetSelected.ts +9 -10
  80. package/src/Viewer/commands/SetSelected2.ts +42 -0
  81. package/src/Viewer/commands/ZoomToObjects.ts +5 -6
  82. package/src/Viewer/commands/ZoomToSelected.ts +3 -1
  83. package/src/Viewer/commands/index.ts +4 -0
  84. package/src/Viewer/components/CameraComponent.ts +6 -1
  85. package/src/Viewer/components/ExtentsComponent.ts +4 -1
  86. package/src/Viewer/components/SelectionComponent.ts +7 -30
  87. package/src/Viewer/components/index.ts +6 -6
  88. package/src/Viewer/draggers/MeasureLineDragger.ts +84 -226
  89. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +263 -34
  90. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +20 -10
  91. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +4 -1
  92. package/src/Viewer/loaders/GLTFBinaryExtension.ts +91 -0
  93. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +13 -19
  94. package/src/Viewer/loaders/GLTFFileDynamicLoader.ts +145 -0
  95. package/src/Viewer/loaders/GLTFLoadingManager.ts +5 -4
  96. package/src/Viewer/loaders/RangesLoader.ts +95 -0
  97. package/src/Viewer/loaders/index.ts +24 -16
  98. package/src/Viewer/measurement/Snapper.ts +208 -0
  99. package/src/Viewer/measurement/UnitConverter.ts +47 -0
  100. package/src/Viewer/measurement/UnitFormatter.ts +95 -0
  101. package/src/Viewer/models/IModelImpl.ts +15 -8
  102. package/src/Viewer/models/ModelImpl.ts +48 -17
  103. package/src/index-umd.ts +1 -1
  104. package/dist/plugins/components/AxesHelperComponent.js.map +0 -1
  105. package/dist/plugins/components/AxesHelperComponent.module.js.map +0 -1
  106. package/dist/plugins/components/ExtentsHelperComponent.js.map +0 -1
  107. package/dist/plugins/components/ExtentsHelperComponent.min.js +0 -24
  108. package/dist/plugins/components/ExtentsHelperComponent.module.js.map +0 -1
  109. package/dist/plugins/components/GridHelperComponent.js.map +0 -1
  110. package/dist/plugins/components/GridHelperComponent.module.js.map +0 -1
  111. package/dist/plugins/components/LightHelperComponent.js.map +0 -1
  112. package/dist/plugins/components/LightHelperComponent.module.js.map +0 -1
  113. package/dist/plugins/components/RoomEnvironmentComponent.js.map +0 -1
  114. package/dist/plugins/components/RoomEnvironmentComponent.module.js.map +0 -1
  115. package/dist/plugins/components/StatsPanelComponent.js.map +0 -1
  116. package/dist/plugins/components/StatsPanelComponent.module.js.map +0 -1
  117. package/dist/plugins/loaders/GLTFCloudLoader.js.map +0 -1
  118. package/dist/plugins/loaders/GLTFCloudLoader.module.js.map +0 -1
  119. package/dist/plugins/loaders/IFCXLoader.js.map +0 -1
  120. package/dist/plugins/loaders/IFCXLoader.module.js.map +0 -1
  121. package/dist/plugins/loaders/PotreeLoader.js.map +0 -1
  122. package/dist/plugins/loaders/PotreeLoader.module.js.map +0 -1
  123. /package/dist/{plugins → extensions}/components/GridHelperComponent.js +0 -0
  124. /package/dist/{plugins → extensions}/components/GridHelperComponent.min.js +0 -0
  125. /package/dist/{plugins → extensions}/components/GridHelperComponent.module.js +0 -0
  126. /package/dist/{plugins → extensions}/components/LightHelperComponent.js +0 -0
  127. /package/dist/{plugins → extensions}/components/LightHelperComponent.min.js +0 -0
  128. /package/dist/{plugins → extensions}/components/LightHelperComponent.module.js +0 -0
  129. /package/dist/{plugins → extensions}/components/RoomEnvironmentComponent.js +0 -0
  130. /package/dist/{plugins → extensions}/components/RoomEnvironmentComponent.min.js +0 -0
  131. /package/dist/{plugins → extensions}/components/RoomEnvironmentComponent.module.js +0 -0
  132. /package/dist/{plugins → extensions}/components/StatsPanelComponent.js +0 -0
  133. /package/dist/{plugins → extensions}/components/StatsPanelComponent.min.js +0 -0
  134. /package/dist/{plugins → extensions}/components/StatsPanelComponent.module.js +0 -0
  135. /package/{plugins → extensions}/components/GridHelperComponent.ts +0 -0
  136. /package/{plugins → extensions}/components/LightHelperComponent.ts +0 -0
  137. /package/{plugins → extensions}/components/RoomEnvironmentComponent.ts +0 -0
  138. /package/{plugins → extensions}/components/StatsPanelComponent.ts +0 -0
  139. /package/{plugins → extensions}/loaders/IFCX/IFCXLoader.ts +0 -0
  140. /package/{plugins → extensions}/loaders/IFCX/index.ts +0 -0
  141. /package/{plugins → extensions}/loaders/IFCX/render.js +0 -0
  142. /package/{plugins → extensions}/loaders/Potree/PotreeModelImpl.ts +0 -0
  143. /package/{plugins → extensions}/loaders/Potree/index.ts +0 -0
@@ -6,29 +6,30 @@ import { ILoadersRegistry } from "@inweb/viewer-core";
6
6
  *
7
7
  * 1. Define a loader class implements {@link ILoader}.
8
8
  * 2. Define a constructor with a `viewer` parameter.
9
- * 3. Override {@link ILoader.isSupport} and сheck if the loader can load the specified file.
9
+ * 3. Override {@link ILoader.isSupport} and check if the loader can load the specified file.
10
10
  * 4. Override {@link ILoader.load} and define the logic for loading the scene from the file.
11
11
  *
12
12
  * The loader should do:
13
13
  *
14
14
  * - Load raw data from file and convert it to the `Three.js` scene.
15
15
  * - Add scene to the viewer `scene`.
16
- * - Create `ModelImpl` for the scene and to the viewer `models` list.
16
+ * - Create `ModelImpl` instance with unique model ID add it to the viewer `models` list.
17
17
  * - Synchronize viewer options and overlay.
18
18
  * - Update the viewer.
19
19
  *
20
20
  * The loader must emit events:
21
21
  *
22
- * - `geometryprogress` - during loading. If progress is not supported, emit it once with a value of 100%
23
- * after the load is complete.
22
+ * - `geometryprogress` - during loading (or once at 100% when complete).
24
23
  * - `databasechunk` - when scene is loaded and ready to render.
25
24
  * 5. Override {@link ILoader.dispose} and release loader resources, if required.
26
- * 6. Register loader provider in the loaders registry by calling the {@link loaders.registerLoader}.
25
+ * 6. Use `this.abortController` (defined in `Loader` class) to abort loading raw data.
26
+ * 7. Register loader provider in the loaders registry by calling the {@link loaders.registerLoader}.
27
27
  *
28
28
  * @example Implementing a custom loader.
29
29
  *
30
30
  * ```javascript
31
- * import { loaders, Loader, ModelImpl, Viewer } from "@inweb/viewer-three";
31
+ * import { Scene } from "three";
32
+ * import { Loader, loaders, ModelImpl, Viewer } from "@inweb/viewer-three";
32
33
  *
33
34
  * class MyLoader extends Loader {
34
35
  * public viewer: Viewer;
@@ -39,18 +40,19 @@ import { ILoadersRegistry } from "@inweb/viewer-core";
39
40
  * }
40
41
  *
41
42
  * override isSupport(file, format): Boolean {
42
- * // place custom logic here
43
- * return ...;
43
+ * // check if this loader supports the file source and format
44
+ * return type file === "string" && format === "myformat";
44
45
  * }
45
46
  *
46
- * override load(file, format, params): Promise<this> {
47
+ * override load(file, format, params = {}): Promise<this> {
48
+ * // load raw data from file (custom loading logic)
49
+ * const data = await fetch(file).then((result) => result.arrayBuffer());
47
50
  *
48
- * // place custom loading logic here
49
- * const scene = ...;
51
+ * // convert raw data to the Three.js scene (custom parsing logic)
52
+ * const scene = this.parse(data);
50
53
  *
51
54
  * const modelImpl = new ModelImpl(scene);
52
- * modelImpl.loader = this;
53
- * modelImpl.viewer = this.viewer;
55
+ * modelImpl.id = params.modelId;
54
56
  *
55
57
  * this.viewer.scene.add(scene);
56
58
  * this.viewer.models.push(modelImpl);
@@ -59,11 +61,17 @@ import { ILoadersRegistry } from "@inweb/viewer-core";
59
61
  * this.viewer.syncOverlay();
60
62
  * this.viewer.update();
61
63
  *
64
+ * this.viewer.emitEvent({ type: "geometryprogress", data: 1, file });
62
65
  * this.viewer.emitEvent({ type: "databasechunk", data: scene, file });
63
66
  *
64
67
  * return Promise.resove(this);
65
68
  * };
66
- * }
69
+ *
70
+ * private parse(data: ArrayBuffer): Scene {
71
+ * // custom parsing logic
72
+ * return new Scene();
73
+ * }
74
+ * }
67
75
  *
68
76
  * loaders.registerLoader("MyLoader", (viewer) => new MyLoader(viewer));
69
77
  * ```
@@ -0,0 +1,15 @@
1
+ import { Camera, Intersection, Object3D, Vector2, Vector3, WebGLRenderer } from "three";
2
+ export declare class Snapper {
3
+ camera: Camera;
4
+ renderer: WebGLRenderer;
5
+ canvas: HTMLCanvasElement;
6
+ private raycaster;
7
+ private detectRadiusInPixels;
8
+ private edgesCache;
9
+ constructor(camera: Camera, renderer: WebGLRenderer, canvas: HTMLCanvasElement);
10
+ isMobile(): boolean;
11
+ getMousePosition(event: MouseEvent, target: Vector2): Vector2;
12
+ getPointerIntersects(mouse: Vector2, objects: Object3D[]): Array<Intersection<Object3D>>;
13
+ getDetectRadius(point: Vector3): number;
14
+ getSnapPoint(mouse: Vector2, objects: Object3D[]): Vector3;
15
+ }
@@ -0,0 +1,63 @@
1
+ export declare const ModelUnits: {
2
+ Meters: {
3
+ name: string;
4
+ type: string;
5
+ scale: number;
6
+ };
7
+ Centimeters: {
8
+ name: string;
9
+ type: string;
10
+ scale: number;
11
+ };
12
+ Millimeters: {
13
+ name: string;
14
+ type: string;
15
+ scale: number;
16
+ };
17
+ Feet: {
18
+ name: string;
19
+ type: string;
20
+ scale: number;
21
+ };
22
+ Inches: {
23
+ name: string;
24
+ type: string;
25
+ scale: number;
26
+ };
27
+ Yards: {
28
+ name: string;
29
+ type: string;
30
+ scale: number;
31
+ };
32
+ Kilometers: {
33
+ name: string;
34
+ type: string;
35
+ scale: number;
36
+ };
37
+ Miles: {
38
+ name: string;
39
+ type: string;
40
+ scale: number;
41
+ };
42
+ Micrometers: {
43
+ name: string;
44
+ type: string;
45
+ scale: number;
46
+ };
47
+ Mils: {
48
+ name: string;
49
+ type: string;
50
+ scale: number;
51
+ };
52
+ MicroInches: {
53
+ name: string;
54
+ type: string;
55
+ scale: number;
56
+ };
57
+ Default: {
58
+ name: string;
59
+ type: string;
60
+ scale: number;
61
+ };
62
+ };
63
+ export declare function convertUnits(fromUnits: string, toUnits: string, distance: number): number;
@@ -0,0 +1,4 @@
1
+ export declare function getDisplayUnit(units: string): any;
2
+ export declare function calculatePrecision(value: number): number;
3
+ export declare function calculateDistance(precision: any): number;
4
+ export declare function formatDistance(distance: number, units: string, precision?: any): string;
@@ -1,19 +1,21 @@
1
1
  import { Box3, Object3D } from "three";
2
- import { ILoader, IViewer } from "@inweb/viewer-core";
2
+ import { IModel } from "@inweb/viewer-core";
3
3
  /**
4
- * Model interface.
4
+ * Basic model implementation.
5
5
  */
6
- export interface IModelImpl {
7
- handle: string;
6
+ export interface IModelImpl extends IModel {
8
7
  scene: Object3D;
9
- loader: ILoader;
10
- viewer: IViewer;
11
- dispose(): void;
8
+ getUnits(): string;
9
+ getUnitScale(): number;
10
+ getUnitString(): string;
11
+ getPrecision(): number;
12
12
  getExtents(target: Box3): Box3;
13
13
  getObjects(): Object3D[];
14
14
  getVisibleObjects(): Object3D[];
15
- hasObject(objects: Object3D): boolean;
15
+ hasObject(object: Object3D): boolean;
16
+ hasHandle(handle: string): boolean;
16
17
  getOwnObjects(objects: Object3D | Object3D[]): Object3D[];
18
+ getOwnHandles(handles: string | string[]): string[];
17
19
  getObjectsByHandles(handles: string | string[]): Object3D[];
18
20
  getHandlesByObjects(objects: Object3D | Object3D[]): string[];
19
21
  hideObjects(objects: Object3D | Object3D[]): this;
@@ -1,19 +1,21 @@
1
1
  import { Box3, Object3D } from "three";
2
- import { ILoader } from "@inweb/viewer-core";
3
2
  import { IModelImpl } from "./IModelImpl";
4
- import { Viewer } from "../Viewer";
5
3
  export declare class ModelImpl implements IModelImpl {
6
- handle: string;
4
+ id: string;
7
5
  scene: Object3D;
8
- loader: ILoader;
9
- viewer: Viewer;
10
6
  constructor(scene: Object3D);
11
7
  dispose(): void;
8
+ getUnits(): string;
9
+ getUnitScale(): number;
10
+ getUnitString(): string;
11
+ getPrecision(): number;
12
12
  getExtents(target: Box3): Box3;
13
13
  getObjects(): Object3D[];
14
14
  getVisibleObjects(): Object3D[];
15
15
  hasObject(object: Object3D): boolean;
16
+ hasHandle(handle: string): boolean;
16
17
  getOwnObjects(objects: Object3D | Object3D[]): Object3D[];
18
+ getOwnHandles(handles: string | string[]): string[];
17
19
  getObjectsByHandles(handles: string | string[]): Object3D[];
18
20
  getHandlesByObjects(objects: Object3D | Object3D[]): string[];
19
21
  hideObjects(objects: Object3D | Object3D[]): this;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inweb/viewer-three",
3
- "version": "26.10.6",
3
+ "version": "26.11.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",
@@ -14,7 +14,7 @@
14
14
  "three.js"
15
15
  ],
16
16
  "sideEffects": [
17
- "dist/plugins/**/*"
17
+ "dist/extensions/**/*"
18
18
  ],
19
19
  "main": "dist/viewer-three.js",
20
20
  "module": "dist/viewer-three.module.js",
@@ -23,22 +23,22 @@
23
23
  "dist",
24
24
  "lib/**/*.d.ts",
25
25
  "src",
26
- "plugins"
26
+ "extensions"
27
27
  ],
28
28
  "scripts": {
29
- "build": "npm run build:viewer && npm run build:plugins",
29
+ "build": "npm run build:viewer && npm run build:extensions",
30
30
  "build:viewer": "rollup -c rollup.config.js",
31
- "build:plugins": "rollup -c rollup.plugins.config.js",
32
- "test": "npm run test:viewer && npm run test:plugins",
31
+ "build:extensions": "rollup -c rollup.extensions.config.js",
32
+ "test": "npm run test:viewer && npm run test:extensions",
33
33
  "test:viewer": "karma start karma.conf.js",
34
- "test:plugins": "karma start karma.plugins.conf.js",
34
+ "test:extensions": "karma start karma.extensions.conf.js",
35
35
  "docs": "typedoc"
36
36
  },
37
37
  "dependencies": {
38
- "@inweb/client": "~26.10.6",
39
- "@inweb/eventemitter2": "~26.10.6",
40
- "@inweb/markup": "~26.10.6",
41
- "@inweb/viewer-core": "~26.10.6"
38
+ "@inweb/client": "~26.11.0",
39
+ "@inweb/eventemitter2": "~26.11.0",
40
+ "@inweb/markup": "~26.11.0",
41
+ "@inweb/viewer-core": "~26.11.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/three": "^0.180.0",
@@ -50,8 +50,8 @@ import {
50
50
  FileSource,
51
51
  IClippingPlane,
52
52
  IComponent,
53
- IEntity,
54
53
  IDragger,
54
+ IEntity,
55
55
  ILoader,
56
56
  IOptions,
57
57
  IOrthogonalCamera,
@@ -80,12 +80,13 @@ export class Viewer
80
80
  implements IViewer, IWorldTransform
81
81
  {
82
82
  public client: Client | undefined;
83
- protected _options: Options;
84
-
85
- private canvaseventlistener: (event: any) => void;
86
-
83
+ public options: IOptions;
87
84
  public canvas: HTMLCanvasElement | undefined;
88
85
  public canvasEvents: string[];
86
+ public loaders: ILoader[];
87
+ public models: IModelImpl[];
88
+
89
+ private canvaseventlistener: (event: any) => void;
89
90
 
90
91
  public scene: Scene | undefined;
91
92
  public helpers: Helpers | undefined;
@@ -98,9 +99,6 @@ export class Viewer
98
99
  public ssaaRenderPass: SSAARenderPass | undefined;
99
100
  public outputPass: OutputPass | undefined;
100
101
  public composer: EffectComposer | undefined;
101
-
102
- public loaders: ILoader[];
103
- public models: IModelImpl[];
104
102
  public selected: Object3D[];
105
103
  public extents: Box3;
106
104
  public target: Vector3;
@@ -120,22 +118,22 @@ export class Viewer
120
118
  */
121
119
  constructor(client?: Client) {
122
120
  super();
123
- this._options = new Options(this);
124
-
125
121
  this.client = client;
122
+ this.options = new Options(this);
123
+ this.loaders = [];
124
+ this.models = [];
126
125
 
127
- this.canvasEvents = CANVAS_EVENTS;
126
+ this.canvasEvents = CANVAS_EVENTS.slice();
128
127
  this.canvaseventlistener = (event: Event) => this.emit(event);
129
128
 
130
- this.loaders = [];
131
- this.models = [];
132
129
  this.selected = [];
133
130
  this.extents = new Box3();
134
- this.target = new Vector3();
131
+ this.target = new Vector3(0, 0, 0);
135
132
 
136
133
  this._activeDragger = null;
137
134
  this._components = [];
138
135
 
136
+ this._renderNeeded = false;
139
137
  this._renderTime = 0;
140
138
 
141
139
  this.render = this.render.bind(this);
@@ -144,10 +142,17 @@ export class Viewer
144
142
  this._markup = new Markup();
145
143
  }
146
144
 
147
- get options(): IOptions {
148
- return this._options;
145
+ /**
146
+ * 2D markup core instance used to create markups.
147
+ *
148
+ * @readonly
149
+ */
150
+ get markup(): IMarkup {
151
+ return this._markup;
149
152
  }
150
153
 
154
+ // IViewer
155
+
151
156
  get draggers(): string[] {
152
157
  return [...draggers.getDraggers().keys()];
153
158
  }
@@ -156,21 +161,11 @@ export class Viewer
156
161
  return [...components.getComponents().keys()];
157
162
  }
158
163
 
159
- /**
160
- * 2D markup core instance used to create markups.
161
- *
162
- * @readonly
163
- */
164
- get markup(): IMarkup {
165
- return this._markup;
166
- }
167
-
168
164
  initialize(canvas: HTMLCanvasElement, onProgress?: (event: ProgressEvent<EventTarget>) => void): Promise<this> {
169
165
  this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
170
166
 
171
167
  this.scene = new Scene();
172
168
  this.helpers = new Helpers();
173
- this.target = new Vector3(0, 0, 0);
174
169
 
175
170
  const pixelRatio = window.devicePixelRatio;
176
171
  const rect = canvas.parentElement.getBoundingClientRect();
@@ -319,6 +314,8 @@ export class Viewer
319
314
  this.emitEvent({ type: "update", data: force });
320
315
  }
321
316
 
317
+ // Internal render routines
318
+
322
319
  render(time?: DOMHighResTimeStamp, force = false): void {
323
320
  if (!this.renderer) return;
324
321
  if (!this._renderNeeded && !force) return;
@@ -341,6 +338,8 @@ export class Viewer
341
338
  this.emitEvent({ type: "render", time, deltaTime });
342
339
  }
343
340
 
341
+ // Internal loading routines
342
+
344
343
  loadReferences(model: Model | File | Assembly): Promise<this> {
345
344
  // todo: load reference as text fonts
346
345
  return Promise.resolve(this);
@@ -357,18 +356,20 @@ export class Viewer
357
356
  * exception will be thrown.
358
357
  *
359
358
  * For files from Open Cloud Server, the default model will be loaded. If there is no default model,
360
- * first availiable model will be loaded. If no models are found in the file, an exception will be
359
+ * the first available model will be loaded. If no models are found in the file, an exception will be
361
360
  * thrown.
362
361
  *
363
362
  * For URLs, the file extension is used to determine the file format. For a `ArrayBuffer` and `Data
364
- * URL`, a file format must be specified using `params.format` parameter (see below). If no appropriate
365
- * loader is found for the specified format, an exception will be thrown.
363
+ * URL`, a file format must be specified using `params.format` parameter. If no appropriate loader is
364
+ * found for the specified format, an exception will be thrown.
366
365
  *
367
366
  * If there was an active dragger before opening the file, it will be deactivated. After opening the
368
367
  * file, you must manually activate the required dragger.
369
368
  *
370
369
  * Fires:
371
370
  *
371
+ * - {@link CancelEvent | cancel}
372
+ * - {@link ClearEvent | clear}
372
373
  * - {@link OpenEvent | open}
373
374
  * - {@link GeometryStartEvent | geometrystart}
374
375
  * - {@link GeometryProgressEvent | geometryprogress}
@@ -377,23 +378,26 @@ export class Viewer
377
378
  * - {@link GeometryEndEvent | geometryend}
378
379
  * - {@link GeometryErrorEvent | geometryerror}
379
380
  *
380
- * @param file - File to load. Can be one of:
381
+ * @param file - File to load. Can be:
381
382
  *
382
383
  * - `File`, `Assembly` or `Model` instance from the Open Cloud Server
383
- * - File `URL` string
384
+ * - `URL` string
384
385
  * - {@link https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs | Data URL} string
385
386
  * - {@link https://developer.mozilla.org/docs/Web/API/File | Web API File} object
386
387
  * - {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer | ArrayBuffer}
387
388
  * object
388
389
  *
389
390
  * @param params - Loading parameters.
390
- * @param params.format - File format string. Required when loading a file as `ArrayBuffer` or `Data
391
- * URL`.
391
+ * @param params.format - File format. Can be `gltf`, `glb` or format from an extension. Required when
392
+ * loading a file as `ArrayBuffer` or `Data URL`.
392
393
  * @param params.mode - File opening mode. Can be one of:
393
394
  *
394
- * - `open` - Unloads an open file and opens a new one. This is default mode.
395
- * - `append` - Appends a file to an already open file.
395
+ * - `file` - Single file mode. Unloads an open file and opens a new one. This is default mode.
396
+ * - `assembly` - Assembly mode. Appends a file to an already open file.
396
397
  *
398
+ * @param params.modelId - Unique model ID in the assembly (multi-model scene). Used as a model prefix
399
+ * when selecting objects (see {@link getSelected2}). Must not contain the ":" (colon). Required when
400
+ * loading a file as `ArrayBuffer` or `Data URL`.
397
401
  * @param params.requestHeader - The
398
402
  * {@link https://developer.mozilla.org/docs/Glossary/Request_header | request header} used in HTTP
399
403
  * request.
@@ -415,6 +419,7 @@ export class Viewer
415
419
  params: {
416
420
  format?: string;
417
421
  mode?: string;
422
+ modelId?: string;
418
423
  requestHeader?: HeadersInit;
419
424
  withCredentials?: boolean;
420
425
  path?: string;
@@ -424,22 +429,27 @@ export class Viewer
424
429
  ): Promise<this> {
425
430
  if (!this.renderer) return this;
426
431
 
427
- if (params.mode !== "a" && params.mode !== "append") {
432
+ const mode = params.mode || "file";
433
+
434
+ if (mode !== "assembly" && mode !== "a" && mode !== "append") {
428
435
  this.cancel();
429
436
  this.clear();
430
437
  }
431
438
 
432
- this.emitEvent({ type: "open", file });
439
+ this.emitEvent({ type: "open", mode, file });
433
440
 
434
441
  let model: any = file;
435
442
  if (model && typeof model.getModels === "function") {
436
443
  const models = await model.getModels();
437
444
  model = models.find((model: Model) => model.default) || models[0] || file;
438
445
  }
446
+ if (model && typeof model.database === "string") {
447
+ file = model.file;
448
+ }
439
449
  if (!model) throw new Error(`Format not supported`);
440
450
 
441
451
  let format = params.format;
442
- if (!format && typeof model.type === "string") format = model.type.split(".").pop();
452
+ if (!format && typeof file["type"] === "string") format = file["type"].split(".").pop();
443
453
  if (!format && typeof file === "string") format = file.split(".").pop();
444
454
  if (!format && file instanceof globalThis.File) format = file.name.split(".").pop();
445
455
 
@@ -483,7 +493,7 @@ export class Viewer
483
493
  "Viewer.loadGltfFile() has been deprecated since 26.4 and will be removed in a future release, use Viewer.open() instead."
484
494
  );
485
495
 
486
- return this.open(file, { ...params, format: "gltf", externalFiles, mode: "append" });
496
+ return this.open(file, { ...params, format: "gltf", externalFiles, mode: "assembly" });
487
497
  }
488
498
 
489
499
  cancel(): this {
@@ -510,6 +520,9 @@ export class Viewer
510
520
  this.scene.clear();
511
521
  this.helpers.clear();
512
522
 
523
+ this.extents.makeEmpty();
524
+ this.target.set(0, 0, 0);
525
+
513
526
  this.syncOptions();
514
527
  this.syncOverlay();
515
528
  this.update(true);
@@ -519,6 +532,10 @@ export class Viewer
519
532
  return this;
520
533
  }
521
534
 
535
+ is3D(): boolean {
536
+ return true;
537
+ }
538
+
522
539
  syncOptions(options: IOptions = this.options): void {
523
540
  if (!this.renderer) return;
524
541
 
@@ -557,10 +574,18 @@ export class Viewer
557
574
  return this.executeCommand("getSelected");
558
575
  }
559
576
 
577
+ getSelected2(): string[] {
578
+ return this.executeCommand("getSelected2");
579
+ }
580
+
560
581
  setSelected(handles?: string[]): void {
561
582
  this.executeCommand("setSelected", handles);
562
583
  }
563
584
 
585
+ setSelected2(handles?: string[]): void {
586
+ this.executeCommand("setSelected2", handles);
587
+ }
588
+
564
589
  clearSelected(): void {
565
590
  this.executeCommand("clearSelected");
566
591
  }
@@ -630,44 +655,6 @@ export class Viewer
630
655
  return this._components.find((component) => component.name === name);
631
656
  }
632
657
 
633
- is3D(): boolean {
634
- return true;
635
- }
636
-
637
- screenToWorld(position: { x: number; y: number }): { x: number; y: number; z: number } {
638
- if (!this.renderer) return { x: position.x, y: position.y, z: 0 };
639
-
640
- const rect = this.canvas.getBoundingClientRect();
641
- const x = position.x / (rect.width / 2) - 1;
642
- const y = -position.y / (rect.height / 2) + 1;
643
-
644
- const point = new Vector3(x, y, -1);
645
- point.unproject(this.camera);
646
-
647
- return { x: point.x, y: point.y, z: point.z };
648
- }
649
-
650
- worldToScreen(position: { x: number; y: number; z: number }): { x: number; y: number } {
651
- if (!this.renderer) return { x: position.x, y: position.y };
652
-
653
- const point = new Vector3(position.x, position.y, position.z);
654
- point.project(this.camera);
655
-
656
- const rect = this.canvas.getBoundingClientRect();
657
- const x = (point.x + 1) * (rect.width / 2);
658
- const y = (-point.y + 1) * (rect.height / 2);
659
-
660
- return { x, y };
661
- }
662
-
663
- getScale(): { x: number; y: number; z: number } {
664
- return { x: 1, y: 1, z: 1 };
665
- }
666
-
667
- executeCommand(id: string, ...args: any[]): any {
668
- return commands.executeCommand(id, this, ...args);
669
- }
670
-
671
658
  drawViewpoint(viewpoint: IViewpoint): void {
672
659
  if (!this.renderer) return;
673
660
 
@@ -731,15 +718,17 @@ export class Viewer
731
718
  };
732
719
 
733
720
  const setClippingPlanes = (clipping_planes: IClippingPlane[]) => {
734
- clipping_planes?.forEach((clipping_plane) => {
735
- const plane = new Plane();
736
- plane.setFromNormalAndCoplanarPoint(
737
- getVector3FromPoint3d(clipping_plane.direction),
738
- getVector3FromPoint3d(clipping_plane.location)
739
- );
740
-
741
- this.renderer.clippingPlanes.push(plane);
742
- });
721
+ if (clipping_planes) {
722
+ clipping_planes.forEach((clipping_plane) => {
723
+ const plane = new Plane();
724
+ plane.setFromNormalAndCoplanarPoint(
725
+ getVector3FromPoint3d(clipping_plane.direction),
726
+ getVector3FromPoint3d(clipping_plane.location)
727
+ );
728
+
729
+ this.renderer.clippingPlanes.push(plane);
730
+ });
731
+ }
743
732
  };
744
733
 
745
734
  const setSelection = (selection: IEntity[]) => {
@@ -759,10 +748,10 @@ export class Viewer
759
748
  setOrthogonalCamera(viewpoint.orthogonal_camera);
760
749
  setPerspectiveCamera(viewpoint.perspective_camera);
761
750
  setClippingPlanes(viewpoint.clipping_planes);
762
- setSelection(viewpoint.selection);
751
+ setSelection(viewpoint.custom_fields?.selection2 || viewpoint.selection);
763
752
  this._markup.setViewpoint(viewpoint);
764
753
 
765
- this.target = getVector3FromPoint3d(viewpoint.custom_fields?.camera_target ?? this.target);
754
+ this.target.copy(getVector3FromPoint3d(viewpoint.custom_fields?.camera_target ?? this.target));
766
755
 
767
756
  this.setActiveDragger(draggerName);
768
757
  this.emitEvent({ type: "drawviewpoint", data: viewpoint });
@@ -814,6 +803,10 @@ export class Viewer
814
803
  return this.getSelected().map((handle) => ({ handle }));
815
804
  };
816
805
 
806
+ const getSelection2 = (): IEntity[] => {
807
+ return this.getSelected2().map((handle) => ({ handle }));
808
+ };
809
+
817
810
  const viewpoint: IViewpoint = { custom_fields: {} };
818
811
 
819
812
  viewpoint.orthogonal_camera = getOrthogonalCamera();
@@ -824,9 +817,48 @@ export class Viewer
824
817
  this._markup.getViewpoint(viewpoint);
825
818
 
826
819
  viewpoint.custom_fields.camera_target = getPoint3dFromVector3(this.target);
820
+ viewpoint.custom_fields.selection2 = getSelection2();
827
821
 
828
822
  this.emitEvent({ type: "createviewpoint", data: viewpoint });
829
823
 
830
824
  return viewpoint;
831
825
  }
826
+
827
+ // IWorldTransform
828
+
829
+ screenToWorld(position: { x: number; y: number }): { x: number; y: number; z: number } {
830
+ if (!this.renderer) return { x: position.x, y: position.y, z: 0 };
831
+
832
+ const rect = this.canvas.getBoundingClientRect();
833
+ const x = position.x / (rect.width / 2) - 1;
834
+ const y = -position.y / (rect.height / 2) + 1;
835
+
836
+ const point = new Vector3(x, y, -1);
837
+ point.unproject(this.camera);
838
+
839
+ return { x: point.x, y: point.y, z: point.z };
840
+ }
841
+
842
+ worldToScreen(position: { x: number; y: number; z: number }): { x: number; y: number } {
843
+ if (!this.renderer) return { x: position.x, y: position.y };
844
+
845
+ const point = new Vector3(position.x, position.y, position.z);
846
+ point.project(this.camera);
847
+
848
+ const rect = this.canvas.getBoundingClientRect();
849
+ const x = (point.x + 1) * (rect.width / 2);
850
+ const y = (-point.y + 1) * (rect.height / 2);
851
+
852
+ return { x, y };
853
+ }
854
+
855
+ getScale(): { x: number; y: number; z: number } {
856
+ return { x: 1, y: 1, z: 1 };
857
+ }
858
+
859
+ // ICommandService
860
+
861
+ executeCommand(id: string, ...args: any[]): any {
862
+ return commands.executeCommand(id, this, ...args);
863
+ }
832
864
  }