@xeokit/xeokit-sdk 2.6.52 → 2.6.54

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.
@@ -21944,6 +21944,30 @@ class Input extends Component {
21944
21944
  */
21945
21945
  this.KEY_SPACE = 32;
21946
21946
 
21947
+ /**
21948
+ * Code for the left mouse button.
21949
+ * @property MOUSE_LEFT_BUTTON
21950
+ * @final
21951
+ * @type {Number}
21952
+ */
21953
+ this.MOUSE_LEFT_BUTTON = 260;
21954
+
21955
+ /**
21956
+ * Code for the middle mouse button.
21957
+ * @property MOUSE_MIDDLE_BUTTON
21958
+ * @final
21959
+ * @type {Number}
21960
+ */
21961
+ this.MOUSE_MIDDLE_BUTTON = 261;
21962
+
21963
+ /**
21964
+ * Code for the right mouse button.
21965
+ * @property MOUSE_RIGHT_BUTTON
21966
+ * @final
21967
+ * @type {Number}
21968
+ */
21969
+ this.MOUSE_RIGHT_BUTTON = 262;
21970
+
21947
21971
  /**
21948
21972
  * The canvas element that mouse and keyboards are bound to.
21949
21973
  *
@@ -97402,6 +97426,7 @@ class MousePanRotateDollyHandler {
97402
97426
  this._scene = scene;
97403
97427
 
97404
97428
  const pickController = controllers.pickController;
97429
+ const cameraControl = controllers.cameraControl;
97405
97430
 
97406
97431
  let lastX = 0;
97407
97432
  let lastY = 0;
@@ -97466,6 +97491,15 @@ class MousePanRotateDollyHandler {
97466
97491
  }
97467
97492
  }
97468
97493
 
97494
+ function isPanning() {
97495
+ return cameraControl._isKeyDownForAction(cameraControl.MOUSE_PAN, keyDown);
97496
+ }
97497
+
97498
+ function isRotating() {
97499
+ return cameraControl._isKeyDownForAction(cameraControl.MOUSE_ROTATE, keyDown);
97500
+ }
97501
+
97502
+
97469
97503
  canvas.addEventListener("mousedown", this._mouseDownHandler = (e) => {
97470
97504
 
97471
97505
  if (!(configs.active && configs.pointerEnabled)) {
@@ -97479,12 +97513,14 @@ class MousePanRotateDollyHandler {
97479
97513
  if (keyDown[scene.input.KEY_SHIFT] || configs.planView) {
97480
97514
 
97481
97515
  mouseDownLeft = true;
97516
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = true;
97482
97517
 
97483
97518
  setMousedownState();
97484
97519
 
97485
97520
  } else {
97486
97521
 
97487
97522
  mouseDownLeft = true;
97523
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = true;
97488
97524
 
97489
97525
  setMousedownState(false);
97490
97526
  }
@@ -97494,6 +97530,7 @@ class MousePanRotateDollyHandler {
97494
97530
  case 2: // Middle/both buttons
97495
97531
 
97496
97532
  mouseDownMiddle = true;
97533
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = true;
97497
97534
 
97498
97535
  setMousedownState();
97499
97536
 
@@ -97502,6 +97539,7 @@ class MousePanRotateDollyHandler {
97502
97539
  case 3: // Right button
97503
97540
 
97504
97541
  mouseDownRight = true;
97542
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = true;
97505
97543
 
97506
97544
  if (configs.panRightClick) {
97507
97545
 
@@ -97531,7 +97569,8 @@ class MousePanRotateDollyHandler {
97531
97569
  const x = states.pointerCanvasPos[0];
97532
97570
  const y = states.pointerCanvasPos[1];
97533
97571
 
97534
- const panning = keyDown[scene.input.KEY_SHIFT] || configs.planView || (!configs.panRightClick && mouseDownMiddle) || (configs.panRightClick && mouseDownRight);
97572
+ const panning = isPanning();
97573
+ const rotating = isRotating();
97535
97574
 
97536
97575
  const xDelta = document.pointerLockElement ? e.movementX : (x - lastX);
97537
97576
  const yDelta = document.pointerLockElement ? e.movementY : (y - lastY);
@@ -97556,7 +97595,7 @@ class MousePanRotateDollyHandler {
97556
97595
  updates.panDeltaY += 0.5 * camera.ortho.scale * (yDelta / canvasHeight);
97557
97596
  }
97558
97597
 
97559
- } else if (mouseDownLeft && !mouseDownMiddle && !mouseDownRight) {
97598
+ } else if (rotating) {
97560
97599
 
97561
97600
  if (!configs.planView) { // No rotating in plan-view mode
97562
97601
 
@@ -97597,16 +97636,25 @@ class MousePanRotateDollyHandler {
97597
97636
  mouseDownLeft = false;
97598
97637
  mouseDownMiddle = false;
97599
97638
  mouseDownRight = false;
97639
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97640
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97641
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97600
97642
  break;
97601
97643
  case 2: // Middle/both buttons
97602
97644
  mouseDownLeft = false;
97603
97645
  mouseDownMiddle = false;
97604
97646
  mouseDownRight = false;
97647
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97648
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97649
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97605
97650
  break;
97606
97651
  case 3: // Right button
97607
97652
  mouseDownLeft = false;
97608
97653
  mouseDownMiddle = false;
97609
97654
  mouseDownRight = false;
97655
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97656
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97657
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97610
97658
  break;
97611
97659
  }
97612
97660
  });
@@ -97644,7 +97692,7 @@ class MousePanRotateDollyHandler {
97644
97692
  let secsNowLast = null;
97645
97693
 
97646
97694
  canvas.addEventListener("wheel", this._mouseWheelHandler = (e) => {
97647
- if (!(configs.active && configs.pointerEnabled && configs.zoomOnMouseWheel)) {
97695
+ if (!(configs.active && configs.pointerEnabled && configs.zoomOnMouseWheel && cameraControl._isKeyDownForAction(cameraControl.MOUSE_DOLLY, keyDown))) {
97648
97696
  return;
97649
97697
  }
97650
97698
  const secsNow = performance.now() / 1000.0;
@@ -97825,6 +97873,7 @@ class MousePickHandler {
97825
97873
  this._clicks = 0;
97826
97874
  this._timeout = null;
97827
97875
  this._lastPickedEntityId = null;
97876
+ this._lastClickedWorldPos = null;
97828
97877
 
97829
97878
  let leftDown = false;
97830
97879
  let rightDown = false;
@@ -97974,11 +98023,16 @@ class MousePickHandler {
97974
98023
  if (pickResult && pickResult.worldPos) {
97975
98024
  pivotController.setPivotPos(pickResult.worldPos);
97976
98025
  pivotController.startPivot();
98026
+ this._lastClickedWorldPos = pickResult.worldPos.slice();
97977
98027
  } else {
97978
98028
  if (configs.smartPivot) {
97979
98029
  pivotController.setCanvasPivotPos(states.pointerCanvasPos);
97980
98030
  } else {
97981
- pivotController.setPivotPos(scene.camera.look);
98031
+ if (this._lastClickedWorldPos) {
98032
+ pivotController.setPivotPos(this._lastClickedWorldPos);
98033
+ } else {
98034
+ pivotController.setPivotPos(scene.camera.look);
98035
+ }
97982
98036
  }
97983
98037
  pivotController.startPivot();
97984
98038
  }
@@ -99694,6 +99748,12 @@ const DEFAULT_SNAP_EDGE = true;
99694
99748
  * keyMap[cameraControl.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
99695
99749
  * keyMap[cameraControl.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
99696
99750
  * keyMap[cameraControl.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
99751
+ * keyMap[cameraControl.MOUSE_PAN] = [[input.KEY_SHIFT, input.MOUSE_LEFT_BUTTON]];
99752
+ * keyMap[cameraControl.MOUSE_ROTATE] = [
99753
+ * [input.KEY_SHIFT, input.MOUSE_MIDDLE_BUTTON],
99754
+ * [input.KEY_SHIFT, input.MOUSE_RIGHT_BUTTON]
99755
+ * ]
99756
+ * keyMap[cameraControl.MOUSE_DOLLY] = [[input.KEY_CTRL, input.MOUSE_RIGHT_BUTTON]];
99697
99757
  *
99698
99758
  * cameraControl.keyMap = keyMap;
99699
99759
  * ````
@@ -99712,6 +99772,70 @@ const DEFAULT_SNAP_EDGE = true;
99712
99772
  *
99713
99773
  * * ````"qwerty"````
99714
99774
  * * ````"azerty"````
99775
+ *
99776
+ * ## Basic Keyboard Mapping
99777
+ * * ````"OR" Relation````
99778
+ * Set multiple keys to trigger an action if any one is pressed:
99779
+ *
99780
+ * ````javascript
99781
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];
99782
+ * ````
99783
+ *
99784
+ * If either ````KEY_S```` or ````KEY_SUBTRACT```` is pressed, the camera will dolly backward.
99785
+ *
99786
+ * * ````"AND" Relation````
99787
+ * To require all keys in a combination to be pressed:
99788
+ *
99789
+ * ````javascript
99790
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [[input.KEY_S, input.KEY_SUBTRACT]];
99791
+ * ````
99792
+ *
99793
+ * The camera will dolly backward if ````both KEY_S```` and ````KEY_SUBTRACT```` are pressed.
99794
+ *
99795
+ * * ````Mix "AND" and "OR" Relation````
99796
+ * Use a combination of keys and groups for flexibility:
99797
+ *
99798
+ * ````javascript
99799
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [
99800
+ * [input.KEY_S, input.KEY_SUBTRACT], // 'And' group
99801
+ * input.KEY_SHIFT // 'Or' with previous
99802
+ * ];
99803
+ * ````
99804
+ *
99805
+ * The camera will dolly backward if ````KEY_S```` + ````KEY_SUBTRACT```` are pressed together, or if ````KEY_SHIFT```` is pressed.
99806
+ *
99807
+ * ## Special Mouse Actions
99808
+ * Certain actions support combinations with specific mouse buttons or events:
99809
+ *
99810
+ * * ````MOUSE_PAN````
99811
+ * For panning with a key and mouse movement:
99812
+ *
99813
+ * ````javascript
99814
+ * keyMap[cameraControl.MOUSE_PAN] = [[input.KEY_SHIFT, input.MOUSE_LEFT_BUTTON]];
99815
+ * ````
99816
+ *
99817
+ * Panning is triggered by pressing ````KEY_SHIFT```` + ````MOUSE_LEFT_BUTTON```` while moving the mouse.
99818
+ *
99819
+ * * ````MOUSE_ROTATE````
99820
+ * Similar to panning, rotation can be configured with key and mouse button combinations:
99821
+ *
99822
+ * ````javascript
99823
+ * keyMap[cameraControl.MOUSE_ROTATE] = [[input.KEY_CTRL, input.MOUSE_LEFT_BUTTON]];
99824
+ * ````
99825
+ *
99826
+ * Rotation is triggered by pressing ````KEY_CTRL```` + ````MOUSE_LEFT_BUTTON```` during mouse movement.
99827
+ *
99828
+ * * ````MOUSE_DOLLY````
99829
+ * Dolly with mouse wheel scrolling and optional key combinations:
99830
+ *
99831
+ * ````javascript
99832
+ * keyMap[cameraControl.MOUSE_DOLLY] = [[input.KEY_ALT]];
99833
+ * ````
99834
+ *
99835
+ * Dolly action occurs when scrolling the mouse wheel with ````KEY_ALT```` held (no need to specify MOUSE_WHEEL).
99836
+ *
99837
+ * ## Special Mouse Actions
99838
+ * Use ````input.MOUSE_LEFT_BUTTON````, ````input.MOUSE_MIDDLE_BUTTON````, and ````input.MOUSE_RIGHT_BUTTON```` in combinations only for camera movements involving the mouse.
99715
99839
  */
99716
99840
  class CameraControl extends Component {
99717
99841
 
@@ -99849,6 +99973,27 @@ class CameraControl extends Component {
99849
99973
  */
99850
99974
  this.AXIS_VIEW_BOTTOM = 17;
99851
99975
 
99976
+ /**
99977
+ * Identifies the XX action.
99978
+ * @final
99979
+ * @type {Number}
99980
+ */
99981
+ this.MOUSE_PAN = 18;
99982
+
99983
+ /**
99984
+ * Identifies the XX action.
99985
+ * @final
99986
+ * @type {Number}
99987
+ */
99988
+ this.MOUSE_ROTATE = 19;
99989
+
99990
+ /**
99991
+ * Identifies the XX action.
99992
+ * @final
99993
+ * @type {Number}
99994
+ */
99995
+ this.MOUSE_DOLLY = 20;
99996
+
99852
99997
  this._keyMap = {}; // Maps key codes to the above actions
99853
99998
 
99854
99999
  this.scene.canvas.canvas.oncontextmenu = (e) => {
@@ -100037,6 +100182,12 @@ class CameraControl extends Component {
100037
100182
  keyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
100038
100183
  keyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
100039
100184
  keyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
100185
+ keyMap[this.MOUSE_PAN] = [
100186
+ [input.MOUSE_LEFT_BUTTON, input.KEY_SHIFT],
100187
+ this._configs.panRightClick ? input.MOUSE_RIGHT_BUTTON : input.MOUSE_MIDDLE_BUTTON
100188
+ ];
100189
+ keyMap[this.MOUSE_ROTATE] = [input.MOUSE_LEFT_BUTTON];
100190
+ keyMap[this.MOUSE_DOLLY] = [];
100040
100191
  break;
100041
100192
 
100042
100193
  case "azerty":
@@ -100058,6 +100209,12 @@ class CameraControl extends Component {
100058
100209
  keyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
100059
100210
  keyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
100060
100211
  keyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
100212
+ keyMap[this.MOUSE_PAN] = [
100213
+ [input.MOUSE_LEFT_BUTTON, input.KEY_SHIFT],
100214
+ this._configs.panRightClick ? input.MOUSE_RIGHT_BUTTON : input.MOUSE_MIDDLE_BUTTON
100215
+ ];
100216
+ keyMap[this.MOUSE_ROTATE] = [input.MOUSE_LEFT_BUTTON];
100217
+ keyMap[this.MOUSE_DOLLY] = [];
100061
100218
  break;
100062
100219
  }
100063
100220
 
@@ -100077,6 +100234,44 @@ class CameraControl extends Component {
100077
100234
  return this._keyMap;
100078
100235
  }
100079
100236
 
100237
+ _areAllKeysDown(keyDownMap, keys) {
100238
+ if (!keys || keys.length <= 0) {
100239
+ return true;
100240
+ }
100241
+ if (!keyDownMap) {
100242
+ return false;
100243
+ }
100244
+ for (let i = 0, len = keys.length; i < len; i++) {
100245
+ const key = keys[i];
100246
+ if (!keyDownMap[key])
100247
+ return false;
100248
+ }
100249
+ return true;
100250
+ }
100251
+
100252
+ _isAnyOtherKeyDown(keyDownMap, keyMap) {
100253
+ for (let i = 0, len = keyDownMap.length; i < len; i++) {
100254
+ if (keyDownMap[i]) {
100255
+ if (Array.isArray(keyMap)) {
100256
+ if (keyMap.indexOf(i) < 0) return true;
100257
+ }
100258
+ else if (i !== keyMap) return true;
100259
+ }
100260
+ }
100261
+ return false;
100262
+ }
100263
+
100264
+ _isMouseAction(action) {
100265
+ switch (action) {
100266
+ case this.MOUSE_ROTATE:
100267
+ case this.MOUSE_DOLLY:
100268
+ case this.MOUSE_PAN:
100269
+ return true;
100270
+ default:
100271
+ return false;
100272
+ }
100273
+ }
100274
+
100080
100275
  /**
100081
100276
  * Returns true if any keys configured for the given action are down.
100082
100277
  * @param action
@@ -100088,14 +100283,21 @@ class CameraControl extends Component {
100088
100283
  if (!keys) {
100089
100284
  return false;
100090
100285
  }
100286
+ if (keys.length === 0 && this._isMouseAction(action)) return true;
100091
100287
  if (!keyDownMap) {
100092
100288
  keyDownMap = this.scene.input.keyDown;
100093
100289
  }
100094
100290
  for (let i = 0, len = keys.length; i < len; i++) {
100095
100291
  const key = keys[i];
100096
- if (keyDownMap[key]) {
100097
- return true;
100292
+ if (!Array.isArray(key)) {
100293
+ if (keyDownMap[key] && !this._isAnyOtherKeyDown(keyDownMap, key))
100294
+ return true;
100098
100295
  }
100296
+ else {
100297
+ if (this._areAllKeysDown(keyDownMap, key) && !this._isAnyOtherKeyDown(keyDownMap, key))
100298
+ return true;
100299
+ }
100300
+
100099
100301
  }
100100
100302
  return false;
100101
100303
  }
@@ -100531,6 +100733,16 @@ class CameraControl extends Component {
100531
100733
  */
100532
100734
  set panRightClick(value) {
100533
100735
  this._configs.panRightClick = value !== false;
100736
+ const panKeyMap = this._keyMap[this.MOUSE_PAN];
100737
+ if (panKeyMap && panKeyMap.length > 0) {
100738
+ const input = this.scene.input;
100739
+ for (let i = 0, len = panKeyMap.length; i < len; i++) {
100740
+ if (this._configs.panRightClick && panKeyMap[i] === input.MOUSE_MIDDLE_BUTTON)
100741
+ this._keyMap[this.MOUSE_PAN][i] = input.MOUSE_RIGHT_BUTTON;
100742
+ else if (!this._configs.panRightClick && panKeyMap[i] === input.MOUSE_RIGHT_BUTTON)
100743
+ this._keyMap[this.MOUSE_PAN][i] = input.MOUSE_MIDDLE_BUTTON;
100744
+ }
100745
+ }
100534
100746
  }
100535
100747
 
100536
100748
  /**
@@ -110465,19 +110677,15 @@ class Viewer {
110465
110677
 
110466
110678
  for (let i = 0, len = pluginContainerElements.length; i < len; i++) {
110467
110679
  const containerElement = pluginContainerElements[i];
110468
- //only calculate the scale for first plugin
110469
- //for all others keep the scale 1 otherwise it will keep multiplying the scale with the base scale of canvas
110470
- //resulting in increase/decreased size for the the canvas that is being overlapped
110471
- const scale = i == 0 ? snapshotCanvas.width / containerElement.clientWidth : 1;
110472
- const off = math.vec2([ 0, 0 ]);
110473
- transformToNode(canvas, containerElement, off);
110474
110680
  await html2canvas(containerElement, {
110475
110681
  canvas: snapshotCanvas,
110476
110682
  backgroundColor: null,
110477
- x: off[0],
110478
- y: off[1],
110479
- scale
110683
+ scale: snapshotCanvas.width / containerElement.clientWidth
110480
110684
  });
110685
+ // Reverts translation and scaling applied to the snapshotCanvas's context
110686
+ // by the html2canvas call (inside the ForeignObjectRenderer's constructor)
110687
+ // (implemented to compensate XCD-153 issue)
110688
+ snapshotCanvas.getContext("2d").resetTransform();
110481
110689
  }
110482
110690
  if (!params.includeGizmos) {
110483
110691
  this.sendToPlugins("snapshotFinished");
@@ -123725,9 +123933,10 @@ class StoreyViewsPlugin extends Plugin {
123725
123933
  * @param {Number[]} worldPos 3D World-space position.
123726
123934
  * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123727
123935
  */
123728
- getStoreyContainingWorldPos(worldPos) {
123729
- for (var storeyId in this.storeys) {
123730
- const storey = this.storeys[storeyId];
123936
+ getStoreyContainingWorldPos(worldPos, modelId = null) {
123937
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
123938
+ for (let storeyId in storeys) {
123939
+ const storey = storeys[storeyId];
123731
123940
  if (math.point3AABB3AbsoluteIntersect(storey.storeyAABB, worldPos)) {
123732
123941
  return storeyId;
123733
123942
  }
@@ -123741,9 +123950,10 @@ class StoreyViewsPlugin extends Plugin {
123741
123950
  * @param {Number[]} worldPos 3D World-space position.
123742
123951
  * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123743
123952
  */
123744
- getStoreyInVerticalRange(worldPos) {
123745
- for (let storeyId in this.storeys) {
123746
- const storey = this.storeys[storeyId];
123953
+ getStoreyInVerticalRange(worldPos, modelId = null) {
123954
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
123955
+ for (let storeyId in storeys) {
123956
+ const storey = storeys[storeyId];
123747
123957
  const aabb = [0, 0, 0, 0, 0, 0], pos = [0, 0, 0];
123748
123958
  aabb[1] = storey.storeyAABB[1];
123749
123959
  aabb[4] = storey.storeyAABB[4];
@@ -123761,12 +123971,14 @@ class StoreyViewsPlugin extends Plugin {
123761
123971
  * @param {Number[]} worldPos 3D World-space position.
123762
123972
  * @returns {String} ID of the lowest/highest story or null.
123763
123973
  */
123764
- isPositionAboveOrBelowBuilding(worldPos) {
123765
- const keys = Object.keys(this.storeys);
123974
+ isPositionAboveOrBelowBuilding(worldPos, modelId = null) {
123975
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
123976
+ const keys = Object.keys(storeys);
123977
+ if(keys.length <= 0) return null;
123766
123978
  const ids = [keys[0], keys[keys.length - 1]];
123767
- if (worldPos[1] < this.storeys[ids[0]].storeyAABB[1])
123979
+ if (worldPos[1] < storeys[ids[0]].storeyAABB[1])
123768
123980
  return ids[0];
123769
- else if (worldPos[1] > this.storeys[ids[1]].storeyAABB[4])
123981
+ else if (worldPos[1] > storeys[ids[1]].storeyAABB[4])
123770
123982
  return ids[1];
123771
123983
  return null;
123772
123984
  }
@@ -123890,8 +124102,8 @@ class StoreyViewsPlugin extends Plugin {
123890
124102
 
123891
124103
  if (storey1MetaObject && (storey1MetaObject.attributes && storey1MetaObject.attributes.elevation !== undefined) &&
123892
124104
  storey2MetaObject && (storey2MetaObject.attributes && storey2MetaObject.attributes.elevation !== undefined)) {
123893
- const elevation1 = storey1MetaObject.attributes.elevation;
123894
- const elevation2 = storey2MetaObject.attributes.elevation;
124105
+ const elevation1 = Number.parseFloat(storey1MetaObject.attributes.elevation);
124106
+ const elevation2 = Number.parseFloat(storey2MetaObject.attributes.elevation);
123895
124107
  if (elevation1 > elevation2) {
123896
124108
  return -1;
123897
124109
  }
@@ -123910,6 +124122,12 @@ class StoreyViewsPlugin extends Plugin {
123910
124122
  }
123911
124123
  });
123912
124124
  }
124125
+
124126
+ _filterStoreys(modelId) {
124127
+ return Object.fromEntries(
124128
+ Object.entries(this.storeys).filter(([_, value]) => value.modelId === modelId)
124129
+ );
124130
+ }
123913
124131
  }
123914
124132
 
123915
124133
  const zeroVec = new Float64Array([0, 0, 1]);
@@ -127473,7 +127691,7 @@ class TreeViewPlugin extends Plugin {
127473
127691
  return;
127474
127692
  }
127475
127693
  const firstChild = children[0];
127476
- if (this._hierarchy === "storeys" && firstChild.type === "IfcBuildingStorey") {
127694
+ if ((this._hierarchy === "storeys" || this._hierarchy === "containment") && firstChild.type === "IfcBuildingStorey") {
127477
127695
  children.sort(this._getSpatialSortFunc());
127478
127696
  } else {
127479
127697
  children.sort(this._alphaSortFunc);
@@ -127484,36 +127702,30 @@ class TreeViewPlugin extends Plugin {
127484
127702
  }
127485
127703
  }
127486
127704
 
127487
- _getSpatialSortFunc() { // Creates cached sort func with Viewer in scope
127705
+ _getSpatialSortFunc() {
127488
127706
  const viewer = this.viewer;
127489
127707
  const scene = viewer.scene;
127490
127708
  const camera = scene.camera;
127491
- const metaScene = viewer.metaScene;
127492
- return this._spatialSortFunc || (this._spatialSortFunc = (node1, node2) => {
127493
- if (!node1.aabb || !node2.aabb) {
127494
- // Sorting on lowest point of the AABB is likely more more robust when objects could overlap storeys
127495
- if (!node1.aabb) {
127496
- node1.aabb = scene.getAABB(metaScene.getObjectIDsInSubtree(node1.objectId));
127709
+ return this._spatialSortFunc || (this._spatialSortFunc = (storey1, storey2) => {
127710
+ if (camera.xUp) ; else if (camera.yUp) ; else ;
127711
+ const metaScene = this.viewer.metaScene;
127712
+ const storey1MetaObject = metaScene.metaObjects[storey1.objectId];
127713
+ const storey2MetaObject = metaScene.metaObjects[storey2.objectId];
127714
+
127715
+ if (storey1MetaObject && (storey1MetaObject.attributes && storey1MetaObject.attributes.elevation !== undefined) &&
127716
+ storey2MetaObject && (storey2MetaObject.attributes && storey2MetaObject.attributes.elevation !== undefined)) {
127717
+ const elevation1 = Number.parseFloat(storey1MetaObject.attributes.elevation);
127718
+ const elevation2 = Number.parseFloat(storey2MetaObject.attributes.elevation);
127719
+ if (elevation1 > elevation2) {
127720
+ return -1;
127497
127721
  }
127498
- if (!node2.aabb) {
127499
- node2.aabb = scene.getAABB(metaScene.getObjectIDsInSubtree(node2.objectId));
127722
+ if (elevation1 < elevation2) {
127723
+ return 1;
127500
127724
  }
127501
- }
127502
- let idx = 0;
127503
- if (camera.xUp) {
127504
- idx = 0;
127505
- } else if (camera.yUp) {
127506
- idx = 1;
127725
+ return 0;
127507
127726
  } else {
127508
- idx = 2;
127509
- }
127510
- if (node1.aabb[idx] > node2.aabb[idx]) {
127511
- return -1;
127512
- }
127513
- if (node1.aabb[idx] < node2.aabb[idx]) {
127514
- return 1;
127727
+ return 0;
127515
127728
  }
127516
- return 0;
127517
127729
  });
127518
127730
  }
127519
127731