@combeenation/3d-viewer 14.1.0 → 15.1.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 (47) hide show
  1. package/dist/lib-cjs/buildinfo.json +1 -1
  2. package/dist/lib-cjs/commonjs.tsconfig.tsbuildinfo +1 -1
  3. package/dist/lib-cjs/index.d.ts +1 -1
  4. package/dist/lib-cjs/index.js +1 -1
  5. package/dist/lib-cjs/index.js.map +1 -1
  6. package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js +0 -16
  7. package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js.map +1 -1
  8. package/dist/lib-cjs/internal/cloning-helper.d.ts +4 -4
  9. package/dist/lib-cjs/internal/cloning-helper.js +22 -7
  10. package/dist/lib-cjs/internal/cloning-helper.js.map +1 -1
  11. package/dist/lib-cjs/internal/paintable-helper.js +2 -54
  12. package/dist/lib-cjs/internal/paintable-helper.js.map +1 -1
  13. package/dist/lib-cjs/internal/svg-helper.d.ts +4 -0
  14. package/dist/lib-cjs/internal/svg-helper.js +67 -0
  15. package/dist/lib-cjs/internal/svg-helper.js.map +1 -0
  16. package/dist/lib-cjs/internal/tags-helper.d.ts +1 -1
  17. package/dist/lib-cjs/internal/tags-helper.js +10 -8
  18. package/dist/lib-cjs/internal/tags-helper.js.map +1 -1
  19. package/dist/lib-cjs/internal/texture-parameter-helper.d.ts +37 -0
  20. package/dist/lib-cjs/internal/texture-parameter-helper.js +287 -0
  21. package/dist/lib-cjs/internal/texture-parameter-helper.js.map +1 -0
  22. package/dist/lib-cjs/manager/material-manager.d.ts +22 -1
  23. package/dist/lib-cjs/manager/material-manager.js +68 -0
  24. package/dist/lib-cjs/manager/material-manager.js.map +1 -1
  25. package/dist/lib-cjs/manager/model-manager.d.ts +4 -2
  26. package/dist/lib-cjs/manager/model-manager.js +7 -1
  27. package/dist/lib-cjs/manager/model-manager.js.map +1 -1
  28. package/dist/lib-cjs/manager/parameter-manager.d.ts +40 -8
  29. package/dist/lib-cjs/manager/parameter-manager.js +88 -11
  30. package/dist/lib-cjs/manager/parameter-manager.js.map +1 -1
  31. package/dist/lib-cjs/viewer-error.d.ts +3 -0
  32. package/dist/lib-cjs/viewer-error.js +3 -0
  33. package/dist/lib-cjs/viewer-error.js.map +1 -1
  34. package/dist/lib-cjs/viewer.js.map +1 -1
  35. package/package.json +13 -10
  36. package/src/index.ts +1 -1
  37. package/src/internal/cbn-custom-babylon-loader-plugin.ts +2 -21
  38. package/src/internal/cloning-helper.ts +29 -5
  39. package/src/internal/paintable-helper.ts +2 -54
  40. package/src/internal/svg-helper.ts +52 -0
  41. package/src/internal/tags-helper.ts +9 -7
  42. package/src/internal/texture-parameter-helper.ts +353 -0
  43. package/src/manager/material-manager.ts +62 -0
  44. package/src/manager/model-manager.ts +11 -5
  45. package/src/manager/parameter-manager.ts +116 -16
  46. package/src/viewer-error.ts +3 -0
  47. package/src/viewer.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AbstractMesh,
3
- AbstractScene,
4
3
  Color3,
4
+ IAssetContainer,
5
5
  Material,
6
6
  PBRMaterial,
7
7
  StandardMaterial,
