@combeenation/3d-viewer 8.0.0 → 9.0.0

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 (49) hide show
  1. package/dist/lib-cjs/api/classes/element.js +20 -25
  2. package/dist/lib-cjs/api/classes/element.js.map +1 -1
  3. package/dist/lib-cjs/api/classes/parameter.d.ts +46 -0
  4. package/dist/lib-cjs/api/classes/parameter.js +103 -0
  5. package/dist/lib-cjs/api/classes/parameter.js.map +1 -1
  6. package/dist/lib-cjs/api/classes/variant.d.ts +8 -0
  7. package/dist/lib-cjs/api/classes/variant.js +17 -5
  8. package/dist/lib-cjs/api/classes/variant.js.map +1 -1
  9. package/dist/lib-cjs/api/classes/viewer.d.ts +2 -2
  10. package/dist/lib-cjs/api/classes/viewer.js +9 -8
  11. package/dist/lib-cjs/api/classes/viewer.js.map +1 -1
  12. package/dist/lib-cjs/api/classes/viewerLight.js +1 -1
  13. package/dist/lib-cjs/api/classes/viewerLight.js.map +1 -1
  14. package/dist/lib-cjs/api/manager/gltfExportManager.d.ts +1 -0
  15. package/dist/lib-cjs/api/manager/gltfExportManager.js +7 -2
  16. package/dist/lib-cjs/api/manager/gltfExportManager.js.map +1 -1
  17. package/dist/lib-cjs/api/manager/tagManager.d.ts +25 -23
  18. package/dist/lib-cjs/api/manager/tagManager.js +176 -98
  19. package/dist/lib-cjs/api/manager/tagManager.js.map +1 -1
  20. package/dist/lib-cjs/api/manager/variantInstanceManager.d.ts +1 -1
  21. package/dist/lib-cjs/api/manager/variantInstanceManager.js +5 -7
  22. package/dist/lib-cjs/api/manager/variantInstanceManager.js.map +1 -1
  23. package/dist/lib-cjs/api/util/babylonHelper.d.ts +5 -3
  24. package/dist/lib-cjs/api/util/babylonHelper.js +51 -14
  25. package/dist/lib-cjs/api/util/babylonHelper.js.map +1 -1
  26. package/dist/lib-cjs/api/util/globalTypes.d.ts +26 -4
  27. package/dist/lib-cjs/api/util/resourceHelper.js +9 -1
  28. package/dist/lib-cjs/api/util/resourceHelper.js.map +1 -1
  29. package/dist/lib-cjs/api/util/sceneLoaderHelper.js +1 -1
  30. package/dist/lib-cjs/api/util/sceneLoaderHelper.js.map +1 -1
  31. package/dist/lib-cjs/api/util/structureHelper.d.ts +6 -6
  32. package/dist/lib-cjs/api/util/structureHelper.js +31 -28
  33. package/dist/lib-cjs/api/util/structureHelper.js.map +1 -1
  34. package/dist/lib-cjs/buildinfo.json +1 -1
  35. package/dist/lib-cjs/commonjs.tsconfig.tsbuildinfo +1 -1
  36. package/package.json +3 -2
  37. package/src/api/classes/element.ts +24 -34
  38. package/src/api/classes/parameter.ts +109 -0
  39. package/src/api/classes/variant.ts +20 -6
  40. package/src/api/classes/viewer.ts +12 -14
  41. package/src/api/classes/viewerLight.ts +2 -2
  42. package/src/api/manager/gltfExportManager.ts +8 -3
  43. package/src/api/manager/tagManager.ts +209 -122
  44. package/src/api/manager/variantInstanceManager.ts +5 -8
  45. package/src/api/util/babylonHelper.ts +60 -13
  46. package/src/api/util/globalTypes.ts +32 -4
  47. package/src/api/util/resourceHelper.ts +10 -3
  48. package/src/api/util/sceneLoaderHelper.ts +2 -2
  49. package/src/api/util/structureHelper.ts +29 -27
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@combeenation/3d-viewer",
3
- "version": "8.0.0",
3
+ "version": "9.0.0",
4
4
  "description": "Combeenation 3D Viewer",
5
5
  "homepage": "https://github.com/Combeenation/3d-viewer#readme",
