@xeokit/xeokit-sdk 2.6.0-beta-11 → 2.6.0-beta-13

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.
@@ -9145,6 +9145,140 @@ class MarqueePickerMouseControl extends Component {
9145
9145
  }
9146
9146
  }
9147
9147
 
9148
+ /**
9149
+ * A PointerCircle shows a circle, centered at the position of the
9150
+ * mouse or touch pointer.
9151
+ */
9152
+ class PointerCircle {
9153
+
9154
+ /**
9155
+ * Constructs a new PointerCircle.
9156
+ * @param viewer The Viewer
9157
+ * @param [cfg] PointerCircle configuration.
9158
+ * @param [cfg.active=true] Whether PointerCircle is active. The PointerCircle can only be shown when this is `true` (default).
9159
+ */
9160
+ constructor(viewer, cfg = {}) {
9161
+
9162
+ this.viewer = viewer;
9163
+ this.scene = this.viewer.scene;
9164
+ this._circleDiv = document.createElement('div');
9165
+ this.viewer.scene.canvas.canvas.parentNode.insertBefore(this._circleDiv, this.viewer.scene.canvas.canvas);
9166
+ this._circleDiv.style.backgroundColor = "transparent";
9167
+ this._circleDiv.style.border = "2px solid green";
9168
+ this._circleDiv.style.borderRadius = "50px";
9169
+ this._circleDiv.style.width = "50px";
9170
+ this._circleDiv.style.height = "50px";
9171
+ this._circleDiv.style.margin = "-200px -200px";
9172
+ this._circleDiv.style.zIndex = "100000";
9173
+ this._circleDiv.style.position = "absolute";
9174
+ this._circleDiv.style.pointerEvents = "none";
9175
+
9176
+ this._circlePos = null;
9177
+
9178
+ this._circleMaxRadius = 200;
9179
+ this._circleMinRadius = 2;
9180
+
9181
+ this._active = (cfg.active !== false);
9182
+ this._visible = false;
9183
+
9184
+ this._running = false;
9185
+ this._destroyed = false;
9186
+ }
9187
+
9188
+ /**
9189
+ * Show the circle at the given canvas coordinates and begin shrinking it.
9190
+ */
9191
+ start(circlePos) {
9192
+ if (this._destroyed) {
9193
+ return;
9194
+ }
9195
+ this._circlePos = circlePos;
9196
+ this._running = false;
9197
+ this._circleRadius = this._circleMaxRadius;
9198
+ this._circleDiv.style.borderRadius = `${this._circleRadius}px`;
9199
+ this._circleDiv.style.marginLeft = `${this._circlePos[0] - this._circleRadius}px`;
9200
+ this._circleDiv.style.marginTop = `${this._circlePos[1] - this._circleRadius}px`;
9201
+
9202
+ const startValue = this._circleMaxRadius;
9203
+ const endValue = 2;
9204
+ let startTime;
9205
+ const duration = 300;
9206
+
9207
+ const animateCircle = (currentTime) => {
9208
+ if (!this._running) {
9209
+ return;
9210
+ }
9211
+ if (!startTime) {
9212
+ startTime = currentTime;
9213
+ }
9214
+
9215
+ const elapsedTime = currentTime - startTime;
9216
+ const progress = Math.min(elapsedTime / duration, 1);
9217
+ const interpolatedValue = startValue + (endValue - startValue) * progress;
9218
+
9219
+ this._circleRadius = interpolatedValue;
9220
+ this._circleDiv.style.width = `${this._circleRadius}px`;
9221
+ this._circleDiv.style.height = `${this._circleRadius}px`;
9222
+ this._circleDiv.style.marginLeft = `${this._circlePos[0] - this._circleRadius / 2}px`;
9223
+ this._circleDiv.style.marginTop = `${this._circlePos[1] - this._circleRadius / 2}px`;
9224
+
9225
+ if (progress < 1) {
9226
+ requestAnimationFrame(animateCircle);
9227
+ }
9228
+ };
9229
+ this._running = true;
9230
+ requestAnimationFrame(animateCircle);
9231
+ this._circleDiv.style.visibility = "visible";
9232
+ }
9233
+
9234
+ /**
9235
+ * Stop the shricking circle and hide it.
9236
+ */
9237
+ stop() {
9238
+ if (this._destroyed) {
9239
+ return;
9240
+ }
9241
+ this._running = false;
9242
+ this._circleRadius = this._circleMaxRadius;
9243
+ this._circleDiv.style.borderRadius = `${this._circleRadius}px`;
9244
+ this._circleDiv.style.visibility = "hidden";
9245
+ }
9246
+
9247
+ /**
9248
+ * Sets the zoom factor for the lens.
9249
+ *
9250
+ * This is `2` by default.
9251
+ *
9252
+ * @param durationMs
9253
+ */
9254
+ set durationMs(durationMs) {
9255
+ this.stop();
9256
+ this._durationMs = durationMs;
9257
+ }
9258
+
9259
+ /**
9260
+ * Gets the zoom factor for the lens.
9261
+ *
9262
+ * This is `2` by default.
9263
+ *
9264
+ * @returns Number
9265
+ */
9266
+ get durationMs() {
9267
+ return this._durationMs;
9268
+ }
9269
+
9270
+ /**
9271
+ * Destroys this PointerCircle.
9272
+ */
9273
+ destroy() {
9274
+ if (!this._destroyed) {
9275
+ this.stop();
9276
+ document.body.removeChild(this._circleDiv);
9277
+ this._destroyed = true;
9278
+ }
9279
+ }
9280
+ }
9281
+
9148
9282
  /**
9149
9283
  @desc Base class for {@link Viewer} plugin classes.
9150
9284
  */
@@ -12628,6 +12762,46 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
12628
12762
  * });
12629
12763
  * });
12630
12764
  * ````
