@xeokit/xeokit-sdk 2.6.53 → 2.6.55

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
  *
@@ -61823,7 +61847,7 @@ class VBOInstancingTrianglesLayer {
61823
61847
  state.indicesBuf = new ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.indices), geometry.indices.length, 1, gl.STATIC_DRAW);
61824
61848
  state.numIndices = geometry.indices.length;
61825
61849
  }
61826
- if (geometry.primitive === "triangles" || geometry.primitive === "solid" || geometry.primitive === "surface") {
61850
+ if (geometry.edgeIndices && geometry.edgeIndices.length > 0) {
61827
61851
  state.edgeIndicesBuf = new ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.edgeIndices), geometry.edgeIndices.length, 1, gl.STATIC_DRAW);
61828
61852
  }
61829
61853
 
@@ -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;
@@ -97438,7 +97463,6 @@ class MousePanRotateDollyHandler {
97438
97463
  });
97439
97464
 
97440
97465
  function setMousedownState(pick = true) {
97441
- canvas.style.cursor = "move";
97442
97466
  setMousedownPositions();
97443
97467
  if (pick) {
97444
97468
  setMousedownPick();
@@ -97466,6 +97490,15 @@ class MousePanRotateDollyHandler {
97466
97490
  }
97467
97491
  }
97468
97492
 
97493
+ function isPanning() {
97494
+ return cameraControl._isKeyDownForAction(cameraControl.MOUSE_PAN, keyDown);
97495
+ }
97496
+
97497
+ function isRotating() {
97498
+ return cameraControl._isKeyDownForAction(cameraControl.MOUSE_ROTATE, keyDown);
97499
+ }
97500
+
97501
+
97469
97502
  canvas.addEventListener("mousedown", this._mouseDownHandler = (e) => {
97470
97503
 
97471
97504
  if (!(configs.active && configs.pointerEnabled)) {
@@ -97479,12 +97512,14 @@ class MousePanRotateDollyHandler {
97479
97512
  if (keyDown[scene.input.KEY_SHIFT] || configs.planView) {
97480
97513
 
97481
97514
  mouseDownLeft = true;
97515
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = true;
97482
97516
 
97483
97517
  setMousedownState();
97484
97518
 
97485
97519
  } else {
97486
97520
 
97487
97521
  mouseDownLeft = true;
97522
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = true;
97488
97523
 
97489
97524
  setMousedownState(false);
97490
97525
  }
@@ -97494,6 +97529,7 @@ class MousePanRotateDollyHandler {
97494
97529
  case 2: // Middle/both buttons
97495
97530
 
97496
97531
  mouseDownMiddle = true;
97532
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = true;
97497
97533
 
97498
97534
  setMousedownState();
97499
97535
 
@@ -97502,6 +97538,7 @@ class MousePanRotateDollyHandler {
97502
97538
  case 3: // Right button
97503
97539
 
97504
97540
  mouseDownRight = true;
97541
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = true;
97505
97542
 
97506
97543
  if (configs.panRightClick) {
97507
97544
 
@@ -97531,7 +97568,8 @@ class MousePanRotateDollyHandler {
97531
97568
  const x = states.pointerCanvasPos[0];
97532
97569
  const y = states.pointerCanvasPos[1];
97533
97570
 
97534
- const panning = keyDown[scene.input.KEY_SHIFT] || configs.planView || (!configs.panRightClick && mouseDownMiddle) || (configs.panRightClick && mouseDownRight);
97571
+ const panning = isPanning();
97572
+ const rotating = isRotating();
97535
97573
 
97536
97574
  const xDelta = document.pointerLockElement ? e.movementX : (x - lastX);
97537
97575
  const yDelta = document.pointerLockElement ? e.movementY : (y - lastY);
@@ -97556,7 +97594,7 @@ class MousePanRotateDollyHandler {
97556
97594
  updates.panDeltaY += 0.5 * camera.ortho.scale * (yDelta / canvasHeight);
97557
97595
  }
97558
97596
 
97559
- } else if (mouseDownLeft && !mouseDownMiddle && !mouseDownRight) {
97597
+ } else if (rotating) {
97560
97598
 
97561
97599
  if (!configs.planView) { // No rotating in plan-view mode
97562
97600
 
@@ -97597,16 +97635,25 @@ class MousePanRotateDollyHandler {
97597
97635
  mouseDownLeft = false;
97598
97636
  mouseDownMiddle = false;
97599
97637
  mouseDownRight = false;
97638
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97639
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97640
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97600
97641
  break;
97601
97642
  case 2: // Middle/both buttons
97602
97643
  mouseDownLeft = false;
97603
97644
  mouseDownMiddle = false;
97604
97645
  mouseDownRight = false;
97646
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97647
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97648
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97605
97649
  break;
97606
97650
  case 3: // Right button
97607
97651
  mouseDownLeft = false;
97608
97652
  mouseDownMiddle = false;
97609
97653
  mouseDownRight = false;
97654
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97655
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97656
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97610
97657
  break;
97611
97658
  }
97612
97659
  });
@@ -97644,7 +97691,7 @@ class MousePanRotateDollyHandler {
97644
97691
  let secsNowLast = null;
97645
97692
 
97646
97693
  canvas.addEventListener("wheel", this._mouseWheelHandler = (e) => {
97647
- if (!(configs.active && configs.pointerEnabled && configs.zoomOnMouseWheel)) {
97694
+ if (!(configs.active && configs.pointerEnabled && configs.zoomOnMouseWheel && cameraControl._isKeyDownForAction(cameraControl.MOUSE_DOLLY, keyDown))) {
97648
97695
  return;
97649
97696
  }
97650
97697
  const secsNow = performance.now() / 1000.0;
@@ -97825,6 +97872,7 @@ class MousePickHandler {
97825
97872
  this._clicks = 0;
97826
97873
  this._timeout = null;
97827
97874
  this._lastPickedEntityId = null;
97875
+ this._lastClickedWorldPos = null;
97828
97876
 
97829
97877
  let leftDown = false;
97830
97878
  let rightDown = false;
@@ -97974,11 +98022,16 @@ class MousePickHandler {
97974
98022
  if (pickResult && pickResult.worldPos) {
97975
98023
  pivotController.setPivotPos(pickResult.worldPos);
97976
98024
  pivotController.startPivot();
98025
+ this._lastClickedWorldPos = pickResult.worldPos.slice();
97977
98026
  } else {
97978
98027
  if (configs.smartPivot) {
97979
98028
  pivotController.setCanvasPivotPos(states.pointerCanvasPos);
97980
98029
  } else {
97981
- pivotController.setPivotPos(scene.camera.look);
98030
+ if (this._lastClickedWorldPos) {
98031
+ pivotController.setPivotPos(this._lastClickedWorldPos);
98032
+ } else {
98033
+ pivotController.setPivotPos(scene.camera.look);
98034
+ }
97982
98035
  }
97983
98036
  pivotController.startPivot();
97984
98037
  }
@@ -98200,7 +98253,7 @@ class KeyboardPanRotateDollyHandler {
98200
98253
 
98201
98254
  const keyDownMap = [];
98202
98255
 
98203
- const canvas = scene.canvas.canvas;
98256
+ scene.canvas.canvas;
98204
98257
 
98205
98258
  let mouseMovedSinceLastKeyboardDolly = true;
98206
98259
 
@@ -98216,10 +98269,6 @@ class KeyboardPanRotateDollyHandler {
98216
98269
  return;
98217
98270
  }
98218
98271
  keyDownMap[keyCode] = true;
98219
-
98220
- if (keyCode === input.KEY_SHIFT) {
98221
- canvas.style.cursor = "move";
98222
- }
98223
98272
  });
98224
98273
 
98225
98274
  this._onSceneKeyUp = input.on("keyup", (keyCode) => {
@@ -98228,10 +98277,6 @@ class KeyboardPanRotateDollyHandler {
98228
98277
  }
98229
98278
  keyDownMap[keyCode] = false;
98230
98279
 
98231
- if (keyCode === input.KEY_SHIFT) {
98232
- canvas.style.cursor = null;
98233
- }
98234
-
98235
98280
  if (controllers.pivotController.getPivoting()) {
98236
98281
  controllers.pivotController.endPivot();
98237
98282
  }
@@ -98388,6 +98433,7 @@ class CameraUpdater {
98388
98433
  const pickController = controllers.pickController;
98389
98434
  const pivotController = controllers.pivotController;
98390
98435
  const panController = controllers.panController;
98436
+ const cameraControl = controllers.cameraControl;
98391
98437
 
98392
98438
  let countDown = SCALE_DOLLY_EACH_FRAME; // Decrements on each tick
98393
98439
  let dollyDistFactor = 1.0; // Calculated when countDown is zero
@@ -98512,7 +98558,7 @@ class CameraUpdater {
98512
98558
  updates.rotateDeltaX *= configs.rotationInertia;
98513
98559
  updates.rotateDeltaY *= configs.rotationInertia;
98514
98560
 
98515
- cursorType = "grabbing";
98561
+ cursorType = cameraControl._cursors.rotate;
98516
98562
  }
98517
98563
 
98518
98564
  //----------------------------------------------------------------------------------------------------------
@@ -98578,7 +98624,7 @@ class CameraUpdater {
98578
98624
  camera.pan(vec);
98579
98625
  }
98580
98626
 
98581
- cursorType = "grabbing";
98627
+ cursorType = cameraControl._cursors.pan;
98582
98628
  }
98583
98629
 
98584
98630
  updates.panDeltaX *= configs.panInertia;
@@ -98592,9 +98638,9 @@ class CameraUpdater {
98592
98638
  if (dollyDeltaForDist !== 0) {
98593
98639
 
98594
98640
  if (dollyDeltaForDist < 0) {
98595
- cursorType = "zoom-in";
98641
+ cursorType = cameraControl._cursors.dollyForward;
98596
98642
  } else {
98597
- cursorType = "zoom-out";
98643
+ cursorType = cameraControl._cursors.dollyBackward;
98598
98644
  }
98599
98645
 
98600
98646
  if (configs.firstPerson) {
@@ -99694,6 +99740,12 @@ const DEFAULT_SNAP_EDGE = true;
99694
99740
  * keyMap[cameraControl.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
99695
99741
  * keyMap[cameraControl.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
99696
99742
  * keyMap[cameraControl.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
99743
+ * keyMap[cameraControl.MOUSE_PAN] = [[input.KEY_SHIFT, input.MOUSE_LEFT_BUTTON]];
99744
+ * keyMap[cameraControl.MOUSE_ROTATE] = [
99745
+ * [input.KEY_SHIFT, input.MOUSE_MIDDLE_BUTTON],
99746
+ * [input.KEY_SHIFT, input.MOUSE_RIGHT_BUTTON]
99747
+ * ]
99748
+ * keyMap[cameraControl.MOUSE_DOLLY] = [[input.KEY_CTRL, input.MOUSE_RIGHT_BUTTON]];
99697
99749
  *
99698
99750
  * cameraControl.keyMap = keyMap;
99699
99751
  * ````
@@ -99712,6 +99764,70 @@ const DEFAULT_SNAP_EDGE = true;
99712
99764
  *
99713
99765
  * * ````"qwerty"````
99714
99766
  * * ````"azerty"````
99767
+ *
99768
+ * ## Basic Keyboard Mapping
99769
+ * * ````"OR" Relation````
99770
+ * Set multiple keys to trigger an action if any one is pressed:
99771
+ *
99772
+ * ````javascript
99773
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];
99774
+ * ````
99775
+ *
99776
+ * If either ````KEY_S```` or ````KEY_SUBTRACT```` is pressed, the camera will dolly backward.
99777
+ *
99778
+ * * ````"AND" Relation````
99779
+ * To require all keys in a combination to be pressed:
99780
+ *
99781
+ * ````javascript
99782
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [[input.KEY_S, input.KEY_SUBTRACT]];
99783
+ * ````
99784
+ *
99785
+ * The camera will dolly backward if ````both KEY_S```` and ````KEY_SUBTRACT```` are pressed.
99786
+ *
99787
+ * * ````Mix "AND" and "OR" Relation````
99788
+ * Use a combination of keys and groups for flexibility:
99789
+ *
99790
+ * ````javascript
99791
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [
99792
+ * [input.KEY_S, input.KEY_SUBTRACT], // 'And' group
99793
+ * input.KEY_SHIFT // 'Or' with previous
99794
+ * ];
99795
+ * ````
99796
+ *
99797
+ * The camera will dolly backward if ````KEY_S```` + ````KEY_SUBTRACT```` are pressed together, or if ````KEY_SHIFT```` is pressed.
99798
+ *
99799
+ * ## Special Mouse Actions
99800
+ * Certain actions support combinations with specific mouse buttons or events:
99801
+ *
99802
+ * * ````MOUSE_PAN````
99803
+ * For panning with a key and mouse movement:
99804
+ *
99805
+ * ````javascript
99806
+ * keyMap[cameraControl.MOUSE_PAN] = [[input.KEY_SHIFT, input.MOUSE_LEFT_BUTTON]];
99807
+ * ````
99808
+ *
99809
+ * Panning is triggered by pressing ````KEY_SHIFT```` + ````MOUSE_LEFT_BUTTON```` while moving the mouse.
99810
+ *
99811
+ * * ````MOUSE_ROTATE````
99812
+ * Similar to panning, rotation can be configured with key and mouse button combinations:
99813
+ *
99814
+ * ````javascript
99815
+ * keyMap[cameraControl.MOUSE_ROTATE] = [[input.KEY_CTRL, input.MOUSE_LEFT_BUTTON]];
99816
+ * ````
99817
+ *
99818
+ * Rotation is triggered by pressing ````KEY_CTRL```` + ````MOUSE_LEFT_BUTTON```` during mouse movement.
99819
+ *
99820
+ * * ````MOUSE_DOLLY````
99821
+ * Dolly with mouse wheel scrolling and optional key combinations:
99822
+ *
99823
+ * ````javascript
99824
+ * keyMap[cameraControl.MOUSE_DOLLY] = [[input.KEY_ALT]];
99825
+ * ````
99826
+ *
99827
+ * Dolly action occurs when scrolling the mouse wheel with ````KEY_ALT```` held (no need to specify MOUSE_WHEEL).
99828
+ *
99829
+ * ## Special Mouse Actions
99830
+ * Use ````input.MOUSE_LEFT_BUTTON````, ````input.MOUSE_MIDDLE_BUTTON````, and ````input.MOUSE_RIGHT_BUTTON```` in combinations only for camera movements involving the mouse.
99715
99831
  */
99716
99832
  class CameraControl extends Component {
99717
99833
 
@@ -99849,6 +99965,27 @@ class CameraControl extends Component {
99849
99965
  */
99850
99966
  this.AXIS_VIEW_BOTTOM = 17;
99851
99967
 
99968
+ /**
99969
+ * Identifies the XX action.
99970
+ * @final
99971
+ * @type {Number}
99972
+ */
99973
+ this.MOUSE_PAN = 18;
99974
+
99975
+ /**
99976
+ * Identifies the XX action.
99977
+ * @final
99978
+ * @type {Number}
99979
+ */
99980
+ this.MOUSE_ROTATE = 19;
99981
+
99982
+ /**
99983
+ * Identifies the XX action.
99984
+ * @final
99985
+ * @type {Number}
99986
+ */
99987
+ this.MOUSE_DOLLY = 20;
99988
+
99852
99989
  this._keyMap = {}; // Maps key codes to the above actions
99853
99990
 
99854
99991
  this.scene.canvas.canvas.oncontextmenu = (e) => {
@@ -99964,6 +100101,13 @@ class CameraControl extends Component {
99964
100101
  new KeyboardPanRotateDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates)
99965
100102
  ];
99966
100103
 
100104
+ this._cursors = {
100105
+ dollyForward: "zoom-in",
100106
+ dollyBackward: "zoom-out",
100107
+ rotate: 'grabbing',
100108
+ pan: 'move',
100109
+ };
100110
+
99967
100111
  // Applies scheduled updates to the Camera on each Scene "tick" event
99968
100112
 
99969
100113
  this._cameraUpdater = new CameraUpdater(this.scene, this._controllers, this._configs, this._states, this._updates);
@@ -100037,6 +100181,12 @@ class CameraControl extends Component {
100037
100181
  keyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
100038
100182
  keyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
100039
100183
  keyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
100184
+ keyMap[this.MOUSE_PAN] = [
100185
+ [input.MOUSE_LEFT_BUTTON, input.KEY_SHIFT],
100186
+ this._configs.panRightClick ? input.MOUSE_RIGHT_BUTTON : input.MOUSE_MIDDLE_BUTTON
100187
+ ];
100188
+ keyMap[this.MOUSE_ROTATE] = [input.MOUSE_LEFT_BUTTON];
100189
+ keyMap[this.MOUSE_DOLLY] = [];
100040
100190
  break;
100041
100191
 
100042
100192
  case "azerty":
@@ -100058,6 +100208,12 @@ class CameraControl extends Component {
100058
100208
  keyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
100059
100209
  keyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
100060
100210
  keyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
100211
+ keyMap[this.MOUSE_PAN] = [
100212
+ [input.MOUSE_LEFT_BUTTON, input.KEY_SHIFT],
100213
+ this._configs.panRightClick ? input.MOUSE_RIGHT_BUTTON : input.MOUSE_MIDDLE_BUTTON
100214
+ ];
100215
+ keyMap[this.MOUSE_ROTATE] = [input.MOUSE_LEFT_BUTTON];
100216
+ keyMap[this.MOUSE_DOLLY] = [];
100061
100217
  break;
100062
100218
  }
100063
100219
 
@@ -100077,6 +100233,44 @@ class CameraControl extends Component {
100077
100233
  return this._keyMap;
100078
100234
  }
100079
100235
 
100236
+ _areAllKeysDown(keyDownMap, keys) {
100237
+ if (!keys || keys.length <= 0) {
100238
+ return true;
100239
+ }
100240
+ if (!keyDownMap) {
100241
+ return false;
100242
+ }
100243
+ for (let i = 0, len = keys.length; i < len; i++) {
100244
+ const key = keys[i];
100245
+ if (!keyDownMap[key])
100246
+ return false;
100247
+ }
100248
+ return true;
100249
+ }
100250
+
100251
+ _isAnyOtherKeyDown(keyDownMap, keyMap) {
100252
+ for (let i = 0, len = keyDownMap.length; i < len; i++) {
100253
+ if (keyDownMap[i]) {
100254
+ if (Array.isArray(keyMap)) {
100255
+ if (keyMap.indexOf(i) < 0) return true;
100256
+ }
100257
+ else if (i !== keyMap) return true;
100258
+ }
100259
+ }
100260
+ return false;
100261
+ }
100262
+
100263
+ _isMouseAction(action) {
100264
+ switch (action) {
100265
+ case this.MOUSE_ROTATE:
100266
+ case this.MOUSE_DOLLY:
100267
+ case this.MOUSE_PAN:
100268
+ return true;
100269
+ default:
100270
+ return false;
100271
+ }
100272
+ }
100273
+
100080
100274
  /**
100081
100275
  * Returns true if any keys configured for the given action are down.
100082
100276
  * @param action
@@ -100088,14 +100282,21 @@ class CameraControl extends Component {
100088
100282
  if (!keys) {
100089
100283
  return false;
100090
100284
  }
100285
+ if (keys.length === 0 && this._isMouseAction(action)) return true;
100091
100286
  if (!keyDownMap) {
100092
100287
  keyDownMap = this.scene.input.keyDown;
100093
100288
  }
100094
100289
  for (let i = 0, len = keys.length; i < len; i++) {
100095
100290
  const key = keys[i];
100096
- if (keyDownMap[key]) {
100097
- return true;
100291
+ if (!Array.isArray(key)) {
100292
+ if (keyDownMap[key] && !this._isAnyOtherKeyDown(keyDownMap, key))
100293
+ return true;
100294
+ }
100295
+ else {
100296
+ if (this._areAllKeysDown(keyDownMap, key) && !this._isAnyOtherKeyDown(keyDownMap, key))
100297
+ return true;
100098
100298
  }
100299
+
100099
100300
  }
100100
100301
  return false;
100101
100302
  }
@@ -100268,6 +100469,37 @@ class CameraControl extends Component {
100268
100469
  this._configs.pointerEnabled = !!value;
100269
100470
  }
100270
100471
 
100472
+ /**
100473
+ * Sets the cursor to be used when a particular action is being performed.
100474
+ *
100475
+ * Accepted actions are:
100476
+ *
100477
+ * * "dollyForward" - when the camera is dollying in the forward direction
100478
+ * * "dollyBackward" - when the camera is dollying in the backward direction
100479
+ * * "pan" - when the camera is being panned
100480
+ * * "rotate" - when the camera is being rotated
100481
+ *
100482
+ * @param {String} action
100483
+ * @param {String} style
100484
+ */
100485
+ setCursorStyle(action, style) {
100486
+ if (Object.prototype.hasOwnProperty.call(this._cursors, action)) {
100487
+ this._cursors = { ...this._cursors, [action]: style };
100488
+ }
100489
+ else
100490
+ console.warn(`Action '${action}' is not valid for cursor styles.`);
100491
+ }
100492
+
100493
+ /**
100494
+ * Gets the current style for a particular action.
100495
+ *
100496
+ * @param {String} action To get the style for
100497
+ * @returns {String} style set on the cursor for action
100498
+ */
100499
+ getCursorStyle(action) {
100500
+ return this._cursors[action] || null;
100501
+ }
100502
+
100271
100503
  _reset() {
100272
100504
  for (let i = 0, len = this._handlers.length; i < len; i++) {
100273
100505
  const handler = this._handlers[i];
@@ -100531,6 +100763,16 @@ class CameraControl extends Component {
100531
100763
  */
100532
100764
  set panRightClick(value) {
100533
100765
  this._configs.panRightClick = value !== false;
100766
+ const panKeyMap = this._keyMap[this.MOUSE_PAN];
100767
+ if (panKeyMap && panKeyMap.length > 0) {
100768
+ const input = this.scene.input;
100769
+ for (let i = 0, len = panKeyMap.length; i < len; i++) {
100770
+ if (this._configs.panRightClick && panKeyMap[i] === input.MOUSE_MIDDLE_BUTTON)
100771
+ this._keyMap[this.MOUSE_PAN][i] = input.MOUSE_RIGHT_BUTTON;
100772
+ else if (!this._configs.panRightClick && panKeyMap[i] === input.MOUSE_RIGHT_BUTTON)
100773
+ this._keyMap[this.MOUSE_PAN][i] = input.MOUSE_MIDDLE_BUTTON;
100774
+ }
100775
+ }
100534
100776
  }
100535
100777
 
100536
100778
  /**
@@ -110465,19 +110707,15 @@ class Viewer {
110465
110707
 
110466
110708
  for (let i = 0, len = pluginContainerElements.length; i < len; i++) {
110467
110709
  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
110710
  await html2canvas(containerElement, {
110475
110711
  canvas: snapshotCanvas,
110476
110712
  backgroundColor: null,
110477
- x: off[0],
110478
- y: off[1],
110479
- scale
110713
+ scale: snapshotCanvas.width / containerElement.clientWidth
110480
110714
  });
110715
+ // Reverts translation and scaling applied to the snapshotCanvas's context
110716
+ // by the html2canvas call (inside the ForeignObjectRenderer's constructor)
110717
+ // (implemented to compensate XCD-153 issue)
110718
+ snapshotCanvas.getContext("2d").resetTransform();
110481
110719
  }
110482
110720
  if (!params.includeGizmos) {
110483
110721
  this.sendToPlugins("snapshotFinished");
@@ -123725,9 +123963,10 @@ class StoreyViewsPlugin extends Plugin {
123725
123963
  * @param {Number[]} worldPos 3D World-space position.
123726
123964
  * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123727
123965
  */
123728
- getStoreyContainingWorldPos(worldPos) {
123729
- for (var storeyId in this.storeys) {
123730
- const storey = this.storeys[storeyId];
123966
+ getStoreyContainingWorldPos(worldPos, modelId = null) {
123967
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
123968
+ for (let storeyId in storeys) {
123969
+ const storey = storeys[storeyId];
123731
123970
  if (math.point3AABB3AbsoluteIntersect(storey.storeyAABB, worldPos)) {
123732
123971
  return storeyId;
123733
123972
  }
@@ -123741,9 +123980,10 @@ class StoreyViewsPlugin extends Plugin {
123741
123980
  * @param {Number[]} worldPos 3D World-space position.
123742
123981
  * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123743
123982
  */
123744
- getStoreyInVerticalRange(worldPos) {
123745
- for (let storeyId in this.storeys) {
123746
- const storey = this.storeys[storeyId];
123983
+ getStoreyInVerticalRange(worldPos, modelId = null) {
123984
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
123985
+ for (let storeyId in storeys) {
123986
+ const storey = storeys[storeyId];
123747
123987
  const aabb = [0, 0, 0, 0, 0, 0], pos = [0, 0, 0];
123748
123988
  aabb[1] = storey.storeyAABB[1];
123749
123989
  aabb[4] = storey.storeyAABB[4];
@@ -123761,12 +124001,14 @@ class StoreyViewsPlugin extends Plugin {
123761
124001
  * @param {Number[]} worldPos 3D World-space position.
123762
124002
  * @returns {String} ID of the lowest/highest story or null.
123763
124003
  */
123764
- isPositionAboveOrBelowBuilding(worldPos) {
123765
- const keys = Object.keys(this.storeys);
124004
+ isPositionAboveOrBelowBuilding(worldPos, modelId = null) {
124005
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
124006
+ const keys = Object.keys(storeys);
124007
+ if(keys.length <= 0) return null;
123766
124008
  const ids = [keys[0], keys[keys.length - 1]];
123767
- if (worldPos[1] < this.storeys[ids[0]].storeyAABB[1])
124009
+ if (worldPos[1] < storeys[ids[0]].storeyAABB[1])
123768
124010
  return ids[0];
123769
- else if (worldPos[1] > this.storeys[ids[1]].storeyAABB[4])
124011
+ else if (worldPos[1] > storeys[ids[1]].storeyAABB[4])
123770
124012
  return ids[1];
123771
124013
  return null;
123772
124014
  }
@@ -123890,8 +124132,8 @@ class StoreyViewsPlugin extends Plugin {
123890
124132
 
123891
124133
  if (storey1MetaObject && (storey1MetaObject.attributes && storey1MetaObject.attributes.elevation !== undefined) &&
123892
124134
  storey2MetaObject && (storey2MetaObject.attributes && storey2MetaObject.attributes.elevation !== undefined)) {
123893
- const elevation1 = storey1MetaObject.attributes.elevation;
123894
- const elevation2 = storey2MetaObject.attributes.elevation;
124135
+ const elevation1 = Number.parseFloat(storey1MetaObject.attributes.elevation);
124136
+ const elevation2 = Number.parseFloat(storey2MetaObject.attributes.elevation);
123895
124137
  if (elevation1 > elevation2) {
123896
124138
  return -1;
123897
124139
  }
@@ -123910,6 +124152,12 @@ class StoreyViewsPlugin extends Plugin {
123910
124152
  }
123911
124153
  });
123912
124154
  }
124155
+
124156
+ _filterStoreys(modelId) {
124157
+ return Object.fromEntries(
124158
+ Object.entries(this.storeys).filter(([_, value]) => value.modelId === modelId)
124159
+ );
124160
+ }
123913
124161
  }
123914
124162
 
123915
124163
  const zeroVec = new Float64Array([0, 0, 1]);
@@ -127496,8 +127744,8 @@ class TreeViewPlugin extends Plugin {
127496
127744
 
127497
127745
  if (storey1MetaObject && (storey1MetaObject.attributes && storey1MetaObject.attributes.elevation !== undefined) &&
127498
127746
  storey2MetaObject && (storey2MetaObject.attributes && storey2MetaObject.attributes.elevation !== undefined)) {
127499
- const elevation1 = storey1MetaObject.attributes.elevation;
127500
- const elevation2 = storey2MetaObject.attributes.elevation;
127747
+ const elevation1 = Number.parseFloat(storey1MetaObject.attributes.elevation);
127748
+ const elevation2 = Number.parseFloat(storey2MetaObject.attributes.elevation);
127501
127749
  if (elevation1 > elevation2) {
127502
127750
  return -1;
127503
127751
  }