feat: Enhance ArmBot and StaticMachine mechanics with trigger handling and reset functionality

This commit is contained in:
Jerald-Golden-B 2025-04-08 18:31:57 +05:30
parent a6993ccd2e
commit 43df50c576
6 changed files with 274 additions and 48 deletions

View File

@ -1,65 +1,121 @@
import React, { useRef, useMemo } from "react"; import React, { useRef, useMemo, useCallback, useState } from "react";
import { InfoIcon } from "../../../icons/ExportCommonIcons"; import { InfoIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store"; import {
useSelectedActionSphere,
useSimulationStates,
useSocketStore
} from "../../../../store/store";
import * as Types from '../../../../types/world/worldTypes'; import * as Types from '../../../../types/world/worldTypes';
import PositionInput from "../customInput/PositionInputs"; import LabeledButton from "../../../ui/inputs/LabledButton";
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt"; import LabledDropdown from "../../../ui/inputs/LabledDropdown";
const ArmBotMechanics: React.FC = () => { const ArmBotMechanics: React.FC = () => {
const { selectedActionSphere } = useSelectedActionSphere(); const { selectedActionSphere } = useSelectedActionSphere();
const { simulationStates, setSimulationStates } = useSimulationStates(); const { simulationStates, setSimulationStates } = useSimulationStates();
const { socket } = useSocketStore(); const { socket } = useSocketStore();
const [selectedTrigger, setSelectedTrigger] = useState<string | null>(null);
const propertiesContainerRef = useRef<HTMLDivElement>(null); const propertiesContainerRef = useRef<HTMLDivElement>(null);
const { selectedPoint, connectedPointUuids } = useMemo(() => { // Get connected models for dropdowns
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] }; const connectedModels = useMemo(() => {
if (!selectedActionSphere?.points?.uuid) return [];
const vehiclePaths = simulationStates.filter( }, [selectedActionSphere, simulationStates]);
// Get triggers only from connected models
const connectedTriggers = useMemo(() => {
}, [connectedModels, simulationStates]);
const { selectedPoint } = useMemo(() => {
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null };
const armBotPaths = simulationStates.filter(
(path): path is Types.ArmBotEventsSchema => path.type === "ArmBot" (path): path is Types.ArmBotEventsSchema => path.type === "ArmBot"
); );
const points = vehiclePaths.find( const points = armBotPaths.find(
(path) => path.points.uuid === selectedActionSphere.points.uuid (path) => path.points.uuid === selectedActionSphere.points.uuid
)?.points; )?.points;
if (!points) return { selectedPoint: null, connectedPointUuids: [] };
const connectedUuids: string[] = [];
if (points.connections?.targets) {
points.connections.targets.forEach(target => {
connectedUuids.push(target.pointUUID);
});
}
return { return {
selectedPoint: points, selectedPoint: points || null
connectedPointUuids: connectedUuids
}; };
}, [selectedActionSphere, simulationStates]); }, [selectedActionSphere, simulationStates]);
const updateBackend = async (updatedPath: Types.ArmBotEventsSchema | undefined) => { const updateBackend = async (updatedPath: Types.ArmBotEventsSchema | undefined) => {
if (!updatedPath) return; // if (!updatedPath) return;
const email = localStorage.getItem("email"); // const email = localStorage.getItem("email");
const organization = email ? email.split("@")[1].split(".")[0] : ""; // const organization = email ? email.split("@")[1].split(".")[0] : "";
// await setEventApi( // const data = {
// organization, // organization: organization,
// updatedPath.modeluuid, // modeluuid: updatedPath.modeluuid,
// { type: "ArmBot", points: updatedPath.points } // eventData: { type: "ArmBot", points: updatedPath.points }
// ); // }
const data = {
organization: organization,
modeluuid: updatedPath.modeluuid,
eventData: { type: "ArmBot", points: updatedPath.points }
}
socket.emit('v2:model-asset:updateEventData', data);
// socket.emit('v2:model-asset:updateEventData', data);
} }
// const handleActionUpdate = useCallback((updatedAction: Partial<Types.ArmBotEventsSchema['points']['actions']>) => {
// if (!selectedActionSphere?.points?.uuid) return;
// const updatedPaths = simulationStates.map((path) => {
// return path;
// });
// const updatedPath = updatedPaths.find(
// (path): path is Types.ArmBotEventsSchema =>
// path.type === "ArmBot" &&
// path.points.uuid === selectedActionSphere.points.uuid
// );
// updateBackend(updatedPath);
// setSimulationStates(updatedPaths);
// }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
// const handleSpeedChange = useCallback((speed: number) => {
// handleActionUpdate({ speed });
// }, [handleActionUpdate]);
// const handleProcessChange = useCallback((processes: Types.ArmBotEventsSchema['points']['actions']['processes']) => {
// handleActionUpdate({ processes });
// }, [handleActionUpdate]);
// const handleTriggerSelect = useCallback((displayName: string) => {
// const selected = connectedTriggers.find(t => t.displayName === displayName);
// setSelectedTrigger(selected?.uuid || null);
// }, [connectedTriggers]);
// const handleStartPointSelect = useCallback((pointUUID: string) => {
// if (!selectedTrigger || !selectedPoint) return;
// const updatedProcesses = selectedPoint.actions.processes?.map(process =>
// process.triggerId === selectedTrigger
// ? { ...process, startPoint: pointUUID }
// : process
// ) || [];
// handleProcessChange(updatedProcesses);
// }, [selectedTrigger, selectedPoint, handleProcessChange]);
// const handleEndPointSelect = useCallback((pointUUID: string) => {
// if (!selectedTrigger || !selectedPoint) return;
// const updatedProcesses = selectedPoint.actions.processes?.map(process =>
// process.triggerId === selectedTrigger
// ? { ...process, endPoint: pointUUID }
// : process
// ) || [];
// handleProcessChange(updatedProcesses);
// }, [selectedTrigger, selectedPoint, handleProcessChange]);
// const getCurrentProcess = useCallback(() => {
// if (!selectedTrigger || !selectedPoint) return null;
// return selectedPoint.actions.processes?.find(p => p.triggerId === selectedTrigger);
// }, [selectedTrigger, selectedPoint]);
return ( return (
<div className="machine-mechanics-container" key={selectedPoint?.uuid}> <div className="machine-mechanics-container" key={selectedPoint?.uuid}>
@ -71,16 +127,50 @@ const ArmBotMechanics: React.FC = () => {
<div className="selected-properties-container" ref={propertiesContainerRef}> <div className="selected-properties-container" ref={propertiesContainerRef}>
<div className="properties-header">ArmBot Properties</div> <div className="properties-header">ArmBot Properties</div>
{selectedPoint && ( {/* {selectedPoint && (
<> <>
<InputWithDropDown
key={`speed-${selectedPoint.uuid}`}
label="ArmBot Speed"
value={selectedPoint.actions.speed.toString()}
onChange={(value) => handleSpeedChange(parseInt(value))}
/>
<LabledDropdown
key={`trigger-select-${selectedPoint.uuid}`}
label="Select Trigger"
defaultOption={connectedTriggers.find(t => t.uuid === selectedTrigger)?.displayName || ''}
onSelect={handleTriggerSelect}
options={connectedTriggers.map(trigger => trigger.displayName)}
/>
{selectedTrigger && (
<>
<LabledDropdown
key={`start-point-${selectedTrigger}`}
label="Start Point"
defaultOption={getCurrentProcess()?.startPoint || ''}
onSelect={handleStartPointSelect}
options={connectedModels.map((model, index) => `${model.modelName} [${index}]`)}
/>
<LabledDropdown
key={`end-point-${selectedTrigger}`}
label="End Point"
defaultOption={getCurrentProcess()?.endPoint || ''}
onSelect={handleEndPointSelect}
options={connectedModels.map((model, index) => `${model.modelName} [${index}]`)}
/>
</>
)}
</> </>
)} )} */}
</div> </div>
<div className="footer"> <div className="footer">
<InfoIcon /> <InfoIcon />
Configure armbot properties. Configure ArmBot properties and trigger-based processes.
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,9 +1,9 @@
import React, { useRef, useMemo } from "react"; import React, { useRef, useMemo, useCallback } from "react";
import { InfoIcon } from "../../../icons/ExportCommonIcons"; import { InfoIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown"; import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store"; import { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
import * as Types from '../../../../types/world/worldTypes'; import * as Types from '../../../../types/world/worldTypes';
import PositionInput from "../customInput/PositionInputs"; import LabledDropdown from "../../../ui/inputs/LabledDropdown";
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt"; import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
const StaticMachineMechanics: React.FC = () => { const StaticMachineMechanics: React.FC = () => {
@ -16,11 +16,11 @@ const StaticMachineMechanics: React.FC = () => {
const { selectedPoint, connectedPointUuids } = useMemo(() => { const { selectedPoint, connectedPointUuids } = useMemo(() => {
if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] }; if (!selectedActionSphere?.points?.uuid) return { selectedPoint: null, connectedPointUuids: [] };
const vehiclePaths = simulationStates.filter( const staticMachinePaths = simulationStates.filter(
(path): path is Types.StaticMachineEventsSchema => path.type === "StaticMachine" (path): path is Types.StaticMachineEventsSchema => path.type === "StaticMachine"
); );
const points = vehiclePaths.find( const points = staticMachinePaths.find(
(path) => path.points.uuid === selectedActionSphere.points.uuid (path) => path.points.uuid === selectedActionSphere.points.uuid
)?.points; )?.points;
@ -47,7 +47,7 @@ const StaticMachineMechanics: React.FC = () => {
// await setEventApi( // await setEventApi(
// organization, // organization,
// updatedPath.modeluuid, // updatedPath.modeluuid,
// { type: "StaticMachine", points: updatedPath.points } // { type: "Vehicle", points: updatedPath.points }
// ); // );
const data = { const data = {
@ -57,9 +57,77 @@ const StaticMachineMechanics: React.FC = () => {
} }
socket.emit('v2:model-asset:updateEventData', data); socket.emit('v2:model-asset:updateEventData', data);
} }
const handleActionUpdate = useCallback((updatedAction: Partial<Types.StaticMachineEventsSchema['points']['actions']>) => {
if (!selectedActionSphere?.points?.uuid) return;
const updatedPaths = simulationStates.map((path) => {
if (path.type === "StaticMachine" && path.points.uuid === selectedActionSphere.points.uuid) {
return {
...path,
points: {
...path.points,
actions: {
...path.points.actions,
...updatedAction
}
}
};
}
return path;
});
const updatedPath = updatedPaths.find(
(path): path is Types.StaticMachineEventsSchema =>
path.type === "StaticMachine" &&
path.points.uuid === selectedActionSphere.points.uuid
);
updateBackend(updatedPath);
setSimulationStates(updatedPaths);
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
const handleBufferChange = useCallback((buffer: number) => {
handleActionUpdate({ buffer });
}, [handleActionUpdate]);
const handleMaterialChange = useCallback((material: string) => {
handleActionUpdate({ material });
}, [handleActionUpdate]);
const handleTriggerChange = useCallback((updatedTrigger: Partial<Types.StaticMachineEventsSchema['points']['triggers']>) => {
if (!selectedActionSphere?.points?.uuid) return;
const updatedPaths = simulationStates.map((path) => {
if (path.type === "StaticMachine" && path.points.uuid === selectedActionSphere.points.uuid) {
return {
...path,
points: {
...path.points,
triggers: {
...path.points.triggers,
...updatedTrigger
}
}
};
}
return path;
});
const updatedPath = updatedPaths.find(
(path): path is Types.StaticMachineEventsSchema =>
path.type === "StaticMachine" &&
path.points.uuid === selectedActionSphere.points.uuid
);
updateBackend(updatedPath);
setSimulationStates(updatedPaths);
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
const handleTriggerTypeChange = useCallback((type: string) => {
handleTriggerChange({ type });
}, [handleTriggerChange]);
return ( return (
<div className="machine-mechanics-container" key={selectedPoint?.uuid}> <div className="machine-mechanics-container" key={selectedPoint?.uuid}>
@ -67,20 +135,50 @@ const StaticMachineMechanics: React.FC = () => {
{selectedActionSphere?.path?.modelName || "Machine point not found"} {selectedActionSphere?.path?.modelName || "Machine point not found"}
</div> </div>
<div className="machine-mechanics-content-container"> <div className="machine-mechanics-content-container">
<div className="selected-properties-container" ref={propertiesContainerRef}> <div className="selected-properties-container" ref={propertiesContainerRef}>
<div className="properties-header">Machine Properties</div> <div className="properties-header">Machine Properties</div>
{selectedPoint && ( {selectedPoint && (
<> <>
<InputWithDropDown
key={`buffer-${selectedPoint.uuid}`}
label="Buffer Time"
value={selectedPoint.actions.buffer.toString()}
onChange={(value) => handleBufferChange(parseInt(value))}
/>
<LabledDropdown
key={`material-${selectedPoint.uuid}`}
label="Material"
defaultOption={selectedPoint.actions.material}
onSelect={(value) => handleMaterialChange(value)}
options={["Inherit", "Crate", "Box"]}
/>
<LabledDropdown
key={`trigger-type-${selectedPoint.uuid}`}
label="Trigger Type"
defaultOption={selectedPoint.triggers.type}
onSelect={(value) => handleTriggerTypeChange(value)}
options={["OnComplete", "OnStart"]}
/>
{/* <LabeledButton
label="Reset"
value="Reset Settings"
onClick={() => {
// Implement reset functionality if needed
}}
/> */}
</> </>
)} )}
</div> </div>
<div className="footer"> <div className="footer">
<InfoIcon /> <InfoIcon />
Configure machine properties. Configure machine interaction properties and triggers.
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,6 +5,7 @@ import { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionS
import * as Types from '../../../../types/world/worldTypes'; import * as Types from '../../../../types/world/worldTypes';
import PositionInput from "../customInput/PositionInputs"; import PositionInput from "../customInput/PositionInputs";
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt"; import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
import LabeledButton from "../../../ui/inputs/LabledButton";
const VehicleMechanics: React.FC = () => { const VehicleMechanics: React.FC = () => {
const { selectedActionSphere } = useSelectedActionSphere(); const { selectedActionSphere } = useSelectedActionSphere();
@ -126,6 +127,33 @@ const VehicleMechanics: React.FC = () => {
setSimulationStates(updatedPaths); setSimulationStates(updatedPaths);
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]); }, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
const ResetVehicleState = React.useCallback(() => {
if (!selectedActionSphere?.points?.uuid) return;
const updatedPaths = simulationStates.map((state) => {
if (state.type === "Vehicle" && state.points.uuid === selectedActionSphere.points.uuid) {
return {
...state,
points: {
...state.points,
actions: { ...state.points.actions, start: {}, end: {} }
}
};
}
return state;
});
const updatedPath = updatedPaths.find(
(path): path is Types.VehicleEventsSchema =>
path.type === "Vehicle" &&
path.points.uuid === selectedActionSphere.points.uuid
);
updateBackend(updatedPath);
setSimulationStates(updatedPaths);
}, [selectedActionSphere?.points?.uuid, simulationStates, setSimulationStates]);
const handleStartEyeDropClick = () => { const handleStartEyeDropClick = () => {
setEditingPoint('start'); setEditingPoint('start');
setEyeDropMode(true); setEyeDropMode(true);
@ -193,6 +221,14 @@ const VehicleMechanics: React.FC = () => {
handleEyeDropClick={handleEndEyeDropClick} handleEyeDropClick={handleEndEyeDropClick}
/> />
<LabeledButton
label="Reset"
value="Clear Points"
onClick={() => {
ResetVehicleState();
}}
/>
<InputWithDropDown <InputWithDropDown
key={`hitcount-${selectedPoint.uuid}`} key={`hitcount-${selectedPoint.uuid}`}
label="Hit Count" label="Hit Count"

View File

@ -193,6 +193,8 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
if (deleteTool) { if (deleteTool) {
DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, setSimulationStates, socket); DeleteFloorItems(itemsGroup, hoveredDeletableFloorItem, setFloorItems, setSimulationStates, socket);
// Remove EventData if there are any in the asset.
} }
const Mode = transformMode; const Mode = transformMode;

View File

@ -434,7 +434,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
}; };
const backendEventData = { const backendEventData = {
type: 'StaticMachine', type: 'ArmBot',
points: createArmBotPoint() points: createArmBotPoint()
}; };

View File

@ -416,7 +416,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
}; };
const backendEventData = { const backendEventData = {
type: 'StaticMachine', type: 'ArmBot',
points: createArmBotPoint() points: createArmBotPoint()
}; };