@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,225 @@
1
+ import {
2
+ AbstractMesh,
3
+ AssetContainer,
4
+ InstancedMesh,
5
+ Mesh,
6
+ MorphTargetManager,
7
+ NodeNamingStrategy,
8
+ Scene,
9
+ TagNamingStrategy,
10
+ TransformNode,
11
+ } from '../index';
12
+ import {
13
+ clearInternalMetadataValue,
14
+ cloneInternalMetadata,
15
+ cloneMetadata,
16
+ getInternalMetadataValue,
17
+ setInternalMetadataValue,
18
+ } from './metadataHelper';
19
+ import { cloneTags, getTags, setTags } from './tagsHelper';
20
+
21
+ const _defaultNodeNamingStrategy: NodeNamingStrategy = (node: TransformNode, newModelName: string): string => {
22
+ return `${node.name}.${newModelName}`;
23
+ };
24
+ const _defaultTagNamingStrategy: TagNamingStrategy = (tag: string, newModelName: string): string => {
25
+ // don't rename tags by default
26
+ return tag;
27
+ };
28
+
29
+ /**
30
+ * Clones the node hierarchy of the asset container with some special treatment that differs from Babylon.js default
31
+ * cloning behaviour, such as:
32
+ * - create new instances of morph target manager
33
+ * - deep cloning internal metadata
34
+ * - deep cloning metadata and tags for instanced meshes
35
+ * - reassigns source meshes in cloned asset container
36
+ * Furthermore there is the possibility to adjust naming of nodes and tags in the cloned asset container
37
+ */
38
+ export function cloneModelAssetContainer(
39
+ sourceAssetContainer: AssetContainer,
40
+ newModelName: string,
41
+ renaming: {
42
+ nodeNamingStrategy?: NodeNamingStrategy;
43
+ tagNamingStrategy?: TagNamingStrategy;
44
+ },
45
+ scene: Scene
46
+ ): AssetContainer {
47
+ const targetAssetContainer = new AssetContainer(scene);
48
+
49
+ sourceAssetContainer.rootNodes.forEach(node => {
50
+ if (node instanceof TransformNode) {
51
+ // this is the actual node tree cloning procedure
52
+ _cloneNode(node, newModelName, null, targetAssetContainer, {
53
+ nodeNamingStrategy: renaming?.nodeNamingStrategy,
54
+ tagNamingStrategy: renaming?.tagNamingStrategy,
55
+ });
56
+ }
57
+ });
58
+
59
+ targetAssetContainer.populateRootNodes();
60
+ targetAssetContainer.rootNodes.forEach(node => {
61
+ if (node instanceof TransformNode) {
62
+ // reassigning instanced meshes can only be done after the model has been fully cloned, as we can't be sure if
63
+ // the source or instanced mesh is handled prior
64
+ _reAssignSourceMesh(node, sourceAssetContainer.meshes, targetAssetContainer.meshes);
65
+ }
66
+ });
67
+
68
+ // morph target manager is not cloned per default, therefore morph targets would affect original and cloned model at
69
+ // the same time, which we don't want
70
+ sourceAssetContainer.morphTargetManagers.forEach(sourceMTM => {
71
+ cloneMorphTargetManager(sourceMTM, targetAssetContainer);
72
+ });
73
+
74
+ _clearCloningMetadata(sourceAssetContainer);
75
+ _clearCloningMetadata(targetAssetContainer);
76
+
77
+ // hide immediately, so that show model code can do it's thing (scene preparation) before finally showing the model
78
+ targetAssetContainer.removeAllFromScene();
79
+
80
+ return targetAssetContainer;
81
+ }
82
+
83
+ /**
84
+ * Helper function for cloning a morph target manager and updating all the mesh assignments.
85
+ * Meshes need to be already available in the target asset container.
86
+ */
87
+ export function cloneMorphTargetManager(
88
+ sourceMTM: MorphTargetManager,
89
+ targetAssetContainer: AssetContainer
90
+ ): MorphTargetManager {
91
+ const clonedMTM = sourceMTM.clone();
92
+
93
+ clonedMTM._parentContainer = targetAssetContainer;
94
+ targetAssetContainer.morphTargetManagers.push(clonedMTM);
95
+
96
+ targetAssetContainer.meshes.forEach(mesh => {
97
+ if (mesh.morphTargetManager?.uniqueId === sourceMTM.uniqueId) {
98
+ mesh.morphTargetManager = clonedMTM;
99
+ }
100
+ });
101
+
102
+ return clonedMTM;
103
+ }
104
+
105
+ /**
106
+ * The actual geometry cloning function.
107
+ * Calls "clone" function of dedicated Node type and recourses into children to clone the whole node tree.
108
+ * Adds temporary metadata for special treatment of certain node types (e.g. InstancedMesh).
109
+ */
110
+ function _cloneNode(
111
+ node: TransformNode,
112
+ newModelName: string,
113
+ newParent: TransformNode | null,
114
+ assetContainer: AssetContainer,
115
+ renaming: {
116
+ nodeNamingStrategy?: NodeNamingStrategy;
117
+ tagNamingStrategy?: TagNamingStrategy;
118
+ }
119
+ ): void {
120
+ const nodeNamingStrategy = renaming.nodeNamingStrategy ?? _defaultNodeNamingStrategy;
121
+ const tagNamingStrategy = renaming.tagNamingStrategy ?? _defaultTagNamingStrategy;
122
+
123
+ const cloneName = nodeNamingStrategy(node, newModelName);
124
+ const clone = node.clone(cloneName, newParent, true);
125
+ if (!clone) {
126
+ throw new Error(`Cloning node "${node.name}" failed`);
127
+ }
128
+
129
+ clone.id = cloneName;
130
+ // create a deep clone for internal metadata, as the default clone function uses the same assignment of the sources
131
+ // internal metadata
132
+ cloneInternalMetadata(node, clone);
133
+ // ATM the assignment from clone to source is needed for reassigning instanced meshes after cloning
134
+ // may be usefull for other node types in the future as well
135
+ setInternalMetadataValue(clone, 'cloneSource', node.uniqueId);
136
+ setInternalMetadataValue(node, 'cloneTarget', clone.uniqueId);
137
+
138
+ if (node instanceof InstancedMesh) {
139
+ _cloneInstancedMeshData(node, clone as InstancedMesh);
140
+ }
141
+
142
+ const sourceTags = getTags(node);
143
+ const mappedTags = sourceTags.map(tag => tagNamingStrategy(tag, newModelName));
144
+ setTags(clone, mappedTags);
145
+
146
+ clone._parentContainer = assetContainer;
147
+ // TODO WTT: create global helper function for distinguishing between transform nodes and meshes
148
+ if (clone instanceof AbstractMesh) {
149
+ assetContainer.meshes.push(clone);
150
+ } else {
151
+ assetContainer.transformNodes.push(clone);
152
+ }
153
+
154
+ const children = node.getChildTransformNodes(true);
155
+ children.forEach(child => _cloneNode(child, newModelName, clone, assetContainer, renaming));
156
+ }
157
+
158
+ /**
159
+ * Cloned instanced meshes are having the same source mesh as their cloning source.
160
+ * However we want the cloned source mesh to be the actual source.
161
+ * Exchanging and reassigning is done within this function.
162
+ * Operates on the given `node` and all its children recursively.
163
+ */
164
+ function _reAssignSourceMesh(node: TransformNode, sourceMeshes: AbstractMesh[], clonedMeshes: AbstractMesh[]): void {
165
+ if (node instanceof InstancedMesh) {
166
+ // find the cloned instance and source mesh
167
+ const clonedInstance = node;
168
+ const originalInstance = _findByUniqueId(
169
+ sourceMeshes,
170
+ getInternalMetadataValue(clonedInstance, 'cloneSource') as number
171
+ );
172
+ if (originalInstance instanceof InstancedMesh) {
173
+ const originalSource = originalInstance.sourceMesh;
174
+ const clonedSource = _findByUniqueId(
175
+ clonedMeshes,
176
+ getInternalMetadataValue(originalSource, 'cloneTarget') as number
177
+ );
178
+ if (clonedSource instanceof Mesh) {
179
+ // it's not possible to just exchange the source mesh => readonly property
180
+ // we have to create a new clone with the correct source mesh
181
+ const exchangedInstance = clonedInstance.clone(clonedInstance.name, clonedInstance.parent, true, clonedSource);
182
+ clonedInstance._parentContainer!.meshes.push(exchangedInstance);
183
+
184
+ _cloneInstancedMeshData(clonedInstance, exchangedInstance);
185
+
186
+ // re-reference the childs of the cloned instance as well
187
+ const childs = clonedInstance.getChildTransformNodes(true);
188
+ childs.forEach(child => (child.parent = exchangedInstance));
189
+ }
190
+ }
191
+
192
+ // old instance mesh is not needed anymore and can be disposed
193
+ clonedInstance.dispose();
194
+ }
195
+
196
+ // recurse into childs
197
+ const children = node.getChildTransformNodes(true);
198
+ children.forEach(child => _reAssignSourceMesh(child, sourceMeshes, clonedMeshes));
199
+ }
200
+
201
+ /**
202
+ * Removes metadata entries "cloneSource" and "cloneTarget" from all meshes and transform nodes inside the asset
203
+ * container
204
+ */
205
+ function _clearCloningMetadata(assetContainer: AssetContainer): void {
206
+ [...assetContainer.meshes, ...assetContainer.transformNodes].forEach(node => {
207
+ clearInternalMetadataValue(node, 'cloneSource');
208
+ clearInternalMetadataValue(node, 'cloneTarget');
209
+ });
210
+ }
211
+
212
+ /**
213
+ * "InstancedMesh.clone" function doesn't clone tags and metadata, also the enabled state doesn't seem to be cloned
214
+ * correctly.
215
+ * This function adjusts the behaviour to fulfill our expectations.
216
+ */
217
+ function _cloneInstancedMeshData(sourceInstancedMesh: InstancedMesh, targetInstancedMesh: InstancedMesh): void {
218
+ targetInstancedMesh.setEnabled(sourceInstancedMesh.isEnabled(false));
219
+ cloneMetadata(sourceInstancedMesh, targetInstancedMesh);
220
+ cloneTags(sourceInstancedMesh, targetInstancedMesh);
221
+ }
222
+
223
+ function _findByUniqueId(nodes: TransformNode[], uniqueId: number): TransformNode | undefined {
224
+ return nodes.find(node => node.uniqueId === uniqueId);
225
+ }
@@ -0,0 +1,25 @@
1
+ import { LimitTextureSizeConfig } from '../index';
2
+
3
+ /**
4
+ * Checks if the current device is an iPhone
5
+ */
6
+ export function getIsIPhone(): boolean {
7
+ const isIPhone = /iPhone/.test(navigator.userAgent);
8
+
9
+ return isIPhone;
10
+ }
11
+
12
+ /**
13
+ * Checks if the current device is "scaled down", as defined in the Spec
14
+ */
15
+ export function getIsScaledDownDevice(limitTextureSize: LimitTextureSizeConfig | false): boolean {
16
+ if (!limitTextureSize) {
17
+ // no down scaling defined
18
+ return false;
19
+ }
20
+
21
+ // check device
22
+ const deviceFits = limitTextureSize.devices === 'all' || (limitTextureSize.devices === 'iPhone' && getIsIPhone());
23
+
24
+ return deviceFits;
25
+ }
@@ -1,23 +1,64 @@
1
- import { VertexBuffer } from '@babylonjs/core/Buffers/buffer';
2
- import { Vector3 } from '@babylonjs/core/Maths/math.vector';
3
- import type { Geometry } from '@babylonjs/core/Meshes/geometry';
4
- import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
5
- import { Mesh } from '@babylonjs/core/Meshes/mesh';
6
- import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
7
- import type { MorphTarget } from '@babylonjs/core/Morph/morphTarget';
8
- import { MorphTargetManager } from '@babylonjs/core/Morph/morphTargetManager';
9
- import type { FloatArray } from '@babylonjs/core/types';
1
+ import {
2
+ ExcludedGeometry,
3
+ ExcludedGeometryList,
4
+ FloatArray,
5
+ Geometry,
6
+ InstancedMesh,
7
+ Mesh,
8
+ MorphTarget,
9
+ MorphTargetManager,
10
+ ParameterSubject,
11
+ TransformNode,
12
+ Vector3,
13
+ VertexBuffer,
14
+ } from '../index';
15
+ import { cloneInternalMetadata } from './metadataHelper';
16
+ import { hasTag } from './tagsHelper';
17
+
18
+ /**
19
+ * Find out if a node is part of a list of excluded geometry
20
+ * @param node BJS node
21
+ * @param list list of excluded geometry
22
+ * @returns boolean based on whether node (or one of its parents) was found in list
23
+ */
24
+ export function isNodeExcluded(nodeToCheck: TransformNode, list: ExcludedGeometryList): boolean {
25
+ // CAUTION: node has to be the same instance
26
+ const checkNode = (excludedNode: TransformNode): boolean => excludedNode === nodeToCheck;
27
+ const checkTagManagerSubject = (excludedSubject: ParameterSubject): boolean => {
28
+ const nameMatches = !!excludedSubject.nodeName && excludedSubject.nodeName === nodeToCheck.name;
29
+ const tagMatches = !!excludedSubject.tagName && hasTag(nodeToCheck, excludedSubject.tagName);
30
+ return nameMatches || tagMatches;
31
+ };
32
+ const check = (geometryToExclude: ExcludedGeometry): boolean => {
33
+ if (geometryToExclude instanceof TransformNode) {
34
+ return checkNode(geometryToExclude);
35
+ }
36
+ if ((geometryToExclude as ParameterSubject).tagName || (geometryToExclude as ParameterSubject).nodeName) {
37
+ return checkTagManagerSubject(geometryToExclude as ParameterSubject);
38
+ }
39
+ return false;
40
+ };
41
+
42
+ let isExcluded = list.some(geometryToExclude => check(geometryToExclude));
43
+ // consider parent as well
44
+ if (!isExcluded && nodeToCheck.parent instanceof TransformNode) {
45
+ isExcluded = isNodeExcluded(nodeToCheck.parent, list);
46
+ }
47
+
48
+ return isExcluded;
49
+ }
10
50
 
