@xeokit/xeokit-sdk 2.6.37 → 2.6.40
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 +127 -220
- package/dist/xeokit-sdk.es.js +127 -220
- package/dist/xeokit-sdk.es5.js +72 -75
- package/dist/xeokit-sdk.min.cjs.js +3 -3
- package/dist/xeokit-sdk.min.es.js +4 -4
- package/dist/xeokit-sdk.min.es5.js +3 -3
- package/package.json +1 -1
- package/src/extras/ContextMenu/ContextMenu.js +17 -14
- package/src/plugins/DistanceMeasurementsPlugin/DistanceMeasurement.js +10 -10
- package/src/plugins/DotBIMLoaderPlugin/DotBIMLoaderPlugin.js +39 -46
- package/src/plugins/GLTFLoaderPlugin/GLTFDefaultDataSource.js +6 -0
- package/src/plugins/GLTFLoaderPlugin/GLTFSceneModelLoader.js +47 -146
- package/src/plugins/TreeViewPlugin/RenderService.js +4 -1
- package/src/plugins/TreeViewPlugin/TreeViewPlugin.js +12 -6
- package/src/viewer/scene/model/vbo/batching/triangles/VBOBatchingTrianglesBuffer.js +3 -3
- package/types/plugins/FastNavPlugin/FastNavPlugin.d.ts +2 -0
- package/types/plugins/TreeViewPlugin/TreeViewPlugin.d.ts +2 -0
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Map} from "../../viewer/scene/utils/Map.js";
|
|
1
|
+
import { Map } from "../../viewer/scene/utils/Map.js";
|
|
2
2
|
|
|
3
3
|
const idMap = new Map();
|
|
4
4
|
|
|
@@ -636,21 +636,27 @@ class ContextMenu {
|
|
|
636
636
|
if (itemSubMenu) {
|
|
637
637
|
|
|
638
638
|
html.push(
|
|
639
|
-
'<li id="' + item.id + '" class="xeokit-context-menu-item"
|
|
640
|
-
((groupIdx === groupLen - 1) || ((j < lenj - 1)) ? 'border-bottom: 0' : 'border-bottom: 1px solid black') +
|
|
641
|
-
'">' +
|
|
639
|
+
'<li id="' + item.id + '" class="xeokit-context-menu-item">' +
|
|
642
640
|
actionTitle +
|
|
643
641
|
' [MORE]' +
|
|
644
642
|
'</li>');
|
|
643
|
+
if (!((groupIdx === groupLen - 1) || (j < lenj - 1))) {
|
|
644
|
+
html.push(
|
|
645
|
+
'<li id="' + item.id + '" class="xeokit-context-menu-item-separator"></li>'
|
|
646
|
+
);
|
|
647
|
+
}
|
|
645
648
|
|
|
646
649
|
} else {
|
|
647
650
|
|
|
648
651
|
html.push(
|
|
649
|
-
'<li id="' + item.id + '" class="xeokit-context-menu-item"
|
|
650
|
-
((groupIdx === groupLen - 1) || ((j < lenj - 1)) ? 'border-bottom: 0' : 'border-bottom: 1px solid black') +
|
|
651
|
-
'">' +
|
|
652
|
+
'<li id="' + item.id + '" class="xeokit-context-menu-item">' +
|
|
652
653
|
actionTitle +
|
|
653
654
|
'</li>');
|
|
655
|
+
if (!((groupIdx === groupLen - 1) || (j < lenj - 1))) {
|
|
656
|
+
html.push(
|
|
657
|
+
'<li id="' + item.id + '" class="xeokit-context-menu-item-separator"></li>'
|
|
658
|
+
);
|
|
659
|
+
}
|
|
654
660
|
}
|
|
655
661
|
}
|
|
656
662
|
}
|
|
@@ -848,14 +854,11 @@ class ContextMenu {
|
|
|
848
854
|
const shown = getShown(this._context);
|
|
849
855
|
item.shown = shown;
|
|
850
856
|
if (!shown) {
|
|
851
|
-
itemElement.style.
|
|
852
|
-
itemElement.style.height = "0";
|
|
853
|
-
itemElement.style.padding = "0";
|
|
857
|
+
itemElement.style.display = "none";
|
|
854
858
|
continue;
|
|
855
859
|
} else {
|
|
856
|
-
itemElement.style.
|
|
857
|
-
|
|
858
|
-
itemElement.style.padding = null;
|
|
860
|
+
itemElement.style.display = "";
|
|
861
|
+
|
|
859
862
|
}
|
|
860
863
|
const enabled = getEnabled(this._context);
|
|
861
864
|
item.enabled = enabled;
|
|
@@ -925,4 +928,4 @@ class ContextMenu {
|
|
|
925
928
|
}
|
|
926
929
|
}
|
|
927
930
|
|
|
928
|
-
export {ContextMenu};
|
|
931
|
+
export { ContextMenu };
|
|
@@ -366,6 +366,16 @@ class DistanceMeasurement extends Component {
|
|
|
366
366
|
const scene = this.plugin.viewer.scene;
|
|
367
367
|
|
|
368
368
|
if (this._wpDirty) {
|
|
369
|
+
const delta = math.subVec3(
|
|
370
|
+
this._targetWorld,
|
|
371
|
+
this._originWorld,
|
|
372
|
+
tmpVec3
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* The length detected for each measurement axis.
|
|
377
|
+
*/
|
|
378
|
+
this._factors = math.transformVec3(this._axesBasis, delta);
|
|
369
379
|
|
|
370
380
|
this._measurementOrientation = determineMeasurementOrientation(this._originWorld, this._targetWorld, 0);
|
|
371
381
|
if(this._measurementOrientation === 'Vertical' && this.useRotationAdjustment){
|
|
@@ -390,16 +400,6 @@ class DistanceMeasurement extends Component {
|
|
|
390
400
|
this._wp[15] = 1.0;
|
|
391
401
|
}
|
|
392
402
|
else {
|
|
393
|
-
const delta = math.subVec3(
|
|
394
|
-
this._targetWorld,
|
|
395
|
-
this._originWorld,
|
|
396
|
-
tmpVec3
|
|
397
|
-
);
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* The length detected for each measurement axis.
|
|
401
|
-
*/
|
|
402
|
-
this._factors = math.transformVec3(this._axesBasis, delta);
|
|
403
403
|
|
|
404
404
|
this._wp[0] = this._originWorld[0];
|
|
405
405
|
this._wp[1] = this._originWorld[1];
|
|
@@ -16,8 +16,8 @@ import {IFCObjectDefaults} from "../../viewer/metadata/IFCObjectDefaults.js";
|
|
|
16
16
|
* set ````true```` and will be registered by {@link Entity#id} in {@link Scene#objects}.
|
|
17
17
|
* * When loading, can set the World-space position, scale and rotation of each model within World space,
|
|
18
18
|
* along with initial properties for all the model's {@link Entity}s.
|
|
19
|
-
* * Allows to mask which
|
|
20
|
-
* * Allows to configure initial viewer state for specified
|
|
19
|
+
* * Allows to mask which types we want to load.
|
|
20
|
+
* * Allows to configure initial viewer state for specified types (color, visibility, selection, highlighted, X-rayed, pickable, etc).
|
|
21
21
|
*
|
|
22
22
|
* ## Usage
|
|
23
23
|
*
|
|
@@ -87,9 +87,9 @@ import {IFCObjectDefaults} from "../../viewer/metadata/IFCObjectDefaults.js";
|
|
|
87
87
|
* });
|
|
88
88
|
* ````
|
|
89
89
|
*
|
|
90
|
-
* ## Including and excluding
|
|
90
|
+
* ## Including and excluding types
|
|
91
91
|
*
|
|
92
|
-
* We can also load only those objects that have the specified
|
|
92
|
+
* We can also load only those objects that have the specified types. In the example below, we'll load only the
|
|
93
93
|
* objects that represent walls.
|
|
94
94
|
*
|
|
95
95
|
* ````javascript
|
|
@@ -100,7 +100,7 @@ import {IFCObjectDefaults} from "../../viewer/metadata/IFCObjectDefaults.js";
|
|
|
100
100
|
* });
|
|
101
101
|
* ````
|
|
102
102
|
*
|
|
103
|
-
* We can also load only those objects that **don't** have the specified
|
|
103
|
+
* We can also load only those objects that **don't** have the specified types. In the example below, we'll load only the
|
|
104
104
|
* objects that do not represent empty space.
|
|
105
105
|
*
|
|
106
106
|
* ````javascript
|
|
@@ -111,13 +111,13 @@ import {IFCObjectDefaults} from "../../viewer/metadata/IFCObjectDefaults.js";
|
|
|
111
111
|
* });
|
|
112
112
|
* ````
|
|
113
113
|
*
|
|
114
|
-
* # Configuring initial
|
|
114
|
+
* # Configuring initial object appearances
|
|
115
115
|
*
|
|
116
|
-
* We can specify the custom initial appearance of loaded objects according to their
|
|
116
|
+
* We can specify the custom initial appearance of loaded objects according to their types.
|
|
117
117
|
*
|
|
118
118
|
* This is useful for things like:
|
|
119
119
|
*
|
|
120
|
-
* * setting the colors to our objects according to their
|
|
120
|
+
* * setting the colors to our objects according to their types,
|
|
121
121
|
* * automatically hiding ````IfcSpace```` objects, and
|
|
122
122
|
* * ensuring that ````IfcWindow```` objects are always transparent.
|
|
123
123
|
* <br>
|
|
@@ -149,7 +149,7 @@ import {IFCObjectDefaults} from "../../viewer/metadata/IFCObjectDefaults.js";
|
|
|
149
149
|
* });
|
|
150
150
|
* ````
|
|
151
151
|
*
|
|
152
|
-
* When we don't customize the appearance of
|
|
152
|
+
* When we don't customize the appearance of types, as just above, then IfcSpace elements tend to obscure other
|
|
153
153
|
* elements, which can be confusing.
|
|
154
154
|
*
|
|
155
155
|
* It's often helpful to make IfcSpaces transparent and unpickable, like this:
|
|
@@ -349,36 +349,36 @@ export class DotBIMLoaderPlugin extends Plugin {
|
|
|
349
349
|
|
|
350
350
|
const dbMeshLoaded = {};
|
|
351
351
|
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
const
|
|
355
|
-
const
|
|
352
|
+
const projectId = math.createUUID();
|
|
353
|
+
const siteId = math.createUUID();
|
|
354
|
+
const buildingId = math.createUUID();
|
|
355
|
+
const buildingStoryId = math.createUUID();
|
|
356
356
|
|
|
357
357
|
const metaModelData = {
|
|
358
358
|
metaObjects: [
|
|
359
359
|
{
|
|
360
|
-
id:
|
|
361
|
-
name: "
|
|
362
|
-
type: "
|
|
360
|
+
id: projectId,
|
|
361
|
+
name: "Project",
|
|
362
|
+
type: "Project",
|
|
363
363
|
parent: null
|
|
364
364
|
},
|
|
365
365
|
{
|
|
366
|
-
id:
|
|
367
|
-
name: "
|
|
368
|
-
type: "
|
|
369
|
-
parent:
|
|
366
|
+
id: siteId,
|
|
367
|
+
name: "Site",
|
|
368
|
+
type: "Site",
|
|
369
|
+
parent: projectId
|
|
370
370
|
},
|
|
371
371
|
{
|
|
372
|
-
id:
|
|
373
|
-
name: "
|
|
374
|
-
type: "
|
|
375
|
-
parent:
|
|
372
|
+
id: buildingId,
|
|
373
|
+
name: "Building",
|
|
374
|
+
type: "Building",
|
|
375
|
+
parent: siteId
|
|
376
376
|
},
|
|
377
377
|
{
|
|
378
|
-
id:
|
|
379
|
-
name: "
|
|
380
|
-
type: "
|
|
381
|
-
parent:
|
|
378
|
+
id: buildingStoryId,
|
|
379
|
+
name: "BuildingStorey",
|
|
380
|
+
type: "BuildingStorey",
|
|
381
|
+
parent: buildingId
|
|
382
382
|
}
|
|
383
383
|
],
|
|
384
384
|
propertySets: []
|
|
@@ -503,7 +503,7 @@ export class DotBIMLoaderPlugin extends Plugin {
|
|
|
503
503
|
id: `${dbMeshId}-${faceColor}`,
|
|
504
504
|
primitive: "triangles",
|
|
505
505
|
positions: trianglesCoordinates,
|
|
506
|
-
indices: [...Array(trianglesCoordinates.length).keys()]
|
|
506
|
+
indices: [...Array(trianglesCoordinates.length / 3).keys()]
|
|
507
507
|
});
|
|
508
508
|
const meshId = `${objectId}-mesh-${faceColor}`;
|
|
509
509
|
const faceColorArray = faceColor.split(',').map(Number);
|
|
@@ -545,30 +545,23 @@ export class DotBIMLoaderPlugin extends Plugin {
|
|
|
545
545
|
});
|
|
546
546
|
}
|
|
547
547
|
|
|
548
|
+
let properties = [];
|
|
548
549
|
for (let infoKey in info) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
properties.push({
|
|
555
|
-
name: infoKey,
|
|
556
|
-
value: info[infoKey]
|
|
557
|
-
});
|
|
558
|
-
}
|
|
559
|
-
if (properties) {
|
|
560
|
-
metaModelData.propertySets.push({
|
|
561
|
-
id: objectId,
|
|
562
|
-
properties
|
|
563
|
-
});
|
|
564
|
-
}
|
|
550
|
+
properties.push({
|
|
551
|
+
name: infoKey,
|
|
552
|
+
value: info[infoKey]
|
|
553
|
+
});
|
|
565
554
|
}
|
|
555
|
+
metaModelData.propertySets.push({
|
|
556
|
+
id: objectId,
|
|
557
|
+
properties
|
|
558
|
+
});
|
|
566
559
|
|
|
567
560
|
metaModelData.metaObjects.push({
|
|
568
561
|
id: objectId,
|
|
569
562
|
name: info && info.Name && info.Name !== "None" ? info.Name : `${element.type} ${objectId}`,
|
|
570
563
|
type: element.type,
|
|
571
|
-
parent:
|
|
564
|
+
parent: buildingStoryId,
|
|
572
565
|
propertySetIds: [objectId]
|
|
573
566
|
});
|
|
574
567
|
}
|
|
@@ -9,6 +9,12 @@ import {core} from "../../viewer/scene/core.js";
|
|
|
9
9
|
class GLTFDefaultDataSource {
|
|
10
10
|
|
|
11
11
|
constructor(cfg = {}) {
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Set `true` to enable cache busting for HTTP GETs.
|
|
15
|
+
* This is `true` by default.
|
|
16
|
+
* @type {boolean}
|
|
17
|
+
*/
|
|
12
18
|
this.cacheBuster = (cfg.cacheBuster !== false);
|
|
13
19
|
}
|
|
14
20
|
|
|
@@ -395,173 +395,74 @@ function loadDefaultScene(ctx) {
|
|
|
395
395
|
error(ctx, "glTF has no default scene");
|
|
396
396
|
return;
|
|
397
397
|
}
|
|
398
|
-
loadScene(ctx, scene);
|
|
399
|
-
}
|
|
400
398
|
|
|
401
|
-
function loadScene(ctx, scene) {
|
|
402
399
|
const nodes = scene.nodes;
|
|
403
400
|
if (!nodes) {
|
|
404
401
|
return;
|
|
405
402
|
}
|
|
406
|
-
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
407
|
-
const node = nodes[i];
|
|
408
|
-
countMeshUsage(ctx, node);
|
|
409
|
-
}
|
|
410
|
-
for (let i = 0, len = nodes.length; i < len && !ctx.nodesHaveNames; i++) {
|
|
411
|
-
const node = nodes[i];
|
|
412
|
-
if (testIfNodesHaveNames(node)) {
|
|
413
|
-
ctx.nodesHaveNames = true;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
if (!ctx.nodesHaveNames) {
|
|
417
|
-
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
418
|
-
const node = nodes[i];
|
|
419
|
-
parseNodesWithoutNames(ctx, node, 0, null);
|
|
420
|
-
}
|
|
421
|
-
} else {
|
|
422
|
-
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
423
|
-
const node = nodes[i];
|
|
424
|
-
parseNodesWithNames(ctx, node, 0, null);
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
403
|
|
|
429
|
-
function
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const children = node.children;
|
|
436
|
-
for (let i = 0, len = children.length; i < len; i++) {
|
|
437
|
-
const childNode = children[i];
|
|
438
|
-
if (!childNode) {
|
|
439
|
-
error(ctx, "Node not found: " + i);
|
|
440
|
-
continue;
|
|
404
|
+
(function accumulateMeshInstantes(nodes) {
|
|
405
|
+
nodes.forEach(node => {
|
|
406
|
+
const mesh = node.mesh;
|
|
407
|
+
if (mesh) {
|
|
408
|
+
mesh.instances ||= 0;
|
|
409
|
+
mesh.instances += 1;
|
|
441
410
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
function testIfNodesHaveNames(node) {
|
|
448
|
-
if (node.name) {
|
|
449
|
-
return true;
|
|
450
|
-
}
|
|
451
|
-
if (node.children) {
|
|
452
|
-
const children = node.children;
|
|
453
|
-
for (let i = 0, len = children.length; i < len; i++) {
|
|
454
|
-
const childNode = children[i];
|
|
455
|
-
if (testIfNodesHaveNames(childNode)) {
|
|
456
|
-
return true;
|
|
411
|
+
if (node.children) {
|
|
412
|
+
accumulateMeshInstantes(node.children);
|
|
457
413
|
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
return false;
|
|
461
|
-
}
|
|
414
|
+
});
|
|
415
|
+
})(nodes);
|
|
462
416
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
for (let i = 0, len = children.length; i < len; i++) {
|
|
477
|
-
const childNode = children[i];
|
|
478
|
-
parseNodesWithoutNames(ctx, childNode, depth + 1, matrix, node);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
if (depth === 0) {
|
|
482
|
-
let entityId = "entity-" + ctx.nextId++;
|
|
483
|
-
if (meshIds && meshIds.length > 0) {
|
|
484
|
-
ctx.sceneModel.createEntity({
|
|
485
|
-
id: entityId,
|
|
486
|
-
meshIds,
|
|
487
|
-
isObject: true
|
|
488
|
-
});
|
|
489
|
-
if (ctx.autoMetaModel) {
|
|
490
|
-
ctx.metaObjects.push({
|
|
491
|
-
id: entityId,
|
|
492
|
-
type: "Default",
|
|
493
|
-
name: entityId,
|
|
494
|
-
parent: ctx.sceneModel.id
|
|
495
|
-
});
|
|
417
|
+
// Create a SceneMesh for each mesh primitive, and a SceneModelEntity for the root node and each named node.
|
|
418
|
+
const meshIdsStack = [];
|
|
419
|
+
let meshIds = null;
|
|
420
|
+
(function createSceneMeshesAndEntities(nodes, depth, parentMatrix) {
|
|
421
|
+
nodes.forEach(node => {
|
|
422
|
+
const nodeName = node.name;
|
|
423
|
+
let entityId = (((nodeName !== undefined) && (nodeName !== null) && nodeName)
|
|
424
|
+
||
|
|
425
|
+
((depth === 0) && ("entity-" + ctx.nextId++)));
|
|
426
|
+
|
|
427
|
+
if (entityId) {
|
|
428
|
+
while (ctx.sceneModel.objects[entityId]) {
|
|
429
|
+
entityId = "entity-" + ctx.nextId++;
|
|
496
430
|
}
|
|
497
|
-
meshIds
|
|
431
|
+
meshIdsStack.push(meshIds);
|
|
432
|
+
meshIds = [];
|
|
498
433
|
}
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
})();
|
|
502
|
-
|
|
503
|
-
const parseNodesWithNames = (function () {
|
|
504
|
-
|
|
505
|
-
const objectIdStack = [];
|
|
506
|
-
const meshIdsStack = [];
|
|
507
|
-
let meshIds = [];
|
|
508
434
|
|
|
509
|
-
|
|
510
|
-
matrix = parseNodeMatrix(node, matrix);
|
|
511
|
-
if (meshIds && node.mesh) {
|
|
512
|
-
parseNodeMesh(node, ctx, matrix, meshIds);
|
|
513
|
-
}
|
|
435
|
+
const matrix = parseNodeMatrix(node, parentMatrix);
|
|
514
436
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
let entityId = node.name;
|
|
518
|
-
if (!!entityId && ctx.sceneModel.objects[entityId]) {
|
|
519
|
-
// ctx.log(`Warning: Two or more glTF nodes found with same 'name' attribute: '${entityId} - will randomly-generating an object ID in XKT`);
|
|
520
|
-
}
|
|
521
|
-
while (!entityId || ctx.sceneModel.objects[entityId]) {
|
|
522
|
-
entityId = "entity-" + ctx.nextId++;
|
|
437
|
+
if (node.mesh) {
|
|
438
|
+
parseNodeMesh(node, ctx, matrix, meshIds);
|
|
523
439
|
}
|
|
524
|
-
objectIdStack.push(entityId);
|
|
525
|
-
meshIdsStack.push(meshIds);
|
|
526
|
-
}
|
|
527
440
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
for (let i = 0, len = children.length; i < len; i++) {
|
|
531
|
-
const childNode = children[i];
|
|
532
|
-
parseNodesWithNames(ctx, childNode, depth + 1, matrix);
|
|
441
|
+
if (node.children) {
|
|
442
|
+
createSceneMeshesAndEntities(node.children, depth + 1, matrix);
|
|
533
443
|
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// Post-order visit scene node
|
|
537
444
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
if (!entityId) { // For when there are no nodes with names
|
|
542
|
-
entityId = "entity-" + ctx.nextId++;
|
|
543
|
-
}
|
|
544
|
-
let entityMeshIds = meshIdsStack.pop();
|
|
545
|
-
if (meshIds && meshIds.length > 0) {
|
|
546
|
-
ctx.sceneModel.createEntity({
|
|
547
|
-
id: entityId,
|
|
548
|
-
meshIds: entityMeshIds,
|
|
549
|
-
isObject: true
|
|
550
|
-
});
|
|
551
|
-
if (ctx.autoMetaModel) {
|
|
552
|
-
ctx.metaObjects.push({
|
|
445
|
+
if (entityId) {
|
|
446
|
+
if (meshIds.length > 0) {
|
|
447
|
+
ctx.sceneModel.createEntity({
|
|
553
448
|
id: entityId,
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
parent: ctx.sceneModel.id
|
|
449
|
+
meshIds: meshIds,
|
|
450
|
+
isObject: true
|
|
557
451
|
});
|
|
452
|
+
if (ctx.autoMetaModel) {
|
|
453
|
+
ctx.metaObjects.push({
|
|
454
|
+
id: entityId,
|
|
455
|
+
type: "Default",
|
|
456
|
+
name: entityId,
|
|
457
|
+
parent: ctx.sceneModel.id
|
|
458
|
+
});
|
|
459
|
+
}
|
|
558
460
|
}
|
|
461
|
+
meshIds = meshIdsStack.pop();
|
|
559
462
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
})();
|
|
564
|
-
|
|
463
|
+
});
|
|
464
|
+
})(nodes, 0, null);
|
|
465
|
+
};
|
|
565
466
|
|
|
566
467
|
/**
|
|
567
468
|
* Parses transform at the given glTF node.
|
|
@@ -135,12 +135,15 @@ export class RenderService {
|
|
|
135
135
|
return element.checked;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
setCheckbox(nodeId, checked) {
|
|
138
|
+
setCheckbox(nodeId, checked, indeterminate = false) {
|
|
139
139
|
const checkbox = document.getElementById(`checkbox-${nodeId}`);
|
|
140
140
|
if (checkbox) {
|
|
141
141
|
if (checked !== checkbox.checked) {
|
|
142
142
|
checkbox.checked = checked;
|
|
143
143
|
}
|
|
144
|
+
if (indeterminate !== checkbox.indeterminate) {
|
|
145
|
+
checkbox.indeterminate = indeterminate;
|
|
146
|
+
}
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
|
|
@@ -361,6 +361,7 @@ export class TreeViewPlugin extends Plugin {
|
|
|
361
361
|
* vertical World axis. For all hierarchy types, other node types will be ordered in the ascending alphanumeric order of their titles.
|
|
362
362
|
* @param {Boolean} [cfg.pruneEmptyNodes=true] When true, will not contain nodes that don't have content in the {@link Scene}. These are nodes whose {@link MetaObject}s don't have {@link Entity}s.
|
|
363
363
|
* @param {RenderService} [cfg.renderService] Optional {@link RenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}.
|
|
364
|
+
* @param {Boolean} [cfg.showIndeterminate=false] When true, will show indeterminate state for checkboxes when some but not all child nodes are checked
|
|
364
365
|
*/
|
|
365
366
|
constructor(viewer, cfg = {}) {
|
|
366
367
|
|
|
@@ -412,6 +413,7 @@ export class TreeViewPlugin extends Plugin {
|
|
|
412
413
|
this._pruneEmptyNodes = cfg.pruneEmptyNodes;
|
|
413
414
|
this._showListItemElementId = null;
|
|
414
415
|
this._renderService = cfg.renderService || new RenderService();
|
|
416
|
+
this._showIndeterminate = cfg.showIndeterminate ?? false;
|
|
415
417
|
|
|
416
418
|
if (!this._renderService) {
|
|
417
419
|
throw new Error('TreeViewPlugin: no render service set');
|
|
@@ -453,8 +455,10 @@ export class TreeViewPlugin extends Plugin {
|
|
|
453
455
|
} else {
|
|
454
456
|
parent.numVisibleEntities--;
|
|
455
457
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
+
const indeterminate = this._showIndeterminate
|
|
459
|
+
&& parent.numVisibleEntities > 0
|
|
460
|
+
&& parent.numVisibleEntities < parent.numEntities;
|
|
461
|
+
this._renderService.setCheckbox(parent.nodeId, (parent.numVisibleEntities > 0), indeterminate);
|
|
458
462
|
|
|
459
463
|
parent = parent.parent;
|
|
460
464
|
}
|
|
@@ -536,8 +540,10 @@ export class TreeViewPlugin extends Plugin {
|
|
|
536
540
|
} else {
|
|
537
541
|
parent.numVisibleEntities -= numUpdated;
|
|
538
542
|
}
|
|
539
|
-
|
|
540
|
-
|
|
543
|
+
const indeterminate = this._showIndeterminate
|
|
544
|
+
&& parent.numVisibleEntities > 0
|
|
545
|
+
&& parent.numVisibleEntities < parent.numEntities;
|
|
546
|
+
this._renderService.setCheckbox(parent.nodeId, (parent.numVisibleEntities > 0), indeterminate);
|
|
541
547
|
|
|
542
548
|
parent = parent.parent;
|
|
543
549
|
}
|
|
@@ -777,8 +783,8 @@ export class TreeViewPlugin extends Plugin {
|
|
|
777
783
|
collapse() {
|
|
778
784
|
for (let i = 0, len = this._rootNodes.length; i < len; i++) {
|
|
779
785
|
const rootNode = this._rootNodes[i];
|
|
780
|
-
const
|
|
781
|
-
this._collapseNode(
|
|
786
|
+
const nodeId = rootNode.nodeId;
|
|
787
|
+
this._collapseNode(nodeId);
|
|
782
788
|
}
|
|
783
789
|
}
|
|
784
790
|
|
|
@@ -7,9 +7,9 @@ const configs = new Configs();
|
|
|
7
7
|
*/
|
|
8
8
|
export class VBOBatchingTrianglesBuffer {
|
|
9
9
|
|
|
10
|
-
constructor() {
|
|
11
|
-
this.maxVerts =
|
|
12
|
-
this.maxIndices =
|
|
10
|
+
constructor(maxBatchSize = configs.maxGeometryBatchSize) {
|
|
11
|
+
this.maxVerts = maxBatchSize;
|
|
12
|
+
this.maxIndices = maxBatchSize * 3; // Rough rule-of-thumb
|
|
13
13
|
this.positions = [];
|
|
14
14
|
this.colors = [];
|
|
15
15
|
this.uv = [];
|
|
@@ -4,6 +4,8 @@ import { Viewer } from "../../viewer/Viewer";
|
|
|
4
4
|
export declare type FastNavPluginConfiguration = {
|
|
5
5
|
/** Optional ID for this plugin, so that we can find it within {@link Viewer.plugins}. */
|
|
6
6
|
id?: string;
|
|
7
|
+
/** Whether to temporarily hide color textures whenever we interact with the Viewer. */
|
|
8
|
+
hideColorTexture?: boolean;
|
|
7
9
|
/** Whether to temporarily hide physically-based rendering (PBR) whenever we interact with the Viewer. */
|
|
8
10
|
hidePBR?: boolean;
|
|
9
11
|
/** Whether to temporarily hide scalable ambient occlusion (SAO) whenever we interact with the Viewer. */
|
|
@@ -19,6 +19,8 @@ export declare type TreeViewPluginConfiguration = {
|
|
|
19
19
|
pruneEmptyNodes?: boolean;
|
|
20
20
|
/** Optional {@link ITreeViewRenderService} to use. Defaults to the {@link TreeViewPlugin}'s default {@link RenderService}. */
|
|
21
21
|
renderService?: ITreeViewRenderService;
|
|
22
|
+
/** When true, will show indeterminate state for checkboxes when some but not all child nodes are checked */
|
|
23
|
+
showIndeterminate?: boolean;
|
|
22
24
|
};
|
|
23
25
|
|
|
24
26
|
/**
|