vim-web 0.3.42-dev.1 → 0.3.42-dev.10

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 (25) hide show
  1. package/dist/types/core-viewers/ultra/viewer/socketClient.d.ts +5 -4
  2. package/dist/types/core-viewers/ultra/viewer/viewer.d.ts +1 -1
  3. package/dist/types/core-viewers/webgl/loader/materials/ghostMaterial.d.ts +16 -0
  4. package/dist/types/core-viewers/webgl/loader/materials/simpleMaterial.d.ts +10 -5
  5. package/dist/types/core-viewers/webgl/loader/materials/viewerMaterials.d.ts +9 -8
  6. package/dist/types/core-viewers/webgl/loader/mesh.d.ts +2 -1
  7. package/dist/types/core-viewers/webgl/loader/progressive/insertableMesh.d.ts +2 -1
  8. package/dist/types/core-viewers/webgl/loader/progressive/instancedMesh.d.ts +3 -1
  9. package/dist/types/core-viewers/webgl/loader/scene.d.ts +3 -2
  10. package/dist/types/core-viewers/webgl/viewer/environment/environment.d.ts +0 -6
  11. package/dist/types/core-viewers/webgl/viewer/rendering/renderScene.d.ts +8 -4
  12. package/dist/types/core-viewers/webgl/viewer/rendering/renderer.d.ts +5 -9
  13. package/dist/types/core-viewers/webgl/viewer/selection.d.ts +1 -0
  14. package/dist/types/core-viewers/webgl/viewer/settings/viewerSettings.d.ts +4 -39
  15. package/dist/types/react-viewers/helpers/inputs.d.ts +1 -2
  16. package/dist/types/react-viewers/helpers/isolation.d.ts +91 -50
  17. package/dist/types/react-viewers/settings/settings.d.ts +3 -2
  18. package/dist/vim-web.iife.js +342 -560
  19. package/dist/vim-web.iife.js.map +1 -1
  20. package/dist/vim-web.js +348 -566
  21. package/dist/vim-web.js.map +1 -1
  22. package/package.json +1 -1
  23. package/dist/types/core-viewers/webgl/images.d.ts +0 -4
  24. package/dist/types/core-viewers/webgl/loader/materials/isolationMaterial.d.ts +0 -12
  25. 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;
@@ -47662,7 +47663,6 @@ void main() {
47662
47663
  vertexColors: true,
47663
47664
  flatShading: true,
47664
47665
  side: DoubleSide
47665
- //shininess: 20
47666
47666
  });
47667
47667
  }
