@combeenation/3d-viewer 12.4.1 → 13.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 (213) 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 +63 -63
  4. package/dist/lib-cjs/index.js +81 -114
  5. package/dist/lib-cjs/index.js.map +1 -1
  6. package/dist/lib-cjs/internal/cbnCustomBabylonLoaderPlugin.d.ts +10 -0
  7. package/dist/lib-cjs/internal/cbnCustomBabylonLoaderPlugin.js +124 -0
  8. package/dist/lib-cjs/internal/cbnCustomBabylonLoaderPlugin.js.map +1 -0
  9. package/dist/lib-cjs/internal/cloningHelper.d.ts +19 -0
  10. package/dist/lib-cjs/internal/cloningHelper.js +165 -0
  11. package/dist/lib-cjs/internal/cloningHelper.js.map +1 -0
  12. package/dist/lib-cjs/internal/deviceHelper.d.ts +9 -0
  13. package/dist/lib-cjs/{api/util → internal}/deviceHelper.js +6 -10
  14. package/dist/lib-cjs/internal/deviceHelper.js.map +1 -0
  15. package/dist/lib-cjs/internal/geometryHelper.d.ts +21 -0
  16. package/dist/lib-cjs/{api/util → internal}/geometryHelper.js +57 -24
  17. package/dist/lib-cjs/internal/geometryHelper.js.map +1 -0
  18. package/dist/lib-cjs/internal/metadataHelper.d.ts +26 -0
  19. package/dist/lib-cjs/internal/metadataHelper.js +51 -0
  20. package/dist/lib-cjs/internal/metadataHelper.js.map +1 -0
  21. package/dist/lib-cjs/internal/paintableHelper.d.ts +40 -0
  22. package/dist/lib-cjs/internal/paintableHelper.js +287 -0
  23. package/dist/lib-cjs/internal/paintableHelper.js.map +1 -0
  24. package/dist/lib-cjs/internal/tagsHelper.d.ts +12 -0
  25. package/dist/lib-cjs/internal/tagsHelper.js +38 -0
  26. package/dist/lib-cjs/internal/tagsHelper.js.map +1 -0
  27. package/dist/lib-cjs/manager/cameraManager.d.ts +51 -0
  28. package/dist/lib-cjs/manager/cameraManager.js +154 -0
  29. package/dist/lib-cjs/manager/cameraManager.js.map +1 -0
  30. package/dist/lib-cjs/manager/debugManager.d.ts +60 -0
  31. package/dist/lib-cjs/manager/debugManager.js +218 -0
  32. package/dist/lib-cjs/manager/debugManager.js.map +1 -0
  33. package/dist/lib-cjs/manager/eventManager.d.ts +52 -0
  34. package/dist/lib-cjs/manager/eventManager.js +72 -0
  35. package/dist/lib-cjs/manager/eventManager.js.map +1 -0
  36. package/dist/lib-cjs/{api/manager → manager}/gltfExportManager.d.ts +29 -34
  37. package/dist/lib-cjs/{api/manager → manager}/gltfExportManager.js +99 -120
  38. package/dist/lib-cjs/manager/gltfExportManager.js.map +1 -0
  39. package/dist/lib-cjs/manager/materialManager.d.ts +35 -0
  40. package/dist/lib-cjs/manager/materialManager.js +126 -0
  41. package/dist/lib-cjs/manager/materialManager.js.map +1 -0
  42. package/dist/lib-cjs/manager/modelManager.d.ts +145 -0
  43. package/dist/lib-cjs/manager/modelManager.js +381 -0
  44. package/dist/lib-cjs/manager/modelManager.js.map +1 -0
  45. package/dist/lib-cjs/manager/parameterManager.d.ts +210 -0
  46. package/dist/lib-cjs/manager/parameterManager.js +515 -0
  47. package/dist/lib-cjs/manager/parameterManager.js.map +1 -0
  48. package/dist/lib-cjs/manager/sceneManager.d.ts +45 -0
  49. package/dist/lib-cjs/manager/sceneManager.js +65 -0
  50. package/dist/lib-cjs/manager/sceneManager.js.map +1 -0
  51. package/dist/lib-cjs/manager/screenshotManager.d.ts +36 -0
  52. package/dist/lib-cjs/manager/screenshotManager.js +40 -0
  53. package/dist/lib-cjs/manager/screenshotManager.js.map +1 -0
  54. package/dist/lib-cjs/manager/textureManager.d.ts +12 -0
  55. package/dist/lib-cjs/manager/textureManager.js +44 -0
  56. package/dist/lib-cjs/manager/textureManager.js.map +1 -0
  57. package/dist/lib-cjs/viewer.d.ts +117 -0
  58. package/dist/lib-cjs/viewer.js +222 -0
  59. package/dist/lib-cjs/viewer.js.map +1 -0
  60. package/dist/lib-cjs/{api/classes/viewerError.d.ts → viewerError.d.ts} +6 -1
  61. package/dist/lib-cjs/{api/classes/viewerError.js → viewerError.js} +6 -1
  62. package/dist/lib-cjs/viewerError.js.map +1 -0
  63. package/package.json +10 -11
  64. package/src/dev.ts +14 -37
  65. package/src/{types.d.ts → globalTypes.d.ts} +8 -18
  66. package/src/index.ts +79 -113
  67. package/src/internal/cbnCustomBabylonLoaderPlugin.ts +149 -0
  68. package/src/internal/cloningHelper.ts +225 -0
  69. package/src/internal/deviceHelper.ts +25 -0
  70. package/src/{api/util → internal}/geometryHelper.ts +63 -24
  71. package/src/internal/metadataHelper.ts +63 -0
  72. package/src/internal/paintableHelper.ts +310 -0
  73. package/src/internal/tagsHelper.ts +41 -0
  74. package/src/manager/cameraManager.ts +236 -0
  75. package/src/manager/debugManager.ts +245 -0
  76. package/src/manager/eventManager.ts +72 -0
  77. package/src/{api/manager → manager}/gltfExportManager.ts +132 -125
  78. package/src/manager/materialManager.ts +135 -0
  79. package/src/manager/modelManager.ts +456 -0
  80. package/src/manager/parameterManager.ts +652 -0
  81. package/src/manager/sceneManager.ts +101 -0
  82. package/src/manager/screenshotManager.ts +59 -0
  83. package/src/manager/textureManager.ts +32 -0
  84. package/src/viewer.ts +296 -0
  85. package/src/{api/classes/viewerError.ts → viewerError.ts} +6 -1
  86. package/dist/lib-cjs/api/classes/animationInterface.d.ts +0 -8
  87. package/dist/lib-cjs/api/classes/animationInterface.js +0 -3
  88. package/dist/lib-cjs/api/classes/animationInterface.js.map +0 -1
  89. package/dist/lib-cjs/api/classes/dottedPath.d.ts +0 -79
  90. package/dist/lib-cjs/api/classes/dottedPath.js +0 -167
  91. package/dist/lib-cjs/api/classes/dottedPath.js.map +0 -1
  92. package/dist/lib-cjs/api/classes/element.d.ts +0 -153
  93. package/dist/lib-cjs/api/classes/element.js +0 -703
  94. package/dist/lib-cjs/api/classes/element.js.map +0 -1
  95. package/dist/lib-cjs/api/classes/event.d.ts +0 -401
  96. package/dist/lib-cjs/api/classes/event.js +0 -425
  97. package/dist/lib-cjs/api/classes/event.js.map +0 -1
  98. package/dist/lib-cjs/api/classes/eventBroadcaster.d.ts +0 -26
  99. package/dist/lib-cjs/api/classes/eventBroadcaster.js +0 -50
  100. package/dist/lib-cjs/api/classes/eventBroadcaster.js.map +0 -1
  101. package/dist/lib-cjs/api/classes/fuzzyMap.d.ts +0 -7
  102. package/dist/lib-cjs/api/classes/fuzzyMap.js +0 -22
  103. package/dist/lib-cjs/api/classes/fuzzyMap.js.map +0 -1
  104. package/dist/lib-cjs/api/classes/parameter.d.ts +0 -410
  105. package/dist/lib-cjs/api/classes/parameter.js +0 -643
  106. package/dist/lib-cjs/api/classes/parameter.js.map +0 -1
  107. package/dist/lib-cjs/api/classes/parameterObservable.d.ts +0 -36
  108. package/dist/lib-cjs/api/classes/parameterObservable.js +0 -73
  109. package/dist/lib-cjs/api/classes/parameterObservable.js.map +0 -1
  110. package/dist/lib-cjs/api/classes/parameterizable.d.ts +0 -15
  111. package/dist/lib-cjs/api/classes/parameterizable.js +0 -103
  112. package/dist/lib-cjs/api/classes/parameterizable.js.map +0 -1
  113. package/dist/lib-cjs/api/classes/placementAnimation.d.ts +0 -45
  114. package/dist/lib-cjs/api/classes/placementAnimation.js +0 -177
  115. package/dist/lib-cjs/api/classes/placementAnimation.js.map +0 -1
  116. package/dist/lib-cjs/api/classes/variant.d.ts +0 -261
  117. package/dist/lib-cjs/api/classes/variant.js +0 -873
  118. package/dist/lib-cjs/api/classes/variant.js.map +0 -1
  119. package/dist/lib-cjs/api/classes/variantInstance.d.ts +0 -53
  120. package/dist/lib-cjs/api/classes/variantInstance.js +0 -126
  121. package/dist/lib-cjs/api/classes/variantInstance.js.map +0 -1
  122. package/dist/lib-cjs/api/classes/variantParameterizable.d.ts +0 -17
  123. package/dist/lib-cjs/api/classes/variantParameterizable.js +0 -87
  124. package/dist/lib-cjs/api/classes/variantParameterizable.js.map +0 -1
  125. package/dist/lib-cjs/api/classes/viewer.d.ts +0 -215
  126. package/dist/lib-cjs/api/classes/viewer.js +0 -709
  127. package/dist/lib-cjs/api/classes/viewer.js.map +0 -1
  128. package/dist/lib-cjs/api/classes/viewerError.js.map +0 -1
  129. package/dist/lib-cjs/api/classes/viewerLight.d.ts +0 -66
  130. package/dist/lib-cjs/api/classes/viewerLight.js +0 -345
  131. package/dist/lib-cjs/api/classes/viewerLight.js.map +0 -1
  132. package/dist/lib-cjs/api/internal/lensRendering.d.ts +0 -8
  133. package/dist/lib-cjs/api/internal/lensRendering.js +0 -12
  134. package/dist/lib-cjs/api/internal/lensRendering.js.map +0 -1
  135. package/dist/lib-cjs/api/internal/sceneSetup.d.ts +0 -13
  136. package/dist/lib-cjs/api/internal/sceneSetup.js +0 -228
  137. package/dist/lib-cjs/api/internal/sceneSetup.js.map +0 -1
  138. package/dist/lib-cjs/api/manager/animationManager.d.ts +0 -30
  139. package/dist/lib-cjs/api/manager/animationManager.js +0 -127
  140. package/dist/lib-cjs/api/manager/animationManager.js.map +0 -1
  141. package/dist/lib-cjs/api/manager/gltfExportManager.js.map +0 -1
  142. package/dist/lib-cjs/api/manager/sceneManager.d.ts +0 -33
  143. package/dist/lib-cjs/api/manager/sceneManager.js +0 -129
  144. package/dist/lib-cjs/api/manager/sceneManager.js.map +0 -1
  145. package/dist/lib-cjs/api/manager/tagManager.d.ts +0 -118
  146. package/dist/lib-cjs/api/manager/tagManager.js +0 -531
  147. package/dist/lib-cjs/api/manager/tagManager.js.map +0 -1
  148. package/dist/lib-cjs/api/manager/textureLoadManager.d.ts +0 -22
  149. package/dist/lib-cjs/api/manager/textureLoadManager.js +0 -108
  150. package/dist/lib-cjs/api/manager/textureLoadManager.js.map +0 -1
  151. package/dist/lib-cjs/api/manager/variantInstanceManager.d.ts +0 -106
  152. package/dist/lib-cjs/api/manager/variantInstanceManager.js +0 -291
  153. package/dist/lib-cjs/api/manager/variantInstanceManager.js.map +0 -1
  154. package/dist/lib-cjs/api/store/specStorage.d.ts +0 -32
  155. package/dist/lib-cjs/api/store/specStorage.js +0 -66
  156. package/dist/lib-cjs/api/store/specStorage.js.map +0 -1
  157. package/dist/lib-cjs/api/util/babylonHelper.d.ts +0 -238
  158. package/dist/lib-cjs/api/util/babylonHelper.js +0 -826
  159. package/dist/lib-cjs/api/util/babylonHelper.js.map +0 -1
  160. package/dist/lib-cjs/api/util/debugHelper.d.ts +0 -9
  161. package/dist/lib-cjs/api/util/debugHelper.js +0 -94
  162. package/dist/lib-cjs/api/util/debugHelper.js.map +0 -1
  163. package/dist/lib-cjs/api/util/deviceHelper.d.ts +0 -9
  164. package/dist/lib-cjs/api/util/deviceHelper.js.map +0 -1
  165. package/dist/lib-cjs/api/util/geometryHelper.d.ts +0 -17
  166. package/dist/lib-cjs/api/util/geometryHelper.js.map +0 -1
  167. package/dist/lib-cjs/api/util/globalTypes.d.ts +0 -490
  168. package/dist/lib-cjs/api/util/globalTypes.js +0 -2
  169. package/dist/lib-cjs/api/util/globalTypes.js.map +0 -1
  170. package/dist/lib-cjs/api/util/resourceHelper.d.ts +0 -58
  171. package/dist/lib-cjs/api/util/resourceHelper.js +0 -215
  172. package/dist/lib-cjs/api/util/resourceHelper.js.map +0 -1
  173. package/dist/lib-cjs/api/util/sceneLoaderHelper.d.ts +0 -58
  174. package/dist/lib-cjs/api/util/sceneLoaderHelper.js +0 -229
  175. package/dist/lib-cjs/api/util/sceneLoaderHelper.js.map +0 -1
  176. package/dist/lib-cjs/api/util/stringHelper.d.ts +0 -13
  177. package/dist/lib-cjs/api/util/stringHelper.js +0 -33
  178. package/dist/lib-cjs/api/util/stringHelper.js.map +0 -1
  179. package/dist/lib-cjs/api/util/structureHelper.d.ts +0 -9
  180. package/dist/lib-cjs/api/util/structureHelper.js +0 -58
  181. package/dist/lib-cjs/api/util/structureHelper.js.map +0 -1
  182. package/src/api/classes/animationInterface.ts +0 -10
  183. package/src/api/classes/dottedPath.ts +0 -181
  184. package/src/api/classes/element.ts +0 -766
  185. package/src/api/classes/event.ts +0 -457
  186. package/src/api/classes/eventBroadcaster.ts +0 -52
  187. package/src/api/classes/fuzzyMap.ts +0 -21
  188. package/src/api/classes/parameter.ts +0 -686
  189. package/src/api/classes/parameterObservable.ts +0 -73
  190. package/src/api/classes/parameterizable.ts +0 -87
  191. package/src/api/classes/placementAnimation.ts +0 -162
  192. package/src/api/classes/variant.ts +0 -965
  193. package/src/api/classes/variantInstance.ts +0 -123
  194. package/src/api/classes/variantParameterizable.ts +0 -83
  195. package/src/api/classes/viewer.ts +0 -751
  196. package/src/api/classes/viewerLight.ts +0 -335
  197. package/src/api/internal/debugViewer.ts +0 -90
  198. package/src/api/internal/lensRendering.ts +0 -9
  199. package/src/api/internal/sceneSetup.ts +0 -208
  200. package/src/api/manager/animationManager.ts +0 -143
  201. package/src/api/manager/sceneManager.ts +0 -134
  202. package/src/api/manager/tagManager.ts +0 -572
  203. package/src/api/manager/textureLoadManager.ts +0 -107
  204. package/src/api/manager/variantInstanceManager.ts +0 -306
  205. package/src/api/store/specStorage.ts +0 -68
  206. package/src/api/util/babylonHelper.ts +0 -915
  207. package/src/api/util/debugHelper.ts +0 -121
  208. package/src/api/util/deviceHelper.ts +0 -31
  209. package/src/api/util/globalTypes.ts +0 -566
  210. package/src/api/util/resourceHelper.ts +0 -201
  211. package/src/api/util/sceneLoaderHelper.ts +0 -247
  212. package/src/api/util/stringHelper.ts +0 -30
  213. package/src/api/util/structureHelper.ts +0 -62
