Merge remote-tracking branch 'origin/main-dev' into main-demo
This commit is contained in:
@@ -617,7 +617,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
|||||||
showEyeDropper={field.showEyeDropper}
|
showEyeDropper={field.showEyeDropper}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
{/* add delete */}
|
||||||
{singleValueFields.map((field, index) => (
|
{singleValueFields.map((field, index) => (
|
||||||
<DataSourceSelector
|
<DataSourceSelector
|
||||||
key={field.id}
|
key={field.id}
|
||||||
@@ -633,6 +633,13 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
|||||||
updateDataValue(selectedBlock, selectedElement, newDataValue);
|
updateDataValue(selectedBlock, selectedElement, newDataValue);
|
||||||
}}
|
}}
|
||||||
showEyeDropper={field.showEyeDropper}
|
showEyeDropper={field.showEyeDropper}
|
||||||
|
showDeleteBtn={true}
|
||||||
|
onDelete={() => {
|
||||||
|
const current = Array.isArray(element.dataBinding?.dataValue) ? element.dataBinding!.dataValue : [];
|
||||||
|
const next = [...current];
|
||||||
|
next.splice(index, 1);
|
||||||
|
updateDataValue(selectedBlock, selectedElement, next);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
@@ -659,7 +666,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
|||||||
showEyeDropper={field.showEyeDropper}
|
showEyeDropper={field.showEyeDropper}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
{/* add delete */}
|
||||||
{multipleSourceFields.map((field, index) => (
|
{multipleSourceFields.map((field, index) => (
|
||||||
<DataSourceSelector
|
<DataSourceSelector
|
||||||
key={field.id}
|
key={field.id}
|
||||||
@@ -675,6 +682,13 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
|||||||
updateDataSource(selectedBlock, selectedElement, next);
|
updateDataSource(selectedBlock, selectedElement, next);
|
||||||
}}
|
}}
|
||||||
showEyeDropper={field.showEyeDropper}
|
showEyeDropper={field.showEyeDropper}
|
||||||
|
showDeleteBtn={true}
|
||||||
|
onDelete={() => {
|
||||||
|
const current = Array.isArray(element.dataBinding?.dataSource) ? element.dataBinding!.dataSource : [];
|
||||||
|
const next = [...current];
|
||||||
|
next.splice(index, 1);
|
||||||
|
updateDataSource(selectedBlock, selectedElement, next);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export const calculateMinBlockSize = (block: Block): Size => {
|
|||||||
let minWidth = 100;
|
let minWidth = 100;
|
||||||
let minHeight = 50;
|
let minHeight = 50;
|
||||||
let stackedHeight = 0; // Track cumulative height for stacked elements
|
let stackedHeight = 0; // Track cumulative height for stacked elements
|
||||||
|
let stackedElementCount = 0; // Track number of stacked elements for gap calculation
|
||||||
|
|
||||||
block.elements.forEach((element) => {
|
block.elements.forEach((element) => {
|
||||||
if (element.positionType === "absolute") {
|
if (element.positionType === "absolute") {
|
||||||
@@ -17,12 +18,15 @@ export const calculateMinBlockSize = (block: Block): Size => {
|
|||||||
minWidth = Math.max(minWidth, (element.size?.width || 200) + 40);
|
minWidth = Math.max(minWidth, (element.size?.width || 200) + 40);
|
||||||
// Height: sum them up since they stack
|
// Height: sum them up since they stack
|
||||||
stackedHeight += element.size?.height || 60;
|
stackedHeight += element.size?.height || 60;
|
||||||
|
stackedElementCount++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add padding to stacked height and compare with minHeight from absolute elements
|
// Add padding to stacked height and gaps between elements
|
||||||
if (stackedHeight > 0) {
|
if (stackedHeight > 0) {
|
||||||
minHeight = Math.max(minHeight, stackedHeight + 40);
|
// Add 10px gap between each pair of stacked elements
|
||||||
|
const gapsBetweenElements = Math.max(0, stackedElementCount - 1) * 5;
|
||||||
|
minHeight = Math.max(minHeight, stackedHeight + gapsBetweenElements + 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { width: minWidth, height: minHeight };
|
return { width: minWidth, height: minHeight };
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { EyeDroperIcon } from "../../icons/ExportCommonIcons";
|
import { EyeDroperIcon } from "../../icons/ExportCommonIcons";
|
||||||
import RegularDropDownID from "./RegularDropDownID";
|
import RegularDropDownID from "./RegularDropDownID";
|
||||||
|
import { DeleteIcon } from "../../icons/ContextMenuIcons";
|
||||||
|
|
||||||
type DataSourceSelectorProps = {
|
type DataSourceSelectorProps = {
|
||||||
label?: string;
|
label?: string;
|
||||||
@@ -12,9 +13,11 @@ type DataSourceSelectorProps = {
|
|||||||
onSelect: (value: { id: string; label: string }) => void;
|
onSelect: (value: { id: string; label: string }) => void;
|
||||||
eyeDropperActive?: boolean; // initial state
|
eyeDropperActive?: boolean; // initial state
|
||||||
showEyeDropper?: boolean;
|
showEyeDropper?: boolean;
|
||||||
|
showDeleteBtn?: boolean;
|
||||||
|
onDelete?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({ label = "Data Source", options, selected, onSelect, showEyeDropper = true }) => {
|
const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({ label = "Data Source", options, selected, onSelect, showEyeDropper = true, showDeleteBtn, onDelete }) => {
|
||||||
// Local state to toggle EyeDropper
|
// Local state to toggle EyeDropper
|
||||||
const [isEyeActive, setIsEyeActive] = useState(false);
|
const [isEyeActive, setIsEyeActive] = useState(false);
|
||||||
|
|
||||||
@@ -31,6 +34,12 @@ const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({ label = "Data S
|
|||||||
<EyeDroperIcon isActive={isEyeActive} />
|
<EyeDroperIcon isActive={isEyeActive} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showDeleteBtn && (
|
||||||
|
<div className="delete" onClick={() => onDelete?.()} style={{ cursor: onDelete ? "pointer" : "default" }}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -193,6 +193,9 @@ function Analyzer() {
|
|||||||
// Track previous vehicle phases to detect trip completion
|
// Track previous vehicle phases to detect trip completion
|
||||||
const previousVehiclePhasesRef = useRef<Record<string, string>>({});
|
const previousVehiclePhasesRef = useRef<Record<string, string>>({});
|
||||||
|
|
||||||
|
// Track previous crane phases to detect cycle completion
|
||||||
|
const previousCranePhasesRef = useRef<Record<string, string>>({});
|
||||||
|
|
||||||
// Material lifecycle tracking
|
// Material lifecycle tracking
|
||||||
const materialLifecycleRef = useRef<
|
const materialLifecycleRef = useRef<
|
||||||
Record<
|
Record<
|
||||||
@@ -227,6 +230,7 @@ function Analyzer() {
|
|||||||
previousArmBotActionsRef.current = {};
|
previousArmBotActionsRef.current = {};
|
||||||
previousHumanCountsRef.current = {};
|
previousHumanCountsRef.current = {};
|
||||||
previousVehiclePhasesRef.current = {};
|
previousVehiclePhasesRef.current = {};
|
||||||
|
previousCranePhasesRef.current = {};
|
||||||
materialLifecycleRef.current = {};
|
materialLifecycleRef.current = {};
|
||||||
setAnalysis(null);
|
setAnalysis(null);
|
||||||
setAnalyzing(false);
|
setAnalyzing(false);
|
||||||
@@ -2487,6 +2491,49 @@ function Analyzer() {
|
|||||||
});
|
});
|
||||||
}, [vehicles, isPlaying]);
|
}, [vehicles, isPlaying]);
|
||||||
|
|
||||||
|
// Monitor Crane phase changes to track completed cycles, loads, and lifts
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPlaying) return;
|
||||||
|
|
||||||
|
cranes.forEach((crane) => {
|
||||||
|
const previousPhase = previousCranePhasesRef.current[crane.modelUuid];
|
||||||
|
const currentPhase = crane.currentPhase;
|
||||||
|
|
||||||
|
// Check for transition from 'pickup-drop' to 'init' (Cycle completed)
|
||||||
|
if (previousPhase === "pickup-drop" && currentPhase === "init") {
|
||||||
|
// Increment cycles completed
|
||||||
|
if (!completedActionsRef.current[crane.modelUuid]) {
|
||||||
|
completedActionsRef.current[crane.modelUuid] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[crane.modelUuid]++;
|
||||||
|
|
||||||
|
// Track loads handled (number of materials carried in this cycle)
|
||||||
|
const loadsInCycle = crane.currentMaterials?.length || 1;
|
||||||
|
if (!completedActionsRef.current[`${crane.modelUuid}_loads`]) {
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_loads`] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_loads`] += loadsInCycle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track lifts (picking phase indicates a lift operation)
|
||||||
|
if (previousPhase !== "picking" && currentPhase === "picking") {
|
||||||
|
if (!completedActionsRef.current[`${crane.modelUuid}_lifts`]) {
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_lifts`] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_lifts`]++;
|
||||||
|
|
||||||
|
// Track lift height (assuming a default lift height of 5 meters for now)
|
||||||
|
// In a real scenario, this would be calculated from crane constraints
|
||||||
|
if (!completedActionsRef.current[`${crane.modelUuid}_lift_height`]) {
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_lift_height`] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[`${crane.modelUuid}_lift_height`] += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
previousCranePhasesRef.current[crane.modelUuid] = currentPhase;
|
||||||
|
});
|
||||||
|
}, [cranes, isPlaying]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -701,12 +701,17 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: var(--background-color-button);
|
background: var(--background-color-button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.delete {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.regularDropdown-container {
|
.regularDropdown-container {
|
||||||
.icon {
|
.icon {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user