@xeokit/xeokit-sdk 2.6.64 → 2.6.65

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 (27) hide show
  1. package/dist/xeokit-sdk.cjs.js +123 -205
  2. package/dist/xeokit-sdk.es.js +123 -205
  3. package/dist/xeokit-sdk.es5.js +52 -63
  4. package/dist/xeokit-sdk.min.cjs.js +5 -5
  5. package/dist/xeokit-sdk.min.es.js +5 -5
  6. package/dist/xeokit-sdk.min.es5.js +4 -4
  7. package/package.json +1 -1
  8. package/src/extras/PointerLens/PointerLens.js +27 -46
  9. package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +29 -20
  10. package/src/plugins/AnnotationsPlugin/Annotation.js +3 -0
  11. package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +27 -33
  12. package/src/plugins/SectionPlanesPlugin/Control.js +26 -115
  13. package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +10 -4
  14. package/src/plugins/lib/html/MenuEvent.js +3 -1
  15. package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +1 -2
  16. package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +1 -1
  17. package/types/plugins/AngleMeasurementsPlugin/index.d.ts +2 -1
  18. package/types/plugins/CityJSONLoaderPlugin/CityJSONLoaderPlugin.d.ts +4 -0
  19. package/types/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.d.ts +121 -0
  20. package/types/plugins/DotBIMLoaderPlugin/index.d.ts +1 -0
  21. package/types/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.d.ts +4 -0
  22. package/types/plugins/LASLoaderPlugin/LASLoaderPlugin.d.ts +4 -0
  23. package/types/plugins/STLLoaderPlugin/STLLoaderPlugin.d.ts +4 -0
  24. package/types/plugins/TreeViewPlugin/TreeViewPlugin.d.ts +4 -0
  25. package/types/plugins/WebIFCLoaderPlugin/WebIFCLoaderPlugin.d.ts +4 -0
  26. package/types/plugins/XKTLoaderPlugin/XKTLoaderPlugin.d.ts +19 -1
  27. package/types/plugins/index.d.ts +1 -0
