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

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 +343 -560
  19. package/dist/vim-web.iife.js.map +1 -1
  20. package/dist/vim-web.js +349 -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() {
@@ -52973,6 +52836,7 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
52973
52836
  add(target) {
52974
52837
  if (target instanceof Scene) {
52975
52838
  this.addScene(target);
52839
+ target.material = this._modelMaterial;
52976
52840
  return;
52977
52841
  }
52978
52842
  this._2dCount += this.count2dObjects(target);
@@ -53022,16 +52886,31 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
53022
52886
  this._boundingBox = void 0;
53023
52887
  this._memory = 0;
53024
52888
  }
53025
- get material() {
53026
- return this._material;
52889
+ get modelMaterial() {
52890
+ return this._modelMaterial;
53027
52891
  }
53028
- set material(material) {
53029
- this._material = material;
52892
+ set modelMaterial(material) {
52893
+ this._modelMaterial = material;
53030
52894
  this._vimScenes.forEach((s) => {
53031
- s.meshes.forEach((m) => {
53032
- m.mesh.material = material;
53033
- });
52895
+ s.material = material;
53034
52896
  });
52897
+ this.updateInstanceMeshVisibility();
52898
+ }
52899
+ updateInstanceMeshVisibility() {
52900
+ var _a2, _b2;
52901
+ const hide = ((_b2 = (_a2 = this._modelMaterial) == null ? void 0 : _a2[1]) == null ? void 0 : _b2.userData.isGhost) === true;
52902
+ for (const mesh of this.meshes) {
52903
+ if (mesh instanceof InstancedMesh) {
52904
+ if (this.smallGhostThreshold <= 0) {
52905
+ mesh.mesh.visible = true;
52906
+ continue;
52907
+ }
52908
+ const visible2 = mesh.getSubmeshes().some(
52909
+ (m) => m.object.visible
52910
+ );
52911
+ mesh.mesh.visible = !(hide && !visible2 && mesh.size < this.smallGhostThreshold);
52912
+ }
52913
+ }
53035
52914
  }
53036
52915
  addScene(scene) {
53037
52916
  this._vimScenes.push(scene);
@@ -55637,7 +55516,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
55637
55516
  this.minZ.constant = -box.min.z;
55638
55517
  this.box.copy(box);
55639
55518
  this._renderer.needsUpdate = true;
55640
- this._renderer.skipAntialias = true;
55641
55519
  }
55642
55520
  /**
55643
55521
  * Determines whether objecets outside the section box will be culled or not.
@@ -56596,7 +56474,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56596
56474
  __publicField(this, "_composer");
56597
56475
  __publicField(this, "_materials");
56598
56476
  __publicField(this, "_renderText");
56599
- __publicField(this, "_skipAntialias");
56600
56477
  __publicField(this, "_needsUpdate");
56601
56478
  __publicField(this, "_onSceneUpdate", new distExports$1.SignalDispatcher());
56602
56479
  __publicField(this, "_onBoxUpdated", new distExports$1.SignalDispatcher());
@@ -56658,17 +56535,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56658
56535
  set needsUpdate(value) {
56659
56536
  this._needsUpdate = this._needsUpdate || value;
56660
56537
  }
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
56538
  /**
56673
56539
  * Removes all objects from rendering and disposes the WebGL context.
56674
56540
  */
@@ -56689,6 +56555,12 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56689
56555
  this._scene.scene.background = color;
56690
56556
  this.needsUpdate = true;
56691
56557
  }
56558
+ get modelMaterial() {
56559
+ return this._scene.modelMaterial;
56560
+ }
56561
+ set modelMaterial(material) {
56562
+ this._scene.modelMaterial = material;
56563
+ }
56692
56564
  /**
56693
56565
  * Signal dispatched at the end of each frame if the scene was updated, such as visibility changes.
56694
56566
  */
@@ -56713,6 +56585,12 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56713
56585
  this._renderText = value;
56714
56586
  this.textRenderer.domElement.style.display = value ? "block" : "none";
56715
56587
  }
56588
+ get smallGhostThreshold() {
56589
+ return this._scene.smallGhostThreshold;
56590
+ }
56591
+ set smallGhostThreshold(value) {
56592
+ this._scene.smallGhostThreshold = value;
56593
+ }
56716
56594
  /**
56717
56595
  * Returns the bounding box encompassing all rendered objects.
56718
56596
  * @param target - Box in which to copy the result. A new instance is created if undefined.
@@ -56752,7 +56630,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
56752
56630
  this._composer.render();
56753
56631
  }
56754
56632
  this._needsUpdate = false;
56755
- this.skipAntialias = false;
56756
56633
  if (this.textEnabled && this._scene.has2dObjects()) {
56757
56634
  this.textRenderer.render(this._scene.scene, this._camera.three);
56758
56635
  }
@@ -57018,14 +56895,6 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
57018
56895
  groundColor: get2("skybox.groundColor", strToColor),
57019
56896
  sharpness: get2("skybox.sharpness", Number.parseFloat)
57020
56897
  },
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
56898
  skylight: {
57030
56899
  skyColor: get2("skylight.skyColor", strToColor),
57031
56900
  groundColor: get2("skylight.groundColor", strToColor),
@@ -57053,9 +56922,9 @@ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAYAAACAvzbMAAAAAXNSR0IArs
57053
56922
  color: get2("materials.highlight.color", strToColor),
57054
56923
  opacity: get2("materials.highlight.opacity", Number.parseFloat)
57055
56924
  },
57056
- isolation: {
57057
- color: get2("materials.isolation.color", strToColor),
57058
- opacity: get2("materials.isolation.opacity", Number.parseFloat)
56925
+ ghost: {
56926
+ color: get2("materials.ghost.color", strToColor),
56927
+ opacity: get2("materials.ghost.opacity", Number.parseFloat)
57059
56928
  },
57060
56929
  section: {
57061
56930
  strokeWidth: get2("materials.section.strokeWidth", Number.parseFloat),
@@ -59735,7 +59604,6 @@ Averrage Date/Second ${avgDataRatePS} kb
59735
59604
  __publicField(this, "_rpcCallId", 0);
59736
59605
  __publicField(this, "_reconnectTimeout");
59737
59606
  __publicField(this, "_connectionTimeout");
59738
- __publicField(this, "_retries", -1);
59739
59607
  __publicField(this, "_validateConnection");
59740
59608
  /**
59741
59609
  * Callback function to handle incoming video frames.
@@ -59746,7 +59614,7 @@ Averrage Date/Second ${avgDataRatePS} kb
59746
59614
  __publicField(this, "_state", { status: "disconnected" });
59747
59615
  __publicField(this, "_onStatusUpdate", new distExports.SimpleEventDispatcher());
59748
59616
  __publicField(this, "_connectPromise", new ResolvedPromise(void 0));
59749
- __publicField(this, "_connectingUrl");
59617
+ __publicField(this, "_connectionSettings");
59750
59618
  this._logger = logger;
59751
59619
  this._rpcCallId = 0;
59752
59620
  this._streamLogger = new StreamLogger(logger);
@@ -59779,7 +59647,8 @@ Averrage Date/Second ${avgDataRatePS} kb
59779
59647
  * @returns The WebSocket URL as a string, or undefined if not set.
59780
59648
  */
59781
59649
  get url() {
59782
- return this._connectingUrl;
59650
+ var _a2;
59651
+ return (_a2 = this._connectionSettings) == null ? void 0 : _a2.url;
59783
59652
  }
59784
59653
  /**
59785
59654
  * Connects to a WebSocket server at the specified URL.
@@ -59789,7 +59658,9 @@ Averrage Date/Second ${avgDataRatePS} kb
59789
59658
  connect(settings2) {
59790
59659
  settings2 = {
59791
59660
  url: (settings2 == null ? void 0 : settings2.url) ?? DEFAULT_LOCAL_ULTRA_SERVER_URL,
59792
- retries: (settings2 == null ? void 0 : settings2.retries) ?? 0
59661
+ retries: (settings2 == null ? void 0 : settings2.retries) ?? -1,
59662
+ timeout: (settings2 == null ? void 0 : settings2.timeout) ?? 5e3,
59663
+ retryDelay: (settings2 == null ? void 0 : settings2.retryDelay) ?? 5e3
59793
59664
  };
59794
59665
  const url = settings2.url;
59795
59666
  if (!isWebSocketUrl(url)) {
@@ -59801,17 +59672,18 @@ Averrage Date/Second ${avgDataRatePS} kb
59801
59672
  return this._connectPromise.promise;
59802
59673
  } else {
59803
59674
  this._clearSocket();
59675
+ this._connectionSettings = void 0;
59804
59676
  this._connectPromise.reject("Connection to a different server");
59805
- this._connectPromise = new ControllablePromise();
59806
59677
  }
59807
- } else if (this._connectingUrl !== url) {
59678
+ }
59679
+ if (this.url !== url) {
59808
59680
  this._connectPromise = new ControllablePromise();
59809
- this._connectingUrl = url;
59681
+ this._connectionSettings = settings2;
59810
59682
  }
59811
59683
  this.updateState({ status: "connecting" });
59812
59684
  try {
59813
59685
  this._socket = new WebSocket(url);
59814
- this._connectionTimeout = setTimeout(() => this._onClose(), 5e3);
59686
+ this._connectionTimeout = setTimeout(() => this._onClose(), settings2.timeout);
59815
59687
  this._socket.onopen = (e) => {
59816
59688
  this._onOpen(e);
59817
59689
  };
@@ -59834,15 +59706,15 @@ Averrage Date/Second ${avgDataRatePS} kb
59834
59706
  * Disconnects from the current WebSocket server.
59835
59707
  */
59836
59708
  disconnect(error) {
59837
- this._logger.log("Disconnecting from: ", this._connectingUrl);
59838
- this._connectingUrl = void 0;
59709
+ this._logger.log("Disconnecting from: ", this.url);
59710
+ this._connectionSettings = void 0;
59839
59711
  this._disconnect(error);
59840
59712
  }
59841
59713
  /**
59842
59714
  * Handles the disconnection logic, stopping logging and clearing the socket.
59843
59715
  */
59844
59716
  _disconnect(error) {
59845
- console.log("disconnect", error);
59717
+ this._logger.log("disconnect", error);
59846
59718
  clearTimeout(this._reconnectTimeout);
59847
59719
  clearTimeout(this._connectionTimeout);
59848
59720
  this._streamLogger.stopLogging();
@@ -59923,26 +59795,30 @@ Averrage Date/Second ${avgDataRatePS} kb
59923
59795
  this._logger.log("Connected to: ", (_a2 = this._socket) == null ? void 0 : _a2.url);
59924
59796
  this.updateState({ status: "connected" });
59925
59797
  this._streamLogger.startLoggging();
59926
- this._connectPromise.resolve();
59798
+ this._connectPromise.resolve(true);
59927
59799
  }
59928
59800
  /**
59929
59801
  * Handler for WebSocket 'close' event.
59930
59802
  * @param _event - The event object.
59931
59803
  */
59932
59804
  _onClose(_event) {
59933
- clearTimeout(this._connectionTimeout);
59934
- this._disconnect({ status: "error", error: "connection", serverUrl: this._connectingUrl });
59805
+ const connecting = this.state.status === "connecting" || this.state.status === "validating";
59935
59806
  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);
59807
+ clearTimeout(this._connectionTimeout);
59808
+ this._disconnect({ status: "error", error: "connection", serverUrl: this.url });
59809
+ if (connecting && this._connectionSettings.retries === 0) {
59810
+ this._logger.log("No more retries left");
59811
+ this._connectPromise.resolve(false);
59812
+ return;
59945
59813
  }
59814
+ this._logger.log("Attempting to reconnect in 5 seconds");
59815
+ this._reconnectTimeout = setTimeout(() => {
59816
+ this.updateState({ status: "connecting" });
59817
+ if (connecting) {
59818
+ this._connectionSettings.retries--;
59819
+ }
59820
+ this.connect(this._connectionSettings);
59821
+ }, this._connectionSettings.retryDelay);
59946
59822
  }