@@ -14,6 +14,12 @@ import {
14
14
  import { getInternalMetadataValue, setInternalMetadataValue } from '../internal/metadata-helper';
15
15
  import { paintableParameterObserver } from '../internal/paintable-helper';
16
16
  import { getTags, hasTag } from '../internal/tags-helper';
17
+ import {
18
+ BuiltInTextureParameter,
19
+ BuiltInTextureParameterKeys,
20
+ ParameterTextureChannelsKeys,
21
+ createBuiltInTextureParameter,
22
+ } from '../internal/texture-parameter-helper';
17
23
  import { capitalize, isString } from 'lodash-es';
18
24
 
19
25
  /**
@@ -28,6 +34,18 @@ export const BuiltInParameter = {
28
34
  Color: 'color',
29
35
  Roughness: 'roughness',
30
36
  Metallic: 'metallic',
37
+ /**
38
+ * Texture parameters are always a combination of the channel (e.g. `albedoTexture`) and a sub parameter
39
+ * (e.g. `uScale`). Use this function to create the parameter accordingly
40
+ * (e.g. createTextureParameter("albedoTexture", "uScale")).
41
+ */
42
+ createTextureParameter: (channel: ParameterTextureChannelsKeys, parameter: BuiltInTextureParameterKeys): string =>
43
+ `${channel}.${parameter}`,
44
+ UseDetailmap: 'useDetailmap',
45
+ };
46
+
47
+ /** @ignore @deprected Use "texture parameters" {@link BuiltInParameter}.`createTextureParameter` instead */
48
+ export const LegacyParameter = {
31
49
  Paintable: 'paintable',
32
50
  };
33
51
 
