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:
Jerald-Golden-B 2025-04-15 14:15:39 +05:30
parent ca3028985f
commit 5cef9bdb8a
23 changed files with 383 additions and 189 deletions

View File

@ -2,7 +2,7 @@ import React, { useRef, useMemo, useCallback, useState } from "react";
import { InfoIcon, AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
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 { handleResize } from "../../../../functions/handleResizePannel";
@ -224,19 +224,28 @@ const ArmBotMechanics: React.FC = () => {
}, [selectedPoint, selectedProcessIndex, handleProcessChange]);
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;
const oldProcess = selectedPoint.actions.processes[index];
const updatedProcesses = [...selectedPoint.actions.processes];
// Only reset start/end if new trigger invalidates them (your logic can expand this)
updatedProcesses[index] = {
...oldProcess,
triggerId: selected.uuid,
startPoint: oldProcess.startPoint || "", // preserve if exists
endPoint: oldProcess.endPoint || "" // preserve if exists
startPoint: oldProcess.startPoint || "",
endPoint: oldProcess.endPoint || ""
};
handleProcessChange(updatedProcesses);
@ -298,8 +307,10 @@ const ArmBotMechanics: React.FC = () => {
<InputWithDropDown
key={`speed-${selectedPoint.uuid}`}
label="ArmBot Speed"
min={0.1}
step={0.1}
value={selectedPoint.actions.speed.toString()}
onChange={(value) => handleSpeedChange(parseInt(value))}
onChange={(value) => handleSpeedChange(parseFloat(value))}
/>
<div className="actions">

View File

@ -17,7 +17,7 @@ import {
useSocketStore,
} from "../../../../store/store";
import * as THREE from "three";
import * as SimulationTypes from "../../../../types/simulation";
import * as SimulationTypes from "../../../../types/simulationTypes";
import InputToggle from "../../../ui/inputs/InputToggle";
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";

View File

@ -2,7 +2,7 @@ import React, { useRef, useMemo, useCallback } from "react";
import { InfoIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
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 { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";

View File

@ -2,7 +2,7 @@ import React, { useRef, useMemo } from "react";
import { InfoIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
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 { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
import LabeledButton from "../../../ui/inputs/LabledButton";

View File

@ -4,7 +4,8 @@ import RenameInput from "./RenameInput";
type InputWithDropDownProps = {
label: string;
value: string;
min?: number
min?: number;
step?: number;
defaultValue?: string;
options?: string[]; // Array of dropdown options
activeOption?: string; // The currently active dropdown option
@ -18,6 +19,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
label,
value,
min,
step,
defaultValue,
options,
activeOption,
@ -45,6 +47,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
<div className="input default" id={separatedWords}>
<input
min={min}
step={step}
type="number"
defaultValue={value}
onChange={(e) => {

View File

@ -5,7 +5,7 @@ import { toast } from 'react-toastify';
import TempLoader from './tempLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
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 { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
import { Socket } from 'socket.io-client';

View File

@ -2,7 +2,7 @@ import { toast } from 'react-toastify';
import * as THREE from 'three';
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 { Socket } from 'socket.io-client';
import { getFloorAssets } from '../../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';

View File

@ -5,7 +5,7 @@ import * as THREE from 'three';
import * as CONSTANTS from '../../../types/world/worldConstants';
import { toast } from 'react-toastify';
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 { getCamera } from '../../../services/factoryBuilder/camera/getCameraApi';
import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi';
@ -228,7 +228,6 @@ function processEventData(item: SimulationTypes.EventData, setSimulationStates:
} else if (item.eventData?.type === 'StaticMachine') {
const data: any = item.eventData;
item.eventData.points.position = [0, 1.5, 1]
data.modeluuid = item.modeluuid;
data.modelName = item.modelname;
data.position = item.position;

View File

@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
import { toast } from "react-toastify";
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
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";
const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, selectionGroup, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) => {

View File

@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
import { toast } from "react-toastify";
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
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 { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";

View File

@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
import { toast } from "react-toastify";
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";
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {

View File

@ -5,7 +5,7 @@ import { useFloorItems, useSelectedAssets, useSimulationStates, useSocketStore,
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
import { toast } from "react-toastify";
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";
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {

View File

@ -8,7 +8,7 @@ import BoundingBox from "./boundingBoxHelper";
import { toast } from "react-toastify";
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
import * as Types from "../../../../types/world/worldTypes";
import * as SimulationTypes from "../../../../types/simulation";
import * as SimulationTypes from "../../../../types/simulationTypes";
import DuplicationControls from "./duplicationControls";
import CopyPasteControls from "./copyPasteControls";
@ -199,6 +199,7 @@ const SelectionControls: React.FC = () => {
setDuplicatedObjects([]);
setSelectedAssets([]);
};
const updateBackend = async (updatedPaths: (SimulationTypes.ConveyorEventsSchema | SimulationTypes.VehicleEventsSchema | SimulationTypes.StaticMachineEventsSchema | SimulationTypes.ArmBotEventsSchema)[]) => {
if (updatedPaths.length === 0) return;
const email = localStorage.getItem("email");

View File

@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
import { useThree } from "@react-three/fiber";
import useModuleStore from "../../../store/useModuleStore";
import { useSimulationStates } from "../../../store/store";
import * as SimulationTypes from '../../../types/simulation';
import * as SimulationTypes from '../../../types/simulationTypes';
import { ArmbotInstances } from "./ArmBotInstances";
interface ArmBotState {
@ -12,14 +12,18 @@ interface ArmBotState {
status: string;
material: 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 { scene } = useThree();
const { simulationStates } = useSimulationStates();
const [armBots, setArmBots] = useState<ArmBotState[]>([]);
useEffect(() => {
const filtered = simulationStates.filter((s): s is SimulationTypes.ArmBotEventsSchema => s.type === "ArmBot");
@ -30,7 +34,7 @@ const ArmBot: React.FC = () => {
status: "idle",
material: "default",
triggerId: '',
connections: bot.points.connections
actions: bot.points.actions
}));
setArmBots(initialStates);
}, [simulationStates]);

View File

@ -1,5 +1,15 @@
import IkInstances from "./IkInstances";
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 {
uuid: string;
@ -8,18 +18,65 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
connections: any
actions: {
uuid: string;
name: string;
speed: number;
processes: {
triggerId: string;
startPoint: string;
endPoint: string;
}[];
};
}
interface ArmbotInstancesProps {
index: number;
armBot: ArmBotState;
setArmBots: (armBots: ArmBotState[]) => void;
setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>;
}
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 (
<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}
/>
);
};

View File

@ -1,96 +1,245 @@
import { useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useState, useRef } from "react";
import { useFrame } from "@react-three/fiber";
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 = ({
ikSolver,
process,
selectedTrigger,
targetBoneName,
}: {
ikSolver: any;
process: {
trigger: string;
start: THREE.Vector3;
end: THREE.Vector3;
speed: number;
}[];
selectedTrigger: string;
targetBoneName: string;
}) => {
uuid,
logStatus,
groupRef,
updateArmBotStatus
}: IKAnimationControllerProps) => {
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 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(() => {
setProgress(0);
}, [selectedTrigger]);
const processedCurves = useMemo(() => {
const restPosition = new THREE.Vector3(0.2, 2.3, 1.6);
return process.map((p) => {
const mid = new THREE.Vector3(
(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
useEffect(() => {
if (ikSolver) {
const targetBone = ikSolver.mesh.skeleton.bones.find(
(b: any) => b.name === targetBoneName
);
const points = [
restPosition.clone(),
p.start.clone(),
mid.clone(),
p.end.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]);
if (targetBone) {
initialStartPositionRef.current = targetBone.position.clone();
calculateInitialCurve(targetBone.position);
logStatus(`[Arm ${uuid}] Initializing IK system, starting position: ${targetBone.position.toArray()}`);
}
}
}, [ikSolver]);
const totalDist = restToStartDist + startToEndDist + endToRestDist;
const restToStartRange = [0, restToStartDist / totalDist];
const startToEndRange = [
restToStartRange[1],
restToStartRange[1] + startToEndDist / totalDist,
];
const endToRestRange = [startToEndRange[1], 1];
// Log state changes
useEffect(() => {
const prev = prevStateRef.current;
return {
trigger: p.trigger,
curve,
speed: p.speed,
restToStartRange,
startToEndRange,
endToRestRange,
};
if (prev.isInitializing !== isInitializing) {
if (!isInitializing) {
logStatus(`[Arm ${uuid}] Completed initialization, now at rest position`);
}
}
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(() => {
return processedCurves.find((c) => c.trigger === selectedTrigger);
return processedCurves.find((c) => c?.trigger === selectedTrigger);
}, [processedCurves, selectedTrigger]);
// Initial movement to rest position
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(
(b: any) => b.name === targetBoneName
);
if (!targetBone) return;
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;
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) => {
const next = prev + delta * currentSpeed;
if (next >= 1) {
targetBone.position.copy(curve.getPoint(1));
return 1;
}
targetBone.position.copy(curve.getPoint(next));
return next;
});
// Update status when it changes
if (prevStatusRef.current !== currentStatus) {
updateArmBotStatus(currentStatus);
prevStatusRef.current = currentStatus;
}
// Only update progress if we're not already at the end
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();
});
@ -98,4 +247,4 @@ const IKAnimationController = ({
return null;
};
export default IKAnimationController;
export default IKAnimationController;

View File

@ -1,43 +1,40 @@
import * as THREE from "three";
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 { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { clone } from "three/examples/jsm/utils/SkeletonUtils";
import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver";
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 [selectedTrigger, setSelectedTrigger] = useState<string>("idle");
const [selectedTrigger, setSelectedTrigger] = useState<string>("");
const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
const draco = new DRACOLoader();
draco.setDecoderPath(
"https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/"
);
draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/");
loader.setDRACOLoader(draco);
});
const cloned = useMemo(() => clone(gltf.scene), [gltf]);
const groupRef = useRef<any>(null);
const [selectedArm, setSelectedArm] = useState<THREE.Group>();
const targetBoneName = "Target";
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(() => {
if (!gltf) return;
const OOI: any = {};
@ -86,7 +83,7 @@ const IkInstances = ({ modelUrl, position, rotation }: { modelUrl: string; posit
}, [gltf]);
useEffect(() => {
const triggers = ['Trigger1', 'Trigger2'];
const triggers = ["9f4a9b8b-e60d-4754-8c99-d71979da0e71", "b77b4f0a-ce55-4fe0-a181-a43ab3d01c83"];
let index = 0;
const cycleTriggers = setInterval(() => {
@ -97,30 +94,33 @@ const IkInstances = ({ modelUrl, position, rotation }: { modelUrl: string; posit
return () => clearInterval(cycleTriggers);
}, []);
const logStatus = (status: string) => {
// console.log(status);
}
return (
<>
<group
ref={groupRef}
onClick={(e) => {
e.stopPropagation();
setSelectedArm(groupRef.current?.getObjectByName(targetBoneName))
}}
position={position}
rotation={rotation}
>
<primitive
object={cloned}
position={position}
rotation={rotation}
scale={[1, 1, 1]}
name={`arm-bot`}
/>
</group>
<IKAnimationController
ikSolver={ikSolver}
process={process}
process={processes}
selectedTrigger={selectedTrigger}
targetBoneName={targetBoneName}
uuid={uuid}
logStatus={logStatus}
groupRef={groupRef}
updateArmBotStatus={updateArmBotStatus}
/>
{/* {selectedArm && <TransformControls object={selectedArm} />} */}
</>
);
};

View File

@ -2,7 +2,7 @@ import { useFrame, useThree } from '@react-three/fiber';
import React, { useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
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 { useDeleteTool, useIsConnecting, useRenderDistance, useSimulationStates, useSocketStore } from '../../../store/store';
import useModuleStore from '../../../store/useModuleStore';
@ -982,7 +982,6 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec
setSimulationStates(updatedStates);
};
return (
<group name='simulationConnectionGroup' visible={!isPlaying}>
{simulationStates.flatMap(path => {

View File

@ -1,5 +1,5 @@
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 { Sphere, TransformControls } from "@react-three/drei";
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(() => {
if (eyeDropMode) {
raycaster.setFromCamera(pointer, camera);
@ -445,7 +406,6 @@ function PathCreation({ pathsGroupRef, }: { pathsGroupRef: React.MutableRefObjec
ref={transformRef}
object={selectedActionSphere.points}
mode={transformMode}
onMouseUp={updateSimulationPaths}
/>
)}
</group>

View File

@ -458,7 +458,7 @@ import { useThree } from "@react-three/fiber";
import {
ConveyorEventsSchema,
VehicleEventsSchema,
} from "../../../types/simulation";
} from "../../../types/simulationTypes";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
// Type definitions

View File

@ -7,39 +7,50 @@ import ProcessContainer from "./process/processContainer";
import Agv from "../builder/agv/agv";
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() {
const { activeModule } = useModuleStore();
const pathsGroupRef = useRef() as React.MutableRefObject<THREE.Group>;
const [processes, setProcesses] = useState<any[]>([]);
const agvRef = useRef([]);
const MaterialRef = useRef([]);
const { activeModule } = useModuleStore();
const pathsGroupRef = useRef() as React.MutableRefObject<THREE.Group>;
const [armBots, setArmBots] = useState<ArmBotState[]>([]);
const [processes, setProcesses] = useState<any[]>([]);
const agvRef = useRef([]);
const MaterialRef = useRef([]);
return (
<>
{activeModule === "simulation" && (
return (
<>
<PathCreation pathsGroupRef={pathsGroupRef} />
{activeModule === "simulation" && (
<>
<PathCreation pathsGroupRef={pathsGroupRef} />
<PathConnector pathsGroupRef={pathsGroupRef} />
<PathConnector pathsGroupRef={pathsGroupRef} />
<ProcessContainer
processes={processes}
setProcesses={setProcesses}
agvRef={agvRef}
MaterialRef={MaterialRef}
/>
<ProcessContainer
processes={processes}
setProcesses={setProcesses}
agvRef={agvRef}
MaterialRef={MaterialRef}
/>
<Agv
processes={processes}
agvRef={agvRef}
MaterialRef={MaterialRef}
/>
<Agv
processes={processes}
agvRef={agvRef}
MaterialRef={MaterialRef}
/>
</>
)}
<ArmBot armBots={armBots} setArmBots={setArmBots} />
</>
)}
<ArmBot />
</>
);
);
}
export default Simulation;

View File

@ -1,6 +1,6 @@
import * as THREE from "three";
import * as Types from "../types/world/worldTypes";
import * as SimulationTypes from "../types/simulation";
import * as SimulationTypes from "../types/simulationTypes";
import { create } from "zustand";
import { io } from "socket.io-client";