59947
59823
  /**
59948
59824
  * Sends binary data over the WebSocket connection.
@@ -60315,31 +60191,6 @@ Averrage Date/Second ${avgDataRatePS} kb
60315
60191
  this._pendingFrame = frame;
60316
60192
  }
60317
60193
  }
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
60194
  class LoadSuccess {
60344
60195
  constructor(vim) {
60345
60196
  __publicField(this, "isError", false);
@@ -60362,8 +60213,8 @@ Averrage Date/Second ${avgDataRatePS} kb
60362
60213
  let LoadRequest$1 = class LoadRequest {
60363
60214
  constructor() {
60364
60215
  __publicField(this, "_progress", 0);
60365
- __publicField(this, "_progressPromise", new DeferredPromise$1());
60366
- __publicField(this, "_completionPromise", new DeferredPromise$1());
60216
+ __publicField(this, "_progressPromise", new ControllablePromise());
60217
+ __publicField(this, "_completionPromise", new ControllablePromise());
60367
60218
  __publicField(this, "_result");
60368
60219
  }
60369
60220
  get isCompleted() {
@@ -60376,18 +60227,18 @@ Averrage Date/Second ${avgDataRatePS} kb
60376
60227
  return;
60377
60228
  }
60378
60229
  while (this._result === void 0) {
60379
- await this._progressPromise;
60230
+ await this._progressPromise.promise;
60380
60231
  yield this._progress;
60381
60232
  }
60382
60233
  }
60383
60234
  async getResult() {
60384
- await this._completionPromise;
60235
+ await this._completionPromise.promise;
60385
60236
  return this._result;
60386
60237
  }
60387
60238
  onProgress(progress) {
60388
60239
  this._progress = progress;
60389
60240
  this._progressPromise.resolve();
60390
- this._progressPromise = new DeferredPromise$1();
60241
+ this._progressPromise = new ControllablePromise();
60391
60242
  }
60392
60243
  success(vim) {
60393
60244
  this._result = new LoadSuccess(vim);
@@ -61768,7 +61619,7 @@ Averrage Date/Second ${avgDataRatePS} kb
61768
61619
  * @returns A promise that resolves when the connection is established.
61769
61620
  */
