@inweb/viewer-visualize 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 (41) hide show
  1. package/README.md +6 -4
  2. package/dist/viewer-visualize.js +591 -475
  3. package/dist/viewer-visualize.js.map +1 -1
  4. package/dist/viewer-visualize.min.js +1 -1
  5. package/dist/viewer-visualize.module.js +583 -483
  6. package/dist/viewer-visualize.module.js.map +1 -1
  7. package/lib/Viewer/Commands/GetSelected2.d.ts +2 -0
  8. package/lib/Viewer/Commands/SetSelected.d.ts +1 -1
  9. package/lib/Viewer/Commands/SetSelected2.d.ts +2 -0
  10. package/lib/Viewer/Components/index.d.ts +8 -7
  11. package/lib/Viewer/Draggers/MeasureLineDragger/MeasureLineItem.d.ts +5 -1
  12. package/lib/Viewer/Draggers/MeasureLineDragger/index.d.ts +3 -2
  13. package/lib/Viewer/Loaders/VSFXCloudLoader.d.ts +1 -1
  14. package/lib/Viewer/Loaders/VSFXCloudPartialLoader.d.ts +1 -1
  15. package/lib/Viewer/Loaders/index.d.ts +14 -9
  16. package/lib/Viewer/Models/IModelImpl.d.ts +5 -0
  17. package/lib/Viewer/Models/ModelImpl.d.ts +5 -0
  18. package/lib/Viewer/Viewer.d.ts +129 -136
  19. package/package.json +5 -5
  20. package/src/Viewer/Commands/ClearSelected.ts +3 -1
  21. package/src/Viewer/Commands/GetSelected2.ts +33 -0
  22. package/src/Viewer/Commands/HideSelected.ts +3 -1
  23. package/src/Viewer/Commands/SelectModel.ts +2 -3
  24. package/src/Viewer/Commands/SetSelected.ts +5 -2
  25. package/src/Viewer/Commands/SetSelected2.ts +39 -0
  26. package/src/Viewer/Commands/index.ts +4 -0
  27. package/src/Viewer/Components/index.ts +8 -7
  28. package/src/Viewer/Draggers/Common/OdBaseDragger.ts +3 -2
  29. package/src/Viewer/Draggers/MeasureLineDragger/MeasureLineItem.ts +44 -13
  30. package/src/Viewer/Draggers/MeasureLineDragger/index.ts +53 -18
  31. package/src/Viewer/Draggers/OdJoyStickDragger.ts +2 -2
  32. package/src/Viewer/Loaders/VSFCloudLoader.ts +6 -0
  33. package/src/Viewer/Loaders/VSFFileLoader.ts +7 -1
  34. package/src/Viewer/Loaders/VSFXCloudLoader.ts +7 -1
  35. package/src/Viewer/Loaders/VSFXCloudPartialLoader.ts +8 -2
  36. package/src/Viewer/Loaders/VSFXCloudStreamingLoader.ts +7 -1
  37. package/src/Viewer/Loaders/VSFXFileLoader.ts +7 -1
  38. package/src/Viewer/Loaders/index.ts +14 -9
  39. package/src/Viewer/Models/IModelImpl.ts +29 -0
  40. package/src/Viewer/Models/ModelImpl.ts +32 -0
  41. package/src/Viewer/Viewer.ts +780 -775
