@inweb/viewer-visualize 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 (36) hide show
  1. package/dist/viewer-visualize.js +470 -422
  2. package/dist/viewer-visualize.js.map +1 -1
  3. package/dist/viewer-visualize.min.js +1 -1
  4. package/dist/viewer-visualize.module.js +462 -422
  5. package/dist/viewer-visualize.module.js.map +1 -1
  6. package/lib/Viewer/Commands/GetSelected2.d.ts +2 -0
  7. package/lib/Viewer/Commands/SetSelected.d.ts +1 -1
  8. package/lib/Viewer/Commands/SetSelected2.d.ts +2 -0
  9. package/lib/Viewer/Components/index.d.ts +8 -7
  10. package/lib/Viewer/Loaders/VSFXCloudLoader.d.ts +1 -1
  11. package/lib/Viewer/Loaders/VSFXCloudPartialLoader.d.ts +1 -1
  12. package/lib/Viewer/Loaders/index.d.ts +14 -9
  13. package/lib/Viewer/Models/IModelImpl.d.ts +5 -0
  14. package/lib/Viewer/Models/ModelImpl.d.ts +5 -0
  15. package/lib/Viewer/Viewer.d.ts +129 -136
  16. package/package.json +6 -6
  17. package/src/Viewer/Commands/ClearSelected.ts +3 -1
  18. package/src/Viewer/Commands/GetSelected2.ts +33 -0
  19. package/src/Viewer/Commands/HideSelected.ts +3 -1
  20. package/src/Viewer/Commands/SelectModel.ts +2 -3
  21. package/src/Viewer/Commands/SetSelected.ts +5 -2
  22. package/src/Viewer/Commands/SetSelected2.ts +39 -0
  23. package/src/Viewer/Commands/index.ts +4 -0
  24. package/src/Viewer/Components/index.ts +8 -7
  25. package/src/Viewer/Draggers/Common/OdBaseDragger.ts +3 -2
  26. package/src/Viewer/Draggers/OdJoyStickDragger.ts +2 -2
  27. package/src/Viewer/Loaders/VSFCloudLoader.ts +6 -0
  28. package/src/Viewer/Loaders/VSFFileLoader.ts +7 -1
  29. package/src/Viewer/Loaders/VSFXCloudLoader.ts +7 -1
  30. package/src/Viewer/Loaders/VSFXCloudPartialLoader.ts +8 -2
  31. package/src/Viewer/Loaders/VSFXCloudStreamingLoader.ts +7 -1
  32. package/src/Viewer/Loaders/VSFXFileLoader.ts +7 -1
  33. package/src/Viewer/Loaders/index.ts +14 -9
  34. package/src/Viewer/Models/IModelImpl.ts +29 -0
  35. package/src/Viewer/Models/ModelImpl.ts +32 -0
  36. package/src/Viewer/Viewer.ts +780 -775
@@ -0,0 +1,39 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
24
+ import { Viewer } from "../Viewer";
25
+
26
+ export function setSelected2(viewer: Viewer, handles2: string[] = []): void {
27
+ const handles = [];
28
+
29
+ handles2.forEach((handle) => {
30
+ if (!handle.includes(":")) {
31
+ handles.push(handle);
32
+ } else
33
+ viewer.models.forEach((model) => {
34
+ if (handle.split(":", 1)[0] === model.id + "") handles.push(handle);
35
+ });
36
+ });
37
+
38
+ return viewer.executeCommand("setSelected", handles);
39
+ }
@@ -32,6 +32,7 @@ import { explode, collect } from "./Explode";
32
32
  import { getDefaultViewPositions } from "./GetDefaultViewPositions";
33
33
  import { getModels } from "./GetModels";
34
34
  import { getSelected } from "./GetSelected";
35
+ import { getSelected2 } from "./GetSelected2";
35
36
  import { hideSelected } from "./HideSelected";
36
37
  import { isolateSelected } from "./IsolateSelected";
37
38
  import { regenerateAll } from "./RegenerateAll";
