@2112-lab/central-plant 0.1.39 → 0.1.41

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.
Files changed (45) hide show
  1. package/dist/bundle/index.js +7991 -7054
  2. package/dist/cjs/src/core/centralPlant.js +48 -3
  3. package/dist/cjs/src/core/centralPlantInternals.js +75 -566
  4. package/dist/cjs/src/core/sceneViewer.js +38 -13
  5. package/dist/cjs/src/index.js +6 -4
  6. package/dist/cjs/src/managers/components/pathfindingManager.js +75 -60
  7. package/dist/cjs/src/managers/components/transformOperationsManager.js +929 -0
  8. package/dist/cjs/src/managers/controls/keyboardControlsManager.js +57 -1
  9. package/dist/cjs/src/managers/controls/transformControls.js +11 -3
  10. package/dist/cjs/src/managers/controls/transformControlsManager.js +563 -263
  11. package/dist/cjs/src/managers/pathfinding/ConnectorManager.js +385 -0
  12. package/dist/cjs/src/managers/pathfinding/PathIntersectionDetector.js +387 -0
  13. package/dist/cjs/src/managers/pathfinding/PathRenderingManager.js +401 -0
  14. package/dist/cjs/src/managers/pathfinding/pathfindingManager.js +378 -0
  15. package/dist/cjs/src/managers/pathfinding/sceneDataManager.js +256 -0
  16. package/dist/cjs/src/managers/scene/animationManager.js +145 -0
  17. package/dist/cjs/src/managers/scene/sceneExportManager.js +14 -13
  18. package/dist/cjs/src/managers/scene/sceneOperationsManager.js +516 -21
  19. package/dist/cjs/src/managers/scene/sceneTooltipsManager.js +1 -8
  20. package/dist/cjs/src/managers/system/operationHistoryManager.js +414 -0
  21. package/dist/cjs/src/managers/system/settingsManager.js +2 -1
  22. package/dist/cjs/src/utils/objectTypes.js +5 -7
  23. package/dist/esm/src/core/centralPlant.js +48 -3
  24. package/dist/esm/src/core/centralPlantInternals.js +76 -567
  25. package/dist/esm/src/core/sceneViewer.js +38 -13
  26. package/dist/esm/src/index.js +4 -3
  27. package/dist/esm/src/managers/components/pathfindingManager.js +75 -60
  28. package/dist/esm/src/managers/components/transformOperationsManager.js +904 -0
  29. package/dist/esm/src/managers/controls/keyboardControlsManager.js +57 -1
  30. package/dist/esm/src/managers/controls/transformControls.js +11 -3
  31. package/dist/esm/src/managers/controls/transformControlsManager.js +564 -264
  32. package/dist/esm/src/managers/pathfinding/ConnectorManager.js +361 -0
  33. package/dist/esm/src/managers/pathfinding/PathIntersectionDetector.js +363 -0
  34. package/dist/esm/src/managers/pathfinding/PathRenderingManager.js +377 -0
  35. package/dist/esm/src/managers/pathfinding/pathfindingManager.js +374 -0
  36. package/dist/esm/src/managers/pathfinding/sceneDataManager.js +232 -0
  37. package/dist/esm/src/managers/scene/animationManager.js +141 -0
  38. package/dist/esm/src/managers/scene/sceneExportManager.js +14 -13
  39. package/dist/esm/src/managers/scene/sceneOperationsManager.js +516 -21
  40. package/dist/esm/src/managers/scene/sceneTooltipsManager.js +1 -8
  41. package/dist/esm/src/managers/system/operationHistoryManager.js +409 -0
  42. package/dist/esm/src/managers/system/settingsManager.js +2 -1
  43. package/dist/esm/src/utils/objectTypes.js +5 -7
  44. package/dist/index.d.ts +2 -2
  45. package/package.json +1 -1
