@xeokit/xeokit-sdk 2.6.64 → 2.6.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/xeokit-sdk.cjs.js +123 -205
- package/dist/xeokit-sdk.es.js +123 -205
- package/dist/xeokit-sdk.es5.js +52 -63
- package/dist/xeokit-sdk.min.cjs.js +5 -5
- package/dist/xeokit-sdk.min.es.js +5 -5
- package/dist/xeokit-sdk.min.es5.js +4 -4
- package/package.json +1 -1
- package/src/extras/PointerLens/PointerLens.js +27 -46
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +29 -20
- package/src/plugins/AnnotationsPlugin/Annotation.js +3 -0
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +27 -33
- package/src/plugins/SectionPlanesPlugin/Control.js +26 -115
- package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +10 -4
- package/src/plugins/lib/html/MenuEvent.js +3 -1
- package/src/viewer/scene/model/dtx/triangles/DTXTrianglesLayer.js +1 -2
- package/src/viewer/scene/model/vbo/instancing/lines/VBOInstancingLinesLayer.js +1 -1
- package/types/plugins/AngleMeasurementsPlugin/index.d.ts +2 -1
- package/types/plugins/CityJSONLoaderPlugin/CityJSONLoaderPlugin.d.ts +4 -0
- package/types/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.d.ts +121 -0
- package/types/plugins/DotBIMLoaderPlugin/index.d.ts +1 -0
- package/types/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.d.ts +4 -0
- package/types/plugins/LASLoaderPlugin/LASLoaderPlugin.d.ts +4 -0
- package/types/plugins/STLLoaderPlugin/STLLoaderPlugin.d.ts +4 -0
- package/types/plugins/TreeViewPlugin/TreeViewPlugin.d.ts +4 -0
- package/types/plugins/WebIFCLoaderPlugin/WebIFCLoaderPlugin.d.ts +4 -0
- package/types/plugins/XKTLoaderPlugin/XKTLoaderPlugin.d.ts +19 -1
- package/types/plugins/index.d.ts +1 -0
package/package.json
CHANGED
|
@@ -53,13 +53,10 @@ export class PointerLens {
|
|
|
53
53
|
this.scene = this.viewer.scene;
|
|
54
54
|
|
|
55
55
|
this._lensCursorDiv = document.createElement('div');
|
|
56
|
-
this.
|
|
57
|
-
this._lensCursorDiv.style.
|
|
58
|
-
this._lensCursorDiv.style.
|
|
59
|
-
this._lensCursorDiv.style.
|
|
60
|
-
this._lensCursorDiv.style.width = "10px";
|
|
61
|
-
this._lensCursorDiv.style.height = "10px";
|
|
62
|
-
this._lensCursorDiv.style.margin = "-200px -200px";
|
|
56
|
+
this._lensParams = { canvasSize: 300, cursorBorder: 2, cursorSize: 10 };
|
|
57
|
+
this._lensCursorDiv.style.borderRadius = "50%";
|
|
58
|
+
this._lensCursorDiv.style.width = this._lensParams.cursorSize + "px";
|
|
59
|
+
this._lensCursorDiv.style.height = this._lensParams.cursorSize + "px";
|
|
63
60
|
this._lensCursorDiv.style.zIndex = "100000";
|
|
64
61
|
this._lensCursorDiv.style.position = "absolute";
|
|
65
62
|
this._lensCursorDiv.style.pointerEvents = "none";
|
|
@@ -72,8 +69,8 @@ export class PointerLens {
|
|
|
72
69
|
this._lensContainer.style.background = "white";
|
|
73
70
|
// this._lensContainer.style.opacity = "0";
|
|
74
71
|
this._lensContainer.style.borderRadius = "50%";
|
|
75
|
-
this._lensContainer.style.width
|
|
76
|
-
this._lensContainer.style.height = "
|
|
72
|
+
this._lensContainer.style.width = this._lensParams.canvasSize + "px";
|
|
73
|
+
this._lensContainer.style.height = this._lensParams.canvasSize + "px";
|
|
77
74
|
|
|
78
75
|
this._lensContainer.style.zIndex = "15000";
|
|
79
76
|
this._lensContainer.style.position = "absolute";
|
|
@@ -85,13 +82,14 @@ export class PointerLens {
|
|
|
85
82
|
// this._lensCanvas.style.background = "darkblue";
|
|
86
83
|
this._lensCanvas.style.borderRadius = "50%";
|
|
87
84
|
|
|
88
|
-
this._lensCanvas.style.width
|
|
89
|
-
this._lensCanvas.style.height = "
|
|
85
|
+
this._lensCanvas.style.width = this._lensParams.canvasSize + "px";
|
|
86
|
+
this._lensCanvas.style.height = this._lensParams.canvasSize + "px";
|
|
90
87
|
this._lensCanvas.style.zIndex = "15000";
|
|
91
88
|
this._lensCanvas.style.pointerEvents = "none";
|
|
92
89
|
|
|
93
90
|
document.body.appendChild(this._lensContainer);
|
|
94
91
|
this._lensContainer.appendChild(this._lensCanvas);
|
|
92
|
+
this._lensContainer.appendChild(this._lensCursorDiv);
|
|
95
93
|
|
|
96
94
|
this._lensCanvasContext = this._lensCanvas.getContext('2d');
|
|
97
95
|
this._canvasElement = this.viewer.scene.canvas.canvas;
|
|
@@ -109,7 +107,7 @@ export class PointerLens {
|
|
|
109
107
|
|
|
110
108
|
this._active = (cfg.active !== false);
|
|
111
109
|
this._visible = false;
|
|
112
|
-
this.
|
|
110
|
+
this.snapped = false;
|
|
113
111
|
|
|
114
112
|
this._onViewerRendering = this.viewer.scene.on("rendering", () => {
|
|
115
113
|
if (this._active && this._visible) {
|
|
@@ -156,21 +154,13 @@ export class PointerLens {
|
|
|
156
154
|
this._lensCanvas.height // destination height
|
|
157
155
|
);
|
|
158
156
|
|
|
159
|
-
const
|
|
160
|
-
(lensRect.left + lensRect.right) / 2 - canvasRect.left,
|
|
161
|
-
(lensRect.top + lensRect.bottom) / 2 - canvasRect.top
|
|
162
|
-
];
|
|
157
|
+
const middle = this._lensParams.canvasSize / 2 - this._lensParams.cursorSize / 2 - this._lensParams.cursorBorder;
|
|
163
158
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const deltaY = this._snappedCanvasPos[1] - this._canvasPos[1];
|
|
159
|
+
const deltaX = this._snappedCanvasPos ? (this._snappedCanvasPos[0] - this._canvasPos[0]) : 0;
|
|
160
|
+
const deltaY = this._snappedCanvasPos ? (this._snappedCanvasPos[1] - this._canvasPos[1]) : 0;
|
|
167
161
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
} else {
|
|
171
|
-
this._lensCursorDiv.style.marginLeft = `${centerLensCanvas[0] - 10}px`;
|
|
172
|
-
this._lensCursorDiv.style.marginTop = `${centerLensCanvas[1] - 10}px`;
|
|
173
|
-
}
|
|
162
|
+
this._lensCursorDiv.style.left = `${middle + deltaX * this._zoomLevel}px`;
|
|
163
|
+
this._lensCursorDiv.style.top = `${middle + deltaY * this._zoomLevel}px`;
|
|
174
164
|
}
|
|
175
165
|
|
|
176
166
|
|
|
@@ -238,14 +228,10 @@ export class PointerLens {
|
|
|
238
228
|
* @private
|
|
239
229
|
*/
|
|
240
230
|
set snapped(snapped) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
} else {
|
|
246
|
-
this._lensCursorDiv.style.background = "pink";
|
|
247
|
-
this._lensCursorDiv.style.border = "2px solid red";
|
|
248
|
-
}
|
|
231
|
+
this._snapped = snapped;
|
|
232
|
+
const [ bg, border ] = snapped ? [ "greenyellow", "green" ] : [ "pink", "red" ];
|
|
233
|
+
this._lensCursorDiv.style.background = bg;
|
|
234
|
+
this._lensCursorDiv.style.border = this._lensParams.cursorBorder + "px solid " + border;
|
|
249
235
|
}
|
|
250
236
|
|
|
251
237
|
/**
|
|
@@ -257,19 +243,19 @@ export class PointerLens {
|
|
|
257
243
|
get snapped() {
|
|
258
244
|
return this._snapped;
|
|
259
245
|
}
|
|
260
|
-
|
|
246
|
+
|
|
247
|
+
_updateActiveVisible() {
|
|
248
|
+
this._lensContainer.style.visibility = (this._active && this._visible) ? "visible" : "hidden";
|
|
249
|
+
this.update();
|
|
250
|
+
}
|
|
251
|
+
|
|
261
252
|
/**
|
|
262
253
|
* Sets if this PointerLens is active.
|
|
263
254
|
* @param active
|
|
264
255
|
*/
|
|
265
256
|
set active(active) {
|
|
266
257
|
this._active = active;
|
|
267
|
-
this.
|
|
268
|
-
if (!active || !this._visible ) {
|
|
269
|
-
this._lensCursorDiv.style.marginLeft = `-100px`;
|
|
270
|
-
this._lensCursorDiv.style.marginTop = `-100px`;
|
|
271
|
-
}
|
|
272
|
-
this.update();
|
|
258
|
+
this._updateActiveVisible();
|
|
273
259
|
}
|
|
274
260
|
|
|
275
261
|
/**
|
|
@@ -288,12 +274,7 @@ export class PointerLens {
|
|
|
288
274
|
*/
|
|
289
275
|
set visible(visible) {
|
|
290
276
|
this._visible = visible;
|
|
291
|
-
this.
|
|
292
|
-
if (!visible || !this._active) {
|
|
293
|
-
this._lensCursorDiv.style.marginLeft = `-100px`;
|
|
294
|
-
this._lensCursorDiv.style.marginTop = `-100px`;
|
|
295
|
-
}
|
|
296
|
-
this.update();
|
|
277
|
+
this._updateActiveVisible();
|
|
297
278
|
}
|
|
298
279
|
|
|
299
280
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {math} from "../../viewer/scene/math/math.js";
|
|
2
2
|
import {PointerCircle} from "../../extras/PointerCircle/PointerCircle.js";
|
|
3
3
|
import {AngleMeasurementsControl} from "./AngleMeasurementsControl.js";
|
|
4
|
-
|
|
4
|
+
import {transformToNode} from "../lib/ui/index.js";
|
|
5
5
|
|
|
6
6
|
const WAITING_FOR_ORIGIN_TOUCH_START = 0;
|
|
7
7
|
const WAITING_FOR_ORIGIN_QUICK_TOUCH_END = 1;
|
|
@@ -17,6 +17,8 @@ const WAITING_FOR_TARGET_LONG_TOUCH_END = 8;
|
|
|
17
17
|
|
|
18
18
|
const TOUCH_CANCELING = 7;
|
|
19
19
|
|
|
20
|
+
const tmpVec2 = math.vec2();
|
|
21
|
+
|
|
20
22
|
/**
|
|
21
23
|
* Creates {@link AngleMeasurement}s from touch input.
|
|
22
24
|
*
|
|
@@ -155,6 +157,19 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
155
157
|
this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
|
|
156
158
|
}
|
|
157
159
|
|
|
160
|
+
const copyCanvasPos = (event, dst) => {
|
|
161
|
+
dst[0] = event.clientX;
|
|
162
|
+
dst[1] = event.clientY;
|
|
163
|
+
transformToNode(canvas.ownerDocument.documentElement, canvas, dst);
|
|
164
|
+
return dst;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const toBodyPos = (pos, dst) => {
|
|
168
|
+
dst.set(pos);
|
|
169
|
+
transformToNode(canvas, canvas.ownerDocument.documentElement, dst);
|
|
170
|
+
return dst;
|
|
171
|
+
};
|
|
172
|
+
|
|
158
173
|
canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
|
|
159
174
|
|
|
160
175
|
const currentNumTouches = event.touches.length;
|
|
@@ -168,11 +183,8 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
168
183
|
}
|
|
169
184
|
|
|
170
185
|
const touch = event.touches[0];
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
touchStartCanvasPos.set([touchX, touchY]);
|
|
175
|
-
touchMoveCanvasPos.set([touchX, touchY]);
|
|
186
|
+
copyCanvasPos(touch, touchStartCanvasPos);
|
|
187
|
+
touchMoveCanvasPos.set(touchStartCanvasPos);
|
|
176
188
|
|
|
177
189
|
switch (this._touchState) {
|
|
178
190
|
|
|
@@ -188,7 +200,7 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
188
200
|
});
|
|
189
201
|
if (snapPickResult && snapPickResult.snapped) {
|
|
190
202
|
pointerWorldPos.set(snapPickResult.worldPos);
|
|
191
|
-
this.pointerCircle.start(snapPickResult.snappedCanvasPos);
|
|
203
|
+
this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
|
|
192
204
|
} else {
|
|
193
205
|
const pickResult = scene.pick({
|
|
194
206
|
canvasPos: touchMoveCanvasPos,
|
|
@@ -196,7 +208,7 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
196
208
|
})
|
|
197
209
|
if (pickResult && pickResult.worldPos) {
|
|
198
210
|
pointerWorldPos.set(pickResult.worldPos);
|
|
199
|
-
this.pointerCircle.start(pickResult.canvasPos);
|
|
211
|
+
this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
|
|
200
212
|
} else {
|
|
201
213
|
return;
|
|
202
214
|
}
|
|
@@ -303,7 +315,7 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
303
315
|
this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
|
|
304
316
|
this.pointerLens.snapped = true;
|
|
305
317
|
}
|
|
306
|
-
this.pointerCircle.start(snapPickResult.snappedCanvasPos);
|
|
318
|
+
this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
|
|
307
319
|
pointerWorldPos.set(snapPickResult.worldPos);
|
|
308
320
|
this._currentAngleMeasurement.corner.worldPos = snapPickResult.worldPos;
|
|
309
321
|
this._currentAngleMeasurement.corner.entity = snapPickResult.entity;
|
|
@@ -325,7 +337,7 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
325
337
|
this.pointerLens.cursorPos = pickResult.canvasPos;
|
|
326
338
|
this.pointerLens.snapped = false;
|
|
327
339
|
}
|
|
328
|
-
this.pointerCircle.start(pickResult.canvasPos);
|
|
340
|
+
this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
|
|
329
341
|
pointerWorldPos.set(pickResult.worldPos);
|
|
330
342
|
this._currentAngleMeasurement.corner.worldPos = pickResult.worldPos;
|
|
331
343
|
this._currentAngleMeasurement.corner.entity = pickResult.entity;
|
|
@@ -396,7 +408,7 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
396
408
|
this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
|
|
397
409
|
this.pointerLens.snapped = true;
|
|
398
410
|
}
|
|
399
|
-
this.pointerCircle.start(snapPickResult.snappedCanvasPos);
|
|
411
|
+
this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
|
|
400
412
|
pointerWorldPos.set(snapPickResult.worldPos);
|
|
401
413
|
this._currentAngleMeasurement.target.worldPos = snapPickResult.worldPos;
|
|
402
414
|
this._currentAngleMeasurement.target.entity = snapPickResult.entity;
|
|
@@ -418,7 +430,7 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
418
430
|
this.pointerLens.cursorPos = pickResult.canvasPos;
|
|
419
431
|
this.pointerLens.snapped = false;
|
|
420
432
|
}
|
|
421
|
-
this.pointerCircle.start(pickResult.canvasPos);
|
|
433
|
+
this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
|
|
422
434
|
pointerWorldPos.set(pickResult.worldPos);
|
|
423
435
|
this._currentAngleMeasurement.target.worldPos = pickResult.worldPos;
|
|
424
436
|
this._currentAngleMeasurement.target.entity = pickResult.entity;
|
|
@@ -482,14 +494,11 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
482
494
|
}
|
|
483
495
|
|
|
484
496
|
const touch = event.touches[0];
|
|
485
|
-
const touchX = touch.clientX;
|
|
486
|
-
const touchY = touch.clientY;
|
|
487
|
-
|
|
488
497
|
if (touch.identifier !== touchId) {
|
|
489
498
|
return;
|
|
490
499
|
}
|
|
491
500
|
|
|
492
|
-
|
|
501
|
+
copyCanvasPos(touch, touchMoveCanvasPos);
|
|
493
502
|
|
|
494
503
|
let snapPickResult;
|
|
495
504
|
let pickResult;
|
|
@@ -662,9 +671,6 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
662
671
|
}
|
|
663
672
|
|
|
664
673
|
const touch = event.changedTouches[0];
|
|
665
|
-
const touchX = touch.clientX;
|
|
666
|
-
const touchY = touch.clientY;
|
|
667
|
-
|
|
668
674
|
if (touch.identifier !== touchId) {
|
|
669
675
|
return;
|
|
670
676
|
}
|
|
@@ -674,7 +680,10 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
674
680
|
longTouchTimeout = null;
|
|
675
681
|
}
|
|
676
682
|
|
|
677
|
-
|
|
683
|
+
copyCanvasPos(touch, touchEndCanvasPos);
|
|
684
|
+
|
|
685
|
+
const touchX = touchEndCanvasPos[0];
|
|
686
|
+
const touchY = touchEndCanvasPos[1];
|
|
678
687
|
|
|
679
688
|
switch (this._touchState) {
|
|
680
689
|
|
|
@@ -173,6 +173,9 @@ class Annotation extends Marker {
|
|
|
173
173
|
addContextMenuListener(this._marker, e => {
|
|
174
174
|
e.preventDefault();
|
|
175
175
|
this.plugin.fire("contextmenu", this);
|
|
176
|
+
}, e => {
|
|
177
|
+
e.preventDefault();
|
|
178
|
+
this.plugin.fire("markerClicked", this);
|
|
176
179
|
})
|
|
177
180
|
this._marker.addEventListener("mouseenter", () => {
|
|
178
181
|
this.plugin.fire("markerMouseEnter", this);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {math} from "../../viewer/scene/math/math.js";
|
|
2
2
|
import {PointerCircle} from "../../extras/PointerCircle/PointerCircle.js";
|
|
3
3
|
import {DistanceMeasurementsControl} from "./DistanceMeasurementsControl.js";
|
|
4
|
-
|
|
4
|
+
import {transformToNode} from "../lib/ui/index.js";
|
|
5
5
|
|
|
6
6
|
const WAITING_FOR_ORIGIN_TOUCH_START = 0;
|
|
7
7
|
const WAITING_FOR_ORIGIN_QUICK_TOUCH_END = 1;
|
|
@@ -13,6 +13,8 @@ const WAITING_FOR_TARGET_LONG_TOUCH_END = 5;
|
|
|
13
13
|
|
|
14
14
|
const TOUCH_CANCELING = 7;
|
|
15
15
|
|
|
16
|
+
const tmpVec2 = math.vec2();
|
|
17
|
+
|
|
16
18
|
/**
|
|
17
19
|
* Creates {@link DistanceMeasurement}s from touch input.
|
|
18
20
|
*
|
|
@@ -159,6 +161,19 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
159
161
|
this._touchState = WAITING_FOR_ORIGIN_TOUCH_START;
|
|
160
162
|
}
|
|
161
163
|
|
|
164
|
+
const copyCanvasPos = (event, dst) => {
|
|
165
|
+
dst[0] = event.clientX;
|
|
166
|
+
dst[1] = event.clientY;
|
|
167
|
+
transformToNode(canvas.ownerDocument.documentElement, canvas, dst);
|
|
168
|
+
return dst;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const toBodyPos = (pos, dst) => {
|
|
172
|
+
dst.set(pos);
|
|
173
|
+
transformToNode(canvas, canvas.ownerDocument.documentElement, dst);
|
|
174
|
+
return dst;
|
|
175
|
+
};
|
|
176
|
+
|
|
162
177
|
canvas.addEventListener("touchstart", this._onCanvasTouchStart = (event) => {
|
|
163
178
|
|
|
164
179
|
const currentNumTouches = event.touches.length;
|
|
@@ -172,16 +187,8 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
172
187
|
}
|
|
173
188
|
|
|
174
189
|
const touch = event.touches[0];
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const rect = canvas.getBoundingClientRect();
|
|
178
|
-
|
|
179
|
-
// Calculate the touch position relative to the canvas
|
|
180
|
-
const touchX = touch.clientX - rect.left;
|
|
181
|
-
const touchY = touch.clientY - rect.top;
|
|
182
|
-
|
|
183
|
-
touchStartCanvasPos.set([touchX, touchY]);
|
|
184
|
-
touchMoveCanvasPos.set([touchX, touchY]);
|
|
190
|
+
copyCanvasPos(touch, touchStartCanvasPos);
|
|
191
|
+
touchMoveCanvasPos.set(touchStartCanvasPos);
|
|
185
192
|
|
|
186
193
|
switch (this._touchState) {
|
|
187
194
|
|
|
@@ -197,7 +204,7 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
197
204
|
});
|
|
198
205
|
if (snapPickResult && snapPickResult.snapped) {
|
|
199
206
|
pointerWorldPos.set(snapPickResult.worldPos);
|
|
200
|
-
this.pointerCircle.start(snapPickResult.snappedCanvasPos);
|
|
207
|
+
this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
|
|
201
208
|
} else {
|
|
202
209
|
const pickResult = scene.pick({
|
|
203
210
|
canvasPos: touchMoveCanvasPos,
|
|
@@ -205,7 +212,7 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
205
212
|
})
|
|
206
213
|
if (pickResult && pickResult.worldPos) {
|
|
207
214
|
pointerWorldPos.set(pickResult.worldPos);
|
|
208
|
-
this.pointerCircle.start(pickResult.canvasPos);
|
|
215
|
+
this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
|
|
209
216
|
} else {
|
|
210
217
|
return;
|
|
211
218
|
}
|
|
@@ -309,7 +316,7 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
309
316
|
this.pointerLens.cursorPos = snapPickResult.snappedCanvasPos;
|
|
310
317
|
this.pointerLens.snapped = true;
|
|
311
318
|
}
|
|
312
|
-
this.pointerCircle.start(snapPickResult.snappedCanvasPos);
|
|
319
|
+
this.pointerCircle.start(toBodyPos(snapPickResult.snappedCanvasPos, tmpVec2));
|
|
313
320
|
pointerWorldPos.set(snapPickResult.worldPos);
|
|
314
321
|
this._currentDistanceMeasurement.target.worldPos = snapPickResult.worldPos;
|
|
315
322
|
this._currentDistanceMeasurement.target.entity = snapPickResult.entity;
|
|
@@ -327,7 +334,7 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
327
334
|
this.pointerLens.cursorPos = pickResult.canvasPos;
|
|
328
335
|
this.pointerLens.snapped = false;
|
|
329
336
|
}
|
|
330
|
-
this.pointerCircle.start(pickResult.canvasPos);
|
|
337
|
+
this.pointerCircle.start(toBodyPos(pickResult.canvasPos, tmpVec2));
|
|
331
338
|
pointerWorldPos.set(pickResult.worldPos);
|
|
332
339
|
this._currentDistanceMeasurement.target.worldPos = pickResult.worldPos;
|
|
333
340
|
this._currentDistanceMeasurement.target.entity = pickResult.entity;
|
|
@@ -386,19 +393,11 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
386
393
|
}
|
|
387
394
|
|
|
388
395
|
const touch = event.touches[0];
|
|
389
|
-
|
|
390
|
-
// Get the canvas's bounding rectangle
|
|
391
|
-
const rect = canvas.getBoundingClientRect();
|
|
392
|
-
|
|
393
|
-
// Calculate the touch position relative to the canvas
|
|
394
|
-
const touchX = touch.clientX - rect.left;
|
|
395
|
-
const touchY = touch.clientY - rect.top;
|
|
396
|
-
|
|
397
396
|
if (touch.identifier !== touchId) {
|
|
398
397
|
return;
|
|
399
398
|
}
|
|
400
399
|
|
|
401
|
-
|
|
400
|
+
copyCanvasPos(touch, touchMoveCanvasPos);
|
|
402
401
|
|
|
403
402
|
let snapPickResult;
|
|
404
403
|
let pickResult;
|
|
@@ -563,14 +562,6 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
563
562
|
}
|
|
564
563
|
|
|
565
564
|
const touch = event.changedTouches[0];
|
|
566
|
-
|
|
567
|
-
// Get the canvas's bounding rectangle
|
|
568
|
-
const rect = canvas.getBoundingClientRect();
|
|
569
|
-
|
|
570
|
-
// Calculate the touch position relative to the canvas
|
|
571
|
-
const touchX = touch.clientX - rect.left;
|
|
572
|
-
const touchY = touch.clientY - rect.top;
|
|
573
|
-
|
|
574
565
|
if (touch.identifier !== touchId) {
|
|
575
566
|
return;
|
|
576
567
|
}
|
|
@@ -580,7 +571,10 @@ export class DistanceMeasurementsTouchControl extends DistanceMeasurementsContro
|
|
|
580
571
|
longTouchTimeout = null;
|
|
581
572
|
}
|
|
582
573
|
|
|
583
|
-
|
|
574
|
+
copyCanvasPos(touch, touchEndCanvasPos);
|
|
575
|
+
|
|
576
|
+
const touchX = touchEndCanvasPos[0];
|
|
577
|
+
const touchY = touchEndCanvasPos[1];
|
|
584
578
|
|
|
585
579
|
switch (this._touchState) {
|
|
586
580
|
|
|
@@ -270,8 +270,10 @@ class Control {
|
|
|
270
270
|
isObject: false
|
|
271
271
|
}), NO_STATE_INHERIT);
|
|
272
272
|
|
|
273
|
+
const localToWorldVec = (localVec, worldVec) => math.vec3ApplyQuaternion(rootNode.quaternion, localVec, worldVec);
|
|
274
|
+
|
|
273
275
|
const closestPointOnAxis = (function() {
|
|
274
|
-
const worldAxis = math.
|
|
276
|
+
const worldAxis = math.vec3();
|
|
275
277
|
const org = math.vec3();
|
|
276
278
|
const dir = math.vec3();
|
|
277
279
|
return (canvasPos, dst) => {
|
|
@@ -306,22 +308,39 @@ class Control {
|
|
|
306
308
|
if (closestPointOnAxis(canvasPos, tempVec3)) {
|
|
307
309
|
math.subVec3(tempVec3, initOffset, tempVec3);
|
|
308
310
|
setPos(tempVec3);
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
+
if (this._sectionPlane) {
|
|
312
|
+
this._sectionPlane.pos = tempVec3;
|
|
311
313
|
}
|
|
312
314
|
}
|
|
313
315
|
});
|
|
314
316
|
}
|
|
315
317
|
};
|
|
316
318
|
|
|
317
|
-
const lastCanvasPos = math.vec2();
|
|
318
319
|
handlers[rotateHandle.id] = {
|
|
319
320
|
setActivated: a => hoop.visible = a,
|
|
320
321
|
initDragAction: (initCanvasPos) => {
|
|
321
|
-
|
|
322
|
+
const rotationFromCanvasPos = (function() {
|
|
323
|
+
const planeCanvasPos = camera.projectWorldPos(pos);
|
|
324
|
+
localToWorldVec(rgb, tempVec3);
|
|
325
|
+
math.transformVec3(camera.normalMatrix, tempVec3, tempVec3);
|
|
326
|
+
const axisCoeff = Math.sign(tempVec3[2]);
|
|
327
|
+
return (canvasPos) => {
|
|
328
|
+
const dx = canvasPos[0] - planeCanvasPos[0];
|
|
329
|
+
const dy = canvasPos[1] - planeCanvasPos[1];
|
|
330
|
+
return axisCoeff * Math.atan2(-dy, dx);
|
|
331
|
+
};
|
|
332
|
+
})();
|
|
333
|
+
|
|
334
|
+
let lastRotation = rotationFromCanvasPos(initCanvasPos);
|
|
335
|
+
|
|
322
336
|
return canvasPos => {
|
|
323
|
-
|
|
324
|
-
|
|
337
|
+
const rotation = rotationFromCanvasPos(canvasPos);
|
|
338
|
+
rootNode.rotate(rgb, (rotation - lastRotation) * 180 / Math.PI);
|
|
339
|
+
if (this._sectionPlane) {
|
|
340
|
+
ignoreNextSectionPlaneDirUpdate = true;
|
|
341
|
+
this._sectionPlane.dir = math.vec3ApplyQuaternion(rootNode.quaternion, [0, 0, 1], tempVec3);
|
|
342
|
+
}
|
|
343
|
+
lastRotation = rotation;
|
|
325
344
|
};
|
|
326
345
|
}
|
|
327
346
|
};
|
|
@@ -457,114 +476,6 @@ class Control {
|
|
|
457
476
|
cleanups.push(() => scene.off(onSceneTick));
|
|
458
477
|
}
|
|
459
478
|
|
|
460
|
-
const getClickCoordsWithinElement = (event, canvasPos) => {
|
|
461
|
-
if (!event) {
|
|
462
|
-
event = window.event;
|
|
463
|
-
canvasPos[0] = event.x;
|
|
464
|
-
canvasPos[1] = event.y;
|
|
465
|
-
} else {
|
|
466
|
-
const element = event.target;
|
|
467
|
-
const rect = element.getBoundingClientRect();
|
|
468
|
-
canvasPos[0] = event.clientX - rect.left;
|
|
469
|
-
canvasPos[1] = event.clientY - rect.top;
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
const localToWorldVec = (function () {
|
|
474
|
-
const mat = math.mat4();
|
|
475
|
-
return function (localVec, worldVec) {
|
|
476
|
-
math.quaternionToMat4(rootNode.quaternion, mat);
|
|
477
|
-
math.transformVec3(mat, localVec, worldVec);
|
|
478
|
-
math.normalizeVec3(worldVec);
|
|
479
|
-
return worldVec;
|
|
480
|
-
};
|
|
481
|
-
})();
|
|
482
|
-
|
|
483
|
-
const getTranslationPlane = (worldAxis, planeNormal) => {
|
|
484
|
-
const absX = Math.abs(worldAxis[0]);
|
|
485
|
-
if (absX > Math.abs(worldAxis[1]) && absX > Math.abs(worldAxis[2])) {
|
|
486
|
-
math.cross3Vec3(worldAxis, [0, 1, 0], planeNormal);
|
|
487
|
-
} else {
|
|
488
|
-
math.cross3Vec3(worldAxis, [1, 0, 0], planeNormal);
|
|
489
|
-
}
|
|
490
|
-
math.cross3Vec3(planeNormal, worldAxis, planeNormal);
|
|
491
|
-
math.normalizeVec3(planeNormal);
|
|
492
|
-
};
|
|
493
|
-
|
|
494
|
-
const self = this;
|
|
495
|
-
var dragRotateSectionPlane = (function () {
|
|
496
|
-
const p1 = math.vec4();
|
|
497
|
-
const p2 = math.vec4();
|
|
498
|
-
const c = math.vec4();
|
|
499
|
-
const worldAxis = math.vec4();
|
|
500
|
-
const dir = math.vec3();
|
|
501
|
-
const mat = math.mat4();
|
|
502
|
-
const planeNormal = math.vec3();
|
|
503
|
-
return function (baseAxis, fromMouse, toMouse) {
|
|
504
|
-
localToWorldVec(baseAxis, worldAxis);
|
|
505
|
-
const hasData = getPointerPlaneIntersect(fromMouse, worldAxis, p1) && getPointerPlaneIntersect(toMouse, worldAxis, p2);
|
|
506
|
-
if (!hasData) { // Find intersections with view plane and project down to origin
|
|
507
|
-
getTranslationPlane(worldAxis, planeNormal);
|
|
508
|
-
getPointerPlaneIntersect(fromMouse, planeNormal, p1, 1); // Ensure plane moves closer to camera so angles become workable
|
|
509
|
-
getPointerPlaneIntersect(toMouse, planeNormal, p2, 1);
|
|
510
|
-
var dot = math.dotVec3(p1, worldAxis);
|
|
511
|
-
p1[0] -= dot * worldAxis[0];
|
|
512
|
-
p1[1] -= dot * worldAxis[1];
|
|
513
|
-
p1[2] -= dot * worldAxis[2];
|
|
514
|
-
dot = math.dotVec3(p2, worldAxis);
|
|
515
|
-
p2[0] -= dot * worldAxis[0];
|
|
516
|
-
p2[1] -= dot * worldAxis[1];
|
|
517
|
-
p2[2] -= dot * worldAxis[2];
|
|
518
|
-
}
|
|
519
|
-
math.normalizeVec3(p1);
|
|
520
|
-
math.normalizeVec3(p2);
|
|
521
|
-
dot = math.dotVec3(p1, p2);
|
|
522
|
-
dot = math.clamp(dot, -1.0, 1.0); // Rounding errors cause dot to exceed allowed range
|
|
523
|
-
var incDegrees = Math.acos(dot) * math.RADTODEG;
|
|
524
|
-
math.cross3Vec3(p1, p2, c);
|
|
525
|
-
if (math.dotVec3(c, worldAxis) < 0.0) {
|
|
526
|
-
incDegrees = -incDegrees;
|
|
527
|
-
}
|
|
528
|
-
rootNode.rotate(baseAxis, incDegrees);
|
|
529
|
-
|
|
530
|
-
if (self._sectionPlane) {
|
|
531
|
-
math.quaternionToMat4(rootNode.quaternion, mat); // << ---
|
|
532
|
-
math.transformVec3(mat, [0, 0, 1], dir);
|
|
533
|
-
ignoreNextSectionPlaneDirUpdate = true;
|
|
534
|
-
self._sectionPlane.dir = dir;
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
})();
|
|
538
|
-
|
|
539
|
-
var getPointerPlaneIntersect = (function () {
|
|
540
|
-
const dir = math.vec4([0, 0, 0, 1]);
|
|
541
|
-
const matrix = math.mat4();
|
|
542
|
-
return function (mouse, axis, dest, offset) {
|
|
543
|
-
offset = offset || 0;
|
|
544
|
-
dir[0] = mouse[0] / canvas.width * 2.0 - 1.0;
|
|
545
|
-
dir[1] = -(mouse[1] / canvas.height * 2.0 - 1.0);
|
|
546
|
-
dir[2] = 0.0;
|
|
547
|
-
dir[3] = 1.0;
|
|
548
|
-
math.mulMat4(camera.projMatrix, camera.viewMatrix, matrix); // Unproject norm device coords to view coords
|
|
549
|
-
math.inverseMat4(matrix);
|
|
550
|
-
math.transformVec4(matrix, dir, dir);
|
|
551
|
-
math.mulVec4Scalar(dir, 1.0 / dir[3]); // This is now point A on the ray in world space
|
|
552
|
-
var rayO = camera.eye; // The direction
|
|
553
|
-
math.subVec4(dir, rayO, dir);
|
|
554
|
-
const origin = self._sectionPlane.pos; // Plane origin:
|
|
555
|
-
var d = -math.dotVec3(origin, axis) - offset;
|
|
556
|
-
var dot = math.dotVec3(axis, dir);
|
|
557
|
-
if (Math.abs(dot) > 0.005) {
|
|
558
|
-
var t = -(math.dotVec3(axis, rayO) + d) / dot;
|
|
559
|
-
math.mulVec3Scalar(dir, t, dest);
|
|
560
|
-
math.addVec3(dest, rayO);
|
|
561
|
-
math.subVec3(dest, origin, dest);
|
|
562
|
-
return true;
|
|
563
|
-
}
|
|
564
|
-
return false;
|
|
565
|
-
};
|
|
566
|
-
})();
|
|
567
|
-
|
|
568
479
|
{
|
|
569
480
|
let deactivateActive = null;
|
|
570
481
|
let currentDrag = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Plugin} from "../../viewer/Plugin.js";
|
|
2
|
-
import {RenderService} from "./RenderService.js";
|
|
1
|
+
import { Plugin } from "../../viewer/Plugin.js";
|
|
2
|
+
import { RenderService } from "./RenderService.js";
|
|
3
3
|
|
|
4
4
|
const treeViews = [];
|
|
5
5
|
|
|
@@ -363,6 +363,8 @@ export class TreeViewPlugin extends Plugin {
|
|
|
363
363
|
* @param {RenderService} [cfg.renderService] Optional {@link RenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}.
|
|
364
364
|
* @param {Boolean} [cfg.showIndeterminate=false] When true, will show indeterminate state for checkboxes when some but not all child nodes are checked
|
|
365
365
|
* @param {Boolean} [cfg.showProjectNode=false] When true, will show top level project node when hierarchy is set to "storeys"
|
|
366
|
+
* @param {Function} [cfg.elevationSortFunction] Optional function to replace the default elevation sort function. The function should take two nodes and return -1, 0 or 1.
|
|
367
|
+
* @param {Function} [cfg.defaultSortFunction] Optional function to replace the default sort function. The function should take two nodes and return -1, 0 or 1.
|
|
366
368
|
*/
|
|
367
369
|
constructor(viewer, cfg = {}) {
|
|
368
370
|
|
|
@@ -416,6 +418,8 @@ export class TreeViewPlugin extends Plugin {
|
|
|
416
418
|
this._renderService = cfg.renderService || new RenderService();
|
|
417
419
|
this._showIndeterminate = cfg.showIndeterminate ?? false;
|
|
418
420
|
this._showProjectNode = cfg.showProjectNode ?? false;
|
|
421
|
+
this._elevationSortFunction = cfg.elevationSortFunction ?? undefined;
|
|
422
|
+
this._defaultSortFunction = cfg.defaultSortFunction ?? undefined;
|
|
419
423
|
|
|
420
424
|
if (!this._renderService) {
|
|
421
425
|
throw new Error('TreeViewPlugin: no render service set');
|
|
@@ -1229,9 +1233,11 @@ export class TreeViewPlugin extends Plugin {
|
|
|
1229
1233
|
}
|
|
1230
1234
|
const firstChild = children[0];
|
|
1231
1235
|
if ((this._hierarchy === "storeys" || this._hierarchy === "containment") && firstChild.type === "IfcBuildingStorey") {
|
|
1232
|
-
children.sort(this.
|
|
1236
|
+
if (this._elevationSortFunction) children.sort(this._elevationSortFunction);
|
|
1237
|
+
else children.sort(this._getSpatialSortFunc());
|
|
1233
1238
|
} else {
|
|
1234
|
-
children.sort(this.
|
|
1239
|
+
if (this._defaultSortFunction) children.sort(this._defaultSortFunction)
|
|
1240
|
+
else children.sort(this._alphaSortFunc);
|
|
1235
1241
|
}
|
|
1236
1242
|
for (let i = 0, len = children.length; i < len; i++) {
|
|
1237
1243
|
const node = children[i];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { os } from "../../../viewer/utils/os.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
//failCallback will be called when the press is not long enough to considered a long press
|
|
4
|
+
export function addContextMenuListener(elem, callback, failCallback = () => {}) {
|
|
4
5
|
if (!elem || !callback) return;
|
|
5
6
|
|
|
6
7
|
let timeout = null;
|
|
@@ -54,6 +55,7 @@ export function addContextMenuListener(elem, callback) {
|
|
|
54
55
|
const touchEndHandler = (event) => {
|
|
55
56
|
event.preventDefault();
|
|
56
57
|
if (timeout) {
|
|
58
|
+
failCallback(event);
|
|
57
59
|
clearTimeout(timeout);
|
|
58
60
|
timeout = null;
|
|
59
61
|
}
|