vim-web 0.3.42 → 0.3.43

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 (26) hide show
  1. package/dist/types/core-viewers/ultra/index.d.ts +1 -1
  2. package/dist/types/core-viewers/ultra/viewer/socketClient.d.ts +10 -3
  3. package/dist/types/core-viewers/ultra/viewer/viewer.d.ts +2 -3
  4. package/dist/types/core-viewers/webgl/loader/materials/ghostMaterial.d.ts +16 -0
  5. package/dist/types/core-viewers/webgl/loader/materials/simpleMaterial.d.ts +10 -5
  6. package/dist/types/core-viewers/webgl/loader/materials/viewerMaterials.d.ts +9 -8
  7. package/dist/types/core-viewers/webgl/loader/mesh.d.ts +2 -1
  8. package/dist/types/core-viewers/webgl/loader/progressive/insertableMesh.d.ts +2 -1
  9. package/dist/types/core-viewers/webgl/loader/progressive/instancedMesh.d.ts +3 -1
  10. package/dist/types/core-viewers/webgl/loader/scene.d.ts +3 -2
  11. package/dist/types/core-viewers/webgl/viewer/environment/environment.d.ts +0 -6
  12. package/dist/types/core-viewers/webgl/viewer/rendering/renderScene.d.ts +8 -4
  13. package/dist/types/core-viewers/webgl/viewer/rendering/renderer.d.ts +5 -9
  14. package/dist/types/core-viewers/webgl/viewer/selection.d.ts +1 -0
  15. package/dist/types/core-viewers/webgl/viewer/settings/viewerSettings.d.ts +4 -39
  16. package/dist/types/react-viewers/helpers/inputs.d.ts +1 -2
  17. package/dist/types/react-viewers/helpers/isolation.d.ts +91 -50
  18. package/dist/types/react-viewers/settings/settings.d.ts +3 -2
  19. package/dist/vim-web.iife.js +355 -556
  20. package/dist/vim-web.iife.js.map +1 -1
  21. package/dist/vim-web.js +361 -562
  22. package/dist/vim-web.js.map +1 -1
  23. package/package.json +1 -1
  24. package/dist/types/core-viewers/webgl/images.d.ts +0 -4
  25. package/dist/types/core-viewers/webgl/loader/materials/isolationMaterial.d.ts +0 -12
  26. package/dist/types/core-viewers/webgl/viewer/environment/groundPlane.d.ts +0 -25
@@ -45349,6 +45349,7 @@ void main() {
45349
45349
  return this._value;
45350
45350
  }
45351
45351
  apply(value) {
45352
+ value ?? this.defaultValue;
45352
45353
  if (this._value === value) return false;
45353
45354
  this._value = value;
45354
45355
  if (!this._meshes) return false;
@@ -45716,9 +45717,15 @@ void main() {
45716
45717
  return this._visibleAttribute.value;
45717
45718
  }
45718
45719
  set visible(value) {
45720
+ var _a2;
45719
45721
  if (this._visibleAttribute.apply(value)) {
45720
45722
  this.vim.scene.setDirty();
45721
45723
  }
45724
+ if (value) {
45725
+ (_a2 = this._meshes) == null ? void 0 : _a2.forEach((m) => {
45726
+ m.mesh.mesh.visible = true;
45727
+ });
45728
+ }
45722
45729
  }
45723
45730
  /**
45724
45731
  * Gets or sets the display color of this object.
@@ -47662,7 +47669,6 @@ void main() {
47662
47669
  vertexColors: true,
47663
47670
  flatShading: true,
47664
47671
  side: DoubleSide
47665
- //shininess: 20
47666
47672
  });
47667
47673
  }
47668
47674
  function createBasicTransparent() {
@@ -47928,107 +47934,69 @@ void main() {
47928
47934
  `
47929
47935
  });
47930
47936
  }
47931
- function createIsolationMaterial() {
47937
+ function createGhostMaterial() {
47932
47938
  return new ShaderMaterial({
47939
+ userData: {
47940
+ isGhost: true
47941
+ },
47933
47942
  uniforms: {
47934
- opacity: { value: 0.1 },
47943
+ // Uniform controlling the overall transparency of the non-visible objects.
47944
+ opacity: { value: 1e-3 },
47945
+ // Uniform specifying the fill color for non-visible objects.
47935
47946
  fillColor: { value: new Vector3$1(0, 0, 0) }
47936
47947
  },
47948
+ // Render only the front side of faces to prevent drawing internal geometry.
47949
+ side: FrontSide,
47950
+ // Enable support for vertex colors.
47937
47951
  vertexColors: true,
47952
+ // Enable transparency for the material.
47938
47953
  transparent: true,
47954
+ // Enable clipping planes for geometry slicing.
47939
47955
  clipping: true,
47956
+ // Prevent writing to the depth buffer for proper blending of transparent objects.
47957
+ depthWrite: false,
47958
+ // Perform depth testing to ensure correct rendering order.
47959
+ depthTest: true,
47940
47960
  vertexShader: (
47941
47961
  /* glsl */
47942
47962
  `
47943
-
47944
- #include <common>
47945
- #include <logdepthbuf_pars_vertex>
47946
47963
  #include <clipping_planes_pars_vertex>
47947
-
47948
- // VISIBILITY
47949
- // Instance or vertex attribute to hide objects
47950
- // Used as instance attribute for instanced mesh and as vertex attribute for merged meshes.
47951
- attribute float ignore;
47952
-
47953
- // Passed to fragment to discard them
47954
- varying float vIgnore;
47955
- varying vec3 vPosition;
47956
-
47957
-
47958
- // COLORING
47959
- varying vec3 vColor;
47960
-
47961
- // attribute for color override
47962
- // merged meshes use it as vertex attribute
47963
- // instanced meshes use it as an instance attribute
47964
- attribute float colored;
47965
47964
 
47966
- // There seems to be an issue where setting mehs.instanceColor
47967
- // doesn't properly set USE_INSTANCING_COLOR
47968
- // so we always use it as a fix
47969
- #ifndef USE_INSTANCING_COLOR
47970
- attribute vec3 instanceColor;
47971
- #endif
47965
+ // Attribute to determine if an object or vertex should be visible.
47966
+ // Used as an instance attribute for instanced meshes or a vertex attribute for merged meshes.
47967
+ attribute float ignore;
47972
47968
 
47973
47969
  void main() {
47970
+ // Standard transformations to calculate vertex position.
47974
47971
  #include <begin_vertex>
47975
47972
  #include <project_vertex>
47976
47973
  #include <clipping_planes_vertex>
47977
- #include <logdepthbuf_vertex>
47978
-
47979
- // VISIBILITY
47980
- // Set frag ignore from instance or vertex attribute
47981
- vIgnore = ignore;
47982
-
47983
- // COLORING
47984
- vColor = color.xyz;
47985
-
47986
- // colored == 1 -> instance color
47987
- // colored == 0 -> vertex color
47988
- #ifdef USE_INSTANCING
47989
- vColor.xyz = colored * instanceColor.xyz + (1.0f - colored) * color.xyz;
47990
- #endif
47991
-
47992
47974
 
47993
- // ORDERING
47994
- if(vIgnore > 0.0f){
47995
- gl_Position.z = 1.0f;
47996
- }else{
47997
- gl_Position.z = -1.0f;
47975
+ // Hide objects or vertices where the 'ignore' attribute is set to 0.
47976
+ if (ignore == 0.0) {
47977
+ // Push the vertex far out of view, effectively hiding it.
47978
+ gl_Position = vec4(1e20, 1e20, 1e20, 1.0);
47998
47979
  }
47999
-
48000
- // LIGHTING
48001
- vPosition = vec3(mvPosition ) / mvPosition .w;
48002
47980
  }
48003
- `
47981
+ `
48004
47982
  ),
48005
47983
  fragmentShader: (
48006
47984
  /* glsl */
48007
47985
  `
48008
47986
  #include <clipping_planes_pars_fragment>
48009
- varying float vIgnore;
47987
+
47988
+ // Uniform controlling the transparency level of the material.
48010
47989
  uniform float opacity;
47990
+ // Uniform specifying the fill color for non-visible objects.
48011
47991
  uniform vec3 fillColor;
48012
- varying vec3 vPosition;
48013
- varying vec3 vColor;
48014
47992
 
48015
47993
  void main() {
47994
+ // Handle clipping planes to discard fragments outside the defined planes.
48016
47995
  #include <clipping_planes_fragment>
48017
-
48018
- if (vIgnore > 0.0f){
48019
- gl_FragColor = vec4(fillColor, opacity);
48020
- }
48021
- else{
48022
- gl_FragColor = vec4(vColor.x, vColor.y, vColor.z, 1.0f);
48023
-
48024
- // LIGHTING
48025
- vec3 normal = normalize( cross(dFdx(vPosition), dFdy(vPosition)) );
48026
- float light = dot(normal, normalize(vec3(1.4142f, 1.732f, 2.2360f)));
48027
- light = 0.5 + (light *0.5);
48028
- gl_FragColor.xyz *= light;
48029
- }
47996
+ // Set the fragment color to the specified fill color and opacity.
47997
+ gl_FragColor = vec4(fillColor, opacity);
48030
47998
  }
48031
- `
47999
+ `
48032
48000
  )
48033
48001
  });
48034
48002
  }