61770
61621
  async connect(settings2) {
61771
- await this._socketClient.connect(settings2);
61622
+ return this._socketClient.connect(settings2);
61772
61623
  }
61773
61624
  /**
61774
61625
  * Disconnects from the current VIM Ultra server.
@@ -67026,12 +66877,13 @@ Averrage Date/Second ${avgDataRatePS} kb
67026
66877
  return isTrue(settings2.ui.projectInspector) || isTrue(settings2.ui.settings) || isTrue(settings2.ui.help) || isTrue(settings2.ui.maximise);
67027
66878
  }
67028
66879
  const defaultSettings = {
67029
- peformance: {
67030
- useFastMaterial: false
66880
+ materials: {
66881
+ useFastMaterial: false,
66882
+ useGhostMaterial: true,
66883
+ smallGhostThreshold: 10
67031
66884
  },
67032
66885
  isolation: {
67033
- enable: true,
67034
- useIsolationMaterial: true
66886
+ enable: true
67035
66887
  },
67036
66888
  capacity: {
67037
66889
  canFollowUrl: true,
@@ -67111,7 +66963,7 @@ Averrage Date/Second ${avgDataRatePS} kb
67111
66963
  }, []);
67112
66964
  const onIsolationBtn = () => {
67113
66965
  props.settings.update(
67114
- (s) => s.isolation.useIsolationMaterial = !s.isolation.useIsolationMaterial
66966
+ (s) => s.materials.useGhostMaterial = !s.materials.useGhostMaterial
67115
66967
  );
67116
66968
  };
67117
66969
  const onHomeBtn = () => {
@@ -67121,11 +66973,11 @@ Averrage Date/Second ${avgDataRatePS} kb
67121
66973
  const btnIsolation = /* @__PURE__ */ jsxRuntimeExports.jsx(
67122
66974
  "button",
67123
66975
  {
67124
- "data-tip": props.settings.value.isolation.useIsolationMaterial ? "Disable Ghosting" : "Enable Ghosting",
66976
+ "data-tip": props.settings.value.materials.useGhostMaterial ? "Disable Ghosting" : "Enable Ghosting",
67125
66977
  onClick: onIsolationBtn,
67126
66978
  className: "vim-isolation-btn " + btnStyle2,
67127
66979
  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" })
66980
+ 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
66981
  }
67130
66982
  );