6
6
  "bugs": {
@@ -32,7 +32,7 @@
32
32
  "dist-full": "npm run clean-dist && npm run lint && cross-env NODE_ENV='production' webpack --config build/webpack.conf.js --progress && npm run replace-version",
33
33
  "docs-local": "typedoc --tsconfig tsconfig.json --media doc/assets --out docs-local",
34
34
  "docs-publish": "typedoc --tsconfig tsconfig.json --media doc/assets --out docs",
35
- "format": "prettier --write .",
35
+ "format": "prettier --write ./src",
36
36
  "generate-profile": "cross-env NODE_ENV='dev' webpack --config build/webpack.conf.js --profile --json > dist/webpack-stats.json",
37
37
  "lint": "eslint src/**",
38
38
  "pack": "npm run dist-cjs && npm pack",
@@ -52,6 +52,7 @@
52
52
  "@babylonjs/serializers": "5.27.1",
53
53
  "eventemitter3": "4.0.7",
54
54
  "gsap": "3.11.2",
55
+ "is-svg": "^5.0.0",
55
56
  "lodash-es": "4.17.21"
56
57
  },
57
58
  "devDependencies": {
@@ -7,8 +7,9 @@ import {
7
7
  cloneTransformNode,
8
8
  cloneTransformNodeMaterial,
9
9
  deactivateTransformNode as deactivate,
10
+ drawPaintableOnMaterial,
10
11
  getClientRectFromMesh,
11
- injectNodeMetadata,
12
+ injectMetadata,
12
13
  mapToDottedNodes,
13
14
  removeFromHighlightLayer,
14
15
  removeFromShadowGenerator,
@@ -16,7 +17,6 @@ import {
16
17
  setMaterialColor,
17
18
  setMaterialMetallness,
18
19
  setMaterialRoughness,
19
- setMaterialTexture,
20
20
  setReceiveShadows,
21
21
  transformTransformNode,
22
22
  } from '../util/babylonHelper';
@@ -31,13 +31,12 @@ import { HighlightLayer } from '@babylonjs/core/Layers/highlightLayer';
31
31
  import { ShadowGenerator } from '@babylonjs/core/Lights/Shadows/shadowGenerator';
32
32
  import { Light } from '@babylonjs/core/Lights/light';
33
33
  import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial';
34
- import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
35
34
  import { Material } from '@babylonjs/core/Materials/material';
36
35
  import { Color3 } from '@babylonjs/core/Maths/math.color';
37
36
  import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
38
37
  import { Mesh } from '@babylonjs/core/Meshes/mesh';
39
38
  import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
40
- import { has, isArray, isNumber, isPlainObject, merge, union } from 'lodash-es';
39
+ import { has, isArray, isNumber, merge, union } from 'lodash-es';
41
40
 
42
41
  /**
43
42
  * An {@link Element} of a {@link Variant}. Acts as a container for diverse definitions. Lives only in the context of a
@@ -320,7 +319,7 @@ export class Element extends VariantParameterizable {
320
319
  }
321
320
  if (!has(node.metadata, 'dirty.material.texture')) {
322
321
  // inject initial value and mark as dirty
323
- injectNodeMetadata(node, { dirty: { material: { texture: true } } });
322
+ injectMetadata(node, { dirty: { material: { texture: true } } });
324
323
  }
325
324
  } else if (!node.material) {
326
325
  // paintables should also work if no material is assigned to the node per default
@@ -338,35 +337,26 @@ export class Element extends VariantParameterizable {
338
337
  // Removing this line will most likely break existing configurators, so be cautios!
339
338
  node.material.transparencyMode = Material.MATERIAL_ALPHATESTANDBLEND;
340
339
 
341
- // consider width and height of the paintable
342
- const widthAndHeight = {
343
- width: imageSource.width,
344
- height: imageSource.height,
345
- };
346
340
  const paintableDefinition = this.getPaintableDefinition(paintable);
347
341
  if (isNumber(paintableDefinition.textureOptions)) {
348
- widthAndHeight.width = paintableDefinition.textureOptions;
349
- widthAndHeight.height = paintableDefinition.textureOptions;
350
- } else if (isPlainObject(paintableDefinition.textureOptions)) {
351
- widthAndHeight.width = paintableDefinition.textureOptions.width;
352
- widthAndHeight.height = paintableDefinition.textureOptions.height;
342
+ // convert into object to satisfy the interface of `drawPaintableOnMaterial`
343
+ paintableDefinition.textureOptions = {
344
+ width: paintableDefinition.textureOptions,
345
+ height: paintableDefinition.textureOptions,
346
+ };
353
347
  }
354
348
 
355
- // create dynamic texture on which the image can be drawn
356
- const texture = new DynamicTexture(
357
- `${this.id}.${paintable}.texture`,
358
- widthAndHeight,
359
- this.variant.viewer.scene,
360
- false
361
- );
362
-
363
- // draw image on texture
364
- const ctx = texture.getContext();
365
- ctx.drawImage(imageSource, 0, 0);
366
- texture.update(false);
349
+ // convert texture size options into scale values, as the scaling is now done via uvScale properties
350
+ const paintableOptions: PaintableOptions = {};
351
+ if (paintableDefinition.textureOptions.width) {
352
+ paintableOptions.uScale = paintableDefinition.textureOptions.width / (imageSource.width as number);
353
+ }
354
+ if (paintableDefinition.textureOptions.height) {
355
+ paintableOptions.vScale = paintableDefinition.textureOptions.height / (imageSource.height as number);
356
+ }
367
357
 
368
- // finally apply the texture on the desired node material
369
- setMaterialTexture(node, texture, false);
358
+ // forward to generic "paintable" call
359
+ drawPaintableOnMaterial(node.material, imageSource, this.variant.viewer.scene, paintableOptions);
370
360
 
371
361
  return this;
372
362
  }
@@ -435,12 +425,12 @@ export class Element extends VariantParameterizable {
435
425
  }
436
426
  // The default behaviour.
437
427
  element.nodes.forEach(node => {
438
- injectNodeMetadata(node, { visibility: node.isEnabled() });
428
+ injectMetadata(node, { visibility: node.isEnabled() });
439
429
  activate(node);
440
430
  });
441
431
  } else if (visible === false) {
442
432
  element.nodes.forEach(node => {
443
- injectNodeMetadata(node, { visibility: node.isEnabled() });
433
+ injectMetadata(node, { visibility: node.isEnabled() });
444
434
  deactivate(node);
445
435
  });
446
436
  }
@@ -514,7 +504,7 @@ export class Element extends VariantParameterizable {
514
504
  }
515
505
  if (!has(node.metadata, 'dirty.material.color')) {
516
506
  // inject initial value and mark as dirty
517
- injectNodeMetadata(node, { dirty: { material: { color: oldValue } } });
507
+ injectMetadata(node, { dirty: { material: { color: oldValue } } });
518
508
  }
519
509
  }
520
510
  setMaterialColor(node, color);
@@ -532,7 +522,7 @@ export class Element extends VariantParameterizable {
532
522
  }
533
523
  if (!has(node.metadata, 'dirty.material.metallness')) {
534
524
  // inject initial value and mark as dirty
535
- injectNodeMetadata(node, { dirty: { material: { metallness: oldValue } } });
525
+ injectMetadata(node, { dirty: { material: { metallness: oldValue } } });
536
526
  }
537
527
  }
538
528
  setMaterialMetallness(node, metallness);
@@ -550,7 +540,7 @@ export class Element extends VariantParameterizable {
550
540
  }
551
541
  if (!has(node.metadata, 'dirty.material.roughness')) {
552
542
  // inject initial value and mark as dirty
553
- injectNodeMetadata(node, { dirty: { material: { roughness: oldValue } } });
543
+ injectMetadata(node, { dirty: { material: { roughness: oldValue } } });
554
544
  }
555
545
  }
556
546
  setMaterialRoughness(node, roughness);
@@ -139,6 +139,45 @@ export class Parameter {
139
139
  */
140
140
  public static readonly ROTATION = 'rotation';
141
141
 
142
+ /**
143
+ * Mutates the color.
144
+ *
145
+ * Scopes:
146
+ * * {@link Material} via {@link TagManager}
147
+ *
148
+ * @parser {@link parseColor}
149
+ */
150
+ public static readonly COLOR = 'color';
151
+
152
+ /**
153
+ * Mutates the metallic.
154
+ *
155
+ * Scopes:
156
+ * * {@link Material} via {@link TagManager}
157
+ *
158
+ * @parser {@link parseNumber}
159
+ */
160
+ public static readonly METALLIC = 'metallic';
161
+
162
+ /**
163
+ * Mutates the texture of a material, based on an svg string, image path or image data.
164
+ *
165
+ * Scopes:
166
+ * * {@link Material} via {@link TagManager}
167
+ *
168
+ */
169
+ public static readonly PAINTABLE = 'paintable';
170
+
171
+ /**
172
+ * Mutates the roughness.
173
+ *
174
+ * Scopes:
175
+ * * {@link Material} via {@link TagManager}
176
+ *
177
+ * @parser {@link parseNumber}
178
+ */
179
+ public static readonly ROUGHNESS = 'roughness';
180
+
142
181
  /**
143
182
  * Mutates whether a shadow should be casted or not.
144
183
  *
@@ -549,6 +588,76 @@ export class Parameter {
549
588
  return parseFloat(value.toString());
550
589
  }
551
590
 
591
+ /**
592
+ * Parses string defintion of a paintable into a paintable object.
593
+ * Here are some examples:
594
+ * - '{ "src": "pathToCertain.jpg", "uScale": 0.5 }' => default definition as JSON object
595
+ * - 'pathToCertain.jpg' => short hand definition, only contains source string
596
+ * - '{ "src": "pathToCertain.jpg", "uScale": -1, "vScale": -1, "uOffset": 0, "vOffset": 0 }' => full content,
597
+ * paintable texture is flipped in both directions
598
+ * - '<svg>...</svg>' => SVG content can be used directly
599
+ * - { "src": "<svg>...</svg>", "uScale": 0.5 } => SVG in src property works as well
600
+ */
601
+ public static parsePaintableValue(value: ParameterValue): PaintableValue {
602
+ if (!isString(value)) {
603
+ throw new Error(`Unable to parse "${value}" to a PaintableValue: not a string.`);
604
+ }
605
+
606
+ const paintableValue: PaintableValue = { src: '' };
607
+ let valObj: { [key: string]: any } | null = null;
608
+
609
+ try {
610
+ valObj = JSON.parse(value);
611
+ } catch {
612
+ // use string directly
613
+ paintableValue.src = value;
614
+
615
+ if (value.startsWith('{')) {
616
+ // seems like the user tried to use a JSON string, as the input starts with {
617
+ throw new Error(`Unable to parse "${value}" to a PaintableValue: not a valid JSON string.`);
618
+ }
619
+ }
620
+
621
+ if (valObj) {
622
+ // input string is JSON, src attribute is required
623
+ if (!valObj.src) {
624
+ throw new Error(`Unable to parse "${value}" to a PaintableValue: property "src" is missing.`);
625
+ }
626
+
627
+ if (!isString(valObj.src)) {
628
+ throw new Error(`Unable to parse "${value}" to a PaintableValue: property "src" is not a string.`);
629
+ }
630
+
631
+ // split src and options
632
+ const { src, ...options } = valObj;
633
+ paintableValue.src = src;
634
+
635
+ // only forward valid paintable options
636
+ const validOptionKeys = ['uScale', 'vScale', 'uOffset', 'vOffset'];
637
+ const { validOptions, invalidKeys } = Object.entries(options).reduce(
638
+ (accRes, [curKey, curValue]) => {
639
+ const isValidKey = validOptionKeys.includes(curKey);
640
+ if (isValidKey) {
641
+ accRes.validOptions[curKey] = curValue;
642
+ } else {
643
+ accRes.invalidKeys.push(curKey);
644
+ }
645
+
646
+ return accRes;
647
+ },
648
+ { validOptions: {} as { [key: string]: any }, invalidKeys: [] as string[] }
649
+ );
650
+
651
+ if (invalidKeys.length) {
652
+ console.warn('parsePaintableValue: invalid paintable options provided: ' + invalidKeys.toString());
653
+ }
654
+
655
+ paintableValue.options = validOptions;
656
+ }
657
+
658
+ return paintableValue;
659
+ }
660
+
552
661
  /**
553
662
  * Parses a string with comma separated values to a list of strings.
554
663
  */
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  deactivateTransformNode,
3
3
  getDottedPathForNode,
4
- injectNodeMetadata,
4
+ injectMetadata,
5
5
  intersectingNodeNames,
6
6
  reportDuplicateNodeNames,
7
7
  } from '../util/babylonHelper';
@@ -244,6 +244,20 @@ export class Variant extends Parameterizable {
244
244
  return this.elements.reduce((a, c) => [...a, ...c.nodesFlat], [] as TransformNode[]);
245
245
  }
246
246
 
247
+ /**
248
+ * The cloned Meshes of all {@link Element}s created for this {@link Variant} flattened.
249
+ */
250
+ get elementMeshesFlat(): Mesh[] {
251
+ return this.elements.reduce((a, c) => [...a, ...c.meshesFlat], [] as Mesh[]);
252
+ }
253
+
254
+ /**
255
+ * The cloned Meshes of all {@link Element}s created for this {@link Variant} flattened.
256
+ */
257
+ get elementAbstractMeshesFlat(): AbstractMesh[] {
258
+ return this.elements.reduce((a, c) => [...a, ...c.abstractMeshesFlat], [] as AbstractMesh[]);
259
+ }
260
+
247
261
  /**
248
262
  * All {@link Element}s from this {@link Variant}'s parents.
249
263
  */
@@ -662,16 +676,16 @@ export class Variant extends Parameterizable {
662
676
  );
663
677
  nodes.forEach(node => {
664
678
  deactivateTransformNode(node, false);
665
- injectNodeMetadata(node, { dottedPath: getDottedPathForNode(node), originalName: node.name }, false);
679
+ injectMetadata(node, { dottedPath: getDottedPathForNode(node), originalName: node.name }, false);
666
680
  });
667
681
  this.assetContainer.lights.forEach(light => {
668
682
  light.setEnabled(false);
669
- injectNodeMetadata(light, { dottedPath: getDottedPathForNode(light), originalName: light.name }, false);
683
+ injectMetadata(light, { dottedPath: getDottedPathForNode(light), originalName: light.name }, false);
670
684
  this.viewer.scene.addLight(light);
671
685
  });
672
686
  this.assetContainer.cameras.forEach(camera => {
673
687
  camera.setEnabled(false);
674
- injectNodeMetadata(camera, { dottedPath: getDottedPathForNode(camera), originalName: camera.name }, false);
688
+ injectMetadata(camera, { dottedPath: getDottedPathForNode(camera), originalName: camera.name }, false);
675
689
  this.viewer.scene.addCamera(camera);
676
690
  });
677
691
  this.assetContainer.materials.forEach(material => this.viewer.scene.materials.push(material));
@@ -907,7 +921,7 @@ export class Variant extends Parameterizable {
907
921
  // inject node meta to all inherited elements
908
922
  // we do this to inject the deepest and most concrete variant information to all cloned nodes in the tree
909
923
  this.inheritedElements.forEach(element =>
910
- element.nodes.forEach(node => injectNodeMetadata(node, { variant: this, variantParameterizable: element }))
924
+ element.nodes.forEach(node => injectMetadata(node, { variant: this, variantParameterizable: element }))
911
925
  );
912
926
  return this;
913
927
  }
@@ -920,7 +934,7 @@ export class Variant extends Parameterizable {
920
934
  this.viewerLights.push(await ViewerLight.create(this, name));
921
935
  }
922
936
  this.inheritedViewerLights.forEach(viewerLight => {
923
- injectNodeMetadata(viewerLight.light, { variant: this, variantParameterizable: viewerLight });
937
+ injectMetadata(viewerLight.light, { variant: this, variantParameterizable: viewerLight });
924
938
  });
925
939
  return this;
926
940
  }
