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