@@ -30,11 +30,12 @@ import {
30
30
  FileSource,
31
31
  IClippingPlane,
32
32
  IComponent,
33
- IEntity,
34
33
  IDragger,
34
+ IEntity,
35
35
  ILoader,
36
36
  IOrthogonalCamera,
37
37
  IOptions,
38
+ IPerspectiveCamera,
38
39
  IPoint,
39
40
  IViewer,
40
41
  IViewpoint,
@@ -48,6 +49,7 @@ import { draggers } from "./Draggers";
48
49
  import { commands } from "./Commands";
49
50
  import { components } from "./Components";
50
51
  import { loaders } from "./Loaders";
52
+ import { IModelImpl } from "./Models/IModelImpl";
51
53
 
52
54
  import { loadVisualizeJs } from "./utils";
53
55
  import { MarkupFactory, MarkupType } from "./Markup/MarkupFactory";
@@ -57,36 +59,38 @@ const OVERLAY_VIEW_NAME = "$OVERLAY_VIEW_NAME";
57
59
  const isExist = (value) => value !== undefined && value !== null;
58
60
 
59
61
  /**
60
- * 3D viewer powered by {@link https://cloud.opendesign.com/docs/index.html#/visualizejs | VisualizeJS}
61
- * library.
62
+ * 3D viewer powered by {@link https://cloud.opendesign.com/docs/index.html#/visualizejs | VisualizeJS}.
62
63
  */
63
64
  export class Viewer
64
65
  extends EventEmitter2<ViewerEventMap & CanvasEventMap & OptionsEventMap>
65
66
  implements IViewer, IWorldTransform
66
67
  {
68
+ public client: Client | undefined;
69
+ public options: IOptions;
70
+ public canvas: HTMLCanvasElement | undefined;
71
+ public canvasEvents: string[];
72
+ public loaders: ILoader[];
73
+ public models: IModelImpl[];
74
+
75
+ private canvaseventlistener: (event: Event) => void;
76
+
77
+ private _visualizeJsUrl = "";
78
+ private _visualizeJs: any;
79
+ private _visualizeTimestamp: number;
80
+ private _viewer: any;
81
+ private _crossOrigin;
82
+
67
83
  private _activeDragger: IDragger | null;
68
- private _components: Array<IComponent>;
69
- private _enableAutoUpdate: boolean;
84
+ private _components: IComponent[];
85
+
70
86
  private _renderNeeded: boolean;
71
87
  private _renderTime: DOMHighResTimeStamp;
88
+ private _enableAutoUpdate: boolean;
72
89
  private _isRunAsyncUpdate: boolean;
73
90
 
74
- protected _options: Options;
75
- protected _visualizeJsUrl = "";
76
- protected _visualizeJs: any;
77
- protected _visualizeTimestamp: number;
78
- protected _viewer: any;
79
- protected _crossOrigin;
80
-
81
- private canvaseventlistener: (event: Event) => void;
91
+ public _abortControllerForReferences: AbortController | undefined;
82
92
 
83
- public canvasEvents: string[];
84
93
  private _markup: IMarkup;
85
- public canvas: HTMLCanvasElement | undefined;
86
-
87
- public _abortControllerForReferences: AbortController | undefined;
88
- public client: Client | undefined;
89
- public loaders: Array<ILoader>;
90
94
 
91
95
  /**
92
96
  * @param client - The `Client` instance that is used to load model reference files from the Open Cloud
@@ -113,21 +117,20 @@ export class Viewer
113
117
  super();
114
118
  this.configure(params);
115
119
 
116
- this._options = new Options(this);
117
-
118
120
  this.client = client;
121
+ this.options = new Options(this);
119
122
  this.loaders = [];
123
+ this.models = [];
124
+
125
+ this.canvasEvents = CANVAS_EVENTS.slice();
126
+ this.canvaseventlistener = (event: Event) => this.emit(event);
120
127
 
121
128
  this._activeDragger = null;
122
129
  this._components = [];
123
130
 
131
+ this._renderNeeded = false;
124
132
  this._renderTime = 0;
125
-
126
- this.canvasEvents = CANVAS_EVENTS.slice();
127
- this.canvaseventlistener = (event: Event) => this.emit(event);
128
-
129
133
  this._enableAutoUpdate = params.enableAutoUpdate ?? true;
130
- this._renderNeeded = false;
131
134
  this._isRunAsyncUpdate = false;
132
135
 
133
136
  this.render = this.render.bind(this);
@@ -136,13 +139,6 @@ export class Viewer
136
139
  this._markup = MarkupFactory.createMarkup(params.markupType);
137
140
  }
138
141
 
139
- /**
140
- * Viewer options.
141
- */
142
- get options(): IOptions {
143
- return this._options;
144
- }
145
-
146
142
  /**
147
143
  * `VisualizeJS` library URL. Use {@link configure | configure()} to change library URL.
148
144
  *
@@ -152,6 +148,30 @@ export class Viewer
152
148
  return this._visualizeJsUrl;
153
149
  }
154
150
 
151
+ /**
152
+ * Returns `VisualizeJS` {@link https://cloud.opendesign.com/docs/index.html#/visualizejs_api | module}
153
+ * instance.
154
+ */
155
+ get visualizeJs(): any {
156
+ return this._visualizeJs;
157
+ }
158
+
159
+ /**
160
+ * Returns `VisualizeJS` {@link https://cloud.opendesign.com/docs/index.html#/visualizejs_api | module}
161
+ * instance.
162
+ */
163
+ visLib(): any {
164
+ return this._visualizeJs;
165
+ }
166
+
167
+ /**
168
+ * Returns `VisualizeJS` {@link https://cloud.opendesign.com/docs/index.html#/vis/Viewer | Viewer}
169
+ * instance.
170
+ */
171
+ visViewer(): any {
172
+ return this._viewer;
173
+ }
174
+
155
175
  /**
156
176
  * 2D markup core instance used to create markups.
157
177
  *
@@ -179,6 +199,16 @@ export class Viewer
179
199
  return this;
180
200
  }
181
201
 
202
+ // IViewer
203
+
204
+ get draggers(): string[] {
205
+ return [...draggers.getDraggers().keys()];
206
+ }
207
+
208
+ get components(): string[] {
209
+ return [...components.getComponents().keys()];
210
+ }
211
+
182
212
  /**
183
213
  * Loads the `VisualizeJS` module and initializes it with the specified canvas. Call
184
214
  * {@link dispose | dispose()} to release allocated resources.
@@ -197,12 +227,13 @@ export class Viewer
197
227
  async initialize(canvas: HTMLCanvasElement, onProgress?: (event: ProgressEvent) => void): Promise<this> {
198
228
  this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
199
229
 
230
+ const pixelRatio = window.devicePixelRatio;
200
231
  const rect = canvas.parentElement.getBoundingClientRect();
201
232
  const width = rect.width || 1;
202
233
  const height = rect.height || 1;
203
234
 
204
- canvas.width = Math.round(width * window.devicePixelRatio);
205
- canvas.height = Math.round(height * window.devicePixelRatio);
235
+ canvas.width = Math.round(width * pixelRatio);
236
+ canvas.height = Math.round(height * pixelRatio);
206
237
 
207
238
  canvas.style.width = width + "px";
208
239
  canvas.style.height = height + "px";
@@ -306,28 +337,7 @@ export class Viewer
306
337
  this.emitEvent({ type: "resize", width, height });
307
338
  }
308
339
 
309
- // internal render/resize routines
310
-
311
- public render(time?: DOMHighResTimeStamp) {
312
- if (!this.visualizeJs) return;
313
- if (this._isRunAsyncUpdate) return;
314
-
315
- const renderNeeded = this.visViewer().isRunningAnimation() || this._renderNeeded;
316
- if (!renderNeeded) return;
317
-
318
- if (!time) time = performance.now();
319
- const deltaTime = (time - this._renderTime) / 1000;
320
-
321
- this._renderTime = time;
322
- this._renderNeeded = !this.visViewer().getActiveDevice().isValid();
323
-
324
- this.visViewer().update();
325
- this._activeDragger?.updatePreview?.();
326
-
327
- this.emitEvent({ type: "render", time, deltaTime });
328
- }
329
-
330
- public resize(): this {
340
+ resize(): this {
331
341
  console.warn(
332
342
  "Viewer.resize() has been deprecated since 26.9 and will be removed in a future release, use Viewer.setSize() instead."
333
343
  );
@@ -365,515 +375,76 @@ export class Viewer
365
375
  this.emitEvent({ type: "update", data: force });
366
376
  }
367
377
 
368
- private scheduleUpdateAsync(maxScheduleUpdateTimeInMs = 50): Promise<void> {
369
- return new Promise<void>((resolve, reject) => {
370
- setTimeout(() => {
371
- try {
372
- if (this._enableAutoUpdate) {
373
- this.visViewer()?.update(maxScheduleUpdateTimeInMs);
374
- this._activeDragger?.updatePreview?.();
375
- }
376
- this.emitEvent({ type: "update", data: false });
377
- resolve();
378
- } catch (e) {
379
- console.error(e);
380
- reject();
381
- }
382
- }, 0);
383
- });
384
- }
378
+ // Internal render routines
385
379
 
386
- /**
387
- * Updates the viewer asynchronously without locking the user interface. Used to update the viewer
388
- * after changes that require a long rendering time.
389
- *
390
- * Do nothing if the auto-update mode is disabled in the constructor. In this case, register an
391
- * `update` event handler and update the `VisualizeJS` viewer and active dragger manually.
392
- *
393
- * Fires:
394
- *
395
- * - {@link UpdateEvent | update}
396
- *
397
- * @param maxScheduleUpdateTimeInMs - Maximum time for one update, default 30 ms.
398
- * @param maxScheduleUpdateCount - Maximum count of scheduled updates.
399
- */
400
- async updateAsync(maxScheduleUpdateTimeInMs = 50, maxScheduleUpdateCount = 50): Promise<void> {
380
+ render(time?: DOMHighResTimeStamp) {
401
381
  if (!this.visualizeJs) return;
382
+ if (this._isRunAsyncUpdate) return;
402
383
 
403
- this._isRunAsyncUpdate = true;
404
- try {
405
- const device = this.visViewer().getActiveDevice();
406
- for (let iterationCount = 0; !device.isValid() && iterationCount < maxScheduleUpdateCount; iterationCount++) {
407
- await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
408
- }
409
- await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
410
- } catch (e) {
411
- console.error(e);
412
- } finally {
413
- this._isRunAsyncUpdate = false;
414
- }
415
- }
384
+ const renderNeeded = this.visViewer().isRunningAnimation() || this._renderNeeded;
385
+ if (!renderNeeded) return;
416
386
 
417
- /**
418
- * Returns `VisualizeJS` {@link https://cloud.opendesign.com/docs/index.html#/visualizejs_api | module}
419
- * instance.
420
- */
421
- get visualizeJs(): any {
422
- return this._visualizeJs;
423
- }
387
+ if (!time) time = performance.now();
388
+ const deltaTime = (time - this._renderTime) / 1000;
424
389
 
425
- /**
426
- * Returns `VisualizeJS` {@link https://cloud.opendesign.com/docs/index.html#/visualizejs_api | module}
427
- * instance.
428
- */
429
- visLib(): any {
430
- return this._visualizeJs;
431
- }
390
+ this._renderTime = time;
391
+ this._renderNeeded = !this.visViewer().getActiveDevice().isValid();
432
392
 
433
- /**
434
- * Returns `VisualizeJS` {@link https://cloud.opendesign.com/docs/index.html#/vis/Viewer | Viewer}
435
- * instance.
436
- */
437
- visViewer(): any {
438
- return this._viewer;
393
+ this.visViewer().update();
394
+ this._activeDragger?.updatePreview?.();
395
+
396
+ this.emitEvent({ type: "render", time, deltaTime });
439
397
  }
440
398
 
441
- // update the VisualizeJS options
399
+ // Internal loading routines
442
400
 
443
- syncOpenCloudVisualStyle(): this {
401
+ async loadReferences(model: Model | File | Assembly): Promise<this> {
444
402
  if (!this.visualizeJs) return this;
403
+ if (!this.client) return this;
404
+ if (!model.getReferences) return this;
445
405
 
446
- const visLib = this.visLib();
447
- const visViewer = this.visViewer();
448
-
449
- const device = visViewer.getActiveDevice();
450
- if (device.isNull()) return this;
451
-
452
- const view = device.getActiveView();
453
-
454
- view.enableDefaultLighting(true, visLib.DefaultLightingType.kTwoLights);
455
- view.setDefaultLightingIntensity(1.25);
456
-
457
- // Visualize.js 25.11 and earlier threw an exception if the style did not exist.
458
- let visualStyleId;
459
- try {
460
- visualStyleId = visViewer.findVisualStyle("OpenCloud");
461
- } catch {
462
- visualStyleId = undefined;
463
- }
406
+ const abortController = new AbortController();
464
407
 
465
- if (!visualStyleId || visualStyleId.isNull()) {
466
- visualStyleId = visViewer.createVisualStyle("OpenCloud");
408
+ this._abortControllerForReferences?.abort();
409
+ this._abortControllerForReferences = abortController;
467
410
 
468
- const colorDef = new visLib.OdTvColorDef(66, 66, 66);
469
- const shadedVsId = visViewer.findVisualStyle("Realistic");
411
+ let references: any[] = [];
412
+ await model
413
+ .getReferences(abortController.signal)
414
+ .then((data) => (references = data.references))
415
+ .catch((e) => console.error("Cannot load model references.", e));
470
416
 
471
- const visualStylePtr = visualStyleId.openObject();
472
- visualStylePtr.copyFrom(shadedVsId);
473
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kFaceModifiers, 0, visLib.VisualStyleOperations.kSet);
474
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModel, 2, visLib.VisualStyleOperations.kSet);
475
- visualStylePtr.setOptionDouble(visLib.VisualStyleOptions.kEdgeCreaseAngle, 60, visLib.VisualStyleOperations.kSet);
476
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeStyles, 0, visLib.VisualStyleOperations.kSet);
477
- visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModifiers, 8, visLib.VisualStyleOperations.kSet);
478
- visualStylePtr.setOptionColor(
479
- visLib.VisualStyleOptions.kEdgeColorValue,
480
- colorDef,
481
- visLib.VisualStyleOperations.kSet
482
- );
483
- visualStylePtr.delete();
417
+ for (const file of references) {
418
+ await this.client
419
+ .downloadFile(file.id, undefined, abortController.signal)
420
+ .then((arrayBuffer) => this.visualizeJs?.getViewer().addEmbeddedFile(file.name, new Uint8Array(arrayBuffer)))
421
+ .catch((e) => console.error(`Cannot load reference file ${file.name}.`, e));
484
422
  }
485
423
 
486
- view.visualStyle = visualStyleId;
487
-
488
- view.delete();
489
- device.delete();
490
-
491
424
  return this;
492
425
  }
493
426
 
494
- syncOptions(options: IOptions = this.options): this {
495
- if (!this.visualizeJs) return this;
427
+ applyModelTransformMatrix(model: Model | Assembly) {
428
+ this.executeCommand("applyModelTransform", model);
429
+ }
496
430
 
497
- this.syncOpenCloudVisualStyle();
431
+ applySceneGraphSettings(options = this.options) {
432
+ if (!this.visualizeJs) return;
498
433
 
499
434
  const visLib = this.visLib();
500
435
  const visViewer = this.visViewer();
501
436
 
502
437
  const device = visViewer.getActiveDevice();
503
- if (device.isNull()) return this;
504
-
505
- if (options.showWCS !== visViewer.getEnableWCS()) {
506
- visViewer.setEnableWCS(options.showWCS);
507
- }
508
- if (options.cameraAnimation !== visViewer.getEnableAnimation()) {
509
- visViewer.setEnableAnimation(options.cameraAnimation);
510
- }
511
-
512
- const antialiasing = options.antialiasing === true || options.antialiasing === "fxaa";
513
- if (antialiasing !== visViewer.fxaaAntiAliasing3d) {
514
- visViewer.fxaaAntiAliasing3d = antialiasing;
515
- visViewer.fxaaQuality = 5;
516
- }
517
-
518
- if (options.shadows !== visViewer.shadows) {
519
- visViewer.shadows = options.shadows;
520
-
521
- const canvas = visLib.canvas;
522
- device.invalidate([0, canvas.width, canvas.height, 0]);
438
+ if (isExist(options.sceneGraph)) {
439
+ device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, !options.sceneGraph);
523
440
  }
441
+ // if (options.enablePartialMode && visLib.HpTrc.Usd >= visViewer.memoryLimit) {
442
+ // device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, true);
443
+ // }
444
+ device.delete();
524
445
 
525
- if (options.groundShadow !== visViewer.groundShadow) {
526
- visViewer.groundShadow = options.groundShadow;
527
- }
528
-
529
- if (options.ambientOcclusion !== device.getOptionBool(visLib.DeviceOptions.kSSAOEnable)) {
530
- device.setOptionBool(visLib.DeviceOptions.kSSAOEnable, options.ambientOcclusion);
531
- device.setOptionBool(visLib.DeviceOptions.kSSAODynamicRadius, true);
532
- device.setOptionDouble(visLib.DeviceOptions.kSSAORadius, 1);
533
- device.setOptionInt32(visLib.DeviceOptions.kSSAOLoops, 32);
534
- device.setOptionDouble(visLib.DeviceOptions.kSSAOPower, 2);
535
- device.setOptionInt32(visLib.DeviceOptions.kSSAOBlurRadius, 2);
536
-
537
- const activeView = visViewer.activeView;
538
- activeView.setSSAOEnabled(options.ambientOcclusion);
539
- activeView.delete();
540
- }
541
-
542
- if (isExist(options.edgeModel)) {
543
- const activeView = device.getActiveView();
544
-
545
- const visualStyleId = visViewer.findVisualStyle("OpenCloud");
546
- const visualStylePtr = visualStyleId.openObject();
547
-
548
- visualStylePtr.setOptionInt32(
549
- visLib.VisualStyleOptions.kEdgeModel,
550
- options.edgeModel ? 2 : 0,
551
- visLib.VisualStyleOperations.kSet
552
- );
553
-
554
- activeView.visualStyle = visualStyleId;
555
-
556
- visualStylePtr.delete();
557
- visualStyleId.delete();
558
- activeView.delete();
559
- }
560
-
561
- device.delete();
562
-
563
- this.syncHighlightingOptions(options);
564
- this.update();
565
-
566
- return this;
567
- }
568
-
569
- syncHighlightingOptions(options: IOptions = this.options): this {
570
- if (!this.visualizeJs) return this;
571
-
572
- const params = options.enableCustomHighlight ? options : Options.defaults();
573
-
574
- const visLib = this.visLib();
575
- const visViewer = this.visViewer();
576
- const { Entry, OdTvRGBColorDef } = visLib;
577
-
578
- const highlightStyleId = visViewer.findHighlightStyle("Web_Default");
579
- const highlightStylePtr = highlightStyleId.openObject();
580
-
581
- if (isExist(params.facesColor)) {
582
- const color = new OdTvRGBColorDef(params.facesColor.r, params.facesColor.g, params.facesColor.b);
583
- highlightStylePtr.setFacesColor(Entry.k3D.value | Entry.k3DTop.value, color);
584
- color.delete();
585
- }
586
-
587
- if (isExist(params.facesOverlap)) {
588
- highlightStylePtr.setFacesVisibility(Entry.k3DTop.value, params.facesOverlap);
589
- }
590
- if (isExist(params.facesTransparancy)) {
591
- highlightStylePtr.setFacesTransparency(Entry.k3D.value | Entry.k3DTop.value, params.facesTransparancy);
592
- }
593
-
594
- if (isExist(params.edgesColor)) {
595
- const color = new OdTvRGBColorDef(params.edgesColor.r, params.edgesColor.g, params.edgesColor.b);
596
- highlightStylePtr.setEdgesColor(
597
- Entry.k3DTop.value | Entry.k3D.value | Entry.k2D.value | Entry.k2DTop.value,
598
- color
599
- );
600
- color.delete();
601
- }
602
-
603
- if (isExist(params.edgesVisibility)) {
604
- highlightStylePtr.setEdgesVisibility(
605
- Entry.k2D.value | Entry.k2DTop.value | Entry.k3DTop.value | Entry.k3D.value,
606
- params.edgesVisibility
607
- );
608
- }
609
- if (isExist(params.edgesOverlap)) {
610
- const visibility = !isExist(params.edgesVisibility) ? true : params.edgesVisibility;
611
- highlightStylePtr.setEdgesVisibility(Entry.k2DTop.value | Entry.k3DTop.value, params.edgesOverlap && visibility);
612
- }
613
-
614
- const device = visViewer.getActiveDevice();
615
- if (!device.isNull()) {
616
- const canvas = visLib.canvas;
617
-
618
- device.invalidate([0, canvas.width, canvas.height, 0]);
619
- device.delete();
620
- }
621
-
622
- return this;
623
- }
624
-
625
- get draggers(): string[] {
626
- return [...draggers.getDraggers().keys()];
627
- }
628
-
629
- get components(): string[] {
630
- return [...components.getComponents().keys()];
631
- }
632
-
633
- /**
634
- * Deprecated since `25.12`. Use {@link draggers.registerDragger} instead.
635
- */
636
- public registerDragger(name: string, dragger: typeof Dragger): void {
637
- console.warn(
638
- "Viewer.registerDragger() has been deprecated since 25.12 and will be removed in a future release, use draggers('visualizejs').registerDragger() instead."
639
- );
640
- draggers.registerDragger(name, (viewer: IViewer) => new dragger(viewer));
641
- }
642
-
643
- activeDragger(): IDragger | null {
644
- return this._activeDragger;
645
- }
646
-
647
- setActiveDragger(name = ""): IDragger | null {
648
- if (!this._activeDragger || this._activeDragger.name !== name) {
649
- const oldDragger = this._activeDragger;
650
- let newDragger = null;
651
-
652
- if (this._activeDragger) {
653
- this._activeDragger.dispose();
654
- this._activeDragger = null;
655
- }
656
- if (this.visualizeJs) {
657
- newDragger = draggers.createDragger(name, this);
658
- if (newDragger) {
659
- this._activeDragger = newDragger;
660
- this._activeDragger.initialize?.();
661
- }
662
- }
663
- const canvas = this.canvas;
664
- if (canvas) {
665
- if (oldDragger) canvas.classList.remove(`oda-cursor-${oldDragger.name.toLowerCase()}`);
666
- if (newDragger) canvas.classList.add(`oda-cursor-${newDragger.name.toLowerCase()}`);
667
- }
668
-
669
- this.emitEvent({ type: "changeactivedragger", data: name });
670
- this.update();
671
- }
672
- return this._activeDragger;
673
- }
674
-
675
- resetActiveDragger(): void {
676
- const dragger = this._activeDragger;
677
- if (dragger) {
678
- this.setActiveDragger();
679
- this.setActiveDragger(dragger.name);
680
- }
681
- }
682
-
683
- getComponent(name: string): IComponent {
684
- return this._components.find((component) => component.name === name);
685
- }
686
-
687
- clearSlices(): void {
688
- if (!this.visualizeJs) return;
689
-
690
- const visViewer = this.visViewer();
691
- const activeView = visViewer.activeView;
692
- activeView.removeCuttingPlanes();
693
- activeView.delete();
694
-
695
- this.update();
696
- }
697
-
698
- clearOverlay(): void {
699
- if (!this.visualizeJs) return;
700
-
701
- this._markup.clearOverlay();
702
- this.update();
703
- }
704
-
705
- syncOverlay(): void {
706
- if (!this.visualizeJs) return;
707
-
708
- const visViewer = this.visViewer();
709
- const activeView = visViewer.activeView;
710
-
711
- let overlayView = visViewer.getViewByName(OVERLAY_VIEW_NAME);
712
- if (!overlayView) {
713
- const markupModel = visViewer.getMarkupModel();
714
- const pDevice = visViewer.getActiveDevice();
715
-
716
- overlayView = pDevice.createView(OVERLAY_VIEW_NAME, false);
717
- overlayView.addModel(markupModel);
718
-
719
- activeView.addSibling(overlayView);
720
- pDevice.addView(overlayView);
721
- }
722
-
723
- overlayView.viewPosition = activeView.viewPosition;
724
- overlayView.viewTarget = activeView.viewTarget;
725
- overlayView.upVector = activeView.upVector;
726
- overlayView.viewFieldWidth = activeView.viewFieldWidth;
727
- overlayView.viewFieldHeight = activeView.viewFieldHeight;
728
-
729
- const viewPort = overlayView.getViewport();
730
- overlayView.setViewport(viewPort.lowerLeft, viewPort.upperRight);
731
- overlayView.vportRect = activeView.vportRect;
732
-
733
- this._markup.syncOverlay();
734
- this.update();
735
- }
736
-
737
- is3D(): boolean {
738
- if (!this.visualizeJs) return false;
739
-
740
- const visViewer = this.visViewer();
741
- const ext = visViewer.getActiveExtents();
742
- const min = ext.min();
743
- const max = ext.max();
744
- const extHeight = max[2] - min[2];
745
- return extHeight !== 0;
746
-
747
- //return visViewer.activeView.upVector[1] >= 0.95;
748
- }
749
-
750
- screenToWorld(position: { x: number; y: number }): { x: number; y: number; z: number } {
751
- if (!this.visualizeJs) return { x: position.x, y: position.y, z: 0 };
752
-
753
- const activeView = this.visViewer().activeView;
754
- const worldPoint = activeView.transformScreenToWorld(
755
- position.x * window.devicePixelRatio,
756
- position.y * window.devicePixelRatio
757
- );
758
-
759
- const result = { x: worldPoint[0], y: worldPoint[1], z: worldPoint[2] };
760
-
761
- activeView.delete();
762
-
763
- return result;
764
- }
765
-
766
- worldToScreen(position: { x: number; y: number; z: number }): { x: number; y: number } {
767
- if (!this.visualizeJs) return { x: position.x, y: position.y };
768
-
769
- const activeView = this.visViewer().activeView;
770
- const devicePoint = activeView.transformWorldToScreen(position.x, position.y, position.z);
771
-
772
- const result = { x: devicePoint[0] / window.devicePixelRatio, y: devicePoint[1] / window.devicePixelRatio };
773
-
774
- activeView.delete();
775
-
776
- return result;
777
- }
778
-
779
- getScale(): { x: number; y: number; z: number } {
780
- const result = { x: 1.0, y: 1.0, z: 1.0 };
781
-
782
- const projMatrix = this.visViewer().activeView.projectionMatrix;
783
- const tolerance = 1.0e-6;
784
-
785
- const x = projMatrix.get(0, 0);
786
- if (x > tolerance || x < -tolerance) result.x = 1 / x;
787
-
788
- const y = projMatrix.get(1, 1);
789
- if (y > tolerance || y < -tolerance) result.y = 1 / y;
790
-
791
- const z = projMatrix.get(2, 2);
792
- if (z > tolerance || z < -tolerance) result.z = 1 / z;
793
-
794
- return result;
795
- }
796
-
797
- getSelected(): string[] {
798
- return this.executeCommand("getSelected");
799
- }
800
-
801
- setSelected(handles?: string[]): void {
802
- this.executeCommand("setSelected", handles);
803
- }
804
-
805
- clearSelected(): void {
806
- this.executeCommand("clearSelected");
807
- }
808
-
809
- hideSelected(): void {
810
- this.executeCommand("hideSelected");
811
- }
812
-
813
- isolateSelected(): void {
814
- this.executeCommand("isolateSelected");
815
- }
816
-
817
- showAll(): void {
818
- this.executeCommand("showAll");
819
- }
820
-
821
- explode(index = 0): void {
822
- this.executeCommand("explode", index);
823
- }
824
-
825
- collect(): void {
826
- this.executeCommand("collect");
827
- }
828
-
829
- // Internal loading routines
830
-
831
- async loadReferences(model: Model | File | Assembly): Promise<this> {
832
- if (!this.visualizeJs) return this;
833
- if (!this.client) return this;
834
- if (!model.getReferences) return this;
835
-
836
- const abortController = new AbortController();
837
- this._abortControllerForReferences?.abort();
838
- this._abortControllerForReferences = abortController;
839
-
840
- let references: any[] = [];
841
- await model
842
- .getReferences(abortController.signal)
843
- .then((data) => (references = data.references))
844
- .catch((e) => console.error("Cannot load model references.", e));
845
-
846
- for (const file of references) {
847
- await this.client
848
- .downloadFile(file.id, undefined, abortController.signal)
849
- .then((arrayBuffer) => this.visualizeJs?.getViewer().addEmbeddedFile(file.name, new Uint8Array(arrayBuffer)))
850
- .catch((e) => console.error(`Cannot load reference file ${file.name}.`, e));
851
- }
852
-
853
- return this;
854
- }
855
-
856
- applyModelTransformMatrix(model: Model | Assembly) {
857
- this.executeCommand("applyModelTransform", model);
858
- }
859
-
860
- applySceneGraphSettings(options = this.options) {
861
- if (!this.visualizeJs) return;
862
-
863
- const visLib = this.visLib();
864
- const visViewer = this.visViewer();
865
-
866
- const device = visViewer.getActiveDevice();
867
- if (isExist(options.sceneGraph)) {
868
- device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, !options.sceneGraph);
869
- }
870
- // if (options.enablePartialMode && visLib.HpTrc.Usd >= visViewer.memoryLimit) {
871
- // device.setOptionBool(visLib.DeviceOptions.kDelaySceneGraphProc, true);
872
- // }
873
- device.delete();
874
-
875
- this.update();
876
- }
446
+ this.update();
447
+ }
877
448
 