11
51
  /**
12
52
  * Creates a "standard" mesh from an instanced mesh, by cloning the source mesh and applying transformation data
13
53
  */
14
- const createMeshFromInstancedMesh = function (
54
+ export function createMeshFromInstancedMesh(
15
55
  instancedMesh: InstancedMesh,
16
56
  newName: string,
17
- clonedParent: Nullable<TransformNode>
18
- ) {
57
+ clonedParent: TransformNode
58
+ ): Mesh {
19
59
  // first create a clone of the source mesh
20
60
  const newMesh = instancedMesh.sourceMesh.clone(newName, clonedParent, true);
61
+ cloneInternalMetadata(instancedMesh.sourceMesh, newMesh);
21
62
  // apply the transformation data, it's important to create clones of the transformations to not touch the original
22
63
  // transformation when applying changes (eg: geometry baking)
23
64
  newMesh.position = instancedMesh.position.clone();
@@ -33,13 +74,13 @@ const createMeshFromInstancedMesh = function (
33
74
  newMesh.setEnabled(instancedMesh.isEnabled(false));
34
75
 
35
76
  return newMesh;
36
- };
77
+ }
37
78
 
38
79
  /**
39
80
  * Removes transformation data from the mesh and stores it in the geometry, which is called "baking".
40
81
  * Also considers the geometry change from morph targets.
41
82
  */
42
- const bakeGeometryOfMesh = function (mesh: Mesh) {
83
+ export function bakeGeometryOfMesh(mesh: Mesh): void {
43
84
  if (!mesh.geometry) {
44
85
  // no geometry available, nothing to do
45
86
  return;
@@ -79,27 +120,27 @@ const bakeGeometryOfMesh = function (mesh: Mesh) {
79
120
 
80
121
  // bake the transformation data in the mesh geometry, fortunately there is already a help function from Babylon.js
81
122
  mesh.bakeCurrentTransformIntoVertices();
82
- };
123
+ }
83
124
 
84
125
  /**
85
126
  * Resets transformation to initial state
86
127
  */
87
- const resetTransformation = function (node: TransformNode) {
128
+ export function resetTransformation(node: TransformNode): void {
88
129
  node.position = new Vector3(0, 0, 0);
89
130
  node.rotation = new Vector3(0, 0, 0);
90
131
  node.rotationQuaternion = null;
91
132
  node.scaling = new Vector3(1, 1, 1);
92
- };
133
+ }
93
134
 
94
135
  /**
95
136
  * @param kind morph targets can affect various vertices kinds, whereas "position" is the most common one
96
137
  * still other kinds (like normals or tangents) can be affected as well and can be provided on this input
97
138
  */
98
- const _bakeMorphTargetManagerIntoVertices = function (
139
+ function _bakeMorphTargetManagerIntoVertices(
99
140
  kind: string,
100
141
  morphTargetManager: MorphTargetManager,
101
142
  geometry: Geometry
102
- ) {
143
+ ): void {
103
144
  const origVerticesData = geometry.getVerticesData(kind);
104
145
  if (!origVerticesData) {
105
146
  // no vertices data for this kind availabe on the mesh geometry
@@ -122,9 +163,9 @@ const _bakeMorphTargetManagerIntoVertices = function (
122
163
 
123
164
  // apply the updated vertices data
124
165
  geometry.setVerticesData(kind, verticesData);
125
- };
166
+ }
126
167
 
127
- const _getVerticesDataFromMorphTarget = function (kind: string, morphTarget: MorphTarget): Nullable<FloatArray> {
168
+ function _getVerticesDataFromMorphTarget(kind: string, morphTarget: MorphTarget): FloatArray | null {
128
169
  switch (kind) {
129
170
  case VertexBuffer.PositionKind:
130
171
  return morphTarget.getPositions();
@@ -137,6 +178,4 @@ const _getVerticesDataFromMorphTarget = function (kind: string, morphTarget: Mor
137
178
  }
138
179
 
139
180
  return null;
140
- };
141
-
142
- export { createMeshFromInstancedMesh, bakeGeometryOfMesh, resetTransformation };
181
+ }
@@ -0,0 +1,63 @@
1
+ import { BaseTexture, Material, Node } from '../index';
2
+ import { cloneDeep } from 'lodash-es';
3
+
4
+ type MetadataValue = string | number | boolean | undefined;
5
+ type MetadataTarget = Node | Material | BaseTexture;
6
+ type MetadataKeys =
7
+ // CBN babylon loader
8
+ | 'deferredMaterial'
9
+ // material manager
10
+ | 'materialToBeSet'
11
+ // GLTF export
12
+ | 'exportNode'
13
+ | 'deleteAfterExport'
14
+ | 'exchangeMaterialWith'
15
+ // cloning
16
+ | 'cloneSource'
17
+ | 'cloneTarget';
18
+
19
+ // TODO WTT: use generics or some kind of logic that is able to type the metadata according to their key
20
+ /**
21
+ * Sets certain metadata on the objects INTERNAL metadata storage.
22
+ * "object._internalMetadata.cbn" is reserved for CBN specific metadata information.
23
+ * The objects public metadata ("object.metadata") is not affected and should therefore not interfere with metadata
24
+ * that is used in consumer projects.
25
+ */
26
+ export function setInternalMetadataValue(object: MetadataTarget, key: MetadataKeys, value: MetadataValue): void {
27
+ if (!object._internalMetadata) {
28
+ object._internalMetadata = {};
29
+ }
30
+ if (!object._internalMetadata.cbn) {
31
+ object._internalMetadata.cbn = {};
32
+ }
33
+
34
+ object._internalMetadata.cbn[key] = value;
35
+ }
36
+
37
+ export function clearInternalMetadataValue(object: MetadataTarget, key: MetadataKeys): void {
38
+ delete object._internalMetadata?.cbn?.[key];
39
+ }
40
+
41
+ export function getInternalMetadataValue(object: MetadataTarget, key: MetadataKeys): MetadataValue {
42
+ return object._internalMetadata?.cbn?.[key];
43
+ }
44
+
45
+ /**
46
+ * Creates a deep clone from the source objects internal metadata and assigns it to the target objects metadata.
47
+ * This is required as Babylon.js only creates shallow clones of the internal metadata, which would be problematic for
48
+ * our needs.
49
+ */
50
+ export function cloneInternalMetadata(sourceObject: MetadataTarget, targetObject: MetadataTarget): void {
51
+ targetObject._internalMetadata = cloneDeep(sourceObject._internalMetadata);
52
+ }
53
+
54
+ /**
55
+ * Clones the metadata from one object to another.
56
+ * CAUTION: this is now the public available "object.metadata" object.
57
+ * We need this function internally when cloning instanced meshes.
58
+ */
59
+ export function cloneMetadata(sourceObject: MetadataTarget, targetObject: MetadataTarget): void {
60
+ const clonedMetadata = cloneDeep(sourceObject.metadata);
61
+
62
+ targetObject.metadata = clonedMetadata;
63
+ }