@2112-lab/central-plant 0.2.5 → 0.2.10
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 +715 -34
- package/dist/cjs/src/core/centralPlant.js +118 -1
- package/dist/cjs/src/core/centralPlantInternals.js +83 -17
- package/dist/cjs/src/core/pathfindingData.js +61 -5
- package/dist/cjs/src/core/sceneViewer.js +1 -1
- package/dist/cjs/src/index.js +3 -0
- package/dist/cjs/src/managers/pathfinding/PathFlowManager.js +265 -0
- package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +63 -8
- package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +133 -2
- package/dist/esm/src/core/centralPlant.js +118 -1
- package/dist/esm/src/core/centralPlantInternals.js +83 -17
- package/dist/esm/src/core/pathfindingData.js +61 -6
- package/dist/esm/src/core/sceneViewer.js +1 -1
- package/dist/esm/src/index.js +2 -1
- package/dist/esm/src/managers/pathfinding/PathFlowManager.js +261 -0
- package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +63 -8
- package/dist/esm/src/managers/pathfinding/pathfindingManager.js +134 -3
- package/dist/index.d.ts +75 -0
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -25783,10 +25783,19 @@ function createPathfindingRequest(startConnector, endConnector) {
|
|
|
25783
25783
|
};
|
|
25784
25784
|
}
|
|
25785
25785
|
|
|
25786
|
+
/**
|
|
25787
|
+
* The official set of flow-related attribute keys that can be set on a path.
|
|
25788
|
+
* These attributes belong to the full path and are inherited by all segments.
|
|
25789
|
+
*
|
|
25790
|
+
* @type {string[]}
|
|
25791
|
+
*/
|
|
25792
|
+
var FLOW_ATTRIBUTE_KEYS = ['flowDirection', 'flowSpeed', 'flowTemperature', 'flowMaterial'];
|
|
25793
|
+
|
|
25786
25794
|
/**
|
|
25787
25795
|
* Data structure for storing path information with segments.
|
|
25788
25796
|
* Tracks both computed and declared (manually edited) segments.
|
|
25789
|
-
*
|
|
25797
|
+
* Also stores path-level flow attributes shared by all segments.
|
|
25798
|
+
*
|
|
25790
25799
|
* Business logic layer - stores coordinate data without Three.js dependencies.
|
|
25791
25800
|
*/
|
|
25792
25801
|
var PathData = /*#__PURE__*/function () {
|
|
@@ -25806,16 +25815,60 @@ var PathData = /*#__PURE__*/function () {
|
|
|
25806
25815
|
* @type {Array<{start: {x, y, z}, end: {x, y, z}, isDeclared: boolean, modifiedAt: number|null}>}
|
|
25807
25816
|
*/
|
|
25808
25817
|
this.segments = [];
|
|
25818
|
+
|
|
25819
|
+
/**
|
|
25820
|
+
* Path-level flow attributes shared by all segments within this path.
|
|
25821
|
+
* Keys must come from FLOW_ATTRIBUTE_KEYS. Values are application-defined.
|
|
25822
|
+
* @type {Record<string, any>}
|
|
25823
|
+
*/
|
|
25824
|
+
this.flowAttributes = {};
|
|
25809
25825
|
this.createdAt = Date.now();
|
|
25810
25826
|
}
|
|
25811
25827
|
|
|
25812
25828
|
/**
|
|
25813
|
-
*
|
|
25814
|
-
*
|
|
25815
|
-
*
|
|
25816
|
-
* @param {
|
|
25829
|
+
* Set a flow attribute on this path.
|
|
25830
|
+
* All segments within this path inherit the value.
|
|
25831
|
+
*
|
|
25832
|
+
* @param {string} key - Attribute key (should be one of FLOW_ATTRIBUTE_KEYS)
|
|
25833
|
+
* @param {any} value - Attribute value
|
|
25817
25834
|
*/
|
|
25818
25835
|
return _createClass(PathData, [{
|
|
25836
|
+
key: "setFlowAttribute",
|
|
25837
|
+
value: function setFlowAttribute(key, value) {
|
|
25838
|
+
this.flowAttributes[key] = value;
|
|
25839
|
+
}
|
|
25840
|
+
|
|
25841
|
+
/**
|
|
25842
|
+
* Get the declared value of a flow attribute.
|
|
25843
|
+
* Returns null if the attribute has not been set.
|
|
25844
|
+
*
|
|
25845
|
+
* @param {string} key - Attribute key
|
|
25846
|
+
* @returns {any|null}
|
|
25847
|
+
*/
|
|
25848
|
+
}, {
|
|
25849
|
+
key: "getFlowAttribute",
|
|
25850
|
+
value: function getFlowAttribute(key) {
|
|
25851
|
+
return Object.prototype.hasOwnProperty.call(this.flowAttributes, key) ? this.flowAttributes[key] : null;
|
|
25852
|
+
}
|
|
25853
|
+
|
|
25854
|
+
/**
|
|
25855
|
+
* Get a shallow copy of all declared flow attributes.
|
|
25856
|
+
*
|
|
25857
|
+
* @returns {Record<string, any>}
|
|
25858
|
+
*/
|
|
25859
|
+
}, {
|
|
25860
|
+
key: "getAllFlowAttributes",
|
|
25861
|
+
value: function getAllFlowAttributes() {
|
|
25862
|
+
return _objectSpread2({}, this.flowAttributes);
|
|
25863
|
+
}
|
|
25864
|
+
|
|
25865
|
+
/**
|
|
25866
|
+
* Add a computed segment (from pathfinding algorithm)
|
|
25867
|
+
*
|
|
25868
|
+
* @param {{x: number, y: number, z: number}} start - Start coordinate
|
|
25869
|
+
* @param {{x: number, y: number, z: number}} end - End coordinate
|
|
25870
|
+
*/
|
|
25871
|
+
}, {
|
|
25819
25872
|
key: "addSegment",
|
|
25820
25873
|
value: function addSegment(start, end) {
|
|
25821
25874
|
this.segments.push({
|
|
@@ -25892,6 +25945,7 @@ var PathData = /*#__PURE__*/function () {
|
|
|
25892
25945
|
segments: this.segments.map(function (seg) {
|
|
25893
25946
|
return _objectSpread2({}, seg);
|
|
25894
25947
|
}),
|
|
25948
|
+
flowAttributes: _objectSpread2({}, this.flowAttributes),
|
|
25895
25949
|
createdAt: this.createdAt
|
|
25896
25950
|
};
|
|
25897
25951
|
}
|
|
@@ -25952,6 +26006,7 @@ var PathData = /*#__PURE__*/function () {
|
|
|
25952
26006
|
pathData.segments = json.segments.map(function (seg) {
|
|
25953
26007
|
return _objectSpread2({}, seg);
|
|
25954
26008
|
});
|
|
26009
|
+
pathData.flowAttributes = json.flowAttributes ? _objectSpread2({}, json.flowAttributes) : {};
|
|
25955
26010
|
pathData.createdAt = json.createdAt || Date.now();
|
|
25956
26011
|
return pathData;
|
|
25957
26012
|
}
|
|
@@ -26109,16 +26164,58 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26109
26164
|
emissive: 0
|
|
26110
26165
|
});
|
|
26111
26166
|
_this.registerDisposable(_this._gatewayGeometry, _this._gatewayMaterial);
|
|
26167
|
+
|
|
26168
|
+
/**
|
|
26169
|
+
* Map of pathId -> THREE.Material for per-path color control.
|
|
26170
|
+
* pathId format: "${from}-->${to}"
|
|
26171
|
+
* All segments within a path share the same material instance.
|
|
26172
|
+
* @type {Map<string, THREE.Material>}
|
|
26173
|
+
*/
|
|
26174
|
+
_this._pathMaterials = new Map();
|
|
26112
26175
|
return _this;
|
|
26113
26176
|
}
|
|
26114
26177
|
|
|
26115
26178
|
/**
|
|
26116
|
-
*
|
|
26117
|
-
*
|
|
26118
|
-
* @
|
|
26179
|
+
* Dispose all tracked per-path materials and clear the map.
|
|
26180
|
+
* Called at the start of createPipePaths to clean up stale materials.
|
|
26181
|
+
* @private
|
|
26119
26182
|
*/
|
|
26120
26183
|
_inherits(PathRenderingManager, _BaseDisposable);
|
|
26121
26184
|
return _createClass(PathRenderingManager, [{
|
|
26185
|
+
key: "_clearPathMaterials",
|
|
26186
|
+
value: function _clearPathMaterials() {
|
|
26187
|
+
this._pathMaterials.forEach(function (mat) {
|
|
26188
|
+
return mat.dispose();
|
|
26189
|
+
});
|
|
26190
|
+
this._pathMaterials.clear();
|
|
26191
|
+
}
|
|
26192
|
+
|
|
26193
|
+
/**
|
|
26194
|
+
* Update the color of all pipe segments belonging to a specific path.
|
|
26195
|
+
* Operates on the shared per-path material — no scene traversal needed.
|
|
26196
|
+
*
|
|
26197
|
+
* @param {string} from - Source connector ID
|
|
26198
|
+
* @param {string} to - Target connector ID
|
|
26199
|
+
* @param {string|number} color - Any value accepted by THREE.Color.set()
|
|
26200
|
+
*/
|
|
26201
|
+
}, {
|
|
26202
|
+
key: "updatePathColor",
|
|
26203
|
+
value: function updatePathColor(from, to, color) {
|
|
26204
|
+
var pathId = "".concat(from, "-->").concat(to);
|
|
26205
|
+
var mat = this._pathMaterials.get(pathId);
|
|
26206
|
+
if (mat) {
|
|
26207
|
+
mat.color.set(color);
|
|
26208
|
+
} else {
|
|
26209
|
+
console.warn("\u26A0\uFE0F PathRenderingManager.updatePathColor: no material found for path \"".concat(pathId, "\""));
|
|
26210
|
+
}
|
|
26211
|
+
}
|
|
26212
|
+
|
|
26213
|
+
/**
|
|
26214
|
+
* Get path colors for visual distinction
|
|
26215
|
+
* @param {number} index - Path index
|
|
26216
|
+
* @returns {string} Hex color string
|
|
26217
|
+
*/
|
|
26218
|
+
}, {
|
|
26122
26219
|
key: "getPathColor",
|
|
26123
26220
|
value: function getPathColor(index) {
|
|
26124
26221
|
var colors = [
|
|
@@ -26273,7 +26370,11 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26273
26370
|
var globalSegmentIndex = maxExistingIndex + 1;
|
|
26274
26371
|
console.log("\uD83D\uDD22 Starting segment index at ".concat(globalSegmentIndex, " (max existing: ").concat(maxExistingIndex, ")"));
|
|
26275
26372
|
var pipeRadius = 0.1;
|
|
26276
|
-
|
|
26373
|
+
// Base material created once; per-path materials are cloned from it below.
|
|
26374
|
+
var baseMaterial = this.createPipeMaterial(crosscubeTextureSet);
|
|
26375
|
+
|
|
26376
|
+
// Dispose previous path materials (they were attached to now-removed segments)
|
|
26377
|
+
this._clearPathMaterials();
|
|
26277
26378
|
paths.forEach(function (pathData, index) {
|
|
26278
26379
|
if (pathData.path && pathData.path.length >= 2) {
|
|
26279
26380
|
// Convert path points to Vector3 objects for consistent handling
|
|
@@ -26290,6 +26391,12 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26290
26391
|
}
|
|
26291
26392
|
});
|
|
26292
26393
|
|
|
26394
|
+
// Create a per-path material clone so each path can have its color updated independently.
|
|
26395
|
+
var pathId = "".concat(pathData.from, "-->").concat(pathData.to);
|
|
26396
|
+
var perPathMaterial = baseMaterial.clone();
|
|
26397
|
+
_this3._pathMaterials.set(pathId, perPathMaterial);
|
|
26398
|
+
console.log("\uD83C\uDFA8 Created per-path material for \"".concat(pathId, "\""));
|
|
26399
|
+
|
|
26293
26400
|
// Check if endpoints are component connectors (from pathfinder result)
|
|
26294
26401
|
var fromIsComponentConnector = pathData.fromObjectType === 'component-connector';
|
|
26295
26402
|
var toIsComponentConnector = pathData.toObjectType === 'component-connector';
|
|
@@ -26314,13 +26421,13 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26314
26421
|
var cylinderGeometry = new THREE__namespace.CylinderGeometry(pipeRadius, pipeRadius, length, 16, 1, false);
|
|
26315
26422
|
|
|
26316
26423
|
// Determine material (debug red if rectified and in dev mode)
|
|
26317
|
-
var materialToUse =
|
|
26424
|
+
var materialToUse = perPathMaterial;
|
|
26318
26425
|
|
|
26319
26426
|
// Check for dev mode (strict localhost only)
|
|
26320
26427
|
var isDev = typeof window !== 'undefined' && (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
|
|
26321
26428
|
if (isDev && pathData.rectifiedSegments && pathData.rectifiedSegments.includes(j)) {
|
|
26322
|
-
// Create red debug material by cloning the
|
|
26323
|
-
materialToUse =
|
|
26429
|
+
// Create red debug material by cloning the per-path material to match the look
|
|
26430
|
+
materialToUse = perPathMaterial.clone();
|
|
26324
26431
|
materialToUse.color.setHex(0xff0000);
|
|
26325
26432
|
console.log("\uD83C\uDFA8 Coloring rectified segment ".concat(j, " red"));
|
|
26326
26433
|
}
|
|
@@ -26382,7 +26489,7 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26382
26489
|
sceneViewer.scene.add(cylinder);
|
|
26383
26490
|
|
|
26384
26491
|
// Add smooth elbow joints only at actual direction changes (not at every point)
|
|
26385
|
-
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius,
|
|
26492
|
+
_this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, perPathMaterial, pathData, index, cylinder // Pass the segment so elbow can be added as a child
|
|
26386
26493
|
);
|
|
26387
26494
|
}
|
|
26388
26495
|
}
|
|
@@ -26487,6 +26594,9 @@ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
26487
26594
|
value: function dispose() {
|
|
26488
26595
|
console.log('🗑️ Disposing PathRenderingManager...');
|
|
26489
26596
|
|
|
26597
|
+
// Dispose per-path materials
|
|
26598
|
+
this._clearPathMaterials();
|
|
26599
|
+
|
|
26490
26600
|
// Call parent dispose to clean up registered resources (shared gateway geometry/material)
|
|
26491
26601
|
_superPropGet(PathRenderingManager, "dispose", this, 3)([]);
|
|
26492
26602
|
|
|
@@ -27923,7 +28033,11 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
27923
28033
|
key: "_executePathfinding",
|
|
27924
28034
|
value: (function () {
|
|
27925
28035
|
var _executePathfinding2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(sceneData, connections) {
|
|
27926
|
-
var
|
|
28036
|
+
var _this4 = this,
|
|
28037
|
+
_sceneDataCopy$childr,
|
|
28038
|
+
_sceneDataCopy$childr2,
|
|
28039
|
+
_pathfindingResult$pa,
|
|
28040
|
+
_pathfindingResult$pa2;
|
|
27927
28041
|
var options,
|
|
27928
28042
|
_options$context,
|
|
27929
28043
|
context,
|
|
@@ -27984,6 +28098,15 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
27984
28098
|
|
|
27985
28099
|
// Create pipe paths with materials using the paths from pathfinder
|
|
27986
28100
|
this.renderingManager.createPipePaths(pathfindingResult.paths, this.crosscubeTextureSet);
|
|
28101
|
+
|
|
28102
|
+
// ── Stage 3b: Ensure PathData entries exist for all rendered paths ──────
|
|
28103
|
+
// This preserves any flowAttributes already set on existing entries.
|
|
28104
|
+
if (pathfindingResult.paths) {
|
|
28105
|
+
pathfindingResult.paths.forEach(function (path) {
|
|
28106
|
+
var pathId = "".concat(path.from, "-->").concat(path.to);
|
|
28107
|
+
_this4._getOrCreatePathData(pathId, path.from, path.to);
|
|
28108
|
+
});
|
|
28109
|
+
}
|
|
27987
28110
|
timers.pathRendering = performance.now() - renderStart;
|
|
27988
28111
|
|
|
27989
28112
|
// ── Performance Summary ────────────────────────────────────────────
|
|
@@ -28021,6 +28144,26 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
28021
28144
|
return this.sceneDataManager.getSimplifiedSceneData();
|
|
28022
28145
|
}
|
|
28023
28146
|
|
|
28147
|
+
/**
|
|
28148
|
+
* Return an existing PathData for pathId from the store, or create and register a new one.
|
|
28149
|
+
* Preserves existing flowAttributes when the entry already exists.
|
|
28150
|
+
*
|
|
28151
|
+
* @param {string} pathId - Canonical path identifier "${from}-->${to}"
|
|
28152
|
+
* @param {string} from - Source connector ID
|
|
28153
|
+
* @param {string} to - Target connector ID
|
|
28154
|
+
* @returns {PathData}
|
|
28155
|
+
* @private
|
|
28156
|
+
*/
|
|
28157
|
+
}, {
|
|
28158
|
+
key: "_getOrCreatePathData",
|
|
28159
|
+
value: function _getOrCreatePathData(pathId, from, to) {
|
|
28160
|
+
if (!this.pathDataStore.has(pathId)) {
|
|
28161
|
+
var pd = new PathData(pathId, from, to);
|
|
28162
|
+
this.pathDataStore.set(pathId, pd);
|
|
28163
|
+
}
|
|
28164
|
+
return this.pathDataStore.get(pathId);
|
|
28165
|
+
}
|
|
28166
|
+
|
|
28024
28167
|
/**
|
|
28025
28168
|
* Initialize pathfinder and create paths
|
|
28026
28169
|
*/
|
|
@@ -28028,12 +28171,33 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
28028
28171
|
key: "initializePathfinder",
|
|
28029
28172
|
value: (function () {
|
|
28030
28173
|
var _initializePathfinder = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(data, crosscubeTextureSet) {
|
|
28031
|
-
var
|
|
28174
|
+
var _this5 = this,
|
|
28175
|
+
_this$sceneViewer;
|
|
28176
|
+
var pathfindingResult, originalToSubPaths, fromEndpointAttrs, flowMgr;
|
|
28032
28177
|
return _regenerator().w(function (_context2) {
|
|
28033
28178
|
while (1) switch (_context2.n) {
|
|
28034
28179
|
case 0:
|
|
28035
28180
|
this.crosscubeTextureSet = crosscubeTextureSet;
|
|
28036
28181
|
|
|
28182
|
+
// ── Pre-load declared flowAttributes from connections JSON ─────────────
|
|
28183
|
+
// This must happen before pathfinding so that PathData entries carrying
|
|
28184
|
+
// flowAttributes are available for visualization right after rendering.
|
|
28185
|
+
if (Array.isArray(data.connections)) {
|
|
28186
|
+
data.connections.forEach(function (conn) {
|
|
28187
|
+
if (conn.flowAttributes && _typeof(conn.flowAttributes) === 'object') {
|
|
28188
|
+
var pathId = "".concat(conn.from, "-->").concat(conn.to);
|
|
28189
|
+
var pd = _this5._getOrCreatePathData(pathId, conn.from, conn.to);
|
|
28190
|
+
Object.entries(conn.flowAttributes).forEach(function (_ref) {
|
|
28191
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
28192
|
+
key = _ref2[0],
|
|
28193
|
+
value = _ref2[1];
|
|
28194
|
+
pd.setFlowAttribute(key, value);
|
|
28195
|
+
});
|
|
28196
|
+
console.log("\uD83C\uDF0A Loaded flowAttributes for path \"".concat(pathId, "\":"), conn.flowAttributes);
|
|
28197
|
+
}
|
|
28198
|
+
});
|
|
28199
|
+
}
|
|
28200
|
+
|
|
28037
28201
|
// Use shared pathfinding logic with gateway creation enabled
|
|
28038
28202
|
_context2.n = 1;
|
|
28039
28203
|
return this._executePathfinding(data.scene, data.connections, {
|
|
@@ -28042,6 +28206,83 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
28042
28206
|
});
|
|
28043
28207
|
case 1:
|
|
28044
28208
|
pathfindingResult = _context2.v;
|
|
28209
|
+
// ── Propagate flowAttributes to gateway-split rendered paths ──────────
|
|
28210
|
+
// The pathfinder may split a connection A→B through gateway waypoints,
|
|
28211
|
+
// producing sub-paths like A→G and G→B with different pathIds.
|
|
28212
|
+
// We need to copy the original connection's flowAttributes onto every
|
|
28213
|
+
// rendered sub-path entry in pathDataStore so the visualisation can
|
|
28214
|
+
// find them by their rendered pathId.
|
|
28215
|
+
if (Array.isArray(data.connections) && pathfindingResult) {
|
|
28216
|
+
// Pass 1: use the explicit gateway connection mappings to get a precise
|
|
28217
|
+
// original→sub-path map.
|
|
28218
|
+
originalToSubPaths = new Map(); // origPathId → Set<renderedPathId>
|
|
28219
|
+
if (pathfindingResult.gateways) {
|
|
28220
|
+
pathfindingResult.gateways.forEach(function (gateway) {
|
|
28221
|
+
var _ref3 = gateway.connections || {},
|
|
28222
|
+
removed = _ref3.removed,
|
|
28223
|
+
added = _ref3.added;
|
|
28224
|
+
if (!(removed !== null && removed !== void 0 && removed.length) || !(added !== null && added !== void 0 && added.length)) return;
|
|
28225
|
+
removed.forEach(function (removedConn) {
|
|
28226
|
+
var origId = "".concat(removedConn.from, "-->").concat(removedConn.to);
|
|
28227
|
+
if (!originalToSubPaths.has(origId)) originalToSubPaths.set(origId, new Set());
|
|
28228
|
+
added.forEach(function (addedConn) {
|
|
28229
|
+
originalToSubPaths.get(origId).add("".concat(addedConn.from, "-->").concat(addedConn.to));
|
|
28230
|
+
});
|
|
28231
|
+
});
|
|
28232
|
+
});
|
|
28233
|
+
}
|
|
28234
|
+
data.connections.forEach(function (conn) {
|
|
28235
|
+
if (!conn.flowAttributes) return;
|
|
28236
|
+
var origId = "".concat(conn.from, "-->").concat(conn.to);
|
|
28237
|
+
var subPathIds = new Set(originalToSubPaths.get(origId) || []);
|
|
28238
|
+
subPathIds.add(origId); // include the direct path if it wasn't rewired
|
|
28239
|
+
|
|
28240
|
+
subPathIds.forEach(function (subPathId) {
|
|
28241
|
+
var pd = _this5.pathDataStore.get(subPathId);
|
|
28242
|
+
if (pd && Object.keys(pd.flowAttributes).length === 0) {
|
|
28243
|
+
Object.entries(conn.flowAttributes).forEach(function (_ref4) {
|
|
28244
|
+
var _ref5 = _slicedToArray(_ref4, 2),
|
|
28245
|
+
key = _ref5[0],
|
|
28246
|
+
value = _ref5[1];
|
|
28247
|
+
pd.setFlowAttribute(key, value);
|
|
28248
|
+
});
|
|
28249
|
+
console.log("\uD83C\uDF0A Propagated flowAttributes to sub-path \"".concat(subPathId, "\" from \"").concat(origId, "\""));
|
|
28250
|
+
}
|
|
28251
|
+
});
|
|
28252
|
+
});
|
|
28253
|
+
|
|
28254
|
+
// Pass 2: endpoint fallback for any rendered path still missing attributes
|
|
28255
|
+
// (covers Gateway→Gateway intermediate segments not captured by gateway.connections.added)
|
|
28256
|
+
fromEndpointAttrs = new Map(); // connectorId → flowAttributes
|
|
28257
|
+
data.connections.forEach(function (conn) {
|
|
28258
|
+
if (conn.flowAttributes && !fromEndpointAttrs.has(conn.from)) {
|
|
28259
|
+
fromEndpointAttrs.set(conn.from, conn.flowAttributes);
|
|
28260
|
+
}
|
|
28261
|
+
});
|
|
28262
|
+
this.pathDataStore.forEach(function (pd, pathId) {
|
|
28263
|
+
if (Object.keys(pd.flowAttributes).length > 0) return;
|
|
28264
|
+
var sepIdx = pathId.indexOf('-->');
|
|
28265
|
+
if (sepIdx === -1) return;
|
|
28266
|
+
var from = pathId.slice(0, sepIdx);
|
|
28267
|
+
var attrs = fromEndpointAttrs.get(from);
|
|
28268
|
+
if (attrs) {
|
|
28269
|
+
Object.entries(attrs).forEach(function (_ref6) {
|
|
28270
|
+
var _ref7 = _slicedToArray(_ref6, 2),
|
|
28271
|
+
key = _ref7[0],
|
|
28272
|
+
value = _ref7[1];
|
|
28273
|
+
return pd.setFlowAttribute(key, value);
|
|
28274
|
+
});
|
|
28275
|
+
console.log("\uD83C\uDF0A Endpoint-matched flowAttributes for path \"".concat(pathId, "\""));
|
|
28276
|
+
}
|
|
28277
|
+
});
|
|
28278
|
+
}
|
|
28279
|
+
|
|
28280
|
+
// ── Apply flow visualizations now that paths are rendered ──────────────
|
|
28281
|
+
flowMgr = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.managers) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.pathFlowManager;
|
|
28282
|
+
if (flowMgr) {
|
|
28283
|
+
flowMgr.applyAllVisualizations();
|
|
28284
|
+
}
|
|
28285
|
+
|
|
28045
28286
|
// Update connections with rewired connections
|
|
28046
28287
|
if (pathfindingResult.rewiredConnections) {
|
|
28047
28288
|
// data.connections = pathfindingResult.rewiredConnections;
|
|
@@ -28221,6 +28462,262 @@ var PathfindingManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
28221
28462
|
}]);
|
|
28222
28463
|
}(BaseDisposable);
|
|
28223
28464
|
|
|
28465
|
+
// ── Temperature visualisation constants ────────────────────────────────────
|
|
28466
|
+
|
|
28467
|
+
/** Minimum temperature in the colour ramp (maps to pure blue). */
|
|
28468
|
+
var TEMP_MIN = 0;
|
|
28469
|
+
|
|
28470
|
+
/** Maximum temperature in the colour ramp (maps to pure red). */
|
|
28471
|
+
var TEMP_MAX = 100;
|
|
28472
|
+
|
|
28473
|
+
/**
|
|
28474
|
+
* Convert a temperature value to a CSS hex colour string using a blue→red HSL
|
|
28475
|
+
* ramp. Values are clamped to [TEMP_MIN, TEMP_MAX].
|
|
28476
|
+
*
|
|
28477
|
+
* • TEMP_MIN → hsl(240, 80%, 50%) — blue
|
|
28478
|
+
* • TEMP_MAX → hsl(0, 80%, 50%) — red
|
|
28479
|
+
*
|
|
28480
|
+
* @param {number} temp
|
|
28481
|
+
* @returns {string} CSS hex colour string e.g. '#2255cc'
|
|
28482
|
+
*/
|
|
28483
|
+
function temperatureToColor(temp) {
|
|
28484
|
+
var clamped = Math.max(TEMP_MIN, Math.min(TEMP_MAX, temp));
|
|
28485
|
+
var t = (clamped - TEMP_MIN) / (TEMP_MAX - TEMP_MIN); // 0 (cold) → 1 (hot)
|
|
28486
|
+
// Map t=0 → hue 240 (blue), t=1 → hue 0 (red)
|
|
28487
|
+
var hue = Math.round(240 - t * 240);
|
|
28488
|
+
return "hsl(".concat(hue, ", 80%, 50%)");
|
|
28489
|
+
}
|
|
28490
|
+
|
|
28491
|
+
// ── PathFlowManager ─────────────────────────────────────────────────────────
|
|
28492
|
+
|
|
28493
|
+
var PathFlowManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
28494
|
+
/**
|
|
28495
|
+
* @param {Object} sceneViewer - The central sceneViewer hub
|
|
28496
|
+
*/
|
|
28497
|
+
function PathFlowManager(sceneViewer) {
|
|
28498
|
+
var _this;
|
|
28499
|
+
_classCallCheck(this, PathFlowManager);
|
|
28500
|
+
_this = _callSuper(this, PathFlowManager);
|
|
28501
|
+
_this.sceneViewer = sceneViewer;
|
|
28502
|
+
|
|
28503
|
+
/**
|
|
28504
|
+
* Runtime-only attribute overrides.
|
|
28505
|
+
* Map<pathId, Record<attributeKey, value>>
|
|
28506
|
+
* Cleared when the session ends or resetDerived() is called.
|
|
28507
|
+
* @type {Map<string, Record<string, any>>}
|
|
28508
|
+
*/
|
|
28509
|
+
_this._derivedStore = new Map();
|
|
28510
|
+
return _this;
|
|
28511
|
+
}
|
|
28512
|
+
|
|
28513
|
+
// ── Public API — attribute write ──────────────────────────────────────────
|
|
28514
|
+
|
|
28515
|
+
/**
|
|
28516
|
+
* Set a declared (persistent) flow attribute on a path.
|
|
28517
|
+
* The value is stored in PathData and will be serialised with the scene.
|
|
28518
|
+
* Triggers a visual update.
|
|
28519
|
+
*
|
|
28520
|
+
* @param {string} pathId - e.g. "PUMP-1-CONN-1-->CHILLER-1-CONN-2"
|
|
28521
|
+
* @param {string} key - One of FLOW_ATTRIBUTE_KEYS
|
|
28522
|
+
* @param {any} value
|
|
28523
|
+
*/
|
|
28524
|
+
_inherits(PathFlowManager, _BaseDisposable);
|
|
28525
|
+
return _createClass(PathFlowManager, [{
|
|
28526
|
+
key: "setDeclared",
|
|
28527
|
+
value: function setDeclared(pathId, key, value) {
|
|
28528
|
+
var pd = this._getPathData(pathId);
|
|
28529
|
+
if (!pd) {
|
|
28530
|
+
console.warn("PathFlowManager.setDeclared: no PathData found for \"".concat(pathId, "\""));
|
|
28531
|
+
return;
|
|
28532
|
+
}
|
|
28533
|
+
pd.setFlowAttribute(key, value);
|
|
28534
|
+
this.applyVisualizationForPath(pathId);
|
|
28535
|
+
}
|
|
28536
|
+
|
|
28537
|
+
/**
|
|
28538
|
+
* Set a derived (runtime) flow attribute on a path.
|
|
28539
|
+
* Overrides the declared value during this session but is not persisted.
|
|
28540
|
+
* Triggers a visual update.
|
|
28541
|
+
*
|
|
28542
|
+
* @param {string} pathId
|
|
28543
|
+
* @param {string} key
|
|
28544
|
+
* @param {any} value
|
|
28545
|
+
*/
|
|
28546
|
+
}, {
|
|
28547
|
+
key: "setDerived",
|
|
28548
|
+
value: function setDerived(pathId, key, value) {
|
|
28549
|
+
if (!this._derivedStore.has(pathId)) {
|
|
28550
|
+
this._derivedStore.set(pathId, {});
|
|
28551
|
+
}
|
|
28552
|
+
this._derivedStore.get(pathId)[key] = value;
|
|
28553
|
+
this.applyVisualizationForPath(pathId);
|
|
28554
|
+
}
|
|
28555
|
+
|
|
28556
|
+
/**
|
|
28557
|
+
* Clear derived overrides for one path or all paths, then re-apply
|
|
28558
|
+
* visualizations so that declared values take effect again.
|
|
28559
|
+
*
|
|
28560
|
+
* @param {string} [pathId] - Omit to reset all paths.
|
|
28561
|
+
*/
|
|
28562
|
+
}, {
|
|
28563
|
+
key: "resetDerived",
|
|
28564
|
+
value: function resetDerived(pathId) {
|
|
28565
|
+
var _this2 = this;
|
|
28566
|
+
if (pathId !== undefined) {
|
|
28567
|
+
this._derivedStore.delete(pathId);
|
|
28568
|
+
this.applyVisualizationForPath(pathId);
|
|
28569
|
+
} else {
|
|
28570
|
+
var affected = _toConsumableArray(this._derivedStore.keys());
|
|
28571
|
+
this._derivedStore.clear();
|
|
28572
|
+
affected.forEach(function (id) {
|
|
28573
|
+
return _this2.applyVisualizationForPath(id);
|
|
28574
|
+
});
|
|
28575
|
+
}
|
|
28576
|
+
}
|
|
28577
|
+
|
|
28578
|
+
// ── Public API — attribute read ───────────────────────────────────────────
|
|
28579
|
+
|
|
28580
|
+
/**
|
|
28581
|
+
* Resolve the effective value of a single attribute for a path.
|
|
28582
|
+
* Resolution order: derived > declared > null.
|
|
28583
|
+
*
|
|
28584
|
+
* @param {string} pathId
|
|
28585
|
+
* @param {string} key
|
|
28586
|
+
* @returns {any|null}
|
|
28587
|
+
*/
|
|
28588
|
+
}, {
|
|
28589
|
+
key: "resolve",
|
|
28590
|
+
value: function resolve(pathId, key) {
|
|
28591
|
+
var derived = this._derivedStore.get(pathId);
|
|
28592
|
+
if (derived && Object.prototype.hasOwnProperty.call(derived, key)) {
|
|
28593
|
+
return derived[key];
|
|
28594
|
+
}
|
|
28595
|
+
var pd = this._getPathData(pathId);
|
|
28596
|
+
if (pd) {
|
|
28597
|
+
return pd.getFlowAttribute(key);
|
|
28598
|
+
}
|
|
28599
|
+
return null;
|
|
28600
|
+
}
|
|
28601
|
+
|
|
28602
|
+
/**
|
|
28603
|
+
* Resolve all four flow attributes for a path as a plain object.
|
|
28604
|
+
* Each key is either the effective value or null if unset.
|
|
28605
|
+
*
|
|
28606
|
+
* @param {string} pathId
|
|
28607
|
+
* @returns {{ flowDirection: any, flowSpeed: any, flowTemperature: any, flowMaterial: any }}
|
|
28608
|
+
*/
|
|
28609
|
+
}, {
|
|
28610
|
+
key: "resolveAll",
|
|
28611
|
+
value: function resolveAll(pathId) {
|
|
28612
|
+
var _this3 = this;
|
|
28613
|
+
return Object.fromEntries(FLOW_ATTRIBUTE_KEYS.map(function (key) {
|
|
28614
|
+
return [key, _this3.resolve(pathId, key)];
|
|
28615
|
+
}));
|
|
28616
|
+
}
|
|
28617
|
+
|
|
28618
|
+
// ── Visualization ─────────────────────────────────────────────────────────
|
|
28619
|
+
|
|
28620
|
+
/**
|
|
28621
|
+
* Compute and apply the visual colour for a single path based on its resolved
|
|
28622
|
+
* flow attributes. Currently maps flowTemperature to a blue→red colour ramp.
|
|
28623
|
+
* No-ops gracefully if the path has no renderable attributes or no pipe
|
|
28624
|
+
* material exists yet.
|
|
28625
|
+
*
|
|
28626
|
+
* @param {string} pathId
|
|
28627
|
+
*/
|
|
28628
|
+
}, {
|
|
28629
|
+
key: "applyVisualizationForPath",
|
|
28630
|
+
value: function applyVisualizationForPath(pathId) {
|
|
28631
|
+
var temp = this.resolve(pathId, 'flowTemperature');
|
|
28632
|
+
if (temp === null || temp === undefined) {
|
|
28633
|
+
return; // No temperature declared — leave default pipe color
|
|
28634
|
+
}
|
|
28635
|
+
var color = temperatureToColor(temp);
|
|
28636
|
+
var renderingManager = this._getRenderingManager();
|
|
28637
|
+
if (!renderingManager) return;
|
|
28638
|
+
|
|
28639
|
+
// pathId = "from-->to"; extract the two halves
|
|
28640
|
+
var sepIdx = pathId.indexOf('-->');
|
|
28641
|
+
if (sepIdx === -1) {
|
|
28642
|
+
console.warn("PathFlowManager: malformed pathId \"".concat(pathId, "\""));
|
|
28643
|
+
return;
|
|
28644
|
+
}
|
|
28645
|
+
var from = pathId.slice(0, sepIdx);
|
|
28646
|
+
var to = pathId.slice(sepIdx + 3);
|
|
28647
|
+
renderingManager.updatePathColor(from, to, color);
|
|
28648
|
+
console.log("\uD83C\uDF21\uFE0F PathFlowManager: \"".concat(pathId, "\" \u2192 flowTemperature ").concat(temp, " \u2192 ").concat(color));
|
|
28649
|
+
}
|
|
28650
|
+
|
|
28651
|
+
/**
|
|
28652
|
+
* Apply visualizations for every known path (union of pathDataStore and derived store).
|
|
28653
|
+
* Call this after scene load or after bulk attribute changes.
|
|
28654
|
+
*/
|
|
28655
|
+
}, {
|
|
28656
|
+
key: "applyAllVisualizations",
|
|
28657
|
+
value: function applyAllVisualizations() {
|
|
28658
|
+
var _this4 = this;
|
|
28659
|
+
var pathIds = new Set();
|
|
28660
|
+
var pfMgr = this._getPathfindingManager();
|
|
28661
|
+
if (pfMgr !== null && pfMgr !== void 0 && pfMgr.pathDataStore) {
|
|
28662
|
+
pfMgr.pathDataStore.forEach(function (_, id) {
|
|
28663
|
+
return pathIds.add(id);
|
|
28664
|
+
});
|
|
28665
|
+
}
|
|
28666
|
+
this._derivedStore.forEach(function (_, id) {
|
|
28667
|
+
return pathIds.add(id);
|
|
28668
|
+
});
|
|
28669
|
+
pathIds.forEach(function (id) {
|
|
28670
|
+
return _this4.applyVisualizationForPath(id);
|
|
28671
|
+
});
|
|
28672
|
+
console.log("\uD83C\uDF0A PathFlowManager.applyAllVisualizations: processed ".concat(pathIds.size, " path(s)"));
|
|
28673
|
+
}
|
|
28674
|
+
|
|
28675
|
+
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
|
28676
|
+
}, {
|
|
28677
|
+
key: "dispose",
|
|
28678
|
+
value: function dispose() {
|
|
28679
|
+
this._derivedStore.clear();
|
|
28680
|
+
this.sceneViewer = null;
|
|
28681
|
+
_superPropGet(PathFlowManager, "dispose", this, 3)([]);
|
|
28682
|
+
}
|
|
28683
|
+
|
|
28684
|
+
// ── Private helpers ───────────────────────────────────────────────────────
|
|
28685
|
+
|
|
28686
|
+
/**
|
|
28687
|
+
* @returns {import('../../core/pathfindingData.js').PathData|null}
|
|
28688
|
+
* @private
|
|
28689
|
+
*/
|
|
28690
|
+
}, {
|
|
28691
|
+
key: "_getPathData",
|
|
28692
|
+
value: function _getPathData(pathId) {
|
|
28693
|
+
var _this$_getPathfinding, _this$_getPathfinding2;
|
|
28694
|
+
return (_this$_getPathfinding = (_this$_getPathfinding2 = this._getPathfindingManager()) === null || _this$_getPathfinding2 === void 0 || (_this$_getPathfinding2 = _this$_getPathfinding2.pathDataStore) === null || _this$_getPathfinding2 === void 0 ? void 0 : _this$_getPathfinding2.get(pathId)) !== null && _this$_getPathfinding !== void 0 ? _this$_getPathfinding : null;
|
|
28695
|
+
}
|
|
28696
|
+
|
|
28697
|
+
/**
|
|
28698
|
+
* @returns {import('../pathfinding/pathfindingManager.js').PathfindingManager|null}
|
|
28699
|
+
* @private
|
|
28700
|
+
*/
|
|
28701
|
+
}, {
|
|
28702
|
+
key: "_getPathfindingManager",
|
|
28703
|
+
value: function _getPathfindingManager() {
|
|
28704
|
+
var _this$sceneViewer$man, _this$sceneViewer;
|
|
28705
|
+
return (_this$sceneViewer$man = (_this$sceneViewer = this.sceneViewer) === null || _this$sceneViewer === void 0 || (_this$sceneViewer = _this$sceneViewer.managers) === null || _this$sceneViewer === void 0 ? void 0 : _this$sceneViewer.pathfindingManager) !== null && _this$sceneViewer$man !== void 0 ? _this$sceneViewer$man : null;
|
|
28706
|
+
}
|
|
28707
|
+
|
|
28708
|
+
/**
|
|
28709
|
+
* @returns {import('../pathfinding/PathRenderingManager.js').PathRenderingManager|null}
|
|
28710
|
+
* @private
|
|
28711
|
+
*/
|
|
28712
|
+
}, {
|
|
28713
|
+
key: "_getRenderingManager",
|
|
28714
|
+
value: function _getRenderingManager() {
|
|
28715
|
+
var _this$_getPathfinding3, _this$_getPathfinding4;
|
|
28716
|
+
return (_this$_getPathfinding3 = (_this$_getPathfinding4 = this._getPathfindingManager()) === null || _this$_getPathfinding4 === void 0 ? void 0 : _this$_getPathfinding4.renderingManager) !== null && _this$_getPathfinding3 !== void 0 ? _this$_getPathfinding3 : null;
|
|
28717
|
+
}
|
|
28718
|
+
}]);
|
|
28719
|
+
}(BaseDisposable);
|
|
28720
|
+
|
|
28224
28721
|
var BehaviorManager = /*#__PURE__*/function (_BaseDisposable) {
|
|
28225
28722
|
function BehaviorManager(sceneViewer) {
|
|
28226
28723
|
var _this;
|
|
@@ -36042,6 +36539,59 @@ var Viewport2DManager = /*#__PURE__*/function (_BaseDisposable2) {
|
|
|
36042
36539
|
}]);
|
|
36043
36540
|
}(BaseDisposable);
|
|
36044
36541
|
|
|
36542
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
36543
|
+
// Flow-direction helpers (module-level)
|
|
36544
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
36545
|
+
|
|
36546
|
+
/**
|
|
36547
|
+
* Returns the flow direction of a connector from the current scene data.
|
|
36548
|
+
* @param {Object} sceneData - currentSceneData object
|
|
36549
|
+
* @param {string} connectorId
|
|
36550
|
+
* @returns {'in'|'out'|'bi'} Defaults to 'bi' if not set.
|
|
36551
|
+
*/
|
|
36552
|
+
function _getConnectorFlow(sceneData, connectorId) {
|
|
36553
|
+
var _sceneData$scene;
|
|
36554
|
+
var children = (sceneData === null || sceneData === void 0 || (_sceneData$scene = sceneData.scene) === null || _sceneData$scene === void 0 ? void 0 : _sceneData$scene.children) || [];
|
|
36555
|
+
var _iterator = _createForOfIteratorHelper(children),
|
|
36556
|
+
_step;
|
|
36557
|
+
try {
|
|
36558
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
36559
|
+
var component = _step.value;
|
|
36560
|
+
var _iterator2 = _createForOfIteratorHelper(component.children || []),
|
|
36561
|
+
_step2;
|
|
36562
|
+
try {
|
|
36563
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
36564
|
+
var _child$userData;
|
|
36565
|
+
var child = _step2.value;
|
|
36566
|
+
if (((_child$userData = child.userData) === null || _child$userData === void 0 ? void 0 : _child$userData.objectType) === 'connector' && child.uuid === connectorId) {
|
|
36567
|
+
return child.userData.flow || 'bi';
|
|
36568
|
+
}
|
|
36569
|
+
}
|
|
36570
|
+
} catch (err) {
|
|
36571
|
+
_iterator2.e(err);
|
|
36572
|
+
} finally {
|
|
36573
|
+
_iterator2.f();
|
|
36574
|
+
}
|
|
36575
|
+
}
|
|
36576
|
+
} catch (err) {
|
|
36577
|
+
_iterator.e(err);
|
|
36578
|
+
} finally {
|
|
36579
|
+
_iterator.f();
|
|
36580
|
+
}
|
|
36581
|
+
return 'bi';
|
|
36582
|
+
}
|
|
36583
|
+
|
|
36584
|
+
/**
|
|
36585
|
+
* Returns true if fromFlow → toFlow is a valid connection.
|
|
36586
|
+
* @param {'in'|'out'|'bi'} fromFlow
|
|
36587
|
+
* @param {'in'|'out'|'bi'} toFlow
|
|
36588
|
+
* @returns {boolean}
|
|
36589
|
+
*/
|
|
36590
|
+
function _areFlowsCompatible$1(fromFlow, toFlow) {
|
|
36591
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
36592
|
+
return fromFlow !== toFlow;
|
|
36593
|
+
}
|
|
36594
|
+
|
|
36045
36595
|
/**
|
|
36046
36596
|
* CentralPlantInternals class containing internal methods and functionality
|
|
36047
36597
|
*/
|
|
@@ -36103,6 +36653,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36103
36653
|
this.centralPlant.managers.environmentManager = new EnvironmentManager(this.centralPlant.sceneViewer);
|
|
36104
36654
|
this.centralPlant.managers.keyboardControlsManager = new KeyboardControlsManager(this.centralPlant.sceneViewer);
|
|
36105
36655
|
this.centralPlant.managers.pathfindingManager = new PathfindingManager(this.centralPlant.sceneViewer);
|
|
36656
|
+
this.centralPlant.managers.pathFlowManager = new PathFlowManager(this.centralPlant.sceneViewer);
|
|
36106
36657
|
this.centralPlant.managers.behaviorManager = new BehaviorManager(this.centralPlant.sceneViewer);
|
|
36107
36658
|
this.centralPlant.managers.sceneOperationsManager = new SceneOperationsManager(this.centralPlant.sceneViewer);
|
|
36108
36659
|
this.centralPlant.managers.animationManager = new AnimationManager(this.centralPlant.sceneViewer);
|
|
@@ -36493,12 +37044,12 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36493
37044
|
console.log("\uD83D\uDD27 Translating ".concat(selectedObjects.length, " selected object(s) on ").concat(axis, " axis by ").concat(value));
|
|
36494
37045
|
|
|
36495
37046
|
// Translate each selected object using the appropriate method
|
|
36496
|
-
var
|
|
36497
|
-
|
|
37047
|
+
var _iterator3 = _createForOfIteratorHelper(selectedObjects),
|
|
37048
|
+
_step3;
|
|
36498
37049
|
try {
|
|
36499
|
-
for (
|
|
37050
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
36500
37051
|
var _obj$userData;
|
|
36501
|
-
var obj =
|
|
37052
|
+
var obj = _step3.value;
|
|
36502
37053
|
var objectType = (_obj$userData = obj.userData) === null || _obj$userData === void 0 ? void 0 : _obj$userData.objectType;
|
|
36503
37054
|
var objectId = obj.uuid;
|
|
36504
37055
|
var success = false;
|
|
@@ -36525,9 +37076,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36525
37076
|
}
|
|
36526
37077
|
}
|
|
36527
37078
|
} catch (err) {
|
|
36528
|
-
|
|
37079
|
+
_iterator3.e(err);
|
|
36529
37080
|
} finally {
|
|
36530
|
-
|
|
37081
|
+
_iterator3.f();
|
|
36531
37082
|
}
|
|
36532
37083
|
result.success = result.translatedCount === result.totalCount;
|
|
36533
37084
|
if (result.success) {
|
|
@@ -36711,7 +37262,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36711
37262
|
}, {
|
|
36712
37263
|
key: "addConnection",
|
|
36713
37264
|
value: function addConnection(fromConnectorId, toConnectorId) {
|
|
36714
|
-
var _this$centralPlant$sc4;
|
|
37265
|
+
var _this$centralPlant$sc4, _this$centralPlant$sc5;
|
|
36715
37266
|
// Use centralized validation for connection parameters
|
|
36716
37267
|
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
37268
|
var validation = this.validator.validateConnectionParams(fromConnectorId, toConnectorId, existingConnections);
|
|
@@ -36719,6 +37270,17 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36719
37270
|
return false; // Validator already logged the error
|
|
36720
37271
|
}
|
|
36721
37272
|
|
|
37273
|
+
// Validate flow direction compatibility
|
|
37274
|
+
var sceneData = (_this$centralPlant$sc5 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc5 === void 0 ? void 0 : _this$centralPlant$sc5.currentSceneData;
|
|
37275
|
+
if (sceneData) {
|
|
37276
|
+
var fromFlow = _getConnectorFlow(sceneData, fromConnectorId);
|
|
37277
|
+
var toFlow = _getConnectorFlow(sceneData, toConnectorId);
|
|
37278
|
+
if (!_areFlowsCompatible$1(fromFlow, toFlow)) {
|
|
37279
|
+
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."));
|
|
37280
|
+
return false;
|
|
37281
|
+
}
|
|
37282
|
+
}
|
|
37283
|
+
|
|
36722
37284
|
// Validate scene availability
|
|
36723
37285
|
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer);
|
|
36724
37286
|
if (!sceneValidation.isValid) {
|
|
@@ -36839,7 +37401,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36839
37401
|
}, {
|
|
36840
37402
|
key: "addComponent",
|
|
36841
37403
|
value: function addComponent(libraryId) {
|
|
36842
|
-
var _this$centralPlant$
|
|
37404
|
+
var _this$centralPlant$sc6;
|
|
36843
37405
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
36844
37406
|
// Use centralized validation for component addition parameters
|
|
36845
37407
|
var existingIds = this.getComponentIds();
|
|
@@ -36849,7 +37411,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36849
37411
|
}
|
|
36850
37412
|
|
|
36851
37413
|
// Validate scene availability
|
|
36852
|
-
var sceneValidation = this.validator.validateSceneViewer(this.centralPlant.sceneViewer, (_this$centralPlant$
|
|
37414
|
+
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
37415
|
if (!sceneValidation.isValid) {
|
|
36854
37416
|
return false;
|
|
36855
37417
|
}
|
|
@@ -36868,7 +37430,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36868
37430
|
return false;
|
|
36869
37431
|
}
|
|
36870
37432
|
try {
|
|
36871
|
-
var _componentData$childr, _componentData$childr2, _this$centralPlant$
|
|
37433
|
+
var _componentData$childr, _componentData$childr2, _this$centralPlant$sc7, _componentData$childr3, _componentData$defaul;
|
|
36872
37434
|
// Generate a unique component ID if not provided
|
|
36873
37435
|
var componentId = options.customId || this.generateUniqueComponentId(libraryId);
|
|
36874
37436
|
|
|
@@ -36980,7 +37542,7 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
36980
37542
|
componentModel.updateMatrixWorld(true);
|
|
36981
37543
|
|
|
36982
37544
|
// Check if component is underground and fix if needed (based on settings)
|
|
36983
|
-
var checkUnderground = (_this$centralPlant$
|
|
37545
|
+
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
37546
|
if (checkUnderground) {
|
|
36985
37547
|
var wasFixed = this.fixUndergroundComponent(componentModel);
|
|
36986
37548
|
if (wasFixed) {
|
|
@@ -37078,8 +37640,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37078
37640
|
// responds to tooltip-driven state changes immediately after drop.
|
|
37079
37641
|
// (The scene-load path uses _processBehaviors instead, which runs on loadSceneData.)
|
|
37080
37642
|
if ((_componentData$defaul = componentData.defaultBehaviors) !== null && _componentData$defaul !== void 0 && _componentData$defaul.length) {
|
|
37081
|
-
var _this$centralPlant$
|
|
37082
|
-
var som = (_this$centralPlant$
|
|
37643
|
+
var _this$centralPlant$sc8, _som$registerBehavior;
|
|
37644
|
+
var som = (_this$centralPlant$sc8 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc8 === void 0 ? void 0 : _this$centralPlant$sc8.sceneOperationsManager;
|
|
37083
37645
|
som === null || som === void 0 || (_som$registerBehavior = som.registerBehaviorsForComponentInstance) === null || _som$registerBehavior === void 0 || _som$registerBehavior.call(som, componentData, componentId);
|
|
37084
37646
|
}
|
|
37085
37647
|
|
|
@@ -37141,9 +37703,9 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37141
37703
|
}, {
|
|
37142
37704
|
key: "deleteComponent",
|
|
37143
37705
|
value: function deleteComponent(componentId) {
|
|
37144
|
-
var _this$centralPlant$
|
|
37706
|
+
var _this$centralPlant$sc9;
|
|
37145
37707
|
// Check if component manager is available
|
|
37146
|
-
var componentManager = (_this$centralPlant$
|
|
37708
|
+
var componentManager = (_this$centralPlant$sc9 = this.centralPlant.sceneViewer) === null || _this$centralPlant$sc9 === void 0 ? void 0 : _this$centralPlant$sc9.componentManager;
|
|
37147
37709
|
if (!componentManager) {
|
|
37148
37710
|
console.error('❌ deleteComponent(): Component manager not available');
|
|
37149
37711
|
return false;
|
|
@@ -37218,8 +37780,8 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37218
37780
|
}
|
|
37219
37781
|
var componentIds = [];
|
|
37220
37782
|
this.centralPlant.sceneViewer.scene.traverse(function (child) {
|
|
37221
|
-
var _child$
|
|
37222
|
-
if (((_child$
|
|
37783
|
+
var _child$userData2;
|
|
37784
|
+
if (((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.objectType) === 'component') {
|
|
37223
37785
|
componentIds.push(child.uuid || child.userData.originalUuid);
|
|
37224
37786
|
}
|
|
37225
37787
|
});
|
|
@@ -37228,6 +37790,22 @@ var CentralPlantInternals = /*#__PURE__*/function () {
|
|
|
37228
37790
|
}]);
|
|
37229
37791
|
}();
|
|
37230
37792
|
|
|
37793
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
37794
|
+
// Flow-direction compatibility helper (module-level, no class dependency)
|
|
37795
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
37796
|
+
|
|
37797
|
+
/**
|
|
37798
|
+
* Returns true if the two flow directions are compatible for a connection.
|
|
37799
|
+
* @param {string} fromFlow - 'in' | 'out' | 'bi'
|
|
37800
|
+
* @param {string} toFlow - 'in' | 'out' | 'bi'
|
|
37801
|
+
* @returns {boolean}
|
|
37802
|
+
*/
|
|
37803
|
+
function _areFlowsCompatible(fromFlow, toFlow) {
|
|
37804
|
+
if (fromFlow === 'bi' || toFlow === 'bi') return true;
|
|
37805
|
+
// in ↔ out are compatible; in → in and out → out are not
|
|
37806
|
+
return fromFlow !== toFlow;
|
|
37807
|
+
}
|
|
37808
|
+
|
|
37231
37809
|
/**
|
|
37232
37810
|
* CentralPlant class that manages all scene utility instances and provides public API
|
|
37233
37811
|
*
|
|
@@ -37238,7 +37816,7 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
37238
37816
|
* Initialize the CentralPlant manager
|
|
37239
37817
|
*
|
|
37240
37818
|
* @constructor
|
|
37241
|
-
* @version 0.2.
|
|
37819
|
+
* @version 0.2.10
|
|
37242
37820
|
* @updated 2025-10-22
|
|
37243
37821
|
*
|
|
37244
37822
|
* @description Creates a new CentralPlant instance and initializes internal managers and utilities.
|
|
@@ -38171,6 +38749,107 @@ var CentralPlant = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
38171
38749
|
return availableConnectorIds;
|
|
38172
38750
|
}
|
|
38173
38751
|
|
|
38752
|
+
/**
|
|
38753
|
+
* Get available connectors with their flow direction metadata.
|
|
38754
|
+
* Same filtering logic as getAvailableConnections() but returns objects instead of strings.
|
|
38755
|
+
* @returns {Array<{id: string, flow: string}>} Array of connector info objects.
|
|
38756
|
+
* flow is one of 'in', 'out', 'bi'. Defaults to 'bi' if not set in userData.
|
|
38757
|
+
* @example
|
|
38758
|
+
* const infos = centralPlant.getAvailableConnectionsInfo()
|
|
38759
|
+
* // [{ id: 'PUMP-1-CONNECTOR-1', flow: 'out' }, ...]
|
|
38760
|
+
*/
|
|
38761
|
+
}, {
|
|
38762
|
+
key: "getAvailableConnectionsInfo",
|
|
38763
|
+
value: function getAvailableConnectionsInfo() {
|
|
38764
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
38765
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Scene viewer or current scene data not available');
|
|
38766
|
+
return [];
|
|
38767
|
+
}
|
|
38768
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
38769
|
+
if (!sceneData.scene || !sceneData.scene.children) {
|
|
38770
|
+
console.warn('⚠️ getAvailableConnectionsInfo(): Invalid scene data structure');
|
|
38771
|
+
return [];
|
|
38772
|
+
}
|
|
38773
|
+
var allConnectorInfos = [];
|
|
38774
|
+
sceneData.scene.children.forEach(function (component) {
|
|
38775
|
+
if (component.children && Array.isArray(component.children)) {
|
|
38776
|
+
component.children.forEach(function (child) {
|
|
38777
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
38778
|
+
allConnectorInfos.push({
|
|
38779
|
+
id: child.uuid,
|
|
38780
|
+
flow: child.userData.flow || 'bi'
|
|
38781
|
+
});
|
|
38782
|
+
}
|
|
38783
|
+
});
|
|
38784
|
+
}
|
|
38785
|
+
});
|
|
38786
|
+
var existingConnections = this.getConnections();
|
|
38787
|
+
var usedConnectorIds = new Set();
|
|
38788
|
+
existingConnections.forEach(function (connection) {
|
|
38789
|
+
if (connection.from) usedConnectorIds.add(connection.from);
|
|
38790
|
+
if (connection.to) usedConnectorIds.add(connection.to);
|
|
38791
|
+
});
|
|
38792
|
+
return allConnectorInfos.filter(function (info) {
|
|
38793
|
+
return !usedConnectorIds.has(info.id);
|
|
38794
|
+
});
|
|
38795
|
+
}
|
|
38796
|
+
|
|
38797
|
+
/**
|
|
38798
|
+
* Validate all connections in the current scene for flow direction compatibility.
|
|
38799
|
+
* @returns {{ valid: Array<Object>, invalid: Array<{connection: Object, reason: string}> }}
|
|
38800
|
+
* @example
|
|
38801
|
+
* const result = centralPlant.validateConnections()
|
|
38802
|
+
* result.invalid.forEach(({ connection, reason }) => console.warn(reason, connection))
|
|
38803
|
+
*/
|
|
38804
|
+
}, {
|
|
38805
|
+
key: "validateConnections",
|
|
38806
|
+
value: function validateConnections() {
|
|
38807
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
38808
|
+
console.warn('⚠️ validateConnections(): Scene viewer or current scene data not available');
|
|
38809
|
+
return {
|
|
38810
|
+
valid: [],
|
|
38811
|
+
invalid: []
|
|
38812
|
+
};
|
|
38813
|
+
}
|
|
38814
|
+
var connections = this.getConnections();
|
|
38815
|
+
var sceneData = this.sceneViewer.currentSceneData;
|
|
38816
|
+
|
|
38817
|
+
// Build lookup map: connectorId → flow
|
|
38818
|
+
var flowMap = {};
|
|
38819
|
+
var scene = sceneData.scene || {};
|
|
38820
|
+
var children = scene.children || [];
|
|
38821
|
+
children.forEach(function (component) {
|
|
38822
|
+
if (component.children && Array.isArray(component.children)) {
|
|
38823
|
+
component.children.forEach(function (child) {
|
|
38824
|
+
if (child.userData && child.userData.objectType === 'connector' && child.uuid) {
|
|
38825
|
+
flowMap[child.uuid] = child.userData.flow || 'bi';
|
|
38826
|
+
}
|
|
38827
|
+
});
|
|
38828
|
+
}
|
|
38829
|
+
});
|
|
38830
|
+
var valid = [];
|
|
38831
|
+
var invalid = [];
|
|
38832
|
+
connections.forEach(function (connection) {
|
|
38833
|
+
var fromFlow = flowMap[connection.from] || 'bi';
|
|
38834
|
+
var toFlow = flowMap[connection.to] || 'bi';
|
|
38835
|
+
if (_areFlowsCompatible(fromFlow, toFlow)) {
|
|
38836
|
+
valid.push(connection);
|
|
38837
|
+
} else {
|
|
38838
|
+
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");
|
|
38839
|
+
console.warn("\u26A0\uFE0F validateConnections(): ".concat(reason));
|
|
38840
|
+
invalid.push({
|
|
38841
|
+
connection: connection,
|
|
38842
|
+
reason: reason
|
|
38843
|
+
});
|
|
38844
|
+
}
|
|
38845
|
+
});
|
|
38846
|
+
console.log("\u2705 validateConnections(): ".concat(valid.length, " valid, ").concat(invalid.length, " invalid connections"));
|
|
38847
|
+
return {
|
|
38848
|
+
valid: valid,
|
|
38849
|
+
invalid: invalid
|
|
38850
|
+
};
|
|
38851
|
+
}
|
|
38852
|
+
|
|
38174
38853
|
// ─────────────────────────────────────────────────────────────────────────
|
|
38175
38854
|
// BEHAVIORS API
|
|
38176
38855
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -40154,7 +40833,7 @@ var sceneViewer = /*#__PURE__*/function (_BaseDisposable) {
|
|
|
40154
40833
|
this.centralPlant.attachToComponent();
|
|
40155
40834
|
|
|
40156
40835
|
// Sync our managers tracking object after attachment
|
|
40157
|
-
managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'behaviorManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
|
|
40836
|
+
managerKeys = ['threeJSResourceManager', 'performanceMonitorManager', 'settingsManager', 'sceneExportManager', 'componentManager', 'sceneInitializationManager', 'environmentManager', 'keyboardControlsManager', 'pathfindingManager', 'pathFlowManager', 'behaviorManager', 'sceneOperationsManager', 'animationManager', 'cameraControlsManager', 'componentDragManager', 'tooltipsManager', 'componentTooltipManager']; // Populate our managers tracking object
|
|
40158
40837
|
managerKeys.forEach(function (key) {
|
|
40159
40838
|
if (_this2[key]) {
|
|
40160
40839
|
_this2.managers[key] = _this2[key];
|
|
@@ -43770,10 +44449,12 @@ exports.ComponentDragManager = ComponentDragManager;
|
|
|
43770
44449
|
exports.ComponentManager = ComponentManager;
|
|
43771
44450
|
exports.ComponentTooltipManager = ComponentTooltipManager;
|
|
43772
44451
|
exports.EnvironmentManager = EnvironmentManager;
|
|
44452
|
+
exports.FLOW_ATTRIBUTE_KEYS = FLOW_ATTRIBUTE_KEYS;
|
|
43773
44453
|
exports.KeyboardControlsManager = KeyboardControlsManager;
|
|
43774
44454
|
exports.ModelManager = ModelManager;
|
|
43775
44455
|
exports.OperationHistoryManager = OperationHistoryManager;
|
|
43776
44456
|
exports.PathData = PathData;
|
|
44457
|
+
exports.PathFlowManager = PathFlowManager;
|
|
43777
44458
|
exports.PathfindingManager = PathfindingManager;
|
|
43778
44459
|
exports.PerformanceMonitorManager = PerformanceMonitorManager;
|
|
43779
44460
|
exports.Rendering2D = rendering2D;
|