feat: Enhance EventProperties and mechanics components with new state management and action handling; add DelayAction component and remove unused IkInstances

This commit is contained in:
Jerald-Golden-B 2025-04-24 19:15:36 +05:30
parent a305c3c006
commit 4310b473d0
8 changed files with 481 additions and 152 deletions

View File

@ -123,7 +123,7 @@ const SideBarRight: React.FC = () => {
</div>
</div>
)}
{subModule === "mechanics" && selectedEventData && selectedEventSphere && (
{subModule === "mechanics" && (
<div className="sidebar-right-container">
<div className="sidebar-right-content-container">
<EventProperties />

View File

@ -22,6 +22,9 @@ import Trigger from "./trigger/Trigger";
import { useSelectedEventData, useSelectedProduct } from "../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../store/simulation/useProductStore";
import ConveyorMechanics from "./mechanics/conveyorMechanics";
import VehicleMechanics from "./mechanics/vehicleMechanics";
import RoboticArmMechanics from "./mechanics/roboticArmMechanics";
const EventProperties: React.FC = () => {
const actionsContainerRef = useRef<HTMLDivElement>(null);
@ -32,21 +35,43 @@ const EventProperties: React.FC = () => {
const { getEventByModelUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
// State for derived values
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(null);
const [assetType, setAssetType] = useState<string | null>(null);
const [availableActions, setAvailableActions] = useState({
defaultOption: "default",
options: ["default"]
});
const [actions, setActions] = useState<{ uuid: string; name: string }[]>([]);
const [speed, setSpeed] = useState("0.5");
useEffect(() => {
const actions = getActions();
if (actions.length > 0 && !selectedItem.item) {
setSelectedItem({ item: actions[0] });
const event = getCurrentEventData();
setCurrentEventData(event);
const type = determineAssetType(event);
setAssetType(type);
const actionsConfig = determineAvailableActions(type);
setAvailableActions(actionsConfig);
const actionList = getActionList(event, type);
setActions(actionList);
if (actionList.length > 0 && !selectedItem.item) {
setSelectedItem({ item: actionList[0] });
}
}, [selectedEventData]);
const currentSpeed = getCurrentSpeed();
setSpeed(currentSpeed);
}, [selectedEventData, selectedProduct]);
const getCurrentEventData = () => {
if (!selectedEventData?.data || !selectedProduct) return null;
const event = getEventByModelUuid(selectedProduct.productId, selectedEventData.data.modelUuid);
return event || null;
return getEventByModelUuid(selectedProduct.productId, selectedEventData.data.modelUuid) || null;
};
const getAssetType = () => {
const event = getCurrentEventData();
const determineAssetType = (event: EventsSchema | null) => {
if (!event) return null;
switch (event.type) {
@ -59,8 +84,8 @@ const EventProperties: React.FC = () => {
}
};
const getAvailableActions = () => {
switch (getAssetType()) {
const determineAvailableActions = (type: string | null) => {
switch (type) {
case "conveyor":
return {
defaultOption: "default",
@ -94,12 +119,10 @@ const EventProperties: React.FC = () => {
}
};
// Get actions based on asset type
const getActions = () => {
const getActionList = (event: EventsSchema | null, type: string | null) => {
if (!selectedEventData?.data) return [];
const event = selectedEventData.data;
switch (getAssetType()) {
switch (type) {
case "conveyor":
return (event as ConveyorEventSchema).points
.find((point) => point.uuid === selectedEventData?.selectedPoint)
@ -141,8 +164,13 @@ const EventProperties: React.FC = () => {
}
};
const getCurrentSpeed = () => {
if (!selectedEventData) return "0.5";
if ("speed" in selectedEventData.data) return selectedEventData.data.speed.toString();
return "0.5";
};
const handleActionToggle = (actionUuid: string) => {
const actions = getActions();
const selected = actions.find(action => action.uuid === actionUuid);
if (selected) {
setSelectedItem({ item: selected });
@ -150,130 +178,128 @@ const EventProperties: React.FC = () => {
};
const handleDeleteAction = (actionUuid: string) => {
};
const actions = getActions();
const getSpeed = () => {
if (!selectedEventData) return "0.5";
if ("speed" in selectedEventData.data) return selectedEventData.data.speed.toString();
return "0.5";
// Implementation for delete action
};
return (
<>
{getCurrentEventData() &&
<div className="event-proprties-wrapper">
<div className="header">
<div className="header-value">{selectedEventData?.data.modelName}</div>
</div>
<div className="global-props">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value="0.5"
min={0}
step={0.1}
defaultValue={getSpeed()}
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
</div>
<div className="event-proprties-wrapper">
{currentEventData &&
<>
<div className="header">
<div className="header-value">{selectedEventData?.data.modelName}</div>
</div>
<div className="global-props">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value="0.5"
min={0}
step={0.1}
defaultValue={speed}
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
</div>
<div className="property-item">
<InputWithDropDown
label="Delay"
value="0.5"
min={0}
step={0.1}
defaultValue="0.5"
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
<div className="property-item">
<InputWithDropDown
label="Delay"
value="0.5"
min={0}
step={0.1}
defaultValue="0.5"
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
</div>
</div>
</div>
</div>
{getAssetType() === 'roboticArm' &&
<div className="actions-list-container">
<div className="actions">
<div className="header">
<div className="header-value">Actions</div>
<div className="add-button" onClick={() => { }}>
<AddIcon /> Add
</div>
</div>
<div
className="lists-main-container"
ref={actionsContainerRef}
style={{ height: "120px" }}
>
<div className="list-container">
{actions.map((action) => (
<div
key={action.uuid}
className={`list-item ${selectedItem.item?.uuid === action.uuid ? "active" : ""}`}
>
<div
className="value"
onClick={() => handleActionToggle(action.uuid)}
>
<RenameInput value={action.name} />
</div>
{actions.length > 1 && (
<div
className="remove-button"
onClick={() => handleDeleteAction(action.uuid)}
>
<RemoveIcon />
</div>
)}
</div>
))}
{assetType === 'roboticArm' &&
<div className="actions-list-container">
<div className="actions">
<div className="header">
<div className="header-value">Actions</div>
<div className="add-button" onClick={() => { }}>
<AddIcon /> Add
</div>
</div>
<div
className="resize-icon"
id="action-resize"
onMouseDown={(e) => handleResize(e, actionsContainerRef)}
className="lists-main-container"
ref={actionsContainerRef}
style={{ height: "120px" }}
>
<ResizeHeightIcon />
<div className="list-container">
{actions.map((action) => (
<div
key={action.uuid}
className={`list-item ${selectedItem.item?.uuid === action.uuid ? "active" : ""}`}
>
<div
className="value"
onClick={() => handleActionToggle(action.uuid)}
>
<RenameInput value={action.name} />
</div>
{actions.length > 1 && (
<div
className="remove-button"
onClick={() => handleDeleteAction(action.uuid)}
>
<RemoveIcon />
</div>
)}
</div>
))}
</div>
<div
className="resize-icon"
id="action-resize"
onMouseDown={(e) => handleResize(e, actionsContainerRef)}
>
<ResizeHeightIcon />
</div>
</div>
</div>
</div>
}
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput value="Action Name" />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={availableActions.defaultOption}
options={availableActions.options}
onSelect={(option) => setActiveOption(option)}
/>
{activeOption === "default" && <DefaultAction />}
{activeOption === "spawn" && <SpawnAction />}
{activeOption === "swap" && <SwapAction />}
{activeOption === "despawn" && <DespawnAction />}
{activeOption === "travel" && <TravelAction />}
{activeOption === "pickAndPlace" && <PickAndPlaceAction />}
{activeOption === "process" && <ProcessAction />}
{activeOption === "store" && <StorageAction />}
</div>
</div>
}
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput value="Action Name" />
<div className="tirgger">
<Trigger />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={getAvailableActions().defaultOption}
options={getAvailableActions().options}
onSelect={(option) => setActiveOption(option)}
/>
{activeOption === "default" && <DefaultAction />}
{activeOption === "spawn" && <SpawnAction />}
{activeOption === "swap" && <SwapAction />}
{activeOption === "despawn" && <DespawnAction />}
{activeOption === "travel" && <TravelAction />}
{activeOption === "pickAndPlace" && <PickAndPlaceAction />}
{activeOption === "process" && <ProcessAction />}
{activeOption === "store" && <StorageAction />}
</div>
</div>
<div className="tirgger">
<Trigger />
</div>
</div>
}
{/* {assetType === 'conveyor' && <ConveyorMechanics />}
{assetType === 'vehicle' && <VehicleMechanics />}
{assetType === 'roboticArm' && <RoboticArmMechanics />} */}
</>
}
</div>
</>
);
};
export default EventProperties;
export default EventProperties;

View File

@ -0,0 +1,22 @@
import React from "react";
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
const DelayAction: React.FC = () => {
return (
<>
<InputWithDropDown
label="Delay"
value="0.5"
min={0}
step={0.1}
defaultValue="0.5"
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
</>
);
};
export default DelayAction;

View File

@ -4,17 +4,6 @@ import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
const DespawnAction: React.FC = () => {
return (
<>
<InputWithDropDown
label="Delay"
value=""
min={0}
step={0.1}
max={10}
defaultValue="0"
activeOption="s"
onClick={() => {}}
onChange={(value) => console.log(value)}
/>
</>
);
};

View File

@ -1,8 +1,84 @@
import React from 'react'
import { useEffect, useState } from 'react'
import InputWithDropDown from '../../../../../ui/inputs/InputWithDropDown'
import DelayAction from '../actions/DelayAction'
import RenameInput from '../../../../../ui/inputs/RenameInput'
import LabledDropdown from '../../../../../ui/inputs/LabledDropdown'
import DespawnAction from '../actions/DespawnAction'
import SwapAction from '../actions/SwapAction'
import SpawnAction from '../actions/SpawnAction'
import DefaultAction from '../actions/DefaultAction'
import Trigger from '../trigger/Trigger'
import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
function ConveyorMechanics() {
const [activeOption, setActiveOption] = useState("default");
const [selectedPointData, setSelectedPointData] = useState<PointsScheme | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
useEffect(() => {
if (selectedEventData) {
const point = getPointByUuid(selectedProduct.productId, selectedEventData?.data.modelUuid, selectedEventData?.selectedPoint);
if (point && 'action' in point) {
setSelectedPointData(point as PointsScheme & { action: { actionType: string } });
setActiveOption((point as PointsScheme & { action: { actionType: string } }).action.actionType);
}
}
}, [selectedProduct, selectedEventData])
const availableActions = {
defaultOption: "default",
options: ["default", "spawn", "swap", "delay", "despawn"],
};
return (
<>
{selectedEventData &&
<>
<div key={selectedPointData?.uuid} className="global-props">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value="0.5"
min={0}
step={0.1}
defaultValue={"0.5"}
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
</div>
</div>
</div>
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput value="Action Name" />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={selectedPointData && 'action' in selectedPointData
? (selectedPointData as PointsScheme & { action: { actionType: string } }).action.actionType
: "default"}
options={availableActions.options}
onSelect={(option) => setActiveOption(option)}
/>
{activeOption === "default" && <DefaultAction />}
{activeOption === "spawn" && <SpawnAction />}
{activeOption === "swap" && <SwapAction />}
{activeOption === "despawn" && <DespawnAction />}
{activeOption === "delay" && <DelayAction />}
</div>
</div>
<div className="tirgger">
<Trigger />
</div>
</>
}
</>
)
}

View File

@ -1,8 +1,170 @@
import React from 'react'
import { useEffect, useRef, useState } from 'react'
import * as THREE from 'three';
import InputWithDropDown from '../../../../../ui/inputs/InputWithDropDown'
import RenameInput from '../../../../../ui/inputs/RenameInput'
import LabledDropdown from '../../../../../ui/inputs/LabledDropdown'
import Trigger from '../trigger/Trigger'
import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import { AddIcon, RemoveIcon, ResizeHeightIcon } from '../../../../../icons/ExportCommonIcons'
import { handleResize } from '../../../../../../functions/handleResizePannel'
import PickAndPlaceAction from '../actions/PickAndPlaceAction'
function RoboticArmMechanics() {
const actionsContainerRef = useRef<HTMLDivElement>(null);
const [activeOption, setActiveOption] = useState("pickAndPlace");
const [selectedItem, setSelectedItem] = useState<{ item: { uuid: string; name: string } | null; }>({ item: null });
const { selectedEventData } = useSelectedEventData();
const { getEventByModelUuid, addAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const availableActions = {
defaultOption: "pickAndPlace",
options: ["pickAndPlace"]
};
const [actions, setActions] = useState<{ uuid: string; name: string }[]>([]);
useEffect(() => {
const event = getCurrentEventData();
const actionList = getActionList(event as RoboticArmEventSchema);
setActions(actionList);
if (actionList.length > 0 && !selectedItem.item) {
setSelectedItem({ item: actionList[0] });
}
}, [selectedEventData, selectedProduct]);
const getCurrentEventData = () => {
if (!selectedEventData?.data || !selectedProduct) return null;
return getEventByModelUuid(selectedProduct.productId, selectedEventData.data.modelUuid) || null;
};
const getActionList = (event: RoboticArmEventSchema) => {
if (!event || !('point' in event)) return [];
return event.point.actions.flatMap(
(action) =>
action.triggers.map((trigger) => ({
uuid: trigger.triggerUuid,
name: trigger.triggerName,
}))
) || [];
};
const handleActionToggle = (actionUuid: string) => {
const action = actions.find(a => a.uuid === actionUuid);
if (action) {
setSelectedItem({ item: action });
}
};
const handleAddAction = () => {
if (selectedEventData) {
const newEvent = {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action ${actions.length + 1}`,
actionType: "pickAndPlace" as const,
process: {
startPoint: null as [number, number, number] | null,
endPoint: null as [number, number, number] | null
},
triggers: [] as TriggerSchema[]
}
addAction(
selectedProduct.productId,
selectedEventData?.data.modelUuid,
selectedEventData?.selectedPoint,
newEvent
)
}
};
const handleDeleteAction = (actionUuid: string) => {
};
return (
<>
<div className="global-props">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value="0.5"
min={0}
step={0.1}
defaultValue={'0.5'}
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
</div>
</div>
</div>
<div className="actions-list-container">
<div className="actions">
<div className="header">
<div className="header-value">Actions</div>
<div className="add-button" onClick={() => handleAddAction()}>
<AddIcon /> Add
</div>
</div>
<div
className="lists-main-container"
ref={actionsContainerRef}
style={{ height: "120px" }}
>
<div className="list-container">
{actions.map((action) => (
<div
key={action.uuid}
className={`list-item ${selectedItem.item?.uuid === action.uuid ? "active" : ""}`}
>
<div
className="value"
onClick={() => handleActionToggle(action.uuid)}
>
<RenameInput value={action.name} />
</div>
{actions.length > 1 && (
<div
className="remove-button"
onClick={() => handleDeleteAction(action.uuid)}
>
<RemoveIcon />
</div>
)}
</div>
))}
</div>
<div
className="resize-icon"
id="action-resize"
onMouseDown={(e) => handleResize(e, actionsContainerRef)}
>
<ResizeHeightIcon />
</div>
</div>
</div>
</div>
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput value={selectedItem.item?.name || "Action Name"} />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={availableActions.defaultOption}
options={availableActions.options}
onSelect={(option) => setActiveOption(option)}
/>
{activeOption === "pickAndPlace" && <PickAndPlaceAction />}
</div>
</div>
<div className="tirgger">
<Trigger />
</div>
</>
)
}

View File

@ -1,8 +1,76 @@
import React from 'react'
import { useEffect, useState } from 'react'
import InputWithDropDown from '../../../../../ui/inputs/InputWithDropDown'
import RenameInput from '../../../../../ui/inputs/RenameInput'
import LabledDropdown from '../../../../../ui/inputs/LabledDropdown'
import Trigger from '../trigger/Trigger'
import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import TravelAction from '../actions/TravelAction'
function VehicleMechanics() {
const [activeOption, setActiveOption] = useState("default");
const [selectedPointData, setSelectedPointData] = useState<PointsScheme | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
useEffect(() => {
if (selectedEventData) {
const point = getPointByUuid(selectedProduct.productId, selectedEventData?.data.modelUuid, selectedEventData?.selectedPoint);
if (point && 'action' in point) {
setSelectedPointData(point as PointsScheme & { action: { actionType: string } });
setActiveOption((point as PointsScheme & { action: { actionType: string } }).action.actionType);
}
}
}, [selectedProduct, selectedEventData])
const availableActions = {
defaultOption: "travel",
options: ["travel"],
};
return (
<>
{selectedEventData &&
<>
<div className="global-props">
<div className="property-list-container">
<div className="property-item">
<InputWithDropDown
label="Speed"
value="0.5"
min={0}
step={0.1}
defaultValue={"0.5"}
max={10}
activeOption="s"
onClick={() => { }}
onChange={(value) => console.log(value)}
/>
</div>
</div>
</div>
<div className="selected-actions-details">
<div className="selected-actions-header">
<RenameInput value="Action Name" />
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={selectedPointData && 'action' in selectedPointData
? (selectedPointData as PointsScheme & { action: { actionType: string } }).action.actionType
: "default"}
options={availableActions.options}
onSelect={(option) => setActiveOption(option)}
/>
{activeOption === "travel" && <TravelAction />}
</div>
</div>
<div className="tirgger">
<Trigger />
</div>
</>
}
</>
)
}

View File

@ -1,14 +0,0 @@
import React from 'react'
import IKInstance from './ikInstance/ikInstance';
function IkInstances() {
return (
<>
<IKInstance />
</>
)
}
export default IkInstances;