@2112-lab/central-plant 0.3.56 → 0.3.58
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/dist/bundle/index.js +119 -35
- package/dist/cjs/src/core/centralPlant.js +32 -20
- package/dist/cjs/src/managers/cache/CacheManager.js +18 -7
- package/dist/cjs/src/managers/controls/transformControlsManager.js +61 -2
- package/dist/cjs/src/managers/environment/environmentManager.js +8 -6
- package/dist/esm/src/core/centralPlant.js +32 -20
- package/dist/esm/src/managers/cache/CacheManager.js +18 -7
- package/dist/esm/src/managers/controls/transformControlsManager.js +61 -2
- package/dist/esm/src/managers/environment/environmentManager.js +8 -6
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -4109,6 +4109,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
4109
4109
|
// Update bounding box if the transformed object is in current selection
|
|
4110
4110
|
if (_this.selectedObjects.includes(eventData.object)) {
|
|
4111
4111
|
console.log('🔲 Updating bounding boxes for selected objects after transform');
|
|
4112
|
+
// Reposition the transform gizmo (and its selection group) to follow the
|
|
4113
|
+
// object's new position. Programmatic transforms (e.g. the Transform tab's
|
|
4114
|
+
// Translate/Rotate buttons) move the object directly without touching the
|
|
4115
|
+
// multi-selection group the gizmo is attached to, so without this the widget
|
|
4116
|
+
// would stay at the pre-transform centroid.
|
|
4117
|
+
_this.syncSelectionToObjects();
|
|
4112
4118
|
_this.updateBoundingBox();
|
|
4113
4119
|
}
|
|
4114
4120
|
};
|
|
@@ -5215,6 +5221,59 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
5215
5221
|
console.log("\uD83D\uDCE6 Multi-selection group created at centroid:", centroid.toArray());
|
|
5216
5222
|
}
|
|
5217
5223
|
|
|
5224
|
+
/**
|
|
5225
|
+
* Re-sync the multi-selection group (and the attached transform gizmo) to the
|
|
5226
|
+
* current world positions of the selected objects, in place.
|
|
5227
|
+
*
|
|
5228
|
+
* Used after a *programmatic* transform (e.g. the Transform tab's Translate /
|
|
5229
|
+
* Rotate buttons), which mutates the object directly and does not move the
|
|
5230
|
+
* selection group the gizmo is attached to. Unlike a full updateMultiSelection()
|
|
5231
|
+
* this keeps the same group instance so the gizmo doesn't detach/re-attach.
|
|
5232
|
+
*
|
|
5233
|
+
* It also refreshes the cached original transforms so a subsequent gizmo drag
|
|
5234
|
+
* computes its delta from the object's new position rather than jumping.
|
|
5235
|
+
*/
|
|
5236
|
+
}, {
|
|
5237
|
+
key: "syncSelectionToObjects",
|
|
5238
|
+
value: function syncSelectionToObjects() {
|
|
5239
|
+
var _this$transformContro;
|
|
5240
|
+
if (!this.multiSelectionGroup || this.selectedObjects.length === 0) {
|
|
5241
|
+
return;
|
|
5242
|
+
}
|
|
5243
|
+
|
|
5244
|
+
// Recompute the centroid from the objects' current world positions.
|
|
5245
|
+
var centroid = new THREE__namespace.Vector3();
|
|
5246
|
+
this.selectedObjects.forEach(function (obj) {
|
|
5247
|
+
obj.updateMatrixWorld(true);
|
|
5248
|
+
var worldPos = new THREE__namespace.Vector3();
|
|
5249
|
+
obj.getWorldPosition(worldPos);
|
|
5250
|
+
centroid.add(worldPos);
|
|
5251
|
+
});
|
|
5252
|
+
centroid.divideScalar(this.selectedObjects.length);
|
|
5253
|
+
|
|
5254
|
+
// Move the group (and thus the attached gizmo) to the new centroid. Reset any
|
|
5255
|
+
// rotation so the gizmo matches the freshly-created-group convention.
|
|
5256
|
+
this.multiSelectionGroup.position.copy(centroid);
|
|
5257
|
+
this.multiSelectionGroup.rotation.set(0, 0, 0);
|
|
5258
|
+
this.multiSelectionGroup.updateMatrixWorld(true);
|
|
5259
|
+
|
|
5260
|
+
// Refresh cached originals so applyRealtimeTransform's delta stays correct on
|
|
5261
|
+
// the next drag (its "original centroid" is derived from these values).
|
|
5262
|
+
this.selectedObjects.forEach(function (obj) {
|
|
5263
|
+
obj.userData._multiSelectOriginalPosition = obj.position.clone();
|
|
5264
|
+
obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
|
|
5265
|
+
obj.userData._multiSelectOriginalScale = obj.scale.clone();
|
|
5266
|
+
var worldPos = new THREE__namespace.Vector3();
|
|
5267
|
+
obj.getWorldPosition(worldPos);
|
|
5268
|
+
obj.userData._multiSelectOriginalWorldPosition = worldPos;
|
|
5269
|
+
});
|
|
5270
|
+
|
|
5271
|
+
// Keep the gizmo's world matrix in sync with the repositioned group.
|
|
5272
|
+
if ((_this$transformContro = this.transformControls) !== null && _this$transformContro !== void 0 && _this$transformContro.object) {
|
|
5273
|
+
this.transformControls.updateMatrixWorld(true);
|
|
5274
|
+
}
|
|
5275
|
+
}
|
|
5276
|
+
|
|
5218
5277
|
/**
|
|
5219
5278
|
* Create a bounding box that encompasses all selected objects
|
|
5220
5279
|
*/
|
|
@@ -5494,10 +5553,10 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
5494
5553
|
}, {
|
|
5495
5554
|
key: "toggleTransformMode",
|
|
5496
5555
|
value: function toggleTransformMode() {
|
|
5497
|
-
var _this$
|
|
5556
|
+
var _this$transformContro2;
|
|
5498
5557
|
var newMode = this.currentMode === 'translate' ? 'rotate' : 'translate';
|
|
5499
5558
|
this.setMode(newMode);
|
|
5500
|
-
if ((_this$
|
|
5559
|
+
if ((_this$transformContro2 = this.transformControls) !== null && _this$transformContro2 !== void 0 && _this$transformContro2.object) {
|
|
5501
5560
|
this.transformControls.updateMatrixWorld(true);
|
|
5502
5561
|
}
|
|
5503
5562
|
}
|
|
@@ -27361,13 +27420,15 @@ var EnvironmentManager = /*#__PURE__*/function () {
|
|
|
27361
27420
|
return this.createSkybox();
|
|
27362
27421
|
case 1:
|
|
27363
27422
|
this.setupLighting();
|
|
27364
|
-
_context4.n = 2;
|
|
27365
|
-
return this.addTexturedGround();
|
|
27366
|
-
case 2:
|
|
27367
|
-
// await this.addBrickWalls()
|
|
27368
27423
|
this.addHorizonFog();
|
|
27369
|
-
|
|
27370
|
-
|
|
27424
|
+
|
|
27425
|
+
// 2. Add ground (synchronously adds basic mesh)
|
|
27426
|
+
// We do NOT await the texture loading here to speed up scene "Ready" state
|
|
27427
|
+
this.addTexturedGround().catch(function (err) {
|
|
27428
|
+
return console.warn('⚠️ Ground texture load failed:', err);
|
|
27429
|
+
});
|
|
27430
|
+
console.log('Environment initialization completed (textures loading in background)');
|
|
27431
|
+
case 2:
|
|
27371
27432
|
return _context4.a(2);
|
|
27372
27433
|
}
|
|
27373
27434
|
}, _callee4, this);
|
|
@@ -41823,7 +41884,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
41823
41884
|
* Initialize the CentralPlant manager
|
|
41824
41885
|
*
|
|
41825
41886
|
* @constructor
|
|
41826
|
-
* @version 0.3.
|
|
41887
|
+
* @version 0.3.58
|
|
41827
41888
|
* @updated 2025-10-22
|
|
41828
41889
|
*
|
|
41829
41890
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -44441,23 +44502,18 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
44441
44502
|
/**
|
|
44442
44503
|
* Initialize model preloading from component dictionary
|
|
44443
44504
|
* @param {string} [basePath='/library/'] - Base path for both dictionary and models (can be local path or S3 URL)
|
|
44444
|
-
* @
|
|
44445
|
-
* @
|
|
44446
|
-
* @
|
|
44447
|
-
* // Local files (default)
|
|
44448
|
-
* await centralPlant.initializeModelPreloading()
|
|
44449
|
-
*
|
|
44450
|
-
* // S3 bucket
|
|
44451
|
-
* await centralPlant.initializeModelPreloading('https://my-bucket.s3.amazonaws.com/library/')
|
|
44452
|
-
*
|
|
44453
|
-
* // Custom local path
|
|
44454
|
-
* await centralPlant.initializeModelPreloading('/custom/assets/')
|
|
44505
|
+
* @param {Object} [options={}] - Optimization options
|
|
44506
|
+
* @param {boolean} [options.autoPreloadModels=true] - If false, only loads the dictionary and skips preloading GLBs (improves initial load)
|
|
44507
|
+
* @returns {Promise<Object>} Preloading progress results or dictionary summary
|
|
44455
44508
|
*/
|
|
44456
44509
|
}, {
|
|
44457
44510
|
key: "initializeModelPreloading",
|
|
44458
44511
|
value: (function () {
|
|
44459
44512
|
var _initializeModelPreloading = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
|
|
44460
44513
|
var basePath,
|
|
44514
|
+
options,
|
|
44515
|
+
_options$autoPreloadM,
|
|
44516
|
+
autoPreloadModels,
|
|
44461
44517
|
normalizedBasePath,
|
|
44462
44518
|
dictionaryPath,
|
|
44463
44519
|
modelsBasePath,
|
|
@@ -44471,6 +44527,8 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
44471
44527
|
while (1) switch (_context10.n) {
|
|
44472
44528
|
case 0:
|
|
44473
44529
|
basePath = _args10.length > 0 && _args10[0] !== undefined ? _args10[0] : '/library/';
|
|
44530
|
+
options = _args10.length > 1 && _args10[1] !== undefined ? _args10[1] : {};
|
|
44531
|
+
_options$autoPreloadM = options.autoPreloadModels, autoPreloadModels = _options$autoPreloadM === void 0 ? true : _options$autoPreloadM;
|
|
44474
44532
|
_context10.p = 1;
|
|
44475
44533
|
// Ensure basePath ends with a slash
|
|
44476
44534
|
normalizedBasePath = basePath.endsWith('/') ? basePath : "".concat(basePath, "/");
|
|
@@ -44480,6 +44538,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
44480
44538
|
console.log("\uD83D\uDCC2 Base path: ".concat(normalizedBasePath));
|
|
44481
44539
|
console.log("\uD83D\uDCDA Dictionary path: ".concat(dictionaryPath));
|
|
44482
44540
|
console.log("\uFFFD Models path: ".concat(modelsBasePath));
|
|
44541
|
+
console.log("\u26A1 Auto-preload models: ".concat(autoPreloadModels));
|
|
44483
44542
|
|
|
44484
44543
|
// Load the component dictionary
|
|
44485
44544
|
_context10.n = 2;
|
|
@@ -44496,25 +44555,39 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
44496
44555
|
return response.json();
|
|
44497
44556
|
case 4:
|
|
44498
44557
|
componentDictionary = _context10.v;
|
|
44499
|
-
console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary));
|
|
44558
|
+
console.log('📚 Component dictionary loaded:', Object.keys(componentDictionary).length);
|
|
44500
44559
|
|
|
44501
|
-
//
|
|
44560
|
+
// Get the model preloader utility
|
|
44502
44561
|
_modelPreloader2 = this.getUtility('modelPreloader');
|
|
44503
|
-
|
|
44504
|
-
|
|
44562
|
+
if (autoPreloadModels) {
|
|
44563
|
+
_context10.n = 5;
|
|
44564
|
+
break;
|
|
44565
|
+
}
|
|
44566
|
+
console.log('⚡ Lazy loading enabled: skipping automatic GLB preloading');
|
|
44567
|
+
// We still need to give the preloader the dictionary and base path for later use
|
|
44568
|
+
_modelPreloader2.componentDictionary = componentDictionary;
|
|
44569
|
+
_modelPreloader2.setModelsBasePath(modelsBasePath);
|
|
44570
|
+
return _context10.a(2, {
|
|
44571
|
+
successCount: 0,
|
|
44572
|
+
failureCount: 0,
|
|
44573
|
+
dictionaryCount: Object.keys(componentDictionary).length
|
|
44574
|
+
});
|
|
44505
44575
|
case 5:
|
|
44576
|
+
_context10.n = 6;
|
|
44577
|
+
return _modelPreloader2.preloadAllModels(componentDictionary, modelsBasePath);
|
|
44578
|
+
case 6:
|
|
44506
44579
|
progress = _context10.v;
|
|
44507
44580
|
console.log('🎉 Model preloading completed:', progress);
|
|
44508
44581
|
return _context10.a(2, progress);
|
|
44509
|
-
case
|
|
44510
|
-
_context10.p =
|
|
44582
|
+
case 7:
|
|
44583
|
+
_context10.p = 7;
|
|
44511
44584
|
_t3 = _context10.v;
|
|
44512
44585
|
console.error('❌ Failed to initialize model preloading:', _t3);
|
|
44513
44586
|
throw _t3;
|
|
44514
|
-
case
|
|
44587
|
+
case 8:
|
|
44515
44588
|
return _context10.a(2);
|
|
44516
44589
|
}
|
|
44517
|
-
}, _callee10, this, [[1,
|
|
44590
|
+
}, _callee10, this, [[1, 7]]);
|
|
44518
44591
|
}));
|
|
44519
44592
|
function initializeModelPreloading() {
|
|
44520
44593
|
return _initializeModelPreloading.apply(this, arguments);
|
|
@@ -46484,7 +46557,7 @@ var CacheManager = /*#__PURE__*/function () {
|
|
|
46484
46557
|
key: "execute",
|
|
46485
46558
|
value: (function () {
|
|
46486
46559
|
var _execute = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(_ref) {
|
|
46487
|
-
var cacheKey, sourceKey, expiryMs, fetcher, processor, _ref$metadata, metadata, cacheName, cache, cachedResponse, cachedTime, age, result, fetchResult, blobOrJson, contentType, contentSize, responseBody, headers, cacheResponse, fallbackResult, _t2;
|
|
46560
|
+
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;
|
|
46488
46561
|
return _regenerator().w(function (_context4) {
|
|
46489
46562
|
while (1) switch (_context4.n) {
|
|
46490
46563
|
case 0:
|
|
@@ -46537,7 +46610,9 @@ var CacheManager = /*#__PURE__*/function () {
|
|
|
46537
46610
|
_context4.n = 9;
|
|
46538
46611
|
break;
|
|
46539
46612
|
}
|
|
46540
|
-
|
|
46613
|
+
error = new Error("Fetch failed: ".concat(fetchResult.status)); // Do not retry 404s - the file is genuinely missing
|
|
46614
|
+
if (fetchResult.status === 404) error.noRetry = true;
|
|
46615
|
+
throw error;
|
|
46541
46616
|
case 9:
|
|
46542
46617
|
_context4.n = 10;
|
|
46543
46618
|
return processor(fetchResult.clone());
|
|
@@ -46588,20 +46663,29 @@ var CacheManager = /*#__PURE__*/function () {
|
|
|
46588
46663
|
case 15:
|
|
46589
46664
|
fallbackResult = _context4.v;
|
|
46590
46665
|
if (!(fallbackResult instanceof Response)) {
|
|
46666
|
+
_context4.n = 18;
|
|
46667
|
+
break;
|
|
46668
|
+
}
|
|
46669
|
+
if (fallbackResult.ok) {
|
|
46591
46670
|
_context4.n = 16;
|
|
46592
46671
|
break;
|
|
46593
46672
|
}
|
|
46594
|
-
|
|
46673
|
+
throw new Error("Fallback fetch failed: ".concat(fallbackResult.status));
|
|
46595
46674
|
case 16:
|
|
46596
|
-
|
|
46675
|
+
_context4.n = 17;
|
|
46676
|
+
return processor(fallbackResult);
|
|
46597
46677
|
case 17:
|
|
46598
|
-
_context4.
|
|
46678
|
+
return _context4.a(2, _context4.v);
|
|
46679
|
+
case 18:
|
|
46680
|
+
return _context4.a(2, fallbackResult);
|
|
46681
|
+
case 19:
|
|
46682
|
+
_context4.p = 19;
|
|
46599
46683
|
_context4.v;
|
|
46600
46684
|
throw _t2;
|
|
46601
|
-
case
|
|
46685
|
+
case 20:
|
|
46602
46686
|
return _context4.a(2);
|
|
46603
46687
|
}
|
|
46604
|
-
}, _callee4, this, [[14,
|
|
46688
|
+
}, _callee4, this, [[14, 19], [1, 13]]);
|
|
46605
46689
|
}));
|
|
46606
46690
|
function execute(_x2) {
|
|
46607
46691
|
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.
|
|
61
|
+
* @version 0.3.58
|
|
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
|
-
* @
|
|
2680
|
-
* @
|
|
2681
|
-
* @
|
|
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
|
-
//
|
|
2734
|
+
// Get the model preloader utility
|
|
2737
2735
|
_modelPreloader2 = this.getUtility('modelPreloader');
|
|
2738
|
-
|
|
2739
|
-
|
|
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
|
|
2745
|
-
_context10.p =
|
|
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
|
|
2761
|
+
case 8:
|
|
2750
2762
|
return _context10.a(2);
|
|
2751
2763
|
}
|
|
2752
|
-
}, _callee10, this, [[1,
|
|
2764
|
+
}, _callee10, this, [[1, 7]]);
|
|
2753
2765
|
}));
|
|
2754
2766
|
function initializeModelPreloading() {
|
|
2755
2767
|
return _initializeModelPreloading.apply(this, arguments);
|
|
@@ -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
|
-
|
|
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
|
-
|
|
318
|
+
throw new Error("Fallback fetch failed: ".concat(fallbackResult.status));
|
|
313
319
|
case 16:
|
|
314
|
-
|
|
320
|
+
_context4.n = 17;
|
|
321
|
+
return processor(fallbackResult);
|
|
315
322
|
case 17:
|
|
316
|
-
_context4.
|
|
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
|
|
330
|
+
case 20:
|
|
320
331
|
return _context4.a(2);
|
|
321
332
|
}
|
|
322
|
-
}, _callee4, this, [[14,
|
|
333
|
+
}, _callee4, this, [[14, 19], [1, 13]]);
|
|
323
334
|
}));
|
|
324
335
|
function execute(_x2) {
|
|
325
336
|
return _execute.apply(this, arguments);
|
|
@@ -164,6 +164,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
164
164
|
// Update bounding box if the transformed object is in current selection
|
|
165
165
|
if (_this.selectedObjects.includes(eventData.object)) {
|
|
166
166
|
console.log('🔲 Updating bounding boxes for selected objects after transform');
|
|
167
|
+
// Reposition the transform gizmo (and its selection group) to follow the
|
|
168
|
+
// object's new position. Programmatic transforms (e.g. the Transform tab's
|
|
169
|
+
// Translate/Rotate buttons) move the object directly without touching the
|
|
170
|
+
// multi-selection group the gizmo is attached to, so without this the widget
|
|
171
|
+
// would stay at the pre-transform centroid.
|
|
172
|
+
_this.syncSelectionToObjects();
|
|
167
173
|
_this.updateBoundingBox();
|
|
168
174
|
}
|
|
169
175
|
};
|
|
@@ -1270,6 +1276,59 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
1270
1276
|
console.log("\uD83D\uDCE6 Multi-selection group created at centroid:", centroid.toArray());
|
|
1271
1277
|
}
|
|
1272
1278
|
|
|
1279
|
+
/**
|
|
1280
|
+
* Re-sync the multi-selection group (and the attached transform gizmo) to the
|
|
1281
|
+
* current world positions of the selected objects, in place.
|
|
1282
|
+
*
|
|
1283
|
+
* Used after a *programmatic* transform (e.g. the Transform tab's Translate /
|
|
1284
|
+
* Rotate buttons), which mutates the object directly and does not move the
|
|
1285
|
+
* selection group the gizmo is attached to. Unlike a full updateMultiSelection()
|
|
1286
|
+
* this keeps the same group instance so the gizmo doesn't detach/re-attach.
|
|
1287
|
+
*
|
|
1288
|
+
* It also refreshes the cached original transforms so a subsequent gizmo drag
|
|
1289
|
+
* computes its delta from the object's new position rather than jumping.
|
|
1290
|
+
*/
|
|
1291
|
+
}, {
|
|
1292
|
+
key: "syncSelectionToObjects",
|
|
1293
|
+
value: function syncSelectionToObjects() {
|
|
1294
|
+
var _this$transformContro;
|
|
1295
|
+
if (!this.multiSelectionGroup || this.selectedObjects.length === 0) {
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
// Recompute the centroid from the objects' current world positions.
|
|
1300
|
+
var centroid = new THREE__namespace.Vector3();
|
|
1301
|
+
this.selectedObjects.forEach(function (obj) {
|
|
1302
|
+
obj.updateMatrixWorld(true);
|
|
1303
|
+
var worldPos = new THREE__namespace.Vector3();
|
|
1304
|
+
obj.getWorldPosition(worldPos);
|
|
1305
|
+
centroid.add(worldPos);
|
|
1306
|
+
});
|
|
1307
|
+
centroid.divideScalar(this.selectedObjects.length);
|
|
1308
|
+
|
|
1309
|
+
// Move the group (and thus the attached gizmo) to the new centroid. Reset any
|
|
1310
|
+
// rotation so the gizmo matches the freshly-created-group convention.
|
|
1311
|
+
this.multiSelectionGroup.position.copy(centroid);
|
|
1312
|
+
this.multiSelectionGroup.rotation.set(0, 0, 0);
|
|
1313
|
+
this.multiSelectionGroup.updateMatrixWorld(true);
|
|
1314
|
+
|
|
1315
|
+
// Refresh cached originals so applyRealtimeTransform's delta stays correct on
|
|
1316
|
+
// the next drag (its "original centroid" is derived from these values).
|
|
1317
|
+
this.selectedObjects.forEach(function (obj) {
|
|
1318
|
+
obj.userData._multiSelectOriginalPosition = obj.position.clone();
|
|
1319
|
+
obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
|
|
1320
|
+
obj.userData._multiSelectOriginalScale = obj.scale.clone();
|
|
1321
|
+
var worldPos = new THREE__namespace.Vector3();
|
|
1322
|
+
obj.getWorldPosition(worldPos);
|
|
1323
|
+
obj.userData._multiSelectOriginalWorldPosition = worldPos;
|
|
1324
|
+
});
|
|
1325
|
+
|
|
1326
|
+
// Keep the gizmo's world matrix in sync with the repositioned group.
|
|
1327
|
+
if ((_this$transformContro = this.transformControls) !== null && _this$transformContro !== void 0 && _this$transformContro.object) {
|
|
1328
|
+
this.transformControls.updateMatrixWorld(true);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1273
1332
|
/**
|
|
1274
1333
|
* Create a bounding box that encompasses all selected objects
|
|
1275
1334
|
*/
|
|
@@ -1549,10 +1608,10 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
1549
1608
|
}, {
|
|
1550
1609
|
key: "toggleTransformMode",
|
|
1551
1610
|
value: function toggleTransformMode() {
|
|
1552
|
-
var _this$
|
|
1611
|
+
var _this$transformContro2;
|
|
1553
1612
|
var newMode = this.currentMode === 'translate' ? 'rotate' : 'translate';
|
|
1554
1613
|
this.setMode(newMode);
|
|
1555
|
-
if ((_this$
|
|
1614
|
+
if ((_this$transformContro2 = this.transformControls) !== null && _this$transformContro2 !== void 0 && _this$transformContro2.object) {
|
|
1556
1615
|
this.transformControls.updateMatrixWorld(true);
|
|
1557
1616
|
}
|
|
1558
1617
|
}
|
|
@@ -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
|
-
|
|
432
|
-
|
|
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);
|
|
@@ -34,7 +34,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
34
34
|
* Initialize the CentralPlant manager
|
|
35
35
|
*
|
|
36
36
|
* @constructor
|
|
37
|
-
* @version 0.3.
|
|
37
|
+
* @version 0.3.58
|
|
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
|
-
* @
|
|
2656
|
-
* @
|
|
2657
|
-
* @
|
|
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
|
-
//
|
|
2710
|
+
// Get the model preloader utility
|
|
2713
2711
|
_modelPreloader2 = this.getUtility('modelPreloader');
|
|
2714
|
-
|
|
2715
|
-
|
|
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
|
|
2721
|
-
_context10.p =
|
|
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
|
|
2737
|
+
case 8:
|
|
2726
2738
|
return _context10.a(2);
|
|
2727
2739
|
}
|
|
2728
|
-
}, _callee10, this, [[1,
|
|
2740
|
+
}, _callee10, this, [[1, 7]]);
|
|
2729
2741
|
}));
|
|
2730
2742
|
function initializeModelPreloading() {
|
|
2731
2743
|
return _initializeModelPreloading.apply(this, arguments);
|
|
@@ -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
|
-
|
|
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
|
-
|
|
314
|
+
throw new Error("Fallback fetch failed: ".concat(fallbackResult.status));
|
|
309
315
|
case 16:
|
|
310
|
-
|
|
316
|
+
_context4.n = 17;
|
|
317
|
+
return processor(fallbackResult);
|
|
311
318
|
case 17:
|
|
312
|
-
_context4.
|
|
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
|
|
326
|
+
case 20:
|
|
316
327
|
return _context4.a(2);
|
|
317
328
|
}
|
|
318
|
-
}, _callee4, this, [[14,
|
|
329
|
+
}, _callee4, this, [[14, 19], [1, 13]]);
|
|
319
330
|
}));
|
|
320
331
|
function execute(_x2) {
|
|
321
332
|
return _execute.apply(this, arguments);
|
|
@@ -140,6 +140,12 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
140
140
|
// Update bounding box if the transformed object is in current selection
|
|
141
141
|
if (_this.selectedObjects.includes(eventData.object)) {
|
|
142
142
|
console.log('🔲 Updating bounding boxes for selected objects after transform');
|
|
143
|
+
// Reposition the transform gizmo (and its selection group) to follow the
|
|
144
|
+
// object's new position. Programmatic transforms (e.g. the Transform tab's
|
|
145
|
+
// Translate/Rotate buttons) move the object directly without touching the
|
|
146
|
+
// multi-selection group the gizmo is attached to, so without this the widget
|
|
147
|
+
// would stay at the pre-transform centroid.
|
|
148
|
+
_this.syncSelectionToObjects();
|
|
143
149
|
_this.updateBoundingBox();
|
|
144
150
|
}
|
|
145
151
|
};
|
|
@@ -1246,6 +1252,59 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
1246
1252
|
console.log("\uD83D\uDCE6 Multi-selection group created at centroid:", centroid.toArray());
|
|
1247
1253
|
}
|
|
1248
1254
|
|
|
1255
|
+
/**
|
|
1256
|
+
* Re-sync the multi-selection group (and the attached transform gizmo) to the
|
|
1257
|
+
* current world positions of the selected objects, in place.
|
|
1258
|
+
*
|
|
1259
|
+
* Used after a *programmatic* transform (e.g. the Transform tab's Translate /
|
|
1260
|
+
* Rotate buttons), which mutates the object directly and does not move the
|
|
1261
|
+
* selection group the gizmo is attached to. Unlike a full updateMultiSelection()
|
|
1262
|
+
* this keeps the same group instance so the gizmo doesn't detach/re-attach.
|
|
1263
|
+
*
|
|
1264
|
+
* It also refreshes the cached original transforms so a subsequent gizmo drag
|
|
1265
|
+
* computes its delta from the object's new position rather than jumping.
|
|
1266
|
+
*/
|
|
1267
|
+
}, {
|
|
1268
|
+
key: "syncSelectionToObjects",
|
|
1269
|
+
value: function syncSelectionToObjects() {
|
|
1270
|
+
var _this$transformContro;
|
|
1271
|
+
if (!this.multiSelectionGroup || this.selectedObjects.length === 0) {
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
// Recompute the centroid from the objects' current world positions.
|
|
1276
|
+
var centroid = new THREE.Vector3();
|
|
1277
|
+
this.selectedObjects.forEach(function (obj) {
|
|
1278
|
+
obj.updateMatrixWorld(true);
|
|
1279
|
+
var worldPos = new THREE.Vector3();
|
|
1280
|
+
obj.getWorldPosition(worldPos);
|
|
1281
|
+
centroid.add(worldPos);
|
|
1282
|
+
});
|
|
1283
|
+
centroid.divideScalar(this.selectedObjects.length);
|
|
1284
|
+
|
|
1285
|
+
// Move the group (and thus the attached gizmo) to the new centroid. Reset any
|
|
1286
|
+
// rotation so the gizmo matches the freshly-created-group convention.
|
|
1287
|
+
this.multiSelectionGroup.position.copy(centroid);
|
|
1288
|
+
this.multiSelectionGroup.rotation.set(0, 0, 0);
|
|
1289
|
+
this.multiSelectionGroup.updateMatrixWorld(true);
|
|
1290
|
+
|
|
1291
|
+
// Refresh cached originals so applyRealtimeTransform's delta stays correct on
|
|
1292
|
+
// the next drag (its "original centroid" is derived from these values).
|
|
1293
|
+
this.selectedObjects.forEach(function (obj) {
|
|
1294
|
+
obj.userData._multiSelectOriginalPosition = obj.position.clone();
|
|
1295
|
+
obj.userData._multiSelectOriginalRotation = obj.rotation.clone();
|
|
1296
|
+
obj.userData._multiSelectOriginalScale = obj.scale.clone();
|
|
1297
|
+
var worldPos = new THREE.Vector3();
|
|
1298
|
+
obj.getWorldPosition(worldPos);
|
|
1299
|
+
obj.userData._multiSelectOriginalWorldPosition = worldPos;
|
|
1300
|
+
});
|
|
1301
|
+
|
|
1302
|
+
// Keep the gizmo's world matrix in sync with the repositioned group.
|
|
1303
|
+
if ((_this$transformContro = this.transformControls) !== null && _this$transformContro !== void 0 && _this$transformContro.object) {
|
|
1304
|
+
this.transformControls.updateMatrixWorld(true);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1249
1308
|
/**
|
|
1250
1309
|
* Create a bounding box that encompasses all selected objects
|
|
1251
1310
|
*/
|
|
@@ -1525,10 +1584,10 @@ var TransformControlsManager = /*#__PURE__*/function () {
|
|
|
1525
1584
|
}, {
|
|
1526
1585
|
key: "toggleTransformMode",
|
|
1527
1586
|
value: function toggleTransformMode() {
|
|
1528
|
-
var _this$
|
|
1587
|
+
var _this$transformContro2;
|
|
1529
1588
|
var newMode = this.currentMode === 'translate' ? 'rotate' : 'translate';
|
|
1530
1589
|
this.setMode(newMode);
|
|
1531
|
-
if ((_this$
|
|
1590
|
+
if ((_this$transformContro2 = this.transformControls) !== null && _this$transformContro2 !== void 0 && _this$transformContro2.object) {
|
|
1532
1591
|
this.transformControls.updateMatrixWorld(true);
|
|
1533
1592
|
}
|
|
1534
1593
|
}
|
|
@@ -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
|
-
|
|
408
|
-
|
|
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);
|