Merge remote-tracking branch 'origin/main-dev' into feature/layout-comparison-version
This commit is contained in:
@@ -70,12 +70,19 @@ function StorageMechanics() {
|
||||
};
|
||||
|
||||
const handleCapacityChange = (value: string) => {
|
||||
if (!selectedEventData) return;
|
||||
if (!selectedEventData || selectedEventData.data.type !== "storageUnit") return;
|
||||
|
||||
const numericValue = parseInt(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
const event = peekUpdateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, { storageCapacity: numericValue } as StorageEventSchema);
|
||||
const currentCount = selectedEventData.data.storageCount;
|
||||
const updatedEventData: Partial<StorageEventSchema> = { storageCapacity: numericValue };
|
||||
|
||||
if (currentCount > numericValue) {
|
||||
updatedEventData.storageCount = numericValue;
|
||||
}
|
||||
|
||||
const event = peekUpdateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, updatedEventData as StorageEventSchema);
|
||||
|
||||
if (event) {
|
||||
updateBackend(event);
|
||||
@@ -83,11 +90,15 @@ function StorageMechanics() {
|
||||
};
|
||||
|
||||
const handleSpawnCountChange = (value: string) => {
|
||||
if (!selectedEventData) return;
|
||||
if (!selectedEventData || selectedEventData.data.type !== "storageUnit") return;
|
||||
|
||||
const numericValue = parseInt(value);
|
||||
if (isNaN(numericValue)) return;
|
||||
|
||||
const { storageCapacity } = selectedEventData.data;
|
||||
|
||||
if (numericValue > storageCapacity) return;
|
||||
|
||||
const event = peekUpdateEvent(selectedProduct.productUuid, selectedEventData.data.modelUuid, { storageCount: numericValue } as StorageEventSchema);
|
||||
|
||||
if (event) {
|
||||
|
||||
@@ -92,9 +92,9 @@ const Tools: React.FC = () => {
|
||||
// 3. Update tools behavior based on selected tool and view mode
|
||||
useEffect(() => {
|
||||
resetTools();
|
||||
updateToolBehavior(activeTool, toggleView);
|
||||
updateToolBehavior(activeTool, toggleView, activeModule);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [activeTool, toggleView]);
|
||||
}, [activeTool, toggleView, activeModule]);
|
||||
|
||||
// 4. Dropdown auto-close
|
||||
useEffect(() => {
|
||||
@@ -111,7 +111,7 @@ const Tools: React.FC = () => {
|
||||
setToolMode(null);
|
||||
};
|
||||
|
||||
const updateToolBehavior = (tool: string, is2D: boolean) => {
|
||||
const updateToolBehavior = (tool: string, is2D: boolean, activeModule: string) => {
|
||||
switch (tool) {
|
||||
case "cursor":
|
||||
is2D ? setToolMode("move") : setToolMode("cursor");
|
||||
@@ -129,10 +129,27 @@ const Tools: React.FC = () => {
|
||||
is2D && setToolMode("Floor");
|
||||
break;
|
||||
case "move":
|
||||
if (!is2D) setToolMode("Move-Asset");
|
||||
if (!is2D) {
|
||||
if (activeModule === "builder") {
|
||||
setToolMode("Move-Asset");
|
||||
} else if (activeModule === "simulation") {
|
||||
setToolMode("Move-Point");
|
||||
} else {
|
||||
setToolMode("Move-Asset");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "rotate":
|
||||
if (!is2D) setToolMode("Rotate-Asset");
|
||||
if (!is2D) {
|
||||
if (activeModule === "builder") {
|
||||
setToolMode("Rotate-Asset");
|
||||
} else if (activeModule === "simulation") {
|
||||
setToolMode("Rotate-Point");
|
||||
} else {
|
||||
setToolMode("Rotate-Asset");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "measure":
|
||||
setToolMode("MeasurementScale");
|
||||
|
||||
@@ -528,12 +528,12 @@ export const AssetOutline = () => {
|
||||
if (isGroup(draggedItem)) {
|
||||
addChildToGroup(targetGroupUuid, {
|
||||
type: "Group",
|
||||
childrenUuid: draggedItem.groupUuid,
|
||||
childUuid: draggedItem.groupUuid,
|
||||
});
|
||||
} else {
|
||||
addChildToGroup(targetGroupUuid, {
|
||||
type: "Asset",
|
||||
childrenUuid: draggedItem.modelUuid,
|
||||
childUuid: draggedItem.modelUuid,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ function SimulationResponses() {
|
||||
|
||||
if (hasSelectedAction && hasNewAction && newActions.length > 0 && diffActions.length > 0) {
|
||||
setSelectedAction(diffActions[0].actionUuid, diffActions[0].actionName);
|
||||
} else if (selectedAction.actionId && selectedAction.actionName) {
|
||||
const action: [string, string] = [selectedAction.actionId, selectedAction.actionName];
|
||||
setTimeout(() => {
|
||||
setSelectedAction(...action);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ function GroupControls() {
|
||||
isLocked: false,
|
||||
isExpanded: true,
|
||||
children: assetUuids.map((assetUuid) => {
|
||||
return { type: "Asset", childrenUuid: assetUuid };
|
||||
return { type: "Asset", childUuid: assetUuid };
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as THREE from "three";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import useModuleStore, { useSubModuleStore } from "../../../../../store/ui/useModuleStore";
|
||||
import { useToolMode } from "../../../../../store/builder/store";
|
||||
import { useActiveTool, useToolMode } from "../../../../../store/builder/store";
|
||||
import { TransformControls } from "@react-three/drei";
|
||||
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
|
||||
import { useSelectedEventSphere, useSelectedEventData, useDeletableEventSphere } from "../../../../../store/simulation/useSimulationStore";
|
||||
@@ -18,6 +18,7 @@ function PointsCreator() {
|
||||
const { gl, raycaster, scene, pointer, camera } = useThree();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { toolMode } = useToolMode();
|
||||
const { setActiveTool } = useActiveTool();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { simulationSocket } = useSocketStore();
|
||||
const { eventStore, productStore, versionStore } = useSceneContext();
|
||||
@@ -41,9 +42,11 @@ function PointsCreator() {
|
||||
const { projectId } = useParams();
|
||||
|
||||
useEffect(() => {
|
||||
clearSelectedEventSphere();
|
||||
clearSelectedEventData();
|
||||
clearDeletableEventSphere();
|
||||
if (toolMode !== "Move-Point" && toolMode !== "Rotate-Point" && activeModule !== "simulation") {
|
||||
clearSelectedEventSphere();
|
||||
clearSelectedEventData();
|
||||
clearDeletableEventSphere();
|
||||
}
|
||||
}, [toolMode, activeModule]);
|
||||
|
||||
const updateBackend = (eventData: EventsSchema) => {
|
||||
@@ -81,13 +84,28 @@ function PointsCreator() {
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
const keyCombination = detectModifierKeys(e);
|
||||
if (!selectedEventSphere) return;
|
||||
if (!selectedEventSphere || e.repeat) return;
|
||||
|
||||
if (keyCombination === "G") {
|
||||
setTransformMode((prev) => (prev === "translate" ? null : "translate"));
|
||||
setTransformMode((prev) => {
|
||||
const newMode = prev === "translate" ? null : "translate";
|
||||
setTimeout(() => {
|
||||
newMode === "translate" ? setActiveTool("move") : setActiveTool("cursor");
|
||||
}, 0);
|
||||
return newMode;
|
||||
});
|
||||
}
|
||||
|
||||
if (keyCombination === "R") {
|
||||
setTransformMode((prev) => (prev === "rotate" ? null : "rotate"));
|
||||
setTransformMode((prev) => {
|
||||
const newMode = prev === "rotate" ? null : "rotate";
|
||||
setTimeout(() => {
|
||||
newMode === "rotate" ? setActiveTool("rotate") : setActiveTool("cursor");
|
||||
}, 0);
|
||||
return newMode;
|
||||
});
|
||||
}
|
||||
|
||||
if (keyCombination === "DELETE") {
|
||||
deletePointfromConveyor(selectedEventSphere);
|
||||
}
|
||||
@@ -97,6 +115,16 @@ function PointsCreator() {
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [selectedEventSphere]);
|
||||
|
||||
useEffect(() => {
|
||||
if (toolMode === "Move-Point") {
|
||||
setTransformMode("translate");
|
||||
} else if (toolMode === "Rotate-Point") {
|
||||
setTransformMode("rotate");
|
||||
} else {
|
||||
setTransformMode(null);
|
||||
}
|
||||
}, [selectedEventSphere, toolMode]);
|
||||
|
||||
const deletePointfromConveyor = (selectedEventSphere: THREE.Mesh) => {
|
||||
const eventModel = getEventByModelUuidFromProduct(selectedProduct.productUuid, selectedEventSphere.userData.modelUuid);
|
||||
if (!eventModel || eventModel.type !== "transfer" || eventModel.points.length < 2) return;
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function PointInstance({ point, modelUuid, color, ...meshProps }:
|
||||
const { deletableEventSphere, setDeletableEventSphere, clearDeletableEventSphere } = useDeletableEventSphere();
|
||||
const { toolMode } = useToolMode();
|
||||
const { productStore, versionStore } = useSceneContext();
|
||||
const { getEventByModelUuid, getTriggersByTriggeredPointUuid, peekRemoveTriggersAndPoints, peekRemovePoint, selectedProduct, updateEvent } = productStore();
|
||||
const { getEventByModelUuid, getTriggersByTriggeredPointUuid, peekRemoveTriggersAndPoints, selectedProduct, updateEvent } = productStore();
|
||||
const { selectedVersion } = versionStore();
|
||||
const { projectId } = useParams();
|
||||
|
||||
@@ -69,7 +69,7 @@ export default function PointInstance({ point, modelUuid, color, ...meshProps }:
|
||||
position={new THREE.Vector3(...point.position)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
if (toolMode === "cursor") {
|
||||
if (toolMode === "cursor" || toolMode === "Move-Point" || toolMode === "Rotate-Point") {
|
||||
setSelectedEventSphere(ref.current);
|
||||
} else if (toolMode === "3D-Delete") {
|
||||
handleEventPointDelete();
|
||||
|
||||
@@ -19,7 +19,7 @@ export const createAssetGroupApi = async ({
|
||||
isLocked: boolean;
|
||||
children: {
|
||||
type: "Asset" | "Group";
|
||||
childrenUuid: string;
|
||||
childUuid: string;
|
||||
}[];
|
||||
}) => {
|
||||
try {
|
||||
|
||||
@@ -21,9 +21,9 @@ interface AssetGroupStore {
|
||||
hasSelectedGroup: (groupUuid: string) => boolean;
|
||||
|
||||
// Group children management
|
||||
addChildToGroup: (groupUuid: string, child: { type: "Asset" | "Group"; childrenUuid: string }) => { updatedGroups: AssetGroup[] };
|
||||
addChildToGroup: (groupUuid: string, child: { type: "Asset" | "Group"; childUuid: string }) => { updatedGroups: AssetGroup[] };
|
||||
removeChildFromGroup: (groupUuid: string, childUuid: string) => void;
|
||||
getGroupChildren: (groupUuid: string) => { type: "Asset" | "Group"; childrenUuid: string }[];
|
||||
getGroupChildren: (groupUuid: string) => { type: "Asset" | "Group"; childUuid: string }[];
|
||||
|
||||
// Group properties
|
||||
setGroupName: (groupUuid: string, newName: string) => void;
|
||||
@@ -71,14 +71,14 @@ export const createAssetGroupStore = () => {
|
||||
|
||||
// Find all asset children in the new group
|
||||
const assetChildren = group.children.filter((child) => child.type === "Asset");
|
||||
const assetUuids = new Set(assetChildren.map((child) => child.childrenUuid));
|
||||
const assetUuids = new Set(assetChildren.map((child) => child.childUuid));
|
||||
|
||||
// Remove these assets from existing groups and track updated groups
|
||||
const updatedGroups: AssetGroup[] = [];
|
||||
|
||||
state.assetGroups.forEach((existingGroup) => {
|
||||
const originalLength = existingGroup.children.length;
|
||||
existingGroup.children = existingGroup.children.filter((child) => !(child.type === "Asset" && assetUuids.has(child.childrenUuid)));
|
||||
existingGroup.children = existingGroup.children.filter((child) => !(child.type === "Asset" && assetUuids.has(child.childUuid)));
|
||||
|
||||
// If group was modified, add to updated groups
|
||||
if (existingGroup.children.length !== originalLength) {
|
||||
@@ -99,7 +99,7 @@ export const createAssetGroupStore = () => {
|
||||
set((state) => {
|
||||
// First remove this group from any parent groups
|
||||
state.assetGroups.forEach((group) => {
|
||||
group.children = group.children.filter((child) => !(child.type === "Group" && child.childrenUuid === groupUuid));
|
||||
group.children = group.children.filter((child) => !(child.type === "Group" && child.childUuid === groupUuid));
|
||||
});
|
||||
|
||||
// Then remove the group itself
|
||||
@@ -181,7 +181,7 @@ export const createAssetGroupStore = () => {
|
||||
if (group.groupUuid === groupUuid) return; // skip target group
|
||||
|
||||
const originalLength = group.children.length;
|
||||
group.children = group.children.filter((c) => c.childrenUuid !== child.childrenUuid);
|
||||
group.children = group.children.filter((c) => c.childUuid !== child.childUuid);
|
||||
|
||||
if (group.children.length !== originalLength) {
|
||||
updatedGroups.push({ ...group });
|
||||
@@ -189,7 +189,7 @@ export const createAssetGroupStore = () => {
|
||||
});
|
||||
|
||||
// 2️⃣ Add the child to the target group (if not already present)
|
||||
if (!targetGroup.children.some((c) => c.childrenUuid === child.childrenUuid)) {
|
||||
if (!targetGroup.children.some((c) => c.childUuid === child.childUuid)) {
|
||||
targetGroup.children.push(child);
|
||||
updatedGroups.push({ ...targetGroup });
|
||||
}
|
||||
@@ -207,7 +207,7 @@ export const createAssetGroupStore = () => {
|
||||
set((state) => {
|
||||
const group = state.assetGroups.find((g) => g.groupUuid === groupUuid);
|
||||
if (group) {
|
||||
group.children = group.children.filter((child) => child.childrenUuid !== childUuid);
|
||||
group.children = group.children.filter((child) => child.childUuid !== childUuid);
|
||||
state.groupHierarchy = get().buildHierarchy([], state.assetGroups);
|
||||
}
|
||||
});
|
||||
@@ -274,14 +274,14 @@ export const createAssetGroupStore = () => {
|
||||
|
||||
group.children.forEach((child) => {
|
||||
if (child.type === "Asset") {
|
||||
const asset = assetMap.get(child.childrenUuid);
|
||||
const asset = assetMap.get(child.childUuid);
|
||||
if (asset) {
|
||||
children.push(asset);
|
||||
// Remove from assetMap so we know it's been processed
|
||||
assetMap.delete(child.childrenUuid);
|
||||
assetMap.delete(child.childUuid);
|
||||
}
|
||||
} else if (child.type === "Group") {
|
||||
const childGroup = groupMap.get(child.childrenUuid);
|
||||
const childGroup = groupMap.get(child.childUuid);
|
||||
if (childGroup) {
|
||||
children.push(buildNode(childGroup));
|
||||
}
|
||||
@@ -303,7 +303,7 @@ export const createAssetGroupStore = () => {
|
||||
groups.forEach((group) => {
|
||||
group.children.forEach((child) => {
|
||||
if (child.type === "Group") {
|
||||
childGroupUuids.add(child.childrenUuid);
|
||||
childGroupUuids.add(child.childUuid);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -347,7 +347,7 @@ export const createAssetGroupStore = () => {
|
||||
isLocked: node.isLocked,
|
||||
isExpanded: node.isExpanded,
|
||||
children: node.children.map((child) =>
|
||||
"modelUuid" in child ? { type: "Asset" as const, childrenUuid: child.modelUuid } : { type: "Group" as const, childrenUuid: child.groupUuid }
|
||||
"modelUuid" in child ? { type: "Asset" as const, childUuid: child.modelUuid } : { type: "Group" as const, childUuid: child.groupUuid }
|
||||
),
|
||||
});
|
||||
processedGroups.add(node.groupUuid);
|
||||
@@ -408,11 +408,11 @@ export const createAssetGroupStore = () => {
|
||||
|
||||
const allChildren: string[] = [];
|
||||
|
||||
const collectChildren = (children: { type: "Asset" | "Group"; childrenUuid: string }[]) => {
|
||||
const collectChildren = (children: { type: "Asset" | "Group"; childUuid: string }[]) => {
|
||||
children.forEach((child) => {
|
||||
allChildren.push(child.childrenUuid);
|
||||
allChildren.push(child.childUuid);
|
||||
if (child.type === "Group") {
|
||||
const childGroup = get().assetGroups.find((g) => g.groupUuid === child.childrenUuid);
|
||||
const childGroup = get().assetGroups.find((g) => g.groupUuid === child.childUuid);
|
||||
if (childGroup) {
|
||||
collectChildren(childGroup.children);
|
||||
}
|
||||
@@ -430,11 +430,11 @@ export const createAssetGroupStore = () => {
|
||||
},
|
||||
|
||||
getGroupsContainingAsset: (assetUuid) => {
|
||||
return get().assetGroups.filter((group) => group.children.some((child) => child.type === "Asset" && child.childrenUuid === assetUuid));
|
||||
return get().assetGroups.filter((group) => group.children.some((child) => child.type === "Asset" && child.childUuid === assetUuid));
|
||||
},
|
||||
|
||||
getGroupsContainingGroup: (childGroupUuid) => {
|
||||
return get().assetGroups.filter((group) => group.children.some((child) => child.type === "Group" && child.childrenUuid === childGroupUuid));
|
||||
return get().assetGroups.filter((group) => group.children.some((child) => child.type === "Group" && child.childUuid === childGroupUuid));
|
||||
},
|
||||
|
||||
getParentGroup: (item) => {
|
||||
|
||||
@@ -575,32 +575,12 @@ export const createProductStore = () => {
|
||||
}
|
||||
} else if ("point" in eventClone) {
|
||||
const point = (eventClone as any).point;
|
||||
if (eventClone.type === "roboticArm") {
|
||||
if ("actions" in point) {
|
||||
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
|
||||
if (index !== -1) {
|
||||
point.actions.splice(index, 1);
|
||||
updatedEvent = eventClone;
|
||||
return updatedEvent;
|
||||
}
|
||||
}
|
||||
} else if (eventClone.type === "human") {
|
||||
if ("actions" in point) {
|
||||
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
|
||||
if (index !== -1) {
|
||||
point.actions.splice(index, 1);
|
||||
updatedEvent = eventClone;
|
||||
return updatedEvent;
|
||||
}
|
||||
}
|
||||
} else if (eventClone.type === "crane") {
|
||||
if ("actions" in point) {
|
||||
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
|
||||
if (index !== -1) {
|
||||
point.actions.splice(index, 1);
|
||||
updatedEvent = eventClone;
|
||||
return updatedEvent;
|
||||
}
|
||||
if ("actions" in point) {
|
||||
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
|
||||
if (index !== -1) {
|
||||
point.actions.splice(index, 1);
|
||||
updatedEvent = eventClone;
|
||||
return updatedEvent;
|
||||
}
|
||||
} else if ("action" in point && point.action?.actionUuid === actionUuid) {
|
||||
point.action = undefined;
|
||||
|
||||
2
app/src/types/builderTypes.d.ts
vendored
2
app/src/types/builderTypes.d.ts
vendored
@@ -58,7 +58,7 @@ interface AssetGroup {
|
||||
isExpanded: boolean;
|
||||
children: {
|
||||
type: "Asset" | "Group";
|
||||
childrenUuid: string;
|
||||
childUuid: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user