@@ -319,19 +337,31 @@ export class ParameterManager {
319
337
 
320
338
  /**
321
339
  * Applies all existing parameter entries to a certain "model", as defined in the {@link ModelManager}.\
322
- * This can be usefull when updating the model before showing it in the scene.
340
+ * This can be useful when updating the model before showing it in the scene.
341
+ *
342
+ * @internal
343
+ */
344
+ public async applyAllParameterValuesToModel(model: IAssetContainer): Promise<void> {
345
+ await this._applyParameterValues(this._parameterEntries, model);
346
+ }
347
+
348
+ /**
349
+ * Removes existing parameter entries of all nodes of a model.\
350
+ * This can be useful to clean up the parameter state when removing a (cloned) model.
323
351
  *
324
352
  * @internal
325
353
  */
326
- public async applyAllParameterValuesToModel(model: AbstractScene): Promise<void> {
327
- const parameterEntriesToApply = this._parameterEntries;
354
+ public removeParameterEntriesOfModel(model: IAssetContainer): void {
355
+ const allNodeNames = [...model.meshes, ...model.transformNodes].map(node => node.name);
328
356
 
329
- await this._applyParameterValues(parameterEntriesToApply, model);
357
+ this._parameterEntries = this._parameterEntries.filter(
358
+ entry => !allNodeNames.includes(entry.subject.nodeName ?? '')
359
+ );
330
360
  }
331
361
 
332
362
  /**
333
363
  * Applies all parameter values which are targeting a material.\
334
- * This can be usefull when updating a material definition before creating it.
364
+ * This can be useful when updating a material definition before creating it.
335
365
  *
336
366
  * @internal
337
367
  */
@@ -350,6 +380,50 @@ export class ParameterManager {
350
380
  await this._applyParameterValues(parameterEntriesToApply);
351
381
  }
352
382
 
383
+ /**
384
+ * Removes all parameter entries of a certain material.\
385
+ * This can be useful to clean up the parameter state when removing a (cloned) material.
386
+ *
387
+ * @internal
388
+ */
389
+ public removeParameterEntriesOfMaterial(material: Material): void {
390
+ this._parameterEntries = this._parameterEntries.filter(entry => entry.subject.materialName !== material.id);
391
+ }
392
+
393
+ /**
394
+ * Applies subset of texture parameter values which are targeting a certain texture channel in a material.\
395
+ * This can be useful when updating texture settings (e.g. uScale) before the texture is actually created.
396
+ *
397
+ * @internal
398
+ */
399
+ public async applyTextureSettingsParameter(
400
+ material: PBRMaterial,
401
+ channel: ParameterTextureChannelsKeys
402
+ ): Promise<void> {
403
+ const tags = getTags(material);
404
+
405
+ const parameterEntriesToApply: ParameterEntry[] = [];
406
+ tags.forEach(tagName => {
407
+ const tagParamEntries = this._getEntriesOfSubject({ tagName });
408
+ parameterEntriesToApply.push(...tagParamEntries);
409
+ });
410
+
411
+ const materialParamEntries = this._getEntriesOfSubject({ materialName: material.id });
412
+ parameterEntriesToApply.push(...materialParamEntries);
413
+
414
+ const textureParameterEntriesToApply = parameterEntriesToApply.filter(parameterEntry => {
415
+ const paramPath = parameterEntry.parameterName.split('.');
416
+ // find texture parameters of this channel, e.g. "albedoTexture.uScale"
417
+ // "image" should not be applied here as this is part of the texture initialization anyway
418
+ const isTextureParamOfChannel =
419
+ paramPath.length === 2 && paramPath[0] === channel && paramPath[1] !== BuiltInTextureParameter.image;
420
+
421
+ return isTextureParamOfChannel;
422
+ });
423
+
424
+ await this._applyParameterValues(textureParameterEntriesToApply);
425
+ }
426
+
353
427
  /**
354
428
  * @returns Desired parameter value of a certain node.
355
429
  * Tags are considered as well but have lower priority than node parameters, as these are more specific.
@@ -405,9 +479,19 @@ export class ParameterManager {
405
479
 
406
480
  for (const node of nodes) {
407
481
  if (visible) {
408
- const deferredMaterial = getInternalMetadataValue(node, 'deferredMaterial');
409
- if (deferredMaterial) {
410
- await this.viewer.materialManager.setMaterialOnMesh(deferredMaterial as string, node as AbstractMesh);
482
+ // if a mesh gets visible by this operation we have to activate the assigned material which is stored in the
483
+ // internal metadata
484
+ // => consider child meshes as well (CB-10143)
485
+ const activatedNodes = [node, ...node.getChildMeshes(false)];
486
+ for (const activatedNode of activatedNodes) {
487
+ const deferredMaterial = getInternalMetadataValue(activatedNode, 'deferredMaterial');
488
+ if (deferredMaterial) {
489
+ await this.viewer.materialManager.setMaterialOnMesh(
490
+ deferredMaterial as string,
491
+ // this cast is fine, as deferred material can only be set on meshes
492
+ activatedNode as AbstractMesh
493
+ );
494
+ }
411
495
  }
412
496
 
413
497
  node.setEnabled(true);
@@ -422,9 +506,22 @@ export class ParameterManager {
422
506
  for (const node of nodes) {
423
507
  // NOTE: don't use node.isEnabled() as visibility observer is probably called in same cycle but later
424
508
  // however the parameter value is already correct at this stage
425
- const rawVisibleValue = this.getParameterValueOfNode(node, BuiltInParameter.Visible);
509
+ // we have to go through all parents as well, because a parent may have been set to false, which also disables
510
+ // this child node
511
+ let curNode: TransformNode | null = node;
512
+ let visibleByParameter: boolean | undefined = undefined;
513
+ while (curNode && visibleByParameter !== false) {
514
+ const curNodeVisibleByParameter = this.getParameterValueOfNode(curNode, BuiltInParameter.Visible);
515
+ if (curNodeVisibleByParameter !== undefined) {
516
+ visibleByParameter = curNodeVisibleByParameter as boolean;
517
+ }
518
+ curNode = curNode.parent as TransformNode;
519
+ }
520
+
521
+ // parameter visibility has priority, but if the visiblity is not controlled by the parameter use the plain
522
+ // Babylon.js isEnabled() check
426
523
  const visible =
427
- rawVisibleValue !== undefined ? ParameterManager.parseBoolean(rawVisibleValue) : node.isEnabled();
524
+ visibleByParameter !== undefined ? ParameterManager.parseBoolean(visibleByParameter) : node.isEnabled();
428
525
  if (visible) {
429
526
  // TODO WTT: check mesh type and throw error if it doesn't fit
430
527
  // think of creating a framework with type guards (isMesh, canHaveMaterial, ...) around this
@@ -503,9 +600,12 @@ export class ParameterManager {
503
600
  }
504
601
  }
505
602
  });
506
- this.setParameterObserver(BuiltInParameter.Paintable, async ({ newValue, materials }) => {
603
+ this.setParameterObserver(LegacyParameter.Paintable, async ({ newValue, materials }) => {
507
604
  paintableParameterObserver(newValue, materials, this.viewer.scene);
508
605
  });
606
+
607
+ // texture parameter use a more generic approach (`channel`.`parameter`) and are therefore coded in a dedicated file
608
+ createBuiltInTextureParameter(this, this.viewer.scene);
509
609
  }
510
610
 
511
611
  /**
@@ -543,7 +643,7 @@ export class ParameterManager {
543
643
  */
544
644
  protected async _applyParameterValues(
545
645
  parameterEntries: ParameterEntry[],
546
- assetContainer?: AbstractScene
646
+ assetContainer?: IAssetContainer
547
647
  ): Promise<void> {
548
648
  const tagParamEntries = parameterEntries.filter(entry => isTagParameterSubject(entry.subject));
549
649
  const nonTagParamEntries = parameterEntries.filter(entry => !isTagParameterSubject(entry.subject));
@@ -565,7 +665,7 @@ export class ParameterManager {
565
665
  protected async _applyParameterValue(
566
666
  subject: ParameterSubject,
567
667
  parameterName: ParameterName,
568
- assetContainer?: AbstractScene
668
+ assetContainer?: IAssetContainer
569
669
  ): Promise<void> {
570
670
  const parameterEntry = this._getEntry(subject, parameterName);
571
671
  const observer = this._parameterObserver[parameterName];
@@ -585,7 +685,7 @@ export class ParameterManager {
585
685
  });
586
686
  }
587
687
 
588
- protected _getAffectedMaterials(subject: ParameterSubject, assetContainer?: AbstractScene): Material[] {
688
+ protected _getAffectedMaterials(subject: ParameterSubject, assetContainer?: IAssetContainer): Material[] {
589
689
  assetContainer = assetContainer ?? this.viewer.scene;
590
690
  let materials: Material[] = [];
591
691
 
@@ -602,7 +702,7 @@ export class ParameterManager {
602
702
  return materials;
603
703
  }
604
704
 
605
- protected _getAffectedNodes(subject: ParameterSubject, assetContainer?: AbstractScene): TransformNode[] {
705
+ protected _getAffectedNodes(subject: ParameterSubject, assetContainer?: IAssetContainer): TransformNode[] {
606
706
  assetContainer = assetContainer ?? this.viewer.scene;
607
707
  const allNodes = [...assetContainer.meshes, ...assetContainer.transformNodes];
608
708
  let nodes: TransformNode[] = [];
@@ -26,6 +26,9 @@ export const ViewerErrorIds = {
26
26
  ModelIsNotAClone: 'ModelIsNotAClone',
27
27
  AssetLoadingFailed: 'AssetLoadingFailed',
28
28
  MaterialCouldNotBeParsed: 'MaterialCouldNotBeParsed',
29
+ TextureCouldNotBeParsed: 'TextureCouldNotBeParsed',
30
+ MaterialAlreadyExists: 'MaterialAlreadyExists',
31
+ NotAClonedMaterial: 'NotAClonedMaterial',
29
32
  };
30
33
 
31
34
  /** @internal */
package/src/viewer.ts CHANGED
@@ -112,7 +112,7 @@ export class Viewer {
112
112
  return this._scene;
113
113
  }
114
114
  get engine(): Engine {
115
- return this.scene.getEngine();
115
+ return this.scene.getEngine() as Engine;
116
116
  }
117
117
  get cameraManager(): CameraManager {
118
118
  return this._cameraManager;