@combeenation/3d-viewer 6.5.0 → 7.0.0-beta1

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.
Files changed (69) hide show
  1. package/dist/lib-cjs/api/classes/element.d.ts +4 -0
  2. package/dist/lib-cjs/api/classes/element.js +59 -58
  3. package/dist/lib-cjs/api/classes/element.js.map +1 -1
  4. package/dist/lib-cjs/api/classes/event.d.ts +55 -1
  5. package/dist/lib-cjs/api/classes/event.js +55 -1
  6. package/dist/lib-cjs/api/classes/event.js.map +1 -1
  7. package/dist/lib-cjs/api/classes/fuzzyMap.d.ts +7 -0
  8. package/dist/lib-cjs/api/classes/fuzzyMap.js +22 -0
  9. package/dist/lib-cjs/api/classes/fuzzyMap.js.map +1 -0
  10. package/dist/lib-cjs/api/classes/parameter.d.ts +12 -0
  11. package/dist/lib-cjs/api/classes/parameter.js +86 -33
  12. package/dist/lib-cjs/api/classes/parameter.js.map +1 -1
  13. package/dist/lib-cjs/api/classes/parameterObservable.js +2 -27
  14. package/dist/lib-cjs/api/classes/parameterObservable.js.map +1 -1
  15. package/dist/lib-cjs/api/classes/variant.d.ts +23 -4
  16. package/dist/lib-cjs/api/classes/variant.js +45 -20
  17. package/dist/lib-cjs/api/classes/variant.js.map +1 -1
  18. package/dist/lib-cjs/api/classes/variantInstance.d.ts +11 -2
  19. package/dist/lib-cjs/api/classes/variantInstance.js +22 -2
  20. package/dist/lib-cjs/api/classes/variantInstance.js.map +1 -1
  21. package/dist/lib-cjs/api/classes/viewer.d.ts +13 -1
  22. package/dist/lib-cjs/api/classes/viewer.js +57 -7
  23. package/dist/lib-cjs/api/classes/viewer.js.map +1 -1
  24. package/dist/lib-cjs/api/classes/viewerLight.js.map +1 -1
  25. package/dist/lib-cjs/api/manager/animationManager.d.ts +3 -3
  26. package/dist/lib-cjs/api/manager/animationManager.js.map +1 -1
  27. package/dist/lib-cjs/api/manager/sceneManager.js.map +1 -1
  28. package/dist/lib-cjs/api/manager/tagManager.d.ts +108 -0
  29. package/dist/lib-cjs/api/manager/tagManager.js +420 -0
  30. package/dist/lib-cjs/api/manager/tagManager.js.map +1 -0
  31. package/dist/lib-cjs/api/manager/variantInstanceManager.d.ts +8 -3
  32. package/dist/lib-cjs/api/manager/variantInstanceManager.js +27 -8
  33. package/dist/lib-cjs/api/manager/variantInstanceManager.js.map +1 -1
  34. package/dist/lib-cjs/api/store/specStorage.d.ts +8 -0
  35. package/dist/lib-cjs/api/store/specStorage.js +15 -0
  36. package/dist/lib-cjs/api/store/specStorage.js.map +1 -1
  37. package/dist/lib-cjs/api/util/babylonHelper.d.ts +36 -7
  38. package/dist/lib-cjs/api/util/babylonHelper.js +92 -15
  39. package/dist/lib-cjs/api/util/babylonHelper.js.map +1 -1
  40. package/dist/lib-cjs/api/util/globalTypes.d.ts +38 -1
  41. package/dist/lib-cjs/api/util/sceneLoaderHelper.d.ts +1 -0
  42. package/dist/lib-cjs/api/util/sceneLoaderHelper.js +20 -2
  43. package/dist/lib-cjs/api/util/sceneLoaderHelper.js.map +1 -1
  44. package/dist/lib-cjs/buildinfo.json +1 -1
  45. package/dist/lib-cjs/commonjs.tsconfig.tsbuildinfo +1 -1
  46. package/dist/lib-cjs/index.d.ts +2 -1
  47. package/dist/lib-cjs/index.js +3 -1
  48. package/dist/lib-cjs/index.js.map +1 -1
  49. package/package.json +1 -1
  50. package/src/api/classes/element.ts +96 -82
  51. package/src/api/classes/event.ts +68 -1
  52. package/src/api/classes/fuzzyMap.ts +21 -0
  53. package/src/api/classes/parameter.ts +91 -34
  54. package/src/api/classes/parameterObservable.ts +2 -29
  55. package/src/api/classes/variant.ts +82 -33
  56. package/src/api/classes/variantInstance.ts +27 -1
  57. package/src/api/classes/viewer.ts +63 -12
  58. package/src/api/classes/viewerLight.ts +10 -10
  59. package/src/api/manager/animationManager.ts +2 -2
  60. package/src/api/manager/sceneManager.ts +5 -1
  61. package/src/api/manager/tagManager.ts +451 -0
  62. package/src/api/manager/variantInstanceManager.ts +35 -8
  63. package/src/api/store/specStorage.ts +17 -0
  64. package/src/api/util/babylonHelper.ts +99 -21
  65. package/src/api/util/globalTypes.ts +56 -1
  66. package/src/api/util/sceneLoaderHelper.ts +21 -2
  67. package/src/dev.ts +3 -1
  68. package/src/index.ts +2 -0
  69. package/src/types.d.ts +7 -0
