Refactor simulation types and update imports
- Renamed simulation type imports from `simulation` to `simulationTypes` across multiple files for consistency. - Consolidated simulation type definitions into a new `simulationTypes.d.ts` file. - Updated relevant components (e.g., `ArmBot`, `IkInstances`, `PathConnector`, etc.) to use the new type definitions. - Removed the old `simulation.d.ts` file to clean up the codebase. - Adjusted function signatures and state management in components to align with the new type structure.
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useRef, useMemo, useCallback, useState } from "react";
|
|||||||
import { InfoIcon, AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons";
|
import { InfoIcon, AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||||
import { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
import { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
||||||
import * as SimulationTypes from '../../../../types/simulation';
|
import * as SimulationTypes from '../../../../types/simulationTypes';
|
||||||
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
||||||
import { handleResize } from "../../../../functions/handleResizePannel";
|
import { handleResize } from "../../../../functions/handleResizePannel";
|
||||||
|
|
||||||
@@ -224,19 +224,28 @@ const ArmBotMechanics: React.FC = () => {
|
|||||||
}, [selectedPoint, selectedProcessIndex, handleProcessChange]);
|
}, [selectedPoint, selectedProcessIndex, handleProcessChange]);
|
||||||
|
|
||||||
const handleTriggerSelect = useCallback((displayName: string, index: number) => {
|
const handleTriggerSelect = useCallback((displayName: string, index: number) => {
|
||||||
const selected = connectedTriggers.find(t => t.displayName === displayName);
|
const availableOptions = getFilteredTriggerOptions(index);
|
||||||
|
const selectedDisplayIndex = availableOptions.indexOf(displayName);
|
||||||
|
|
||||||
|
const filteredTriggers = connectedTriggers.filter(trigger =>
|
||||||
|
!selectedPoint?.actions.processes
|
||||||
|
?.filter((_, i) => i !== index)
|
||||||
|
.map(p => p.triggerId)
|
||||||
|
.includes(trigger.uuid)
|
||||||
|
);
|
||||||
|
|
||||||
|
const selected = filteredTriggers[selectedDisplayIndex];
|
||||||
|
|
||||||
if (!selected || !selectedPoint?.actions.processes) return;
|
if (!selected || !selectedPoint?.actions.processes) return;
|
||||||
|
|
||||||
const oldProcess = selectedPoint.actions.processes[index];
|
const oldProcess = selectedPoint.actions.processes[index];
|
||||||
|
|
||||||
const updatedProcesses = [...selectedPoint.actions.processes];
|
const updatedProcesses = [...selectedPoint.actions.processes];
|
||||||
|
|
||||||
// Only reset start/end if new trigger invalidates them (your logic can expand this)
|
|
||||||
updatedProcesses[index] = {
|
updatedProcesses[index] = {
|
||||||
...oldProcess,
|
...oldProcess,
|
||||||
triggerId: selected.uuid,
|
triggerId: selected.uuid,
|
||||||
startPoint: oldProcess.startPoint || "", // preserve if exists
|
startPoint: oldProcess.startPoint || "",
|
||||||
endPoint: oldProcess.endPoint || "" // preserve if exists
|
endPoint: oldProcess.endPoint || ""
|
||||||
};
|
};
|
||||||
|
|
||||||
handleProcessChange(updatedProcesses);
|
handleProcessChange(updatedProcesses);
|
||||||
@@ -298,8 +307,10 @@ const ArmBotMechanics: React.FC = () => {
|
|||||||
<InputWithDropDown
|
<InputWithDropDown
|
||||||
key={`speed-${selectedPoint.uuid}`}
|
key={`speed-${selectedPoint.uuid}`}
|
||||||
label="ArmBot Speed"
|
label="ArmBot Speed"
|
||||||
|
min={0.1}
|
||||||
|
step={0.1}
|
||||||
value={selectedPoint.actions.speed.toString()}
|
value={selectedPoint.actions.speed.toString()}
|
||||||
onChange={(value) => handleSpeedChange(parseInt(value))}
|
onChange={(value) => handleSpeedChange(parseFloat(value))}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
useSocketStore,
|
useSocketStore,
|
||||||
} from "../../../../store/store";
|
} from "../../../../store/store";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
import InputToggle from "../../../ui/inputs/InputToggle";
|
import InputToggle from "../../../ui/inputs/InputToggle";
|
||||||
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||||
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ 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 { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
import { useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
||||||
import * as SimulationTypes from '../../../../types/simulation';
|
import * as SimulationTypes from '../../../../types/simulationTypes';
|
||||||
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
||||||
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useRef, useMemo } 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 { useEditingPoint, useEyeDropMode, usePreviewPosition, useSelectedActionSphere, useSimulationStates, useSocketStore } from "../../../../store/store";
|
||||||
import * as SimulationTypes from '../../../../types/simulation';
|
import * as SimulationTypes from '../../../../types/simulationTypes';
|
||||||
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";
|
import LabeledButton from "../../../ui/inputs/LabledButton";
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import RenameInput from "./RenameInput";
|
|||||||
type InputWithDropDownProps = {
|
type InputWithDropDownProps = {
|
||||||
label: string;
|
label: string;
|
||||||
value: string;
|
value: string;
|
||||||
min?: number
|
min?: number;
|
||||||
|
step?: number;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
options?: string[]; // Array of dropdown options
|
options?: string[]; // Array of dropdown options
|
||||||
activeOption?: string; // The currently active dropdown option
|
activeOption?: string; // The currently active dropdown option
|
||||||
@@ -18,6 +19,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
|||||||
label,
|
label,
|
||||||
value,
|
value,
|
||||||
min,
|
min,
|
||||||
|
step,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
options,
|
options,
|
||||||
activeOption,
|
activeOption,
|
||||||
@@ -45,6 +47,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
|||||||
<div className="input default" id={separatedWords}>
|
<div className="input default" id={separatedWords}>
|
||||||
<input
|
<input
|
||||||
min={min}
|
min={min}
|
||||||
|
step={step}
|
||||||
type="number"
|
type="number"
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { toast } from 'react-toastify';
|
|||||||
import TempLoader from './tempLoader';
|
import TempLoader from './tempLoader';
|
||||||
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
|
import { retrieveGLTF, storeGLTF } from '../../../../utils/indexDB/idbUtils';
|
||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { toast } from 'react-toastify';
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
|
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
|
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
|
||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
import { getFloorAssets } from '../../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
|
import { getFloorAssets } from '../../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import * as THREE from 'three';
|
|||||||
import * as CONSTANTS from '../../../types/world/worldConstants';
|
import * as CONSTANTS from '../../../types/world/worldConstants';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import * as Types from "../../../types/world/worldTypes";
|
import * as Types from "../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../..//types/simulation";
|
import * as SimulationTypes from "../../../types/simulationTypes";
|
||||||
import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils';
|
import { initializeDB, retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils';
|
||||||
import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi';
|
import { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi';
|
||||||
import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
|
import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
|
||||||
@@ -228,7 +228,6 @@ function processEventData(item: SimulationTypes.EventData, setSimulationStates:
|
|||||||
} else if (item.eventData?.type === 'StaticMachine') {
|
} else if (item.eventData?.type === 'StaticMachine') {
|
||||||
|
|
||||||
const data: any = item.eventData;
|
const data: any = item.eventData;
|
||||||
item.eventData.points.position = [0, 1.5, 1]
|
|
||||||
data.modeluuid = item.modeluuid;
|
data.modeluuid = item.modeluuid;
|
||||||
data.modelName = item.modelname;
|
data.modelName = item.modelname;
|
||||||
data.position = item.position;
|
data.position = item.position;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
|
|||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
|
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
|
||||||
|
|
||||||
const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
|
const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
|
|||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||||
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
|
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
|
|||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
|
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
|
||||||
|
|
||||||
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
|
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
|
|||||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||||
|
|
||||||
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
|
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import BoundingBox from "./boundingBoxHelper";
|
|||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
|
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../../../../types/simulation";
|
import * as SimulationTypes from "../../../../types/simulationTypes";
|
||||||
|
|
||||||
import DuplicationControls from "./duplicationControls";
|
import DuplicationControls from "./duplicationControls";
|
||||||
import CopyPasteControls from "./copyPasteControls";
|
import CopyPasteControls from "./copyPasteControls";
|
||||||
@@ -199,6 +199,7 @@ const SelectionControls: React.FC = () => {
|
|||||||
setDuplicatedObjects([]);
|
setDuplicatedObjects([]);
|
||||||
setSelectedAssets([]);
|
setSelectedAssets([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateBackend = async (updatedPaths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
|
const updateBackend = async (updatedPaths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
|
||||||
if (updatedPaths.length === 0) return;
|
if (updatedPaths.length === 0) return;
|
||||||
const email = localStorage.getItem("email");
|
const email = localStorage.getItem("email");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { useThree } from "@react-three/fiber";
|
import { useThree } from "@react-three/fiber";
|
||||||
import useModuleStore from "../../../store/useModuleStore";
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
import { useSimulationStates } from "../../../store/store";
|
import { useSimulationStates } from "../../../store/store";
|
||||||
import * as SimulationTypes from '../../../types/simulation';
|
import * as SimulationTypes from '../../../types/simulationTypes';
|
||||||
import { ArmbotInstances } from "./ArmBotInstances";
|
import { ArmbotInstances } from "./ArmBotInstances";
|
||||||
|
|
||||||
interface ArmBotState {
|
interface ArmBotState {
|
||||||
@@ -12,14 +12,18 @@ interface ArmBotState {
|
|||||||
status: string;
|
status: string;
|
||||||
material: string;
|
material: string;
|
||||||
triggerId: string;
|
triggerId: string;
|
||||||
connections: any
|
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArmBot: React.FC = () => {
|
interface ArmBotProps {
|
||||||
|
armBots: ArmBotState[];
|
||||||
|
setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArmBot = ({ armBots, setArmBots }: ArmBotProps) => {
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const { scene } = useThree();
|
const { scene } = useThree();
|
||||||
const { simulationStates } = useSimulationStates();
|
const { simulationStates } = useSimulationStates();
|
||||||
const [armBots, setArmBots] = useState<ArmBotState[]>([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filtered = simulationStates.filter((s): s is SimulationTypes.ArmBotEventsSchema => s.type === "ArmBot");
|
const filtered = simulationStates.filter((s): s is SimulationTypes.ArmBotEventsSchema => s.type === "ArmBot");
|
||||||
@@ -30,7 +34,7 @@ const ArmBot: React.FC = () => {
|
|||||||
status: "idle",
|
status: "idle",
|
||||||
material: "default",
|
material: "default",
|
||||||
triggerId: '',
|
triggerId: '',
|
||||||
connections: bot.points.connections
|
actions: bot.points.actions
|
||||||
}));
|
}));
|
||||||
setArmBots(initialStates);
|
setArmBots(initialStates);
|
||||||
}, [simulationStates]);
|
}, [simulationStates]);
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
import IkInstances from "./IkInstances";
|
import IkInstances from "./IkInstances";
|
||||||
import armModel from "../../../assets/gltf-glb/rigged/ik_arm_4.glb";
|
import armModel from "../../../assets/gltf-glb/rigged/ik_arm_4.glb";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useThree } from "@react-three/fiber";
|
||||||
|
import { Vector3 } from "three";
|
||||||
|
|
||||||
|
interface Process {
|
||||||
|
triggerId: string;
|
||||||
|
startPoint?: Vector3;
|
||||||
|
endPoint?: Vector3;
|
||||||
|
speed: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface ArmBotState {
|
interface ArmBotState {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
@@ -8,18 +18,65 @@ interface ArmBotState {
|
|||||||
status: string;
|
status: string;
|
||||||
material: string;
|
material: string;
|
||||||
triggerId: string;
|
triggerId: string;
|
||||||
connections: any
|
actions: {
|
||||||
|
uuid: string;
|
||||||
|
name: string;
|
||||||
|
speed: number;
|
||||||
|
processes: {
|
||||||
|
triggerId: string;
|
||||||
|
startPoint: string;
|
||||||
|
endPoint: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ArmbotInstancesProps {
|
interface ArmbotInstancesProps {
|
||||||
index: number;
|
index: number;
|
||||||
armBot: ArmBotState;
|
armBot: ArmBotState;
|
||||||
setArmBots: (armBots: ArmBotState[]) => void;
|
setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ArmbotInstances: React.FC<ArmbotInstancesProps> = ({ index, armBot, setArmBots }) => {
|
export const ArmbotInstances: React.FC<ArmbotInstancesProps> = ({ index, armBot, setArmBots }) => {
|
||||||
|
const { scene } = useThree();
|
||||||
|
const [processes, setProcesses] = useState<Process[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if (armBot.actions.processes.length > 0) {
|
||||||
|
const mappedProcesses = armBot.actions.processes.map((process) => {
|
||||||
|
return {
|
||||||
|
triggerId: process.triggerId,
|
||||||
|
startPoint: scene.getObjectByProperty('uuid', process.startPoint)?.getWorldPosition(new Vector3()),
|
||||||
|
endPoint: scene.getObjectByProperty('uuid', process.endPoint)?.getWorldPosition(new Vector3()),
|
||||||
|
speed: armBot.actions.speed
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setProcesses(mappedProcesses);
|
||||||
|
} else {
|
||||||
|
setProcesses([]);
|
||||||
|
}
|
||||||
|
}, [armBot, scene]);
|
||||||
|
|
||||||
|
const updateArmBotStatus = (status: string) => {
|
||||||
|
setArmBots((prevArmBots) => {
|
||||||
|
return prevArmBots.map(bot => {
|
||||||
|
if (bot.uuid === armBot.uuid) {
|
||||||
|
return { ...bot, status };
|
||||||
|
}
|
||||||
|
return bot;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IkInstances key={index} modelUrl={armModel} position={armBot.position} rotation={armBot.rotation} />
|
<IkInstances
|
||||||
|
key={index}
|
||||||
|
uuid={armBot.uuid}
|
||||||
|
modelUrl={armModel}
|
||||||
|
position={armBot.position}
|
||||||
|
rotation={armBot.rotation}
|
||||||
|
processes={processes}
|
||||||
|
updateArmBotStatus={updateArmBotStatus}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1,96 +1,245 @@
|
|||||||
import { useEffect, useMemo, useState } from "react";
|
import { useEffect, useMemo, useState, useRef } from "react";
|
||||||
import { useFrame } from "@react-three/fiber";
|
import { useFrame } from "@react-three/fiber";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||||
|
|
||||||
|
type IKAnimationControllerProps = {
|
||||||
|
ikSolver: any;
|
||||||
|
process: {
|
||||||
|
triggerId: string;
|
||||||
|
startPoint: THREE.Vector3;
|
||||||
|
endPoint: THREE.Vector3;
|
||||||
|
speed: number;
|
||||||
|
}[];
|
||||||
|
selectedTrigger: string;
|
||||||
|
targetBoneName: string;
|
||||||
|
uuid: string;
|
||||||
|
logStatus: (status: string) => void;
|
||||||
|
groupRef: React.RefObject<THREE.Group>;
|
||||||
|
updateArmBotStatus: (status: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
const IKAnimationController = ({
|
const IKAnimationController = ({
|
||||||
ikSolver,
|
ikSolver,
|
||||||
process,
|
process,
|
||||||
selectedTrigger,
|
selectedTrigger,
|
||||||
targetBoneName,
|
targetBoneName,
|
||||||
}: {
|
uuid,
|
||||||
ikSolver: any;
|
logStatus,
|
||||||
process: {
|
groupRef,
|
||||||
trigger: string;
|
updateArmBotStatus
|
||||||
start: THREE.Vector3;
|
}: IKAnimationControllerProps) => {
|
||||||
end: THREE.Vector3;
|
|
||||||
speed: number;
|
|
||||||
}[];
|
|
||||||
selectedTrigger: string;
|
|
||||||
targetBoneName: string;
|
|
||||||
}) => {
|
|
||||||
const [progress, setProgress] = useState(0);
|
const [progress, setProgress] = useState(0);
|
||||||
|
const [initialProgress, setInitialProgress] = useState(0);
|
||||||
|
const [needsInitialMovement, setNeedsInitialMovement] = useState(true);
|
||||||
|
const [isInitializing, setIsInitializing] = useState(true);
|
||||||
const restSpeed = 0.1;
|
const restSpeed = 0.1;
|
||||||
|
const restPosition = new THREE.Vector3(0, 2, 1.6);
|
||||||
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
|
||||||
|
// Track previous states for comparison
|
||||||
|
const prevStateRef = useRef({
|
||||||
|
isInitializing: true,
|
||||||
|
needsInitialMovement: true,
|
||||||
|
selectedTrigger: "",
|
||||||
|
progress: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
// Track previous status for comparison
|
||||||
|
const prevStatusRef = useRef("");
|
||||||
|
|
||||||
|
const initialCurveRef = useRef<THREE.CatmullRomCurve3 | null>(null);
|
||||||
|
const initialStartPositionRef = useRef<THREE.Vector3 | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setProgress(0);
|
setProgress(0);
|
||||||
}, [selectedTrigger]);
|
}, [selectedTrigger]);
|
||||||
|
|
||||||
const processedCurves = useMemo(() => {
|
useEffect(() => {
|
||||||
const restPosition = new THREE.Vector3(0.2, 2.3, 1.6);
|
if (ikSolver) {
|
||||||
return process.map((p) => {
|
const targetBone = ikSolver.mesh.skeleton.bones.find(
|
||||||
const mid = new THREE.Vector3(
|
(b: any) => b.name === targetBoneName
|
||||||
(p.start.x + p.end.x) / 1,
|
|
||||||
Math.max(p.start.y, p.end.y) + 0.8,
|
|
||||||
(p.start.z + p.end.z) / 0.9
|
|
||||||
);
|
);
|
||||||
const points = [
|
if (targetBone) {
|
||||||
restPosition.clone(),
|
initialStartPositionRef.current = targetBone.position.clone();
|
||||||
p.start.clone(),
|
calculateInitialCurve(targetBone.position);
|
||||||
mid.clone(),
|
logStatus(`[Arm ${uuid}] Initializing IK system, starting position: ${targetBone.position.toArray()}`);
|
||||||
p.end.clone(),
|
}
|
||||||
restPosition.clone(),
|
}
|
||||||
];
|
}, [ikSolver]);
|
||||||
const curve = new THREE.CatmullRomCurve3(points);
|
|
||||||
const restToStartDist = points[0].distanceTo(points[1]);
|
|
||||||
const startToEndDist = points[1].distanceTo(points[3]);
|
|
||||||
const endToRestDist = points[3].distanceTo(points[4]);
|
|
||||||
|
|
||||||
const totalDist = restToStartDist + startToEndDist + endToRestDist;
|
// Log state changes
|
||||||
const restToStartRange = [0, restToStartDist / totalDist];
|
useEffect(() => {
|
||||||
const startToEndRange = [
|
const prev = prevStateRef.current;
|
||||||
restToStartRange[1],
|
|
||||||
restToStartRange[1] + startToEndDist / totalDist,
|
|
||||||
];
|
|
||||||
const endToRestRange = [startToEndRange[1], 1];
|
|
||||||
|
|
||||||
return {
|
if (prev.isInitializing !== isInitializing) {
|
||||||
trigger: p.trigger,
|
if (!isInitializing) {
|
||||||
curve,
|
logStatus(`[Arm ${uuid}] Completed initialization, now at rest position`);
|
||||||
speed: p.speed,
|
}
|
||||||
restToStartRange,
|
}
|
||||||
startToEndRange,
|
|
||||||
endToRestRange,
|
if (prev.needsInitialMovement !== needsInitialMovement && !needsInitialMovement) {
|
||||||
};
|
logStatus(`[Arm ${uuid}] Reached rest position, ready for animation`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev.selectedTrigger !== selectedTrigger) {
|
||||||
|
logStatus(`[Arm ${uuid}] Processing new trigger: ${selectedTrigger}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update previous state
|
||||||
|
prevStateRef.current = {
|
||||||
|
isInitializing,
|
||||||
|
needsInitialMovement,
|
||||||
|
selectedTrigger,
|
||||||
|
progress
|
||||||
|
};
|
||||||
|
}, [isInitializing, needsInitialMovement, selectedTrigger, progress]);
|
||||||
|
|
||||||
|
const calculateInitialCurve = (startPosition: THREE.Vector3) => {
|
||||||
|
const direction = new THREE.Vector3().subVectors(restPosition, startPosition);
|
||||||
|
const distance = direction.length();
|
||||||
|
direction.normalize();
|
||||||
|
|
||||||
|
const perpendicular = new THREE.Vector3(-direction.z, 0, direction.x).normalize();
|
||||||
|
|
||||||
|
const midHeight = 0.5;
|
||||||
|
const tiltAmount = 1;
|
||||||
|
const mid = new THREE.Vector3()
|
||||||
|
.addVectors(startPosition, restPosition)
|
||||||
|
.multiplyScalar(0.5)
|
||||||
|
.add(perpendicular.clone().multiplyScalar(distance * 0.3 * tiltAmount))
|
||||||
|
.add(new THREE.Vector3(0, midHeight, 0));
|
||||||
|
|
||||||
|
initialCurveRef.current = new THREE.CatmullRomCurve3([
|
||||||
|
startPosition,
|
||||||
|
new THREE.Vector3().lerpVectors(startPosition, mid, 0.33),
|
||||||
|
mid,
|
||||||
|
new THREE.Vector3().lerpVectors(mid, restPosition, 0.66),
|
||||||
|
restPosition
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const processedCurves = useMemo(() => {
|
||||||
|
return process.map((p) => {
|
||||||
|
const tempLift = 0.5;
|
||||||
|
const localStart = groupRef.current?.worldToLocal(p.startPoint.clone().add(new THREE.Vector3(0, tempLift, 0)));
|
||||||
|
const localEnd = groupRef.current?.worldToLocal(p.endPoint.clone().add(new THREE.Vector3(0, tempLift, 0)));
|
||||||
|
|
||||||
|
if (localStart && localEnd) {
|
||||||
|
|
||||||
|
const mid = new THREE.Vector3(
|
||||||
|
(localStart.x + localEnd.x) / 1,
|
||||||
|
Math.max(localStart.y, localEnd.y) + 0.8,
|
||||||
|
(localStart.z + localEnd.z) / 0.9
|
||||||
|
);
|
||||||
|
|
||||||
|
const points = [
|
||||||
|
restPosition.clone(),
|
||||||
|
localStart.clone(),
|
||||||
|
mid.clone(),
|
||||||
|
localEnd.clone(),
|
||||||
|
restPosition.clone(),
|
||||||
|
];
|
||||||
|
const curve = new THREE.CatmullRomCurve3(points);
|
||||||
|
const restToStartDist = points[0].distanceTo(points[1]);
|
||||||
|
const startToEndDist = points[1].distanceTo(points[3]);
|
||||||
|
const endToRestDist = points[3].distanceTo(points[4]);
|
||||||
|
|
||||||
|
const totalDist = restToStartDist + startToEndDist + endToRestDist;
|
||||||
|
const restToStartRange = [0, restToStartDist / totalDist];
|
||||||
|
const startToEndRange = [
|
||||||
|
restToStartRange[1],
|
||||||
|
restToStartRange[1] + startToEndDist / totalDist,
|
||||||
|
];
|
||||||
|
const endToRestRange = [startToEndRange[1], 1];
|
||||||
|
|
||||||
|
return {
|
||||||
|
trigger: p.triggerId,
|
||||||
|
curve,
|
||||||
|
speed: p.speed,
|
||||||
|
restToStartRange,
|
||||||
|
startToEndRange,
|
||||||
|
endToRestRange,
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, [process]);
|
}, [process, groupRef]);
|
||||||
|
|
||||||
const activeCurve = useMemo(() => {
|
const activeCurve = useMemo(() => {
|
||||||
return processedCurves.find((c) => c.trigger === selectedTrigger);
|
return processedCurves.find((c) => c?.trigger === selectedTrigger);
|
||||||
}, [processedCurves, selectedTrigger]);
|
}, [processedCurves, selectedTrigger]);
|
||||||
|
|
||||||
|
// Initial movement to rest position
|
||||||
useFrame((_, delta) => {
|
useFrame((_, delta) => {
|
||||||
if (!ikSolver || !activeCurve) return;
|
if (!ikSolver || !needsInitialMovement || !isInitializing || !initialCurveRef.current) return;
|
||||||
|
|
||||||
const { curve, speed, startToEndRange } = activeCurve;
|
const targetBone = ikSolver.mesh.skeleton.bones.find(
|
||||||
|
(b: any) => b.name === targetBoneName
|
||||||
|
);
|
||||||
|
if (!targetBone) return;
|
||||||
|
|
||||||
|
setInitialProgress((prev) => {
|
||||||
|
const next = prev + delta * 0.5;
|
||||||
|
if (next >= 1) {
|
||||||
|
targetBone.position.copy(restPosition);
|
||||||
|
setNeedsInitialMovement(false);
|
||||||
|
setIsInitializing(false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
targetBone.position.copy(initialCurveRef.current!.getPoint(next));
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
|
||||||
|
ikSolver.update();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Main animation loop
|
||||||
|
useFrame((_, delta) => {
|
||||||
|
if (!ikSolver || !activeCurve || isInitializing) return;
|
||||||
|
|
||||||
|
const { curve, speed, restToStartRange, startToEndRange, endToRestRange } = activeCurve;
|
||||||
const targetBone = ikSolver.mesh.skeleton.bones.find(
|
const targetBone = ikSolver.mesh.skeleton.bones.find(
|
||||||
(b: any) => b.name === targetBoneName
|
(b: any) => b.name === targetBoneName
|
||||||
);
|
);
|
||||||
if (!targetBone) return;
|
if (!targetBone) return;
|
||||||
|
|
||||||
let currentSpeed = restSpeed;
|
let currentSpeed = restSpeed;
|
||||||
if (progress >= startToEndRange[0] && progress < startToEndRange[1]) {
|
let currentStatus = "idle"; // Default status
|
||||||
|
|
||||||
|
// Determine current phase and status
|
||||||
|
if (progress < restToStartRange[1]) {
|
||||||
|
currentSpeed = restSpeed;
|
||||||
|
currentStatus = "moving"; // Moving to start point
|
||||||
|
} else if (progress >= startToEndRange[0] && progress < startToEndRange[1]) {
|
||||||
currentSpeed = speed;
|
currentSpeed = speed;
|
||||||
|
currentStatus = "moving"; // Moving between points
|
||||||
|
} else if (progress >= endToRestRange[0] && progress < 1) {
|
||||||
|
currentSpeed = restSpeed;
|
||||||
|
currentStatus = "moving"; // Returning to rest
|
||||||
|
} else if (progress >= 1) {
|
||||||
|
currentStatus = "idle"; // Completed cycle
|
||||||
}
|
}
|
||||||
|
|
||||||
setProgress((prev) => {
|
// Update status when it changes
|
||||||
const next = prev + delta * currentSpeed;
|
if (prevStatusRef.current !== currentStatus) {
|
||||||
if (next >= 1) {
|
updateArmBotStatus(currentStatus);
|
||||||
targetBone.position.copy(curve.getPoint(1));
|
prevStatusRef.current = currentStatus;
|
||||||
return 1;
|
}
|
||||||
}
|
|
||||||
targetBone.position.copy(curve.getPoint(next));
|
// Only update progress if we're not already at the end
|
||||||
return next;
|
if (progress < 1) {
|
||||||
});
|
setProgress((prev) => {
|
||||||
|
const next = prev + delta * currentSpeed;
|
||||||
|
return Math.min(next, 1); // Cap at 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update bone position based on progress
|
||||||
|
if (progress < 1) {
|
||||||
|
targetBone.position.copy(curve.getPoint(progress));
|
||||||
|
} else {
|
||||||
|
targetBone.position.copy(curve.getPoint(1));
|
||||||
|
}
|
||||||
|
|
||||||
ikSolver.update();
|
ikSolver.update();
|
||||||
});
|
});
|
||||||
@@ -98,4 +247,4 @@ const IKAnimationController = ({
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default IKAnimationController;
|
export default IKAnimationController;
|
||||||
@@ -1,43 +1,40 @@
|
|||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useEffect, useMemo, useRef, useState } from "react";
|
import { useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useLoader } from "@react-three/fiber";
|
import { useFrame, useLoader } from "@react-three/fiber";
|
||||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
||||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||||
import { clone } from "three/examples/jsm/utils/SkeletonUtils";
|
import { clone } from "three/examples/jsm/utils/SkeletonUtils";
|
||||||
import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver";
|
import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver";
|
||||||
import IKAnimationController from "./IKAnimationController";
|
import IKAnimationController from "./IKAnimationController";
|
||||||
|
import { TransformControls } from "@react-three/drei";
|
||||||
|
|
||||||
const IkInstances = ({ modelUrl, position, rotation }: { modelUrl: string; position: [number, number, number]; rotation: [number, number, number]; }) => {
|
const IkInstances = ({
|
||||||
|
uuid,
|
||||||
|
modelUrl,
|
||||||
|
processes,
|
||||||
|
position,
|
||||||
|
rotation,
|
||||||
|
updateArmBotStatus
|
||||||
|
}: {
|
||||||
|
uuid: string;
|
||||||
|
modelUrl: string;
|
||||||
|
processes: any;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
updateArmBotStatus: (status: string) => void;
|
||||||
|
}) => {
|
||||||
const [ikSolver, setIkSolver] = useState<any>(null);
|
const [ikSolver, setIkSolver] = useState<any>(null);
|
||||||
const [selectedTrigger, setSelectedTrigger] = useState<string>("idle");
|
const [selectedTrigger, setSelectedTrigger] = useState<string>("");
|
||||||
const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
|
const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
|
||||||
const draco = new DRACOLoader();
|
const draco = new DRACOLoader();
|
||||||
draco.setDecoderPath(
|
draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/");
|
||||||
"https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/"
|
|
||||||
);
|
|
||||||
loader.setDRACOLoader(draco);
|
loader.setDRACOLoader(draco);
|
||||||
});
|
});
|
||||||
const cloned = useMemo(() => clone(gltf.scene), [gltf]);
|
const cloned = useMemo(() => clone(gltf.scene), [gltf]);
|
||||||
const groupRef = useRef<any>(null);
|
const groupRef = useRef<any>(null);
|
||||||
const [selectedArm, setSelectedArm] = useState<THREE.Group>();
|
|
||||||
const targetBoneName = "Target";
|
const targetBoneName = "Target";
|
||||||
const skinnedMeshName = "link_0";
|
const skinnedMeshName = "link_0";
|
||||||
|
|
||||||
const process = useMemo(() => [
|
|
||||||
{
|
|
||||||
trigger: "Trigger1",
|
|
||||||
start: new THREE.Vector3(-0.75, 1.5, -2.2),
|
|
||||||
end: new THREE.Vector3(0, 1.2, 2.2),
|
|
||||||
speed: 0.25,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
trigger: "Trigger2",
|
|
||||||
start: new THREE.Vector3(0, 1.2, 2.2),
|
|
||||||
end: new THREE.Vector3(0.75, 1.5, -2.2),
|
|
||||||
speed: 0.22,
|
|
||||||
}
|
|
||||||
], []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!gltf) return;
|
if (!gltf) return;
|
||||||
const OOI: any = {};
|
const OOI: any = {};
|
||||||
@@ -86,7 +83,7 @@ const IkInstances = ({ modelUrl, position, rotation }: { modelUrl: string; posit
|
|||||||
}, [gltf]);
|
}, [gltf]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const triggers = ['Trigger1', 'Trigger2'];
|
const triggers = ["9f4a9b8b-e60d-4754-8c99-d71979da0e71", "b77b4f0a-ce55-4fe0-a181-a43ab3d01c83"];
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
|
||||||
const cycleTriggers = setInterval(() => {
|
const cycleTriggers = setInterval(() => {
|
||||||
@@ -97,30 +94,33 @@ const IkInstances = ({ modelUrl, position, rotation }: { modelUrl: string; posit
|
|||||||
return () => clearInterval(cycleTriggers);
|
return () => clearInterval(cycleTriggers);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const logStatus = (status: string) => {
|
||||||
|
// console.log(status);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<group
|
<group
|
||||||
ref={groupRef}
|
ref={groupRef}
|
||||||
onClick={(e) => {
|
position={position}
|
||||||
e.stopPropagation();
|
rotation={rotation}
|
||||||
setSelectedArm(groupRef.current?.getObjectByName(targetBoneName))
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<primitive
|
<primitive
|
||||||
object={cloned}
|
object={cloned}
|
||||||
position={position}
|
|
||||||
rotation={rotation}
|
|
||||||
scale={[1, 1, 1]}
|
scale={[1, 1, 1]}
|
||||||
name={`arm-bot`}
|
name={`arm-bot`}
|
||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
<IKAnimationController
|
<IKAnimationController
|
||||||
ikSolver={ikSolver}
|
ikSolver={ikSolver}
|
||||||
process={process}
|
process={processes}
|
||||||
selectedTrigger={selectedTrigger}
|
selectedTrigger={selectedTrigger}
|
||||||
targetBoneName={targetBoneName}
|
targetBoneName={targetBoneName}
|
||||||
|
uuid={uuid}
|
||||||
|
logStatus={logStatus}
|
||||||
|
groupRef={groupRef}
|
||||||
|
updateArmBotStatus={updateArmBotStatus}
|
||||||
/>
|
/>
|
||||||
{/* {selectedArm && <TransformControls object={selectedArm} />} */}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useFrame, useThree } from '@react-three/fiber';
|
|||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import * as Types from '../../../types/world/worldTypes';
|
import * as Types from '../../../types/world/worldTypes';
|
||||||
import * as SimulationTypes from '../../../types/simulation';
|
import * as SimulationTypes from '../../../types/simulationTypes';
|
||||||
import { QuadraticBezierLine } from '@react-three/drei';
|
import { QuadraticBezierLine } from '@react-three/drei';
|
||||||
import { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore } from '../../../store/store';
|
import { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore } from '../../../store/store';
|
||||||
import useModuleStore from '../../../store/useModuleStore';
|
import useModuleStore from '../../../store/useModuleStore';
|
||||||
@@ -982,7 +982,6 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
setSimulationStates(updatedStates);
|
setSimulationStates(updatedStates);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group name='simulationConnectionGroup' visible={!isPlaying}>
|
<group name='simulationConnectionGroup' visible={!isPlaying}>
|
||||||
{simulationStates.flatMap(path => {
|
{simulationStates.flatMap(path => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import * as SimulationTypes from "../../../types/simulation";
|
import * as SimulationTypes from "../../../types/simulationTypes";
|
||||||
import { useRef, useState, useEffect, useMemo } from "react";
|
import { useRef, useState, useEffect, useMemo } from "react";
|
||||||
import { Sphere, TransformControls } from "@react-three/drei";
|
import { Sphere, TransformControls } from "@react-three/drei";
|
||||||
import {
|
import {
|
||||||
@@ -66,45 +66,6 @@ function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateSimulationPaths = () => {
|
|
||||||
if (!selectedActionSphere) return;
|
|
||||||
|
|
||||||
const updatedPaths = simulationStates.map((path) => {
|
|
||||||
if (path.type === "Conveyor") {
|
|
||||||
return {
|
|
||||||
...path,
|
|
||||||
points: path.points.map((point) =>
|
|
||||||
point.uuid === selectedActionSphere.points.uuid
|
|
||||||
? {
|
|
||||||
...point,
|
|
||||||
position: [
|
|
||||||
selectedActionSphere.points.position.x,
|
|
||||||
selectedActionSphere.points.position.y,
|
|
||||||
selectedActionSphere.points.position.z,
|
|
||||||
],
|
|
||||||
rotation: [
|
|
||||||
selectedActionSphere.points.rotation.x,
|
|
||||||
selectedActionSphere.points.rotation.y,
|
|
||||||
selectedActionSphere.points.rotation.z,
|
|
||||||
],
|
|
||||||
}
|
|
||||||
: point
|
|
||||||
),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}) as SimulationTypes.ConveyorEventsSchema[];
|
|
||||||
|
|
||||||
const updatedPath = updatedPaths.find(
|
|
||||||
(path) => path.type === "Conveyor" && path.points.some((point) => point.uuid === selectedActionSphere.points.uuid)
|
|
||||||
);
|
|
||||||
|
|
||||||
// console.log("Updated Path:", updatedPath);
|
|
||||||
|
|
||||||
setSimulationStates(updatedPaths);
|
|
||||||
};
|
|
||||||
|
|
||||||
useFrame(() => {
|
useFrame(() => {
|
||||||
if (eyeDropMode) {
|
if (eyeDropMode) {
|
||||||
raycaster.setFromCamera(pointer, camera);
|
raycaster.setFromCamera(pointer, camera);
|
||||||
@@ -445,7 +406,6 @@ function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObjec
|
|||||||
ref={transformRef}
|
ref={transformRef}
|
||||||
object={selectedActionSphere.points}
|
object={selectedActionSphere.points}
|
||||||
mode={transformMode}
|
mode={transformMode}
|
||||||
onMouseUp={updateSimulationPaths}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
@@ -458,7 +458,7 @@ import { useThree } from "@react-three/fiber";
|
|||||||
import {
|
import {
|
||||||
ConveyorEventsSchema,
|
ConveyorEventsSchema,
|
||||||
VehicleEventsSchema,
|
VehicleEventsSchema,
|
||||||
} from "../../../types/simulation";
|
} from "../../../types/simulationTypes";
|
||||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||||
|
|
||||||
// Type definitions
|
// Type definitions
|
||||||
|
|||||||
@@ -7,39 +7,50 @@ import ProcessContainer from "./process/processContainer";
|
|||||||
import Agv from "../builder/agv/agv";
|
import Agv from "../builder/agv/agv";
|
||||||
import ArmBot from "./armbot/ArmBot";
|
import ArmBot from "./armbot/ArmBot";
|
||||||
|
|
||||||
|
interface ArmBotState {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
status: string;
|
||||||
|
material: string;
|
||||||
|
triggerId: string;
|
||||||
|
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
|
||||||
|
}
|
||||||
|
|
||||||
function Simulation() {
|
function Simulation() {
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const pathsGroupRef = useRef() as React.MutableRefObject<THREE.Group>;
|
const pathsGroupRef = useRef() as React.MutableRefObject<THREE.Group>;
|
||||||
const [processes, setProcesses] = useState<any[]>([]);
|
const [armBots, setArmBots] = useState<ArmBotState[]>([]);
|
||||||
const agvRef = useRef([]);
|
const [processes, setProcesses] = useState<any[]>([]);
|
||||||
const MaterialRef = useRef([]);
|
const agvRef = useRef([]);
|
||||||
|
const MaterialRef = useRef([]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
{activeModule === "simulation" && (
|
|
||||||
<>
|
<>
|
||||||
<PathCreation pathsGroupRef={pathsGroupRef} />
|
{activeModule === "simulation" && (
|
||||||
|
<>
|
||||||
|
<PathCreation pathsGroupRef={pathsGroupRef} />
|
||||||
|
|
||||||
<PathConnector pathsGroupRef={pathsGroupRef} />
|
<PathConnector pathsGroupRef={pathsGroupRef} />
|
||||||
|
|
||||||
<ProcessContainer
|
<ProcessContainer
|
||||||
processes={processes}
|
processes={processes}
|
||||||
setProcesses={setProcesses}
|
setProcesses={setProcesses}
|
||||||
agvRef={agvRef}
|
agvRef={agvRef}
|
||||||
MaterialRef={MaterialRef}
|
MaterialRef={MaterialRef}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Agv
|
<Agv
|
||||||
processes={processes}
|
processes={processes}
|
||||||
agvRef={agvRef}
|
agvRef={agvRef}
|
||||||
MaterialRef={MaterialRef}
|
MaterialRef={MaterialRef}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<ArmBot armBots={armBots} setArmBots={setArmBots} />
|
||||||
</>
|
</>
|
||||||
)}
|
);
|
||||||
<ArmBot />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Simulation;
|
export default Simulation;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import * as Types from "../types/world/worldTypes";
|
import * as Types from "../types/world/worldTypes";
|
||||||
import * as SimulationTypes from "../types/simulation";
|
import * as SimulationTypes from "../types/simulationTypes";
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { io } from "socket.io-client";
|
import { io } from "socket.io-client";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user