@@ -0,0 +1,245 @@
1
+ import {
2
+ AxesViewer,
3
+ BoundingSphere,
4
+ Color3,
5
+ DynamicTexture,
6
+ IInspectorOptions,
7
+ MeshBuilder,
8
+ Scene,
9
+ StandardMaterial,
10
+ TransformNode,
11
+ UtilityLayerRenderer,
12
+ Vector3,
13
+ Viewer,
14
+ ViewerEvent,
15
+ } from '../index';
16
+
17
+ type DebugAxisKeys = 'X' | 'Y' | 'Z';
18
+ type DebugAxisConfig = { color: Color3; position: Vector3 };
19
+
20
+ /**
21
+ * Manager for debugging functionalities
22
+ */
23
+ export class DebugManager {
24
+ protected static _DEBUG_AXIS_MAP: Record<DebugAxisKeys, DebugAxisConfig> = {
25
+ X: { color: Color3.Red().scale(0.5), position: new Vector3(1, 0, 0) },
26
+ Y: { color: Color3.Green().scale(0.5), position: new Vector3(0, 1, 0) },
27
+ Z: { color: Color3.Blue().scale(0.5), position: new Vector3(0, 0, 1) },
28
+ };
29
+ protected static _WORLD_COORD_ROOT_KEY = '__world_coordinates__';
30
+ protected static _BOUNDING_SPHERE_KEY = '__bounding_sphere__';
31
+
32
+ protected _axesViewer: AxesViewer | null = null;
33
+ protected _showBoundingSphereForAutofocus: boolean = false;
34
+
35
+ /** @internal */
36
+ public constructor(protected viewer: Viewer) {}
37
+
38
+ /**
39
+ * Assign callback for drawing bounding sphere on autofocusing
40
+ * @internal
41
+ */
42
+ public registerAutofocusStartListener(): void {
43
+ this.viewer.eventManager.addListener(ViewerEvent.AutofocusStart, boundingSphere =>
44
+ this._drawBoundingSphereForAutofocus(boundingSphere)
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Enables the Babylon.js [Inspector](https://doc.babylonjs.com/toolsAndResources/tools/inspector).\
50
+ * Due to the additional size of the inspector, this function is only available in "development" builds!
51
+ *
52
+ * @returns Signalizes if inspector could be loaded
53
+ */
54
+ public async showInspector(options?: IInspectorOptions): Promise<boolean> {
55
+ if (process.env.NODE_ENV === 'development') {
56
+ const inspModule = await import(/* webpackChunkName: "inspector"*/ '@babylonjs/inspector');
57
+
58
+ if (!options && window.Cbn) {
59
+ // special case for usage in Combeenation configurator:
60
+ // if no options are set the inspector will be rendered into the parent element of the configurator
61
+ // in this way the configurator layout itself will not be affected by the inspector
62
+ const cfgrParentEl = window.Cbn.utils.Viewer3dHelper.getCfgrParentDomElementForInspector();
63
+ inspModule.Inspector.Show(this.viewer.scene, { globalRoot: cfgrParentEl });
64
+ } else {
65
+ inspModule.Inspector.Show(this.viewer.scene, options ?? {});
66
+ }
67
+
68
+ // load additional packages for certain inspector features like "node material editor"
69
+ // this is done after showing the debug layer to save time
70
+ await import(/* webpackChunkName: "node-material-editor" */ '@babylonjs/node-editor');
71
+ await import(/* webpackChunkName: "node-geometry-editor" */ '@babylonjs/node-geometry-editor');
72
+
73
+ return true;
74
+ } else {
75
+ // inspector not available, set according warning message in console
76
+ if (window.Cbn) {
77
+ console.warn(`Inspector not loaded.
78
+ The inspector can only be used in development builds (e.g. during development with watch mode, in the configurator preview, ...)
79
+ but not in production (e.g. production build of Custom JS, published configurator, ...).`);
80
+ } else {
81
+ console.warn(`Inspector not loaded.
82
+ The inspector can only be used in development builds.`);
83
+ }
84
+
85
+ return false;
86
+ }
87
+ }
88
+
89
+ public hideInspector(): void {
90
+ this.viewer.scene.debugLayer?.hide();
91
+ }
92
+
93
+ /**
94
+ * Show world coordinate system with given dimension.\
95
+ * This is especially usefull when working on project with tricky positioning. (e.g. clones)
96
+ */
97
+ public showWorldCoordinates(dimension: number): void {
98
+ // make sure to remove already existing debug coordinate systems
99
+ this.hideWorldCoordinates();
100
+
101
+ // draw in utility layer, so that there is no interaction with the actually scene content
102
+ // (e.g. glb export, autofocus)
103
+ const utilityLayerScene = UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene;
104
+
105
+ const worldCoordRoot = new TransformNode(DebugManager._WORLD_COORD_ROOT_KEY, utilityLayerScene);
106
+ // axes viewer coordinate system is a bit too large
107
+ // multiply with unify factor to create arrows which exactly match the length of the input dimension
108
+ const factor = DebugManager._getWorldCoordinatesAxesUnifyFactor();
109
+ this._axesViewer = new AxesViewer(utilityLayerScene, dimension * factor);
110
+
111
+ DebugManager._prepareWorldCoordinateAxis('X', this._axesViewer.xAxis, worldCoordRoot, dimension, utilityLayerScene);
112
+ DebugManager._prepareWorldCoordinateAxis('Y', this._axesViewer.yAxis, worldCoordRoot, dimension, utilityLayerScene);
113
+ DebugManager._prepareWorldCoordinateAxis('Z', this._axesViewer.zAxis, worldCoordRoot, dimension, utilityLayerScene);
114
+ }
115
+
116
+ public hideWorldCoordinates(): void {
117
+ const utilityLayerScene = UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene;
118
+
119
+ this._axesViewer?.dispose();
120
+ this._axesViewer = null;
121
+
122
+ const worldCoordRoot = utilityLayerScene.getTransformNodeByName(DebugManager._WORLD_COORD_ROOT_KEY);
123
+ if (worldCoordRoot) {
124
+ worldCoordRoot.dispose(false, true);
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Draws a wireframe bounding sphere on the next call of {@link CameraManager.autofocusActiveCamera}.\
130
+ * This is usefull for checking which parts of the scene get centered.
131
+ */
132
+ public showBoundingSphereForAutofocus(): void {
133
+ this._showBoundingSphereForAutofocus = true;
134
+ }
135
+
136
+ public hideBoundingSphereForAutofocus(): void {
137
+ this._showBoundingSphereForAutofocus = false;
138
+ this._removeBoundingSphereForAutofocus();
139
+ }
140
+
141
+ /**
142
+ * Adjust and enhance coordinate axes to fulfill our needs.
143
+ * - moves nodes into common root
144
+ * - adds text node
145
+ */
146
+ protected static _prepareWorldCoordinateAxis(
147
+ text: 'X' | 'Y' | 'Z',
148
+ axis: TransformNode,
149
+ root: TransformNode,
150
+ dimension: number,
151
+ utilityLayerScene: Scene
152
+ ): void {
153
+ // create unique names
154
+ axis.name = `${DebugManager._WORLD_COORD_ROOT_KEY}.${text}`;
155
+ axis.parent = root;
156
+
157
+ // create text mesh via dynamic texture
158
+ const dynamicTexture = new DynamicTexture(
159
+ `${DebugManager._WORLD_COORD_ROOT_KEY}.${text}`,
160
+ 50,
161
+ utilityLayerScene,
162
+ true
163
+ );
164
+ dynamicTexture.hasAlpha = true;
165
+ // 42.5 is a magic offset, so that the text is vertically centered for font size 50px
166
+ // horizontal centering works well with the standard behaviour of Babylon.js (setting "null" as "width")
167
+ dynamicTexture.drawText(text, null, 42.5, 'bold 50px Arial', 'white', 'transparent', true);
168
+
169
+ const material = new StandardMaterial(`${DebugManager._WORLD_COORD_ROOT_KEY}.${text}`, utilityLayerScene);
170
+ material.disableLighting = true;
171
+ material.emissiveColor = DebugManager._DEBUG_AXIS_MAP[text].color;
172
+ material.diffuseTexture = dynamicTexture;
173
+
174
+ const plane = MeshBuilder.CreatePlane(
175
+ `${DebugManager._WORLD_COORD_ROOT_KEY}.${text}.TextPlane`,
176
+ { size: dimension / 10 },
177
+ utilityLayerScene
178
+ );
179
+ // make sure that text is located outside of arrow
180
+ plane.position = DebugManager._DEBUG_AXIS_MAP[text].position.multiplyByFloats(
181
+ dimension * 1.05,
182
+ dimension * 1.05,
183
+ dimension * 1.05
184
+ );
185
+ plane.parent = root;
186
+ plane.material = material;
187
+ // will be rendered on top of "default" meshes => taken from Babylon.js repo "AxesViewer" implementation
188
+ plane.renderingGroupId = 2;
189
+ // setting billboard mode ensures, that the text is always readable
190
+ plane.billboardMode = TransformNode.BILLBOARDMODE_ALL;
191
+ }
192
+
193
+ /**
194
+ * Calculate factor for creating world coordinate axes with exactly one unit in length
195
+ */
196
+ protected static _getWorldCoordinatesAxesUnifyFactor(): number {
197
+ // These constants are taken from the Babylon.js repository
198
+ const coneZPosOffset = 0.3;
199
+ const coneHeight = 0.075;
200
+ const baseScaling = 4;
201
+
202
+ // cone is moved 0.3 units away from the center
203
+ // the origin of the cone will be located on 1.2, if combined with the base scaling of 4
204
+ // invert that offset to get the origin to 1
205
+ // also consider the cone height to move the tip of the cone to 1 instead the center
206
+ const factor = 1 / ((coneZPosOffset + coneHeight / 2) * baseScaling);
207
+
208
+ return factor;
209
+ }
210
+
211
+ /**
212
+ * Visualize bounding sphere which is used to zoom in via `autofocusActiveCamera` function
213
+ */
214
+ protected _drawBoundingSphereForAutofocus(boundingSphere: BoundingSphere): void {
215
+ if (!this._showBoundingSphereForAutofocus) {
216
+ return;
217
+ }
218
+
219
+ this._removeBoundingSphereForAutofocus();
220
+
221
+ const utilityLayerScene = UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene;
222
+ let boundingMaterial = utilityLayerScene.getMaterialByName(DebugManager._BOUNDING_SPHERE_KEY);
223
+ if (!boundingMaterial) {
224
+ boundingMaterial = new StandardMaterial(DebugManager._BOUNDING_SPHERE_KEY, utilityLayerScene);
225
+ boundingMaterial.wireframe = true;
226
+ boundingMaterial.alpha = 0.1;
227
+ (boundingMaterial as StandardMaterial).emissiveColor = new Color3(1, 1, 1);
228
+ }
229
+
230
+ const sphere = MeshBuilder.CreateSphere(
231
+ DebugManager._BOUNDING_SPHERE_KEY,
232
+ { diameter: boundingSphere.radius * 2 },
233
+ utilityLayerScene
234
+ );
235
+ sphere.position = boundingSphere.center;
236
+ sphere.material = boundingMaterial;
237
+ sphere.isPickable = false;
238
+ }
239
+
240
+ protected _removeBoundingSphereForAutofocus(): void {
241
+ const utilityLayerScene = UtilityLayerRenderer.DefaultUtilityLayer.utilityLayerScene;
242
+ const existingSphere = utilityLayerScene.getMeshByName(DebugManager._BOUNDING_SPHERE_KEY);
243
+ existingSphere?.dispose();
244
+ }
245
+ }
@@ -0,0 +1,72 @@
1
+ import { Viewer } from '../index';
2
+ import EventEmitter from 'eventemitter3';
3
+
4
+ // NOTE: ATM we expose only very few events, due to the following reasons:
5
+ // - Code is generally asynchronous and can be awaited by consumer
6
+ // - We don't want to bloat the code with events that are never used
7
+
8
+ /**
9
+ * Events that are fired by the viewer
10
+ */
11
+ export enum ViewerEvent {
12
+ /**
13
+ * Requested material is not available in the scene yet and is about to be created
14
+ * @param materialId
15
+ */
16
+ MaterialCreationStart = 'MaterialCreationStart',
17
+ /**
18
+ * Material creation has been finished, that includes:
19
+ * - Load definition from Combeenation server
20
+ * - Load all textures
21
+ * - Compile shader
22
+ * @param materialId
23
+ * @param allMaterialsCreated signalizes that no more materials are currently being created
24
+ */
25
+ MaterialCreationEnd = 'MaterialCreationEnd',
26
+ /**
27
+ * Bounding sphere for autofocusing camera has been calculated.
28
+ * This is used internally for debugging purposes.
29
+ * @param boundingSphere
30
+ */
31
+ AutofocusStart = 'AutofocusStart',
32
+ }
33
+
34
+ /**
35
+ * Manager for eventing system, which ATM is only a slim wrapper about the "eventemitter3" library
36
+ */
37
+ export class EventManager {
38
+ protected _eventEmitter: EventEmitter;
39
+
40
+ /** @internal */
41
+ public constructor(protected viewer: Viewer) {
42
+ this._eventEmitter = new EventEmitter();
43
+ }
44
+
45
+ /**
46
+ * Used @internal to fire a viewer event
47
+ */
48
+ public fireEvent(event: ViewerEvent, ...args: any[]): void {
49
+ this._eventEmitter.emit(event, ...args);
50
+ }
51
+
52
+ /**
53
+ * Add listener to certain viewer event
54
+ */
55
+ public addListener(event: ViewerEvent, fn: EventEmitter.ListenerFn): void {
56
+ this._eventEmitter.addListener(event, fn);
57
+ }
58
+
59
+ /**
60
+ * Remove listener to viewer event
61
+ */
62
+ public removeListener(event: ViewerEvent, fn: EventEmitter.ListenerFn): void {
63
+ this._eventEmitter.removeListener(event, fn);
64
+ }
65
+
66
+ /**
67
+ * Used @internal to clean eventing sytem before viewer destruction
68
+ */
69
+ public removeAllListeners(event?: ViewerEvent): void {
70
+ this._eventEmitter.removeAllListeners(event);
71
+ }
72
+ }
@@ -1,36 +1,113 @@
1
- import { Viewer } from '../classes/viewer';
2
- import { injectMetadata } from '../util/babylonHelper';
3
- import { getIsScaledDownDevice } from '../util/deviceHelper';
4
- import { bakeGeometryOfMesh, createMeshFromInstancedMesh, resetTransformation } from '../util/geometryHelper';
5
- import { isNodeIncludedInExclusionList } from '../util/structureHelper';
6
- import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial';
7
- import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
8
- import { RenderTargetTexture } from '@babylonjs/core/Materials/Textures/renderTargetTexture';
9
- import { Vector3 } from '@babylonjs/core/Maths/math.vector';
10
- import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
11
- import { Mesh } from '@babylonjs/core/Meshes/mesh';
12
- import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
13
- import { Node as BjsNode } from '@babylonjs/core/node';
14
- import '@babylonjs/serializers/glTF/2.0/Extensions/KHR_texture_transform';
15
- import { GLTF2Export } from '@babylonjs/serializers/glTF/2.0/glTFSerializer';
16
-
1
+ import {
2
+ DynamicTexture,
3
+ ExcludedGeometryList,
4
+ GLTF2Export,
5
+ IExportOptions,
6
+ InstancedMesh,
7
+ Material,
8
+ Mesh,
9
+ Node,
10
+ PBRMaterial,
11
+ RenderTargetTexture,
12
+ TransformNode,
13
+ Vector3,
14
+ Viewer,
15
+ } from '../index';
16
+ import { getIsScaledDownDevice } from '../internal/deviceHelper';
17
+ import { bakeGeometryOfMesh, createMeshFromInstancedMesh, resetTransformation } from '../internal/geometryHelper';
18
+ import { isNodeExcluded } from '../internal/geometryHelper';
19
+ import { cloneInternalMetadata, getInternalMetadataValue, setInternalMetadataValue } from '../internal/metadataHelper';
20
+
21
+ /**
22
+ * Manager for gltf export and augmented reality features
23
+ */
17
24
  export class GltfExportManager {
18
- protected static readonly _METADATA_PROPS = {
19
- exportNode: 'exportNode',
20
- deleteAfterExport: 'deleteAfterExport',
21
- exchangeMaterialWith: 'exchangeMaterialWith',
22
- };
23
25
  protected static readonly _EXPORT_ROOT_NAME = '__export_root__';
24
26
 
25
27
  protected _maxTextureSize: number;
26
28
 
27
- protected constructor(protected viewer: Viewer) {
28
- // store initial max texture size, so that we can restore it in the post processing
29
- this._maxTextureSize = viewer.engine.getCaps().maxTextureSize;
29
+ /**
30
+ * Defines options for the export.
31
+ * We don't allow the user to overwrite certain settings, since we rely on properties like `removeNoopRootNodes` to
32
+ * stay `true` in order to make the AR export work.
33
+ * We could theoretically allow it if AR optimization is not desired, but this may confuse the user.
34
+ */
35
+ protected static _gltfExportOptions(optimizeForAR: boolean, excluded?: ExcludedGeometryList): IExportOptions {
36
+ return {
37
+ shouldExportNode: function (node: Node): boolean {
38
+ if (optimizeForAR) {
39
+ // we explicitely marked nodes, that should be exported in AR mode
40
+ return getInternalMetadataValue(node, 'exportNode') as boolean;
41
+ } else {
42
+ // use the default export node check (enabled state, exclusion list, etc...)
43
+ return GltfExportManager._shouldExportNode(node, excluded);
44
+ }
45
+ },
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Checks if a node should be available in the export
51
+ */
52
+ protected static _shouldExportNode(node: Node, excluded?: ExcludedGeometryList): boolean {
53
+ if (!(node instanceof TransformNode)) {
54
+ return false;
55
+ }
56
+ // TODO WTT: think of adding "BackgroundHelper" and nodes with "infiniteDistance" here as well, at least in AR mode
57
+ if (!node.isEnabled()) {
58
+ return false;
59
+ }
60
+ if (excluded && isNodeExcluded(node, excluded)) {
61
+ return false;
62
+ }
63
+
64
+ return true;
65
+ }
66
+
67
+ /**
68
+ * Creates a clone of the material which should be used for the export.
69
+ * This is mostly required for recreating textures with lower sizes.
70
+ * CAUTION: Material exchanging is not supported for materials that contain certain texture types:
71
+ * - Dynamic textures (Paintables): Cloning dynamic textures doesn't clone the canvas context
72
+ * => so the clone is just empty
73
+ * - Render target textures: Disposing the clone will leave the scene in a "not ready" state
74
+ * => this scenario is not fully analyzed yet, but it's not really worth the effort right now, since this kind of
75
+ * of texture is not really used ATM
76
+ */
77
+ protected static _exchangeMaterial(material: Material): void {
78
+ const baseTextures = material.getActiveTextures();
79
+ const hasDynamicTextures = baseTextures.some(texture => texture instanceof DynamicTexture);
80
+ const hasRenderTargetTextures = baseTextures.some(texture => texture instanceof RenderTargetTexture);
81
+ if (hasDynamicTextures || hasRenderTargetTextures) {
82
+ const textureTypesString = [
83
+ hasDynamicTextures ? 'Dynamic Textures' : '',
84
+ hasRenderTargetTextures ? 'Render Target Textures' : '',
85
+ ]
86
+ .filter(Boolean)
87
+ .join();
88
+ console.warn(
89
+ `Couldn't exchange material "${material.name}" in GLB export, as it contains unsupported texture type(s) (${textureTypesString}). The export will still work, but the textures of this material will keep their original size.`
90
+ );
91
+
92
+ return;
93
+ }
94
+
95
+ const newName = `${material.name}_clone`;
96
+ const clonedMaterial = material.clone(newName)!;
97
+ cloneInternalMetadata(material, clonedMaterial);
98
+ const clonedTextures = clonedMaterial.getActiveTextures();
99
+
100
+ // mark all exported textures, so that they will be deleted after the export
101
+ clonedTextures.forEach(texture => setInternalMetadataValue(texture, 'deleteAfterExport', true));
102
+
103
+ setInternalMetadataValue(material, 'exchangeMaterialWith', clonedMaterial.uniqueId);
104
+ setInternalMetadataValue(clonedMaterial, 'deleteAfterExport', true);
30
105
  }
31
106
 
32
- public static async create(viewer: Viewer): Promise<GltfExportManager> {
33
- return new GltfExportManager(viewer);
107
+ /** @internal */
108
+ public constructor(protected viewer: Viewer) {
109
+ // store initial max texture size, so that we can restore it in the post processing
110
+ this._maxTextureSize = viewer.engine.getCaps().maxTextureSize;
34
111
  }
35
112
 
36
113
  /**
@@ -40,7 +117,11 @@ export class GltfExportManager {
40
117
  * is mostly targeting Apples .usdz format.
41
118
  * @param excluded Optional list of geometry (meshes, elements, variants,...) to be excluded from the export.
42
119
  */
43
- public async exportGlb(filename = 'glb-export.glb', optimizeForAR: boolean = false, excluded?: ExcludedGeometryList) {
120
+ public async exportGlb(
121
+ filename = 'glb-export.glb',
122
+ optimizeForAR: boolean = false,
123
+ excluded?: ExcludedGeometryList
124
+ ): Promise<File | undefined> {
44
125
  await this._exportPreProcess(optimizeForAR, excluded);
45
126
 
46
127
  const glbData = await GLTF2Export.GLBAsync(
@@ -71,7 +152,11 @@ export class GltfExportManager {
71
152
  * is mostly targeting Apples .usdz format.
72
153
  * @param excluded Optional list of geometry (meshes, elements, variants,...) to be excluded from the export.
73
154
  */
74
- public async exportGltfToFile(filename: string, optimizeForAR: boolean = false, excluded?: ExcludedGeometryList) {
155
+ public async exportGltfToFile(
156
+ filename: string,
157
+ optimizeForAR: boolean = false,
158
+ excluded?: ExcludedGeometryList
159
+ ): Promise<void> {
75
160
  await this._exportPreProcess(optimizeForAR, excluded);
76
161
 
77
162
  const gltf = await GLTF2Export.GLTFAsync(
@@ -91,7 +176,11 @@ export class GltfExportManager {
91
176
  * is mostly targeting Apples .usdz format.
92
177
  * @param excluded Optional list of geometry (meshes, elements, variants,...) to be excluded from the export.
93
178
  */
94
- public async exportGlbToFile(filename: string, optimizeForAR: boolean = false, excluded?: ExcludedGeometryList) {
179
+ public async exportGlbToFile(
180
+ filename: string,
181
+ optimizeForAR: boolean = false,
182
+ excluded?: ExcludedGeometryList
183
+ ): Promise<void> {
95
184
  await this._exportPreProcess(optimizeForAR, excluded);
96
185
 
97
186
  const glb = await GLTF2Export.GLBAsync(
@@ -125,7 +214,7 @@ export class GltfExportManager {
125
214
  // we don't have to rescale anything if are already on a downscaled device, since the textures are already <= 1024
126
215
  // also we have to be very cautios with copying textures on these devices, since we are potentially very limited
127
216
  // with the available memory
128
- const isScaledDownDevice = getIsScaledDownDevice();
217
+ const isScaledDownDevice = getIsScaledDownDevice(this.viewer.viewerSettings.limitTextureSize);
129
218
  if (!isScaledDownDevice) {
130
219
  // the idea is to re-create all textures with a smaller texture size
131
220
  // we have to exchange all materials for this to work
@@ -147,10 +236,8 @@ export class GltfExportManager {
147
236
  // TODO BJS Update: Test AR export on iPhones as well and double check if we still need this special logic
148
237
  const exportRootNode = new TransformNode(GltfExportManager._EXPORT_ROOT_NAME, this.viewer.scene);
149
238
  exportRootNode.scaling = new Vector3(-1, 1, 1);
150
- injectMetadata(exportRootNode!, {
151
- [GltfExportManager._METADATA_PROPS.exportNode]: true,
152
- [GltfExportManager._METADATA_PROPS.deleteAfterExport]: true,
153
- });
239
+ setInternalMetadataValue(exportRootNode, 'exportNode', true);
240
+ setInternalMetadataValue(exportRootNode, 'deleteAfterExport', true);
154
241
 
155
242
  // create clones of each node (recursively), optionally exchange with cloned materials and mark these nodes for the
156
243
  // export
@@ -178,15 +265,15 @@ export class GltfExportManager {
178
265
 
179
266
  // dispose all nodes, materials and textures that have only been created for the export
180
267
  this.viewer.scene.rootNodes
181
- .filter(rootNode => rootNode.metadata?.[GltfExportManager._METADATA_PROPS.deleteAfterExport])
268
+ .filter(rootNode => getInternalMetadataValue(rootNode, 'deleteAfterExport'))
182
269
  .forEach(rootNode => rootNode.dispose());
183
270
 
184
271
  this.viewer.scene.materials
185
- .filter(mat => !!mat.metadata?.[GltfExportManager._METADATA_PROPS.deleteAfterExport])
272
+ .filter(mat => getInternalMetadataValue(mat, 'deleteAfterExport'))
186
273
  .forEach(material => material.dispose(false, false));
187
274
 
188
275
  this.viewer.scene.textures
189
- .filter(texture => !!texture.metadata?.[GltfExportManager._METADATA_PROPS.deleteAfterExport])
276
+ .filter(texture => getInternalMetadataValue(texture, 'deleteAfterExport'))
190
277
  .forEach(texture => texture.dispose());
191
278
 
192
279
  // reset engines max texture size and resume rendering
@@ -198,7 +285,7 @@ export class GltfExportManager {
198
285
  * Creates a clone of the node which should be used for the export.
199
286
  * Also switches to the cloned material if required.
200
287
  */
201
- protected _prepareNodeForExport(node: BjsNode, clonedParent: TransformNode, excluded?: ExcludedGeometryList) {
288
+ protected _prepareNodeForExport(node: Node, clonedParent: TransformNode, excluded?: ExcludedGeometryList): void {
202
289
  if (!GltfExportManager._shouldExportNode(node, excluded)) {
203
290
  return;
204
291
  }
@@ -212,21 +299,20 @@ export class GltfExportManager {
212
299
  transformNode instanceof InstancedMesh
213
300
  ? createMeshFromInstancedMesh(transformNode, clonedNodeName, clonedParent)
214
301
  : transformNode.clone(clonedNodeName, clonedParent, true)!;
302
+ cloneInternalMetadata(transformNode, clonedNode);
215
303
 
216
304
  // exchange material
217
305
  if (clonedNode instanceof Mesh) {
218
306
  const exchangeWithMaterial =
219
- clonedNode.material?.metadata?.[GltfExportManager._METADATA_PROPS.exchangeMaterialWith];
307
+ clonedNode.material && getInternalMetadataValue(clonedNode.material, 'exchangeMaterialWith');
220
308
  if (exchangeWithMaterial) {
221
- clonedNode.material = this.viewer.scene.getMaterialByUniqueID(exchangeWithMaterial);
309
+ clonedNode.material = this.viewer.scene.getMaterialByUniqueID(exchangeWithMaterial as number);
222
310
  }
223
311
  }
224
312
 
225
313
  // signalize that this is a cloned node
226
- injectMetadata(clonedNode, {
227
- [GltfExportManager._METADATA_PROPS.exportNode]: true,
228
- [GltfExportManager._METADATA_PROPS.deleteAfterExport]: true,
229
- });
314
+ setInternalMetadataValue(clonedNode, 'exportNode', true);
315
+ setInternalMetadataValue(clonedNode, 'deleteAfterExport', true);
230
316
 
231
317
  // handle children
232
318
  const childs = transformNode.getChildTransformNodes(true);
@@ -236,7 +322,7 @@ export class GltfExportManager {
236
322
  /**
237
323
  * Help function for receiving all nodes that are marked for the export
238
324
  */
239
- protected _getNodesMarkedForExport(meshesOnly?: boolean) {
325
+ protected _getNodesMarkedForExport(meshesOnly?: boolean): TransformNode[] {
240
326
  const nodes: TransformNode[] = [...this.viewer.scene.meshes];
241
327
  if (!meshesOnly) {
242
328
  nodes.push(...this.viewer.scene.transformNodes);
@@ -244,7 +330,7 @@ export class GltfExportManager {
244
330
 
245
331
  const filteredNodes = nodes.filter(
246
332
  node =>
247
- !!node.metadata?.[GltfExportManager._METADATA_PROPS.exportNode] &&
333
+ getInternalMetadataValue(node, 'exportNode') &&
248
334
  // in the desired use cases we want to exclude the export root node
249
335
  // maybe add a parameter if we have to include it in certain scenarios in the future
250
336
  node.name !== GltfExportManager._EXPORT_ROOT_NAME
@@ -252,83 +338,4 @@ export class GltfExportManager {
252
338
 
253
339
  return filteredNodes;
254
340
  }
255
-
256
- /**
257
- * Defines options for the export.
258
- * We don't allow the user to overwrite certain settings, since we rely on properties like `removeNoopRootNodes` to
259
- * stay `true` in order to make the AR export work.
260
- * We could theoretically allow it if AR optimization is not desired, but this may confuse the user.
261
- */
262
- protected static _gltfExportOptions(optimizeForAR: boolean, excluded?: ExcludedGeometryList): IExportOptions {
263
- return {
264
- shouldExportNode: function (node: BjsNode) {
265
- if (optimizeForAR) {
266
- // we explicitely marked nodes, that should be exported in AR mode
267
- return !!node.metadata?.[GltfExportManager._METADATA_PROPS.exportNode];
268
- } else {
269
- // use the default export node check (enabled state, exclusion list, etc...)
270
- return GltfExportManager._shouldExportNode(node, excluded);
271
- }
272
- },
273
- };
274
- }
275
-
276
- /**
277
- * Checks if a node should be available in the export
278
- */
279
- protected static _shouldExportNode(node: BjsNode, excluded?: ExcludedGeometryList): boolean {
280
- if (!(node instanceof TransformNode)) {
281
- return false;
282
- }
283
- // TODO: think of adding "BackgroundHelper" and nodes with "infiniteDistance" here as well, at least in AR mode
284
- if (!node.isEnabled()) {
285
- return false;
286
- }
287
- if (excluded && isNodeIncludedInExclusionList(node, excluded)) {
288
- return false;
289
- }
290
-
291
- return true;
292
- }
293
-
294
- /**
295
- * Creates a clone of the material which should be used for the export.
296
- * This is mostly required for recreating textures with lower sizes.
297
- * CAUTION: Material exchanging is not supported for materials that contain certain texture types:
298
- * - Dynamic textures (Paintables): Cloning dynamic textures doesn't clone the canvas context
299
- * => so the clone is just empty
300
- * - Render target textures: Disposing the clone will leave the scene in a "not ready" state
301
- * => this scenario is not fully analyzed yet, but it's not really worth the effort right now, since this kind of
302
- * of texture is not really used ATM
303
- */
304
- protected static _exchangeMaterial(material: Material) {
305
- const baseTextures = material.getActiveTextures();
306
- const hasDynamicTextures = baseTextures.some(texture => texture instanceof DynamicTexture);
307
- const hasRenderTargetTextures = baseTextures.some(texture => texture instanceof RenderTargetTexture);
308
- if (hasDynamicTextures || hasRenderTargetTextures) {
309
- const textureTypesString = [
310
- hasDynamicTextures ? 'Dynamic Textures' : '',
311
- hasRenderTargetTextures ? 'Render Target Textures' : '',
312
- ]
313
- .filter(Boolean)
314
- .join();
315
- console.warn(
316
- `Couldn't exchange material "${material.name}" in GLB export, as it contains unsupported texture type(s) (${textureTypesString}). The export will still work, but the textures of this material will keep their original size.`
317
- );
318
-
319
- return;
320
- }
321
-
322
- const newName = `${material.name}_clone`;
323
- const clonedMaterial = material.clone(newName)!;
324
- const clonedTextures = clonedMaterial.getActiveTextures();
325
-
326
- // mark all exported textures, so that they will be deleted after the export
327
- clonedTextures.forEach(texture =>
328
- injectMetadata(texture, { [GltfExportManager._METADATA_PROPS.deleteAfterExport]: true })
329
- );
330
-
331
- injectMetadata(material, { [GltfExportManager._METADATA_PROPS.exchangeMaterialWith]: clonedMaterial.uniqueId });
332
- injectMetadata(clonedMaterial, { [GltfExportManager._METADATA_PROPS.deleteAfterExport]: true });
333
- }
334
341
  }