@@ -0,0 +1,377 @@
1
+ import { inherits as _inherits, createClass as _createClass, toConsumableArray as _toConsumableArray, objectSpread2 as _objectSpread2, construct as _construct, superPropGet as _superPropGet, classCallCheck as _classCallCheck, callSuper as _callSuper } from '../../../_virtual/_rollupPluginBabelHelpers.js';
2
+ import * as THREE from 'three';
3
+ import { BaseDisposable } from '../../core/baseDisposable.js';
4
+
5
+ var PathRenderingManager = /*#__PURE__*/function (_BaseDisposable) {
6
+ function PathRenderingManager(sceneViewer) {
7
+ var _this;
8
+ _classCallCheck(this, PathRenderingManager);
9
+ _this = _callSuper(this, PathRenderingManager);
10
+ _this.sceneViewer = sceneViewer;
11
+
12
+ // Shared gateway resources to prevent memory leaks
13
+ _this._gatewayGeometry = new THREE.SphereGeometry(0.15, 16, 16);
14
+ _this._gatewayMaterial = new THREE.MeshStandardMaterial({
15
+ color: 0xFFFFFF,
16
+ roughness: 0.7,
17
+ metalness: 0.3,
18
+ emissive: 0
19
+ });
20
+ _this.registerDisposable(_this._gatewayGeometry, _this._gatewayMaterial);
21
+ return _this;
22
+ }
23
+
24
+ /**
25
+ * Get path colors for visual distinction
26
+ * @param {number} index - Path index
27
+ * @returns {string} Hex color string
28
+ */
29
+ _inherits(PathRenderingManager, _BaseDisposable);
30
+ return _createClass(PathRenderingManager, [{
31
+ key: "getPathColor",
32
+ value: function getPathColor(index) {
33
+ var colors = [
34
+ // '#468e49',
35
+ '#245e29'
36
+ // '#2e80d2',
37
+ // '#1d51a1'
38
+ ];
39
+ return colors[index % colors.length];
40
+ }
41
+
42
+ /**
43
+ * Create gateways in the scene from pathfinding results
44
+ * @param {Object} pathfindingResult - Result object from pathfinder containing gateways
45
+ */
46
+ }, {
47
+ key: "createGateways",
48
+ value: function createGateways(pathfindingResult) {
49
+ var _this2 = this;
50
+ pathfindingResult.gateways.forEach(function (gateway) {
51
+ if (!gateway.position) {
52
+ console.warn("\u26A0\uFE0F Gateway ".concat(gateway.id, " missing position, skipping creation"));
53
+ return;
54
+ }
55
+
56
+ // Check if gateway already exists in scene (prevent duplicates)
57
+ var existingGateway = _this2.sceneViewer.scene.getObjectByProperty('uuid', gateway.id);
58
+ if (existingGateway) {
59
+ console.log("\u2139\uFE0F Gateway ".concat(gateway.id, " already exists, skipping creation"));
60
+ return;
61
+ }
62
+
63
+ // Create gateway mesh using shared geometry and material
64
+ var gatewayMesh = new THREE.Mesh(_this2._gatewayGeometry, _this2._gatewayMaterial);
65
+
66
+ // Handle position format: pathfinder returns {x,y,z} object or [x,y,z] array
67
+ if (Array.isArray(gateway.position)) {
68
+ gatewayMesh.position.fromArray(gateway.position);
69
+ } else if (gateway.position.x !== undefined) {
70
+ gatewayMesh.position.set(gateway.position.x, gateway.position.y, gateway.position.z);
71
+ } else {
72
+ console.error("\u274C Invalid gateway position format for ".concat(gateway.id, ":"), gateway.position);
73
+ return;
74
+ }
75
+ gatewayMesh.uuid = gateway.id;
76
+
77
+ // Set userData to make gateways selectable
78
+ gatewayMesh.userData = {
79
+ objectType: 'gateway',
80
+ isDeclared: false,
81
+ gatewayId: gateway.id,
82
+ originalUuid: gateway.id,
83
+ // Deep copy connections to prevent mutations affecting pathfinder's internal state
84
+ connections: gateway.connections ? {
85
+ removed: gateway.connections.removed ? _toConsumableArray(gateway.connections.removed) : [],
86
+ added: gateway.connections.added ? _toConsumableArray(gateway.connections.added) : []
87
+ } : {
88
+ removed: [],
89
+ added: []
90
+ }
91
+ };
92
+
93
+ // Add to scene
94
+ _this2.sceneViewer.scene.add(gatewayMesh);
95
+ console.log("\uD83D\uDD27 Created gateway: ".concat(gateway.id, " at [").concat(gatewayMesh.position.x.toFixed(2), ", ").concat(gatewayMesh.position.y.toFixed(2), ", ").concat(gatewayMesh.position.z.toFixed(2), "]"));
96
+ });
97
+ }
98
+
99
+ /**
100
+ * Material factory function for pipe materials
101
+ * @param {Object} crosscubeTextureSet - Texture set for pipe materials
102
+ * @returns {THREE.Material} Pipe material
103
+ */
104
+ }, {
105
+ key: "createPipeMaterial",
106
+ value: function createPipeMaterial(crosscubeTextureSet) {
107
+ if (crosscubeTextureSet) {
108
+ var materialProps = _objectSpread2(_objectSpread2({}, crosscubeTextureSet.config.materialProps), {}, {
109
+ color: this.getPathColor(0),
110
+ map: crosscubeTextureSet.textures.diffuse,
111
+ normalMap: crosscubeTextureSet.textures.normal,
112
+ roughnessMap: crosscubeTextureSet.textures.roughness,
113
+ metalness: 0.2,
114
+ roughness: 0.9,
115
+ clearcoat: 0.2,
116
+ clearcoatRoughness: 0.2,
117
+ envMapIntensity: 0.6,
118
+ reflectivity: 0.4
119
+ // transparent: true,
120
+ // opacity: 0.75
121
+ });
122
+
123
+ // Handle normalScale conversion to Vector2
124
+ if (materialProps.normalScale && Array.isArray(materialProps.normalScale)) {
125
+ materialProps.normalScale = _construct(THREE.Vector2, _toConsumableArray(materialProps.normalScale));
126
+ }
127
+ var material = new THREE.MeshPhysicalMaterial(materialProps);
128
+
129
+ // Configure texture wrapping and repeat
130
+ var pipeTextures = [material.map, material.normalMap, material.roughnessMap].filter(Boolean);
131
+ pipeTextures.forEach(function (texture) {
132
+ texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
133
+ texture.repeat.set(crosscubeTextureSet.config.repeat.x * 2, crosscubeTextureSet.config.repeat.y * 2);
134
+ });
135
+ return material;
136
+ } else {
137
+ return new THREE.MeshPhysicalMaterial({
138
+ color: this.getPathColor(0),
139
+ metalness: 0.9,
140
+ roughness: 0.7,
141
+ clearcoat: 0.1,
142
+ clearcoatRoughness: 0.3,
143
+ envMapIntensity: 1.5,
144
+ reflectivity: 0.3
145
+ });
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Create pipe paths from pathfinding results
151
+ * @param {Array} paths - Array of path objects from pathfinder
152
+ * @param {Object} crosscubeTextureSet - Texture set for pipe materials
153
+ */
154
+ }, {
155
+ key: "createPipePaths",
156
+ value: function createPipePaths(paths, crosscubeTextureSet) {
157
+ var _this3 = this;
158
+ var sceneViewer = this.sceneViewer;
159
+ var globalSegmentIndex = 0; // Counter for globally unique segment indices
160
+
161
+ paths.forEach(function (pathData, index) {
162
+ if (pathData.path && pathData.path.length >= 2) {
163
+ var pipeRadius = 0.1;
164
+ var pipeMaterial = _this3.createPipeMaterial(crosscubeTextureSet);
165
+
166
+ // Convert path points to Vector3 objects for consistent handling
167
+ var pathPoints = pathData.path.map(function (point) {
168
+ if (point instanceof THREE.Vector3) {
169
+ return point.clone();
170
+ } else if (Array.isArray(point)) {
171
+ return new THREE.Vector3().fromArray(point);
172
+ } else if (point.x !== undefined && point.y !== undefined && point.z !== undefined) {
173
+ return new THREE.Vector3(point.x, point.y, point.z);
174
+ } else {
175
+ console.warn('Unknown point format in createPipePaths:', point);
176
+ return new THREE.Vector3(0, 0, 0);
177
+ }
178
+ });
179
+
180
+ // Create one cylinder per segment (after colinear optimization, this should be minimal segments)
181
+ for (var j = 0; j < pathPoints.length - 1; j++) {
182
+ var start = pathPoints[j];
183
+ var end = pathPoints[j + 1];
184
+ var direction = new THREE.Vector3().subVectors(end, start);
185
+ var length = direction.length();
186
+
187
+ // Skip zero-length segments
188
+ if (length < 1e-6) {
189
+ console.warn("Skipping zero-length segment in path ".concat(pathData.from, "-").concat(pathData.to));
190
+ continue;
191
+ }
192
+ var cylinderGeometry = new THREE.CylinderGeometry(pipeRadius, pipeRadius, length, 16, 1, false);
193
+ var cylinder = new THREE.Mesh(cylinderGeometry, pipeMaterial);
194
+ cylinder.position.copy(start).add(end).multiplyScalar(0.5);
195
+ var quaternion = new THREE.Quaternion();
196
+ var up = new THREE.Vector3(0, 1, 0);
197
+ quaternion.setFromUnitVectors(up, direction.clone().normalize());
198
+ cylinder.quaternion.copy(quaternion);
199
+ cylinder.castShadow = true;
200
+ cylinder.receiveShadow = true;
201
+
202
+ // Set UUID to SEGMENT-{globalSegmentIndex} format
203
+ cylinder.uuid = "SEGMENT-".concat(globalSegmentIndex);
204
+
205
+ // Make pipe segments selectable and add identifying data
206
+ var segmentId = cylinder.uuid;
207
+
208
+ // Add userData to make pipe segments selectable and for tooltip display
209
+ cylinder.userData = {
210
+ objectType: 'segment',
211
+ segmentId: segmentId,
212
+ segmentIndex: globalSegmentIndex,
213
+ pathFrom: pathData.from,
214
+ pathTo: pathData.to
215
+ };
216
+
217
+ // Increment global segment counter
218
+ globalSegmentIndex++;
219
+
220
+ // Add segment directly to scene instead of to polyline
221
+ sceneViewer.scene.add(cylinder);
222
+
223
+ // Add smooth elbow joints only at actual direction changes (not at every point)
224
+ _this3.createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, sceneViewer.scene // Pass scene instead of polyline
225
+ );
226
+ }
227
+ console.log("\u2705 Created pipe path ".concat(pathData.from, "-").concat(pathData.to, " with ").concat(pathPoints.length - 1, " segments"));
228
+ }
229
+ });
230
+ }
231
+
232
+ /**
233
+ * Create and add elbow joint if there's a direction change at the current segment
234
+ * @param {Array<THREE.Vector3>} pathPoints - Array of path points
235
+ * @param {number} j - Current segment index
236
+ * @param {number} pipeRadius - Radius of the pipe
237
+ * @param {THREE.Material} pipeMaterial - Material for the elbow
238
+ * @param {Object} pathData - Path data object with from/to information
239
+ * @param {number} index - Path index for naming
240
+ * @param {THREE.Scene} scene - Scene object to add elbow to directly
241
+ */
242
+ }, {
243
+ key: "createAndAddElbowIfNeeded",
244
+ value: function createAndAddElbowIfNeeded(pathPoints, j, pipeRadius, pipeMaterial, pathData, index, scene) {
245
+ // Only check if there are at least 2 more points ahead
246
+ if (j >= pathPoints.length - 2) {
247
+ return;
248
+ }
249
+ var currentSegment = pathPoints[j + 1].clone().sub(pathPoints[j]).normalize();
250
+ var nextSegment = pathPoints[j + 2].clone().sub(pathPoints[j + 1]).normalize();
251
+
252
+ // Check if there's actually a direction change (not just continuing straight)
253
+ var angle = currentSegment.angleTo(nextSegment);
254
+ var minAngle = Math.PI / 36; // 5 degrees minimum for creating an elbow
255
+
256
+ if (angle <= minAngle) {
257
+ return; // No significant direction change
258
+ }
259
+ var elbowGeometry = this.createElbowGeometry(pathPoints[j], pathPoints[j + 1], pathPoints[j + 2], pipeRadius);
260
+ if (!elbowGeometry) {
261
+ return; // Failed to create geometry
262
+ }
263
+ var elbow = new THREE.Mesh(elbowGeometry, pipeMaterial);
264
+ elbow.castShadow = true;
265
+ elbow.receiveShadow = true;
266
+
267
+ // Make elbows selectable as well
268
+ var elbowId = "pipe-elbow-".concat(pathData.from, "-").concat(pathData.to, "-").concat(j);
269
+ elbow.uuid = "Pipe Elbow ".concat(j + 1, ": ").concat(pathData.from, "-").concat(pathData.to);
270
+
271
+ // Add userData for elbows too
272
+ elbow.userData = {
273
+ isPipeElbow: true,
274
+ elbowId: elbowId,
275
+ elbowIndex: j,
276
+ pathFrom: pathData.from,
277
+ pathTo: pathData.to,
278
+ angle: (angle * 180 / Math.PI).toFixed(1),
279
+ // Add component data for tooltips
280
+ component: {
281
+ type: 'PipeElbow',
282
+ attributes: {
283
+ angle: {
284
+ key: 'Bend Angle',
285
+ value: (angle * 180 / Math.PI).toFixed(1),
286
+ unit: '°'
287
+ }
288
+ }
289
+ }
290
+ };
291
+ scene.add(elbow);
292
+ }
293
+
294
+ /**
295
+ * Create smooth elbow geometry to connect two pipe segments (optimized for 90-degree angles)
296
+ * @param {THREE.Vector3} point1 - First point (before the joint)
297
+ * @param {THREE.Vector3} point2 - Joint point (center of the elbow)
298
+ * @param {THREE.Vector3} point3 - Third point (after the joint)
299
+ * @param {number} radius - Pipe radius
300
+ * @returns {THREE.BufferGeometry} Elbow geometry
301
+ */
302
+ }, {
303
+ key: "createElbowGeometry",
304
+ value: function createElbowGeometry(point1, point2, point3, radius) {
305
+ try {
306
+ // Fixed elbow radius for 90-degree bends (simplified)
307
+ var elbowRadius = radius * 3;
308
+
309
+ // Create a curve for the 90-degree elbow
310
+ var curve = this.createElbowCurve(point1, point2, point3, elbowRadius);
311
+
312
+ // Fixed tubular segments for 90-degree bends (quarter circle)
313
+ var tubularSegments = 12; // Good balance for smooth 90° curves
314
+ var radialSegments = 16;
315
+ var closed = false;
316
+ var elbowGeometry = new THREE.TubeGeometry(curve, tubularSegments, radius, radialSegments, closed);
317
+ return elbowGeometry;
318
+ } catch (error) {
319
+ console.warn('Failed to create elbow geometry:', error);
320
+ return null;
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Create a smooth curve for the 90-degree elbow joint (simplified)
326
+ * @param {THREE.Vector3} point1 - First point
327
+ * @param {THREE.Vector3} point2 - Joint point
328
+ * @param {THREE.Vector3} point3 - Third point
329
+ * @param {number} elbowRadius - Radius of the elbow curve
330
+ * @returns {THREE.Curve} Curve for the elbow
331
+ */
332
+ }, {
333
+ key: "createElbowCurve",
334
+ value: function createElbowCurve(point1, point2, point3, elbowRadius) {
335
+ // Calculate direction vectors
336
+ var dir1 = point2.clone().sub(point1).normalize();
337
+ var dir2 = point3.clone().sub(point2).normalize();
338
+
339
+ // For 90-degree bends, we can use a simpler approach with a quarter circle
340
+ // The curve radius is proportional to the elbow radius
341
+ var curveRadius = elbowRadius * 0.001;
342
+
343
+ // Calculate the offset distance from the joint point
344
+ var offset = curveRadius;
345
+
346
+ // Calculate start and end points of the curve (offset from the joint)
347
+ var curveStart = point2.clone().sub(dir1.clone().multiplyScalar(offset));
348
+ var curveEnd = point2.clone().add(dir2.clone().multiplyScalar(offset));
349
+
350
+ // For a 90-degree bend, the control point is at the corner
351
+ // We can use a quadratic bezier curve for simplicity
352
+ var controlPoint = point2.clone();
353
+
354
+ // Create a quadratic bezier curve (simpler than cubic for 90° bends)
355
+ var curve = new THREE.QuadraticBezierCurve3(curveStart, controlPoint, curveEnd);
356
+ return curve;
357
+ }
358
+
359
+ /**
360
+ * Dispose of rendering resources
361
+ */
362
+ }, {
363
+ key: "dispose",
364
+ value: function dispose() {
365
+ console.log('🗑️ Disposing PathRenderingManager...');
366
+
367
+ // Call parent dispose to clean up registered resources (shared gateway geometry/material)
368
+ _superPropGet(PathRenderingManager, "dispose", this, 3)([]);
369
+
370
+ // Nullify properties
371
+ this.sceneViewer = null;
372
+ console.log('✅ PathRenderingManager disposed');
373
+ }
374
+ }]);
375
+ }(BaseDisposable);
376
+
377
+ export { PathRenderingManager };