@2112-lab/central-plant 0.1.25 → 0.1.27
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 +387 -3
- package/dist/cjs/src/core/centralPlant.js +387 -3
- package/dist/esm/src/core/centralPlant.js +388 -4
- package/package.json +1 -1
package/dist/bundle/index.js
CHANGED
|
@@ -25861,12 +25861,133 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
25861
25861
|
return true;
|
|
25862
25862
|
}
|
|
25863
25863
|
|
|
25864
|
+
/**
|
|
25865
|
+
* Rotate a component by componentId
|
|
25866
|
+
* @param {string} componentId - The UUID of the component to rotate
|
|
25867
|
+
* @param {string} axis - The axis to rotate around ('x', 'y', or 'z')
|
|
25868
|
+
* @param {number} value - The value to rotate by in degrees
|
|
25869
|
+
* @returns {boolean} True if rotation was successful, false otherwise
|
|
25870
|
+
* @description Rotates a component around the specified axis by the given angle in degrees.
|
|
25871
|
+
* The rotation is applied incrementally to the component's current rotation.
|
|
25872
|
+
* @example
|
|
25873
|
+
* // Rotate a component 45 degrees around Y axis
|
|
25874
|
+
* const success = centralPlant.rotate('component-uuid-123', 'y', 45);
|
|
25875
|
+
*
|
|
25876
|
+
* // Rotate a component -90 degrees around Z axis
|
|
25877
|
+
* centralPlant.rotate('component-uuid-456', 'z', -90);
|
|
25878
|
+
*
|
|
25879
|
+
* // Rotate a component 180 degrees around X axis
|
|
25880
|
+
* centralPlant.rotate('component-uuid-789', 'x', 180);
|
|
25881
|
+
*
|
|
25882
|
+
* @since 0.1.25
|
|
25883
|
+
*/
|
|
25884
|
+
}, {
|
|
25885
|
+
key: "rotate",
|
|
25886
|
+
value: function rotate(componentId, axis, value) {
|
|
25887
|
+
// Validate input parameters
|
|
25888
|
+
if (!componentId || typeof componentId !== 'string') {
|
|
25889
|
+
console.error('❌ rotate(): Invalid componentId provided. Must be a non-empty string:', componentId);
|
|
25890
|
+
return false;
|
|
25891
|
+
}
|
|
25892
|
+
if (!['x', 'y', 'z'].includes(axis)) {
|
|
25893
|
+
console.error('❌ rotate(): Invalid axis provided. Must be "x", "y", or "z":', axis);
|
|
25894
|
+
return false;
|
|
25895
|
+
}
|
|
25896
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
25897
|
+
console.error('❌ rotate(): Invalid value provided. Must be a number:', value);
|
|
25898
|
+
return false;
|
|
25899
|
+
}
|
|
25900
|
+
|
|
25901
|
+
// Check if scene viewer and scene are available
|
|
25902
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
25903
|
+
console.error('❌ rotate(): Scene viewer or scene not available');
|
|
25904
|
+
return false;
|
|
25905
|
+
}
|
|
25906
|
+
|
|
25907
|
+
// Find the component in the scene
|
|
25908
|
+
var component = null;
|
|
25909
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
25910
|
+
var _child$userData2;
|
|
25911
|
+
if (child.uuid === componentId || ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === componentId) {
|
|
25912
|
+
component = child;
|
|
25913
|
+
}
|
|
25914
|
+
});
|
|
25915
|
+
if (!component) {
|
|
25916
|
+
console.error("\u274C rotate(): Component with ID '".concat(componentId, "' not found in scene"));
|
|
25917
|
+
return false;
|
|
25918
|
+
}
|
|
25919
|
+
if (!component.userData.libraryId) {
|
|
25920
|
+
console.error("\u274C rotate(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
25921
|
+
return false;
|
|
25922
|
+
}
|
|
25923
|
+
|
|
25924
|
+
// Store previous rotation for potential undo
|
|
25925
|
+
var previousRotation = {
|
|
25926
|
+
x: component.rotation.x,
|
|
25927
|
+
y: component.rotation.y,
|
|
25928
|
+
z: component.rotation.z
|
|
25929
|
+
};
|
|
25930
|
+
|
|
25931
|
+
// Convert degrees to radians
|
|
25932
|
+
var radians = value * Math.PI / 180;
|
|
25933
|
+
console.log("\uD83D\uDD04 rotate(): Rotating component ".concat(componentId, " around ").concat(axis, " axis by ").concat(value, " degrees (").concat(radians, " radians)"));
|
|
25934
|
+
|
|
25935
|
+
// Apply the rotation
|
|
25936
|
+
component.rotation[axis] += radians;
|
|
25937
|
+
|
|
25938
|
+
// Update the associated JSON object in currentSceneData if it exists
|
|
25939
|
+
if (this.sceneViewer.currentSceneData && this.sceneViewer.currentSceneData.scene) {
|
|
25940
|
+
if (component.userData.associatedJsonObject) {
|
|
25941
|
+
// Convert back to degrees for JSON storage
|
|
25942
|
+
component.userData.associatedJsonObject.rotation = component.userData.associatedJsonObject.rotation || {
|
|
25943
|
+
x: 0,
|
|
25944
|
+
y: 0,
|
|
25945
|
+
z: 0
|
|
25946
|
+
};
|
|
25947
|
+
component.userData.associatedJsonObject.rotation[axis] = component.rotation[axis] * 180 / Math.PI;
|
|
25948
|
+
console.log("\uD83D\uDD04 Updated associated JSON object rotation for ".concat(componentId));
|
|
25949
|
+
}
|
|
25950
|
+
}
|
|
25951
|
+
|
|
25952
|
+
// Update matrices
|
|
25953
|
+
component.updateMatrix();
|
|
25954
|
+
component.updateMatrixWorld(true);
|
|
25955
|
+
|
|
25956
|
+
// Record the transform for potential undo
|
|
25957
|
+
this.internals.recordTransform({
|
|
25958
|
+
type: 'rotate',
|
|
25959
|
+
object: component,
|
|
25960
|
+
values: {
|
|
25961
|
+
axis: axis,
|
|
25962
|
+
value: value,
|
|
25963
|
+
radians: radians
|
|
25964
|
+
},
|
|
25965
|
+
previousValues: {
|
|
25966
|
+
rotation: previousRotation
|
|
25967
|
+
}
|
|
25968
|
+
});
|
|
25969
|
+
|
|
25970
|
+
// Emit transform event if available
|
|
25971
|
+
if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
|
|
25972
|
+
this.sceneViewer.emit('objectTransformed', {
|
|
25973
|
+
object: component,
|
|
25974
|
+
transformType: 'rotate',
|
|
25975
|
+
axis: axis,
|
|
25976
|
+
value: value,
|
|
25977
|
+
radians: radians,
|
|
25978
|
+
previousRotation: previousRotation
|
|
25979
|
+
});
|
|
25980
|
+
}
|
|
25981
|
+
console.log("\u2705 rotate(): Component ".concat(componentId, " rotated successfully"));
|
|
25982
|
+
return true;
|
|
25983
|
+
}
|
|
25984
|
+
|
|
25864
25985
|
/**
|
|
25865
25986
|
* Update paths in the scene
|
|
25866
25987
|
* @returns {boolean} True if paths were updated successfully, false otherwise
|
|
25867
25988
|
* @description Triggers an update of all connection paths/pipes in the scene to reflect
|
|
25868
|
-
* current component positions and connections. This
|
|
25869
|
-
*
|
|
25989
|
+
* current component positions and connections. This method ensures all scene data is
|
|
25990
|
+
* synchronized before updating paths for guaranteed accuracy.
|
|
25870
25991
|
* @example
|
|
25871
25992
|
* // After moving components or changing connections
|
|
25872
25993
|
* const success = centralPlant.updatePaths();
|
|
@@ -25882,8 +26003,15 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
25882
26003
|
return false;
|
|
25883
26004
|
}
|
|
25884
26005
|
try {
|
|
26006
|
+
// Step 1: Ensure scene data is synchronized before updating paths
|
|
26007
|
+
console.log('🔄 updatePaths(): Synchronizing scene data before path update...');
|
|
26008
|
+
if (!this.syncSceneData()) {
|
|
26009
|
+
console.warn('⚠️ updatePaths(): Scene data synchronization failed, proceeding with caution');
|
|
26010
|
+
}
|
|
26011
|
+
|
|
26012
|
+
// Step 2: Update paths with synchronized data
|
|
25885
26013
|
this.sceneViewer.updatePaths();
|
|
25886
|
-
console.log('✅ updatePaths(): Paths updated successfully');
|
|
26014
|
+
console.log('✅ updatePaths(): Paths updated successfully with synchronized data');
|
|
25887
26015
|
return true;
|
|
25888
26016
|
} catch (error) {
|
|
25889
26017
|
console.error('❌ updatePaths(): Error updating paths:', error);
|
|
@@ -25891,6 +26019,262 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
25891
26019
|
}
|
|
25892
26020
|
}
|
|
25893
26021
|
|
|
26022
|
+
/**
|
|
26023
|
+
* Synchronize scene data to ensure all component positions and properties are up-to-date
|
|
26024
|
+
* @returns {boolean} True if synchronization was successful, false otherwise
|
|
26025
|
+
* @description Updates the currentSceneData to match the actual Three.js scene state.
|
|
26026
|
+
* This includes component positions, rotations, scales, and world bounding boxes.
|
|
26027
|
+
* Should be called before operations that depend on accurate scene data.
|
|
26028
|
+
* @example
|
|
26029
|
+
* // Ensure scene data is current before pathfinding
|
|
26030
|
+
* const success = centralPlant.syncSceneData();
|
|
26031
|
+
* if (success) {
|
|
26032
|
+
* console.log('Scene data synchronized with Three.js scene');
|
|
26033
|
+
* }
|
|
26034
|
+
*/
|
|
26035
|
+
}, {
|
|
26036
|
+
key: "syncSceneData",
|
|
26037
|
+
value: function syncSceneData() {
|
|
26038
|
+
var _this = this;
|
|
26039
|
+
// Check if scene viewer and currentSceneData are available
|
|
26040
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
26041
|
+
console.warn('⚠️ syncSceneData(): Scene viewer or current scene data not available');
|
|
26042
|
+
return false;
|
|
26043
|
+
}
|
|
26044
|
+
if (!this.sceneViewer.scene) {
|
|
26045
|
+
console.warn('⚠️ syncSceneData(): Three.js scene not available');
|
|
26046
|
+
return false;
|
|
26047
|
+
}
|
|
26048
|
+
try {
|
|
26049
|
+
console.log('🔄 syncSceneData(): Starting scene data synchronization...');
|
|
26050
|
+
|
|
26051
|
+
// Get reference to currentSceneData
|
|
26052
|
+
var currentSceneData = this.sceneViewer.currentSceneData;
|
|
26053
|
+
if (!currentSceneData.scene || !currentSceneData.scene.object || !currentSceneData.scene.object.children) {
|
|
26054
|
+
console.warn('⚠️ syncSceneData(): Invalid currentSceneData structure');
|
|
26055
|
+
return false;
|
|
26056
|
+
}
|
|
26057
|
+
|
|
26058
|
+
// Update each component in scene data to match Three.js scene
|
|
26059
|
+
var updatedCount = 0;
|
|
26060
|
+
currentSceneData.scene.object.children.forEach(function (sceneDataChild, index) {
|
|
26061
|
+
// Find matching Three.js object
|
|
26062
|
+
var matchingThreeObject = null;
|
|
26063
|
+
_this.sceneViewer.scene.traverse(function (threeObject) {
|
|
26064
|
+
var _sceneDataChild$userD, _threeObject$userData, _threeObject$userData2;
|
|
26065
|
+
// Check various UUID matching strategies
|
|
26066
|
+
if (threeObject.uuid === sceneDataChild.uuid || threeObject.uuid === ((_sceneDataChild$userD = sceneDataChild.userData) === null || _sceneDataChild$userD === void 0 ? void 0 : _sceneDataChild$userD.originalUuid) || ((_threeObject$userData = threeObject.userData) === null || _threeObject$userData === void 0 ? void 0 : _threeObject$userData.originalUuid) === sceneDataChild.uuid || ((_threeObject$userData2 = threeObject.userData) === null || _threeObject$userData2 === void 0 ? void 0 : _threeObject$userData2.hardcodedUuid) === sceneDataChild.uuid) {
|
|
26067
|
+
matchingThreeObject = threeObject;
|
|
26068
|
+
}
|
|
26069
|
+
});
|
|
26070
|
+
if (matchingThreeObject) {
|
|
26071
|
+
// Update position, rotation, and scale
|
|
26072
|
+
sceneDataChild.position = {
|
|
26073
|
+
x: matchingThreeObject.position.x,
|
|
26074
|
+
y: matchingThreeObject.position.y,
|
|
26075
|
+
z: matchingThreeObject.position.z
|
|
26076
|
+
};
|
|
26077
|
+
sceneDataChild.rotation = {
|
|
26078
|
+
x: matchingThreeObject.rotation.x,
|
|
26079
|
+
y: matchingThreeObject.rotation.y,
|
|
26080
|
+
z: matchingThreeObject.rotation.z
|
|
26081
|
+
};
|
|
26082
|
+
sceneDataChild.scale = {
|
|
26083
|
+
x: matchingThreeObject.scale.x,
|
|
26084
|
+
y: matchingThreeObject.scale.y,
|
|
26085
|
+
z: matchingThreeObject.scale.z
|
|
26086
|
+
};
|
|
26087
|
+
|
|
26088
|
+
// Update matrix
|
|
26089
|
+
sceneDataChild.matrix = matchingThreeObject.matrix.elements;
|
|
26090
|
+
|
|
26091
|
+
// Update world bounding box
|
|
26092
|
+
if (matchingThreeObject.isMesh) {
|
|
26093
|
+
var boundingBox = new THREE__namespace.Box3().setFromObject(matchingThreeObject);
|
|
26094
|
+
if (!sceneDataChild.userData) sceneDataChild.userData = {};
|
|
26095
|
+
sceneDataChild.userData.worldBoundingBox = {
|
|
26096
|
+
min: boundingBox.min.toArray(),
|
|
26097
|
+
max: boundingBox.max.toArray()
|
|
26098
|
+
};
|
|
26099
|
+
}
|
|
26100
|
+
|
|
26101
|
+
// Sync children (connectors) if they exist
|
|
26102
|
+
if (sceneDataChild.children && matchingThreeObject.children) {
|
|
26103
|
+
sceneDataChild.children.forEach(function (sceneChild, childIndex) {
|
|
26104
|
+
var matchingChild = matchingThreeObject.children.find(function (threeChild) {
|
|
26105
|
+
var _sceneChild$userData, _threeChild$userData;
|
|
26106
|
+
return threeChild.uuid === sceneChild.uuid || threeChild.uuid === ((_sceneChild$userData = sceneChild.userData) === null || _sceneChild$userData === void 0 ? void 0 : _sceneChild$userData.originalUuid) || ((_threeChild$userData = threeChild.userData) === null || _threeChild$userData === void 0 ? void 0 : _threeChild$userData.originalUuid) === sceneChild.uuid;
|
|
26107
|
+
});
|
|
26108
|
+
if (matchingChild) {
|
|
26109
|
+
var _matchingChild$userDa;
|
|
26110
|
+
// Update child position, rotation, and scale
|
|
26111
|
+
sceneChild.position = {
|
|
26112
|
+
x: matchingChild.position.x,
|
|
26113
|
+
y: matchingChild.position.y,
|
|
26114
|
+
z: matchingChild.position.z
|
|
26115
|
+
};
|
|
26116
|
+
sceneChild.rotation = {
|
|
26117
|
+
x: matchingChild.rotation.x,
|
|
26118
|
+
y: matchingChild.rotation.y,
|
|
26119
|
+
z: matchingChild.rotation.z
|
|
26120
|
+
};
|
|
26121
|
+
sceneChild.scale = {
|
|
26122
|
+
x: matchingChild.scale.x,
|
|
26123
|
+
y: matchingChild.scale.y,
|
|
26124
|
+
z: matchingChild.scale.z
|
|
26125
|
+
};
|
|
26126
|
+
|
|
26127
|
+
// Update direction vector for connectors
|
|
26128
|
+
if ((_matchingChild$userDa = matchingChild.userData) !== null && _matchingChild$userDa !== void 0 && _matchingChild$userDa.direction) {
|
|
26129
|
+
if (!sceneChild.userData) sceneChild.userData = {};
|
|
26130
|
+
sceneChild.userData.direction = _toConsumableArray(matchingChild.userData.direction);
|
|
26131
|
+
}
|
|
26132
|
+
}
|
|
26133
|
+
});
|
|
26134
|
+
}
|
|
26135
|
+
updatedCount++;
|
|
26136
|
+
} else {
|
|
26137
|
+
console.warn("\u26A0\uFE0F syncSceneData(): No matching Three.js object found for scene data child: ".concat(sceneDataChild.uuid));
|
|
26138
|
+
}
|
|
26139
|
+
});
|
|
26140
|
+
|
|
26141
|
+
// Force recompute world bounding boxes for pathfinding accuracy
|
|
26142
|
+
if (this.sceneViewer.pathfindingManager && typeof this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes === 'function') {
|
|
26143
|
+
this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes(currentSceneData);
|
|
26144
|
+
console.log('🔄 syncSceneData(): Recomputed world bounding boxes for pathfinding');
|
|
26145
|
+
}
|
|
26146
|
+
console.log("\u2705 syncSceneData(): Synchronized ".concat(updatedCount, " components successfully"));
|
|
26147
|
+
return true;
|
|
26148
|
+
} catch (error) {
|
|
26149
|
+
console.error('❌ syncSceneData(): Error synchronizing scene data:', error);
|
|
26150
|
+
return false;
|
|
26151
|
+
}
|
|
26152
|
+
}
|
|
26153
|
+
|
|
26154
|
+
/**
|
|
26155
|
+
* Force complete scene data synchronization using SceneOperationsManager
|
|
26156
|
+
* @returns {boolean} True if forced synchronization was successful, false otherwise
|
|
26157
|
+
* @description Uses the SceneOperationsManager's updateSceneDataAfterTransform method
|
|
26158
|
+
* to update scene data for every component. This is more thorough than syncSceneData()
|
|
26159
|
+
* and should be used when maximum accuracy is required.
|
|
26160
|
+
* @example
|
|
26161
|
+
* // Force complete synchronization before critical operations
|
|
26162
|
+
* const success = centralPlant.forceSyncSceneData();
|
|
26163
|
+
* if (success) {
|
|
26164
|
+
* console.log('Complete scene data synchronization completed');
|
|
26165
|
+
* }
|
|
26166
|
+
*/
|
|
26167
|
+
}, {
|
|
26168
|
+
key: "forceSyncSceneData",
|
|
26169
|
+
value: function forceSyncSceneData() {
|
|
26170
|
+
var _this2 = this;
|
|
26171
|
+
// Check if scene viewer and sceneOperationsManager are available
|
|
26172
|
+
if (!this.sceneViewer || !this.sceneViewer.sceneOperationsManager) {
|
|
26173
|
+
console.warn('⚠️ forceSyncSceneData(): Scene viewer or scene operations manager not available');
|
|
26174
|
+
return false;
|
|
26175
|
+
}
|
|
26176
|
+
if (!this.sceneViewer.currentSceneData) {
|
|
26177
|
+
console.warn('⚠️ forceSyncSceneData(): Current scene data not available');
|
|
26178
|
+
return false;
|
|
26179
|
+
}
|
|
26180
|
+
if (!this.sceneViewer.scene) {
|
|
26181
|
+
console.warn('⚠️ forceSyncSceneData(): Three.js scene not available');
|
|
26182
|
+
return false;
|
|
26183
|
+
}
|
|
26184
|
+
try {
|
|
26185
|
+
console.log('🔄 forceSyncSceneData(): Starting forced scene data synchronization...');
|
|
26186
|
+
var syncedCount = 0;
|
|
26187
|
+
var currentSceneData = this.sceneViewer.currentSceneData;
|
|
26188
|
+
|
|
26189
|
+
// Traverse all objects in the Three.js scene and update their scene data
|
|
26190
|
+
this.sceneViewer.scene.traverse(function (threeObject) {
|
|
26191
|
+
// Only sync objects that have component-related userData
|
|
26192
|
+
if (threeObject.userData && (threeObject.userData.componentType === 'component' || threeObject.userData.componentType === 'gateway' || threeObject.userData.libraryId)) {
|
|
26193
|
+
console.log("\uD83D\uDD04 Syncing object: ".concat(threeObject.uuid, " (").concat(threeObject.userData.componentType || 'unknown', ")"));
|
|
26194
|
+
|
|
26195
|
+
// Use the existing updateSceneDataAfterTransform method
|
|
26196
|
+
var success = _this2.sceneViewer.sceneOperationsManager.updateSceneDataAfterTransform(threeObject, currentSceneData);
|
|
26197
|
+
if (success) {
|
|
26198
|
+
syncedCount++;
|
|
26199
|
+
} else {
|
|
26200
|
+
console.warn("\u26A0\uFE0F Failed to sync object: ".concat(threeObject.uuid));
|
|
26201
|
+
}
|
|
26202
|
+
}
|
|
26203
|
+
});
|
|
26204
|
+
console.log("\u2705 forceSyncSceneData(): Force synchronized ".concat(syncedCount, " objects successfully"));
|
|
26205
|
+
return true;
|
|
26206
|
+
} catch (error) {
|
|
26207
|
+
console.error('❌ forceSyncSceneData(): Error during forced scene data synchronization:', error);
|
|
26208
|
+
return false;
|
|
26209
|
+
}
|
|
26210
|
+
}
|
|
26211
|
+
|
|
26212
|
+
/**
|
|
26213
|
+
* Update paths with optional scene data synchronization level
|
|
26214
|
+
* @param {string} [syncLevel='auto'] - Level of synchronization: 'none', 'basic', 'complete', or 'auto'
|
|
26215
|
+
* @returns {boolean} True if paths were updated successfully, false otherwise
|
|
26216
|
+
* @description Enhanced updatePaths method that allows choosing the level of scene data
|
|
26217
|
+
* synchronization before updating paths. The 'auto' level intelligently chooses based
|
|
26218
|
+
* on scene complexity and recent changes.
|
|
26219
|
+
* @example
|
|
26220
|
+
* // Update paths with automatic synchronization (recommended)
|
|
26221
|
+
* centralPlant.updatePathsWithSync('auto');
|
|
26222
|
+
*
|
|
26223
|
+
* // Update paths with complete synchronization (most accurate)
|
|
26224
|
+
* centralPlant.updatePathsWithSync('complete');
|
|
26225
|
+
*
|
|
26226
|
+
* // Update paths without synchronization (fastest)
|
|
26227
|
+
* centralPlant.updatePathsWithSync('none');
|
|
26228
|
+
*/
|
|
26229
|
+
}, {
|
|
26230
|
+
key: "updatePathsWithSync",
|
|
26231
|
+
value: function updatePathsWithSync() {
|
|
26232
|
+
var syncLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'auto';
|
|
26233
|
+
if (!this.sceneViewer || !this.sceneViewer.updatePaths) {
|
|
26234
|
+
console.warn('⚠️ updatePathsWithSync(): Scene viewer or updatePaths method not available');
|
|
26235
|
+
return false;
|
|
26236
|
+
}
|
|
26237
|
+
try {
|
|
26238
|
+
// Determine sync level automatically if needed
|
|
26239
|
+
if (syncLevel === 'auto') {
|
|
26240
|
+
var _this$transformHistor;
|
|
26241
|
+
// Use basic sync by default, but upgrade to complete if recent transforms detected
|
|
26242
|
+
syncLevel = (_this$transformHistor = this.transformHistory) !== null && _this$transformHistor !== void 0 && _this$transformHistor.lastTransform && Date.now() - new Date(this.transformHistory.lastTransform.timestamp).getTime() < 5000 ? 'complete' : 'basic';
|
|
26243
|
+
console.log("\uD83E\uDD16 updatePathsWithSync(): Auto-selected sync level: ".concat(syncLevel));
|
|
26244
|
+
}
|
|
26245
|
+
|
|
26246
|
+
// Perform synchronization based on level
|
|
26247
|
+
var syncSuccess = true;
|
|
26248
|
+
switch (syncLevel) {
|
|
26249
|
+
case 'none':
|
|
26250
|
+
console.log('⚡ updatePathsWithSync(): Skipping synchronization for speed');
|
|
26251
|
+
break;
|
|
26252
|
+
case 'basic':
|
|
26253
|
+
console.log('🔄 updatePathsWithSync(): Performing basic scene data synchronization...');
|
|
26254
|
+
syncSuccess = this.syncSceneData();
|
|
26255
|
+
break;
|
|
26256
|
+
case 'complete':
|
|
26257
|
+
console.log('🔄 updatePathsWithSync(): Performing complete scene data synchronization...');
|
|
26258
|
+
syncSuccess = this.forceSyncSceneData();
|
|
26259
|
+
break;
|
|
26260
|
+
default:
|
|
26261
|
+
console.warn("\u26A0\uFE0F updatePathsWithSync(): Unknown sync level '".concat(syncLevel, "', defaulting to basic"));
|
|
26262
|
+
syncSuccess = this.syncSceneData();
|
|
26263
|
+
}
|
|
26264
|
+
if (!syncSuccess && syncLevel !== 'none') {
|
|
26265
|
+
console.warn('⚠️ updatePathsWithSync(): Scene data synchronization failed, proceeding with caution');
|
|
26266
|
+
}
|
|
26267
|
+
|
|
26268
|
+
// Update paths
|
|
26269
|
+
this.sceneViewer.updatePaths();
|
|
26270
|
+
console.log("\u2705 updatePathsWithSync(): Paths updated successfully with '".concat(syncLevel, "' synchronization"));
|
|
26271
|
+
return true;
|
|
26272
|
+
} catch (error) {
|
|
26273
|
+
console.error('❌ updatePathsWithSync(): Error updating paths with sync:', error);
|
|
26274
|
+
return false;
|
|
26275
|
+
}
|
|
26276
|
+
}
|
|
26277
|
+
|
|
25894
26278
|
/**
|
|
25895
26279
|
* Add a connection between two connector IDs to the connections list
|
|
25896
26280
|
* @param {string} fromConnectorId - The UUID of the source connector
|
|
@@ -565,12 +565,133 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
565
565
|
return true;
|
|
566
566
|
}
|
|
567
567
|
|
|
568
|
+
/**
|
|
569
|
+
* Rotate a component by componentId
|
|
570
|
+
* @param {string} componentId - The UUID of the component to rotate
|
|
571
|
+
* @param {string} axis - The axis to rotate around ('x', 'y', or 'z')
|
|
572
|
+
* @param {number} value - The value to rotate by in degrees
|
|
573
|
+
* @returns {boolean} True if rotation was successful, false otherwise
|
|
574
|
+
* @description Rotates a component around the specified axis by the given angle in degrees.
|
|
575
|
+
* The rotation is applied incrementally to the component's current rotation.
|
|
576
|
+
* @example
|
|
577
|
+
* // Rotate a component 45 degrees around Y axis
|
|
578
|
+
* const success = centralPlant.rotate('component-uuid-123', 'y', 45);
|
|
579
|
+
*
|
|
580
|
+
* // Rotate a component -90 degrees around Z axis
|
|
581
|
+
* centralPlant.rotate('component-uuid-456', 'z', -90);
|
|
582
|
+
*
|
|
583
|
+
* // Rotate a component 180 degrees around X axis
|
|
584
|
+
* centralPlant.rotate('component-uuid-789', 'x', 180);
|
|
585
|
+
*
|
|
586
|
+
* @since 0.1.25
|
|
587
|
+
*/
|
|
588
|
+
}, {
|
|
589
|
+
key: "rotate",
|
|
590
|
+
value: function rotate(componentId, axis, value) {
|
|
591
|
+
// Validate input parameters
|
|
592
|
+
if (!componentId || typeof componentId !== 'string') {
|
|
593
|
+
console.error('❌ rotate(): Invalid componentId provided. Must be a non-empty string:', componentId);
|
|
594
|
+
return false;
|
|
595
|
+
}
|
|
596
|
+
if (!['x', 'y', 'z'].includes(axis)) {
|
|
597
|
+
console.error('❌ rotate(): Invalid axis provided. Must be "x", "y", or "z":', axis);
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
601
|
+
console.error('❌ rotate(): Invalid value provided. Must be a number:', value);
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Check if scene viewer and scene are available
|
|
606
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
607
|
+
console.error('❌ rotate(): Scene viewer or scene not available');
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Find the component in the scene
|
|
612
|
+
var component = null;
|
|
613
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
614
|
+
var _child$userData2;
|
|
615
|
+
if (child.uuid === componentId || ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === componentId) {
|
|
616
|
+
component = child;
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
if (!component) {
|
|
620
|
+
console.error("\u274C rotate(): Component with ID '".concat(componentId, "' not found in scene"));
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
if (!component.userData.libraryId) {
|
|
624
|
+
console.error("\u274C rotate(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
625
|
+
return false;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Store previous rotation for potential undo
|
|
629
|
+
var previousRotation = {
|
|
630
|
+
x: component.rotation.x,
|
|
631
|
+
y: component.rotation.y,
|
|
632
|
+
z: component.rotation.z
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
// Convert degrees to radians
|
|
636
|
+
var radians = value * Math.PI / 180;
|
|
637
|
+
console.log("\uD83D\uDD04 rotate(): Rotating component ".concat(componentId, " around ").concat(axis, " axis by ").concat(value, " degrees (").concat(radians, " radians)"));
|
|
638
|
+
|
|
639
|
+
// Apply the rotation
|
|
640
|
+
component.rotation[axis] += radians;
|
|
641
|
+
|
|
642
|
+
// Update the associated JSON object in currentSceneData if it exists
|
|
643
|
+
if (this.sceneViewer.currentSceneData && this.sceneViewer.currentSceneData.scene) {
|
|
644
|
+
if (component.userData.associatedJsonObject) {
|
|
645
|
+
// Convert back to degrees for JSON storage
|
|
646
|
+
component.userData.associatedJsonObject.rotation = component.userData.associatedJsonObject.rotation || {
|
|
647
|
+
x: 0,
|
|
648
|
+
y: 0,
|
|
649
|
+
z: 0
|
|
650
|
+
};
|
|
651
|
+
component.userData.associatedJsonObject.rotation[axis] = component.rotation[axis] * 180 / Math.PI;
|
|
652
|
+
console.log("\uD83D\uDD04 Updated associated JSON object rotation for ".concat(componentId));
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// Update matrices
|
|
657
|
+
component.updateMatrix();
|
|
658
|
+
component.updateMatrixWorld(true);
|
|
659
|
+
|
|
660
|
+
// Record the transform for potential undo
|
|
661
|
+
this.internals.recordTransform({
|
|
662
|
+
type: 'rotate',
|
|
663
|
+
object: component,
|
|
664
|
+
values: {
|
|
665
|
+
axis: axis,
|
|
666
|
+
value: value,
|
|
667
|
+
radians: radians
|
|
668
|
+
},
|
|
669
|
+
previousValues: {
|
|
670
|
+
rotation: previousRotation
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
// Emit transform event if available
|
|
675
|
+
if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
|
|
676
|
+
this.sceneViewer.emit('objectTransformed', {
|
|
677
|
+
object: component,
|
|
678
|
+
transformType: 'rotate',
|
|
679
|
+
axis: axis,
|
|
680
|
+
value: value,
|
|
681
|
+
radians: radians,
|
|
682
|
+
previousRotation: previousRotation
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
console.log("\u2705 rotate(): Component ".concat(componentId, " rotated successfully"));
|
|
686
|
+
return true;
|
|
687
|
+
}
|
|
688
|
+
|
|
568
689
|
/**
|
|
569
690
|
* Update paths in the scene
|
|
570
691
|
* @returns {boolean} True if paths were updated successfully, false otherwise
|
|
571
692
|
* @description Triggers an update of all connection paths/pipes in the scene to reflect
|
|
572
|
-
* current component positions and connections. This
|
|
573
|
-
*
|
|
693
|
+
* current component positions and connections. This method ensures all scene data is
|
|
694
|
+
* synchronized before updating paths for guaranteed accuracy.
|
|
574
695
|
* @example
|
|
575
696
|
* // After moving components or changing connections
|
|
576
697
|
* const success = centralPlant.updatePaths();
|
|
@@ -586,8 +707,15 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
586
707
|
return false;
|
|
587
708
|
}
|
|
588
709
|
try {
|
|
710
|
+
// Step 1: Ensure scene data is synchronized before updating paths
|
|
711
|
+
console.log('🔄 updatePaths(): Synchronizing scene data before path update...');
|
|
712
|
+
if (!this.syncSceneData()) {
|
|
713
|
+
console.warn('⚠️ updatePaths(): Scene data synchronization failed, proceeding with caution');
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// Step 2: Update paths with synchronized data
|
|
589
717
|
this.sceneViewer.updatePaths();
|
|
590
|
-
console.log('✅ updatePaths(): Paths updated successfully');
|
|
718
|
+
console.log('✅ updatePaths(): Paths updated successfully with synchronized data');
|
|
591
719
|
return true;
|
|
592
720
|
} catch (error) {
|
|
593
721
|
console.error('❌ updatePaths(): Error updating paths:', error);
|
|
@@ -595,6 +723,262 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
595
723
|
}
|
|
596
724
|
}
|
|
597
725
|
|
|
726
|
+
/**
|
|
727
|
+
* Synchronize scene data to ensure all component positions and properties are up-to-date
|
|
728
|
+
* @returns {boolean} True if synchronization was successful, false otherwise
|
|
729
|
+
* @description Updates the currentSceneData to match the actual Three.js scene state.
|
|
730
|
+
* This includes component positions, rotations, scales, and world bounding boxes.
|
|
731
|
+
* Should be called before operations that depend on accurate scene data.
|
|
732
|
+
* @example
|
|
733
|
+
* // Ensure scene data is current before pathfinding
|
|
734
|
+
* const success = centralPlant.syncSceneData();
|
|
735
|
+
* if (success) {
|
|
736
|
+
* console.log('Scene data synchronized with Three.js scene');
|
|
737
|
+
* }
|
|
738
|
+
*/
|
|
739
|
+
}, {
|
|
740
|
+
key: "syncSceneData",
|
|
741
|
+
value: function syncSceneData() {
|
|
742
|
+
var _this = this;
|
|
743
|
+
// Check if scene viewer and currentSceneData are available
|
|
744
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
745
|
+
console.warn('⚠️ syncSceneData(): Scene viewer or current scene data not available');
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
if (!this.sceneViewer.scene) {
|
|
749
|
+
console.warn('⚠️ syncSceneData(): Three.js scene not available');
|
|
750
|
+
return false;
|
|
751
|
+
}
|
|
752
|
+
try {
|
|
753
|
+
console.log('🔄 syncSceneData(): Starting scene data synchronization...');
|
|
754
|
+
|
|
755
|
+
// Get reference to currentSceneData
|
|
756
|
+
var currentSceneData = this.sceneViewer.currentSceneData;
|
|
757
|
+
if (!currentSceneData.scene || !currentSceneData.scene.object || !currentSceneData.scene.object.children) {
|
|
758
|
+
console.warn('⚠️ syncSceneData(): Invalid currentSceneData structure');
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// Update each component in scene data to match Three.js scene
|
|
763
|
+
var updatedCount = 0;
|
|
764
|
+
currentSceneData.scene.object.children.forEach(function (sceneDataChild, index) {
|
|
765
|
+
// Find matching Three.js object
|
|
766
|
+
var matchingThreeObject = null;
|
|
767
|
+
_this.sceneViewer.scene.traverse(function (threeObject) {
|
|
768
|
+
var _sceneDataChild$userD, _threeObject$userData, _threeObject$userData2;
|
|
769
|
+
// Check various UUID matching strategies
|
|
770
|
+
if (threeObject.uuid === sceneDataChild.uuid || threeObject.uuid === ((_sceneDataChild$userD = sceneDataChild.userData) === null || _sceneDataChild$userD === void 0 ? void 0 : _sceneDataChild$userD.originalUuid) || ((_threeObject$userData = threeObject.userData) === null || _threeObject$userData === void 0 ? void 0 : _threeObject$userData.originalUuid) === sceneDataChild.uuid || ((_threeObject$userData2 = threeObject.userData) === null || _threeObject$userData2 === void 0 ? void 0 : _threeObject$userData2.hardcodedUuid) === sceneDataChild.uuid) {
|
|
771
|
+
matchingThreeObject = threeObject;
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
if (matchingThreeObject) {
|
|
775
|
+
// Update position, rotation, and scale
|
|
776
|
+
sceneDataChild.position = {
|
|
777
|
+
x: matchingThreeObject.position.x,
|
|
778
|
+
y: matchingThreeObject.position.y,
|
|
779
|
+
z: matchingThreeObject.position.z
|
|
780
|
+
};
|
|
781
|
+
sceneDataChild.rotation = {
|
|
782
|
+
x: matchingThreeObject.rotation.x,
|
|
783
|
+
y: matchingThreeObject.rotation.y,
|
|
784
|
+
z: matchingThreeObject.rotation.z
|
|
785
|
+
};
|
|
786
|
+
sceneDataChild.scale = {
|
|
787
|
+
x: matchingThreeObject.scale.x,
|
|
788
|
+
y: matchingThreeObject.scale.y,
|
|
789
|
+
z: matchingThreeObject.scale.z
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
// Update matrix
|
|
793
|
+
sceneDataChild.matrix = matchingThreeObject.matrix.elements;
|
|
794
|
+
|
|
795
|
+
// Update world bounding box
|
|
796
|
+
if (matchingThreeObject.isMesh) {
|
|
797
|
+
var boundingBox = new THREE__namespace.Box3().setFromObject(matchingThreeObject);
|
|
798
|
+
if (!sceneDataChild.userData) sceneDataChild.userData = {};
|
|
799
|
+
sceneDataChild.userData.worldBoundingBox = {
|
|
800
|
+
min: boundingBox.min.toArray(),
|
|
801
|
+
max: boundingBox.max.toArray()
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Sync children (connectors) if they exist
|
|
806
|
+
if (sceneDataChild.children && matchingThreeObject.children) {
|
|
807
|
+
sceneDataChild.children.forEach(function (sceneChild, childIndex) {
|
|
808
|
+
var matchingChild = matchingThreeObject.children.find(function (threeChild) {
|
|
809
|
+
var _sceneChild$userData, _threeChild$userData;
|
|
810
|
+
return threeChild.uuid === sceneChild.uuid || threeChild.uuid === ((_sceneChild$userData = sceneChild.userData) === null || _sceneChild$userData === void 0 ? void 0 : _sceneChild$userData.originalUuid) || ((_threeChild$userData = threeChild.userData) === null || _threeChild$userData === void 0 ? void 0 : _threeChild$userData.originalUuid) === sceneChild.uuid;
|
|
811
|
+
});
|
|
812
|
+
if (matchingChild) {
|
|
813
|
+
var _matchingChild$userDa;
|
|
814
|
+
// Update child position, rotation, and scale
|
|
815
|
+
sceneChild.position = {
|
|
816
|
+
x: matchingChild.position.x,
|
|
817
|
+
y: matchingChild.position.y,
|
|
818
|
+
z: matchingChild.position.z
|
|
819
|
+
};
|
|
820
|
+
sceneChild.rotation = {
|
|
821
|
+
x: matchingChild.rotation.x,
|
|
822
|
+
y: matchingChild.rotation.y,
|
|
823
|
+
z: matchingChild.rotation.z
|
|
824
|
+
};
|
|
825
|
+
sceneChild.scale = {
|
|
826
|
+
x: matchingChild.scale.x,
|
|
827
|
+
y: matchingChild.scale.y,
|
|
828
|
+
z: matchingChild.scale.z
|
|
829
|
+
};
|
|
830
|
+
|
|
831
|
+
// Update direction vector for connectors
|
|
832
|
+
if ((_matchingChild$userDa = matchingChild.userData) !== null && _matchingChild$userDa !== void 0 && _matchingChild$userDa.direction) {
|
|
833
|
+
if (!sceneChild.userData) sceneChild.userData = {};
|
|
834
|
+
sceneChild.userData.direction = _rollupPluginBabelHelpers.toConsumableArray(matchingChild.userData.direction);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
updatedCount++;
|
|
840
|
+
} else {
|
|
841
|
+
console.warn("\u26A0\uFE0F syncSceneData(): No matching Three.js object found for scene data child: ".concat(sceneDataChild.uuid));
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
// Force recompute world bounding boxes for pathfinding accuracy
|
|
846
|
+
if (this.sceneViewer.pathfindingManager && typeof this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes === 'function') {
|
|
847
|
+
this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes(currentSceneData);
|
|
848
|
+
console.log('🔄 syncSceneData(): Recomputed world bounding boxes for pathfinding');
|
|
849
|
+
}
|
|
850
|
+
console.log("\u2705 syncSceneData(): Synchronized ".concat(updatedCount, " components successfully"));
|
|
851
|
+
return true;
|
|
852
|
+
} catch (error) {
|
|
853
|
+
console.error('❌ syncSceneData(): Error synchronizing scene data:', error);
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* Force complete scene data synchronization using SceneOperationsManager
|
|
860
|
+
* @returns {boolean} True if forced synchronization was successful, false otherwise
|
|
861
|
+
* @description Uses the SceneOperationsManager's updateSceneDataAfterTransform method
|
|
862
|
+
* to update scene data for every component. This is more thorough than syncSceneData()
|
|
863
|
+
* and should be used when maximum accuracy is required.
|
|
864
|
+
* @example
|
|
865
|
+
* // Force complete synchronization before critical operations
|
|
866
|
+
* const success = centralPlant.forceSyncSceneData();
|
|
867
|
+
* if (success) {
|
|
868
|
+
* console.log('Complete scene data synchronization completed');
|
|
869
|
+
* }
|
|
870
|
+
*/
|
|
871
|
+
}, {
|
|
872
|
+
key: "forceSyncSceneData",
|
|
873
|
+
value: function forceSyncSceneData() {
|
|
874
|
+
var _this2 = this;
|
|
875
|
+
// Check if scene viewer and sceneOperationsManager are available
|
|
876
|
+
if (!this.sceneViewer || !this.sceneViewer.sceneOperationsManager) {
|
|
877
|
+
console.warn('⚠️ forceSyncSceneData(): Scene viewer or scene operations manager not available');
|
|
878
|
+
return false;
|
|
879
|
+
}
|
|
880
|
+
if (!this.sceneViewer.currentSceneData) {
|
|
881
|
+
console.warn('⚠️ forceSyncSceneData(): Current scene data not available');
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
if (!this.sceneViewer.scene) {
|
|
885
|
+
console.warn('⚠️ forceSyncSceneData(): Three.js scene not available');
|
|
886
|
+
return false;
|
|
887
|
+
}
|
|
888
|
+
try {
|
|
889
|
+
console.log('🔄 forceSyncSceneData(): Starting forced scene data synchronization...');
|
|
890
|
+
var syncedCount = 0;
|
|
891
|
+
var currentSceneData = this.sceneViewer.currentSceneData;
|
|
892
|
+
|
|
893
|
+
// Traverse all objects in the Three.js scene and update their scene data
|
|
894
|
+
this.sceneViewer.scene.traverse(function (threeObject) {
|
|
895
|
+
// Only sync objects that have component-related userData
|
|
896
|
+
if (threeObject.userData && (threeObject.userData.componentType === 'component' || threeObject.userData.componentType === 'gateway' || threeObject.userData.libraryId)) {
|
|
897
|
+
console.log("\uD83D\uDD04 Syncing object: ".concat(threeObject.uuid, " (").concat(threeObject.userData.componentType || 'unknown', ")"));
|
|
898
|
+
|
|
899
|
+
// Use the existing updateSceneDataAfterTransform method
|
|
900
|
+
var success = _this2.sceneViewer.sceneOperationsManager.updateSceneDataAfterTransform(threeObject, currentSceneData);
|
|
901
|
+
if (success) {
|
|
902
|
+
syncedCount++;
|
|
903
|
+
} else {
|
|
904
|
+
console.warn("\u26A0\uFE0F Failed to sync object: ".concat(threeObject.uuid));
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
console.log("\u2705 forceSyncSceneData(): Force synchronized ".concat(syncedCount, " objects successfully"));
|
|
909
|
+
return true;
|
|
910
|
+
} catch (error) {
|
|
911
|
+
console.error('❌ forceSyncSceneData(): Error during forced scene data synchronization:', error);
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Update paths with optional scene data synchronization level
|
|
918
|
+
* @param {string} [syncLevel='auto'] - Level of synchronization: 'none', 'basic', 'complete', or 'auto'
|
|
919
|
+
* @returns {boolean} True if paths were updated successfully, false otherwise
|
|
920
|
+
* @description Enhanced updatePaths method that allows choosing the level of scene data
|
|
921
|
+
* synchronization before updating paths. The 'auto' level intelligently chooses based
|
|
922
|
+
* on scene complexity and recent changes.
|
|
923
|
+
* @example
|
|
924
|
+
* // Update paths with automatic synchronization (recommended)
|
|
925
|
+
* centralPlant.updatePathsWithSync('auto');
|
|
926
|
+
*
|
|
927
|
+
* // Update paths with complete synchronization (most accurate)
|
|
928
|
+
* centralPlant.updatePathsWithSync('complete');
|
|
929
|
+
*
|
|
930
|
+
* // Update paths without synchronization (fastest)
|
|
931
|
+
* centralPlant.updatePathsWithSync('none');
|
|
932
|
+
*/
|
|
933
|
+
}, {
|
|
934
|
+
key: "updatePathsWithSync",
|
|
935
|
+
value: function updatePathsWithSync() {
|
|
936
|
+
var syncLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'auto';
|
|
937
|
+
if (!this.sceneViewer || !this.sceneViewer.updatePaths) {
|
|
938
|
+
console.warn('⚠️ updatePathsWithSync(): Scene viewer or updatePaths method not available');
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
try {
|
|
942
|
+
// Determine sync level automatically if needed
|
|
943
|
+
if (syncLevel === 'auto') {
|
|
944
|
+
var _this$transformHistor;
|
|
945
|
+
// Use basic sync by default, but upgrade to complete if recent transforms detected
|
|
946
|
+
syncLevel = (_this$transformHistor = this.transformHistory) !== null && _this$transformHistor !== void 0 && _this$transformHistor.lastTransform && Date.now() - new Date(this.transformHistory.lastTransform.timestamp).getTime() < 5000 ? 'complete' : 'basic';
|
|
947
|
+
console.log("\uD83E\uDD16 updatePathsWithSync(): Auto-selected sync level: ".concat(syncLevel));
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// Perform synchronization based on level
|
|
951
|
+
var syncSuccess = true;
|
|
952
|
+
switch (syncLevel) {
|
|
953
|
+
case 'none':
|
|
954
|
+
console.log('⚡ updatePathsWithSync(): Skipping synchronization for speed');
|
|
955
|
+
break;
|
|
956
|
+
case 'basic':
|
|
957
|
+
console.log('🔄 updatePathsWithSync(): Performing basic scene data synchronization...');
|
|
958
|
+
syncSuccess = this.syncSceneData();
|
|
959
|
+
break;
|
|
960
|
+
case 'complete':
|
|
961
|
+
console.log('🔄 updatePathsWithSync(): Performing complete scene data synchronization...');
|
|
962
|
+
syncSuccess = this.forceSyncSceneData();
|
|
963
|
+
break;
|
|
964
|
+
default:
|
|
965
|
+
console.warn("\u26A0\uFE0F updatePathsWithSync(): Unknown sync level '".concat(syncLevel, "', defaulting to basic"));
|
|
966
|
+
syncSuccess = this.syncSceneData();
|
|
967
|
+
}
|
|
968
|
+
if (!syncSuccess && syncLevel !== 'none') {
|
|
969
|
+
console.warn('⚠️ updatePathsWithSync(): Scene data synchronization failed, proceeding with caution');
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// Update paths
|
|
973
|
+
this.sceneViewer.updatePaths();
|
|
974
|
+
console.log("\u2705 updatePathsWithSync(): Paths updated successfully with '".concat(syncLevel, "' synchronization"));
|
|
975
|
+
return true;
|
|
976
|
+
} catch (error) {
|
|
977
|
+
console.error('❌ updatePathsWithSync(): Error updating paths with sync:', error);
|
|
978
|
+
return false;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
598
982
|
/**
|
|
599
983
|
* Add a connection between two connector IDs to the connections list
|
|
600
984
|
* @param {string} fromConnectorId - The UUID of the source connector
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createClass as _createClass, objectSpread2 as _objectSpread2, classCallCheck as _classCallCheck } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
1
|
+
import { createClass as _createClass, objectSpread2 as _objectSpread2, toConsumableArray as _toConsumableArray, classCallCheck as _classCallCheck } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
import { CentralPlantInternals } from './centralPlantInternals.js';
|
|
4
4
|
import '../rendering/modelPreloader.js';
|
|
@@ -541,12 +541,133 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
541
541
|
return true;
|
|
542
542
|
}
|
|
543
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Rotate a component by componentId
|
|
546
|
+
* @param {string} componentId - The UUID of the component to rotate
|
|
547
|
+
* @param {string} axis - The axis to rotate around ('x', 'y', or 'z')
|
|
548
|
+
* @param {number} value - The value to rotate by in degrees
|
|
549
|
+
* @returns {boolean} True if rotation was successful, false otherwise
|
|
550
|
+
* @description Rotates a component around the specified axis by the given angle in degrees.
|
|
551
|
+
* The rotation is applied incrementally to the component's current rotation.
|
|
552
|
+
* @example
|
|
553
|
+
* // Rotate a component 45 degrees around Y axis
|
|
554
|
+
* const success = centralPlant.rotate('component-uuid-123', 'y', 45);
|
|
555
|
+
*
|
|
556
|
+
* // Rotate a component -90 degrees around Z axis
|
|
557
|
+
* centralPlant.rotate('component-uuid-456', 'z', -90);
|
|
558
|
+
*
|
|
559
|
+
* // Rotate a component 180 degrees around X axis
|
|
560
|
+
* centralPlant.rotate('component-uuid-789', 'x', 180);
|
|
561
|
+
*
|
|
562
|
+
* @since 0.1.25
|
|
563
|
+
*/
|
|
564
|
+
}, {
|
|
565
|
+
key: "rotate",
|
|
566
|
+
value: function rotate(componentId, axis, value) {
|
|
567
|
+
// Validate input parameters
|
|
568
|
+
if (!componentId || typeof componentId !== 'string') {
|
|
569
|
+
console.error('❌ rotate(): Invalid componentId provided. Must be a non-empty string:', componentId);
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
if (!['x', 'y', 'z'].includes(axis)) {
|
|
573
|
+
console.error('❌ rotate(): Invalid axis provided. Must be "x", "y", or "z":', axis);
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
577
|
+
console.error('❌ rotate(): Invalid value provided. Must be a number:', value);
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Check if scene viewer and scene are available
|
|
582
|
+
if (!this.sceneViewer || !this.sceneViewer.scene) {
|
|
583
|
+
console.error('❌ rotate(): Scene viewer or scene not available');
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Find the component in the scene
|
|
588
|
+
var component = null;
|
|
589
|
+
this.sceneViewer.scene.traverse(function (child) {
|
|
590
|
+
var _child$userData2;
|
|
591
|
+
if (child.uuid === componentId || ((_child$userData2 = child.userData) === null || _child$userData2 === void 0 ? void 0 : _child$userData2.originalUuid) === componentId) {
|
|
592
|
+
component = child;
|
|
593
|
+
}
|
|
594
|
+
});
|
|
595
|
+
if (!component) {
|
|
596
|
+
console.error("\u274C rotate(): Component with ID '".concat(componentId, "' not found in scene"));
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
if (!component.userData.libraryId) {
|
|
600
|
+
console.error("\u274C rotate(): Object with ID '".concat(componentId, "' is not a valid component"));
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// Store previous rotation for potential undo
|
|
605
|
+
var previousRotation = {
|
|
606
|
+
x: component.rotation.x,
|
|
607
|
+
y: component.rotation.y,
|
|
608
|
+
z: component.rotation.z
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
// Convert degrees to radians
|
|
612
|
+
var radians = value * Math.PI / 180;
|
|
613
|
+
console.log("\uD83D\uDD04 rotate(): Rotating component ".concat(componentId, " around ").concat(axis, " axis by ").concat(value, " degrees (").concat(radians, " radians)"));
|
|
614
|
+
|
|
615
|
+
// Apply the rotation
|
|
616
|
+
component.rotation[axis] += radians;
|
|
617
|
+
|
|
618
|
+
// Update the associated JSON object in currentSceneData if it exists
|
|
619
|
+
if (this.sceneViewer.currentSceneData && this.sceneViewer.currentSceneData.scene) {
|
|
620
|
+
if (component.userData.associatedJsonObject) {
|
|
621
|
+
// Convert back to degrees for JSON storage
|
|
622
|
+
component.userData.associatedJsonObject.rotation = component.userData.associatedJsonObject.rotation || {
|
|
623
|
+
x: 0,
|
|
624
|
+
y: 0,
|
|
625
|
+
z: 0
|
|
626
|
+
};
|
|
627
|
+
component.userData.associatedJsonObject.rotation[axis] = component.rotation[axis] * 180 / Math.PI;
|
|
628
|
+
console.log("\uD83D\uDD04 Updated associated JSON object rotation for ".concat(componentId));
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Update matrices
|
|
633
|
+
component.updateMatrix();
|
|
634
|
+
component.updateMatrixWorld(true);
|
|
635
|
+
|
|
636
|
+
// Record the transform for potential undo
|
|
637
|
+
this.internals.recordTransform({
|
|
638
|
+
type: 'rotate',
|
|
639
|
+
object: component,
|
|
640
|
+
values: {
|
|
641
|
+
axis: axis,
|
|
642
|
+
value: value,
|
|
643
|
+
radians: radians
|
|
644
|
+
},
|
|
645
|
+
previousValues: {
|
|
646
|
+
rotation: previousRotation
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
// Emit transform event if available
|
|
651
|
+
if (this.sceneViewer.emit && typeof this.sceneViewer.emit === 'function') {
|
|
652
|
+
this.sceneViewer.emit('objectTransformed', {
|
|
653
|
+
object: component,
|
|
654
|
+
transformType: 'rotate',
|
|
655
|
+
axis: axis,
|
|
656
|
+
value: value,
|
|
657
|
+
radians: radians,
|
|
658
|
+
previousRotation: previousRotation
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
console.log("\u2705 rotate(): Component ".concat(componentId, " rotated successfully"));
|
|
662
|
+
return true;
|
|
663
|
+
}
|
|
664
|
+
|
|
544
665
|
/**
|
|
545
666
|
* Update paths in the scene
|
|
546
667
|
* @returns {boolean} True if paths were updated successfully, false otherwise
|
|
547
668
|
* @description Triggers an update of all connection paths/pipes in the scene to reflect
|
|
548
|
-
* current component positions and connections. This
|
|
549
|
-
*
|
|
669
|
+
* current component positions and connections. This method ensures all scene data is
|
|
670
|
+
* synchronized before updating paths for guaranteed accuracy.
|
|
550
671
|
* @example
|
|
551
672
|
* // After moving components or changing connections
|
|
552
673
|
* const success = centralPlant.updatePaths();
|
|
@@ -562,8 +683,15 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
562
683
|
return false;
|
|
563
684
|
}
|
|
564
685
|
try {
|
|
686
|
+
// Step 1: Ensure scene data is synchronized before updating paths
|
|
687
|
+
console.log('🔄 updatePaths(): Synchronizing scene data before path update...');
|
|
688
|
+
if (!this.syncSceneData()) {
|
|
689
|
+
console.warn('⚠️ updatePaths(): Scene data synchronization failed, proceeding with caution');
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// Step 2: Update paths with synchronized data
|
|
565
693
|
this.sceneViewer.updatePaths();
|
|
566
|
-
console.log('✅ updatePaths(): Paths updated successfully');
|
|
694
|
+
console.log('✅ updatePaths(): Paths updated successfully with synchronized data');
|
|
567
695
|
return true;
|
|
568
696
|
} catch (error) {
|
|
569
697
|
console.error('❌ updatePaths(): Error updating paths:', error);
|
|
@@ -571,6 +699,262 @@ var CentralPlant = /*#__PURE__*/function () {
|
|
|
571
699
|
}
|
|
572
700
|
}
|
|
573
701
|
|
|
702
|
+
/**
|
|
703
|
+
* Synchronize scene data to ensure all component positions and properties are up-to-date
|
|
704
|
+
* @returns {boolean} True if synchronization was successful, false otherwise
|
|
705
|
+
* @description Updates the currentSceneData to match the actual Three.js scene state.
|
|
706
|
+
* This includes component positions, rotations, scales, and world bounding boxes.
|
|
707
|
+
* Should be called before operations that depend on accurate scene data.
|
|
708
|
+
* @example
|
|
709
|
+
* // Ensure scene data is current before pathfinding
|
|
710
|
+
* const success = centralPlant.syncSceneData();
|
|
711
|
+
* if (success) {
|
|
712
|
+
* console.log('Scene data synchronized with Three.js scene');
|
|
713
|
+
* }
|
|
714
|
+
*/
|
|
715
|
+
}, {
|
|
716
|
+
key: "syncSceneData",
|
|
717
|
+
value: function syncSceneData() {
|
|
718
|
+
var _this = this;
|
|
719
|
+
// Check if scene viewer and currentSceneData are available
|
|
720
|
+
if (!this.sceneViewer || !this.sceneViewer.currentSceneData) {
|
|
721
|
+
console.warn('⚠️ syncSceneData(): Scene viewer or current scene data not available');
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
if (!this.sceneViewer.scene) {
|
|
725
|
+
console.warn('⚠️ syncSceneData(): Three.js scene not available');
|
|
726
|
+
return false;
|
|
727
|
+
}
|
|
728
|
+
try {
|
|
729
|
+
console.log('🔄 syncSceneData(): Starting scene data synchronization...');
|
|
730
|
+
|
|
731
|
+
// Get reference to currentSceneData
|
|
732
|
+
var currentSceneData = this.sceneViewer.currentSceneData;
|
|
733
|
+
if (!currentSceneData.scene || !currentSceneData.scene.object || !currentSceneData.scene.object.children) {
|
|
734
|
+
console.warn('⚠️ syncSceneData(): Invalid currentSceneData structure');
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Update each component in scene data to match Three.js scene
|
|
739
|
+
var updatedCount = 0;
|
|
740
|
+
currentSceneData.scene.object.children.forEach(function (sceneDataChild, index) {
|
|
741
|
+
// Find matching Three.js object
|
|
742
|
+
var matchingThreeObject = null;
|
|
743
|
+
_this.sceneViewer.scene.traverse(function (threeObject) {
|
|
744
|
+
var _sceneDataChild$userD, _threeObject$userData, _threeObject$userData2;
|
|
745
|
+
// Check various UUID matching strategies
|
|
746
|
+
if (threeObject.uuid === sceneDataChild.uuid || threeObject.uuid === ((_sceneDataChild$userD = sceneDataChild.userData) === null || _sceneDataChild$userD === void 0 ? void 0 : _sceneDataChild$userD.originalUuid) || ((_threeObject$userData = threeObject.userData) === null || _threeObject$userData === void 0 ? void 0 : _threeObject$userData.originalUuid) === sceneDataChild.uuid || ((_threeObject$userData2 = threeObject.userData) === null || _threeObject$userData2 === void 0 ? void 0 : _threeObject$userData2.hardcodedUuid) === sceneDataChild.uuid) {
|
|
747
|
+
matchingThreeObject = threeObject;
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
if (matchingThreeObject) {
|
|
751
|
+
// Update position, rotation, and scale
|
|
752
|
+
sceneDataChild.position = {
|
|
753
|
+
x: matchingThreeObject.position.x,
|
|
754
|
+
y: matchingThreeObject.position.y,
|
|
755
|
+
z: matchingThreeObject.position.z
|
|
756
|
+
};
|
|
757
|
+
sceneDataChild.rotation = {
|
|
758
|
+
x: matchingThreeObject.rotation.x,
|
|
759
|
+
y: matchingThreeObject.rotation.y,
|
|
760
|
+
z: matchingThreeObject.rotation.z
|
|
761
|
+
};
|
|
762
|
+
sceneDataChild.scale = {
|
|
763
|
+
x: matchingThreeObject.scale.x,
|
|
764
|
+
y: matchingThreeObject.scale.y,
|
|
765
|
+
z: matchingThreeObject.scale.z
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
// Update matrix
|
|
769
|
+
sceneDataChild.matrix = matchingThreeObject.matrix.elements;
|
|
770
|
+
|
|
771
|
+
// Update world bounding box
|
|
772
|
+
if (matchingThreeObject.isMesh) {
|
|
773
|
+
var boundingBox = new THREE.Box3().setFromObject(matchingThreeObject);
|
|
774
|
+
if (!sceneDataChild.userData) sceneDataChild.userData = {};
|
|
775
|
+
sceneDataChild.userData.worldBoundingBox = {
|
|
776
|
+
min: boundingBox.min.toArray(),
|
|
777
|
+
max: boundingBox.max.toArray()
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Sync children (connectors) if they exist
|
|
782
|
+
if (sceneDataChild.children && matchingThreeObject.children) {
|
|
783
|
+
sceneDataChild.children.forEach(function (sceneChild, childIndex) {
|
|
784
|
+
var matchingChild = matchingThreeObject.children.find(function (threeChild) {
|
|
785
|
+
var _sceneChild$userData, _threeChild$userData;
|
|
786
|
+
return threeChild.uuid === sceneChild.uuid || threeChild.uuid === ((_sceneChild$userData = sceneChild.userData) === null || _sceneChild$userData === void 0 ? void 0 : _sceneChild$userData.originalUuid) || ((_threeChild$userData = threeChild.userData) === null || _threeChild$userData === void 0 ? void 0 : _threeChild$userData.originalUuid) === sceneChild.uuid;
|
|
787
|
+
});
|
|
788
|
+
if (matchingChild) {
|
|
789
|
+
var _matchingChild$userDa;
|
|
790
|
+
// Update child position, rotation, and scale
|
|
791
|
+
sceneChild.position = {
|
|
792
|
+
x: matchingChild.position.x,
|
|
793
|
+
y: matchingChild.position.y,
|
|
794
|
+
z: matchingChild.position.z
|
|
795
|
+
};
|
|
796
|
+
sceneChild.rotation = {
|
|
797
|
+
x: matchingChild.rotation.x,
|
|
798
|
+
y: matchingChild.rotation.y,
|
|
799
|
+
z: matchingChild.rotation.z
|
|
800
|
+
};
|
|
801
|
+
sceneChild.scale = {
|
|
802
|
+
x: matchingChild.scale.x,
|
|
803
|
+
y: matchingChild.scale.y,
|
|
804
|
+
z: matchingChild.scale.z
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
// Update direction vector for connectors
|
|
808
|
+
if ((_matchingChild$userDa = matchingChild.userData) !== null && _matchingChild$userDa !== void 0 && _matchingChild$userDa.direction) {
|
|
809
|
+
if (!sceneChild.userData) sceneChild.userData = {};
|
|
810
|
+
sceneChild.userData.direction = _toConsumableArray(matchingChild.userData.direction);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
updatedCount++;
|
|
816
|
+
} else {
|
|
817
|
+
console.warn("\u26A0\uFE0F syncSceneData(): No matching Three.js object found for scene data child: ".concat(sceneDataChild.uuid));
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
// Force recompute world bounding boxes for pathfinding accuracy
|
|
822
|
+
if (this.sceneViewer.pathfindingManager && typeof this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes === 'function') {
|
|
823
|
+
this.sceneViewer.pathfindingManager.recomputeWorldBoundingBoxes(currentSceneData);
|
|
824
|
+
console.log('🔄 syncSceneData(): Recomputed world bounding boxes for pathfinding');
|
|
825
|
+
}
|
|
826
|
+
console.log("\u2705 syncSceneData(): Synchronized ".concat(updatedCount, " components successfully"));
|
|
827
|
+
return true;
|
|
828
|
+
} catch (error) {
|
|
829
|
+
console.error('❌ syncSceneData(): Error synchronizing scene data:', error);
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Force complete scene data synchronization using SceneOperationsManager
|
|
836
|
+
* @returns {boolean} True if forced synchronization was successful, false otherwise
|
|
837
|
+
* @description Uses the SceneOperationsManager's updateSceneDataAfterTransform method
|
|
838
|
+
* to update scene data for every component. This is more thorough than syncSceneData()
|
|
839
|
+
* and should be used when maximum accuracy is required.
|
|
840
|
+
* @example
|
|
841
|
+
* // Force complete synchronization before critical operations
|
|
842
|
+
* const success = centralPlant.forceSyncSceneData();
|
|
843
|
+
* if (success) {
|
|
844
|
+
* console.log('Complete scene data synchronization completed');
|
|
845
|
+
* }
|
|
846
|
+
*/
|
|
847
|
+
}, {
|
|
848
|
+
key: "forceSyncSceneData",
|
|
849
|
+
value: function forceSyncSceneData() {
|
|
850
|
+
var _this2 = this;
|
|
851
|
+
// Check if scene viewer and sceneOperationsManager are available
|
|
852
|
+
if (!this.sceneViewer || !this.sceneViewer.sceneOperationsManager) {
|
|
853
|
+
console.warn('⚠️ forceSyncSceneData(): Scene viewer or scene operations manager not available');
|
|
854
|
+
return false;
|
|
855
|
+
}
|
|
856
|
+
if (!this.sceneViewer.currentSceneData) {
|
|
857
|
+
console.warn('⚠️ forceSyncSceneData(): Current scene data not available');
|
|
858
|
+
return false;
|
|
859
|
+
}
|
|
860
|
+
if (!this.sceneViewer.scene) {
|
|
861
|
+
console.warn('⚠️ forceSyncSceneData(): Three.js scene not available');
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
try {
|
|
865
|
+
console.log('🔄 forceSyncSceneData(): Starting forced scene data synchronization...');
|
|
866
|
+
var syncedCount = 0;
|
|
867
|
+
var currentSceneData = this.sceneViewer.currentSceneData;
|
|
868
|
+
|
|
869
|
+
// Traverse all objects in the Three.js scene and update their scene data
|
|
870
|
+
this.sceneViewer.scene.traverse(function (threeObject) {
|
|
871
|
+
// Only sync objects that have component-related userData
|
|
872
|
+
if (threeObject.userData && (threeObject.userData.componentType === 'component' || threeObject.userData.componentType === 'gateway' || threeObject.userData.libraryId)) {
|
|
873
|
+
console.log("\uD83D\uDD04 Syncing object: ".concat(threeObject.uuid, " (").concat(threeObject.userData.componentType || 'unknown', ")"));
|
|
874
|
+
|
|
875
|
+
// Use the existing updateSceneDataAfterTransform method
|
|
876
|
+
var success = _this2.sceneViewer.sceneOperationsManager.updateSceneDataAfterTransform(threeObject, currentSceneData);
|
|
877
|
+
if (success) {
|
|
878
|
+
syncedCount++;
|
|
879
|
+
} else {
|
|
880
|
+
console.warn("\u26A0\uFE0F Failed to sync object: ".concat(threeObject.uuid));
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
console.log("\u2705 forceSyncSceneData(): Force synchronized ".concat(syncedCount, " objects successfully"));
|
|
885
|
+
return true;
|
|
886
|
+
} catch (error) {
|
|
887
|
+
console.error('❌ forceSyncSceneData(): Error during forced scene data synchronization:', error);
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Update paths with optional scene data synchronization level
|
|
894
|
+
* @param {string} [syncLevel='auto'] - Level of synchronization: 'none', 'basic', 'complete', or 'auto'
|
|
895
|
+
* @returns {boolean} True if paths were updated successfully, false otherwise
|
|
896
|
+
* @description Enhanced updatePaths method that allows choosing the level of scene data
|
|
897
|
+
* synchronization before updating paths. The 'auto' level intelligently chooses based
|
|
898
|
+
* on scene complexity and recent changes.
|
|
899
|
+
* @example
|
|
900
|
+
* // Update paths with automatic synchronization (recommended)
|
|
901
|
+
* centralPlant.updatePathsWithSync('auto');
|
|
902
|
+
*
|
|
903
|
+
* // Update paths with complete synchronization (most accurate)
|
|
904
|
+
* centralPlant.updatePathsWithSync('complete');
|
|
905
|
+
*
|
|
906
|
+
* // Update paths without synchronization (fastest)
|
|
907
|
+
* centralPlant.updatePathsWithSync('none');
|
|
908
|
+
*/
|
|
909
|
+
}, {
|
|
910
|
+
key: "updatePathsWithSync",
|
|
911
|
+
value: function updatePathsWithSync() {
|
|
912
|
+
var syncLevel = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'auto';
|
|
913
|
+
if (!this.sceneViewer || !this.sceneViewer.updatePaths) {
|
|
914
|
+
console.warn('⚠️ updatePathsWithSync(): Scene viewer or updatePaths method not available');
|
|
915
|
+
return false;
|
|
916
|
+
}
|
|
917
|
+
try {
|
|
918
|
+
// Determine sync level automatically if needed
|
|
919
|
+
if (syncLevel === 'auto') {
|
|
920
|
+
var _this$transformHistor;
|
|
921
|
+
// Use basic sync by default, but upgrade to complete if recent transforms detected
|
|
922
|
+
syncLevel = (_this$transformHistor = this.transformHistory) !== null && _this$transformHistor !== void 0 && _this$transformHistor.lastTransform && Date.now() - new Date(this.transformHistory.lastTransform.timestamp).getTime() < 5000 ? 'complete' : 'basic';
|
|
923
|
+
console.log("\uD83E\uDD16 updatePathsWithSync(): Auto-selected sync level: ".concat(syncLevel));
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// Perform synchronization based on level
|
|
927
|
+
var syncSuccess = true;
|
|
928
|
+
switch (syncLevel) {
|
|
929
|
+
case 'none':
|
|
930
|
+
console.log('⚡ updatePathsWithSync(): Skipping synchronization for speed');
|
|
931
|
+
break;
|
|
932
|
+
case 'basic':
|
|
933
|
+
console.log('🔄 updatePathsWithSync(): Performing basic scene data synchronization...');
|
|
934
|
+
syncSuccess = this.syncSceneData();
|
|
935
|
+
break;
|
|
936
|
+
case 'complete':
|
|
937
|
+
console.log('🔄 updatePathsWithSync(): Performing complete scene data synchronization...');
|
|
938
|
+
syncSuccess = this.forceSyncSceneData();
|
|
939
|
+
break;
|
|
940
|
+
default:
|
|
941
|
+
console.warn("\u26A0\uFE0F updatePathsWithSync(): Unknown sync level '".concat(syncLevel, "', defaulting to basic"));
|
|
942
|
+
syncSuccess = this.syncSceneData();
|
|
943
|
+
}
|
|
944
|
+
if (!syncSuccess && syncLevel !== 'none') {
|
|
945
|
+
console.warn('⚠️ updatePathsWithSync(): Scene data synchronization failed, proceeding with caution');
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// Update paths
|
|
949
|
+
this.sceneViewer.updatePaths();
|
|
950
|
+
console.log("\u2705 updatePathsWithSync(): Paths updated successfully with '".concat(syncLevel, "' synchronization"));
|
|
951
|
+
return true;
|
|
952
|
+
} catch (error) {
|
|
953
|
+
console.error('❌ updatePathsWithSync(): Error updating paths with sync:', error);
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
574
958
|
/**
|
|
575
959
|
* Add a connection between two connector IDs to the connections list
|
|
576
960
|
* @param {string} fromConnectorId - The UUID of the source connector
|