@@ -48316,42 +48284,40 @@ void main() {
48316
48284
  }
48317
48285
  function createSimpleMaterial() {
48318
48286
  return new ShaderMaterial({
48319
- uniforms: {
48320
- opacity: { value: 0.1 },
48321
- fillColor: { value: new Vector3$1(0, 0, 0) }
48322
- },
48287
+ side: DoubleSide,
48288
+ // No uniforms are needed for this shader.
48289
+ uniforms: {},
48290
+ // Enable vertex colors for both instanced and merged meshes.
48323
48291
  vertexColors: true,
48324
- // transparent: true,
48292
+ // Enable support for clipping planes.
48325
48293
  clipping: true,
48326
48294
  vertexShader: (
48327
48295
  /* glsl */
48328
48296
  `
48329
-
48330
48297
  #include <common>
48331
48298
  #include <logdepthbuf_pars_vertex>
48332
48299
  #include <clipping_planes_pars_vertex>
48333
-
48300
+
48334
48301
  // VISIBILITY
48335
- // Instance or vertex attribute to hide objects
48336
- // Used as instance attribute for instanced mesh and as vertex attribute for merged meshes.
48302
+ // Determines if an object or vertex should be visible.
48303
+ // Used as an instance attribute for instanced meshes or as a vertex attribute for merged meshes.
48337
48304
  attribute float ignore;
48338
48305
 
48339
- // Passed to fragment to discard them
48340
- varying float vIgnore;
48306
+ // LIGHTING
48307
+ // Passes the vertex position to the fragment shader for lighting calculations.
48341
48308
  varying vec3 vPosition;
48342
48309
 
48343
-
48344
48310
  // COLORING
48311
+ // Passes the color of the vertex or instance to the fragment shader.
48345
48312
  varying vec3 vColor;
48346
48313
 
48347
- // attribute for color override
48348
- // merged meshes use it as vertex attribute
48349
- // instanced meshes use it as an instance attribute
48314
+ // Determines whether to use instance color (1.0) or vertex color (0.0).
48315
+ // For merged meshes, this is used as a vertex attribute.
48316
+ // For instanced meshes, this is used as an instance attribute.
48350
48317
  attribute float colored;
48351
48318
 
48352
- // There seems to be an issue where setting mehs.instanceColor
48353
- // doesn't properly set USE_INSTANCING_COLOR
48354
- // so we always use it as a fix
48319
+ // Fix for a known issue where setting mesh.instanceColor does not properly enable USE_INSTANCING_COLOR.
48320
+ // This ensures that instance colors are always used when required.
48355
48321
  #ifndef USE_INSTANCING_COLOR
48356
48322
  attribute vec3 instanceColor;
48357
48323
  #endif
@@ -48362,49 +48328,59 @@ void main() {
48362
48328
  #include <clipping_planes_vertex>
48363
48329
  #include <logdepthbuf_vertex>
48364
48330
 
48365
- // VISIBILITY
48366
- // Set frag ignore from instance or vertex attribute
48367
- vIgnore = ignore;
48331
+ // If ignore is greater than 0, hide the object by moving it far out of view.
48332
+ if (ignore > 0.0) {
48333
+ gl_Position = vec4(1e20, 1e20, 1e20, 1.0);
48334
+ return;
48335
+ }
48368
48336
 
48369
48337
  // COLORING
48338
+ // Default to the vertex color.
48370
48339
  vColor = color.xyz;
48371
48340
 
48372
- // colored == 1 -> instance color
48373
- // colored == 0 -> vertex color
48341
+ // Blend instance and vertex colors based on the colored attribute.
48342
+ // colored == 1.0 -> use instance color.
48343
+ // colored == 0.0 -> use vertex color.
48374
48344
  #ifdef USE_INSTANCING
48375
- vColor.xyz = colored * instanceColor.xyz + (1.0f - colored) * color.xyz;
48345
+ vColor.xyz = colored * instanceColor.xyz + (1.0 - colored) * color.xyz;
48376
48346
  #endif
48377
48347
 
48378
- gl_Position.z = -10.0f;
48379
-
48380
48348
  // LIGHTING
48381
- vPosition = vec3(mvPosition ) / mvPosition .w;
48349
+ // Pass the model-view position to the fragment shader for lighting calculations.
48350
+ vPosition = vec3(mvPosition) / mvPosition.w;
48382
48351
  }
48383
48352
  `
48384
48353
  ),
48385
48354
  fragmentShader: (
48386
48355
  /* glsl */
48387
48356
  `
48357
+ #include <common>
48358
+ #include <logdepthbuf_pars_fragment>
48388
48359
  #include <clipping_planes_pars_fragment>
48389
- varying float vIgnore;
48360
+
48361
+
48362
+ // Position and color data passed from the vertex shader.
48390
48363
  varying vec3 vPosition;
48391
48364
  varying vec3 vColor;
48392
48365
 
48393
48366
  void main() {
48394
48367
  #include <clipping_planes_fragment>
48368
+ #include <logdepthbuf_fragment>
48395
48369
 
48396
- if (vIgnore > 0.0f){
48397
- discard;
48398
- }
48399
- else{
48400
- gl_FragColor = vec4(vColor.x, vColor.y, vColor.z, 1.0f);
48370
+ // Set the fragment color to the interpolated vertex or instance color.
48371
+ gl_FragColor = vec4(vColor, 1.0);
48401
48372
 
48402
- // LIGHTING
48403
- vec3 normal = normalize( cross(dFdx(vPosition), dFdy(vPosition)) );
48404
- float light = dot(normal, normalize(vec3(1.4142f, 1.732f, 2.2360f)));
48405
- light = 0.5 + (light *0.5);
48406
- gl_FragColor.xyz *= light;
48407
- }
48373
+ // LIGHTING
48374
+ // Compute a pseudo-normal using screen-space derivatives of the vertex position.
48375
+ vec3 normal = normalize(cross(dFdx(vPosition), dFdy(vPosition)));
48376
+
48377
+ // Apply simple directional lighting.
48378
+ // Normalize the light direction for consistent shading.
48379
+ float light = dot(normal, normalize(vec3(1.4142, 1.732, 2.236)));
48380
+ light = 0.5 + (light * 0.5); // Adjust light intensity to range [0.5, 1.0].
48381
+
48382
+ // Modulate the fragment color by the lighting intensity.
48383
+ gl_FragColor.xyz *= light;
48408
48384
  }
48409
48385
  `
48410
48386
  )
@@ -48503,7 +48479,7 @@ void main() {
48503
48479
  }
48504
48480
  }
48505
48481
  const _ViewerMaterials = class _ViewerMaterials {
48506
- constructor(opaque, transparent, simple, wireframe, isolation, mask, outline, merge, skyBox) {
48482
+ constructor(opaque, transparent, simple, wireframe, ghost2, mask, outline, merge, skyBox) {
48507
48483
  /**
48508
48484
  * Material used for opaque model geometry.
48509
48485
  */
@@ -48523,7 +48499,7 @@ void main() {
48523
48499
  /**
48524
48500
  * Material used to show traces of hidden objects.
48525
48501
  */
48526
- __publicField(this, "isolation");
48502
+ __publicField(this, "ghost");
48527
48503
  /**
48528
48504
  * Material used to filter out what is not selected for selection outline effect.
48529
48505
  */
@@ -48551,7 +48527,7 @@ void main() {
48551
48527
  this.transparent = transparent ?? createTransparent();
48552
48528
  this.simple = simple ?? createSimpleMaterial();
48553
48529
  this.wireframe = wireframe ?? createWireframe();
48554
- this.isolation = isolation ?? createIsolationMaterial();
48530
+ this.ghost = ghost2 ?? createGhostMaterial();
48555
48531
  this.mask = mask ?? createMaskMaterial();
48556
48532
  this.outline = outline ?? new OutlineMaterial();
48557
48533
  this.merge = merge ?? new MergeMaterial();
@@ -48573,8 +48549,8 @@ void main() {
48573
48549
  applySettings(settings2) {
48574
48550
  this.opaque.color = settings2.materials.standard.color;
48575
48551
  this.transparent.color = settings2.materials.standard.color;
48576
- this.isolationOpacity = settings2.materials.isolation.opacity;
48577
- this.isolationColor = settings2.materials.isolation.color;
48552
+ this.ghostOpacity = settings2.materials.ghost.opacity;
48553
+ this.ghostColor = settings2.materials.ghost.color;
48578
48554
  this.wireframeColor = settings2.materials.highlight.color;
48579
48555
  this.wireframeOpacity = settings2.materials.highlight.opacity;
48580
48556
  this.sectionStrokeWitdh = settings2.materials.section.strokeWidth;
@@ -48603,26 +48579,27 @@ void main() {
48603
48579
  this._onUpdate.dispatch();
48604
48580
  }
48605
48581
  /**
48606
- * Determines the opacity of the isolation material.
48582
+ * Determines the opacity of the ghost material.
48607
48583
  */
48608
- get isolationOpacity() {
48609
- return this.isolation.opacity;
48584
+ get ghostOpacity() {
48585
+ const mat = this.ghost;
48586
+ return mat.uniforms.opacity.value;
48610
48587
  }
48611
- set isolationOpacity(opacity) {
48612
- const mat = this.isolation;
48588
+ set ghostOpacity(opacity) {
48589
+ const mat = this.ghost;
48613
48590
  mat.uniforms.opacity.value = opacity;
48614
48591
  mat.uniformsNeedUpdate = true;
48615
48592
  this._onUpdate.dispatch();
48616
48593
  }
48617
48594
  /**
48618
- * Determines the color of the isolation material.
48595
+ * Determines the color of the ghost material.
48619
48596
  */
48620
- get isolationColor() {
48621
- const mat = this.isolation;
48597
+ get ghostColor() {
48598
+ const mat = this.ghost;
48622
48599
  return mat.uniforms.fillColor.value;
48623
48600
  }
48624
- set isolationColor(color) {
48625
- const mat = this.isolation;
48601
+ set ghostColor(color) {
48602
+ const mat = this.ghost;
48626
48603
  mat.uniforms.fillColor.value = color;
48627
48604
  mat.uniformsNeedUpdate = true;
48628
48605
  this._onUpdate.dispatch();
@@ -48683,10 +48660,11 @@ void main() {
48683
48660
  }
48684
48661
  set clippingPlanes(value) {
48685
48662
  this._clippingPlanes = value;
48663
+ this.simple.clippingPlanes = value ?? null;
48686
48664
  this.opaque.clippingPlanes = value ?? null;
48687
48665
  this.transparent.clippingPlanes = value ?? null;
48688
48666
  this.wireframe.clippingPlanes = value ?? null;
48689
- this.isolation.clippingPlanes = value ?? null;
48667
+ this.ghost.clippingPlanes = value ?? null;
48690
48668
  this.mask.clippingPlanes = value ?? null;
48691
48669
  this._onUpdate.dispatch();
48692
48670
  }
@@ -48806,7 +48784,7 @@ void main() {
48806
48784
  this.opaque.dispose();
48807
48785
  this.transparent.dispose();
48808
48786
  this.wireframe.dispose();
48809
- this.isolation.dispose();
48787
+ this.ghost.dispose();
48810
48788
  this.mask.dispose();
48811
48789
  this.outline.dispose();
48812
48790
  }
@@ -48918,16 +48896,12 @@ void main() {
48918
48896
  setMaterial(value) {
48919
48897
  if (this._material === value) return;
48920
48898
  if (this.ignoreSceneMaterial) return;
48921
- if (value) {
48922
- if (!this._material) {
48923
- this._material = this.mesh.material;
48924
- }
48925
- this.mesh.material = value;
48926
- } else {
48927
- if (this._material) {
48928
- this.mesh.material = this._material;
48929
- this._material = void 0;
48930
- }
48899
+ this.mesh.material = value ?? this._material;
48900
+ this.mesh.geometry.clearGroups();
48901
+ if (value instanceof Array) {
48902
+ value.forEach((m, i2) => {
48903
+ this.mesh.geometry.addGroup(0, Infinity, i2);
48904
+ });
48931
48905
  }
48932
48906
  }
48933
48907
  }
@@ -48985,13 +48959,17 @@ void main() {
48985
48959
  // State
48986
48960
  __publicField(this, "ignoreSceneMaterial");
48987
48961
  __publicField(this, "_material");
48962
+ __publicField(this, "size", 0);
48963
+ var _a2;
48988
48964
  this.g3dMesh = g3d2;
48989
48965
  this.mesh = mesh;
48990
48966
  this.mesh.userData.vim = this;
48991
48967
  this.bimInstances = g3d2 instanceof distExports$2.G3dMesh ? instances.map((i2) => g3d2.scene.instanceNodes[i2]) : instances;
48992
48968
  this.meshInstances = instances;
48993
48969
  this.boxes = g3d2 instanceof distExports$2.G3dMesh ? this.importBoundingBoxes() : this.computeBoundingBoxes();
48970
+ this.size = ((_a2 = this.boxes[0]) == null ? void 0 : _a2.getSize(new Vector3$1()).length()) ?? 0;
48994
48971
  this.boundingBox = this.computeBoundingBox(this.boxes);
48972
+ this._material = this.mesh.material;
48995
48973
  }
48996
48974
  get merged() {
48997
48975
  return false;
@@ -49015,16 +48993,12 @@ void main() {
49015
48993
  setMaterial(value) {
49016
48994
  if (this._material === value) return;
49017
48995
  if (this.ignoreSceneMaterial) return;
49018
- if (value) {
49019
- if (!this._material) {
49020
- this._material = this.mesh.material;
49021
- }
49022
- this.mesh.material = value;
49023
- } else {
49024
- if (this._material) {
49025
- this.mesh.material = this._material;
49026
- this._material = void 0;
49027
- }
48996
+ this.mesh.material = value ?? this._material;
48997
+ this.mesh.geometry.clearGroups();
48998
+ if (value instanceof Array) {
48999
+ value.forEach((m, i2) => {
49000
+ this.mesh.geometry.addGroup(0, Infinity, i2);
49001
+ });
49028
49002
  }
49029
49003
  }
49030
49004
  computeBoundingBoxes() {
@@ -49963,7 +49937,7 @@ void main() {
49963
49937
  }
49964
49938
  return vim;
49965
49939
  }
49966
- let DeferredPromise$2 = class DeferredPromise extends Promise {
49940
+ let DeferredPromise$1 = class DeferredPromise extends Promise {
49967
49941
  constructor(executor = () => {
49968
49942
  }) {
49969
49943
  var _a2;
@@ -50026,8 +50000,8 @@ void main() {
50026
50000
  __publicField(this, "_error");
50027
50001
  // Promises to await progress updates and completion
50028
50002
  __publicField(this, "_progress", { loaded: 0, total: 0, all: /* @__PURE__ */ new Map() });
50029
- __publicField(this, "_progressPromise", new DeferredPromise$2());
50030
- __publicField(this, "_completionPromise", new DeferredPromise$2());
50003
+ __publicField(this, "_progressPromise", new DeferredPromise$1());
50004
+ __publicField(this, "_completionPromise", new DeferredPromise$1());
50031
50005
  this._source = source;
50032
50006
  this._settings = settings2;
50033
50007
  this.startRequest();
@@ -50041,7 +50015,7 @@ void main() {
50041
50015
  const vim = await open(this._bfast, this._settings, (progress) => {
50042
50016
  this._progress = progress;
50043
50017
  this._progressPromise.resolve(progress);
50044
- this._progressPromise = new DeferredPromise$2();
50018
+ this._progressPromise = new DeferredPromise$1();
50045
50019
  });
50046
50020
  this._vimResult = vim;
50047
50021
  } catch (err) {
@@ -50096,9 +50070,6 @@ void main() {
50096
50070
  }
50097
50071
  return true;
50098
50072
  }
50099
- const floor$1 = `
50100
- data:image/png;base64,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
50101
- `;
50102
50073
  class AxesSettings {
50103
50074
  constructor(init) {
50104
50075
  __publicField(this, "size", 84);
@@ -50174,14 +50145,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
50174
50145
  // less white
50175
50146
  sharpness: 2
50176
50147
  },
50177
- groundPlane: {
50178
- visible: false,
50179
- encoding: "base64",
50180
- texture: floor$1,
50181
- opacity: 1,
50182
- color: new Color(16777215),
50183
- size: 5
50184
- },
50185
50148
  skylight: {
50186
50149
  skyColor: new Color(16777215),
50187
50150
  groundColor: new Color(16777215),
@@ -50209,9 +50172,9 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
50209
50172
  color: new Color(7000831),
50210
50173
  opacity: 0.5
50211
50174
  },
50212
- isolation: {
50175
+ ghost: {
50213
50176
  color: new Color(5132892),
50214
- opacity: 0.08
50177
+ opacity: 0.01
50215
50178
  },
50216
50179
  section: {
50217
50180
  strokeWidth: 0.01,
@@ -52399,6 +52362,9 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52399
52362
  });
52400
52363
  this._onValueChanged.dispatch();
52401
52364
  }
52365
+ any() {
52366
+ return this._objects.size > 0;
52367
+ }
52402
52368
  /**
52403
52369
  * Returns true if the given object is currently selected.
52404
52370
  * @param {IObject} object The object to check for selection.
@@ -52508,92 +52474,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52508
52474
  this._materials.focusIntensity = focus / 2;
52509
52475
  }
52510
52476
  }
52511
- class GroundPlane {
52512
- constructor(settings2) {
52513
- __publicField(this, "mesh");
52514
- __publicField(this, "_source");
52515
- __publicField(this, "_size", 1);
52516
- // disposable
52517
- __publicField(this, "_geometry");
52518
- __publicField(this, "_material");
52519
- __publicField(this, "_texture");
52520
- this._geometry = new PlaneGeometry();
52521
- this._material = new MeshBasicMaterial({
52522
- transparent: true,
52523
- depthTest: true,
52524
- depthWrite: false
52525
- });
52526
- this.mesh = new Mesh(this._geometry, this._material);
52527
- this.mesh.renderOrder = -1;
52528
- this._size = settings2.groundPlane.size;
52529
- this.mesh.visible = settings2.groundPlane.visible;
52530
- this.applyTexture(
52531
- settings2.groundPlane.encoding,
52532
- settings2.groundPlane.texture
52533
- );
52534
- this._material.color.copy(settings2.groundPlane.color);
52535
- this._material.opacity = settings2.groundPlane.opacity;
52536
- }
52537
- /**
52538
- * Whether the ground plane is visible or not.
52539
- */
52540
- get visible() {
52541
- return this.mesh.visible;
52542
- }
52543
- set visible(value) {
52544
- this.mesh.visible = value;
52545
- }
52546
- adaptToContent(box) {
52547
- const center = box.getCenter(new Vector3$1());
52548
- const position = new Vector3$1(
52549
- center.x,
52550
- box.min.y - Math.abs(box.min.y) * 0.01,
52551
- center.z
52552
- );
52553
- this.mesh.position.copy(position);
52554
- this.mesh.quaternion.copy(
52555
- new Quaternion().setFromEuler(new Euler(1.5 * Math.PI, 0, 0))
52556
- );
52557
- const sphere = box == null ? void 0 : box.getBoundingSphere(new Sphere());
52558
- const size = ((sphere == null ? void 0 : sphere.radius) ?? 1) * this._size;
52559
- const scale = new Vector3$1(1, 1, 1).multiplyScalar(size);
52560
- this.mesh.scale.copy(scale);
52561
- }
52562
- applyTexture(encoding, source) {
52563
- var _a2;
52564
- if (source === this._source) return;
52565
- this._source = source;
52566
- (_a2 = this._texture) == null ? void 0 : _a2.dispose();
52567
- this._texture = void 0;
52568
- if (!source || !encoding) return;
52569
- if (encoding === "url") {
52570
- const loader = new TextureLoader();
52571
- this._texture = loader.load(source);
52572
- }
52573
- if (encoding === "base64") {
52574
- const image = new Image();
52575
- image.src = source;
52576
- const txt = new Texture();
52577
- this._texture = txt;
52578
- this._texture.image = image;
52579
- image.onload = () => {
52580
- txt.needsUpdate = true;
52581
- };
52582
- }
52583
- if (!this._texture) {
52584
- console.error("Failed to load texture: " + source);
52585
- return;
52586
- }
52587
- this._material.map = this._texture;
52588
- }
52589
- dispose() {
52590
- var _a2, _b2, _c;
52591
- (_a2 = this._geometry) == null ? void 0 : _a2.dispose();
52592
- (_b2 = this._material) == null ? void 0 : _b2.dispose();
52593
- (_c = this._texture) == null ? void 0 : _c.dispose();
52594
- this._texture = void 0;
52595
- }
52596
- }
52597
52477
  class Skybox {
52598
52478
  constructor(camera2, renderer, materials, settings2) {
52599
52479
  __publicField(this, "mesh");
@@ -52738,28 +52618,22 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52738
52618
  * The array of directional lights in the scene.
52739
52619
  */
52740
52620
  __publicField(this, "sunLights");
52741
- /**
52742
- * The ground plane under the model in the scene.
52743
- */
52744
- __publicField(this, "groundPlane");
52745
52621
  /*
52746
52622
  * The skybox in the scene.
52747
52623
  */
52748
52624
  __publicField(this, "skybox");
52749
52625
  this._camera = camera2;
52750
52626
  this._renderer = renderer;
52751
- this.groundPlane = new GroundPlane(settings2);
52752
52627
  this.skyLight = this.createSkyLight(settings2);
52753
52628
  this.skybox = new Skybox(camera2, renderer, viewerMaterials, settings2);
52754
52629
  this.sunLights = this.createSunLights(settings2);
52755
- this.setupRendererListeners();
52756
52630
  this.addObjectsToRenderer();
52757
52631
  }
52758
52632
  /**
52759
52633
  * Returns all three objects composing the environment
52760
52634
  */
52761
52635
  getObjects() {
52762
- return [this.groundPlane.mesh, this.skyLight, ...this.sunLights.map((l) => l.light), this.skybox.mesh];
52636
+ return [this.skyLight, ...this.sunLights.map((l) => l.light), this.skybox.mesh];
52763
52637
  }
52764
52638
  createSkyLight(settings2) {
52765
52639
  const { skyColor, groundColor, intensity } = settings2.skylight;
@@ -52773,12 +52647,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52773
52647
  addObjectsToRenderer() {
52774
52648
  this.getObjects().forEach((o) => this._renderer.add(o));
52775
52649
  }
52776
- setupRendererListeners() {
52777
- this._renderer.onBoxUpdated.subscribe(() => {
52778
- const box = this._renderer.getBoundingBox();
52779
- this.groundPlane.adaptToContent(box);
52780
- });
52781
- }
52782
52650
  /**
52783
52651
  * Dispose of all resources.
52784
52652
  */
@@ -52786,7 +52654,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52786
52654
  this.getObjects().forEach((o) => this._renderer.remove(o));
52787
52655
  this.sunLights.forEach((s) => s.dispose());
52788
52656
  this.skyLight.dispose();
52789
- this.groundPlane.dispose();
52790
52657
  this.skybox.dispose();
52791
52658
  }
52792
52659
  }
@@ -52919,14 +52786,16 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52919
52786
  __publicField(this, "scene");
52920
52787
  // state
52921
52788
  __publicField(this, "boxUpdated", false);
52789
+ // public value
52790
+ __publicField(this, "smallGhostThreshold", 10);
52922
52791
  __publicField(this, "_vimScenes", []);
52923
52792
  __publicField(this, "_boundingBox");
52924
52793
  __publicField(this, "_memory", 0);
52925
52794
  __publicField(this, "_2dCount", 0);
52926
- __publicField(this, "_material");
52795
+ __publicField(this, "_modelMaterial");
52927
52796
  this.scene = new Scene$1();
52928
52797
  }
52929
- get models() {
52798
+ get meshes() {
52930
52799
  return this._vimScenes.flatMap((s) => s.meshes);
52931
52800
  }
52932
52801
  get estimatedMemory() {
@@ -52973,6 +52842,7 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52973
52842
  add(target) {
52974
52843
  if (target instanceof Scene) {
52975
52844
  this.addScene(target);
52845
+ target.material = this._modelMaterial;
52976
52846
  return;
52977
52847
  }
52978
52848
  this._2dCount += this.count2dObjects(target);
@@ -53022,16 +52892,31 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
53022
52892
  this._boundingBox = void 0;
53023
52893
  this._memory = 0;
53024
52894
  }
53025
- get material() {
53026
- return this._material;
52895
+ get modelMaterial() {
52896
+ return this._modelMaterial;
53027
52897
  }
53028
- set material(material) {
53029
- this._material = material;
52898
+ set modelMaterial(material) {
52899
+ this._modelMaterial = material;
53030
52900
  this._vimScenes.forEach((s) => {
53031
- s.meshes.forEach((m) => {
53032
- m.mesh.material = material;
53033
- });
52901
+ s.material = material;
53034
52902
  });
52903
+ this.updateInstanceMeshVisibility();
52904
+ }
52905
+ updateInstanceMeshVisibility() {
52906
+ var _a2, _b2;
52907
+ const hide = ((_b2 = (_a2 = this._modelMaterial) == null ? void 0 : _a2[1]) == null ? void 0 : _b2.userData.isGhost) === true;
52908
+ for (const mesh of this.meshes) {
52909
+ if (mesh instanceof InstancedMesh) {
52910
+ if (this.smallGhostThreshold <= 0) {
52911
+ mesh.mesh.visible = true;
52912
+ continue;
52913
+ }
52914
+ const visible2 = mesh.getSubmeshes().some(
52915
+ (m) => m.object.visible
52916
+ );
52917
+ mesh.mesh.visible = !(hide && !visible2 && mesh.size < this.smallGhostThreshold);
52918
+ }
52919
+ }
53035
52920
  }
53036
52921
  addScene(scene) {
53037
52922
  this._vimScenes.push(scene);
@@ -55637,7 +55522,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
55637
55522
  this.minZ.constant = -box.min.z;
55638
55523
  this.box.copy(box);
55639
55524
  this._renderer.needsUpdate = true;
55640
- this._renderer.skipAntialias = true;
55641
55525
  }
55642
55526
  /**
55643
55527
  * Determines whether objecets outside the section box will be culled or not.
@@ -56596,7 +56480,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56596
56480
  __publicField(this, "_composer");
56597
56481
  __publicField(this, "_materials");
56598
56482
  __publicField(this, "_renderText");
56599
- __publicField(this, "_skipAntialias");
56600
56483
  __publicField(this, "_needsUpdate");
56601
56484
  __publicField(this, "_onSceneUpdate", new distExports$1.SignalDispatcher());
56602
56485
  __publicField(this, "_onBoxUpdated", new distExports$1.SignalDispatcher());
@@ -56658,17 +56541,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56658
56541
  set needsUpdate(value) {
56659
56542
  this._needsUpdate = this._needsUpdate || value;
56660
56543
  }
56661
- /**
56662
- * Indicates whether the next render should skip antialiasing.
56663
- * Useful for expensive operations such as the section box.
56664
- * Can only be set to true. Cleared on each render.
56665
- */
56666
- get skipAntialias() {
56667
- return this._skipAntialias;
56668
- }
56669
- set skipAntialias(value) {
56670
- this._skipAntialias = this._skipAntialias || value;
56671
- }
56672
56544
  /**
56673
56545
  * Removes all objects from rendering and disposes the WebGL context.
56674
56546
  */
@@ -56689,6 +56561,12 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56689
56561
  this._scene.scene.background = color;
56690
56562
  this.needsUpdate = true;
56691
56563
  }
56564
+ get modelMaterial() {
56565
+ return this._scene.modelMaterial;
56566
+ }
56567
+ set modelMaterial(material) {
56568
+ this._scene.modelMaterial = material;
56569
+ }
56692
56570
  /**
56693
56571
  * Signal dispatched at the end of each frame if the scene was updated, such as visibility changes.
56694
56572
  */
@@ -56713,6 +56591,12 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56713
56591
  this._renderText = value;
56714
56592
  this.textRenderer.domElement.style.display = value ? "block" : "none";
56715
56593
  }
56594
+ get smallGhostThreshold() {
56595
+ return this._scene.smallGhostThreshold;
56596
+ }
56597
+ set smallGhostThreshold(value) {
56598
+ this._scene.smallGhostThreshold = value;
56599
+ }
56716
56600
  /**
56717
56601
  * Returns the bounding box encompassing all rendered objects.
56718
56602
  * @param target - Box in which to copy the result. A new instance is created if undefined.
@@ -56752,7 +56636,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56752
56636
  this._composer.render();
56753
56637
  }
56754
56638
  this._needsUpdate = false;
56755
- this.skipAntialias = false;
56756
56639
  if (this.textEnabled && this._scene.has2dObjects()) {
56757
56640
  this.textRenderer.render(this._scene.scene, this._camera.three);
56758
56641
  }
@@ -57018,14 +56901,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
57018
56901
  groundColor: get2("skybox.groundColor", strToColor),
57019
56902
  sharpness: get2("skybox.sharpness", Number.parseFloat)
57020
56903
  },
57021
- groundPlane: {
57022
- visible: get2("groundPlane.visible", strToBool),
57023
- encoding: get2("groundPlane.encoding"),
57024
- texture: get2("groundPlane.texture"),
57025
- opacity: get2("groundPlane.opacity", Number.parseFloat),
57026
- color: get2("groundPlane.color", strToColor),
57027
- size: get2("groundPlane.size", Number.parseFloat)
57028
- },
57029
56904
  skylight: {
57030
56905
  skyColor: get2("skylight.skyColor", strToColor),
57031
56906
  groundColor: get2("skylight.groundColor", strToColor),
@@ -57053,9 +56928,9 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
57053
56928
  color: get2("materials.highlight.color", strToColor),
57054
56929
  opacity: get2("materials.highlight.opacity", Number.parseFloat)
57055
56930
  },
57056
- isolation: {
57057
- color: get2("materials.isolation.color", strToColor),
57058
- opacity: get2("materials.isolation.opacity", Number.parseFloat)
56931
+ ghost: {
56932
+ color: get2("materials.ghost.color", strToColor),
56933
+ opacity: get2("materials.ghost.opacity", Number.parseFloat)
57059
56934
  },
57060
56935
  section: {
57061
56936
  strokeWidth: get2("materials.section.strokeWidth", Number.parseFloat),
@@ -59720,6 +59595,7 @@ Averrage Date/Second ${avgDataRatePS} kb
59720
59595
  ControllablePromise,
59721
59596
  ResolvedPromise
59722
59597
  }, Symbol.toStringTag, { value: "Module" }));
59598
+ const DEFAULT_LOCAL_ULTRA_SERVER_URL = "ws://localhost:8123";
59723
59599
  class SocketClient {
59724
59600
  /**
59725
59601
  * Constructs a new Messenger instance.
@@ -59744,7 +59620,7 @@ Averrage Date/Second ${avgDataRatePS} kb
59744
59620
  __publicField(this, "_state", { status: "disconnected" });
59745
59621
  __publicField(this, "_onStatusUpdate", new distExports.SimpleEventDispatcher());
59746
59622
  __publicField(this, "_connectPromise", new ResolvedPromise(void 0));
59747
- __publicField(this, "_connectingUrl");
59623
+ __publicField(this, "_connectionSettings");
59748
59624
  this._logger = logger;
59749
59625
  this._rpcCallId = 0;
59750
59626
  this._streamLogger = new StreamLogger(logger);
@@ -59777,14 +59653,22 @@ Averrage Date/Second ${avgDataRatePS} kb
59777
59653
  * @returns The WebSocket URL as a string, or undefined if not set.
59778
59654
  */
59779
59655
  get url() {
59780
- return this._connectingUrl;
59656
+ var _a2;
59657
+ return (_a2 = this._connectionSettings) == null ? void 0 : _a2.url;
59781
59658
  }
59782
59659
  /**
59783
59660
  * Connects to a WebSocket server at the specified URL.
59784
59661
  * @param url - The WebSocket URL to connect to.
59785
59662
  * @returns A promise that resolves when the connection is established.
59786
59663
  */
59787
- connect(url) {
59664
+ connect(settings2) {
59665
+ settings2 = {
59666
+ url: (settings2 == null ? void 0 : settings2.url) ?? DEFAULT_LOCAL_ULTRA_SERVER_URL,
59667
+ retries: (settings2 == null ? void 0 : settings2.retries) ?? -1,
59668
+ timeout: (settings2 == null ? void 0 : settings2.timeout) ?? 5e3,
59669
+ retryDelay: (settings2 == null ? void 0 : settings2.retryDelay) ?? 5e3
59670
+ };
59671
+ const url = settings2.url;
59788
59672
  if (!isWebSocketUrl(url)) {
59789
59673
  this._disconnect({ status: "error", error: "connection", serverUrl: url });
59790
59674
  return Promise.reject(new Error(`Invalid WebSocket URL: ${url}`));
@@ -59794,17 +59678,18 @@ Averrage Date/Second ${avgDataRatePS} kb
59794
59678
  return this._connectPromise.promise;
59795
59679
  } else {
59796
59680
  this._clearSocket();
59681
+ this._connectionSettings = void 0;
59797
59682
  this._connectPromise.reject("Connection to a different server");
59798
- this._connectPromise = new ControllablePromise();
59799
59683
  }
59800
- } else if (this._connectingUrl !== url) {
59684
+ }
59685
+ if (this.url !== url) {
59801
59686
  this._connectPromise = new ControllablePromise();
59802
- this._connectingUrl = url;
59687
+ this._connectionSettings = settings2;
59803
59688
  }
59804
59689
  this.updateState({ status: "connecting" });
59805
59690
  try {
59806
59691
  this._socket = new WebSocket(url);
59807
- this._connectionTimeout = setTimeout(() => this._onClose(), 5e3);
59692
+ this._connectionTimeout = setTimeout(() => this._onClose(), settings2.timeout);
59808
59693
  this._socket.onopen = (e) => {
59809
59694
  this._onOpen(e);
59810
59695
  };
@@ -59827,15 +59712,15 @@ Averrage Date/Second ${avgDataRatePS} kb
59827
59712
  * Disconnects from the current WebSocket server.
59828
59713
  */
59829
59714
  disconnect(error) {
59830
- this._logger.log("Disconnecting from: ", this._connectingUrl);
59831
- this._connectingUrl = void 0;
59715
+ this._logger.log("Disconnecting from: ", this.url);
59716
+ this._connectionSettings = void 0;
59832
59717
  this._disconnect(error);
59833
59718
  }
59834
59719
  /**
59835
59720
  * Handles the disconnection logic, stopping logging and clearing the socket.
59836
59721
  */
59837
59722
  _disconnect(error) {
59838
- console.log("disconnect", error);
59723
+ this._logger.log("disconnect", error);
59839
59724
  clearTimeout(this._reconnectTimeout);
59840
59725
  clearTimeout(this._connectionTimeout);
59841
59726
  this._streamLogger.stopLogging();
@@ -59916,21 +59801,30 @@ Averrage Date/Second ${avgDataRatePS} kb
59916
59801
  this._logger.log("Connected to: ", (_a2 = this._socket) == null ? void 0 : _a2.url);
59917
59802
  this.updateState({ status: "connected" });
59918
59803
  this._streamLogger.startLoggging();
59919
- this._connectPromise.resolve();
59804
+ this._connectPromise.resolve(true);
59920
59805
  }
59921
59806
  /**
59922
59807
  * Handler for WebSocket 'close' event.
59923
59808
  * @param _event - The event object.
59924
59809
  */
59925
59810
  _onClose(_event) {
59926
- clearTimeout(this._connectionTimeout);
59927
- this._disconnect({ status: "error", error: "connection", serverUrl: this._connectingUrl });
59811
+ const connecting = this.state.status === "connecting" || this.state.status === "validating";
59928
59812
  this._logger.log("WebSocket closed.");
59813
+ clearTimeout(this._connectionTimeout);
59814
+ this._disconnect({ status: "error", error: "connection", serverUrl: this.url });
59815
+ if (connecting && this._connectionSettings.retries === 0) {
59816
+ this._logger.log("No more retries left");
59817
+ this._connectPromise.resolve(false);
59818
+ return;
59819
+ }
59929
59820
  this._logger.log("Attempting to reconnect in 5 seconds");
59930
59821
  this._reconnectTimeout = setTimeout(() => {
59931
59822
  this.updateState({ status: "connecting" });
59932
- this.connect(this._connectingUrl);
59933
- }, 5e3);
59823
+ if (connecting) {
59824
+ this._connectionSettings.retries--;
59825
+ }
59826
+ this.connect(this._connectionSettings);
59827
+ }, this._connectionSettings.retryDelay);
59934
59828
  }
59935
59829
  /**
59936
59830
  * Sends binary data over the WebSocket connection.
@@ -60303,31 +60197,6 @@ Averrage Date/Second ${avgDataRatePS} kb
60303
60197
  this._pendingFrame = frame;
60304
60198
  }
60305
60199
  }
60306
- let DeferredPromise$1 = class DeferredPromise extends Promise {
60307
- constructor(executor = () => {
60308
- }) {
60309
- var _a2;
60310
- let resolver;
60311
- let rejector;
60312
- super((resolve, reject) => {
60313
- resolver = resolve;
60314
- rejector = reject;
60315
- return executor(resolve, reject);
60316
- });
60317
- __publicField(this, "resolve");
60318
- __publicField(this, "reject");
60319
- __publicField(this, "initialCallStack");
60320
- this.resolve = resolver;
60321
- this.reject = rejector;
60322
- this.initialCallStack = (_a2 = Error().stack) == null ? void 0 : _a2.split("\n").slice(2).join("\n");
60323
- }
60324
- /** @throws error with amended call stack */
60325
- rejectWithError(error) {
60326
- var _a2;
60327
- error.stack = [(_a2 = error.stack) == null ? void 0 : _a2.split("\n")[0], this.initialCallStack].join("\n");
60328
- this.reject(error);
60329
- }
60330
- };
60331
60200
  class LoadSuccess {
60332
60201
  constructor(vim) {
60333
60202
  __publicField(this, "isError", false);
@@ -60350,8 +60219,8 @@ Averrage Date/Second ${avgDataRatePS} kb
60350
60219
  let LoadRequest$1 = class LoadRequest {
60351
60220
  constructor() {
60352
60221
  __publicField(this, "_progress", 0);
60353
- __publicField(this, "_progressPromise", new DeferredPromise$1());
60354
- __publicField(this, "_completionPromise", new DeferredPromise$1());
60222
+ __publicField(this, "_progressPromise", new ControllablePromise());
60223
+ __publicField(this, "_completionPromise", new ControllablePromise());
60355
60224
  __publicField(this, "_result");
60356
60225
  }
60357
60226
  get isCompleted() {
@@ -60364,18 +60233,18 @@ Averrage Date/Second ${avgDataRatePS} kb
60364
60233
  return;
60365
60234
  }
60366
60235
  while (this._result === void 0) {
60367
- await this._progressPromise;
60236
+ await this._progressPromise.promise;
60368
60237
  yield this._progress;
60369
60238
  }
60370
60239
  }
60371
60240
  async getResult() {
60372
- await this._completionPromise;
60241
+ await this._completionPromise.promise;
60373
60242
  return this._result;
60374
60243
  }
60375
60244
  onProgress(progress) {
60376
60245
  this._progress = progress;
60377
60246
  this._progressPromise.resolve();
60378
- this._progressPromise = new DeferredPromise$1();
60247
+ this._progressPromise = new ControllablePromise();
60379
60248
  }
60380
60249
  success(vim) {
60381
60250
  this._result = new LoadSuccess(vim);
@@ -61583,7 +61452,6 @@ Averrage Date/Second ${avgDataRatePS} kb
61583
61452
  }
61584
61453
  }
61585
61454
  }
61586
- const DEFAULT_LOCAL_ULTRA_SERVER_URL = "ws://localhost:8123";
61587
61455
  const INVALID_HANDLE = 4294967295;
61588
61456
  class Viewer {
61589
61457
  /**
@@ -61756,8 +61624,8 @@ Averrage Date/Second ${avgDataRatePS} kb
61756
61624
  * @param url - The server URL to connect to. Defaults to 'ws://localhost:8123'.
61757
61625
  * @returns A promise that resolves when the connection is established.
61758
61626
  */
61759
- async connect(url = DEFAULT_LOCAL_ULTRA_SERVER_URL) {
61760
- await this._socketClient.connect(url);
61627
+ async connect(settings2) {
61628
+ return this._socketClient.connect(settings2);
61761
61629
  }
61762
61630
  /**
61763
61631
  * Disconnects from the current VIM Ultra server.
@@ -61820,7 +61688,6 @@ Averrage Date/Second ${avgDataRatePS} kb
61820
61688
  __proto__: null,
61821
61689
  Box3,
61822
61690
  ColorHandle,
61823
- DEFAULT_LOCAL_ULTRA_SERVER_URL,
61824
61691
  INVALID_HANDLE,
61825
61692
  Matrix44: Matrix4,
61826
61693
  RGB,
@@ -67016,12 +66883,13 @@ Averrage Date/Second ${avgDataRatePS} kb
67016
66883
  return isTrue(settings2.ui.projectInspector) || isTrue(settings2.ui.settings) || isTrue(settings2.ui.help) || isTrue(settings2.ui.maximise);
67017
66884
  }
67018
66885
  const defaultSettings = {
67019
- peformance: {
67020
- useFastMaterial: false
66886
+ materials: {
66887
+ useFastMaterial: false,
66888
+ useGhostMaterial: true,
66889
+ smallGhostThreshold: 10
67021
66890
  },
67022
66891
  isolation: {
67023
- enable: true,
67024
- useIsolationMaterial: true
66892
+ enable: true
67025
66893
  },
67026
66894
  capacity: {
67027
66895
  canFollowUrl: true,
@@ -67101,7 +66969,7 @@ Averrage Date/Second ${avgDataRatePS} kb
67101
66969
  }, []);
67102
66970
  const onIsolationBtn = () => {
67103
66971
  props.settings.update(
67104
- (s) => s.isolation.useIsolationMaterial = !s.isolation.useIsolationMaterial
66972
+ (s) => s.materials.useGhostMaterial = !s.materials.useGhostMaterial
67105
66973
  );
67106
66974
  };
67107
66975
  const onHomeBtn = () => {
@@ -67111,11 +66979,11 @@ Averrage Date/Second ${avgDataRatePS} kb
67111
66979
  const btnIsolation = /* @__PURE__ */ jsxRuntimeExports.jsx(
67112
66980
  "button",
67113
66981
  {
67114
- "data-tip": props.settings.value.isolation.useIsolationMaterial ? "Disable Ghosting" : "Enable Ghosting",
66982
+ "data-tip": props.settings.value.materials.useGhostMaterial ? "Disable Ghosting" : "Enable Ghosting",
67115
66983
  onClick: onIsolationBtn,
67116
66984
  className: "vim-isolation-btn " + btnStyle2,
67117
66985
  type: "button",
67118
- children: props.settings.value.isolation.useIsolationMaterial ? /* @__PURE__ */ jsxRuntimeExports.jsx(ghost, { height: 20, width: 20, fill: "currentColor" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ghostDead, { height: 20, width: 20, fill: "currentColor" })
66986
+ children: props.settings.value.materials.useGhostMaterial ? /* @__PURE__ */ jsxRuntimeExports.jsx(ghost, { height: 20, width: 20, fill: "currentColor" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ghostDead, { height: 20, width: 20, fill: "currentColor" })
67119
66987
  }
67120
66988
  );
67121
66989
  const btnHome = /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -67645,7 +67513,7 @@ Averrage Date/Second ${avgDataRatePS} kb
67645
67513
  id: elementIds.buttonToggleIsolation,
67646
67514
  enabled: () => isTrue(props.settings.ui.toggleIsolation),
67647
67515
  tip: "Toggle Isolation",
67648
- action: () => props.isolation.toggleIsolation("controlBar"),
67516
+ action: () => props.isolation.toggle("controlBar"),
67649
67517
  icon: toggleIsolation,
67650
67518
  style: buttonDefaultStyle
67651
67519
  }
@@ -71666,7 +71534,7 @@ Averrage Date/Second ${avgDataRatePS} kb
71666
71534
  };
71667
71535
  const [clipping, setClipping] = React2.useState(isClipping());
71668
71536
  const [, setVersion] = React2.useState(0);
71669
- const hidden2 = props.isolation.any();
71537
+ const hidden2 = props.isolation.isActive();
71670
71538
  React2.useEffect(() => {
71671
71539
  const subState = viewer.gizmos.section.onStateChanged.subscribe(() => {
71672
71540
  setSection({
@@ -74049,31 +73917,17 @@ Averrage Date/Second ${avgDataRatePS} kb
74049
73917
  ),
74050
73918
  settingsSubtitle("Materials"),
74051
73919
  settingsToggle(
74052
- "Use Isolation Material",
74053
- (settings2) => settings2.isolation.useIsolationMaterial,
73920
+ "Use Ghost Material",
73921
+ (settings2) => settings2.materials.useGhostMaterial,
74054
73922
  (settings2, value) => {
74055
- settings2.isolation.useIsolationMaterial = value;
74056
- if (settings2.peformance.useFastMaterial && value) {
74057
- settings2.peformance.useFastMaterial = false;
74058
- }
73923
+ settings2.materials.useGhostMaterial = value;
74059
73924
  }
74060
73925
  ),
74061
73926
  settingsToggle(
74062
73927
  "Use Performance Material",
74063
- (settings2) => settings2.peformance.useFastMaterial,
73928
+ (settings2) => settings2.materials.useFastMaterial,
74064
73929
  (settings2, value) => {
74065
- settings2.peformance.useFastMaterial = value;
74066
- if (settings2.isolation.useIsolationMaterial && value) {
74067
- settings2.isolation.useIsolationMaterial = false;
74068
- }
74069
- }
74070
- ),
74071
- settingsSubtitle("Scene"),
74072
- settingsToggle(
74073
- "Show Ground Plane",
74074
- (_) => props.viewer.environment.groundPlane.visible,
74075
- (_, value) => {
74076
- props.viewer.environment.groundPlane.visible = value;
73930
+ settings2.materials.useFastMaterial = value;
74077
73931
  }
74078
73932
  ),
74079
73933
  settingsSubtitle("Panels"),
@@ -74347,7 +74201,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74347
74201
  __publicField(this, "_default");
74348
74202
  __publicField(this, "_isolation");
74349
74203
  __publicField(this, "_sideState");
74350
- __publicField(this, "_help");
74351
74204
  __publicField(this, "_getSelection", () => {
74352
74205
  return [...this._viewer.selection.objects].filter(
74353
74206
  (o) => o.type === "Object3D"
@@ -74377,7 +74230,7 @@ Averrage Date/Second ${avgDataRatePS} kb
74377
74230
  return true;
74378
74231
  }
74379
74232
  case KEYS.KEY_I: {
74380
- this._isolation.toggleIsolation("keyboard");
74233
+ this._isolation.toggle("keyboard");
74381
74234
  return true;
74382
74235
  }
74383
74236
  case KEYS.KEY_ESCAPE: {
@@ -74385,7 +74238,7 @@ Averrage Date/Second ${avgDataRatePS} kb
74385
74238
  this._viewer.selection.clear();
74386
74239
  return true;
74387
74240
  }
74388
- if (this._isolation.any()) {
74241
+ if (this._isolation.isActive()) {
74389
74242
  this._isolation.clear("keyboard");
74390
74243
  return true;
74391
74244
  }
@@ -74467,7 +74320,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74467
74320
  var _a2;
74468
74321
  const next = { ...settings2 };
74469
74322
  updater(next);
74470
- validateSettings(next);
74471
74323
  saveSettingsToLocal(next);
74472
74324
  setSettings(next);
74473
74325
  (_a2 = onUpdate.current) == null ? void 0 : _a2.call(onUpdate, next);
@@ -74487,11 +74339,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74487
74339
  [settings2]
74488
74340
  );
74489
74341
  }
74490
- function validateSettings(settings2) {
74491
- if (settings2.peformance.useFastMaterial && settings2.isolation.useIsolationMaterial) {
74492
- settings2.peformance.useFastMaterial = false;
74493
- }
74494
- }
74495
74342
  function applySettings(viewer, settings2) {
74496
74343
  const performance2 = document.getElementsByClassName("vim-performance-div")[0];
74497
74344
  if (performance2) {
@@ -74501,240 +74348,192 @@ Averrage Date/Second ${avgDataRatePS} kb
74501
74348
  performance2.classList.add("vc-hidden");
74502
74349
  }
74503
74350
  }
74504
- viewer.vims.forEach((v) => {
74505
- if (settings2.peformance.useFastMaterial && v.scene.material === void 0) {
74506
- v.scene.material = viewer.materials.simple;
74507
- }
74508
- if (!settings2.peformance.useFastMaterial && v.scene.material === viewer.materials.simple) {
74509
- v.scene.material = void 0;
74510
- }
74511
- });
74351
+ viewer.renderer.smallGhostThreshold = settings2.materials.smallGhostThreshold;
74512
74352
  }
74513
74353
  class Isolation {
74354
+ /**
74355
+ * Constructs an IsolationManager.
74356
+ *
74357
+ * @param viewer - The VIM Viewer responsible for managing the 3D scene and objects.
74358
+ * @param camera - A component that handles camera control and framing.
74359
+ * @param settings - The settings that control isolation and material usage.
74360
+ */
74514
74361
  constructor(viewer, camera2, settings2) {
74515
74362
  __publicField(this, "_viewer");
74516
74363
  __publicField(this, "_settings");
74517
- __publicField(this, "_isolation");
74518
- __publicField(this, "_lastIsolation");
74364
+ __publicField(this, "_isolation", []);
74519
74365
  __publicField(this, "_camera");
74520
- __publicField(this, "_references", /* @__PURE__ */ new Map());
74521
74366
  __publicField(this, "_onChanged", new distExports.SimpleEventDispatcher());
74522
74367
  this._viewer = viewer;
74523
74368
  this._camera = camera2;
74524
74369
  this.applySettings(settings2);
74525
74370
  }
74526
- /** Signal dispatched when the isolation set changes. */
74371
+ /**
74372
+ * An event that is dispatched whenever the isolation set changes.
74373
+ *
74374
+ * @remarks
74375
+ * This can be used by other parts of the application to react to isolation
74376
+ * updates (for example, updating UI or triggering additional viewport actions).
74377
+ *
74378
+ * @returns {ISimpleEvent<string>} Event interface for subscribing to isolation changes.
74379
+ */
74527
74380
  get onChanged() {
74528
74381
  return this._onChanged.asEvent();
74529
74382
  }
74530
74383
  /**
74531
- * Applies relevant settings to isolation.
74532
- * @param settings The settings to be applied to isolation.
74384
+ * Applies relevant settings to the isolation behavior.
74385
+ *
74386
+ * @param settings - The new settings to apply.
74387
+ *
74388
+ * @remarks
74389
+ * This updates the internal reference to settings and immediately sets
74390
+ * the material based on whether isolation is currently active.
74533
74391
  */
74534
74392
  applySettings(settings2) {
74535
- var _a2;
74536
74393
  this._settings = settings2;
74537
74394
  if (!this._settings.isolation.enable) return;
74538
- const set2 = new Set((_a2 = this._isolation) == null ? void 0 : _a2.map((o) => o.vim));
74539
- this._viewer.vims.forEach((v) => {
74540
- v.scene.material = this.getMaterial(this._settings, set2.has(v));
74541
- });
74395
+ this._viewer.renderer.modelMaterial = this.getMaterial(this._settings, this.isActive());
74542
74396
  }
74543
74397
  /**
74544
- * Sets the reference objects for a given VIM.
74545
- * @param vim The VIM for which reference objects are being set.
74546
- * @param reference An array of reference objects or the string 'always' to indicate permanent reference.
74398
+ * Checks if isolation is currently active (i.e., any objects are isolated).
74399
+ *
74400
+ * @returns True if isolation is active; otherwise, false.
74547
74401
  */
74548
- setReference(vim, reference) {
74549
- const value = reference === "always" ? reference : new Set(reference);
74550
- this._references.set(vim, value);
74402
+ isActive() {
74403
+ return this._isolation.length > 0;
74551
74404
  }
74552
74405
  /**
74553
- * Retrieves the reference objects set for a given VIM.
74554
- * @param vim The VIM for which reference objects are being retrieved.
74555
- * @returns The reference objects set for the specified VIM.
74556
- */
74557
- getReference(vim) {
74558
- return this._references.get(vim);
74559
- }
74560
- /**
74561
- * Clears all reference objects set for VIMs.
74562
- */
74563
- clearReferences() {
74564
- this._references.clear();
74565
- }
74566
- /**
74567
- * Returns true if there are currently objects isolated.
74568
- * @returns True if there are currently objects isolated; otherwise, false.
74569
- */
74570
- any() {
74571
- return this._isolation !== void 0;
74572
- }
74573
- /**
74574
- * Returns the current array of isolated objects.
74575
- * @returns The array of objects currently isolated, or undefined if no objects are isolated.
74406
+ * Retrieves the current array of isolated objects.
74407
+ *
74408
+ * @returns An array of isolated objects, or undefined if isolation is not active.
74576
74409
  */
74577
74410
  current() {
74578
74411
  return this._isolation;
74579
74412
  }
74580
74413
  /**
74581
- * Isolates the objects in the given array and shows the rest as ghost.
74582
- * @param objects An array of objects to isolate.
74583
- * @param source The source of isolation.
74584
- * @returns True if isolation occurs; otherwise, false.
74414
+ * Sets the specified objects as isolated, hiding or ghosting the rest.
74415
+ *
74416
+ * @param objects - The objects to isolate.
74417
+ * @param source - A label or identifier indicating the source of this action (e.g., "user").
74585
74418
  */
74586
74419
  isolate(objects, source) {
74587
74420
  if (!this._settings.isolation.enable) return;
74588
- if (this._isolation) {
74589
- this._lastIsolation = this._isolation;
74590
- }
74591
- const isolated = this._isolate(this._viewer, this._settings, objects);
74592
- this._isolation = isolated ? objects : void 0;
74421
+ this._isolation = objects ?? [];
74422
+ this._apply(source);
74593
74423
  this._camera.frameVisibleObjects();
74594
- this._onChanged.dispatch(source);
74595
- return isolated;
74596
74424
  }
74597
74425
  /**
74598
- * Toggles current isolation based on selection.
74599
- * @param source The source of isolation.
74426
+ * Toggles isolation by using the current selection.
74427
+ *
74428
+ * @param source - A label or identifier for the isolation action.
74429
+ *
74430
+ * @remarks
74431
+ * This method replaces the current isolation set with whatever objects are
74432
+ * currently selected. If selection is empty, it effectively clears isolation.
74600
74433
  */
74601
- toggleIsolation(source) {
74434
+ toggle(source) {
74602
74435
  if (!this._settings.isolation.enable) return;
74603
- const selection = [...this._viewer.selection.objects].filter((o) => o.type === "Object3D");
74604
- if (this._isolation) {
74605
- this._lastIsolation = this._isolation;
74606
- }
74607
- if (this._isolation) {
74608
- if (selection.length === 0 || ArrayEquals(this._isolation, selection)) {
74609
- this._showAll();
74610
- this._isolation = void 0;
74611
- } else {
74612
- const isolated = this._isolate(this._viewer, this._settings, selection);
74613
- this._isolation = isolated ? selection : void 0;
74614
- this._camera.frameVisibleObjects();
74615
- this._viewer.selection.clear();
74616
- }
74617
- } else {
74618
- if (selection.length > 0) {
74619
- const isolated = this._isolate(this._viewer, this._settings, selection);
74620
- this._isolation = isolated ? selection : void 0;
74621
- this._camera.frameVisibleObjects();
74622
- this._viewer.selection.clear();
74623
- } else if (this._lastIsolation) {
74624
- const isolated = this._isolate(
74625
- this._viewer,
74626
- this._settings,
74627
- this._lastIsolation
74628
- );
74629
- this._isolation = isolated ? [...this._lastIsolation] : void 0;
74630
- }
74631
- }
74632
- this._onChanged.dispatch(source);
74436
+ this._isolation = [...this._viewer.selection.objects].filter((o) => o.type === "Object3D");
74437
+ this._apply(source);
74438
+ this._camera.frameVisibleObjects();
74439
+ this._viewer.selection.clear();
74633
74440
  }
74634
74441
  /**
74635
- * Removes the given objects from the isolation set.
74636
- * @param objects An array of objects to be removed from isolation.
74637
- * @param source The source of the removal operation.
74442
+ * Hides the specified objects from the isolation set.
74443
+ *
74444
+ * @param objects - The objects to hide.
74445
+ * @param source - A label or identifier for the isolation action.
74446
+ *
74447
+ * @remarks
74448
+ * If there is no active isolation set (i.e., all objects are visible),
74449
+ * the method first treats all objects in the scene as isolated,
74450
+ * and then removes the specified objects. This ensures the specified
74451
+ * objects become hidden.
74638
74452
  */
74639
74453
  hide(objects, source) {
74640
74454
  if (!this._settings.isolation.enable) return;
74641
- const selection = new Set(objects);
74642
- const initial = this._isolation ?? this._viewer.vims[0].getObjects();
74643
- const result = [];
74644
- for (const obj of initial) {
74645
- if (!selection.has(obj)) result.push(obj);
74646
- }
74647
- const isolated = this._isolate(this._viewer, this._settings, result);
74648
- this._isolation = isolated ? result : void 0;
74649
- this._onChanged.dispatch(source);
74455
+ this._isolation = this._isolation.length === 0 ? this.getAllObjects() : this._isolation;
74456
+ this._isolation = this._isolation.filter((o) => !objects.includes(o));
74457
+ this._apply(source);
74650
74458
  objects.forEach((o) => this._viewer.selection.remove(o));
74651
74459
  }
74652
74460
  /**
74653
- * Adds the given objects to the isolation set.
74654
- * @param objects An array of objects to be added to isolation.
74655
- * @param source The source of the addition operation.
74461
+ * Adds the specified objects to the current isolation set (making them visible).
74462
+ *
74463
+ * @param objects - The objects to show.
74464
+ * @param source - A label or identifier for the isolation action.
74656
74465
  */
74657
74466
  show(objects, source) {
74658
74467
  if (!this._settings.isolation.enable) return;
74659
- const isolation = this._isolation ?? [];
74660
- objects.forEach((o) => isolation.push(o));
74661
- const result = [...new Set(isolation)];
74662
- const isolated = this._isolate(this._viewer, this._settings, result);
74663
- this._isolation = isolated ? result : void 0;
74664
- this._onChanged.dispatch(source);
74468
+ objects.forEach((o) => this._isolation.push(o));
74469
+ this._apply(source);
74665
74470
  }
74666
74471
  /**
74667
- * Clears the current isolation.
74668
- * @param source The source of the isolation clearing operation.
74472
+ * Clears the current isolation set, making all objects visible.
74473
+ *
74474
+ * @param source - A label or identifier for the isolation action.
74669
74475
  */
74670
74476
  clear(source) {
74671
74477
  if (!this._settings.isolation.enable) return;
74672
- this._showAll();
74673
- this._lastIsolation = this._isolation;
74674
- this._isolation = void 0;
74675
- this._onChanged.dispatch(source);
74478
+ this._isolation.length = 0;
74479
+ this._apply(source);
74676
74480
  }
74677
74481
  /**
74678
- * Show all objects and quit isolation mode.
74482
+ * Constructs the correct material (or array of materials) based on the given settings.
74483
+ *
74484
+ * @param settings - The current component settings, including isolation rules.
74485
+ * @param isolate - Whether or not isolation is active.
74486
+ * @returns The material(s) to assign to the renderer, or undefined if default materials should be used.
74487
+ *
74488
+ * @remarks
74489
+ * - If isolation is active and `useGhostMaterial` is true, an array containing
74490
+ * the simple and ghost materials is returned.
74491
+ * - If fast materials are enabled, the simple material is returned.
74492
+ * - Otherwise, defaults to undefined, allowing the system to pick a standard material.
74679
74493
  */
74680
- _showAll() {
74681
- this._viewer.vims.forEach((v) => {
74682
- for (const obj of v.getObjects()) {
74683
- obj.visible = true;
74684
- }
74685
- v.scene.material = this.getMaterial(this._settings, false);
74686
- });
74687
- }
74688
74494
  getMaterial(settings2, isolate) {
74689
- if (settings2.peformance.useFastMaterial) {
74690
- return this._viewer.materials.simple;
74691
- }
74692
- if (!settings2.isolation.useIsolationMaterial) {
74693
- return void 0;
74495
+ if (isolate && settings2.materials.useGhostMaterial) {
74496
+ return [this._viewer.materials.simple, this._viewer.materials.ghost];
74694
74497
  }
74695
- if (!isolate) {
74696
- return void 0;
74498
+ if (settings2.materials.useFastMaterial) {
74499
+ return this._viewer.materials.simple;
74697
74500
  }
74698
- return this._viewer.materials.isolation;
74501
+ return void 0;
74699
74502
  }
74700
- _isolate(viewer, settings2, objects) {
74701
- let useIsolation = false;
74702
- if (!objects) {
74703
- this._showAll();
74704
- } else {
74705
- const set2 = new Set(objects);
74706
- let all = true;
74707
- viewer.vims.forEach((vim) => {
74708
- for (const obj of vim.getObjects()) {
74709
- if (obj.hasMesh) {
74710
- obj.visible = set2.has(obj);
74711
- all = all && obj.visible;
74712
- }
74713
- }
74714
- const reference = this._references.get(vim);
74715
- if (reference === void 0) {
74716
- useIsolation = !all;
74717
- } else if (reference === "always") {
74718
- useIsolation = true;
74719
- } else {
74720
- useIsolation = !setsEqual(reference, set2);
74503
+ /**
74504
+ * Applies the current isolation state: sets visibility for objects, updates materials,
74505
+ * and dispatches the changed event.
74506
+ *
74507
+ * @param source - A label or identifier for the isolation action.
74508
+ */
74509
+ _apply(source) {
74510
+ let all = true;
74511
+ let any = false;
74512
+ const set2 = this._isolation.length > 0 ? new Set(this._isolation) : void 0;
74513
+ this._viewer.vims.forEach((vim) => {
74514
+ for (const obj of vim.getObjects()) {
74515
+ if (obj.hasMesh) {
74516
+ obj.visible = (set2 == null ? void 0 : set2.has(obj)) ?? true;
74517
+ all = all && obj.visible;
74518
+ any = any || obj.visible;
74721
74519
  }
74722
- vim.scene.material = this.getMaterial(this._settings, useIsolation);
74723
- });
74724
- }
74725
- return useIsolation;
74726
- }
74727
- }
74728
- function setsEqual(set1, set2) {
74729
- if (set1.size !== set2.size) {
74730
- return false;
74520
+ }
74521
+ });
74522
+ this._viewer.renderer.modelMaterial = this.getMaterial(this._settings, any && !all);
74523
+ this._onChanged.dispatch(source);
74731
74524
  }
74732
- for (const item of set1) {
74733
- if (!set2.has(item)) {
74734
- return false;
74735
- }
74525
+ /**
74526
+ * Gathers all objects from all loaded VIM instances.
74527
+ *
74528
+ * @returns An array of all objects within the loaded VIM scenes.
74529
+ */
74530
+ getAllObjects() {
74531
+ let objects = [];
74532
+ this._viewer.vims.forEach((vim) => {
74533
+ objects = objects.concat(vim.getObjects());
74534
+ });
74535
+ return objects;
74736
74536
  }
74737
- return true;
74738
74537
  }
74739
74538
  class ComponentCamera {
74740
74539
  constructor(viewer) {
@@ -75920,7 +75719,7 @@ Averrage Date/Second ${avgDataRatePS} kb
75920
75719
  }
75921
75720
  if (state.status === "connecting") {
75922
75721
  if (modal.current === void 0 || modal.current.type === "loading") {
75923
- modal.loading({ message: "Connecting to VIM Ultra server..." });
75722
+ modal.loading({ message: "Initializing..." });
75924
75723
  }
75925
75724
  }
75926
75725
  if (state.status === "error") {