@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
@@ -1059,13 +1059,10 @@ class PointerLens {
1059
1059
  this.scene = this.viewer.scene;
1060
1060
 
1061
1061
  this._lensCursorDiv = document.createElement('div');
1062
- this.viewer.scene.canvas.canvas.parentNode.insertBefore(this._lensCursorDiv, this.viewer.scene.canvas.canvas);
1063
- this._lensCursorDiv.style.background = "pink";
1064
- this._lensCursorDiv.style.border = "2px solid red";
1065
- this._lensCursorDiv.style.borderRadius = "20px";
1066
- this._lensCursorDiv.style.width = "10px";
1067
- this._lensCursorDiv.style.height = "10px";
1068
- this._lensCursorDiv.style.margin = "-200px -200px";
1062
+ this._lensParams = { canvasSize: 300, cursorBorder: 2, cursorSize: 10 };
1063
+ this._lensCursorDiv.style.borderRadius = "50%";
1064
+ this._lensCursorDiv.style.width = this._lensParams.cursorSize + "px";
1065
+ this._lensCursorDiv.style.height = this._lensParams.cursorSize + "px";
1069
1066
  this._lensCursorDiv.style.zIndex = "100000";
1070
1067
  this._lensCursorDiv.style.position = "absolute";
1071
1068
  this._lensCursorDiv.style.pointerEvents = "none";
@@ -1078,8 +1075,8 @@ class PointerLens {
1078
1075
  this._lensContainer.style.background = "white";
1079
1076
  // this._lensContainer.style.opacity = "0";
1080
1077
  this._lensContainer.style.borderRadius = "50%";
1081
- this._lensContainer.style.width = "300px";
1082
- this._lensContainer.style.height = "300px";
1078
+ this._lensContainer.style.width = this._lensParams.canvasSize + "px";
1079
+ this._lensContainer.style.height = this._lensParams.canvasSize + "px";
1083
1080
 
1084
1081
  this._lensContainer.style.zIndex = "15000";
1085
1082
  this._lensContainer.style.position = "absolute";
@@ -1091,13 +1088,14 @@ class PointerLens {
1091
1088
  // this._lensCanvas.style.background = "darkblue";
1092
1089
  this._lensCanvas.style.borderRadius = "50%";
1093
1090
 
1094
- this._lensCanvas.style.width = "300px";
1095
- this._lensCanvas.style.height = "300px";
1091
+ this._lensCanvas.style.width = this._lensParams.canvasSize + "px";
1092
+ this._lensCanvas.style.height = this._lensParams.canvasSize + "px";
1096
1093
  this._lensCanvas.style.zIndex = "15000";
1097
1094
  this._lensCanvas.style.pointerEvents = "none";
1098
1095
 
1099
1096
  document.body.appendChild(this._lensContainer);
1100
1097
  this._lensContainer.appendChild(this._lensCanvas);
1098
+ this._lensContainer.appendChild(this._lensCursorDiv);
1101
1099
 
1102
1100
  this._lensCanvasContext = this._lensCanvas.getContext('2d');
1103
1101
  this._canvasElement = this.viewer.scene.canvas.canvas;
@@ -1115,7 +1113,7 @@ class PointerLens {
1115
1113
 
1116
1114
  this._active = (cfg.active !== false);
1117
1115
  this._visible = false;
1118
- this._snapped = false;
1116
+ this.snapped = false;
1119
1117
 
1120
1118
  this._onViewerRendering = this.viewer.scene.on("rendering", () => {
1121
1119
  if (this._active && this._visible) {
@@ -1162,21 +1160,13 @@ class PointerLens {
1162
1160
  this._lensCanvas.height // destination height
1163
1161
  );
1164
1162
 
1165
- const centerLensCanvas = [
1166
- (lensRect.left + lensRect.right) / 2 - canvasRect.left,
1167
- (lensRect.top + lensRect.bottom) / 2 - canvasRect.top
1168
- ];
1163
+ const middle = this._lensParams.canvasSize / 2 - this._lensParams.cursorSize / 2 - this._lensParams.cursorBorder;
1169
1164
 
1170
- if (this._snappedCanvasPos) {
1171
- const deltaX = this._snappedCanvasPos[0] - this._canvasPos[0];
1172
- const deltaY = this._snappedCanvasPos[1] - this._canvasPos[1];
1165
+ const deltaX = this._snappedCanvasPos ? (this._snappedCanvasPos[0] - this._canvasPos[0]) : 0;
1166
+ const deltaY = this._snappedCanvasPos ? (this._snappedCanvasPos[1] - this._canvasPos[1]) : 0;
1173
1167
 
1174
- this._lensCursorDiv.style.marginLeft = `${centerLensCanvas[0] + deltaX * this._zoomLevel - 10}px`;
1175
- this._lensCursorDiv.style.marginTop = `${centerLensCanvas[1] + deltaY * this._zoomLevel - 10}px`;
1176
- } else {
1177
- this._lensCursorDiv.style.marginLeft = `${centerLensCanvas[0] - 10}px`;
1178
- this._lensCursorDiv.style.marginTop = `${centerLensCanvas[1] - 10}px`;
1179
- }
1168
+ this._lensCursorDiv.style.left = `${middle + deltaX * this._zoomLevel}px`;
1169
+ this._lensCursorDiv.style.top = `${middle + deltaY * this._zoomLevel}px`;
1180
1170
  }
1181
1171
 
1182
1172
 
@@ -1244,14 +1234,10 @@ class PointerLens {
1244
1234
  * @private
1245
1235
  */
1246
1236
  set snapped(snapped) {
1247
- this._snapped = snapped;
1248
- if (snapped) {
1249
- this._lensCursorDiv.style.background = "greenyellow";
1250
- this._lensCursorDiv.style.border = "2px solid green";
1251
- } else {
1252
- this._lensCursorDiv.style.background = "pink";
1253
- this._lensCursorDiv.style.border = "2px solid red";
1254
- }
1237
+ this._snapped = snapped;
1238
+ const [ bg, border ] = snapped ? [ "greenyellow", "green" ] : [ "pink", "red" ];
1239
+ this._lensCursorDiv.style.background = bg;
1240
+ this._lensCursorDiv.style.border = this._lensParams.cursorBorder + "px solid " + border;
1255
1241
  }
1256
1242
 
1257
1243
  /**
@@ -1263,19 +1249,19 @@ class PointerLens {
1263
1249
  get snapped() {
1264
1250
  return this._snapped;
1265
1251
  }
1266
-
1252
+
1253
+ _updateActiveVisible() {
1254
+ this._lensContainer.style.visibility = (this._active && this._visible) ? "visible" : "hidden";
1255
+ this.update();
1256
+ }
1257
+
1267
1258
  /**
1268
1259
  * Sets if this PointerLens is active.
1269
1260
  * @param active
1270
1261
  */
1271
1262
  set active(active) {
1272
1263
  this._active = active;
1273
- this._lensContainer.style.visibility = (active && this._visible) ? "visible" : "hidden";
1274
- if (!active || !this._visible ) {
1275
- this._lensCursorDiv.style.marginLeft = `-100px`;
1276
- this._lensCursorDiv.style.marginTop = `-100px`;
1277
- }
1278
- this.update();
1264
+ this._updateActiveVisible();
1279
1265
  }
1280
1266
 
1281
1267
  /**
@@ -1294,12 +1280,7 @@ class PointerLens {
1294
1280
  */
1295
1281
  set visible(visible) {
1296
1282
  this._visible = visible;
1297
- this._lensContainer.style.visibility = (visible && this._active) ? "visible" : "hidden";
1298
- if (!visible || !this._active) {
1299
- this._lensCursorDiv.style.marginLeft = `-100px`;
1300
- this._lensCursorDiv.style.marginTop = `-100px`;
1301
- }
1302
- this.update();
1283
+ this._updateActiveVisible();
1303
1284
  }
1304
1285
 
1305
1286
  /**
@@ -9590,7 +9571,8 @@ const os = {
9590
9571
  }
9591
9572
  };
9592
9573
 
9593
- function addContextMenuListener(elem, callback) {
9574
+ //failCallback will be called when the press is not long enough to considered a long press
9575
+ function addContextMenuListener(elem, callback, failCallback = () => {}) {
9594
9576
  if (!elem || !callback) return;
9595
9577
 
9596
9578
  let timeout = null;
@@ -9644,6 +9626,7 @@ function addContextMenuListener(elem, callback) {
9644
9626
  const touchEndHandler = (event) => {
9645
9627
  event.preventDefault();
9646
9628
  if (timeout) {
9629
+ failCallback(event);
9647
9630
  clearTimeout(timeout);
9648
9631
  timeout = null;
9649
9632
  }
@@ -13785,6 +13768,8 @@ const WAITING_FOR_TARGET_LONG_TOUCH_END$1 = 8;
13785
13768
 
13786
13769
  const TOUCH_CANCELING$1 = 7;
13787
13770
 
13771
+ const tmpVec2$1 = math.vec2();
13772
+
13788
13773
  /**
13789
13774
  * Creates {@link AngleMeasurement}s from touch input.
13790
13775
  *
@@ -13923,6 +13908,19 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13923
13908
  this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13924
13909
  };
13925
13910
 
13911
+ const copyCanvasPos = (event, dst) => {
13912
+ dst[0] = event.clientX;
13913
+ dst[1] = event.clientY;
13914
+ transformToNode(canvas.ownerDocument.documentElement, canvas, dst);
13915
+ return dst;
13916
+ };
13917
+
13918
+ const toBodyPos = (pos, dst) => {
13919
+ dst.set(pos);
13920
+ transformToNode(canvas, canvas.ownerDocument.documentElement, dst);
13921
+ return dst;
13922
+ };
13923
+
13926
13924
  canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
13927
13925
 
13928
13926
  const currentNumTouches = event.touches.length;
@@ -13936,11 +13934,8 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13936
13934
  }
13937
13935
 
13938
13936
  const touch = event.touches[0];
13939
- const touchX = touch.clientX;
13940
- const touchY = touch.clientY;
13941
-
13942
- touchStartCanvasPos.set([touchX, touchY]);
13943
- touchMoveCanvasPos.set([touchX, touchY]);
13937
+ copyCanvasPos(touch, touchStartCanvasPos);
13938
+ touchMoveCanvasPos.set(touchStartCanvasPos);
13944
13939
 
13945
13940
  switch (this._touchState) {
13946
13941
 
@@ -13956,7 +13951,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13956
13951
  });
13957
13952
  if (snapPickResult && snapPickResult.snapped) {
13958
13953
  pointerWorldPos.set(snapPickResult.worldPos);
13959
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
13954
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2$1));
13960
13955
  } else {
13961
13956
  const pickResult = scene.pick({
13962
13957
  canvasPos: touchMoveCanvasPos,
@@ -13964,7 +13959,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13964
13959
  });
13965
13960
  if (pickResult && pickResult.worldPos) {
13966
13961
  pointerWorldPos.set(pickResult.worldPos);
13967
- this.pointerCircle.start(pickResult.canvasPos);
13962
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2$1));
13968
13963
  } else {
13969
13964
  return;
13970
13965
  }
@@ -14071,7 +14066,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14071
14066
  this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
14072
14067
  this.pointerLens.snapped = true;
14073
14068
  }
14074
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
14069
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2$1));
14075
14070
  pointerWorldPos.set(snapPickResult.worldPos);
14076
14071
  this._currentAngleMeasurement.corner.worldPos = snapPickResult.worldPos;
14077
14072
  this._currentAngleMeasurement.corner.entity = snapPickResult.entity;
@@ -14093,7 +14088,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14093
14088
  this.pointerLens.cursorPos = pickResult.canvasPos;
14094
14089
  this.pointerLens.snapped = false;
14095
14090
  }
14096
- this.pointerCircle.start(pickResult.canvasPos);
14091
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2$1));
14097
14092
  pointerWorldPos.set(pickResult.worldPos);
14098
14093
  this._currentAngleMeasurement.corner.worldPos = pickResult.worldPos;
14099
14094
  this._currentAngleMeasurement.corner.entity = pickResult.entity;
@@ -14164,7 +14159,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14164
14159
  this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
14165
14160
  this.pointerLens.snapped = true;
14166
14161
  }
14167
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
14162
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2$1));
14168
14163
  pointerWorldPos.set(snapPickResult.worldPos);
14169
14164
  this._currentAngleMeasurement.target.worldPos = snapPickResult.worldPos;
14170
14165
  this._currentAngleMeasurement.target.entity = snapPickResult.entity;
@@ -14186,7 +14181,7 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14186
14181
  this.pointerLens.cursorPos = pickResult.canvasPos;
14187
14182
  this.pointerLens.snapped = false;
14188
14183
  }
14189
- this.pointerCircle.start(pickResult.canvasPos);
14184
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2$1));
14190
14185
  pointerWorldPos.set(pickResult.worldPos);
14191
14186
  this._currentAngleMeasurement.target.worldPos = pickResult.worldPos;
14192
14187
  this._currentAngleMeasurement.target.entity = pickResult.entity;
@@ -14250,14 +14245,11 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14250
14245
  }
14251
14246
 
14252
14247
  const touch = event.touches[0];
14253
- const touchX = touch.clientX;
14254
- const touchY = touch.clientY;
14255
-
14256
14248
  if (touch.identifier !== touchId) {
14257
14249
  return;
14258
14250
  }
14259
14251
 
14260
- touchMoveCanvasPos.set([touchX, touchY]);
14252
+ copyCanvasPos(touch, touchMoveCanvasPos);
14261
14253
 
14262
14254
  let snapPickResult;
14263
14255
  let pickResult;
@@ -14427,9 +14419,6 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14427
14419
  }
14428
14420
 
14429
14421
  const touch = event.changedTouches[0];
14430
- const touchX = touch.clientX;
14431
- const touchY = touch.clientY;
14432
-
14433
14422
  if (touch.identifier !== touchId) {
14434
14423
  return;
14435
14424
  }
@@ -14439,7 +14428,10 @@ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
14439
14428
  longTouchTimeout = null;
14440
14429
  }
14441
14430
 
14442
- touchEndCanvasPos.set([touchX, touchY]);
14431
+ copyCanvasPos(touch, touchEndCanvasPos);
14432
+
14433
+ const touchX = touchEndCanvasPos[0];
14434
+ const touchY = touchEndCanvasPos[1];
14443
14435
 
14444
14436
  switch (this._touchState) {
14445
14437
 
@@ -14920,6 +14912,9 @@ class Annotation extends Marker {
14920
14912
  addContextMenuListener(this._marker, e => {
14921
14913
  e.preventDefault();
14922
14914
  this.plugin.fire("contextmenu", this);
14915
+ }, e => {
14916
+ e.preventDefault();
14917
+ this.plugin.fire("markerClicked", this);
14923
14918
  });
14924
14919
  this._marker.addEventListener("mouseenter", () => {
14925
14920
  this.plugin.fire("markerMouseEnter", this);
@@ -66124,7 +66119,7 @@ class VBOInstancingLinesLayer {
66124
66119
 
66125
66120
  let pickFlag = (visible && !culled && pickable) ? RENDER_PASSES.PICK : RENDER_PASSES.NOT_RENDERED;
66126
66121
 
66127
- const clippableFlag = !!(flags & ENTITY_FLAGS.CLIPPABLE) ? 255 : 0;
66122
+ const clippableFlag = !!(flags & ENTITY_FLAGS.CLIPPABLE) ? 1 : 0;
66128
66123
 
66129
66124
  let vertFlag = 0;
66130
66125
  vertFlag |= colorFlag;
@@ -80701,8 +80696,7 @@ class DTXTrianglesLayer {
80701
80696
  worldPos[2] = positions[i + 2];
80702
80697
  worldPos[3] = 1.0;
80703
80698
  math.decompressPosition(worldPos, positionsDecodeMatrix);
80704
- math.transformPoint4(this.model.worldMatrix, worldPos, worldPos);
80705
- math.transformPoint4(this.model.worldMatrix, worldPos, worldPos);
80699
+ math.mulMat4v4(this.model.worldMatrix, worldPos, worldPos);
80706
80700
  worldPos[0] += offsetX;
80707
80701
  worldPos[1] += offsetY;
80708
80702
  worldPos[2] += offsetZ;
@@ -89878,6 +89872,8 @@ const WAITING_FOR_TARGET_LONG_TOUCH_END = 5;
89878
89872
 
89879
89873
  const TOUCH_CANCELING = 7;
89880
89874
 
89875
+ const tmpVec2 = math.vec2();
89876
+
89881
89877
  /**
89882
89878
  * Creates {@link DistanceMeasurement}s from touch input.
89883
89879
  *
@@ -90024,6 +90020,19 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90024
90020
  this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
90025
90021
  };
90026
90022
 
90023
+ const copyCanvasPos = (event, dst) => {
90024
+ dst[0] = event.clientX;
90025
+ dst[1] = event.clientY;
90026
+ transformToNode(canvas.ownerDocument.documentElement, canvas, dst);
90027
+ return dst;
90028
+ };
90029
+
90030
+ const toBodyPos = (pos, dst) => {
90031
+ dst.set(pos);
90032
+ transformToNode(canvas, canvas.ownerDocument.documentElement, dst);
90033
+ return dst;
90034
+ };
90035
+
90027
90036
  canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
90028
90037
 
90029
90038
  const currentNumTouches = event.touches.length;
@@ -90037,16 +90046,8 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90037
90046
  }
90038
90047
 
90039
90048
  const touch = event.touches[0];
90040
-
90041
- // Get the canvas's bounding rectangle
90042
- const rect = canvas.getBoundingClientRect();
90043
-
90044
- // Calculate the touch position relative to the canvas
90045
- const touchX = touch.clientX - rect.left;
90046
- const touchY = touch.clientY - rect.top;
90047
-
90048
- touchStartCanvasPos.set([touchX, touchY]);
90049
- touchMoveCanvasPos.set([touchX, touchY]);
90049
+ copyCanvasPos(touch, touchStartCanvasPos);
90050
+ touchMoveCanvasPos.set(touchStartCanvasPos);
90050
90051
 
90051
90052
  switch (this._touchState) {
90052
90053
 
@@ -90062,7 +90063,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90062
90063
  });
90063
90064
  if (snapPickResult && snapPickResult.snapped) {
90064
90065
  pointerWorldPos.set(snapPickResult.worldPos);
90065
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
90066
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
90066
90067
  } else {
90067
90068
  const pickResult = scene.pick({
90068
90069
  canvasPos: touchMoveCanvasPos,
@@ -90070,7 +90071,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90070
90071
  });
90071
90072
  if (pickResult && pickResult.worldPos) {
90072
90073
  pointerWorldPos.set(pickResult.worldPos);
90073
- this.pointerCircle.start(pickResult.canvasPos);
90074
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
90074
90075
  } else {
90075
90076
  return;
90076
90077
  }
@@ -90174,7 +90175,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90174
90175
  this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
90175
90176
  this.pointerLens.snapped = true;
90176
90177
  }
90177
- this.pointerCircle.start(snapPickResult.snappedCanvasPos);
90178
+ this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
90178
90179
  pointerWorldPos.set(snapPickResult.worldPos);
90179
90180
  this._currentDistanceMeasurement.target.worldPos = snapPickResult.worldPos;
90180
90181
  this._currentDistanceMeasurement.target.entity = snapPickResult.entity;
@@ -90192,7 +90193,7 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90192
90193
  this.pointerLens.cursorPos = pickResult.canvasPos;
90193
90194
  this.pointerLens.snapped = false;
90194
90195
  }
90195
- this.pointerCircle.start(pickResult.canvasPos);
90196
+ this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
90196
90197
  pointerWorldPos.set(pickResult.worldPos);
90197
90198
  this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
90198
90199
  this._currentDistanceMeasurement.target.entity = pickResult.entity;
@@ -90251,19 +90252,11 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90251
90252
  }
90252
90253
 
90253
90254
  const touch = event.touches[0];
90254
-
90255
- // Get the canvas's bounding rectangle
90256
- const rect = canvas.getBoundingClientRect();
90257
-
90258
- // Calculate the touch position relative to the canvas
90259
- const touchX = touch.clientX - rect.left;
90260
- const touchY = touch.clientY - rect.top;
90261
-
90262
90255
  if (touch.identifier !== touchId) {
90263
90256
  return;
90264
90257
  }
90265
90258
 
90266
- touchMoveCanvasPos.set([touchX, touchY]);
90259
+ copyCanvasPos(touch, touchMoveCanvasPos);
90267
90260
 
90268
90261
  let snapPickResult;
90269
90262
  let pickResult;
@@ -90425,14 +90418,6 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90425
90418
  }
90426
90419
 
90427
90420
  const touch = event.changedTouches[0];
90428
-
90429
- // Get the canvas's bounding rectangle
90430
- const rect = canvas.getBoundingClientRect();
90431
-
90432
- // Calculate the touch position relative to the canvas
90433
- const touchX = touch.clientX - rect.left;
90434
- const touchY = touch.clientY - rect.top;
90435
-
90436
90421
  if (touch.identifier !== touchId) {
90437
90422
  return;
90438
90423
  }
@@ -90442,7 +90427,10 @@ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
90442
90427
  longTouchTimeout = null;
90443
90428
  }
90444
90429
 
90445
- touchEndCanvasPos.set([touchX, touchY]);
90430
+ copyCanvasPos(touch, touchEndCanvasPos);
90431
+
90432
+ const touchX = touchEndCanvasPos[0];
90433
+ const touchY = touchEndCanvasPos[1];
90446
90434
 
90447
90435
  switch (this._touchState) {
90448
90436
 
@@ -120991,8 +120979,10 @@ class Control {
120991
120979
  isObject: false
120992
120980
  }), NO_STATE_INHERIT);
120993
120981
 
120982
+ const localToWorldVec = (localVec, worldVec) => math.vec3ApplyQuaternion(rootNode.quaternion, localVec, worldVec);
120983
+
120994
120984
  const closestPointOnAxis = (function() {
120995
- const worldAxis = math.vec4();
120985
+ const worldAxis = math.vec3();
120996
120986
  const org = math.vec3();
120997
120987
  const dir = math.vec3();
120998
120988
  return (canvasPos, dst) => {
@@ -121027,22 +121017,39 @@ class Control {
121027
121017
  if (closestPointOnAxis(canvasPos, tempVec3)) {
121028
121018
  math.subVec3(tempVec3, initOffset, tempVec3);
121029
121019
  setPos(tempVec3);
121030
- if (self._sectionPlane) {
121031
- self._sectionPlane.pos = tempVec3;
121020
+ if (this._sectionPlane) {
121021
+ this._sectionPlane.pos = tempVec3;
121032
121022
  }
121033
121023
  }
121034
121024
  });
121035
121025
  }
121036
121026
  };
121037
121027
 
121038
- const lastCanvasPos = math.vec2();
121039
121028
  handlers[rotateHandle.id] = {
121040
121029
  setActivated: a => hoop.visible = a,
121041
121030
  initDragAction: (initCanvasPos) => {
121042
- lastCanvasPos.set(initCanvasPos);
121031
+ const rotationFromCanvasPos = (function() {
121032
+ const planeCanvasPos = camera.projectWorldPos(pos);
121033
+ localToWorldVec(rgb, tempVec3);
121034
+ math.transformVec3(camera.normalMatrix, tempVec3, tempVec3);
121035
+ const axisCoeff = Math.sign(tempVec3[2]);
121036
+ return (canvasPos) => {
121037
+ const dx = canvasPos[0] - planeCanvasPos[0];
121038
+ const dy = canvasPos[1] - planeCanvasPos[1];
121039
+ return axisCoeff * Math.atan2(-dy, dx);
121040
+ };
121041
+ })();
121042
+
121043
+ let lastRotation = rotationFromCanvasPos(initCanvasPos);
121044
+
121043
121045
  return canvasPos => {
121044
- dragRotateSectionPlane(rgb, lastCanvasPos, canvasPos);
121045
- lastCanvasPos.set(canvasPos);
121046
+ const rotation = rotationFromCanvasPos(canvasPos);
121047
+ rootNode.rotate(rgb, (rotation - lastRotation) * 180 / Math.PI);
121048
+ if (this._sectionPlane) {
121049
+ ignoreNextSectionPlaneDirUpdate = true;
121050
+ this._sectionPlane.dir = math.vec3ApplyQuaternion(rootNode.quaternion, [0, 0, 1], tempVec3);
121051
+ }
121052
+ lastRotation = rotation;
121046
121053
  };
121047
121054
  }
121048
121055
  };
@@ -121178,101 +121185,6 @@ class Control {
121178
121185
  cleanups.push(() => scene.off(onSceneTick));
121179
121186
  }
121180
121187
 
121181
- const localToWorldVec = (function () {
121182
- const mat = math.mat4();
121183
- return function (localVec, worldVec) {
121184
- math.quaternionToMat4(rootNode.quaternion, mat);
121185
- math.transformVec3(mat, localVec, worldVec);
121186
- math.normalizeVec3(worldVec);
121187
- return worldVec;
121188
- };
121189
- })();
121190
-
121191
- const getTranslationPlane = (worldAxis, planeNormal) => {
121192
- const absX = Math.abs(worldAxis[0]);
121193
- if (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {
121194
- math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);
121195
- } else {
121196
- math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);
121197
- }
121198
- math.cross3Vec3(planeNormal, worldAxis, planeNormal);
121199
- math.normalizeVec3(planeNormal);
121200
- };
121201
-
121202
- const self = this;
121203
- var dragRotateSectionPlane = (function () {
121204
- const p1 = math.vec4();
121205
- const p2 = math.vec4();
121206
- const c = math.vec4();
121207
- const worldAxis = math.vec4();
121208
- const dir = math.vec3();
121209
- const mat = math.mat4();
121210
- const planeNormal = math.vec3();
121211
- return function (baseAxis, fromMouse, toMouse) {
121212
- localToWorldVec(baseAxis, worldAxis);
121213
- const hasData = getPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);
121214
- if (!hasData) { // Find intersections with view plane and project down to origin
121215
- getTranslationPlane(worldAxis, planeNormal);
121216
- getPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable
121217
- getPointerPlaneIntersect(toMouse, planeNormal, p2, 1);
121218
- var dot = math.dotVec3(p1, worldAxis);
121219
- p1[0] -= dot * worldAxis[0];
121220
- p1[1] -= dot * worldAxis[1];
121221
- p1[2] -= dot * worldAxis[2];
121222
- dot = math.dotVec3(p2, worldAxis);
121223
- p2[0] -= dot * worldAxis[0];
121224
- p2[1] -= dot * worldAxis[1];
121225
- p2[2] -= dot * worldAxis[2];
121226
- }
121227
- math.normalizeVec3(p1);
121228
- math.normalizeVec3(p2);
121229
- dot = math.dotVec3(p1, p2);
121230
- dot = math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range
121231
- var incDegrees = Math.acos(dot) * math.RADTODEG;
121232
- math.cross3Vec3(p1, p2, c);
121233
- if (math.dotVec3(c, worldAxis) < 0.0) {
121234
- incDegrees = -incDegrees;
121235
- }
121236
- rootNode.rotate(baseAxis, incDegrees);
121237
-
121238
- if (self._sectionPlane) {
121239
- math.quaternionToMat4(rootNode.quaternion, mat); // << ---
121240
- math.transformVec3(mat, [0, 0, 1], dir);
121241
- ignoreNextSectionPlaneDirUpdate = true;
121242
- self._sectionPlane.dir = dir;
121243
- }
121244
- };
121245
- })();
121246
-
121247
- var getPointerPlaneIntersect = (function () {
121248
- const dir = math.vec4([0, 0, 0, 1]);
121249
- const matrix = math.mat4();
121250
- return function (mouse, axis, dest, offset) {
121251
- offset = offset || 0;
121252
- dir[0] = mouse[0] / canvas.width * 2.0 - 1.0;
121253
- dir[1] = -(mouse[1] / canvas.height * 2.0 - 1.0);
121254
- dir[2] = 0.0;
121255
- dir[3] = 1.0;
121256
- math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords
121257
- math.inverseMat4(matrix);
121258
- math.transformVec4(matrix, dir, dir);
121259
- math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space
121260
- var rayO = camera.eye; // The direction
121261
- math.subVec4(dir, rayO, dir);
121262
- const origin = self._sectionPlane.pos; // Plane origin:
121263
- var d = -math.dotVec3(origin, axis) - offset;
121264
- var dot = math.dotVec3(axis, dir);
121265
- if (Math.abs(dot) > 0.005) {
121266
- var t = -(math.dotVec3(axis, rayO) + d) / dot;
121267
- math.mulVec3Scalar(dir, t, dest);
121268
- math.addVec3(dest, rayO);
121269
- math.subVec3(dest, origin, dest);
121270
- return true;
121271
- }
121272
- return false;
121273
- };
121274
- })();
121275
-
121276
121188
  {
121277
121189
  let deactivateActive = null;
121278
121190
  let currentDrag = null;
@@ -126055,6 +125967,8 @@ class TreeViewPlugin extends Plugin {
126055
125967
  * @param {RenderService} [cfg.renderService] Optional {@link RenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}.
126056
125968
  * @param {Boolean} [cfg.showIndeterminate=false] When true, will show indeterminate state for checkboxes when some but not all child nodes are checked
126057
125969
  * @param {Boolean} [cfg.showProjectNode=false] When true, will show top level project node when hierarchy is set to "storeys"
125970
+ * @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.
125971
+ * @param {Function} [cfg.defaultSortFunction] Optional function to replace the default sort function. The function should take two nodes and return -1, 0 or 1.
126058
125972
  */
126059
125973
  constructor(viewer, cfg = {}) {
126060
125974
 
@@ -126108,6 +126022,8 @@ class TreeViewPlugin extends Plugin {
126108
126022
  this._renderService = cfg.renderService || new RenderService();
126109
126023
  this._showIndeterminate = cfg.showIndeterminate ?? false;
126110
126024
  this._showProjectNode = cfg.showProjectNode ?? false;
126025
+ this._elevationSortFunction = cfg.elevationSortFunction ?? undefined;
126026
+ this._defaultSortFunction = cfg.defaultSortFunction ?? undefined;
126111
126027
 
126112
126028
  if (!this._renderService) {
126113
126029
  throw new Error('TreeViewPlugin: no render service set');
@@ -126921,9 +126837,11 @@ class TreeViewPlugin extends Plugin {
126921
126837
  }
126922
126838
  const firstChild = children[0];
126923
126839
  if ((this._hierarchy === "storeys" || this._hierarchy === "containment") && firstChild.type === "IfcBuildingStorey") {
126924
- children.sort(this._getSpatialSortFunc());
126840
+ if (this._elevationSortFunction) children.sort(this._elevationSortFunction);
126841
+ else children.sort(this._getSpatialSortFunc());
126925
126842
  } else {
126926
- children.sort(this._alphaSortFunc);
126843
+ if (this._defaultSortFunction) children.sort(this._defaultSortFunction);
126844
+ else children.sort(this._alphaSortFunc);
126927
126845
  }
126928
126846
  for (let i = 0, len = children.length; i < len; i++) {
126929
126847
  const node = children[i];