@@ -41,6 +42,7 @@ import { setActiveDragger } from "./SetActiveDragger";
41
42
  import { setDefaultViewPosition } from "./SetDefaultViewPosition";
42
43
  import { setMarkupColor } from "./SetMarkupColor";
43
44
  import { setSelected } from "./SetSelected";
45
+ import { setSelected2 } from "./SetSelected2";
44
46
  import { showAll } from "./ShowAll";
45
47
  import { zoomToExtents } from "./ZoomToExtents";
46
48
  import { zoomToObjects } from "./ZoomToObjects";
@@ -87,6 +89,7 @@ commands.registerCommand("collect", collect);
87
89
  commands.registerCommand("getDefaultViewPositions", getDefaultViewPositions);
88
90
  commands.registerCommand("getModels", getModels);
89
91
  commands.registerCommand("getSelected", getSelected);
92
+ commands.registerCommand("getSelected2", getSelected2);
90
93
  commands.registerCommand("hideSelected", hideSelected);
91
94
  commands.registerCommand("isolateSelected", isolateSelected);
92
95
  commands.registerCommand("regenerateAll", regenerateAll);
@@ -96,6 +99,7 @@ commands.registerCommand("setActiveDragger", setActiveDragger);
96
99
  commands.registerCommand("setDefaultViewPosition", setDefaultViewPosition);
97
100
  commands.registerCommand("setMarkupColor", setMarkupColor);
98
101
  commands.registerCommand("setSelected", setSelected);
102
+ commands.registerCommand("setSelected2", setSelected2);
99
103
  commands.registerCommand("showAll", showAll);
100
104
  commands.registerCommand("zoomToExtents", zoomToExtents);
101
105
  commands.registerCommand("zoomToObjects", zoomToObjects);
@@ -37,8 +37,8 @@ import { ResetComponent } from "./ResetComponent";
37
37
  *
38
38
  * 1. Define a component class implements {@link IComponent}.
39
39
  * 2. Define a constructor with a `viewer` parameter and add mouse event listeners for the specified viewer.
40
- * 3. Define the component logic in the event listeners. For example, listen for the `mousedown` event and
41
- * select objects when the left mouse button is pressed.
40
+ * 3. Define the component logic in the event listeners. For example, listen for the `geometryend` event and
41
+ * implement post-processing logic for the model.
42
42
  * 4. Override {@link IComponent.dispose} and remove mouse event listeners from the viewer.
43
43
  * 5. Register component provider in the components registry by calling the
44
44
  * {@link components.registerComponent}.
@@ -51,18 +51,19 @@ import { ResetComponent } from "./ResetComponent";
51
51
  * class MyComponent implements IComponent {
52
52
  * protected viewer: Viewer;
53
53
  *
54
- * constructor(viewer: Viewer) {
54
+ * constructor(viewer: Viewer) {
55
55
  * this.viewer = viewer;
56
- * this.viewer.addEventListener("mousedown", this.onMouseDown);
56
+ * this.viewer.addEventListener("geometryend", this.onGeometryEnd);
57
57
  * }
58
58
  *
59
59
  * override dispose() {
60
- * this.viewer.removeEventListener("mousedown", this.onMouseDown);
60
+ * this.viewer.removeEventListener("geometryend", this.onGeometryEnd);
61
61
  * }
62
62
  *
63
- * onMouseDown = (event: PointerEvent) => {
64
- * // place custom logic here
63
+ * onGeometryEnd = (event: MouseEvent) => {
64
+ * this.viewer.executeCommand("zoomToExtents");
65
65
  * };
66
+ *
66
67
  * }
67
68
  *
68
69
  * components.registerComponent( "MyComponent", (viewer): IComponent => new MyComponent(viewer));
@@ -135,8 +135,9 @@ export class OdBaseDragger extends OdaGeAction {
135
135
  this.subject.update();
136
136
 
137
137
  const selectionSet = viewer.getSelected();
138
- const handles = this.subject.getSelected();
139
- this.onmessage({ type: "select", data: selectionSet, handles });
138
+
139
+ this.onmessage({ type: "select", data: selectionSet, handles: this.subject.getSelected() });
140
+ this.onmessage({ type: "select2", data: selectionSet, handles: this.subject.getSelected2() });
140
141
  }
141
142
  }
142
143
 
@@ -100,7 +100,7 @@ export class OdJoyStickDragger {
100
100
  callback({
101
101
  x: 100 * ((movedX - centerX) / maxMoveStick),
102
102
  y: 100 * ((movedY - centerY) / maxMoveStick) * -1,
103
- global: global,
103
+ global,
104
104
  });
105
105
  }
106
106
  };
