@2112-lab/central-plant 0.1.95 → 0.1.97

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.
@@ -24181,7 +24181,7 @@ var SceneInitializationManager = /*#__PURE__*/function () {
24181
24181
  containerWidth = containerRect.width;
24182
24182
  containerHeight = containerRect.height; // Create camera (Z-up coordinate system with flipped Y)
24183
24183
  component.camera = new THREE__namespace.PerspectiveCamera(50, containerWidth / containerHeight, 0.01, 1000);
24184
- component.camera.position.set(-8, -9, 4); // Flipped Y direction
24184
+ component.camera.position.set(-8, -9, 2); // Flipped Y direction
24185
24185
  component.camera.up.set(0, 0, 1); // Set Z as up vector
24186
24186
 
24187
24187
  // Create renderer
@@ -25184,8 +25184,8 @@ var EnvironmentManager = /*#__PURE__*/function () {
25184
25184
  case 0:
25185
25185
  component = this.sceneViewer;
25186
25186
  console.debug('Starting addTexturedGround...');
25187
- groundSize = 30;
25188
- groundGeometry = new THREE__namespace.PlaneGeometry(groundSize, groundSize);
25187
+ groundSize = 90;
25188
+ groundGeometry = new THREE__namespace.CircleGeometry(groundSize / 2, 16);
25189
25189
  groundMaterial = new THREE__namespace.MeshStandardMaterial({
25190
25190
  color: 0x777777,
25191
25191
  metalness: 0.2,
@@ -25373,7 +25373,7 @@ var EnvironmentManager = /*#__PURE__*/function () {
25373
25373
  key: "addHorizonFog",
25374
25374
  value: function addHorizonFog() {
25375
25375
  var component = this.sceneViewer;
25376
- var groundSize = 30;
25376
+ var groundSize = 60;
25377
25377
  var fogSize = groundSize * 10;
25378
25378
  var fogMaterial = new THREE__namespace.ShaderMaterial({
25379
25379
  transparent: true,
@@ -25392,7 +25392,7 @@ var EnvironmentManager = /*#__PURE__*/function () {
25392
25392
  var fogGeometry = new THREE__namespace.PlaneGeometry(fogSize, fogSize);
25393
25393
  var fogPlane = new THREE__namespace.Mesh(fogGeometry, fogMaterial);
25394
25394
  fogPlane.rotation.x = 0; // No rotation needed for Z-up coordinate system
25395
- fogPlane.position.z = -3.0; // Position fog plane below ground level
25395
+ fogPlane.position.z = -8.0; // Position fog plane below ground level
25396
25396
  fogPlane.name = "fogPlane";
25397
25397
  component.scene.add(fogPlane);
25398
25398
  return fogPlane;
@@ -25415,12 +25415,10 @@ var EnvironmentManager = /*#__PURE__*/function () {
25415
25415
  _context4.n = 2;
25416
25416
  return this.addTexturedGround();
25417
25417
  case 2:
25418
- _context4.n = 3;
25419
- return this.addBrickWalls();
25420
- case 3:
25418
+ // await this.addBrickWalls()
25421
25419
  this.addHorizonFog();
25422
25420
  console.log('Environment initialization completed');
25423
- case 4:
25421
+ case 3:
25424
25422
  return _context4.a(2);
25425
25423
  }
25426
25424
  }, _callee4, this);
@@ -28581,6 +28579,15 @@ var BehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
28581
28579
  value: function _applyAction(object, propertyPath, value) {
28582
28580
  if (!object || typeof propertyPath !== 'string') return;
28583
28581
  var parts = propertyPath.split('.');
28582
+
28583
+ // Clone shared material onto this mesh before mutating any material property.
28584
+ // Three.js reuses the same Material instance across all meshes loaded from the
28585
+ // same GLB, so without cloning a color/emissive change would bleed to every
28586
+ // other component instance that shares the model.
28587
+ if (parts[0] === 'material' && object.isMesh && object.material && !object.userData._behaviorMaterialCloned) {
28588
+ object.material = object.material.clone();
28589
+ object.userData._behaviorMaterialCloned = true;
28590
+ }
28584
28591
  var target = object;
28585
28592
  for (var i = 0; i < parts.length - 1; i++) {
28586
28593
  if (target == null) {
@@ -31201,6 +31208,19 @@ var SceneOperationsManager = /*#__PURE__*/function () {
31201
31208
  return b.id;
31202
31209
  }));
31203
31210
 
31211
+ // Build a set of (component::attachment::state) tuples covered by explicit
31212
+ // behaviors. If an expanded default behavior would produce the SAME input
31213
+ // tuple, the explicit behavior is treated as the intentional override and
31214
+ // the default expansion is skipped. This prevents a component's built-in
31215
+ // switch→LED wiring from doubling-up when the user has deliberately authored
31216
+ // cross-component behaviors that re-wire the same switch.
31217
+ var explicitInputTuples = new Set(explicitBehaviors.filter(function (b) {
31218
+ var _b$input, _b$input2, _b$input3;
31219
+ return ((_b$input = b.input) === null || _b$input === void 0 ? void 0 : _b$input.component) && ((_b$input2 = b.input) === null || _b$input2 === void 0 ? void 0 : _b$input2.attachment) && ((_b$input3 = b.input) === null || _b$input3 === void 0 ? void 0 : _b$input3.state);
31220
+ }).map(function (b) {
31221
+ return "".concat(b.input.component, "::").concat(b.input.attachment, "::").concat(b.input.state);
31222
+ }));
31223
+
31204
31224
  // Build a set of instanceUuids already covered by behaviorRef entries in
31205
31225
  // data.behaviors (written by the exporter for smart component defaults).
31206
31226
  // Step B skips these instances to avoid loading the same behaviors twice —
@@ -31229,10 +31249,20 @@ var SceneOperationsManager = /*#__PURE__*/function () {
31229
31249
  var compData = componentDictionary[libraryId];
31230
31250
  if (!(compData !== null && compData !== void 0 && (_compData$defaultBeha = compData.defaultBehaviors) !== null && _compData$defaultBeha !== void 0 && _compData$defaultBeha.length)) return;
31231
31251
  compData.defaultBehaviors.forEach(function (template) {
31252
+ var _expanded$input, _expanded$input2, _expanded$input3;
31232
31253
  var expanded = _this5._expandDefaultBehavior(template, instanceUuid, componentDictionary);
31233
31254
  if (!expanded) return;
31234
31255
  // Skip if an explicit scene behavior already covers this id
31235
31256
  if (explicitIds.has(expanded.id)) return;
31257
+ // Skip if an explicit scene behavior already covers the same
31258
+ // (component, attachment, state) input tuple. This prevents a
31259
+ // component's built-in default wiring (e.g. switch → own LED) from
31260
+ // double-firing when the user has authored a cross-component override
31261
+ // that rewires the same switch to a different target.
31262
+ if ((_expanded$input = expanded.input) !== null && _expanded$input !== void 0 && _expanded$input.component && (_expanded$input2 = expanded.input) !== null && _expanded$input2 !== void 0 && _expanded$input2.attachment && (_expanded$input3 = expanded.input) !== null && _expanded$input3 !== void 0 && _expanded$input3.state) {
31263
+ var tuple = "".concat(expanded.input.component, "::").concat(expanded.input.attachment, "::").concat(expanded.input.state);
31264
+ if (explicitInputTuples.has(tuple)) return;
31265
+ }
31236
31266
  // All component defaultBehaviors are re-derivable from the component
31237
31267
  // asset at export time (via compact behaviorRef), so mark them all.
31238
31268
  expanded._isDefaultBehavior = true;
@@ -37203,7 +37233,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
37203
37233
  * Initialize the CentralPlant manager
37204
37234
  *
37205
37235
  * @constructor
37206
- * @version 0.1.95
37236
+ * @version 0.1.97
37207
37237
  * @updated 2025-10-22
37208
37238
  *
37209
37239
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -19,7 +19,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
19
19
  * Initialize the CentralPlant manager
20
20
  *
21
21
  * @constructor
22
- * @version 0.1.95
22
+ * @version 0.1.97
23
23
  * @updated 2025-10-22
24
24
  *
25
25
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -344,6 +344,15 @@ var BehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
344
344
  value: function _applyAction(object, propertyPath, value) {
345
345
  if (!object || typeof propertyPath !== 'string') return;
346
346
  var parts = propertyPath.split('.');
347
+
348
+ // Clone shared material onto this mesh before mutating any material property.
349
+ // Three.js reuses the same Material instance across all meshes loaded from the
350
+ // same GLB, so without cloning a color/emissive change would bleed to every
351
+ // other component instance that shares the model.
352
+ if (parts[0] === 'material' && object.isMesh && object.material && !object.userData._behaviorMaterialCloned) {
353
+ object.material = object.material.clone();
354
+ object.userData._behaviorMaterialCloned = true;
355
+ }
347
356
  var target = object;
348
357
  for (var i = 0; i < parts.length - 1; i++) {
349
358
  if (target == null) {
@@ -195,8 +195,8 @@ var EnvironmentManager = /*#__PURE__*/function () {
195
195
  case 0:
196
196
  component = this.sceneViewer;
197
197
  console.debug('Starting addTexturedGround...');
198
- groundSize = 30;
199
- groundGeometry = new THREE__namespace.PlaneGeometry(groundSize, groundSize);
198
+ groundSize = 90;
199
+ groundGeometry = new THREE__namespace.CircleGeometry(groundSize / 2, 16);
200
200
  groundMaterial = new THREE__namespace.MeshStandardMaterial({
201
201
  color: 0x777777,
202
202
  metalness: 0.2,
@@ -384,7 +384,7 @@ var EnvironmentManager = /*#__PURE__*/function () {
384
384
  key: "addHorizonFog",
385
385
  value: function addHorizonFog() {
386
386
  var component = this.sceneViewer;
387
- var groundSize = 30;
387
+ var groundSize = 60;
388
388
  var fogSize = groundSize * 10;
389
389
  var fogMaterial = new THREE__namespace.ShaderMaterial({
390
390
  transparent: true,
@@ -403,7 +403,7 @@ var EnvironmentManager = /*#__PURE__*/function () {
403
403
  var fogGeometry = new THREE__namespace.PlaneGeometry(fogSize, fogSize);
404
404
  var fogPlane = new THREE__namespace.Mesh(fogGeometry, fogMaterial);
405
405
  fogPlane.rotation.x = 0; // No rotation needed for Z-up coordinate system
406
- fogPlane.position.z = -3.0; // Position fog plane below ground level
406
+ fogPlane.position.z = -8.0; // Position fog plane below ground level
407
407
  fogPlane.name = "fogPlane";
408
408
  component.scene.add(fogPlane);
409
409
  return fogPlane;
@@ -426,12 +426,10 @@ var EnvironmentManager = /*#__PURE__*/function () {
426
426
  _context4.n = 2;
427
427
  return this.addTexturedGround();
428
428
  case 2:
429
- _context4.n = 3;
430
- return this.addBrickWalls();
431
- case 3:
429
+ // await this.addBrickWalls()
432
430
  this.addHorizonFog();
433
431
  console.log('Environment initialization completed');
434
- case 4:
432
+ case 3:
435
433
  return _context4.a(2);
436
434
  }
437
435
  }, _callee4, this);
@@ -54,7 +54,7 @@ var SceneInitializationManager = /*#__PURE__*/function () {
54
54
  containerWidth = containerRect.width;
55
55
  containerHeight = containerRect.height; // Create camera (Z-up coordinate system with flipped Y)
56
56
  component.camera = new THREE__namespace.PerspectiveCamera(50, containerWidth / containerHeight, 0.01, 1000);
57
- component.camera.position.set(-8, -9, 4); // Flipped Y direction
57
+ component.camera.position.set(-8, -9, 2); // Flipped Y direction
58
58
  component.camera.up.set(0, 0, 1); // Set Z as up vector
59
59
 
60
60
  // Create renderer
@@ -1219,6 +1219,19 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1219
1219
  return b.id;
1220
1220
  }));
1221
1221
 
1222
+ // Build a set of (component::attachment::state) tuples covered by explicit
1223
+ // behaviors. If an expanded default behavior would produce the SAME input
1224
+ // tuple, the explicit behavior is treated as the intentional override and
1225
+ // the default expansion is skipped. This prevents a component's built-in
1226
+ // switch→LED wiring from doubling-up when the user has deliberately authored
1227
+ // cross-component behaviors that re-wire the same switch.
1228
+ var explicitInputTuples = new Set(explicitBehaviors.filter(function (b) {
1229
+ var _b$input, _b$input2, _b$input3;
1230
+ return ((_b$input = b.input) === null || _b$input === void 0 ? void 0 : _b$input.component) && ((_b$input2 = b.input) === null || _b$input2 === void 0 ? void 0 : _b$input2.attachment) && ((_b$input3 = b.input) === null || _b$input3 === void 0 ? void 0 : _b$input3.state);
1231
+ }).map(function (b) {
1232
+ return "".concat(b.input.component, "::").concat(b.input.attachment, "::").concat(b.input.state);
1233
+ }));
1234
+
1222
1235
  // Build a set of instanceUuids already covered by behaviorRef entries in
1223
1236
  // data.behaviors (written by the exporter for smart component defaults).
1224
1237
  // Step B skips these instances to avoid loading the same behaviors twice —
@@ -1247,10 +1260,20 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1247
1260
  var compData = componentDictionary[libraryId];
1248
1261
  if (!(compData !== null && compData !== void 0 && (_compData$defaultBeha = compData.defaultBehaviors) !== null && _compData$defaultBeha !== void 0 && _compData$defaultBeha.length)) return;
1249
1262
  compData.defaultBehaviors.forEach(function (template) {
1263
+ var _expanded$input, _expanded$input2, _expanded$input3;
1250
1264
  var expanded = _this5._expandDefaultBehavior(template, instanceUuid, componentDictionary);
1251
1265
  if (!expanded) return;
1252
1266
  // Skip if an explicit scene behavior already covers this id
1253
1267
  if (explicitIds.has(expanded.id)) return;
1268
+ // Skip if an explicit scene behavior already covers the same
1269
+ // (component, attachment, state) input tuple. This prevents a
1270
+ // component's built-in default wiring (e.g. switch → own LED) from
1271
+ // double-firing when the user has authored a cross-component override
1272
+ // that rewires the same switch to a different target.
1273
+ if ((_expanded$input = expanded.input) !== null && _expanded$input !== void 0 && _expanded$input.component && (_expanded$input2 = expanded.input) !== null && _expanded$input2 !== void 0 && _expanded$input2.attachment && (_expanded$input3 = expanded.input) !== null && _expanded$input3 !== void 0 && _expanded$input3.state) {
1274
+ var tuple = "".concat(expanded.input.component, "::").concat(expanded.input.attachment, "::").concat(expanded.input.state);
1275
+ if (explicitInputTuples.has(tuple)) return;
1276
+ }
1254
1277
  // All component defaultBehaviors are re-derivable from the component
1255
1278
  // asset at export time (via compact behaviorRef), so mark them all.
1256
1279
  expanded._isDefaultBehavior = true;
@@ -15,7 +15,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
15
15
  * Initialize the CentralPlant manager
16
16
  *
17
17
  * @constructor
18
- * @version 0.1.95
18
+ * @version 0.1.97
19
19
  * @updated 2025-10-22
20
20
  *
21
21
  * @description Creates a new CentralPlant instance and initializes internal managers and utilities.
@@ -340,6 +340,15 @@ var BehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
340
340
  value: function _applyAction(object, propertyPath, value) {
341
341
  if (!object || typeof propertyPath !== 'string') return;
342
342
  var parts = propertyPath.split('.');
343
+
344
+ // Clone shared material onto this mesh before mutating any material property.
345
+ // Three.js reuses the same Material instance across all meshes loaded from the
346
+ // same GLB, so without cloning a color/emissive change would bleed to every
347
+ // other component instance that shares the model.
348
+ if (parts[0] === 'material' && object.isMesh && object.material && !object.userData._behaviorMaterialCloned) {
349
+ object.material = object.material.clone();
350
+ object.userData._behaviorMaterialCloned = true;
351
+ }
343
352
  var target = object;
344
353
  for (var i = 0; i < parts.length - 1; i++) {
345
354
  if (target == null) {
@@ -171,8 +171,8 @@ var EnvironmentManager = /*#__PURE__*/function () {
171
171
  case 0:
172
172
  component = this.sceneViewer;
173
173
  console.debug('Starting addTexturedGround...');
174
- groundSize = 30;
175
- groundGeometry = new THREE.PlaneGeometry(groundSize, groundSize);
174
+ groundSize = 90;
175
+ groundGeometry = new THREE.CircleGeometry(groundSize / 2, 16);
176
176
  groundMaterial = new THREE.MeshStandardMaterial({
177
177
  color: 0x777777,
178
178
  metalness: 0.2,
@@ -360,7 +360,7 @@ var EnvironmentManager = /*#__PURE__*/function () {
360
360
  key: "addHorizonFog",
361
361
  value: function addHorizonFog() {
362
362
  var component = this.sceneViewer;
363
- var groundSize = 30;
363
+ var groundSize = 60;
364
364
  var fogSize = groundSize * 10;
365
365
  var fogMaterial = new THREE.ShaderMaterial({
366
366
  transparent: true,
@@ -379,7 +379,7 @@ var EnvironmentManager = /*#__PURE__*/function () {
379
379
  var fogGeometry = new THREE.PlaneGeometry(fogSize, fogSize);
380
380
  var fogPlane = new THREE.Mesh(fogGeometry, fogMaterial);
381
381
  fogPlane.rotation.x = 0; // No rotation needed for Z-up coordinate system
382
- fogPlane.position.z = -3.0; // Position fog plane below ground level
382
+ fogPlane.position.z = -8.0; // Position fog plane below ground level
383
383
  fogPlane.name = "fogPlane";
384
384
  component.scene.add(fogPlane);
385
385
  return fogPlane;
@@ -402,12 +402,10 @@ var EnvironmentManager = /*#__PURE__*/function () {
402
402
  _context4.n = 2;
403
403
  return this.addTexturedGround();
404
404
  case 2:
405
- _context4.n = 3;
406
- return this.addBrickWalls();
407
- case 3:
405
+ // await this.addBrickWalls()
408
406
  this.addHorizonFog();
409
407
  console.log('Environment initialization completed');
410
- case 4:
408
+ case 3:
411
409
  return _context4.a(2);
412
410
  }
413
411
  }, _callee4, this);
@@ -30,7 +30,7 @@ var SceneInitializationManager = /*#__PURE__*/function () {
30
30
  containerWidth = containerRect.width;
31
31
  containerHeight = containerRect.height; // Create camera (Z-up coordinate system with flipped Y)
32
32
  component.camera = new THREE.PerspectiveCamera(50, containerWidth / containerHeight, 0.01, 1000);
33
- component.camera.position.set(-8, -9, 4); // Flipped Y direction
33
+ component.camera.position.set(-8, -9, 2); // Flipped Y direction
34
34
  component.camera.up.set(0, 0, 1); // Set Z as up vector
35
35
 
36
36
  // Create renderer
@@ -1195,6 +1195,19 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1195
1195
  return b.id;
1196
1196
  }));
1197
1197
 
1198
+ // Build a set of (component::attachment::state) tuples covered by explicit
1199
+ // behaviors. If an expanded default behavior would produce the SAME input
1200
+ // tuple, the explicit behavior is treated as the intentional override and
1201
+ // the default expansion is skipped. This prevents a component's built-in
1202
+ // switch→LED wiring from doubling-up when the user has deliberately authored
1203
+ // cross-component behaviors that re-wire the same switch.
1204
+ var explicitInputTuples = new Set(explicitBehaviors.filter(function (b) {
1205
+ var _b$input, _b$input2, _b$input3;
1206
+ return ((_b$input = b.input) === null || _b$input === void 0 ? void 0 : _b$input.component) && ((_b$input2 = b.input) === null || _b$input2 === void 0 ? void 0 : _b$input2.attachment) && ((_b$input3 = b.input) === null || _b$input3 === void 0 ? void 0 : _b$input3.state);
1207
+ }).map(function (b) {
1208
+ return "".concat(b.input.component, "::").concat(b.input.attachment, "::").concat(b.input.state);
1209
+ }));
1210
+
1198
1211
  // Build a set of instanceUuids already covered by behaviorRef entries in
1199
1212
  // data.behaviors (written by the exporter for smart component defaults).
1200
1213
  // Step B skips these instances to avoid loading the same behaviors twice —
@@ -1223,10 +1236,20 @@ var SceneOperationsManager = /*#__PURE__*/function () {
1223
1236
  var compData = componentDictionary[libraryId];
1224
1237
  if (!(compData !== null && compData !== void 0 && (_compData$defaultBeha = compData.defaultBehaviors) !== null && _compData$defaultBeha !== void 0 && _compData$defaultBeha.length)) return;
1225
1238
  compData.defaultBehaviors.forEach(function (template) {
1239
+ var _expanded$input, _expanded$input2, _expanded$input3;
1226
1240
  var expanded = _this5._expandDefaultBehavior(template, instanceUuid, componentDictionary);
1227
1241
  if (!expanded) return;
1228
1242
  // Skip if an explicit scene behavior already covers this id
1229
1243
  if (explicitIds.has(expanded.id)) return;
1244
+ // Skip if an explicit scene behavior already covers the same
1245
+ // (component, attachment, state) input tuple. This prevents a
1246
+ // component's built-in default wiring (e.g. switch → own LED) from
1247
+ // double-firing when the user has authored a cross-component override
1248
+ // that rewires the same switch to a different target.
1249
+ if ((_expanded$input = expanded.input) !== null && _expanded$input !== void 0 && _expanded$input.component && (_expanded$input2 = expanded.input) !== null && _expanded$input2 !== void 0 && _expanded$input2.attachment && (_expanded$input3 = expanded.input) !== null && _expanded$input3 !== void 0 && _expanded$input3.state) {
1250
+ var tuple = "".concat(expanded.input.component, "::").concat(expanded.input.attachment, "::").concat(expanded.input.state);
1251
+ if (explicitInputTuples.has(tuple)) return;
1252
+ }
1230
1253
  // All component defaultBehaviors are re-derivable from the component
1231
1254
  // asset at export time (via compact behaviorRef), so mark them all.
1232
1255
  expanded._isDefaultBehavior = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@2112-lab/central-plant",
3
- "version": "0.1.95",
3
+ "version": "0.1.97",
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",