@2112-lab/central-plant 0.2.5 → 0.2.8
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 +199 -18
- package/dist/cjs/src/core/centralPlant.js +118 -1
- package/dist/cjs/src/core/centralPlantInternals.js +81 -17
- package/dist/esm/src/core/centralPlant.js +118 -1
- package/dist/esm/src/core/centralPlantInternals.js +81 -17
- package/dist/index.d.ts +19 -0
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -36042,6 +36042,59 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
36042
36042
|
}]);
|
|
36043
36043
|
}(BaseDisposable);
|
|
36044
36044
|
|
|
36045
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
36046
|
+
// Flow-direction helpers (module-level)
|
|
36047
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
36048
|
+
|
|
36049
|
+
/**
|
|
36050
|
+
* Returns the flow direction of a connector from the current scene data.
|
|
36051
|
+
* @param {Object} sceneData - currentSceneData object
|
|
36052
|
+
* @param {string} connectorId
|
|
36053
|
+
* @returns {'in'|'out'|'bi'} Defaults to 'bi' if not set.
|
|
36054
|
+
*/
|
|
36055
|
+
function _getConnectorFlow(sceneData, connectorId) {
|
|
36056
|
+
var _sceneData$scene;
|
|
36057
|
+
var children = (sceneData === null || sceneData === void 0 || (_sceneData$scene = sceneData.scene) === null || _sceneData$scene === void 0 ? void 0 : _sceneData$scene.children) || [];
|
|
36058
|
+
var _iterator = _createForOfIteratorHelper(children),
|
|
36059
|
+
_step;
|
|
36060
|
+
try {
|
|
36061
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
36062
|
+
var component = _step.value;
|
|
36063
|
+
var _iterator2 = _createForOfIteratorHelper(component.children || []),
|
|
36064
|
+
_step2;
|
|
36065
|
+
try {
|
|
36066
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
36067
|
+
var _child$userData;
|
|
36068
|
+
var child = _step2.value;
|
|
36069
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector' && child.uuid === connectorId) {
|
|
36070
|
+
return child.userData.flow || 'bi';
|
|
36071
|
+
}
|
|
36072
|
+
}
|
|
36073
|
+
} catch (err) {
|
|
36074
|
+
_iterator2.e(err);
|
|
36075
|
+
} finally {
|
|
36076
|
+
_iterator2.f();
|
|
36077
|
+
}
|
|
36078
|
+
}
|
|
36079
|
+
} catch (err) {
|
|
36080
|
+
_iterator.e(err);
|
|
36081
|
+
} finally {
|
|
36082
|
+
_iterator.f();
|
|
36083
|
+
}
|
|
36084
|
+
return 'bi';
|
|
36085
|
+
}
|
|
36086
|
+
|
|
36087
|
+
/**
|
|
36088
|
+
* Returns true if fromFlow → toFlow is a valid connection.
|
|
36089
|
+
* @param {'in'|'out'|'bi'} fromFlow
|
|
36090
|
+
* @param {'in'|'out'|'bi'} toFlow
|
|
36091
|
+
* @returns {boolean}
|
|
36092
|
+
*/
|
|
36093
|
+
function _areFlowsCompatible$1(fromFlow, toFlow) {
|
|
36094
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
36095
|
+
return fromFlow !== toFlow;
|
|
36096
|
+
}
|
|
36097
|
+
|
|
36045
36098
|
/**
|
|
36046
36099
|
* CentralPlantInternals class containing internal methods and functionality
|
|
36047
36100
|
*/
|
|
@@ -36493,12 +36546,12 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36493
36546
|
console.log("\uD83D\uDD27 Translating ".concat(selectedObjects.length, " selected object(s) on ").concat(axis, " axis by ").concat(value));
|
|
36494
36547
|
|
|
36495
36548
|
// Translate each selected object using the appropriate method
|
|
36496
|
-
var
|
|
36497
|
-
|
|
36549
|
+
var _iterator3 = _createForOfIteratorHelper(selectedObjects),
|
|
36550
|
+
_step3;
|
|
36498
36551
|
try {
|
|
36499
|
-
for (
|
|
36552
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
36500
36553
|
var _obj$userData;
|
|
36501
|
-
var obj =
|
|
36554
|
+
var obj = _step3.value;
|
|
36502
36555
|
var objectType = (_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType;
|
|
36503
36556
|
var objectId = obj.uuid;
|
|
36504
36557
|
var success = false;
|
|
@@ -36525,9 +36578,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36525
36578
|
}
|
|
36526
36579
|
}
|
|
36527
36580
|
} catch (err) {
|
|
36528
|
-
|
|
36581
|
+
_iterator3.e(err);
|
|
36529
36582
|
} finally {
|
|
36530
|
-
|
|
36583
|
+
_iterator3.f();
|
|
36531
36584
|
}
|
|
36532
36585
|
result.success = result.translatedCount === result.totalCount;
|
|
36533
36586
|
if (result.success) {
|
|
@@ -36711,7 +36764,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36711
36764
|
}, {
|
|
36712
36765
|
key: "addConnection",
|
|
36713
36766
|
value: function addConnection(fromConnectorId, toConnectorId) {
|
|
36714
|
-
var _this$centralPlant$sc4;
|
|
36767
|
+
var _this$centralPlant$sc4, _this$centralPlant$sc5;
|
|
36715
36768
|
// Use centralized validation for connection parameters
|
|
36716
36769
|
var existingConnections = ((_this$centralPlant$sc4 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc4 === void 0 || (_this$centralPlant$sc4 = _this$centralPlant$sc4.currentSceneData) === null || _this$centralPlant$sc4 === void 0 ? void 0 : _this$centralPlant$sc4.connections) || [];
|
|
36717
36770
|
var validation = this.validator.validateConnectionParams(fromConnectorId, toConnectorId, existingConnections);
|
|
@@ -36719,6 +36772,17 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36719
36772
|
return false; // Validator already logged the error
|
|
36720
36773
|
}
|
|
36721
36774
|
|
|
36775
|
+
// Validate flow direction compatibility
|
|
36776
|
+
var sceneData = (_this$centralPlant$sc5 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc5 === void 0 ? void 0 : _this$centralPlant$sc5.currentSceneData;
|
|
36777
|
+
if (sceneData) {
|
|
36778
|
+
var fromFlow = _getConnectorFlow(sceneData, fromConnectorId);
|
|
36779
|
+
var toFlow = _getConnectorFlow(sceneData, toConnectorId);
|
|
36780
|
+
if (!_areFlowsCompatible$1(fromFlow, toFlow)) {
|
|
36781
|
+
console.error("\u274C addConnection(): Incompatible flow directions \u2014 '".concat(fromConnectorId, "' is '").concat(fromFlow, "' and '").concat(toConnectorId, "' is '").concat(toFlow, "'. ") + "'".concat(fromFlow, "' \u2192 '").concat(toFlow, "' connections are not allowed."));
|
|
36782
|
+
return false;
|
|
36783
|
+
}
|
|
36784
|
+
}
|
|
36785
|
+
|
|
36722
36786
|
// Validate scene availability
|
|
36723
36787
|
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer);
|
|
36724
36788
|
if (!sceneValidation.isValid) {
|
|
@@ -36839,7 +36903,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36839
36903
|
}, {
|
|
36840
36904
|
key: "addComponent",
|
|
36841
36905
|
value: function addComponent(libraryId) {
|
|
36842
|
-
var _this$centralPlant$
|
|
36906
|
+
var _this$centralPlant$sc6;
|
|
36843
36907
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
36844
36908
|
// Use centralized validation for component addition parameters
|
|
36845
36909
|
var existingIds = this.getComponentIds();
|
|
@@ -36849,7 +36913,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36849
36913
|
}
|
|
36850
36914
|
|
|
36851
36915
|
// Validate scene availability
|
|
36852
|
-
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$
|
|
36916
|
+
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$sc6 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc6 === void 0 ? void 0 : _this$centralPlant$sc6.scene);
|
|
36853
36917
|
if (!sceneValidation.isValid) {
|
|
36854
36918
|
return false;
|
|
36855
36919
|
}
|
|
@@ -36868,7 +36932,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36868
36932
|
return false;
|
|
36869
36933
|
}
|
|
36870
36934
|
try {
|
|
36871
|
-
var _componentData$childr, _componentData$childr2, _this$centralPlant$
|
|
36935
|
+
var _componentData$childr, _componentData$childr2, _this$centralPlant$sc7, _componentData$childr3, _componentData$defaul;
|
|
36872
36936
|
// Generate a unique component ID if not provided
|
|
36873
36937
|
var componentId = options.customId || this.generateUniqueComponentId(libraryId);
|
|
36874
36938
|
|
|
@@ -36980,7 +37044,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36980
37044
|
componentModel.updateMatrixWorld(true);
|
|
36981
37045
|
|
|
36982
37046
|
// Check if component is underground and fix if needed (based on settings)
|
|
36983
|
-
var checkUnderground = (_this$centralPlant$
|
|
37047
|
+
var checkUnderground = (_this$centralPlant$sc7 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc7 === void 0 || (_this$centralPlant$sc7 = _this$centralPlant$sc7.managers) === null || _this$centralPlant$sc7 === void 0 || (_this$centralPlant$sc7 = _this$centralPlant$sc7.settingsManager) === null || _this$centralPlant$sc7 === void 0 ? void 0 : _this$centralPlant$sc7.getSetting('scene', 'checkUnderground');
|
|
36984
37048
|
if (checkUnderground) {
|
|
36985
37049
|
var wasFixed = this.fixUndergroundComponent(componentModel);
|
|
36986
37050
|
if (wasFixed) {
|
|
@@ -37078,8 +37142,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37078
37142
|
// responds to tooltip-driven state changes immediately after drop.
|
|
37079
37143
|
// (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
|
|
37080
37144
|
if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
|
|
37081
|
-
var _this$centralPlant$
|
|
37082
|
-
var som = (_this$centralPlant$
|
|
37145
|
+
var _this$centralPlant$sc8, _som$registerBehavior;
|
|
37146
|
+
var som = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.sceneOperationsManager;
|
|
37083
37147
|
som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
|
|
37084
37148
|
}
|
|
37085
37149
|
|
|
@@ -37141,9 +37205,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37141
37205
|
}, {
|
|
37142
37206
|
key: "deleteComponent",
|
|
37143
37207
|
value: function deleteComponent(componentId) {
|
|
37144
|
-
var _this$centralPlant$
|
|
37208
|
+
var _this$centralPlant$sc9;
|
|
37145
37209
|
// Check if component manager is available
|
|
37146
|
-
var componentManager = (_this$centralPlant$
|
|
37210
|
+
var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
|
|
37147
37211
|
if (!componentManager) {
|
|
37148
37212
|
console.error('❌ deleteComponent(): Component manager not available');
|
|
37149
37213
|
return false;
|
|
@@ -37218,8 +37282,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37218
37282
|
}
|
|
37219
37283
|
var componentIds = [];
|
|
37220
37284
|
this.centralPlant.sceneViewer.scene.traverse(function (child) {
|
|
37221
|
-
var _child$
|
|
37222
|
-
if (((_child$
|
|
37285
|
+
var _child$userData2;
|
|
37286
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'component') {
|
|
37223
37287
|
componentIds.push(child.uuid || child.userData.originalUuid);
|
|
37224
37288
|
}
|
|
37225
37289
|
});
|
|
@@ -37228,6 +37292,22 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37228
37292
|
}]);
|
|
37229
37293
|
}();
|
|
37230
37294
|
|
|
37295
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
37296
|
+
// Flow-direction compatibility helper (module-level, no class dependency)
|
|
37297
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
37298
|
+
|
|
37299
|
+
/**
|
|
37300
|
+
* Returns true if the two flow directions are compatible for a connection.
|
|
37301
|
+
* @param {string} fromFlow - 'in' | 'out' | 'bi'
|
|
37302
|
+
* @param {string} toFlow - 'in' | 'out' | 'bi'
|
|
37303
|
+
* @returns {boolean}
|
|
37304
|
+
*/
|
|
37305
|
+
function _areFlowsCompatible(fromFlow, toFlow) {
|
|
37306
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
37307
|
+
// in ↔ out are compatible; in → in and out → out are not
|
|
37308
|
+
return fromFlow !== toFlow;
|
|
37309
|
+
}
|
|
37310
|
+
|
|
37231
37311
|
/**
|
|
37232
37312
|
* CentralPlant class that manages all scene utility instances and provides public API
|
|
37233
37313
|
*
|
|
@@ -37238,7 +37318,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
37238
37318
|
* Initialize the CentralPlant manager
|
|
37239
37319
|
*
|
|
37240
37320
|
* @constructor
|
|
37241
|
-
* @version 0.2.
|
|
37321
|
+
* @version 0.2.8
|
|
37242
37322
|
* @updated 2025-10-22
|
|
37243
37323
|
*
|
|
37244
37324
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -38171,6 +38251,107 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38171
38251
|
return availableConnectorIds;
|
|
38172
38252
|
}
|
|
38173
38253
|
|
|
38254
|
+
/**
|
|
38255
|
+
* Get available connectors with their flow direction metadata.
|
|
38256
|
+
* Same filtering logic as getAvailableConnections() but returns objects instead of strings.
|
|
38257
|
+
* @returns {Array<{id: string, flow: string}>} Array of connector info objects.
|
|
38258
|
+
* flow is one of 'in', 'out', 'bi'. Defaults to 'bi' if not set in userData.
|
|
38259
|
+
* @example
|
|
38260
|
+
* const infos = centralPlant.getAvailableConnectionsInfo()
|
|
38261
|
+
* // [{ id: 'PUMP-1-CONNECTOR-1', flow: 'out' }, ...]
|
|
38262
|
+
*/
|
|
38263
|
+
}, {
|
|
38264
|
+
key: "getAvailableConnectionsInfo",
|
|
38265
|
+
value: function getAvailableConnectionsInfo() {
|
|
38266
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
38267
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or current scene data not available');
|
|
38268
|
+
return [];
|
|
38269
|
+
}
|
|
38270
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
38271
|
+
if (!sceneData.scene || !sceneData.scene.children) {
|
|
38272
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Invalid scene data structure');
|
|
38273
|
+
return [];
|
|
38274
|
+
}
|
|
38275
|
+
var allConnectorInfos = [];
|
|
38276
|
+
sceneData.scene.children.forEach(function (component) {
|
|
38277
|
+
if (component.children && Array.isArray(component.children)) {
|
|
38278
|
+
component.children.forEach(function (child) {
|
|
38279
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
38280
|
+
allConnectorInfos.push({
|
|
38281
|
+
id: child.uuid,
|
|
38282
|
+
flow: child.userData.flow || 'bi'
|
|
38283
|
+
});
|
|
38284
|
+
}
|
|
38285
|
+
});
|
|
38286
|
+
}
|
|
38287
|
+
});
|
|
38288
|
+
var existingConnections = this.getConnections();
|
|
38289
|
+
var usedConnectorIds = new Set();
|
|
38290
|
+
existingConnections.forEach(function (connection) {
|
|
38291
|
+
if (connection.from) usedConnectorIds.add(connection.from);
|
|
38292
|
+
if (connection.to) usedConnectorIds.add(connection.to);
|
|
38293
|
+
});
|
|
38294
|
+
return allConnectorInfos.filter(function (info) {
|
|
38295
|
+
return !usedConnectorIds.has(info.id);
|
|
38296
|
+
});
|
|
38297
|
+
}
|
|
38298
|
+
|
|
38299
|
+
/**
|
|
38300
|
+
* Validate all connections in the current scene for flow direction compatibility.
|
|
38301
|
+
* @returns {{ valid: Array<Object>, invalid: Array<{connection: Object, reason: string}> }}
|
|
38302
|
+
* @example
|
|
38303
|
+
* const result = centralPlant.validateConnections()
|
|
38304
|
+
* result.invalid.forEach(({ connection, reason }) => console.warn(reason, connection))
|
|
38305
|
+
*/
|
|
38306
|
+
}, {
|
|
38307
|
+
key: "validateConnections",
|
|
38308
|
+
value: function validateConnections() {
|
|
38309
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
38310
|
+
console.warn('⚠️ validateConnections(): Scene viewer or current scene data not available');
|
|
38311
|
+
return {
|
|
38312
|
+
valid: [],
|
|
38313
|
+
invalid: []
|
|
38314
|
+
};
|
|
38315
|
+
}
|
|
38316
|
+
var connections = this.getConnections();
|
|
38317
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
38318
|
+
|
|
38319
|
+
// Build lookup map: connectorId → flow
|
|
38320
|
+
var flowMap = {};
|
|
38321
|
+
var scene = sceneData.scene || {};
|
|
38322
|
+
var children = scene.children || [];
|
|
38323
|
+
children.forEach(function (component) {
|
|
38324
|
+
if (component.children && Array.isArray(component.children)) {
|
|
38325
|
+
component.children.forEach(function (child) {
|
|
38326
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
38327
|
+
flowMap[child.uuid] = child.userData.flow || 'bi';
|
|
38328
|
+
}
|
|
38329
|
+
});
|
|
38330
|
+
}
|
|
38331
|
+
});
|
|
38332
|
+
var valid = [];
|
|
38333
|
+
var invalid = [];
|
|
38334
|
+
connections.forEach(function (connection) {
|
|
38335
|
+
var fromFlow = flowMap[connection.from] || 'bi';
|
|
38336
|
+
var toFlow = flowMap[connection.to] || 'bi';
|
|
38337
|
+
if (_areFlowsCompatible(fromFlow, toFlow)) {
|
|
38338
|
+
valid.push(connection);
|
|
38339
|
+
} else {
|
|
38340
|
+
var reason = "Incompatible flow directions: connector '".concat(connection.from, "' is '").concat(fromFlow, "' and connector '").concat(connection.to, "' is '").concat(toFlow, "' \u2014 ").concat(fromFlow, " \u2192 ").concat(toFlow, " is not allowed");
|
|
38341
|
+
console.warn("\u26A0\uFE0F validateConnections(): ".concat(reason));
|
|
38342
|
+
invalid.push({
|
|
38343
|
+
connection: connection,
|
|
38344
|
+
reason: reason
|
|
38345
|
+
});
|
|
38346
|
+
}
|
|
38347
|
+
});
|
|
38348
|
+
console.log("\u2705 validateConnections(): ".concat(valid.length, " valid, ").concat(invalid.length, " invalid connections"));
|
|
38349
|
+
return {
|
|
38350
|
+
valid: valid,
|
|
38351
|
+
invalid: invalid
|
|
38352
|
+
};
|
|
38353
|
+
}
|
|
38354
|
+
|
|
38174
38355
|
// ─────────────────────────────────────────────────────────────────────────
|
|
38175
38356
|
// BEHAVIORS API
|
|
38176
38357
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -9,6 +9,22 @@ var DisposalUtilities = require('../utils/DisposalUtilities.js');
|
|
|
9
9
|
var centralPlantInternals = require('./centralPlantInternals.js');
|
|
10
10
|
require('../rendering/modelPreloader.js');
|
|
11
11
|
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
// Flow-direction compatibility helper (module-level, no class dependency)
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Returns true if the two flow directions are compatible for a connection.
|
|
18
|
+
* @param {string} fromFlow - 'in' | 'out' | 'bi'
|
|
19
|
+
* @param {string} toFlow - 'in' | 'out' | 'bi'
|
|
20
|
+
* @returns {boolean}
|
|
21
|
+
*/
|
|
22
|
+
function _areFlowsCompatible(fromFlow, toFlow) {
|
|
23
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
24
|
+
// in ↔ out are compatible; in → in and out → out are not
|
|
25
|
+
return fromFlow !== toFlow;
|
|
26
|
+
}
|
|
27
|
+
|
|
12
28
|
/**
|
|
13
29
|
* CentralPlant class that manages all scene utility instances and provides public API
|
|
14
30
|
*
|
|
@@ -19,7 +35,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
19
35
|
* Initialize the CentralPlant manager
|
|
20
36
|
*
|
|
21
37
|
* @constructor
|
|
22
|
-
* @version 0.2.
|
|
38
|
+
* @version 0.2.8
|
|
23
39
|
* @updated 2025-10-22
|
|
24
40
|
*
|
|
25
41
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -952,6 +968,107 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
952
968
|
return availableConnectorIds;
|
|
953
969
|
}
|
|
954
970
|
|
|
971
|
+
/**
|
|
972
|
+
* Get available connectors with their flow direction metadata.
|
|
973
|
+
* Same filtering logic as getAvailableConnections() but returns objects instead of strings.
|
|
974
|
+
* @returns {Array<{id: string, flow: string}>} Array of connector info objects.
|
|
975
|
+
* flow is one of 'in', 'out', 'bi'. Defaults to 'bi' if not set in userData.
|
|
976
|
+
* @example
|
|
977
|
+
* const infos = centralPlant.getAvailableConnectionsInfo()
|
|
978
|
+
* // [{ id: 'PUMP-1-CONNECTOR-1', flow: 'out' }, ...]
|
|
979
|
+
*/
|
|
980
|
+
}, {
|
|
981
|
+
key: "getAvailableConnectionsInfo",
|
|
982
|
+
value: function getAvailableConnectionsInfo() {
|
|
983
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
984
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or current scene data not available');
|
|
985
|
+
return [];
|
|
986
|
+
}
|
|
987
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
988
|
+
if (!sceneData.scene || !sceneData.scene.children) {
|
|
989
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Invalid scene data structure');
|
|
990
|
+
return [];
|
|
991
|
+
}
|
|
992
|
+
var allConnectorInfos = [];
|
|
993
|
+
sceneData.scene.children.forEach(function (component) {
|
|
994
|
+
if (component.children && Array.isArray(component.children)) {
|
|
995
|
+
component.children.forEach(function (child) {
|
|
996
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
997
|
+
allConnectorInfos.push({
|
|
998
|
+
id: child.uuid,
|
|
999
|
+
flow: child.userData.flow || 'bi'
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
});
|
|
1005
|
+
var existingConnections = this.getConnections();
|
|
1006
|
+
var usedConnectorIds = new Set();
|
|
1007
|
+
existingConnections.forEach(function (connection) {
|
|
1008
|
+
if (connection.from) usedConnectorIds.add(connection.from);
|
|
1009
|
+
if (connection.to) usedConnectorIds.add(connection.to);
|
|
1010
|
+
});
|
|
1011
|
+
return allConnectorInfos.filter(function (info) {
|
|
1012
|
+
return !usedConnectorIds.has(info.id);
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Validate all connections in the current scene for flow direction compatibility.
|
|
1018
|
+
* @returns {{ valid: Array<Object>, invalid: Array<{connection: Object, reason: string}> }}
|
|
1019
|
+
* @example
|
|
1020
|
+
* const result = centralPlant.validateConnections()
|
|
1021
|
+
* result.invalid.forEach(({ connection, reason }) => console.warn(reason, connection))
|
|
1022
|
+
*/
|
|
1023
|
+
}, {
|
|
1024
|
+
key: "validateConnections",
|
|
1025
|
+
value: function validateConnections() {
|
|
1026
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
1027
|
+
console.warn('⚠️ validateConnections(): Scene viewer or current scene data not available');
|
|
1028
|
+
return {
|
|
1029
|
+
valid: [],
|
|
1030
|
+
invalid: []
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
var connections = this.getConnections();
|
|
1034
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
1035
|
+
|
|
1036
|
+
// Build lookup map: connectorId → flow
|
|
1037
|
+
var flowMap = {};
|
|
1038
|
+
var scene = sceneData.scene || {};
|
|
1039
|
+
var children = scene.children || [];
|
|
1040
|
+
children.forEach(function (component) {
|
|
1041
|
+
if (component.children && Array.isArray(component.children)) {
|
|
1042
|
+
component.children.forEach(function (child) {
|
|
1043
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
1044
|
+
flowMap[child.uuid] = child.userData.flow || 'bi';
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
var valid = [];
|
|
1050
|
+
var invalid = [];
|
|
1051
|
+
connections.forEach(function (connection) {
|
|
1052
|
+
var fromFlow = flowMap[connection.from] || 'bi';
|
|
1053
|
+
var toFlow = flowMap[connection.to] || 'bi';
|
|
1054
|
+
if (_areFlowsCompatible(fromFlow, toFlow)) {
|
|
1055
|
+
valid.push(connection);
|
|
1056
|
+
} else {
|
|
1057
|
+
var reason = "Incompatible flow directions: connector '".concat(connection.from, "' is '").concat(fromFlow, "' and connector '").concat(connection.to, "' is '").concat(toFlow, "' \u2014 ").concat(fromFlow, " \u2192 ").concat(toFlow, " is not allowed");
|
|
1058
|
+
console.warn("\u26A0\uFE0F validateConnections(): ".concat(reason));
|
|
1059
|
+
invalid.push({
|
|
1060
|
+
connection: connection,
|
|
1061
|
+
reason: reason
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
console.log("\u2705 validateConnections(): ".concat(valid.length, " valid, ").concat(invalid.length, " invalid connections"));
|
|
1066
|
+
return {
|
|
1067
|
+
valid: valid,
|
|
1068
|
+
invalid: invalid
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
|
|
955
1072
|
// ─────────────────────────────────────────────────────────────────────────
|
|
956
1073
|
// BEHAVIORS API
|
|
957
1074
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -50,6 +50,59 @@ function _interopNamespace(e) {
|
|
|
50
50
|
|
|
51
51
|
var THREE__namespace = /*#__PURE__*/_interopNamespace(THREE);
|
|
52
52
|
|
|
53
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
54
|
+
// Flow-direction helpers (module-level)
|
|
55
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns the flow direction of a connector from the current scene data.
|
|
59
|
+
* @param {Object} sceneData - currentSceneData object
|
|
60
|
+
* @param {string} connectorId
|
|
61
|
+
* @returns {'in'|'out'|'bi'} Defaults to 'bi' if not set.
|
|
62
|
+
*/
|
|
63
|
+
function _getConnectorFlow(sceneData, connectorId) {
|
|
64
|
+
var _sceneData$scene;
|
|
65
|
+
var children = (sceneData === null || sceneData === void 0 || (_sceneData$scene = sceneData.scene) === null || _sceneData$scene === void 0 ? void 0 : _sceneData$scene.children) || [];
|
|
66
|
+
var _iterator = _rollupPluginBabelHelpers.createForOfIteratorHelper(children),
|
|
67
|
+
_step;
|
|
68
|
+
try {
|
|
69
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
70
|
+
var component = _step.value;
|
|
71
|
+
var _iterator2 = _rollupPluginBabelHelpers.createForOfIteratorHelper(component.children || []),
|
|
72
|
+
_step2;
|
|
73
|
+
try {
|
|
74
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
75
|
+
var _child$userData;
|
|
76
|
+
var child = _step2.value;
|
|
77
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector' && child.uuid === connectorId) {
|
|
78
|
+
return child.userData.flow || 'bi';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} catch (err) {
|
|
82
|
+
_iterator2.e(err);
|
|
83
|
+
} finally {
|
|
84
|
+
_iterator2.f();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
} catch (err) {
|
|
88
|
+
_iterator.e(err);
|
|
89
|
+
} finally {
|
|
90
|
+
_iterator.f();
|
|
91
|
+
}
|
|
92
|
+
return 'bi';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns true if fromFlow → toFlow is a valid connection.
|
|
97
|
+
* @param {'in'|'out'|'bi'} fromFlow
|
|
98
|
+
* @param {'in'|'out'|'bi'} toFlow
|
|
99
|
+
* @returns {boolean}
|
|
100
|
+
*/
|
|
101
|
+
function _areFlowsCompatible(fromFlow, toFlow) {
|
|
102
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
103
|
+
return fromFlow !== toFlow;
|
|
104
|
+
}
|
|
105
|
+
|
|
53
106
|
/**
|
|
54
107
|
* CentralPlantInternals class containing internal methods and functionality
|
|
55
108
|
*/
|
|
@@ -501,12 +554,12 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
501
554
|
console.log("\uD83D\uDD27 Translating ".concat(selectedObjects.length, " selected object(s) on ").concat(axis, " axis by ").concat(value));
|
|
502
555
|
|
|
503
556
|
// Translate each selected object using the appropriate method
|
|
504
|
-
var
|
|
505
|
-
|
|
557
|
+
var _iterator3 = _rollupPluginBabelHelpers.createForOfIteratorHelper(selectedObjects),
|
|
558
|
+
_step3;
|
|
506
559
|
try {
|
|
507
|
-
for (
|
|
560
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
508
561
|
var _obj$userData;
|
|
509
|
-
var obj =
|
|
562
|
+
var obj = _step3.value;
|
|
510
563
|
var objectType = (_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType;
|
|
511
564
|
var objectId = obj.uuid;
|
|
512
565
|
var success = false;
|
|
@@ -533,9 +586,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
533
586
|
}
|
|
534
587
|
}
|
|
535
588
|
} catch (err) {
|
|
536
|
-
|
|
589
|
+
_iterator3.e(err);
|
|
537
590
|
} finally {
|
|
538
|
-
|
|
591
|
+
_iterator3.f();
|
|
539
592
|
}
|
|
540
593
|
result.success = result.translatedCount === result.totalCount;
|
|
541
594
|
if (result.success) {
|
|
@@ -719,7 +772,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
719
772
|
}, {
|
|
720
773
|
key: "addConnection",
|
|
721
774
|
value: function addConnection(fromConnectorId, toConnectorId) {
|
|
722
|
-
var _this$centralPlant$sc4;
|
|
775
|
+
var _this$centralPlant$sc4, _this$centralPlant$sc5;
|
|
723
776
|
// Use centralized validation for connection parameters
|
|
724
777
|
var existingConnections = ((_this$centralPlant$sc4 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc4 === void 0 || (_this$centralPlant$sc4 = _this$centralPlant$sc4.currentSceneData) === null || _this$centralPlant$sc4 === void 0 ? void 0 : _this$centralPlant$sc4.connections) || [];
|
|
725
778
|
var validation = this.validator.validateConnectionParams(fromConnectorId, toConnectorId, existingConnections);
|
|
@@ -727,6 +780,17 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
727
780
|
return false; // Validator already logged the error
|
|
728
781
|
}
|
|
729
782
|
|
|
783
|
+
// Validate flow direction compatibility
|
|
784
|
+
var sceneData = (_this$centralPlant$sc5 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc5 === void 0 ? void 0 : _this$centralPlant$sc5.currentSceneData;
|
|
785
|
+
if (sceneData) {
|
|
786
|
+
var fromFlow = _getConnectorFlow(sceneData, fromConnectorId);
|
|
787
|
+
var toFlow = _getConnectorFlow(sceneData, toConnectorId);
|
|
788
|
+
if (!_areFlowsCompatible(fromFlow, toFlow)) {
|
|
789
|
+
console.error("\u274C addConnection(): Incompatible flow directions \u2014 '".concat(fromConnectorId, "' is '").concat(fromFlow, "' and '").concat(toConnectorId, "' is '").concat(toFlow, "'. ") + "'".concat(fromFlow, "' \u2192 '").concat(toFlow, "' connections are not allowed."));
|
|
790
|
+
return false;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
730
794
|
// Validate scene availability
|
|
731
795
|
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer);
|
|
732
796
|
if (!sceneValidation.isValid) {
|
|
@@ -847,7 +911,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
847
911
|
}, {
|
|
848
912
|
key: "addComponent",
|
|
849
913
|
value: function addComponent(libraryId) {
|
|
850
|
-
var _this$centralPlant$
|
|
914
|
+
var _this$centralPlant$sc6;
|
|
851
915
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
852
916
|
// Use centralized validation for component addition parameters
|
|
853
917
|
var existingIds = this.getComponentIds();
|
|
@@ -857,7 +921,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
857
921
|
}
|
|
858
922
|
|
|
859
923
|
// Validate scene availability
|
|
860
|
-
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$
|
|
924
|
+
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$sc6 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc6 === void 0 ? void 0 : _this$centralPlant$sc6.scene);
|
|
861
925
|
if (!sceneValidation.isValid) {
|
|
862
926
|
return false;
|
|
863
927
|
}
|
|
@@ -876,7 +940,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
876
940
|
return false;
|
|
877
941
|
}
|
|
878
942
|
try {
|
|
879
|
-
var _componentData$childr, _componentData$childr2, _this$centralPlant$
|
|
943
|
+
var _componentData$childr, _componentData$childr2, _this$centralPlant$sc7, _componentData$childr3, _componentData$defaul;
|
|
880
944
|
// Generate a unique component ID if not provided
|
|
881
945
|
var componentId = options.customId || this.generateUniqueComponentId(libraryId);
|
|
882
946
|
|
|
@@ -988,7 +1052,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
988
1052
|
componentModel.updateMatrixWorld(true);
|
|
989
1053
|
|
|
990
1054
|
// Check if component is underground and fix if needed (based on settings)
|
|
991
|
-
var checkUnderground = (_this$centralPlant$
|
|
1055
|
+
var checkUnderground = (_this$centralPlant$sc7 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc7 === void 0 || (_this$centralPlant$sc7 = _this$centralPlant$sc7.managers) === null || _this$centralPlant$sc7 === void 0 || (_this$centralPlant$sc7 = _this$centralPlant$sc7.settingsManager) === null || _this$centralPlant$sc7 === void 0 ? void 0 : _this$centralPlant$sc7.getSetting('scene', 'checkUnderground');
|
|
992
1056
|
if (checkUnderground) {
|
|
993
1057
|
var wasFixed = this.fixUndergroundComponent(componentModel);
|
|
994
1058
|
if (wasFixed) {
|
|
@@ -1086,8 +1150,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1086
1150
|
// responds to tooltip-driven state changes immediately after drop.
|
|
1087
1151
|
// (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
|
|
1088
1152
|
if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
|
|
1089
|
-
var _this$centralPlant$
|
|
1090
|
-
var som = (_this$centralPlant$
|
|
1153
|
+
var _this$centralPlant$sc8, _som$registerBehavior;
|
|
1154
|
+
var som = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.sceneOperationsManager;
|
|
1091
1155
|
som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
|
|
1092
1156
|
}
|
|
1093
1157
|
|
|
@@ -1149,9 +1213,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1149
1213
|
}, {
|
|
1150
1214
|
key: "deleteComponent",
|
|
1151
1215
|
value: function deleteComponent(componentId) {
|
|
1152
|
-
var _this$centralPlant$
|
|
1216
|
+
var _this$centralPlant$sc9;
|
|
1153
1217
|
// Check if component manager is available
|
|
1154
|
-
var componentManager = (_this$centralPlant$
|
|
1218
|
+
var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
|
|
1155
1219
|
if (!componentManager) {
|
|
1156
1220
|
console.error('❌ deleteComponent(): Component manager not available');
|
|
1157
1221
|
return false;
|
|
@@ -1226,8 +1290,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1226
1290
|
}
|
|
1227
1291
|
var componentIds = [];
|
|
1228
1292
|
this.centralPlant.sceneViewer.scene.traverse(function (child) {
|
|
1229
|
-
var _child$
|
|
1230
|
-
if (((_child$
|
|
1293
|
+
var _child$userData2;
|
|
1294
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'component') {
|
|
1231
1295
|
componentIds.push(child.uuid || child.userData.originalUuid);
|
|
1232
1296
|
}
|
|
1233
1297
|
});
|
|
@@ -5,6 +5,22 @@ import { DisposalUtilities } from '../utils/DisposalUtilities.js';
|
|
|
5
5
|
import { CentralPlantInternals } from './centralPlantInternals.js';
|
|
6
6
|
import '../rendering/modelPreloader.js';
|
|
7
7
|
|
|
8
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
// Flow-direction compatibility helper (module-level, no class dependency)
|
|
10
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns true if the two flow directions are compatible for a connection.
|
|
14
|
+
* @param {string} fromFlow - 'in' | 'out' | 'bi'
|
|
15
|
+
* @param {string} toFlow - 'in' | 'out' | 'bi'
|
|
16
|
+
* @returns {boolean}
|
|
17
|
+
*/
|
|
18
|
+
function _areFlowsCompatible(fromFlow, toFlow) {
|
|
19
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
20
|
+
// in ↔ out are compatible; in → in and out → out are not
|
|
21
|
+
return fromFlow !== toFlow;
|
|
22
|
+
}
|
|
23
|
+
|
|
8
24
|
/**
|
|
9
25
|
* CentralPlant class that manages all scene utility instances and provides public API
|
|
10
26
|
*
|
|
@@ -15,7 +31,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
15
31
|
* Initialize the CentralPlant manager
|
|
16
32
|
*
|
|
17
33
|
* @constructor
|
|
18
|
-
* @version 0.2.
|
|
34
|
+
* @version 0.2.8
|
|
19
35
|
* @updated 2025-10-22
|
|
20
36
|
*
|
|
21
37
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -948,6 +964,107 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
948
964
|
return availableConnectorIds;
|
|
949
965
|
}
|
|
950
966
|
|
|
967
|
+
/**
|
|
968
|
+
* Get available connectors with their flow direction metadata.
|
|
969
|
+
* Same filtering logic as getAvailableConnections() but returns objects instead of strings.
|
|
970
|
+
* @returns {Array<{id: string, flow: string}>} Array of connector info objects.
|
|
971
|
+
* flow is one of 'in', 'out', 'bi'. Defaults to 'bi' if not set in userData.
|
|
972
|
+
* @example
|
|
973
|
+
* const infos = centralPlant.getAvailableConnectionsInfo()
|
|
974
|
+
* // [{ id: 'PUMP-1-CONNECTOR-1', flow: 'out' }, ...]
|
|
975
|
+
*/
|
|
976
|
+
}, {
|
|
977
|
+
key: "getAvailableConnectionsInfo",
|
|
978
|
+
value: function getAvailableConnectionsInfo() {
|
|
979
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
980
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or current scene data not available');
|
|
981
|
+
return [];
|
|
982
|
+
}
|
|
983
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
984
|
+
if (!sceneData.scene || !sceneData.scene.children) {
|
|
985
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Invalid scene data structure');
|
|
986
|
+
return [];
|
|
987
|
+
}
|
|
988
|
+
var allConnectorInfos = [];
|
|
989
|
+
sceneData.scene.children.forEach(function (component) {
|
|
990
|
+
if (component.children && Array.isArray(component.children)) {
|
|
991
|
+
component.children.forEach(function (child) {
|
|
992
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
993
|
+
allConnectorInfos.push({
|
|
994
|
+
id: child.uuid,
|
|
995
|
+
flow: child.userData.flow || 'bi'
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
|
+
var existingConnections = this.getConnections();
|
|
1002
|
+
var usedConnectorIds = new Set();
|
|
1003
|
+
existingConnections.forEach(function (connection) {
|
|
1004
|
+
if (connection.from) usedConnectorIds.add(connection.from);
|
|
1005
|
+
if (connection.to) usedConnectorIds.add(connection.to);
|
|
1006
|
+
});
|
|
1007
|
+
return allConnectorInfos.filter(function (info) {
|
|
1008
|
+
return !usedConnectorIds.has(info.id);
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
/**
|
|
1013
|
+
* Validate all connections in the current scene for flow direction compatibility.
|
|
1014
|
+
* @returns {{ valid: Array<Object>, invalid: Array<{connection: Object, reason: string}> }}
|
|
1015
|
+
* @example
|
|
1016
|
+
* const result = centralPlant.validateConnections()
|
|
1017
|
+
* result.invalid.forEach(({ connection, reason }) => console.warn(reason, connection))
|
|
1018
|
+
*/
|
|
1019
|
+
}, {
|
|
1020
|
+
key: "validateConnections",
|
|
1021
|
+
value: function validateConnections() {
|
|
1022
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
1023
|
+
console.warn('⚠️ validateConnections(): Scene viewer or current scene data not available');
|
|
1024
|
+
return {
|
|
1025
|
+
valid: [],
|
|
1026
|
+
invalid: []
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
var connections = this.getConnections();
|
|
1030
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
1031
|
+
|
|
1032
|
+
// Build lookup map: connectorId → flow
|
|
1033
|
+
var flowMap = {};
|
|
1034
|
+
var scene = sceneData.scene || {};
|
|
1035
|
+
var children = scene.children || [];
|
|
1036
|
+
children.forEach(function (component) {
|
|
1037
|
+
if (component.children && Array.isArray(component.children)) {
|
|
1038
|
+
component.children.forEach(function (child) {
|
|
1039
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
1040
|
+
flowMap[child.uuid] = child.userData.flow || 'bi';
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
var valid = [];
|
|
1046
|
+
var invalid = [];
|
|
1047
|
+
connections.forEach(function (connection) {
|
|
1048
|
+
var fromFlow = flowMap[connection.from] || 'bi';
|
|
1049
|
+
var toFlow = flowMap[connection.to] || 'bi';
|
|
1050
|
+
if (_areFlowsCompatible(fromFlow, toFlow)) {
|
|
1051
|
+
valid.push(connection);
|
|
1052
|
+
} else {
|
|
1053
|
+
var reason = "Incompatible flow directions: connector '".concat(connection.from, "' is '").concat(fromFlow, "' and connector '").concat(connection.to, "' is '").concat(toFlow, "' \u2014 ").concat(fromFlow, " \u2192 ").concat(toFlow, " is not allowed");
|
|
1054
|
+
console.warn("\u26A0\uFE0F validateConnections(): ".concat(reason));
|
|
1055
|
+
invalid.push({
|
|
1056
|
+
connection: connection,
|
|
1057
|
+
reason: reason
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
1061
|
+
console.log("\u2705 validateConnections(): ".concat(valid.length, " valid, ").concat(invalid.length, " invalid connections"));
|
|
1062
|
+
return {
|
|
1063
|
+
valid: valid,
|
|
1064
|
+
invalid: invalid
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
|
|
951
1068
|
// ─────────────────────────────────────────────────────────────────────────
|
|
952
1069
|
// BEHAVIORS API
|
|
953
1070
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -26,6 +26,59 @@ import { generateUuidFromName, getHardcodedUuid, findObjectByHardcodedUuid, gene
|
|
|
26
26
|
import { attachIODevicesToComponent } from '../utils/ioDeviceUtils.js';
|
|
27
27
|
import modelPreloader from '../rendering/modelPreloader.js';
|
|
28
28
|
|
|
29
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
30
|
+
// Flow-direction helpers (module-level)
|
|
31
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Returns the flow direction of a connector from the current scene data.
|
|
35
|
+
* @param {Object} sceneData - currentSceneData object
|
|
36
|
+
* @param {string} connectorId
|
|
37
|
+
* @returns {'in'|'out'|'bi'} Defaults to 'bi' if not set.
|
|
38
|
+
*/
|
|
39
|
+
function _getConnectorFlow(sceneData, connectorId) {
|
|
40
|
+
var _sceneData$scene;
|
|
41
|
+
var children = (sceneData === null || sceneData === void 0 || (_sceneData$scene = sceneData.scene) === null || _sceneData$scene === void 0 ? void 0 : _sceneData$scene.children) || [];
|
|
42
|
+
var _iterator = _createForOfIteratorHelper(children),
|
|
43
|
+
_step;
|
|
44
|
+
try {
|
|
45
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
46
|
+
var component = _step.value;
|
|
47
|
+
var _iterator2 = _createForOfIteratorHelper(component.children || []),
|
|
48
|
+
_step2;
|
|
49
|
+
try {
|
|
50
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
51
|
+
var _child$userData;
|
|
52
|
+
var child = _step2.value;
|
|
53
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector' && child.uuid === connectorId) {
|
|
54
|
+
return child.userData.flow || 'bi';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
_iterator2.e(err);
|
|
59
|
+
} finally {
|
|
60
|
+
_iterator2.f();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
_iterator.e(err);
|
|
65
|
+
} finally {
|
|
66
|
+
_iterator.f();
|
|
67
|
+
}
|
|
68
|
+
return 'bi';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Returns true if fromFlow → toFlow is a valid connection.
|
|
73
|
+
* @param {'in'|'out'|'bi'} fromFlow
|
|
74
|
+
* @param {'in'|'out'|'bi'} toFlow
|
|
75
|
+
* @returns {boolean}
|
|
76
|
+
*/
|
|
77
|
+
function _areFlowsCompatible(fromFlow, toFlow) {
|
|
78
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
79
|
+
return fromFlow !== toFlow;
|
|
80
|
+
}
|
|
81
|
+
|
|
29
82
|
/**
|
|
30
83
|
* CentralPlantInternals class containing internal methods and functionality
|
|
31
84
|
*/
|
|
@@ -477,12 +530,12 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
477
530
|
console.log("\uD83D\uDD27 Translating ".concat(selectedObjects.length, " selected object(s) on ").concat(axis, " axis by ").concat(value));
|
|
478
531
|
|
|
479
532
|
// Translate each selected object using the appropriate method
|
|
480
|
-
var
|
|
481
|
-
|
|
533
|
+
var _iterator3 = _createForOfIteratorHelper(selectedObjects),
|
|
534
|
+
_step3;
|
|
482
535
|
try {
|
|
483
|
-
for (
|
|
536
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
484
537
|
var _obj$userData;
|
|
485
|
-
var obj =
|
|
538
|
+
var obj = _step3.value;
|
|
486
539
|
var objectType = (_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType;
|
|
487
540
|
var objectId = obj.uuid;
|
|
488
541
|
var success = false;
|
|
@@ -509,9 +562,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
509
562
|
}
|
|
510
563
|
}
|
|
511
564
|
} catch (err) {
|
|
512
|
-
|
|
565
|
+
_iterator3.e(err);
|
|
513
566
|
} finally {
|
|
514
|
-
|
|
567
|
+
_iterator3.f();
|
|
515
568
|
}
|
|
516
569
|
result.success = result.translatedCount === result.totalCount;
|
|
517
570
|
if (result.success) {
|
|
@@ -695,7 +748,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
695
748
|
}, {
|
|
696
749
|
key: "addConnection",
|
|
697
750
|
value: function addConnection(fromConnectorId, toConnectorId) {
|
|
698
|
-
var _this$centralPlant$sc4;
|
|
751
|
+
var _this$centralPlant$sc4, _this$centralPlant$sc5;
|
|
699
752
|
// Use centralized validation for connection parameters
|
|
700
753
|
var existingConnections = ((_this$centralPlant$sc4 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc4 === void 0 || (_this$centralPlant$sc4 = _this$centralPlant$sc4.currentSceneData) === null || _this$centralPlant$sc4 === void 0 ? void 0 : _this$centralPlant$sc4.connections) || [];
|
|
701
754
|
var validation = this.validator.validateConnectionParams(fromConnectorId, toConnectorId, existingConnections);
|
|
@@ -703,6 +756,17 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
703
756
|
return false; // Validator already logged the error
|
|
704
757
|
}
|
|
705
758
|
|
|
759
|
+
// Validate flow direction compatibility
|
|
760
|
+
var sceneData = (_this$centralPlant$sc5 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc5 === void 0 ? void 0 : _this$centralPlant$sc5.currentSceneData;
|
|
761
|
+
if (sceneData) {
|
|
762
|
+
var fromFlow = _getConnectorFlow(sceneData, fromConnectorId);
|
|
763
|
+
var toFlow = _getConnectorFlow(sceneData, toConnectorId);
|
|
764
|
+
if (!_areFlowsCompatible(fromFlow, toFlow)) {
|
|
765
|
+
console.error("\u274C addConnection(): Incompatible flow directions \u2014 '".concat(fromConnectorId, "' is '").concat(fromFlow, "' and '").concat(toConnectorId, "' is '").concat(toFlow, "'. ") + "'".concat(fromFlow, "' \u2192 '").concat(toFlow, "' connections are not allowed."));
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
706
770
|
// Validate scene availability
|
|
707
771
|
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer);
|
|
708
772
|
if (!sceneValidation.isValid) {
|
|
@@ -823,7 +887,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
823
887
|
}, {
|
|
824
888
|
key: "addComponent",
|
|
825
889
|
value: function addComponent(libraryId) {
|
|
826
|
-
var _this$centralPlant$
|
|
890
|
+
var _this$centralPlant$sc6;
|
|
827
891
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
828
892
|
// Use centralized validation for component addition parameters
|
|
829
893
|
var existingIds = this.getComponentIds();
|
|
@@ -833,7 +897,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
833
897
|
}
|
|
834
898
|
|
|
835
899
|
// Validate scene availability
|
|
836
|
-
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$
|
|
900
|
+
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$sc6 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc6 === void 0 ? void 0 : _this$centralPlant$sc6.scene);
|
|
837
901
|
if (!sceneValidation.isValid) {
|
|
838
902
|
return false;
|
|
839
903
|
}
|
|
@@ -852,7 +916,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
852
916
|
return false;
|
|
853
917
|
}
|
|
854
918
|
try {
|
|
855
|
-
var _componentData$childr, _componentData$childr2, _this$centralPlant$
|
|
919
|
+
var _componentData$childr, _componentData$childr2, _this$centralPlant$sc7, _componentData$childr3, _componentData$defaul;
|
|
856
920
|
// Generate a unique component ID if not provided
|
|
857
921
|
var componentId = options.customId || this.generateUniqueComponentId(libraryId);
|
|
858
922
|
|
|
@@ -964,7 +1028,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
964
1028
|
componentModel.updateMatrixWorld(true);
|
|
965
1029
|
|
|
966
1030
|
// Check if component is underground and fix if needed (based on settings)
|
|
967
|
-
var checkUnderground = (_this$centralPlant$
|
|
1031
|
+
var checkUnderground = (_this$centralPlant$sc7 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc7 === void 0 || (_this$centralPlant$sc7 = _this$centralPlant$sc7.managers) === null || _this$centralPlant$sc7 === void 0 || (_this$centralPlant$sc7 = _this$centralPlant$sc7.settingsManager) === null || _this$centralPlant$sc7 === void 0 ? void 0 : _this$centralPlant$sc7.getSetting('scene', 'checkUnderground');
|
|
968
1032
|
if (checkUnderground) {
|
|
969
1033
|
var wasFixed = this.fixUndergroundComponent(componentModel);
|
|
970
1034
|
if (wasFixed) {
|
|
@@ -1062,8 +1126,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1062
1126
|
// responds to tooltip-driven state changes immediately after drop.
|
|
1063
1127
|
// (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
|
|
1064
1128
|
if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
|
|
1065
|
-
var _this$centralPlant$
|
|
1066
|
-
var som = (_this$centralPlant$
|
|
1129
|
+
var _this$centralPlant$sc8, _som$registerBehavior;
|
|
1130
|
+
var som = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.sceneOperationsManager;
|
|
1067
1131
|
som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
|
|
1068
1132
|
}
|
|
1069
1133
|
|
|
@@ -1125,9 +1189,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1125
1189
|
}, {
|
|
1126
1190
|
key: "deleteComponent",
|
|
1127
1191
|
value: function deleteComponent(componentId) {
|
|
1128
|
-
var _this$centralPlant$
|
|
1192
|
+
var _this$centralPlant$sc9;
|
|
1129
1193
|
// Check if component manager is available
|
|
1130
|
-
var componentManager = (_this$centralPlant$
|
|
1194
|
+
var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
|
|
1131
1195
|
if (!componentManager) {
|
|
1132
1196
|
console.error('❌ deleteComponent(): Component manager not available');
|
|
1133
1197
|
return false;
|
|
@@ -1202,8 +1266,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
1202
1266
|
}
|
|
1203
1267
|
var componentIds = [];
|
|
1204
1268
|
this.centralPlant.sceneViewer.scene.traverse(function (child) {
|
|
1205
|
-
var _child$
|
|
1206
|
-
if (((_child$
|
|
1269
|
+
var _child$userData2;
|
|
1270
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'component') {
|
|
1207
1271
|
componentIds.push(child.uuid || child.userData.originalUuid);
|
|
1208
1272
|
}
|
|
1209
1273
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,25 @@
|
|
|
5
5
|
* organized by their functional categories.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
// ─── Connector flow types ─────────────────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
/** The flow direction of a connector port. */
|
|
11
|
+
export type FlowDirection = 'in' | 'out' | 'bi'
|
|
12
|
+
|
|
13
|
+
/** Connector descriptor returned by getAvailableConnectionsInfo(). */
|
|
14
|
+
export interface ConnectorInfo {
|
|
15
|
+
/** The connector's UUID as it appears in the scene JSON. */
|
|
16
|
+
id: string
|
|
17
|
+
/** Flow direction. Defaults to 'bi' for connectors that do not declare one. */
|
|
18
|
+
flow: FlowDirection
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Result of validateConnections(). */
|
|
22
|
+
export interface ConnectionValidationResult {
|
|
23
|
+
valid: Array<{ from: string; to: string }>
|
|
24
|
+
invalid: Array<{ connection: { from: string; to: string }; reason: string }>
|
|
25
|
+
}
|
|
26
|
+
|
|
8
27
|
// ─── I/O Device types ────────────────────────────────────────────────────────
|
|
9
28
|
|
|
10
29
|
export interface IoDeviceState {
|