@inweb/viewer-three 26.10.6 → 26.11.1

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 (84) hide show
  1. package/dist/plugins/components/AxesHelperComponent.js +23 -1
  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 +24 -2
  5. package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -1
  6. package/dist/plugins/components/ExtentsHelperComponent.js +18 -0
  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 +19 -1
  10. package/dist/plugins/components/ExtentsHelperComponent.module.js.map +1 -1
  11. package/dist/plugins/loaders/GLTFCloudLoader.js +2 -3
  12. package/dist/plugins/loaders/GLTFCloudLoader.js.map +1 -1
  13. package/dist/plugins/loaders/GLTFCloudLoader.min.js +1 -1
  14. package/dist/plugins/loaders/GLTFCloudLoader.module.js +2 -3
  15. package/dist/plugins/loaders/GLTFCloudLoader.module.js.map +1 -1
  16. package/dist/plugins/loaders/GLTFFileLoader.js +2499 -0
  17. package/dist/plugins/loaders/GLTFFileLoader.js.map +1 -0
  18. package/dist/plugins/loaders/GLTFFileLoader.min.js +24 -0
  19. package/dist/plugins/loaders/GLTFFileLoader.module.js +74 -0
  20. package/dist/plugins/loaders/GLTFFileLoader.module.js.map +1 -0
  21. package/dist/plugins/loaders/IFCXLoader.js +5 -7
  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 +5 -7
  25. package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
  26. package/dist/plugins/loaders/PotreeLoader.js +1 -2
  27. package/dist/plugins/loaders/PotreeLoader.js.map +1 -1
  28. package/dist/plugins/loaders/PotreeLoader.min.js +1 -1
  29. package/dist/plugins/loaders/PotreeLoader.module.js +1 -2
  30. package/dist/plugins/loaders/PotreeLoader.module.js.map +1 -1
  31. package/dist/viewer-three.js +770 -2777
  32. package/dist/viewer-three.js.map +1 -1
  33. package/dist/viewer-three.min.js +3 -3
  34. package/dist/viewer-three.module.js +609 -206
  35. package/dist/viewer-three.module.js.map +1 -1
  36. package/lib/Viewer/Viewer.d.ts +27 -20
  37. package/lib/Viewer/commands/GetSelected2.d.ts +2 -0
  38. package/lib/Viewer/commands/SelectModel.d.ts +1 -1
  39. package/lib/Viewer/commands/SetSelected2.d.ts +2 -0
  40. package/lib/Viewer/components/index.d.ts +6 -6
  41. package/lib/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.d.ts +0 -1
  42. package/lib/Viewer/loaders/GLTFBinaryExtension.d.ts +5 -0
  43. package/lib/Viewer/loaders/GLTFCloudDynamicLoader.d.ts +2 -2
  44. package/lib/Viewer/loaders/{GLTFFileLoader.d.ts → GLTFFileDynamicLoader.d.ts} +7 -1
  45. package/lib/Viewer/loaders/GLTFLoadingManager.d.ts +4 -3
  46. package/lib/Viewer/loaders/RangesLoader.d.ts +15 -0
  47. package/lib/Viewer/loaders/index.d.ts +22 -14
  48. package/lib/Viewer/models/IModelImpl.d.ts +6 -8
  49. package/lib/Viewer/models/ModelImpl.d.ts +3 -5
  50. package/package.json +5 -5
  51. package/plugins/components/AxesHelperComponent.ts +31 -2
  52. package/plugins/components/ExtentsHelperComponent.ts +25 -0
  53. package/plugins/loaders/GLTFCloudLoader.ts +2 -3
  54. package/{src/Viewer → plugins}/loaders/GLTFFileLoader.ts +21 -12
  55. package/plugins/loaders/IFCX/IFCXCloudLoader.ts +5 -5
  56. package/plugins/loaders/IFCX/IFCXFileLoader.ts +3 -4
  57. package/plugins/loaders/Potree/PotreeFileLoader.ts +3 -4
  58. package/src/Viewer/Viewer.ts +120 -88
  59. package/src/Viewer/commands/ClearSelected.ts +3 -1
  60. package/src/Viewer/commands/GetModels.ts +1 -1
  61. package/src/Viewer/commands/GetSelected.ts +2 -2
  62. package/src/Viewer/commands/GetSelected2.ts +34 -0
  63. package/src/Viewer/commands/HideSelected.ts +3 -1
  64. package/src/Viewer/commands/SelectModel.ts +5 -5
  65. package/src/Viewer/commands/SetSelected.ts +9 -10
  66. package/src/Viewer/commands/SetSelected2.ts +42 -0
  67. package/src/Viewer/commands/ZoomToObjects.ts +5 -6
  68. package/src/Viewer/commands/ZoomToSelected.ts +3 -1
  69. package/src/Viewer/commands/index.ts +4 -0
  70. package/src/Viewer/components/CameraComponent.ts +6 -1
  71. package/src/Viewer/components/ExtentsComponent.ts +4 -1
  72. package/src/Viewer/components/SelectionComponent.ts +2 -0
  73. package/src/Viewer/components/index.ts +6 -6
  74. package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +253 -22
  75. package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +20 -10
  76. package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +3 -1
  77. package/src/Viewer/loaders/GLTFBinaryExtension.ts +91 -0
  78. package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +13 -19
  79. package/src/Viewer/loaders/GLTFFileDynamicLoader.ts +145 -0
  80. package/src/Viewer/loaders/GLTFLoadingManager.ts +5 -4
  81. package/src/Viewer/loaders/RangesLoader.ts +95 -0
  82. package/src/Viewer/loaders/index.ts +24 -16
  83. package/src/Viewer/models/IModelImpl.ts +8 -9
  84. package/src/Viewer/models/ModelImpl.ts +30 -17