878
449
  /**
879
450
  * Loads a file into the viewer.
@@ -890,8 +461,8 @@ export class Viewer
890
461
  * thrown.
891
462
  *
892
463
  * For URLs, the file extension is used to determine the file format. For a `ArrayBuffer` and `Data
893
- * URL`, a file format must be specified using `params.format` parameter (see below). If no appropriate
894
- * loader is found for the specified format, an exception will be thrown.
464
+ * URL`, a file format must be specified using `params.format` parameter. If no appropriate loader is
465
+ * found for the specified format, an exception will be thrown.
895
466
  *
896
467
  * If there was an active dragger before opening the file, it will be deactivated. After opening the
897
468
  * file, you must manually activate the required dragger.
@@ -908,6 +479,8 @@ export class Viewer
908
479
  *
909
480
  * Fires:
910
481
  *
482
+ * - {@link CancelEvent | cancel}
483
+ * - {@link ClearEvent | clear}
911
484
  * - {@link OpenEvent | open}
912
485
  * - {@link GeometryStartEvent | geometrystart}
913
486
  * - {@link GeometryProgressEvent | geometryprogress}
@@ -916,19 +489,20 @@ export class Viewer
916
489
  * - {@link GeometryEndEvent | geometryend}
917
490
  * - {@link GeometryErrorEvent | geometryerror}
918
491
  *
919
- * @param file - File to load. Can be one of:
492
+ * @param file - File to load. Can be:
920
493
  *
921
494
  * - `File`, `Assembly` or `Model` instance from the Open Cloud Server
922
- * - File `URL` string
495
+ * - `URL` string
923
496
  * - {@link https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/Data_URIs | Data URL} string
924
- * - {@link https://developer.mozilla.org/docs/Web/API/File | Web API File} object
497
+ * - {@link https://developer.mozilla.org/docs/Web/API/File | Web API dFile} object
925
498
  * - {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer | ArrayBuffer}
926
499
  * object
927
500
  *
928
501
  * @param params - Loading parameters.
929
- * @param params.format - File format string. Required when loading a file as `ArrayBuffer` or `Data
930
- * URL`.
502
+ * @param params.format - File format. Can be one of `vsf` or `vsfx`. Required when loading a file as
503
+ * `ArrayBuffer` or `Data URL`.
931
504
  * @param params.mode - Reserved for future use.
505
+ * @param params.modelId - Reserved for future use.
932
506
  * @param params.requestHeader - The
933
507
  * {@link https://developer.mozilla.org/docs/Glossary/Request_header | request header} used in HTTP
934
508
  * request.
@@ -942,227 +516,529 @@ export class Viewer
942
516
  params: {
943
517
  format?: string;
944
518
  mode?: string;
519
+ modelId?: string;
945
520
  requestHeader?: HeadersInit;
946
521
  withCredentials?: boolean;
947
522
  } = {}
948
523
  ): Promise<this> {
949
524
  if (!this.visualizeJs) return this;
950
525
 
951
- this.cancel();
952
- this.clear();
526
+ this.cancel();
527
+ this.clear();
528
+
529
+ this.emitEvent({ type: "open", mode: "file", file });
530
+
531
+ let model: any = file;
532
+ if (model && typeof model.getModels === "function") {
533
+ const models = await model.getModels();
534
+ model = models.find((model: Model) => model.default) || models[0] || file;
535
+ }
536
+ if (model && typeof model.database === "string") {
537
+ file = model.file;
538
+ }
539
+ if (!model) throw new Error(`Format not supported`);
540
+
541
+ let format = params.format;
542
+ if (!format && typeof file["type"] === "string") format = file["type"].split(".").pop();
543
+ if (!format && typeof file === "string") format = file.split(".").pop();
544
+ if (!format && file instanceof globalThis.File) format = file.name.split(".").pop();
545
+
546
+ const loader = loaders.createLoader(this, model, format);
547
+ if (!loader) throw new Error(`Format not supported`);
548
+ this.loaders.push(loader);
549
+
550
+ this.emitEvent({ type: "geometrystart", file, model });
551
+ try {
552
+ await this.loadReferences(model);
553
+ await loader.load(model, format, params);
554
+ } catch (error: any) {
555
+ this.emitEvent({ type: "geometryerror", data: error, file, model });
556
+ throw error;
557
+ }
558
+ this.emitEvent({ type: "geometryend", file, model });
559
+
560
+ if (this.visualizeJs) {
561
+ this.applyModelTransformMatrix(model);
562
+ this.applySceneGraphSettings();
563
+ }
564
+
565
+ return this;
566
+ }
567
+
568
+ /**
569
+ * Deprecated since `26.4`. Use {@link open | open()} instead.
570
+ *
571
+ * @deprecated
572
+ */
573
+ openVsfFile(buffer: Uint8Array | ArrayBuffer): this {
574
+ console.warn(
575
+ "Viewer.openVsfFile() has been deprecated since 26.4 and will be removed in a future release, use Viewer.open() instead."
576
+ );
577
+
578
+ if (!this.visualizeJs) return this;
579
+
580
+ this.cancel();
581
+ this.clear();
582
+
583
+ this.emitEvent({ type: "open", mode: "file", file: "", buffer });
584
+
585
+ const visViewer = this.visViewer();
586
+
587
+ this.emitEvent({ type: "geometrystart", file: "", buffer });
588
+ try {
589
+ const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
590
+ visViewer.parseFile(data);
591
+
592
+ this.syncOptions();
593
+ this.syncOverlay();
594
+ this.update(true);
595
+
596
+ this.emitEvent({ type: "geometryprogress", data: 1, file: "", buffer });
597
+ this.emitEvent({ type: "databasechunk", data, file: "", buffer });
598
+ } catch (error: any) {
599
+ this.emitEvent({ type: "geometryerror", data: error, file: "", buffer });
600
+ throw error;
601
+ }
602
+ this.emitEvent({ type: "geometryend", file: "", buffer });
603
+
604
+ return this;
605
+ }
606
+
607
+ /**
608
+ * Deprecated since `26.4`. Use {@link open | open()} instead.
609
+ *
610
+ * @deprecated
611
+ */
612
+ openVsfxFile(buffer: Uint8Array | ArrayBuffer): this {
613
+ console.warn(
614
+ "Viewer.openVsfxFile() has been deprecated since 26.4 and will be removed in a future release, use Viewer.open() instead."
615
+ );
616
+
617
+ if (!this.visualizeJs) return this;
618
+
619
+ this.cancel();
620
+ this.clear();
621
+
622
+ this.emitEvent({ type: "open", mode: "file", file: "", buffer });
623
+
624
+ const visViewer = this.visViewer();
625
+
626
+ this.emitEvent({ type: "geometrystart", file: "", buffer });
627
+ try {
628
+ const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
629
+ visViewer.parseVsfx(data);
630
+
631
+ this.syncOptions();
632
+ this.syncOverlay();
633
+ this.update(true);
634
+
635
+ this.emitEvent({ type: "geometryprogress", data: 1, file: "", buffer });
636
+ this.emitEvent({ type: "databasechunk", data, file: "", buffer });
637
+ } catch (error: any) {
638
+ this.emitEvent({ type: "geometryerror", data: error, file: "", buffer });
639
+ throw error;
640
+ }
641
+ this.emitEvent({ type: "geometryend", file: "", buffer });
642
+
643
+ return this;
644
+ }
645
+
646
+ cancel(): this {
647
+ this._abortControllerForReferences?.abort();
648
+ this._abortControllerForReferences = undefined;
649
+
650
+ this.loaders.forEach((loader) => loader.cancel());
651
+
652
+ this.emitEvent({ type: "cancel" });
653
+ return this;
654
+ }
655
+
656
+ clear(): this {
657
+ if (!this.visualizeJs) return this;
658
+
659
+ const visViewer = this.visViewer();
660
+
661
+ this.setActiveDragger();
662
+ this.clearSlices();
663
+ this.clearOverlay();
664
+ this.clearSelected();
665
+
666
+ this.loaders.forEach((loader) => loader.dispose());
667
+ this.loaders = [];
668
+
669
+ this.models.forEach((model) => model.dispose());
670
+ this.models = [];
671
+
672
+ visViewer.clear();
673
+ visViewer.createLocalDatabase();
674
+
675
+ this.syncOptions();
676
+ this.syncOverlay();
677
+ this.update(true);
678
+
679
+ this.emitEvent({ type: "clear" });
680
+
681
+ return this;
682
+ }
683
+
684
+ is3D(): boolean {
685
+ if (!this.visualizeJs) return false;
686
+
687
+ const visViewer = this.visViewer();
688
+ const ext = visViewer.getActiveExtents();
689
+ const min = ext.min();
690
+ const max = ext.max();
691
+ const extHeight = max[2] - min[2];
692
+ return extHeight !== 0;
693
+
694
+ //return visViewer.activeView.upVector[1] >= 0.95;
695
+ }
696
+
697
+ syncOptions(options: IOptions = this.options): this {
698
+ if (!this.visualizeJs) return this;
699
+
700
+ const visLib = this.visLib();
701
+ const visViewer = this.visViewer();
702
+
703
+ const device = visViewer.getActiveDevice();
704
+ if (device.isNull()) return this;
705
+
706
+ // sync Open Cloud visual style
707
+
708
+ const view = device.getActiveView();
709
+
710
+ view.enableDefaultLighting(true, visLib.DefaultLightingType.kTwoLights);
711
+ view.setDefaultLightingIntensity(1.25);
712
+
713
+ let visualStyleId: any;
714
+ try {
715
+ visualStyleId = visViewer.findVisualStyle("OpenCloud");
716
+ } catch {
717
+ // Visualize.js 25.11 and earlier threw an exception if the style did not exist.
718
+ visualStyleId = undefined;
719
+ }
720
+
721
+ if (!visualStyleId || visualStyleId.isNull()) {
722
+ visualStyleId = visViewer.createVisualStyle("OpenCloud");
723
+
724
+ const colorDef = new visLib.OdTvColorDef(66, 66, 66);
725
+ const shadedVsId = visViewer.findVisualStyle("Realistic");
726
+
727
+ const visualStylePtr = visualStyleId.openObject();
728
+ visualStylePtr.copyFrom(shadedVsId);
729
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kFaceModifiers, 0, visLib.VisualStyleOperations.kSet);
730
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModel, 2, visLib.VisualStyleOperations.kSet);
731
+ visualStylePtr.setOptionDouble(visLib.VisualStyleOptions.kEdgeCreaseAngle, 60, visLib.VisualStyleOperations.kSet);
732
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeStyles, 0, visLib.VisualStyleOperations.kSet);
733
+ visualStylePtr.setOptionInt32(visLib.VisualStyleOptions.kEdgeModifiers, 8, visLib.VisualStyleOperations.kSet);
734
+ visualStylePtr.setOptionColor(
735
+ visLib.VisualStyleOptions.kEdgeColorValue,
736
+ colorDef,
737
+ visLib.VisualStyleOperations.kSet
738
+ );
739
+ visualStylePtr.delete();
740
+ }
741
+
742
+ view.visualStyle = visualStyleId;
743
+
744
+ // sync Visualize options
745
+
746
+ if (options.showWCS !== visViewer.getEnableWCS()) {
747
+ visViewer.setEnableWCS(options.showWCS);
748
+ }
749
+ if (options.cameraAnimation !== visViewer.getEnableAnimation()) {
750
+ visViewer.setEnableAnimation(options.cameraAnimation);
751
+ }
752
+
753
+ const antialiasing = options.antialiasing === true || options.antialiasing === "fxaa";
754
+ if (antialiasing !== visViewer.fxaaAntiAliasing3d) {
755
+ visViewer.fxaaAntiAliasing3d = antialiasing;
756
+ visViewer.fxaaQuality = 5;
757
+ }
758
+
759
+ if (options.shadows !== visViewer.shadows) {
760
+ visViewer.shadows = options.shadows;
761
+
762
+ // const canvas = visLib.canvas;
763
+ // device.invalidate([0, canvas.width, canvas.height, 0]);
764
+ }
765
+
766
+ if (options.groundShadow !== visViewer.groundShadow) {
767
+ visViewer.groundShadow = options.groundShadow;
768
+ }
769
+
770
+ if (options.ambientOcclusion !== device.getOptionBool(visLib.DeviceOptions.kSSAOEnable)) {
771
+ device.setOptionBool(visLib.DeviceOptions.kSSAOEnable, options.ambientOcclusion);
772
+ device.setOptionBool(visLib.DeviceOptions.kSSAODynamicRadius, true);
773
+ device.setOptionDouble(visLib.DeviceOptions.kSSAORadius, 1);
774
+ device.setOptionInt32(visLib.DeviceOptions.kSSAOLoops, 32);
775
+ device.setOptionDouble(visLib.DeviceOptions.kSSAOPower, 2);
776
+ device.setOptionInt32(visLib.DeviceOptions.kSSAOBlurRadius, 2);
777
+
778
+ const activeView = visViewer.activeView;
779
+ activeView.setSSAOEnabled(options.ambientOcclusion);
780
+ activeView.delete();
781
+ }
953
782
 
