@xeokit/xeokit-sdk 2.6.9 → 2.6.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/web-ifc.wasm +0 -0
- package/dist/xeokit-sdk.cjs.js +1164 -134
- package/dist/xeokit-sdk.es.js +1163 -135
- package/dist/xeokit-sdk.es5.js +521 -53
- 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/plugins/AngleMeasurementsPlugin/AngleMeasurementsControl.js +10 -0
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.js +9 -0
- package/src/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.js +9 -0
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.js +182 -42
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsControl.js +11 -0
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.js +11 -0
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsPlugin.js +18 -1
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.js +15 -0
- package/src/plugins/DotBIMLoaderPlugin/DotBIMDefaultDataSource.js +29 -0
- package/src/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.js +536 -0
- package/src/plugins/DotBIMLoaderPlugin/index.js +2 -0
- package/src/plugins/GLTFLoaderPlugin/GLTFLoaderPlugin.js +74 -0
- package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +53 -58
- package/src/plugins/LASLoaderPlugin/LASLoaderPlugin.js +59 -2
- package/src/plugins/index.js +2 -1
- package/src/plugins/lib/html/Dot.js +38 -6
- package/src/plugins/lib/html/Label.js +48 -7
- package/src/plugins/lib/html/Wire.js +38 -6
- package/src/viewer/Viewer.js +1 -1
- package/src/viewer/scene/CameraControl/lib/handlers/MouseMiscHandler.js +2 -2
- package/src/viewer/scene/marker/Marker.js +3 -3
- package/src/viewer/scene/model/SceneModel.js +17 -9
- package/src/viewer/utils/os.js +11 -0
- package/types/plugins/AngleMeasurementsPlugin/AngleMeasurementsControl.d.ts +7 -0
- package/types/plugins/AngleMeasurementsPlugin/AngleMeasurementsMouseControl.d.ts +8 -0
- package/types/plugins/AngleMeasurementsPlugin/AngleMeasurementsTouchControl.d.ts +8 -0
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.d.ts +70 -0
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsControl.d.ts +7 -0
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsMouseControl.d.ts +8 -0
- package/types/plugins/DistanceMeasurementsPlugin/DistanceMeasurementsTouchControl.d.ts +8 -0
|
@@ -141,6 +141,7 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok) {
|
|
|
141
141
|
}).then((gltfData) => {
|
|
142
142
|
const ctx = {
|
|
143
143
|
src: src,
|
|
144
|
+
entityId: options.entityId,
|
|
144
145
|
metaModelCorrections: metaModelJSON ? getMetaModelCorrections(metaModelJSON) : null,
|
|
145
146
|
loadBuffer: options.loadBuffer,
|
|
146
147
|
basePath: options.basePath,
|
|
@@ -586,29 +587,9 @@ function loadNode(ctx, node, depth, matrix) {
|
|
|
586
587
|
meshCfg.origin = origin;
|
|
587
588
|
}
|
|
588
589
|
|
|
589
|
-
// if (createEntity) {
|
|
590
|
-
// if (createEntity.colorize) {
|
|
591
|
-
// meshCfg.color = createEntity.colorize;
|
|
592
|
-
// }
|
|
593
|
-
// if (createEntity.opacity !== undefined && createEntity.opacity !== null) {
|
|
594
|
-
// meshCfg.opacity = createEntity.opacity;
|
|
595
|
-
// }
|
|
596
|
-
// }
|
|
597
|
-
|
|
598
590
|
sceneModel.createMesh(meshCfg);
|
|
599
591
|
deferredMeshIds.push(meshCfg.id);
|
|
600
592
|
}
|
|
601
|
-
// if (createEntity) {
|
|
602
|
-
// sceneModel.createEntity(utils.apply(createEntity, {
|
|
603
|
-
// meshIds: deferredMeshIds,
|
|
604
|
-
// isObject: true
|
|
605
|
-
// }));
|
|
606
|
-
// } else {
|
|
607
|
-
// sceneModel.createEntity({
|
|
608
|
-
// meshIds: deferredMeshIds,
|
|
609
|
-
// isObject: true
|
|
610
|
-
// });
|
|
611
|
-
// }
|
|
612
593
|
}
|
|
613
594
|
}
|
|
614
595
|
|
|
@@ -622,48 +603,62 @@ function loadNode(ctx, node, depth, matrix) {
|
|
|
622
603
|
|
|
623
604
|
// Post-order visit scene node
|
|
624
605
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
606
|
+
if (ctx.entityId) {
|
|
607
|
+
if (depth ===0) {
|
|
608
|
+
sceneModel.createEntity({
|
|
609
|
+
id: ctx.entityId,
|
|
610
|
+
meshIds: deferredMeshIds,
|
|
611
|
+
isObject: true
|
|
612
|
+
});
|
|
613
|
+
deferredMeshIds.length = 0;
|
|
629
614
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
//
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
615
|
+
} else {
|
|
616
|
+
const nodeName = node.name;
|
|
617
|
+
if (((nodeName !== undefined && nodeName !== null) || depth === 0) && deferredMeshIds.length > 0) {
|
|
618
|
+
if (nodeName === undefined || nodeName === null) {
|
|
619
|
+
ctx.log(`Warning: 'name' properties not found on glTF scene nodes - will randomly-generate object IDs in XKT`);
|
|
620
|
+
}
|
|
621
|
+
let entityId = nodeName; // Fall back on generated ID when `name` not found on glTF scene node(s)
|
|
622
|
+
// if (!!entityId && sceneModel.entities[entityId]) {
|
|
623
|
+
// ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${nodeName} - will randomly-generating an object ID in XKT`);
|
|
624
|
+
// }
|
|
625
|
+
// while (!entityId || sceneModel.entities[entityId]) {
|
|
626
|
+
// entityId = "entity-" + ctx.nextId++;
|
|
627
|
+
// }
|
|
628
|
+
if (ctx.metaModelCorrections) {
|
|
629
|
+
// Merging meshes into XKTObjects that map to metaobjects
|
|
630
|
+
const rootMetaObject = ctx.metaModelCorrections.eachChildRoot[entityId];
|
|
631
|
+
if (rootMetaObject) {
|
|
632
|
+
const rootMetaObjectStats = ctx.metaModelCorrections.eachRootStats[rootMetaObject.id];
|
|
633
|
+
rootMetaObjectStats.countChildren++;
|
|
634
|
+
if (rootMetaObjectStats.countChildren >= rootMetaObjectStats.numChildren) {
|
|
635
|
+
sceneModel.createEntity({
|
|
636
|
+
id: rootMetaObject.id,
|
|
637
|
+
meshIds: deferredMeshIds,
|
|
638
|
+
isObject: true
|
|
639
|
+
});
|
|
640
|
+
deferredMeshIds.length = 0;
|
|
641
|
+
}
|
|
642
|
+
} else {
|
|
643
|
+
const metaObject = ctx.metaModelCorrections.metaObjectsMap[entityId];
|
|
644
|
+
if (metaObject) {
|
|
645
|
+
sceneModel.createEntity({
|
|
646
|
+
id: entityId,
|
|
647
|
+
meshIds: deferredMeshIds,
|
|
648
|
+
isObject: true
|
|
649
|
+
});
|
|
650
|
+
deferredMeshIds.length = 0;
|
|
651
|
+
}
|
|
649
652
|
}
|
|
650
653
|
} else {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
}
|
|
654
|
+
// Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
|
|
655
|
+
sceneModel.createEntity({
|
|
656
|
+
id: entityId,
|
|
657
|
+
meshIds: deferredMeshIds,
|
|
658
|
+
isObject: true
|
|
659
|
+
});
|
|
660
|
+
deferredMeshIds.length = 0;
|
|
659
661
|
}
|
|
660
|
-
} else {
|
|
661
|
-
// Create an XKTObject from the meshes at each named glTF node, don't care about metaobjects
|
|
662
|
-
sceneModel.createEntity({
|
|
663
|
-
id: entityId,
|
|
664
|
-
meshIds: deferredMeshIds
|
|
665
|
-
});
|
|
666
|
-
deferredMeshIds.length = 0;
|
|
667
662
|
}
|
|
668
663
|
}
|
|
669
664
|
}
|
|
@@ -143,6 +143,60 @@ const MAX_VERTICES = 500000; // TODO: Rough estimate
|
|
|
143
143
|
* });
|
|
144
144
|
* ````
|
|
145
145
|
*
|
|
146
|
+
* ## Showing a LAS/LAZ model in TreeViewPlugin
|
|
147
|
+
*
|
|
148
|
+
* We can use the `load()` method's `elementId` parameter
|
|
149
|
+
* to make LASLoaderPlugin load the entire model into a single Entity that gets this ID.
|
|
150
|
+
*
|
|
151
|
+
* In conjunction with that parameter, we can then use the `load()` method's `metaModelJSON` parameter to create a MetaModel that
|
|
152
|
+
* contains a MetaObject that corresponds to that Entity.
|
|
153
|
+
*
|
|
154
|
+
* When we've done that, then xeokit's {@link TreeViewPlugin} is able to have a node that represents the model and controls
|
|
155
|
+
* the visibility of that Entity (ie. to control the visibility of the entire model).
|
|
156
|
+
*
|
|
157
|
+
* The snippet below shows how this is done.
|
|
158
|
+
*
|
|
159
|
+
* ````javascript
|
|
160
|
+
* import {Viewer, LASLoaderPlugin, NavCubePlugin, TreeViewPlugin} from "../../dist/xeokit-sdk.es.js";
|
|
161
|
+
*
|
|
162
|
+
* const viewer = new Viewer({
|
|
163
|
+
* canvasId: "myCanvas",
|
|
164
|
+
* transparent: true
|
|
165
|
+
* });
|
|
166
|
+
*
|
|
167
|
+
* new TreeViewPlugin(viewer, {
|
|
168
|
+
* containerElement: document.getElementById("treeViewContainer"),
|
|
169
|
+
* hierarchy: "containment"
|
|
170
|
+
* });
|
|
171
|
+
*
|
|
172
|
+
* const lasLoader = new LASLoaderPlugin(viewer);
|
|
173
|
+
*
|
|
174
|
+
* const sceneModel = lasLoader.load({ // Creates a SceneModel with ID "myScanModel"
|
|
175
|
+
* id: "myScanModel",
|
|
176
|
+
* src: "../../assets/models/las/Nalls_Pumpkin_Hill.laz",
|
|
177
|
+
* rotation: [-90, 0, 0],
|
|
178
|
+
*
|
|
179
|
+
* entityId: "3toKckUfH2jBmd$7uhJHa4", // Creates an Entity with this ID
|
|
180
|
+
*
|
|
181
|
+
* metaModelJSON: { // Creates a MetaModel with ID "myScanModel"
|
|
182
|
+
* "metaObjects": [
|
|
183
|
+
* {
|
|
184
|
+
* "id": "3toKckUfH2jBmd$7uhJHa6", // Creates this MetaObject with this ID
|
|
185
|
+
* "name": "My Project",
|
|
186
|
+
* "type": "Default",
|
|
187
|
+
* "parent": null
|
|
188
|
+
* },
|
|
189
|
+
* {
|
|
190
|
+
* "id": "3toKckUfH2jBmd$7uhJHa4", // Creates this MetaObject with this ID
|
|
191
|
+
* "name": "My Scan",
|
|
192
|
+
* "type": "Default",
|
|
193
|
+
* "parent": "3toKckUfH2jBmd$7uhJHa6"
|
|
194
|
+
* }
|
|
195
|
+
* ]
|
|
196
|
+
* }
|
|
197
|
+
* });
|
|
198
|
+
* ````
|
|
199
|
+
*
|
|
146
200
|
* @class LASLoaderPlugin
|
|
147
201
|
* @since 2.0.17
|
|
148
202
|
*/
|
|
@@ -493,7 +547,7 @@ class LASLoaderPlugin extends Plugin {
|
|
|
493
547
|
}
|
|
494
548
|
*/
|
|
495
549
|
|
|
496
|
-
const pointsObjectId = math.createUUID();
|
|
550
|
+
const pointsObjectId = params.entityId || math.createUUID();
|
|
497
551
|
|
|
498
552
|
sceneModel.createEntity({
|
|
499
553
|
id: pointsObjectId,
|
|
@@ -503,7 +557,10 @@ class LASLoaderPlugin extends Plugin {
|
|
|
503
557
|
|
|
504
558
|
sceneModel.finalize();
|
|
505
559
|
|
|
506
|
-
if (params.
|
|
560
|
+
if (params.metaModelJSON) {
|
|
561
|
+
const metaModelId = sceneModel.id;
|
|
562
|
+
this.viewer.metaScene.createMetaModel(metaModelId, params.metaModelJSON, options);
|
|
563
|
+
} else if (params.loadMetadata !== false) {
|
|
507
564
|
const rootMetaObjectId = math.createUUID();
|
|
508
565
|
const metadata = {
|
|
509
566
|
projectId: "",
|
package/src/plugins/index.js
CHANGED
|
@@ -18,4 +18,5 @@ export * from "./XKTLoaderPlugin/index.js";
|
|
|
18
18
|
export * from "./XML3DLoaderPlugin/index.js";
|
|
19
19
|
export * from "./WebIFCLoaderPlugin/index.js";
|
|
20
20
|
export * from "./LASLoaderPlugin/index.js";
|
|
21
|
-
export * from "./CityJSONLoaderPlugin/index.js";
|
|
21
|
+
export * from "./CityJSONLoaderPlugin/index.js";
|
|
22
|
+
export * from "./DotBIMLoaderPlugin/index.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { os } from "../../../viewer/utils/os.js";
|
|
1
2
|
/** @private */
|
|
2
3
|
class Dot {
|
|
3
4
|
|
|
@@ -97,11 +98,42 @@ class Dot {
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
if (cfg.onContextMenu) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
if(os.isIphoneSafari()){
|
|
102
|
+
dotClickable.addEventListener('touchstart', (event) => {
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
if(this._timeout){
|
|
105
|
+
clearTimeout(this._timeout);
|
|
106
|
+
this._timeout = null;
|
|
107
|
+
}
|
|
108
|
+
this._timeout = setTimeout(() => {
|
|
109
|
+
event.clientX = event.touches[0].clientX;
|
|
110
|
+
event.clientY = event.touches[0].clientY;
|
|
111
|
+
cfg.onContextMenu(event, this);
|
|
112
|
+
clearTimeout(this._timeout);
|
|
113
|
+
this._timeout = null;
|
|
114
|
+
}, 500);
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
dotClickable.addEventListener('touchend', (event) => {
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
//stops short touches from calling the timeout
|
|
120
|
+
if(this._timeout) {
|
|
121
|
+
clearTimeout(this._timeout);
|
|
122
|
+
this._timeout = null;
|
|
123
|
+
}
|
|
124
|
+
} )
|
|
125
|
+
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
dotClickable.addEventListener('contextmenu', (event) => {
|
|
129
|
+
console.log(event);
|
|
130
|
+
cfg.onContextMenu(event, this);
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
event.stopPropagation();
|
|
133
|
+
console.log("Label context menu")
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
105
137
|
}
|
|
106
138
|
|
|
107
139
|
this.setPos(cfg.x || 0, cfg.y || 0);
|
|
@@ -150,7 +182,7 @@ class Dot {
|
|
|
150
182
|
}
|
|
151
183
|
|
|
152
184
|
setClickable(clickable) {
|
|
153
|
-
this._dotClickable.style["pointer-events"] = (
|
|
185
|
+
this._dotClickable.style["pointer-events"] = (clickable) ? "all" : "none";
|
|
154
186
|
}
|
|
155
187
|
|
|
156
188
|
setHighlighted(highlighted) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { os } from "../../../viewer/utils/os.js";
|
|
1
2
|
/** @private */
|
|
2
3
|
class Label {
|
|
3
4
|
|
|
@@ -13,6 +14,7 @@ class Label {
|
|
|
13
14
|
|
|
14
15
|
this._label = document.createElement('div');
|
|
15
16
|
this._label.className += this._label.className ? ' viewer-ruler-label' : 'viewer-ruler-label';
|
|
17
|
+
this._timeout = null;
|
|
16
18
|
|
|
17
19
|
var label = this._label;
|
|
18
20
|
var style = label.style;
|
|
@@ -84,12 +86,42 @@ class Label {
|
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
if (cfg.onContextMenu) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
if(os.isIphoneSafari()){
|
|
90
|
+
label.addEventListener('touchstart', (event) => {
|
|
91
|
+
event.preventDefault();
|
|
92
|
+
if(this._timeout){
|
|
93
|
+
clearTimeout(this._timeout);
|
|
94
|
+
this._timeout = null;
|
|
95
|
+
}
|
|
96
|
+
this._timeout = setTimeout(() => {
|
|
97
|
+
event.clientX = event.touches[0].clientX;
|
|
98
|
+
event.clientY = event.touches[0].clientY;
|
|
99
|
+
cfg.onContextMenu(event, this);
|
|
100
|
+
clearTimeout(this._timeout);
|
|
101
|
+
this._timeout = null;
|
|
102
|
+
}, 500);
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
label.addEventListener('touchend', (event) => {
|
|
106
|
+
event.preventDefault();
|
|
107
|
+
//stops short touches from calling the timeout
|
|
108
|
+
if(this._timeout) {
|
|
109
|
+
clearTimeout(this._timeout);
|
|
110
|
+
this._timeout = null;
|
|
111
|
+
}
|
|
112
|
+
} )
|
|
113
|
+
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
label.addEventListener('contextmenu', (event) => {
|
|
117
|
+
console.log(event);
|
|
118
|
+
cfg.onContextMenu(event, this);
|
|
119
|
+
event.preventDefault();
|
|
120
|
+
event.stopPropagation();
|
|
121
|
+
console.log("Label context menu")
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
93
125
|
}
|
|
94
126
|
}
|
|
95
127
|
|
|
@@ -164,7 +196,14 @@ class Label {
|
|
|
164
196
|
}
|
|
165
197
|
|
|
166
198
|
setClickable(clickable) {
|
|
167
|
-
this._label.style["pointer-events"] = (
|
|
199
|
+
this._label.style["pointer-events"] = (clickable) ? "all" : "none";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
setPrefix(prefix) {
|
|
203
|
+
if(this._prefix === prefix){
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
this._prefix = prefix;
|
|
168
207
|
}
|
|
169
208
|
|
|
170
209
|
destroy() {
|
|
@@ -172,6 +211,8 @@ class Label {
|
|
|
172
211
|
this._label.parentElement.removeChild(this._label);
|
|
173
212
|
}
|
|
174
213
|
}
|
|
214
|
+
|
|
215
|
+
|
|
175
216
|
}
|
|
176
217
|
|
|
177
218
|
export {Label};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { os } from "../../../viewer/utils/os.js";
|
|
1
2
|
/** @private */
|
|
2
3
|
class Wire {
|
|
3
4
|
|
|
@@ -114,11 +115,42 @@ class Wire {
|
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
if (cfg.onContextMenu) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
if(os.isIphoneSafari()){
|
|
119
|
+
wireClickable.addEventListener('touchstart', (event) => {
|
|
120
|
+
event.preventDefault();
|
|
121
|
+
if(this._timeout){
|
|
122
|
+
clearTimeout(this._timeout);
|
|
123
|
+
this._timeout = null;
|
|
124
|
+
}
|
|
125
|
+
this._timeout = setTimeout(() => {
|
|
126
|
+
event.clientX = event.touches[0].clientX;
|
|
127
|
+
event.clientY = event.touches[0].clientY;
|
|
128
|
+
cfg.onContextMenu(event, this);
|
|
129
|
+
clearTimeout(this._timeout);
|
|
130
|
+
this._timeout = null;
|
|
131
|
+
}, 500);
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
wireClickable.addEventListener('touchend', (event) => {
|
|
135
|
+
event.preventDefault();
|
|
136
|
+
//stops short touches from calling the timeout
|
|
137
|
+
if(this._timeout) {
|
|
138
|
+
clearTimeout(this._timeout);
|
|
139
|
+
this._timeout = null;
|
|
140
|
+
}
|
|
141
|
+
} )
|
|
142
|
+
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
wireClickable.addEventListener('contextmenu', (event) => {
|
|
146
|
+
console.log(event);
|
|
147
|
+
cfg.onContextMenu(event, this);
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
event.stopPropagation();
|
|
150
|
+
console.log("Label context menu")
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
122
154
|
}
|
|
123
155
|
|
|
124
156
|
this._x1 = 0;
|
|
@@ -193,7 +225,7 @@ class Wire {
|
|
|
193
225
|
}
|
|
194
226
|
|
|
195
227
|
setClickable(clickable) {
|
|
196
|
-
this._wireClickable.style["pointer-events"] = (
|
|
228
|
+
this._wireClickable.style["pointer-events"] = (clickable) ? "all" : "none";
|
|
197
229
|
}
|
|
198
230
|
|
|
199
231
|
setHighlighted(highlighted) {
|
package/src/viewer/Viewer.js
CHANGED
|
@@ -3,7 +3,7 @@ import {CameraFlightAnimation} from "./scene/camera/CameraFlightAnimation.js";
|
|
|
3
3
|
import {CameraControl} from "./scene/CameraControl/CameraControl.js";
|
|
4
4
|
import {MetaScene} from "./metadata/MetaScene.js";
|
|
5
5
|
import {LocaleService} from "./localization/LocaleService.js";
|
|
6
|
-
import html2canvas from 'html2canvas/dist/html2canvas.esm.js';
|
|
6
|
+
import html2canvas from '../../node_modules/html2canvas/dist/html2canvas.esm.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* The 3D Viewer at the heart of the xeokit SDK.
|
|
@@ -59,8 +59,8 @@ function getCanvasPosFromEvent(event, canvas, canvasPos) {
|
|
|
59
59
|
canvasPos[1] = event.y;
|
|
60
60
|
} else {
|
|
61
61
|
const { left, top } = canvas.getBoundingClientRect();
|
|
62
|
-
canvasPos[0] = event.clientX - left
|
|
63
|
-
canvasPos[1] = event.clientY - top
|
|
62
|
+
canvasPos[0] = event.clientX - left;
|
|
63
|
+
canvasPos[1] = event.clientY - top;
|
|
64
64
|
}
|
|
65
65
|
return canvasPos;
|
|
66
66
|
}
|
|
@@ -65,7 +65,7 @@ const tempVec4b = math.vec4();
|
|
|
65
65
|
* });
|
|
66
66
|
*
|
|
67
67
|
* // Create the Marker, associated with our Mesh Entity
|
|
68
|
-
* const myMarker = new Marker({
|
|
68
|
+
* const myMarker = new Marker(viewer, {
|
|
69
69
|
* entity: entity,
|
|
70
70
|
* worldPos: [10,0,0],
|
|
71
71
|
* occludable: true
|
|
@@ -196,7 +196,7 @@ class Marker extends Component {
|
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
198
|
if (this._onEntityDestroyed !== null) {
|
|
199
|
-
this._entity.off(this._onEntityDestroyed);
|
|
199
|
+
this._entity.model.off(this._onEntityDestroyed);
|
|
200
200
|
this._onEntityDestroyed = null;
|
|
201
201
|
}
|
|
202
202
|
if (this._onEntityModelDestroyed !== null) {
|
|
@@ -212,7 +212,7 @@ class Marker extends Component {
|
|
|
212
212
|
this._onEntityModelDestroyed = null;
|
|
213
213
|
});
|
|
214
214
|
} else {
|
|
215
|
-
this._onEntityDestroyed = this._entity.on("destroyed", () => {
|
|
215
|
+
this._onEntityDestroyed = this._entity.model.on("destroyed", () => {
|
|
216
216
|
this._entity = null;
|
|
217
217
|
this._onEntityDestroyed = null;
|
|
218
218
|
});
|
|
@@ -43,6 +43,7 @@ import {SceneModelTransform} from "./SceneModelTransform.js";
|
|
|
43
43
|
const tempVec3a = math.vec3();
|
|
44
44
|
|
|
45
45
|
const tempOBB3 = math.OBB3();
|
|
46
|
+
const tempQuaternion = math.vec4();
|
|
46
47
|
|
|
47
48
|
const DEFAULT_SCALE = math.vec3([1, 1, 1]);
|
|
48
49
|
const DEFAULT_POSITION = math.vec3([0, 0, 0]);
|
|
@@ -2723,6 +2724,7 @@ export class SceneModel extends Component {
|
|
|
2723
2724
|
* @param {Number[]} [cfg.position=[0,0,0]] Local 3D position of the mesh. Overridden by ````transformId````.
|
|
2724
2725
|
* @param {Number[]} [cfg.scale=[1,1,1]] Scale of the mesh. Overridden by ````transformId````.
|
|
2725
2726
|
* @param {Number[]} [cfg.rotation=[0,0,0]] Rotation of the mesh as Euler angles given in degrees, for each of the X, Y and Z axis. Overridden by ````transformId````.
|
|
2727
|
+
* @param {Number[]} [cfg.quaternion] Rotation of the mesh as a quaternion. Overridden by ````rotation````.
|
|
2726
2728
|
* @param {Number[]} [cfg.matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]] Mesh modelling transform matrix. Overrides the ````position````, ````scale```` and ````rotation```` parameters. Also overridden by ````transformId````.
|
|
2727
2729
|
* @param {Number[]} [cfg.color=[1,1,1]] RGB color in range ````[0..1, 0..1, 0..1]````. Overridden by texture set ````colorTexture````. Overrides ````colors```` and ````colorsCompressed````.
|
|
2728
2730
|
* @param {Number} [cfg.opacity=1] Opacity in range ````[0..1]````. Overridden by texture set ````colorTexture````.
|
|
@@ -2797,12 +2799,15 @@ export class SceneModel extends Component {
|
|
|
2797
2799
|
|
|
2798
2800
|
if (cfg.matrix) {
|
|
2799
2801
|
cfg.meshMatrix = cfg.matrix;
|
|
2800
|
-
} else if (cfg.scale || cfg.rotation || cfg.position) {
|
|
2802
|
+
} else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
|
|
2801
2803
|
const scale = cfg.scale || DEFAULT_SCALE;
|
|
2802
2804
|
const position = cfg.position || DEFAULT_POSITION;
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2805
|
+
if (cfg.rotation) {
|
|
2806
|
+
math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
|
|
2807
|
+
cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
|
|
2808
|
+
} else {
|
|
2809
|
+
cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
|
|
2810
|
+
}
|
|
2806
2811
|
}
|
|
2807
2812
|
|
|
2808
2813
|
if (cfg.positionsDecodeBoundary) {
|
|
@@ -2990,13 +2995,16 @@ export class SceneModel extends Component {
|
|
|
2990
2995
|
// MATRIX
|
|
2991
2996
|
|
|
2992
2997
|
if (cfg.matrix) {
|
|
2993
|
-
cfg.meshMatrix = cfg.matrix
|
|
2994
|
-
} else {
|
|
2998
|
+
cfg.meshMatrix = cfg.matrix;
|
|
2999
|
+
} else if (cfg.scale || cfg.rotation || cfg.position || cfg.quaternion) {
|
|
2995
3000
|
const scale = cfg.scale || DEFAULT_SCALE;
|
|
2996
3001
|
const position = cfg.position || DEFAULT_POSITION;
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3002
|
+
if (cfg.rotation) {
|
|
3003
|
+
math.eulerToQuaternion(cfg.rotation, "XYZ", tempQuaternion);
|
|
3004
|
+
cfg.meshMatrix = math.composeMat4(position, tempQuaternion, scale, math.mat4());
|
|
3005
|
+
} else {
|
|
3006
|
+
cfg.meshMatrix = math.composeMat4(position, cfg.quaternion || DEFAULT_QUATERNION, scale, math.mat4());
|
|
3007
|
+
}
|
|
3000
3008
|
}
|
|
3001
3009
|
|
|
3002
3010
|
math.AABB3ToOBB3(cfg.geometry.aabb, tempOBB3);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const os = {
|
|
2
|
+
isIphoneSafari() {
|
|
3
|
+
const userAgent = window.navigator.userAgent;
|
|
4
|
+
const isIphone = /iPhone/i.test(userAgent);
|
|
5
|
+
const isSafari = /Safari/i.test(userAgent) && !/Chrome/i.test(userAgent);
|
|
6
|
+
|
|
7
|
+
return isIphone && isSafari;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export {os};
|
|
@@ -55,6 +55,13 @@ export declare class AngleMeasurementsControl extends Component {
|
|
|
55
55
|
*/
|
|
56
56
|
deactivate(): void;
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsControl, if any.
|
|
60
|
+
*
|
|
61
|
+
* @returns {null|AngleMeasurement}
|
|
62
|
+
*/
|
|
63
|
+
get currentMeasurement() : AngleMeasurement
|
|
64
|
+
|
|
58
65
|
/**
|
|
59
66
|
* Resets this AngleMeasurementsControl.
|
|
60
67
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {AngleMeasurementsControl} from "./AngleMeasurementsControl.js";
|
|
2
2
|
import {AngleMeasurementsPlugin} from "./AngleMeasurementsPlugin";
|
|
3
3
|
import {PointerLens} from "../../extras/";
|
|
4
|
+
import {AngleMeasurement} from "./AngleMeasurement";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Creates {@link AngleMeasurement}s in an {@link AngleMeasurementsPlugin} from mouse input.
|
|
@@ -87,6 +88,13 @@ export class AngleMeasurementsMouseControl extends AngleMeasurementsControl {
|
|
|
87
88
|
*/
|
|
88
89
|
reset(): void;
|
|
89
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsMouseControl, if any.
|
|
93
|
+
*
|
|
94
|
+
* @returns {null|AngleMeasurement}
|
|
95
|
+
*/
|
|
96
|
+
get currentMeasurement() : AngleMeasurement
|
|
97
|
+
|
|
90
98
|
/**
|
|
91
99
|
* Destroys this AngleMeasurementsMouseControl.
|
|
92
100
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AngleMeasurementsControl } from "./AngleMeasurementsControl";
|
|
2
2
|
import {AngleMeasurementsPlugin} from "./AngleMeasurementsPlugin";
|
|
3
3
|
import {PointerLens} from "../../extras/";
|
|
4
|
+
import {AngleMeasurement} from "./AngleMeasurement";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Creates {@link AngleMeasurement}s in an {@link AngleMeasurementsPlugin} from touch input.
|
|
@@ -87,6 +88,13 @@ export class AngleMeasurementsTouchControl extends AngleMeasurementsControl {
|
|
|
87
88
|
*/
|
|
88
89
|
reset(): void;
|
|
89
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Gets the {@link AngleMeasurement} under construction by this AngleMeasurementsTouchControl, if any.
|
|
93
|
+
*
|
|
94
|
+
* @returns {null|AngleMeasurement}
|
|
95
|
+
*/
|
|
96
|
+
get currentMeasurement() : AngleMeasurement
|
|
97
|
+
|
|
90
98
|
/**
|
|
91
99
|
* Destroys this AngleMeasurementsTouchControl.
|
|
92
100
|
*/
|