@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.
@@ -0,0 +1,753 @@
1
+ import {math} from "../../viewer/scene/math/math.js";
2
+ import {PointerCircle} from "../../extras/PointerCircle/PointerCircle.js";
3
+ import {DistanceMeasurementsControl} from "./DistanceMeasurementsControl.js";
4
+
5
+
6
+ const WAITING_FOR_ORIGIN_TOUCH_START = 0;
7
+ const WAITING_FOR_ORIGIN_QUICK_TOUCH_END = 1;
8
+ const WAITING_FOR_ORIGIN_LONG_TOUCH_END = 2;
9
+
10
+ const WAITING_FOR_TARGET_TOUCH_START = 3;
11
+ const WAITING_FOR_TARGET_QUICK_TOUCH_END = 4;
12
+ const WAITING_FOR_TARGET_LONG_TOUCH_END = 5;
13
+
14
+ const TOUCH_CANCELING = 7;
15
+
16
+ /**
17
+ * Creates {@link DistanceMeasurement}s from touch input.
18
+ *
19
+ * See {@link DistanceMeasurementsPlugin} for more info.
20
+ *
21
+ */
22
+ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsControl {
23
+
24
+ /**
25
+ * Creates a DistanceMeasurementsTouchControl bound to the given DistanceMeasurementsPlugin.
26
+ */
27
+ constructor(distanceMeasurementsPlugin, cfg = {}) {
28
+
29
+ super(distanceMeasurementsPlugin.viewer.scene);
30
+
31
+ this.pointerLens = cfg.pointerLens;
32
+ this.pointerCircle = new PointerCircle(distanceMeasurementsPlugin.viewer);
33
+
34
+ this._active = false;
35
+
36
+ const markerDiv = document.createElement('div');
37
+ const canvas = this.scene.canvas.canvas;
38
+ canvas.parentNode.insertBefore(markerDiv, canvas);
39
+
40
+ markerDiv.style.background = "black";
41
+ markerDiv.style.border = "2px solid blue";
42
+ markerDiv.style.borderRadius = "10px";
43
+ markerDiv.style.width = "5px";
44
+ markerDiv.style.height = "5px";
45
+ markerDiv.style.margin = "-200px -200px";
46
+ markerDiv.style.zIndex = "100";
47
+ markerDiv.style.position = "absolute";
48
+ markerDiv.style.pointerEvents = "none";
49
+
50
+ this.markerDiv = markerDiv;
51
+
52
+ this._currentDistanceMeasurement = null;
53
+
54
+ this._currentDistanceMeasurementInitState = {
55
+ wireVisible: null,
56
+ axisVisible: null,
57
+ xAxisVisible: null,
58
+ yaxisVisible: null,
59
+ zAxisVisible: null,
60
+ targetVisible: null,
61
+ }
62
+
63
+ this._onCanvasTouchStart = null;
64
+ this._onCanvasTouchEnd = null;
65
+ this._longTouchTimeoutMs = 300;
66
+ this._snapToEdge = cfg.snapToEdge !== false;
67
+ this._snapToVertex = cfg.snapToVertex !== false;
68
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
69
+
70
+ this._attachPlugin(distanceMeasurementsPlugin, cfg);
71
+ }
72
+
73
+ _attachPlugin(distanceMeasurementsPlugin) {
74
+
75
+ /**
76
+ * The {@link DistanceMeasurementsPlugin} that owns this DistanceMeasurementsTouchControl.
77
+ * @type {DistanceMeasurementsPlugin}
78
+ */
79
+ this.distanceMeasurementsPlugin = distanceMeasurementsPlugin;
80
+
81
+ /**
82
+ * The {@link DistanceMeasurementsPlugin} that owns this DistanceMeasurementsTouchControl.
83
+ * @type {DistanceMeasurementsPlugin}
84
+ */
85
+ this.plugin = distanceMeasurementsPlugin;
86
+ }
87
+
88
+ /** Gets if this DistanceMeasurementsTouchControl is currently active, where it is responding to input.
89
+ *
90
+ * @returns {Boolean}
91
+ */
92
+ get active() {
93
+ return this._active;
94
+ }
95
+
96
+ /**
97
+ * Sets whether snap-to-vertex is enabled for this DistanceMeasurementsTouchControl.
98
+ * This is `true` by default.
99
+ * @param snapToVertex
100
+ */
101
+ set snapToVertex(snapToVertex) {
102
+ this._snapToVertex = snapToVertex;
103
+ }
104
+
105
+ /**
106
+ * Gets whether snap-to-vertex is enabled for this DistanceMeasurementsTouchControl.
107
+ * This is `true` by default.
108
+ * @returns {*}
109
+ */
110
+ get snapToVertex() {
111
+ return this._snapToVertex;
112
+ }
113
+
114
+ /**
115
+ * Sets whether snap-to-edge is enabled for this DistanceMeasurementsTouchControl.
116
+ * This is `true` by default.
117
+ * @param snapToEdge
118
+ */
119
+ set snapToEdge(snapToEdge) {
120
+ this._snapToEdge = snapToEdge;
121
+ }
122
+
123
+ /**
124
+ * Gets whether snap-to-edge is enabled for this DistanceMeasurementsTouchControl.
125
+ * This is `true` by default.
126
+ * @returns {*}
127
+ */
128
+ get snapToEdge() {
129
+ return this._snapToEdge;
130
+ }
131
+
132
+ /**
133
+ * Activates this DistanceMeasurementsTouchControl, ready to respond to input.
134
+ */
135
+ activate() {
136
+
137
+ if (this._active) {
138
+ return;
139
+ }
140
+
141
+ const plugin = this.plugin;
142
+ const scene = this.scene;
143
+ const canvas = scene.canvas.canvas;
144
+ const pointerLens = plugin.pointerLens;
145
+ const pointerWorldPos = math.vec3();
146
+
147
+ const touchTolerance = 20;
148
+
149
+ let longTouchTimeout = null;
150
+
151
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
152
+
153
+ const touchStartCanvasPos = math.vec2();
154
+ const touchMoveCanvasPos = math.vec2();
155
+ const touchEndCanvasPos = math.vec2();
156
+
157
+ let touchId = null;
158
+
159
+ const disableCameraMouseControl = () => {
160
+ this.plugin.viewer.cameraControl.active = false;
161
+ }
162
+
163
+ const enableCameraMouseControl = () => {
164
+ this.plugin.viewer.cameraControl.active = true;
165
+ }
166
+
167
+ const cancel = () => {
168
+ if (longTouchTimeout) {
169
+ clearTimeout(longTouchTimeout);
170
+ longTouchTimeout = null;
171
+ }
172
+ if (this._currentDistanceMeasurement) {
173
+ this._currentDistanceMeasurement.destroy();
174
+ this._currentDistanceMeasurement = null;
175
+ }
176
+ enableCameraMouseControl();
177
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
178
+ }
179
+
180
+ canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
181
+
182
+ const currentNumTouches = event.touches.length;
183
+
184
+ if (currentNumTouches !== 1) {
185
+ if (longTouchTimeout) {
186
+ clearTimeout(longTouchTimeout);
187
+ longTouchTimeout = null;
188
+ }
189
+ return;
190
+ }
191
+
192
+ const touch = event.touches[0];
193
+ const touchX = touch.clientX;
194
+ const touchY = touch.clientY;
195
+
196
+ touchStartCanvasPos.set([touchX, touchY]);
197
+ touchMoveCanvasPos.set([touchX, touchY]);
198
+
199
+ switch (this._touchState) {
200
+
201
+ case WAITING_FOR_ORIGIN_TOUCH_START:
202
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
203
+ cancel();
204
+ return;
205
+ }
206
+ const snapPickResult = scene.pick({
207
+ canvasPos: touchMoveCanvasPos,
208
+ snapToVertex: this._snapToVertex,
209
+ snapToEdge: this._snapToEdge
210
+ });
211
+ if (snapPickResult && snapPickResult.snapped) {
212
+ pointerWorldPos.set(snapPickResult.worldPos);
213
+ this.pointerCircle.start(snapPickResult.snappedCanvasPos);
214
+ } else {
215
+ const pickResult = scene.pick({
216
+ canvasPos: touchMoveCanvasPos,
217
+ pickSurface: true
218
+ })
219
+ if (pickResult && pickResult.worldPos) {
220
+ pointerWorldPos.set(pickResult.worldPos);
221
+ this.pointerCircle.start(pickResult.canvasPos);
222
+ } else {
223
+ return;
224
+ }
225
+ }
226
+ longTouchTimeout = setTimeout(() => {
227
+ if (currentNumTouches !== 1 ||
228
+ touchMoveCanvasPos[0] > touchStartCanvasPos[0] + touchTolerance ||
229
+ touchMoveCanvasPos[0] < touchStartCanvasPos[0] - touchTolerance ||
230
+ touchMoveCanvasPos[1] > touchStartCanvasPos[1] + touchTolerance ||
231
+ touchMoveCanvasPos[1] < touchStartCanvasPos[1] - touchTolerance) {
232
+ return; // Has moved
233
+ }
234
+ // Long touch
235
+ if (this.pointerLens) {
236
+ this.pointerLens.visible = true;
237
+ this.pointerLens.canvasPos = touchStartCanvasPos;
238
+ this.pointerLens.cursorPos = touchStartCanvasPos;
239
+ }
240
+ if (this.pointerLens) {
241
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
242
+ this.pointerLens.snapped = false;
243
+ }
244
+ if (this.pointerLens) {
245
+ this.pointerLens.cursorPos = snapPickResult.canvasPos;
246
+ this.pointerLens.snapped = true;
247
+ }
248
+ // pointerWorldPos.set(snapPickResult.snappedWorldPos);
249
+ if (!this._currentDistanceMeasurement) {
250
+ this._currentDistanceMeasurement = plugin.createMeasurement({
251
+ id: math.createUUID(),
252
+ origin: {
253
+ worldPos: pointerWorldPos
254
+ },
255
+ target: {
256
+ worldPos: pointerWorldPos
257
+ }
258
+ });
259
+ this._currentDistanceMeasurement.labelsVisible = false;
260
+ this._currentDistanceMeasurement.xAxisVisible = false;
261
+ this._currentDistanceMeasurement.yAxisVisible = false;
262
+ this._currentDistanceMeasurement.zAxisVisible = false;
263
+ this._currentDistanceMeasurement.wireVisible = false;
264
+ this._currentDistanceMeasurement.originVisible = true;
265
+ this._currentDistanceMeasurement.targetVisible = false;
266
+ this._currentDistanceMeasurement.clickable = false;
267
+ } else {
268
+ this._currentDistanceMeasurement.origin.worldPos = pointerWorldPos;
269
+ }
270
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
271
+ // if (this.pointerLens) {
272
+ // this.pointerLens.cursorPos = pickResult.canvasPos;
273
+ // this.pointerLens.snapped = false;
274
+ // }
275
+ this._touchState = WAITING_FOR_ORIGIN_LONG_TOUCH_END;
276
+ // console.log("touchstart: this._touchState= WAITING_FOR_ORIGIN_TOUCH_START -> WAITING_FOR_ORIGIN_LONG_TOUCH_END")
277
+ disableCameraMouseControl();
278
+ }, this._longTouchTimeoutMs);
279
+ this._touchState = WAITING_FOR_ORIGIN_QUICK_TOUCH_END;
280
+ // console.log("touchstart: this._touchState= WAITING_FOR_ORIGIN_TOUCH_START -> WAITING_FOR_ORIGIN_QUICK_TOUCH_END")
281
+
282
+ touchId = touch.identifier;
283
+
284
+ break;
285
+
286
+
287
+ case WAITING_FOR_TARGET_TOUCH_START:
288
+
289
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
290
+ clearTimeout(longTouchTimeout);
291
+ longTouchTimeout = null;
292
+ return;
293
+ }
294
+ if (currentNumTouches === 1) { // One finger down
295
+ longTouchTimeout = setTimeout(() => {
296
+ longTouchTimeout = null;
297
+ if (currentNumTouches !== 1 ||
298
+ touchMoveCanvasPos[0] > touchStartCanvasPos[0] + touchTolerance ||
299
+ touchMoveCanvasPos[0] < touchStartCanvasPos[0] - touchTolerance ||
300
+ touchMoveCanvasPos[1] > touchStartCanvasPos[1] + touchTolerance ||
301
+ touchMoveCanvasPos[1] < touchStartCanvasPos[1] - touchTolerance) {
302
+ // Has moved
303
+ return;
304
+ }
305
+
306
+ // Long touch
307
+ if (this.pointerLens) {
308
+ this.pointerLens.visible = true;
309
+ this.pointerLens.canvasPos = touchStartCanvasPos;
310
+ this.pointerLens.snapped = false;
311
+ }
312
+
313
+ const snapPickResult = scene.pick({
314
+ canvasPos: touchMoveCanvasPos,
315
+ snapToVertex: this._snapToVertex,
316
+ snapToEdge: this._snapToEdge
317
+ });
318
+ if (snapPickResult && snapPickResult.snapped) {
319
+ if (this.pointerLens) {
320
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
321
+ this.pointerLens.snapped = true;
322
+ }
323
+ this.pointerCircle.start(snapPickResult.snappedCanvasPos);
324
+ pointerWorldPos.set(snapPickResult.worldPos);
325
+ this._currentDistanceMeasurement.target.worldPos = snapPickResult.worldPos;
326
+ this._currentDistanceMeasurement.targetVisible = true;
327
+ this._currentDistanceMeasurement.wireVisible = true;
328
+ this._currentDistanceMeasurement.labelsVisible = true;
329
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
330
+ } else {
331
+ const pickResult = scene.pick({
332
+ canvasPos: touchMoveCanvasPos,
333
+ pickSurface: true
334
+ })
335
+ if (pickResult && pickResult.worldPos) {
336
+ if (this.pointerLens) {
337
+ this.pointerLens.cursorPos = pickResult.canvasPos;
338
+ this.pointerLens.snapped = false;
339
+ }
340
+ this.pointerCircle.start(pickResult.canvasPos);
341
+ pointerWorldPos.set(pickResult.worldPos);
342
+ this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
343
+ this._currentDistanceMeasurement.targetVisible = true;
344
+ this._currentDistanceMeasurement.wireVisible = true;
345
+ this._currentDistanceMeasurement.labelsVisible = true;
346
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
347
+ } else {
348
+ if (this.pointerLens) {
349
+ this.pointerLens.cursorPos = null;
350
+ this.pointerLens.snapped = false;
351
+
352
+ }
353
+ }
354
+ }
355
+ this._touchState = WAITING_FOR_TARGET_LONG_TOUCH_END;
356
+ // console.log("touchstart: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_LONG_TOUCH_END")
357
+
358
+ disableCameraMouseControl();
359
+
360
+ }, this._longTouchTimeoutMs);
361
+
362
+ this._touchState = WAITING_FOR_TARGET_QUICK_TOUCH_END;
363
+ // console.log("touchstart: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_QUICK_TOUCH_END")
364
+ }
365
+
366
+ touchId = touch.identifier;
367
+
368
+ break;
369
+
370
+ default:
371
+ if (longTouchTimeout !== null) {
372
+ clearTimeout(longTouchTimeout);
373
+ longTouchTimeout = null;
374
+ }
375
+ this._touchState = TOUCH_CANCELING;
376
+ // console.log("touchstart: this._touchState= default -> TOUCH_CANCELING")
377
+ return;
378
+ }
379
+
380
+ }, {passive: true});
381
+
382
+
383
+ canvas.addEventListener("touchmove", (event) => {
384
+
385
+ this.pointerCircle.stop();
386
+
387
+ const currentNumTouches = event.touches.length;
388
+
389
+ if (currentNumTouches !== 1 || event.changedTouches.length !== 1) {
390
+ if (longTouchTimeout) {
391
+ clearTimeout(longTouchTimeout);
392
+ longTouchTimeout = null;
393
+ }
394
+ return;
395
+ }
396
+
397
+ const touch = event.touches[0];
398
+ const touchX = touch.clientX;
399
+ const touchY = touch.clientY;
400
+
401
+ if (touch.identifier !== touchId) {
402
+ return;
403
+ }
404
+
405
+ touchMoveCanvasPos.set([touchX, touchY]);
406
+
407
+ let snapPickResult;
408
+ let pickResult;
409
+
410
+ switch (this._touchState) {
411
+
412
+ case WAITING_FOR_ORIGIN_LONG_TOUCH_END:
413
+ if (this.pointerLens) {
414
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
415
+ }
416
+ snapPickResult = scene.pick({
417
+ canvasPos: touchMoveCanvasPos,
418
+
419
+
420
+ snapToVertex: this._snapToVertex,
421
+ snapToEdge: this._snapToEdge
422
+ });
423
+ if (snapPickResult && (snapPickResult.snapped)) {
424
+ if (this.pointerLens) {
425
+ this.pointerLens.snappedCanvasPos = snapPickResult.snappedCanvasPos;
426
+ this.pointerLens.snapped = true;
427
+ }
428
+ pointerWorldPos.set(snapPickResult.worldPos);
429
+ if (!this._currentDistanceMeasurement) {
430
+ this._currentDistanceMeasurement = plugin.createMeasurement({
431
+ id: math.createUUID(),
432
+ origin: {
433
+ worldPos: snapPickResult.worldPos
434
+ },
435
+ target: {
436
+ worldPos: snapPickResult.worldPos
437
+ }
438
+ });
439
+ this._currentDistanceMeasurement.labelsVisible = false;
440
+ this._currentDistanceMeasurement.xAxisVisible = false;
441
+ this._currentDistanceMeasurement.yAxisVisible = false;
442
+ this._currentDistanceMeasurement.zAxisVisible = false;
443
+ this._currentDistanceMeasurement.wireVisible = false;
444
+ this._currentDistanceMeasurement.originVisible = true;
445
+ this._currentDistanceMeasurement.targetVisible = false;
446
+ this._currentDistanceMeasurement.clickable = false;
447
+ } else {
448
+ this._currentDistanceMeasurement.origin.worldPos = snapPickResult.worldPos;
449
+ }
450
+
451
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
452
+ } else {
453
+ pickResult = scene.pick({
454
+ canvasPos: touchMoveCanvasPos,
455
+ pickSurface: true
456
+ })
457
+ if (pickResult && pickResult.worldPos) {
458
+ if (this.pointerLens) {
459
+ this.pointerLens.cursorPos = pickResult.canvasPos;
460
+ this.pointerLens.snapped = false;
461
+ }
462
+ pointerWorldPos.set(pickResult.worldPos);
463
+ if (!this._currentDistanceMeasurement) {
464
+ this._currentDistanceMeasurement = plugin.createMeasurement({
465
+ id: math.createUUID(),
466
+ origin: {
467
+ worldPos: pickResult.worldPos
468
+ },
469
+ target: {
470
+ worldPos: pickResult.worldPos
471
+ }
472
+ });
473
+ this._currentDistanceMeasurement.labelsVisible = false;
474
+ this._currentDistanceMeasurement.xAxisVisible = false;
475
+ this._currentDistanceMeasurement.yAxisVisible = false;
476
+ this._currentDistanceMeasurement.zAxisVisible = false;
477
+ this._currentDistanceMeasurement.wireVisible = false;
478
+ this._currentDistanceMeasurement.originVisible = true;
479
+ this._currentDistanceMeasurement.targetVisible = false;
480
+ this._currentDistanceMeasurement.clickable = false;
481
+ } else {
482
+ this._currentDistanceMeasurement.origin.worldPos = pickResult.worldPos;
483
+ }
484
+
485
+ this.distanceMeasurementsPlugin.fire("measurementStart", this._currentDistanceMeasurement);
486
+ } else {
487
+ if (this.pointerLens) {
488
+ this.pointerLens.cursorPos = null;
489
+ this.pointerLens.snapped = false;
490
+ }
491
+ }
492
+ }
493
+ this._touchState = WAITING_FOR_ORIGIN_LONG_TOUCH_END;
494
+ // console.log("touchmove: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END -> WAITING_FOR_ORIGIN_LONG_TOUCH_END")
495
+ break;
496
+
497
+ // case WAITING_FOR_TARGET_TOUCH_START:
498
+ // this._touchState = WAITING_FOR_TARGET_TOUCH_START;
499
+ // console.log("touchmove: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_TARGET_TOUCH_START")
500
+ // break;
501
+
502
+ case WAITING_FOR_TARGET_LONG_TOUCH_END:
503
+ if (currentNumTouches !== 1 && longTouchTimeout !== null) { // Two or more fingers down
504
+ clearTimeout(longTouchTimeout);
505
+ longTouchTimeout = null;
506
+ if (this.pointerLens) {
507
+ this.pointerLens.visible = false;
508
+ }
509
+ this._touchState = TOUCH_CANCELING;
510
+ // console.log("touchmove: this._touchState= QUICK_TOUCH_FINDING_TARGET -> TOUCH_CANCELING")
511
+ return;
512
+ }
513
+ if (this.pointerLens) {
514
+ this.pointerLens.canvasPos = touchMoveCanvasPos;
515
+ }
516
+ snapPickResult = scene.pick({
517
+ canvasPos: touchMoveCanvasPos,
518
+ snapToVertex: this._snapToVertex,
519
+ snapToEdge: this._snapToEdge
520
+ });
521
+ if (snapPickResult && snapPickResult.worldPos) {
522
+ if (this.pointerLens) {
523
+ this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
524
+ this.pointerLens.snapped = true;
525
+ }
526
+ this._currentDistanceMeasurement.target.worldPos = snapPickResult.worldPos;
527
+ this._currentDistanceMeasurement.targetVisible = true;
528
+ this._currentDistanceMeasurement.wireVisible = true;
529
+ this._currentDistanceMeasurement.labelsVisible = true;
530
+ } else {
531
+ pickResult = scene.pick({
532
+ canvasPos: touchMoveCanvasPos,
533
+ pickSurface: true
534
+ })
535
+ if (pickResult && pickResult.worldPos) {
536
+ if (this.pointerLens) {
537
+ this.pointerLens.cursorPos = pickResult.canvasPos;
538
+ this.pointerLens.snapped = false;
539
+ }
540
+ this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
541
+ this._currentDistanceMeasurement.targetVisible = true;
542
+ this._currentDistanceMeasurement.wireVisible = true;
543
+ this._currentDistanceMeasurement.labelsVisible = true;
544
+
545
+ }
546
+ }
547
+ this._touchState = WAITING_FOR_TARGET_LONG_TOUCH_END;
548
+ break;
549
+
550
+ default:
551
+ break;
552
+ }
553
+ }, {passive: true});
554
+
555
+ canvas.addEventListener("touchend", this._onCanvasTouchEnd = (event) => {
556
+
557
+ this.pointerCircle.stop();
558
+
559
+ const numChangedTouches = event.changedTouches.length;
560
+
561
+ if (numChangedTouches !== 1) {
562
+ return;
563
+ }
564
+
565
+ const touch = event.changedTouches[0];
566
+ const touchX = touch.clientX;
567
+ const touchY = touch.clientY;
568
+
569
+ if (touch.identifier !== touchId) {
570
+ return;
571
+ }
572
+
573
+ if (longTouchTimeout) {
574
+ clearTimeout(longTouchTimeout);
575
+ longTouchTimeout = null;
576
+ }
577
+
578
+ touchEndCanvasPos.set([touchX, touchY]);
579
+
580
+ switch (this._touchState) {
581
+
582
+ case WAITING_FOR_ORIGIN_QUICK_TOUCH_END: {
583
+ if (numChangedTouches !== 1 ||
584
+ touchX > touchStartCanvasPos[0] + touchTolerance ||
585
+ touchX < touchStartCanvasPos[0] - touchTolerance ||
586
+ touchY > touchStartCanvasPos[1] + touchTolerance ||
587
+ touchY < touchStartCanvasPos[1] - touchTolerance) {
588
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
589
+ return;
590
+ }
591
+ const pickResult = scene.pick({
592
+ canvasPos: touchMoveCanvasPos,
593
+ pickSurface: true
594
+ });
595
+ if (pickResult && pickResult.worldPos) {
596
+ this._currentDistanceMeasurement = plugin.createMeasurement({
597
+ id: math.createUUID(),
598
+ origin: {
599
+ worldPos: pickResult.worldPos
600
+ },
601
+ target: {
602
+ worldPos: pickResult.worldPos
603
+ }
604
+ });
605
+ this._currentDistanceMeasurement.labelsVisible = false;
606
+ this._currentDistanceMeasurement.xAxisVisible = false;
607
+ this._currentDistanceMeasurement.yAxisVisible = false;
608
+ this._currentDistanceMeasurement.zAxisVisible = false;
609
+ this._currentDistanceMeasurement.wireVisible = false;
610
+ this._currentDistanceMeasurement.originVisible = true;
611
+ this._currentDistanceMeasurement.targetVisible = false;
612
+ this._currentDistanceMeasurement.clickable = false;
613
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START;
614
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_QUICK_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
615
+ } else {
616
+ if (this._currentDistanceMeasurement) {
617
+ this._currentDistanceMeasurement.destroy();
618
+ }
619
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
620
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_QUICK_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
621
+ }
622
+ }
623
+ enableCameraMouseControl();
624
+ break;
625
+
626
+ case WAITING_FOR_ORIGIN_LONG_TOUCH_END:
627
+ if (this.pointerLens) {
628
+ this.pointerLens.visible = false;
629
+ }
630
+ if (!this._currentDistanceMeasurement) {
631
+ if (this.pointerLens) {
632
+ this.pointerLens.snapped = false;
633
+ this.pointerLens.visible = false;
634
+ }
635
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
636
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END (no measurement) -> WAITING_FOR_ORIGIN_TOUCH_START")
637
+ } else {
638
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START;
639
+ // console.log("touchend: this._touchState= WAITING_FOR_ORIGIN_LONG_TOUCH_END (picked, begin measurement) -> WAITING_FOR_TARGET_TOUCH_START")
640
+ }
641
+ enableCameraMouseControl();
642
+ break;
643
+
644
+ case WAITING_FOR_TARGET_QUICK_TOUCH_END: {
645
+ if (numChangedTouches !== 1 ||
646
+ touchX > touchStartCanvasPos[0] + touchTolerance ||
647
+ touchX < touchStartCanvasPos[0] - touchTolerance ||
648
+ touchY > touchStartCanvasPos[1] + touchTolerance ||
649
+ touchY < touchStartCanvasPos[1] - touchTolerance) {
650
+ this._touchState = WAITING_FOR_TARGET_TOUCH_START;
651
+ return;
652
+ }
653
+ const pickResult = scene.pick({
654
+ canvasPos: touchMoveCanvasPos,
655
+ pickSurface: true
656
+ });
657
+ if (pickResult && pickResult.worldPos) {
658
+ this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
659
+ this._currentDistanceMeasurement.targetVisible = true;
660
+ this._currentDistanceMeasurement.wireVisible = true;
661
+ this._currentDistanceMeasurement.labelsVisible = true;
662
+ this.distanceMeasurementsPlugin.fire("measurementEnd", this._currentDistanceMeasurement);
663
+ this._currentDistanceMeasurement = null;
664
+ } else {
665
+ if (this._currentDistanceMeasurement) {
666
+ this._currentDistanceMeasurement.destroy();
667
+ this._currentDistanceMeasurement = null;
668
+ }
669
+ }
670
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
671
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_TOUCH_START -> WAITING_FOR_ORIGIN_TOUCH_START")
672
+ }
673
+ enableCameraMouseControl();
674
+ break;
675
+
676
+ case WAITING_FOR_TARGET_LONG_TOUCH_END:
677
+ if (this.pointerLens) {
678
+ this.pointerLens.visible = false;
679
+ }
680
+ if (!this._currentDistanceMeasurement || !this._currentDistanceMeasurement.targetVisible) {
681
+ if (this._currentDistanceMeasurement) {
682
+ this._currentDistanceMeasurement.destroy();
683
+ this._currentDistanceMeasurement = null;
684
+ }
685
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
686
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_LONG_TOUCH_END (no target found) -> WAITING_FOR_ORIGIN_TOUCH_START")
687
+ } else {
688
+ this._currentDistanceMeasurement.clickable = true;
689
+ this.distanceMeasurementsPlugin.fire("measurementEnd", this._currentDistanceMeasurement);
690
+ this._currentDistanceMeasurement = null;
691
+ this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
692
+ // console.log("touchend: this._touchState= WAITING_FOR_TARGET_LONG_TOUCH_END -> WAITING_FOR_ORIGIN_TOUCH_START")
693
+ }
694
+ enableCameraMouseControl();
695
+ break;
696
+ }
697
+
698
+ }, {passive: true});
699
+
700
+ this._active = true;
701
+ }
702
+
703
+ /**
704
+ * Deactivates this DistanceMeasurementsTouchControl, making it unresponsive to input.
705
+ *
706
+ * Destroys any {@link DistanceMeasurement} under construction.
707
+ */
708
+ deactivate() {
709
+ if (!this._active) {
710
+ return;
711
+ }
712
+ if (this.plugin.pointerLens) {
713
+ this.plugin.pointerLens.visible = false;
714
+ }
715
+ this.reset();
716
+ const canvas = this.plugin.viewer.scene.canvas.canvas;
717
+ canvas.removeEventListener("touchstart", this._onCanvasTouchStart);
718
+ canvas.removeEventListener("touchend", this._onCanvasTouchEnd);
719
+ if (this._currentDistanceMeasurement) {
720
+ this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
721
+ this._currentDistanceMeasurement.destroy();
722
+ this._currentDistanceMeasurement = null;
723
+ }
724
+ this._active = false;
725
+ this.plugin.viewer.cameraControl.active = true;
726
+ }
727
+
728
+ /**
729
+ * Resets this DistanceMeasurementsTouchControl.
730
+ *
731
+ * Destroys any {@link DistanceMeasurement} under construction.
732
+ *
733
+ * Does nothing if the DistanceMeasurementsTouchControl is not active.
734
+ */
735
+ reset() {
736
+ if (!this._active) {
737
+ return;
738
+ }
739
+ if (this._currentDistanceMeasurement) {
740
+ this.distanceMeasurementsPlugin.fire("measurementCancel", this._currentDistanceMeasurement);
741
+ this._currentDistanceMeasurement.destroy();
742
+ this._currentDistanceMeasurement = null;
743
+ }
744
+ }
745
+
746
+ /**
747
+ * Destroys this DistanceMeasurementsTouchControl.
748
+ */
749
+ destroy() {
750
+ this.deactivate();
751
+ super.destroy();
752
+ }
753
+ }