@xeokit/xeokit-sdk 2.4.2-beta-14 → 2.4.2-beta-15
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 +206 -69
- package/dist/xeokit-sdk.es.js +206 -69
- package/dist/xeokit-sdk.es5.js +318 -209
- package/dist/xeokit-sdk.min.cjs.js +2 -2
- 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/collision/ObjectsKdTree3.js +2 -0
- package/src/viewer/scene/CameraControl/lib/controllers/PickController.js +1 -22
- 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 +62 -0
package/dist/xeokit-sdk.es.js
CHANGED
|
@@ -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.
|
|
@@ -20014,23 +20099,31 @@ class Input extends Component {
|
|
|
20014
20099
|
}
|
|
20015
20100
|
});
|
|
20016
20101
|
|
|
20102
|
+
const tickifedMouseMoveFn = this.scene.tickify(
|
|
20103
|
+
() => this.fire("mousemove", this.mouseCanvasPos, true)
|
|
20104
|
+
);
|
|
20105
|
+
|
|
20017
20106
|
this.element.addEventListener("mousemove", this._mouseMoveListener = (e) => {
|
|
20018
20107
|
if (!this.enabled) {
|
|
20019
20108
|
return;
|
|
20020
20109
|
}
|
|
20021
20110
|
this._getMouseCanvasPos(e);
|
|
20022
|
-
|
|
20111
|
+
tickifedMouseMoveFn();
|
|
20023
20112
|
if (this.mouseover) {
|
|
20024
20113
|
e.preventDefault();
|
|
20025
20114
|
}
|
|
20026
20115
|
});
|
|
20027
20116
|
|
|
20117
|
+
const tickifiedMouseWheelFn = this.scene.tickify(
|
|
20118
|
+
(delta) => { this.fire("mousewheel", delta, true); }
|
|
20119
|
+
);
|
|
20120
|
+
|
|
20028
20121
|
this.element.addEventListener("wheel", this._mouseWheelListener = (e, d) => {
|
|
20029
20122
|
if (!this.enabled) {
|
|
20030
20123
|
return;
|
|
20031
20124
|
}
|
|
20032
20125
|
const delta = Math.max(-1, Math.min(1, -e.deltaY * 40));
|
|
20033
|
-
|
|
20126
|
+
tickifiedMouseWheelFn(delta);
|
|
20034
20127
|
}, {passive: true});
|
|
20035
20128
|
|
|
20036
20129
|
// mouseclicked
|
|
@@ -27854,6 +27947,11 @@ class Scene extends Component {
|
|
|
27854
27947
|
throw "Mandatory config expected: valid canvasId or canvasElement";
|
|
27855
27948
|
}
|
|
27856
27949
|
|
|
27950
|
+
/**
|
|
27951
|
+
* @type {{[key: string]: {wrapperFunc: Function, tickSubId: string}}}
|
|
27952
|
+
*/
|
|
27953
|
+
this._tickifiedFunctions = {};
|
|
27954
|
+
|
|
27857
27955
|
const transparent = (!!cfg.transparent);
|
|
27858
27956
|
const alphaDepthMask = (!!cfg.alphaDepthMask);
|
|
27859
27957
|
|
|
@@ -30016,6 +30114,63 @@ class Scene extends Component {
|
|
|
30016
30114
|
return changed;
|
|
30017
30115
|
}
|
|
30018
30116
|
|
|
30117
|
+
/**
|
|
30118
|
+
* This method will "tickify" the provided `cb` function.
|
|
30119
|
+
*
|
|
30120
|
+
* This means, the function will be wrapped so:
|
|
30121
|
+
*
|
|
30122
|
+
* - it runs time-aligned to scene ticks
|
|
30123
|
+
* - it runs maximum once per scene-tick
|
|
30124
|
+
*
|
|
30125
|
+
* @param {Function} cb The function to tickify
|
|
30126
|
+
* @returns {Function)}
|
|
30127
|
+
*/
|
|
30128
|
+
tickify(cb) {
|
|
30129
|
+
const cbString = cb.toString();
|
|
30130
|
+
|
|
30131
|
+
/**
|
|
30132
|
+
* Check if the function is already tickified, and if so return the cached one.
|
|
30133
|
+
*/
|
|
30134
|
+
if (cbString in this._tickifiedFunctions) {
|
|
30135
|
+
return this._tickifiedFunctions[cbString].wrapperFunc;
|
|
30136
|
+
}
|
|
30137
|
+
|
|
30138
|
+
let alreadyRun = 0;
|
|
30139
|
+
let needToRun = 0;
|
|
30140
|
+
|
|
30141
|
+
let lastArgs;
|
|
30142
|
+
|
|
30143
|
+
/**
|
|
30144
|
+
* The provided `cb` function is replaced with a "set-dirty" function
|
|
30145
|
+
*
|
|
30146
|
+
* @type {Function}
|
|
30147
|
+
*/
|
|
30148
|
+
const wrapperFunc = function (...args) {
|
|
30149
|
+
lastArgs = args;
|
|
30150
|
+
needToRun++;
|
|
30151
|
+
};
|
|
30152
|
+
|
|
30153
|
+
/**
|
|
30154
|
+
* An each scene tick, if the "dirty-flag" is set, run the `cb` function.
|
|
30155
|
+
*
|
|
30156
|
+
* This will make it run time-aligned to the scene tick.
|
|
30157
|
+
*/
|
|
30158
|
+
const tickSubId = this.on("tick", () => {
|
|
30159
|
+
const tmp = needToRun;
|
|
30160
|
+
if (tmp > alreadyRun) {
|
|
30161
|
+
alreadyRun = tmp;
|
|
30162
|
+
cb(...lastArgs);
|
|
30163
|
+
}
|
|
30164
|
+
});
|
|
30165
|
+
|
|
30166
|
+
/**
|
|
30167
|
+
* And, store the list of subscribers.
|
|
30168
|
+
*/
|
|
30169
|
+
this._tickifiedFunctions[cbString] = { tickSubId, wrapperFunc };
|
|
30170
|
+
|
|
30171
|
+
return wrapperFunc;
|
|
30172
|
+
}
|
|
30173
|
+
|
|
30019
30174
|
/**
|
|
30020
30175
|
* Destroys this Scene.
|
|
30021
30176
|
*/
|
|
@@ -87283,29 +87438,12 @@ class PickController {
|
|
|
87283
87438
|
this._lastPickedEntityId = null;
|
|
87284
87439
|
|
|
87285
87440
|
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
87441
|
}
|
|
87297
87442
|
|
|
87298
87443
|
/**
|
|
87299
87444
|
* Immediately attempts a pick, if scheduled.
|
|
87300
87445
|
*/
|
|
87301
|
-
|
|
87302
|
-
|
|
87303
|
-
if (!this._needToUpdate) {
|
|
87304
|
-
return;
|
|
87305
|
-
}
|
|
87306
|
-
|
|
87307
|
-
this._needToUpdate = false;
|
|
87308
|
-
|
|
87446
|
+
update() {
|
|
87309
87447
|
if (!this._configs.pointerEnabled) {
|
|
87310
87448
|
return;
|
|
87311
87449
|
}
|
|
@@ -87480,10 +87618,6 @@ class PickController {
|
|
|
87480
87618
|
|
|
87481
87619
|
this._needFireEvents = 0;
|
|
87482
87620
|
}
|
|
87483
|
-
|
|
87484
|
-
destroy() {
|
|
87485
|
-
this._scene.off(this._tickSub);
|
|
87486
|
-
}
|
|
87487
87621
|
}
|
|
87488
87622
|
|
|
87489
87623
|
/**
|
|
@@ -87978,75 +88112,78 @@ class MousePickHandler {
|
|
|
87978
88112
|
}
|
|
87979
88113
|
};
|
|
87980
88114
|
|
|
87981
|
-
|
|
88115
|
+
const tickifiedMouseMoveFn = scene.tickify (
|
|
88116
|
+
this._canvasMouseMoveHandler = (e) => {
|
|
88117
|
+
if (!(configs.active && configs.pointerEnabled)) {
|
|
88118
|
+
return;
|
|
88119
|
+
}
|
|
87982
88120
|
|
|
87983
|
-
|
|
87984
|
-
|
|
87985
|
-
|
|
88121
|
+
if (leftDown || rightDown) {
|
|
88122
|
+
return;
|
|
88123
|
+
}
|
|
87986
88124
|
|
|
87987
|
-
|
|
87988
|
-
|
|
87989
|
-
|
|
88125
|
+
const hoverSubs = cameraControl.hasSubs("hover");
|
|
88126
|
+
const hoverEnterSubs = cameraControl.hasSubs("hoverEnter");
|
|
88127
|
+
const hoverOutSubs = cameraControl.hasSubs("hoverOut");
|
|
88128
|
+
const hoverOffSubs = cameraControl.hasSubs("hoverOff");
|
|
88129
|
+
const hoverSurfaceSubs = cameraControl.hasSubs("hoverSurface");
|
|
88130
|
+
const hoverSnapOrSurfaceSubs = cameraControl.hasSubs("hoverSnapOrSurface");
|
|
87990
88131
|
|
|
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");
|
|
88132
|
+
if (hoverSubs || hoverEnterSubs || hoverOutSubs || hoverOffSubs || hoverSurfaceSubs || hoverSnapOrSurfaceSubs) {
|
|
87997
88133
|
|
|
87998
|
-
|
|
88134
|
+
pickController.pickCursorPos = states.pointerCanvasPos;
|
|
88135
|
+
pickController.schedulePickEntity = true;
|
|
88136
|
+
pickController.schedulePickSurface = hoverSurfaceSubs;
|
|
88137
|
+
pickController.scheduleSnapOrPick = hoverSnapOrSurfaceSubs;
|
|
87999
88138
|
|
|
88000
|
-
|
|
88001
|
-
pickController.schedulePickEntity = true;
|
|
88002
|
-
pickController.schedulePickSurface = hoverSurfaceSubs;
|
|
88003
|
-
pickController.scheduleSnapOrPick = hoverSnapOrSurfaceSubs;
|
|
88139
|
+
pickController.update();
|
|
88004
88140
|
|
|
88005
|
-
|
|
88141
|
+
if (pickController.pickResult) {
|
|
88006
88142
|
|
|
88007
|
-
|
|
88143
|
+
if (pickController.pickResult.entity) {
|
|
88144
|
+
const pickedEntityId = pickController.pickResult.entity.id;
|
|
88145
|
+
|
|
88146
|
+
if (this._lastPickedEntityId !== pickedEntityId) {
|
|
88008
88147
|
|
|
88009
|
-
|
|
88010
|
-
const pickedEntityId = pickController.pickResult.entity.id;
|
|
88148
|
+
if (this._lastPickedEntityId !== undefined) {
|
|
88011
88149
|
|
|
88012
|
-
|
|
88150
|
+
cameraControl.fire("hoverOut", { // Hovered off an entity
|
|
88151
|
+
entity: scene.objects[this._lastPickedEntityId]
|
|
88152
|
+
}, true);
|
|
88153
|
+
}
|
|
88013
88154
|
|
|
88014
|
-
|
|
88155
|
+
cameraControl.fire("hoverEnter", pickController.pickResult, true); // Hovering over a new entity
|
|
88015
88156
|
|
|
88016
|
-
|
|
88017
|
-
entity: scene.objects[this._lastPickedEntityId]
|
|
88018
|
-
}, true);
|
|
88157
|
+
this._lastPickedEntityId = pickedEntityId;
|
|
88019
88158
|
}
|
|
88159
|
+
}
|
|
88020
88160
|
|
|
88021
|
-
|
|
88161
|
+
cameraControl.fire("hover", pickController.pickResult, true);
|
|
88022
88162
|
|
|
88023
|
-
|
|
88163
|
+
if (pickController.pickResult.worldPos || pickController.pickResult.snappedWorldPos) { // Hovering the surface of an entity
|
|
88164
|
+
cameraControl.fire("hoverSurface", pickController.pickResult, true);
|
|
88024
88165
|
}
|
|
88025
|
-
}
|
|
88026
88166
|
|
|
88027
|
-
|
|
88167
|
+
} else {
|
|
88028
88168
|
|
|
88029
|
-
|
|
88030
|
-
cameraControl.fire("hoverSurface", pickController.pickResult, true);
|
|
88031
|
-
}
|
|
88169
|
+
if (this._lastPickedEntityId !== undefined) {
|
|
88032
88170
|
|
|
88033
|
-
|
|
88171
|
+
cameraControl.fire("hoverOut", { // Hovered off an entity
|
|
88172
|
+
entity: scene.objects[this._lastPickedEntityId]
|
|
88173
|
+
}, true);
|
|
88034
88174
|
|
|
88035
|
-
|
|
88175
|
+
this._lastPickedEntityId = undefined;
|
|
88176
|
+
}
|
|
88036
88177
|
|
|
88037
|
-
cameraControl.fire("
|
|
88038
|
-
|
|
88178
|
+
cameraControl.fire("hoverOff", { // Not hovering on any entity
|
|
88179
|
+
canvasPos: pickController.pickCursorPos
|
|
88039
88180
|
}, true);
|
|
88040
|
-
|
|
88041
|
-
this._lastPickedEntityId = undefined;
|
|
88042
88181
|
}
|
|
88043
|
-
|
|
88044
|
-
cameraControl.fire("hoverOff", { // Not hovering on any entity
|
|
88045
|
-
canvasPos: pickController.pickCursorPos
|
|
88046
|
-
}, true);
|
|
88047
88182
|
}
|
|
88048
88183
|
}
|
|
88049
|
-
|
|
88184
|
+
);
|
|
88185
|
+
|
|
88186
|
+
canvas.addEventListener("mousemove", tickifiedMouseMoveFn);
|
|
88050
88187
|
|
|
88051
88188
|
canvas.addEventListener('mousedown', this._canvasMouseDownHandler = (e) => {
|
|
88052
88189
|
|