@combeenation/3d-viewer 5.1.2 → 5.2.0-alpha1

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 (322) hide show
  1. package/README.md +111 -111
  2. package/dist/lib-cjs/buildinfo.json +3 -3
  3. package/dist/lib-cjs/commonjs.tsconfig.tsbuildinfo +1 -0
  4. package/dist/lib-cjs/{api → src/api}/classes/animationInterface.d.ts +8 -8
  5. package/dist/lib-cjs/src/api/classes/animationInterface.js +3 -0
  6. package/dist/lib-cjs/src/api/classes/animationInterface.js.map +1 -0
  7. package/dist/{lib-es6 → lib-cjs/src}/api/classes/dottedPath.d.ts +79 -79
  8. package/dist/lib-cjs/src/api/classes/dottedPath.js +167 -0
  9. package/dist/lib-cjs/src/api/classes/dottedPath.js.map +1 -0
  10. package/dist/lib-cjs/{api → src/api}/classes/element.d.ts +149 -149
  11. package/dist/lib-cjs/src/api/classes/element.js +669 -0
  12. package/dist/lib-cjs/src/api/classes/element.js.map +1 -0
  13. package/dist/{lib-es6 → lib-cjs/src}/api/classes/event.d.ts +326 -326
  14. package/dist/lib-cjs/src/api/classes/event.js +350 -0
  15. package/dist/lib-cjs/src/api/classes/event.js.map +1 -0
  16. package/dist/{lib-es6 → lib-cjs/src}/api/classes/eventBroadcaster.d.ts +26 -26
  17. package/dist/lib-cjs/src/api/classes/eventBroadcaster.js +50 -0
  18. package/dist/lib-cjs/src/api/classes/eventBroadcaster.js.map +1 -0
  19. package/dist/{lib-es6 → lib-cjs/src}/api/classes/parameter.d.ts +336 -336
  20. package/dist/lib-cjs/src/api/classes/parameter.js +462 -0
  21. package/dist/lib-cjs/src/api/classes/parameter.js.map +1 -0
  22. package/dist/lib-cjs/{api → src/api}/classes/parameterObservable.d.ts +36 -36
  23. package/dist/lib-cjs/src/api/classes/parameterObservable.js +98 -0
  24. package/dist/lib-cjs/src/api/classes/parameterObservable.js.map +1 -0
  25. package/dist/lib-cjs/{api → src/api}/classes/parameterizable.d.ts +15 -15
  26. package/dist/lib-cjs/src/api/classes/parameterizable.js +103 -0
  27. package/dist/lib-cjs/src/api/classes/parameterizable.js.map +1 -0
  28. package/dist/lib-cjs/{api → src/api}/classes/placementAnimation.d.ts +45 -44
  29. package/dist/lib-cjs/{api → src/api}/classes/placementAnimation.js +175 -163
  30. package/dist/lib-cjs/src/api/classes/placementAnimation.js.map +1 -0
  31. package/dist/{lib-es6 → lib-cjs/src}/api/classes/variant.d.ts +234 -234
  32. package/dist/lib-cjs/src/api/classes/variant.js +837 -0
  33. package/dist/lib-cjs/src/api/classes/variant.js.map +1 -0
  34. package/dist/lib-cjs/{api → src/api}/classes/variantInstance.d.ts +45 -45
  35. package/dist/lib-cjs/src/api/classes/variantInstance.js +102 -0
  36. package/dist/lib-cjs/src/api/classes/variantInstance.js.map +1 -0
  37. package/dist/{lib-es6 → lib-cjs/src}/api/classes/variantParameterizable.d.ts +17 -17
  38. package/dist/lib-cjs/src/api/classes/variantParameterizable.js +89 -0
  39. package/dist/lib-cjs/src/api/classes/variantParameterizable.js.map +1 -0
  40. package/dist/lib-cjs/{api → src/api}/classes/viewer.d.ts +187 -184
  41. package/dist/lib-cjs/src/api/classes/viewer.js +594 -0
  42. package/dist/lib-cjs/src/api/classes/viewer.js.map +1 -0
  43. package/dist/lib-cjs/{api → src/api}/classes/viewerLight.d.ts +66 -66
  44. package/dist/lib-cjs/src/api/classes/viewerLight.js +344 -0
  45. package/dist/lib-cjs/src/api/classes/viewerLight.js.map +1 -0
  46. package/dist/{lib-es6 → lib-cjs/src}/api/internal/lensRendering.d.ts +8 -8
  47. package/dist/lib-cjs/{api → src/api}/internal/lensRendering.js +11 -11
  48. package/dist/lib-cjs/src/api/internal/lensRendering.js.map +1 -0
  49. package/dist/{lib-es6 → lib-cjs/src}/api/internal/sceneSetup.d.ts +13 -13
  50. package/dist/lib-cjs/src/api/internal/sceneSetup.js +226 -0
  51. package/dist/lib-cjs/src/api/internal/sceneSetup.js.map +1 -0
  52. package/dist/lib-cjs/{api → src/api}/manager/animationManager.d.ts +30 -29
  53. package/dist/lib-cjs/src/api/manager/animationManager.js +127 -0
  54. package/dist/lib-cjs/src/api/manager/animationManager.js.map +1 -0
  55. package/dist/lib-cjs/{api → src/api}/manager/gltfExportManager.d.ts +65 -65
  56. package/dist/lib-cjs/src/api/manager/gltfExportManager.js +197 -0
  57. package/dist/lib-cjs/src/api/manager/gltfExportManager.js.map +1 -0
  58. package/dist/lib-cjs/{api → src/api}/manager/sceneManager.d.ts +31 -31
  59. package/dist/lib-cjs/src/api/manager/sceneManager.js +128 -0
  60. package/dist/lib-cjs/src/api/manager/sceneManager.js.map +1 -0
  61. package/dist/{lib-es6 → lib-cjs/src}/api/manager/variantInstanceManager.d.ts +92 -92
  62. package/dist/lib-cjs/src/api/manager/variantInstanceManager.js +261 -0
  63. package/dist/lib-cjs/src/api/manager/variantInstanceManager.js.map +1 -0
  64. package/dist/{lib-es6 → lib-cjs/src}/api/store/specStorage.d.ts +24 -24
  65. package/dist/lib-cjs/{api → src/api}/store/specStorage.js +50 -51
  66. package/dist/lib-cjs/src/api/store/specStorage.js.map +1 -0
  67. package/dist/{lib-es6 → lib-cjs/src}/api/util/babylonHelper.d.ts +174 -174
  68. package/dist/lib-cjs/{api → src/api}/util/babylonHelper.js +591 -611
  69. package/dist/lib-cjs/src/api/util/babylonHelper.js.map +1 -0
  70. package/dist/{lib-es6 → lib-cjs/src}/api/util/globalTypes.d.ts +366 -366
  71. package/dist/lib-cjs/src/api/util/globalTypes.js +2 -0
  72. package/dist/lib-cjs/src/api/util/globalTypes.js.map +1 -0
  73. package/dist/lib-cjs/{api → src/api}/util/resourceHelper.d.ts +58 -58
  74. package/dist/lib-cjs/src/api/util/resourceHelper.js +202 -0
  75. package/dist/lib-cjs/src/api/util/resourceHelper.js.map +1 -0
  76. package/dist/lib-cjs/{api → src/api}/util/sceneLoaderHelper.d.ts +35 -35
  77. package/dist/lib-cjs/{api → src/api}/util/sceneLoaderHelper.js +141 -140
  78. package/dist/lib-cjs/src/api/util/sceneLoaderHelper.js.map +1 -0
  79. package/dist/{lib-es6 → lib-cjs/src}/api/util/stringHelper.d.ts +9 -9
  80. package/dist/lib-cjs/{api → src/api}/util/stringHelper.js +23 -25
  81. package/dist/lib-cjs/src/api/util/stringHelper.js.map +1 -0
  82. package/dist/{lib-es6 → lib-cjs/src}/api/util/structureHelper.d.ts +9 -9
  83. package/dist/lib-cjs/{api → src/api}/util/structureHelper.js +48 -48
  84. package/dist/lib-cjs/src/api/util/structureHelper.js.map +1 -0
  85. package/dist/lib-cjs/{index.d.ts → src/index.d.ts} +51 -49
  86. package/dist/lib-cjs/{index.js → src/index.js} +110 -89
  87. package/dist/lib-cjs/src/index.js.map +1 -0
  88. package/dist/lib-es6/buildinfo.json +3 -3
  89. package/dist/lib-es6/es6.tsconfig.tsbuildinfo +1 -0
  90. package/dist/lib-es6/{api → src/api}/classes/animationInterface.d.ts +8 -8
  91. package/dist/lib-es6/src/api/classes/animationInterface.js +2 -0
  92. package/dist/lib-es6/src/api/classes/animationInterface.js.map +1 -0
  93. package/dist/{lib-cjs → lib-es6/src}/api/classes/dottedPath.d.ts +79 -79
  94. package/dist/lib-es6/src/api/classes/dottedPath.js +163 -0
  95. package/dist/lib-es6/src/api/classes/dottedPath.js.map +1 -0
  96. package/dist/lib-es6/{api → src/api}/classes/element.d.ts +149 -149
  97. package/dist/lib-es6/src/api/classes/element.js +665 -0
  98. package/dist/lib-es6/src/api/classes/element.js.map +1 -0
  99. package/dist/{lib-cjs → lib-es6/src}/api/classes/event.d.ts +326 -326
  100. package/dist/lib-es6/src/api/classes/event.js +346 -0
  101. package/dist/lib-es6/src/api/classes/event.js.map +1 -0
  102. package/dist/{lib-cjs → lib-es6/src}/api/classes/eventBroadcaster.d.ts +26 -26
  103. package/dist/lib-es6/src/api/classes/eventBroadcaster.js +43 -0
  104. package/dist/lib-es6/src/api/classes/eventBroadcaster.js.map +1 -0
  105. package/dist/{lib-cjs → lib-es6/src}/api/classes/parameter.d.ts +336 -336
  106. package/dist/lib-es6/src/api/classes/parameter.js +458 -0
  107. package/dist/lib-es6/src/api/classes/parameter.js.map +1 -0
  108. package/dist/lib-es6/{api → src/api}/classes/parameterObservable.d.ts +36 -36
  109. package/dist/lib-es6/src/api/classes/parameterObservable.js +94 -0
  110. package/dist/lib-es6/src/api/classes/parameterObservable.js.map +1 -0
  111. package/dist/lib-es6/{api → src/api}/classes/parameterizable.d.ts +15 -15
  112. package/dist/lib-es6/src/api/classes/parameterizable.js +99 -0
  113. package/dist/lib-es6/src/api/classes/parameterizable.js.map +1 -0
  114. package/dist/lib-es6/{api → src/api}/classes/placementAnimation.d.ts +45 -44
  115. package/dist/lib-es6/{api → src/api}/classes/placementAnimation.js +171 -160
  116. package/dist/lib-es6/src/api/classes/placementAnimation.js.map +1 -0
  117. package/dist/{lib-cjs → lib-es6/src}/api/classes/variant.d.ts +234 -234
  118. package/dist/lib-es6/src/api/classes/variant.js +833 -0
  119. package/dist/lib-es6/src/api/classes/variant.js.map +1 -0
  120. package/dist/lib-es6/{api → src/api}/classes/variantInstance.d.ts +45 -45
  121. package/dist/lib-es6/src/api/classes/variantInstance.js +98 -0
  122. package/dist/lib-es6/src/api/classes/variantInstance.js.map +1 -0
  123. package/dist/{lib-cjs → lib-es6/src}/api/classes/variantParameterizable.d.ts +17 -17
  124. package/dist/lib-es6/src/api/classes/variantParameterizable.js +85 -0
  125. package/dist/lib-es6/src/api/classes/variantParameterizable.js.map +1 -0
  126. package/dist/lib-es6/{api → src/api}/classes/viewer.d.ts +187 -184
  127. package/dist/lib-es6/src/api/classes/viewer.js +587 -0
  128. package/dist/lib-es6/src/api/classes/viewer.js.map +1 -0
  129. package/dist/lib-es6/{api → src/api}/classes/viewerLight.d.ts +66 -66
  130. package/dist/lib-es6/src/api/classes/viewerLight.js +317 -0
  131. package/dist/lib-es6/src/api/classes/viewerLight.js.map +1 -0
  132. package/dist/{lib-cjs → lib-es6/src}/api/internal/lensRendering.d.ts +8 -8
  133. package/dist/lib-es6/{api → src/api}/internal/lensRendering.js +8 -8
  134. package/dist/lib-es6/src/api/internal/lensRendering.js.map +1 -0
  135. package/dist/{lib-cjs → lib-es6/src}/api/internal/sceneSetup.d.ts +13 -13
  136. package/dist/lib-es6/src/api/internal/sceneSetup.js +198 -0
  137. package/dist/lib-es6/src/api/internal/sceneSetup.js.map +1 -0
  138. package/dist/lib-es6/{api → src/api}/manager/animationManager.d.ts +30 -29
  139. package/dist/lib-es6/src/api/manager/animationManager.js +123 -0
  140. package/dist/lib-es6/src/api/manager/animationManager.js.map +1 -0
  141. package/dist/lib-es6/{api → src/api}/manager/gltfExportManager.d.ts +65 -65
  142. package/dist/lib-es6/{api → src/api}/manager/gltfExportManager.js +192 -220
  143. package/dist/lib-es6/src/api/manager/gltfExportManager.js.map +1 -0
  144. package/dist/lib-es6/{api → src/api}/manager/sceneManager.d.ts +31 -31
  145. package/dist/lib-es6/src/api/manager/sceneManager.js +124 -0
  146. package/dist/lib-es6/src/api/manager/sceneManager.js.map +1 -0
  147. package/dist/{lib-cjs → lib-es6/src}/api/manager/variantInstanceManager.d.ts +92 -92
  148. package/dist/lib-es6/src/api/manager/variantInstanceManager.js +257 -0
  149. package/dist/lib-es6/src/api/manager/variantInstanceManager.js.map +1 -0
  150. package/dist/{lib-cjs → lib-es6/src}/api/store/specStorage.d.ts +24 -24
  151. package/dist/lib-es6/{api → src/api}/store/specStorage.js +46 -48
  152. package/dist/lib-es6/src/api/store/specStorage.js.map +1 -0
  153. package/dist/{lib-cjs → lib-es6/src}/api/util/babylonHelper.d.ts +174 -174
  154. package/dist/lib-es6/{api → src/api}/util/babylonHelper.js +561 -581
  155. package/dist/lib-es6/src/api/util/babylonHelper.js.map +1 -0
  156. package/dist/{lib-cjs → lib-es6/src}/api/util/globalTypes.d.ts +366 -366
  157. package/dist/lib-es6/src/api/util/globalTypes.js +2 -0
  158. package/dist/lib-es6/src/api/util/globalTypes.js.map +1 -0
  159. package/dist/lib-es6/{api → src/api}/util/resourceHelper.d.ts +58 -58
  160. package/dist/lib-es6/src/api/util/resourceHelper.js +192 -0
  161. package/dist/lib-es6/src/api/util/resourceHelper.js.map +1 -0
  162. package/dist/lib-es6/{api → src/api}/util/sceneLoaderHelper.d.ts +35 -35
  163. package/dist/lib-es6/{api → src/api}/util/sceneLoaderHelper.js +131 -133
  164. package/dist/lib-es6/src/api/util/sceneLoaderHelper.js.map +1 -0
  165. package/dist/{lib-cjs → lib-es6/src}/api/util/stringHelper.d.ts +9 -9
  166. package/dist/lib-es6/{api → src/api}/util/stringHelper.js +19 -21
  167. package/dist/lib-es6/src/api/util/stringHelper.js.map +1 -0
  168. package/dist/{lib-cjs → lib-es6/src}/api/util/structureHelper.d.ts +9 -9
  169. package/dist/lib-es6/{api → src/api}/util/structureHelper.js +45 -45
  170. package/dist/lib-es6/src/api/util/structureHelper.js.map +1 -0
  171. package/dist/lib-es6/{index.js → src/index.d.ts} +51 -51
  172. package/dist/lib-es6/{index.d.ts → src/index.js} +49 -49
  173. package/dist/lib-es6/src/index.js.map +1 -0
  174. package/dist/lib-full/lens-rendering.js +2 -0
  175. package/dist/lib-full/lens-rendering.js.map +1 -0
  176. package/dist/lib-full/main.js +3 -0
  177. package/dist/lib-full/main.js.LICENSE.txt +9 -0
  178. package/dist/lib-full/main.js.map +1 -0
  179. package/package.json +76 -88
  180. package/src/api/classes/animationInterface.ts +10 -10
  181. package/src/api/classes/dottedPath.ts +181 -181
  182. package/src/api/classes/element.ts +716 -716
  183. package/src/api/classes/event.ts +367 -367
  184. package/src/api/classes/eventBroadcaster.ts +52 -52
  185. package/src/api/classes/parameter.ts +494 -494
  186. package/src/api/classes/parameterObservable.ts +100 -100
  187. package/src/api/classes/parameterizable.ts +87 -87
  188. package/src/api/classes/placementAnimation.ts +161 -160
  189. package/src/api/classes/variant.ts +904 -905
  190. package/src/api/classes/variantInstance.ts +97 -97
  191. package/src/api/classes/variantParameterizable.ts +85 -85
  192. package/src/api/classes/viewer.ts +669 -668
  193. package/src/api/classes/viewerLight.ts +334 -334
  194. package/src/api/internal/debugViewer.ts +90 -90
  195. package/src/api/internal/lensRendering.ts +9 -10
  196. package/src/api/internal/sceneSetup.ts +204 -204
  197. package/src/api/manager/animationManager.ts +143 -142
  198. package/src/api/manager/gltfExportManager.ts +191 -191
  199. package/src/api/manager/sceneManager.ts +127 -127
  200. package/src/api/manager/variantInstanceManager.ts +265 -265
  201. package/src/api/store/specStorage.ts +51 -51
  202. package/src/api/util/babylonHelper.ts +663 -663
  203. package/src/api/util/globalTypes.ts +413 -413
  204. package/src/api/util/resourceHelper.ts +189 -189
  205. package/src/api/util/sceneLoaderHelper.ts +148 -147
  206. package/src/api/util/stringHelper.ts +23 -23
  207. package/src/api/util/structureHelper.ts +49 -49
  208. package/src/dev.ts +61 -64
  209. package/src/index.ts +96 -94
  210. package/src/types.d.ts +28 -28
  211. package/dist/lib-cjs/api/classes/animationInterface.js +0 -2
  212. package/dist/lib-cjs/api/classes/animationInterface.js.map +0 -1
  213. package/dist/lib-cjs/api/classes/dottedPath.js +0 -188
  214. package/dist/lib-cjs/api/classes/dottedPath.js.map +0 -1
  215. package/dist/lib-cjs/api/classes/element.js +0 -824
  216. package/dist/lib-cjs/api/classes/element.js.map +0 -1
  217. package/dist/lib-cjs/api/classes/elementParameterizable.d.ts +0 -14
  218. package/dist/lib-cjs/api/classes/elementParameterizable.js +0 -135
  219. package/dist/lib-cjs/api/classes/elementParameterizable.js.map +0 -1
  220. package/dist/lib-cjs/api/classes/event.js +0 -372
  221. package/dist/lib-cjs/api/classes/event.js.map +0 -1
  222. package/dist/lib-cjs/api/classes/eventBroadcaster.js +0 -54
  223. package/dist/lib-cjs/api/classes/eventBroadcaster.js.map +0 -1
  224. package/dist/lib-cjs/api/classes/parameter.js +0 -472
  225. package/dist/lib-cjs/api/classes/parameter.js.map +0 -1
  226. package/dist/lib-cjs/api/classes/parameterObservable.js +0 -102
  227. package/dist/lib-cjs/api/classes/parameterObservable.js.map +0 -1
  228. package/dist/lib-cjs/api/classes/parameterizable.js +0 -150
  229. package/dist/lib-cjs/api/classes/parameterizable.js.map +0 -1
  230. package/dist/lib-cjs/api/classes/placementAnimation.js.map +0 -1
  231. package/dist/lib-cjs/api/classes/variant.js +0 -1204
  232. package/dist/lib-cjs/api/classes/variant.js.map +0 -1
  233. package/dist/lib-cjs/api/classes/variantInstance.js +0 -109
  234. package/dist/lib-cjs/api/classes/variantInstance.js.map +0 -1
  235. package/dist/lib-cjs/api/classes/variantParameterizable.js +0 -100
  236. package/dist/lib-cjs/api/classes/variantParameterizable.js.map +0 -1
  237. package/dist/lib-cjs/api/classes/viewer.js +0 -732
  238. package/dist/lib-cjs/api/classes/viewer.js.map +0 -1
  239. package/dist/lib-cjs/api/classes/viewerLight.js +0 -393
  240. package/dist/lib-cjs/api/classes/viewerLight.js.map +0 -1
  241. package/dist/lib-cjs/api/internal/debugViewer.d.ts +0 -13
  242. package/dist/lib-cjs/api/internal/debugViewer.js +0 -87
  243. package/dist/lib-cjs/api/internal/debugViewer.js.map +0 -1
  244. package/dist/lib-cjs/api/internal/lensRendering.js.map +0 -1
  245. package/dist/lib-cjs/api/internal/sceneSetup.js +0 -239
  246. package/dist/lib-cjs/api/internal/sceneSetup.js.map +0 -1
  247. package/dist/lib-cjs/api/manager/animationManager.js +0 -131
  248. package/dist/lib-cjs/api/manager/animationManager.js.map +0 -1
  249. package/dist/lib-cjs/api/manager/gltfExportManager.js +0 -224
  250. package/dist/lib-cjs/api/manager/gltfExportManager.js.map +0 -1
  251. package/dist/lib-cjs/api/manager/sceneManager.js +0 -153
  252. package/dist/lib-cjs/api/manager/sceneManager.js.map +0 -1
  253. package/dist/lib-cjs/api/manager/variantInstanceManager.js +0 -336
  254. package/dist/lib-cjs/api/manager/variantInstanceManager.js.map +0 -1
  255. package/dist/lib-cjs/api/store/specStorage.js.map +0 -1
  256. package/dist/lib-cjs/api/util/babylonHelper.js.map +0 -1
  257. package/dist/lib-cjs/api/util/globalTypes.js +0 -2
  258. package/dist/lib-cjs/api/util/globalTypes.js.map +0 -1
  259. package/dist/lib-cjs/api/util/resourceHelper.js +0 -258
  260. package/dist/lib-cjs/api/util/resourceHelper.js.map +0 -1
  261. package/dist/lib-cjs/api/util/sceneLoaderHelper.js.map +0 -1
  262. package/dist/lib-cjs/api/util/stringHelper.js.map +0 -1
  263. package/dist/lib-cjs/api/util/structureHelper.js.map +0 -1
  264. package/dist/lib-cjs/index.js.map +0 -1
  265. package/dist/lib-es6/api/classes/animationInterface.js +0 -2
  266. package/dist/lib-es6/api/classes/animationInterface.js.map +0 -1
  267. package/dist/lib-es6/api/classes/dottedPath.js +0 -185
  268. package/dist/lib-es6/api/classes/dottedPath.js.map +0 -1
  269. package/dist/lib-es6/api/classes/element.js +0 -821
  270. package/dist/lib-es6/api/classes/element.js.map +0 -1
  271. package/dist/lib-es6/api/classes/event.js +0 -369
  272. package/dist/lib-es6/api/classes/event.js.map +0 -1
  273. package/dist/lib-es6/api/classes/eventBroadcaster.js +0 -51
  274. package/dist/lib-es6/api/classes/eventBroadcaster.js.map +0 -1
  275. package/dist/lib-es6/api/classes/parameter.js +0 -469
  276. package/dist/lib-es6/api/classes/parameter.js.map +0 -1
  277. package/dist/lib-es6/api/classes/parameterObservable.js +0 -99
  278. package/dist/lib-es6/api/classes/parameterObservable.js.map +0 -1
  279. package/dist/lib-es6/api/classes/parameterizable.js +0 -147
  280. package/dist/lib-es6/api/classes/parameterizable.js.map +0 -1
  281. package/dist/lib-es6/api/classes/placementAnimation.js.map +0 -1
  282. package/dist/lib-es6/api/classes/variant.js +0 -1199
  283. package/dist/lib-es6/api/classes/variant.js.map +0 -1
  284. package/dist/lib-es6/api/classes/variantInstance.js +0 -106
  285. package/dist/lib-es6/api/classes/variantInstance.js.map +0 -1
  286. package/dist/lib-es6/api/classes/variantParameterizable.js +0 -97
  287. package/dist/lib-es6/api/classes/variantParameterizable.js.map +0 -1
  288. package/dist/lib-es6/api/classes/viewer.js +0 -729
  289. package/dist/lib-es6/api/classes/viewer.js.map +0 -1
  290. package/dist/lib-es6/api/classes/viewerLight.js +0 -390
  291. package/dist/lib-es6/api/classes/viewerLight.js.map +0 -1
  292. package/dist/lib-es6/api/internal/debugViewer.d.ts +0 -13
  293. package/dist/lib-es6/api/internal/debugViewer.js +0 -84
  294. package/dist/lib-es6/api/internal/debugViewer.js.map +0 -1
  295. package/dist/lib-es6/api/internal/lensRendering.js.map +0 -1
  296. package/dist/lib-es6/api/internal/sceneSetup.js +0 -234
  297. package/dist/lib-es6/api/internal/sceneSetup.js.map +0 -1
  298. package/dist/lib-es6/api/manager/animationManager.js +0 -128
  299. package/dist/lib-es6/api/manager/animationManager.js.map +0 -1
  300. package/dist/lib-es6/api/manager/gltfExportManager.js.map +0 -1
  301. package/dist/lib-es6/api/manager/sceneManager.js +0 -150
  302. package/dist/lib-es6/api/manager/sceneManager.js.map +0 -1
  303. package/dist/lib-es6/api/manager/variantInstanceManager.js +0 -333
  304. package/dist/lib-es6/api/manager/variantInstanceManager.js.map +0 -1
  305. package/dist/lib-es6/api/store/specStorage.js.map +0 -1
  306. package/dist/lib-es6/api/util/babylonHelper.js.map +0 -1
  307. package/dist/lib-es6/api/util/globalTypes.js +0 -2
  308. package/dist/lib-es6/api/util/globalTypes.js.map +0 -1
  309. package/dist/lib-es6/api/util/resourceHelper.js +0 -248
  310. package/dist/lib-es6/api/util/resourceHelper.js.map +0 -1
  311. package/dist/lib-es6/api/util/sceneLoaderHelper.js.map +0 -1
  312. package/dist/lib-es6/api/util/stringHelper.js.map +0 -1
  313. package/dist/lib-es6/api/util/structureHelper.js.map +0 -1
  314. package/dist/lib-es6/index.js.map +0 -1
  315. package/dist/webpack-stats.json +0 -0
  316. package/src/buildinfo.json +0 -3
  317. package/src/commonjs.tsconfig.json +0 -10
  318. package/src/declaration.tsconfig.json +0 -8
  319. package/src/es6.tsconfig.json +0 -10
  320. package/src/pagesconfig.json +0 -81
  321. package/src/tsconfig.json +0 -33
  322. package/src/tsconfig.types.json +0 -9