12765
+ *
12766
+ * ## Example 5: Creating AngleMeasurements with Touch Input
12767
+ *
12768
+ * In our fifth example, we'll show how to create angle measurements with touch input, with snapping
12769
+ * to the nearest vertex or edge. While creating the measurements, a long-touch when setting the
12770
+ * start, corner or end point will cause the point to snap to the nearest vertex or edge. A quick
12771
+ * touch-release will immediately set the point at the tapped position on the object surface.
12772
+ *
12773
+ * [[Run example](/examples/measurement/#angle_createWithTouch_snapping)]
12774
+ *
12775
+ * ````javascript
12776
+ * import {Viewer, XKTLoaderPlugin, AngleMeasurementsPlugin, AngleMeasurementsTouchControl} from "xeokit-sdk.es.js";
12777
+ *
12778
+ * const viewer = new Viewer({
12779
+ * canvasId: "myCanvas",
12780
+ * transparent: true
12781
+ * });
12782
+ *
12783
+ * viewer.scene.camera.eye = [-2.37, 18.97, -26.12];
12784
+ * viewer.scene.camera.look = [10.97, 5.82, -11.22];
12785
+ * viewer.scene.camera.up = [0.36, 0.83, 0.40];
12786
+ *
12787
+ * const xktLoader = new XKTLoaderPlugin(viewer);
12788
+ *
12789
+ * const angleMeasurements = new AngleMeasurementsPlugin(viewer);
12790
+ *
12791
+ * const model = xktLoader.load({
12792
+ * src: "./models/xkt/duplex/duplex.xkt"
12793
+ * });
12794
+ *
12795
+ * const angleMeasurements = new AngleMeasurementsPlugin(viewer);
12796
+ *
12797
+ * const angleMeasurementsTouchControl = new AngleMeasurementsTouchControl(angleMeasurements, {
12798
+ * pointerLens : new PointerLens(viewer),
12799
+ * snapToVertex: true,
12800
+ * snapToEdge: true
12801
+ * })
12802
+ *
12803
+ * angleMeasurementsTouchControl.activate();
12804
+ * ````
12631
12805
  */
12632
12806
  class AngleMeasurementsPlugin extends Plugin {
12633
12807
 
@@ -12829,6 +13003,915 @@ class AngleMeasurementsPlugin extends Plugin {
12829
13003
  }
12830
13004
  }
12831
13005
 
13006
+ const WAITING_FOR_ORIGIN_TOUCH_START$1 = 0;
13007
+ const WAITING_FOR_ORIGIN_QUICK_TOUCH_END$1 = 1;
13008
+ const WAITING_FOR_ORIGIN_LONG_TOUCH_END$1 = 2;
13009
+
13010
+ const WAITING_FOR_CORNER_TOUCH_START = 3;
13011
+ const WAITING_FOR_CORNER_QUICK_TOUCH_END = 4;
13012
+ const WAITING_FOR_CORNER_LONG_TOUCH_END = 5;
13013
+
13014
+ const WAITING_FOR_TARGET_TOUCH_START$1 = 6;
13015
+ const WAITING_FOR_TARGET_QUICK_TOUCH_END$1 = 7;
13016
+ const WAITING_FOR_TARGET_LONG_TOUCH_END$1 = 8;
13017
+
13018
+ const TOUCH_CANCELING$1 = 7;
13019
+
13020
+ /**
13021
+ * Creates {@link AngleMeasurement}s from touch input.
13022
+ *
13023
+ * See {@link AngleMeasurementsPlugin} for more info.
13024
+ *
13025
+ */
13026
+ class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
13027
+
13028
+ /**
13029
+ * Creates a AngleMeasurementsTouchControl bound to the given AngleMeasurementsPlugin.
13030
+ */
13031
+ constructor(angleMeasurementsPlugin, cfg = {}) {
13032
+
13033
+ super(angleMeasurementsPlugin.viewer.scene);
13034
+
13035
+ this.pointerLens = cfg.pointerLens;
13036
+ this.pointerCircle = new PointerCircle(angleMeasurementsPlugin.viewer);
13037
+
13038
+ this._active = false;
13039
+
13040
+ const markerDiv = document.createElement('div');
13041
+ const canvas = this.scene.canvas.canvas;
13042
+ canvas.parentNode.insertBefore(markerDiv, canvas);
13043
+
13044
+ markerDiv.style.background = "black";
13045
+ markerDiv.style.border = "2px solid blue";
13046
+ markerDiv.style.borderRadius = "10px";
13047
+ markerDiv.style.width = "5px";
13048
+ markerDiv.style.height = "5px";
13049
+ markerDiv.style.margin = "-200px -200px";
13050
+ markerDiv.style.zIndex = "100";
13051
+ markerDiv.style.position = "absolute";
13052
+ markerDiv.style.pointerEvents = "none";
13053
+
13054
+ this.markerDiv = markerDiv;
13055
+
13056
+ this._currentAngleMeasurement = null;
13057
+
13058
+ this._onCanvasTouchStart = null;
13059
+ this._onCanvasTouchEnd = null;
13060
+ this._longTouchTimeoutMs = 300;
13061
+ this._snapToEdge = cfg.snapToEdge !== false;
13062
+ this._snapToVertex = cfg.snapToVertex !== false;
13063
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13064
+
13065
+ this._attachPlugin(angleMeasurementsPlugin, cfg);
13066
+ }
13067
+
13068
+ _attachPlugin(angleMeasurementsPlugin) {
13069
+
13070
+ /**
13071
+ * The {@link AngleMeasurementsPlugin} that owns this AngleMeasurementsTouchControl.
13072
+ * @type {AngleMeasurementsPlugin}
13073
+ */
13074
+ this.angleMeasurementsPlugin = angleMeasurementsPlugin;
13075
+
13076
+ /**
13077
+ * The {@link AngleMeasurementsPlugin} that owns this AngleMeasurementsTouchControl.
13078
+ * @type {AngleMeasurementsPlugin}
13079
+ */
13080
+ this.plugin = angleMeasurementsPlugin;
13081
+ }
13082
+
13083
+ /** Gets if this AngleMeasurementsTouchControl is currently active, where it is responding to input.
13084
+ *
13085
+ * @returns {Boolean}
13086
+ */
13087
+ get active() {
13088
+ return this._active;
13089
+ }
13090
+
13091
+ /**
13092
+ * Sets whether snap-to-vertex is enabled for this AngleMeasurementsTouchControl.
13093
+ * This is `true` by default.
13094
+ * @param snapToVertex
13095
+ */
13096
+ set snapToVertex(snapToVertex) {
13097
+ this._snapToVertex = snapToVertex;
13098
+ }
13099
+
13100
+ /**
13101
+ * Gets whether snap-to-vertex is enabled for this AngleMeasurementsTouchControl.
13102
+ * This is `true` by default.
13103
+ * @returns {*}
13104
+ */
13105
+ get snapToVertex() {
13106
+ return this._snapToVertex;
13107
+ }
13108
+
13109
+ /**
13110
+ * Sets whether snap-to-edge is enabled for this AngleMeasurementsTouchControl.
13111
+ * This is `true` by default.
13112
+ * @param snapToEdge
13113
+ */
13114
+ set snapToEdge(snapToEdge) {
13115
+ this._snapToEdge = snapToEdge;
13116
+ }
13117
+
13118
+ /**
13119
+ * Gets whether snap-to-edge is enabled for this AngleMeasurementsTouchControl.
13120
+ * This is `true` by default.
13121
+ * @returns {*}
13122
+ */
13123
+ get snapToEdge() {
13124
+ return this._snapToEdge;
13125
+ }
13126
+
13127
+ /**
13128
+ * Activates this AngleMeasurementsTouchControl, ready to respond to input.
13129
+ */
13130
+ activate() {
13131
+
13132
+ if (this._active) {
13133
+ return;
13134
+ }
13135
+
13136
+ const plugin = this.plugin;
13137
+ const scene = this.scene;
13138
+ const canvas = scene.canvas.canvas;
13139
+ plugin.pointerLens;
13140
+ const pointerWorldPos = math.vec3();
13141
+
13142
+ const touchTolerance = 20;
13143
+
13144
+ let longTouchTimeout = null;
13145
+
13146
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13147
+
13148
+ const touchStartCanvasPos = math.vec2();
13149
+ const touchMoveCanvasPos = math.vec2();
13150
+ const touchEndCanvasPos = math.vec2();
13151
+
13152
+ let touchId = null;
13153
+
13154
+ const disableCameraMouseControl = () => {
13155
+ this.plugin.viewer.cameraControl.active = false;
13156
+ };
13157
+
13158
+ const enableCameraMouseControl = () => {
13159
+ this.plugin.viewer.cameraControl.active = true;
13160
+ };
13161
+
13162
+ const cancel = () => {
13163
+ if (longTouchTimeout) {
13164
+ clearTimeout(longTouchTimeout);
13165
+ longTouchTimeout = null;
13166
+ }
13167
+ if (this._currentAngleMeasurement) {
13168
+ this._currentAngleMeasurement.destroy();
13169
+ this._currentAngleMeasurement = null;
13170
+ }
13171
+ enableCameraMouseControl();
13172
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13173
+ };
13174
+
13175
+ canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
13176
+
13177
+ const currentNumTouches = event.touches.length;
13178
+
13179
+ if (currentNumTouches !== 1) {
13180
+ if (longTouchTimeout) {
13181
+ clearTimeout(longTouchTimeout);
13182
+ longTouchTimeout = null;
13183
+ }
13184
+ return;
13185
+ }
13186
+
13187
+ const touch = event.touches[0];
13188
+ const touchX = touch.clientX;
13189
+ const touchY = touch.clientY;
13190
+
13191
+ touchStartCanvasPos.set([touchX, touchY]);
13192
+ touchMoveCanvasPos.set([touchX, touchY]);
13193
+
13194
+ switch (this._touchState) {
13195
+
13196
+ case WAITING_FOR_ORIGIN_TOUCH_START$1:
13197
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
13198
+ cancel();
13199
+ return;
13200
+ }
13201
+ const snapPickResult = scene.pick({
13202
+ canvasPos: touchMoveCanvasPos,
13203
+ snapToVertex: this._snapToVertex,
13204
+ snapToEdge: this._snapToEdge
13205
+ });
13206
+ if (snapPickResult && snapPickResult.snapped) {
13207
+ pointerWorldPos.set(snapPickResult.worldPos);
13208
+ this.pointerCircle.start(snapPickResult.snappedCanvasPos);
13209
+ } else {
13210
+ const pickResult = scene.pick({
13211
+ canvasPos: touchMoveCanvasPos,
13212
+ pickSurface: true
13213
+ });
13214
+ if (pickResult && pickResult.worldPos) {
13215
+ pointerWorldPos.set(pickResult.worldPos);
13216
+ this.pointerCircle.start(pickResult.canvasPos);
13217
+ } else {
13218
+ return;
13219
+ }
13220
+ }
13221
+ longTouchTimeout = setTimeout(() => {
13222
+ if (currentNumTouches !== 1 ||
13223
+ touchMoveCanvasPos[0] > touchStartCanvasPos[0] + touchTolerance ||
13224
+ touchMoveCanvasPos[0] < touchStartCanvasPos[0] - touchTolerance ||
13225
+ touchMoveCanvasPos[1] > touchStartCanvasPos[1] + touchTolerance ||
13226
+ touchMoveCanvasPos[1] < touchStartCanvasPos[1] - touchTolerance) {
13227
+ return; // Has moved
13228
+ }
13229
+ // Long touch
13230
+ if (this.pointerLens) {
13231
+ this.pointerLens.visible = true;
13232
+ this.pointerLens.canvasPos = touchStartCanvasPos;
13233
+ this.pointerLens.cursorPos = touchStartCanvasPos;
13234
+ }
13235
+ if (this.pointerLens) {
13236
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
13237
+ this.pointerLens.snapped = false;
13238
+ }
13239
+ if (this.pointerLens) {
13240
+ this.pointerLens.cursorPos = snapPickResult.canvasPos;
13241
+ this.pointerLens.snapped = true;
13242
+ }
13243
+ // pointerWorldPos.set(snapPickResult.worldPos);
13244
+ if (!this._currentAngleMeasurement) {
13245
+ this._currentAngleMeasurement = plugin.createMeasurement({
13246
+ id: math.createUUID(),
13247
+ origin: {
13248
+ worldPos: snapPickResult.worldPos
13249
+ },
13250
+ corner: {
13251
+ worldPos: snapPickResult.worldPos
13252
+ },
13253
+ target: {
13254
+ worldPos: snapPickResult.worldPos
13255
+ }
13256
+ });
13257
+ this._currentAngleMeasurement.clickable = false;
13258
+ this._currentAngleMeasurement.originVisible = true;
13259
+ this._currentAngleMeasurement.originWireVisible = false;
13260
+ this._currentAngleMeasurement.cornerVisible = false;
13261
+ this._currentAngleMeasurement.cornerWireVisible = false;
13262
+ this._currentAngleMeasurement.targetVisible = false;
13263
+ this._currentAngleMeasurement.targetWireVisible = false;
13264
+ this._currentAngleMeasurement.angleVisible = false;
13265
+ } else {
13266
+ this._currentAngleMeasurement.origin.worldPos = pointerWorldPos;
13267
+ }
13268
+ this.angleMeasurementsPlugin.fire("measurementStart", this._currentAngleMeasurement);
13269
+ // if (this.pointerLens) {
13270
+ // this.pointerLens.cursorPos = pickResult.canvasPos;
13271
+ // this.pointerLens.snapped = false;
13272
+ // }
13273
+ this._touchState = WAITING_FOR_ORIGIN_LONG_TOUCH_END$1;
13274
+ // console.log("touchstart: this._touchState= WAITING_FOR_ORIGIN_TOUCH_START -> WAITING_FOR_ORIGIN_LONG_TOUCH_END")
13275
+ disableCameraMouseControl();
13276
+ }, this._longTouchTimeoutMs);
13277
+ this._touchState = WAITING_FOR_ORIGIN_QUICK_TOUCH_END$1;
13278
+ //console.log("touchstart: this._touchState= WAITING_FOR_ORIGIN_TOUCH_START -> WAITING_FOR_ORIGIN_QUICK_TOUCH_END")
13279
+
13280
+ touchId = touch.identifier;
13281
+
13282
+ break;
13283
+
13284
+ case WAITING_FOR_CORNER_TOUCH_START:
13285
+
13286
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
13287
+ clearTimeout(longTouchTimeout);
13288
+ longTouchTimeout = null;
13289
+ return;
13290
+ }
13291
+ if (currentNumTouches === 1) { // One finger down
13292
+ longTouchTimeout = setTimeout(() => {
13293
+ longTouchTimeout = null;
13294
+ if (currentNumTouches !== 1 ||
13295
+ touchMoveCanvasPos[0] > touchStartCanvasPos[0] + touchTolerance ||
13296
+ touchMoveCanvasPos[0] < touchStartCanvasPos[0] - touchTolerance ||
13297
+ touchMoveCanvasPos[1] > touchStartCanvasPos[1] + touchTolerance ||
13298
+ touchMoveCanvasPos[1] < touchStartCanvasPos[1] - touchTolerance) {
13299
+ // Has moved
13300
+ return;
13301
+ }
13302
+
13303
+ // Long touch
13304
+ if (this.pointerLens) {
13305
+ this.pointerLens.visible = true;
13306
+ this.pointerLens.canvasPos = touchStartCanvasPos;
13307
+ this.pointerLens.snapped = false;
13308
+ }
13309
+
13310
+ const snapPickResult = scene.pick({
13311
+ canvasPos: touchMoveCanvasPos,
13312
+ snapToVertex: this._snapToVertex,
13313
+ snapToEdge: this._snapToEdge
13314
+ });
13315
+ if (snapPickResult && snapPickResult.snapped) {
13316
+ if (this.pointerLens) {
13317
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
13318
+ this.pointerLens.snapped = true;
13319
+ }
13320
+ this.pointerCircle.start(snapPickResult.snappedCanvasPos);
13321
+ pointerWorldPos.set(snapPickResult.worldPos);
13322
+ this._currentAngleMeasurement.corner.worldPos = snapPickResult.worldPos;
13323
+ this._currentAngleMeasurement.originVisible = true;
13324
+ this._currentAngleMeasurement.originWireVisible = true;
13325
+ this._currentAngleMeasurement.cornerVisible = true;
13326
+ this._currentAngleMeasurement.cornerWireVisible = false;
13327
+ this._currentAngleMeasurement.targetVisible = false;
13328
+ this._currentAngleMeasurement.targetWireVisible = false;
13329
+ this._currentAngleMeasurement.angleVisible = false;
13330
+ this.angleMeasurementsPlugin.fire("measurementStart", this._currentAngleMeasurement);
13331
+ } else {
13332
+ const pickResult = scene.pick({
13333
+ canvasPos: touchMoveCanvasPos,
13334
+ pickSurface: true
13335
+ });
13336
+ if (pickResult && pickResult.worldPos) {
13337
+ if (this.pointerLens) {
13338
+ this.pointerLens.cursorPos = pickResult.canvasPos;
13339
+ this.pointerLens.snapped = false;
13340
+ }
13341
+ this.pointerCircle.start(pickResult.canvasPos);
13342
+ pointerWorldPos.set(pickResult.worldPos);
13343
+ this._currentAngleMeasurement.corner.worldPos = pickResult.worldPos;
13344
+ this._currentAngleMeasurement.originVisible = true;
13345
+ this._currentAngleMeasurement.originWireVisible = true;
13346
+ this._currentAngleMeasurement.cornerVisible = true;
13347
+ this._currentAngleMeasurement.cornerWireVisible = false;
13348
+ this._currentAngleMeasurement.targetVisible = false;
13349
+ this._currentAngleMeasurement.targetWireVisible = false;
13350
+ this._currentAngleMeasurement.angleVisible = false;
13351
+ this.angleMeasurementsPlugin.fire("measurementStart", this._currentAngleMeasurement);
13352
+ } else {
13353
+ if (this.pointerLens) {
13354
+ this.pointerLens.cursorPos = null;
13355
+ this.pointerLens.snapped = false;
13356
+
13357
+ }
13358
+ }
13359
+ }
13360
+ this._touchState = WAITING_FOR_CORNER_LONG_TOUCH_END;
13361
+ // console.log("touchstart: this._touchState= WAITING_FOR_CORNER_TOUCH_START -> WAITING_FOR_CORNER_LONG_TOUCH_END")
13362
+
13363
+ disableCameraMouseControl();
13364
+
13365
+ }, this._longTouchTimeoutMs);
13366
+
13367
+ this._touchState = WAITING_FOR_CORNER_QUICK_TOUCH_END;
13368
+ // console.log("touchstart: this._touchState= WAITING_FOR_CORNER_TOUCH_START -> WAITING_FOR_CORNER_QUICK_TOUCH_END")
13369
+ }
13370
+
13371
+ touchId = touch.identifier;
13372
+
13373
+ break;
13374
+
13375
+ case WAITING_FOR_TARGET_TOUCH_START$1:
13376
+
13377
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
13378
+ clearTimeout(longTouchTimeout);
13379
+ longTouchTimeout = null;
13380
+ return;
13381
+ }
13382
+ if (currentNumTouches === 1) { // One finger down
13383
+ longTouchTimeout = setTimeout(() => {
13384
+ longTouchTimeout = null;
13385
+ if (currentNumTouches !== 1 ||
13386
+ touchMoveCanvasPos[0] > touchStartCanvasPos[0] + touchTolerance ||
13387
+ touchMoveCanvasPos[0] < touchStartCanvasPos[0] - touchTolerance ||
13388
+ touchMoveCanvasPos[1] > touchStartCanvasPos[1] + touchTolerance ||
13389
+ touchMoveCanvasPos[1] < touchStartCanvasPos[1] - touchTolerance) {
13390
+ // Has moved
13391
+ return;
13392
+ }
13393
+
13394
+ // Long touch
13395
+ if (this.pointerLens) {
13396
+ this.pointerLens.visible = true;
13397
+ this.pointerLens.canvasPos = touchStartCanvasPos;
13398
+ this.pointerLens.snapped = false;
13399
+ }
13400
+
13401
+ const snapPickResult = scene.pick({
13402
+ canvasPos: touchMoveCanvasPos,
13403
+ snapToVertex: this._snapToVertex,
13404
+ snapToEdge: this._snapToEdge
13405
+ });
13406
+ if (snapPickResult && snapPickResult.snapped) {
13407
+ if (this.pointerLens) {
13408
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
13409
+ this.pointerLens.snapped = true;
13410
+ }
13411
+ this.pointerCircle.start(snapPickResult.snappedCanvasPos);
13412
+ pointerWorldPos.set(snapPickResult.worldPos);
13413
+ this._currentAngleMeasurement.target.worldPos = snapPickResult.worldPos;
13414
+ this._currentAngleMeasurement.originVisible = true;
13415
+ this._currentAngleMeasurement.originWireVisible = true;
13416
+ this._currentAngleMeasurement.cornerVisible = true;
13417
+ this._currentAngleMeasurement.cornerWireVisible = true;
13418
+ this._currentAngleMeasurement.targetVisible = true;
13419
+ this._currentAngleMeasurement.targetWireVisible = true;
13420
+ this._currentAngleMeasurement.angleVisible = true;
13421
+ this.angleMeasurementsPlugin.fire("measurementStart", this._currentAngleMeasurement);
13422
+ } else {
13423
+ const pickResult = scene.pick({
13424
+ canvasPos: touchMoveCanvasPos,
13425
+ pickSurface: true
13426
+ });
13427
+ if (pickResult && pickResult.worldPos) {
13428
+ if (this.pointerLens) {
13429
+ this.pointerLens.cursorPos = pickResult.canvasPos;
13430
+ this.pointerLens.snapped = false;
13431
+ }
13432
+ this.pointerCircle.start(pickResult.canvasPos);
13433
+ pointerWorldPos.set(pickResult.worldPos);
13434
+ this._currentAngleMeasurement.target.worldPos = pickResult.worldPos;
13435
+ this._currentAngleMeasurement.originVisible = true;
13436
+ this._currentAngleMeasurement.originWireVisible = true;
13437
+ this._currentAngleMeasurement.cornerVisible = true;
13438
+ this._currentAngleMeasurement.cornerWireVisible = true;
13439
+ this._currentAngleMeasurement.targetVisible = true;
13440
+ this._currentAngleMeasurement.targetWireVisible = true;
13441
+ this._currentAngleMeasurement.angleVisible = true;
13442
+ this.angleMeasurementsPlugin.fire("measurementStart", this._currentAngleMeasurement);
13443
+ } else {
13444
+ if (this.pointerLens) {
13445
+ this.pointerLens.cursorPos = null;
13446
+ this.pointerLens.snapped = false;
13447
+
13448
+ }
13449
+ }
13450
+ }
13451
+ this._touchState = WAITING_FOR_TARGET_LONG_TOUCH_END$1;
13452
+ // console.log("touchstart: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_LONG_TOUCH_END")
13453
+
13454
+ disableCameraMouseControl();
13455
+
13456
+ }, this._longTouchTimeoutMs);
13457
+
13458
+ this._touchState = WAITING_FOR_TARGET_QUICK_TOUCH_END$1;
13459
+ // console.log("touchstart: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_QUICK_TOUCH_END")
13460
+ }
13461
+
13462
+ touchId = touch.identifier;
13463
+
13464
+ break;
13465
+
13466
+
13467
+ default:
13468
+ if (longTouchTimeout !== null) {
13469
+ clearTimeout(longTouchTimeout);
13470
+ longTouchTimeout = null;
13471
+ }
13472
+ this._touchState = TOUCH_CANCELING$1;
13473
+ // console.log("touchstart: this._touchState= default -> TOUCH_CANCELING")
13474
+ return;
13475
+ }
13476
+
13477
+ }, {passive: true});
13478
+
13479
+
13480
+ canvas.addEventListener("touchmove", (event) => {
13481
+
13482
+ this.pointerCircle.stop();
13483
+
13484
+ const currentNumTouches = event.touches.length;
13485
+
13486
+ if (currentNumTouches !== 1 || event.changedTouches.length !== 1) {
13487
+ if (longTouchTimeout) {
13488
+ clearTimeout(longTouchTimeout);
13489
+ longTouchTimeout = null;
13490
+ }
13491
+ return;
13492
+ }
13493
+
13494
+ const touch = event.touches[0];
13495
+ const touchX = touch.clientX;
13496
+ const touchY = touch.clientY;
13497
+
13498
+ if (touch.identifier !== touchId) {
13499
+ return;
13500
+ }
13501
+
13502
+ touchMoveCanvasPos.set([touchX, touchY]);
13503
+
13504
+ let snapPickResult;
13505
+ let pickResult;
13506
+
13507
+ switch (this._touchState) {
13508
+
13509
+ case WAITING_FOR_ORIGIN_LONG_TOUCH_END$1:
13510
+ if (this.pointerLens) {
13511
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
13512
+ }
13513
+ snapPickResult = scene.pick({
13514
+ canvasPos: touchMoveCanvasPos,
13515
+ snapToVertex: this._snapToVertex,
13516
+ snapToEdge: this._snapToEdge
13517
+ });
13518
+ if (snapPickResult && (snapPickResult.snapped)) {
13519
+ if (this.pointerLens) {
13520
+ this.pointerLens.snappedCanvasPos = snapPickResult.snappedCanvasPos;
13521
+ this.pointerLens.snapped = true;
13522
+ }
13523
+ pointerWorldPos.set(snapPickResult.worldPos);
13524
+ this._currentAngleMeasurement.origin.worldPos = snapPickResult.worldPos;
13525
+ } else {
13526
+ pickResult = scene.pick({
13527
+ canvasPos: touchMoveCanvasPos,
13528
+ pickSurface: true
13529
+ });
13530
+ if (pickResult && pickResult.worldPos) {
13531
+ if (this.pointerLens) {
13532
+ this.pointerLens.cursorPos = pickResult.canvasPos;
13533
+ this.pointerLens.snapped = false;
13534
+ }
13535
+ pointerWorldPos.set(pickResult.worldPos);
13536
+ this._currentAngleMeasurement.origin.worldPos = pickResult.worldPos;
13537
+ } else {
13538
+ if (this.pointerLens) {
13539
+ this.pointerLens.cursorPos = null;
13540
+ this.pointerLens.snapped = false;
13541
+ }
13542
+ }
13543
+ }
13544
+ this._touchState = WAITING_FOR_ORIGIN_LONG_TOUCH_END$1;
13545
+ // console.log("touchmove: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END -> WAITING_FOR_ORIGIN_LONG_TOUCH_END")
13546
+ break;
13547
+
13548
+ case WAITING_FOR_CORNER_LONG_TOUCH_END:
13549
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
13550
+ clearTimeout(longTouchTimeout);
13551
+ longTouchTimeout = null;
13552
+ if (this.pointerLens) {
13553
+ this.pointerLens.visible = false;
13554
+ }
13555
+ this._touchState = TOUCH_CANCELING$1;
13556
+ // console.log("touchmove: this._touchState= QUICK_TOUCH_FINDING_CORNER -> TOUCH_CANCELING")
13557
+ return;
13558
+ }
13559
+ if (this.pointerLens) {
13560
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
13561
+ }
13562
+ snapPickResult = scene.pick({
13563
+ canvasPos: touchMoveCanvasPos,
13564
+ snapToVertex: this._snapToVertex,
13565
+ snapToEdge: this._snapToEdge
13566
+ });
13567
+ if (snapPickResult && snapPickResult.worldPos) {
13568
+ if (this.pointerLens) {
13569
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
13570
+ this.pointerLens.snapped = true;
13571
+ }
13572
+ this._currentAngleMeasurement.corner.worldPos = snapPickResult.worldPos;
13573
+ this._currentAngleMeasurement.originVisible = true;
13574
+ this._currentAngleMeasurement.originWireVisible = true;
13575
+ this._currentAngleMeasurement.cornerVisible = true;
13576
+ this._currentAngleMeasurement.cornerWireVisible = false;
13577
+ this._currentAngleMeasurement.targetVisible = false;
13578
+ this._currentAngleMeasurement.targetWireVisible = false;
13579
+ this._currentAngleMeasurement.angleVisible = false;
13580
+ } else {
13581
+ pickResult = scene.pick({
13582
+ canvasPos: touchMoveCanvasPos,
13583
+ pickSurface: true
13584
+ });
13585
+ if (pickResult && pickResult.worldPos) {
13586
+ if (this.pointerLens) {
13587
+ this.pointerLens.cursorPos = pickResult.canvasPos;
13588
+ this.pointerLens.snapped = false;
13589
+ }
13590
+ this._currentAngleMeasurement.corner.worldPos = pickResult.worldPos;
13591
+ this._currentAngleMeasurement.originVisible = true;
13592
+ this._currentAngleMeasurement.originWireVisible = true;
13593
+ this._currentAngleMeasurement.cornerVisible = true;
13594
+ this._currentAngleMeasurement.cornerWireVisible = false;
13595
+ this._currentAngleMeasurement.targetVisible = false;
13596
+ this._currentAngleMeasurement.targetWireVisible = false;
13597
+ this._currentAngleMeasurement.angleVisible = false;
13598
+ }
13599
+ }
13600
+ this._touchState = WAITING_FOR_CORNER_LONG_TOUCH_END;
13601
+ break;
13602
+
13603
+
13604
+ case WAITING_FOR_TARGET_LONG_TOUCH_END$1:
13605
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
13606
+ clearTimeout(longTouchTimeout);
13607
+ longTouchTimeout = null;
13608
+ if (this.pointerLens) {
13609
+ this.pointerLens.visible = false;
13610
+ }
13611
+ this._touchState = TOUCH_CANCELING$1;
13612
+ // console.log("touchmove: this._touchState= QUICK_TOUCH_FINDING_TARGET -> TOUCH_CANCELING")
13613
+ return;
13614
+ }
13615
+ if (this.pointerLens) {
13616
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
13617
+ }
13618
+ snapPickResult = scene.pick({
13619
+ canvasPos: touchMoveCanvasPos,
13620
+ snapToVertex: this._snapToVertex,
13621
+ snapToEdge: this._snapToEdge
13622
+ });
13623
+ if (snapPickResult && snapPickResult.worldPos) {
13624
+ if (this.pointerLens) {
13625
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
13626
+ this.pointerLens.snapped = true;
13627
+ }
13628
+ this._currentAngleMeasurement.target.worldPos = snapPickResult.worldPos;
13629
+ this._currentAngleMeasurement.originVisible = true;
13630
+ this._currentAngleMeasurement.originWireVisible = true;
13631
+ this._currentAngleMeasurement.cornerVisible = true;
13632
+ this._currentAngleMeasurement.cornerWireVisible = true;
13633
+ this._currentAngleMeasurement.targetVisible = true;
13634
+ this._currentAngleMeasurement.targetWireVisible = true;
13635
+ this._currentAngleMeasurement.angleVisible = true;
13636
+ } else {
13637
+ pickResult = scene.pick({
13638
+ canvasPos: touchMoveCanvasPos,
13639
+ pickSurface: true
13640
+ });
13641
+ if (pickResult && pickResult.worldPos) {
13642
+ if (this.pointerLens) {
13643
+ this.pointerLens.cursorPos = pickResult.canvasPos;
13644
+ this.pointerLens.snapped = false;
13645
+ }
13646
+ this._currentAngleMeasurement.target.worldPos = pickResult.worldPos;
13647
+ this._currentAngleMeasurement.originVisible = true;
13648
+ this._currentAngleMeasurement.originWireVisible = true;
13649
+ this._currentAngleMeasurement.cornerVisible = true;
13650
+ this._currentAngleMeasurement.cornerWireVisible = true;
13651
+ this._currentAngleMeasurement.targetVisible = true;
13652
+ this._currentAngleMeasurement.targetWireVisible = true;
13653
+ this._currentAngleMeasurement.angleVisible = true;
13654
+ }
13655
+ }
13656
+ this._touchState = WAITING_FOR_TARGET_LONG_TOUCH_END$1;
13657
+ break;
13658
+ }
13659
+ }, {passive: true});
13660
+
13661
+ canvas.addEventListener("touchend", this._onCanvasTouchEnd = (event) => {
13662
+
13663
+ this.pointerCircle.stop();
13664
+
13665
+ const numChangedTouches = event.changedTouches.length;
13666
+
13667
+ if (numChangedTouches !== 1) {
13668
+ return;
13669
+ }
13670
+
13671
+ const touch = event.changedTouches[0];
13672
+ const touchX = touch.clientX;
13673
+ const touchY = touch.clientY;
13674
+
13675
+ if (touch.identifier !== touchId) {
13676
+ return;
13677
+ }
13678
+
13679
+ if (longTouchTimeout) {
13680
+ clearTimeout(longTouchTimeout);
13681
+ longTouchTimeout = null;
13682
+ }
13683
+
13684
+ touchEndCanvasPos.set([touchX, touchY]);
13685
+
13686
+ switch (this._touchState) {
13687
+
13688
+ case WAITING_FOR_ORIGIN_QUICK_TOUCH_END$1: {
13689
+ if (numChangedTouches !== 1 ||
13690
+ touchX > touchStartCanvasPos[0] + touchTolerance ||
13691
+ touchX < touchStartCanvasPos[0] - touchTolerance ||
13692
+ touchY > touchStartCanvasPos[1] + touchTolerance ||
13693
+ touchY < touchStartCanvasPos[1] - touchTolerance) {
13694
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13695
+ return;
13696
+ }
13697
+ const pickResult = scene.pick({
13698
+ canvasPos: touchMoveCanvasPos,
13699
+ pickSurface: true
13700
+ });
13701
+ if (pickResult && pickResult.worldPos) {
13702
+ this._currentAngleMeasurement = plugin.createMeasurement({
13703
+ id: math.createUUID(),
13704
+ origin: {
13705
+ worldPos: pickResult.worldPos
13706
+ },
13707
+ corner: {
13708
+ worldPos: pickResult.worldPos
13709
+ },
13710
+ target: {
13711
+ worldPos: pickResult.worldPos
13712
+ }
13713
+ });
13714
+ this._currentAngleMeasurement.clickable = false;
13715
+ this._currentAngleMeasurement.originVisible = true;
13716
+ this._currentAngleMeasurement.originWireVisible = false;
13717
+ this._currentAngleMeasurement.cornerVisible = false;
13718
+ this._currentAngleMeasurement.cornerWireVisible = false;
13719
+ this._currentAngleMeasurement.targetVisible = false;
13720
+ this._currentAngleMeasurement.targetWireVisible = false;
13721
+ this._currentAngleMeasurement.angleVisible = false;
13722
+ this._touchState = WAITING_FOR_CORNER_TOUCH_START;
13723
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_QUICK_TOUCH_END -> WAITING_FOR_CORNER_TOUCH_START")
13724
+ } else {
13725
+ if (this._currentAngleMeasurement) {
13726
+ this._currentAngleMeasurement.destroy();
13727
+ this._currentAngleMeasurement = null;
13728
+ }
13729
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13730
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_QUICK_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
13731
+ }
13732
+ }
13733
+ enableCameraMouseControl();
13734
+ break;
13735
+
13736
+ case WAITING_FOR_ORIGIN_LONG_TOUCH_END$1:
13737
+ if (this.pointerLens) {
13738
+ this.pointerLens.visible = false;
13739
+ }
13740
+ if (!this._currentAngleMeasurement) {
13741
+ if (this.pointerLens) {
13742
+ this.pointerLens.snapped = false;
13743
+ this.pointerLens.visible = false;
13744
+ }
13745
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13746
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END (no measurement) -> WAITING_FOR_ORIGIN_TOUCH_START")
13747
+ } else {
13748
+ this._touchState = WAITING_FOR_CORNER_TOUCH_START;
13749
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END (picked, begin measurement) -> WAITING_FOR_CORNER_TOUCH_START")
13750
+ }
13751
+ enableCameraMouseControl();
13752
+ break;
13753
+
13754
+ case WAITING_FOR_CORNER_QUICK_TOUCH_END: {
13755
+ if (numChangedTouches !== 1 ||
13756
+ touchX > touchStartCanvasPos[0] + touchTolerance ||
13757
+ touchX < touchStartCanvasPos[0] - touchTolerance ||
13758
+ touchY > touchStartCanvasPos[1] + touchTolerance ||
13759
+ touchY < touchStartCanvasPos[1] - touchTolerance) {
13760
+ this._touchState = WAITING_FOR_CORNER_TOUCH_START;
13761
+ return;
13762
+ }
13763
+ const pickResult = scene.pick({
13764
+ canvasPos: touchMoveCanvasPos,
13765
+ pickSurface: true
13766
+ });
13767
+ if (pickResult && pickResult.worldPos) {
13768
+ this._currentAngleMeasurement.corner.worldPos = pickResult.worldPos;
13769
+ this._currentAngleMeasurement.originVisible = true;
13770
+ this._currentAngleMeasurement.originWireVisible = true;
13771
+ this._currentAngleMeasurement.cornerVisible = true;
13772
+ this._currentAngleMeasurement.cornerWireVisible = false;
13773
+ this._currentAngleMeasurement.targetVisible = false;
13774
+ this._currentAngleMeasurement.targetWireVisible = false;
13775
+ this._currentAngleMeasurement.angleVisible = false;
13776
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START$1;
13777
+ // console.log("touchend: this._touchState= WAITING_FOR_CORNER_TOUCH_START -> WAITING_FOR_ORIGIN_TOUCH_START")
13778
+ } else {
13779
+ if (this._currentAngleMeasurement) {
13780
+ this._currentAngleMeasurement.destroy();
13781
+ this._currentAngleMeasurement = null;
13782
+ }
13783
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13784
+ // console.log("touchend: this._touchState= WAITING_FOR_CORNER_TOUCH_START -> WAITING_FOR_ORIGIN_TOUCH_START")
13785
+ }
13786
+
13787
+ }
13788
+ enableCameraMouseControl();
13789
+ break;
13790
+
13791
+ case WAITING_FOR_CORNER_LONG_TOUCH_END:
13792
+ if (this.pointerLens) {
13793
+ this.pointerLens.visible = false;
13794
+ }
13795
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START$1;
13796
+ // console.log("touchend: this._touchState= WAITING_FOR_CORNER_LONG_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
13797
+ enableCameraMouseControl();
13798
+ break;
13799
+
13800
+ case WAITING_FOR_TARGET_QUICK_TOUCH_END$1: {
13801
+ if (numChangedTouches !== 1 ||
13802
+ touchX > touchStartCanvasPos[0] + touchTolerance ||
13803
+ touchX < touchStartCanvasPos[0] - touchTolerance ||
13804
+ touchY > touchStartCanvasPos[1] + touchTolerance ||
13805
+ touchY < touchStartCanvasPos[1] - touchTolerance) {
13806
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START$1;
13807
+ return;
13808
+ }
13809
+ const pickResult = scene.pick({
13810
+ canvasPos: touchMoveCanvasPos,
13811
+ pickSurface: true
13812
+ });
13813
+ if (pickResult && pickResult.worldPos) {
13814
+ this._currentAngleMeasurement.target.worldPos = pickResult.worldPos;
13815
+ this._currentAngleMeasurement.originVisible = true;
13816
+ this._currentAngleMeasurement.originWireVisible = true;
13817
+ this._currentAngleMeasurement.cornerVisible = true;
13818
+ this._currentAngleMeasurement.cornerWireVisible = true;
13819
+ this._currentAngleMeasurement.targetVisible = true;
13820
+ this._currentAngleMeasurement.targetWireVisible = true;
13821
+ this._currentAngleMeasurement.angleVisible = true;
13822
+ this.angleMeasurementsPlugin.fire("measurementEnd", this._currentAngleMeasurement);
13823
+ this._currentAngleMeasurement = null;
13824
+ } else {
13825
+ if (this._currentAngleMeasurement) {
13826
+ this._currentAngleMeasurement.destroy();
13827
+ this._currentAngleMeasurement = null;
13828
+ }
13829
+ }
13830
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13831
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_ORIGIN_TOUCH_START")
13832
+ }
13833
+ enableCameraMouseControl();
13834
+ break;
13835
+
13836
+ case WAITING_FOR_TARGET_LONG_TOUCH_END$1:
13837
+ if (this.pointerLens) {
13838
+ this.pointerLens.visible = false;
13839
+ }
13840
+ if (!this._currentAngleMeasurement || !this._currentAngleMeasurement.targetVisible) {
13841
+ if (this._currentAngleMeasurement) {
13842
+ this._currentAngleMeasurement.destroy();
13843
+ this._currentAngleMeasurement = null;
13844
+ }
13845
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13846
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_LONG_TOUCH_END (no target found) -> WAITING_FOR_ORIGIN_TOUCH_START")
13847
+ } else {
13848
+ this._currentAngleMeasurement.clickable = true;
13849
+ this.angleMeasurementsPlugin.fire("measurementEnd", this._currentAngleMeasurement);
13850
+ this._currentAngleMeasurement = null;
13851
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START$1;
13852
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_LONG_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
13853
+ }
13854
+ enableCameraMouseControl();
13855
+ break;
13856
+ }
13857
+
13858
+ }, {passive: true});
13859
+
13860
+ this._active = true;
13861
+ }
13862
+
13863
+ /**
13864
+ * Deactivates this AngleMeasurementsTouchControl, making it unresponsive to input.
13865
+ *
13866
+ * Destroys any {@link AngleMeasurement} under construction.
13867
+ */
13868
+ deactivate() {
13869
+ if (!this._active) {
13870
+ return;
13871
+ }
13872
+ if (this.plugin.pointerLens) {
13873
+ this.plugin.pointerLens.visible = false;
13874
+ }
13875
+ this.reset();
13876
+ const canvas = this.plugin.viewer.scene.canvas.canvas;
13877
+ canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
13878
+ canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
13879
+ if (this._currentAngleMeasurement) {
13880
+ this.angleMeasurementsPlugin.fire("measurementCancel", this._currentAngleMeasurement);
13881
+ this._currentAngleMeasurement.destroy();
13882
+ this._currentAngleMeasurement = null;
13883
+ }
13884
+ this._active = false;
13885
+ this.plugin.viewer.cameraControl.active = true;
13886
+ }
13887
+
13888
+ /**
13889
+ * Resets this AngleMeasurementsTouchControl.
13890
+ *
13891
+ * Destroys any {@link AngleMeasurement} under construction.
13892
+ *
13893
+ * Does nothing if the AngleMeasurementsTouchControl is not active.
13894
+ */
13895
+ reset() {
13896
+ if (!this._active) {
13897
+ return;
13898
+ }
13899
+ if (this._currentAngleMeasurement) {
13900
+ this.angleMeasurementsPlugin.fire("measurementCancel", this._currentAngleMeasurement);
13901
+ this._currentAngleMeasurement.destroy();
13902
+ this._currentAngleMeasurement = null;
13903
+ }
13904
+ }
13905
+
13906
+ /**
13907
+ * Destroys this AngleMeasurementsTouchControl.
13908
+ */
13909
+ destroy() {
13910
+ this.deactivate();
13911
+ super.destroy();
13912
+ }
13913
+ }
13914
+
12832
13915
  /**
12833
13916
  * A {@link Marker} with an HTML label attached to it, managed by an {@link AnnotationsPlugin}.
12834
13917
  *
@@ -15263,6 +16346,14 @@ class PickResult {
15263
16346
  }
15264
16347
  }
15265
16348
 
16349
+ /**
16350
+ * True if snapped to edge or vertex.
16351
+ * @returns {boolean}
16352
+ */
16353
+ get snapped() {
16354
+ return this.snappedToEdge || this.snappedToVertex;
16355
+ }
16356
+
15266
16357
  /**
15267
16358
  * @private
15268
16359
  */
