@babylonjs/viewer 5.0.0 → 5.0.3

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 (127) hide show
  1. package/configuration/configuration.d.ts +107 -107
  2. package/configuration/configuration.js +15 -15
  3. package/configuration/configurationCompatibility.d.ts +8 -8
  4. package/configuration/configurationCompatibility.js +65 -65
  5. package/configuration/configurationContainer.d.ts +10 -10
  6. package/configuration/configurationContainer.js +9 -9
  7. package/configuration/globals.d.ts +6 -6
  8. package/configuration/globals.js +17 -17
  9. package/configuration/index.d.ts +2 -2
  10. package/configuration/index.js +3 -3
  11. package/configuration/interfaces/cameraConfiguration.d.ts +31 -31
  12. package/configuration/interfaces/cameraConfiguration.js +1 -1
  13. package/configuration/interfaces/colorGradingConfiguration.d.ts +81 -81
  14. package/configuration/interfaces/colorGradingConfiguration.js +1 -1
  15. package/configuration/interfaces/defaultRenderingPipelineConfiguration.d.ts +20 -20
  16. package/configuration/interfaces/defaultRenderingPipelineConfiguration.js +1 -1
  17. package/configuration/interfaces/environmentMapConfiguration.d.ts +22 -22
  18. package/configuration/interfaces/environmentMapConfiguration.js +1 -1
  19. package/configuration/interfaces/groundConfiguration.d.ts +24 -24
  20. package/configuration/interfaces/groundConfiguration.js +1 -1
  21. package/configuration/interfaces/imageProcessingConfiguration.d.ts +43 -43
  22. package/configuration/interfaces/imageProcessingConfiguration.js +1 -1
  23. package/configuration/interfaces/index.d.ts +15 -15
  24. package/configuration/interfaces/index.js +15 -15
  25. package/configuration/interfaces/lightConfiguration.d.ts +60 -60
  26. package/configuration/interfaces/lightConfiguration.js +1 -1
  27. package/configuration/interfaces/modelAnimationConfiguration.d.ts +26 -26
  28. package/configuration/interfaces/modelAnimationConfiguration.js +1 -1
  29. package/configuration/interfaces/modelConfiguration.d.ts +65 -65
  30. package/configuration/interfaces/modelConfiguration.js +1 -1
  31. package/configuration/interfaces/observersConfiguration.d.ts +5 -5
  32. package/configuration/interfaces/observersConfiguration.js +1 -1
  33. package/configuration/interfaces/sceneConfiguration.d.ts +48 -48
  34. package/configuration/interfaces/sceneConfiguration.js +1 -1
  35. package/configuration/interfaces/sceneOptimizerConfiguration.d.ts +23 -23
  36. package/configuration/interfaces/sceneOptimizerConfiguration.js +1 -1
  37. package/configuration/interfaces/skyboxConfiguration.d.ts +21 -21
  38. package/configuration/interfaces/skyboxConfiguration.js +1 -1
  39. package/configuration/interfaces/templateConfiguration.d.ts +67 -67
  40. package/configuration/interfaces/templateConfiguration.js +1 -1
  41. package/configuration/interfaces/vrConfiguration.d.ts +16 -16
  42. package/configuration/interfaces/vrConfiguration.js +1 -1
  43. package/configuration/loader.d.ts +4 -4
  44. package/configuration/loader.js +16 -16
  45. package/configuration/mappers.d.ts +42 -42
  46. package/configuration/mappers.js +190 -190
  47. package/configuration/renderOnlyLoader.d.ts +33 -33
  48. package/configuration/renderOnlyLoader.js +161 -161
  49. package/configuration/types/default.d.ts +6 -6
  50. package/configuration/types/default.js +120 -120
  51. package/configuration/types/environmentMap.d.ts +5 -5
  52. package/configuration/types/environmentMap.js +13 -13
  53. package/configuration/types/extended.d.ts +6 -6
  54. package/configuration/types/extended.js +316 -316
  55. package/configuration/types/index.d.ts +13 -13
  56. package/configuration/types/index.js +49 -49
  57. package/configuration/types/minimal.d.ts +6 -6
  58. package/configuration/types/minimal.js +42 -42
  59. package/configuration/types/renderOnlyDefault.d.ts +30 -30
  60. package/configuration/types/renderOnlyDefault.js +30 -30
  61. package/configuration/types/shadowLight.d.ts +9 -9
  62. package/configuration/types/shadowLight.js +63 -63
  63. package/helper/index.d.ts +26 -26
  64. package/helper/index.js +62 -62
  65. package/index.d.ts +30 -30
  66. package/index.js +45 -45
  67. package/initializer.d.ts +11 -11
  68. package/initializer.js +34 -34
  69. package/interfaces.d.ts +5 -5
  70. package/interfaces.js +1 -1
  71. package/labs/environmentSerializer.d.ts +126 -126
  72. package/labs/environmentSerializer.js +190 -190
  73. package/labs/texture.d.ts +183 -183
  74. package/labs/texture.js +300 -300
  75. package/labs/viewerLabs.d.ts +51 -51
  76. package/labs/viewerLabs.js +133 -133
  77. package/loader/modelLoader.d.ts +47 -47
  78. package/loader/modelLoader.js +189 -189
  79. package/loader/plugins/applyMaterialConfig.d.ts +12 -12
  80. package/loader/plugins/applyMaterialConfig.js +15 -15
  81. package/loader/plugins/extendedMaterialLoaderPlugin.d.ts +9 -9
  82. package/loader/plugins/extendedMaterialLoaderPlugin.js +15 -15
  83. package/loader/plugins/index.d.ts +18 -18
  84. package/loader/plugins/index.js +42 -42
  85. package/loader/plugins/loaderPlugin.d.ts +24 -24
  86. package/loader/plugins/loaderPlugin.js +1 -1
  87. package/loader/plugins/msftLodLoaderPlugin.d.ts +12 -12
  88. package/loader/plugins/msftLodLoaderPlugin.js +20 -20
  89. package/loader/plugins/telemetryLoaderPlugin.d.ts +12 -12
  90. package/loader/plugins/telemetryLoaderPlugin.js +35 -35
  91. package/managers/observablesManager.d.ts +66 -66
  92. package/managers/observablesManager.js +34 -34
  93. package/managers/sceneManager.d.ts +243 -243
  94. package/managers/sceneManager.js +1388 -1388
  95. package/managers/telemetryManager.d.ts +57 -57
  96. package/managers/telemetryManager.js +113 -113
  97. package/model/modelAnimation.d.ts +215 -215
  98. package/model/modelAnimation.js +232 -232
  99. package/model/viewerModel.d.ts +228 -228
  100. package/model/viewerModel.js +669 -669
  101. package/optimizer/custom/extended.d.ts +11 -11
  102. package/optimizer/custom/extended.js +98 -98
  103. package/optimizer/custom/index.d.ts +8 -8
  104. package/optimizer/custom/index.js +24 -24
  105. package/package.json +5 -5
  106. package/renderOnlyIndex.d.ts +11 -11
  107. package/renderOnlyIndex.js +17 -17
  108. package/templating/eventManager.d.ts +35 -35
  109. package/templating/eventManager.js +65 -65
  110. package/templating/plugins/hdButtonPlugin.d.ts +9 -9
  111. package/templating/plugins/hdButtonPlugin.js +21 -21
  112. package/templating/plugins/printButton.d.ts +9 -9
  113. package/templating/plugins/printButton.js +40 -40
  114. package/templating/templateManager.d.ts +190 -190
  115. package/templating/templateManager.js +553 -553
  116. package/templating/viewerTemplatePlugin.d.ts +21 -21
  117. package/templating/viewerTemplatePlugin.js +68 -68
  118. package/viewer/defaultViewer.d.ts +122 -122
  119. package/viewer/defaultViewer.js +665 -665
  120. package/viewer/renderOnlyViewer.d.ts +8 -8
  121. package/viewer/renderOnlyViewer.js +43 -43
  122. package/viewer/viewer.d.ts +254 -254
  123. package/viewer/viewer.js +777 -777
  124. package/viewer/viewerManager.d.ts +55 -55
  125. package/viewer/viewerManager.js +87 -87
  126. package/viewer/viewerWithTemplate.d.ts +9 -9
  127. package/viewer/viewerWithTemplate.js +19 -19
