@preference-sl/pref-viewer 2.14.0-beta.5 → 2.14.0-beta.6

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@preference-sl/pref-viewer",
3
- "version": "2.14.0-beta.5",
3
+ "version": "2.14.0-beta.6",
4
4
  "description": "Web Component to preview GLTF models with Babylon.js",
5
5
  "author": "Alex Moreno Palacio <amoreno@preference.es>",
6
6
  "scripts": {
@@ -114,7 +114,6 @@ export default class BabylonJSController {
114
114
  #options = {};
115
115
 
116
116
  #gltfResolver = null; // GLTFResolver instance
117
- #loadGeneration = 0; // incremented per #loadContainers call to discard stale deferred results
118
117
  #babylonJSAnimationController = null; // AnimationController instance
119
118
 
120
119
  #renderPipelines = {
@@ -2401,51 +2400,23 @@ export default class BabylonJSController {
2401
2400
 
2402
2401
  /**
2403
2402
  * Loads all asset containers (model, environment, materials, etc.) and adds them to the scene.
2404
- *
2405
- * Uses **two-phase progressive loading** when the environment container is pending:
2406
- * Phase 1 – Load model + materials, apply them, and start the render loop so the user sees
2407
- * the configured product immediately.
2408
- * Phase 2 The environment (scene with trees, walls, floor…) was already downloading in
2409
- * parallel. Once it resolves, briefly stop rendering, splice it in, reapply
2410
- * camera/IBL/visibility options, and restart.
2411
- *
2412
- * When the environment is *not* pending (e.g. only the model changed), the original
2413
- * single-phase behaviour is preserved — all containers settle immediately and are applied
2414
- * together.
2415
- *
2416
- * A generation counter (`#loadGeneration`) guards Phase 2: if a newer `load()` call starts
2417
- * while the environment is still downloading, the stale result is disposed instead of applied.
2418
- *
2419
- * @private
2420
- * @param {boolean} [force=false] - Bypass cached size/timestamp checks.
2421
- * @returns {Promise<{success: boolean, error: any}>}
2403
+ * @private
2404
+ * @returns {Promise<{success: boolean, error: any}>} Resolves to an object indicating if loading succeeded and any error encountered.
2405
+ * @description
2406
+ * Waits for all containers to load in parallel, then replaces or adds them to the scene as needed.
2407
+ * Applies material and camera options, sets wall/floor visibility, and initializes lights and shadows.
2408
+ * Returns an object with success status and error details.
2422
2409
  */
2423
2410
  async #loadContainers(force = false) {
2424
- const generation = ++this.#loadGeneration;
2425
2411
  this.#detachAnimationChangedListener();
2426
2412
  await this.#stopRender();
2427
2413
 
2428
2414
  let oldModelMetadata = { ...(this.#containers.model?.state?.metadata ?? {}) };
2429
2415
  let newModelMetadata = {};
2430
2416
 
2431
- // Kick off ALL container loads in parallel — the heavy environment download starts now.
2432
- const allLoadPromises = new Map();
2417
+ const promiseArray = [];
2433
2418
  Object.values(this.#containers).forEach((container) => {
2434
- allLoadPromises.set(container.state.name, this.#loadAssetContainer(container, force));
2435
- });
2436
-
2437
- // When the environment is pending (heavy scene geometry) we defer it to Phase 2 so
2438
- // the model can render first. Non-pending environments resolve immediately with
2439
- // [container, false] and are handled in Phase 1 like any other container.
2440
- const environmentPending = this.#containers.environment?.state?.isPending === true;
2441
- const priorityPromises = [];
2442
- let deferredPromise = null;
2443
- allLoadPromises.forEach((promise, name) => {
2444
- if (name === "environment" && environmentPending) {
2445
- deferredPromise = promise;
2446
- } else {
2447
- priorityPromises.push(promise);
2448
- }
2419
+ promiseArray.push(this.#loadAssetContainer(container, force));
2449
2420
  });
2450
2421
 
2451
2422
  let detail = {
@@ -2453,18 +2424,13 @@ export default class BabylonJSController {
2453
2424
  error: null,
2454
2425
  };
2455
2426
 
2456
- // ── Phase 1: Priority containers (model + materials) ────────────────────
2457
- await Promise.allSettled(priorityPromises)
2427
+ await Promise.allSettled(promiseArray)
2458
2428
  .then(async (values) => {
2459
2429
  // Scene may have been disposed (disconnectedCallback) while async loading was in
2460
2430
  // progress. Abort cleanly: #replaceContainer already guards the GPU calls, but
2461
2431
  // we skip the post-load option/visibility calls too to avoid further null-derefs.
2462
2432
  if (!this.#scene) {
2463
2433
  values.forEach((result) => { result.value?.[1]?.dispose(); });
2464
- if (deferredPromise) {
2465
- deferredPromise.then((r) => { r?.[1]?.dispose?.(); }).catch(() => {});
2466
- deferredPromise = null;
2467
- }
2468
2434
  return;
2469
2435
  }
2470
2436
  this.#disposeAnimationController();
@@ -2503,10 +2469,7 @@ export default class BabylonJSController {
2503
2469
  detail.error = error;
2504
2470
  })
2505
2471
  .finally(async () => {
2506
- if (!deferredPromise) {
2507
- // No deferred work — single-phase path (original behaviour).
2508
- this.#checkModelMetadata(oldModelMetadata, newModelMetadata);
2509
- }
2472
+ this.#checkModelMetadata(oldModelMetadata, newModelMetadata);
2510
2473
  this.#setMaxSimultaneousLights();
2511
2474
  this.#babylonJSAnimationController = new BabylonJSAnimationController(this.#containers.model.assetContainer);
2512
2475
  // Apply stored highlight settings so fresh page loads respect persisted state
@@ -2519,48 +2482,6 @@ export default class BabylonJSController {
2519
2482
  }
2520
2483
  await this.#startRender();
2521
2484
  });
2522
-
2523
- // ── Phase 2: Deferred environment (already downloading in parallel) ─────
2524
- if (deferredPromise) {
2525
- let deferredResult;
2526
- try {
2527
- deferredResult = await deferredPromise;
2528
- } catch (error) {
2529
- console.error("PrefViewer: failed to load environment progressively", error);
2530
- deferredResult = [this.#containers.environment, null];
2531
- }
2532
-
2533
- // A newer load() was triggered while we waited — discard stale results.
2534
- if (this.#loadGeneration !== generation) {
2535
- deferredResult?.[1]?.dispose?.();
2536
- return detail;
2537
- }
2538
-
2539
- if (this.#scene) {
2540
- const [container, assetContainer] = deferredResult;
2541
- if (assetContainer) {
2542
- this.#detachAnimationChangedListener();
2543
- await this.#stopRender();
2544
- this.#assetContainer_retagCameras(assetContainer);
2545
- this.#replaceContainer(container, assetContainer);
2546
- container.state.setSuccess(true);
2547
- this.#setOptions_Camera();
2548
- await this.#setOptions_IBL();
2549
- this.#setVisibilityOfWallAndFloorInModel();
2550
- this.#checkModelMetadata(oldModelMetadata, newModelMetadata);
2551
- this.#setMaxSimultaneousLights();
2552
- this.#babylonJSAnimationController = new BabylonJSAnimationController(this.#containers.model.assetContainer);
2553
- if (this.#babylonJSAnimationController?.hasAnimations?.()) {
2554
- this.#attachAnimationChangedListener();
2555
- }
2556
- await this.#startRender();
2557
- } else {
2558
- container.state.setSuccess(false);
2559
- this.#checkModelMetadata(oldModelMetadata, newModelMetadata);
2560
- }
2561
- }
2562
- }
2563
-
2564
2485
  return detail;
2565
2486
  }
2566
2487