@@ -86430,6 +87521,46 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
86430
87521
  * });
86431
87522
  * });
86432
87523
  * ````
87524
+ *
87525
+ * ## Example 5: Creating DistanceMeasurements with Touch Input
87526
+ *
87527
+ * In our fifth example, we'll show how to create distance measurements with touch input, with snapping
87528
+ * to the nearest vertex or edge. While creating the measurements, a long-touch when setting the
87529
+ * start or end point will cause the point to snap to the nearest vertex or edge. A quick
87530
+ * touch-release will immediately set the point at the tapped position on the object surface.
87531
+ *
87532
+ * [[Run example](/examples/measurement/#distance_createWithTouch_snapping)]
87533
+ *
87534
+ * ````javascript
87535
+ * import {Viewer, XKTLoaderPlugin, DistanceMeasurementsPlugin, DistanceMeasurementsTouchControl} from "xeokit-sdk.es.js";
87536
+ *
87537
+ * const viewer = new Viewer({
87538
+ * canvasId: "myCanvas",
87539
+ * transparent: true
87540
+ * });
87541
+ *
87542
+ * viewer.scene.camera.eye = [-2.37, 18.97, -26.12];
87543
+ * viewer.scene.camera.look = [10.97, 5.82, -11.22];
87544
+ * viewer.scene.camera.up = [0.36, 0.83, 0.40];
87545
+ *
87546
+ * const xktLoader = new XKTLoaderPlugin(viewer);
87547
+ *
87548
+ * const distanceMeasurements = new DistanceMeasurementsPlugin(viewer);
87549
+ *
87550
+ * const model = xktLoader.load({
87551
+ * src: "./models/xkt/duplex/duplex.xkt"
87552
+ * });
87553
+ *
87554
+ * const distanceMeasurements = new DistanceMeasurementsPlugin(viewer);
87555
+ *
87556
+ * const distanceMeasurementsTouchControl = new DistanceMeasurementsTouchControl(distanceMeasurements, {
87557
+ * pointerLens : new PointerLens(viewer),
87558
+ * snapToVertex: true,
87559
+ * snapToEdge: true
87560
+ * })
87561
+ *
87562
+ * distanceMeasurementsTouchControl.activate();
87563
+ * ````
86433
87564
  */
86434
87565
  class DistanceMeasurementsPlugin extends Plugin {
86435
87566
 
@@ -86663,7 +87794,7 @@ class DistanceMeasurementsPlugin extends Plugin {
86663
87794
  }
86664
87795
 
86665
87796
  /**
86666
- * Shows all or hides the angle label of each {@link DistanceMeasurement}.
87797
+ * Shows all or hides the distance label of each {@link DistanceMeasurement}.
86667
87798
  *
86668
87799
  * @param {Boolean} labelsShown Whether or not to show the labels.
86669
87800
  */
@@ -86715,6 +87846,752 @@ class DistanceMeasurementsPlugin extends Plugin {
86715
87846
  }
86716
87847
  }
86717
87848
 
87849
+ const WAITING_FOR_ORIGIN_TOUCH_START = 0;
87850
+ const WAITING_FOR_ORIGIN_QUICK_TOUCH_END = 1;
87851
+ const WAITING_FOR_ORIGIN_LONG_TOUCH_END = 2;
87852
+
87853
+ const WAITING_FOR_TARGET_TOUCH_START = 3;
87854
+ const WAITING_FOR_TARGET_QUICK_TOUCH_END = 4;
87855
+ const WAITING_FOR_TARGET_LONG_TOUCH_END = 5;
87856
+
87857
+ const TOUCH_CANCELING = 7;
87858
+
87859
+ /**
87860
+ * Creates {@link DistanceMeasurement}s from touch input.
87861
+ *
87862
+ * See {@link DistanceMeasurementsPlugin} for more info.
87863
+ *
87864
+ */
87865
+ class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
87866
+
87867
+ /**
87868
+ * Creates a DistanceMeasurementsTouchControl bound to the given DistanceMeasurementsPlugin.
87869
+ */
87870
+ constructor(distanceMeasurementsPlugin, cfg = {}) {
87871
+
87872
+ super(distanceMeasurementsPlugin.viewer.scene);
87873
+
87874
+ this.pointerLens = cfg.pointerLens;
87875
+ this.pointerCircle = new PointerCircle(distanceMeasurementsPlugin.viewer);
87876
+
87877
+ this._active = false;
87878
+
87879
+ const markerDiv = document.createElement('div');
87880
+ const canvas = this.scene.canvas.canvas;
87881
+ canvas.parentNode.insertBefore(markerDiv, canvas);
87882
+
87883
+ markerDiv.style.background = "black";
87884
+ markerDiv.style.border = "2px solid blue";
87885
+ markerDiv.style.borderRadius = "10px";
87886
+ markerDiv.style.width = "5px";
87887
+ markerDiv.style.height = "5px";
87888
+ markerDiv.style.margin = "-200px -200px";
87889
+ markerDiv.style.zIndex = "100";
87890
+ markerDiv.style.position = "absolute";
87891
+ markerDiv.style.pointerEvents = "none";
87892
+
87893
+ this.markerDiv = markerDiv;
87894
+
87895
+ this._currentDistanceMeasurement = null;
87896
+
87897
+ this._currentDistanceMeasurementInitState = {
87898
+ wireVisible: null,
87899
+ axisVisible: null,
87900
+ xAxisVisible: null,
87901
+ yaxisVisible: null,
87902
+ zAxisVisible: null,
87903
+ targetVisible: null,
87904
+ };
87905
+
87906
+ this._onCanvasTouchStart = null;
87907
+ this._onCanvasTouchEnd = null;
87908
+ this._longTouchTimeoutMs = 300;
87909
+ this._snapToEdge = cfg.snapToEdge !== false;
87910
+ this._snapToVertex = cfg.snapToVertex !== false;
87911
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
87912
+
87913
+ this._attachPlugin(distanceMeasurementsPlugin, cfg);
87914
+ }
87915
+
87916
+ _attachPlugin(distanceMeasurementsPlugin) {
87917
+
87918
+ /**
87919
+ * The {@link DistanceMeasurementsPlugin} that owns this DistanceMeasurementsTouchControl.
87920
+ * @type {DistanceMeasurementsPlugin}
87921
+ */
87922
+ this.distanceMeasurementsPlugin = distanceMeasurementsPlugin;
87923
+
87924
+ /**
87925
+ * The {@link DistanceMeasurementsPlugin} that owns this DistanceMeasurementsTouchControl.
87926
+ * @type {DistanceMeasurementsPlugin}
87927
+ */
87928
+ this.plugin = distanceMeasurementsPlugin;
87929
+ }
87930
+
87931
+ /** Gets if this DistanceMeasurementsTouchControl is currently active, where it is responding to input.
87932
+ *
87933
+ * @returns {Boolean}
87934
+ */
87935
+ get active() {
87936
+ return this._active;
87937
+ }
87938
+
87939
+ /**
87940
+ * Sets whether snap-to-vertex is enabled for this DistanceMeasurementsTouchControl.
87941
+ * This is `true` by default.
87942
+ * @param snapToVertex
87943
+ */
87944
+ set snapToVertex(snapToVertex) {
87945
+ this._snapToVertex = snapToVertex;
87946
+ }
87947
+
87948
+ /**
87949
+ * Gets whether snap-to-vertex is enabled for this DistanceMeasurementsTouchControl.
87950
+ * This is `true` by default.
87951
+ * @returns {*}
87952
+ */
87953
+ get snapToVertex() {
87954
+ return this._snapToVertex;
87955
+ }
87956
+
87957
+ /**
87958
+ * Sets whether snap-to-edge is enabled for this DistanceMeasurementsTouchControl.
87959
+ * This is `true` by default.
87960
+ * @param snapToEdge
87961
+ */
87962
+ set snapToEdge(snapToEdge) {
87963
+ this._snapToEdge = snapToEdge;
87964
+ }
87965
+
87966
+ /**
87967
+ * Gets whether snap-to-edge is enabled for this DistanceMeasurementsTouchControl.
87968
+ * This is `true` by default.
87969
+ * @returns {*}
87970
+ */
87971
+ get snapToEdge() {
87972
+ return this._snapToEdge;
87973
+ }
87974
+
87975
+ /**
87976
+ * Activates this DistanceMeasurementsTouchControl, ready to respond to input.
87977
+ */
87978
+ activate() {
87979
+
87980
+ if (this._active) {
87981
+ return;
87982
+ }
87983
+
87984
+ const plugin = this.plugin;
87985
+ const scene = this.scene;
87986
+ const canvas = scene.canvas.canvas;
87987
+ plugin.pointerLens;
87988
+ const pointerWorldPos = math.vec3();
87989
+
87990
+ const touchTolerance = 20;
87991
+
87992
+ let longTouchTimeout = null;
87993
+
87994
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
87995
+
87996
+ const touchStartCanvasPos = math.vec2();
87997
+ const touchMoveCanvasPos = math.vec2();
87998
+ const touchEndCanvasPos = math.vec2();
87999
+
88000
+ let touchId = null;
88001
+
88002
+ const disableCameraMouseControl = () => {
88003
+ this.plugin.viewer.cameraControl.active = false;
88004
+ };
88005
+
88006
+ const enableCameraMouseControl = () => {
88007
+ this.plugin.viewer.cameraControl.active = true;
88008
+ };
88009
+
88010
+ const cancel = () => {
88011
+ if (longTouchTimeout) {
88012
+ clearTimeout(longTouchTimeout);
88013
+ longTouchTimeout = null;
88014
+ }
88015
+ if (this._currentDistanceMeasurement) {
88016
+ this._currentDistanceMeasurement.destroy();
88017
+ this._currentDistanceMeasurement = null;
88018
+ }
88019
+ enableCameraMouseControl();
88020
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
88021
+ };
88022
+
88023
+ canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
88024
+
88025
+ const currentNumTouches = event.touches.length;
88026
+
88027
+ if (currentNumTouches !== 1) {
88028
+ if (longTouchTimeout) {
88029
+ clearTimeout(longTouchTimeout);
88030
+ longTouchTimeout = null;
88031
+ }
88032
+ return;
88033
+ }
88034
+
88035
+ const touch = event.touches[0];
88036
+ const touchX = touch.clientX;
88037
+ const touchY = touch.clientY;
88038
+
88039
+ touchStartCanvasPos.set([touchX, touchY]);
88040
+ touchMoveCanvasPos.set([touchX, touchY]);
88041
+
88042
+ switch (this._touchState) {
88043
+
88044
+ case WAITING_FOR_ORIGIN_TOUCH_START:
88045
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
88046
+ cancel();
88047
+ return;
88048
+ }
88049
+ const snapPickResult = scene.pick({
88050
+ canvasPos: touchMoveCanvasPos,
88051
+ snapToVertex: this._snapToVertex,
88052
+ snapToEdge: this._snapToEdge
88053
+ });
88054
+ if (snapPickResult && snapPickResult.snapped) {
88055
+ pointerWorldPos.set(snapPickResult.worldPos);
88056
+ this.pointerCircle.start(snapPickResult.snappedCanvasPos);
88057
+ } else {
88058
+ const pickResult = scene.pick({
88059
+ canvasPos: touchMoveCanvasPos,
88060
+ pickSurface: true
88061
+ });
88062
+ if (pickResult && pickResult.worldPos) {
88063
+ pointerWorldPos.set(pickResult.worldPos);
88064
+ this.pointerCircle.start(pickResult.canvasPos);
88065
+ } else {
88066
+ return;
88067
+ }
88068
+ }
88069
+ longTouchTimeout = setTimeout(() => {
88070
+ if (currentNumTouches !== 1 ||
88071
+ touchMoveCanvasPos[0] > touchStartCanvasPos[0] + touchTolerance ||
88072
+ touchMoveCanvasPos[0] < touchStartCanvasPos[0] - touchTolerance ||
88073
+ touchMoveCanvasPos[1] > touchStartCanvasPos[1] + touchTolerance ||
88074
+ touchMoveCanvasPos[1] < touchStartCanvasPos[1] - touchTolerance) {
88075
+ return; // Has moved
88076
+ }
88077
+ // Long touch
88078
+ if (this.pointerLens) {
88079
+ this.pointerLens.visible = true;
88080
+ this.pointerLens.canvasPos = touchStartCanvasPos;
88081
+ this.pointerLens.cursorPos = touchStartCanvasPos;
88082
+ }
88083
+ if (this.pointerLens) {
88084
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
88085
+ this.pointerLens.snapped = false;
88086
+ }
88087
+ if (this.pointerLens) {
88088
+ this.pointerLens.cursorPos = snapPickResult.canvasPos;
88089
+ this.pointerLens.snapped = true;
88090
+ }
88091
+ // pointerWorldPos.set(snapPickResult.snappedWorldPos);
88092
+ if (!this._currentDistanceMeasurement) {
88093
+ this._currentDistanceMeasurement = plugin.createMeasurement({
88094
+ id: math.createUUID(),
88095
+ origin: {
88096
+ worldPos: pointerWorldPos
88097
+ },
88098
+ target: {
88099
+ worldPos: pointerWorldPos
88100
+ }
88101
+ });
88102
+ this._currentDistanceMeasurement.labelsVisible = false;
88103
+ this._currentDistanceMeasurement.xAxisVisible = false;
88104
+ this._currentDistanceMeasurement.yAxisVisible = false;
88105
+ this._currentDistanceMeasurement.zAxisVisible = false;
88106
+ this._currentDistanceMeasurement.wireVisible = false;
88107
+ this._currentDistanceMeasurement.originVisible = true;
88108
+ this._currentDistanceMeasurement.targetVisible = false;
88109
+ this._currentDistanceMeasurement.clickable = false;
88110
+ } else {
88111
+ this._currentDistanceMeasurement.origin.worldPos = pointerWorldPos;
88112
+ }
88113
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
88114
+ // if (this.pointerLens) {
88115
+ // this.pointerLens.cursorPos = pickResult.canvasPos;
88116
+ // this.pointerLens.snapped = false;
88117
+ // }
88118
+ this._touchState = WAITING_FOR_ORIGIN_LONG_TOUCH_END;
88119
+ // console.log("touchstart: this._touchState= WAITING_FOR_ORIGIN_TOUCH_START -> WAITING_FOR_ORIGIN_LONG_TOUCH_END")
88120
+ disableCameraMouseControl();
88121
+ }, this._longTouchTimeoutMs);
88122
+ this._touchState = WAITING_FOR_ORIGIN_QUICK_TOUCH_END;
88123
+ // console.log("touchstart: this._touchState= WAITING_FOR_ORIGIN_TOUCH_START -> WAITING_FOR_ORIGIN_QUICK_TOUCH_END")
88124
+
88125
+ touchId = touch.identifier;
88126
+
88127
+ break;
88128
+
88129
+
88130
+ case WAITING_FOR_TARGET_TOUCH_START:
88131
+
88132
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
88133
+ clearTimeout(longTouchTimeout);
88134
+ longTouchTimeout = null;
88135
+ return;
88136
+ }
88137
+ if (currentNumTouches === 1) { // One finger down
88138
+ longTouchTimeout = setTimeout(() => {
88139
+ longTouchTimeout = null;
88140
+ if (currentNumTouches !== 1 ||
88141
+ touchMoveCanvasPos[0] > touchStartCanvasPos[0] + touchTolerance ||
88142
+ touchMoveCanvasPos[0] < touchStartCanvasPos[0] - touchTolerance ||
88143
+ touchMoveCanvasPos[1] > touchStartCanvasPos[1] + touchTolerance ||
88144
+ touchMoveCanvasPos[1] < touchStartCanvasPos[1] - touchTolerance) {
88145
+ // Has moved
88146
+ return;
88147
+ }
88148
+
88149
+ // Long touch
88150
+ if (this.pointerLens) {
88151
+ this.pointerLens.visible = true;
88152
+ this.pointerLens.canvasPos = touchStartCanvasPos;
88153
+ this.pointerLens.snapped = false;
88154
+ }
88155
+
88156
+ const snapPickResult = scene.pick({
88157
+ canvasPos: touchMoveCanvasPos,
88158
+ snapToVertex: this._snapToVertex,
88159
+ snapToEdge: this._snapToEdge
88160
+ });
88161
+ if (snapPickResult && snapPickResult.snapped) {
88162
+ if (this.pointerLens) {
88163
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
88164
+ this.pointerLens.snapped = true;
88165
+ }
88166
+ this.pointerCircle.start(snapPickResult.snappedCanvasPos);
88167
+ pointerWorldPos.set(snapPickResult.worldPos);
88168
+ this._currentDistanceMeasurement.target.worldPos = snapPickResult.worldPos;
88169
+ this._currentDistanceMeasurement.targetVisible = true;
88170
+ this._currentDistanceMeasurement.wireVisible = true;
88171
+ this._currentDistanceMeasurement.labelsVisible = true;
88172
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
88173
+ } else {
88174
+ const pickResult = scene.pick({
88175
+ canvasPos: touchMoveCanvasPos,
88176
+ pickSurface: true
88177
+ });
88178
+ if (pickResult && pickResult.worldPos) {
88179
+ if (this.pointerLens) {
88180
+ this.pointerLens.cursorPos = pickResult.canvasPos;
88181
+ this.pointerLens.snapped = false;
88182
+ }
88183
+ this.pointerCircle.start(pickResult.canvasPos);
88184
+ pointerWorldPos.set(pickResult.worldPos);
88185
+ this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
88186
+ this._currentDistanceMeasurement.targetVisible = true;
88187
+ this._currentDistanceMeasurement.wireVisible = true;
88188
+ this._currentDistanceMeasurement.labelsVisible = true;
88189
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
88190
+ } else {
88191
+ if (this.pointerLens) {
88192
+ this.pointerLens.cursorPos = null;
88193
+ this.pointerLens.snapped = false;
88194
+
88195
+ }
88196
+ }
88197
+ }
88198
+ this._touchState = WAITING_FOR_TARGET_LONG_TOUCH_END;
88199
+ // console.log("touchstart: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_LONG_TOUCH_END")
88200
+
88201
+ disableCameraMouseControl();
88202
+
88203
+ }, this._longTouchTimeoutMs);
88204
+
88205
+ this._touchState = WAITING_FOR_TARGET_QUICK_TOUCH_END;
88206
+ // console.log("touchstart: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_QUICK_TOUCH_END")
88207
+ }
88208
+
88209
+ touchId = touch.identifier;
88210
+
88211
+ break;
88212
+
88213
+ default:
88214
+ if (longTouchTimeout !== null) {
88215
+ clearTimeout(longTouchTimeout);
88216
+ longTouchTimeout = null;
88217
+ }
88218
+ this._touchState = TOUCH_CANCELING;
88219
+ // console.log("touchstart: this._touchState= default -> TOUCH_CANCELING")
88220
+ return;
88221
+ }
88222
+
88223
+ }, {passive: true});
88224
+
88225
+
88226
+ canvas.addEventListener("touchmove", (event) => {
88227
+
88228
+ this.pointerCircle.stop();
88229
+
88230
+ const currentNumTouches = event.touches.length;
88231
+
88232
+ if (currentNumTouches !== 1 || event.changedTouches.length !== 1) {
88233
+ if (longTouchTimeout) {
88234
+ clearTimeout(longTouchTimeout);
88235
+ longTouchTimeout = null;
88236
+ }
88237
+ return;
88238
+ }
88239
+
88240
+ const touch = event.touches[0];
88241
+ const touchX = touch.clientX;
88242
+ const touchY = touch.clientY;
88243
+
88244
+ if (touch.identifier !== touchId) {
88245
+ return;
88246
+ }
88247
+
88248
+ touchMoveCanvasPos.set([touchX, touchY]);
88249
+
88250
+ let snapPickResult;
88251
+ let pickResult;
88252
+
88253
+ switch (this._touchState) {
88254
+
88255
+ case WAITING_FOR_ORIGIN_LONG_TOUCH_END:
88256
+ if (this.pointerLens) {
88257
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
88258
+ }
88259
+ snapPickResult = scene.pick({
88260
+ canvasPos: touchMoveCanvasPos,
88261
+
88262
+
88263
+ snapToVertex: this._snapToVertex,
88264
+ snapToEdge: this._snapToEdge
88265
+ });
88266
+ if (snapPickResult && (snapPickResult.snapped)) {
88267
+ if (this.pointerLens) {
88268
+ this.pointerLens.snappedCanvasPos = snapPickResult.snappedCanvasPos;
88269
+ this.pointerLens.snapped = true;
88270
+ }
88271
+ pointerWorldPos.set(snapPickResult.worldPos);
88272
+ if (!this._currentDistanceMeasurement) {
88273
+ this._currentDistanceMeasurement = plugin.createMeasurement({
88274
+ id: math.createUUID(),
88275
+ origin: {
88276
+ worldPos: snapPickResult.worldPos
88277
+ },
88278
+ target: {
88279
+ worldPos: snapPickResult.worldPos
88280
+ }
88281
+ });
88282
+ this._currentDistanceMeasurement.labelsVisible = false;
88283
+ this._currentDistanceMeasurement.xAxisVisible = false;
88284
+ this._currentDistanceMeasurement.yAxisVisible = false;
88285
+ this._currentDistanceMeasurement.zAxisVisible = false;
88286
+ this._currentDistanceMeasurement.wireVisible = false;
88287
+ this._currentDistanceMeasurement.originVisible = true;
88288
+ this._currentDistanceMeasurement.targetVisible = false;
88289
+ this._currentDistanceMeasurement.clickable = false;
88290
+ } else {
88291
+ this._currentDistanceMeasurement.origin.worldPos = snapPickResult.worldPos;
88292
+ }
88293
+
88294
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
88295
+ } else {
88296
+ pickResult = scene.pick({
88297
+ canvasPos: touchMoveCanvasPos,
88298
+ pickSurface: true
88299
+ });
88300
+ if (pickResult && pickResult.worldPos) {
88301
+ if (this.pointerLens) {
88302
+ this.pointerLens.cursorPos = pickResult.canvasPos;
88303
+ this.pointerLens.snapped = false;
88304
+ }
88305
+ pointerWorldPos.set(pickResult.worldPos);
88306
+ if (!this._currentDistanceMeasurement) {
88307
+ this._currentDistanceMeasurement = plugin.createMeasurement({
88308
+ id: math.createUUID(),
88309
+ origin: {
88310
+ worldPos: pickResult.worldPos
88311
+ },
88312
+ target: {
88313
+ worldPos: pickResult.worldPos
88314
+ }
88315
+ });
88316
+ this._currentDistanceMeasurement.labelsVisible = false;
88317
+ this._currentDistanceMeasurement.xAxisVisible = false;
88318
+ this._currentDistanceMeasurement.yAxisVisible = false;
88319
+ this._currentDistanceMeasurement.zAxisVisible = false;
88320
+ this._currentDistanceMeasurement.wireVisible = false;
88321
+ this._currentDistanceMeasurement.originVisible = true;
88322
+ this._currentDistanceMeasurement.targetVisible = false;
88323
+ this._currentDistanceMeasurement.clickable = false;
88324
+ } else {
88325
+ this._currentDistanceMeasurement.origin.worldPos = pickResult.worldPos;
88326
+ }
88327
+
88328
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
88329
+ } else {
88330
+ if (this.pointerLens) {
88331
+ this.pointerLens.cursorPos = null;
88332
+ this.pointerLens.snapped = false;
88333
+ }
88334
+ }
88335
+ }
88336
+ this._touchState = WAITING_FOR_ORIGIN_LONG_TOUCH_END;
88337
+ // console.log("touchmove: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END -> WAITING_FOR_ORIGIN_LONG_TOUCH_END")
88338
+ break;
88339
+
88340
+ // case WAITING_FOR_TARGET_TOUCH_START:
88341
+ // this._touchState = WAITING_FOR_TARGET_TOUCH_START;
88342
+ // console.log("touchmove: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_TOUCH_START")
88343
+ // break;
88344
+
88345
+ case WAITING_FOR_TARGET_LONG_TOUCH_END:
88346
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
88347
+ clearTimeout(longTouchTimeout);
88348
+ longTouchTimeout = null;
88349
+ if (this.pointerLens) {
88350
+ this.pointerLens.visible = false;
88351
+ }
88352
+ this._touchState = TOUCH_CANCELING;
88353
+ // console.log("touchmove: this._touchState= QUICK_TOUCH_FINDING_TARGET -> TOUCH_CANCELING")
88354
+ return;
88355
+ }
88356
+ if (this.pointerLens) {
88357
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
88358
+ }
88359
+ snapPickResult = scene.pick({
88360
+ canvasPos: touchMoveCanvasPos,
88361
+ snapToVertex: this._snapToVertex,
88362
+ snapToEdge: this._snapToEdge
88363
+ });
88364
+ if (snapPickResult && snapPickResult.worldPos) {
88365
+ if (this.pointerLens) {
88366
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
88367
+ this.pointerLens.snapped = true;
88368
+ }
88369
+ this._currentDistanceMeasurement.target.worldPos = snapPickResult.worldPos;
88370
+ this._currentDistanceMeasurement.targetVisible = true;
88371
+ this._currentDistanceMeasurement.wireVisible = true;
88372
+ this._currentDistanceMeasurement.labelsVisible = true;
88373
+ } else {
88374
+ pickResult = scene.pick({
88375
+ canvasPos: touchMoveCanvasPos,
88376
+ pickSurface: true
88377
+ });
88378
+ if (pickResult && pickResult.worldPos) {
88379
+ if (this.pointerLens) {
88380
+ this.pointerLens.cursorPos = pickResult.canvasPos;
88381
+ this.pointerLens.snapped = false;
88382
+ }
88383
+ this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
88384
+ this._currentDistanceMeasurement.targetVisible = true;
88385
+ this._currentDistanceMeasurement.wireVisible = true;
88386
+ this._currentDistanceMeasurement.labelsVisible = true;
88387
+
88388
+ }
88389
+ }
88390
+ this._touchState = WAITING_FOR_TARGET_LONG_TOUCH_END;
88391
+ break;
88392
+ }
88393
+ }, {passive: true});
88394
+
88395
+ canvas.addEventListener("touchend", this._onCanvasTouchEnd = (event) => {
88396
+
88397
+ this.pointerCircle.stop();
88398
+
88399
+ const numChangedTouches = event.changedTouches.length;
88400
+
88401
+ if (numChangedTouches !== 1) {
88402
+ return;
88403
+ }
88404
+
88405
+ const touch = event.changedTouches[0];
88406
+ const touchX = touch.clientX;
88407
+ const touchY = touch.clientY;
88408
+
88409
+ if (touch.identifier !== touchId) {
88410
+ return;
88411
+ }
88412
+
88413
+ if (longTouchTimeout) {
88414
+ clearTimeout(longTouchTimeout);
88415
+ longTouchTimeout = null;
88416
+ }
88417
+
88418
+ touchEndCanvasPos.set([touchX, touchY]);
88419
+
88420
+ switch (this._touchState) {
88421
+
88422
+ case WAITING_FOR_ORIGIN_QUICK_TOUCH_END: {
88423
+ if (numChangedTouches !== 1 ||
88424
+ touchX > touchStartCanvasPos[0] + touchTolerance ||
88425
+ touchX < touchStartCanvasPos[0] - touchTolerance ||
88426
+ touchY > touchStartCanvasPos[1] + touchTolerance ||
88427
+ touchY < touchStartCanvasPos[1] - touchTolerance) {
88428
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
88429
+ return;
88430
+ }
88431
+ const pickResult = scene.pick({
88432
+ canvasPos: touchMoveCanvasPos,
88433
+ pickSurface: true
88434
+ });
88435
+ if (pickResult && pickResult.worldPos) {
88436
+ this._currentDistanceMeasurement = plugin.createMeasurement({
88437
+ id: math.createUUID(),
88438
+ origin: {
88439
+ worldPos: pickResult.worldPos
88440
+ },
88441
+ target: {
88442
+ worldPos: pickResult.worldPos
88443
+ }
88444
+ });
88445
+ this._currentDistanceMeasurement.labelsVisible = false;
88446
+ this._currentDistanceMeasurement.xAxisVisible = false;
88447
+ this._currentDistanceMeasurement.yAxisVisible = false;
88448
+ this._currentDistanceMeasurement.zAxisVisible = false;
88449
+ this._currentDistanceMeasurement.wireVisible = false;
88450
+ this._currentDistanceMeasurement.originVisible = true;
88451
+ this._currentDistanceMeasurement.targetVisible = false;
88452
+ this._currentDistanceMeasurement.clickable = false;
88453
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START;
88454
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_QUICK_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
88455
+ } else {
88456
+ if (this._currentDistanceMeasurement) {
88457
+ this._currentDistanceMeasurement.destroy();
88458
+ }
88459
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
88460
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_QUICK_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
88461
+ }
88462
+ }
88463
+ enableCameraMouseControl();
88464
+ break;
88465
+
88466
+ case WAITING_FOR_ORIGIN_LONG_TOUCH_END:
88467
+ if (this.pointerLens) {
88468
+ this.pointerLens.visible = false;
88469
+ }
88470
+ if (!this._currentDistanceMeasurement) {
88471
+ if (this.pointerLens) {
88472
+ this.pointerLens.snapped = false;
88473
+ this.pointerLens.visible = false;
88474
+ }
88475
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
88476
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END (no measurement) -> WAITING_FOR_ORIGIN_TOUCH_START")
88477
+ } else {
88478
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START;
88479
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END (picked, begin measurement) -> WAITING_FOR_TARGET_TOUCH_START")
88480
+ }
88481
+ enableCameraMouseControl();
88482
+ break;
88483
+
88484
+ case WAITING_FOR_TARGET_QUICK_TOUCH_END: {
88485
+ if (numChangedTouches !== 1 ||
88486
+ touchX > touchStartCanvasPos[0] + touchTolerance ||
88487
+ touchX < touchStartCanvasPos[0] - touchTolerance ||
88488
+ touchY > touchStartCanvasPos[1] + touchTolerance ||
88489
+ touchY < touchStartCanvasPos[1] - touchTolerance) {
88490
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START;
88491
+ return;
88492
+ }
88493
+ const pickResult = scene.pick({
88494
+ canvasPos: touchMoveCanvasPos,
88495
+ pickSurface: true
88496
+ });
88497
+ if (pickResult && pickResult.worldPos) {
88498
+ this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
88499
+ this._currentDistanceMeasurement.targetVisible = true;
88500
+ this._currentDistanceMeasurement.wireVisible = true;
88501
+ this._currentDistanceMeasurement.labelsVisible = true;
88502
+ this.distanceMeasurementsPlugin.fire("measurementEnd", this._currentDistanceMeasurement);
88503
+ this._currentDistanceMeasurement = null;
88504
+ } else {
88505
+ if (this._currentDistanceMeasurement) {
88506
+ this._currentDistanceMeasurement.destroy();
88507
+ this._currentDistanceMeasurement = null;
88508
+ }
88509
+ }
88510
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
88511
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_ORIGIN_TOUCH_START")
88512
+ }
88513
+ enableCameraMouseControl();
88514
+ break;
88515
+
88516
+ case WAITING_FOR_TARGET_LONG_TOUCH_END:
88517
+ if (this.pointerLens) {
88518
+ this.pointerLens.visible = false;
88519
+ }
88520
+ if (!this._currentDistanceMeasurement || !this._currentDistanceMeasurement.targetVisible) {
88521
+ if (this._currentDistanceMeasurement) {
88522
+ this._currentDistanceMeasurement.destroy();
88523
+ this._currentDistanceMeasurement = null;
88524
+ }
88525
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
88526
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_LONG_TOUCH_END (no target found) -> WAITING_FOR_ORIGIN_TOUCH_START")
88527
+ } else {
88528
+ this._currentDistanceMeasurement.clickable = true;
88529
+ this.distanceMeasurementsPlugin.fire("measurementEnd", this._currentDistanceMeasurement);
88530
+ this._currentDistanceMeasurement = null;
88531
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
88532
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_LONG_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
88533
+ }
88534
+ enableCameraMouseControl();
88535
+ break;
88536
+ }
88537
+
88538
+ }, {passive: true});
88539
+
88540
+ this._active = true;
88541
+ }
88542
+
88543
+ /**
88544
+ * Deactivates this DistanceMeasurementsTouchControl, making it unresponsive to input.
88545
+ *
88546
+ * Destroys any {@link DistanceMeasurement} under construction.
88547
+ */
88548
+ deactivate() {
88549
+ if (!this._active) {
88550
+ return;
88551
+ }
88552
+ if (this.plugin.pointerLens) {
88553
+ this.plugin.pointerLens.visible = false;
88554
+ }
88555
+ this.reset();
88556
+ const canvas = this.plugin.viewer.scene.canvas.canvas;
88557
+ canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
88558
+ canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
88559
+ if (this._currentDistanceMeasurement) {
88560
+ this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
88561
+ this._currentDistanceMeasurement.destroy();
88562
+ this._currentDistanceMeasurement = null;
88563
+ }
88564
+ this._active = false;
88565
+ this.plugin.viewer.cameraControl.active = true;
88566
+ }
88567
+
88568
+ /**
88569
+ * Resets this DistanceMeasurementsTouchControl.
88570
+ *
88571
+ * Destroys any {@link DistanceMeasurement} under construction.
88572
+ *
88573
+ * Does nothing if the DistanceMeasurementsTouchControl is not active.
88574
+ */
88575
+ reset() {
88576
+ if (!this._active) {
88577
+ return;
88578
+ }
88579
+ if (this._currentDistanceMeasurement) {
88580
+ this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
88581
+ this._currentDistanceMeasurement.destroy();
88582
+ this._currentDistanceMeasurement = null;
88583
+ }
88584
+ }
88585
+
88586
+ /**
88587
+ * Destroys this DistanceMeasurementsTouchControl.
88588
+ */
88589
+ destroy() {
88590
+ this.deactivate();
88591
+ super.destroy();
88592
+ }
88593
+ }
88594
+
86718
88595
  /**
86719
88596
  * {@link Viewer} plugin that makes interaction smoother with large models, by temporarily switching
86720
88597
  * the Viewer to faster, lower-quality rendering modes whenever we interact.
@@ -134411,6 +136288,7 @@ exports.AmbientLight = AmbientLight;
134411
136288
  exports.AngleMeasurementsControl = AngleMeasurementsControl;
134412
136289
  exports.AngleMeasurementsMouseControl = AngleMeasurementsMouseControl;
134413
136290
  exports.AngleMeasurementsPlugin = AngleMeasurementsPlugin;
136291
+ exports.AngleMeasurementsTouchControl = AngleMeasurementsTouchControl;
134414
136292
  exports.AnnotationsPlugin = AnnotationsPlugin;
134415
136293
  exports.AxisGizmoPlugin = AxisGizmoPlugin;
134416
136294
  exports.BCFViewpointsPlugin = BCFViewpointsPlugin;
@@ -134434,6 +136312,7 @@ exports.DirLight = DirLight;
134434
136312
  exports.DistanceMeasurementsControl = DistanceMeasurementsControl;
134435
136313
  exports.DistanceMeasurementsMouseControl = DistanceMeasurementsMouseControl;
134436
136314
  exports.DistanceMeasurementsPlugin = DistanceMeasurementsPlugin;
136315
+ exports.DistanceMeasurementsTouchControl = DistanceMeasurementsTouchControl;
134437
136316
  exports.EdgeMaterial = EdgeMaterial;
134438
136317
  exports.EmphasisMaterial = EmphasisMaterial;
134439
136318
  exports.FaceAlignedSectionPlanesPlugin = FaceAlignedSectionPlanesPlugin;
@@ -134489,6 +136368,7 @@ exports.PerformanceModel = PerformanceModel;
134489
136368
  exports.PhongMaterial = PhongMaterial;
134490
136369
  exports.Plugin = Plugin;
134491
136370
  exports.PointLight = PointLight;
136371
+ exports.PointerCircle = PointerCircle;
134492
136372
  exports.PointerLens = PointerLens;
134493
136373
  exports.QuadraticBezierCurve = QuadraticBezierCurve;
134494
136374
  exports.Queue = Queue;