@@ -1055,13 +1055,10 @@ class PointerLens {
1055
1055
  this.scene = this.viewer.scene;
1056
1056
 
1057
1057
  this._lensCursorDiv = document.createElement('div');
1058
- this.viewer.scene.canvas.canvas.parentNode.insertBefore(this._lensCursorDiv, this.viewer.scene.canvas.canvas);
1059
- this._lensCursorDiv.style.background = "pink";
1060
- this._lensCursorDiv.style.border = "2px solid red";
1061
- this._lensCursorDiv.style.borderRadius = "20px";
1062
- this._lensCursorDiv.style.width = "10px";
1063
- this._lensCursorDiv.style.height = "10px";
1064
- this._lensCursorDiv.style.margin = "-200px -200px";
1058
+ this._lensParams = { canvasSize: 300, cursorBorder: 2, cursorSize: 10 };
1059
+ this._lensCursorDiv.style.borderRadius = "50%";
1060
+ this._lensCursorDiv.style.width = this._lensParams.cursorSize + "px";
1061
+ this._lensCursorDiv.style.height = this._lensParams.cursorSize + "px";
1065
1062
  this._lensCursorDiv.style.zIndex = "100000";
1066
1063
  this._lensCursorDiv.style.position = "absolute";
1067
1064
  this._lensCursorDiv.style.pointerEvents = "none";
@@ -1074,8 +1071,8 @@ class PointerLens {
1074
1071
  this._lensContainer.style.background = "white";
1075
1072
  // this._lensContainer.style.opacity = "0";
1076
1073
  this._lensContainer.style.borderRadius = "50%";
1077
- this._lensContainer.style.width = "300px";
1078
- this._lensContainer.style.height = "300px";
1074
+ this._lensContainer.style.width = this._lensParams.canvasSize + "px";
1075
+ this._lensContainer.style.height = this._lensParams.canvasSize + "px";
1079
1076
 
1080
1077
  this._lensContainer.style.zIndex = "15000";
1081
1078
  this._lensContainer.style.position = "absolute";
@@ -1087,13 +1084,14 @@ class PointerLens {
1087
1084
  // this._lensCanvas.style.background = "darkblue";
1088
1085
  this._lensCanvas.style.borderRadius = "50%";
1089
1086
 
1090
- this._lensCanvas.style.width = "300px";
1091
- this._lensCanvas.style.height = "300px";
1087
+ this._lensCanvas.style.width = this._lensParams.canvasSize + "px";
1088
+ this._lensCanvas.style.height = this._lensParams.canvasSize + "px";
1092
1089
  this._lensCanvas.style.zIndex = "15000";
1093
1090
  this._lensCanvas.style.pointerEvents = "none";
1094
1091
 
1095
1092
  document.body.appendChild(this._lensContainer);
1096
1093
  this._lensContainer.appendChild(this._lensCanvas);
1094
+ this._lensContainer.appendChild(this._lensCursorDiv);
1097
1095
 
1098
1096
  this._lensCanvasContext = this._lensCanvas.getContext('2d');
1099
1097
  this._canvasElement = this.viewer.scene.canvas.canvas;
@@ -1111,7 +1109,7 @@ class PointerLens {
1111
1109
 
1112
1110
  this._active = (cfg.active !== false);
1113
1111
  this._visible = false;
1114
- this._snapped = false;
1112
+ this.snapped = false;
1115
1113
 
1116
1114
  this._onViewerRendering = this.viewer.scene.on("rendering", () => {
1117
1115
  if (this._active && this._visible) {
@@ -1158,21 +1156,13 @@ class PointerLens {
1158
1156
  this._lensCanvas.height // destination height
1159
1157
  );
1160
1158
 
1161
- const centerLensCanvas = [
1162
- (lensRect.left + lensRect.right) / 2 - canvasRect.left,
1163
- (lensRect.top + lensRect.bottom) / 2 - canvasRect.top
1164
- ];
1159
+ const middle = this._lensParams.canvasSize / 2 - this._lensParams.cursorSize / 2 - this._lensParams.cursorBorder;
1165
1160
 
1166
- if (this._snappedCanvasPos) {
1167
- const deltaX = this._snappedCanvasPos[0] - this._canvasPos[0];
1168
- const deltaY = this._snappedCanvasPos[1] - this._canvasPos[1];
1161
+ const deltaX = this._snappedCanvasPos ? (this._snappedCanvasPos[0] - this._canvasPos[0]) : 0;
1162
+ const deltaY = this._snappedCanvasPos ? (this._snappedCanvasPos[1] - this._canvasPos[1]) : 0;
1169
1163
 
1170
- this._lensCursorDiv.style.marginLeft = `${centerLensCanvas[0] + deltaX * this._zoomLevel - 10}px`;
1171
- this._lensCursorDiv.style.marginTop = `${centerLensCanvas[1] + deltaY * this._zoomLevel - 10}px`;
1172
- } else {
1173
- this._lensCursorDiv.style.marginLeft = `${centerLensCanvas[0] - 10}px`;
1174
- this._lensCursorDiv.style.marginTop = `${centerLensCanvas[1] - 10}px`;
1175
- }
1164
+ this._lensCursorDiv.style.left = `${middle + deltaX * this._zoomLevel}px`;
1165
+ this._lensCursorDiv.style.top = `${middle + deltaY * this._zoomLevel}px`;
1176
1166
  }
1177
1167
 
1178
1168
 
@@ -1240,14 +1230,10 @@ class PointerLens {
1240
1230
  * @private
1241
1231
  */
1242
1232
  set snapped(snapped) {
1243
- this._snapped = snapped;
1244
- if (snapped) {
1245
- this._lensCursorDiv.style.background = "greenyellow";
1246
- this._lensCursorDiv.style.border = "2px solid green";
1247
- } else {
1248
- this._lensCursorDiv.style.background = "pink";
1249
- this._lensCursorDiv.style.border = "2px solid red";
1250
- }
1233
+ this._snapped = snapped;
1234
+ const [ bg, border ] = snapped ? [ "greenyellow", "green" ] : [ "pink", "red" ];
1235
+ this._lensCursorDiv.style.background = bg;
1236
+ this._lensCursorDiv.style.border = this._lensParams.cursorBorder + "px solid " + border;
1251
1237
  }
1252
1238
 
1253
1239
  /**
@@ -1259,19 +1245,19 @@ class PointerLens {
1259
1245
  get snapped() {
1260
1246
  return this._snapped;
1261
1247
  }
1262
-
1248
+
1249
+ _updateActiveVisible() {
1250
+ this._lensContainer.style.visibility = (this._active && this._visible) ? "visible" : "hidden";
1251
+ this.update();
1252
+ }
1253
+
1263
1254
  /**
1264
1255
  * Sets if this PointerLens is active.
1265
1256
  * @param active
1266
1257
  */
1267
1258
  set active(active) {
1268
1259
  this._active = active;
1269
- this._lensContainer.style.visibility = (active && this._visible) ? "visible" : "hidden";
1270
- if (!active || !this._visible ) {
1271
- this._lensCursorDiv.style.marginLeft = `-100px`;
1272
- this._lensCursorDiv.style.marginTop = `-100px`;
1273
- }
1274
- this.update();
1260
+ this._updateActiveVisible();
1275
1261
  }
1276
1262
 
1277
1263
  /**
@@ -1290,12 +1276,7 @@ class PointerLens {
1290
1276
  */
1291
1277
  set visible(visible) {
1292
1278
  this._visible = visible;
1293
- this._lensContainer.style.visibility = (visible && this._active) ? "visible" : "hidden";
1294
- if (!visible || !this._active) {
1295
- this._lensCursorDiv.style.marginLeft = `-100px`;
1296
- this._lensCursorDiv.style.marginTop = `-100px`;
1297
- }
1298
- this.update();
1279
+ this._updateActiveVisible();
1299
1280
  }
1300
1281
 
1301
1282
  /**
@@ -9586,7 +9567,8 @@ const os = {
9586
9567
  }
9587
9568
  };
9588
9569
 
9589
- function addContextMenuListener(elem, callback) {
9570
+ //failCallback will be called when the press is not long enough to considered a long press
9571
+ function addContextMenuListener(elem, callback, failCallback = () => {}) {
9590
9572
  if (!elem || !callback) return;
9591
9573
 
9592
9574
  let timeout = null;
@@ -9640,6 +9622,7 @@ function addContextMenuListener(elem, callback) {
9640
9622
  const touchEndHandler = (event) => {
9641
9623
  event.preventDefault();
9642
9624
  if (timeout) {
9625
+ failCallback(event);
9643
9626
  clearTimeout(timeout);
9644
9627
  timeout = null;
9645
9628
  }
@@ -13781,6 +13764,8 @@ const WAITING_FOR_TARGET_LONG_TOUCH_END$1 = 8;
13781
13764
 
13782
13765
  const TOUCH_CANCELING$1 = 7;
13783
13766
 
13767
+ const tmpVec2$1 = math.vec2();
13768
+
13784
13769
  /**
13785
13770
  * Creates {@link AngleMeasurement}s from touch input.
13786
13771
  *
@@ -13919,6 +13904,19 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13919
13904
  this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13920
13905
  };
13921
13906
 
13907
+ const copyCanvasPos = (event, dst) => {
13908
+ dst[0] = event.clientX;
13909
+ dst[1] = event.clientY;
13910
+ transformToNode(canvas.ownerDocument.documentElement, canvas, dst);
13911
+ return dst;
13912
+ };
13913
+
13914
+ const toBodyPos = (pos, dst) => {
13915
+ dst.set(pos);
13916
+ transformToNode(canvas, canvas.ownerDocument.documentElement, dst);
13917
+ return dst;
13918
+ };
13919
+
13922
13920
  canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
13923
13921
 
13924
13922
  const currentNumTouches = event.touches.length;
@@ -13932,11 +13930,8 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13932
13930
  }
13933
13931
 
13934
13932
  const touch = event.touches[0];
13935
- const touchX = touch.clientX;
13936
- const touchY = touch.clientY;
13937
-
13938
- touchStartCanvasPos.set([touchX, touchY]);
13939
- touchMoveCanvasPos.set([touchX, touchY]);
13933
+ copyCanvasPos(touch, touchStartCanvasPos);
13934
+ touchMoveCanvasPos.set(touchStartCanvasPos);
13940
13935
 
13941
13936
  switch (this._touchState) {
13942
13937
 
@@ -13952,7 +13947,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13952
13947
  });
13953
13948
  if (snapPickResult && snapPickResult.snapped) {
13954
13949
  pointerWorldPos.set(snapPickResult.worldPos);
13955
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
13950
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2$1));
13956
13951
  } else {
13957
13952
  const pickResult = scene.pick({
13958
13953
  canvasPos: touchMoveCanvasPos,
@@ -13960,7 +13955,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13960
13955
  });
13961
13956
  if (pickResult && pickResult.worldPos) {
13962
13957
  pointerWorldPos.set(pickResult.worldPos);
13963
- this.pointerCircle.start(pickResult.canvasPos);
13958
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2$1));
13964
13959
  } else {
13965
13960
  return;
13966
13961
  }
@@ -14067,7 +14062,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14067
14062
  this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
14068
14063
  this.pointerLens.snapped = true;
14069
14064
  }
14070
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
14065
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2$1));
14071
14066
  pointerWorldPos.set(snapPickResult.worldPos);
14072
14067
  this._currentAngleMeasurement.corner.worldPos = snapPickResult.worldPos;
14073
14068
  this._currentAngleMeasurement.corner.entity = snapPickResult.entity;
@@ -14089,7 +14084,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14089
14084
  this.pointerLens.cursorPos = pickResult.canvasPos;
14090
14085
  this.pointerLens.snapped = false;
14091
14086
  }
14092
- this.pointerCircle.start(pickResult.canvasPos);
14087
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2$1));
14093
14088
  pointerWorldPos.set(pickResult.worldPos);
14094
14089
  this._currentAngleMeasurement.corner.worldPos = pickResult.worldPos;
14095
14090
  this._currentAngleMeasurement.corner.entity = pickResult.entity;
@@ -14160,7 +14155,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14160
14155
  this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
14161
14156
  this.pointerLens.snapped = true;
14162
14157
  }
14163
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
14158
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2$1));
14164
14159
  pointerWorldPos.set(snapPickResult.worldPos);
14165
14160
  this._currentAngleMeasurement.target.worldPos = snapPickResult.worldPos;
14166
14161
  this._currentAngleMeasurement.target.entity = snapPickResult.entity;
@@ -14182,7 +14177,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14182
14177
  this.pointerLens.cursorPos = pickResult.canvasPos;
14183
14178
  this.pointerLens.snapped = false;
14184
14179
  }
14185
- this.pointerCircle.start(pickResult.canvasPos);
14180
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2$1));
14186
14181
  pointerWorldPos.set(pickResult.worldPos);
14187
14182
  this._currentAngleMeasurement.target.worldPos = pickResult.worldPos;
14188
14183
  this._currentAngleMeasurement.target.entity = pickResult.entity;
@@ -14246,14 +14241,11 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14246
14241
  }
14247
14242
 
14248
14243
  const touch = event.touches[0];
14249
- const touchX = touch.clientX;
14250
- const touchY = touch.clientY;
14251
-
14252
14244
  if (touch.identifier !== touchId) {
14253
14245
  return;
14254
14246
  }
14255
14247
 
14256
- touchMoveCanvasPos.set([touchX, touchY]);
14248
+ copyCanvasPos(touch, touchMoveCanvasPos);
14257
14249
 
14258
14250
  let snapPickResult;
14259
14251
  let pickResult;
@@ -14423,9 +14415,6 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14423
14415
  }
14424
14416
 
14425
14417
  const touch = event.changedTouches[0];
14426
- const touchX = touch.clientX;
14427
- const touchY = touch.clientY;
14428
-
14429
14418
  if (touch.identifier !== touchId) {
14430
14419
  return;
14431
14420
  }
@@ -14435,7 +14424,10 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14435
14424
  longTouchTimeout = null;
14436
14425
  }
14437
14426
 
14438
- touchEndCanvasPos.set([touchX, touchY]);
14427
+ copyCanvasPos(touch, touchEndCanvasPos);
14428
+
14429
+ const touchX = touchEndCanvasPos[0];
14430
+ const touchY = touchEndCanvasPos[1];
14439
14431
 
14440
14432
  switch (this._touchState) {
14441
14433
 
@@ -14916,6 +14908,9 @@ class Annotation extends Marker {
14916
14908
  addContextMenuListener(this._marker, e => {
14917
14909
  e.preventDefault();
14918
14910
  this.plugin.fire("contextmenu", this);
14911
+ }, e => {
14912
+ e.preventDefault();
14913
+ this.plugin.fire("markerClicked", this);
14919
14914
  });
14920
14915
  this._marker.addEventListener("mouseenter", () => {
14921
14916
  this.plugin.fire("markerMouseEnter", this);
@@ -66120,7 +66115,7 @@ class VBOInstancingLinesLayer {
66120
66115
 
66121
66116
  let pickFlag = (visible && !culled && pickable) ? RENDER_PASSES.PICK : RENDER_PASSES.NOT_RENDERED;
66122
66117
 
66123
- const clippableFlag = !!(flags & ENTITY_FLAGS.CLIPPABLE) ? 255 : 0;
66118
+ const clippableFlag = !!(flags & ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;
66124
66119
 
66125
66120
  let vertFlag = 0;
66126
66121
  vertFlag |= colorFlag;
@@ -80697,8 +80692,7 @@ class DTXTrianglesLayer {
80697
80692
  worldPos[2] = positions[i + 2];
80698
80693
  worldPos[3] = 1.0;
80699
80694
  math.decompressPosition(worldPos, positionsDecodeMatrix);
80700
- math.transformPoint4(this.model.worldMatrix, worldPos, worldPos);
80701
- math.transformPoint4(this.model.worldMatrix, worldPos, worldPos);
80695
+ math.mulMat4v4(this.model.worldMatrix, worldPos, worldPos);
80702
80696
  worldPos[0] += offsetX;
80703
80697
  worldPos[1] += offsetY;
80704
80698
  worldPos[2] += offsetZ;
@@ -89874,6 +89868,8 @@ const WAITING_FOR_TARGET_LONG_TOUCH_END = 5;
89874
89868
 
89875
89869
  const TOUCH_CANCELING = 7;
89876
89870
 
89871
+ const tmpVec2 = math.vec2();
89872
+
89877
89873
  /**
89878
89874
  * Creates {@link DistanceMeasurement}s from touch input.
89879
89875
  *
@@ -90020,6 +90016,19 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90020
90016
  this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
90021
90017
  };
90022
90018
 
90019
+ const copyCanvasPos = (event, dst) => {
90020
+ dst[0] = event.clientX;
90021
+ dst[1] = event.clientY;
90022
+ transformToNode(canvas.ownerDocument.documentElement, canvas, dst);
90023
+ return dst;
90024
+ };
90025
+
90026
+ const toBodyPos = (pos, dst) => {
90027
+ dst.set(pos);
90028
+ transformToNode(canvas, canvas.ownerDocument.documentElement, dst);
90029
+ return dst;
90030
+ };
90031
+
90023
90032
  canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
90024
90033
 
90025
90034
  const currentNumTouches = event.touches.length;
@@ -90033,16 +90042,8 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90033
90042
  }
90034
90043
 
90035
90044
  const touch = event.touches[0];
90036
-
90037
- // Get the canvas's bounding rectangle
90038
- const rect = canvas.getBoundingClientRect();
90039
-
90040
- // Calculate the touch position relative to the canvas
90041
- const touchX = touch.clientX - rect.left;
90042
- const touchY = touch.clientY - rect.top;
90043
-
90044
- touchStartCanvasPos.set([touchX, touchY]);
90045
- touchMoveCanvasPos.set([touchX, touchY]);
90045
+ copyCanvasPos(touch, touchStartCanvasPos);
90046
+ touchMoveCanvasPos.set(touchStartCanvasPos);
90046
90047
 
90047
90048
  switch (this._touchState) {
90048
90049
 
@@ -90058,7 +90059,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90058
90059
  });
90059
90060
  if (snapPickResult && snapPickResult.snapped) {
90060
90061
  pointerWorldPos.set(snapPickResult.worldPos);
90061
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
90062
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
90062
90063
  } else {
90063
90064
  const pickResult = scene.pick({
90064
90065
  canvasPos: touchMoveCanvasPos,
@@ -90066,7 +90067,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90066
90067
  });
90067
90068
  if (pickResult && pickResult.worldPos) {
90068
90069
  pointerWorldPos.set(pickResult.worldPos);
90069
- this.pointerCircle.start(pickResult.canvasPos);
90070
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
90070
90071
  } else {
90071
90072
  return;
90072
90073
  }
@@ -90170,7 +90171,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90170
90171
  this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
90171
90172
  this.pointerLens.snapped = true;
90172
90173
  }
90173
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
90174
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
90174
90175
  pointerWorldPos.set(snapPickResult.worldPos);
90175
90176
  this._currentDistanceMeasurement.target.worldPos = snapPickResult.worldPos;
90176
90177
  this._currentDistanceMeasurement.target.entity = snapPickResult.entity;
@@ -90188,7 +90189,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90188
90189
  this.pointerLens.cursorPos = pickResult.canvasPos;
90189
90190
  this.pointerLens.snapped = false;
90190
90191
  }
90191
- this.pointerCircle.start(pickResult.canvasPos);
90192
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
90192
90193
  pointerWorldPos.set(pickResult.worldPos);
90193
90194
  this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
90194
90195
  this._currentDistanceMeasurement.target.entity = pickResult.entity;
@@ -90247,19 +90248,11 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90247
90248
  }
90248
90249
 
90249
90250
  const touch = event.touches[0];
90250
-
90251
- // Get the canvas's bounding rectangle
90252
- const rect = canvas.getBoundingClientRect();
90253
-
90254
- // Calculate the touch position relative to the canvas
90255
- const touchX = touch.clientX - rect.left;
90256
- const touchY = touch.clientY - rect.top;
90257
-
90258
90251
  if (touch.identifier !== touchId) {
90259
90252
  return;
90260
90253
  }
90261
90254
 
90262
- touchMoveCanvasPos.set([touchX, touchY]);
90255
+ copyCanvasPos(touch, touchMoveCanvasPos);
90263
90256
 
90264
90257
  let snapPickResult;
90265
90258
  let pickResult;
@@ -90421,14 +90414,6 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90421
90414
  }
90422
90415
 
90423
90416
  const touch = event.changedTouches[0];
90424
-
90425
- // Get the canvas's bounding rectangle
90426
- const rect = canvas.getBoundingClientRect();
90427
-
90428
- // Calculate the touch position relative to the canvas
90429
- const touchX = touch.clientX - rect.left;
90430
- const touchY = touch.clientY - rect.top;
90431
-
90432
90417
  if (touch.identifier !== touchId) {
90433
90418
  return;
90434
90419
  }
@@ -90438,7 +90423,10 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90438
90423
  longTouchTimeout = null;
90439
90424
  }
90440
90425
 
90441
- touchEndCanvasPos.set([touchX, touchY]);
90426
+ copyCanvasPos(touch, touchEndCanvasPos);
90427
+
90428
+ const touchX = touchEndCanvasPos[0];
90429
+ const touchY = touchEndCanvasPos[1];
90442
90430
 
90443
90431
  switch (this._touchState) {
90444
90432
 
@@ -120987,8 +120975,10 @@ class Control {
120987
120975
  isObject: false
120988
120976
  }), NO_STATE_INHERIT);
120989
120977
 
120978
+ const localToWorldVec = (localVec, worldVec) => math.vec3ApplyQuaternion(rootNode.quaternion, localVec, worldVec);
120979
+
120990
120980
  const closestPointOnAxis = (function() {
120991
- const worldAxis = math.vec4();
120981
+ const worldAxis = math.vec3();
120992
120982
  const org = math.vec3();
120993
120983
  const dir = math.vec3();
120994
120984
  return (canvasPos, dst) => {
@@ -121023,22 +121013,39 @@ class Control {
121023
121013
  if (closestPointOnAxis(canvasPos, tempVec3)) {
121024
121014
  math.subVec3(tempVec3, initOffset, tempVec3);
121025
121015
  setPos(tempVec3);
121026
- if (self._sectionPlane) {
121027
- self._sectionPlane.pos = tempVec3;
121016
+ if (this._sectionPlane) {
121017
+ this._sectionPlane.pos = tempVec3;
121028
121018
  }
121029
121019
  }
121030
121020
  });
121031
121021
  }
121032
121022
  };
121033
121023
 
121034
- const lastCanvasPos = math.vec2();
121035
121024
  handlers[rotateHandle.id] = {
121036
121025
  setActivated: a => hoop.visible = a,
121037
121026
  initDragAction: (initCanvasPos) => {
121038
- lastCanvasPos.set(initCanvasPos);
121027
+ const rotationFromCanvasPos = (function() {
121028
+ const planeCanvasPos = camera.projectWorldPos(pos);
121029
+ localToWorldVec(rgb, tempVec3);
121030
+ math.transformVec3(camera.normalMatrix, tempVec3, tempVec3);
121031
+ const axisCoeff = Math.sign(tempVec3[2]);
121032
+ return (canvasPos) => {
121033
+ const dx = canvasPos[0] - planeCanvasPos[0];
121034
+ const dy = canvasPos[1] - planeCanvasPos[1];
121035
+ return axisCoeff * Math.atan2(-dy, dx);
121036
+ };
121037
+ })();
121038
+
121039
+ let lastRotation = rotationFromCanvasPos(initCanvasPos);
121040
+
121039
121041
  return canvasPos => {
121040
- dragRotateSectionPlane(rgb, lastCanvasPos, canvasPos);
121041
- lastCanvasPos.set(canvasPos);
121042
+ const rotation = rotationFromCanvasPos(canvasPos);
121043
+ rootNode.rotate(rgb, (rotation - lastRotation) * 180 / Math.PI);
121044
+ if (this._sectionPlane) {
121045
+ ignoreNextSectionPlaneDirUpdate = true;
121046
+ this._sectionPlane.dir = math.vec3ApplyQuaternion(rootNode.quaternion, [0, 0, 1], tempVec3);
121047
+ }
121048
+ lastRotation = rotation;
121042
121049
  };
121043
121050
  }
121044
121051
  };
@@ -121174,101 +121181,6 @@ class Control {
121174
121181
  cleanups.push(() => scene.off(onSceneTick));
121175
121182
  }
121176
121183
 
121177
- const localToWorldVec = (function () {
121178
- const mat = math.mat4();
121179
- return function (localVec, worldVec) {
121180
- math.quaternionToMat4(rootNode.quaternion, mat);
121181
- math.transformVec3(mat, localVec, worldVec);
121182
- math.normalizeVec3(worldVec);
121183
- return worldVec;
121184
- };
121185
- })();
121186
-
121187
- const getTranslationPlane = (worldAxis, planeNormal) => {
121188
- const absX = Math.abs(worldAxis[0]);
121189
- if (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {
121190
- math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);
121191
- } else {
121192
- math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);
121193
- }
121194
- math.cross3Vec3(planeNormal, worldAxis, planeNormal);
121195
- math.normalizeVec3(planeNormal);
121196
- };
121197
-
121198
- const self = this;
121199
- var dragRotateSectionPlane = (function () {
121200
- const p1 = math.vec4();
121201
- const p2 = math.vec4();
121202
- const c = math.vec4();
121203
- const worldAxis = math.vec4();
121204
- const dir = math.vec3();
121205
- const mat = math.mat4();
121206
- const planeNormal = math.vec3();
121207
- return function (baseAxis, fromMouse, toMouse) {
121208
- localToWorldVec(baseAxis, worldAxis);
121209
- const hasData = getPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);
121210
- if (!hasData) { // Find intersections with view plane and project down to origin
121211
- getTranslationPlane(worldAxis, planeNormal);
121212
- getPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable
121213
- getPointerPlaneIntersect(toMouse, planeNormal, p2, 1);
121214
- var dot = math.dotVec3(p1, worldAxis);
121215
- p1[0] -= dot * worldAxis[0];
121216
- p1[1] -= dot * worldAxis[1];
121217
- p1[2] -= dot * worldAxis[2];
121218
- dot = math.dotVec3(p2, worldAxis);
121219
- p2[0] -= dot * worldAxis[0];
121220
- p2[1] -= dot * worldAxis[1];
121221
- p2[2] -= dot * worldAxis[2];
121222
- }
121223
- math.normalizeVec3(p1);
121224
- math.normalizeVec3(p2);
121225
- dot = math.dotVec3(p1, p2);
121226
- dot = math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range
121227
- var incDegrees = Math.acos(dot) * math.RADTODEG;
121228
- math.cross3Vec3(p1, p2, c);
121229
- if (math.dotVec3(c, worldAxis) < 0.0) {
121230
- incDegrees = -incDegrees;
121231
- }
121232
- rootNode.rotate(baseAxis, incDegrees);
121233
-
121234
- if (self._sectionPlane) {
121235
- math.quaternionToMat4(rootNode.quaternion, mat); // << ---
121236
- math.transformVec3(mat, [0, 0, 1], dir);
121237
- ignoreNextSectionPlaneDirUpdate = true;
121238
- self._sectionPlane.dir = dir;
121239
- }
121240
- };
121241
- })();
121242
-
121243
- var getPointerPlaneIntersect = (function () {
121244
- const dir = math.vec4([0, 0, 0, 1]);
121245
- const matrix = math.mat4();
121246
- return function (mouse, axis, dest, offset) {
121247
- offset = offset || 0;
121248
- dir[0] = mouse[0] / canvas.width * 2.0 - 1.0;
121249
- dir[1] = -(mouse[1] / canvas.height * 2.0 - 1.0);
121250
- dir[2] = 0.0;
121251
- dir[3] = 1.0;
121252
- math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords
121253
- math.inverseMat4(matrix);
121254
- math.transformVec4(matrix, dir, dir);
121255
- math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space
121256
- var rayO = camera.eye; // The direction
121257
- math.subVec4(dir, rayO, dir);
121258
- const origin = self._sectionPlane.pos; // Plane origin:
121259
- var d = -math.dotVec3(origin, axis) - offset;
121260
- var dot = math.dotVec3(axis, dir);
121261
- if (Math.abs(dot) > 0.005) {
121262
- var t = -(math.dotVec3(axis, rayO) + d) / dot;
121263
- math.mulVec3Scalar(dir, t, dest);
121264
- math.addVec3(dest, rayO);
121265
- math.subVec3(dest, origin, dest);
121266
- return true;
121267
- }
121268
- return false;
121269
- };
121270
- })();
121271
-
121272
121184
  {
121273
121185
  let deactivateActive = null;
121274
121186
  let currentDrag = null;
@@ -126051,6 +125963,8 @@ class TreeViewPlugin extends Plugin {
126051
125963
  * @param {RenderService} [cfg.renderService] Optional {@link RenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}.
126052
125964
  * @param {Boolean} [cfg.showIndeterminate=false] When true, will show indeterminate state for checkboxes when some but not all child nodes are checked
126053
125965
  * @param {Boolean} [cfg.showProjectNode=false] When true, will show top level project node when hierarchy is set to "storeys"
125966
+ * @param {Function} [cfg.elevationSortFunction] Optional function to replace the default elevation sort function. The function should take two nodes and return -1, 0 or 1.
125967
+ * @param {Function} [cfg.defaultSortFunction] Optional function to replace the default sort function. The function should take two nodes and return -1, 0 or 1.
126054
125968
  */
126055
125969
  constructor(viewer, cfg = {}) {
126056
125970
 
@@ -126104,6 +126018,8 @@ class TreeViewPlugin extends Plugin {
126104
126018
  this._renderService = cfg.renderService || new RenderService();
126105
126019
  this._showIndeterminate = cfg.showIndeterminate ?? false;
126106
126020
  this._showProjectNode = cfg.showProjectNode ?? false;
126021
+ this._elevationSortFunction = cfg.elevationSortFunction ?? undefined;
126022
+ this._defaultSortFunction = cfg.defaultSortFunction ?? undefined;
126107
126023
 
126108
126024
  if (!this._renderService) {
126109
126025
  throw new Error('TreeViewPlugin: no render service set');
@@ -126917,9 +126833,11 @@ class TreeViewPlugin extends Plugin {
126917
126833
  }
126918
126834
  const firstChild = children[0];
126919
126835
  if ((this._hierarchy === "storeys" || this._hierarchy === "containment") && firstChild.type === "IfcBuildingStorey") {
126920
- children.sort(this._getSpatialSortFunc());
126836
+ if (this._elevationSortFunction) children.sort(this._elevationSortFunction);
126837
+ else children.sort(this._getSpatialSortFunc());
126921
126838
  } else {
126922
- children.sort(this._alphaSortFunc);
126839
+ if (this._defaultSortFunction) children.sort(this._defaultSortFunction);
126840
+ else children.sort(this._alphaSortFunc);
126923
126841
  }
126924
126842
  for (let i = 0, len = children.length; i < len; i++) {
126925
126843
  const node = children[i];