@2112-lab/central-plant 0.3.55 → 0.3.57

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.
@@ -27361,13 +27361,15 @@ var EnvironmentManager = /*#__PURE__*/function () {
27361
27361
  return this.createSkybox();
27362
27362
  case 1:
27363
27363
  this.setupLighting();
27364
- _context4.n = 2;
27365
- return this.addTexturedGround();
27366
- case 2:
27367
- // await this.addBrickWalls()
27368
27364
  this.addHorizonFog();
27369
- console.log('Environment initialization completed');
27370
- case 3:
27365
+
27366
+ // 2. Add ground (synchronously adds basic mesh)
27367
+ // We do NOT await the texture loading here to speed up scene "Ready" state
27368
+ this.addTexturedGround().catch(function (err) {
27369
+ return console.warn('⚠️ Ground texture load failed:', err);
27370
+ });
27371
+ console.log('Environment initialization completed (textures loading in background)');
27372
+ case 2:
27371
27373
  return _context4.a(2);
27372
27374
  }
27373
27375
  }, _callee4, this);
@@ -34899,31 +34901,39 @@ var SceneOperationsManager = /*#__PURE__*/function () {
34899
34901
  component = this.sceneViewer;
34900
34902
  _context8.p = 1;
34901
34903
  defaultCentralPlantUrl = process.env.DEFAULT_CENTRAL_PLANT_URL;
34902
- _context8.n = 2;
34903
- return fetch(defaultCentralPlantUrl);
34904
+ console.log('🔍 [SceneOperations] Attempting loadScene with URL:', defaultCentralPlantUrl);
34905
+ if (defaultCentralPlantUrl) {
34906
+ _context8.n = 2;
34907
+ break;
34908
+ }
34909
+ console.log('ℹ️ [SceneOperations] No default scene URL provided, skipping automatic load');
34910
+ return _context8.a(2);
34904
34911
  case 2:
34905
- response = _context8.v;
34906
34912
  _context8.n = 3;
34907
- return response.json();
34913
+ return fetch(defaultCentralPlantUrl);
34908
34914
  case 3:
34915
+ response = _context8.v;
34916
+ _context8.n = 4;
34917
+ return response.json();
34918
+ case 4:
34909
34919
  data = _context8.v;
34910
34920
  // Store current scene data even for default scene
34911
34921
  component.currentSceneData = data;
34912
34922
 
34913
34923
  // Use the consolidated scene loading function (treat as imported to ensure consistent behavior)
34914
- _context8.n = 4;
34924
+ _context8.n = 5;
34915
34925
  return this.loadSceneFromData(data);
34916
- case 4:
34917
- _context8.n = 6;
34918
- break;
34919
34926
  case 5:
34920
- _context8.p = 5;
34927
+ _context8.n = 7;
34928
+ break;
34929
+ case 6:
34930
+ _context8.p = 6;
34921
34931
  _t4 = _context8.v;
34922
34932
  console.error('Error loading default scene:', _t4);
34923
- case 6:
34933
+ case 7:
34924
34934
  return _context8.a(2);
34925
34935
  }
34926
- }, _callee8, this, [[1, 5]]);
34936
+ }, _callee8, this, [[1, 6]]);
34927
34937
  }));
34928
34938
  function loadScene() {
34929
34939
  return _loadScene.apply(this, arguments);
@@ -41815,7 +41825,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
41815
41825
  * Initialize the CentralPlant manager
41816
41826
  *
41817
41827
  * @constructor
41818
- * @version 0.3.55
41828
+ * @version 0.3.57
41819
41829
  * @updated 2025-10-22
41820
41830
  *
41821
41831
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -44433,23 +44443,18 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
44433
44443
  /**
44434
44444
  * Initialize model preloading from component dictionary
44435
44445
  * @param {string} [basePath='/library/'] - Base path for both dictionary and models (can be local path or S3 URL)
44436
- * @returns {Promise<Object>} Preloading progress results
44437
- * @description Loads the component dictionary and preloads all models for better performance
44438
- * @example
44439
- * // Local files (default)
44440
- * await centralPlant.initializeModelPreloading()
44441
- *
44442
- * // S3 bucket
44443
- * await centralPlant.initializeModelPreloading('https://my-bucket.s3.amazonaws.com/library/')
44444
- *
44445
- * // Custom local path
44446
- * await centralPlant.initializeModelPreloading('/custom/assets/')
44446
+ * @param {Object} [options={}] - Optimization options
44447
+ * @param {boolean} [options.autoPreloadModels=true] - If false, only loads the dictionary and skips preloading GLBs (improves initial load)
44448
+ * @returns {Promise<Object>} Preloading progress results or dictionary summary
44447
44449
  */
44448
44450
  }, {
44449
44451
  key: "initializeModelPreloading",
44450
44452
  value: (function () {
44451
44453
  var _initializeModelPreloading = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
44452
44454
  var basePath,
44455
+ options,
44456
+ _options$autoPreloadM,
44457
+ autoPreloadModels,
44453
44458
  normalizedBasePath,
44454
44459
  dictionaryPath,
44455
44460
  modelsBasePath,
@@ -44463,6 +44468,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
44463
44468
  while (1) switch (_context10.n) {
44464
44469
  case 0:
44465
44470
  basePath = _args10.length > 0 && _args10[0] !== undefined ? _args10[0] : '/library/';
44471
+ options = _args10.length > 1 && _args10[1] !== undefined ? _args10[1] : {};
44472
+ _options$autoPreloadM = options.autoPreloadModels, autoPreloadModels = _options$autoPreloadM === void 0 ? true : _options$autoPreloadM;
44466
44473
  _context10.p = 1;
44467
44474
  // Ensure basePath ends with a slash
44468
44475
  normalizedBasePath = basePath.endsWith('/') ? basePath : "".concat(basePath, "/");
@@ -44472,6 +44479,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
44472
44479
  console.log("\uD83D\uDCC2 Base path: ".concat(normalizedBasePath));
44473
44480
  console.log("\uD83D\uDCDA Dictionary path: ".concat(dictionaryPath));
44474
44481
  console.log("\uFFFD Models path: ".concat(modelsBasePath));
44482
+ console.log("\u26A1 Auto-preload models: ".concat(autoPreloadModels));
44475
44483
 
44476
44484
  // Load the component dictionary
44477
44485
  _context10.n = 2;
@@ -44488,25 +44496,39 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
44488
44496
  return response.json();
44489
44497
  case 4:
44490
44498
  componentDictionary = _context10.v;
44491
- console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary));
44499
+ console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary).length);
44492
44500
 