47668
47668
  function createBasicTransparent() {
@@ -47928,107 +47928,69 @@ void main() {
47928
47928
  `
47929
47929
  });
47930
47930
  }
47931
- function createIsolationMaterial() {
47931
+ function createGhostMaterial() {
47932
47932
  return new ShaderMaterial({
47933
+ userData: {
47934
+ isGhost: true
47935
+ },
47933
47936
  uniforms: {
47934
- opacity: { value: 0.1 },
47937
+ // Uniform controlling the overall transparency of the non-visible objects.
47938
+ opacity: { value: 1e-3 },
47939
+ // Uniform specifying the fill color for non-visible objects.
47935
47940
  fillColor: { value: new Vector3$1(0, 0, 0) }
47936
47941
  },
47942
+ // Render only the front side of faces to prevent drawing internal geometry.
47943
+ side: FrontSide,
47944
+ // Enable support for vertex colors.
47937
47945
  vertexColors: true,
47946
+ // Enable transparency for the material.
47938
47947
  transparent: true,
47948
+ // Enable clipping planes for geometry slicing.
47939
47949
  clipping: true,
47950
+ // Prevent writing to the depth buffer for proper blending of transparent objects.
47951
+ depthWrite: false,
47952
+ // Perform depth testing to ensure correct rendering order.
47953
+ depthTest: true,
47940
47954
  vertexShader: (
47941
47955
  /* glsl */
47942
47956
  `
47943
-
47944
- #include <common>
47945
- #include <logdepthbuf_pars_vertex>
47946
47957
  #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
47958
 
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
-
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
47959
+ // Attribute to determine if an object or vertex should be visible.
47960
+ // Used as an instance attribute for instanced meshes or a vertex attribute for merged meshes.
47961
+ attribute float ignore;
47972
47962
 
47973
47963
  void main() {
47964
+ // Standard transformations to calculate vertex position.
47974
47965
  #include <begin_vertex>
47975
47966
  #include <project_vertex>
47976
47967
  #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
47968
 
47992
-
47993
- // ORDERING
47994
- if(vIgnore > 0.0f){
47995
- gl_Position.z = 1.0f;
47996
- }else{
47997
- gl_Position.z = -1.0f;
47969
+ // Hide objects or vertices where the 'ignore' attribute is set to 0.
47970
+ if (ignore == 0.0) {
47971
+ // Push the vertex far out of view, effectively hiding it.
47972
+ gl_Position = vec4(1e20, 1e20, 1e20, 1.0);
47998
47973
  }
47999
-
48000
- // LIGHTING
48001
- vPosition = vec3(mvPosition ) / mvPosition .w;
48002
47974
  }
48003
- `
47975
+ `
48004
47976
  ),
48005
47977
  fragmentShader: (
48006
47978
  /* glsl */
48007
47979
  `
48008
47980
  #include <clipping_planes_pars_fragment>
48009
- varying float vIgnore;
47981
+
47982
+ // Uniform controlling the transparency level of the material.
48010
47983
  uniform float opacity;
47984
+ // Uniform specifying the fill color for non-visible objects.
48011
47985
  uniform vec3 fillColor;
48012
- varying vec3 vPosition;
48013
- varying vec3 vColor;
48014
47986
 
48015
47987
  void main() {
47988
+ // Handle clipping planes to discard fragments outside the defined planes.
48016
47989
  #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
- }
47990
+ // Set the fragment color to the specified fill color and opacity.
47991
+ gl_FragColor = vec4(fillColor, opacity);
48030
47992
  }
48031
- `
47993
+ `
48032
47994
  )
48033
47995
  });
48034
47996
  }
@@ -48316,42 +48278,40 @@ void main() {
48316
48278
  }
48317
48279
  function createSimpleMaterial() {
48318
48280
  return new ShaderMaterial({
48319
- uniforms: {
48320
- opacity: { value: 0.1 },
48321
- fillColor: { value: new Vector3$1(0, 0, 0) }
48322
- },
48281
+ side: DoubleSide,
48282
+ // No uniforms are needed for this shader.
48283
+ uniforms: {},
48284
+ // Enable vertex colors for both instanced and merged meshes.
48323
48285
  vertexColors: true,
48324
- // transparent: true,
48286
+ // Enable support for clipping planes.
48325
48287
  clipping: true,
48326
48288
  vertexShader: (
48327
48289
  /* glsl */
48328
48290
  `
48329
-
48330
48291
  #include <common>
48331
48292
  #include <logdepthbuf_pars_vertex>
48332
48293
  #include <clipping_planes_pars_vertex>
48333
-
48294
+
48334
48295
  // VISIBILITY
48335
- // Instance or vertex attribute to hide objects
48336
- // Used as instance attribute for instanced mesh and as vertex attribute for merged meshes.
48296
+ // Determines if an object or vertex should be visible.
48297
+ // Used as an instance attribute for instanced meshes or as a vertex attribute for merged meshes.
48337
48298
  attribute float ignore;
48338
48299
 
48339
- // Passed to fragment to discard them
48340
- varying float vIgnore;
48300
+ // LIGHTING
48301
+ // Passes the vertex position to the fragment shader for lighting calculations.
48341
48302
  varying vec3 vPosition;
48342
48303
 
48343
-
48344
48304
  // COLORING
48305
+ // Passes the color of the vertex or instance to the fragment shader.
48345
48306
  varying vec3 vColor;
48346
48307
 
48347
- // attribute for color override
48348
- // merged meshes use it as vertex attribute
48349
- // instanced meshes use it as an instance attribute
48308
+ // Determines whether to use instance color (1.0) or vertex color (0.0).
48309
+ // For merged meshes, this is used as a vertex attribute.
48310
+ // For instanced meshes, this is used as an instance attribute.
48350
48311
  attribute float colored;
48351
48312
 
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
48313
+ // Fix for a known issue where setting mesh.instanceColor does not properly enable USE_INSTANCING_COLOR.
48314
+ // This ensures that instance colors are always used when required.
48355
48315
  #ifndef USE_INSTANCING_COLOR
48356
48316
  attribute vec3 instanceColor;
48357
48317
  #endif
@@ -48362,49 +48322,59 @@ void main() {
48362
48322
  #include <clipping_planes_vertex>
48363
48323
  #include <logdepthbuf_vertex>
48364
48324
 
48365
- // VISIBILITY
48366
- // Set frag ignore from instance or vertex attribute
48367
- vIgnore = ignore;
48325
+ // If ignore is greater than 0, hide the object by moving it far out of view.
48326
+ if (ignore > 0.0) {
48327
+ gl_Position = vec4(1e20, 1e20, 1e20, 1.0);
48328
+ return;
48329
+ }
48368
48330
 
48369
48331
  // COLORING
48332
+ // Default to the vertex color.
48370
48333
  vColor = color.xyz;
48371
48334
 
48372
- // colored == 1 -> instance color
48373
- // colored == 0 -> vertex color
48335
+ // Blend instance and vertex colors based on the colored attribute.
48336
+ // colored == 1.0 -> use instance color.
48337
+ // colored == 0.0 -> use vertex color.
48374
48338
  #ifdef USE_INSTANCING
48375
- vColor.xyz = colored * instanceColor.xyz + (1.0f - colored) * color.xyz;
48339
+ vColor.xyz = colored * instanceColor.xyz + (1.0 - colored) * color.xyz;
48376
48340
  #endif
48377
48341
 
48378
- gl_Position.z = -10.0f;
48379
-
48380
48342
  // LIGHTING
48381
- vPosition = vec3(mvPosition ) / mvPosition .w;
48343
+ // Pass the model-view position to the fragment shader for lighting calculations.
48344
+ vPosition = vec3(mvPosition) / mvPosition.w;
48382
48345
  }
48383
48346
  `
48384
48347
  ),
48385
48348
  fragmentShader: (
48386
48349
  /* glsl */
48387
48350
  `
48351
+ #include <common>
48352
+ #include <logdepthbuf_pars_fragment>
48388
48353
  #include <clipping_planes_pars_fragment>
48389
- varying float vIgnore;
48354
+
48355
+
48356
+ // Position and color data passed from the vertex shader.
48390
48357
  varying vec3 vPosition;
48391
48358
  varying vec3 vColor;
48392
48359
 
48393
48360
  void main() {
48394
48361
  #include <clipping_planes_fragment>
48362
+ #include <logdepthbuf_fragment>
48395
48363
 
48396
- if (vIgnore > 0.0f){
48397
- discard;
48398
- }
48399
- else{
48400
- gl_FragColor = vec4(vColor.x, vColor.y, vColor.z, 1.0f);
48364
+ // Set the fragment color to the interpolated vertex or instance color.
48365
+ gl_FragColor = vec4(vColor, 1.0);
48401
48366
 
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
- }
48367
+ // LIGHTING
48368
+ // Compute a pseudo-normal using screen-space derivatives of the vertex position.
48369
+ vec3 normal = normalize(cross(dFdx(vPosition), dFdy(vPosition)));
48370
+
48371
+ // Apply simple directional lighting.
48372
+ // Normalize the light direction for consistent shading.
48373
+ float light = dot(normal, normalize(vec3(1.4142, 1.732, 2.236)));
48374
+ light = 0.5 + (light * 0.5); // Adjust light intensity to range [0.5, 1.0].
48375
+
48376
+ // Modulate the fragment color by the lighting intensity.
48377
+ gl_FragColor.xyz *= light;
48408
48378
  }
48409
48379
  `
48410
48380
  )
@@ -48503,7 +48473,7 @@ void main() {
48503
48473
  }
48504
48474
  }
48505
48475
  const _ViewerMaterials = class _ViewerMaterials {
48506
- constructor(opaque, transparent, simple, wireframe, isolation, mask, outline, merge, skyBox) {
48476
+ constructor(opaque, transparent, simple, wireframe, ghost2, mask, outline, merge, skyBox) {
48507
48477
  /**
48508
48478
  * Material used for opaque model geometry.
48509
48479
  */
@@ -48523,7 +48493,7 @@ void main() {
48523
48493
  /**
48524
48494
  * Material used to show traces of hidden objects.
48525
48495
  */
48526
- __publicField(this, "isolation");
48496
+ __publicField(this, "ghost");
48527
48497
  /**
48528
48498
  * Material used to filter out what is not selected for selection outline effect.
48529
48499
  */
@@ -48551,7 +48521,7 @@ void main() {
48551
48521
  this.transparent = transparent ?? createTransparent();
48552
48522
  this.simple = simple ?? createSimpleMaterial();
48553
48523
  this.wireframe = wireframe ?? createWireframe();
48554
- this.isolation = isolation ?? createIsolationMaterial();
48524
+ this.ghost = ghost2 ?? createGhostMaterial();
48555
48525
  this.mask = mask ?? createMaskMaterial();
48556
48526
  this.outline = outline ?? new OutlineMaterial();
48557
48527
  this.merge = merge ?? new MergeMaterial();
@@ -48573,8 +48543,8 @@ void main() {
48573
48543
  applySettings(settings2) {
48574
48544
  this.opaque.color = settings2.materials.standard.color;
48575
48545
  this.transparent.color = settings2.materials.standard.color;
48576
- this.isolationOpacity = settings2.materials.isolation.opacity;
48577
- this.isolationColor = settings2.materials.isolation.color;
48546
+ this.ghostOpacity = settings2.materials.ghost.opacity;
48547
+ this.ghostColor = settings2.materials.ghost.color;
48578
48548
  this.wireframeColor = settings2.materials.highlight.color;
48579
48549
  this.wireframeOpacity = settings2.materials.highlight.opacity;
48580
48550
  this.sectionStrokeWitdh = settings2.materials.section.strokeWidth;
@@ -48603,26 +48573,27 @@ void main() {
48603
48573
  this._onUpdate.dispatch();
48604
48574
  }
48605
48575
  /**
48606
- * Determines the opacity of the isolation material.
48576
+ * Determines the opacity of the ghost material.
48607
48577
  */
48608
- get isolationOpacity() {
48609
- return this.isolation.opacity;
48578
+ get ghostOpacity() {
48579
+ const mat = this.ghost;
48580
+ return mat.uniforms.opacity.value;
48610
48581
  }
48611
- set isolationOpacity(opacity) {
48612
- const mat = this.isolation;
48582
+ set ghostOpacity(opacity) {
48583
+ const mat = this.ghost;
48613
48584
  mat.uniforms.opacity.value = opacity;
48614
48585
  mat.uniformsNeedUpdate = true;
48615
48586
  this._onUpdate.dispatch();
48616
48587
  }
48617
48588
  /**
48618
- * Determines the color of the isolation material.
48589
+ * Determines the color of the ghost material.
48619
48590
  */
48620
- get isolationColor() {
48621
- const mat = this.isolation;
48591
+ get ghostColor() {
48592
+ const mat = this.ghost;
48622
48593
  return mat.uniforms.fillColor.value;
48623
48594
  }
48624
- set isolationColor(color) {
48625
- const mat = this.isolation;
48595
+ set ghostColor(color) {
48596
+ const mat = this.ghost;
48626
48597
  mat.uniforms.fillColor.value = color;
48627
48598
  mat.uniformsNeedUpdate = true;
48628
48599
  this._onUpdate.dispatch();
@@ -48683,10 +48654,11 @@ void main() {
48683
48654
  }
48684
48655
  set clippingPlanes(value) {
48685
48656
  this._clippingPlanes = value;
48657
+ this.simple.clippingPlanes = value ?? null;
48686
48658
  this.opaque.clippingPlanes = value ?? null;
48687
48659
  this.transparent.clippingPlanes = value ?? null;
48688
48660
  this.wireframe.clippingPlanes = value ?? null;
48689
- this.isolation.clippingPlanes = value ?? null;
48661
+ this.ghost.clippingPlanes = value ?? null;
48690
48662
  this.mask.clippingPlanes = value ?? null;
48691
48663
  this._onUpdate.dispatch();
48692
48664
  }
@@ -48806,7 +48778,7 @@ void main() {
48806
48778
  this.opaque.dispose();
48807
48779
  this.transparent.dispose();
48808
48780
  this.wireframe.dispose();
48809
- this.isolation.dispose();
48781
+ this.ghost.dispose();
48810
48782
  this.mask.dispose();
48811
48783
  this.outline.dispose();
48812
48784
  }
@@ -48918,16 +48890,12 @@ void main() {
48918
48890
  setMaterial(value) {
48919
48891
  if (this._material === value) return;
48920
48892
  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
- }
48893
+ this.mesh.material = value ?? this._material;
48894
+ this.mesh.geometry.clearGroups();
48895
+ if (value instanceof Array) {
48896
+ value.forEach((m, i2) => {
48897
+ this.mesh.geometry.addGroup(0, Infinity, i2);
48898
+ });
48931
48899
  }
48932
48900
  }
48933
48901
  }
@@ -48985,13 +48953,17 @@ void main() {
48985
48953
  // State
48986
48954
  __publicField(this, "ignoreSceneMaterial");
48987
48955
  __publicField(this, "_material");
48956
+ __publicField(this, "size", 0);
48957
+ var _a2;
48988
48958
  this.g3dMesh = g3d2;
48989
48959
  this.mesh = mesh;
48990
48960
  this.mesh.userData.vim = this;
48991
48961
  this.bimInstances = g3d2 instanceof distExports$2.G3dMesh ? instances.map((i2) => g3d2.scene.instanceNodes[i2]) : instances;
48992
48962
  this.meshInstances = instances;
48993
48963
  this.boxes = g3d2 instanceof distExports$2.G3dMesh ? this.importBoundingBoxes() : this.computeBoundingBoxes();
48964
+ this.size = ((_a2 = this.boxes[0]) == null ? void 0 : _a2.getSize(new Vector3$1()).length()) ?? 0;
48994
48965
  this.boundingBox = this.computeBoundingBox(this.boxes);
48966
+ this._material = this.mesh.material;
48995
48967
  }
48996
48968
  get merged() {
48997
48969
  return false;
@@ -49015,16 +48987,12 @@ void main() {
49015
48987
  setMaterial(value) {
49016
48988
  if (this._material === value) return;
49017
48989
  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
- }
48990
+ this.mesh.material = value ?? this._material;
48991
+ this.mesh.geometry.clearGroups();
48992
+ if (value instanceof Array) {
48993
+ value.forEach((m, i2) => {
48994
+ this.mesh.geometry.addGroup(0, Infinity, i2);
48995
+ });
49028
48996
  }
49029
48997
  }
49030
48998
  computeBoundingBoxes() {
@@ -49963,7 +49931,7 @@ void main() {
49963
49931
  }
49964
49932
  return vim;
49965
49933
  }
49966
- let DeferredPromise$2 = class DeferredPromise extends Promise {
49934
+ let DeferredPromise$1 = class DeferredPromise extends Promise {
49967
49935
  constructor(executor = () => {
49968
49936
  }) {
49969
49937
  var _a2;
@@ -50026,8 +49994,8 @@ void main() {
50026
49994
  __publicField(this, "_error");
50027
49995
  // Promises to await progress updates and completion
50028
49996
  __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());
49997
+ __publicField(this, "_progressPromise", new DeferredPromise$1());
49998
+ __publicField(this, "_completionPromise", new DeferredPromise$1());
50031
49999
  this._source = source;
50032
50000
  this._settings = settings2;
50033
50001
  this.startRequest();
@@ -50041,7 +50009,7 @@ void main() {
50041
50009
  const vim = await open(this._bfast, this._settings, (progress) => {
50042
50010
  this._progress = progress;
50043
50011
  this._progressPromise.resolve(progress);
50044
- this._progressPromise = new DeferredPromise$2();
50012
+ this._progressPromise = new DeferredPromise$1();
50045
50013
  });
50046
50014
  this._vimResult = vim;
50047
50015
  } catch (err) {
@@ -50096,9 +50064,6 @@ void main() {
50096
50064
  }
50097
50065
  return true;
50098
50066
  }
50099
- const floor$1 = `
50100
- data:image/png;base64,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
50101
- `;
50102
50067
  class AxesSettings {
50103
50068
  constructor(init) {
50104
50069
  __publicField(this, "size", 84);
@@ -50174,14 +50139,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
50174
50139
  // less white
50175
50140
  sharpness: 2
50176
50141
  },
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
50142
  skylight: {
50186
50143
  skyColor: new Color(16777215),
50187
50144
  groundColor: new Color(16777215),
@@ -50209,9 +50166,9 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
50209
50166
  color: new Color(7000831),
50210
50167
  opacity: 0.5
50211
50168
  },
50212
- isolation: {
50169
+ ghost: {
50213
50170
  color: new Color(5132892),
50214
- opacity: 0.08
50171
+ opacity: 0.01
50215
50172
  },
50216
50173
  section: {
50217
50174
  strokeWidth: 0.01,
@@ -52399,6 +52356,9 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52399
52356
  });
52400
52357
  this._onValueChanged.dispatch();
52401
52358
  }
52359
+ any() {
52360
+ return this._objects.size > 0;
52361
+ }
52402
52362
  /**
52403
52363
  * Returns true if the given object is currently selected.
52404
52364
  * @param {IObject} object The object to check for selection.
@@ -52508,92 +52468,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52508
52468
  this._materials.focusIntensity = focus / 2;
52509
52469
  }
52510
52470
  }
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
52471
  class Skybox {
52598
52472
  constructor(camera2, renderer, materials, settings2) {
52599
52473
  __publicField(this, "mesh");
@@ -52738,28 +52612,22 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52738
52612
  * The array of directional lights in the scene.
52739
52613
  */
52740
52614
  __publicField(this, "sunLights");
52741
- /**
52742
- * The ground plane under the model in the scene.
52743
- */
52744
- __publicField(this, "groundPlane");
52745
52615
  /*
52746
52616
  * The skybox in the scene.
52747
52617
  */
52748
52618
  __publicField(this, "skybox");
52749
52619
  this._camera = camera2;
52750
52620
  this._renderer = renderer;
52751
- this.groundPlane = new GroundPlane(settings2);
52752
52621
  this.skyLight = this.createSkyLight(settings2);
52753
52622
  this.skybox = new Skybox(camera2, renderer, viewerMaterials, settings2);
52754
52623
  this.sunLights = this.createSunLights(settings2);
52755
- this.setupRendererListeners();
52756
52624
  this.addObjectsToRenderer();
52757
52625
  }
52758
52626
  /**
52759
52627
  * Returns all three objects composing the environment
52760
52628
  */
52761
52629
  getObjects() {
52762
- return [this.groundPlane.mesh, this.skyLight, ...this.sunLights.map((l) => l.light), this.skybox.mesh];
52630
+ return [this.skyLight, ...this.sunLights.map((l) => l.light), this.skybox.mesh];
52763
52631
  }
52764
52632
  createSkyLight(settings2) {
52765
52633
  const { skyColor, groundColor, intensity } = settings2.skylight;
@@ -52773,12 +52641,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52773
52641
  addObjectsToRenderer() {
52774
52642
  this.getObjects().forEach((o) => this._renderer.add(o));
52775
52643
  }
52776
- setupRendererListeners() {
52777
- this._renderer.onBoxUpdated.subscribe(() => {
52778
- const box = this._renderer.getBoundingBox();
52779
- this.groundPlane.adaptToContent(box);
52780
- });
52781
- }
52782
52644
  /**
52783
52645
  * Dispose of all resources.
52784
52646
  */
@@ -52786,7 +52648,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52786
52648
  this.getObjects().forEach((o) => this._renderer.remove(o));
52787
52649
  this.sunLights.forEach((s) => s.dispose());
52788
52650
  this.skyLight.dispose();
52789
- this.groundPlane.dispose();
52790
52651
  this.skybox.dispose();
52791
52652
  }
52792
52653
  }
@@ -52919,14 +52780,16 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52919
52780
  __publicField(this, "scene");
52920
52781
  // state
52921
52782
  __publicField(this, "boxUpdated", false);
52783
+ // public value
52784
+ __publicField(this, "smallGhostThreshold", 10);
52922
52785
  __publicField(this, "_vimScenes", []);
52923
52786
  __publicField(this, "_boundingBox");
52924
52787
  __publicField(this, "_memory", 0);
52925
52788
  __publicField(this, "_2dCount", 0);
52926
- __publicField(this, "_material");
52789
+ __publicField(this, "_modelMaterial");
52927
52790
  this.scene = new Scene$1();
52928
52791
  }
52929
- get models() {
52792
+ get meshes() {
52930
52793
  return this._vimScenes.flatMap((s) => s.meshes);
52931
52794
  }
52932
52795
  get estimatedMemory() {
@@ -53022,16 +52885,31 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
53022
52885
  this._boundingBox = void 0;
53023
52886
  this._memory = 0;
53024
52887
  }
53025
- get material() {
53026
- return this._material;
52888
+ get modelMaterial() {
52889
+ return this._modelMaterial;
53027
52890
  }
53028
- set material(material) {
53029
- this._material = material;
52891
+ set modelMaterial(material) {
52892
+ this._modelMaterial = material;
53030
52893
  this._vimScenes.forEach((s) => {
53031
- s.meshes.forEach((m) => {
53032
- m.mesh.material = material;
53033
- });
52894
+ s.material = material;
53034
52895
  });
52896
+ this.updateInstanceMeshVisibility();
52897
+ }
52898
+ updateInstanceMeshVisibility() {
52899
+ var _a2, _b2;
52900
+ const hide = ((_b2 = (_a2 = this._modelMaterial) == null ? void 0 : _a2[1]) == null ? void 0 : _b2.userData.isGhost) === true;
52901
+ for (const mesh of this.meshes) {
52902
+ if (mesh instanceof InstancedMesh) {
52903
+ if (this.smallGhostThreshold <= 0) {
52904
+ mesh.mesh.visible = true;
52905
+ continue;
52906
+ }
52907
+ const visible2 = mesh.getSubmeshes().some(
52908
+ (m) => m.object.visible
52909
+ );
52910
+ mesh.mesh.visible = !(hide && !visible2 && mesh.size < this.smallGhostThreshold);
52911
+ }
52912
+ }
53035
52913
  }
53036
52914
  addScene(scene) {
53037
52915
  this._vimScenes.push(scene);
@@ -55637,7 +55515,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
55637
55515
  this.minZ.constant = -box.min.z;
55638
55516
  this.box.copy(box);
55639
55517
  this._renderer.needsUpdate = true;
55640
- this._renderer.skipAntialias = true;
55641
55518
  }
55642
55519
  /**
55643
55520
  * Determines whether objecets outside the section box will be culled or not.
@@ -56596,7 +56473,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56596
56473
  __publicField(this, "_composer");
56597
56474
  __publicField(this, "_materials");
56598
56475
  __publicField(this, "_renderText");
56599
- __publicField(this, "_skipAntialias");
56600
56476
  __publicField(this, "_needsUpdate");
56601
56477
  __publicField(this, "_onSceneUpdate", new distExports$1.SignalDispatcher());
56602
56478
  __publicField(this, "_onBoxUpdated", new distExports$1.SignalDispatcher());
@@ -56658,17 +56534,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56658
56534
  set needsUpdate(value) {
56659
56535
  this._needsUpdate = this._needsUpdate || value;
56660
56536
  }
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
56537
  /**
56673
56538
  * Removes all objects from rendering and disposes the WebGL context.
56674
56539
  */
@@ -56689,6 +56554,12 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56689
56554
  this._scene.scene.background = color;
56690
56555
  this.needsUpdate = true;
56691
56556
  }
56557
+ get modelMaterial() {
56558
+ return this._scene.modelMaterial;
56559
+ }
56560
+ set modelMaterial(material) {
56561
+ this._scene.modelMaterial = material;
56562
+ }
56692
56563
  /**
56693
56564
  * Signal dispatched at the end of each frame if the scene was updated, such as visibility changes.
56694
56565
  */
@@ -56713,6 +56584,12 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56713
56584
  this._renderText = value;
56714
56585
  this.textRenderer.domElement.style.display = value ? "block" : "none";
56715
56586
  }
56587
+ get smallGhostThreshold() {
56588
+ return this._scene.smallGhostThreshold;
56589
+ }
56590
+ set smallGhostThreshold(value) {
56591
+ this._scene.smallGhostThreshold = value;
56592
+ }
56716
56593
  /**
56717
56594
  * Returns the bounding box encompassing all rendered objects.
56718
56595
  * @param target - Box in which to copy the result. A new instance is created if undefined.
@@ -56752,7 +56629,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56752
56629
  this._composer.render();
56753
56630
  }
56754
56631
  this._needsUpdate = false;
56755
- this.skipAntialias = false;
56756
56632
  if (this.textEnabled && this._scene.has2dObjects()) {
56757
56633
  this.textRenderer.render(this._scene.scene, this._camera.three);
56758
56634
  }
@@ -57018,14 +56894,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
57018
56894
  groundColor: get2("skybox.groundColor", strToColor),
57019
56895
  sharpness: get2("skybox.sharpness", Number.parseFloat)
57020
56896
  },
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
56897
  skylight: {
57030
56898
  skyColor: get2("skylight.skyColor", strToColor),
57031
56899
  groundColor: get2("skylight.groundColor", strToColor),
@@ -57053,9 +56921,9 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
57053
56921
  color: get2("materials.highlight.color", strToColor),
57054
56922
  opacity: get2("materials.highlight.opacity", Number.parseFloat)
57055
56923
  },
57056
- isolation: {
57057
- color: get2("materials.isolation.color", strToColor),
57058
- opacity: get2("materials.isolation.opacity", Number.parseFloat)
56924
+ ghost: {
56925
+ color: get2("materials.ghost.color", strToColor),
56926
+ opacity: get2("materials.ghost.opacity", Number.parseFloat)
57059
56927
  },
57060
56928
  section: {
57061
56929
  strokeWidth: get2("materials.section.strokeWidth", Number.parseFloat),
@@ -59735,7 +59603,6 @@ Averrage Date/Second ${avgDataRatePS} kb
59735
59603
  __publicField(this, "_rpcCallId", 0);
59736
59604
  __publicField(this, "_reconnectTimeout");
59737
59605
  __publicField(this, "_connectionTimeout");
59738
- __publicField(this, "_retries", -1);
59739
59606
  __publicField(this, "_validateConnection");
59740
59607
  /**
59741
59608
  * Callback function to handle incoming video frames.
@@ -59746,7 +59613,7 @@ Averrage Date/Second ${avgDataRatePS} kb
59746
59613
  __publicField(this, "_state", { status: "disconnected" });
59747
59614
  __publicField(this, "_onStatusUpdate", new distExports.SimpleEventDispatcher());
59748
59615
  __publicField(this, "_connectPromise", new ResolvedPromise(void 0));
59749
- __publicField(this, "_connectingUrl");
59616
+ __publicField(this, "_connectionSettings");
59750
59617
  this._logger = logger;
59751
59618
  this._rpcCallId = 0;
59752
59619
  this._streamLogger = new StreamLogger(logger);
@@ -59779,7 +59646,8 @@ Averrage Date/Second ${avgDataRatePS} kb
59779
59646
  * @returns The WebSocket URL as a string, or undefined if not set.
59780
59647
  */
59781
59648
  get url() {
59782
- return this._connectingUrl;
59649
+ var _a2;
59650
+ return (_a2 = this._connectionSettings) == null ? void 0 : _a2.url;
59783
59651
  }
59784
59652
  /**
59785
59653
  * Connects to a WebSocket server at the specified URL.
@@ -59789,7 +59657,9 @@ Averrage Date/Second ${avgDataRatePS} kb
59789
59657
  connect(settings2) {
59790
59658
  settings2 = {
59791
59659
  url: (settings2 == null ? void 0 : settings2.url) ?? DEFAULT_LOCAL_ULTRA_SERVER_URL,
59792
- retries: (settings2 == null ? void 0 : settings2.retries) ?? 0
59660
+ retries: (settings2 == null ? void 0 : settings2.retries) ?? -1,
59661
+ timeout: (settings2 == null ? void 0 : settings2.timeout) ?? 5e3,
59662
+ retryDelay: (settings2 == null ? void 0 : settings2.retryDelay) ?? 5e3
59793
59663
  };
59794
59664
  const url = settings2.url;
59795
59665
  if (!isWebSocketUrl(url)) {
@@ -59801,17 +59671,18 @@ Averrage Date/Second ${avgDataRatePS} kb
59801
59671
  return this._connectPromise.promise;
59802
59672
  } else {
59803
59673
  this._clearSocket();
59674
+ this._connectionSettings = void 0;
59804
59675
  this._connectPromise.reject("Connection to a different server");
59805
- this._connectPromise = new ControllablePromise();
59806
59676
  }
59807
- } else if (this._connectingUrl !== url) {
59677
+ }
59678
+ if (this.url !== url) {
59808
59679
  this._connectPromise = new ControllablePromise();
59809
- this._connectingUrl = url;
59680
+ this._connectionSettings = settings2;
59810
59681
  }
59811
59682
  this.updateState({ status: "connecting" });
59812
59683
  try {
59813
59684
  this._socket = new WebSocket(url);
59814
- this._connectionTimeout = setTimeout(() => this._onClose(), 5e3);
59685
+ this._connectionTimeout = setTimeout(() => this._onClose(), settings2.timeout);
59815
59686
  this._socket.onopen = (e) => {
59816
59687
  this._onOpen(e);
59817
59688
  };
@@ -59834,15 +59705,15 @@ Averrage Date/Second ${avgDataRatePS} kb
59834
59705
  * Disconnects from the current WebSocket server.
59835
59706
  */
59836
59707
  disconnect(error) {
59837
- this._logger.log("Disconnecting from: ", this._connectingUrl);
59838
- this._connectingUrl = void 0;
59708
+ this._logger.log("Disconnecting from: ", this.url);
59709
+ this._connectionSettings = void 0;
59839
59710
  this._disconnect(error);
59840
59711
  }
59841
59712
  /**
59842
59713
  * Handles the disconnection logic, stopping logging and clearing the socket.
59843
59714
  */
59844
59715
  _disconnect(error) {
59845
- console.log("disconnect", error);
59716
+ this._logger.log("disconnect", error);
59846
59717
  clearTimeout(this._reconnectTimeout);
59847
59718
  clearTimeout(this._connectionTimeout);
59848
59719
  this._streamLogger.stopLogging();
@@ -59923,26 +59794,30 @@ Averrage Date/Second ${avgDataRatePS} kb
59923
59794
  this._logger.log("Connected to: ", (_a2 = this._socket) == null ? void 0 : _a2.url);
59924
59795
  this.updateState({ status: "connected" });
59925
59796
  this._streamLogger.startLoggging();
59926
- this._connectPromise.resolve();
59797
+ this._connectPromise.resolve(true);
59927
59798
  }
59928
59799
  /**
59929
59800
  * Handler for WebSocket 'close' event.
59930
59801
  * @param _event - The event object.
59931
59802
  */
59932
59803
  _onClose(_event) {
59933
- clearTimeout(this._connectionTimeout);
59934
- this._disconnect({ status: "error", error: "connection", serverUrl: this._connectingUrl });
59804
+ const connecting = this.state.status === "connecting" || this.state.status === "validating";
59935
59805
  this._logger.log("WebSocket closed.");
59936
- if (this._retries !== 0) {
59937
- this._logger.log("Attempting to reconnect in 5 seconds");
59938
- this._reconnectTimeout = setTimeout(() => {
59939
- this.updateState({ status: "connecting" });
59940
- this.connect({
59941
- url: this._connectingUrl,
59942
- retries: this._retries - 1
59943
- });
59944
- }, 5e3);
59806
+ clearTimeout(this._connectionTimeout);
59807
+ this._disconnect({ status: "error", error: "connection", serverUrl: this.url });
59808
+ if (connecting && this._connectionSettings.retries === 0) {
59809
+ this._logger.log("No more retries left");
59810
+ this._connectPromise.resolve(false);
59811
+ return;
59945
59812
  }
59813
+ this._logger.log("Attempting to reconnect in 5 seconds");
59814
+ this._reconnectTimeout = setTimeout(() => {
59815
+ this.updateState({ status: "connecting" });
59816
+ if (connecting) {
59817
+ this._connectionSettings.retries--;
59818
+ }
59819
+ this.connect(this._connectionSettings);
59820
+ }, this._connectionSettings.retryDelay);
59946
59821
  }
59947
59822
  /**
59948
59823
  * Sends binary data over the WebSocket connection.
@@ -60315,31 +60190,6 @@ Averrage Date/Second ${avgDataRatePS} kb
60315
60190
  this._pendingFrame = frame;
60316
60191
  }
60317
60192
  }
60318
- let DeferredPromise$1 = class DeferredPromise extends Promise {
60319
- constructor(executor = () => {
60320
- }) {
60321
- var _a2;
60322
- let resolver;
60323
- let rejector;
60324
- super((resolve, reject) => {
60325
- resolver = resolve;
60326
- rejector = reject;
60327
- return executor(resolve, reject);
60328
- });
60329
- __publicField(this, "resolve");
60330
- __publicField(this, "reject");
60331
- __publicField(this, "initialCallStack");
60332
- this.resolve = resolver;
60333
- this.reject = rejector;
60334
- this.initialCallStack = (_a2 = Error().stack) == null ? void 0 : _a2.split("\n").slice(2).join("\n");
60335
- }
60336
- /** @throws error with amended call stack */
60337
- rejectWithError(error) {
60338
- var _a2;
60339
- error.stack = [(_a2 = error.stack) == null ? void 0 : _a2.split("\n")[0], this.initialCallStack].join("\n");
60340
- this.reject(error);
60341
- }
60342
- };
60343
60193
  class LoadSuccess {
60344
60194
  constructor(vim) {
60345
60195
  __publicField(this, "isError", false);
@@ -60362,8 +60212,8 @@ Averrage Date/Second ${avgDataRatePS} kb
60362
60212
  let LoadRequest$1 = class LoadRequest {
60363
60213
  constructor() {
60364
60214
  __publicField(this, "_progress", 0);
60365
- __publicField(this, "_progressPromise", new DeferredPromise$1());
60366
- __publicField(this, "_completionPromise", new DeferredPromise$1());
60215
+ __publicField(this, "_progressPromise", new ControllablePromise());
60216
+ __publicField(this, "_completionPromise", new ControllablePromise());
60367
60217
  __publicField(this, "_result");
60368
60218
  }
60369
60219
  get isCompleted() {
@@ -60376,18 +60226,18 @@ Averrage Date/Second ${avgDataRatePS} kb
60376
60226
  return;
60377
60227
  }
60378
60228
  while (this._result === void 0) {
60379
- await this._progressPromise;
60229
+ await this._progressPromise.promise;
60380
60230
  yield this._progress;
60381
60231
  }
60382
60232
  }
60383
60233
  async getResult() {
60384
- await this._completionPromise;
60234
+ await this._completionPromise.promise;
60385
60235
  return this._result;
60386
60236
  }
60387
60237
  onProgress(progress) {
60388
60238
  this._progress = progress;
60389
60239
  this._progressPromise.resolve();
60390
- this._progressPromise = new DeferredPromise$1();
60240
+ this._progressPromise = new ControllablePromise();
60391
60241
  }
60392
60242
  success(vim) {
60393
60243
  this._result = new LoadSuccess(vim);
@@ -61768,7 +61618,7 @@ Averrage Date/Second ${avgDataRatePS} kb
61768
61618
  * @returns A promise that resolves when the connection is established.
61769
61619
  */
61770
61620
  async connect(settings2) {
61771
- await this._socketClient.connect(settings2);
61621
+ return this._socketClient.connect(settings2);
61772
61622
  }
61773
61623
  /**
61774
61624
  * Disconnects from the current VIM Ultra server.
@@ -67026,12 +66876,13 @@ Averrage Date/Second ${avgDataRatePS} kb
67026
66876
  return isTrue(settings2.ui.projectInspector) || isTrue(settings2.ui.settings) || isTrue(settings2.ui.help) || isTrue(settings2.ui.maximise);
67027
66877
  }
67028
66878
  const defaultSettings = {
67029
- peformance: {
67030
- useFastMaterial: false
66879
+ materials: {
66880
+ useFastMaterial: false,
66881
+ useGhostMaterial: true,
66882
+ smallGhostThreshold: 10
67031
66883
  },
67032
66884
  isolation: {
67033
- enable: true,
67034
- useIsolationMaterial: true
66885
+ enable: true
67035
66886
  },
67036
66887
  capacity: {
67037
66888
  canFollowUrl: true,
@@ -67111,7 +66962,7 @@ Averrage Date/Second ${avgDataRatePS} kb
67111
66962
  }, []);
67112
66963
  const onIsolationBtn = () => {
67113
66964
  props.settings.update(
67114
- (s) => s.isolation.useIsolationMaterial = !s.isolation.useIsolationMaterial
66965
+ (s) => s.materials.useGhostMaterial = !s.materials.useGhostMaterial
67115
66966
  );
67116
66967
  };
67117
66968
  const onHomeBtn = () => {
@@ -67121,11 +66972,11 @@ Averrage Date/Second ${avgDataRatePS} kb
67121
66972
  const btnIsolation = /* @__PURE__ */ jsxRuntimeExports.jsx(
67122
66973
  "button",
67123
66974
  {
67124
- "data-tip": props.settings.value.isolation.useIsolationMaterial ? "Disable Ghosting" : "Enable Ghosting",
66975
+ "data-tip": props.settings.value.materials.useGhostMaterial ? "Disable Ghosting" : "Enable Ghosting",
67125
66976
  onClick: onIsolationBtn,
67126
66977
  className: "vim-isolation-btn " + btnStyle2,
67127
66978
  type: "button",
67128
- 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" })
66979
+ 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" })
67129
66980
  }
67130
66981
  );
67131
66982
  const btnHome = /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -67655,7 +67506,7 @@ Averrage Date/Second ${avgDataRatePS} kb
67655
67506
  id: elementIds.buttonToggleIsolation,
67656
67507
  enabled: () => isTrue(props.settings.ui.toggleIsolation),
67657
67508
  tip: "Toggle Isolation",
67658
- action: () => props.isolation.toggleIsolation("controlBar"),
67509
+ action: () => props.isolation.toggle("controlBar"),
67659
67510
  icon: toggleIsolation,
67660
67511
  style: buttonDefaultStyle
67661
67512
  }
@@ -71676,7 +71527,7 @@ Averrage Date/Second ${avgDataRatePS} kb
71676
71527
  };
71677
71528
  const [clipping, setClipping] = React2.useState(isClipping());
71678
71529
  const [, setVersion] = React2.useState(0);
71679
- const hidden2 = props.isolation.any();
71530
+ const hidden2 = props.isolation.isActive();
71680
71531
  React2.useEffect(() => {
71681
71532
  const subState = viewer.gizmos.section.onStateChanged.subscribe(() => {
71682
71533
  setSection({
@@ -74059,31 +73910,17 @@ Averrage Date/Second ${avgDataRatePS} kb
74059
73910
  ),
74060
73911
  settingsSubtitle("Materials"),
74061
73912
  settingsToggle(
74062
- "Use Isolation Material",
74063
- (settings2) => settings2.isolation.useIsolationMaterial,
73913
+ "Use Ghost Material",
73914
+ (settings2) => settings2.materials.useGhostMaterial,
74064
73915
  (settings2, value) => {
74065
- settings2.isolation.useIsolationMaterial = value;
74066
- if (settings2.peformance.useFastMaterial && value) {
74067
- settings2.peformance.useFastMaterial = false;
74068
- }
73916
+ settings2.materials.useGhostMaterial = value;
74069
73917
  }
74070
73918
  ),
74071
73919
  settingsToggle(
74072
73920
  "Use Performance Material",
74073
- (settings2) => settings2.peformance.useFastMaterial,
73921
+ (settings2) => settings2.materials.useFastMaterial,
74074
73922
  (settings2, value) => {
74075
- settings2.peformance.useFastMaterial = value;
74076
- if (settings2.isolation.useIsolationMaterial && value) {
74077
- settings2.isolation.useIsolationMaterial = false;
74078
- }
74079
- }
74080
- ),
74081
- settingsSubtitle("Scene"),
74082
- settingsToggle(
74083
- "Show Ground Plane",
74084
- (_) => props.viewer.environment.groundPlane.visible,
74085
- (_, value) => {
74086
- props.viewer.environment.groundPlane.visible = value;
73923
+ settings2.materials.useFastMaterial = value;
74087
73924
  }
74088
73925
  ),
74089
73926
  settingsSubtitle("Panels"),
@@ -74357,7 +74194,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74357
74194
  __publicField(this, "_default");
74358
74195
  __publicField(this, "_isolation");
74359
74196
  __publicField(this, "_sideState");
74360
- __publicField(this, "_help");
74361
74197
  __publicField(this, "_getSelection", () => {
74362
74198
  return [...this._viewer.selection.objects].filter(
74363
74199
  (o) => o.type === "Object3D"
@@ -74387,7 +74223,7 @@ Averrage Date/Second ${avgDataRatePS} kb
74387
74223
  return true;
74388
74224
  }
74389
74225
  case KEYS.KEY_I: {
74390
- this._isolation.toggleIsolation("keyboard");
74226
+ this._isolation.toggle("keyboard");
74391
74227
  return true;
74392
74228
  }
74393
74229
  case KEYS.KEY_ESCAPE: {
@@ -74395,7 +74231,7 @@ Averrage Date/Second ${avgDataRatePS} kb
74395
74231
  this._viewer.selection.clear();
74396
74232
  return true;
74397
74233
  }
74398
- if (this._isolation.any()) {
74234
+ if (this._isolation.isActive()) {
74399
74235
  this._isolation.clear("keyboard");
74400
74236
  return true;
74401
74237
  }
@@ -74477,7 +74313,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74477
74313
  var _a2;
74478
74314
  const next = { ...settings2 };
74479
74315
  updater(next);
74480
- validateSettings(next);
74481
74316
  saveSettingsToLocal(next);
74482
74317
  setSettings(next);
74483
74318
  (_a2 = onUpdate.current) == null ? void 0 : _a2.call(onUpdate, next);
@@ -74497,11 +74332,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74497
74332
  [settings2]
74498
74333
  );
74499
74334
  }
74500
- function validateSettings(settings2) {
74501
- if (settings2.peformance.useFastMaterial && settings2.isolation.useIsolationMaterial) {
74502
- settings2.peformance.useFastMaterial = false;
74503
- }
74504
- }
74505
74335
  function applySettings(viewer, settings2) {
74506
74336
  const performance2 = document.getElementsByClassName("vim-performance-div")[0];
74507
74337
  if (performance2) {
@@ -74511,240 +74341,192 @@ Averrage Date/Second ${avgDataRatePS} kb
74511
74341
  performance2.classList.add("vc-hidden");
74512
74342
  }
74513
74343
  }
74514
- viewer.vims.forEach((v) => {
74515
- if (settings2.peformance.useFastMaterial && v.scene.material === void 0) {
74516
- v.scene.material = viewer.materials.simple;
74517
- }
74518
- if (!settings2.peformance.useFastMaterial && v.scene.material === viewer.materials.simple) {
74519
- v.scene.material = void 0;
74520
- }
74521
- });
74344
+ viewer.renderer.smallGhostThreshold = settings2.materials.smallGhostThreshold;
74522
74345
  }
74523
74346
  class Isolation {
74347
+ /**
74348
+ * Constructs an IsolationManager.
74349
+ *
74350
+ * @param viewer - The VIM Viewer responsible for managing the 3D scene and objects.
74351
+ * @param camera - A component that handles camera control and framing.
74352
+ * @param settings - The settings that control isolation and material usage.
74353
+ */
74524
74354
  constructor(viewer, camera2, settings2) {
74525
74355
  __publicField(this, "_viewer");
74526
74356
  __publicField(this, "_settings");
74527
- __publicField(this, "_isolation");
74528
- __publicField(this, "_lastIsolation");
74357
+ __publicField(this, "_isolation", []);
74529
74358
  __publicField(this, "_camera");
74530
- __publicField(this, "_references", /* @__PURE__ */ new Map());
74531
74359
  __publicField(this, "_onChanged", new distExports.SimpleEventDispatcher());
74532
74360
  this._viewer = viewer;
74533
74361
  this._camera = camera2;
74534
74362
  this.applySettings(settings2);
74535
74363
  }
74536
- /** Signal dispatched when the isolation set changes. */
74364
+ /**
74365
+ * An event that is dispatched whenever the isolation set changes.
74366
+ *
74367
+ * @remarks
74368
+ * This can be used by other parts of the application to react to isolation
74369
+ * updates (for example, updating UI or triggering additional viewport actions).
74370
+ *
74371
+ * @returns {ISimpleEvent<string>} Event interface for subscribing to isolation changes.
74372
+ */
74537
74373
  get onChanged() {
74538
74374
  return this._onChanged.asEvent();
74539
74375
  }
74540
74376
  /**
74541
- * Applies relevant settings to isolation.
74542
- * @param settings The settings to be applied to isolation.
74377
+ * Applies relevant settings to the isolation behavior.
74378
+ *
74379
+ * @param settings - The new settings to apply.
74380
+ *
74381
+ * @remarks
74382
+ * This updates the internal reference to settings and immediately sets
74383
+ * the material based on whether isolation is currently active.
74543
74384
  */
74544
74385
  applySettings(settings2) {
74545
- var _a2;
74546
74386
  this._settings = settings2;
74547
74387
  if (!this._settings.isolation.enable) return;
74548
- const set2 = new Set((_a2 = this._isolation) == null ? void 0 : _a2.map((o) => o.vim));
74549
- this._viewer.vims.forEach((v) => {
74550
- v.scene.material = this.getMaterial(this._settings, set2.has(v));
74551
- });
74552
- }
74553
- /**
74554
- * Sets the reference objects for a given VIM.
74555
- * @param vim The VIM for which reference objects are being set.
74556
- * @param reference An array of reference objects or the string 'always' to indicate permanent reference.
74557
- */
74558
- setReference(vim, reference) {
74559
- const value = reference === "always" ? reference : new Set(reference);
74560
- this._references.set(vim, value);
74561
- }
74562
- /**
74563
- * Retrieves the reference objects set for a given VIM.
74564
- * @param vim The VIM for which reference objects are being retrieved.
74565
- * @returns The reference objects set for the specified VIM.
74566
- */
74567
- getReference(vim) {
74568
- return this._references.get(vim);
74569
- }
74570
- /**
74571
- * Clears all reference objects set for VIMs.
74572
- */
74573
- clearReferences() {
74574
- this._references.clear();
74388
+ this._viewer.renderer.modelMaterial = this.getMaterial(this._settings, this.isActive());
74575
74389
  }
74576
74390
  /**
74577
- * Returns true if there are currently objects isolated.
74578
- * @returns True if there are currently objects isolated; otherwise, false.
74391
+ * Checks if isolation is currently active (i.e., any objects are isolated).
74392
+ *
74393
+ * @returns True if isolation is active; otherwise, false.
74579
74394
  */
74580
- any() {
74581
- return this._isolation !== void 0;
74395
+ isActive() {
74396
+ return this._isolation.length > 0;
74582
74397
  }
74583
74398
  /**
74584
- * Returns the current array of isolated objects.
74585
- * @returns The array of objects currently isolated, or undefined if no objects are isolated.
74399
+ * Retrieves the current array of isolated objects.
74400
+ *
74401
+ * @returns An array of isolated objects, or undefined if isolation is not active.
74586
74402
  */
74587
74403
  current() {
74588
74404
  return this._isolation;
74589
74405
  }
74590
74406
  /**
74591
- * Isolates the objects in the given array and shows the rest as ghost.
74592
- * @param objects An array of objects to isolate.
74593
- * @param source The source of isolation.
74594
- * @returns True if isolation occurs; otherwise, false.
74407
+ * Sets the specified objects as isolated, hiding or ghosting the rest.
74408
+ *
74409
+ * @param objects - The objects to isolate.
74410
+ * @param source - A label or identifier indicating the source of this action (e.g., "user").
74595
74411
  */
74596
74412
  isolate(objects, source) {
74597
74413
  if (!this._settings.isolation.enable) return;
74598
- if (this._isolation) {
74599
- this._lastIsolation = this._isolation;
74600
- }
74601
- const isolated = this._isolate(this._viewer, this._settings, objects);
74602
- this._isolation = isolated ? objects : void 0;
74414
+ this._isolation = objects ?? [];
74415
+ this._apply(source);
74603
74416
  this._camera.frameVisibleObjects();
74604
- this._onChanged.dispatch(source);
74605
- return isolated;
74606
74417
  }
74607
74418
  /**
74608
- * Toggles current isolation based on selection.
74609
- * @param source The source of isolation.
74419
+ * Toggles isolation by using the current selection.
74420
+ *
74421
+ * @param source - A label or identifier for the isolation action.
74422
+ *
74423
+ * @remarks
74424
+ * This method replaces the current isolation set with whatever objects are
74425
+ * currently selected. If selection is empty, it effectively clears isolation.
74610
74426
  */
74611
- toggleIsolation(source) {
74427
+ toggle(source) {
74612
74428
  if (!this._settings.isolation.enable) return;
74613
- const selection = [...this._viewer.selection.objects].filter((o) => o.type === "Object3D");
74614
- if (this._isolation) {
74615
- this._lastIsolation = this._isolation;
74616
- }
74617
- if (this._isolation) {
74618
- if (selection.length === 0 || ArrayEquals(this._isolation, selection)) {
74619
- this._showAll();
74620
- this._isolation = void 0;
74621
- } else {
74622
- const isolated = this._isolate(this._viewer, this._settings, selection);
74623
- this._isolation = isolated ? selection : void 0;
74624
- this._camera.frameVisibleObjects();
74625
- this._viewer.selection.clear();
74626
- }
74627
- } else {
74628
- if (selection.length > 0) {
74629
- const isolated = this._isolate(this._viewer, this._settings, selection);
74630
- this._isolation = isolated ? selection : void 0;
74631
- this._camera.frameVisibleObjects();
74632
- this._viewer.selection.clear();
74633
- } else if (this._lastIsolation) {
74634
- const isolated = this._isolate(
74635
- this._viewer,
74636
- this._settings,
74637
- this._lastIsolation
74638
- );
74639
- this._isolation = isolated ? [...this._lastIsolation] : void 0;
74640
- }
74641
- }
74642
- this._onChanged.dispatch(source);
74429
+ this._isolation = [...this._viewer.selection.objects].filter((o) => o.type === "Object3D");
74430
+ this._apply(source);
74431
+ this._camera.frameVisibleObjects();
74432
+ this._viewer.selection.clear();
74643
74433
  }
74644
74434
  /**
74645
- * Removes the given objects from the isolation set.
74646
- * @param objects An array of objects to be removed from isolation.
74647
- * @param source The source of the removal operation.
74435
+ * Hides the specified objects from the isolation set.
74436
+ *
74437
+ * @param objects - The objects to hide.
74438
+ * @param source - A label or identifier for the isolation action.
74439
+ *
74440
+ * @remarks
74441
+ * If there is no active isolation set (i.e., all objects are visible),
74442
+ * the method first treats all objects in the scene as isolated,
74443
+ * and then removes the specified objects. This ensures the specified
74444
+ * objects become hidden.
74648
74445
  */
74649
74446
  hide(objects, source) {
74650
74447
  if (!this._settings.isolation.enable) return;
74651
- const selection = new Set(objects);
74652
- const initial = this._isolation ?? this._viewer.vims[0].getObjects();
74653
- const result = [];
74654
- for (const obj of initial) {
74655
- if (!selection.has(obj)) result.push(obj);
74656
- }
74657
- const isolated = this._isolate(this._viewer, this._settings, result);
74658
- this._isolation = isolated ? result : void 0;
74659
- this._onChanged.dispatch(source);
74448
+ this._isolation = this._isolation.length === 0 ? this.getAllObjects() : this._isolation;
74449
+ this._isolation = this._isolation.filter((o) => !objects.includes(o));
74450
+ this._apply(source);
74660
74451
  objects.forEach((o) => this._viewer.selection.remove(o));
74661
74452
  }
74662
74453
  /**
74663
- * Adds the given objects to the isolation set.
74664
- * @param objects An array of objects to be added to isolation.
74665
- * @param source The source of the addition operation.
74454
+ * Adds the specified objects to the current isolation set (making them visible).
74455
+ *
74456
+ * @param objects - The objects to show.
74457
+ * @param source - A label or identifier for the isolation action.
74666
74458
  */
74667
74459
  show(objects, source) {
74668
74460
  if (!this._settings.isolation.enable) return;
74669
- const isolation = this._isolation ?? [];
74670
- objects.forEach((o) => isolation.push(o));
74671
- const result = [...new Set(isolation)];
74672
- const isolated = this._isolate(this._viewer, this._settings, result);
74673
- this._isolation = isolated ? result : void 0;
74674
- this._onChanged.dispatch(source);
74461
+ objects.forEach((o) => this._isolation.push(o));
74462
+ this._apply(source);
74675
74463
  }
74676
74464
  /**
74677
- * Clears the current isolation.
74678
- * @param source The source of the isolation clearing operation.
74465
+ * Clears the current isolation set, making all objects visible.
74466
+ *
74467
+ * @param source - A label or identifier for the isolation action.
74679
74468
  */
74680
74469
  clear(source) {
74681
74470
  if (!this._settings.isolation.enable) return;
74682
- this._showAll();
74683
- this._lastIsolation = this._isolation;
74684
- this._isolation = void 0;
74685
- this._onChanged.dispatch(source);
74471
+ this._isolation.length = 0;
74472
+ this._apply(source);
74686
74473
  }
74687
74474
  /**
74688
- * Show all objects and quit isolation mode.
74475
+ * Constructs the correct material (or array of materials) based on the given settings.
74476
+ *
74477
+ * @param settings - The current component settings, including isolation rules.
74478
+ * @param isolate - Whether or not isolation is active.
74479
+ * @returns The material(s) to assign to the renderer, or undefined if default materials should be used.
74480
+ *
74481
+ * @remarks
74482
+ * - If isolation is active and `useGhostMaterial` is true, an array containing
74483
+ * the simple and ghost materials is returned.
74484
+ * - If fast materials are enabled, the simple material is returned.
74485
+ * - Otherwise, defaults to undefined, allowing the system to pick a standard material.
74689
74486
  */
74690
- _showAll() {
74691
- this._viewer.vims.forEach((v) => {
74692
- for (const obj of v.getObjects()) {
74693
- obj.visible = true;
74694
- }
74695
- v.scene.material = this.getMaterial(this._settings, false);
74696
- });
74697
- }
74698
74487
  getMaterial(settings2, isolate) {
74699
- if (settings2.peformance.useFastMaterial) {
74700
- return this._viewer.materials.simple;
74701
- }
74702
- if (!settings2.isolation.useIsolationMaterial) {
74703
- return void 0;
74488
+ if (isolate && settings2.materials.useGhostMaterial) {
74489
+ return [this._viewer.materials.simple, this._viewer.materials.ghost];
74704
74490
  }
74705
- if (!isolate) {
74706
- return void 0;
74491
+ if (settings2.materials.useFastMaterial) {
74492
+ return this._viewer.materials.simple;
74707
74493
  }
74708
- return this._viewer.materials.isolation;
74494
+ return void 0;
74709
74495
  }
74710
- _isolate(viewer, settings2, objects) {
74711
- let useIsolation = false;
74712
- if (!objects) {
74713
- this._showAll();
74714
- } else {
74715
- const set2 = new Set(objects);
74716
- let all = true;
74717
- viewer.vims.forEach((vim) => {
74718
- for (const obj of vim.getObjects()) {
74719
- if (obj.hasMesh) {
74720
- obj.visible = set2.has(obj);
74721
- all = all && obj.visible;
74722
- }
74723
- }
74724
- const reference = this._references.get(vim);
74725
- if (reference === void 0) {
74726
- useIsolation = !all;
74727
- } else if (reference === "always") {
74728
- useIsolation = true;
74729
- } else {
74730
- useIsolation = !setsEqual(reference, set2);
74496
+ /**
74497
+ * Applies the current isolation state: sets visibility for objects, updates materials,
74498
+ * and dispatches the changed event.
74499
+ *
74500
+ * @param source - A label or identifier for the isolation action.
74501
+ */
74502
+ _apply(source) {
74503
+ let all = true;
74504
+ let any = false;
74505
+ const set2 = this._isolation.length > 0 ? new Set(this._isolation) : void 0;
74506
+ this._viewer.vims.forEach((vim) => {
74507
+ for (const obj of vim.getObjects()) {
74508
+ if (obj.hasMesh) {
74509
+ obj.visible = (set2 == null ? void 0 : set2.has(obj)) ?? true;
74510
+ all = all && obj.visible;
74511
+ any = any || obj.visible;
74731
74512
  }
74732
- vim.scene.material = this.getMaterial(this._settings, useIsolation);
74733
- });
74734
- }
74735
- return useIsolation;
74736
- }
74737
- }
74738
- function setsEqual(set1, set2) {
74739
- if (set1.size !== set2.size) {
74740
- return false;
74513
+ }
74514
+ });
74515
+ this._viewer.renderer.modelMaterial = this.getMaterial(this._settings, any && !all);
74516
+ this._onChanged.dispatch(source);
74741
74517
  }
74742
- for (const item of set1) {
74743
- if (!set2.has(item)) {
74744
- return false;
74745
- }
74518
+ /**
74519
+ * Gathers all objects from all loaded VIM instances.
74520
+ *
74521
+ * @returns An array of all objects within the loaded VIM scenes.
74522
+ */
74523
+ getAllObjects() {
74524
+ let objects = [];
74525
+ this._viewer.vims.forEach((vim) => {
74526
+ objects = objects.concat(vim.getObjects());
74527
+ });
74528
+ return objects;
74746
74529
  }
74747
- return true;
74748
74530
  }
74749
74531
  class ComponentCamera {
74750
74532
  constructor(viewer) {