954
- this.emitEvent({ type: "open", file });
783
+ if (isExist(options.edgeModel)) {
784
+ const activeView = device.getActiveView();
955
785
 
956
- let model: any = file;
957
- if (model && typeof model.getModels === "function") {
958
- const models = await model.getModels();
959
- model = models.find((model: Model) => model.default) || models[0] || file;
786
+ const visualStyleId = visViewer.findVisualStyle("OpenCloud");
787
+ const visualStylePtr = visualStyleId.openObject();
788
+
789
+ visualStylePtr.setOptionInt32(
790
+ visLib.VisualStyleOptions.kEdgeModel,
791
+ options.edgeModel ? 2 : 0,
792
+ visLib.VisualStyleOperations.kSet
793
+ );
794
+
795
+ activeView.visualStyle = visualStyleId;
796
+
797
+ visualStylePtr.delete();
798
+ visualStyleId.delete();
799
+ activeView.delete();
960
800
  }
961
- if (!model) throw new Error(`Format not supported`);
962
801
 
963
- let format = params.format;
964
- if (!format && typeof model.type === "string") format = model.type.split(".").pop();
965
- if (!format && typeof file === "string") format = file.split(".").pop();
966
- if (!format && file instanceof globalThis.File) format = file.name.split(".").pop();
802
+ // sync highlighting options
967
803
 
968
- const loader = loaders.createLoader(this, model, format);
969
- if (!loader) throw new Error(`Format not supported`);
970
- this.loaders.push(loader);
804
+ const params = options.enableCustomHighlight ? options : Options.defaults();
971
805
 
972
- this.emitEvent({ type: "geometrystart", file, model });
973
- try {
974
- await this.loadReferences(model);
975
- await loader.load(model, format, params);
976
- } catch (error: any) {
977
- this.emitEvent({ type: "geometryerror", data: error, file, model });
978
- throw error;
806
+ const { Entry, OdTvRGBColorDef } = visLib;
807
+
808
+ const highlightStyleId = visViewer.findHighlightStyle("Web_Default");
809
+ const highlightStylePtr = highlightStyleId.openObject();
810
+
811
+ if (isExist(params.facesColor)) {
812
+ const color = new OdTvRGBColorDef(params.facesColor.r, params.facesColor.g, params.facesColor.b);
813
+ highlightStylePtr.setFacesColor(Entry.k3D.value | Entry.k3DTop.value, color);
814
+ color.delete();
979
815
  }
980
- this.emitEvent({ type: "geometryend", file, model });
981
816
 
982
- if (this.visualizeJs) {
983
- this.applyModelTransformMatrix(model);
984
- this.applySceneGraphSettings();
817
+ if (isExist(params.facesOverlap)) {
818
+ highlightStylePtr.setFacesVisibility(Entry.k3DTop.value, params.facesOverlap);
819
+ }
820
+ if (isExist(params.facesTransparancy)) {
821
+ highlightStylePtr.setFacesTransparency(Entry.k3D.value | Entry.k3DTop.value, params.facesTransparancy);
985
822
  }
986
823
 
987
- return this;
988
- }
824
+ if (isExist(params.edgesColor)) {
825
+ const color = new OdTvRGBColorDef(params.edgesColor.r, params.edgesColor.g, params.edgesColor.b);
826
+ highlightStylePtr.setEdgesColor(
827
+ Entry.k3DTop.value | Entry.k3D.value | Entry.k2D.value | Entry.k2DTop.value,
828
+ color
829
+ );
830
+ color.delete();
831
+ }
989
832
 
990
- /**
991
- * Deprecated since `26.4`. Use {@link open | open()} instead.
992
- *
993
- * @deprecated
994
- */
995
- openVsfFile(buffer: Uint8Array | ArrayBuffer): this {
996
- console.warn(
997
- "Viewer.openVsfFile() has been deprecated since 26.4 and will be removed in a future release, use Viewer.open() instead."
998
- );
833
+ if (isExist(params.edgesVisibility)) {
834
+ highlightStylePtr.setEdgesVisibility(
835
+ Entry.k2D.value | Entry.k2DTop.value | Entry.k3DTop.value | Entry.k3D.value,
836
+ params.edgesVisibility
837
+ );
838
+ }
839
+ if (isExist(params.edgesOverlap)) {
840
+ const visibility = !isExist(params.edgesVisibility) ? true : params.edgesVisibility;
841
+ highlightStylePtr.setEdgesVisibility(Entry.k2DTop.value | Entry.k3DTop.value, params.edgesOverlap && visibility);
842
+ }
999
843
 
1000
- if (!this.visualizeJs) return this;
844
+ // const canvas = visLib.canvas;
845
+ // device.invalidate([0, canvas.width, canvas.height, 0]);
1001
846
 
1002
- this.cancel();
1003
- this.clear();
847
+ view.delete();
848
+ device.delete();
849
+
850
+ this.update();
851
+
852
+ return this;
853
+ }
1004
854
 
1005
- this.emitEvent({ type: "open", file: "", buffer });
855
+ syncOverlay(): void {
856
+ if (!this.visualizeJs) return;
1006
857
 
1007
858
  const visViewer = this.visViewer();
859
+ const activeView = visViewer.activeView;
1008
860
 
1009
- this.emitEvent({ type: "geometrystart", file: "", buffer });
1010
- try {
1011
- const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
1012
- visViewer.parseFile(data);
861
+ let overlayView = visViewer.getViewByName(OVERLAY_VIEW_NAME);
862
+ if (!overlayView) {
863
+ const markupModel = visViewer.getMarkupModel();
864
+ const pDevice = visViewer.getActiveDevice();
1013
865
 
1014
- this.syncOptions();
1015
- this.syncOverlay();
1016
- this.update(true);
866
+ overlayView = pDevice.createView(OVERLAY_VIEW_NAME, false);
867
+ overlayView.addModel(markupModel);
1017
868
 
1018
- this.emitEvent({ type: "geometryprogress", data: 1, file: "", buffer });
1019
- this.emitEvent({ type: "databasechunk", data, file: "", buffer });
1020
- } catch (error: any) {
1021
- this.emitEvent({ type: "geometryerror", data: error, file: "", buffer });
1022
- throw error;
869
+ activeView.addSibling(overlayView);
870
+ pDevice.addView(overlayView);
1023
871
  }
1024
- this.emitEvent({ type: "geometryend", file: "", buffer });
1025
872
 
1026
- return this;
1027
- }
873
+ overlayView.viewPosition = activeView.viewPosition;
874
+ overlayView.viewTarget = activeView.viewTarget;
875
+ overlayView.upVector = activeView.upVector;
876
+ overlayView.viewFieldWidth = activeView.viewFieldWidth;
877
+ overlayView.viewFieldHeight = activeView.viewFieldHeight;
1028
878
 
1029
- /**
1030
- * Deprecated since `26.4`. Use {@link open | open()} instead.
1031
- *
1032
- * @deprecated
1033
- */
1034
- openVsfxFile(buffer: Uint8Array | ArrayBuffer): this {
1035
- console.warn(
1036
- "Viewer.openVsfxFile() has been deprecated since 26.4 and will be removed in a future release, use Viewer.open() instead."
1037
- );
879
+ const viewPort = overlayView.getViewport();
880
+ overlayView.setViewport(viewPort.lowerLeft, viewPort.upperRight);
881
+ overlayView.vportRect = activeView.vportRect;
1038
882
 
1039
- if (!this.visualizeJs) return this;
883
+ this._markup.syncOverlay();
884
+ this.update();
885
+ }
1040
886
 
1041
- this.cancel();
1042
- this.clear();
887
+ clearOverlay(): void {
888
+ if (!this.visualizeJs) return;
889
+
890
+ this._markup.clearOverlay();
891
+ this.update();
892
+ }
1043
893
 
1044
- this.emitEvent({ type: "open", file: "", buffer });
894
+ clearSlices(): void {
895
+ if (!this.visualizeJs) return;
1045
896
 
1046
897
  const visViewer = this.visViewer();
898
+ const activeView = visViewer.activeView;
899
+ activeView.removeCuttingPlanes();
900
+ activeView.delete();
1047
901
 
1048
- this.emitEvent({ type: "geometrystart", file: "", buffer });
1049
- try {
1050
- const data = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
1051
- visViewer.parseVsfx(data);
902
+ this.update();
903
+ }
1052
904
 
1053
- this.syncOptions();
1054
- this.syncOverlay();
1055
- this.update(true);
905
+ getSelected(): string[] {
906
+ return this.executeCommand("getSelected");
907
+ }
1056
908
 
1057
- this.emitEvent({ type: "geometryprogress", data: 1, file: "", buffer });
1058
- this.emitEvent({ type: "databasechunk", data, file: "", buffer });
1059
- } catch (error: any) {
1060
- this.emitEvent({ type: "geometryerror", data: error, file: "", buffer });
1061
- throw error;
1062
- }
1063
- this.emitEvent({ type: "geometryend", file: "", buffer });
909
+ setSelected(handles?: string[]): void {
910
+ this.executeCommand("setSelected", handles);
911
+ }
1064
912
 
1065
- return this;
913
+ getSelected2(): string[] {
914
+ return this.executeCommand("getSelected2");
1066
915
  }
1067
916
 
1068
- cancel(): this {
1069
- this._abortControllerForReferences?.abort();
1070
- this._abortControllerForReferences = undefined;
917
+ setSelected2(handles?: string[]): void {
918
+ this.executeCommand("setSelected2", handles);
919
+ }
1071
920
 
1072
- this.loaders.forEach((loader) => loader.cancel());
921
+ clearSelected(): void {
922
+ this.executeCommand("clearSelected");
923
+ }
1073
924
 
1074
- this.emitEvent({ type: "cancel" });
1075
- return this;
925
+ hideSelected(): void {
926
+ this.executeCommand("hideSelected");
1076
927
  }
1077
928
 
1078
- clear(): this {
1079
- if (!this.visualizeJs) return this;
929
+ isolateSelected(): void {
930
+ this.executeCommand("isolateSelected");
931
+ }
1080
932
 
1081
- const visViewer = this.visViewer();
933
+ showAll(): void {
934
+ this.executeCommand("showAll");
935
+ }
1082
936
 
1083
- this.setActiveDragger();
1084
- this.clearSlices();
1085
- this.clearOverlay();
1086
- this.clearSelected();
937
+ explode(index = 0): void {
938
+ this.executeCommand("explode", index);
939
+ }
1087
940
 
1088
- this.loaders.forEach((loader) => loader.dispose());
1089
- this.loaders = [];
941
+ collect(): void {
942
+ this.executeCommand("collect");
943
+ }
1090
944
 
1091
- visViewer.clear();
1092
- visViewer.createLocalDatabase();
945
+ /**
946
+ * Deprecated since `25.12`. Use {@link draggers.registerDragger} instead.
947
+ */
948
+ public registerDragger(name: string, dragger: typeof Dragger): void {
949
+ console.warn(
950
+ "Viewer.registerDragger() has been deprecated since 25.12 and will be removed in a future release, use draggers('visualizejs').registerDragger() instead."
951
+ );
952
+ draggers.registerDragger(name, (viewer: IViewer) => new dragger(viewer));
953
+ }
1093
954
 
1094
- this.syncOptions();
1095
- this.syncOverlay();
1096
- this.update(true);
955
+ activeDragger(): IDragger | null {
956
+ return this._activeDragger;
957
+ }
1097
958
 
1098
- this.emitEvent({ type: "clear" });
959
+ setActiveDragger(name = ""): IDragger | null {
960
+ if (!this._activeDragger || this._activeDragger.name !== name) {
961
+ const oldDragger = this._activeDragger;
962
+ let newDragger = null;
1099
963
 
1100
- return this;
1101
- }
964
+ if (this._activeDragger) {
965
+ this._activeDragger.dispose();
966
+ this._activeDragger = null;
967
+ }
968
+ if (this.visualizeJs) {
969
+ newDragger = draggers.createDragger(name, this);
970
+ if (newDragger) {
971
+ this._activeDragger = newDragger;
972
+ this._activeDragger.initialize?.();
973
+ }
974
+ }
975
+ const canvas = this.canvas;
976
+ if (canvas) {
977
+ if (oldDragger) canvas.classList.remove(`oda-cursor-${oldDragger.name.toLowerCase()}`);
978
+ if (newDragger) canvas.classList.add(`oda-cursor-${newDragger.name.toLowerCase()}`);
979
+ }
1102
980
 
1103
- /**
1104
- * Deprecated since `25.11`. Use {@link IMarkup.getMarkupColor | markup.getMarkupColor()} instead.
1105
- */
1106
- getMarkupColor(): { r: number; g: number; b: number } {
1107
- console.warn(
1108
- "Viewer.getMarkupColor() has been deprecated since 25.11 and will be removed in a future release, use Viewer.markup.getMarkupColor() instead."
1109
- );
1110
- return this._markup.getMarkupColor();
981
+ this.emitEvent({ type: "changeactivedragger", data: name });
982
+ this.update();
983
+ }
984
+ return this._activeDragger;
1111
985
  }
1112
986
 
1113
- /**
1114
- * Deprecated since `25.11`. Use {@link IMarkup.setMarkupColor | markup.setMarkupColor()} instead.
1115
- */
1116
- setMarkupColor(r = 255, g = 0, b = 0): void {
1117
- console.warn(
1118
- "Viewer.setMarkupColor() has been deprecated since 25.11 and will be removed in a future release, use Viewer.markup.setMarkupColor() instead."
1119
- );
1120
- this._markup.setMarkupColor(r, g, b);
987
+ resetActiveDragger(): void {
988
+ const dragger = this._activeDragger;
989
+ if (dragger) {
990
+ this.setActiveDragger();
991
+ this.setActiveDragger(dragger.name);
992
+ }
1121
993
  }
1122
994
 
1123
- /**
1124
- * Deprecated since `25.11`. Use {@link IMarkup.colorizeAllMarkup | markup.colorizeAllMarkup()} instead.
1125
- */
1126
- colorizeAllMarkup(r = 255, g = 0, b = 0): void {
1127
- console.warn(
1128
- "Viewer.colorizeAllMarkup() has been deprecated since 25.11 and will be removed in a future release, use Viewer.markup.colorizeAllMarkup() instead."
1129
- );
1130
- this._markup.colorizeAllMarkup(r, g, b);
995
+ getComponent(name: string): IComponent {
996
+ return this._components.find((component) => component.name === name);
1131
997
  }
1132
998
 
1133
- /**
1134
- * Deprecated since `25.11`. Use
1135
- * {@link IMarkup.colorizeSelectedMarkups | markup.colorizeSelectedMarkups()} instead.
1136
- */
1137
- colorizeSelectedMarkups(r = 255, g = 0, b = 0): void {
1138
- this._markup.colorizeSelectedMarkups(r, g, b);
1139
- }
999
+ drawViewpoint(viewpoint: IViewpoint): void {
1000
+ if (!this.visualizeJs) return;
1140
1001
 
1141
- /**
1142
- * Adds an empty `Visualize` markup entity to the overlay.
1143
- */
1144
- addMarkupEntity(entityName: string) {
1145
- if (!this.visualizeJs) return null;
1002
+ const visViewer = this.visViewer();
1003
+ const activeView = visViewer.activeView;
1146
1004
 
1147
- this.syncOverlay();
1005
+ const getPoint3dAsArray = (point3d: IPoint): number[] => {
1006
+ return [point3d.x, point3d.y, point3d.z];
1007
+ };
1148
1008
 
1149
- const visViewer = this.visViewer();
1150
- const model = visViewer.getMarkupModel();
1151
- const entityId = model.appendEntity(entityName);
1152
- const entityPtr = entityId.openObject();
1009
+ const setOrthogonalCamera = (orthogonal_camera: IOrthogonalCamera) => {
1010
+ if (orthogonal_camera) {
1011
+ activeView.setView(
1012
+ getPoint3dAsArray(orthogonal_camera.view_point),
1013
+ getPoint3dAsArray(orthogonal_camera.direction),
1014
+ getPoint3dAsArray(orthogonal_camera.up_vector),
1015
+ orthogonal_camera.field_width,
1016
+ orthogonal_camera.field_height,
1017
+ true
1018
+ );
1153
1019
 
1154
- const color = this.getMarkupColor();
1155
- entityPtr.setColor(color.r, color.g, color.b);
1156
- entityPtr.setLineWeight(2);
1157
- entityPtr.delete();
1020
+ this.syncOverlay();
1021
+ this.emitEvent({ type: "changecameramode", mode: "orthographic" });
1022
+ }
1023
+ };
1158
1024
 
1159
- this.update();
1025
+ const setPerspectiveCamera = (perspective_camera: IPerspectiveCamera) => {};
1160
1026
 
1161
- return entityId;
1162
- }
1027
+ const setClippingPlanes = (clipping_planes: IClippingPlane[]) => {
1028
+ if (clipping_planes) {
1029
+ for (const clipping_plane of clipping_planes) {
1030
+ const cuttingPlane = new (this.visLib().OdTvPlane)();
1031
+ cuttingPlane.set(getPoint3dAsArray(clipping_plane.location), getPoint3dAsArray(clipping_plane.direction));
1163
1032
 
1164
- drawViewpoint(viewpoint: IViewpoint): void {
1165
- if (!this.visualizeJs) return;
1033
+ activeView.addCuttingPlane(cuttingPlane);
1034
+ activeView.setEnableCuttingPlaneFill(true, 0x66, 0x66, 0x66);
1035
+ }
1036
+ }
1037
+ };
1038
+
1039
+ const setSelection = (selection: IEntity[]) => {
1040
+ if (selection) this.setSelected(selection.map((component) => component.handle));
1041
+ };
1166
1042
 
1167
1043
  const draggerName = this._activeDragger?.name;
1168
1044
 
@@ -1174,9 +1050,10 @@ export class Viewer
1174
1050
  this.showAll();
1175
1051
  this.explode();
1176
1052
 
1177
- this.setOrthogonalCameraSettings(viewpoint.orthogonal_camera);
1178
- this.setClippingPlanes(viewpoint.clipping_planes);
1179
- this.setSelection(viewpoint.selection);
1053
+ setOrthogonalCamera(viewpoint.orthogonal_camera);
1054
+ setPerspectiveCamera(viewpoint.perspective_camera);
1055
+ setClippingPlanes(viewpoint.clipping_planes);
1056
+ setSelection(viewpoint.custom_fields?.selection2 || viewpoint.selection);
1180
1057
  this._markup.setViewpoint(viewpoint);
1181
1058
 
1182
1059
  this.setActiveDragger(draggerName);
@@ -1187,103 +1064,119 @@ export class Viewer
1187
1064
  createViewpoint(): IViewpoint {
1188
1065
  if (!this.visualizeJs) return {};
1189
1066
 
1190
- const viewpoint: IViewpoint = {};
1067
+ const visViewer = this.visViewer();
1068
+ const activeView = visViewer.activeView;
1069
+
1070
+ const getPoint3dFromArray = (array: number[]): IPoint => {
1071
+ return { x: array[0], y: array[1], z: array[2] };
1072
+ };
1073
+
1074
+ const getOrthogonalCamera = (): IOrthogonalCamera => {
1075
+ return {
1076
+ view_point: getPoint3dFromArray(activeView.viewPosition),
1077
+ direction: getPoint3dFromArray(activeView.viewTarget),
1078
+ up_vector: getPoint3dFromArray(activeView.upVector),
1079
+ field_width: activeView.viewFieldWidth,
1080
+ field_height: activeView.viewFieldHeight,
1081
+ view_to_world_scale: 1,
1082
+ };
1083
+ };
1084
+
1085
+ const getPerspectiveCamera = (): IPerspectiveCamera => {
1086
+ return undefined;
1087
+ };
1088
+
1089
+ const getClippingPlanes = (): IClippingPlane[] => {
1090
+ const clipping_planes = [];
1091
+ for (let i = 0; i < activeView.numCuttingPlanes(); i++) {
1092
+ const cuttingPlane = activeView.getCuttingPlane(i);
1093
+
1094
+ const clipping_plane = {
1095
+ location: getPoint3dFromArray(cuttingPlane.getOrigin()),
1096
+ direction: getPoint3dFromArray(cuttingPlane.normal()),
1097
+ };
1098
+
1099
+ clipping_planes.push(clipping_plane);
1100
+ }
1101
+
1102
+ return clipping_planes;
1103
+ };
1104
+
1105
+ const getSelection = (): IEntity[] => {
1106
+ return this.getSelected().map((handle) => ({ handle }));
1107
+ };
1108
+
1109
+ const getSelection2 = (): IEntity[] => {
1110
+ return this.getSelected2().map((handle) => ({ handle }));
1111
+ };
1112
+
1113
+ const viewpoint: IViewpoint = { custom_fields: {} };
1191
1114
 
1192
- viewpoint.orthogonal_camera = this.getOrthogonalCameraSettings();
1193
- viewpoint.clipping_planes = this.getClippingPlanes();
1194
- viewpoint.selection = this.getSelection();
1115
+ viewpoint.orthogonal_camera = getOrthogonalCamera();
1116
+ viewpoint.perspective_camera = getPerspectiveCamera();
1117
+ viewpoint.clipping_planes = getClippingPlanes();
1118
+ viewpoint.selection = getSelection();
1195
1119
  viewpoint.description = new Date().toDateString();
1196
1120
  this._markup.getViewpoint(viewpoint);
1197
1121
 
1122
+ viewpoint.custom_fields.selection2 = getSelection2();
1123
+
1198
1124
  this.emitEvent({ type: "createviewpoint", data: viewpoint });
1199
1125
 
1200
1126
  return viewpoint;
1201
1127
  }
1202
1128
 
1203
- private getPoint3dFromArray(array: number[]) {
1204
- return { x: array[0], y: array[1], z: array[2] };
1205
- }
1129
+ // IWorldTransform
1206
1130
 
1207
- private getLogicalPoint3dAsArray(point3d: IPoint) {
1208
- return [point3d.x, point3d.y, point3d.z];
1209
- }
1131
+ screenToWorld(position: { x: number; y: number }): { x: number; y: number; z: number } {
1132
+ if (!this.visualizeJs) return { x: position.x, y: position.y, z: 0 };
1210
1133
 
1211
- private getOrthogonalCameraSettings(): IOrthogonalCamera {
1212
- const visViewer = this.visViewer();
1213
- const activeView = visViewer.activeView;
1134
+ const activeView = this.visViewer().activeView;
1135
+ const worldPoint = activeView.transformScreenToWorld(
1136
+ position.x * window.devicePixelRatio,
1137
+ position.y * window.devicePixelRatio
1138
+ );
1214
1139
 
1215
- return {
1216
- view_point: this.getPoint3dFromArray(activeView.viewPosition),
1217
- direction: this.getPoint3dFromArray(activeView.viewTarget),
1218
- up_vector: this.getPoint3dFromArray(activeView.upVector),
1219
- field_width: activeView.viewFieldWidth,
1220
- field_height: activeView.viewFieldHeight,
1221
- view_to_world_scale: 1,
1222
- };
1223
- }
1140
+ const result = { x: worldPoint[0], y: worldPoint[1], z: worldPoint[2] };
1224
1141
 
1225
- private setOrthogonalCameraSettings(settings: IOrthogonalCamera) {
1226
- const visViewer = this.visViewer();
1227
- const activeView = visViewer.activeView;
1142
+ activeView.delete();
1228
1143
 
1229
- if (settings) {
1230
- activeView.setView(
1231
- this.getLogicalPoint3dAsArray(settings.view_point),
1232
- this.getLogicalPoint3dAsArray(settings.direction),
1233
- this.getLogicalPoint3dAsArray(settings.up_vector),
1234
- settings.field_width,
1235
- settings.field_height,
1236
- true
1237
- );
1238
- this.syncOverlay();
1239
- }
1144
+ return result;
1240
1145
  }
1241
1146
 
1242
- private getClippingPlanes(): IClippingPlane[] {
1243
- const visViewer = this.visViewer();
1244
- const activeView = visViewer.activeView;
1147
+ worldToScreen(position: { x: number; y: number; z: number }): { x: number; y: number } {
1148
+ if (!this.visualizeJs) return { x: position.x, y: position.y };
1245
1149
 
1246
- const clipping_planes = [];
1247
- for (let i = 0; i < activeView.numCuttingPlanes(); i++) {
1248
- const cuttingPlane = activeView.getCuttingPlane(i);
1150
+ const activeView = this.visViewer().activeView;
1151
+ const devicePoint = activeView.transformWorldToScreen(position.x, position.y, position.z);
1249
1152
 
1250
- const clipping_plane = {
1251
- location: this.getPoint3dFromArray(cuttingPlane.getOrigin()),
1252
- direction: this.getPoint3dFromArray(cuttingPlane.normal()),
1253
- };
1153
+ const result = { x: devicePoint[0] / window.devicePixelRatio, y: devicePoint[1] / window.devicePixelRatio };
1254
1154
 
1255
- clipping_planes.push(clipping_plane);
1256
- }
1155
+ activeView.delete();
1257
1156
 
1258
- return clipping_planes;
1157
+ return result;
1259
1158
  }
1260
1159
 
1261
- private setClippingPlanes(clipping_planes: IClippingPlane[]) {
1262
- if (clipping_planes) {
1263
- const visViewer = this.visViewer();
1264
- const activeView = visViewer.activeView;
1160
+ getScale(): { x: number; y: number; z: number } {
1161
+ const result = { x: 1.0, y: 1.0, z: 1.0 };
1265
1162
 
1266
- for (const clipping_plane of clipping_planes) {
1267
- const cuttingPlane = new (this.visLib().OdTvPlane)();
1268
- cuttingPlane.set(
1269
- this.getLogicalPoint3dAsArray(clipping_plane.location),
1270
- this.getLogicalPoint3dAsArray(clipping_plane.direction)
1271
- );
1163
+ const projMatrix = this.visViewer().activeView.projectionMatrix;
1164
+ const tolerance = 1.0e-6;
1272
1165
 
1273
- activeView.addCuttingPlane(cuttingPlane);
1274
- activeView.setEnableCuttingPlaneFill(true, 0x66, 0x66, 0x66);
1275
- }
1276
- }
1277
- }
1166
+ const x = projMatrix.get(0, 0);
1167
+ if (x > tolerance || x < -tolerance) result.x = 1 / x;
1278
1168
 
1279
- private getSelection(): IEntity[] {
1280
- return this.getSelected().map((handle) => ({ handle }));
1281
- }
1169
+ const y = projMatrix.get(1, 1);
1170
+ if (y > tolerance || y < -tolerance) result.y = 1 / y;
1171
+
1172
+ const z = projMatrix.get(2, 2);
1173
+ if (z > tolerance || z < -tolerance) result.z = 1 / z;
1282
1174
 
1283
- private setSelection(selection: IEntity[]) {
1284
- this.setSelected(selection?.map((component) => component.handle));
1175
+ return result;
1285
1176
  }
1286
1177
 
1178
+ // ICommandService
1179
+
1287
1180
  /**
1288
1181
  * Executes the command denoted by the given command. If the command is not found, tries to set active
1289
1182
  * dragger with the specified name.
@@ -1325,6 +1218,118 @@ export class Viewer
1325
1218
  return commands.executeCommand(id, this, ...args);
1326
1219
  }
1327
1220
 
1221
+ // VisualizeJS viewer specific
1222
+
1223
+ /**
1224
+ * Adds an empty `Visualize` markup entity to the VisualizeJS overlay.
1225
+ */
1226
+ addMarkupEntity(entityName: string) {
1227
+ if (!this.visualizeJs) return null;
1228
+
1229
+ this.syncOverlay();
1230
+
1231
+ const visViewer = this.visViewer();
1232
+ const model = visViewer.getMarkupModel();
1233
+ const entityId = model.appendEntity(entityName);
1234
+ const entityPtr = entityId.openObject();
1235
+
1236
+ const color = this.getMarkupColor();
1237
+ entityPtr.setColor(color.r, color.g, color.b);
1238
+ entityPtr.setLineWeight(2);
1239
+ entityPtr.delete();
1240
+
1241
+ this.update();
1242
+
1243
+ return entityId;
1244
+ }
1245
+
1246
+ /**
1247
+ * Deprecated since `25.11`. Use {@link IMarkup.getMarkupColor | markup.getMarkupColor()} instead.
1248
+ */
1249
+ getMarkupColor(): { r: number; g: number; b: number } {
1250
+ console.warn(
1251
+ "Viewer.getMarkupColor() has been deprecated since 25.11 and will be removed in a future release, use Viewer.markup.getMarkupColor() instead."
1252
+ );
1253
+ return this._markup.getMarkupColor();
1254
+ }
1255
+
1256
+ /**
1257
+ * Deprecated since `25.11`. Use {@link IMarkup.setMarkupColor | markup.setMarkupColor()} instead.
1258
+ */
1259
+ setMarkupColor(r = 255, g = 0, b = 0): void {
1260
+ console.warn(
1261
+ "Viewer.setMarkupColor() has been deprecated since 25.11 and will be removed in a future release, use Viewer.markup.setMarkupColor() instead."
1262
+ );
1263
+ this._markup.setMarkupColor(r, g, b);
1264
+ }
1265
+
1266
+ /**
1267
+ * Deprecated since `25.11`. Use {@link IMarkup.colorizeAllMarkup | markup.colorizeAllMarkup()} instead.
1268
+ */
1269
+ colorizeAllMarkup(r = 255, g = 0, b = 0): void {
1270
+ console.warn(
1271
+ "Viewer.colorizeAllMarkup() has been deprecated since 25.11 and will be removed in a future release, use Viewer.markup.colorizeAllMarkup() instead."
1272
+ );
1273
+ this._markup.colorizeAllMarkup(r, g, b);
1274
+ }
1275
+
1276
+ /**
1277
+ * Deprecated since `25.11`. Use
1278
+ * {@link IMarkup.colorizeSelectedMarkups | markup.colorizeSelectedMarkups()} instead.
1279
+ */
1280
+ colorizeSelectedMarkups(r = 255, g = 0, b = 0): void {
1281
+ this._markup.colorizeSelectedMarkups(r, g, b);
1282
+ }
1283
+
1284
+ private scheduleUpdateAsync(maxScheduleUpdateTimeInMs = 50): Promise<void> {
1285
+ return new Promise<void>((resolve, reject) => {
1286
+ setTimeout(() => {
1287
+ try {
1288
+ if (this._enableAutoUpdate) {
1289
+ this.visViewer()?.update(maxScheduleUpdateTimeInMs);
1290
+ this._activeDragger?.updatePreview?.();
1291
+ }
1292
+ this.emitEvent({ type: "update", data: false });
1293
+ resolve();
1294
+ } catch (e) {
1295
+ console.error(e);
1296
+ reject();
1297
+ }
1298
+ }, 0);
1299
+ });
1300
+ }
1301
+
1302
+ /**
1303
+ * Updates the viewer asynchronously without locking the user interface. Used to update the viewer
1304
+ * after changes that require a long rendering time.
1305
+ *
1306
+ * Do nothing if the auto-update mode is disabled in the constructor. In this case, register an
1307
+ * `update` event handler and update the `VisualizeJS` viewer and active dragger manually.
1308
+ *
1309
+ * Fires:
1310
+ *
1311
+ * - {@link UpdateEvent | update}
1312
+ *
1313
+ * @param maxScheduleUpdateTimeInMs - Maximum time for one update, default 30 ms.
1314
+ * @param maxScheduleUpdateCount - Maximum count of scheduled updates.
1315
+ */
1316
+ async updateAsync(maxScheduleUpdateTimeInMs = 50, maxScheduleUpdateCount = 50): Promise<void> {
1317
+ if (!this.visualizeJs) return;
1318
+
1319
+ this._isRunAsyncUpdate = true;
1320
+ try {
1321
+ const device = this.visViewer().getActiveDevice();
1322
+ for (let iterationCount = 0; !device.isValid() && iterationCount < maxScheduleUpdateCount; iterationCount++) {
1323
+ await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
1324
+ }
1325
+ await this.scheduleUpdateAsync(maxScheduleUpdateTimeInMs);
1326
+ } catch (e) {
1327
+ console.error(e);
1328
+ } finally {
1329
+ this._isRunAsyncUpdate = false;
1330
+ }
1331
+ }
1332
+
1328
1333
  public deviceAutoRegeneration() {
1329
1334
  const visViewer = this.visViewer();
1330
1335
  const device = visViewer.getActiveDevice();