44493
- // Start preloading all models with the specified base path
44501
+ // Get the model preloader utility
44494
44502
  _modelPreloader2 = this.getUtility('modelPreloader');
44495
- _context10.n = 5;
44496
- return _modelPreloader2.preloadAllModels(componentDictionary, modelsBasePath);
44503
+ if (autoPreloadModels) {
44504
+ _context10.n = 5;
44505
+ break;
44506
+ }
44507
+ console.log('⚡ Lazy loading enabled: skipping automatic GLB preloading');
44508
+ // We still need to give the preloader the dictionary and base path for later use
44509
+ _modelPreloader2.componentDictionary = componentDictionary;
44510
+ _modelPreloader2.setModelsBasePath(modelsBasePath);
44511
+ return _context10.a(2, {
44512
+ successCount: 0,
44513
+ failureCount: 0,
44514
+ dictionaryCount: Object.keys(componentDictionary).length
44515
+ });
44497
44516
  case 5:
44517
+ _context10.n = 6;
44518
+ return _modelPreloader2.preloadAllModels(componentDictionary, modelsBasePath);
44519
+ case 6:
44498
44520
  progress = _context10.v;
44499
44521
  console.log('🎉 Model preloading completed:', progress);
44500
44522
  return _context10.a(2, progress);
44501
- case 6:
44502
- _context10.p = 6;
44523
+ case 7:
44524
+ _context10.p = 7;
44503
44525
  _t3 = _context10.v;
44504
44526
  console.error('❌ Failed to initialize model preloading:', _t3);
44505
44527
  throw _t3;
44506
- case 7:
44528
+ case 8:
44507
44529
  return _context10.a(2);
44508
44530
  }
44509
- }, _callee10, this, [[1, 6]]);
44531
+ }, _callee10, this, [[1, 7]]);
44510
44532
  }));