@@ -10,7 +10,7 @@ import { backgroundDomeName, envHelperMetadataName } from '../util/babylonHelper
10
10
  import { debounce, loadJavascript, loadJson } from '../util/resourceHelper';
11
11
  import { getCustomCbnBabylonLoaderPlugin } from '../util/sceneLoaderHelper';
12
12
  import { replaceDots } from '../util/stringHelper';
13
- import { isMeshIncludedInExclusionList } from '../util/structureHelper';
13
+ import { isNodeIncludedInExclusionList } from '../util/structureHelper';
14
14
  import * as Index from './../../index';
15
15
  import { AnimationInterface } from './animationInterface';
16
16
  import { Event } from './event';
@@ -35,7 +35,7 @@ import { Mesh } from '@babylonjs/core/Meshes/mesh';
35
35
  import { ScreenshotTools } from '@babylonjs/core/Misc/screenshotTools';
36
36
  import { WebXRSessionManager } from '@babylonjs/core/XR/webXRSessionManager';
37
37
  import { Scene } from '@babylonjs/core/scene';
38
- import { isArray, isString } from 'lodash-es';
38
+ import { isString } from 'lodash-es';
39
39
 
40
40
  /**
41
41
  * The main exposed object. This is the entry point into the application
@@ -308,6 +308,10 @@ export class Viewer extends EventBroadcaster {
308
308
  indexJson.scene = sceneJson;
309
309
  }
310
310
  this._scene = await this.initScene();
311
+ // set initial tag manager parameter values
312
+ if (tagManagerParameterValues) {
313
+ await this.tagManager.setParameterValues(tagManagerParameterValues);
314
+ }
311
315
  // create instance manager
312
316
  this._variantInstances = await VariantInstanceManager.create(this);
313
317
  // create optional default instances
@@ -317,7 +321,7 @@ export class Viewer extends EventBroadcaster {
317
321
  indexJson.setup = setupJson;
318
322
  }
319
323
  this.printInstanceDefinitions(indexJson.setup);
320
- await this.createVariantInstances(tagManagerParameterValues);
324
+ await this.createVariantInstances();
321
325
  }
322
326
  this.broadcastEvent(Event.VARIANT_INSTANCES_READY, this);
323
327
  // create gltf export manager
@@ -486,7 +490,7 @@ export class Viewer extends EventBroadcaster {
486
490
  // ignore meshes with infinite distance, typically these are sky boxes
487
491
  const hasInfiniteDistance = mesh.infiniteDistance;
488
492
  // ignore excluded meshes
489
- const isExcluded = excludeGeometry ? isMeshIncludedInExclusionList(mesh as Mesh, excludeGeometry) : false;
493
+ const isExcluded = excludeGeometry ? isNodeIncludedInExclusionList(mesh, excludeGeometry) : false;
490
494
  return isEnabled && isNotBBoxMesh && hasValidBBoxInfo && !hasInfiniteDistance && !isExcluded;
491
495
  })
492
496
  .reduce(
@@ -579,7 +583,7 @@ export class Viewer extends EventBroadcaster {
579
583
  * Resets everything by calling {@link destroy} to clear all references and {@link bootstrap} to setup a clean
580
584
  * environment
581
585
  */
