@babylonjs/core 9.12.0 → 9.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/Behaviors/Cameras/interpolatingBehavior.d.ts +17 -2
  2. package/Behaviors/Cameras/interpolatingBehavior.js +53 -23
  3. package/Behaviors/Cameras/interpolatingBehavior.js.map +1 -1
  4. package/Cameras/Inputs/flyCameraKeyboardInput.js +9 -1
  5. package/Cameras/Inputs/flyCameraKeyboardInput.js.map +1 -1
  6. package/Cameras/Inputs/flyCameraMouseInput.d.ts +2 -0
  7. package/Cameras/Inputs/flyCameraMouseInput.js +14 -2
  8. package/Cameras/Inputs/flyCameraMouseInput.js.map +1 -1
  9. package/Cameras/Inputs/freeCameraKeyboardMoveInput.js +25 -5
  10. package/Cameras/Inputs/freeCameraKeyboardMoveInput.js.map +1 -1
  11. package/Cameras/Inputs/freeCameraMouseInput.d.ts +14 -0
  12. package/Cameras/Inputs/freeCameraMouseInput.js +26 -4
  13. package/Cameras/Inputs/freeCameraMouseInput.js.map +1 -1
  14. package/Cameras/Inputs/freeCameraTouchInput.js +16 -5
  15. package/Cameras/Inputs/freeCameraTouchInput.js.map +1 -1
  16. package/Cameras/Inputs/geospatialCameraKeyboardInput.js +8 -1
  17. package/Cameras/Inputs/geospatialCameraKeyboardInput.js.map +1 -1
  18. package/Cameras/arcRotateCamera.pure.js.map +1 -1
  19. package/Cameras/flyCamera.pure.d.ts +8 -0
  20. package/Cameras/flyCamera.pure.js.map +1 -1
  21. package/Cameras/freeCamera.pure.d.ts +8 -0
  22. package/Cameras/freeCamera.pure.js.map +1 -1
  23. package/Cameras/geospatialCamera.pure.d.ts +30 -7
  24. package/Cameras/geospatialCamera.pure.js +39 -14
  25. package/Cameras/geospatialCamera.pure.js.map +1 -1
  26. package/Cameras/geospatialCameraMovement.js +2 -2
  27. package/Cameras/geospatialCameraMovement.js.map +1 -1
  28. package/Cameras/index.d.ts +1 -0
  29. package/Cameras/index.js +1 -0
  30. package/Cameras/index.js.map +1 -1
  31. package/Cameras/pure.d.ts +1 -0
  32. package/Cameras/pure.js +1 -0
  33. package/Cameras/pure.js.map +1 -1
  34. package/Cameras/targetCamera.pure.d.ts +25 -0
  35. package/Cameras/targetCamera.pure.js +83 -25
  36. package/Cameras/targetCamera.pure.js.map +1 -1
  37. package/Cameras/targetCameraMovement.d.ts +56 -0
  38. package/Cameras/targetCameraMovement.js +63 -0
  39. package/Cameras/targetCameraMovement.js.map +1 -0
  40. package/Collisions/gpuPicker.d.ts +111 -4
  41. package/Collisions/gpuPicker.js +673 -106
  42. package/Collisions/gpuPicker.js.map +1 -1
  43. package/Engines/AbstractEngine/abstractEngine.scissor.d.ts +18 -0
  44. package/Engines/AbstractEngine/abstractEngine.scissor.js +2 -0
  45. package/Engines/AbstractEngine/abstractEngine.scissor.js.map +1 -0
  46. package/Engines/Native/nativeInterfaces.d.ts +1 -0
  47. package/Engines/Native/nativeInterfaces.js.map +1 -1
  48. package/Engines/abstractEngine.pure.js +2 -2
  49. package/Engines/abstractEngine.pure.js.map +1 -1
  50. package/Engines/engine.d.ts +1 -0
  51. package/Engines/engine.js +1 -0
  52. package/Engines/engine.js.map +1 -1
  53. package/Engines/engine.pure.d.ts +0 -12
  54. package/Engines/engine.pure.js +0 -20
  55. package/Engines/engine.pure.js.map +1 -1
  56. package/Engines/nullEngine.pure.d.ts +66 -0
  57. package/Engines/nullEngine.pure.js +97 -0
  58. package/Engines/nullEngine.pure.js.map +1 -1
  59. package/Engines/pure.d.ts +1 -0
  60. package/Engines/pure.js +1 -0
  61. package/Engines/pure.js.map +1 -1
  62. package/Engines/thinEngine.scissor.d.ts +6 -0
  63. package/Engines/thinEngine.scissor.js +9 -0
  64. package/Engines/thinEngine.scissor.js.map +1 -0
  65. package/Engines/thinEngine.scissor.pure.d.ts +6 -0
  66. package/Engines/thinEngine.scissor.pure.js +24 -0
  67. package/Engines/thinEngine.scissor.pure.js.map +1 -0
  68. package/Engines/thinNativeEngine.d.ts +0 -1
  69. package/Engines/thinNativeEngine.js +0 -1
  70. package/Engines/thinNativeEngine.js.map +1 -1
  71. package/Engines/thinNativeEngine.pure.d.ts +3 -0
  72. package/Engines/thinNativeEngine.pure.js +50 -4
  73. package/Engines/thinNativeEngine.pure.js.map +1 -1
  74. package/Engines/webgpuEngine.pure.js.map +1 -1
  75. package/Loading/sceneLoader.d.ts +5 -1
  76. package/Loading/sceneLoader.js +298 -401
  77. package/Loading/sceneLoader.js.map +1 -1
  78. package/Materials/GaussianSplatting/gaussianSplattingGpuPickingMaterialPlugin.pure.d.ts +15 -0
  79. package/Materials/GaussianSplatting/gaussianSplattingGpuPickingMaterialPlugin.pure.js +34 -1
  80. package/Materials/GaussianSplatting/gaussianSplattingGpuPickingMaterialPlugin.pure.js.map +1 -1
  81. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.d.ts +9 -0
  82. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js +26 -2
  83. package/Materials/GaussianSplatting/gaussianSplattingMaterial.pure.js.map +1 -1
  84. package/Materials/GreasedLine/greasedLinePluginMaterialShadersGLSL.js +10 -3
  85. package/Materials/GreasedLine/greasedLinePluginMaterialShadersGLSL.js.map +1 -1
  86. package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.pure.js +3 -1
  87. package/Materials/Node/Blocks/GaussianSplatting/gaussianSplattingBlock.pure.js.map +1 -1
  88. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js +18 -8
  89. package/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.js.map +1 -1
  90. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +77 -1
  91. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +243 -104
  92. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
  93. package/Meshes/GaussianSplatting/gaussianSplattingSortWorker.d.ts +39 -0
  94. package/Meshes/GaussianSplatting/gaussianSplattingSortWorker.js +308 -0
  95. package/Meshes/GaussianSplatting/gaussianSplattingSortWorker.js.map +1 -0
  96. package/Meshes/geometry.js +30 -15
  97. package/Meshes/geometry.js.map +1 -1
  98. package/Meshes/mesh.pure.js +26 -14
  99. package/Meshes/mesh.pure.js.map +1 -1
  100. package/Misc/tools.pure.js +1 -1
  101. package/Misc/tools.pure.js.map +1 -1
  102. package/Shaders/ShadersInclude/gaussianSplatting.js +1 -0
  103. package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
  104. package/Shaders/gaussianSplatting.fragment.js +17 -1
  105. package/Shaders/gaussianSplatting.fragment.js.map +1 -1
  106. package/Shaders/gaussianSplatting.vertex.js +1 -1
  107. package/Shaders/gaussianSplatting.vertex.js.map +1 -1
  108. package/Shaders/gaussianSplattingDepth.vertex.js +1 -1
  109. package/Shaders/gaussianSplattingDepth.vertex.js.map +1 -1
  110. package/Shaders/greasedLine.vertex.js +19 -3
  111. package/Shaders/greasedLine.vertex.js.map +1 -1
  112. package/Shaders/picking.fragment.js +39 -3
  113. package/Shaders/picking.fragment.js.map +1 -1
  114. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +3 -1
  115. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
  116. package/ShadersWGSL/gaussianSplatting.fragment.js +14 -1
  117. package/ShadersWGSL/gaussianSplatting.fragment.js.map +1 -1
  118. package/ShadersWGSL/gaussianSplatting.vertex.js +2 -2
  119. package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
  120. package/ShadersWGSL/gaussianSplattingDepth.vertex.js +2 -2
  121. package/ShadersWGSL/gaussianSplattingDepth.vertex.js.map +1 -1
  122. package/ShadersWGSL/picking.fragment.js +22 -1
  123. package/ShadersWGSL/picking.fragment.js.map +1 -1
  124. package/package.json +3 -2
  125. package/scene.pure.d.ts +12 -0
  126. package/scene.pure.js +36 -0
  127. package/scene.pure.js.map +1 -1