44511
44533
  function initializeModelPreloading() {
44512
44534
  return _initializeModelPreloading.apply(this, arguments);
@@ -45047,7 +45069,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
45047
45069
  key: "initializeScene",
45048
45070
  value: (function () {
45049
45071
  var _initializeScene = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
45050
- var initStart, phase1Start, phase1Time, phase2Start, parallelInitPromises, phase2Time, phase3Start, sceneSetupPromises, phase3Time, phase4Start, phase4Time, phase5Start, phase5Time, initTime, _t2;
45072
+ var initStart, phase1Start, phase1Time, phase2Start, parallelInitPromises, phase2Time, phase3Start, skipDefaultLoad, sceneSetupPromises, phase3Time, phase4Start, phase4Time, phase5Start, phase5Time, initTime, _t2;
45051
45073
  return _regenerator().w(function (_context2) {
45052
45074
  while (1) switch (_context2.n) {
45053
45075
  case 0:
@@ -45095,7 +45117,11 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
45095
45117
  // Phase 3: Scene loading and transform setup (can be parallelized)
45096
45118
  phase3Start = performance.now();
45097
45119
  console.log('📍 Phase 3: Scene loading and transform setup...');
45098
- sceneSetupPromises = [this.loadScene().catch(function (error) {
45120
+
45121
+ // Explicitly check if we should skip the default load
45122
+ skipDefaultLoad = process.env.SKIP_DEFAULT_LOAD === 'true';
45123
+ console.log("\uD83D\uDD0D [SceneViewer] skipDefaultLoad: ".concat(skipDefaultLoad));
45124
+ sceneSetupPromises = [skipDefaultLoad ? Promise.resolve() : this.loadScene().catch(function (error) {
45099
45125
  console.error('❌ Scene loading failed:', error);
45100
45126
  throw error;
45101
45127
  }), this.setupTransformControls().catch(function (error) {
@@ -46472,7 +46498,7 @@ var CacheManager = /*#__PURE__*/function () {
46472
46498
  key: "execute",
46473
46499
  value: (function () {
46474
46500
  var _execute = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(_ref) {
46475
- var cacheKey, sourceKey, expiryMs, fetcher, processor, _ref$metadata, metadata, cacheName, cache, cachedResponse, cachedTime, age, result, fetchResult, blobOrJson, contentType, contentSize, responseBody, headers, cacheResponse, fallbackResult, _t2;
46501
+ var cacheKey, sourceKey, expiryMs, fetcher, processor, _ref$metadata, metadata, cacheName, cache, cachedResponse, cachedTime, age, result, fetchResult, blobOrJson, error, contentType, contentSize, responseBody, headers, cacheResponse, fallbackResult, _t2;
46476
46502
  return _regenerator().w(function (_context4) {
46477
46503
  while (1) switch (_context4.n) {
46478
46504
  case 0:
@@ -46525,7 +46551,9 @@ var CacheManager = /*#__PURE__*/function () {
46525
46551
  _context4.n = 9;
46526
46552
  break;
46527
46553
  }
46528
- throw new Error("Fetch failed: ".concat(fetchResult.status));
46554
+ error = new Error("Fetch failed: ".concat(fetchResult.status)); // Do not retry 404s - the file is genuinely missing
46555
+ if (fetchResult.status === 404) error.noRetry = true;
46556
+ throw error;
46529
46557
  case 9:
46530
46558
  _context4.n = 10;
46531
46559
  return processor(fetchResult.clone());
@@ -46576,20 +46604,29 @@ var CacheManager = /*#__PURE__*/function () {
46576
46604
  case 15:
46577
46605
  fallbackResult = _context4.v;
46578
46606
  if (!(fallbackResult instanceof Response)) {
46607
+ _context4.n = 18;
46608
+ break;
46609
+ }
46610
+ if (fallbackResult.ok) {
46579
46611
  _context4.n = 16;
46580
46612
  break;
46581
46613
  }
46582
- return _context4.a(2, processor(fallbackResult));
46614
+ throw new Error("Fallback fetch failed: ".concat(fallbackResult.status));
46583
46615
  case 16:
46584
- return _context4.a(2, fallbackResult);
46616
+ _context4.n = 17;
46617
+ return processor(fallbackResult);
46585
46618
  case 17:
46586
- _context4.p = 17;
46619
+ return _context4.a(2, _context4.v);
46620
+ case 18:
46621
+ return _context4.a(2, fallbackResult);
46622
+ case 19:
46623
+ _context4.p = 19;
46587
46624
  _context4.v;
46588
46625
  throw _t2;
46589
- case 18:
46626
+ case 20:
46590
46627
  return _context4.a(2);
46591
46628
  }
46592
- }, _callee4, this, [[14, 17], [1, 13]]);
46629
+ }, _callee4, this, [[14, 19], [1, 13]]);
46593
46630
  }));
46594
46631
  function execute(_x2) {
46595
46632
  return _execute.apply(this, arguments);
@@ -58,7 +58,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
58
58
  * Initialize the CentralPlant manager
59
59
  *
60
60
  * @constructor
61
- * @version 0.3.55
61
+ * @version 0.3.57
62
62
  * @updated 2025-10-22
63
63
  *
64
64
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -2676,23 +2676,18 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2676
2676
  /**
2677
2677
  * Initialize model preloading from component dictionary
2678
2678
  * @param {string} [basePath='/library/'] - Base path for both dictionary and models (can be local path or S3 URL)
2679
- * @returns {Promise<Object>} Preloading progress results
2680
- * @description Loads the component dictionary and preloads all models for better performance
2681
- * @example
2682
- * // Local files (default)
2683
- * await centralPlant.initializeModelPreloading()
2684
- *
2685
- * // S3 bucket
2686
- * await centralPlant.initializeModelPreloading('https://my-bucket.s3.amazonaws.com/library/')
2687
- *
2688
- * // Custom local path
2689
- * await centralPlant.initializeModelPreloading('/custom/assets/')
2679
+ * @param {Object} [options={}] - Optimization options
2680
+ * @param {boolean} [options.autoPreloadModels=true] - If false, only loads the dictionary and skips preloading GLBs (improves initial load)
2681
+ * @returns {Promise<Object>} Preloading progress results or dictionary summary
2690
2682
  */
2691
2683
  }, {
2692
2684
  key: "initializeModelPreloading",
2693
2685
  value: (function () {
2694
2686
  var _initializeModelPreloading = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee10() {
2695
2687
  var basePath,
2688
+ options,
2689
+ _options$autoPreloadM,
2690
+ autoPreloadModels,
2696
2691
  normalizedBasePath,
2697
2692
  dictionaryPath,
2698
2693
  modelsBasePath,
@@ -2706,6 +2701,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2706
2701
  while (1) switch (_context10.n) {
2707
2702
  case 0:
2708
2703
  basePath = _args10.length > 0 && _args10[0] !== undefined ? _args10[0] : '/library/';
2704
+ options = _args10.length > 1 && _args10[1] !== undefined ? _args10[1] : {};
2705
+ _options$autoPreloadM = options.autoPreloadModels, autoPreloadModels = _options$autoPreloadM === void 0 ? true : _options$autoPreloadM;
2709
2706
  _context10.p = 1;
2710
2707
  // Ensure basePath ends with a slash
2711
2708
  normalizedBasePath = basePath.endsWith('/') ? basePath : "".concat(basePath, "/");
@@ -2715,6 +2712,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2715
2712
  console.log("\uD83D\uDCC2 Base path: ".concat(normalizedBasePath));
2716
2713
  console.log("\uD83D\uDCDA Dictionary path: ".concat(dictionaryPath));
2717
2714
  console.log("\uFFFD Models path: ".concat(modelsBasePath));
2715
+ console.log("\u26A1 Auto-preload models: ".concat(autoPreloadModels));
2718
2716
 
2719
2717
  // Load the component dictionary
2720
2718
  _context10.n = 2;
@@ -2731,25 +2729,39 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2731
2729
  return response.json();
2732
2730
  case 4:
2733
2731
  componentDictionary = _context10.v;
2734
- console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary));
2732
+ console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary).length);
2735
2733
 
2736
- // Start preloading all models with the specified base path
2734
+ // Get the model preloader utility
2737
2735
  _modelPreloader2 = this.getUtility('modelPreloader');
2738
- _context10.n = 5;
2739
- return _modelPreloader2.preloadAllModels(componentDictionary, modelsBasePath);
2736
+ if (autoPreloadModels) {
2737
+ _context10.n = 5;
2738
+ break;
2739
+ }
2740
+ console.log('⚡ Lazy loading enabled: skipping automatic GLB preloading');
2741
+ // We still need to give the preloader the dictionary and base path for later use
2742
+ _modelPreloader2.componentDictionary = componentDictionary;
2743
+ _modelPreloader2.setModelsBasePath(modelsBasePath);
2744
+ return _context10.a(2, {
2745
+ successCount: 0,
2746
+ failureCount: 0,
2747
+ dictionaryCount: Object.keys(componentDictionary).length
2748
+ });
2740
2749
  case 5:
2750
+ _context10.n = 6;
2751
+ return _modelPreloader2.preloadAllModels(componentDictionary, modelsBasePath);
2752
+ case 6:
2741
2753
  progress = _context10.v;
2742
2754
  console.log('🎉 Model preloading completed:', progress);
2743
2755
  return _context10.a(2, progress);
2744
- case 6:
2745
- _context10.p = 6;
2756
+ case 7:
2757
+ _context10.p = 7;
2746
2758
  _t3 = _context10.v;
2747
2759
  console.error('❌ Failed to initialize model preloading:', _t3);
2748
2760
  throw _t3;
2749
- case 7:
2761
+ case 8:
2750
2762
  return _context10.a(2);
2751
2763
  }
2752
- }, _callee10, this, [[1, 6]]);
2764
+ }, _callee10, this, [[1, 7]]);
2753
2765
  }));
2754
2766
  function initializeModelPreloading() {
2755
2767
  return _initializeModelPreloading.apply(this, arguments);
@@ -138,7 +138,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
138
138
  key: "initializeScene",
139
139
  value: (function () {
140
140
  var _initializeScene = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee2() {
141
- var initStart, phase1Start, phase1Time, phase2Start, parallelInitPromises, phase2Time, phase3Start, sceneSetupPromises, phase3Time, phase4Start, phase4Time, phase5Start, phase5Time, initTime, _t2;
141
+ var initStart, phase1Start, phase1Time, phase2Start, parallelInitPromises, phase2Time, phase3Start, skipDefaultLoad, sceneSetupPromises, phase3Time, phase4Start, phase4Time, phase5Start, phase5Time, initTime, _t2;
142
142
  return _rollupPluginBabelHelpers.regenerator().w(function (_context2) {
143
143
  while (1) switch (_context2.n) {
144
144
  case 0:
@@ -186,7 +186,11 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
186
186
  // Phase 3: Scene loading and transform setup (can be parallelized)
187
187
  phase3Start = performance.now();
188
188
  console.log('📍 Phase 3: Scene loading and transform setup...');
189
- sceneSetupPromises = [this.loadScene().catch(function (error) {
189
+
190
+ // Explicitly check if we should skip the default load
191
+ skipDefaultLoad = process.env.SKIP_DEFAULT_LOAD === 'true';
192
+ console.log("\uD83D\uDD0D [SceneViewer] skipDefaultLoad: ".concat(skipDefaultLoad));
193
+ sceneSetupPromises = [skipDefaultLoad ? Promise.resolve() : this.loadScene().catch(function (error) {
190
194
  console.error('❌ Scene loading failed:', error);
191
195
  throw error;
192
196
  }), this.setupTransformControls().catch(function (error) {
@@ -202,7 +202,7 @@ var CacheManager = /*#__PURE__*/function () {
202
202
  key: "execute",
203
203
  value: (function () {
204
204
  var _execute = _rollupPluginBabelHelpers.asyncToGenerator(/*#__PURE__*/_rollupPluginBabelHelpers.regenerator().m(function _callee4(_ref) {
205
- var cacheKey, sourceKey, expiryMs, fetcher, processor, _ref$metadata, metadata, cacheName, cache, cachedResponse, cachedTime, age, result, fetchResult, blobOrJson, contentType, contentSize, responseBody, headers, cacheResponse, fallbackResult, _t2;
205
+ var cacheKey, sourceKey, expiryMs, fetcher, processor, _ref$metadata, metadata, cacheName, cache, cachedResponse, cachedTime, age, result, fetchResult, blobOrJson, error, contentType, contentSize, responseBody, headers, cacheResponse, fallbackResult, _t2;
206
206
  return _rollupPluginBabelHelpers.regenerator().w(function (_context4) {
207
207
  while (1) switch (_context4.n) {
208
208
  case 0:
@@ -255,7 +255,9 @@ var CacheManager = /*#__PURE__*/function () {
255
255
  _context4.n = 9;
256
256
  break;
257
257
  }
258
- throw new Error("Fetch failed: ".concat(fetchResult.status));
258
+ error = new Error("Fetch failed: ".concat(fetchResult.status)); // Do not retry 404s - the file is genuinely missing
259
+ if (fetchResult.status === 404) error.noRetry = true;
260
+ throw error;
259
261
  case 9:
260
262
  _context4.n = 10;
261
263
  return processor(fetchResult.clone());
@@ -306,20 +308,29 @@ var CacheManager = /*#__PURE__*/function () {
306
308
  case 15:
307
309
  fallbackResult = _context4.v;
308
310
  if (!(fallbackResult instanceof Response)) {
311
+ _context4.n = 18;
312
+ break;
313
+ }
314
+ if (fallbackResult.ok) {
309
315
  _context4.n = 16;
310
316
  break;
311
317
  }
312
- return _context4.a(2, processor(fallbackResult));
318
+ throw new Error("Fallback fetch failed: ".concat(fallbackResult.status));
313
319
  case 16:
314
- return _context4.a(2, fallbackResult);
320
+ _context4.n = 17;
321
+ return processor(fallbackResult);
315
322
  case 17:
316
- _context4.p = 17;
323
+ return _context4.a(2, _context4.v);
324
+ case 18:
325
+ return _context4.a(2, fallbackResult);
326
+ case 19:
327
+ _context4.p = 19;
317
328
  _context4.v;
318
329
  throw _t2;
319
- case 18:
330
+ case 20:
320
331
  return _context4.a(2);
321
332
  }
322
- }, _callee4, this, [[14, 17], [1, 13]]);
333
+ }, _callee4, this, [[14, 19], [1, 13]]);
323
334
  }));
324
335
  function execute(_x2) {
325
336
  return _execute.apply(this, arguments);
@@ -423,13 +423,15 @@ var EnvironmentManager = /*#__PURE__*/function () {
423
423
  return this.createSkybox();
424
424
  case 1:
425
425
  this.setupLighting();
426
- _context4.n = 2;
427
- return this.addTexturedGround();
428
- case 2:
429
- // await this.addBrickWalls()
430
426
  this.addHorizonFog();
431
- console.log('Environment initialization completed');
432
- case 3:
427
+
428
+ // 2. Add ground (synchronously adds basic mesh)
429
+ // We do NOT await the texture loading here to speed up scene "Ready" state
430
+ this.addTexturedGround().catch(function (err) {
431
+ return console.warn('⚠️ Ground texture load failed:', err);
432
+ });
433
+ console.log('Environment initialization completed (textures loading in background)');
434
+ case 2:
433
435
  return _context4.a(2);
434
436
  }
435
437
  }, _callee4, this);
@@ -1194,31 +1194,39 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1194
1194
  component = this.sceneViewer;
1195
1195
  _context8.p = 1;
1196
1196
  defaultCentralPlantUrl = process.env.DEFAULT_CENTRAL_PLANT_URL;
1197
- _context8.n = 2;
1198
- return fetch(defaultCentralPlantUrl);
1197
+ console.log('🔍 [SceneOperations] Attempting loadScene with URL:', defaultCentralPlantUrl);
1198
+ if (defaultCentralPlantUrl) {
1199
+ _context8.n = 2;
1200
+ break;
1201
+ }
1202
+ console.log('ℹ️ [SceneOperations] No default scene URL provided, skipping automatic load');
1203
+ return _context8.a(2);
1199
1204
  case 2:
1200
- response = _context8.v;
1201
1205
  _context8.n = 3;
1202
- return response.json();
1206
+ return fetch(defaultCentralPlantUrl);
1203
1207
  case 3:
1208
+ response = _context8.v;
1209
+ _context8.n = 4;
1210
+ return response.json();
1211
+ case 4:
1204
1212
  data = _context8.v;
1205
1213
  // Store current scene data even for default scene
1206
1214
  component.currentSceneData = data;
1207
1215
 
1208
1216
  // Use the consolidated scene loading function (treat as imported to ensure consistent behavior)
1209
- _context8.n = 4;
1217
+ _context8.n = 5;
1210
1218
  return this.loadSceneFromData(data);
1211
- case 4:
1212
- _context8.n = 6;
1213
- break;
1214
1219
  case 5:
1215
- _context8.p = 5;
1220
+ _context8.n = 7;
1221
+ break;
1222
+ case 6:
1223
+ _context8.p = 6;
1216
1224
  _t4 = _context8.v;
1217
1225
  console.error('Error loading default scene:', _t4);
1218
- case 6:
1226
+ case 7:
1219
1227
  return _context8.a(2);
1220
1228
  }
1221
- }, _callee8, this, [[1, 5]]);
1229
+ }, _callee8, this, [[1, 6]]);
1222
1230
  }));
1223
1231
  function loadScene() {
1224
1232
  return _loadScene.apply(this, arguments);
@@ -34,7 +34,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
34
34
  * Initialize the CentralPlant manager
35
35
  *
36
36
  * @constructor
37
- * @version 0.3.55
37
+ * @version 0.3.57
38
38
  * @updated 2025-10-22
39
39
  *
40
40
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -2652,23 +2652,18 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2652
2652
  /**
2653
2653
  * Initialize model preloading from component dictionary
2654
2654
  * @param {string} [basePath='/library/'] - Base path for both dictionary and models (can be local path or S3 URL)
2655
- * @returns {Promise<Object>} Preloading progress results
2656
- * @description Loads the component dictionary and preloads all models for better performance
2657
- * @example
2658
- * // Local files (default)
2659
- * await centralPlant.initializeModelPreloading()
2660
- *
2661
- * // S3 bucket
2662
- * await centralPlant.initializeModelPreloading('https://my-bucket.s3.amazonaws.com/library/')
2663
- *
2664
- * // Custom local path
2665
- * await centralPlant.initializeModelPreloading('/custom/assets/')
2655
+ * @param {Object} [options={}] - Optimization options
2656
+ * @param {boolean} [options.autoPreloadModels=true] - If false, only loads the dictionary and skips preloading GLBs (improves initial load)
2657
+ * @returns {Promise<Object>} Preloading progress results or dictionary summary
2666
2658
  */
2667
2659
  }, {
2668
2660
  key: "initializeModelPreloading",
2669
2661
  value: (function () {
2670
2662
  var _initializeModelPreloading = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
2671
2663
  var basePath,
2664
+ options,
2665
+ _options$autoPreloadM,
2666
+ autoPreloadModels,
2672
2667
  normalizedBasePath,
2673
2668
  dictionaryPath,
2674
2669
  modelsBasePath,
@@ -2682,6 +2677,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2682
2677
  while (1) switch (_context10.n) {
2683
2678
  case 0:
2684
2679
  basePath = _args10.length > 0 && _args10[0] !== undefined ? _args10[0] : '/library/';
2680
+ options = _args10.length > 1 && _args10[1] !== undefined ? _args10[1] : {};
2681
+ _options$autoPreloadM = options.autoPreloadModels, autoPreloadModels = _options$autoPreloadM === void 0 ? true : _options$autoPreloadM;
2685
2682
  _context10.p = 1;
2686
2683
  // Ensure basePath ends with a slash
2687
2684
  normalizedBasePath = basePath.endsWith('/') ? basePath : "".concat(basePath, "/");
@@ -2691,6 +2688,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2691
2688
  console.log("\uD83D\uDCC2 Base path: ".concat(normalizedBasePath));
2692
2689
  console.log("\uD83D\uDCDA Dictionary path: ".concat(dictionaryPath));
2693
2690
  console.log("\uFFFD Models path: ".concat(modelsBasePath));
2691
+ console.log("\u26A1 Auto-preload models: ".concat(autoPreloadModels));
2694
2692
 
2695
2693
  // Load the component dictionary
2696
2694
  _context10.n = 2;
@@ -2707,25 +2705,39 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
2707
2705
  return response.json();
2708
2706
  case 4:
2709
2707
  componentDictionary = _context10.v;
2710
- console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary));
2708
+ console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary).length);
2711
2709
 
2712
- // Start preloading all models with the specified base path
2710
+ // Get the model preloader utility
2713
2711
  _modelPreloader2 = this.getUtility('modelPreloader');
2714
- _context10.n = 5;
2715
- return _modelPreloader2.preloadAllModels(componentDictionary, modelsBasePath);
2712
+ if (autoPreloadModels) {
2713
+ _context10.n = 5;
2714
+ break;
2715
+ }
2716
+ console.log('⚡ Lazy loading enabled: skipping automatic GLB preloading');
2717
+ // We still need to give the preloader the dictionary and base path for later use
2718
+ _modelPreloader2.componentDictionary = componentDictionary;
2719
+ _modelPreloader2.setModelsBasePath(modelsBasePath);
2720
+ return _context10.a(2, {
2721
+ successCount: 0,
2722
+ failureCount: 0,
2723
+ dictionaryCount: Object.keys(componentDictionary).length
2724
+ });
2716
2725
  case 5:
2726
+ _context10.n = 6;
2727
+ return _modelPreloader2.preloadAllModels(componentDictionary, modelsBasePath);
2728
+ case 6:
2717
2729
  progress = _context10.v;
2718
2730
  console.log('🎉 Model preloading completed:', progress);
2719
2731
  return _context10.a(2, progress);
2720
- case 6:
2721
- _context10.p = 6;
2732
+ case 7:
2733
+ _context10.p = 7;
2722
2734
  _t3 = _context10.v;
2723
2735
  console.error('❌ Failed to initialize model preloading:', _t3);
2724
2736
  throw _t3;
2725
- case 7:
2737
+ case 8:
2726
2738
  return _context10.a(2);
2727
2739
  }
2728
- }, _callee10, this, [[1, 6]]);
2740
+ }, _callee10, this, [[1, 7]]);
2729
2741
  }));
2730
2742
  function initializeModelPreloading() {
2731
2743
  return _initializeModelPreloading.apply(this, arguments);
@@ -134,7 +134,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
134
134
  key: "initializeScene",
135
135
  value: (function () {
136
136
  var _initializeScene = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
137
- var initStart, phase1Start, phase1Time, phase2Start, parallelInitPromises, phase2Time, phase3Start, sceneSetupPromises, phase3Time, phase4Start, phase4Time, phase5Start, phase5Time, initTime, _t2;
137
+ var initStart, phase1Start, phase1Time, phase2Start, parallelInitPromises, phase2Time, phase3Start, skipDefaultLoad, sceneSetupPromises, phase3Time, phase4Start, phase4Time, phase5Start, phase5Time, initTime, _t2;
138
138
  return _regenerator().w(function (_context2) {
139
139
  while (1) switch (_context2.n) {
140
140
  case 0:
@@ -182,7 +182,11 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
182
182
  // Phase 3: Scene loading and transform setup (can be parallelized)
183
183
  phase3Start = performance.now();
184
184
  console.log('📍 Phase 3: Scene loading and transform setup...');
185
- sceneSetupPromises = [this.loadScene().catch(function (error) {
185
+
186
+ // Explicitly check if we should skip the default load
187
+ skipDefaultLoad = process.env.SKIP_DEFAULT_LOAD === 'true';
188
+ console.log("\uD83D\uDD0D [SceneViewer] skipDefaultLoad: ".concat(skipDefaultLoad));
189
+ sceneSetupPromises = [skipDefaultLoad ? Promise.resolve() : this.loadScene().catch(function (error) {
186
190
  console.error('❌ Scene loading failed:', error);
187
191
  throw error;
188
192
  }), this.setupTransformControls().catch(function (error) {
@@ -198,7 +198,7 @@ var CacheManager = /*#__PURE__*/function () {
198
198
  key: "execute",
199
199
  value: (function () {
200
200
  var _execute = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(_ref) {
201
- var cacheKey, sourceKey, expiryMs, fetcher, processor, _ref$metadata, metadata, cacheName, cache, cachedResponse, cachedTime, age, result, fetchResult, blobOrJson, contentType, contentSize, responseBody, headers, cacheResponse, fallbackResult, _t2;
201
+ var cacheKey, sourceKey, expiryMs, fetcher, processor, _ref$metadata, metadata, cacheName, cache, cachedResponse, cachedTime, age, result, fetchResult, blobOrJson, error, contentType, contentSize, responseBody, headers, cacheResponse, fallbackResult, _t2;
202
202
  return _regenerator().w(function (_context4) {
203
203
  while (1) switch (_context4.n) {
204
204
  case 0:
@@ -251,7 +251,9 @@ var CacheManager = /*#__PURE__*/function () {
251
251
  _context4.n = 9;
252
252
  break;
253
253
  }
254
- throw new Error("Fetch failed: ".concat(fetchResult.status));
254
+ error = new Error("Fetch failed: ".concat(fetchResult.status)); // Do not retry 404s - the file is genuinely missing
255
+ if (fetchResult.status === 404) error.noRetry = true;
256
+ throw error;
255
257
  case 9:
256
258
  _context4.n = 10;
257
259
  return processor(fetchResult.clone());
@@ -302,20 +304,29 @@ var CacheManager = /*#__PURE__*/function () {
302
304
  case 15:
303
305
  fallbackResult = _context4.v;
304
306
  if (!(fallbackResult instanceof Response)) {
307
+ _context4.n = 18;
308
+ break;
309
+ }
310
+ if (fallbackResult.ok) {
305
311
  _context4.n = 16;
306
312
  break;
307
313
  }
308
- return _context4.a(2, processor(fallbackResult));
314
+ throw new Error("Fallback fetch failed: ".concat(fallbackResult.status));
309
315
  case 16:
310
- return _context4.a(2, fallbackResult);
316
+ _context4.n = 17;
317
+ return processor(fallbackResult);
311
318
  case 17:
312
- _context4.p = 17;
319
+ return _context4.a(2, _context4.v);
320
+ case 18:
321
+ return _context4.a(2, fallbackResult);
322
+ case 19:
323
+ _context4.p = 19;
313
324
  _context4.v;
314
325
  throw _t2;
315
- case 18:
326
+ case 20:
316
327
  return _context4.a(2);
317
328
  }
318
- }, _callee4, this, [[14, 17], [1, 13]]);
329
+ }, _callee4, this, [[14, 19], [1, 13]]);
319
330
  }));
320
331
  function execute(_x2) {
321
332
  return _execute.apply(this, arguments);
@@ -399,13 +399,15 @@ var EnvironmentManager = /*#__PURE__*/function () {
399
399
  return this.createSkybox();
400
400
  case 1:
401
401
  this.setupLighting();
402
- _context4.n = 2;
403
- return this.addTexturedGround();
404
- case 2:
405
- // await this.addBrickWalls()
406
402
  this.addHorizonFog();
407
- console.log('Environment initialization completed');
408
- case 3:
403
+
404
+ // 2. Add ground (synchronously adds basic mesh)
405
+ // We do NOT await the texture loading here to speed up scene "Ready" state
406
+ this.addTexturedGround().catch(function (err) {
407
+ return console.warn('⚠️ Ground texture load failed:', err);
408
+ });
409
+ console.log('Environment initialization completed (textures loading in background)');
410
+ case 2:
409
411
  return _context4.a(2);
410
412
  }
411
413
  }, _callee4, this);
@@ -1170,31 +1170,39 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1170
1170
  component = this.sceneViewer;
1171
1171
  _context8.p = 1;
1172
1172
  defaultCentralPlantUrl = process.env.DEFAULT_CENTRAL_PLANT_URL;
1173
- _context8.n = 2;
1174
- return fetch(defaultCentralPlantUrl);
1173
+ console.log('🔍 [SceneOperations] Attempting loadScene with URL:', defaultCentralPlantUrl);
1174
+ if (defaultCentralPlantUrl) {
1175
+ _context8.n = 2;
1176
+ break;
1177
+ }
1178
+ console.log('ℹ️ [SceneOperations] No default scene URL provided, skipping automatic load');
1179
+ return _context8.a(2);
1175
1180
  case 2:
1176
- response = _context8.v;
1177
1181
  _context8.n = 3;
1178
- return response.json();
1182
+ return fetch(defaultCentralPlantUrl);
1179
1183
  case 3:
1184
+ response = _context8.v;
1185
+ _context8.n = 4;
1186
+ return response.json();
1187
+ case 4:
1180
1188
  data = _context8.v;
1181
1189
  // Store current scene data even for default scene
1182
1190
  component.currentSceneData = data;
1183
1191
 
1184
1192
  // Use the consolidated scene loading function (treat as imported to ensure consistent behavior)
1185
- _context8.n = 4;
1193
+ _context8.n = 5;
1186
1194
  return this.loadSceneFromData(data);
1187
- case 4:
1188
- _context8.n = 6;
1189
- break;
1190
1195
  case 5:
1191
- _context8.p = 5;
1196
+ _context8.n = 7;
1197
+ break;
1198
+ case 6:
1199
+ _context8.p = 6;
1192
1200
  _t4 = _context8.v;
1193
1201
  console.error('Error loading default scene:', _t4);
1194
- case 6:
1202
+ case 7:
1195
1203
  return _context8.a(2);
1196
1204
  }
1197
- }, _callee8, this, [[1, 5]]);
1205
+ }, _callee8, this, [[1, 6]]);
1198
1206
  }));
1199
1207
  function loadScene() {
1200
1208
  return _loadScene.apply(this, arguments);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2112-lab/central-plant",
3
- "version": "0.3.55",
3
+ "version": "0.3.57",
4
4
  "description": "Utility modules for the Central Plant Application",
5
5
  "main": "dist/bundle/index.js",
6
6
  "module": "dist/esm/src/index.js",