582
- public async reset(tagManagerParameterValues: TagManagerParameterValue[]): Promise<Viewer> {
586
+ public async reset(tagManagerParameterValues?: TagManagerParameterValue[]): Promise<Viewer> {
583
587
  await this.destroy();
584
588
  return this.bootstrap(tagManagerParameterValues);
585
589
  }
@@ -723,7 +727,7 @@ export class Viewer extends EventBroadcaster {
723
727
  this._cloneMaterialsOnMutation = sceneJson.cloneMaterialsOnMutation;
724
728
  }
725
729
  // register observers for tag manager
726
- this.tagManager.registerNewTransformNodeObservers(scene);
730
+ this.tagManager.registerNewObjectObservers(scene);
727
731
  this.broadcastEvent(Event.SCENE_PROCESSING_END, scene);
728
732
  return scene;
729
733
  }
@@ -743,15 +747,10 @@ export class Viewer extends EventBroadcaster {
743
747
  /**
744
748
  * Batch creation of multiple {@link VariantInstance} objects with a {@link SetupJson} object passed
745
749
  */
746
- protected async createVariantInstances(
747
- tagManagerParameterValues?: TagManagerParameterValue[]
748
- ): Promise<VariantInstance[]> {
750
+ protected async createVariantInstances(): Promise<VariantInstance[]> {
749
751
  const setupJson = SpecStorage.get<SetupJson>('setup');
750
752
  const instances: VariantInstance[] = [];
751
753
  for (const instanceDefinition of setupJson.instances) {
752
- if (isArray(tagManagerParameterValues)) {
753
- instanceDefinition.tagManagerParameterValues = tagManagerParameterValues;
754
- }
755
754
  // don't create the instance right away if `lazy` is set, register it for later creation (on first usage) instead
756
755
  // however if the variant should be `visible` by default, `lazy` loading doesn't make sense and should therefore
757
756
  // be overruled by the `visible` flag
@@ -762,8 +761,7 @@ export class Viewer extends EventBroadcaster {
762
761
  const instance = await this.variantInstances.create(
763
762
  instanceDefinition.variant,
764
763
  instanceDefinition.name,
765
- instanceDefinition.parameters,
766
- instanceDefinition.tagManagerParameterValues
764
+ instanceDefinition.parameters
767
765
  );
768
766
  instances.push(instance);
769
767
  }
@@ -3,7 +3,7 @@ import {
3
3
  disableNodeWithParents,
4
4
  enableNodeWithParents,
5
5
  getRootNode,
6
- injectNodeMetadata,
6
+ injectMetadata,
7
7
  transformTransformNode,
8
8
  } from './../util/babylonHelper';
9
9
  import { DottedPath } from './dottedPath';
@@ -294,7 +294,7 @@ export class ViewerLight extends VariantParameterizable {
294
294
  // Create pseudo parent since lights do not implement mutations like "rotation" by itself.
295
295
  babylonLight.parent = new TransformNode('__light__', this.variant.viewer.scene, true);
296
296
  }
297
- injectNodeMetadata(babylonLight.parent, {
297
+ injectMetadata(babylonLight.parent, {
298
298
  variant: this.variant,
299
299
  variantParameterizable: this,
300
300
  });
@@ -1,5 +1,6 @@
1
1
  import { Viewer } from '../classes/viewer';
2
- import { isMeshIncludedInExclusionList } from '../util/structureHelper';
2
+ import { injectMetadata } from '../util/babylonHelper';
3
+ import { isNodeIncludedInExclusionList } from '../util/structureHelper';
3
4
  import { Engine } from '@babylonjs/core/Engines/engine';
4
5
  import { SceneLoader } from '@babylonjs/core/Loading/sceneLoader';
5
6
  import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial';
@@ -15,6 +16,7 @@ import { has, merge } from 'lodash-es';
15
16
  type MetadataMap = { [key: string]: any };
16
17
  export class GltfExportManager {
17
18
  protected static readonly _CLONED_FROM_MAT_METADATA_PROPERTY = 'clonedFrom';
19
+ public static readonly NAME_BEFORE_EXPORT_METADATA_PROPERTY = 'nameBeforeExport';
18
20
 
19
21
  /**
20
22
  * Constructor.
@@ -111,7 +113,7 @@ export class GltfExportManager {
111
113
  if ((node.name as string).startsWith(Viewer.BOUNDING_BOX_NAME)) {
112
114
  return false;
113
115
  }
114
- if (excluded && node instanceof Mesh && isMeshIncludedInExclusionList(node, excluded)) {
116
+ if (excluded && node instanceof TransformNode && isNodeIncludedInExclusionList(node, excluded)) {
115
117
  return false;
116
118
  }
117
119
  return true;
@@ -268,7 +270,10 @@ export class GltfExportManager {
268
270
  */
269
271
  protected setUniqueMeshNames(scene: Scene): void {
270
272
  const allNodes = scene.getNodes().filter(node => node instanceof TransformNode) as TransformNode[];
271
- allNodes.forEach(currMesh => (currMesh.name = `${currMesh.name}_${currMesh.uniqueId}`));
273
+ allNodes.forEach(currMesh => {
274
+ injectMetadata(currMesh, { [GltfExportManager.NAME_BEFORE_EXPORT_METADATA_PROPERTY]: currMesh.name }, false);
275
+ currMesh.name = `${currMesh.name}_${currMesh.uniqueId}`;
276
+ });
272
277
  }
273
278
 
274
279
  /**