@xeokit/xeokit-sdk 2.4.2-beta-14 → 2.4.2-beta-19
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 +506 -319
- package/dist/xeokit-sdk.es.js +506 -319
- package/dist/xeokit-sdk.es5.js +356 -236
- package/dist/xeokit-sdk.min.cjs.js +3 -3
- package/dist/xeokit-sdk.min.es.js +2 -2
- package/dist/xeokit-sdk.min.es5.js +2 -2
- package/package.json +1 -1
- package/src/extras/MarqueePicker/MarqueePicker.js +81 -0
- package/src/extras/MarqueePicker/MarqueePickerMouseControl.js +2 -0
- package/src/extras/PointerLens/PointerLens.js +21 -21
- package/src/extras/collision/ObjectsKdTree3.js +2 -0
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +10 -9
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.js +9 -8
- package/src/viewer/scene/CameraControl/lib/controllers/PickController.js +8 -29
- package/src/viewer/scene/CameraControl/lib/handlers/MousePickHandler.js +48 -45
- package/src/viewer/scene/input/Input.js +10 -2
- package/src/viewer/scene/scene/Scene.js +84 -3
- package/src/viewer/scene/webgl/PickResult.js +27 -2
- package/src/viewer/scene/webgl/Renderer.js +212 -207
package/dist/xeokit-sdk.es.js
CHANGED
|
@@ -1041,8 +1041,8 @@ class PointerLens {
|
|
|
1041
1041
|
this._lensCanvasContext = this._lensCanvas.getContext('2d');
|
|
1042
1042
|
this._canvasElement = this.viewer.scene.canvas.canvas;
|
|
1043
1043
|
|
|
1044
|
-
this.
|
|
1045
|
-
this.
|
|
1044
|
+
this._canvasPos = null;
|
|
1045
|
+
this._snappedCanvasPos = null;
|
|
1046
1046
|
this._lensPosToggle = true;
|
|
1047
1047
|
|
|
1048
1048
|
this._zoomLevel = cfg.zoomLevel || 2;
|
|
@@ -1065,14 +1065,14 @@ class PointerLens {
|
|
|
1065
1065
|
if (!this._active || !this._visible) {
|
|
1066
1066
|
return;
|
|
1067
1067
|
}
|
|
1068
|
-
if (!this.
|
|
1068
|
+
if (!this._canvasPos) {
|
|
1069
1069
|
return;
|
|
1070
1070
|
}
|
|
1071
1071
|
const lensRect = this._lensContainer.getBoundingClientRect();
|
|
1072
1072
|
const canvasRect = this._canvasElement.getBoundingClientRect();
|
|
1073
1073
|
const pointerOnLens =
|
|
1074
|
-
this.
|
|
1075
|
-
this.
|
|
1074
|
+
this._canvasPos[0] < lensRect.right && this._canvasPos[0] > lensRect.left &&
|
|
1075
|
+
this._canvasPos[1] < lensRect.bottom && this._canvasPos[1] > lensRect.top;
|
|
1076
1076
|
this._lensContainer.style.marginLeft = `25px`;
|
|
1077
1077
|
if (pointerOnLens) {
|
|
1078
1078
|
if (this._lensPosToggle) {
|
|
@@ -1086,8 +1086,8 @@ class PointerLens {
|
|
|
1086
1086
|
const size = Math.max(this._lensCanvas.width, this._lensCanvas.height) / this._zoomLevel;
|
|
1087
1087
|
this._lensCanvasContext.drawImage(
|
|
1088
1088
|
this._canvasElement, // source canvas
|
|
1089
|
-
this.
|
|
1090
|
-
this.
|
|
1089
|
+
this._canvasPos[0] - size / 2, // source x (zoom center)
|
|
1090
|
+
this._canvasPos[1] - size / 2, // source y (zoom center)
|
|
1091
1091
|
size, // source width
|
|
1092
1092
|
size, // source height
|
|
1093
1093
|
0, // destination x
|
|
@@ -1101,9 +1101,9 @@ class PointerLens {
|
|
|
1101
1101
|
(lensRect.top + lensRect.bottom) / 2
|
|
1102
1102
|
];
|
|
1103
1103
|
|
|
1104
|
-
if (this.
|
|
1105
|
-
const deltaX = this.
|
|
1106
|
-
const deltaY = this.
|
|
1104
|
+
if (this._snappedCanvasPos) {
|
|
1105
|
+
const deltaX = this._snappedCanvasPos[0] - this._canvasPos[0];
|
|
1106
|
+
const deltaY = this._snappedCanvasPos[1] - this._canvasPos[1];
|
|
1107
1107
|
|
|
1108
1108
|
this._lensCursorDiv.style.marginLeft = `${centerLensCanvas[0] + deltaX * this._zoomLevel - 10}px`;
|
|
1109
1109
|
this._lensCursorDiv.style.marginTop = `${centerLensCanvas[1] + deltaY * this._zoomLevel - 10}px`;
|
|
@@ -1139,10 +1139,10 @@ class PointerLens {
|
|
|
1139
1139
|
|
|
1140
1140
|
/**
|
|
1141
1141
|
* Sets the canvas central position of the lens.
|
|
1142
|
-
* @param
|
|
1142
|
+
* @param canvasPos
|
|
1143
1143
|
*/
|
|
1144
|
-
set
|
|
1145
|
-
this.
|
|
1144
|
+
set canvasPos(canvasPos) {
|
|
1145
|
+
this._canvasPos = canvasPos;
|
|
1146
1146
|
this.update();
|
|
1147
1147
|
}
|
|
1148
1148
|
|
|
@@ -1150,25 +1150,25 @@ class PointerLens {
|
|
|
1150
1150
|
* Gets the canvas central position of the lens.
|
|
1151
1151
|
* @returns {Number[]}
|
|
1152
1152
|
*/
|
|
1153
|
-
get
|
|
1154
|
-
return this.
|
|
1153
|
+
get canvasPos() {
|
|
1154
|
+
return this._canvasPos;
|
|
1155
1155
|
}
|
|
1156
1156
|
|
|
1157
1157
|
/**
|
|
1158
1158
|
* Sets the canvas coordinates of the pointer.
|
|
1159
|
-
* @param
|
|
1159
|
+
* @param snappedCanvasPos
|
|
1160
1160
|
*/
|
|
1161
|
-
set
|
|
1162
|
-
this.
|
|
1161
|
+
set snappedCanvasPos(snappedCanvasPos) {
|
|
1162
|
+
this._snappedCanvasPos = snappedCanvasPos;
|
|
1163
1163
|
this.update();
|
|
1164
1164
|
}
|
|
1165
1165
|
|
|
1166
1166
|
/**
|
|
1167
|
-
* Gets the canvas coordinates of the pointer.
|
|
1167
|
+
* Gets the canvas coordinates of the snapped pointer.
|
|
1168
1168
|
* @returns {Number[]}
|
|
1169
1169
|
*/
|
|
1170
|
-
get
|
|
1171
|
-
return this.
|
|
1170
|
+
get snappedCanvasPos() {
|
|
1171
|
+
return this._snappedCanvasPos;
|
|
1172
1172
|
}
|
|
1173
1173
|
|
|
1174
1174
|
/**
|
|
@@ -6649,6 +6649,8 @@ const kdTreeDimLength$1 = new Float32Array(3);
|
|
|
6649
6649
|
* Automatically indexes a {@link Viewer}'s {@link Entity}s in a 3D k-d tree
|
|
6650
6650
|
* to support fast collision detection with 3D World-space axis-aligned boundaries (AABBs) and frustums.
|
|
6651
6651
|
*
|
|
6652
|
+
* See {@link MarqueePicker} for usage example.
|
|
6653
|
+
*
|
|
6652
6654
|
* An ObjectsKdTree3 is configured with a Viewer, and will then automatically
|
|
6653
6655
|
* keep itself populated with k-d nodes that contain the Viewer's Entitys.
|
|
6654
6656
|
*
|
|
@@ -8577,6 +8579,87 @@ function frustumIntersectsAABB3(frustum, aabb) {
|
|
|
8577
8579
|
|
|
8578
8580
|
/**
|
|
8579
8581
|
* Picks a {@link Viewer}'s {@link Entity}s with a canvas-space 2D marquee box.
|
|
8582
|
+
*
|
|
8583
|
+
* [<img src="https://xeokit.github.io/xeokit-sdk/assets/images/MarqueeSelect.gif">](https://xeokit.github.io/xeokit-sdk/examples/picking/#marqueePick_select)
|
|
8584
|
+
*
|
|
8585
|
+
* * [[Example 1: Select Objects with Marquee](https://xeokit.github.io/xeokit-sdk/examples/picking/#marqueePick_select)]
|
|
8586
|
+
* * [[Example 2: View-Fit Objects with Marquee](https://xeokit.github.io/xeokit-sdk/examples/picking/#marqueePick_viewFit)]
|
|
8587
|
+
*
|
|
8588
|
+
* # Usage
|
|
8589
|
+
*
|
|
8590
|
+
* In the example below, we
|
|
8591
|
+
*
|
|
8592
|
+
* 1. Create a {@link Viewer}, arrange the {@link Camera}
|
|
8593
|
+
* 2. Use an {@link XKTLoaderPlugin} to load a BIM model,
|
|
8594
|
+
* 3. Create a {@link ObjectsKdTree3} to automatically index the `Viewer's` {@link Entity}s for fast spatial lookup,
|
|
8595
|
+
* 4. Create a `MarqueePicker` to pick {@link Entity}s in the {@link Viewer}, using the {@link ObjectsKdTree3} to accelerate picking
|
|
8596
|
+
* 5. Create a {@link MarqueePickerMouseControl} to perform the marquee-picking with the `MarqueePicker`, using mouse input to draw the marquee box on the `Viewer's` canvas.
|
|
8597
|
+
*
|
|
8598
|
+
* When the {@link MarqueePickerMouseControl} is active:
|
|
8599
|
+
*
|
|
8600
|
+
* * Long-click, drag and release on the canvas to define a marque box that picks {@link Entity}s.
|
|
8601
|
+
* * Drag left-to-right to pick {@link Entity}s that intersect the box.
|
|
8602
|
+
* * Drag right-to-left to pick {@link Entity}s that are fully inside the box.
|
|
8603
|
+
* * On release, the `MarqueePicker` will fire a "picked" event with IDs of the picked {@link Entity}s, if any.
|
|
8604
|
+
* * Handling that event, we mark the {@link Entity}s as selected.
|
|
8605
|
+
* * Hold down CTRL to multi-pick.
|
|
8606
|
+
*
|
|
8607
|
+
* ````javascript
|
|
8608
|
+
* import {
|
|
8609
|
+
* Viewer,
|
|
8610
|
+
* XKTLoaderPlugin,
|
|
8611
|
+
* ObjectsKdTree3,
|
|
8612
|
+
* MarqueePicker,
|
|
8613
|
+
* MarqueePickerMouseControl
|
|
8614
|
+
* } from "xeokit-sdk.es.js";
|
|
8615
|
+
*
|
|
8616
|
+
* // 1
|
|
8617
|
+
*
|
|
8618
|
+
* const viewer = new Viewer({
|
|
8619
|
+
* canvasId: "myCanvas"
|
|
8620
|
+
* });
|
|
8621
|
+
*
|
|
8622
|
+
* viewer.scene.camera.eye = [14.9, 14.3, 5.4];
|
|
8623
|
+
* viewer.scene.camera.look = [6.5, 8.3, -4.1];
|
|
8624
|
+
* viewer.scene.camera.up = [-0.28, 0.9, -0.3];
|
|
8625
|
+
*
|
|
8626
|
+
* // 2
|
|
8627
|
+
*
|
|
8628
|
+
* const xktLoader = new XKTLoaderPlugin(viewer);
|
|
8629
|
+
*
|
|
8630
|
+
* const sceneModel = xktLoader.load({
|
|
8631
|
+
* id: "myModel",
|
|
8632
|
+
* src: "../../assets/models/xkt/v8/ifc/HolterTower.ifc.xkt"
|
|
8633
|
+
* });
|
|
8634
|
+
*
|
|
8635
|
+
* // 3
|
|
8636
|
+
*
|
|
8637
|
+
* const objectsKdTree3 = new ObjectsKdTree3({viewer});
|
|
8638
|
+
*
|
|
8639
|
+
* // 4
|
|
8640
|
+
*
|
|
8641
|
+
* const marqueePicker = new MarqueePicker({viewer, objectsKdTree3});
|
|
8642
|
+
*
|
|
8643
|
+
* // 5
|
|
8644
|
+
*
|
|
8645
|
+
* const marqueePickerMouseControl = new MarqueePickerMouseControl({marqueePicker});
|
|
8646
|
+
*
|
|
8647
|
+
* marqueePicker.on("clear", () => {
|
|
8648
|
+
* viewer.scene.setObjectsSelected(viewer.scene.selectedObjectIds, false);
|
|
8649
|
+
* });
|
|
8650
|
+
*
|
|
8651
|
+
* marqueePicker.on("picked", (objectIds) => {
|
|
8652
|
+
* viewer.scene.setObjectsSelected(objectIds, true);
|
|
8653
|
+
* });
|
|
8654
|
+
*
|
|
8655
|
+
* marqueePickerMouseControl.setActive(true);
|
|
8656
|
+
* ````
|
|
8657
|
+
*
|
|
8658
|
+
* # Design Notes
|
|
8659
|
+
*
|
|
8660
|
+
* * The {@link ObjectsKdTree3} can be shared with any other components that want to use it to spatially search for {@link Entity}s.
|
|
8661
|
+
* * The {@link MarqueePickerMouseControl} can be replaced with other types of controllers (i.e. touch), or used alongside them.
|
|
8662
|
+
* * The `MarqueePicker` has no input handlers of its own, and provides an API through which to programmatically control marquee picking. By firing the "picked" events, `MarqueePicker` implements the *Blackboard Pattern*.
|
|
8580
8663
|
*/
|
|
8581
8664
|
class MarqueePicker extends Component {
|
|
8582
8665
|
|
|
@@ -8846,6 +8929,8 @@ MarqueePicker.PICK_MODE_INSIDE = 1;
|
|
|
8846
8929
|
/**
|
|
8847
8930
|
* Controls a {@link MarqueePicker} with mouse input.
|
|
8848
8931
|
*
|
|
8932
|
+
* See {@link MarqueePicker} for usage example.
|
|
8933
|
+
*
|
|
8849
8934
|
* When the MarqueePickerMouseControl is active:
|
|
8850
8935
|
*
|
|
8851
8936
|
* * Long-click, drag and release on the canvas to define a marque box that picks {@link Entity}s.
|
|
@@ -11924,8 +12009,8 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
|
|
|
11924
12009
|
if (event.snappedToVertex || event.snappedToEdge) {
|
|
11925
12010
|
if (pointerLens) {
|
|
11926
12011
|
pointerLens.visible = true;
|
|
11927
|
-
pointerLens.
|
|
11928
|
-
pointerLens.
|
|
12012
|
+
pointerLens.canvasPos = event.canvasPos;
|
|
12013
|
+
pointerLens.snappedCanvasPos = event.snappedCanvasPos || event.canvasPos;
|
|
11929
12014
|
pointerLens.snapped = true;
|
|
11930
12015
|
}
|
|
11931
12016
|
this.markerDiv.style.background = "greenyellow";
|
|
@@ -11933,21 +12018,22 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
|
|
|
11933
12018
|
} else {
|
|
11934
12019
|
if (pointerLens) {
|
|
11935
12020
|
pointerLens.visible = true;
|
|
11936
|
-
pointerLens.
|
|
11937
|
-
pointerLens.
|
|
12021
|
+
pointerLens.canvasPos = event.canvasPos;
|
|
12022
|
+
pointerLens.snappedCanvasPos = event.canvasPos;
|
|
11938
12023
|
pointerLens.snapped = false;
|
|
11939
12024
|
}
|
|
11940
12025
|
this.markerDiv.style.background = "pink";
|
|
11941
12026
|
this.markerDiv.style.border = "2px solid red";
|
|
11942
12027
|
}
|
|
12028
|
+
const canvasPos = event.snappedCanvasPos || event.canvasPos;
|
|
11943
12029
|
mouseHovering = true;
|
|
11944
12030
|
mouseHoverEntity = event.entity;
|
|
11945
12031
|
mouseWorldPos.set(event.worldPos);
|
|
11946
|
-
mouseHoverCanvasPos.set(
|
|
12032
|
+
mouseHoverCanvasPos.set(canvasPos);
|
|
11947
12033
|
switch (this._mouseState) {
|
|
11948
12034
|
case MOUSE_FINDING_ORIGIN:
|
|
11949
|
-
this.markerDiv.style.marginLeft = `${
|
|
11950
|
-
this.markerDiv.style.marginTop = `${
|
|
12035
|
+
this.markerDiv.style.marginLeft = `${canvasPos[0] - 5}px`;
|
|
12036
|
+
this.markerDiv.style.marginTop = `${canvasPos[1] - 5}px`;
|
|
11951
12037
|
break;
|
|
11952
12038
|
case MOUSE_FINDING_CORNER:
|
|
11953
12039
|
if (this._currentAngleMeasurement) {
|
|
@@ -12063,8 +12149,8 @@ class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
|
|
|
12063
12149
|
mouseHovering = false;
|
|
12064
12150
|
if (pointerLens) {
|
|
12065
12151
|
pointerLens.visible = true;
|
|
12066
|
-
pointerLens.
|
|
12067
|
-
pointerLens.
|
|
12152
|
+
pointerLens.pointerPos = event.canvasPos;
|
|
12153
|
+
pointerLens.snappedCanvasPos = event.snappedCanvasPos || event.canvasPos;
|
|
12068
12154
|
pointerLens.snapped = false;
|
|
12069
12155
|
}
|
|
12070
12156
|
this.markerDiv.style.marginLeft = `-100px`;
|
|
@@ -14704,13 +14790,14 @@ class PickResult {
|
|
|
14704
14790
|
*/
|
|
14705
14791
|
this.snappedToVertex = false;
|
|
14706
14792
|
|
|
14707
|
-
this._canvasPos = new Int16Array([0, 0]);
|
|
14708
14793
|
this._origin = new Float64Array([0, 0, 0]);
|
|
14709
14794
|
this._direction = new Float64Array([0, 0, 0]);
|
|
14710
14795
|
this._indices = new Int32Array(3);
|
|
14711
14796
|
this._localPos = new Float64Array([0, 0, 0]);
|
|
14712
14797
|
this._worldPos = new Float64Array([0, 0, 0]);
|
|
14713
14798
|
this._viewPos = new Float64Array([0, 0, 0]);
|
|
14799
|
+
this._canvasPos = new Int16Array([0, 0]);
|
|
14800
|
+
this._snappedCanvasPos = new Int16Array([0, 0]);
|
|
14714
14801
|
this._bary = new Float64Array([0, 0, 0]);
|
|
14715
14802
|
this._worldNormal = new Float64Array([0, 0, 0]);
|
|
14716
14803
|
this._uv = new Float64Array([0, 0]);
|
|
@@ -14719,7 +14806,7 @@ class PickResult {
|
|
|
14719
14806
|
}
|
|
14720
14807
|
|
|
14721
14808
|
/**
|
|
14722
|
-
* Canvas coordinates
|
|
14809
|
+
* Canvas pick coordinates.
|
|
14723
14810
|
* @property canvasPos
|
|
14724
14811
|
* @type {Number[]}
|
|
14725
14812
|
*/
|
|
@@ -14837,6 +14924,29 @@ class PickResult {
|
|
|
14837
14924
|
}
|
|
14838
14925
|
}
|
|
14839
14926
|
|
|
14927
|
+
/**
|
|
14928
|
+
* Canvas cursor coordinates, snapped when snap picking, otherwise same as {@link PickResult#pointerPos}.
|
|
14929
|
+
* @property snappedCanvasPos
|
|
14930
|
+
* @type {Number[]}
|
|
14931
|
+
*/
|
|
14932
|
+
get snappedCanvasPos() {
|
|
14933
|
+
return this._gotSnappedCanvasPos ? this._snappedCanvasPos : null;
|
|
14934
|
+
}
|
|
14935
|
+
|
|
14936
|
+
/**
|
|
14937
|
+
* @private
|
|
14938
|
+
* @param value
|
|
14939
|
+
*/
|
|
14940
|
+
set snappedCanvasPos(value) {
|
|
14941
|
+
if (value) {
|
|
14942
|
+
this._snappedCanvasPos[0] = value[0];
|
|
14943
|
+
this._snappedCanvasPos[1] = value[1];
|
|
14944
|
+
this._gotSnappedCanvasPos = true;
|
|
14945
|
+
} else {
|
|
14946
|
+
this._gotSnappedCanvasPos = false;
|
|
14947
|
+
}
|
|
14948
|
+
}
|
|
14949
|
+
|
|
14840
14950
|
/**
|
|
14841
14951
|
* Picked World-space point.
|
|
14842
14952
|
* @property worldPos
|
|
@@ -14965,6 +15075,7 @@ class PickResult {
|
|
|
14965
15075
|
this.primitive = null;
|
|
14966
15076
|
this.pickSurfacePrecision = false;
|
|
14967
15077
|
this._gotCanvasPos = false;
|
|
15078
|
+
this._gotSnappedCanvasPos = false;
|
|
14968
15079
|
this._gotOrigin = false;
|
|
14969
15080
|
this._gotDirection = false;
|
|
14970
15081
|
this._gotIndices = false;
|
|
@@ -18361,254 +18472,258 @@ const Renderer$1 = function (scene, options) {
|
|
|
18361
18472
|
* @param {number} [snapRadiusInPixels=30]
|
|
18362
18473
|
* @param {boolean} [snapToVertex=true]
|
|
18363
18474
|
* @param {boolean} [snapToEdge=true]
|
|
18364
|
-
*
|
|
18365
|
-
* @returns {
|
|
18475
|
+
* @param pickResult
|
|
18476
|
+
* @returns {PickResult}
|
|
18366
18477
|
*/
|
|
18367
|
-
this.snapPick = function (
|
|
18478
|
+
this.snapPick = (function () {
|
|
18368
18479
|
|
|
18369
|
-
|
|
18370
|
-
return this.pick({canvasPos, pickSurface: true});
|
|
18371
|
-
}
|
|
18480
|
+
const _pickResult = new PickResult();
|
|
18372
18481
|
|
|
18373
|
-
|
|
18482
|
+
return function (canvasPos, snapRadiusInPixels, snapToVertex, snapToEdge, pickResult = _pickResult) {
|
|
18374
18483
|
|
|
18375
|
-
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
frameCtx.pickZNear = scene.camera.project.near;
|
|
18379
|
-
frameCtx.pickZFar = scene.camera.project.far;
|
|
18380
|
-
|
|
18381
|
-
const vertexPickBuffer = renderBufferManager.getRenderBuffer("uniquePickColors-aabs", {
|
|
18382
|
-
depthTexture: true,
|
|
18383
|
-
size: [
|
|
18384
|
-
2 * snapRadiusInPixels + 1,
|
|
18385
|
-
2 * snapRadiusInPixels + 1,
|
|
18386
|
-
]
|
|
18387
|
-
});
|
|
18484
|
+
if (!snapToVertex && !snapToEdge) {
|
|
18485
|
+
return this.pick({canvasPos, pickSurface: true});
|
|
18486
|
+
}
|
|
18388
18487
|
|
|
18389
|
-
|
|
18390
|
-
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
18391
|
-
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight),
|
|
18392
|
-
];
|
|
18488
|
+
const resolutionScale = scene.canvas.resolutionScale;
|
|
18393
18489
|
|
|
18394
|
-
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18490
|
+
frameCtx.reset();
|
|
18491
|
+
frameCtx.backfaces = true;
|
|
18492
|
+
frameCtx.frontface = true; // "ccw"
|
|
18493
|
+
frameCtx.pickZNear = scene.camera.project.near;
|
|
18494
|
+
frameCtx.pickZFar = scene.camera.project.far;
|
|
18398
18495
|
|
|
18399
|
-
|
|
18496
|
+
snapRadiusInPixels = snapRadiusInPixels || 30;
|
|
18400
18497
|
|
|
18401
|
-
|
|
18402
|
-
|
|
18403
|
-
|
|
18404
|
-
|
|
18405
|
-
|
|
18406
|
-
|
|
18407
|
-
|
|
18408
|
-
gl.depthFunc(gl.LEQUAL);
|
|
18409
|
-
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
18410
|
-
gl.clearBufferiv(gl.COLOR, 0, new Int32Array([0, 0, 0, 0]));
|
|
18411
|
-
gl.clearBufferiv(gl.COLOR, 1, new Int32Array([0, 0, 0, 0]));
|
|
18412
|
-
gl.clearBufferuiv(gl.COLOR, 2, new Uint32Array([0, 0, 0, 0]));
|
|
18498
|
+
const vertexPickBuffer = renderBufferManager.getRenderBuffer("uniquePickColors-aabs", {
|
|
18499
|
+
depthTexture: true,
|
|
18500
|
+
size: [
|
|
18501
|
+
2 * snapRadiusInPixels + 1,
|
|
18502
|
+
2 * snapRadiusInPixels + 1,
|
|
18503
|
+
]
|
|
18504
|
+
});
|
|
18413
18505
|
|
|
18414
|
-
|
|
18415
|
-
|
|
18416
|
-
|
|
18506
|
+
frameCtx.snapVectorA = [
|
|
18507
|
+
getClipPosX(canvasPos[0] * resolutionScale, gl.drawingBufferWidth),
|
|
18508
|
+
getClipPosY(canvasPos[1] * resolutionScale, gl.drawingBufferHeight),
|
|
18509
|
+
];
|
|
18417
18510
|
|
|
18418
|
-
|
|
18419
|
-
|
|
18511
|
+
frameCtx.snapInvVectorAB = [
|
|
18512
|
+
gl.drawingBufferWidth / (2 * snapRadiusInPixels),
|
|
18513
|
+
gl.drawingBufferHeight / (2 * snapRadiusInPixels),
|
|
18514
|
+
];
|
|
18420
18515
|
|
|
18421
|
-
|
|
18422
|
-
|
|
18423
|
-
|
|
18424
|
-
|
|
18425
|
-
|
|
18426
|
-
|
|
18427
|
-
|
|
18516
|
+
// Bind and clear the snap render target
|
|
18517
|
+
|
|
18518
|
+
vertexPickBuffer.bind(gl.RGBA32I, gl.RGBA32I, gl.RGBA8UI);
|
|
18519
|
+
gl.viewport(0, 0, vertexPickBuffer.size[0], vertexPickBuffer.size[1]);
|
|
18520
|
+
gl.enable(gl.DEPTH_TEST);
|
|
18521
|
+
gl.frontFace(gl.CCW);
|
|
18522
|
+
gl.disable(gl.CULL_FACE);
|
|
18523
|
+
gl.depthMask(true);
|
|
18524
|
+
gl.disable(gl.BLEND);
|
|
18525
|
+
gl.depthFunc(gl.LEQUAL);
|
|
18526
|
+
gl.clear(gl.DEPTH_BUFFER_BIT);
|
|
18527
|
+
gl.clearBufferiv(gl.COLOR, 0, new Int32Array([0, 0, 0, 0]));
|
|
18528
|
+
gl.clearBufferiv(gl.COLOR, 1, new Int32Array([0, 0, 0, 0]));
|
|
18529
|
+
gl.clearBufferuiv(gl.COLOR, 2, new Uint32Array([0, 0, 0, 0]));
|
|
18530
|
+
|
|
18531
|
+
//////////////////////////////////
|
|
18532
|
+
// Set view and proj mats for VBO renderers
|
|
18533
|
+
///////////////////////////////////////
|
|
18534
|
+
|
|
18535
|
+
const pickViewMatrix = scene.camera.viewMatrix;
|
|
18536
|
+
const pickProjMatrix = scene.camera.projMatrix;
|
|
18537
|
+
|
|
18538
|
+
for (let type in drawableTypeInfo) {
|
|
18539
|
+
if (drawableTypeInfo.hasOwnProperty(type)) {
|
|
18540
|
+
const drawableList = drawableTypeInfo[type].drawableList;
|
|
18541
|
+
for (let i = 0, len = drawableList.length; i < len; i++) {
|
|
18542
|
+
const drawable = drawableList[i];
|
|
18543
|
+
if (drawable.setPickMatrices) { // Eg. SceneModel, which needs pre-loading into texture
|
|
18544
|
+
drawable.setPickMatrices(pickViewMatrix, pickProjMatrix);
|
|
18545
|
+
}
|
|
18428
18546
|
}
|
|
18429
18547
|
}
|
|
18430
18548
|
}
|
|
18431
|
-
}
|
|
18432
18549
|
|
|
18433
|
-
|
|
18434
|
-
|
|
18435
|
-
|
|
18550
|
+
// a) init z-buffer
|
|
18551
|
+
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1, gl.COLOR_ATTACHMENT2]);
|
|
18552
|
+
const layerParamsSurface = snapInitDepthBuf(frameCtx);
|
|
18436
18553
|
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18554
|
+
// b) snap-pick
|
|
18555
|
+
const layerParamsSnap = [];
|
|
18556
|
+
frameCtx.snapPickLayerParams = layerParamsSnap;
|
|
18440
18557
|
|
|
18441
|
-
|
|
18442
|
-
|
|
18558
|
+
gl.depthMask(false);
|
|
18559
|
+
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
|
|
18443
18560
|
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
|
|
18561
|
+
if (snapToVertex && snapToEdge) {
|
|
18562
|
+
frameCtx.snapMode = "edge";
|
|
18563
|
+
snapPickDrawSnapDepths(frameCtx);
|
|
18447
18564
|
|
|
18448
|
-
|
|
18449
|
-
|
|
18565
|
+
frameCtx.snapMode = "vertex";
|
|
18566
|
+
frameCtx.snapPickLayerNumber++;
|
|
18450
18567
|
|
|
18451
|
-
|
|
18452
|
-
|
|
18453
|
-
|
|
18568
|
+
snapPickDrawSnapDepths(frameCtx);
|
|
18569
|
+
} else {
|
|
18570
|
+
frameCtx.snapMode = snapToVertex ? "vertex" : "edge";
|
|
18454
18571
|
|
|
18455
|
-
|
|
18456
|
-
|
|
18572
|
+
snapPickDrawSnapDepths(frameCtx);
|
|
18573
|
+
}
|
|
18457
18574
|
|
|
18458
|
-
|
|
18575
|
+
gl.depthMask(true);
|
|
18459
18576
|
|
|
18460
|
-
|
|
18577
|
+
// Read and decode the snapped coordinates
|
|
18461
18578
|
|
|
18462
|
-
|
|
18463
|
-
|
|
18464
|
-
|
|
18579
|
+
const snapPickResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.INT, Int32Array, 4);
|
|
18580
|
+
const snapPickNormalResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.INT, Int32Array, 4, 1);
|
|
18581
|
+
const snapPickIdResultArray = vertexPickBuffer.readArray(gl.RGBA_INTEGER, gl.UNSIGNED_INT, Uint32Array, 4, 2);
|
|
18465
18582
|
|
|
18466
|
-
|
|
18583
|
+
vertexPickBuffer.unbind();
|
|
18467
18584
|
|
|
18468
|
-
|
|
18585
|
+
// result 1) regular hi-precision world position
|
|
18469
18586
|
|
|
18470
|
-
|
|
18471
|
-
let worldNormal = null;
|
|
18587
|
+
let worldPos = null;
|
|
18472
18588
|
|
|
18473
|
-
|
|
18474
|
-
|
|
18475
|
-
|
|
18476
|
-
|
|
18477
|
-
|
|
18478
|
-
|
|
18589
|
+
const middleX = snapRadiusInPixels;
|
|
18590
|
+
const middleY = snapRadiusInPixels;
|
|
18591
|
+
const middleIndex = (middleX * 4) + (middleY * vertexPickBuffer.size[0] * 4);
|
|
18592
|
+
const pickResultMiddleXY = snapPickResultArray.slice(middleIndex, middleIndex + 4);
|
|
18593
|
+
const pickNormalResultMiddleXY = snapPickNormalResultArray.slice(middleIndex, middleIndex + 4);
|
|
18594
|
+
const pickPickableResultMiddleXY = snapPickIdResultArray.slice(middleIndex, middleIndex + 4);
|
|
18479
18595
|
|
|
18480
|
-
|
|
18481
|
-
|
|
18482
|
-
|
|
18483
|
-
|
|
18484
|
-
|
|
18485
|
-
|
|
18486
|
-
|
|
18487
|
-
|
|
18488
|
-
|
|
18489
|
-
|
|
18490
|
-
|
|
18491
|
-
|
|
18492
|
-
|
|
18493
|
-
|
|
18494
|
-
|
|
18495
|
-
|
|
18496
|
-
|
|
18497
|
-
|
|
18498
|
-
|
|
18499
|
-
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
|
|
18503
|
-
|
|
18504
|
-
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
|
|
18515
|
-
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18534
|
-
|
|
18535
|
-
|
|
18536
|
-
|
|
18537
|
-
|
|
18538
|
-
|
|
18596
|
+
if (pickResultMiddleXY[3] !== 0) {
|
|
18597
|
+
const pickedLayerParmasSurface = layerParamsSurface[Math.abs(pickResultMiddleXY[3]) % layerParamsSurface.length];
|
|
18598
|
+
const origin = pickedLayerParmasSurface.origin;
|
|
18599
|
+
const scale = pickedLayerParmasSurface.coordinateScale;
|
|
18600
|
+
worldPos = [
|
|
18601
|
+
pickResultMiddleXY[0] * scale[0] + origin[0],
|
|
18602
|
+
pickResultMiddleXY[1] * scale[1] + origin[1],
|
|
18603
|
+
pickResultMiddleXY[2] * scale[2] + origin[2],
|
|
18604
|
+
];
|
|
18605
|
+
math.normalizeVec3([
|
|
18606
|
+
pickNormalResultMiddleXY[0] / math.MAX_INT,
|
|
18607
|
+
pickNormalResultMiddleXY[1] / math.MAX_INT,
|
|
18608
|
+
pickNormalResultMiddleXY[2] / math.MAX_INT,
|
|
18609
|
+
]);
|
|
18610
|
+
|
|
18611
|
+
const pickID =
|
|
18612
|
+
pickPickableResultMiddleXY[0]
|
|
18613
|
+
+ (pickPickableResultMiddleXY[1] << 8)
|
|
18614
|
+
+ (pickPickableResultMiddleXY[2] << 16)
|
|
18615
|
+
+ (pickPickableResultMiddleXY[3] << 24);
|
|
18616
|
+
|
|
18617
|
+
pickIDs.items[pickID];
|
|
18618
|
+
}
|
|
18619
|
+
|
|
18620
|
+
// result 2) hi-precision snapped (to vertex/edge) world position
|
|
18621
|
+
|
|
18622
|
+
let snapPickResult = [];
|
|
18623
|
+
|
|
18624
|
+
for (let i = 0; i < snapPickResultArray.length; i += 4) {
|
|
18625
|
+
if (snapPickResultArray[i + 3] > 0) {
|
|
18626
|
+
const pixelNumber = Math.floor(i / 4);
|
|
18627
|
+
const w = vertexPickBuffer.size[0];
|
|
18628
|
+
const x = pixelNumber % w - Math.floor(w / 2);
|
|
18629
|
+
const y = Math.floor(pixelNumber / w) - Math.floor(w / 2);
|
|
18630
|
+
const dist = (Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
|
|
18631
|
+
snapPickResult.push({
|
|
18632
|
+
x,
|
|
18633
|
+
y,
|
|
18634
|
+
dist,
|
|
18635
|
+
isVertex: snapToVertex && snapToEdge ? snapPickResultArray[i + 3] > layerParamsSnap.length / 2 : snapToVertex,
|
|
18636
|
+
result: [
|
|
18637
|
+
snapPickResultArray[i + 0],
|
|
18638
|
+
snapPickResultArray[i + 1],
|
|
18639
|
+
snapPickResultArray[i + 2],
|
|
18640
|
+
snapPickResultArray[i + 3],
|
|
18641
|
+
],
|
|
18642
|
+
normal: [
|
|
18643
|
+
snapPickNormalResultArray[i + 0],
|
|
18644
|
+
snapPickNormalResultArray[i + 1],
|
|
18645
|
+
snapPickNormalResultArray[i + 2],
|
|
18646
|
+
snapPickNormalResultArray[i + 3],
|
|
18647
|
+
],
|
|
18648
|
+
id: [
|
|
18649
|
+
snapPickIdResultArray[i + 0],
|
|
18650
|
+
snapPickIdResultArray[i + 1],
|
|
18651
|
+
snapPickIdResultArray[i + 2],
|
|
18652
|
+
snapPickIdResultArray[i + 3],
|
|
18653
|
+
]
|
|
18654
|
+
});
|
|
18655
|
+
}
|
|
18539
18656
|
}
|
|
18540
|
-
}
|
|
18541
18657
|
|
|
18542
|
-
|
|
18543
|
-
|
|
18544
|
-
|
|
18545
|
-
|
|
18658
|
+
let snappedWorldPos = null;
|
|
18659
|
+
let snappedWorldNormal = null;
|
|
18660
|
+
let snappedPickable = null;
|
|
18661
|
+
let snapType = null;
|
|
18546
18662
|
|
|
18547
|
-
|
|
18548
|
-
|
|
18549
|
-
|
|
18550
|
-
|
|
18551
|
-
|
|
18552
|
-
|
|
18553
|
-
|
|
18554
|
-
|
|
18555
|
-
|
|
18663
|
+
if (snapPickResult.length > 0) {
|
|
18664
|
+
// vertex snap first, then edge snap
|
|
18665
|
+
snapPickResult.sort((a, b) => {
|
|
18666
|
+
if (a.isVertex !== b.isVertex) {
|
|
18667
|
+
return a.isVertex ? -1 : 1;
|
|
18668
|
+
} else {
|
|
18669
|
+
return a.dist - b.dist;
|
|
18670
|
+
}
|
|
18671
|
+
});
|
|
18556
18672
|
|
|
18557
|
-
|
|
18558
|
-
|
|
18559
|
-
|
|
18560
|
-
|
|
18673
|
+
snapType = snapPickResult[0].isVertex ? "vertex" : "edge";
|
|
18674
|
+
const snapPick = snapPickResult[0].result;
|
|
18675
|
+
const snapPickNormal = snapPickResult[0].normal;
|
|
18676
|
+
const snapPickId = snapPickResult[0].id;
|
|
18561
18677
|
|
|
18562
|
-
|
|
18678
|
+
const pickedLayerParmas = layerParamsSnap[snapPick[3]];
|
|
18563
18679
|
|
|
18564
|
-
|
|
18565
|
-
|
|
18680
|
+
const origin = pickedLayerParmas.origin;
|
|
18681
|
+
const scale = pickedLayerParmas.coordinateScale;
|
|
18566
18682
|
|
|
18567
|
-
|
|
18568
|
-
|
|
18569
|
-
|
|
18570
|
-
|
|
18571
|
-
|
|
18683
|
+
snappedWorldNormal = math.normalizeVec3([
|
|
18684
|
+
snapPickNormal[0] / math.MAX_INT,
|
|
18685
|
+
snapPickNormal[1] / math.MAX_INT,
|
|
18686
|
+
snapPickNormal[2] / math.MAX_INT,
|
|
18687
|
+
]);
|
|
18572
18688
|
|
|
18573
|
-
|
|
18574
|
-
|
|
18575
|
-
|
|
18576
|
-
|
|
18577
|
-
|
|
18689
|
+
snappedWorldPos = [
|
|
18690
|
+
snapPick[0] * scale[0] + origin[0],
|
|
18691
|
+
snapPick[1] * scale[1] + origin[1],
|
|
18692
|
+
snapPick[2] * scale[2] + origin[2],
|
|
18693
|
+
];
|
|
18578
18694
|
|
|
18579
|
-
|
|
18695
|
+
snappedPickable = pickIDs.items[
|
|
18580
18696
|
snapPickId[0]
|
|
18581
18697
|
+ (snapPickId[1] << 8)
|
|
18582
18698
|
+ (snapPickId[2] << 16)
|
|
18583
18699
|
+ (snapPickId[3] << 24)
|
|
18584
|
-
|
|
18585
|
-
|
|
18700
|
+
];
|
|
18701
|
+
}
|
|
18586
18702
|
|
|
18587
|
-
|
|
18588
|
-
|
|
18589
|
-
|
|
18703
|
+
if (null === worldPos && null == snappedWorldPos) { // If neither regular pick or snap pick, return null
|
|
18704
|
+
return null;
|
|
18705
|
+
}
|
|
18590
18706
|
|
|
18591
|
-
|
|
18707
|
+
let snappedCanvasPos = null;
|
|
18592
18708
|
|
|
18593
|
-
|
|
18594
|
-
|
|
18595
|
-
|
|
18709
|
+
if (null !== snappedWorldPos) {
|
|
18710
|
+
snappedCanvasPos = scene.camera.projectWorldPos(snappedWorldPos);
|
|
18711
|
+
}
|
|
18596
18712
|
|
|
18597
|
-
|
|
18713
|
+
const snappedEntity = (snappedPickable && snappedPickable.delegatePickedEntity) ? snappedPickable.delegatePickedEntity() : snappedPickable;
|
|
18598
18714
|
|
|
18599
|
-
|
|
18600
|
-
snapType
|
|
18601
|
-
snappedToVertex
|
|
18602
|
-
|
|
18603
|
-
|
|
18604
|
-
|
|
18605
|
-
|
|
18606
|
-
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
entity: snappedEntity
|
|
18715
|
+
pickResult.reset();
|
|
18716
|
+
pickResult.snappedToEdge = (snapType === "edge");
|
|
18717
|
+
pickResult.snappedToVertex = (snapType === "vertex");
|
|
18718
|
+
pickResult.worldPos = snappedWorldPos;
|
|
18719
|
+
pickResult.worldNormal = snappedWorldNormal;
|
|
18720
|
+
pickResult.entity = snappedEntity;
|
|
18721
|
+
pickResult.canvasPos = canvasPos;
|
|
18722
|
+
pickResult.snappedCanvasPos = snappedCanvasPos || canvasPos;
|
|
18723
|
+
|
|
18724
|
+
return pickResult;
|
|
18610
18725
|
};
|
|
18611
|
-
};
|
|
18726
|
+
})();
|
|
18612
18727
|
|
|
18613
18728
|
function unpackDepth(depthZ) {
|
|
18614
18729
|
const vec = [depthZ[0] / 256.0, depthZ[1] / 256.0, depthZ[2] / 256.0, depthZ[3] / 256.0];
|
|
@@ -20014,23 +20129,31 @@ class Input extends Component {
|
|
|
20014
20129
|
}
|
|
20015
20130
|
});
|
|
20016
20131
|
|
|
20132
|
+
const tickifedMouseMoveFn = this.scene.tickify(
|
|
20133
|
+
() => this.fire("mousemove", this.mouseCanvasPos, true)
|
|
20134
|
+
);
|
|
20135
|
+
|
|
20017
20136
|
this.element.addEventListener("mousemove", this._mouseMoveListener = (e) => {
|
|
20018
20137
|
if (!this.enabled) {
|
|
20019
20138
|
return;
|
|
20020
20139
|
}
|
|
20021
20140
|
this._getMouseCanvasPos(e);
|
|
20022
|
-
|
|
20141
|
+
tickifedMouseMoveFn();
|
|
20023
20142
|
if (this.mouseover) {
|
|
20024
20143
|
e.preventDefault();
|
|
20025
20144
|
}
|
|
20026
20145
|
});
|
|
20027
20146
|
|
|
20147
|
+
const tickifiedMouseWheelFn = this.scene.tickify(
|
|
20148
|
+
(delta) => { this.fire("mousewheel", delta, true); }
|
|
20149
|
+
);
|
|
20150
|
+
|
|
20028
20151
|
this.element.addEventListener("wheel", this._mouseWheelListener = (e, d) => {
|
|
20029
20152
|
if (!this.enabled) {
|
|
20030
20153
|
return;
|
|
20031
20154
|
}
|
|
20032
20155
|
const delta = Math.max(-1, Math.min(1, -e.deltaY * 40));
|
|
20033
|
-
|
|
20156
|
+
tickifiedMouseWheelFn(delta);
|
|
20034
20157
|
}, {passive: true});
|
|
20035
20158
|
|
|
20036
20159
|
// mouseclicked
|
|
@@ -27854,6 +27977,11 @@ class Scene extends Component {
|
|
|
27854
27977
|
throw "Mandatory config expected: valid canvasId or canvasElement";
|
|
27855
27978
|
}
|
|
27856
27979
|
|
|
27980
|
+
/**
|
|
27981
|
+
* @type {{[key: string]: {wrapperFunc: Function, tickSubId: string}}}
|
|
27982
|
+
*/
|
|
27983
|
+
this._tickifiedFunctions = {};
|
|
27984
|
+
|
|
27857
27985
|
const transparent = (!!cfg.transparent);
|
|
27858
27986
|
const alphaDepthMask = (!!cfg.alphaDepthMask);
|
|
27859
27987
|
|
|
@@ -29603,6 +29731,9 @@ class Scene extends Component {
|
|
|
29603
29731
|
* @param {Number[]} [params.matrix] 4x4 transformation matrix to define the World-space ray origin and direction, as an alternative to ````origin```` and ````direction````.
|
|
29604
29732
|
* @param {String[]} [params.includeEntities] IDs of {@link Entity}s to restrict picking to. When given, ignores {@link Entity}s whose IDs are not in this list.
|
|
29605
29733
|
* @param {String[]} [params.excludeEntities] IDs of {@link Entity}s to ignore. When given, will pick *through* these {@link Entity}s, as if they were not there.
|
|
29734
|
+
* @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels
|
|
29735
|
+
* @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.
|
|
29736
|
+
* @param {boolean} [params.snapToEdge=true] Whether to snap to edge.
|
|
29606
29737
|
* @param {PickResult} [pickResult] Holds the results of the pick attempt. Will use the Scene's singleton PickResult if you don't supply your own.
|
|
29607
29738
|
* @returns {PickResult} Holds results of the pick attempt, returned when an {@link Entity} is picked, else null. See method comments for description.
|
|
29608
29739
|
*/
|
|
@@ -29637,14 +29768,25 @@ class Scene extends Component {
|
|
|
29637
29768
|
this._needRecompile = false;
|
|
29638
29769
|
}
|
|
29639
29770
|
|
|
29640
|
-
|
|
29771
|
+
if (params.snapToEdge || params.snapToVertex) {
|
|
29772
|
+
pickResult = this._renderer.snapPick(
|
|
29773
|
+
params.canvasPos,
|
|
29774
|
+
params.snapRadius || 30,
|
|
29775
|
+
params.snapToVertex,
|
|
29776
|
+
params.snapToEdge,
|
|
29777
|
+
pickResult
|
|
29778
|
+
);
|
|
29779
|
+
} else {
|
|
29780
|
+
pickResult = this._renderer.pick(params, pickResult);
|
|
29781
|
+
}
|
|
29641
29782
|
|
|
29642
29783
|
if (pickResult) {
|
|
29643
29784
|
if (pickResult.entity && pickResult.entity.fire) {
|
|
29644
|
-
pickResult.entity.fire("picked", pickResult); // TODO:
|
|
29785
|
+
pickResult.entity.fire("picked", pickResult); // TODO: SceneModelEntity doesn't fire events
|
|
29645
29786
|
}
|
|
29646
|
-
return pickResult;
|
|
29647
29787
|
}
|
|
29788
|
+
|
|
29789
|
+
return pickResult;
|
|
29648
29790
|
}
|
|
29649
29791
|
|
|
29650
29792
|
/**
|
|
@@ -29653,8 +29795,13 @@ class Scene extends Component {
|
|
|
29653
29795
|
* @param {Number} [params.snapRadius=30] The snap radius, in canvas pixels
|
|
29654
29796
|
* @param {boolean} [params.snapToVertex=true] Whether to snap to vertex.
|
|
29655
29797
|
* @param {boolean} [params.snapToEdge=true] Whether to snap to edge.
|
|
29798
|
+
* @deprecated
|
|
29656
29799
|
*/
|
|
29657
29800
|
snapPick(params) {
|
|
29801
|
+
if (undefined === this._warnSnapPickDeprecated) {
|
|
29802
|
+
this._warnSnapPickDeprecated = true;
|
|
29803
|
+
this.warn("Scene.snapPick() is deprecated since v2.4.2 - use Scene.pick() instead");
|
|
29804
|
+
}
|
|
29658
29805
|
return this._renderer.snapPick(
|
|
29659
29806
|
params.canvasPos,
|
|
29660
29807
|
params.snapRadius || 30,
|
|
@@ -30016,6 +30163,63 @@ class Scene extends Component {
|
|
|
30016
30163
|
return changed;
|
|
30017
30164
|
}
|
|
30018
30165
|
|
|
30166
|
+
/**
|
|
30167
|
+
* This method will "tickify" the provided `cb` function.
|
|
30168
|
+
*
|
|
30169
|
+
* This means, the function will be wrapped so:
|
|
30170
|
+
*
|
|
30171
|
+
* - it runs time-aligned to scene ticks
|
|
30172
|
+
* - it runs maximum once per scene-tick
|
|
30173
|
+
*
|
|
30174
|
+
* @param {Function} cb The function to tickify
|
|
30175
|
+
* @returns {Function)}
|
|
30176
|
+
*/
|
|
30177
|
+
tickify(cb) {
|
|
30178
|
+
const cbString = cb.toString();
|
|
30179
|
+
|
|
30180
|
+
/**
|
|
30181
|
+
* Check if the function is already tickified, and if so return the cached one.
|
|
30182
|
+
*/
|
|
30183
|
+
if (cbString in this._tickifiedFunctions) {
|
|
30184
|
+
return this._tickifiedFunctions[cbString].wrapperFunc;
|
|
30185
|
+
}
|
|
30186
|
+
|
|
30187
|
+
let alreadyRun = 0;
|
|
30188
|
+
let needToRun = 0;
|
|
30189
|
+
|
|
30190
|
+
let lastArgs;
|
|
30191
|
+
|
|
30192
|
+
/**
|
|
30193
|
+
* The provided `cb` function is replaced with a "set-dirty" function
|
|
30194
|
+
*
|
|
30195
|
+
* @type {Function}
|
|
30196
|
+
*/
|
|
30197
|
+
const wrapperFunc = function (...args) {
|
|
30198
|
+
lastArgs = args;
|
|
30199
|
+
needToRun++;
|
|
30200
|
+
};
|
|
30201
|
+
|
|
30202
|
+
/**
|
|
30203
|
+
* An each scene tick, if the "dirty-flag" is set, run the `cb` function.
|
|
30204
|
+
*
|
|
30205
|
+
* This will make it run time-aligned to the scene tick.
|
|
30206
|
+
*/
|
|
30207
|
+
const tickSubId = this.on("tick", () => {
|
|
30208
|
+
const tmp = needToRun;
|
|
30209
|
+
if (tmp > alreadyRun) {
|
|
30210
|
+
alreadyRun = tmp;
|
|
30211
|
+
cb(...lastArgs);
|
|
30212
|
+
}
|
|
30213
|
+
});
|
|
30214
|
+
|
|
30215
|
+
/**
|
|
30216
|
+
* And, store the list of subscribers.
|
|
30217
|
+
*/
|
|
30218
|
+
this._tickifiedFunctions[cbString] = { tickSubId, wrapperFunc };
|
|
30219
|
+
|
|
30220
|
+
return wrapperFunc;
|
|
30221
|
+
}
|
|
30222
|
+
|
|
30019
30223
|
/**
|
|
30020
30224
|
* Destroys this Scene.
|
|
30021
30225
|
*/
|
|
@@ -49770,18 +49974,19 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
|
|
|
49770
49974
|
this._snapping
|
|
49771
49975
|
? "hoverSnapOrSurface"
|
|
49772
49976
|
: "hoverSurface", event => {
|
|
49977
|
+
const canvasPos = event.snappedCanvasPos || event.canvasPos;
|
|
49773
49978
|
mouseHovering = true;
|
|
49774
49979
|
pointerWorldPos.set(event.worldPos);
|
|
49775
49980
|
pointerCanvasPos.set(event.canvasPos);
|
|
49776
49981
|
if (this._mouseState === MOUSE_FIRST_CLICK_EXPECTED) {
|
|
49777
|
-
this._markerDiv.style.marginLeft = `${
|
|
49778
|
-
this._markerDiv.style.marginTop = `${
|
|
49982
|
+
this._markerDiv.style.marginLeft = `${canvasPos[0] - 5}px`;
|
|
49983
|
+
this._markerDiv.style.marginTop = `${canvasPos[1] - 5}px`;
|
|
49779
49984
|
this._markerDiv.style.background = "pink";
|
|
49780
49985
|
if (event.snappedToVertex || event.snappedToEdge) {
|
|
49781
49986
|
if (this.pointerLens) {
|
|
49782
49987
|
this.pointerLens.visible = true;
|
|
49783
|
-
this.pointerLens.
|
|
49784
|
-
this.pointerLens.
|
|
49988
|
+
this.pointerLens.canvasPos = event.canvasPos;
|
|
49989
|
+
this.pointerLens.snappedCanvasPos = event.snappedCanvasPos || event.canvasPos;
|
|
49785
49990
|
this.pointerLens.snapped = true;
|
|
49786
49991
|
}
|
|
49787
49992
|
this._markerDiv.style.background = "greenyellow";
|
|
@@ -49789,8 +49994,8 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
|
|
|
49789
49994
|
} else {
|
|
49790
49995
|
if (this.pointerLens) {
|
|
49791
49996
|
this.pointerLens.visible = true;
|
|
49792
|
-
this.pointerLens.
|
|
49793
|
-
this.pointerLens.
|
|
49997
|
+
this.pointerLens.canvasPos = event.canvasPos;
|
|
49998
|
+
this.pointerLens.snappedCanvasPos = event.canvasPos;
|
|
49794
49999
|
this.pointerLens.snapped = false;
|
|
49795
50000
|
}
|
|
49796
50001
|
this._markerDiv.style.background = "pink";
|
|
@@ -49872,8 +50077,8 @@ class DistanceMeasurementsMouseControl extends DistanceMeasurementsControl {
|
|
|
49872
50077
|
: "hoverOff", event => {
|
|
49873
50078
|
if (this.pointerLens) {
|
|
49874
50079
|
this.pointerLens.visible = true;
|
|
49875
|
-
this.pointerLens.
|
|
49876
|
-
this.pointerLens.
|
|
50080
|
+
this.pointerLens.canvasPos = event.canvasPos;
|
|
50081
|
+
this.pointerLens.snappedCanvasPos = event.snappedCanvasPos || event.canvasPos;
|
|
49877
50082
|
}
|
|
49878
50083
|
mouseHovering = false;
|
|
49879
50084
|
this._markerDiv.style.marginLeft = `-100px`;
|
|
@@ -87283,29 +87488,12 @@ class PickController {
|
|
|
87283
87488
|
this._lastPickedEntityId = null;
|
|
87284
87489
|
|
|
87285
87490
|
this._needFireEvents = 0;
|
|
87286
|
-
|
|
87287
|
-
this._needToUpdate = false;
|
|
87288
|
-
|
|
87289
|
-
this._tickSub = this._scene.on("tick", () => {
|
|
87290
|
-
this.runUpdate();
|
|
87291
|
-
});
|
|
87292
|
-
}
|
|
87293
|
-
|
|
87294
|
-
update() {
|
|
87295
|
-
this._needToUpdate = true;
|
|
87296
87491
|
}
|
|
87297
87492
|
|
|
87298
87493
|
/**
|
|
87299
87494
|
* Immediately attempts a pick, if scheduled.
|
|
87300
87495
|
*/
|
|
87301
|
-
|
|
87302
|
-
|
|
87303
|
-
if (!this._needToUpdate) {
|
|
87304
|
-
return;
|
|
87305
|
-
}
|
|
87306
|
-
|
|
87307
|
-
this._needToUpdate = false;
|
|
87308
|
-
|
|
87496
|
+
update() {
|
|
87309
87497
|
if (!this._configs.pointerEnabled) {
|
|
87310
87498
|
return;
|
|
87311
87499
|
}
|
|
@@ -87322,13 +87510,13 @@ class PickController {
|
|
|
87322
87510
|
const hasHoverSurfaceSubs = this._cameraControl.hasSubs("hoverSurface");
|
|
87323
87511
|
|
|
87324
87512
|
if (this.scheduleSnapOrPick) {
|
|
87325
|
-
const snapPickResult = this._scene.
|
|
87513
|
+
const snapPickResult = this._scene.pick({
|
|
87326
87514
|
canvasPos: this.pickCursorPos,
|
|
87327
87515
|
snapRadius: this._configs.snapRadius,
|
|
87328
87516
|
snapToVertex: this._configs.snapToVertex,
|
|
87329
87517
|
snapToEdge: this._configs.snapToEdge,
|
|
87330
87518
|
});
|
|
87331
|
-
if (snapPickResult && snapPickResult.
|
|
87519
|
+
if (snapPickResult && (snapPickResult.snappedToEdge || snapPickResult.snappedToVertex)) {
|
|
87332
87520
|
this.snapPickResult = snapPickResult;
|
|
87333
87521
|
this.snappedOrPicked = true;
|
|
87334
87522
|
this._needFireEvents++;
|
|
@@ -87410,14 +87598,14 @@ class PickController {
|
|
|
87410
87598
|
|
|
87411
87599
|
fireEvents() {
|
|
87412
87600
|
|
|
87413
|
-
if (this._needFireEvents
|
|
87601
|
+
if (this._needFireEvents === 0) {
|
|
87414
87602
|
return;
|
|
87415
87603
|
}
|
|
87416
87604
|
|
|
87417
87605
|
if (this.hoveredSnappedOrSurfaceOff) {
|
|
87418
87606
|
this._cameraControl.fire("hoverSnapOrSurfaceOff", {
|
|
87419
87607
|
canvasPos: this.pickCursorPos,
|
|
87420
|
-
|
|
87608
|
+
pointerPos : this.pickCursorPos
|
|
87421
87609
|
}, true);
|
|
87422
87610
|
}
|
|
87423
87611
|
|
|
@@ -87426,9 +87614,9 @@ class PickController {
|
|
|
87426
87614
|
const pickResult = new PickResult();
|
|
87427
87615
|
pickResult.snappedToVertex = this.snapPickResult.snappedToVertex;
|
|
87428
87616
|
pickResult.snappedToEdge = this.snapPickResult.snappedToEdge;
|
|
87429
|
-
pickResult.worldPos = this.snapPickResult.
|
|
87430
|
-
pickResult.
|
|
87431
|
-
pickResult.
|
|
87617
|
+
pickResult.worldPos = this.snapPickResult.worldPos;
|
|
87618
|
+
pickResult.canvasPos = this.pickCursorPos;
|
|
87619
|
+
pickResult.snappedCanvasPos = this.snapPickResult.snappedCanvasPos;
|
|
87432
87620
|
this._cameraControl.fire("hoverSnapOrSurface", pickResult, true);
|
|
87433
87621
|
this.snapPickResult = null;
|
|
87434
87622
|
} else {
|
|
@@ -87480,10 +87668,6 @@ class PickController {
|
|
|
87480
87668
|
|
|
87481
87669
|
this._needFireEvents = 0;
|
|
87482
87670
|
}
|
|
87483
|
-
|
|
87484
|
-
destroy() {
|
|
87485
|
-
this._scene.off(this._tickSub);
|
|
87486
|
-
}
|
|
87487
87671
|
}
|
|
87488
87672
|
|
|
87489
87673
|
/**
|
|
@@ -87978,75 +88162,78 @@ class MousePickHandler {
|
|
|
87978
88162
|
}
|
|
87979
88163
|
};
|
|
87980
88164
|
|
|
87981
|
-
|
|
88165
|
+
const tickifiedMouseMoveFn = scene.tickify (
|
|
88166
|
+
this._canvasMouseMoveHandler = (e) => {
|
|
88167
|
+
if (!(configs.active && configs.pointerEnabled)) {
|
|
88168
|
+
return;
|
|
88169
|
+
}
|
|
87982
88170
|
|
|
87983
|
-
|
|
87984
|
-
|
|
87985
|
-
|
|
88171
|
+
if (leftDown || rightDown) {
|
|
88172
|
+
return;
|
|
88173
|
+
}
|
|
87986
88174
|
|
|
87987
|
-
|
|
87988
|
-
|
|
87989
|
-
|
|
88175
|
+
const hoverSubs = cameraControl.hasSubs("hover");
|
|
88176
|
+
const hoverEnterSubs = cameraControl.hasSubs("hoverEnter");
|
|
88177
|
+
const hoverOutSubs = cameraControl.hasSubs("hoverOut");
|
|
88178
|
+
const hoverOffSubs = cameraControl.hasSubs("hoverOff");
|
|
88179
|
+
const hoverSurfaceSubs = cameraControl.hasSubs("hoverSurface");
|
|
88180
|
+
const hoverSnapOrSurfaceSubs = cameraControl.hasSubs("hoverSnapOrSurface");
|
|
87990
88181
|
|
|
87991
|
-
|
|
87992
|
-
const hoverEnterSubs = cameraControl.hasSubs("hoverEnter");
|
|
87993
|
-
const hoverOutSubs = cameraControl.hasSubs("hoverOut");
|
|
87994
|
-
const hoverOffSubs = cameraControl.hasSubs("hoverOff");
|
|
87995
|
-
const hoverSurfaceSubs = cameraControl.hasSubs("hoverSurface");
|
|
87996
|
-
const hoverSnapOrSurfaceSubs = cameraControl.hasSubs("hoverSnapOrSurface");
|
|
88182
|
+
if (hoverSubs || hoverEnterSubs || hoverOutSubs || hoverOffSubs || hoverSurfaceSubs || hoverSnapOrSurfaceSubs) {
|
|
87997
88183
|
|
|
87998
|
-
|
|
88184
|
+
pickController.pickCursorPos = states.pointerCanvasPos;
|
|
88185
|
+
pickController.schedulePickEntity = true;
|
|
88186
|
+
pickController.schedulePickSurface = hoverSurfaceSubs;
|
|
88187
|
+
pickController.scheduleSnapOrPick = hoverSnapOrSurfaceSubs;
|
|
87999
88188
|
|
|
88000
|
-
|
|
88001
|
-
pickController.schedulePickEntity = true;
|
|
88002
|
-
pickController.schedulePickSurface = hoverSurfaceSubs;
|
|
88003
|
-
pickController.scheduleSnapOrPick = hoverSnapOrSurfaceSubs;
|
|
88189
|
+
pickController.update();
|
|
88004
88190
|
|
|
88005
|
-
|
|
88191
|
+
if (pickController.pickResult) {
|
|
88006
88192
|
|
|
88007
|
-
|
|
88193
|
+
if (pickController.pickResult.entity) {
|
|
88194
|
+
const pickedEntityId = pickController.pickResult.entity.id;
|
|
88008
88195
|
|
|
88009
|
-
|
|
88010
|
-
const pickedEntityId = pickController.pickResult.entity.id;
|
|
88196
|
+
if (this._lastPickedEntityId !== pickedEntityId) {
|
|
88011
88197
|
|
|
88012
|
-
|
|
88198
|
+
if (this._lastPickedEntityId !== undefined) {
|
|
88013
88199
|
|
|
88014
|
-
|
|
88200
|
+
cameraControl.fire("hoverOut", { // Hovered off an entity
|
|
88201
|
+
entity: scene.objects[this._lastPickedEntityId]
|
|
88202
|
+
}, true);
|
|
88203
|
+
}
|
|
88204
|
+
|
|
88205
|
+
cameraControl.fire("hoverEnter", pickController.pickResult, true); // Hovering over a new entity
|
|
88015
88206
|
|
|
88016
|
-
|
|
88017
|
-
entity: scene.objects[this._lastPickedEntityId]
|
|
88018
|
-
}, true);
|
|
88207
|
+
this._lastPickedEntityId = pickedEntityId;
|
|
88019
88208
|
}
|
|
88209
|
+
}
|
|
88020
88210
|
|
|
88021
|
-
|
|
88211
|
+
cameraControl.fire("hover", pickController.pickResult, true);
|
|
88022
88212
|
|
|
88023
|
-
|
|
88213
|
+
if (pickController.pickResult.worldPos || pickController.pickResult.snappedWorldPos) { // Hovering the surface of an entity
|
|
88214
|
+
cameraControl.fire("hoverSurface", pickController.pickResult, true);
|
|
88024
88215
|
}
|
|
88025
|
-
}
|
|
88026
88216
|
|
|
88027
|
-
|
|
88217
|
+
} else {
|
|
88028
88218
|
|
|
88029
|
-
|
|
88030
|
-
cameraControl.fire("hoverSurface", pickController.pickResult, true);
|
|
88031
|
-
}
|
|
88219
|
+
if (this._lastPickedEntityId !== undefined) {
|
|
88032
88220
|
|
|
88033
|
-
|
|
88221
|
+
cameraControl.fire("hoverOut", { // Hovered off an entity
|
|
88222
|
+
entity: scene.objects[this._lastPickedEntityId]
|
|
88223
|
+
}, true);
|
|
88034
88224
|
|
|
88035
|
-
|
|
88225
|
+
this._lastPickedEntityId = undefined;
|
|
88226
|
+
}
|
|
88036
88227
|
|
|
88037
|
-
cameraControl.fire("
|
|
88038
|
-
|
|
88228
|
+
cameraControl.fire("hoverOff", { // Not hovering on any entity
|
|
88229
|
+
canvasPos: pickController.pickCursorPos
|
|
88039
88230
|
}, true);
|
|
88040
|
-
|
|
88041
|
-
this._lastPickedEntityId = undefined;
|
|
88042
88231
|
}
|
|
88043
|
-
|
|
88044
|
-
cameraControl.fire("hoverOff", { // Not hovering on any entity
|
|
88045
|
-
canvasPos: pickController.pickCursorPos
|
|
88046
|
-
}, true);
|
|
88047
88232
|
}
|
|
88048
88233
|
}
|
|
88049
|
-
|
|
88234
|
+
);
|
|
88235
|
+
|
|
88236
|
+
canvas.addEventListener("mousemove", tickifiedMouseMoveFn);
|
|
88050
88237
|
|
|
88051
88238
|
canvas.addEventListener('mousedown', this._canvasMouseDownHandler = (e) => {
|
|
88052
88239
|
|