@@ -116,7 +116,7 @@ export class OdJoyStickDragger {
116
116
  callback({
117
117
  x: 100 * ((movedX - centerX) / maxMoveStick),
118
118
  y: 100 * ((movedY - centerY) / maxMoveStick) * -1,
119
- global: global,
119
+ global,
120
120
  });
121
121
  };
122
122
 
@@ -23,6 +23,7 @@
23
23
 
24
24
  import { Loader } from "@inweb/viewer-core";
25
25
  import { Viewer } from "../Viewer";
26
+ import { ModelImpl } from "../Models/ModelImpl";
26
27
 
27
28
  export class VSFCloudLoader extends Loader {
28
29
  public viewer: Viewer;
@@ -70,6 +71,11 @@ export class VSFCloudLoader extends Loader {
70
71
  }
71
72
 
72
73
  if (i === 0) {
74
+ const modelImpl = new ModelImpl();
75
+ modelImpl.id = model.file.id;
76
+
77
+ this.viewer.models.push(modelImpl);
78
+
73
79
  this.viewer.syncOptions();
74
80
  this.viewer.syncOverlay();
75
81
  this.viewer.update(true);
@@ -23,6 +23,7 @@
23
23
 
24
24
  import { Loader, LoadParams } from "@inweb/viewer-core";
25
25
  import { Viewer } from "../Viewer";
26
+ import { ModelImpl } from "../Models/ModelImpl";
26
27
  import { FileLoader } from "./FileLoader";
27
28
 
28
29
  export class VSFFileLoader extends Loader {
@@ -40,7 +41,7 @@ export class VSFFileLoader extends Loader {
40
41
  );
41
42
  }
42
43
 
43
- override async load(file: any, format?: string, params?: LoadParams): Promise<this> {
44
+ override async load(file: any, format?: string, params: LoadParams = {}): Promise<this> {
44
45
  if (!this.viewer.visualizeJs) return this;
45
46
 
46
47
  const visViewer = this.viewer.visViewer();
@@ -68,6 +69,11 @@ export class VSFFileLoader extends Loader {
68
69
  throw error;
69
70
  }
70
71
 
72
+ const modelImpl = new ModelImpl();
73
+ modelImpl.id = params.modelId || this.extractFileName(file);
74
+
75
+ this.viewer.models.push(modelImpl);
76
+
71
77
  this.viewer.syncOptions();
72
78
  this.viewer.syncOverlay();
73
79
  this.viewer.update(true);
@@ -23,6 +23,7 @@
23
23
 
24
24
  import { Loader } from "@inweb/viewer-core";
25
25
  import { Viewer } from "../Viewer";
26
+ import { ModelImpl } from "../Models/ModelImpl";
26
27
 
27
28
  export class VSFXCloudLoader extends Loader {
28
29
  public viewer: Viewer;
@@ -42,7 +43,7 @@ export class VSFXCloudLoader extends Loader {
42
43
  );
43
44
  }
44
45
 
45
- override async load(model: any, format?: string, params: any = {}): Promise<this> {
46
+ override async load(model: any): Promise<this> {
46
47
  if (!this.viewer.visualizeJs) return Promise.resolve(this);
47
48
 
48
49
  const visViewer = this.viewer.visViewer();
@@ -65,6 +66,11 @@ export class VSFXCloudLoader extends Loader {
65
66
  throw error;
66
67
  }
67
68
 
69
+ const modelImpl = new ModelImpl();
70
+ modelImpl.id = model.file.id;
71
+
72
+ this.viewer.models.push(modelImpl);
73
+
68
74
  this.viewer.syncOptions();
69
75
  this.viewer.syncOverlay();
70
76
  this.viewer.update(true);
@@ -23,6 +23,7 @@
23
23
 
24
24
  import { Loader } from "@inweb/viewer-core";
25
25
  import { Viewer } from "../Viewer";
26
+ import { ModelImpl } from "../Models/ModelImpl";
26
27
  import { UpdateController, UpdateType } from "./UpdateController";
27
28
 
28
29
  const PENDING_REQUESTS_SIZE = 50;
@@ -49,7 +50,7 @@ export class VSFXCloudPartialLoader extends Loader {
49
50
  );
50
51
  }
51
52
 
52
- override async load(model: any, format?: string): Promise<this> {
53
+ override async load(model: any): Promise<this> {
53
54
  if (!this.viewer.visualizeJs) return this;
54
55
 
55
56
  const visViewer = this.viewer.visViewer();
@@ -81,10 +82,15 @@ export class VSFXCloudPartialLoader extends Loader {
81
82
  this.viewer.emitEvent({ type: "geometryprogress", data: progress, file: model.file, model });
82
83
 
83
84
  if (isDatabaseChunk) {
85
+ const modelImpl = new ModelImpl();
86
+ modelImpl.id = model.file.id;
87
+
88
+ this.viewer.models.push(modelImpl);
89
+
84
90
  this.viewer.syncOptions();
85
91
  this.viewer.syncOverlay();
86
-
87
92
  updateController.update(UpdateType.kForce);
93
+
88
94
  this.viewer.emitEvent({ type: "databasechunk", data: chunk, file: model.file, model });
89
95
  } else {
90
96
  updateController.update(UpdateType.kDelay);
@@ -23,6 +23,7 @@
23
23
 
24
24
  import { Loader } from "@inweb/viewer-core";
25
25
  import { Viewer } from "../Viewer";
26
+ import { ModelImpl } from "../Models/ModelImpl";
26
27
  import { UpdateController, UpdateType } from "./UpdateController";
27
28
 
28
29
  export class VSFXCloudStreamingLoader extends Loader {
@@ -79,10 +80,15 @@ export class VSFXCloudStreamingLoader extends Loader {
79
80
  }
80
81
 
81
82
  if (isDatabaseChunk) {
83
+ const modelImpl = new ModelImpl();
84
+ modelImpl.id = model.file.id;
85
+
86
+ this.viewer.models.push(modelImpl);
87
+
82
88
  this.viewer.syncOptions();
83
89
  this.viewer.syncOverlay();
84
-
85
90
  updateController.update(UpdateType.kForce);
91
+
86
92
  this.viewer.emitEvent({ type: "databasechunk", data: chunk, file: model.file, model });
87
93
  } else {
88
94
  updateController.update(UpdateType.kDelay);
@@ -23,6 +23,7 @@
23
23
 
24
24
  import { Loader, LoadParams } from "@inweb/viewer-core";
25
25
  import { Viewer } from "../Viewer";
26
+ import { ModelImpl } from "../Models/ModelImpl";
26
27
  import { FileLoader } from "./FileLoader";
27
28
 
28
29
  export class VSFXFileLoader extends Loader {
@@ -40,7 +41,7 @@ export class VSFXFileLoader extends Loader {
40
41
  );
41
42
  }
42
43
 
43
- override async load(file: any, format?: string, params?: LoadParams): Promise<this> {
44
+ override async load(file: any, format?: string, params: LoadParams = {}): Promise<this> {
44
45
  if (!this.viewer.visualizeJs) return this;
45
46
 
46
47
  const visViewer = this.viewer.visViewer();
@@ -68,6 +69,11 @@ export class VSFXFileLoader extends Loader {
68
69
  throw error;
69
70
  }
70
71
 
72
+ const modelImpl = new ModelImpl();
73
+ modelImpl.id = params.modelId || this.extractFileName(file);
74
+
75
+ this.viewer.models.push(modelImpl);
76
+
71
77
  this.viewer.syncOptions();
72
78
  this.viewer.syncOverlay();
73
79
  this.viewer.update(true);
@@ -38,23 +38,24 @@ import { VSFXCloudPartialLoader } from "./VSFXCloudPartialLoader";
38
38
  *
39
39
  * 1. Define a loader class implements {@link ILoader}.
40
40
  * 2. Define a constructor with a `viewer` parameter.
41
- * 3. Override {@link ILoader.isSupport} and сheck if the loader can load the specified file.
41
+ * 3. Override {@link ILoader.isSupport} and check if the loader can load the specified file.
42
42
  * 4. Override {@link ILoader.load} and define the logic for loading the model from the file.
43
43
  *
44
44
  * The loader should do:
45
45
  *
46
46
  * - Load model data from file into the buffer. The model data must be a `VSFX` format.
47
47
  * - Parse data buffer with the `VisualizeJS` viewer instance.
48
+ * - Create `ModelImpl` instance with unique model ID add it to the viewer `models` list.
48
49
  * - Synchronize viewer styles, options and overlay.
49
50
  * - Update the viewer.
50
51
  *
51
52
  * The loader must emit events:
52
53
  *
53
- * - `geometryprogress` - during loading. If progress is not supported, emit it once with a value of 100%
54
- * after the load is complete.
54
+ * - `geometryprogress` - during loading (or once at 100% when complete).
55
55
  * - `databasechunk` - when model is loaded and ready to render.
56
56
  * 5. Override {@link ILoader.dispose} and release loader resources, if required.
57
- * 6. Register loader provider in the loaders registry by calling the {@link loaders.registerLoader}.
57
+ * 6. Use `this.abortController` (defined in `Loader` class) to abort loading raw data.
58
+ * 7. Register loader provider in the loaders registry by calling the {@link loaders.registerLoader}.
58
59
  *
59
60
  * @example Implementing a custom loader.
60
61
  *
@@ -70,21 +71,25 @@ import { VSFXCloudPartialLoader } from "./VSFXCloudPartialLoader";
70
71
  * }
71
72
  *
72
73
  * override isSupport(file, format): Boolean {
73
- * // place custom logic here
74
- * return ...;
74
+ * // check if this loader supports the file source and format
75
+ * return type file === "string" && format === "myformat";
75
76
  * }
76
77
  *
77
78
  * override load(file, format, params): Promise<this> {
79
+ * // load VSFX data from file (custom loading logic)
80
+ * const data = await fetch(file).then((result) => result.arrayBuffer());
78
81
  *
79
- * // place custom loading logic here
80
- * const data = ...
82
+ * const modelImpl = new ModelImpl();
83
+ * modelImpl.id = params.modelId;
81
84
  *
82
- * this.viewer.visualizeJs.getViewer().parseVsfx(data);
85
+ * this.viewer.visViewer().parseVsfx(new Uint8Array(data));
86
+ * this.viewer.models.push(modelImpl);
83
87
  *
84
88
  * this.viewer.syncOptions();
85
89
  * this.viewer.syncOverlay();
86
90
  * this.viewer.update();
87
91
  *
92
+ * this.viewer.emitEvent({ type: "geometryprogress", data: 1, file });
88
93
  * this.viewer.emitEvent({ type: "databasechunk", data, file });
89
94
  *
90
95
  * return Promise.resove(this);
@@ -0,0 +1,29 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
24
+ import { IModel } from "@inweb/viewer-core";
25
+
26
+ /**
27
+ * Basic model implementation.
28
+ */
29
+ export type IModelImpl = IModel;
@@ -0,0 +1,32 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
24
+ import { IModelImpl } from "./IModelImpl";
25
+
26
+ // Basic model implementation.
27
+
28
+ export class ModelImpl implements IModelImpl {
29
+ public id: string;
30
+
31
+ dispose(): void {}
32
+ }