package/viewer/viewer.js CHANGED
@@ -1,778 +1,778 @@
1
- import { Engine } from "@babylonjs/core/Engines/engine.js";
2
- import { SceneLoader } from "@babylonjs/core/Loading/sceneLoader.js";
3
- import { RenderingManager } from "@babylonjs/core/Rendering/renderingManager.js";
4
- import { Tools } from "@babylonjs/core/Misc/tools.js";
5
- import { Effect } from "@babylonjs/core/Materials/effect.js";
6
- import { processConfigurationCompatibility } from "../configuration/configurationCompatibility.js";
7
- import { ConfigurationContainer } from "../configuration/configurationContainer.js";
8
- import { viewerGlobals } from "../configuration/globals.js";
9
- import { RenderOnlyConfigurationLoader } from "../configuration/renderOnlyLoader.js";
10
- // eslint-disable-next-line import/no-internal-modules
11
- import { deepmerge } from "../helper/index.js";
12
- import { ModelLoader } from "../loader/modelLoader.js";
13
- import { ObservablesManager } from "../managers/observablesManager.js";
14
- import { SceneManager } from "../managers/sceneManager.js";
15
- import { telemetryManager } from "../managers/telemetryManager.js";
16
- import { viewerManager } from "./viewerManager.js";
17
- /**
18
- * The AbstractViewer is the center of Babylon's viewer.
19
- * It is the basic implementation of the default viewer and is responsible of loading and showing the model and the templates
20
- */
21
- var AbstractViewer = /** @class */ (function () {
22
- function AbstractViewer(containerElement, initialConfiguration) {
23
- if (initialConfiguration === void 0) { initialConfiguration = {}; }
24
- var _this = this;
25
- this.containerElement = containerElement;
26
- /**
27
- * A flag that controls whether or not the render loop should be executed
28
- */
29
- this.runRenderLoop = true;
30
- /**
31
- * is this viewer disposed?
32
- */
33
- this._isDisposed = false;
34
- this._hdToggled = false;
35
- this._vrToggled = false;
36
- this._vrModelRepositioning = 0;
37
- this._vrScale = 1;
38
- this._vrInit = false;
39
- /**
40
- * The resize function that will be registered with the window object
41
- */
42
- this._resize = function () {
43
- // Only resize if Canvas is in the DOM
44
- if (!_this.isCanvasInDOM()) {
45
- return;
46
- }
47
- if (_this.canvas.clientWidth <= 0 || _this.canvas.clientHeight <= 0) {
48
- return;
49
- }
50
- if (_this.configuration.engine && _this.configuration.engine.disableResize) {
51
- return;
52
- }
53
- _this.engine.resize();
54
- };
55
- /**
56
- * render loop that will be executed by the engine
57
- * @param force
58
- */
59
- this._render = function (force) {
60
- if (force === void 0) { force = false; }
61
- if (force || (_this.sceneManager.scene && _this.sceneManager.scene.activeCamera)) {
62
- if (_this.runRenderLoop || force) {
63
- _this.engine.performanceMonitor.enable();
64
- _this.sceneManager.scene.render();
65
- _this.onFrameRenderedObservable.notifyObservers(_this);
66
- }
67
- else {
68
- _this.engine.performanceMonitor.disable();
69
- // update camera instead of rendering
70
- _this.sceneManager.scene.activeCamera && _this.sceneManager.scene.activeCamera.update();
71
- }
72
- }
73
- };
74
- // if exists, use the container id. otherwise, generate a random string.
75
- if (containerElement.id) {
76
- this.baseId = containerElement.id;
77
- }
78
- else {
79
- this.baseId = containerElement.id = "bjs" + Math.random().toString(32).substr(2, 8);
80
- }
81
- this._registeredOnBeforeRenderFunctions = [];
82
- this._configurationContainer = new ConfigurationContainer();
83
- this.observablesManager = new ObservablesManager();
84
- this.modelLoader = new ModelLoader(this.observablesManager, this._configurationContainer);
85
- RenderingManager.AUTOCLEAR = false;
86
- // extend the configuration
87
- this._configurationLoader = this.getConfigurationLoader();
88
- this._configurationLoader.loadConfiguration(initialConfiguration, function (configuration) {
89
- _this._onConfigurationLoaded(configuration);
90
- });
91
- this.onSceneInitObservable.add(function () {
92
- _this.updateConfiguration();
93
- });
94
- this.onInitDoneObservable.add(function () {
95
- _this._isInit = true;
96
- _this.engine.runRenderLoop(_this._render);
97
- });
98
- this._prepareContainerElement();
99
- // add this viewer to the viewer manager
100
- viewerManager.addViewer(this);
101
- }
102
- Object.defineProperty(AbstractViewer.prototype, "onSceneInitObservable", {
103
- // observables
104
- /**
105
- * Will notify when the scene was initialized
106
- */
107
- get: function () {
108
- return this.observablesManager.onSceneInitObservable;
109
- },
110
- enumerable: false,
111
- configurable: true
112
- });
113
- Object.defineProperty(AbstractViewer.prototype, "onEngineInitObservable", {
114
- /**
115
- * will notify when the engine was initialized
116
- */
117
- get: function () {
118
- return this.observablesManager.onEngineInitObservable;
119
- },
120
- enumerable: false,
121
- configurable: true
122
- });
123
- Object.defineProperty(AbstractViewer.prototype, "onModelAddedObservable", {
124
- /**
125
- * Will notify when a new model was added to the scene.
126
- * Note that added does not necessarily mean loaded!
127
- */
128
- get: function () {
129
- return this.observablesManager.onModelAddedObservable;
130
- },
131
- enumerable: false,
132
- configurable: true
133
- });
134
- Object.defineProperty(AbstractViewer.prototype, "onModelLoadedObservable", {
135
- /**
136
- * will notify after every model load
137
- */
138
- get: function () {
139
- return this.observablesManager.onModelLoadedObservable;
140
- },
141
- enumerable: false,
142
- configurable: true
143
- });
144
- Object.defineProperty(AbstractViewer.prototype, "onModelLoadProgressObservable", {
145
- /**
146
- * will notify when any model notify of progress
147
- */
148
- get: function () {
149
- return this.observablesManager.onModelLoadProgressObservable;
150
- },
151
- enumerable: false,
152
- configurable: true
153
- });
154
- Object.defineProperty(AbstractViewer.prototype, "onModelLoadErrorObservable", {
155
- /**
156
- * will notify when any model load failed.
157
- */
158
- get: function () {
159
- return this.observablesManager.onModelLoadErrorObservable;
160
- },
161
- enumerable: false,
162
- configurable: true
163
- });
164
- Object.defineProperty(AbstractViewer.prototype, "onModelRemovedObservable", {
165
- /**
166
- * Will notify when a model was removed from the scene;
167
- */
168
- get: function () {
169
- return this.observablesManager.onModelRemovedObservable;
170
- },
171
- enumerable: false,
172
- configurable: true
173
- });
174
- Object.defineProperty(AbstractViewer.prototype, "onLoaderInitObservable", {
175
- /**
176
- * will notify when a new loader was initialized.
177
- * Used mainly to know when a model starts loading.
178
- */
179
- get: function () {
180
- return this.observablesManager.onLoaderInitObservable;
181
- },
182
- enumerable: false,
183
- configurable: true
184
- });
185
- Object.defineProperty(AbstractViewer.prototype, "onInitDoneObservable", {
186
- /**
187
- * Observers registered here will be executed when the entire load process has finished.
188
- */
189
- get: function () {
190
- return this.observablesManager.onViewerInitDoneObservable;
191
- },
192
- enumerable: false,
193
- configurable: true
194
- });
195
- Object.defineProperty(AbstractViewer.prototype, "onFrameRenderedObservable", {
196
- /**
197
- * Functions added to this observable will be executed on each frame rendered.
198
- */
199
- get: function () {
200
- return this.observablesManager.onFrameRenderedObservable;
201
- },
202
- enumerable: false,
203
- configurable: true
204
- });
205
- Object.defineProperty(AbstractViewer.prototype, "onEnteringVRObservable", {
206
- /**
207
- * Observers registered here will be executed when VR more is entered.
208
- */
209
- get: function () {
210
- return this.observablesManager.onEnteringVRObservable;
211
- },
212
- enumerable: false,
213
- configurable: true
214
- });
215
- Object.defineProperty(AbstractViewer.prototype, "onExitingVRObservable", {
216
- /**
217
- * Observers registered here will be executed when VR mode is exited.
218
- */
219
- get: function () {
220
- return this.observablesManager.onExitingVRObservable;
221
- },
222
- enumerable: false,
223
- configurable: true
224
- });
225
- Object.defineProperty(AbstractViewer.prototype, "canvas", {
226
- /**
227
- * The (single) canvas of this viewer
228
- */
229
- get: function () {
230
- return this._canvas;
231
- },
232
- enumerable: false,
233
- configurable: true
234
- });
235
- Object.defineProperty(AbstractViewer.prototype, "configurationContainer", {
236
- get: function () {
237
- return this._configurationContainer;
238
- },
239
- enumerable: false,
240
- configurable: true
241
- });
242
- // eslint-disable-next-line @typescript-eslint/naming-convention
243
- AbstractViewer.prototype.getConfigurationLoader = function () {
244
- return new RenderOnlyConfigurationLoader();
245
- };
246
- /**
247
- * get the baseId of this viewer
248
- */
249
- AbstractViewer.prototype.getBaseId = function () {
250
- return this.baseId;
251
- };
252
- /**
253
- * Do we have a canvas to render on, and is it a part of the scene
254
- */
255
- AbstractViewer.prototype.isCanvasInDOM = function () {
256
- return !!this._canvas && !!this._canvas.parentElement;
257
- };
258
- Object.defineProperty(AbstractViewer.prototype, "renderInBackground", {
259
- /**
260
- * Is the engine currently set to render even when the page is in background
261
- */
262
- get: function () {
263
- return this.engine && this.engine.renderEvenInBackground;
264
- },
265
- /**
266
- * Set the viewer's background rendering flag.
267
- */
268
- set: function (value) {
269
- if (this.engine) {
270
- this.engine.renderEvenInBackground = value;
271
- }
272
- },
273
- enumerable: false,
274
- configurable: true
275
- });
276
- Object.defineProperty(AbstractViewer.prototype, "configuration", {
277
- /**
278
- * Get the configuration object. This is a reference only.
279
- * The configuration can ONLY be updated using the updateConfiguration function.
280
- * changing this object will have no direct effect on the scene.
281
- */
282
- get: function () {
283
- return this._configurationContainer.configuration;
284
- },
285
- enumerable: false,
286
- configurable: true
287
- });
288
- /**
289
- * force resizing the engine.
290
- */
291
- AbstractViewer.prototype.forceResize = function () {
292
- this._resize();
293
- };
294
- AbstractViewer.prototype.toggleHD = function () {
295
- this._hdToggled = !this._hdToggled;
296
- var scale = this._hdToggled ? Math.max(0.5, 1 / (window.devicePixelRatio || 2)) : 1;
297
- this.engine.setHardwareScalingLevel(scale);
298
- };
299
- AbstractViewer.prototype.toggleVR = function () {
300
- if (!this._vrInit) {
301
- this._initVR();
302
- }
303
- if (this.sceneManager.vrHelper && !this.sceneManager.vrHelper.isInVRMode) {
304
- // make sure the floor is set
305
- if (this.sceneManager.environmentHelper && this.sceneManager.environmentHelper.ground) {
306
- this.sceneManager.vrHelper.addFloorMesh(this.sceneManager.environmentHelper.ground);
307
- }
308
- this._vrToggled = true;
309
- this.sceneManager.vrHelper.enterVR();
310
- // position the vr camera to be in front of the object or wherever the user has configured it to be
311
- if (this.sceneManager.vrHelper.currentVRCamera && this.sceneManager.vrHelper.currentVRCamera !== this.sceneManager.camera) {
312
- if (this.configuration.vr && this.configuration.vr.cameraPosition !== undefined) {
313
- this.sceneManager.vrHelper.currentVRCamera.position.copyFromFloats(this.configuration.vr.cameraPosition.x, this.configuration.vr.cameraPosition.y, this.configuration.vr.cameraPosition.z);
314
- }
315
- else {
316
- this.sceneManager.vrHelper.currentVRCamera.position.copyFromFloats(0, this.sceneManager.vrHelper.currentVRCamera.position.y, -1);
317
- }
318
- this.sceneManager.vrHelper.currentVRCamera.rotationQuaternion &&
319
- this.sceneManager.vrHelper.currentVRCamera.rotationQuaternion.copyFromFloats(0, 0, 0, 1);
320
- // set the height of the model to be what the user has configured, or floating by default
321
- if (this.configuration.vr && this.configuration.vr.modelHeightCorrection !== undefined) {
322
- if (typeof this.configuration.vr.modelHeightCorrection === "number") {
323
- this._vrModelRepositioning = this.configuration.vr.modelHeightCorrection;
324
- }
325
- else if (this.configuration.vr.modelHeightCorrection) {
326
- this._vrModelRepositioning = this.sceneManager.vrHelper.currentVRCamera.position.y / 2;
327
- }
328
- else {
329
- this._vrModelRepositioning = 0;
330
- }
331
- }
332
- // scale the model
333
- if (this.sceneManager.models.length) {
334
- var boundingVectors = this.sceneManager.models[0].rootMesh.getHierarchyBoundingVectors();
335
- var sizeVec = boundingVectors.max.subtract(boundingVectors.min);
336
- var maxDimension = Math.max(sizeVec.x, sizeVec.y, sizeVec.z);
337
- this._vrScale = 1 / maxDimension;
338
- if (this.configuration.vr && this.configuration.vr.objectScaleFactor) {
339
- this._vrScale *= this.configuration.vr.objectScaleFactor;
340
- }
341
- this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(this._vrScale);
342
- // reposition the object to "float" in front of the user
343
- this.sceneManager.models[0].rootMesh.position.y += this._vrModelRepositioning;
344
- this.sceneManager.models[0].rootMesh.rotationQuaternion = null;
345
- }
346
- // scale the environment to match the model
347
- if (this.sceneManager.environmentHelper) {
348
- this.sceneManager.environmentHelper.ground && this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(this._vrScale);
349
- this.sceneManager.environmentHelper.skybox && this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(this._vrScale);
350
- }
351
- // post processing
352
- if (this.sceneManager.defaultRenderingPipelineEnabled && this.sceneManager.defaultRenderingPipeline) {
353
- this.sceneManager.defaultRenderingPipeline.imageProcessingEnabled = false;
354
- this.sceneManager.defaultRenderingPipeline.prepare();
355
- }
356
- }
357
- else {
358
- this._vrModelRepositioning = 0;
359
- }
360
- }
361
- else {
362
- if (this.sceneManager.vrHelper) {
363
- this.sceneManager.vrHelper.exitVR();
364
- }
365
- }
366
- };
367
- AbstractViewer.prototype._initVR = function () {
368
- var _this = this;
369
- if (this.sceneManager.vrHelper) {
370
- this.observablesManager.onExitingVRObservable.add(function () {
371
- if (_this._vrToggled) {
372
- _this._vrToggled = false;
373
- // undo the scaling of the model
374
- if (_this.sceneManager.models.length) {
375
- _this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(1 / _this._vrScale);
376
- _this.sceneManager.models[0].rootMesh.position.y -= _this._vrModelRepositioning;
377
- }
378
- // undo the scaling of the environment
379
- if (_this.sceneManager.environmentHelper) {
380
- _this.sceneManager.environmentHelper.ground && _this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(1 / _this._vrScale);
381
- _this.sceneManager.environmentHelper.skybox && _this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(1 / _this._vrScale);
382
- }
383
- // post processing
384
- if (_this.sceneManager.defaultRenderingPipelineEnabled && _this.sceneManager.defaultRenderingPipeline) {
385
- _this.sceneManager.defaultRenderingPipeline.imageProcessingEnabled = true;
386
- _this.sceneManager.defaultRenderingPipeline.prepare();
387
- }
388
- // clear set height and width
389
- _this.canvas.removeAttribute("height");
390
- _this.canvas.removeAttribute("width");
391
- _this.engine.resize();
392
- }
393
- });
394
- }
395
- this._vrInit = true;
396
- };
397
- AbstractViewer.prototype._onConfigurationLoaded = function (configuration) {
398
- var _this = this;
399
- this._configurationContainer.configuration = deepmerge(this.configuration || {}, configuration);
400
- if (this.configuration.observers) {
401
- this._configureObservers(this.configuration.observers);
402
- }
403
- // TODO remove this after testing, as this is done in the updateConfiguration as well.
404
- if (this.configuration.loaderPlugins) {
405
- Object.keys(this.configuration.loaderPlugins).forEach(function (name) {
406
- if (_this.configuration.loaderPlugins && _this.configuration.loaderPlugins[name]) {
407
- _this.modelLoader.addPlugin(name);
408
- }
409
- });
410
- }
411
- this.observablesManager.onViewerInitStartedObservable.notifyObservers(this);
412
- };
413
- /**
414
- * Force a single render loop execution.
415
- */
416
- AbstractViewer.prototype.forceRender = function () {
417
- this._render(true);
418
- };
419
- /**
420
- * Takes a screenshot of the scene and returns it as a base64 encoded png.
421
- * @param callback optional callback that will be triggered when screenshot is done.
422
- * @param width Optional screenshot width (default to 512).
423
- * @param height Optional screenshot height (default to 512).
424
- * @returns a promise with the screenshot data
425
- */
426
- AbstractViewer.prototype.takeScreenshot = function (callback, width, height) {
427
- var _this = this;
428
- if (width === void 0) { width = 0; }
429
- if (height === void 0) { height = 0; }
430
- width = width || this.canvas.clientWidth;
431
- height = height || this.canvas.clientHeight;
432
- // Create the screenshot
433
- return new Promise(function (resolve, reject) {
434
- try {
435
- Tools.CreateScreenshot(_this.engine, _this.sceneManager.camera, { width: width, height: height }, function (data) {
436
- if (callback) {
437
- callback(data);
438
- }
439
- resolve(data);
440
- });
441
- }
442
- catch (e) {
443
- reject(e);
444
- }
445
- });
446
- };
447
- /**
448
- * Update the current viewer configuration with new values.
449
- * Only provided information will be updated, old configuration values will be kept.
450
- * If this.configuration was manually changed, you can trigger this function with no parameters,
451
- * and the entire configuration will be updated.
452
- * @param newConfiguration the partial configuration to update or a URL to a JSON holding the updated configuration
453
- *
454
- */
455
- AbstractViewer.prototype.updateConfiguration = function (newConfiguration) {
456
- var _this = this;
457
- if (newConfiguration === void 0) { newConfiguration = this.configuration; }
458
- if (typeof newConfiguration === "string") {
459
- Tools.LoadFile(newConfiguration, function (data) {
460
- try {
461
- var newData = JSON.parse(data.toString());
462
- return _this.updateConfiguration(newData);
463
- }
464
- catch (e) {
465
- console.log("Error parsing file " + newConfiguration);
466
- }
467
- }, undefined, undefined, undefined, function (error) {
468
- console.log("Error parsing file " + newConfiguration, error);
469
- });
470
- }
471
- else {
472
- //backcompat
473
- processConfigurationCompatibility(newConfiguration);
474
- // update this.configuration with the new data
475
- this._configurationContainer.configuration = deepmerge(this.configuration || {}, newConfiguration);
476
- this.sceneManager.updateConfiguration(newConfiguration);
477
- // observers in configuration
478
- if (newConfiguration.observers) {
479
- this._configureObservers(newConfiguration.observers);
480
- }
481
- if (newConfiguration.loaderPlugins) {
482
- Object.keys(newConfiguration.loaderPlugins).forEach(function (name) {
483
- if (newConfiguration.loaderPlugins && newConfiguration.loaderPlugins[name]) {
484
- _this.modelLoader.addPlugin(name);
485
- }
486
- });
487
- }
488
- }
489
- };
490
- /**
491
- * this is used to register native functions using the configuration object.
492
- * This will configure the observers.
493
- * @param observersConfiguration observers configuration
494
- */
495
- AbstractViewer.prototype._configureObservers = function (observersConfiguration) {
496
- if (observersConfiguration.onEngineInit) {
497
- this.onEngineInitObservable.add(window[observersConfiguration.onEngineInit]);
498
- }
499
- else {
500
- if (observersConfiguration.onEngineInit === "" && this.configuration.observers && this.configuration.observers.onEngineInit) {
501
- this.onEngineInitObservable.removeCallback(window[this.configuration.observers.onEngineInit]);
502
- }
503
- }
504
- if (observersConfiguration.onSceneInit) {
505
- this.onSceneInitObservable.add(window[observersConfiguration.onSceneInit]);
506
- }
507
- else {
508
- if (observersConfiguration.onSceneInit === "" && this.configuration.observers && this.configuration.observers.onSceneInit) {
509
- this.onSceneInitObservable.removeCallback(window[this.configuration.observers.onSceneInit]);
510
- }
511
- }
512
- if (observersConfiguration.onModelLoaded) {
513
- this.onModelLoadedObservable.add(window[observersConfiguration.onModelLoaded]);
514
- }
515
- else {
516
- if (observersConfiguration.onModelLoaded === "" && this.configuration.observers && this.configuration.observers.onModelLoaded) {
517
- this.onModelLoadedObservable.removeCallback(window[this.configuration.observers.onModelLoaded]);
518
- }
519
- }
520
- };
521
- /**
522
- * Dispose the entire viewer including the scene and the engine
523
- */
524
- AbstractViewer.prototype.dispose = function () {
525
- if (this._isDisposed) {
526
- return;
527
- }
528
- window.removeEventListener("resize", this._resize);
529
- if (this.sceneManager) {
530
- if (this.sceneManager.scene && this.sceneManager.scene.activeCamera) {
531
- this.sceneManager.scene.activeCamera.detachControl();
532
- }
533
- this.sceneManager.dispose();
534
- }
535
- this._fpsTimeoutInterval && clearInterval(this._fpsTimeoutInterval);
536
- this.observablesManager.dispose();
537
- this.modelLoader.dispose();
538
- if (this.engine) {
539
- this.engine.dispose();
540
- }
541
- viewerManager.removeViewer(this);
542
- this._isDisposed = true;
543
- };
544
- /**
545
- * This function will execute when the HTML templates finished initializing.
546
- * It should initialize the engine and continue execution.
547
- *
548
- * @returns {Promise<AbstractViewer>} The viewer object will be returned after the object was loaded.
549
- */
550
- AbstractViewer.prototype._onTemplatesLoaded = function () {
551
- return Promise.resolve(this);
552
- };
553
- /**
554
- * This will force the creation of an engine and a scene.
555
- * It will also load a model if preconfigured.
556
- * But first - it will load the extendible onTemplateLoaded()!
557
- */
558
- AbstractViewer.prototype._onTemplateLoaded = function () {
559
- var _this = this;
560
- // check if viewer was disposed right after created
561
- if (this._isDisposed) {
562
- return Promise.reject("viewer was disposed");
563
- }
564
- return this._onTemplatesLoaded().then(function () {
565
- var autoLoad = typeof _this.configuration.model === "string" || (_this.configuration.model && _this.configuration.model.url);
566
- return _this._initEngine()
567
- .then(function (engine) {
568
- return _this.onEngineInitObservable.notifyObserversWithPromise(engine);
569
- })
570
- .then(function () {
571
- _this._initTelemetryEvents();
572
- if (autoLoad) {
573
- return _this.loadModel(_this.configuration.model)
574
- .catch(function () { })
575
- .then(function () {
576
- return _this.sceneManager.scene;
577
- });
578
- }
579
- else {
580
- return _this.sceneManager.scene || _this.sceneManager.initScene(_this.configuration.scene);
581
- }
582
- })
583
- .then(function () {
584
- return _this.onInitDoneObservable.notifyObserversWithPromise(_this);
585
- })
586
- .catch(function (e) {
587
- Tools.Warn(e.toString());
588
- return _this;
589
- });
590
- });
591
- };
592
- /**
593
- * Initialize the engine. Returns a promise in case async calls are needed.
594
- *
595
- * @protected
596
- * @returns {Promise<Engine>}
597
- * @memberof Viewer
598
- */
599
- AbstractViewer.prototype._initEngine = function () {
600
- // init custom shaders
601
- this._injectCustomShaders();
602
- //let canvasElement = this.templateManager.getCanvas();
603
- if (!this.canvas) {
604
- return Promise.reject("Canvas element not found!");
605
- }
606
- var config = this.configuration.engine || {};
607
- // TDO enable further configuration
608
- // check for webgl2 support, force-disable if needed.
609
- if (viewerGlobals.disableWebGL2Support) {
610
- config.engineOptions = config.engineOptions || {};
611
- config.engineOptions.disableWebGL2Support = true;
612
- }
613
- if (this.configuration["3dCommerceCertified"]) {
614
- config.engineOptions = config.engineOptions || {};
615
- config.engineOptions.forceSRGBBufferSupportState = true;
616
- var loader = SceneLoader.GetPluginForExtension(".gltf");
617
- if (loader) {
618
- loader.transparencyAsCoverage = true;
619
- }
620
- SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
621
- if (plugin.name === "gltf") {
622
- var loader_1 = plugin;
623
- loader_1.transparencyAsCoverage = true;
624
- }
625
- });
626
- }
627
- this.engine = new Engine(this.canvas, !!config.antialiasing, config.engineOptions);
628
- if (!config.disableResize) {
629
- window.addEventListener("resize", this._resize);
630
- }
631
- if (this.configuration.engine) {
632
- if (this.configuration.engine.adaptiveQuality) {
633
- var scale = Math.max(0.5, 1 / (window.devicePixelRatio || 2));
634
- this.engine.setHardwareScalingLevel(scale);
635
- }
636
- if (this.configuration.engine.hdEnabled) {
637
- this.toggleHD();
638
- }
639
- }
640
- // create a new template manager for this viewer
641
- this.sceneManager = new SceneManager(this.engine, this._configurationContainer, this.observablesManager);
642
- return Promise.resolve(this.engine);
643
- };
644
- /**
645
- * Initialize a model loading. The returned object (a ViewerModel object) will be loaded in the background.
646
- * The difference between this and loadModel is that loadModel will fulfill the promise when the model finished loading.
647
- *
648
- * @param modelConfig model configuration to use when loading the model.
649
- * @param clearScene should the scene be cleared before loading this model
650
- * @returns a ViewerModel object that is not yet fully loaded.
651
- */
652
- AbstractViewer.prototype.initModel = function (modelConfig, clearScene) {
653
- var _this = this;
654
- if (clearScene === void 0) { clearScene = true; }
655
- var configuration;
656
- if (typeof modelConfig === "string") {
657
- configuration = {
658
- url: modelConfig,
659
- };
660
- }
661
- else if (modelConfig instanceof File) {
662
- configuration = {
663
- file: modelConfig,
664
- root: "file:",
665
- };
666
- }
667
- else {
668
- configuration = modelConfig;
669
- }
670
- if (!configuration.url && !configuration.file) {
671
- throw new Error("no model provided");
672
- }
673
- if (clearScene) {
674
- this.sceneManager.clearScene(true, false);
675
- }
676
- //merge the configuration for future models:
677
- if (this.configuration.model && typeof this.configuration.model === "object") {
678
- var globalConfig = deepmerge({}, this.configuration.model);
679
- configuration = deepmerge(globalConfig, configuration);
680
- if (modelConfig instanceof File) {
681
- configuration.file = modelConfig;
682
- }
683
- }
684
- else {
685
- this.configuration.model = configuration;
686
- }
687
- this._isLoading = true;
688
- var model = this.modelLoader.load(configuration);
689
- this.lastUsedLoader = model.loader;
690
- model.onLoadErrorObservable.add(function (errorObject) {
691
- _this.onModelLoadErrorObservable.notifyObserversWithPromise(errorObject);
692
- });
693
- model.onLoadProgressObservable.add(function (progressEvent) {
694
- _this.onModelLoadProgressObservable.notifyObserversWithPromise(progressEvent);
695
- });
696
- this.onLoaderInitObservable.notifyObserversWithPromise(this.lastUsedLoader);
697
- model.onLoadedObservable.add(function () {
698
- _this._isLoading = false;
699
- });
700
- return model;
701
- };
702
- /**
703
- * load a model using the provided configuration.
704
- * This function, as opposed to initModel, will return a promise that resolves when the model is loaded, and rejects with error.
705
- * If you want to attach to the observables of the model, use initModel instead.
706
- *
707
- * @param modelConfig the model configuration or URL to load.
708
- * @param clearScene Should the scene be cleared before loading the model
709
- * @returns a Promise the fulfills when the model finished loading successfully.
710
- */
711
- AbstractViewer.prototype.loadModel = function (modelConfig, clearScene) {
712
- var _this = this;
713
- if (clearScene === void 0) { clearScene = true; }
714
- if (this._isLoading) {
715
- // We can decide here whether or not to cancel the lst load, but the developer can do that.
716
- return Promise.reject("another model is curently being loaded.");
717
- }
718
- return Promise.resolve(this.sceneManager.scene)
719
- .then(function (scene) {
720
- if (!scene) {
721
- return _this.sceneManager.initScene(_this.configuration.scene);
722
- }
723
- return scene;
724
- })
725
- .then(function () {
726
- var model = _this.initModel(modelConfig, clearScene);
727
- return new Promise(function (resolve, reject) {
728
- // at this point, configuration.model is an object, not a string
729
- model.onLoadedObservable.add(function () {
730
- resolve(model);
731
- });
732
- model.onLoadErrorObservable.add(function (error) {
733
- reject(error);
734
- });
735
- });
736
- });
737
- };
738
- AbstractViewer.prototype._initTelemetryEvents = function () {
739
- var _this = this;
740
- telemetryManager.broadcast("Engine Capabilities", this.baseId, this.engine.getCaps());
741
- telemetryManager.broadcast("Platform Details", this.baseId, {
742
- userAgent: navigator.userAgent,
743
- platform: navigator.platform,
744
- });
745
- telemetryManager.flushWebGLErrors(this.engine, this.baseId);
746
- var trackFPS = function () {
747
- telemetryManager.broadcast("Current FPS", _this.baseId, { fps: _this.engine.getFps() });
748
- };
749
- trackFPS();
750
- // Track the FPS again after 60 seconds
751
- this._fpsTimeoutInterval = window.setInterval(trackFPS, 60 * 1000);
752
- };
753
- /**
754
- * Injects all the spectre shader in the babylon shader store
755
- */
756
- AbstractViewer.prototype._injectCustomShaders = function () {
757
- var customShaders = this.configuration.customShaders;
758
- // Inject all the spectre shader in the babylon shader store.
759
- if (!customShaders) {
760
- return;
761
- }
762
- if (customShaders.shaders) {
763
- Object.keys(customShaders.shaders).forEach(function (key) {
764
- // typescript considers a callback "unsafe", so... '!'
765
- Effect.ShadersStore[key] = customShaders.shaders[key];
766
- });
767
- }
768
- if (customShaders.includes) {
769
- Object.keys(customShaders.includes).forEach(function (key) {
770
- // typescript considers a callback "unsafe", so... '!'
771
- Effect.IncludesShadersStore[key] = customShaders.includes[key];
772
- });
773
- }
774
- };
775
- return AbstractViewer;
776
- }());
777
- export { AbstractViewer };
1
+ import { Engine } from "@babylonjs/core/Engines/engine.js";
2
+ import { SceneLoader } from "@babylonjs/core/Loading/sceneLoader.js";
3
+ import { RenderingManager } from "@babylonjs/core/Rendering/renderingManager.js";
4
+ import { Tools } from "@babylonjs/core/Misc/tools.js";
5
+ import { Effect } from "@babylonjs/core/Materials/effect.js";
6
+ import { processConfigurationCompatibility } from "../configuration/configurationCompatibility.js";
7
+ import { ConfigurationContainer } from "../configuration/configurationContainer.js";
8
+ import { viewerGlobals } from "../configuration/globals.js";
9
+ import { RenderOnlyConfigurationLoader } from "../configuration/renderOnlyLoader.js";
10
+ // eslint-disable-next-line import/no-internal-modules
11
+ import { deepmerge } from "../helper/index.js";
12
+ import { ModelLoader } from "../loader/modelLoader.js";
13
+ import { ObservablesManager } from "../managers/observablesManager.js";
14
+ import { SceneManager } from "../managers/sceneManager.js";
15
+ import { telemetryManager } from "../managers/telemetryManager.js";
16
+ import { viewerManager } from "./viewerManager.js";
17
+ /**
18
+ * The AbstractViewer is the center of Babylon's viewer.
19
+ * It is the basic implementation of the default viewer and is responsible of loading and showing the model and the templates
20
+ */
21
+ var AbstractViewer = /** @class */ (function () {
22
+ function AbstractViewer(containerElement, initialConfiguration) {
23
+ if (initialConfiguration === void 0) { initialConfiguration = {}; }
24
+ var _this = this;
25
+ this.containerElement = containerElement;
26
+ /**
27
+ * A flag that controls whether or not the render loop should be executed
28
+ */
29
+ this.runRenderLoop = true;
30
+ /**
31
+ * is this viewer disposed?
32
+ */
33
+ this._isDisposed = false;
34
+ this._hdToggled = false;
35
+ this._vrToggled = false;
36
+ this._vrModelRepositioning = 0;
37
+ this._vrScale = 1;
38
+ this._vrInit = false;
39
+ /**
40
+ * The resize function that will be registered with the window object
41
+ */
42
+ this._resize = function () {
43
+ // Only resize if Canvas is in the DOM
44
+ if (!_this.isCanvasInDOM()) {
45
+ return;
46
+ }
47
+ if (_this.canvas.clientWidth <= 0 || _this.canvas.clientHeight <= 0) {
48
+ return;
49
+ }
50
+ if (_this.configuration.engine && _this.configuration.engine.disableResize) {
51
+ return;
52
+ }
53
+ _this.engine.resize();
54
+ };
55
+ /**
56
+ * render loop that will be executed by the engine
57
+ * @param force
58
+ */
59
+ this._render = function (force) {
60
+ if (force === void 0) { force = false; }
61
+ if (force || (_this.sceneManager.scene && _this.sceneManager.scene.activeCamera)) {
62
+ if (_this.runRenderLoop || force) {
63
+ _this.engine.performanceMonitor.enable();
64
+ _this.sceneManager.scene.render();
65
+ _this.onFrameRenderedObservable.notifyObservers(_this);
66
+ }
67
+ else {
68
+ _this.engine.performanceMonitor.disable();
69
+ // update camera instead of rendering
70
+ _this.sceneManager.scene.activeCamera && _this.sceneManager.scene.activeCamera.update();
71
+ }
72
+ }
73
+ };
74
+ // if exists, use the container id. otherwise, generate a random string.
75
+ if (containerElement.id) {
76
+ this.baseId = containerElement.id;
77
+ }
78
+ else {
79
+ this.baseId = containerElement.id = "bjs" + Math.random().toString(32).substr(2, 8);
80
+ }
81
+ this._registeredOnBeforeRenderFunctions = [];
82
+ this._configurationContainer = new ConfigurationContainer();
83
+ this.observablesManager = new ObservablesManager();
84
+ this.modelLoader = new ModelLoader(this.observablesManager, this._configurationContainer);
85
+ RenderingManager.AUTOCLEAR = false;
86
+ // extend the configuration
87
+ this._configurationLoader = this.getConfigurationLoader();
88
+ this._configurationLoader.loadConfiguration(initialConfiguration, function (configuration) {
89
+ _this._onConfigurationLoaded(configuration);
90
+ });
91
+ this.onSceneInitObservable.add(function () {
92
+ _this.updateConfiguration();
93
+ });
94
+ this.onInitDoneObservable.add(function () {
95
+ _this._isInit = true;
96
+ _this.engine.runRenderLoop(_this._render);
97
+ });
98
+ this._prepareContainerElement();
99
+ // add this viewer to the viewer manager
100
+ viewerManager.addViewer(this);
101
+ }
102
+ Object.defineProperty(AbstractViewer.prototype, "onSceneInitObservable", {
103
+ // observables
104
+ /**
105
+ * Will notify when the scene was initialized
106
+ */
107
+ get: function () {
108
+ return this.observablesManager.onSceneInitObservable;
109
+ },
110
+ enumerable: false,
111
+ configurable: true
112
+ });
113
+ Object.defineProperty(AbstractViewer.prototype, "onEngineInitObservable", {
114
+ /**
115
+ * will notify when the engine was initialized
116
+ */
117
+ get: function () {
118
+ return this.observablesManager.onEngineInitObservable;
119
+ },
120
+ enumerable: false,
121
+ configurable: true
122
+ });
123
+ Object.defineProperty(AbstractViewer.prototype, "onModelAddedObservable", {
124
+ /**
125
+ * Will notify when a new model was added to the scene.
126
+ * Note that added does not necessarily mean loaded!
127
+ */
128
+ get: function () {
129
+ return this.observablesManager.onModelAddedObservable;
130
+ },
131
+ enumerable: false,
132
+ configurable: true
133
+ });
134
+ Object.defineProperty(AbstractViewer.prototype, "onModelLoadedObservable", {
135
+ /**
136
+ * will notify after every model load
137
+ */
138
+ get: function () {
139
+ return this.observablesManager.onModelLoadedObservable;
140
+ },
141
+ enumerable: false,
142
+ configurable: true
143
+ });
144
+ Object.defineProperty(AbstractViewer.prototype, "onModelLoadProgressObservable", {
145
+ /**
146
+ * will notify when any model notify of progress
147
+ */
148
+ get: function () {
149
+ return this.observablesManager.onModelLoadProgressObservable;
150
+ },
151
+ enumerable: false,
152
+ configurable: true
153
+ });
154
+ Object.defineProperty(AbstractViewer.prototype, "onModelLoadErrorObservable", {
155
+ /**
156
+ * will notify when any model load failed.
157
+ */
158
+ get: function () {
159
+ return this.observablesManager.onModelLoadErrorObservable;
160
+ },
161
+ enumerable: false,
162
+ configurable: true
163
+ });
164
+ Object.defineProperty(AbstractViewer.prototype, "onModelRemovedObservable", {
165
+ /**
166
+ * Will notify when a model was removed from the scene;
167
+ */
168
+ get: function () {
169
+ return this.observablesManager.onModelRemovedObservable;
170
+ },
171
+ enumerable: false,
172
+ configurable: true
173
+ });
174
+ Object.defineProperty(AbstractViewer.prototype, "onLoaderInitObservable", {
175
+ /**
176
+ * will notify when a new loader was initialized.
177
+ * Used mainly to know when a model starts loading.
178
+ */
179
+ get: function () {
180
+ return this.observablesManager.onLoaderInitObservable;
181
+ },
182
+ enumerable: false,
183
+ configurable: true
184
+ });
185
+ Object.defineProperty(AbstractViewer.prototype, "onInitDoneObservable", {
186
+ /**
187
+ * Observers registered here will be executed when the entire load process has finished.
188
+ */
189
+ get: function () {
190
+ return this.observablesManager.onViewerInitDoneObservable;
191
+ },
192
+ enumerable: false,
193
+ configurable: true
194
+ });
195
+ Object.defineProperty(AbstractViewer.prototype, "onFrameRenderedObservable", {
196
+ /**
197
+ * Functions added to this observable will be executed on each frame rendered.
198
+ */
199
+ get: function () {
200
+ return this.observablesManager.onFrameRenderedObservable;
201
+ },
202
+ enumerable: false,
203
+ configurable: true
204
+ });
205
+ Object.defineProperty(AbstractViewer.prototype, "onEnteringVRObservable", {
206
+ /**
207
+ * Observers registered here will be executed when VR more is entered.
208
+ */
209
+ get: function () {
210
+ return this.observablesManager.onEnteringVRObservable;
211
+ },
212
+ enumerable: false,
213
+ configurable: true
214
+ });
215
+ Object.defineProperty(AbstractViewer.prototype, "onExitingVRObservable", {
216
+ /**
217
+ * Observers registered here will be executed when VR mode is exited.
218
+ */
219
+ get: function () {
220
+ return this.observablesManager.onExitingVRObservable;
221
+ },
222
+ enumerable: false,
223
+ configurable: true
224
+ });
225
+ Object.defineProperty(AbstractViewer.prototype, "canvas", {
226
+ /**
227
+ * The (single) canvas of this viewer
228
+ */
229
+ get: function () {
230
+ return this._canvas;
231
+ },
232
+ enumerable: false,
233
+ configurable: true
234
+ });
235
+ Object.defineProperty(AbstractViewer.prototype, "configurationContainer", {
236
+ get: function () {
237
+ return this._configurationContainer;
238
+ },
239
+ enumerable: false,
240
+ configurable: true
241
+ });
242
+ // eslint-disable-next-line @typescript-eslint/naming-convention
243
+ AbstractViewer.prototype.getConfigurationLoader = function () {
244
+ return new RenderOnlyConfigurationLoader();
245
+ };
246
+ /**
247
+ * get the baseId of this viewer
248
+ */
249
+ AbstractViewer.prototype.getBaseId = function () {
250
+ return this.baseId;
251
+ };
252
+ /**
253
+ * Do we have a canvas to render on, and is it a part of the scene
254
+ */
255
+ AbstractViewer.prototype.isCanvasInDOM = function () {
256
+ return !!this._canvas && !!this._canvas.parentElement;
257
+ };
258
+ Object.defineProperty(AbstractViewer.prototype, "renderInBackground", {
259
+ /**
260
+ * Is the engine currently set to render even when the page is in background
261
+ */
262
+ get: function () {
263
+ return this.engine && this.engine.renderEvenInBackground;
264
+ },
265
+ /**
266
+ * Set the viewer's background rendering flag.
267
+ */
268
+ set: function (value) {
269
+ if (this.engine) {
270
+ this.engine.renderEvenInBackground = value;
271
+ }
272
+ },
273
+ enumerable: false,
274
+ configurable: true
275
+ });
276
+ Object.defineProperty(AbstractViewer.prototype, "configuration", {
277
+ /**
278
+ * Get the configuration object. This is a reference only.
279
+ * The configuration can ONLY be updated using the updateConfiguration function.
280
+ * changing this object will have no direct effect on the scene.
281
+ */
282
+ get: function () {
283
+ return this._configurationContainer.configuration;
284
+ },
285
+ enumerable: false,
286
+ configurable: true
287
+ });
288
+ /**
289
+ * force resizing the engine.
290
+ */
291
+ AbstractViewer.prototype.forceResize = function () {
292
+ this._resize();
293
+ };
294
+ AbstractViewer.prototype.toggleHD = function () {
295
+ this._hdToggled = !this._hdToggled;
296
+ var scale = this._hdToggled ? Math.max(0.5, 1 / (window.devicePixelRatio || 2)) : 1;
297
+ this.engine.setHardwareScalingLevel(scale);
298
+ };
299
+ AbstractViewer.prototype.toggleVR = function () {
300
+ if (!this._vrInit) {
301
+ this._initVR();
302
+ }
303
+ if (this.sceneManager.vrHelper && !this.sceneManager.vrHelper.isInVRMode) {
304
+ // make sure the floor is set
305
+ if (this.sceneManager.environmentHelper && this.sceneManager.environmentHelper.ground) {
306
+ this.sceneManager.vrHelper.addFloorMesh(this.sceneManager.environmentHelper.ground);
307
+ }
308
+ this._vrToggled = true;
309
+ this.sceneManager.vrHelper.enterVR();
310
+ // position the vr camera to be in front of the object or wherever the user has configured it to be
311
+ if (this.sceneManager.vrHelper.currentVRCamera && this.sceneManager.vrHelper.currentVRCamera !== this.sceneManager.camera) {
312
+ if (this.configuration.vr && this.configuration.vr.cameraPosition !== undefined) {
313
+ this.sceneManager.vrHelper.currentVRCamera.position.copyFromFloats(this.configuration.vr.cameraPosition.x, this.configuration.vr.cameraPosition.y, this.configuration.vr.cameraPosition.z);
314
+ }
315
+ else {
316
+ this.sceneManager.vrHelper.currentVRCamera.position.copyFromFloats(0, this.sceneManager.vrHelper.currentVRCamera.position.y, -1);
317
+ }
318
+ this.sceneManager.vrHelper.currentVRCamera.rotationQuaternion &&
319
+ this.sceneManager.vrHelper.currentVRCamera.rotationQuaternion.copyFromFloats(0, 0, 0, 1);
320
+ // set the height of the model to be what the user has configured, or floating by default
321
+ if (this.configuration.vr && this.configuration.vr.modelHeightCorrection !== undefined) {
322
+ if (typeof this.configuration.vr.modelHeightCorrection === "number") {
323
+ this._vrModelRepositioning = this.configuration.vr.modelHeightCorrection;
324
+ }
325
+ else if (this.configuration.vr.modelHeightCorrection) {
326
+ this._vrModelRepositioning = this.sceneManager.vrHelper.currentVRCamera.position.y / 2;
327
+ }
328
+ else {
329
+ this._vrModelRepositioning = 0;
330
+ }
331
+ }
332
+ // scale the model
333
+ if (this.sceneManager.models.length) {
334
+ var boundingVectors = this.sceneManager.models[0].rootMesh.getHierarchyBoundingVectors();
335
+ var sizeVec = boundingVectors.max.subtract(boundingVectors.min);
336
+ var maxDimension = Math.max(sizeVec.x, sizeVec.y, sizeVec.z);
337
+ this._vrScale = 1 / maxDimension;
338
+ if (this.configuration.vr && this.configuration.vr.objectScaleFactor) {
339
+ this._vrScale *= this.configuration.vr.objectScaleFactor;
340
+ }
341
+ this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(this._vrScale);
342
+ // reposition the object to "float" in front of the user
343
+ this.sceneManager.models[0].rootMesh.position.y += this._vrModelRepositioning;
344
+ this.sceneManager.models[0].rootMesh.rotationQuaternion = null;
345
+ }
346
+ // scale the environment to match the model
347
+ if (this.sceneManager.environmentHelper) {
348
+ this.sceneManager.environmentHelper.ground && this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(this._vrScale);
349
+ this.sceneManager.environmentHelper.skybox && this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(this._vrScale);
350
+ }
351
+ // post processing
352
+ if (this.sceneManager.defaultRenderingPipelineEnabled && this.sceneManager.defaultRenderingPipeline) {
353
+ this.sceneManager.defaultRenderingPipeline.imageProcessingEnabled = false;
354
+ this.sceneManager.defaultRenderingPipeline.prepare();
355
+ }
356
+ }
357
+ else {
358
+ this._vrModelRepositioning = 0;
359
+ }
360
+ }
361
+ else {
362
+ if (this.sceneManager.vrHelper) {
363
+ this.sceneManager.vrHelper.exitVR();
364
+ }
365
+ }
366
+ };
367
+ AbstractViewer.prototype._initVR = function () {
368
+ var _this = this;
369
+ if (this.sceneManager.vrHelper) {
370
+ this.observablesManager.onExitingVRObservable.add(function () {
371
+ if (_this._vrToggled) {
372
+ _this._vrToggled = false;
373
+ // undo the scaling of the model
374
+ if (_this.sceneManager.models.length) {
375
+ _this.sceneManager.models[0].rootMesh.scaling.scaleInPlace(1 / _this._vrScale);
376
+ _this.sceneManager.models[0].rootMesh.position.y -= _this._vrModelRepositioning;
377
+ }
378
+ // undo the scaling of the environment
379
+ if (_this.sceneManager.environmentHelper) {
380
+ _this.sceneManager.environmentHelper.ground && _this.sceneManager.environmentHelper.ground.scaling.scaleInPlace(1 / _this._vrScale);
381
+ _this.sceneManager.environmentHelper.skybox && _this.sceneManager.environmentHelper.skybox.scaling.scaleInPlace(1 / _this._vrScale);
382
+ }
383
+ // post processing
384
+ if (_this.sceneManager.defaultRenderingPipelineEnabled && _this.sceneManager.defaultRenderingPipeline) {
385
+ _this.sceneManager.defaultRenderingPipeline.imageProcessingEnabled = true;
386
+ _this.sceneManager.defaultRenderingPipeline.prepare();
387
+ }
388
+ // clear set height and width
389
+ _this.canvas.removeAttribute("height");
390
+ _this.canvas.removeAttribute("width");
391
+ _this.engine.resize();
392
+ }
393
+ });
394
+ }
395
+ this._vrInit = true;
396
+ };
397
+ AbstractViewer.prototype._onConfigurationLoaded = function (configuration) {
398
+ var _this = this;
399
+ this._configurationContainer.configuration = deepmerge(this.configuration || {}, configuration);
400
+ if (this.configuration.observers) {
401
+ this._configureObservers(this.configuration.observers);
402
+ }
403
+ // TODO remove this after testing, as this is done in the updateConfiguration as well.
404
+ if (this.configuration.loaderPlugins) {
405
+ Object.keys(this.configuration.loaderPlugins).forEach(function (name) {
406
+ if (_this.configuration.loaderPlugins && _this.configuration.loaderPlugins[name]) {
407
+ _this.modelLoader.addPlugin(name);
408
+ }
409
+ });
410
+ }
411
+ this.observablesManager.onViewerInitStartedObservable.notifyObservers(this);
412
+ };
413
+ /**
414
+ * Force a single render loop execution.
415
+ */
416
+ AbstractViewer.prototype.forceRender = function () {
417
+ this._render(true);
418
+ };
419
+ /**
420
+ * Takes a screenshot of the scene and returns it as a base64 encoded png.
421
+ * @param callback optional callback that will be triggered when screenshot is done.
422
+ * @param width Optional screenshot width (default to 512).
423
+ * @param height Optional screenshot height (default to 512).
424
+ * @returns a promise with the screenshot data
425
+ */
426
+ AbstractViewer.prototype.takeScreenshot = function (callback, width, height) {
427
+ var _this = this;
428
+ if (width === void 0) { width = 0; }
429
+ if (height === void 0) { height = 0; }
430
+ width = width || this.canvas.clientWidth;
431
+ height = height || this.canvas.clientHeight;
432
+ // Create the screenshot
433
+ return new Promise(function (resolve, reject) {
434
+ try {
435
+ Tools.CreateScreenshot(_this.engine, _this.sceneManager.camera, { width: width, height: height }, function (data) {
436
+ if (callback) {
437
+ callback(data);
438
+ }
439
+ resolve(data);
440
+ });
441
+ }
442
+ catch (e) {
443
+ reject(e);
444
+ }
445
+ });
446
+ };
447
+ /**
448
+ * Update the current viewer configuration with new values.
449
+ * Only provided information will be updated, old configuration values will be kept.
450
+ * If this.configuration was manually changed, you can trigger this function with no parameters,
451
+ * and the entire configuration will be updated.
452
+ * @param newConfiguration the partial configuration to update or a URL to a JSON holding the updated configuration
453
+ *
454
+ */
455
+ AbstractViewer.prototype.updateConfiguration = function (newConfiguration) {
456
+ var _this = this;
457
+ if (newConfiguration === void 0) { newConfiguration = this.configuration; }
458
+ if (typeof newConfiguration === "string") {
459
+ Tools.LoadFile(newConfiguration, function (data) {
460
+ try {
461
+ var newData = JSON.parse(data.toString());
462
+ return _this.updateConfiguration(newData);
463
+ }
464
+ catch (e) {
465
+ console.log("Error parsing file " + newConfiguration);
466
+ }
467
+ }, undefined, undefined, undefined, function (error) {
468
+ console.log("Error parsing file " + newConfiguration, error);
469
+ });
470
+ }
471
+ else {
472
+ //backcompat
473
+ processConfigurationCompatibility(newConfiguration);
474
+ // update this.configuration with the new data
475
+ this._configurationContainer.configuration = deepmerge(this.configuration || {}, newConfiguration);
476
+ this.sceneManager.updateConfiguration(newConfiguration);
477
+ // observers in configuration
478
+ if (newConfiguration.observers) {
479
+ this._configureObservers(newConfiguration.observers);
480
+ }
481
+ if (newConfiguration.loaderPlugins) {
482
+ Object.keys(newConfiguration.loaderPlugins).forEach(function (name) {
483
+ if (newConfiguration.loaderPlugins && newConfiguration.loaderPlugins[name]) {
484
+ _this.modelLoader.addPlugin(name);
485
+ }
486
+ });
487
+ }
488
+ }
489
+ };
490
+ /**
491
+ * this is used to register native functions using the configuration object.
492
+ * This will configure the observers.
493
+ * @param observersConfiguration observers configuration
494
+ */
495
+ AbstractViewer.prototype._configureObservers = function (observersConfiguration) {
496
+ if (observersConfiguration.onEngineInit) {
497
+ this.onEngineInitObservable.add(window[observersConfiguration.onEngineInit]);
498
+ }
499
+ else {
500
+ if (observersConfiguration.onEngineInit === "" && this.configuration.observers && this.configuration.observers.onEngineInit) {
501
+ this.onEngineInitObservable.removeCallback(window[this.configuration.observers.onEngineInit]);
502
+ }
503
+ }
504
+ if (observersConfiguration.onSceneInit) {
505
+ this.onSceneInitObservable.add(window[observersConfiguration.onSceneInit]);
506
+ }
507
+ else {
508
+ if (observersConfiguration.onSceneInit === "" && this.configuration.observers && this.configuration.observers.onSceneInit) {
509
+ this.onSceneInitObservable.removeCallback(window[this.configuration.observers.onSceneInit]);
510
+ }
511
+ }
512
+ if (observersConfiguration.onModelLoaded) {
513
+ this.onModelLoadedObservable.add(window[observersConfiguration.onModelLoaded]);
514
+ }
515
+ else {
516
+ if (observersConfiguration.onModelLoaded === "" && this.configuration.observers && this.configuration.observers.onModelLoaded) {
517
+ this.onModelLoadedObservable.removeCallback(window[this.configuration.observers.onModelLoaded]);
518
+ }
519
+ }
520
+ };
521
+ /**
522
+ * Dispose the entire viewer including the scene and the engine
523
+ */
524
+ AbstractViewer.prototype.dispose = function () {
525
+ if (this._isDisposed) {
526
+ return;
527
+ }
528
+ window.removeEventListener("resize", this._resize);
529
+ if (this.sceneManager) {
530
+ if (this.sceneManager.scene && this.sceneManager.scene.activeCamera) {
531
+ this.sceneManager.scene.activeCamera.detachControl();
532
+ }
533
+ this.sceneManager.dispose();
534
+ }
535
+ this._fpsTimeoutInterval && clearInterval(this._fpsTimeoutInterval);
536
+ this.observablesManager.dispose();
537
+ this.modelLoader.dispose();
538
+ if (this.engine) {
539
+ this.engine.dispose();
540
+ }
541
+ viewerManager.removeViewer(this);
542
+ this._isDisposed = true;
543
+ };
544
+ /**
545
+ * This function will execute when the HTML templates finished initializing.
546
+ * It should initialize the engine and continue execution.
547
+ *
548
+ * @returns {Promise<AbstractViewer>} The viewer object will be returned after the object was loaded.
549
+ */
550
+ AbstractViewer.prototype._onTemplatesLoaded = function () {
551
+ return Promise.resolve(this);
552
+ };
553
+ /**
554
+ * This will force the creation of an engine and a scene.
555
+ * It will also load a model if preconfigured.
556
+ * But first - it will load the extendible onTemplateLoaded()!
557
+ */
558
+ AbstractViewer.prototype._onTemplateLoaded = function () {
559
+ var _this = this;
560
+ // check if viewer was disposed right after created
561
+ if (this._isDisposed) {
562
+ return Promise.reject("viewer was disposed");
563
+ }
564
+ return this._onTemplatesLoaded().then(function () {
565
+ var autoLoad = typeof _this.configuration.model === "string" || (_this.configuration.model && _this.configuration.model.url);
566
+ return _this._initEngine()
567
+ .then(function (engine) {
568
+ return _this.onEngineInitObservable.notifyObserversWithPromise(engine);
569
+ })
570
+ .then(function () {
571
+ _this._initTelemetryEvents();
572
+ if (autoLoad) {
573
+ return _this.loadModel(_this.configuration.model)
574
+ .catch(function () { })
575
+ .then(function () {
576
+ return _this.sceneManager.scene;
577
+ });
578
+ }
579
+ else {
580
+ return _this.sceneManager.scene || _this.sceneManager.initScene(_this.configuration.scene);
581
+ }
582
+ })
583
+ .then(function () {
584
+ return _this.onInitDoneObservable.notifyObserversWithPromise(_this);
585
+ })
586
+ .catch(function (e) {
587
+ Tools.Warn(e.toString());
588
+ return _this;
589
+ });
590
+ });
591
+ };
592
+ /**
593
+ * Initialize the engine. Returns a promise in case async calls are needed.
594
+ *
595
+ * @protected
596
+ * @returns {Promise<Engine>}
597
+ * @memberof Viewer
598
+ */
599
+ AbstractViewer.prototype._initEngine = function () {
600
+ // init custom shaders
601
+ this._injectCustomShaders();
602
+ //let canvasElement = this.templateManager.getCanvas();
603
+ if (!this.canvas) {
604
+ return Promise.reject("Canvas element not found!");
605
+ }
606
+ var config = this.configuration.engine || {};
607
+ // TDO enable further configuration
608
+ // check for webgl2 support, force-disable if needed.
609
+ if (viewerGlobals.disableWebGL2Support) {
610
+ config.engineOptions = config.engineOptions || {};
611
+ config.engineOptions.disableWebGL2Support = true;
612
+ }
613
+ if (this.configuration["3dCommerceCertified"]) {
614
+ config.engineOptions = config.engineOptions || {};
615
+ config.engineOptions.forceSRGBBufferSupportState = true;
616
+ var loader = SceneLoader.GetPluginForExtension(".gltf");
617
+ if (loader) {
618
+ loader.transparencyAsCoverage = true;
619
+ }
620
+ SceneLoader.OnPluginActivatedObservable.add(function (plugin) {
621
+ if (plugin.name === "gltf") {
622
+ var loader_1 = plugin;
623
+ loader_1.transparencyAsCoverage = true;
624
+ }
625
+ });
626
+ }
627
+ this.engine = new Engine(this.canvas, !!config.antialiasing, config.engineOptions);
628
+ if (!config.disableResize) {
629
+ window.addEventListener("resize", this._resize);
630
+ }
631
+ if (this.configuration.engine) {
632
+ if (this.configuration.engine.adaptiveQuality) {
633
+ var scale = Math.max(0.5, 1 / (window.devicePixelRatio || 2));
634
+ this.engine.setHardwareScalingLevel(scale);
635
+ }
636
+ if (this.configuration.engine.hdEnabled) {
637
+ this.toggleHD();
638
+ }
639
+ }
640
+ // create a new template manager for this viewer
641
+ this.sceneManager = new SceneManager(this.engine, this._configurationContainer, this.observablesManager);
642
+ return Promise.resolve(this.engine);
643
+ };
644
+ /**
645
+ * Initialize a model loading. The returned object (a ViewerModel object) will be loaded in the background.
646
+ * The difference between this and loadModel is that loadModel will fulfill the promise when the model finished loading.
647
+ *
648
+ * @param modelConfig model configuration to use when loading the model.
649
+ * @param clearScene should the scene be cleared before loading this model
650
+ * @returns a ViewerModel object that is not yet fully loaded.
651
+ */
652
+ AbstractViewer.prototype.initModel = function (modelConfig, clearScene) {
653
+ var _this = this;
654
+ if (clearScene === void 0) { clearScene = true; }
655
+ var configuration;
656
+ if (typeof modelConfig === "string") {
657
+ configuration = {
658
+ url: modelConfig,
659
+ };
660
+ }
661
+ else if (modelConfig instanceof File) {
662
+ configuration = {
663
+ file: modelConfig,
664
+ root: "file:",
665
+ };
666
+ }
667
+ else {
668
+ configuration = modelConfig;
669
+ }
670
+ if (!configuration.url && !configuration.file) {
671
+ throw new Error("no model provided");
672
+ }
673
+ if (clearScene) {
674
+ this.sceneManager.clearScene(true, false);
675
+ }
676
+ //merge the configuration for future models:
677
+ if (this.configuration.model && typeof this.configuration.model === "object") {
678
+ var globalConfig = deepmerge({}, this.configuration.model);
679
+ configuration = deepmerge(globalConfig, configuration);
680
+ if (modelConfig instanceof File) {
681
+ configuration.file = modelConfig;
682
+ }
683
+ }
684
+ else {
685
+ this.configuration.model = configuration;
686
+ }
687
+ this._isLoading = true;
688
+ var model = this.modelLoader.load(configuration);
689
+ this.lastUsedLoader = model.loader;
690
+ model.onLoadErrorObservable.add(function (errorObject) {
691
+ _this.onModelLoadErrorObservable.notifyObserversWithPromise(errorObject);
692
+ });
693
+ model.onLoadProgressObservable.add(function (progressEvent) {
694
+ _this.onModelLoadProgressObservable.notifyObserversWithPromise(progressEvent);
695
+ });
696
+ this.onLoaderInitObservable.notifyObserversWithPromise(this.lastUsedLoader);
697
+ model.onLoadedObservable.add(function () {
698
+ _this._isLoading = false;
699
+ });
700
+ return model;
701
+ };
702
+ /**
703
+ * load a model using the provided configuration.
704
+ * This function, as opposed to initModel, will return a promise that resolves when the model is loaded, and rejects with error.
705
+ * If you want to attach to the observables of the model, use initModel instead.
706
+ *
707
+ * @param modelConfig the model configuration or URL to load.
708
+ * @param clearScene Should the scene be cleared before loading the model
709
+ * @returns a Promise the fulfills when the model finished loading successfully.
710
+ */
711
+ AbstractViewer.prototype.loadModel = function (modelConfig, clearScene) {
712
+ var _this = this;
713
+ if (clearScene === void 0) { clearScene = true; }
714
+ if (this._isLoading) {
715
+ // We can decide here whether or not to cancel the lst load, but the developer can do that.
716
+ return Promise.reject("another model is curently being loaded.");
717
+ }
718
+ return Promise.resolve(this.sceneManager.scene)
719
+ .then(function (scene) {
720
+ if (!scene) {
721
+ return _this.sceneManager.initScene(_this.configuration.scene);
722
+ }
723
+ return scene;
724
+ })
725
+ .then(function () {
726
+ var model = _this.initModel(modelConfig, clearScene);
727
+ return new Promise(function (resolve, reject) {
728
+ // at this point, configuration.model is an object, not a string
729
+ model.onLoadedObservable.add(function () {
730
+ resolve(model);
731
+ });
732
+ model.onLoadErrorObservable.add(function (error) {
733
+ reject(error);
734
+ });
735
+ });
736
+ });
737
+ };
738
+ AbstractViewer.prototype._initTelemetryEvents = function () {
739
+ var _this = this;
740
+ telemetryManager.broadcast("Engine Capabilities", this.baseId, this.engine.getCaps());
741
+ telemetryManager.broadcast("Platform Details", this.baseId, {
742
+ userAgent: navigator.userAgent,
743
+ platform: navigator.platform,
744
+ });
745
+ telemetryManager.flushWebGLErrors(this.engine, this.baseId);
746
+ var trackFPS = function () {
747
+ telemetryManager.broadcast("Current FPS", _this.baseId, { fps: _this.engine.getFps() });
748
+ };
749
+ trackFPS();
750
+ // Track the FPS again after 60 seconds
751
+ this._fpsTimeoutInterval = window.setInterval(trackFPS, 60 * 1000);
752
+ };
753
+ /**
754
+ * Injects all the spectre shader in the babylon shader store
755
+ */
756
+ AbstractViewer.prototype._injectCustomShaders = function () {
757
+ var customShaders = this.configuration.customShaders;
758
+ // Inject all the spectre shader in the babylon shader store.
759
+ if (!customShaders) {
760
+ return;
761
+ }
762
+ if (customShaders.shaders) {
763
+ Object.keys(customShaders.shaders).forEach(function (key) {
764
+ // typescript considers a callback "unsafe", so... '!'
765
+ Effect.ShadersStore[key] = customShaders.shaders[key];
766
+ });
767
+ }
768
+ if (customShaders.includes) {
769
+ Object.keys(customShaders.includes).forEach(function (key) {
770
+ // typescript considers a callback "unsafe", so... '!'
771
+ Effect.IncludesShadersStore[key] = customShaders.includes[key];
772
+ });
773
+ }
774
+ };
775
+ return AbstractViewer;
776
+ }());
777
+ export { AbstractViewer };
778
778
  //# sourceMappingURL=viewer.js.map