@@ -1,668 +1,669 @@
1
- import { EnvironmentHelper } from '@babylonjs/core/Helpers/environmentHelper';
2
- import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera';
3
- import { PickingInfo } from '@babylonjs/core/Collisions/pickingInfo';
4
- import { BoundingInfo } from '@babylonjs/core/Culling/boundingInfo';
5
- import { Engine } from '@babylonjs/core/Engines/engine';
6
- import { HighlightLayer } from '@babylonjs/core/Layers/highlightLayer';
7
- import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
8
- import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
9
- import { Color3 } from '@babylonjs/core/Maths/math.color';
10
- import { Vector3 } from '@babylonjs/core/Maths/math.vector';
11
- import { Mesh } from '@babylonjs/core/Meshes/mesh';
12
- import { ScreenshotTools } from '@babylonjs/core/Misc/screenshotTools';
13
- import { Scene } from '@babylonjs/core/scene';
14
- import { WebXRSessionManager } from '@babylonjs/core/XR/webXRSessionManager';
15
- import { isMeshIncludedInExclusionList } from '../util/structureHelper';
16
- import { isString } from 'lodash-es';
17
- import { version } from '../../buildinfo.json';
18
- import { sceneSetup } from '../internal/sceneSetup';
19
- import { AnimationManager } from '../manager/animationManager';
20
- import { GltfExportManager } from '../manager/gltfExportManager';
21
- import { SceneManager } from '../manager/sceneManager';
22
- import { VariantInstanceManager } from '../manager/variantInstanceManager';
23
- import { SpecStorage } from '../store/specStorage';
24
- import { debounce, loadJavascript, loadJson } from '../util/resourceHelper';
25
- import { Event } from './event';
26
- import { EventBroadcaster } from './eventBroadcaster';
27
- import { Parameter } from './parameter';
28
- import { Variant } from './variant';
29
- import { VariantInstance } from './variantInstance';
30
- import { IPointerEvent } from '@babylonjs/core/Events/deviceInputEvents';
31
- import { DebugLayer } from '@babylonjs/core/Debug/debugLayer';
32
- import { PhotoDome } from '@babylonjs/core/Helpers/photoDome';
33
- import { backgroundDomeName, envHelperMetadataName } from '../util/babylonHelper';
34
- import { ISceneLoaderPlugin, SceneLoader } from '@babylonjs/core/Loading/sceneLoader';
35
- import { getCustomCbnBabylonLoaderPlugin } from '../util/sceneLoaderHelper';
36
-
37
- /**
38
- * The main exposed object. This is the entry point into the application
39
- *
40
- * ```js
41
- * const canvas = document.getElementById( 'babylon-canvas' );
42
- * const viewer = Viewer( canvas, '/path/to/index.json' );
43
- * ```
44
- * The class does nothing on its own and needs to {@link bootstrap}
45
- */
46
- export class Viewer extends EventBroadcaster {
47
- protected _scene: Scene | null = null;
48
-
49
- protected _animationManager: AnimationManager | null = null;
50
-
51
- protected _sceneManager: SceneManager | null = null;
52
-
53
- protected _gltfExportManager: GltfExportManager | null = null;
54
-
55
- protected _variantInstances: VariantInstanceManager | null = null;
56
-
57
- // default value is `true` ATM for compatibility reasons
58
- // in the future material cloning should be the edge case
59
- protected _cloneMaterialsOnMutation: boolean = true;
60
-
61
- protected _isRenderLoopPaused: boolean = false;
62
-
63
- protected _inspectorLoaded: boolean = false;
64
-
65
- static version = version;
66
-
67
- /**
68
- * Constructor
69
- */
70
- public constructor(public readonly canvas: HTMLCanvasElement, protected structureJson: string | StructureJson) {
71
- super();
72
- }
73
-
74
- /**
75
- * Gets the BabylonJS Scene that is attached to the instance.
76
- *
77
- * @throws Error if the `scene` has not been initialized.
78
- */
79
- get scene(): Scene {
80
- if (!this._scene) {
81
- throw new Error(`Scene has not been initialized.`);
82
- }
83
- return this._scene;
84
- }
85
-
86
- /**
87
- * Gets the {@link SceneManager} attached to the viewer.
88
- *
89
- * @throws Error if the {@link SceneManager} has not been initialized.
90
- */
91
- get sceneManager(): SceneManager {
92
- if (!this._sceneManager) {
93
- throw new Error(`SceneManager has not been initialized.`);
94
- }
95
- return this._sceneManager;
96
- }
97
-
98
- /**
99
- * Gets the {@link GltfExportManager} attached to the viewer.
100
- *
101
- * @throws Error if the {@link GltfExportManager} has not been initialized.
102
- */
103
- get gltfExportManager(): GltfExportManager {
104
- if (!this._gltfExportManager) {
105
- throw new Error(`GltfExportManager has not been initialized.`);
106
- }
107
- return this._gltfExportManager;
108
- }
109
-
110
- /**
111
- * Gets the BabylonJS Engine that is attached to the viewer.
112
- */
113
- get engine(): Engine {
114
- return this.scene.getEngine();
115
- }
116
-
117
- /**
118
- * Gets the {@link VariantInstanceManager} attached to the viewer.
119
- *
120
- * @throws Error if the {@link VariantInstanceManager} has not been initialized.
121
- */
122
- get variantInstances(): VariantInstanceManager {
123
- if (!this._variantInstances) {
124
- throw Error(`There is no variantInstanceManager.`);
125
- }
126
- return this._variantInstances;
127
- }
128
-
129
- /**
130
- * Gets the {@link AnimationManager} attached to the viewer.
131
- *
132
- * @throws Error if the {@link AnimationManager} has not been initialized.
133
- */
134
- get animationManager(): AnimationManager {
135
- if (!this._animationManager) {
136
- throw new Error(`There is no animationManager instance.`);
137
- }
138
- return this._animationManager;
139
- }
140
-
141
- /**
142
- * Gets the `cloneMaterialsOnMutation` flag, as defined in the spec
143
- */
144
- get cloneMaterialsOnMutation(): boolean {
145
- return this._cloneMaterialsOnMutation;
146
- }
147
-
148
- /**
149
- * Starts the application. This will
150
- * * load the given "index" JSON file
151
- * * setup the scene with the "scene" JSON file
152
- * * create an (optional) default setup with different variant settings
153
- * * sets up resizing by attaching a debounced version of {@link resize}
154
- *
155
- * @throws Error if any of the files is not found/valid
156
- *
157
- * @emits {@link Event.BOOTSTRAP_START}
158
- * @emits {@link Event.BOOTSTRAP_END}
159
- */
160
- public async bootstrap(): Promise<Viewer> {
161
- this.broadcastEvent(Event.BOOTSTRAP_START, this);
162
-
163
- let indexJson;
164
- if (isString(this.structureJson)) {
165
- indexJson = await loadJson<StructureJson>(this.structureJson);
166
- } else {
167
- indexJson = this.structureJson;
168
- }
169
- if (!indexJson.scene) {
170
- throw new Error(`No "scene" property found for bootstrapping.`);
171
- }
172
- // fill spec store
173
- SpecStorage.createFromSpec(indexJson);
174
-
175
- this.initCbnBabylonLoaderPlugin();
176
-
177
- // load scene
178
- if (isString(indexJson.scene)) {
179
- const sceneJson = await loadJson<SceneJson>(indexJson.scene);
180
- indexJson.scene = sceneJson;
181
- }
182
- this._scene = await this.initScene();
183
- // create instance manager
184
- const rootVariant = await Variant.create('_', indexJson, this);
185
- this._variantInstances = await VariantInstanceManager.create(rootVariant);
186
- // create optional default instances
187
- if (indexJson.setup) {
188
- if (isString(indexJson.setup)) {
189
- const setupJson = await loadJson<SetupJson>(indexJson.setup);
190
- indexJson.setup = setupJson;
191
- }
192
- await this.createVariantInstances();
193
- }
194
- // create gltf export manager
195
- this._gltfExportManager = await GltfExportManager.create(this);
196
- // resize handler
197
- window.addEventListener('resize', debounce(this.resize.bind(this), 100));
198
- // wait until scene is completely ready
199
- await this.scene.whenReadyAsync();
200
- // event broadcasting
201
- this.broadcastEvent(Event.BOOTSTRAP_END, this);
202
- // render loop
203
- this.engine.runRenderLoop(() => {
204
- if (!this._isRenderLoopPaused) this.scene.render();
205
- });
206
- return this;
207
- }
208
-
209
- /**
210
- * Enables the BabylonJS [Inspector](https://doc.babylonjs.com/toolsAndResources/tools/inspector).\
211
- * Due to the additional size of the inspector, the CDN version is used instead of shipping the required code with the viewer.\
212
- * This means that the code will be downloaded only when needed and calling `enableDebugLayer` can take a little while depending on your internet connection etc.
213
- */
214
- public async enableDebugLayer(options?: IInspectorOptions) {
215
- if (!this._inspectorLoaded) {
216
- // CDN version of inspector requires the BabylonJS core to be available as CDN module as well
217
- await loadJavascript('https://cdn.jsdelivr.net/npm/babylonjs@5.6.0/babylon.min.js');
218
-
219
- DebugLayer.InspectorURL =
220
- 'https://cdn.jsdelivr.net/npm/babylonjs-inspector@5.6.0/babylon.inspector.bundle.max.min.js';
221
-
222
- this._inspectorLoaded = true;
223
- }
224
-
225
- await this.scene.debugLayer.show(options);
226
- }
227
-
228
- /**
229
- * Destroys all registered {@link VariantInstance}s that are registered
230
- */
231
- public destroyVariantInstances(): Viewer {
232
- this.variantInstances.all.forEach(variantInstance => {
233
- this.variantInstances.destroy(variantInstance.name);
234
- });
235
- return this;
236
- }
237
-
238
- /**
239
- * Trigger a resize event for the `Engine`
240
- */
241
- public resize(): Viewer {
242
- this.engine.resize();
243
- return this;
244
- }
245
-
246
- /**
247
- * A convenience method for directly getting a Node from a {@link VariantInstance} and an {@link Element} by its
248
- * {@link DottedPath}s.
249
- */
250
- public async getNode(
251
- variantInstanceName: string,
252
- elementDottedPath: DottedPathArgument,
253
- nodeDottedPath: DottedPathArgument
254
- ): Promise<TransformNode> {
255
- const variantInstance = await this.variantInstances.get(variantInstanceName);
256
- return variantInstance.getNode(elementDottedPath, nodeDottedPath);
257
- }
258
-
259
- /**
260
- * A convenience method for directly getting a Node from a {@link VariantInstance} and an {@link Element} by its
261
- * {@link DottedPath}s.
262
- */
263
- public async getMesh(
264
- variantInstanceName: string,
265
- elementDottedPath: DottedPathArgument,
266
- meshDottedPath: DottedPathArgument
267
- ): Promise<Mesh | null> {
268
- const variantInstance = await this.variantInstances.get(variantInstanceName);
269
- return variantInstance.getMesh(elementDottedPath, meshDottedPath);
270
- }
271
-
272
- /**
273
- * Switches the camera
274
- *
275
- * @emits {@link Event.CAMERA_SWITCHED}
276
- */
277
- public switchCamera(newCamera: string, reset: boolean = true): Viewer {
278
- const camera = this.scene.getCameraByName(newCamera);
279
- if (camera) {
280
- const activeCamera = this.scene.activeCamera;
281
- if (activeCamera) {
282
- activeCamera.detachControl(this.engine.getRenderingCanvas()!);
283
- }
284
- if (reset) {
285
- camera.restoreState();
286
- }
287
- this.scene.setActiveCameraByName(newCamera);
288
- camera.attachControl(this.engine.getRenderingCanvas()!);
289
- this.broadcastEvent(Event.CAMERA_SWITCHED, camera);
290
- } else {
291
- throw new Error(`Given camera "${newCamera}" not found.`);
292
- }
293
- // TODO: put traceable observers to new camera (@see element)
294
- return this;
295
- }
296
-
297
- /**
298
- * Moves or animates the active camera to given `placement`.
299
- */
300
- public async moveActiveCameraTo(
301
- placement: string | PlacementDefinition,
302
- animation?: string | AnimationDefinition
303
- ): Promise<AnimationInterface> {
304
- return this.animationManager.animateToPlacement(this.sceneManager.activeCamera, placement, animation);
305
- }
306
-
307
- /**
308
- * Takes a sceenshot the the current scene. The result is a string containing a base64 encoded image
309
- */
310
- public screenshot(settings?: ScreenshotSettings): Promise<string> {
311
- return new Promise((resolve, reject) => {
312
- if (!this.engine) {
313
- return reject('Engine is null');
314
- }
315
- if (!this.scene) {
316
- return reject('Scene is null');
317
- }
318
- this.scene.render(); // in combination with a render target, we need to refresh the scene manually to get the latest view
319
- ScreenshotTools.CreateScreenshotUsingRenderTarget(
320
- this.engine,
321
- this.sceneManager.activeCamera,
322
- settings?.size ?? { width: this.canvas.clientWidth, height: this.canvas.clientHeight },
323
- resolve,
324
- settings?.mimeType ?? 'image/png',
325
- settings?.samples ?? 1,
326
- settings?.antialiasing ?? false,
327
- settings?.fileName ?? 'screenshot.png',
328
- settings?.renderSprites ?? false
329
- );
330
- });
331
- }
332
-
333
- /**
334
- * Checks whether the browser is capable of handling XR.
335
- */
336
- public async isBrowserARCapable(): Promise<boolean> {
337
- return await WebXRSessionManager.IsSessionSupportedAsync('immersive-ar');
338
- }
339
-
340
- /**
341
- * Calculates the bounding box from all visible meshes on the scene.
342
- */
343
- public async calculateBoundingBox(excludeGeometry?: ExcludedGeometryList): Promise<Mesh> {
344
- if (this.scene.meshes.length === 0) {
345
- throw new Error('There are currently no meshes on the scene.');
346
- }
347
- this.scene.render(); // CB-6062: workaround for BoundingBox not respecting render loop
348
- const bbName = '__bounding_box__';
349
-
350
- const { max, min } = this.scene.meshes
351
- .filter(mesh => {
352
- const isEnabled = mesh.isEnabled();
353
- // ignore the existing bounding box mesh for calculating the current one
354
- const isNotBBoxMesh = bbName !== mesh.id;
355
- // ignore meshes with invalid bounding infos
356
- const hasValidBBoxInfo = mesh.getBoundingInfo().boundingSphere.radius > 0;
357
- // ignore excluded meshes
358
- const isExcluded = excludeGeometry ? isMeshIncludedInExclusionList(mesh as Mesh, excludeGeometry) : false;
359
- return isEnabled && isNotBBoxMesh && hasValidBBoxInfo && !isExcluded;
360
- })
361
- .reduce(
362
- (accBBoxMinMax, curMesh, idx) => {
363
- const bBox = curMesh.getBoundingInfo().boundingBox;
364
- // use the first entry in the array as default value and get the resulting maximum/minimum values
365
- const max = idx === 0 ? bBox.maximumWorld : Vector3.Maximize(accBBoxMinMax.max, bBox.maximumWorld);
366
- const min = idx === 0 ? bBox.minimumWorld : Vector3.Minimize(accBBoxMinMax.min, bBox.minimumWorld);
367
- return { max, min };
368
- },
369
- { max: new Vector3(), min: new Vector3() }
370
- );
371
-
372
- let boundingBox = this.scene.getMeshByName(bbName) as Mesh;
373
- if (!boundingBox) {
374
- boundingBox = new Mesh(bbName, this.scene);
375
- }
376
- boundingBox.setBoundingInfo(new BoundingInfo(min, max));
377
- return boundingBox;
378
- }
379
-
380
- /**
381
- * Focuses the camera to see every visible mesh in scene and tries to optimize wheel precision and panning
382
- */
383
- public async autofocusActiveCamera(settings?: AutofocusSettings) {
384
- // first check some preconditions
385
- const activeCamera = this.scene.activeCamera;
386
- if (!activeCamera) {
387
- throw new Error('No active camera found when using autofocus feature.');
388
- }
389
- if (!(activeCamera instanceof ArcRotateCamera)) {
390
- const cameraClsName = activeCamera.getClassName();
391
- throw new Error(`Camera of type "${cameraClsName}" is not implemented yet to use autofocus feature.`);
392
- }
393
-
394
- let exclude = settings?.exclude || [];
395
-
396
- // Exclude shown photo dome or environment helper from bounding box calculation
397
- const photoDome = this.scene.getNodeByName(backgroundDomeName) as undefined | PhotoDome;
398
- const photoDomeMeshes = photoDome?.getChildMeshes();
399
- if (photoDomeMeshes?.length) {
400
- exclude = [...exclude, ...photoDomeMeshes];
401
- }
402
-
403
- const envHelper = this.scene.metadata?.[envHelperMetadataName] as undefined | EnvironmentHelper;
404
- if (envHelper?.rootMesh) {
405
- exclude = [...exclude, envHelper.rootMesh];
406
- }
407
-
408
- // get bounding box of all visible meshes, this is the base for the autofocus algorithm
409
- const boundingBox = await this.calculateBoundingBox(exclude);
410
-
411
- // focus the helper camera and set the calculated camera data to the real camera
412
- const helperCamera = this.getFocusedHelperCamera(boundingBox, settings);
413
- await this.applyFocusedHelperCameraData(activeCamera, helperCamera, settings);
414
-
415
- // remove the helper camera
416
- helperCamera.dispose();
417
- }
418
-
419
- /**
420
- * Resets everything by calling {@link destroy} to clear all references and {@link bootstrap} to setup a clean
421
- * environment
422
- */
423
- public async reset(): Promise<Viewer> {
424
- await this.destroy();
425
- return this.bootstrap();
426
- }
427
-
428
- /**
429
- * Destroys
430
- *
431
- * * all {@link VariantInstance}s using {@link destroyVariantInstances}
432
- * * calling `dispose` on the `Engine` and `Scene`
433
- */
434
- public destroy(): Viewer {
435
- this.destroyVariantInstances();
436
- this.scene.dispose();
437
- SpecStorage.destroy();
438
- return this;
439
- }
440
-
441
- /**
442
- * Show coordinate system with given dimension (for debugging purpose).
443
- */
444
- public showWorldCoordinates(dimension: number) {
445
- const scene = this.scene;
446
- const makeTextPlane = function (text: string, color: string, size: number) {
447
- const dynamicTexture = new DynamicTexture('DynamicTexture', 50, scene, true);
448
- dynamicTexture.hasAlpha = true;
449
- dynamicTexture.drawText(text, 5, 40, 'bold 36px Arial', color, 'transparent', true);
450
- const plane = Mesh.CreatePlane('TextPlane', size, scene, true);
451
- plane.material = new StandardMaterial('TextPlaneMaterial', scene);
452
- plane.material.backFaceCulling = false;
453
- // @ts-ignore
454
- plane.material.specularColor = new Color3(0, 0, 0);
455
- // @ts-ignore
456
- plane.material.diffuseTexture = dynamicTexture;
457
- return plane;
458
- };
459
-
460
- const axisX = Mesh.CreateLines(
461
- 'axisX',
462
- [
463
- Vector3.Zero(),
464
- new Vector3(dimension, 0, 0),
465
- new Vector3(dimension * 0.95, 0.05 * dimension, 0),
466
- new Vector3(dimension, 0, 0),
467
- new Vector3(dimension * 0.95, -0.05 * dimension, 0),
468
- ],
469
- scene,
470
- false
471
- );
472
- axisX.color = new Color3(1, 0, 0);
473
- const xChar = makeTextPlane('X', 'red', dimension / 10);
474
- xChar.position = new Vector3(0.9 * dimension, -0.05 * dimension, 0);
475
- const axisY = Mesh.CreateLines(
476
- 'axisY',
477
- [
478
- Vector3.Zero(),
479
- new Vector3(0, dimension, 0),
480
- new Vector3(-0.05 * dimension, dimension * 0.95, 0),
481
- new Vector3(0, dimension, 0),
482
- new Vector3(0.05 * dimension, dimension * 0.95, 0),
483
- ],
484
- scene,
485
- false
486
- );
487
- axisY.color = new Color3(0, 1, 0);
488
- const yChar = makeTextPlane('Y', 'green', dimension / 10);
489
- yChar.position = new Vector3(0, 0.9 * dimension, -0.05 * dimension);
490
- const axisZ = Mesh.CreateLines(
491
- 'axisZ',
492
- [
493
- Vector3.Zero(),
494
- new Vector3(0, 0, dimension),
495
- new Vector3(0, -0.05 * dimension, dimension * 0.95),
496
- new Vector3(0, 0, dimension),
497
- new Vector3(0, 0.05 * dimension, dimension * 0.95),
498
- ],
499
- scene,
500
- false
501
- );
502
- axisZ.color = new Color3(0, 0, 1);
503
- const zChar = makeTextPlane('Z', 'blue', dimension / 10);
504
- zChar.position = new Vector3(0, 0.05 * dimension, 0.9 * dimension);
505
- }
506
-
507
- /**
508
- * Pause render loop.
509
- */
510
- public pauseRendering() {
511
- this._isRenderLoopPaused = true;
512
- }
513
-
514
- /**
515
- * Resume render loop when paused.
516
- */
517
- public resumeRendering() {
518
- this._isRenderLoopPaused = false;
519
- }
520
-
521
- /**
522
- * @emits {@link Event.SCENE_PROCESSING_START}
523
- * @emits {@link Event.SCENE_PROCESSING_END}
524
- */
525
- protected async initScene(): Promise<Scene> {
526
- const sceneJson = SpecStorage.get<SceneJson>('scene');
527
- this.broadcastEvent(Event.SCENE_PROCESSING_START, sceneJson);
528
- const engine = new Engine(
529
- this.canvas as HTMLCanvasElement,
530
- sceneJson.engine?.antialiasing ?? false,
531
- sceneJson.engine?.options
532
- );
533
- const scene = await sceneSetup(engine, sceneJson);
534
- if (sceneJson.meshPicking) {
535
- new HighlightLayer('default', scene);
536
- scene.onPointerPick = (pointerEvent: IPointerEvent, pickInfo: PickingInfo) => {
537
- if (!pickInfo.hit) {
538
- return;
539
- }
540
- const mesh = pickInfo.pickedMesh;
541
- this.broadcastEvent(Event.MESH_PICKED, mesh, mesh?.metadata.element, mesh?.metadata.variant);
542
- if (mesh?.metadata.element) {
543
- this.broadcastEvent(Event.ELEMENT_PICKED, mesh.metadata.element);
544
- }
545
- if (mesh?.metadata.variant) {
546
- if (mesh.metadata.variant.inheritedParameters[Parameter.HIGHLIGHT_ENABLED]) {
547
- mesh.metadata.variant.toggleHighlight();
548
- }
549
- this.broadcastEvent(Event.VARIANT_PICKED, mesh.metadata.variant);
550
- }
551
- };
552
- }
553
- this._sceneManager = await SceneManager.create(scene);
554
- this._animationManager = await AnimationManager.create(scene);
555
- if (sceneJson.cloneMaterialsOnMutation !== undefined) {
556
- this._cloneMaterialsOnMutation = sceneJson.cloneMaterialsOnMutation;
557
- }
558
- this.broadcastEvent(Event.SCENE_PROCESSING_END, scene);
559
- return scene;
560
- }
561
-
562
- /**
563
- * Register custom file loader for babylon files which adds "missing-material" metadata to meshes which reference
564
- * materials that are not present in the `materials` section of the given babylon file.
565
- *
566
- * Required for babylon files & materials loaded from "Combeenation configurator assets".
567
- */
568
- protected initCbnBabylonLoaderPlugin() {
569
- const previousLoaderPlugin = SceneLoader.GetPluginForExtension('babylon') as ISceneLoaderPlugin;
570
- const customLoaderPlugin = getCustomCbnBabylonLoaderPlugin(previousLoaderPlugin);
571
- SceneLoader.RegisterPlugin(customLoaderPlugin);
572
- }
573
-
574
- /**
575
- * Batch creation of multiple {@link VariantInstance} objects with a {@link SetupJson} object passed
576
- */
577
- protected async createVariantInstances(): Promise<VariantInstance[]> {
578
- const setupJson = SpecStorage.get<SetupJson>('setup');
579
- const instances = [];
580
- for (const instanceDefinition of setupJson.instances) {
581
- if (instanceDefinition.lazy) {
582
- this.variantInstances.register(instanceDefinition);
583
- continue;
584
- }
585
- instances.push(
586
- await this.variantInstances.create(
587
- instanceDefinition.variant,
588
- instanceDefinition.name,
589
- instanceDefinition.parameters
590
- )
591
- );
592
- }
593
- return instances;
594
- }
595
-
596
- /**
597
- * Help function for focusing a helper camera exactly onto the given bounding box
598
- */
599
- private getFocusedHelperCamera(boundingBox: Mesh, settings?: AutofocusSettings): ArcRotateCamera {
600
- // use helper camera to get some default values and set the values of the real camera accordingly
601
- const helperCamera = new ArcRotateCamera(
602
- '__helper_camera__',
603
- 0, // camera angles will be overwritten after the target has been set
604
- 0,
605
- 0, // radius will be calculated, so we can set to 0 here
606
- Vector3.Zero(),
607
- this.scene
608
- );
609
- // this is required for automatically calculating the `lowerRadiusLimit`, so that we don't "dive" into meshes
610
- // see https://doc.babylonjs.com/divingDeeper/behaviors/cameraBehaviors#framing-behavior
611
- helperCamera.useFramingBehavior = true;
612
-
613
- // `minZ` is the camera distance beyond which the mesh will be clipped
614
- // this should be very low, but can't be zero
615
- // a good value seems to be 1% of the bounding box size (= radius), whereas the value shouldn't go above 1, which is also the default value
616
- const radius = boundingBox.getBoundingInfo().boundingSphere.radius;
617
- helperCamera.minZ = Math.min(radius / 100, 1);
618
-
619
- // set desired camera data, these won't be changed by the autofocus function!
620
- // default values should focus the element exactly from the front (= XY Plane)
621
- helperCamera.setTarget(boundingBox, true);
622
- helperCamera.alpha = (settings?.alpha ?? -90) * (Math.PI / 180);
623
- helperCamera.beta = (settings?.beta ?? 90) * (Math.PI / 180);
624
-
625
- // finally zoom to the bounding box
626
- // also apply a zoom factor, this adjusts the borders around the model in the viewport
627
- helperCamera.zoomOnFactor = settings?.radiusFactor || 1;
628
- helperCamera.zoomOn([boundingBox], true);
629
-
630
- return helperCamera;
631
- }
632
-
633
- /**
634
- * Help function for applying the relevant data of the focused helper camera to the real camera
635
- */
636
- private async applyFocusedHelperCameraData(
637
- activeCamera: ArcRotateCamera,
638
- helperCamera: ArcRotateCamera,
639
- settings?: AutofocusSettings
640
- ) {
641
- // limits
642
- activeCamera.minZ = helperCamera.minZ;
643
- activeCamera.maxZ = helperCamera.maxZ;
644
- activeCamera.lowerRadiusLimit = helperCamera.lowerRadiusLimit;
645
- activeCamera.upperRadiusLimit = helperCamera.upperRadiusLimit;
646
-
647
- // additional settings
648
- if (settings?.adjustWheelPrecision !== false) {
649
- activeCamera.wheelPrecision = helperCamera.wheelPrecision;
650
- }
651
- if (settings?.adjustPanningSensibility !== false) {
652
- activeCamera.panningSensibility = helperCamera.panningSensibility;
653
- }
654
- if (settings?.adjustPinchPrecision !== false) {
655
- activeCamera.pinchPrecision = helperCamera.pinchPrecision;
656
- }
657
-
658
- // finally move the camera
659
- // do this at last, so that all camera settings are already considered
660
- const newCameraPosition: PlacementDefinition = {
661
- alpha: helperCamera.alpha,
662
- beta: helperCamera.beta,
663
- radius: helperCamera.radius,
664
- target: helperCamera.target,
665
- };
666
- await this.animationManager.animateToPlacement(activeCamera, newCameraPosition, settings?.animation);
667
- }
668
- }
1
+ import version from '../../../buildinfo.json';
2
+ import { sceneSetup } from '../internal/sceneSetup';
3
+ import { AnimationManager } from '../manager/animationManager';
4
+ import { GltfExportManager } from '../manager/gltfExportManager';
5
+ import { SceneManager } from '../manager/sceneManager';
6
+ import { VariantInstanceManager } from '../manager/variantInstanceManager';
7
+ import { SpecStorage } from '../store/specStorage';
8
+ import { backgroundDomeName, envHelperMetadataName } from '../util/babylonHelper';
9
+ import { debounce, loadJavascript, loadJson } from '../util/resourceHelper';
10
+ import { getCustomCbnBabylonLoaderPlugin } from '../util/sceneLoaderHelper';
11
+ import { isMeshIncludedInExclusionList } from '../util/structureHelper';
12
+ import { AnimationInterface } from './animationInterface';
13
+ import { Event } from './event';
14
+ import { EventBroadcaster } from './eventBroadcaster';
15
+ import { Parameter } from './parameter';
16
+ import { Variant } from './variant';
17
+ import { VariantInstance } from './variantInstance';
18
+ import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera';
19
+ import { PickingInfo } from '@babylonjs/core/Collisions/pickingInfo';
20
+ import { BoundingInfo } from '@babylonjs/core/Culling/boundingInfo';
21
+ import { DebugLayer } from '@babylonjs/core/Debug/debugLayer';
22
+ import { Engine } from '@babylonjs/core/Engines/engine';
23
+ import { IPointerEvent } from '@babylonjs/core/Events/deviceInputEvents';
24
+ import { EnvironmentHelper } from '@babylonjs/core/Helpers/environmentHelper';
25
+ import { PhotoDome } from '@babylonjs/core/Helpers/photoDome';
26
+ import { HighlightLayer } from '@babylonjs/core/Layers/highlightLayer';
27
+ import { ISceneLoaderPlugin, SceneLoader } from '@babylonjs/core/Loading/sceneLoader';
28
+ import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
29
+ import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
30
+ import { Color3 } from '@babylonjs/core/Maths/math.color';
31
+ import { Vector3 } from '@babylonjs/core/Maths/math.vector';
32
+ import { Mesh } from '@babylonjs/core/Meshes/mesh';
33
+ import { ScreenshotTools } from '@babylonjs/core/Misc/screenshotTools';
34
+ import { WebXRSessionManager } from '@babylonjs/core/XR/webXRSessionManager';
35
+ import { Scene } from '@babylonjs/core/scene';
36
+ import { isString } from 'lodash-es';
37
+
38
+ /**
39
+ * The main exposed object. This is the entry point into the application
40
+ *
41
+ * ```js
42
+ * const canvas = document.getElementById( 'babylon-canvas' );
43
+ * const viewer = Viewer( canvas, '/path/to/index.json' );
44
+ * ```
45
+ * The class does nothing on its own and needs to {@link bootstrap}
46
+ */
47
+ export class Viewer extends EventBroadcaster {
48
+ protected _scene: Scene | null = null;
49
+
50
+ protected _animationManager: AnimationManager | null = null;
51
+
52
+ protected _sceneManager: SceneManager | null = null;
53
+
54
+ protected _gltfExportManager: GltfExportManager | null = null;
55
+
56
+ protected _variantInstances: VariantInstanceManager | null = null;
57
+
58
+ // default value is `true` ATM for compatibility reasons
59
+ // in the future material cloning should be the edge case
60
+ protected _cloneMaterialsOnMutation: boolean = true;
61
+
62
+ protected _isRenderLoopPaused: boolean = false;
63
+
64
+ protected _inspectorLoaded: boolean = false;
65
+
66
+ static version = version;
67
+
68
+ /**
69
+ * Constructor
70
+ */
71
+ public constructor(public readonly canvas: HTMLCanvasElement, protected structureJson: string | StructureJson) {
72
+ super();
73
+ }
74
+
75
+ /**
76
+ * Gets the BabylonJS Scene that is attached to the instance.
77
+ *
78
+ * @throws Error if the `scene` has not been initialized.
79
+ */
80
+ get scene(): Scene {
81
+ if (!this._scene) {
82
+ throw new Error(`Scene has not been initialized.`);
83
+ }
84
+ return this._scene;
85
+ }
86
+
87
+ /**
88
+ * Gets the {@link SceneManager} attached to the viewer.
89
+ *
90
+ * @throws Error if the {@link SceneManager} has not been initialized.
91
+ */
92
+ get sceneManager(): SceneManager {
93
+ if (!this._sceneManager) {
94
+ throw new Error(`SceneManager has not been initialized.`);
95
+ }
96
+ return this._sceneManager;
97
+ }
98
+
99
+ /**
100
+ * Gets the {@link GltfExportManager} attached to the viewer.
101
+ *
102
+ * @throws Error if the {@link GltfExportManager} has not been initialized.
103
+ */
104
+ get gltfExportManager(): GltfExportManager {
105
+ if (!this._gltfExportManager) {
106
+ throw new Error(`GltfExportManager has not been initialized.`);
107
+ }
108
+ return this._gltfExportManager;
109
+ }
110
+
111
+ /**
112
+ * Gets the BabylonJS Engine that is attached to the viewer.
113
+ */
114
+ get engine(): Engine {
115
+ return this.scene.getEngine();
116
+ }
117
+
118
+ /**
119
+ * Gets the {@link VariantInstanceManager} attached to the viewer.
120
+ *
121
+ * @throws Error if the {@link VariantInstanceManager} has not been initialized.
122
+ */
123
+ get variantInstances(): VariantInstanceManager {
124
+ if (!this._variantInstances) {
125
+ throw Error(`There is no variantInstanceManager.`);
126
+ }
127
+ return this._variantInstances;
128
+ }
129
+
130
+ /**
131
+ * Gets the {@link AnimationManager} attached to the viewer.
132
+ *
133
+ * @throws Error if the {@link AnimationManager} has not been initialized.
134
+ */
135
+ get animationManager(): AnimationManager {
136
+ if (!this._animationManager) {
137
+ throw new Error(`There is no animationManager instance.`);
138
+ }
139
+ return this._animationManager;
140
+ }
141
+
142
+ /**
143
+ * Gets the `cloneMaterialsOnMutation` flag, as defined in the spec
144
+ */
145
+ get cloneMaterialsOnMutation(): boolean {
146
+ return this._cloneMaterialsOnMutation;
147
+ }
148
+
149
+ /**
150
+ * Starts the application. This will
151
+ * * load the given "index" JSON file
152
+ * * setup the scene with the "scene" JSON file
153
+ * * create an (optional) default setup with different variant settings
154
+ * * sets up resizing by attaching a debounced version of {@link resize}
155
+ *
156
+ * @throws Error if any of the files is not found/valid
157
+ *
158
+ * @emits {@link Event.BOOTSTRAP_START}
159
+ * @emits {@link Event.BOOTSTRAP_END}
160
+ */
161
+ public async bootstrap(): Promise<Viewer> {
162
+ this.broadcastEvent(Event.BOOTSTRAP_START, this);
163
+
164
+ let indexJson;
165
+ if (isString(this.structureJson)) {
166
+ indexJson = await loadJson<StructureJson>(this.structureJson);
167
+ } else {
168
+ indexJson = this.structureJson;
169
+ }
170
+ if (!indexJson.scene) {
171
+ throw new Error(`No "scene" property found for bootstrapping.`);
172
+ }
173
+ // fill spec store
174
+ SpecStorage.createFromSpec(indexJson);
175
+
176
+ this.initCbnBabylonLoaderPlugin();
177
+
178
+ // load scene
179
+ if (isString(indexJson.scene)) {
180
+ const sceneJson = await loadJson<SceneJson>(indexJson.scene);
181
+ indexJson.scene = sceneJson;
182
+ }
183
+ this._scene = await this.initScene();
184
+ // create instance manager
185
+ const rootVariant = await Variant.create('_', indexJson, this);
186
+ this._variantInstances = await VariantInstanceManager.create(rootVariant);
187
+ // create optional default instances
188
+ if (indexJson.setup) {
189
+ if (isString(indexJson.setup)) {
190
+ const setupJson = await loadJson<SetupJson>(indexJson.setup);
191
+ indexJson.setup = setupJson;
192
+ }
193
+ await this.createVariantInstances();
194
+ }
195
+ // create gltf export manager
196
+ this._gltfExportManager = await GltfExportManager.create(this);
197
+ // resize handler
198
+ window.addEventListener('resize', debounce(this.resize.bind(this), 100));
199
+ // wait until scene is completely ready
200
+ await this.scene.whenReadyAsync();
201
+ // event broadcasting
202
+ this.broadcastEvent(Event.BOOTSTRAP_END, this);
203
+ // render loop
204
+ this.engine.runRenderLoop(() => {
205
+ if (!this._isRenderLoopPaused) this.scene.render();
206
+ });
207
+ return this;
208
+ }
209
+
210
+ /**
211
+ * Enables the BabylonJS [Inspector](https://doc.babylonjs.com/toolsAndResources/tools/inspector).\
212
+ * Due to the additional size of the inspector, the CDN version is used instead of shipping the required code with the viewer.\
213
+ * This means that the code will be downloaded only when needed and calling `enableDebugLayer` can take a little while depending on your internet connection etc.
214
+ */
215
+ public async enableDebugLayer(options?: IInspectorOptions) {
216
+ if (!this._inspectorLoaded) {
217
+ // CDN version of inspector requires the BabylonJS core to be available as CDN module as well
218
+ await loadJavascript('https://cdn.jsdelivr.net/npm/babylonjs@5.6.0/babylon.min.js');
219
+
220
+ DebugLayer.InspectorURL =
221
+ 'https://cdn.jsdelivr.net/npm/babylonjs-inspector@5.6.0/babylon.inspector.bundle.max.min.js';
222
+
223
+ this._inspectorLoaded = true;
224
+ }
225
+
226
+ await this.scene.debugLayer.show(options);
227
+ }
228
+
229
+ /**
230
+ * Destroys all registered {@link VariantInstance}s that are registered
231
+ */
232
+ public destroyVariantInstances(): Viewer {
233
+ this.variantInstances.all.forEach(variantInstance => {
234
+ this.variantInstances.destroy(variantInstance.name);
235
+ });
236
+ return this;
237
+ }
238
+
239
+ /**
240
+ * Trigger a resize event for the `Engine`
241
+ */
242
+ public resize(): Viewer {
243
+ this.engine.resize();
244
+ return this;
245
+ }
246
+
247
+ /**
248
+ * A convenience method for directly getting a Node from a {@link VariantInstance} and an {@link Element} by its
249
+ * {@link DottedPath}s.
250
+ */
251
+ public async getNode(
252
+ variantInstanceName: string,
253
+ elementDottedPath: DottedPathArgument,
254
+ nodeDottedPath: DottedPathArgument
255
+ ): Promise<TransformNode> {
256
+ const variantInstance = await this.variantInstances.get(variantInstanceName);
257
+ return variantInstance.getNode(elementDottedPath, nodeDottedPath);
258
+ }
259
+
260
+ /**
261
+ * A convenience method for directly getting a Node from a {@link VariantInstance} and an {@link Element} by its
262
+ * {@link DottedPath}s.
263
+ */
264
+ public async getMesh(
265
+ variantInstanceName: string,
266
+ elementDottedPath: DottedPathArgument,
267
+ meshDottedPath: DottedPathArgument
268
+ ): Promise<Mesh | null> {
269
+ const variantInstance = await this.variantInstances.get(variantInstanceName);
270
+ return variantInstance.getMesh(elementDottedPath, meshDottedPath);
271
+ }
272
+
273
+ /**
274
+ * Switches the camera
275
+ *
276
+ * @emits {@link Event.CAMERA_SWITCHED}
277
+ */
278
+ public switchCamera(newCamera: string, reset: boolean = true): Viewer {
279
+ const camera = this.scene.getCameraByName(newCamera);
280
+ if (camera) {
281
+ const activeCamera = this.scene.activeCamera;
282
+ if (activeCamera) {
283
+ activeCamera.detachControl(this.engine.getRenderingCanvas()!);
284
+ }
285
+ if (reset) {
286
+ camera.restoreState();
287
+ }
288
+ this.scene.setActiveCameraByName(newCamera);
289
+ camera.attachControl(this.engine.getRenderingCanvas()!);
290
+ this.broadcastEvent(Event.CAMERA_SWITCHED, camera);
291
+ } else {
292
+ throw new Error(`Given camera "${newCamera}" not found.`);
293
+ }
294
+ // TODO: put traceable observers to new camera (@see element)
295
+ return this;
296
+ }
297
+
298
+ /**
299
+ * Moves or animates the active camera to given `placement`.
300
+ */
301
+ public async moveActiveCameraTo(
302
+ placement: string | PlacementDefinition,
303
+ animation?: string | AnimationDefinition
304
+ ): Promise<AnimationInterface> {
305
+ return this.animationManager.animateToPlacement(this.sceneManager.activeCamera, placement, animation);
306
+ }
307
+
308
+ /**
309
+ * Takes a sceenshot the the current scene. The result is a string containing a base64 encoded image
310
+ */
311
+ public screenshot(settings?: ScreenshotSettings): Promise<string> {
312
+ return new Promise((resolve, reject) => {
313
+ if (!this.engine) {
314
+ return reject('Engine is null');
315
+ }
316
+ if (!this.scene) {
317
+ return reject('Scene is null');
318
+ }
319
+ this.scene.render(); // in combination with a render target, we need to refresh the scene manually to get the latest view
320
+ ScreenshotTools.CreateScreenshotUsingRenderTarget(
321
+ this.engine,
322
+ this.sceneManager.activeCamera,
323
+ settings?.size ?? { width: this.canvas.clientWidth, height: this.canvas.clientHeight },
324
+ resolve,
325
+ settings?.mimeType ?? 'image/png',
326
+ settings?.samples ?? 1,
327
+ settings?.antialiasing ?? false,
328
+ settings?.fileName ?? 'screenshot.png',
329
+ settings?.renderSprites ?? false
330
+ );
331
+ });
332
+ }
333
+
334
+ /**
335
+ * Checks whether the browser is capable of handling XR.
336
+ */
337
+ public async isBrowserARCapable(): Promise<boolean> {
338
+ return await WebXRSessionManager.IsSessionSupportedAsync('immersive-ar');
339
+ }
340
+
341
+ /**
342
+ * Calculates the bounding box from all visible meshes on the scene.
343
+ */
344
+ public async calculateBoundingBox(excludeGeometry?: ExcludedGeometryList): Promise<Mesh> {
345
+ if (this.scene.meshes.length === 0) {
346
+ throw new Error('There are currently no meshes on the scene.');
347
+ }
348
+ this.scene.render(); // CB-6062: workaround for BoundingBox not respecting render loop
349
+ const bbName = '__bounding_box__';
350
+
351
+ const { max, min } = this.scene.meshes
352
+ .filter(mesh => {
353
+ const isEnabled = mesh.isEnabled();
354
+ // ignore the existing bounding box mesh for calculating the current one
355
+ const isNotBBoxMesh = bbName !== mesh.id;
356
+ // ignore meshes with invalid bounding infos
357
+ const hasValidBBoxInfo = mesh.getBoundingInfo().boundingSphere.radius > 0;
358
+ // ignore excluded meshes
359
+ const isExcluded = excludeGeometry ? isMeshIncludedInExclusionList(mesh as Mesh, excludeGeometry) : false;
360
+ return isEnabled && isNotBBoxMesh && hasValidBBoxInfo && !isExcluded;
361
+ })
362
+ .reduce(
363
+ (accBBoxMinMax, curMesh, idx) => {
364
+ const bBox = curMesh.getBoundingInfo().boundingBox;
365
+ // use the first entry in the array as default value and get the resulting maximum/minimum values
366
+ const max = idx === 0 ? bBox.maximumWorld : Vector3.Maximize(accBBoxMinMax.max, bBox.maximumWorld);
367
+ const min = idx === 0 ? bBox.minimumWorld : Vector3.Minimize(accBBoxMinMax.min, bBox.minimumWorld);
368
+ return { max, min };
369
+ },
370
+ { max: new Vector3(), min: new Vector3() }
371
+ );
372
+
373
+ let boundingBox = this.scene.getMeshByName(bbName) as Mesh;
374
+ if (!boundingBox) {
375
+ boundingBox = new Mesh(bbName, this.scene);
376
+ }
377
+ boundingBox.setBoundingInfo(new BoundingInfo(min, max));
378
+ return boundingBox;
379
+ }
380
+
381
+ /**
382
+ * Focuses the camera to see every visible mesh in scene and tries to optimize wheel precision and panning
383
+ */
384
+ public async autofocusActiveCamera(settings?: AutofocusSettings) {
385
+ // first check some preconditions
386
+ const activeCamera = this.scene.activeCamera;
387
+ if (!activeCamera) {
388
+ throw new Error('No active camera found when using autofocus feature.');
389
+ }
390
+ if (!(activeCamera instanceof ArcRotateCamera)) {
391
+ const cameraClsName = activeCamera.getClassName();
392
+ throw new Error(`Camera of type "${cameraClsName}" is not implemented yet to use autofocus feature.`);
393
+ }
394
+
395
+ let exclude = settings?.exclude || [];
396
+
397
+ // Exclude shown photo dome or environment helper from bounding box calculation
398
+ const photoDome = this.scene.getNodeByName(backgroundDomeName) as undefined | PhotoDome;
399
+ const photoDomeMeshes = photoDome?.getChildMeshes();
400
+ if (photoDomeMeshes?.length) {
401
+ exclude = [...exclude, ...photoDomeMeshes];
402
+ }
403
+
404
+ const envHelper = this.scene.metadata?.[envHelperMetadataName] as undefined | EnvironmentHelper;
405
+ if (envHelper?.rootMesh) {
406
+ exclude = [...exclude, envHelper.rootMesh];
407
+ }
408
+
409
+ // get bounding box of all visible meshes, this is the base for the autofocus algorithm
410
+ const boundingBox = await this.calculateBoundingBox(exclude);
411
+
412
+ // focus the helper camera and set the calculated camera data to the real camera
413
+ const helperCamera = this.getFocusedHelperCamera(boundingBox, settings);
414
+ await this.applyFocusedHelperCameraData(activeCamera, helperCamera, settings);
415
+
416
+ // remove the helper camera
417
+ helperCamera.dispose();
418
+ }
419
+
420
+ /**
421
+ * Resets everything by calling {@link destroy} to clear all references and {@link bootstrap} to setup a clean
422
+ * environment
423
+ */
424
+ public async reset(): Promise<Viewer> {
425
+ await this.destroy();
426
+ return this.bootstrap();
427
+ }
428
+
429
+ /**
430
+ * Destroys
431
+ *
432
+ * * all {@link VariantInstance}s using {@link destroyVariantInstances}
433
+ * * calling `dispose` on the `Engine` and `Scene`
434
+ */
435
+ public destroy(): Viewer {
436
+ this.destroyVariantInstances();
437
+ this.scene.dispose();
438
+ SpecStorage.destroy();
439
+ return this;
440
+ }
441
+
442
+ /**
443
+ * Show coordinate system with given dimension (for debugging purpose).
444
+ */
445
+ public showWorldCoordinates(dimension: number) {
446
+ const scene = this.scene;
447
+ const makeTextPlane = function (text: string, color: string, size: number) {
448
+ const dynamicTexture = new DynamicTexture('DynamicTexture', 50, scene, true);
449
+ dynamicTexture.hasAlpha = true;
450
+ dynamicTexture.drawText(text, 5, 40, 'bold 36px Arial', color, 'transparent', true);
451
+ const plane = Mesh.CreatePlane('TextPlane', size, scene, true);
452
+ plane.material = new StandardMaterial('TextPlaneMaterial', scene);
453
+ plane.material.backFaceCulling = false;
454
+ // @ts-ignore
455
+ plane.material.specularColor = new Color3(0, 0, 0);
456
+ // @ts-ignore
457
+ plane.material.diffuseTexture = dynamicTexture;
458
+ return plane;
459
+ };
460
+
461
+ const axisX = Mesh.CreateLines(
462
+ 'axisX',
463
+ [
464
+ Vector3.Zero(),
465
+ new Vector3(dimension, 0, 0),
466
+ new Vector3(dimension * 0.95, 0.05 * dimension, 0),
467
+ new Vector3(dimension, 0, 0),
468
+ new Vector3(dimension * 0.95, -0.05 * dimension, 0),
469
+ ],
470
+ scene,
471
+ false
472
+ );
473
+ axisX.color = new Color3(1, 0, 0);
474
+ const xChar = makeTextPlane('X', 'red', dimension / 10);
475
+ xChar.position = new Vector3(0.9 * dimension, -0.05 * dimension, 0);
476
+ const axisY = Mesh.CreateLines(
477
+ 'axisY',
478
+ [
479
+ Vector3.Zero(),
480
+ new Vector3(0, dimension, 0),
481
+ new Vector3(-0.05 * dimension, dimension * 0.95, 0),
482
+ new Vector3(0, dimension, 0),
483
+ new Vector3(0.05 * dimension, dimension * 0.95, 0),
484
+ ],
485
+ scene,
486
+ false
487
+ );
488
+ axisY.color = new Color3(0, 1, 0);
489
+ const yChar = makeTextPlane('Y', 'green', dimension / 10);
490
+ yChar.position = new Vector3(0, 0.9 * dimension, -0.05 * dimension);
491
+ const axisZ = Mesh.CreateLines(
492
+ 'axisZ',
493
+ [
494
+ Vector3.Zero(),
495
+ new Vector3(0, 0, dimension),
496
+ new Vector3(0, -0.05 * dimension, dimension * 0.95),
497
+ new Vector3(0, 0, dimension),
498
+ new Vector3(0, 0.05 * dimension, dimension * 0.95),
499
+ ],
500
+ scene,
501
+ false
502
+ );
503
+ axisZ.color = new Color3(0, 0, 1);
504
+ const zChar = makeTextPlane('Z', 'blue', dimension / 10);
505
+ zChar.position = new Vector3(0, 0.05 * dimension, 0.9 * dimension);
506
+ }
507
+
508
+ /**
509
+ * Pause render loop.
510
+ */
511
+ public pauseRendering() {
512
+ this._isRenderLoopPaused = true;
513
+ }
514
+
515
+ /**
516
+ * Resume render loop when paused.
517
+ */
518
+ public resumeRendering() {
519
+ this._isRenderLoopPaused = false;
520
+ }
521
+
522
+ /**
523
+ * @emits {@link Event.SCENE_PROCESSING_START}
524
+ * @emits {@link Event.SCENE_PROCESSING_END}
525
+ */
526
+ protected async initScene(): Promise<Scene> {
527
+ const sceneJson = SpecStorage.get<SceneJson>('scene');
528
+ this.broadcastEvent(Event.SCENE_PROCESSING_START, sceneJson);
529
+ const engine = new Engine(
530
+ this.canvas as HTMLCanvasElement,
531
+ sceneJson.engine?.antialiasing ?? false,
532
+ sceneJson.engine?.options
533
+ );
534
+ const scene = await sceneSetup(engine, sceneJson);
535
+ if (sceneJson.meshPicking) {
536
+ new HighlightLayer('default', scene);
537
+ scene.onPointerPick = (pointerEvent: IPointerEvent, pickInfo: PickingInfo) => {
538
+ if (!pickInfo.hit) {
539
+ return;
540
+ }
541
+ const mesh = pickInfo.pickedMesh;
542
+ this.broadcastEvent(Event.MESH_PICKED, mesh, mesh?.metadata.element, mesh?.metadata.variant);
543
+ if (mesh?.metadata.element) {
544
+ this.broadcastEvent(Event.ELEMENT_PICKED, mesh.metadata.element);
545
+ }
546
+ if (mesh?.metadata.variant) {
547
+ if (mesh.metadata.variant.inheritedParameters[Parameter.HIGHLIGHT_ENABLED]) {
548
+ mesh.metadata.variant.toggleHighlight();
549
+ }
550
+ this.broadcastEvent(Event.VARIANT_PICKED, mesh.metadata.variant);
551
+ }
552
+ };
553
+ }
554
+ this._sceneManager = await SceneManager.create(scene);
555
+ this._animationManager = await AnimationManager.create(scene);
556
+ if (sceneJson.cloneMaterialsOnMutation !== undefined) {
557
+ this._cloneMaterialsOnMutation = sceneJson.cloneMaterialsOnMutation;
558
+ }
559
+ this.broadcastEvent(Event.SCENE_PROCESSING_END, scene);
560
+ return scene;
561
+ }
562
+
563
+ /**
564
+ * Register custom file loader for babylon files which adds "missing-material" metadata to meshes which reference
565
+ * materials that are not present in the `materials` section of the given babylon file.
566
+ *
567
+ * Required for babylon files & materials loaded from "Combeenation configurator assets".
568
+ */
569
+ protected initCbnBabylonLoaderPlugin() {
570
+ const previousLoaderPlugin = SceneLoader.GetPluginForExtension('babylon') as ISceneLoaderPlugin;
571
+ const customLoaderPlugin = getCustomCbnBabylonLoaderPlugin(previousLoaderPlugin);
572
+ SceneLoader.RegisterPlugin(customLoaderPlugin);
573
+ }
574
+
575
+ /**
576
+ * Batch creation of multiple {@link VariantInstance} objects with a {@link SetupJson} object passed
577
+ */
578
+ protected async createVariantInstances(): Promise<VariantInstance[]> {
579
+ const setupJson = SpecStorage.get<SetupJson>('setup');
580
+ const instances: VariantInstance[] = [];
581
+ for (const instanceDefinition of setupJson.instances) {
582
+ if (instanceDefinition.lazy) {
583
+ this.variantInstances.register(instanceDefinition);
584
+ continue;
585
+ }
586
+ instances.push(
587
+ await this.variantInstances.create(
588
+ instanceDefinition.variant,
589
+ instanceDefinition.name,
590
+ instanceDefinition.parameters
591
+ )
592
+ );
593
+ }
594
+ return instances;
595
+ }
596
+
597
+ /**
598
+ * Help function for focusing a helper camera exactly onto the given bounding box
599
+ */
600
+ private getFocusedHelperCamera(boundingBox: Mesh, settings?: AutofocusSettings): ArcRotateCamera {
601
+ // use helper camera to get some default values and set the values of the real camera accordingly
602
+ const helperCamera = new ArcRotateCamera(
603
+ '__helper_camera__',
604
+ 0, // camera angles will be overwritten after the target has been set
605
+ 0,
606
+ 0, // radius will be calculated, so we can set to 0 here
607
+ Vector3.Zero(),
608
+ this.scene
609
+ );
610
+ // this is required for automatically calculating the `lowerRadiusLimit`, so that we don't "dive" into meshes
611
+ // see https://doc.babylonjs.com/divingDeeper/behaviors/cameraBehaviors#framing-behavior
612
+ helperCamera.useFramingBehavior = true;
613
+
614
+ // `minZ` is the camera distance beyond which the mesh will be clipped
615
+ // this should be very low, but can't be zero
616
+ // a good value seems to be 1% of the bounding box size (= radius), whereas the value shouldn't go above 1, which is also the default value
617
+ const radius = boundingBox.getBoundingInfo().boundingSphere.radius;
618
+ helperCamera.minZ = Math.min(radius / 100, 1);
619
+
620
+ // set desired camera data, these won't be changed by the autofocus function!
621
+ // default values should focus the element exactly from the front (= XY Plane)
622
+ helperCamera.setTarget(boundingBox, true);
623
+ helperCamera.alpha = (settings?.alpha ?? -90) * (Math.PI / 180);
624
+ helperCamera.beta = (settings?.beta ?? 90) * (Math.PI / 180);
625
+
626
+ // finally zoom to the bounding box
627
+ // also apply a zoom factor, this adjusts the borders around the model in the viewport
628
+ helperCamera.zoomOnFactor = settings?.radiusFactor || 1;
629
+ helperCamera.zoomOn([boundingBox], true);
630
+
631
+ return helperCamera;
632
+ }
633
+
634
+ /**
635
+ * Help function for applying the relevant data of the focused helper camera to the real camera
636
+ */
637
+ private async applyFocusedHelperCameraData(
638
+ activeCamera: ArcRotateCamera,
639
+ helperCamera: ArcRotateCamera,
640
+ settings?: AutofocusSettings
641
+ ) {
642
+ // limits
643
+ activeCamera.minZ = helperCamera.minZ;
644
+ activeCamera.maxZ = helperCamera.maxZ;
645
+ activeCamera.lowerRadiusLimit = helperCamera.lowerRadiusLimit;
646
+ activeCamera.upperRadiusLimit = helperCamera.upperRadiusLimit;
647
+
648
+ // additional settings
649
+ if (settings?.adjustWheelPrecision !== false) {
650
+ activeCamera.wheelPrecision = helperCamera.wheelPrecision;
651
+ }
652
+ if (settings?.adjustPanningSensibility !== false) {
653
+ activeCamera.panningSensibility = helperCamera.panningSensibility;
654
+ }
655
+ if (settings?.adjustPinchPrecision !== false) {
656
+ activeCamera.pinchPrecision = helperCamera.pinchPrecision;
657
+ }
658
+
659
+ // finally move the camera
660
+ // do this at last, so that all camera settings are already considered
661
+ const newCameraPosition: PlacementDefinition = {
662
+ alpha: helperCamera.alpha,
663
+ beta: helperCamera.beta,
664
+ radius: helperCamera.radius,
665
+ target: helperCamera.target,
666
+ };
667
+ await this.animationManager.animateToPlacement(activeCamera, newCameraPosition, settings?.animation);
668
+ }
669
+ }