@@ -1,4 +1,5 @@
1
1
  import { DottedPath } from '../classes/dottedPath';
2
+ import { Event, emitter } from '../classes/event';
2
3
  import { defaultEnvHelperColor, defaultSceneClearColor } from '../internal/sceneSetup';
3
4
  import {
4
5
  addMissingMaterialObserver,
@@ -23,11 +24,12 @@ import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
23
24
  import { Mesh } from '@babylonjs/core/Meshes/mesh';
24
25
  import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
25
26
  import { Observable } from '@babylonjs/core/Misc/observable';
27
+ import { Tags } from '@babylonjs/core/Misc/tags';
26
28
  import { Tools } from '@babylonjs/core/Misc/tools';
27
29
  import { Node } from '@babylonjs/core/node';
28
30
  import { Scene } from '@babylonjs/core/scene';
29
31
  import { Nullable } from '@babylonjs/core/types';
30
- import { cloneDeep, get, has, merge } from 'lodash-es';
32
+ import { cloneDeep, get, has, merge, uniq } from 'lodash-es';
31
33
 
32
34
  const backgroundDomeName = 'BackgroundDome_ViewerGenerated';
33
35
  const envHelperMetadataName = 'viewerEnvHelper';
@@ -82,21 +84,26 @@ const getDottedPathForNode = function (node: Node): DottedPath {
82
84
 
83
85
  /**
84
86
  * @param node
87
+ * @param nodeNamingStrategy
85
88
  * @param predicate
86
89
  * @param deep
87
90
  * @return TransformNode | null
88
91
  */
89
92
  const cloneTransformNode = function (
90
93
  node: TransformNode,
94
+ nodeNamingStrategy: NodeNamingStrategy,
91
95
  predicate?: (node: TransformNode) => boolean,
92
96
  deep: boolean = true
93
97
  ): TransformNode | null {
94
98
  if (predicate && !predicate(node)) {
95
99
  return null;
96
100
  }
97
- const clone = node.clone(node.name, node.parent, true);
101
+ const newName = nodeNamingStrategy.handler(node, nodeNamingStrategy.payload);
102
+ const clone = node.clone(newName, node.parent, true);
98
103
  if (clone) {
104
+ clone.id = newName;
99
105
  clone.metadata = cloneDeep(node.metadata);
106
+ injectNodeMetadata(clone, { cloneSource: node }, false);
100
107
  // if the cloned node is of type InstancedMesh, due to a bug(?),
101
108
  // the InstancedMesh.isEnabled state may have changed after cloning.
102
109
  // in that case, set the clone's enabled state to the original's state
@@ -107,7 +114,7 @@ const cloneTransformNode = function (
107
114
  if (deep) {
108
115
  const children = node.getChildTransformNodes(true);
109
116
  children.forEach(child => {
110
- const clonedChild = cloneTransformNode(child, predicate, deep);
117
+ const clonedChild = cloneTransformNode(child, nodeNamingStrategy, predicate, deep);
111
118
  if (clonedChild) {
112
119
  clonedChild.parent = clone;
113
120
  }
@@ -174,7 +181,7 @@ const injectNodeMetadata = function (node: Node, metadata: {}, deep: boolean = t
174
181
  */
175
182
  const assertTransformNode = function (
176
183
  node: TransformNode,
177
- assertCallable: CallableFunction,
184
+ assertCallable: (node: TransformNode, ...args: any[]) => void,
178
185
  callableParameters: any[] = [],
179
186
  deep: boolean = true
180
187
  ) {
@@ -185,6 +192,24 @@ const assertTransformNode = function (
185
192
  }
186
193
  };
187
194
 
195
+ /**
196
+ * @param node
197
+ * @param parameter
198
+ */
199
+ const assertMeshCapability = function (node: TransformNode, parameter: string) {
200
+ if (!(node instanceof AbstractMesh)) {
201
+ const cls = node.getClassName();
202
+ throw new Error(
203
+ `Changing parameter "${parameter}" of a(n) ${cls} is not supported. Tried to change node "${node.id}".`
204
+ );
205
+ }
206
+ if (node instanceof InstancedMesh) {
207
+ throw new Error(
208
+ `Changing parameter "${parameter}" of an InstancedMesh is not supported. Tried to change node "${node.id}".`
209
+ );
210
+ }
211
+ };
212
+
188
213
  /**
189
214
  * @param node
190
215
  * @param deep
@@ -372,15 +397,9 @@ const changeEnvironment = function (scene: Scene, envDef: EnvironmentDefinition)
372
397
  * Finally the material will not be applied before all its textures have been loaded. In this way "flickering" effects
373
398
  * will be avoided, since the material would be incomplete without its loaded textures.
374
399
  */
375
- const setMaterial = function (
376
- scene: Scene,
377
- node: TransformNode,
378
- materialId: string,
379
- deep: boolean = true,
380
- variant?: Variant
381
- ) {
400
+ const setMaterial = function (node: TransformNode, materialId: string, deep: boolean = true, variant?: Variant) {
382
401
  if (node instanceof AbstractMesh) {
383
- const materialExists = scene.getMaterialById(materialId);
402
+ const materialExists = node.getScene().getMaterialById(materialId);
384
403
  const hasMissingMaterial = has(node.metadata, missingMaterialMetadataName);
385
404
  const deferMaterialCreation = !materialExists && !node.isEnabled();
386
405
  if (deferMaterialCreation) {
@@ -391,9 +410,9 @@ const setMaterial = function (
391
410
  addMissingMaterialObserver(node);
392
411
  }
393
412
  } else {
394
- // create material an apply it when textures have been loaded
395
- const material = getOrCreateMaterial(scene, materialId, variant);
396
- applyMaterialAfterTexturesLoaded(material, node);
413
+ // create material and apply it when textures have been loaded
414
+ const material = getOrCreateMaterial(node.getScene(), materialId, variant);
415
+ applyMaterial(material, node).then(() => emitter.emit(Event.MESH_MATERIAL_APPLIED, node, material));
397
416
 
398
417
  if (hasMissingMaterial) {
399
418
  delete node.metadata[missingMaterialMetadataName];
@@ -403,7 +422,7 @@ const setMaterial = function (
403
422
  // recursively set materials on children (if desired)
404
423
  if (deep) {
405
424
  for (const child of node.getChildTransformNodes(true)) {
406
- setMaterial(scene, child, materialId, deep, variant);
425
+ setMaterial(child, materialId, deep, variant);
407
426
  }
408
427
  }
409
428
  };
@@ -429,10 +448,10 @@ const getOrCreateMaterial = function (scene: Scene, materialId: string, variant?
429
448
  };
430
449
 
431
450
  /**
432
- * Waits until the materials textures are loaded and sets the material on the node if there is no newer "set material"
433
- * request
451
+ * Waits until the materials textures are loaded and shaders are compiled.
452
+ * Then sets the material on the node if there is no newer "set material" request
434
453
  */
435
- const applyMaterialAfterTexturesLoaded = async function (material: Material, node: AbstractMesh) {
454
+ const applyMaterial = async function (material: Material, node: AbstractMesh) {
436
455
  // set current material id as last valid id, in this case all previously set materials on the node will be invalidated
437
456
  injectNodeMetadata(node, { [materialWaitingToBeSetMetadataName]: material.id }, false);
438
457
 
@@ -451,7 +470,7 @@ const applyMaterialAfterTexturesLoaded = async function (material: Material, nod
451
470
  await Promise.all([promTexturesReady, promMaterialCompiled]);
452
471
 
453
472
  // textures ready, now check if the material is still up-to-date
454
- if (material.id === node.metadata[materialWaitingToBeSetMetadataName]) {
473
+ if (material.id === node.metadata?.[materialWaitingToBeSetMetadataName]) {
455
474
  node.material = material;
456
475
  delete node.metadata[materialWaitingToBeSetMetadataName];
457
476
  }
@@ -505,6 +524,7 @@ const setMaterialColor = function (node: TransformNode, color: Color3, deep: boo
505
524
  default:
506
525
  throw new Error(`Setting color for material of instance "${materialCls}" not implemented (yet).`);
507
526
  }
527
+ setMaterial(node, node.material.id, false);
508
528
  }
509
529
  if (deep) {
510
530
  node.getChildTransformNodes(true).forEach(child => setMaterialColor(child, color, deep));
@@ -529,6 +549,7 @@ const setMaterialTexture = function (node: TransformNode, texture: Texture, deep
529
549
  default:
530
550
  throw new Error(`Setting texture for material of instance "${materialCls}" not implemented (yet).`);
531
551
  }
552
+ setMaterial(node, node.material.id, false);
532
553
  }
533
554
  if (deep) {
534
555
  node.getChildTransformNodes(true).forEach(child => setMaterialTexture(child, texture, deep));
@@ -550,6 +571,7 @@ const setMaterialMetallness = function (node: TransformNode, metallness: number,
550
571
  default:
551
572
  throw new Error(`Setting metallness for material of instance "${materialCls}" not implemented (yet).`);
552
573
  }
574
+ setMaterial(node, node.material.id, false);
553
575
  }
554
576
  if (deep) {
555
577
  node.getChildTransformNodes(true).forEach(child => setMaterialMetallness(child, metallness, deep));
@@ -574,6 +596,7 @@ const setMaterialRoughness = function (node: TransformNode, roughness: number, d
574
596
  default:
575
597
  throw new Error(`Setting roughness for material of instance "${materialCls}" not implemented (yet).`);
576
598
  }
599
+ setMaterial(node, node.material.id, false);
577
600
  }
578
601
  if (deep) {
579
602
  node.getChildTransformNodes(true).forEach(child => setMaterialRoughness(child, roughness, deep));
@@ -704,6 +727,56 @@ const isTextureWithOnLoadObservable = function (texture: BaseTexture): texture i
704
727
  return !!(texture as BaseTextureWithOnLoadObservable).onLoadObservable;
705
728
  };
706
729
 
730
+ /**
731
+ * @param objects
732
+ * @param tagMapping
733
+ */
734
+ const mapTags = function (objects: object[], tagMapping: TagMapping): string[] {
735
+ let affectedTags: string[] = [];
736
+ for (const object of objects) {
737
+ const oldTags = Object.keys(Tags.GetTags(object, false) ?? {});
738
+ const mappedTags = oldTags.map(t => tagMapping[t] || t);
739
+ Tags.RemoveTagsFrom(object, oldTags.join(' '));
740
+ Tags.AddTagsTo(object, mappedTags.join(' '));
741
+ affectedTags = [...affectedTags, ...mappedTags];
742
+ }
743
+ return uniq(affectedTags);
744
+ };
745
+
746
+ /**
747
+ * Gets an array of ids for nodeIds that exist in both TransformNode arrays.
748
+ * @param nodes1
749
+ * @param nodes2
750
+ * @param predicate
751
+ */
752
+ const intersectingNodeNames = function (nodes1: Node[], nodes2: Node[], predicate?: (node: Node) => boolean): string[] {
753
+ const nodeNames1 = nodes1.filter(n => !predicate || predicate(n)).map(n => n.name);
754
+ const nodesNames2 = nodes2.filter(n => !predicate || predicate(n)).map(n => n.name);
755
+ return nodeNames1.filter(n1 => nodesNames2.includes(n1));
756
+ };
757
+
758
+ /**
759
+ * Gets an array of ids for duplicate nodeIds in given node array.
760
+ * @param nodes
761
+ * @param predicate
762
+ */
763
+ const duplicateNodeNames = function (nodes: Node[], predicate?: (node: Node) => boolean): string[] {
764
+ const nodeNames = nodes.filter(n => !predicate || predicate(n)).map(n => n.name);
765
+ return nodeNames.filter((v, i, self) => self.indexOf(v) !== i);
766
+ };
767
+
768
+ /**
769
+ * Reports duplicate nodeIds.
770
+ * @param nodeNames
771
+ */
772
+ const reportDuplicateNodeNames = function (nodeNames: string[]): void {
773
+ if (nodeNames.length > 0) {
774
+ const warn = `There are duplicate nodeNames: ${nodeNames.join(', ')}`;
775
+ console.warn(`!!! Warning !!!\n${warn}`);
776
+ window.Cbn?.Assets.reportDuplicateNodeName(nodeNames);
777
+ }
778
+ };
779
+
707
780
  export {
708
781
  getRootNode,
709
782
  isTextureWithOnLoadObservable,
@@ -713,9 +786,10 @@ export {
713
786
  cloneNodeWithParents,
714
787
  cloneTransformNodeMaterial,
715
788
  getOrCreateMaterial,
716
- applyMaterialAfterTexturesLoaded,
789
+ applyMaterial,
717
790
  injectNodeMetadata,
718
791
  assertTransformNode,
792
+ assertMeshCapability,
719
793
  activateTransformNode,
720
794
  deactivateTransformNode,
721
795
  enableNodeWithParents,
@@ -736,4 +810,8 @@ export {
736
810
  changeEnvironment,
737
811
  backgroundDomeName,
738
812
  envHelperMetadataName,
813
+ mapTags,
814
+ intersectingNodeNames,
815
+ duplicateNodeNames,
816
+ reportDuplicateNodeNames,
739
817
  };
@@ -2,6 +2,7 @@
2
2
  type Viewer = import('../classes/viewer').Viewer;
3
3
  type Variant = import('../classes/variant').Variant;
4
4
  type VariantInstance = import('../classes/variantInstance').VariantInstance;
5
+ type VariantParameterizable = import('../classes/variantParameterizable').VariantParameterizable;
5
6
  /**
6
7
  * Alias for {@link Element} which can be used to prevent name clashes with the web APIs
7
8
  * [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) class
@@ -11,6 +12,8 @@ type DottedPath = import('../classes/dottedPath').DottedPath;
11
12
  type ViewerLight = import('../classes/viewerLight').ViewerLight;
12
13
  type SceneManager = import('../manager/sceneManager').SceneManager;
13
14
 
15
+ type FuzzyMap<K, V> = import('../classes/fuzzyMap').FuzzyMap<K, V>;
16
+
14
17
  // global accessible types imported from BabylonJS
15
18
  type Scene = import('@babylonjs/core/scene').Scene;
16
19
  type Vector3 = import('@babylonjs/core/Maths/math.vector').Vector3;
@@ -42,6 +45,10 @@ type IExportOptions = import('@babylonjs/serializers/glTF/2.0').IExportOptions;
42
45
 
43
46
  type EventEmitter = import('eventemitter3');
44
47
 
48
+ type Undefinable<T> = T | undefined;
49
+
50
+ type Nullable<T> = T | null;
51
+
45
52
  // some more global accessible types
46
53
  type PathDefinitions = {
47
54
  include: string[];
@@ -368,7 +375,13 @@ type ParsedParameterBag = {
368
375
 
369
376
  type DottedPathArgument = string | string[] | DottedPath;
370
377
 
371
- type ParameterObserver = (object: any, oldValue: ParameterValue, newValue: ParameterValue) => void;
378
+ type ParameterObserverResult = any;
379
+
380
+ type ParameterObserver = (
381
+ payload: any,
382
+ oldValue: Undefinable<ParameterValue>,
383
+ newValue: ParameterValue
384
+ ) => ParameterObserverResult;
372
385
 
373
386
  type PlacementDefinitions = {
374
387
  [name: string]: PlacementDefinition;
@@ -435,3 +448,45 @@ type SpecGenerationData = {
435
448
  name: string;
436
449
  url: string;
437
450
  };
451
+
452
+ type TagMapping = {
453
+ [tagName: string]: string;
454
+ };
455
+
456
+ type TagManagerSubject = {
457
+ tagName?: string;
458
+ nodeName?: string;
459
+ };
460
+
461
+ type TagManagerParameterObserver = (payload: TagManagerParameterObserverPayload) => ParameterObserverResult;
462
+
463
+ type TagManagerParameterBag = FuzzyMap<TagManagerSubject, ParameterBag>;
464
+
465
+ type TagManagerParameterObserverBag = Map<string, TagManagerParameterObserver>;
466
+
467
+ type TagManagerParameterObserverPayload = {
468
+ subject: TagManagerSubject;
469
+ nodes: TransformNode[];
470
+ newValue: ParameterValue;
471
+ oldValue: Undefinable<ParameterValue>;
472
+ };
473
+
474
+ type TagManagerParameterValue = {
475
+ tagName?: string;
476
+ nodeName?: string;
477
+ parameterName: string;
478
+ value: ParameterValue;
479
+ };
480
+
481
+ type NodeNamingStrategyPayload = {
482
+ variantInstance: VariantInstance;
483
+ variant: Variant;
484
+ variantParameterizable: VariantParameterizable;
485
+ };
486
+
487
+ type NodeNamingStrategyHandler = (node: TransformNode, payload: NodeNamingStrategyPayload) => string;
488
+
489
+ type NodeNamingStrategy = {
490
+ handler: NodeNamingStrategyHandler;
491
+ payload: NodeNamingStrategyPayload;
492
+ };
@@ -1,4 +1,5 @@
1
- import { applyMaterialAfterTexturesLoaded, getOrCreateMaterial, injectNodeMetadata } from './babylonHelper';
1
+ import { Event, emitter } from '../classes/event';
2
+ import { applyMaterial, getOrCreateMaterial, injectNodeMetadata } from './babylonHelper';
2
3
  import { sleep } from './resourceHelper';
3
4
  import { ISceneLoaderPlugin } from '@babylonjs/core/Loading/sceneLoader';
4
5
  import { Material } from '@babylonjs/core/Materials/material';
@@ -67,7 +68,9 @@ export const getMaterialPostLoadObserver = function (concerningMesh: Mesh) {
67
68
  const missingMatId = concerningMesh.metadata[missingMaterialMetadataName];
68
69
  // get material and apply it on the concerning mesh after all textures have been loaded
69
70
  const material = getOrCreateMaterial(concerningMesh.getScene(), missingMatId);
70
- applyMaterialAfterTexturesLoaded(material, concerningMesh);
71
+ applyMaterial(material, concerningMesh).then(() =>
72
+ emitter.emit(Event.MESH_MATERIAL_APPLIED, concerningMesh, material)
73
+ );
71
74
  // since the material is there now, we do not need the related metadata tag anymore
72
75
  delete concerningMesh.metadata[missingMaterialMetadataName];
73
76
 
@@ -134,6 +137,22 @@ export const addMissingMaterialObserver = function (node: BjsNode) {
134
137
  }
135
138
  };
136
139
 
140
+ export const removeMissingMaterialObserver = function (node: BjsNode) {
141
+ // set the concerning node, i.e. the node the observer should check for missing material.
142
+ // for instanced meshes, we want the sourcemesh here.
143
+ const concerningNode = node instanceof InstancedMesh ? node.sourceMesh : (node as Mesh);
144
+ let currNode: Nullable<BjsNode> = node;
145
+ while (currNode) {
146
+ enableObserverMap[concerningNode.id]?.forEach(entry => {
147
+ if (entry.currNodeId === currNode?.id) {
148
+ currNode.onEnabledStateChangedObservable.remove(entry.observer);
149
+ }
150
+ });
151
+ currNode = currNode.parent;
152
+ }
153
+ delete enableObserverMap[concerningNode.id];
154
+ };
155
+
137
156
  /**
138
157
  * Look up the provided materials (see library import) and create and return one if found.
139
158
  *
package/src/dev.ts CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  afterBootstrap,
4
4
  beforeBootstrap,
5
5
  createSpec,
6
+ createTagManagerParameterValues,
6
7
  createUIelements,
7
8
  getMaterial,
8
9
  mockMaterials,
@@ -33,6 +34,7 @@ window.Cbn = {
33
34
  assertMaterialExists(materialId: string): boolean {
34
35
  return true;
35
36
  },
37
+ reportDuplicateNodeName(nodeNameOrArrayOfNodeNames: string | string[]): void {},
36
38
  },
37
39
  };
38
40
 
@@ -50,7 +52,7 @@ async function bootstrapViewer() {
50
52
  const viewer = new Viewer(canvas, createSpec());
51
53
  await beforeBootstrap(viewer);
52
54
  try {
53
- await viewer.bootstrap();
55
+ await viewer.bootstrap(createTagManagerParameterValues(viewer));
54
56
  } catch (e) {
55
57
  console.error(e);
56
58
  }
package/src/index.ts CHANGED
@@ -17,6 +17,7 @@ import { ViewerLight } from './api/classes/viewerLight';
17
17
  import { AnimationManager } from './api/manager/animationManager';
18
18
  import { GltfExportManager } from './api/manager/gltfExportManager';
19
19
  import { SceneManager } from './api/manager/sceneManager';
20
+ import { TagManager } from './api/manager/tagManager';
20
21
  import { VariantInstanceManager } from './api/manager/variantInstanceManager';
21
22
  import { SpecStorage } from './api/store/specStorage';
22
23
  import * as BabylonHelper from './api/util/babylonHelper';
@@ -95,4 +96,5 @@ export {
95
96
  BabylonHelper,
96
97
  GltfExportManager,
97
98
  SpecStorage,
99
+ TagManager,
98
100
  };
package/src/types.d.ts CHANGED
@@ -23,6 +23,13 @@ interface Window {
23
23
  * @param materialId
24
24
  */
25
25
  assertMaterialExists(materialId: string): boolean;
26
+
27
+ /**
28
+ * Warns user about duplicate nodeNames on scene.
29
+ *
30
+ * @param nodeNameOrArrayOfNodeNames
31
+ */
32
+ reportDuplicateNodeName(nodeNameOrArrayOfNodeNames: string | string[]): void;
26
33
  };
27
34
  };
28
35
  }