@combeenation/3d-viewer 20.0.1 → 21.0.0-alpha2

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.
@@ -165,7 +165,7 @@ function _addMissingMaterialMetadata(dataParsed: unknown, container: AssetContai
165
165
  const materialOnOriginalMesh = parsedMesh?.materialId;
166
166
 
167
167
  if (materialOnOriginalMesh && materialOnImportedMesh !== materialOnOriginalMesh) {
168
- window.Cbn?.Assets.assertMaterialExists(materialOnOriginalMesh);
168
+ window.Cbn?.Assets?.assertMaterialExists?.(materialOnOriginalMesh);
169
169
  setInternalMetadataValue(importedMesh, 'deferredMaterial', materialOnOriginalMesh);
170
170
  }
171
171
  });
@@ -230,7 +230,7 @@ function _createDecals(dataParsed: unknown, container: AssetContainer): void {
230
230
 
231
231
  // optionally set material and tags directly
232
232
  if (materialId) {
233
- window.Cbn?.Assets.assertMaterialExists(materialId);
233
+ window.Cbn?.Assets?.assertMaterialExists?.(materialId);
234
234
  setInternalMetadataValue(decalMesh, 'deferredMaterial', materialId);
235
235
  }
236
236
 
@@ -2,6 +2,7 @@ import {
2
2
  BaseTexture,
3
3
  BuiltInParameter,
4
4
  Material,
5
+ MaterialManager,
5
6
  PBRMaterial,
6
7
  ParameterManager,
7
8
  Scene,
@@ -50,7 +51,11 @@ export const ParameterTextureChannels = {
50
51
  };
51
52
  export type ParameterTextureChannelsKeys = keyof typeof ParameterTextureChannels;
52
53
 
53
- export function createBuiltInTextureParameter(parameterManager: ParameterManager, scene: Scene): void {
54
+ export function createBuiltInTextureParameter(
55
+ parameterManager: ParameterManager,
56
+ materialManager: MaterialManager,
57
+ scene: Scene
58
+ ): void {
54
59
  // create parameter observer for each channel
55
60
  (Object.values(ParameterTextureChannels) as ParameterTextureChannelsKeys[]).forEach(channel => {
56
61
  parameterManager.setParameterObserver(
@@ -100,7 +105,7 @@ export function createBuiltInTextureParameter(parameterManager: ParameterManager
100
105
  } else if (url) {
101
106
  // no texture, or wrong type => create texture from scratch
102
107
  // first we check if some settings were provided in the material definition
103
- const addMatSettings = await window.Cbn?.Assets.getMaterial(pbrMaterial.id);
108
+ const addMatSettings = materialManager.getMaterialDefinition(pbrMaterial.id);
104
109
  const textureSettings = addMatSettings ? _getTextureObjFromParameterChannel(addMatSettings, channel) : {};
105
110
 
106
111
  // overwrite the name with the url, as this is what the texture parser expects
@@ -25,6 +25,7 @@ export class DebugManager {
25
25
 
26
26
  protected _axesViewer: AxesViewer | null = null;
27
27
  protected _showBoundingSphereForAutofocus: boolean = false;
28
+ protected _parentDomElementForInspector: HTMLElement | null = null;
28
29
 
29
30
  /** @internal */
30
31
  public constructor(protected viewer: Viewer) {}
@@ -40,7 +41,16 @@ export class DebugManager {
40
41
  }
41
42
 
42
43
  /**
43
- * Enables the Babylon.js [Inspector](https://doc.babylonjs.com/legacy/inspector/).\
44
+ * Registers a parent DOM element to use as root for the Babylon.js inspector.\
45
+ * When set and no explicit `options` are passed to {@link showInspector}, this element will be used
46
+ * as `globalRoot`, which avoids interference with the surrounding application layout.
47
+ */
48
+ public registerParentDomElementForInspector(el: HTMLElement): void {
49
+ this._parentDomElementForInspector = el;
50
+ }
51
+
52
+ /**
53
+ * Enables the Babylon.js [Inspector](https://doc.babylonjs.com/legacy/inspector()).\
44
54
  * Due to the additional size of the inspector, this function is only available in "development" builds!
45
55
  *
46
56
  * @returns Signalizes if inspector could be loaded
@@ -49,12 +59,16 @@ export class DebugManager {
49
59
  if (process.env.NODE_ENV === 'development') {
50
60
  const inspModule = await import(/* webpackChunkName: "inspector"*/ '@babylonjs/inspector');
51
61
 
52
- if (!options && window.Cbn) {
62
+ const parentEl =
63
+ this._parentDomElementForInspector ??
64
+ // fallback to legacy `window.Cbn` call to support "old" cfgrs (pre Editor V2)
65
+ window.Cbn?.utils?.Viewer3dHelper?.getCfgrParentDomElementForInspector?.();
66
+
67
+ if (!options && parentEl) {
53
68
  // special case for usage in Combeenation configurator:
54
69
  // if no options are set the inspector will be rendered into the parent element of the configurator
55
70
  // in this way the configurator layout itself will not be affected by the inspector
56
- const cfgrParentEl = window.Cbn.utils.Viewer3dHelper.getCfgrParentDomElementForInspector();
57
- inspModule.Inspector.Show(this.viewer.scene, { globalRoot: cfgrParentEl });
71
+ inspModule.Inspector.Show(this.viewer.scene, { globalRoot: parentEl });
58
72
  } else {
59
73
  inspModule.Inspector.Show(this.viewer.scene, options ?? {});
60
74
  }
@@ -20,6 +20,13 @@ export type MaterialCloneOptions = {
20
20
  tagNamingStrategy?: TagNamingStrategy;
21
21
  };
22
22
 
23
+ /**
24
+ * Material definition type, which can be passed to `BABYLON.Material.Parse` to create a runtime material object
25
+ */
26
+ export type MaterialDefinition = {
27
+ [key: string]: any;
28
+ };
29
+
23
30
  /**
24
31
  * Manager for material related tasks
25
32
  */
@@ -30,12 +37,39 @@ export class MaterialManager {
30
37
  */
31
38
  public static readonly CBN_FALLBACK_MATERIAL_NAME = '$fallback';
32
39
 
40
+ protected _materialDefinitions: { [materialId: string]: MaterialDefinition } = {};
33
41
  protected _clonedMaterials: { [name: string]: Material } = {};
34
42
  protected _createMaterialPromises: { [materialId: string]: Promise<Material | null> } = {};
43
+ protected _onMaterialDefinitionNotFound?: (materialId: string) => MaterialDefinition | undefined;
35
44
 
36
45
  /** @internal */
37
46
  public constructor(protected viewer: Viewer) {}
38
47
 
48
+ /**
49
+ * Register material definitions, which serves as a lookup for creating materials via {@link getOrCreateMaterial} or
50
+ * {@link setMaterialOnMesh}.
51
+ */
52
+ public registerMaterials(materialDefinitions: { [materialId: string]: MaterialDefinition }): void {
53
+ for (const materialId in materialDefinitions) {
54
+ if (this._materialDefinitions[materialId]) {
55
+ console.warn(`Material "${materialId}" is already registered.`);
56
+ return;
57
+ }
58
+
59
+ this._materialDefinitions[materialId] = materialDefinitions[materialId];
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Registers a callback function, which will be called when a material definition for a requested material id is not
65
+ * found. Can be used to create fallback material definitions on the fly.
66
+ */
67
+ public setOnMaterialDefinitionNotFoundCallback(
68
+ callback: (materialId: string) => MaterialDefinition | undefined
69
+ ): void {
70
+ this._onMaterialDefinitionNotFound = callback;
71
+ }
72
+
39
73
  /**
40
74
  * Assigns material with certain id to desired mesh.\
41
75
  * Creates the material if not already available (see {@link getOrCreateMaterial}).
@@ -56,9 +90,9 @@ export class MaterialManager {
56
90
 
57
91
  /**
58
92
  * Returns material with certain id if already available in the scene.\
59
- * If this is not the case material is created from a
60
- * "[Material asset](https://docs.combeenation.com/docs/howto-create-and-use-babylon-and-material-asset)"
61
- * on the Combeenation server.\
93
+ * If this is not the case, material is created from registered material definitions, which are most likely coming
94
+ * from "[Material assets](https://docs.combeenation.com/docs/howto-create-and-use-babylon-and-material-asset)" on the
95
+ * Combeenation server.\
62
96
  * Waits until textures of material are fully loaded and shader is compiled. In this way "flickering" effects
63
97
  * will be avoided, since the material would be incomplete without its loaded textures.
64
98
  *
@@ -78,7 +112,7 @@ export class MaterialManager {
78
112
  this.viewer.eventManager.fireEvent(ViewerEvent.MaterialCreationStart, materialId);
79
113
 
80
114
  // request not pending, call the dedicated function
81
- const newCreationProm = this._createFromMaterialAsset(materialId, mesh);
115
+ const newCreationProm = this._createFromMaterialDefinition(materialId, mesh);
82
116
  // store the promise in a global map, so that subsequent requests can reference it
83
117
  this._createMaterialPromises[materialId] = newCreationProm;
84
118
  chosenMaterial = await newCreationProm;
@@ -153,7 +187,29 @@ export class MaterialManager {
153
187
  Object.keys(this._clonedMaterials).forEach(materialId => this.deleteClonedMaterial(materialId));
154
188
  }
155
189
 
156
- protected async _createFromMaterialAsset(materialId: string, mesh?: AbstractMesh): Promise<Material | null> {
190
+ /**
191
+ * Get material definition from registered material definitions or from legacy `Cbn.Assets.getMaterial` call
192
+ *
193
+ * @internal
194
+ */
195
+ public getMaterialDefinition(materialId: string): MaterialDefinition | undefined {
196
+ let definition: MaterialDefinition | undefined = this._materialDefinitions[materialId];
197
+ if (!definition && window.Cbn?.Assets?.getMaterial) {
198
+ // fallback to legacy `Cbn.Assets.getMaterial` call to support "old" cfgrs (pre Editor V2)
199
+ definition = window.Cbn.Assets.getMaterial(materialId) as MaterialDefinition | undefined;
200
+ }
201
+
202
+ if (!definition) {
203
+ console.warn(
204
+ `Material definition for "${materialId}" couldn't be found. Material might not be registered or Material Asset from Combeenation server does not exist or is not connected to the configurator.`
205
+ );
206
+ definition = this._onMaterialDefinitionNotFound?.(materialId);
207
+ }
208
+
209
+ return definition;
210
+ }
211
+
212
+ protected async _createFromMaterialDefinition(materialId: string, mesh?: AbstractMesh): Promise<Material | null> {
157
213
  if (materialId === MaterialManager.CBN_FALLBACK_MATERIAL_NAME) {
158
214
  const fallbackMaterial = new StandardMaterial(MaterialManager.CBN_FALLBACK_MATERIAL_NAME, this.viewer.scene);
159
215
  fallbackMaterial.disableLighting = true;
@@ -161,16 +217,8 @@ export class MaterialManager {
161
217
  return fallbackMaterial;
162
218
  }
163
219
 
164
- if (!window.Cbn) {
165
- return null;
166
- }
167
-
168
- const materialDefinition = await window.Cbn.Assets.getMaterial(materialId);
169
-
220
+ const materialDefinition = this.getMaterialDefinition(materialId);
170
221
  if (!materialDefinition) {
171
- console.warn(
172
- `Trying to create material "${materialId}" from Combeenation asset but according asset does not exist or is not connected to the configurator.`
173
- );
174
222
  return null;
175
223
  }
176
224
 
@@ -584,7 +584,7 @@ export class ParameterManager {
584
584
  */
585
585
  protected _addBuiltInParameterObservers(): void {
586
586
  createBuiltInParameter(this, this.viewer.materialManager);
587
- createBuiltInTextureParameter(this, this.viewer.scene);
587
+ createBuiltInTextureParameter(this, this.viewer.materialManager, this.viewer.scene);
588
588
  createPaintableParameter(this, this.viewer.scene);
589
589
  }
590
590