67131
66983
  const btnHome = /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -67655,7 +67507,7 @@ Averrage Date/Second ${avgDataRatePS} kb
67655
67507
  id: elementIds.buttonToggleIsolation,
67656
67508
  enabled: () => isTrue(props.settings.ui.toggleIsolation),
67657
67509
  tip: "Toggle Isolation",
67658
- action: () => props.isolation.toggleIsolation("controlBar"),
67510
+ action: () => props.isolation.toggle("controlBar"),
67659
67511
  icon: toggleIsolation,
67660
67512
  style: buttonDefaultStyle
67661
67513
  }
@@ -71676,7 +71528,7 @@ Averrage Date/Second ${avgDataRatePS} kb
71676
71528
  };
71677
71529
  const [clipping, setClipping] = React2.useState(isClipping());
71678
71530
  const [, setVersion] = React2.useState(0);
71679
- const hidden2 = props.isolation.any();
71531
+ const hidden2 = props.isolation.isActive();
71680
71532
  React2.useEffect(() => {
71681
71533
  const subState = viewer.gizmos.section.onStateChanged.subscribe(() => {
71682
71534
  setSection({
@@ -74059,31 +73911,17 @@ Averrage Date/Second ${avgDataRatePS} kb
74059
73911
  ),
74060
73912
  settingsSubtitle("Materials"),
74061
73913
  settingsToggle(
74062
- "Use Isolation Material",
74063
- (settings2) => settings2.isolation.useIsolationMaterial,
73914
+ "Use Ghost Material",
73915
+ (settings2) => settings2.materials.useGhostMaterial,
74064
73916
  (settings2, value) => {
74065
- settings2.isolation.useIsolationMaterial = value;
74066
- if (settings2.peformance.useFastMaterial && value) {
74067
- settings2.peformance.useFastMaterial = false;
74068
- }
73917
+ settings2.materials.useGhostMaterial = value;
74069
73918
  }
74070
73919
  ),
74071
73920
  settingsToggle(
74072
73921
  "Use Performance Material",
74073
- (settings2) => settings2.peformance.useFastMaterial,
73922
+ (settings2) => settings2.materials.useFastMaterial,
74074
73923
  (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;
73924
+ settings2.materials.useFastMaterial = value;
74087
73925
  }
74088
73926
  ),
74089
73927
  settingsSubtitle("Panels"),
@@ -74357,7 +74195,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74357
74195
  __publicField(this, "_default");
74358
74196
  __publicField(this, "_isolation");
74359
74197
  __publicField(this, "_sideState");
74360
- __publicField(this, "_help");
74361
74198
  __publicField(this, "_getSelection", () => {
74362
74199
  return [...this._viewer.selection.objects].filter(
74363
74200
  (o) => o.type === "Object3D"
@@ -74387,7 +74224,7 @@ Averrage Date/Second ${avgDataRatePS} kb
74387
74224
  return true;
74388
74225
  }
74389
74226
  case KEYS.KEY_I: {
74390
- this._isolation.toggleIsolation("keyboard");
74227
+ this._isolation.toggle("keyboard");
74391
74228
  return true;
74392
74229
  }
74393
74230
  case KEYS.KEY_ESCAPE: {
@@ -74395,7 +74232,7 @@ Averrage Date/Second ${avgDataRatePS} kb
74395
74232
  this._viewer.selection.clear();
74396
74233
  return true;
74397
74234
  }
74398
- if (this._isolation.any()) {
74235
+ if (this._isolation.isActive()) {
74399
74236
  this._isolation.clear("keyboard");
74400
74237
  return true;
74401
74238
  }
@@ -74477,7 +74314,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74477
74314
  var _a2;
74478
74315
  const next = { ...settings2 };
74479
74316
  updater(next);
74480
- validateSettings(next);
74481
74317
  saveSettingsToLocal(next);
74482
74318
  setSettings(next);
74483
74319
  (_a2 = onUpdate.current) == null ? void 0 : _a2.call(onUpdate, next);
@@ -74497,11 +74333,6 @@ Averrage Date/Second ${avgDataRatePS} kb
74497
74333
  [settings2]
74498
74334
  );
74499
74335
  }
74500
- function validateSettings(settings2) {
74501
- if (settings2.peformance.useFastMaterial && settings2.isolation.useIsolationMaterial) {
74502
- settings2.peformance.useFastMaterial = false;
74503
- }
74504
- }
74505
74336
  function applySettings(viewer, settings2) {
74506
74337
  const performance2 = document.getElementsByClassName("vim-performance-div")[0];
74507
74338
  if (performance2) {
@@ -74511,240 +74342,192 @@ Averrage Date/Second ${avgDataRatePS} kb
74511
74342
  performance2.classList.add("vc-hidden");
74512
74343
  }
74513
74344
  }
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
- });
74345
+ viewer.renderer.smallGhostThreshold = settings2.materials.smallGhostThreshold;
74522
74346
  }
74523
74347
  class Isolation {
74348
+ /**
74349
+ * Constructs an IsolationManager.
74350
+ *
74351
+ * @param viewer - The VIM Viewer responsible for managing the 3D scene and objects.
74352
+ * @param camera - A component that handles camera control and framing.
74353
+ * @param settings - The settings that control isolation and material usage.
74354
+ */
74524
74355
  constructor(viewer, camera2, settings2) {
74525
74356
  __publicField(this, "_viewer");
74526
74357
  __publicField(this, "_settings");
74527
- __publicField(this, "_isolation");
74528
- __publicField(this, "_lastIsolation");
74358
+ __publicField(this, "_isolation", []);
74529
74359
  __publicField(this, "_camera");
74530
- __publicField(this, "_references", /* @__PURE__ */ new Map());
74531
74360
  __publicField(this, "_onChanged", new distExports.SimpleEventDispatcher());
74532
74361
  this._viewer = viewer;
74533
74362
  this._camera = camera2;
74534
74363
  this.applySettings(settings2);
74535
74364
  }
74536
- /** Signal dispatched when the isolation set changes. */
74365
+ /**
74366
+ * An event that is dispatched whenever the isolation set changes.
74367
+ *
74368
+ * @remarks
74369
+ * This can be used by other parts of the application to react to isolation
74370
+ * updates (for example, updating UI or triggering additional viewport actions).
74371
+ *
74372
+ * @returns {ISimpleEvent<string>} Event interface for subscribing to isolation changes.
74373
+ */
74537
74374
  get onChanged() {
74538
74375
  return this._onChanged.asEvent();
74539
74376
  }
74540
74377
  /**
74541
- * Applies relevant settings to isolation.
74542
- * @param settings The settings to be applied to isolation.
74378
+ * Applies relevant settings to the isolation behavior.
74379
+ *
74380
+ * @param settings - The new settings to apply.
74381
+ *
74382
+ * @remarks
74383
+ * This updates the internal reference to settings and immediately sets
74384
+ * the material based on whether isolation is currently active.
74543
74385
  */
74544
74386
  applySettings(settings2) {
74545
- var _a2;
74546
74387
  this._settings = settings2;
74547
74388
  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();
74389
+ this._viewer.renderer.modelMaterial = this.getMaterial(this._settings, this.isActive());
74575
74390
  }
74576
74391
  /**
74577
- * Returns true if there are currently objects isolated.
74578
- * @returns True if there are currently objects isolated; otherwise, false.
74392
+ * Checks if isolation is currently active (i.e., any objects are isolated).
74393
+ *
74394
+ * @returns True if isolation is active; otherwise, false.
74579
74395
  */
74580
- any() {
74581
- return this._isolation !== void 0;
74396
+ isActive() {
74397
+ return this._isolation.length > 0;
74582
74398
  }
74583
74399
  /**
74584
- * Returns the current array of isolated objects.
74585
- * @returns The array of objects currently isolated, or undefined if no objects are isolated.
74400
+ * Retrieves the current array of isolated objects.
74401
+ *
74402
+ * @returns An array of isolated objects, or undefined if isolation is not active.
74586
74403
  */
74587
74404
  current() {
74588
74405
  return this._isolation;
74589
74406
  }
74590
74407
  /**
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.
74408
+ * Sets the specified objects as isolated, hiding or ghosting the rest.
74409
+ *
74410
+ * @param objects - The objects to isolate.
74411
+ * @param source - A label or identifier indicating the source of this action (e.g., "user").
74595
74412
  */
74596
74413
  isolate(objects, source) {
74597
74414
  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;
74415
+ this._isolation = objects ?? [];
74416
+ this._apply(source);
74603
74417
  this._camera.frameVisibleObjects();
74604
- this._onChanged.dispatch(source);
74605
- return isolated;
74606
74418
  }
74607
74419
  /**
74608
- * Toggles current isolation based on selection.
74609
- * @param source The source of isolation.
74420
+ * Toggles isolation by using the current selection.
74421
+ *
74422
+ * @param source - A label or identifier for the isolation action.
74423
+ *
74424
+ * @remarks
74425
+ * This method replaces the current isolation set with whatever objects are
74426
+ * currently selected. If selection is empty, it effectively clears isolation.
74610
74427
  */
74611
- toggleIsolation(source) {
74428
+ toggle(source) {
74612
74429
  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);
74430
+ this._isolation = [...this._viewer.selection.objects].filter((o) => o.type === "Object3D");
74431
+ this._apply(source);
74432
+ this._camera.frameVisibleObjects();
74433
+ this._viewer.selection.clear();
74643
74434
  }
74644
74435
  /**
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.
74436
+ * Hides the specified objects from the isolation set.
74437
+ *
74438
+ * @param objects - The objects to hide.
74439
+ * @param source - A label or identifier for the isolation action.
74440
+ *
74441
+ * @remarks
74442
+ * If there is no active isolation set (i.e., all objects are visible),
74443
+ * the method first treats all objects in the scene as isolated,
74444
+ * and then removes the specified objects. This ensures the specified
74445
+ * objects become hidden.
74648
74446
  */
74649
74447
  hide(objects, source) {
74650
74448
  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);
74449
+ this._isolation = this._isolation.length === 0 ? this.getAllObjects() : this._isolation;
74450
+ this._isolation = this._isolation.filter((o) => !objects.includes(o));
74451
+ this._apply(source);
74660
74452
  objects.forEach((o) => this._viewer.selection.remove(o));
74661
74453
  }
74662
74454
  /**
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.
74455
+ * Adds the specified objects to the current isolation set (making them visible).
74456
+ *
74457
+ * @param objects - The objects to show.
74458
+ * @param source - A label or identifier for the isolation action.
74666
74459
  */
74667
74460
  show(objects, source) {
74668
74461
  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);
74462
+ objects.forEach((o) => this._isolation.push(o));
74463
+ this._apply(source);
74675
74464
  }
74676
74465
  /**
74677
- * Clears the current isolation.
74678
- * @param source The source of the isolation clearing operation.
74466
+ * Clears the current isolation set, making all objects visible.
74467
+ *
74468
+ * @param source - A label or identifier for the isolation action.
74679
74469
  */
74680
74470
  clear(source) {
74681
74471
  if (!this._settings.isolation.enable) return;
74682
- this._showAll();
74683
- this._lastIsolation = this._isolation;
74684
- this._isolation = void 0;
74685
- this._onChanged.dispatch(source);
74472
+ this._isolation.length = 0;
74473
+ this._apply(source);
74686
74474
  }
74687
74475
  /**
74688
- * Show all objects and quit isolation mode.
74476
+ * Constructs the correct material (or array of materials) based on the given settings.
74477
+ *
74478
+ * @param settings - The current component settings, including isolation rules.
74479
+ * @param isolate - Whether or not isolation is active.
74480
+ * @returns The material(s) to assign to the renderer, or undefined if default materials should be used.
74481
+ *
74482
+ * @remarks
74483
+ * - If isolation is active and `useGhostMaterial` is true, an array containing
74484
+ * the simple and ghost materials is returned.
74485
+ * - If fast materials are enabled, the simple material is returned.
74486
+ * - Otherwise, defaults to undefined, allowing the system to pick a standard material.
74689
74487
  */
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
74488
  getMaterial(settings2, isolate) {
74699
- if (settings2.peformance.useFastMaterial) {
74700
- return this._viewer.materials.simple;
74701
- }
74702
- if (!settings2.isolation.useIsolationMaterial) {
74703
- return void 0;
74489
+ if (isolate && settings2.materials.useGhostMaterial) {
74490
+ return [this._viewer.materials.simple, this._viewer.materials.ghost];
74704
74491
  }
74705
- if (!isolate) {
74706
- return void 0;
74492
+ if (settings2.materials.useFastMaterial) {
74493
+ return this._viewer.materials.simple;
74707
74494
  }
74708
- return this._viewer.materials.isolation;
74495
+ return void 0;
74709
74496
  }
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);
74497
+ /**
74498
+ * Applies the current isolation state: sets visibility for objects, updates materials,
74499
+ * and dispatches the changed event.
74500
+ *
74501
+ * @param source - A label or identifier for the isolation action.
74502
+ */
74503
+ _apply(source) {
74504
+ let all = true;
74505
+ let any = false;
74506
+ const set2 = this._isolation.length > 0 ? new Set(this._isolation) : void 0;
74507
+ this._viewer.vims.forEach((vim) => {
74508
+ for (const obj of vim.getObjects()) {
74509
+ if (obj.hasMesh) {
74510
+ obj.visible = (set2 == null ? void 0 : set2.has(obj)) ?? true;
74511
+ all = all && obj.visible;
74512
+ any = any || obj.visible;
74731
74513
  }
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;
74514
+ }
74515
+ });
74516
+ this._viewer.renderer.modelMaterial = this.getMaterial(this._settings, any && !all);
74517
+ this._onChanged.dispatch(source);
74741
74518
  }
74742
- for (const item of set1) {
74743
- if (!set2.has(item)) {
74744
- return false;
74745
- }
74519
+ /**
74520
+ * Gathers all objects from all loaded VIM instances.
74521
+ *
74522
+ * @returns An array of all objects within the loaded VIM scenes.
74523
+ */
74524
+ getAllObjects() {
74525
+ let objects = [];
74526
+ this._viewer.vims.forEach((vim) => {
74527
+ objects = objects.concat(vim.getObjects());
74528
+ });
74529
+ return objects;
74746
74530
  }
74747
- return true;
74748
74531
  }
74749
74532
  class ComponentCamera {
74750
74533
  constructor(viewer) {