@@ -7,7 +7,7 @@ import { SSAARenderPass } from "./postprocessing/SSAARenderPass.js";
7
7
  import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass.js";
8
8
  import { EventEmitter2 } from "@inweb/eventemitter2";
9
9
  import { Assembly, Client, Model, File } from "@inweb/client";
10
- import { CanvasEventMap, FileSource, IComponent, IDragger, ILoader, IOptions, IViewer, IViewpoint, Options, OptionsEventMap, ViewerEventMap } from "@inweb/viewer-core";
10
+ import { CanvasEventMap, FileSource, IComponent, IDragger, ILoader, IOptions, IViewer, IViewpoint, OptionsEventMap, ViewerEventMap } from "@inweb/viewer-core";
11
11
  import { IMarkup, IWorldTransform } from "@inweb/markup";
12
12
  import { IModelImpl } from "./models/IModelImpl";
13
13
  import { Helpers } from "./scenes/Helpers";
@@ -16,10 +16,12 @@ import { Helpers } from "./scenes/Helpers";
16
16
  */
17
17
  export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMap & OptionsEventMap> implements IViewer, IWorldTransform {
18
18
  client: Client | undefined;
19
- protected _options: Options;
20
- private canvaseventlistener;
19
+ options: IOptions;
21
20
  canvas: HTMLCanvasElement | undefined;
22
21
  canvasEvents: string[];
22
+ loaders: ILoader[];
23
+ models: IModelImpl[];
24
+ private canvaseventlistener;
23
25
  scene: Scene | undefined;
24
26
  helpers: Helpers | undefined;
25
27
  camera: PerspectiveCamera | OrthographicCamera | undefined;
@@ -31,8 +33,6 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
31
33
  ssaaRenderPass: SSAARenderPass | undefined;
32
34
  outputPass: OutputPass | undefined;
33
35
  composer: EffectComposer | undefined;
34
- loaders: ILoader[];
35
- models: IModelImpl[];
36
36
  selected: Object3D[];
37
37
  extents: Box3;
38
38
  target: Vector3;
@@ -47,15 +47,14 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
47
47
  * the web or from local computer.
48
48
  */
49
49
  constructor(client?: Client);
50
- get options(): IOptions;
51
- get draggers(): string[];
52
- get components(): string[];
53
50
  /**
54
51
  * 2D markup core instance used to create markups.
55
52
  *
56
53
  * @readonly
57
54
  */
58
55
  get markup(): IMarkup;
56
+ get draggers(): string[];
57
+ get components(): string[];
59
58
  initialize(canvas: HTMLCanvasElement, onProgress?: (event: ProgressEvent<EventTarget>) => void): Promise<this>;
60
59
  dispose(): this;
61
60
  isInitialized(): boolean;
@@ -74,18 +73,20 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
74
73
  * exception will be thrown.
75
74
  *
76
75
  * For files from Open Cloud Server, the default model will be loaded. If there is no default model,
77
- * first availiable model will be loaded. If no models are found in the file, an exception will be
76
+ * the first available model will be loaded. If no models are found in the file, an exception will be
78
77
  * thrown.
79
78
  *
80
79
  * For URLs, the file extension is used to determine the file format. For a `ArrayBuffer` and `Data
81
- * URL`, a file format must be specified using `params.format` parameter (see below). If no appropriate
82
- * loader is found for the specified format, an exception will be thrown.
80
+ * URL`, a file format must be specified using `params.format` parameter. If no appropriate loader is
81
+ * found for the specified format, an exception will be thrown.
83
82
  *
84
83
  * If there was an active dragger before opening the file, it will be deactivated. After opening the
85
84
  * file, you must manually activate the required dragger.
86
85
  *
87
86
  * Fires:
88
87
  *
88
+ * - {@link CancelEvent | cancel}
89
+ * - {@link ClearEvent | clear}
89
90
  * - {@link OpenEvent | open}
90
91
  * - {@link GeometryStartEvent | geometrystart}
91
92
  * - {@link GeometryProgressEvent | geometryprogress}
@@ -94,23 +95,26 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
94
95
  * - {@link GeometryEndEvent | geometryend}
95
96
  * - {@link GeometryErrorEvent | geometryerror}
96
97
  *
97
- * @param file - File to load. Can be one of:
98
+ * @param file - File to load. Can be:
98
99
  *
99
100
  * - `File`, `Assembly` or `Model` instance from the Open Cloud Server
100
- * - File `URL` string
101
+ * - `URL` string
101
102
  * - {@link https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs | Data URL} string
102
103
  * - {@link https://developer.mozilla.org/docs/Web/API/File | Web API File} object
103
104
  * - {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer | ArrayBuffer}
104
105
  * object
105
106
  *
106
107
  * @param params - Loading parameters.
107
- * @param params.format - File format string. Required when loading a file as `ArrayBuffer` or `Data
108
- * URL`.
108
+ * @param params.format - File format. Can be `gltf`, `glb` or format from a plugin. Required when
109
+ * loading a file as `ArrayBuffer` or `Data URL`.
109
110
  * @param params.mode - File opening mode. Can be one of:
110
111
  *
111
- * - `open` - Unloads an open file and opens a new one. This is default mode.
112
- * - `append` - Appends a file to an already open file.
112
+ * - `file` - Single file mode. Unloads an open file and opens a new one. This is default mode.
113
+ * - `assembly` - Assembly mode. Appends a file to an already open file.
113
114
  *
115
+ * @param params.modelId - Unique model ID in the assembly (multi-model scene). Used as a model prefix
116
+ * when selecting objects (see {@link getSelected2}). Must not contain the ":" (colon). Required when
117
+ * loading a file as `ArrayBuffer` or `Data URL`.
114
118
  * @param params.requestHeader - The
115
119
  * {@link https://developer.mozilla.org/docs/Glossary/Request_header | request header} used in HTTP
116
120
  * request.
@@ -130,6 +134,7 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
130
134
  open(file: FileSource, params?: {
131
135
  format?: string;
132
136
  mode?: string;
137
+ modelId?: string;
133
138
  requestHeader?: HeadersInit;
134
139
  withCredentials?: boolean;
135
140
  path?: string;
@@ -150,12 +155,15 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
150
155
  loadGltfFile(file: any, externalFiles: any, params?: any): Promise<this>;
151
156
  cancel(): this;
152
157
  clear(): this;
158
+ is3D(): boolean;
153
159
  syncOptions(options?: IOptions): void;
154
160
  syncOverlay(): void;
155
161
  clearOverlay(): void;
156
162
  clearSlices(): void;
157
163
  getSelected(): string[];
164
+ getSelected2(): string[];
158
165
  setSelected(handles?: string[]): void;
166
+ setSelected2(handles?: string[]): void;
159
167
  clearSelected(): void;
160
168
  hideSelected(): void;
161
169
  isolateSelected(): void;
@@ -166,7 +174,8 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
166
174
  setActiveDragger(name?: string): IDragger | null;
167
175
  resetActiveDragger(): void;
168
176
  getComponent(name: string): IComponent;
169
- is3D(): boolean;
177
+ drawViewpoint(viewpoint: IViewpoint): void;
178
+ createViewpoint(): IViewpoint;
170
179
  screenToWorld(position: {
171
180
  x: number;
172
181
  y: number;
@@ -189,6 +198,4 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
189
198
  z: number;
190
199
  };
191
200
  executeCommand(id: string, ...args: any[]): any;
192
- drawViewpoint(viewpoint: IViewpoint): void;
193
- createViewpoint(): IViewpoint;
194
201
  }
@@ -0,0 +1,2 @@
1
+ import type { Viewer } from "../Viewer";
2
+ export declare function getSelected2(viewer: Viewer): string[];
@@ -1,2 +1,2 @@
1
1
  import type { Viewer } from "../Viewer";
2
- export declare function selectModel(viewer: Viewer, handle: string): void;
2
+ export declare function selectModel(viewer: Viewer, id: string): void;
@@ -0,0 +1,2 @@
1
+ import type { Viewer } from "../Viewer";
2
+ export declare function setSelected2(viewer: Viewer, handles?: string[]): void;
@@ -6,8 +6,8 @@ import { IComponentsRegistry } from "@inweb/viewer-core";
6
6
  *
7
7
  * 1. Define a component class implements {@link IComponent}.
8
8
  * 2. Define a constructor with a `viewer` parameter and add mouse event listeners for the specified viewer.
9
- * 3. Define the component logic in the event listeners. For example, listen for the `mousedown` event and
10
- * select objects when the left mouse button is pressed.
9
+ * 3. Define the component logic in the event listeners. For example, listen for the `geometryend` event and
10
+ * implement post-processing logic for the model.
11
11
  * 4. Override {@link IComponent.dispose} and remove mouse event listeners from the viewer.
12
12
  * 5. Register component provider in the components registry by calling the
13
13
  * {@link components.registerComponent}.
@@ -22,15 +22,15 @@ import { IComponentsRegistry } from "@inweb/viewer-core";
22
22
  *
23
23
  * constructor(viewer: Viewer) {
24
24
  * this.viewer = viewer;
25
- * this.viewer.addEventListener("mousedown", this.onMouseDown);
25
+ * this.viewer.addEventListener("geometryend", this.onGeometryEnd);
26
26
  * }
27
27
  *
28
28
  * override dispose() {
29
- * this.viewer.removeEventListener("mousedown", this.onMouseDown);
29
+ * this.viewer.removeEventListener("geometryend", this.onGeometryEnd);
30
30
  * }
31
31
  *
32
- * onMouseDown = (event: PointerEvent) => {
33
- * // place custom logic here
32
+ * onGeometryEnd = (event: MouseEvent) => {
33
+ * this.viewer.executeCommand("zoomToExtents");
34
34
  * };
35
35
  * }
36
36
  *
@@ -3,7 +3,6 @@ import { ModelImpl } from "../../models/ModelImpl";
3
3
  import { DynamicGltfLoader } from "./DynamicGltfLoader.js";
4
4
  export declare class DynamicModelImpl extends ModelImpl {
5
5
  gltfLoader: DynamicGltfLoader;
6
- modelId: number;
7
6
  getExtents(target: Box3): Box3;
8
7
  getObjects(): Object3D[];
9
8
  getVisibleObjects(): Object3D[];
@@ -0,0 +1,5 @@
1
+ export declare class GLTFBinaryExtension {
2
+ content: string;
3
+ body: ArrayBuffer;
4
+ constructor(data: ArrayBuffer);
5
+ }
@@ -1,7 +1,7 @@
1
- import { ILoader, LoadParams } from "@inweb/viewer-core";
1
+ import { Loader, LoadParams } from "@inweb/viewer-core";
2
2
  import { Viewer } from "../Viewer";
3
3
  import { DynamicGltfLoader } from "./DynamicGltfLoader/DynamicGltfLoader.js";
4
- export declare class GLTFCloudDynamicLoader implements ILoader {
4
+ export declare class GLTFCloudDynamicLoader extends Loader {
5
5
  viewer: Viewer;
6
6
  gltfLoader: DynamicGltfLoader;
7
7
  requestId: number;
@@ -1,9 +1,15 @@
1
1
  import { Loader } from "@inweb/viewer-core";
2
2
  import { Viewer } from "../Viewer";
3
3
  import { GLTFLoadParams } from "./GLTFLoadingManager";
4
- export declare class GLTFFileLoader extends Loader {
4
+ export declare class GLTFFileDynamicLoader extends Loader {
5
5
  viewer: Viewer;
6
+ private gltfLoader;
7
+ private manager;
8
+ private gltf;
9
+ private bin;
6
10
  constructor(viewer: Viewer);
11
+ dispose(): void;
7
12
  isSupport(file: any, format?: string): boolean;
8
13
  load(file: any, format?: string, params?: GLTFLoadParams): Promise<this>;
14
+ cancel(): void;
9
15
  }
@@ -1,11 +1,12 @@
1
+ import { LoadParams } from "@inweb/viewer-core";
1
2
  import { LoadingManager } from "three";
2
3
  export type GLTFFileSource = string | globalThis.File | ArrayBuffer;
3
- export type GLTFLoadParams = {
4
+ export type GLTFLoadParams = LoadParams & {
5
+ requestHeader?: HeadersInit;
6
+ withCredentials?: boolean;
4
7
  path?: string;
5
8
  externalFiles?: Map<string, GLTFFileSource>;
6
9
  crossOrigin?: string;
7
- requestHeader?: HeadersInit;
8
- withCredentials?: boolean;
9
10
  };
10
11
  export declare class GLTFLoadingManager extends LoadingManager {
11
12
  path: string;
@@ -0,0 +1,15 @@
1
+ export interface Range {
2
+ offset: number;
3
+ length: number;
4
+ }
5
+ export declare class RangesLoader {
6
+ private requestHeader;
7
+ private withCredentials;
8
+ private abortSignal;
9
+ constructor();
10
+ setRequestHeader(requestHeader: HeadersInit): void;
11
+ setWithCredentials(withCredentials: boolean): void;
12
+ setAbortSignal(abortSignal: AbortSignal): void;
13
+ load(url: string, ranges: Range[]): Promise<ArrayBuffer>;
14
+ extractRanges(arrayBuffer: ArrayBuffer, ranges: Range[]): ArrayBuffer;
15
+ }
@@ -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
  * ```
@@ -1,19 +1,17 @@
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;
12
8
  getExtents(target: Box3): Box3;
13
9
  getObjects(): Object3D[];
14
10
  getVisibleObjects(): Object3D[];
15
- hasObject(objects: Object3D): boolean;
11
+ hasObject(object: Object3D): boolean;
12
+ hasHandle(handle: string): boolean;
16
13
  getOwnObjects(objects: Object3D | Object3D[]): Object3D[];
14
+ getOwnHandles(handles: string | string[]): string[];
17
15
  getObjectsByHandles(handles: string | string[]): Object3D[];
18
16
  getHandlesByObjects(objects: Object3D | Object3D[]): string[];
19
17
  hideObjects(objects: Object3D | Object3D[]): this;
@@ -1,19 +1,17 @@
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;
12
8
  getExtents(target: Box3): Box3;
13
9
  getObjects(): Object3D[];
14
10
  getVisibleObjects(): Object3D[];
15
11
  hasObject(object: Object3D): boolean;
12
+ hasHandle(handle: string): boolean;
16
13
  getOwnObjects(objects: Object3D | Object3D[]): Object3D[];
14
+ getOwnHandles(handles: string | string[]): string[];
17
15
  getObjectsByHandles(handles: string | string[]): Object3D[];
18
16
  getHandlesByObjects(objects: Object3D | Object3D[]): string[];
19
17
  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.1",
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",
@@ -35,10 +35,10 @@
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.1",
39
+ "@inweb/eventemitter2": "~26.11.1",
40
+ "@inweb/markup": "~26.11.1",
41
+ "@inweb/viewer-core": "~26.11.1"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@types/three": "^0.180.0",
@@ -21,17 +21,21 @@
21
21
  // acknowledge and accept the above terms.
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
- import { AxesHelper, Vector3 } from "three";
24
+ import { AxesHelper, Box3, Vector3 } from "three";
25
25
  import { IComponent, components, Viewer } from "@inweb/viewer-three";
26
26
 
27
27
  class AxesHelperComponent implements IComponent {
28
28
  private viewer: Viewer;
29
29
  private axesHelper1: AxesHelper;
30
30
  private axesHelper2: AxesHelper;
31
+ private modelHelpers: AxesHelper[];
31
32
 
32
33
  constructor(viewer: Viewer) {
33
34
  this.axesHelper1 = new AxesHelper(1);
34
35
  this.axesHelper2 = new AxesHelper(1);
36
+ this.modelHelpers = [];
37
+
38
+ this.axesHelper1.setColors("#ccc", "#ccc", "#cccb");
35
39
 
36
40
  this.viewer = viewer;
37
41
  this.viewer.addEventListener("initialize", this.syncHelper);
@@ -40,6 +44,11 @@ class AxesHelperComponent implements IComponent {
40
44
  }
41
45
 
42
46
  dispose() {
47
+ this.modelHelpers.forEach((helper) => {
48
+ helper.removeFromParent();
49
+ helper.dispose();
50
+ });
51
+
43
52
  this.axesHelper1.removeFromParent();
44
53
  this.axesHelper1.dispose();
45
54
 
@@ -52,6 +61,12 @@ class AxesHelperComponent implements IComponent {
52
61
  }
53
62
 
54
63
  syncHelper = () => {
64
+ this.modelHelpers.forEach((helper) => {
65
+ helper.removeFromParent();
66
+ helper.dispose();
67
+ });
68
+ this.modelHelpers.length = 0;
69
+
55
70
  this.axesHelper1.removeFromParent();
56
71
  this.axesHelper2.removeFromParent();
57
72
 
@@ -59,13 +74,27 @@ class AxesHelperComponent implements IComponent {
59
74
  const center = this.viewer.extents.getCenter(new Vector3());
60
75
 
61
76
  this.axesHelper1.position.set(0, 0, 0);
62
- this.axesHelper1.scale.setScalar(size);
77
+ this.axesHelper1.scale.setScalar(size * 1.25);
63
78
 
64
79
  this.axesHelper2.position.copy(center);
65
80
  this.axesHelper2.scale.setScalar(size);
66
81
 
67
82
  this.viewer.helpers.add(this.axesHelper1);
68
83
  this.viewer.helpers.add(this.axesHelper2);
84
+
85
+ if (this.viewer.models.length < 2) return;
86
+
87
+ this.viewer.models.forEach((model) => {
88
+ const extents = model.getExtents(new Box3());
89
+ const size = extents.getSize(new Vector3()).length();
90
+ const center = extents.getCenter(new Vector3());
91
+
92
+ const helper = new AxesHelper(size);
93
+ helper.position.copy(center);
94
+
95
+ this.modelHelpers.push(helper);
96
+ this.viewer.helpers.add(helper);
97
+ });
69
98
  };
70
99
  }
71
100
 
@@ -27,9 +27,12 @@ import { IComponent, components, Viewer } from "@inweb/viewer-three";
27
27
  class ExtentsHelperComponent implements IComponent {
28
28
  private viewer: Viewer;
29
29
  private boxHelper: Box3Helper;
30
+ private modelHelpers: Box3Helper[];
30
31
 
31
32
  constructor(viewer: Viewer) {
32
33
  this.boxHelper = new Box3Helper(new Box3(), "#ff0000");
34
+ this.modelHelpers = [];
35
+
33
36
  this.viewer = viewer;
34
37
  this.viewer.on("geometryend", this.syncHelper);
35
38
  this.viewer.on("clear", this.syncHelper);
@@ -41,6 +44,11 @@ class ExtentsHelperComponent implements IComponent {
41
44
  }
42
45
 
43
46
  dispose() {
47
+ this.modelHelpers.forEach((helper) => {
48
+ helper.removeFromParent();
49
+ helper.dispose();
50
+ });
51
+
44
52
  this.boxHelper.removeFromParent();
45
53
  this.boxHelper.dispose();
46
54
 
@@ -54,12 +62,29 @@ class ExtentsHelperComponent implements IComponent {
54
62
  }
55
63
 
56
64
  syncHelper = () => {
65
+ this.modelHelpers.forEach((helper) => {
66
+ helper.removeFromParent();
67
+ helper.dispose();
68
+ });
69
+ this.modelHelpers.length = 0;
70
+
57
71
  this.boxHelper.removeFromParent();
58
72
 
59
73
  if (this.viewer.extents.isEmpty()) return;
60
74
 
61
75
  this.boxHelper.box = this.viewer.extents.clone();
62
76
  this.viewer.helpers.add(this.boxHelper);
77
+
78
+ if (this.viewer.models.length < 2) return;
79
+
80
+ this.viewer.models.forEach((model) => {
81
+ const extents = model.getExtents(new Box3());
82
+
83
+ const helper = new Box3Helper(extents, "#ff0000");
84
+
85
+ this.modelHelpers.push(helper);
86
+ this.viewer.helpers.add(helper);
87
+ });
63
88
  };
64
89
  }
65
90
 
@@ -58,10 +58,9 @@ class GLTFCloudLoader extends Loader {
58
58
  if (!this.viewer.scene) return this;
59
59
 
60
60
  const modelImpl = new ModelImpl(gltf.scene);
61
- modelImpl.loader = this;
62
- modelImpl.viewer = this.viewer;
61
+ modelImpl.id = model.file.id;
63
62
 
64
- this.viewer.scene.add(modelImpl.scene);
63
+ this.viewer.scene.add(gltf.scene);
65
64
  this.viewer.models.push(modelImpl);
66
65
 
67
66
  this.viewer.syncOptions();
@@ -22,20 +22,21 @@
22
22
  ///////////////////////////////////////////////////////////////////////////////
23
23
 
24
24
  import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
25
- import { Loader } from "@inweb/viewer-core";
26
-
27
- import { Viewer } from "../Viewer";
28
- import { GLTFLoadingManager, GLTFLoadParams } from "./GLTFLoadingManager";
29
- import { ModelImpl } from "../models/ModelImpl";
25
+ import { GLTFLoadingManager, GLTFLoadParams, Loader, loaders, ModelImpl, Viewer } from "@inweb/viewer-three";
30
26
 
31
27
  export class GLTFFileLoader extends Loader {
32
28
  public viewer: Viewer;
29
+ private manager: GLTFLoadingManager;
33
30
 
34
31
  constructor(viewer: Viewer) {
35
32
  super();
36
33
  this.viewer = viewer;
37
34
  }
38
35
 
36
+ override dispose() {
37
+ if (this.manager) this.manager.dispose();
38
+ }
39
+
39
40
  override isSupport(file: any, format?: string): boolean {
40
41
  return (
41
42
  (typeof file === "string" || file instanceof globalThis.File || file instanceof ArrayBuffer) &&
@@ -43,12 +44,13 @@ export class GLTFFileLoader extends Loader {
43
44
  );
44
45
  }
45
46
 
46
- override async load(file: any, format?: string, params?: GLTFLoadParams): Promise<this> {
47
- const manager = new GLTFLoadingManager(file, params);
47
+ override async load(file: any, format?: string, params: GLTFLoadParams = {}): Promise<this> {
48
+ this.manager = new GLTFLoadingManager(file, params);
48
49
 
49
- const loader = new GLTFLoader(manager);
50
- loader.setPath(manager.path);
50
+ const loader = new GLTFLoader(this.manager);
51
+ loader.setPath(this.manager.path);
51
52
  loader.setCrossOrigin(params.crossOrigin || loader.crossOrigin);
53
+ loader.setRequestHeader((params.requestHeader as any) || {});
52
54
  loader.setWithCredentials(params.withCredentials || loader.withCredentials);
53
55
 
54
56
  const progress = (event: ProgressEvent) => {
@@ -57,12 +59,17 @@ export class GLTFFileLoader extends Loader {
57
59
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, file });
58
60
  };
59
61
 
60
- const gltf = await loader.loadAsync(manager.fileURL, progress);
62
+ const gltf = await loader.loadAsync(this.manager.fileURL, progress);
61
63
  if (!this.viewer.scene) return this;
62
64
 
65
+ let handle = 0;
66
+ gltf.scene.traverse((object) => {
67
+ object.userData = { handle: handle + "", ...object.userData };
68
+ handle++;
69
+ });
70
+
63
71
  const modelImpl = new ModelImpl(gltf.scene);
64
- modelImpl.loader = this;
65
- modelImpl.viewer = this.viewer;
72
+ modelImpl.id = params.modelId || this.extractFileName(file);
66
73
 
67
74
  this.viewer.scene.add(gltf.scene);
68
75
  this.viewer.models.push(modelImpl);
@@ -76,3 +83,5 @@ export class GLTFFileLoader extends Loader {
76
83
  return this;
77
84
  }
78
85
  }
86
+
87
+ loaders.registerLoader("gltf-file", (viewer: any) => new GLTFFileLoader(viewer));