@@ -101,11 +101,91 @@ function formatErrorMessage(fileInfo, message, exception) {
101
101
  }
102
102
  return errorMessage;
103
103
  }
104
- async function loadDataAsync(fileInfo, scene, onSuccess, onProgress, onError, onDispose, pluginExtension, name, pluginOptions) {
104
+ function createLoadError(fileInfo, message, exception) {
105
+ const errorMessage = formatErrorMessage(fileInfo, message, exception);
106
+ return new RuntimeError(errorMessage, ErrorCodes.SceneLoaderError, exception);
107
+ }
108
+ function getErrorMessage(error) {
109
+ return error instanceof Error ? error.message : String(error);
110
+ }
111
+ // Converts an error into a SceneLoader RuntimeError, leaving an already-wrapped SceneLoader error untouched
112
+ // so that it is not double-wrapped (which would duplicate the "Unable to load from ..." prefix).
113
+ function toLoadError(fileInfo, error) {
114
+ return error instanceof RuntimeError && error.errorCode === ErrorCodes.SceneLoaderError ? error : createLoadError(fileInfo, getErrorMessage(error), error);
115
+ }
116
+ const loadAssetContainerNotSupportedMessage = "LoadAssetContainer is not supported by this plugin. Plugin did not provide a loadAssetContainer or loadAssetContainerAsync method.";
117
+ // A synchronous plugin exposes the synchronous import/load methods; an asynchronous plugin exposes the *Async methods.
118
+ function isSyncPlugin(plugin) {
119
+ const candidate = plugin;
120
+ return !!candidate.importMesh || !!candidate.load || !!candidate.loadAssetContainer;
121
+ }
122
+ // Adapts a synchronous ISceneLoaderPlugin into an ISceneLoaderPluginAsync so that callers can use a single
123
+ // promise-based code path regardless of whether the underlying plugin is synchronous or asynchronous.
124
+ // Asynchronous plugins are returned unchanged. The synchronous plugin reports failure via an onError callback
125
+ // and/or a falsy return value; both are translated into a rejected promise.
126
+ function toAsyncPlugin(plugin, fileInfo) {
127
+ if (!isSyncPlugin(plugin)) {
128
+ return plugin;
129
+ }
130
+ const runSync = (invoke) => {
131
+ let pluginError;
132
+ const result = invoke((message, exception) => {
133
+ pluginError = { message, exception };
134
+ });
135
+ if (!result) {
136
+ throw createLoadError(fileInfo, pluginError?.message, pluginError?.exception);
137
+ }
138
+ return result;
139
+ };
140
+ return {
141
+ name: plugin.name,
142
+ extensions: plugin.extensions,
143
+ importMeshAsync: async (meshesNames, scene, data, rootUrl) => {
144
+ const meshes = [];
145
+ const particleSystems = [];
146
+ const skeletons = [];
147
+ runSync((onError) => plugin.importMesh(meshesNames, scene, data, rootUrl, meshes, particleSystems, skeletons, onError));
148
+ return { meshes, particleSystems, skeletons, animationGroups: [], transformNodes: [], geometries: [], lights: [], spriteManagers: [] };
149
+ },
150
+ loadAsync: async (scene, data, rootUrl) => {
151
+ runSync((onError) => plugin.load(scene, data, rootUrl, onError));
152
+ },
153
+ loadAssetContainerAsync: async (scene, data, rootUrl) => {
154
+ return runSync((onError) => plugin.loadAssetContainer(scene, data, rootUrl, onError));
155
+ },
156
+ };
157
+ }
158
+ // Reports a load failure to the legacy onError callback. The onError signature requires a Scene, but a scene
159
+ // may not be available (e.g. the error occurred before any scene was created). In that case, fall back to
160
+ // logging so the error handler does not throw a secondary error and mask the original failure.
161
+ function reportLegacyLoadError(onError, reportScene, error) {
162
+ const message = getErrorMessage(error);
163
+ if (onError && reportScene) {
164
+ onError(reportScene, message, error);
165
+ }
166
+ else {
167
+ Logger.Error(message);
168
+ }
169
+ }
170
+ // Wraps a user supplied progress callback so that an exception thrown by it is logged rather than
171
+ // aborting the entire loading operation.
172
+ function wrapProgress(onProgress) {
173
+ if (!onProgress) {
174
+ return undefined;
175
+ }
176
+ return (event) => {
177
+ try {
178
+ onProgress(event);
179
+ }
180
+ catch (error) {
181
+ Logger.Warn("Error in onProgress callback: " + getErrorMessage(error));
182
+ }
183
+ };
184
+ }
185
+ async function loadDataAsync(fileInfo, scene, onProgress, pluginExtension, name, pluginOptions) {
105
186
  const directLoad = getDirectLoad(fileInfo.url);
106
187
  if (fileInfo.rawData && !pluginExtension) {
107
- // eslint-disable-next-line no-throw-literal
108
- throw "When using ArrayBufferView to load data the file extension must be provided.";
188
+ throw new Error("When using ArrayBufferView to load data the file extension must be provided.");
109
189
  }
110
190
  const fileExtension = !directLoad && !pluginExtension ? getFilenameExtension(fileInfo.url) : "";
111
191
  let registeredPlugin = pluginExtension
@@ -119,7 +199,6 @@ async function loadDataAsync(fileInfo, scene, onSuccess, onProgress, onError, on
119
199
  const response = await _FetchAsync(fileInfo.url, { method: "HEAD", responseHeaders: ["Content-Type"] });
120
200
  const mimeType = response.headerValues ? response.headerValues["Content-Type"] : "";
121
201
  if (mimeType) {
122
- // eslint-disable-next-line require-atomic-updates
123
202
  registeredPlugin = getPluginForMimeType(mimeType);
124
203
  }
125
204
  }
@@ -134,101 +213,103 @@ async function loadDataAsync(fileInfo, scene, onSuccess, onProgress, onError, on
134
213
  throw new Error(`The '${registeredPlugin.plugin.name}' plugin is disabled via the loader options passed to the loading operation.`);
135
214
  }
136
215
  if (fileInfo.rawData && !registeredPlugin.isBinary) {
137
- // eslint-disable-next-line no-throw-literal
138
- throw "Loading from ArrayBufferView can not be used with plugins that don't support binary loading.";
139
- }
140
- const getPluginInstance = (callback) => {
141
- // For plugin factories, the plugin is instantiated on each SceneLoader operation. This makes options handling
142
- // much simpler as we can just pass the options to the factory, rather than passing options through to every possible
143
- // plugin call. Given this, options are only supported for plugins that provide a factory function.
144
- if (IsFactory(registeredPlugin.plugin)) {
145
- const pluginFactory = registeredPlugin.plugin;
146
- const partialPlugin = pluginFactory.createPlugin((pluginOptions ?? {}));
147
- if (partialPlugin instanceof Promise) {
148
- // eslint-disable-next-line github/no-then
149
- partialPlugin.then(callback).catch((error) => {
150
- onError("Error instantiating plugin.", error);
151
- });
152
- // When async factories are used, the plugin instance cannot be returned synchronously.
153
- // In this case, the legacy loader functions will return null.
154
- return null;
155
- }
156
- else {
157
- callback(partialPlugin);
158
- return partialPlugin;
159
- }
160
- }
161
- else {
162
- callback(registeredPlugin.plugin);
163
- return registeredPlugin.plugin;
216
+ throw new Error("Loading from ArrayBufferView can not be used with plugins that don't support binary loading.");
217
+ }
218
+ // For plugin factories, the plugin is instantiated on each SceneLoader operation. This makes options handling
219
+ // much simpler as we can just pass the options to the factory, rather than passing options through to every possible
220
+ // plugin call. Given this, options are only supported for plugins that provide a factory function.
221
+ let plugin;
222
+ if (IsFactory(registeredPlugin.plugin)) {
223
+ const pluginFactory = registeredPlugin.plugin;
224
+ try {
225
+ // Only await when the factory is actually asynchronous, so that for synchronous factories the plugin is
226
+ // instantiated (and onPluginActivatedObservable is notified) synchronously within the calling load operation.
227
+ const createdPlugin = pluginFactory.createPlugin((pluginOptions ?? {}));
228
+ plugin = createdPlugin instanceof Promise ? await createdPlugin : createdPlugin;
164
229
  }
165
- };
166
- return getPluginInstance((plugin) => {
167
- if (!plugin) {
168
- // eslint-disable-next-line no-throw-literal
169
- throw `The loader plugin corresponding to the '${pluginExtension}' file type has not been found. If using es6, please import the plugin you wish to use before.`;
230
+ catch (error) {
231
+ throw createLoadError(fileInfo, "Error instantiating plugin.", error);
170
232
  }
171
- onPluginActivatedObservable.notifyObservers(plugin);
172
- // Check if we have a direct load url. If the plugin is registered to handle
173
- // it or it's not a base64 data url, then pass it through the direct load path.
174
- if (directLoad && ((plugin.canDirectLoad && plugin.canDirectLoad(fileInfo.url)) || !IsBase64DataUrl(fileInfo.url))) {
175
- if (plugin.directLoad) {
176
- const result = plugin.directLoad(scene, directLoad);
177
- if (result instanceof Promise) {
178
- result
179
- // eslint-disable-next-line github/no-then
180
- .then((data) => {
181
- onSuccess(plugin, data);
182
- })
183
- // eslint-disable-next-line github/no-then
184
- .catch((error) => {
185
- onError("Error in directLoad of _loadData: " + error, error);
186
- });
187
- }
188
- else {
189
- onSuccess(plugin, result);
190
- }
233
+ }
234
+ else {
235
+ plugin = registeredPlugin.plugin;
236
+ }
237
+ if (!plugin) {
238
+ throw new Error(`The loader plugin corresponding to the '${pluginExtension}' file type has not been found. If using es6, please import the plugin you wish to use before.`);
239
+ }
240
+ onPluginActivatedObservable.notifyObservers(plugin);
241
+ // Check if we have a direct load url. If the plugin is registered to handle
242
+ // it or it's not a base64 data url, then pass it through the direct load path.
243
+ if (directLoad && ((plugin.canDirectLoad && plugin.canDirectLoad(fileInfo.url)) || !IsBase64DataUrl(fileInfo.url))) {
244
+ if (plugin.directLoad) {
245
+ let data;
246
+ try {
247
+ data = await plugin.directLoad(scene, directLoad);
191
248
  }
192
- else {
193
- onSuccess(plugin, directLoad);
249
+ catch (error) {
250
+ throw createLoadError(fileInfo, "Error in directLoad of _loadData: " + error, error);
194
251
  }
195
- return;
252
+ return { plugin, data };
196
253
  }
197
- const useArrayBuffer = registeredPlugin.isBinary;
198
- const dataCallback = (data, responseURL) => {
199
- if (scene.isDisposed) {
200
- onError("Scene has been disposed");
201
- return;
202
- }
203
- onSuccess(plugin, data, responseURL);
204
- };
254
+ return { plugin, data: directLoad };
255
+ }
256
+ const useArrayBuffer = registeredPlugin.isBinary;
257
+ return await new Promise((resolve, reject) => {
205
258
  let request = null;
206
259
  let pluginDisposed = false;
207
- plugin.onDisposeObservable?.add(() => {
260
+ const onDisposeObserver = plugin.onDisposeObservable?.add(() => {
208
261
  pluginDisposed = true;
209
262
  if (request) {
210
263
  request.abort();
211
264
  request = null;
212
265
  }
213
- onDispose();
266
+ rejectAndCleanup(createLoadError(fileInfo, "Loading was aborted because the plugin was disposed."));
214
267
  });
268
+ // Ensure the onDispose observer is removed once the promise settles, so observers do not accumulate across loads.
269
+ const cleanup = () => {
270
+ if (onDisposeObserver) {
271
+ plugin.onDisposeObservable?.remove(onDisposeObserver);
272
+ }
273
+ };
274
+ const resolveAndCleanup = (value) => {
275
+ cleanup();
276
+ resolve(value);
277
+ };
278
+ const rejectAndCleanup = (error) => {
279
+ cleanup();
280
+ reject(error);
281
+ };
282
+ const dataCallback = (data, responseURL) => {
283
+ if (scene.isDisposed) {
284
+ rejectAndCleanup(createLoadError(fileInfo, "Scene has been disposed"));
285
+ return;
286
+ }
287
+ resolveAndCleanup({ plugin, data, responseURL });
288
+ };
215
289
  const manifestChecked = () => {
216
290
  if (pluginDisposed) {
217
291
  return;
218
292
  }
219
293
  const errorCallback = (request, exception) => {
220
- onError(request?.statusText, exception);
294
+ rejectAndCleanup(createLoadError(fileInfo, request?.statusText, exception));
221
295
  };
222
296
  if (!plugin.loadFile && fileInfo.rawData) {
223
- // eslint-disable-next-line no-throw-literal
224
- throw "Plugin does not support loading ArrayBufferView.";
297
+ rejectAndCleanup(createLoadError(fileInfo, "Plugin does not support loading ArrayBufferView."));
298
+ return;
299
+ }
300
+ try {
301
+ request = plugin.loadFile
302
+ ? plugin.loadFile(scene, fileInfo.rawData || fileInfo.file || fileInfo.url, fileInfo.rootUrl, dataCallback, onProgress, useArrayBuffer, errorCallback, name)
303
+ : scene._loadFile(fileInfo.file || fileInfo.url, dataCallback, onProgress, true, useArrayBuffer, errorCallback);
304
+ }
305
+ catch (error) {
306
+ rejectAndCleanup(createLoadError(fileInfo, undefined, error));
225
307
  }
226
- request = plugin.loadFile
227
- ? plugin.loadFile(scene, fileInfo.rawData || fileInfo.file || fileInfo.url, fileInfo.rootUrl, dataCallback, onProgress, useArrayBuffer, errorCallback, name)
228
- : scene._loadFile(fileInfo.file || fileInfo.url, dataCallback, onProgress, true, useArrayBuffer, errorCallback);
229
308
  };
230
309
  const engine = scene.getEngine();
231
- let canUseOfflineSupport = engine.enableOfflineSupport;
310
+ // File objects and raw data buffers are already in-memory and are not URL-backed requests, so they must
311
+ // not be routed through the offline (manifest/cache) provider.
312
+ let canUseOfflineSupport = !fileInfo.file && !fileInfo.rawData && engine.enableOfflineSupport;
232
313
  if (canUseOfflineSupport) {
233
314
  // Also check for exceptions
234
315
  let exceptionFound = false;
@@ -242,7 +323,12 @@ async function loadDataAsync(fileInfo, scene, onSuccess, onProgress, onError, on
242
323
  }
243
324
  if (canUseOfflineSupport && AbstractEngine.OfflineProviderFactory) {
244
325
  // Checking if a manifest file has been set for this scene and if offline mode has been requested
245
- scene.offlineProvider = AbstractEngine.OfflineProviderFactory(fileInfo.url, manifestChecked, engine.disableManifestCheck);
326
+ try {
327
+ scene.offlineProvider = AbstractEngine.OfflineProviderFactory(fileInfo.url, manifestChecked, engine.disableManifestCheck);
328
+ }
329
+ catch (error) {
330
+ rejectAndCleanup(createLoadError(fileInfo, undefined, error));
331
+ }
246
332
  }
247
333
  else {
248
334
  manifestChecked();
@@ -350,120 +436,55 @@ export function GetRegisteredSceneLoaderPluginMetadata() {
350
436
  */
351
437
  export async function ImportMeshAsync(source, scene, options) {
352
438
  const { meshNames, rootUrl = "", onProgress, pluginExtension, name, pluginOptions } = options ?? {};
353
- return await importMeshAsyncCoreAsync(meshNames, rootUrl, source, scene, onProgress, pluginExtension, name, pluginOptions);
439
+ return await importMeshCoreAsync(meshNames, rootUrl, source, scene, onProgress, pluginExtension, name, pluginOptions);
354
440
  }
355
- async function importMeshAsync(meshNames, rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, onSuccess = null, onProgress = null, onError = null, pluginExtension = null, name = "", pluginOptions = {}) {
441
+ async function importMeshCoreAsync(meshNames, rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, onProgress, pluginExtension, name = "", pluginOptions = {}) {
356
442
  if (!scene) {
357
- Logger.Error("No scene available to import mesh to");
358
- return null;
443
+ throw new Error("No scene available to import mesh to");
359
444
  }
360
445
  const fileInfo = GetFileInfo(rootUrl, sceneFilename);
361
446
  if (!fileInfo) {
362
- return null;
447
+ throw new Error("Cannot load file: a valid scene filename or root url was not provided.");
363
448
  }
364
449
  const loadingToken = {};
365
450
  scene.addPendingData(loadingToken);
366
- const disposeHandler = () => {
367
- scene.removePendingData(loadingToken);
368
- };
369
- const errorHandler = (message, exception) => {
370
- const errorMessage = formatErrorMessage(fileInfo, message, exception);
371
- if (onError) {
372
- onError(scene, errorMessage, new RuntimeError(errorMessage, ErrorCodes.SceneLoaderError, exception));
373
- }
374
- else {
375
- Logger.Error(errorMessage);
376
- // should the exception be thrown?
377
- }
378
- disposeHandler();
379
- };
380
- const progressHandler = onProgress
381
- ? (event) => {
382
- try {
383
- onProgress(event);
384
- }
385
- catch (e) {
386
- errorHandler("Error in onProgress callback: " + e, e);
387
- }
388
- }
389
- : undefined;
390
- const successHandler = (meshes, particleSystems, skeletons, animationGroups, transformNodes, geometries, lights, spriteManagers) => {
391
- scene.importedMeshesFiles.push(fileInfo.url);
392
- if (onSuccess) {
393
- try {
394
- onSuccess(meshes, particleSystems, skeletons, animationGroups, transformNodes, geometries, lights, spriteManagers);
395
- }
396
- catch (e) {
397
- errorHandler("Error in onSuccess callback: " + e, e);
398
- }
399
- }
400
- scene.removePendingData(loadingToken);
401
- };
402
- return await loadDataAsync(fileInfo, scene, (plugin, data, responseURL) => {
451
+ const progressHandler = wrapProgress(onProgress);
452
+ try {
453
+ const { plugin, data, responseURL } = await loadDataAsync(fileInfo, scene, progressHandler, pluginExtension ?? null, name, pluginOptions);
403
454
  if (plugin.rewriteRootURL) {
404
455
  fileInfo.rootUrl = plugin.rewriteRootURL(fileInfo.rootUrl, responseURL);
405
456
  }
406
- if (plugin.importMesh) {
407
- const syncedPlugin = plugin;
408
- const meshes = [];
409
- const particleSystems = [];
410
- const skeletons = [];
411
- if (!syncedPlugin.importMesh(meshNames, scene, data, fileInfo.rootUrl, meshes, particleSystems, skeletons, errorHandler)) {
412
- return;
413
- }
414
- scene.loadingPluginName = plugin.name;
415
- successHandler(meshes, particleSystems, skeletons, [], [], [], [], []);
416
- }
417
- else {
418
- const asyncedPlugin = plugin;
419
- asyncedPlugin
420
- .importMeshAsync(meshNames, scene, data, fileInfo.rootUrl, progressHandler, fileInfo.name)
421
- // eslint-disable-next-line github/no-then
422
- .then((result) => {
423
- scene.loadingPluginName = plugin.name;
424
- successHandler(result.meshes, result.particleSystems, result.skeletons, result.animationGroups, result.transformNodes, result.geometries, result.lights, result.spriteManagers);
425
- })
426
- // eslint-disable-next-line github/no-then
427
- .catch((error) => {
428
- errorHandler(error.message, error);
429
- });
430
- }
431
- }, progressHandler, errorHandler, disposeHandler, pluginExtension, name, pluginOptions);
432
- }
433
- async function importMeshAsyncCoreAsync(meshNames, rootUrl, sceneFilename, scene, onProgress, pluginExtension, name, pluginOptions) {
434
- return await new Promise((resolve, reject) => {
457
+ let result;
435
458
  try {
436
- importMeshAsync(meshNames, rootUrl, sceneFilename, scene, (meshes, particleSystems, skeletons, animationGroups, transformNodes, geometries, lights, spriteManagers) => {
437
- resolve({
438
- meshes: meshes,
439
- particleSystems: particleSystems,
440
- skeletons: skeletons,
441
- animationGroups: animationGroups,
442
- transformNodes: transformNodes,
443
- geometries: geometries,
444
- lights: lights,
445
- spriteManagers: spriteManagers,
446
- });
447
- }, onProgress, (scene, message, exception) => {
448
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
449
- reject(exception || new Error(message));
450
- }, pluginExtension, name, pluginOptions
451
- // eslint-disable-next-line github/no-then
452
- ).catch(reject);
459
+ result = await toAsyncPlugin(plugin, fileInfo).importMeshAsync(meshNames, scene, data, fileInfo.rootUrl, progressHandler, fileInfo.name);
453
460
  }
454
461
  catch (error) {
455
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
456
- reject(error);
462
+ throw toLoadError(fileInfo, error);
457
463
  }
458
- });
464
+ // eslint-disable-next-line require-atomic-updates
465
+ scene.loadingPluginName = plugin.name;
466
+ scene.importedMeshesFiles.push(fileInfo.url);
467
+ return result;
468
+ }
469
+ finally {
470
+ scene.removePendingData(loadingToken);
471
+ }
459
472
  }
460
473
  // This is the core implementation of load scene
461
- async function loadSceneImplAsync(rootUrl, sceneFilename = "", engine = EngineStore.LastCreatedEngine, onSuccess = null, onProgress = null, onError = null, pluginExtension = null, name = "", pluginOptions = {}) {
474
+ async function loadSceneCoreAsync(rootUrl, sceneFilename = "", engine = EngineStore.LastCreatedEngine, onProgress, pluginExtension, name = "", pluginOptions = {}) {
462
475
  if (!engine) {
463
- Tools.Error("No engine available");
464
- return;
476
+ throw new Error("No engine available");
477
+ }
478
+ const scene = new Scene(engine);
479
+ try {
480
+ await appendSceneCoreAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name, pluginOptions);
465
481
  }
466
- await appendSceneImplAsync(rootUrl, sceneFilename, new Scene(engine), onSuccess, onProgress, onError, pluginExtension, name, pluginOptions);
482
+ catch (error) {
483
+ // The scene was created here, so dispose it on failure to avoid leaking the partially loaded scene.
484
+ scene.dispose();
485
+ throw error;
486
+ }
487
+ return scene;
467
488
  }
468
489
  /**
469
490
  * Load a scene
@@ -474,7 +495,7 @@ async function loadSceneImplAsync(rootUrl, sceneFilename = "", engine = EngineSt
474
495
  */
475
496
  export async function LoadSceneAsync(source, engine, options) {
476
497
  const { rootUrl = "", onProgress, pluginExtension, name, pluginOptions } = options ?? {};
477
- return await loadSceneSharedAsync(rootUrl, source, engine, onProgress, pluginExtension, name, pluginOptions);
498
+ return await loadSceneCoreAsync(rootUrl, source, engine, onProgress, pluginExtension, name, pluginOptions);
478
499
  }
479
500
  /**
480
501
  * Load a scene
@@ -487,33 +508,17 @@ export async function LoadSceneAsync(source, engine, options) {
487
508
  export async function loadSceneAsync(source, engine, options) {
488
509
  return await LoadSceneAsync(source, engine, options);
489
510
  }
490
- // This function is shared between the new module level loadSceneAsync and the legacy SceneLoader.LoadAsync
491
- async function loadSceneSharedAsync(rootUrl, sceneFilename, engine, onProgress, pluginExtension, name, pluginOptions) {
492
- return await new Promise((resolve, reject) => {
493
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
494
- loadSceneImplAsync(rootUrl, sceneFilename, engine, (scene) => {
495
- resolve(scene);
496
- }, onProgress, (scene, message, exception) => {
497
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
498
- reject(exception || new Error(message));
499
- }, pluginExtension, name, pluginOptions);
500
- });
501
- }
502
511
  // This is the core implementation of append scene
503
- async function appendSceneImplAsync(rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, onSuccess = null, onProgress = null, onError = null, pluginExtension = null, name = "", pluginOptions = {}) {
512
+ async function appendSceneCoreAsync(rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, onProgress, pluginExtension, name = "", pluginOptions = {}) {
504
513
  if (!scene) {
505
- Logger.Error("No scene available to append to");
506
- return null;
514
+ throw new Error("No scene available to append to");
507
515
  }
508
516
  const fileInfo = GetFileInfo(rootUrl, sceneFilename);
509
517
  if (!fileInfo) {
510
- return null;
518
+ throw new Error("Cannot load file: a valid scene filename or root url was not provided.");
511
519
  }
512
520
  const loadingToken = {};
513
521
  scene.addPendingData(loadingToken);
514
- const disposeHandler = () => {
515
- scene.removePendingData(loadingToken);
516
- };
517
522
  if (SceneLoaderFlags.ShowLoadingScreen && !showingLoadingScreen) {
518
523
  showingLoadingScreen = true;
519
524
  scene.getEngine().displayLoadingUI();
@@ -522,62 +527,22 @@ async function appendSceneImplAsync(rootUrl, sceneFilename = "", scene = EngineS
522
527
  showingLoadingScreen = false;
523
528
  });
524
529
  }
525
- const errorHandler = (message, exception) => {
526
- const errorMessage = formatErrorMessage(fileInfo, message, exception);
527
- if (onError) {
528
- onError(scene, errorMessage, new RuntimeError(errorMessage, ErrorCodes.SceneLoaderError, exception));
529
- }
530
- else {
531
- Logger.Error(errorMessage);
532
- // should the exception be thrown?
533
- }
534
- disposeHandler();
535
- };
536
- const progressHandler = onProgress
537
- ? (event) => {
538
- try {
539
- onProgress(event);
540
- }
541
- catch (e) {
542
- errorHandler("Error in onProgress callback", e);
543
- }
530
+ const progressHandler = wrapProgress(onProgress);
531
+ try {
532
+ const { plugin, data } = await loadDataAsync(fileInfo, scene, progressHandler, pluginExtension ?? null, name, pluginOptions);
533
+ try {
534
+ await toAsyncPlugin(plugin, fileInfo).loadAsync(scene, data, fileInfo.rootUrl, progressHandler, fileInfo.name);
544
535
  }
545
- : undefined;
546
- const successHandler = () => {
547
- if (onSuccess) {
548
- try {
549
- onSuccess(scene);
550
- }
551
- catch (e) {
552
- errorHandler("Error in onSuccess callback", e);
553
- }
536
+ catch (error) {
537
+ throw toLoadError(fileInfo, error);
554
538
  }
539
+ // eslint-disable-next-line require-atomic-updates
540
+ scene.loadingPluginName = plugin.name;
541
+ return scene;
542
+ }
543
+ finally {
555
544
  scene.removePendingData(loadingToken);
556
- };
557
- return await loadDataAsync(fileInfo, scene, (plugin, data) => {
558
- if (plugin.load) {
559
- const syncedPlugin = plugin;
560
- if (!syncedPlugin.load(scene, data, fileInfo.rootUrl, errorHandler)) {
561
- return;
562
- }
563
- scene.loadingPluginName = plugin.name;
564
- successHandler();
565
- }
566
- else {
567
- const asyncedPlugin = plugin;
568
- asyncedPlugin
569
- .loadAsync(scene, data, fileInfo.rootUrl, progressHandler, fileInfo.name)
570
- // eslint-disable-next-line github/no-then
571
- .then(() => {
572
- scene.loadingPluginName = plugin.name;
573
- successHandler();
574
- })
575
- // eslint-disable-next-line github/no-then
576
- .catch((error) => {
577
- errorHandler(error.message, error);
578
- });
579
- }
580
- }, progressHandler, errorHandler, disposeHandler, pluginExtension, name, pluginOptions);
545
+ }
581
546
  }
582
547
  /**
583
548
  * Append a scene
@@ -588,7 +553,7 @@ async function appendSceneImplAsync(rootUrl, sceneFilename = "", scene = EngineS
588
553
  */
589
554
  export async function AppendSceneAsync(source, scene, options) {
590
555
  const { rootUrl = "", onProgress, pluginExtension, name, pluginOptions } = options ?? {};
591
- await appendSceneSharedAsync(rootUrl, source, scene, onProgress, pluginExtension, name, pluginOptions);
556
+ await appendSceneCoreAsync(rootUrl, source, scene, onProgress, pluginExtension, name, pluginOptions);
592
557
  }
593
558
  /**
594
559
  * Append a scene
@@ -601,102 +566,39 @@ export async function AppendSceneAsync(source, scene, options) {
601
566
  export async function appendSceneAsync(source, scene, options) {
602
567
  return await AppendSceneAsync(source, scene, options);
603
568
  }
604
- // This function is shared between the new module level appendSceneAsync and the legacy SceneLoader.AppendAsync
605
- async function appendSceneSharedAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name, pluginOptions) {
606
- return await new Promise((resolve, reject) => {
607
- try {
608
- appendSceneImplAsync(rootUrl, sceneFilename, scene, (scene) => {
609
- resolve(scene);
610
- }, onProgress, (scene, message, exception) => {
611
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
612
- reject(exception || new Error(message));
613
- }, pluginExtension, name, pluginOptions
614
- // eslint-disable-next-line github/no-then
615
- ).catch(reject);
616
- }
617
- catch (error) {
618
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
619
- reject(error);
620
- }
621
- });
622
- }
623
569
  // This is the core implementation of load asset container
624
- async function loadAssetContainerImplAsync(rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, onSuccess = null, onProgress = null, onError = null, pluginExtension = null, name = "", pluginOptions = {}) {
570
+ async function loadAssetContainerCoreAsync(rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, onProgress, pluginExtension, name = "", pluginOptions = {}) {
625
571
  if (!scene) {
626
- Logger.Error("No scene available to load asset container to");
627
- return null;
572
+ throw new Error("No scene available to load asset container to");
628
573
  }
629
574
  const fileInfo = GetFileInfo(rootUrl, sceneFilename);
630
575
  if (!fileInfo) {
631
- return null;
576
+ throw new Error("Cannot load file: a valid scene filename or root url was not provided.");
632
577
  }
633
578
  const loadingToken = {};
634
579
  scene.addPendingData(loadingToken);
635
- const disposeHandler = () => {
636
- scene.removePendingData(loadingToken);
637
- };
638
- const errorHandler = (message, exception) => {
639
- const errorMessage = formatErrorMessage(fileInfo, message, exception);
640
- if (onError) {
641
- onError(scene, errorMessage, new RuntimeError(errorMessage, ErrorCodes.SceneLoaderError, exception));
642
- }
643
- else {
644
- Logger.Error(errorMessage);
645
- // should the exception be thrown?
646
- }
647
- disposeHandler();
648
- };
649
- const progressHandler = onProgress
650
- ? (event) => {
651
- try {
652
- onProgress(event);
653
- }
654
- catch (e) {
655
- errorHandler("Error in onProgress callback", e);
656
- }
580
+ const progressHandler = wrapProgress(onProgress);
581
+ try {
582
+ const { plugin, data } = await loadDataAsync(fileInfo, scene, progressHandler, pluginExtension ?? null, name, pluginOptions);
583
+ const asyncPlugin = toAsyncPlugin(plugin, fileInfo);
584
+ if (!asyncPlugin.loadAssetContainerAsync) {
585
+ throw createLoadError(fileInfo, loadAssetContainerNotSupportedMessage);
586
+ }
587
+ let assetContainer;
588
+ try {
589
+ assetContainer = await asyncPlugin.loadAssetContainerAsync(scene, data, fileInfo.rootUrl, progressHandler, fileInfo.name);
657
590
  }
658
- : undefined;
659
- const successHandler = (assets) => {
660
- if (onSuccess) {
661
- try {
662
- onSuccess(assets);
663
- }
664
- catch (e) {
665
- errorHandler("Error in onSuccess callback", e);
666
- }
591
+ catch (error) {
592
+ throw toLoadError(fileInfo, error);
667
593
  }
594
+ assetContainer.populateRootNodes();
595
+ // eslint-disable-next-line require-atomic-updates
596
+ scene.loadingPluginName = plugin.name;
597
+ return assetContainer;
598
+ }
599
+ finally {
668
600
  scene.removePendingData(loadingToken);
669
- };
670
- return await loadDataAsync(fileInfo, scene, (plugin, data) => {
671
- if (plugin.loadAssetContainer) {
672
- const syncedPlugin = plugin;
673
- const assetContainer = syncedPlugin.loadAssetContainer(scene, data, fileInfo.rootUrl, errorHandler);
674
- if (!assetContainer) {
675
- return;
676
- }
677
- assetContainer.populateRootNodes();
678
- scene.loadingPluginName = plugin.name;
679
- successHandler(assetContainer);
680
- }
681
- else if (plugin.loadAssetContainerAsync) {
682
- const asyncedPlugin = plugin;
683
- asyncedPlugin
684
- .loadAssetContainerAsync(scene, data, fileInfo.rootUrl, progressHandler, fileInfo.name)
685
- // eslint-disable-next-line github/no-then
686
- .then((assetContainer) => {
687
- assetContainer.populateRootNodes();
688
- scene.loadingPluginName = plugin.name;
689
- successHandler(assetContainer);
690
- })
691
- // eslint-disable-next-line github/no-then
692
- .catch((error) => {
693
- errorHandler(error.message, error);
694
- });
695
- }
696
- else {
697
- errorHandler("LoadAssetContainer is not supported by this plugin. Plugin did not provide a loadAssetContainer or loadAssetContainerAsync method.");
698
- }
699
- }, progressHandler, errorHandler, disposeHandler, pluginExtension, name, pluginOptions);
601
+ }
700
602
  }
701
603
  /**
702
604
  * Load a scene into an asset container
@@ -707,7 +609,7 @@ async function loadAssetContainerImplAsync(rootUrl, sceneFilename = "", scene =
707
609
  */
708
610
  export async function LoadAssetContainerAsync(source, scene, options) {
709
611
  const { rootUrl = "", onProgress, pluginExtension, name, pluginOptions } = options ?? {};
710
- return await loadAssetContainerSharedAsync(rootUrl, source, scene, onProgress, pluginExtension, name, pluginOptions);
612
+ return await loadAssetContainerCoreAsync(rootUrl, source, scene, onProgress, pluginExtension, name, pluginOptions);
711
613
  }
712
614
  /**
713
615
  * Load a scene into an asset container
@@ -720,30 +622,10 @@ export async function LoadAssetContainerAsync(source, scene, options) {
720
622
  export async function loadAssetContainerAsync(source, scene, options) {
721
623
  return await LoadAssetContainerAsync(source, scene, options);
722
624
  }
723
- // This function is shared between the new module level loadAssetContainerAsync and the legacy SceneLoader.LoadAssetContainerAsync
724
- async function loadAssetContainerSharedAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name, pluginOptions) {
725
- return await new Promise((resolve, reject) => {
726
- try {
727
- loadAssetContainerImplAsync(rootUrl, sceneFilename, scene, (assets) => {
728
- resolve(assets);
729
- }, onProgress, (scene, message, exception) => {
730
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
731
- reject(exception || new Error(message));
732
- }, pluginExtension, name, pluginOptions
733
- // eslint-disable-next-line github/no-then
734
- ).catch(reject);
735
- }
736
- catch (error) {
737
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
738
- reject(error);
739
- }
740
- });
741
- }
742
625
  // This is the core implementation of import animations
743
- async function importAnimationsImplAsync(rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, overwriteAnimations = true, animationGroupLoadingMode = 0 /* SceneLoaderAnimationGroupLoadingMode.Clean */, targetConverter = null, onSuccess = null, onProgress = null, onError = null, pluginExtension = null, name = "", pluginOptions = {}) {
626
+ async function importAnimationsCoreAsync(rootUrl, sceneFilename = "", scene = EngineStore.LastCreatedScene, overwriteAnimations = true, animationGroupLoadingMode = 0 /* SceneLoaderAnimationGroupLoadingMode.Clean */, targetConverter = null, onProgress, pluginExtension, name = "", pluginOptions = {}) {
744
627
  if (!scene) {
745
- Logger.Error("No scene available to load animations to");
746
- return;
628
+ throw new Error("No scene available to load animations to");
747
629
  }
748
630
  if (overwriteAnimations) {
749
631
  // Reset, stop and dispose all animations before loading new ones
@@ -785,20 +667,14 @@ async function importAnimationsImplAsync(rootUrl, sceneFilename = "", scene = En
785
667
  // nothing to do
786
668
  break;
787
669
  default:
788
- Logger.Error("Unknown animation group loading mode value '" + animationGroupLoadingMode + "'");
789
- return;
670
+ throw new Error("Unknown animation group loading mode value '" + animationGroupLoadingMode + "'");
790
671
  }
791
672
  }
792
673
  const startingIndexForNewAnimatables = scene.animatables.length;
793
- const onAssetContainerLoaded = (container) => {
794
- container.mergeAnimationsTo(scene, scene.animatables.slice(startingIndexForNewAnimatables), targetConverter);
795
- container.dispose();
796
- scene.onAnimationFileImportedObservable.notifyObservers(scene);
797
- if (onSuccess) {
798
- onSuccess(scene);
799
- }
800
- };
801
- await loadAssetContainerImplAsync(rootUrl, sceneFilename, scene, onAssetContainerLoaded, onProgress, onError, pluginExtension, name, pluginOptions);
674
+ const container = await loadAssetContainerCoreAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name, pluginOptions);
675
+ container.mergeAnimationsTo(scene, scene.animatables.slice(startingIndexForNewAnimatables), targetConverter);
676
+ container.dispose();
677
+ scene.onAnimationFileImportedObservable.notifyObservers(scene);
802
678
  }
803
679
  /**
804
680
  * Import animations from a file into a scene
@@ -809,7 +685,7 @@ async function importAnimationsImplAsync(rootUrl, sceneFilename = "", scene = En
809
685
  */
810
686
  export async function ImportAnimationsAsync(source, scene, options) {
811
687
  const { rootUrl = "", overwriteAnimations, animationGroupLoadingMode, targetConverter, onProgress, pluginExtension, name, pluginOptions } = options ?? {};
812
- await importAnimationsSharedAsync(rootUrl, source, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onProgress, pluginExtension, name, pluginOptions);
688
+ await importAnimationsCoreAsync(rootUrl, source, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onProgress, pluginExtension, name, pluginOptions);
813
689
  }
814
690
  /**
815
691
  * Import animations from a file into a scene
@@ -822,25 +698,6 @@ export async function ImportAnimationsAsync(source, scene, options) {
822
698
  export async function importAnimationsAsync(source, scene, options) {
823
699
  return await ImportAnimationsAsync(source, scene, options);
824
700
  }
825
- // This function is shared between the new module level importAnimationsAsync and the legacy SceneLoader.ImportAnimationsAsync
826
- async function importAnimationsSharedAsync(rootUrl, sceneFilename, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onProgress, pluginExtension, name, pluginOptions) {
827
- return await new Promise((resolve, reject) => {
828
- try {
829
- importAnimationsImplAsync(rootUrl, sceneFilename, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, (scene) => {
830
- resolve(scene);
831
- }, onProgress, (scene, message, exception) => {
832
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
833
- reject(exception || new Error(message));
834
- }, pluginExtension, name, pluginOptions
835
- // eslint-disable-next-line github/no-then
836
- ).catch(reject);
837
- }
838
- catch (error) {
839
- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
840
- reject(error);
841
- }
842
- });
843
- }
844
701
  /**
845
702
  * Class used to load scene from various file formats using registered plugins
846
703
  * @see https://doc.babylonjs.com/features/featuresDeepDive/importers/loadingFileTypes
@@ -933,8 +790,16 @@ export class SceneLoader {
933
790
  * @deprecated Please use the module level {@link ImportMeshAsync} instead
934
791
  */
935
792
  static ImportMesh(meshNames, rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension, name, pluginOptions) {
936
- // eslint-disable-next-line github/no-then
937
- importMeshAsync(meshNames, rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension, name, pluginOptions).catch((error) => onError?.(EngineStore.LastCreatedScene, error?.message, error));
793
+ const reportScene = scene ?? EngineStore.LastCreatedScene;
794
+ void (async () => {
795
+ try {
796
+ const result = await importMeshCoreAsync(meshNames, rootUrl, sceneFilename, scene, onProgress, pluginExtension, name, pluginOptions);
797
+ onSuccess?.(result.meshes, result.particleSystems, result.skeletons, result.animationGroups, result.transformNodes, result.geometries, result.lights, result.spriteManagers);
798
+ }
799
+ catch (error) {
800
+ reportLegacyLoadError(onError, reportScene, error);
801
+ }
802
+ })();
938
803
  }
939
804
  /**
940
805
  * Import meshes into a scene
@@ -949,7 +814,7 @@ export class SceneLoader {
949
814
  * @deprecated Please use the module level {@link ImportMeshAsync} instead
950
815
  */
951
816
  static async ImportMeshAsync(meshNames, rootUrl, sceneFilename, scene, onProgress, pluginExtension, name) {
952
- return await importMeshAsyncCoreAsync(meshNames, rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
817
+ return await importMeshCoreAsync(meshNames, rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
953
818
  }
954
819
  /**
955
820
  * Load a scene
@@ -964,8 +829,15 @@ export class SceneLoader {
964
829
  * @deprecated Please use the module level {@link LoadSceneAsync} instead
965
830
  */
966
831
  static Load(rootUrl, sceneFilename, engine, onSuccess, onProgress, onError, pluginExtension, name) {
967
- // eslint-disable-next-line github/no-then
968
- loadSceneImplAsync(rootUrl, sceneFilename, engine, onSuccess, onProgress, onError, pluginExtension, name).catch((error) => onError?.(EngineStore.LastCreatedScene, error?.message, error));
832
+ void (async () => {
833
+ try {
834
+ const scene = await loadSceneCoreAsync(rootUrl, sceneFilename, engine, onProgress, pluginExtension, name);
835
+ onSuccess?.(scene);
836
+ }
837
+ catch (error) {
838
+ reportLegacyLoadError(onError, EngineStore.LastCreatedScene, error);
839
+ }
840
+ })();
969
841
  }
970
842
  /**
971
843
  * Load a scene
@@ -979,7 +851,7 @@ export class SceneLoader {
979
851
  * @deprecated Please use the module level {@link LoadSceneAsync} instead
980
852
  */
981
853
  static async LoadAsync(rootUrl, sceneFilename, engine, onProgress, pluginExtension, name) {
982
- return await loadSceneSharedAsync(rootUrl, sceneFilename, engine, onProgress, pluginExtension, name);
854
+ return await loadSceneCoreAsync(rootUrl, sceneFilename, engine, onProgress, pluginExtension, name);
983
855
  }
984
856
  /**
985
857
  * Append a scene
@@ -994,8 +866,16 @@ export class SceneLoader {
994
866
  * @deprecated Please use the module level {@link AppendSceneAsync} instead
995
867
  */
996
868
  static Append(rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension, name) {
997
- // eslint-disable-next-line github/no-then
998
- appendSceneImplAsync(rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension, name).catch((error) => onError?.((scene ?? EngineStore.LastCreatedScene), error?.message, error));
869
+ const reportScene = scene ?? EngineStore.LastCreatedScene;
870
+ void (async () => {
871
+ try {
872
+ const appendedScene = await appendSceneCoreAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
873
+ onSuccess?.(appendedScene);
874
+ }
875
+ catch (error) {
876
+ reportLegacyLoadError(onError, reportScene, error);
877
+ }
878
+ })();
999
879
  }
1000
880
  /**
1001
881
  * Append a scene
@@ -1009,7 +889,7 @@ export class SceneLoader {
1009
889
  * @deprecated Please use the module level {@link AppendSceneAsync} instead
1010
890
  */
1011
891
  static async AppendAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name) {
1012
- return await appendSceneSharedAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
892
+ return await appendSceneCoreAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
1013
893
  }
1014
894
  /**
1015
895
  * Load a scene into an asset container
@@ -1024,8 +904,16 @@ export class SceneLoader {
1024
904
  * @deprecated Please use the module level {@link LoadAssetContainerAsync} instead
1025
905
  */
1026
906
  static LoadAssetContainer(rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension, name) {
1027
- // eslint-disable-next-line github/no-then
1028
- loadAssetContainerImplAsync(rootUrl, sceneFilename, scene, onSuccess, onProgress, onError, pluginExtension, name).catch((error) => onError?.((scene ?? EngineStore.LastCreatedScene), error?.message, error));
907
+ const reportScene = scene ?? EngineStore.LastCreatedScene;
908
+ void (async () => {
909
+ try {
910
+ const assets = await loadAssetContainerCoreAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
911
+ onSuccess?.(assets);
912
+ }
913
+ catch (error) {
914
+ reportLegacyLoadError(onError, reportScene, error);
915
+ }
916
+ })();
1029
917
  }
1030
918
  /**
1031
919
  * Load a scene into an asset container
@@ -1039,7 +927,7 @@ export class SceneLoader {
1039
927
  * @deprecated Please use the module level {@link LoadAssetContainerAsync} instead
1040
928
  */
1041
929
  static async LoadAssetContainerAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name) {
1042
- return await loadAssetContainerSharedAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
930
+ return await loadAssetContainerCoreAsync(rootUrl, sceneFilename, scene, onProgress, pluginExtension, name);
1043
931
  }
1044
932
  /**
1045
933
  * Import animations from a file into a scene
@@ -1057,9 +945,16 @@ export class SceneLoader {
1057
945
  * @deprecated Please use the module level {@link ImportAnimationsAsync} instead
1058
946
  */
1059
947
  static ImportAnimations(rootUrl, sceneFilename, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onSuccess, onProgress, onError, pluginExtension, name) {
1060
- importAnimationsImplAsync(rootUrl, sceneFilename, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onSuccess, onProgress, onError, pluginExtension, name
1061
- // eslint-disable-next-line github/no-then
1062
- ).catch((error) => onError?.((scene ?? EngineStore.LastCreatedScene), error?.message, error));
948
+ const reportScene = scene ?? EngineStore.LastCreatedScene;
949
+ void (async () => {
950
+ try {
951
+ await importAnimationsCoreAsync(rootUrl, sceneFilename, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onProgress, pluginExtension, name);
952
+ onSuccess?.(reportScene);
953
+ }
954
+ catch (error) {
955
+ reportLegacyLoadError(onError, reportScene, error);
956
+ }
957
+ })();
1063
958
  }
1064
959
  /**
1065
960
  * Import animations from a file into a scene
@@ -1082,7 +977,9 @@ export class SceneLoader {
1082
977
  onSuccess, onProgress,
1083
978
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1084
979
  onError, pluginExtension, name) {
1085
- return await importAnimationsSharedAsync(rootUrl, sceneFilename, scene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onProgress, pluginExtension, name);
980
+ const targetScene = scene ?? EngineStore.LastCreatedScene;
981
+ await importAnimationsCoreAsync(rootUrl, sceneFilename, targetScene, overwriteAnimations, animationGroupLoadingMode, targetConverter, onProgress, pluginExtension, name);
982
+ return targetScene;
1086
983
  }
1087
984
  }
1088
985
  /**