@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.
@@ -21948,6 +21948,30 @@ class Input extends Component {
21948
21948
  */
21949
21949
  this.KEY_SPACE = 32;
21950
21950
 
21951
+ /**
21952
+ * Code for the left mouse button.
21953
+ * @property MOUSE_LEFT_BUTTON
21954
+ * @final
21955
+ * @type {Number}
21956
+ */
21957
+ this.MOUSE_LEFT_BUTTON = 260;
21958
+
21959
+ /**
21960
+ * Code for the middle mouse button.
21961
+ * @property MOUSE_MIDDLE_BUTTON
21962
+ * @final
21963
+ * @type {Number}
21964
+ */
21965
+ this.MOUSE_MIDDLE_BUTTON = 261;
21966
+
21967
+ /**
21968
+ * Code for the right mouse button.
21969
+ * @property MOUSE_RIGHT_BUTTON
21970
+ * @final
21971
+ * @type {Number}
21972
+ */
21973
+ this.MOUSE_RIGHT_BUTTON = 262;
21974
+
21951
21975
  /**
21952
21976
  * The canvas element that mouse and keyboards are bound to.
21953
21977
  *
@@ -61827,7 +61851,7 @@ class VBOInstancingTrianglesLayer {
61827
61851
  state.indicesBuf = new ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.indices), geometry.indices.length, 1, gl.STATIC_DRAW);
61828
61852
  state.numIndices = geometry.indices.length;
61829
61853
  }
61830
- if (geometry.primitive === "triangles" || geometry.primitive === "solid" || geometry.primitive === "surface") {
61854
+ if (geometry.edgeIndices && geometry.edgeIndices.length > 0) {
61831
61855
  state.edgeIndicesBuf = new ArrayBuf(gl, gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(geometry.edgeIndices), geometry.edgeIndices.length, 1, gl.STATIC_DRAW);
61832
61856
  }
61833
61857
 
@@ -97406,6 +97430,7 @@ class MousePanRotateDollyHandler {
97406
97430
  this._scene = scene;
97407
97431
 
97408
97432
  const pickController = controllers.pickController;
97433
+ const cameraControl = controllers.cameraControl;
97409
97434
 
97410
97435
  let lastX = 0;
97411
97436
  let lastY = 0;
@@ -97442,7 +97467,6 @@ class MousePanRotateDollyHandler {
97442
97467
  });
97443
97468
 
97444
97469
  function setMousedownState(pick = true) {
97445
- canvas.style.cursor = "move";
97446
97470
  setMousedownPositions();
97447
97471
  if (pick) {
97448
97472
  setMousedownPick();
@@ -97470,6 +97494,15 @@ class MousePanRotateDollyHandler {
97470
97494
  }
97471
97495
  }
97472
97496
 
97497
+ function isPanning() {
97498
+ return cameraControl._isKeyDownForAction(cameraControl.MOUSE_PAN, keyDown);
97499
+ }
97500
+
97501
+ function isRotating() {
97502
+ return cameraControl._isKeyDownForAction(cameraControl.MOUSE_ROTATE, keyDown);
97503
+ }
97504
+
97505
+
97473
97506
  canvas.addEventListener("mousedown", this._mouseDownHandler = (e) => {
97474
97507
 
97475
97508
  if (!(configs.active && configs.pointerEnabled)) {
@@ -97483,12 +97516,14 @@ class MousePanRotateDollyHandler {
97483
97516
  if (keyDown[scene.input.KEY_SHIFT] || configs.planView) {
97484
97517
 
97485
97518
  mouseDownLeft = true;
97519
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = true;
97486
97520
 
97487
97521
  setMousedownState();
97488
97522
 
97489
97523
  } else {
97490
97524
 
97491
97525
  mouseDownLeft = true;
97526
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = true;
97492
97527
 
97493
97528
  setMousedownState(false);
97494
97529
  }
@@ -97498,6 +97533,7 @@ class MousePanRotateDollyHandler {
97498
97533
  case 2: // Middle/both buttons
97499
97534
 
97500
97535
  mouseDownMiddle = true;
97536
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = true;
97501
97537
 
97502
97538
  setMousedownState();
97503
97539
 
@@ -97506,6 +97542,7 @@ class MousePanRotateDollyHandler {
97506
97542
  case 3: // Right button
97507
97543
 
97508
97544
  mouseDownRight = true;
97545
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = true;
97509
97546
 
97510
97547
  if (configs.panRightClick) {
97511
97548
 
@@ -97535,7 +97572,8 @@ class MousePanRotateDollyHandler {
97535
97572
  const x = states.pointerCanvasPos[0];
97536
97573
  const y = states.pointerCanvasPos[1];
97537
97574
 
97538
- const panning = keyDown[scene.input.KEY_SHIFT] || configs.planView || (!configs.panRightClick && mouseDownMiddle) || (configs.panRightClick && mouseDownRight);
97575
+ const panning = isPanning();
97576
+ const rotating = isRotating();
97539
97577
 
97540
97578
  const xDelta = document.pointerLockElement ? e.movementX : (x - lastX);
97541
97579
  const yDelta = document.pointerLockElement ? e.movementY : (y - lastY);
@@ -97560,7 +97598,7 @@ class MousePanRotateDollyHandler {
97560
97598
  updates.panDeltaY += 0.5 * camera.ortho.scale * (yDelta / canvasHeight);
97561
97599
  }
97562
97600
 
97563
- } else if (mouseDownLeft && !mouseDownMiddle && !mouseDownRight) {
97601
+ } else if (rotating) {
97564
97602
 
97565
97603
  if (!configs.planView) { // No rotating in plan-view mode
97566
97604
 
@@ -97601,16 +97639,25 @@ class MousePanRotateDollyHandler {
97601
97639
  mouseDownLeft = false;
97602
97640
  mouseDownMiddle = false;
97603
97641
  mouseDownRight = false;
97642
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97643
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97644
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97604
97645
  break;
97605
97646
  case 2: // Middle/both buttons
97606
97647
  mouseDownLeft = false;
97607
97648
  mouseDownMiddle = false;
97608
97649
  mouseDownRight = false;
97650
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97651
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97652
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97609
97653
  break;
97610
97654
  case 3: // Right button
97611
97655
  mouseDownLeft = false;
97612
97656
  mouseDownMiddle = false;
97613
97657
  mouseDownRight = false;
97658
+ keyDown[scene.input.MOUSE_LEFT_BUTTON] = false;
97659
+ keyDown[scene.input.MOUSE_MIDDLE_BUTTON] = false;
97660
+ keyDown[scene.input.MOUSE_RIGHT_BUTTON] = false;
97614
97661
  break;
97615
97662
  }
97616
97663
  });
@@ -97648,7 +97695,7 @@ class MousePanRotateDollyHandler {
97648
97695
  let secsNowLast = null;
97649
97696
 
97650
97697
  canvas.addEventListener("wheel", this._mouseWheelHandler = (e) => {
97651
- if (!(configs.active && configs.pointerEnabled && configs.zoomOnMouseWheel)) {
97698
+ if (!(configs.active && configs.pointerEnabled && configs.zoomOnMouseWheel && cameraControl._isKeyDownForAction(cameraControl.MOUSE_DOLLY, keyDown))) {
97652
97699
  return;
97653
97700
  }
97654
97701
  const secsNow = performance.now() / 1000.0;
@@ -97829,6 +97876,7 @@ class MousePickHandler {
97829
97876
  this._clicks = 0;
97830
97877
  this._timeout = null;
97831
97878
  this._lastPickedEntityId = null;
97879
+ this._lastClickedWorldPos = null;
97832
97880
 
97833
97881
  let leftDown = false;
97834
97882
  let rightDown = false;
@@ -97978,11 +98026,16 @@ class MousePickHandler {
97978
98026
  if (pickResult && pickResult.worldPos) {
97979
98027
  pivotController.setPivotPos(pickResult.worldPos);
97980
98028
  pivotController.startPivot();
98029
+ this._lastClickedWorldPos = pickResult.worldPos.slice();
97981
98030
  } else {
97982
98031
  if (configs.smartPivot) {
97983
98032
  pivotController.setCanvasPivotPos(states.pointerCanvasPos);
97984
98033
  } else {
97985
- pivotController.setPivotPos(scene.camera.look);
98034
+ if (this._lastClickedWorldPos) {
98035
+ pivotController.setPivotPos(this._lastClickedWorldPos);
98036
+ } else {
98037
+ pivotController.setPivotPos(scene.camera.look);
98038
+ }
97986
98039
  }
97987
98040
  pivotController.startPivot();
97988
98041
  }
@@ -98204,7 +98257,7 @@ class KeyboardPanRotateDollyHandler {
98204
98257
 
98205
98258
  const keyDownMap = [];
98206
98259
 
98207
- const canvas = scene.canvas.canvas;
98260
+ scene.canvas.canvas;
98208
98261
 
98209
98262
  let mouseMovedSinceLastKeyboardDolly = true;
98210
98263
 
@@ -98220,10 +98273,6 @@ class KeyboardPanRotateDollyHandler {
98220
98273
  return;
98221
98274
  }
98222
98275
  keyDownMap[keyCode] = true;
98223
-
98224
- if (keyCode === input.KEY_SHIFT) {
98225
- canvas.style.cursor = "move";
98226
- }
98227
98276
  });
98228
98277
 
98229
98278
  this._onSceneKeyUp = input.on("keyup", (keyCode) => {
@@ -98232,10 +98281,6 @@ class KeyboardPanRotateDollyHandler {
98232
98281
  }
98233
98282
  keyDownMap[keyCode] = false;
98234
98283
 
98235
- if (keyCode === input.KEY_SHIFT) {
98236
- canvas.style.cursor = null;
98237
- }
98238
-
98239
98284
  if (controllers.pivotController.getPivoting()) {
98240
98285
  controllers.pivotController.endPivot();
98241
98286
  }
@@ -98392,6 +98437,7 @@ class CameraUpdater {
98392
98437
  const pickController = controllers.pickController;
98393
98438
  const pivotController = controllers.pivotController;
98394
98439
  const panController = controllers.panController;
98440
+ const cameraControl = controllers.cameraControl;
98395
98441
 
98396
98442
  let countDown = SCALE_DOLLY_EACH_FRAME; // Decrements on each tick
98397
98443
  let dollyDistFactor = 1.0; // Calculated when countDown is zero
@@ -98516,7 +98562,7 @@ class CameraUpdater {
98516
98562
  updates.rotateDeltaX *= configs.rotationInertia;
98517
98563
  updates.rotateDeltaY *= configs.rotationInertia;
98518
98564
 
98519
- cursorType = "grabbing";
98565
+ cursorType = cameraControl._cursors.rotate;
98520
98566
  }
98521
98567
 
98522
98568
  //----------------------------------------------------------------------------------------------------------
@@ -98582,7 +98628,7 @@ class CameraUpdater {
98582
98628
  camera.pan(vec);
98583
98629
  }
98584
98630
 
98585
- cursorType = "grabbing";
98631
+ cursorType = cameraControl._cursors.pan;
98586
98632
  }
98587
98633
 
98588
98634
  updates.panDeltaX *= configs.panInertia;
@@ -98596,9 +98642,9 @@ class CameraUpdater {
98596
98642
  if (dollyDeltaForDist !== 0) {
98597
98643
 
98598
98644
  if (dollyDeltaForDist < 0) {
98599
- cursorType = "zoom-in";
98645
+ cursorType = cameraControl._cursors.dollyForward;
98600
98646
  } else {
98601
- cursorType = "zoom-out";
98647
+ cursorType = cameraControl._cursors.dollyBackward;
98602
98648
  }
98603
98649
 
98604
98650
  if (configs.firstPerson) {
@@ -99698,6 +99744,12 @@ const DEFAULT_SNAP_EDGE = true;
99698
99744
  * keyMap[cameraControl.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
99699
99745
  * keyMap[cameraControl.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
99700
99746
  * keyMap[cameraControl.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
99747
+ * keyMap[cameraControl.MOUSE_PAN] = [[input.KEY_SHIFT, input.MOUSE_LEFT_BUTTON]];
99748
+ * keyMap[cameraControl.MOUSE_ROTATE] = [
99749
+ * [input.KEY_SHIFT, input.MOUSE_MIDDLE_BUTTON],
99750
+ * [input.KEY_SHIFT, input.MOUSE_RIGHT_BUTTON]
99751
+ * ]
99752
+ * keyMap[cameraControl.MOUSE_DOLLY] = [[input.KEY_CTRL, input.MOUSE_RIGHT_BUTTON]];
99701
99753
  *
99702
99754
  * cameraControl.keyMap = keyMap;
99703
99755
  * ````
@@ -99716,6 +99768,70 @@ const DEFAULT_SNAP_EDGE = true;
99716
99768
  *
99717
99769
  * * ````"qwerty"````
99718
99770
  * * ````"azerty"````
99771
+ *
99772
+ * ## Basic Keyboard Mapping
99773
+ * * ````"OR" Relation````
99774
+ * Set multiple keys to trigger an action if any one is pressed:
99775
+ *
99776
+ * ````javascript
99777
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [input.KEY_S, input.KEY_SUBTRACT];
99778
+ * ````
99779
+ *
99780
+ * If either ````KEY_S```` or ````KEY_SUBTRACT```` is pressed, the camera will dolly backward.
99781
+ *
99782
+ * * ````"AND" Relation````
99783
+ * To require all keys in a combination to be pressed:
99784
+ *
99785
+ * ````javascript
99786
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [[input.KEY_S, input.KEY_SUBTRACT]];
99787
+ * ````
99788
+ *
99789
+ * The camera will dolly backward if ````both KEY_S```` and ````KEY_SUBTRACT```` are pressed.
99790
+ *
99791
+ * * ````Mix "AND" and "OR" Relation````
99792
+ * Use a combination of keys and groups for flexibility:
99793
+ *
99794
+ * ````javascript
99795
+ * keyMap[cameraControl.DOLLY_BACKWARDS] = [
99796
+ * [input.KEY_S, input.KEY_SUBTRACT], // 'And' group
99797
+ * input.KEY_SHIFT // 'Or' with previous
99798
+ * ];
99799
+ * ````
99800
+ *
99801
+ * The camera will dolly backward if ````KEY_S```` + ````KEY_SUBTRACT```` are pressed together, or if ````KEY_SHIFT```` is pressed.
99802
+ *
99803
+ * ## Special Mouse Actions
99804
+ * Certain actions support combinations with specific mouse buttons or events:
99805
+ *
99806
+ * * ````MOUSE_PAN````
99807
+ * For panning with a key and mouse movement:
99808
+ *
99809
+ * ````javascript
99810
+ * keyMap[cameraControl.MOUSE_PAN] = [[input.KEY_SHIFT, input.MOUSE_LEFT_BUTTON]];
99811
+ * ````
99812
+ *
99813
+ * Panning is triggered by pressing ````KEY_SHIFT```` + ````MOUSE_LEFT_BUTTON```` while moving the mouse.
99814
+ *
99815
+ * * ````MOUSE_ROTATE````
99816
+ * Similar to panning, rotation can be configured with key and mouse button combinations:
99817
+ *
99818
+ * ````javascript
99819
+ * keyMap[cameraControl.MOUSE_ROTATE] = [[input.KEY_CTRL, input.MOUSE_LEFT_BUTTON]];
99820
+ * ````
99821
+ *
99822
+ * Rotation is triggered by pressing ````KEY_CTRL```` + ````MOUSE_LEFT_BUTTON```` during mouse movement.
99823
+ *
99824
+ * * ````MOUSE_DOLLY````
99825
+ * Dolly with mouse wheel scrolling and optional key combinations:
99826
+ *
99827
+ * ````javascript
99828
+ * keyMap[cameraControl.MOUSE_DOLLY] = [[input.KEY_ALT]];
99829
+ * ````
99830
+ *
99831
+ * Dolly action occurs when scrolling the mouse wheel with ````KEY_ALT```` held (no need to specify MOUSE_WHEEL).
99832
+ *
99833
+ * ## Special Mouse Actions
99834
+ * Use ````input.MOUSE_LEFT_BUTTON````, ````input.MOUSE_MIDDLE_BUTTON````, and ````input.MOUSE_RIGHT_BUTTON```` in combinations only for camera movements involving the mouse.
99719
99835
  */
99720
99836
  class CameraControl extends Component {
99721
99837
 
@@ -99853,6 +99969,27 @@ class CameraControl extends Component {
99853
99969
  */
99854
99970
  this.AXIS_VIEW_BOTTOM = 17;
99855
99971
 
99972
+ /**
99973
+ * Identifies the XX action.
99974
+ * @final
99975
+ * @type {Number}
99976
+ */
99977
+ this.MOUSE_PAN = 18;
99978
+
99979
+ /**
99980
+ * Identifies the XX action.
99981
+ * @final
99982
+ * @type {Number}
99983
+ */
99984
+ this.MOUSE_ROTATE = 19;
99985
+
99986
+ /**
99987
+ * Identifies the XX action.
99988
+ * @final
99989
+ * @type {Number}
99990
+ */
99991
+ this.MOUSE_DOLLY = 20;
99992
+
99856
99993
  this._keyMap = {}; // Maps key codes to the above actions
99857
99994
 
99858
99995
  this.scene.canvas.canvas.oncontextmenu = (e) => {
@@ -99968,6 +100105,13 @@ class CameraControl extends Component {
99968
100105
  new KeyboardPanRotateDollyHandler(this.scene, this._controllers, this._configs, this._states, this._updates)
99969
100106
  ];
99970
100107
 
100108
+ this._cursors = {
100109
+ dollyForward: "zoom-in",
100110
+ dollyBackward: "zoom-out",
100111
+ rotate: 'grabbing',
100112
+ pan: 'move',
100113
+ };
100114
+
99971
100115
  // Applies scheduled updates to the Camera on each Scene "tick" event
99972
100116
 
99973
100117
  this._cameraUpdater = new CameraUpdater(this.scene, this._controllers, this._configs, this._states, this._updates);
@@ -100041,6 +100185,12 @@ class CameraControl extends Component {
100041
100185
  keyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
100042
100186
  keyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
100043
100187
  keyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
100188
+ keyMap[this.MOUSE_PAN] = [
100189
+ [input.MOUSE_LEFT_BUTTON, input.KEY_SHIFT],
100190
+ this._configs.panRightClick ? input.MOUSE_RIGHT_BUTTON : input.MOUSE_MIDDLE_BUTTON
100191
+ ];
100192
+ keyMap[this.MOUSE_ROTATE] = [input.MOUSE_LEFT_BUTTON];
100193
+ keyMap[this.MOUSE_DOLLY] = [];
100044
100194
  break;
100045
100195
 
100046
100196
  case "azerty":
@@ -100062,6 +100212,12 @@ class CameraControl extends Component {
100062
100212
  keyMap[this.AXIS_VIEW_FRONT] = [input.KEY_NUM_4];
100063
100213
  keyMap[this.AXIS_VIEW_TOP] = [input.KEY_NUM_5];
100064
100214
  keyMap[this.AXIS_VIEW_BOTTOM] = [input.KEY_NUM_6];
100215
+ keyMap[this.MOUSE_PAN] = [
100216
+ [input.MOUSE_LEFT_BUTTON, input.KEY_SHIFT],
100217
+ this._configs.panRightClick ? input.MOUSE_RIGHT_BUTTON : input.MOUSE_MIDDLE_BUTTON
100218
+ ];
100219
+ keyMap[this.MOUSE_ROTATE] = [input.MOUSE_LEFT_BUTTON];
100220
+ keyMap[this.MOUSE_DOLLY] = [];
100065
100221
  break;
100066
100222
  }
100067
100223
 
@@ -100081,6 +100237,44 @@ class CameraControl extends Component {
100081
100237
  return this._keyMap;
100082
100238
  }
100083
100239
 
100240
+ _areAllKeysDown(keyDownMap, keys) {
100241
+ if (!keys || keys.length <= 0) {
100242
+ return true;
100243
+ }
100244
+ if (!keyDownMap) {
100245
+ return false;
100246
+ }
100247
+ for (let i = 0, len = keys.length; i < len; i++) {
100248
+ const key = keys[i];
100249
+ if (!keyDownMap[key])
100250
+ return false;
100251
+ }
100252
+ return true;
100253
+ }
100254
+
100255
+ _isAnyOtherKeyDown(keyDownMap, keyMap) {
100256
+ for (let i = 0, len = keyDownMap.length; i < len; i++) {
100257
+ if (keyDownMap[i]) {
100258
+ if (Array.isArray(keyMap)) {
100259
+ if (keyMap.indexOf(i) < 0) return true;
100260
+ }
100261
+ else if (i !== keyMap) return true;
100262
+ }
100263
+ }
100264
+ return false;
100265
+ }
100266
+
100267
+ _isMouseAction(action) {
100268
+ switch (action) {
100269
+ case this.MOUSE_ROTATE:
100270
+ case this.MOUSE_DOLLY:
100271
+ case this.MOUSE_PAN:
100272
+ return true;
100273
+ default:
100274
+ return false;
100275
+ }
100276
+ }
100277
+
100084
100278
  /**
100085
100279
  * Returns true if any keys configured for the given action are down.
100086
100280
  * @param action
@@ -100092,14 +100286,21 @@ class CameraControl extends Component {
100092
100286
  if (!keys) {
100093
100287
  return false;
100094
100288
  }
100289
+ if (keys.length === 0 && this._isMouseAction(action)) return true;
100095
100290
  if (!keyDownMap) {
100096
100291
  keyDownMap = this.scene.input.keyDown;
100097
100292
  }
100098
100293
  for (let i = 0, len = keys.length; i < len; i++) {
100099
100294
  const key = keys[i];
100100
- if (keyDownMap[key]) {
100101
- return true;
100295
+ if (!Array.isArray(key)) {
100296
+ if (keyDownMap[key] && !this._isAnyOtherKeyDown(keyDownMap, key))
100297
+ return true;
100298
+ }
100299
+ else {
100300
+ if (this._areAllKeysDown(keyDownMap, key) && !this._isAnyOtherKeyDown(keyDownMap, key))
100301
+ return true;
100102
100302
  }
100303
+
100103
100304
  }
100104
100305
  return false;
100105
100306
  }
@@ -100272,6 +100473,37 @@ class CameraControl extends Component {
100272
100473
  this._configs.pointerEnabled = !!value;
100273
100474
  }
100274
100475
 
100476
+ /**
100477
+ * Sets the cursor to be used when a particular action is being performed.
100478
+ *
100479
+ * Accepted actions are:
100480
+ *
100481
+ * * "dollyForward" - when the camera is dollying in the forward direction
100482
+ * * "dollyBackward" - when the camera is dollying in the backward direction
100483
+ * * "pan" - when the camera is being panned
100484
+ * * "rotate" - when the camera is being rotated
100485
+ *
100486
+ * @param {String} action
100487
+ * @param {String} style
100488
+ */
100489
+ setCursorStyle(action, style) {
100490
+ if (Object.prototype.hasOwnProperty.call(this._cursors, action)) {
100491
+ this._cursors = { ...this._cursors, [action]: style };
100492
+ }
100493
+ else
100494
+ console.warn(`Action '${action}' is not valid for cursor styles.`);
100495
+ }
100496
+
100497
+ /**
100498
+ * Gets the current style for a particular action.
100499
+ *
100500
+ * @param {String} action To get the style for
100501
+ * @returns {String} style set on the cursor for action
100502
+ */
100503
+ getCursorStyle(action) {
100504
+ return this._cursors[action] || null;
100505
+ }
100506
+
100275
100507
  _reset() {
100276
100508
  for (let i = 0, len = this._handlers.length; i < len; i++) {
100277
100509
  const handler = this._handlers[i];
@@ -100535,6 +100767,16 @@ class CameraControl extends Component {
100535
100767
  */
100536
100768
  set panRightClick(value) {
100537
100769
  this._configs.panRightClick = value !== false;
100770
+ const panKeyMap = this._keyMap[this.MOUSE_PAN];
100771
+ if (panKeyMap && panKeyMap.length > 0) {
100772
+ const input = this.scene.input;
100773
+ for (let i = 0, len = panKeyMap.length; i < len; i++) {
100774
+ if (this._configs.panRightClick && panKeyMap[i] === input.MOUSE_MIDDLE_BUTTON)
100775
+ this._keyMap[this.MOUSE_PAN][i] = input.MOUSE_RIGHT_BUTTON;
100776
+ else if (!this._configs.panRightClick && panKeyMap[i] === input.MOUSE_RIGHT_BUTTON)
100777
+ this._keyMap[this.MOUSE_PAN][i] = input.MOUSE_MIDDLE_BUTTON;
100778
+ }
100779
+ }
100538
100780
  }
100539
100781
 
100540
100782
  /**
@@ -110469,19 +110711,15 @@ class Viewer {
110469
110711
 
110470
110712
  for (let i = 0, len = pluginContainerElements.length; i < len; i++) {
110471
110713
  const containerElement = pluginContainerElements[i];
110472
- //only calculate the scale for first plugin
110473
- //for all others keep the scale 1 otherwise it will keep multiplying the scale with the base scale of canvas
110474
- //resulting in increase/decreased size for the the canvas that is being overlapped
110475
- const scale = i == 0 ? snapshotCanvas.width / containerElement.clientWidth : 1;
110476
- const off = math.vec2([ 0, 0 ]);
110477
- transformToNode(canvas, containerElement, off);
110478
110714
  await html2canvas(containerElement, {
110479
110715
  canvas: snapshotCanvas,
110480
110716
  backgroundColor: null,
110481
- x: off[0],
110482
- y: off[1],
110483
- scale
110717
+ scale: snapshotCanvas.width / containerElement.clientWidth
110484
110718
  });
110719
+ // Reverts translation and scaling applied to the snapshotCanvas's context
110720
+ // by the html2canvas call (inside the ForeignObjectRenderer's constructor)
110721
+ // (implemented to compensate XCD-153 issue)
110722
+ snapshotCanvas.getContext("2d").resetTransform();
110485
110723
  }
110486
110724
  if (!params.includeGizmos) {
110487
110725
  this.sendToPlugins("snapshotFinished");
@@ -123729,9 +123967,10 @@ class StoreyViewsPlugin extends Plugin {
123729
123967
  * @param {Number[]} worldPos 3D World-space position.
123730
123968
  * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123731
123969
  */
123732
- getStoreyContainingWorldPos(worldPos) {
123733
- for (var storeyId in this.storeys) {
123734
- const storey = this.storeys[storeyId];
123970
+ getStoreyContainingWorldPos(worldPos, modelId = null) {
123971
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
123972
+ for (let storeyId in storeys) {
123973
+ const storey = storeys[storeyId];
123735
123974
  if (math.point3AABB3AbsoluteIntersect(storey.storeyAABB, worldPos)) {
123736
123975
  return storeyId;
123737
123976
  }
@@ -123745,9 +123984,10 @@ class StoreyViewsPlugin extends Plugin {
123745
123984
  * @param {Number[]} worldPos 3D World-space position.
123746
123985
  * @returns {String} ID of the storey containing the position, or null if the position falls outside all the storeys.
123747
123986
  */
123748
- getStoreyInVerticalRange(worldPos) {
123749
- for (let storeyId in this.storeys) {
123750
- const storey = this.storeys[storeyId];
123987
+ getStoreyInVerticalRange(worldPos, modelId = null) {
123988
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
123989
+ for (let storeyId in storeys) {
123990
+ const storey = storeys[storeyId];
123751
123991
  const aabb = [0, 0, 0, 0, 0, 0], pos = [0, 0, 0];
123752
123992
  aabb[1] = storey.storeyAABB[1];
123753
123993
  aabb[4] = storey.storeyAABB[4];
@@ -123765,12 +124005,14 @@ class StoreyViewsPlugin extends Plugin {
123765
124005
  * @param {Number[]} worldPos 3D World-space position.
123766
124006
  * @returns {String} ID of the lowest/highest story or null.
123767
124007
  */
123768
- isPositionAboveOrBelowBuilding(worldPos) {
123769
- const keys = Object.keys(this.storeys);
124008
+ isPositionAboveOrBelowBuilding(worldPos, modelId = null) {
124009
+ const storeys = modelId ? this._filterStoreys(modelId) : this.storeys;
124010
+ const keys = Object.keys(storeys);
124011
+ if(keys.length <= 0) return null;
123770
124012
  const ids = [keys[0], keys[keys.length - 1]];
123771
- if (worldPos[1] < this.storeys[ids[0]].storeyAABB[1])
124013
+ if (worldPos[1] < storeys[ids[0]].storeyAABB[1])
123772
124014
  return ids[0];
123773
- else if (worldPos[1] > this.storeys[ids[1]].storeyAABB[4])
124015
+ else if (worldPos[1] > storeys[ids[1]].storeyAABB[4])
123774
124016
  return ids[1];
123775
124017
  return null;
123776
124018
  }
@@ -123894,8 +124136,8 @@ class StoreyViewsPlugin extends Plugin {
123894
124136
 
123895
124137
  if (storey1MetaObject && (storey1MetaObject.attributes && storey1MetaObject.attributes.elevation !== undefined) &&
123896
124138
  storey2MetaObject && (storey2MetaObject.attributes && storey2MetaObject.attributes.elevation !== undefined)) {
123897
- const elevation1 = storey1MetaObject.attributes.elevation;
123898
- const elevation2 = storey2MetaObject.attributes.elevation;
124139
+ const elevation1 = Number.parseFloat(storey1MetaObject.attributes.elevation);
124140
+ const elevation2 = Number.parseFloat(storey2MetaObject.attributes.elevation);
123899
124141
  if (elevation1 > elevation2) {
123900
124142
  return -1;
123901
124143
  }
@@ -123914,6 +124156,12 @@ class StoreyViewsPlugin extends Plugin {
123914
124156
  }
123915
124157
  });
123916
124158
  }
124159
+
124160
+ _filterStoreys(modelId) {
124161
+ return Object.fromEntries(
124162
+ Object.entries(this.storeys).filter(([_, value]) => value.modelId === modelId)
124163
+ );
124164
+ }
123917
124165
  }
123918
124166
 
123919
124167
  const zeroVec = new Float64Array([0, 0, 1]);
@@ -127500,8 +127748,8 @@ class TreeViewPlugin extends Plugin {
127500
127748
 
127501
127749
  if (storey1MetaObject && (storey1MetaObject.attributes && storey1MetaObject.attributes.elevation !== undefined) &&
127502
127750
  storey2MetaObject && (storey2MetaObject.attributes && storey2MetaObject.attributes.elevation !== undefined)) {
127503
- const elevation1 = storey1MetaObject.attributes.elevation;
127504
- const elevation2 = storey2MetaObject.attributes.elevation;
127751
+ const elevation1 = Number.parseFloat(storey1MetaObject.attributes.elevation);
127752
+ const elevation2 = Number.parseFloat(storey2MetaObject.attributes.elevation);
127505
127753
  if (elevation1 > elevation2) {
127506
127754
  return -1;
127507
127755
  }