feat: Enhance vehicle simulation with draggable path points and interactive controls

This commit is contained in:
2025-07-05 11:16:31 +05:30
parent 3f59f5d2dd
commit 5a0978560c
11 changed files with 996 additions and 134 deletions

47
app/package-lock.json generated
View File

@@ -2026,7 +2026,7 @@
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"devOptional": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
@@ -2038,7 +2038,7 @@
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"devOptional": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
@@ -4180,6 +4180,25 @@
"url": "https://github.com/sponsors/gregberge"
}
},
"node_modules/@testing-library/dom": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
"integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
"@types/aria-query": "^5.0.1",
"aria-query": "5.3.0",
"chalk": "^4.1.0",
"dom-accessibility-api": "^0.5.9",
"lz-string": "^1.5.0",
"pretty-format": "^27.0.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@testing-library/jest-dom": {
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz",
@@ -4291,25 +4310,25 @@
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"dev": true
"devOptional": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
"devOptional": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
"devOptional": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
"devOptional": true
},
"node_modules/@turf/along": {
"version": "7.2.0",
@@ -9063,7 +9082,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
"devOptional": true
},
"node_modules/cross-env": {
"version": "7.0.3",
@@ -9940,7 +9959,7 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"devOptional": true,
"engines": {
"node": ">=0.3.1"
}
@@ -15324,7 +15343,7 @@
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
"devOptional": true
},
"node_modules/makeerror": {
"version": "1.0.12",
@@ -20801,7 +20820,7 @@
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"devOptional": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -20844,7 +20863,7 @@
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"dev": true,
"devOptional": true,
"dependencies": {
"acorn": "^8.11.0"
},
@@ -20856,7 +20875,7 @@
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
"devOptional": true
},
"node_modules/tsconfig-paths": {
"version": "3.15.0",
@@ -21352,7 +21371,7 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
"devOptional": true
},
"node_modules/v8-to-istanbul": {
"version": "8.1.1",
@@ -22411,7 +22430,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"devOptional": true,
"engines": {
"node": ">=6"
}

View File

@@ -38,9 +38,11 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
const handleCreateNewProject = async () => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken")
console.log('refreshToken: ', refreshToken);
try {
const projectId = generateProjectId();
useSocketStore.getState().initializeSocket(email, organization, token);
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
//API for creating new Project
// const project = await createProject(
@@ -56,7 +58,8 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
organization: organization,
projectUuid: projectId,
};
console.log('projectSocket: ', projectSocket);
if (projectSocket) {
const handleResponse = (data: any) => {
if (data.message === "Project created successfully") {

View File

@@ -27,7 +27,6 @@ const EventProperties: React.FC = () => {
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
useEffect(() => {
const event = getCurrentEventData();
setCurrentEventData(event);

View File

@@ -14,6 +14,7 @@ import { useProductContext } from "../../../../../../modules/simulation/products
import { useParams } from "react-router-dom";
import { useVersionContext } from "../../../../../../modules/builder/version/versionContext";
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
import { useSelectedPath } from "../../../../../../store/builder/store";
function VehicleMechanics() {
const [activeOption, setActiveOption] = useState<"default" | "travel">("default");
@@ -27,6 +28,7 @@ function VehicleMechanics() {
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
const { selectedPath, setSelectedPath } = useSelectedPath();
useEffect(() => {
if (selectedEventData && selectedEventData.data.type === "vehicle") {
@@ -290,9 +292,34 @@ function VehicleMechanics() {
type={"Vehicle"}
/>
</div>
<div style={{ display: "flex", gap: "10px", flexDirection: "column", alignItems: "center" }}>
<button style={{
backgroundColor: "#6f42c1",
color: "#f3f3fd",
borderRadius: "15px",
height: "30px",
width: "150px",
border: "none",
cursor: "pointer",
padding: "0 5px",
}} onClick={() => setSelectedPath("auto")}>Auto Generate Path</button>
<button style={{
backgroundColor: "#6f42c1",
color: "#f3f3fd",
borderRadius: "15px",
height: "30px",
width: "150px",
border: "none",
cursor: "pointer",
padding: "0 5px",
}} onClick={() => setSelectedPath("manual")}>Create Path</button>
</div>
</section>
</>
)}
)
}
</>
);
}

View File

@@ -15,6 +15,7 @@ import {
useToolMode,
useRenderDistance,
useLimitDistance,
useLoadingProgress,
} from "../../store/builder/store";
////////// 3D Function Imports //////////
@@ -56,6 +57,7 @@ export default function Builder() {
const { projectId } = useParams();
const { setHoveredPoint, setHoveredLine } = useBuilderStore();
const { userId, organization } = getUserData();
const { loadingProgress } = useLoadingProgress();
useEffect(() => {
if (!toggleView) {
@@ -115,8 +117,7 @@ export default function Builder() {
<CalculateAreaGroup />
<NavMesh />
{loadingProgress == 0 && <NavMesh />}
<DxfFile />
<LayoutImage />

View File

@@ -0,0 +1,420 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { Canvas, useThree, useFrame, ThreeEvent } from '@react-three/fiber';
import { Line, OrbitControls } from '@react-three/drei';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useActiveTool, useSelectedPath } from '../../../../../store/builder/store';
interface InteractivePointsProps {
agvUuid: string;
}
export default function InteractivePoints({ agvUuid }: InteractivePointsProps) {
const { gl, scene, raycaster } = useThree();
const [points, setPoints] = useState<[number, number, number][]>([]);
const { isPaused } = usePauseButtonStore();
const { isPlaying } = usePlayButtonStore();
const { speed } = useAnimationPlaySpeed();
// const raycaster = useRef(new THREE.Raycaster());
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // XZ plane
const progressRef = useRef<number>(0);
const { selectedPath } = useSelectedPath();
const lastTimeRef = useRef(performance.now());
const [isAnyDragging, setIsAnyDragging] = useState<string>("");
const { activeTool } = useActiveTool();
const hasClicked = useRef(false);
useFrame(() => {
if (!isPlaying) return
const now = performance.now();
const delta = (now - lastTimeRef.current) / 1000;
lastTimeRef.current = now;
const object = scene.getObjectByProperty('uuid', agvUuid);
if (!object || points.length < 2) return;
if (isPaused) return;
let totalDistance = 0;
const distances = [];
let accumulatedDistance = 0;
let index = 0;
const rotationSpeed = 1;
for (let i = 0; i < points.length - 1; i++) {
const start = new THREE.Vector3(...points[i]);
const end = new THREE.Vector3(...points[i + 1]);
const segmentDistance = start.distanceTo(end);
distances.push(segmentDistance);
totalDistance += segmentDistance;
}
while (index < distances.length && progressRef.current > accumulatedDistance + distances[index]) {
accumulatedDistance += distances[index];
index++;
}
if (index < distances.length) {
const start = new THREE.Vector3(...points[index]);
const end = new THREE.Vector3(...points[index + 1]);
const segmentDistance = distances[index];
const currentDirection = new THREE.Vector3().subVectors(end, start).normalize();
const targetAngle = Math.atan2(currentDirection.x, currentDirection.z);
const currentAngle = object.rotation.y;
let angleDifference = targetAngle - currentAngle;
if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI;
if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI;
const maxRotationStep = (rotationSpeed * speed * 2) * delta;
object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep);
const isAligned = Math.abs(angleDifference) < 0.01;
if (isAligned) {
progressRef.current += delta * (speed * 2);
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
const position = start.clone().lerp(end, t);
object.position.copy(position);
}
}
});
const downPosition = useRef<{ x: number; y: number } | null>(null);
// const handleMouseDown = (e: MouseEvent) => {
// downPosition.current = { x: e.clientX, y: e.clientY };
// };
// const handleClick = useCallback((e: MouseEvent) => {
// if (
// !downPosition.current ||
// Math.abs(downPosition.current.x - e.clientX) > 2 ||
// Math.abs(downPosition.current.y - e.clientY) > 2
// ) {
// return;
// }
// const intersection = new THREE.Vector3();
// if (raycaster.ray.intersectPlane(plane.current, intersection) && activeTool !== "pen") {
// const pointArray = intersection.toArray() as [number, number, number];
// console.log('pointArray: ', pointArray);
// setPoints((prev) => [...prev, pointArray]);
// console.log("points created");
// }
// }, [activeTool, raycaster]);
const handleMouseDown = useCallback((e: MouseEvent) => {
hasClicked.current = false;
downPosition.current = { x: e.clientX, y: e.clientY };
}, []);
const handleClick = useCallback((e: MouseEvent) => {
if (hasClicked.current) return;
hasClicked.current = true;
if (
!downPosition.current ||
Math.abs(downPosition.current.x - e.clientX) > 2 ||
Math.abs(downPosition.current.y - e.clientY) > 2
) {
return;
}
const intersection = new THREE.Vector3();
if (raycaster.ray.intersectPlane(plane.current, intersection) && activeTool !== "pen") {
const pointArray = intersection.toArray() as [number, number, number];
// ✅ Check if this point already exists
const alreadyExists = points.some((p) =>
Math.abs(p[0] - pointArray[0]) < 0.01 &&
Math.abs(p[1] - pointArray[1]) < 0.01 &&
Math.abs(p[2] - pointArray[2]) < 0.01
);
if (!alreadyExists) {
console.log("pointArray: ", pointArray);
setPoints((prev) => [...prev, pointArray]);
console.log("points created");
}
}
}, [activeTool, raycaster, points]);
// const handleClick = useCallback((e: MouseEvent) => {
// if (
// !downPosition.current ||
// Math.abs(downPosition.current.x - e.clientX) > 2 ||
// Math.abs(downPosition.current.y - e.clientY) > 2
// ) {
// return;
// }
// const intersection = new THREE.Vector3();
// if (raycaster.ray.intersectPlane(plane.current, intersection) && activeTool !== "pen") {
// const pointArray = intersection.toArray() as [number, number, number];
// console.log('pointArray: ', pointArray);
// setPoints((prev) => [...prev, pointArray]);
// console.log("points created");
// }
// }, [activeTool, raycaster]);
useEffect(() => {
if (isPlaying) return;
const domElement = gl.domElement;
domElement.addEventListener('mousedown', handleMouseDown);
domElement.addEventListener('mouseup', handleClick);
return () => {
domElement.removeEventListener('mousedown', handleMouseDown);
domElement.removeEventListener('mouseup', handleClick);
;
};
}, [isPlaying, handleClick, handleMouseDown]);
const updatePoint = (index: number, pos: THREE.Vector3) => {
const updated = [...points];
updated[index] = pos.toArray() as [number, number, number];
setPoints(updated);
};
return (
<>
{selectedPath === "manual" &&
<group>
{points.length > 0 && (
<group >
{points.map((pos, i) =>
(<React.Fragment key={i}>
<DraggableSphere
key={i}
index={i}
position={new THREE.Vector3(...pos)}
onMove={updatePoint}
isAnyDragging={isAnyDragging}
setIsAnyDragging={setIsAnyDragging}
/>
</React.Fragment>)
)}
</group >
)
}
{points && (
points.map((pos, i) => {
if (i < points.length - 1) {
return (
<DraggableLineSegment
key={i}
index={i}
start={new THREE.Vector3(...points[i])}
end={new THREE.Vector3(...points[i + 1])}
updatePoints={(i0, p0, i1, p1) => {
const updated = [...points];
updated[i0] = p0.toArray() as [number, number, number];
updated[i1] = p1.toArray() as [number, number, number];
setPoints(updated);
}}
isAnyDragging={isAnyDragging}
setIsAnyDragging={setIsAnyDragging}
/>
);
}
return null;
})
)}
</group>
}
</>
);
}
// function DraggableSphere({
// index,
// position,
// onMove,
// }: {
// index: number;
// position: THREE.Vector3;
// onMove: (index: number, pos: THREE.Vector3) => void;
// }) {
// const meshRef = useRef<THREE.Mesh>(null);
// const { gl, controls, raycaster } = useThree();
// const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); // XZ plane
// const isDragging = useRef(false);
// const { activeTool } = useActiveTool();
// const onPointerDown = (e: ThreeEvent<PointerEvent>) => {
// if (activeTool !== 'pen') return;
// isDragging.current = true;
// gl.domElement.style.cursor = 'grabbing';
// if (controls) {
// (controls as any).enabled = false;
// }
// };
// const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
// if (!isDragging.current || activeTool !== 'pen') return;
// const intersect = new THREE.Vector3();
// if (raycaster.ray.intersectPlane(plane, intersect)) {
// meshRef.current!.position.copy(intersect);
// onMove(index, intersect);
// }
// };
// const onPointerUp = () => {
// if (activeTool !== 'pen') return;
// isDragging.current = false;
// gl.domElement.style.cursor = 'default';
// if (controls) {
// (controls as any).enabled = true;
// }
// };
// return (
// <mesh
// ref={meshRef}
// position={position}
// onPointerDown={onPointerDown}
// onPointerMove={onPointerMove}
// onPointerUp={onPointerUp}
// onPointerMissed={onPointerUp}
// >
// <sphereGeometry args={[0.2, 16, 16]} />
// <meshStandardMaterial color="red" />
// </mesh>
// );
// }
function DraggableSphere({
index,
position,
onMove,
isAnyDragging,
setIsAnyDragging,
}: {
index: number;
position: THREE.Vector3;
onMove: (index: number, pos: THREE.Vector3) => void;
isAnyDragging: string;
setIsAnyDragging: (val: string) => void;
}) {
const meshRef = useRef<THREE.Mesh>(null);
const { gl, controls, raycaster } = useThree();
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
const { activeTool } = useActiveTool();
const onPointerDown = (e: ThreeEvent<PointerEvent>) => {
e.stopPropagation()
if (activeTool !== 'pen') return;
setIsAnyDragging("point");
gl.domElement.style.cursor = 'grabbing';
if (controls) (controls as any).enabled = false;
};
const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
if (isAnyDragging !== "point" || activeTool !== 'pen') return;
const intersect = new THREE.Vector3();
if (raycaster.ray.intersectPlane(plane, intersect)) {
meshRef.current!.position.copy(intersect);
onMove(index, intersect);
}
};
const onPointerUp = () => {
if (activeTool !== 'pen') return;
setIsAnyDragging("");
gl.domElement.style.cursor = 'default';
if (controls) (controls as any).enabled = true;
};
return (
<mesh
ref={meshRef}
position={position}
onPointerDown={onPointerDown}
onPointerMove={onPointerMove}
onPointerUp={onPointerUp}
onPointerMissed={onPointerUp}
>
<sphereGeometry args={[0.2, 16, 16]} />
<meshStandardMaterial color="red" />
</mesh>
);
}
function DraggableLineSegment({
index,
start,
end,
updatePoints,
isAnyDragging,
setIsAnyDragging,
}: {
index: number;
start: THREE.Vector3;
end: THREE.Vector3;
updatePoints: (i0: number, p0: THREE.Vector3, i1: number, p1: THREE.Vector3) => void;
isAnyDragging: string;
setIsAnyDragging: (val: string) => void;
}) {
const { gl, raycaster, controls } = useThree();
const { activeTool } = useActiveTool();
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
const dragStart = useRef<THREE.Vector3 | null>(null);
const onPointerDown = () => {
if (activeTool !== 'pen' || isAnyDragging) return;
setIsAnyDragging("line");
gl.domElement.style.cursor = 'grabbing';
if (controls) (controls as any).enabled = false;
};
const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
if (isAnyDragging !== "line" || activeTool !== 'pen') return;
const intersect = new THREE.Vector3();
if (raycaster.ray.intersectPlane(plane, intersect)) {
if (!dragStart.current) dragStart.current = intersect.clone();
const offset = new THREE.Vector3().subVectors(intersect, dragStart.current);
const newStart = start.clone().add(offset);
const newEnd = end.clone().add(offset);
updatePoints(index, newStart, index + 1, newEnd);
}
};
const onPointerUp = () => {
if (activeTool !== 'pen') return;
setIsAnyDragging("");
dragStart.current = null;
gl.domElement.style.cursor = 'default';
if (controls) (controls as any).enabled = true;
};
return (
<Line
points={[start, end]}
color="blue"
lineWidth={5}
onPointerDown={onPointerDown}
onPointerMove={onPointerMove}
onPointerUp={onPointerUp}
onPointerMissed={onPointerUp}
/>
);
}

View File

@@ -1,9 +1,12 @@
import { useEffect, useRef, useState } from 'react'
import { useFrame, useThree } from '@react-three/fiber';
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useFrame, useThree, ThreeEvent } from '@react-three/fiber';
import * as THREE from 'three';
import { Line } from '@react-three/drei';
import { Line, TransformControls } from '@react-three/drei';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useActiveTool, useSelectedPath } from '../../../../../store/builder/store';
interface VehicleAnimatorProps {
path: [number, number, number][];
@@ -28,11 +31,13 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
const [objectRotation, setObjectRotation] = useState<{ x: number; y: number; z: number } | undefined>(agvDetail.point?.action?.pickUpPoint?.rotation || { x: 0, y: 0, z: 0 })
const [restRotation, setRestingRotation] = useState<boolean>(true);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
const { scene } = useThree();
const { scene, controls } = useThree();
const { selectedPath } = useSelectedPath();
const [isAnyDragging, setIsAnyDragging] = useState<string>("");
useEffect(() => {
if (currentPhase === 'stationed-pickup' && path.length > 0) {
// console.log('path: ', path);
if (currentPhase === 'stationed-pickup' && path.length > 0 && selectedPath === "auto") {
setCurrentPath(path);
setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation)
} else if (currentPhase === 'pickup-drop' && path.length > 0) {
@@ -42,7 +47,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation)
setCurrentPath(path);
}
}, [currentPhase, path, objectRotation]);
}, [currentPhase, path, objectRotation, selectedPath]);
useEffect(() => {
completedRef.current = false;
@@ -66,87 +71,11 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
}
}, [isReset, isPlaying])
// useFrame((_, delta) => {
// const object = scene.getObjectByProperty('uuid', agvUuid);
// if (!object || currentPath.length < 2) return;
// if (isPaused) return;
// let totalDistance = 0;
// const distances = [];
// let accumulatedDistance = 0;
// let index = 0;
// const rotationSpeed = 1;
// for (let i = 0; i < currentPath.length - 1; i++) {
// const start = new THREE.Vector3(...currentPath[i]);
// const end = new THREE.Vector3(...currentPath[i + 1]);
// const segmentDistance = start.distanceTo(end);
// distances.push(segmentDistance);
// totalDistance += segmentDistance;
// }
// while (index < distances.length && progressRef.current > accumulatedDistance + distances[index]) {
// accumulatedDistance += distances[index];
// index++;
// }
// if (index < distances.length) {
// const start = new THREE.Vector3(...currentPath[index]);
// const end = new THREE.Vector3(...currentPath[index + 1]);
// const segmentDistance = distances[index];
// const currentDirection = new THREE.Vector3().subVectors(end, start).normalize();
// const targetAngle = Math.atan2(currentDirection.x, currentDirection.z);
// const currentAngle = object.rotation.y;
// let angleDifference = targetAngle - currentAngle;
// if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI;
// if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI;
// const maxRotationStep = (rotationSpeed * speed * agvDetail.speed) * delta;
// object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep);
// const isAligned = Math.abs(angleDifference) < 0.01;
// if (isAligned) {
// progressRef.current += delta * (speed * agvDetail.speed);
// const t = (progressRef.current - accumulatedDistance) / segmentDistance;
// const position = start.clone().lerp(end, t);
// object.position.copy(position);
// }
// }
// if (progressRef.current >= totalDistance) {
// if (restRotation && objectRotation) {
// const targetEuler = new THREE.Euler(
// objectRotation.x,
// objectRotation.y - (agvDetail.point.action.steeringAngle),
// objectRotation.z
// );
// const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler);
// object.quaternion.slerp(targetQuaternion, delta * (rotationSpeed * speed * agvDetail.speed));
// if (object.quaternion.angleTo(targetQuaternion) < 0.01) {
// object.quaternion.copy(targetQuaternion);
// object.rotation.copy(targetEuler);
// setRestingRotation(false);
// }
// return;
// }
// }
// if (progressRef.current >= totalDistance) {
// setRestingRotation(true);
// progressRef.current = 0;
// movingForward.current = !movingForward.current;
// setCurrentPath([]);
// handleCallBack();
// if (currentPhase === 'pickup-drop') {
// requestAnimationFrame(startUnloadingProcess);
// }
// }
// });
const lastTimeRef = useRef(performance.now());
useFrame(() => {
if (!isPlaying) return
const now = performance.now();
const delta = (now - lastTimeRef.current) / 1000;
lastTimeRef.current = now;
@@ -225,26 +154,479 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
handleCallBack();
if (currentPhase === 'pickup-drop') {
requestAnimationFrame(startUnloadingProcess);
}
}
});
const updatePoint = (index: number, pos: THREE.Vector3) => {
const updated = [...currentPath];
updated[index] = pos.toArray() as [number, number, number];
setCurrentPath(updated);
};
return (
<>
{currentPath.length > 0 && (
// helper
<group visible={false}>
<Line points={currentPath} color="blue" lineWidth={3} />
{currentPath.map((point, index) => (
<mesh key={index} position={point}>
<sphereGeometry args={[0.1, 16, 16]} />
<meshStandardMaterial color="red" />
</mesh>
))}
</group>
)}
{selectedPath === "auto" && <group>
{currentPath.map((pos, i) => {
if (i < currentPath.length - 1) {
return (
<DraggableLineSegment
key={i}
index={i}
start={new THREE.Vector3(...currentPath[i])}
end={new THREE.Vector3(...currentPath[i + 1])}
updatePoints={(i0, p0, i1, p1) => {
const updated = [...currentPath];
updated[i0] = p0.toArray() as [number, number, number];
updated[i1] = p1.toArray() as [number, number, number];
setCurrentPath(updated);
}}
isAnyDragging={isAnyDragging}
setIsAnyDragging={setIsAnyDragging}
/>
);
}
return null;
})}
{currentPath.length > 0 && (
<group onPointerMissed={() => { if (controls) (controls as any).enabled = true; }}>
{currentPath.map((pos, i) =>
(
<DraggableSphere
key={i}
index={i}
position={new THREE.Vector3(...pos)}
onMove={updatePoint}
isAnyDragging={isAnyDragging}
setIsAnyDragging={setIsAnyDragging}
/>)
)}
</group >
)
}
</group >
}
</>
);
}
export default VehicleAnimator;
export default VehicleAnimator;
function DraggableSphere({
index,
position,
onMove,
isAnyDragging,
setIsAnyDragging,
}: {
index: number;
position: THREE.Vector3;
onMove: (index: number, pos: THREE.Vector3) => void;
isAnyDragging: string;
setIsAnyDragging: (val: string) => void;
}) {
const meshRef = useRef<THREE.Mesh>(null);
const { gl, controls, raycaster } = useThree();
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
const { activeTool } = useActiveTool();
const onPointerDown = (e: ThreeEvent<PointerEvent>) => {
e.stopPropagation()
if (activeTool !== 'pen') return;
setIsAnyDragging("point");
gl.domElement.style.cursor = 'grabbing';
if (controls) (controls as any).enabled = false;
};
const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
if (isAnyDragging !== "point" || activeTool !== 'pen') return;
const intersect = new THREE.Vector3();
if (raycaster.ray.intersectPlane(plane, intersect)) {
meshRef.current!.position.copy(intersect);
onMove(index, intersect);
}
};
const onPointerUp = () => {
if (activeTool !== 'pen') return;
setIsAnyDragging("");
gl.domElement.style.cursor = 'default';
if (controls) (controls as any).enabled = true;
};
useEffect(() => {
gl.domElement.addEventListener("pointerup", onPointerUp);
return (() => {
gl.domElement.removeEventListener("pointerup", onPointerUp);
})
}, [])
return (
<mesh
ref={meshRef}
position={position}
onPointerDown={onPointerDown}
onPointerMove={onPointerMove}
onPointerUp={onPointerUp}
onPointerMissed={onPointerUp}
>
<sphereGeometry args={[0.2, 16, 16]} />
<meshStandardMaterial color="red" />
</mesh>
);
}
// function DraggableLineSegment({
// index,
// start,
// end,
// updatePoints,
// isAnyDragging,
// setIsAnyDragging,
// }: {
// index: number;
// start: THREE.Vector3;
// end: THREE.Vector3;
// updatePoints: (i0: number, p0: THREE.Vector3, i1: number, p1: THREE.Vector3) => void;
// isAnyDragging: string;
// setIsAnyDragging: (val: string) => void;
// }) {
// const meshRef = useRef<THREE.Mesh>(null);
// const { gl, raycaster, controls } = useThree();
// const { activeTool } = useActiveTool();
// const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
// const dragStart = useRef<THREE.Vector3 | null>(null);
// const onPointerDown = () => {
// if (activeTool !== 'pen' || isAnyDragging) return; // <-- Skip if dragging sphere
// setIsAnyDragging("line");
// gl.domElement.style.cursor = 'grabbing';
// if (controls) (controls as any).enabled = false;
// };
// const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
// if (isAnyDragging !== "line" || activeTool !== 'pen') return;
// const intersect = new THREE.Vector3();
// if (raycaster.ray.intersectPlane(plane, intersect)) {
// if (!dragStart.current) dragStart.current = intersect.clone();
// const offset = new THREE.Vector3().subVectors(intersect, dragStart.current);
// const newStart = start.clone().add(offset);
// const newEnd = end.clone().add(offset);
// updatePoints(index, newStart, index + 1, newEnd);
// }
// };
// const onPointerUp = () => {
// if (activeTool !== 'pen') return;
// setIsAnyDragging("");
// dragStart.current = null;
// gl.domElement.style.cursor = 'default';
// if (controls) (controls as any).enabled = true;
// };
// const noopRaycast = (raycaster: THREE.Raycaster, intersects: THREE.Intersection[]) => { };
// return (
// <mesh
// ref={meshRef}
// onPointerDown={onPointerDown}
// onPointerMove={onPointerMove}
// onPointerUp={onPointerUp}
// onPointerMissed={onPointerUp}
// raycast={isAnyDragging === "point" ? noopRaycast : undefined} // ✅ Safe
// >
// <Line points={[start, end]} color="blue" lineWidth={5} />
// </mesh>
// );
// // return (
// // <mesh
// // ref={meshRef}
// // onPointerDown={onPointerDown}
// // onPointerMove={onPointerMove}
// // onPointerUp={onPointerUp}
// // onPointerMissed={onPointerUp}
// // // raycast={isAnyDragging === 'point' ? () => null : undefined}
// // raycast={isAnyDragging === "point" ? () => { } : undefined}
// // // pointerEvents={isAnyDragging === "point" ? "none" : "auto"} // ✅ the correct way
// // >
// // <Line points={[start, end]} color="blue" lineWidth={5} />
// // </mesh>
// // );
// }
function DraggableLineSegment({
index,
start,
end,
updatePoints,
isAnyDragging,
setIsAnyDragging,
}: {
index: number;
start: THREE.Vector3;
end: THREE.Vector3;
updatePoints: (i0: number, p0: THREE.Vector3, i1: number, p1: THREE.Vector3) => void;
isAnyDragging: string;
setIsAnyDragging: (val: string) => void;
}) {
const { gl, raycaster, controls } = useThree();
const { activeTool } = useActiveTool();
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
const dragStart = useRef<THREE.Vector3 | null>(null);
const onPointerDown = () => {
if (activeTool !== 'pen' || isAnyDragging) return;
setIsAnyDragging("line");
gl.domElement.style.cursor = 'grabbing';
if (controls) (controls as any).enabled = false;
};
const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
console.log('isAnyDragging: ', isAnyDragging);
if (isAnyDragging !== "line" || activeTool !== 'pen') return;
const intersect = new THREE.Vector3();
if (raycaster.ray.intersectPlane(plane, intersect)) {
if (!dragStart.current) dragStart.current = intersect.clone();
const offset = new THREE.Vector3().subVectors(intersect, dragStart.current);
const newStart = start.clone().add(offset);
const newEnd = end.clone().add(offset);
updatePoints(index, newStart, index + 1, newEnd);
}
};
const onPointerUp = () => {
if (activeTool !== 'pen') return;
setIsAnyDragging("");
dragStart.current = null;
gl.domElement.style.cursor = 'default';
if (controls) (controls as any).enabled = true;
};
return (
<Line
points={[start, end]}
color="blue"
lineWidth={5}
onPointerDown={onPointerDown}
onPointerMove={onPointerMove}
onPointerUp={onPointerUp}
onPointerMissed={onPointerUp}
/>
);
}
// These are recently edited files. Do not suggest code that has been deleted.
// function DraggableSphere({
// index,
// position,
// onMove,
// isAnyDragging,
// setIsAnyDragging,
// }: {
// index: number;
// position: THREE.Vector3;
// onMove: (index: number, pos: THREE.Vector3) => void;
// isAnyDragging: boolean;
// setIsAnyDragging: (val: boolean) => void;
// }) {
// const meshRef = useRef<THREE.Mesh>(null);
// const { gl, controls, raycaster } = useThree();
// const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); // XZ plane
// const isDragging = useRef(false);
// const { activeTool } = useActiveTool();
// const onPointerDown = (e: ThreeEvent<PointerEvent>) => {
// if (activeTool !== 'pen') return;
// isDragging.current = true;
// gl.domElement.style.cursor = 'grabbing';
// if (controls) {
// (controls as any).enabled = false;
// }
// };
// const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
// if (!isDragging.current || activeTool !== 'pen') return;
// const intersect = new THREE.Vector3();
// if (raycaster.ray.intersectPlane(plane, intersect)) {
// meshRef.current!.position.copy(intersect);
// onMove(index, intersect);
// }
// };
// const onPointerUp = () => {
// if (activeTool !== 'pen') return;
// isDragging.current = false;
// gl.domElement.style.cursor = 'default';
// if (controls) {
// (controls as any).enabled = true;
// }
// };
// return (
// <mesh
// ref={meshRef}
// position={position}
// onPointerDown={onPointerDown}
// onPointerMove={onPointerMove}
// onPointerUp={onPointerUp}
// onPointerMissed={onPointerUp}
// >
// <sphereGeometry args={[0.2, 16, 16]} />
// <meshStandardMaterial color="red" />
// </mesh>
// );
// }
// function DraggableLineSegment({
// index,
// start,
// end,
// updatePoints,
// isAnyDragging,
// setIsAnyDragging,
// }: {
// index: number;
// start: THREE.Vector3;
// end: THREE.Vector3;
// updatePoints: (i0: number, p0: THREE.Vector3, i1: number, p1: THREE.Vector3) => void;
// isAnyDragging: boolean;
// setIsAnyDragging: (val: boolean) => void;
// }) {
// const meshRef = useRef<THREE.Mesh>(null);
// const { gl, camera, controls, raycaster } = useThree();
// const { activeTool } = useActiveTool(); // 👈 Get active tool
// const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
// const isDragging = useRef(false);
// const dragStart = useRef<THREE.Vector3 | null>(null);
// const onPointerDown = () => {
// if (activeTool !== 'pen') return; // 👈 Only allow when tool is 'pen'
// isDragging.current = true;
// gl.domElement.style.cursor = 'grabbing';
// if (controls) (controls as any).enabled = false;
// };
// const onPointerMove = (e: ThreeEvent<PointerEvent>) => {
// if (!isDragging.current || activeTool !== 'pen') return;
// const intersect = new THREE.Vector3();
// if (raycaster.ray.intersectPlane(plane, intersect)) {
// if (!dragStart.current) {
// dragStart.current = intersect.clone();
// }
// const offset = new THREE.Vector3().subVectors(intersect, dragStart.current);
// const newStart = start.clone().add(offset);
// const newEnd = end.clone().add(offset);
// updatePoints(index, newStart, index + 1, newEnd);
// }
// };
// const onPointerUp = () => {
// if (activeTool !== 'pen') return;
// isDragging.current = false;
// dragStart.current = null;
// gl.domElement.style.cursor = 'default';
// if (controls) (controls as any).enabled = true;
// };
// return (
// <mesh
// ref={meshRef}
// onPointerDown={onPointerDown}
// onPointerMove={onPointerMove}
// onPointerUp={onPointerUp}
// onPointerMissed={onPointerUp}
// >
// <Line points={[start, end]} color="blue" lineWidth={10} />
// </mesh>
// );
// }
// return (
// <>
// {selectedPath === "auto" && <group>
// {/* {currentPath.map((pos, i) => {
// if (i < currentPath.length - 1) {
// return (
// <DraggableLineSegment
// key={i}
// index={i}
// start={new THREE.Vector3(...currentPath[i])}
// end={new THREE.Vector3(...currentPath[i + 1])}
// updatePoints={(i0, p0, i1, p1) => {
// const updated = [...currentPath];
// updated[i0] = p0.toArray() as [number, number, number];
// updated[i1] = p1.toArray() as [number, number, number];
// setCurrentPath(updated);
// }}
// />
// );
// }
// return null;
// })} */}
// {currentPath.length > 0 && (
// <group onPointerMissed={() => { if (controls) (controls as any).enabled = true; }}>
// <Line points={currentPath} color="blue" lineWidth={3} />
// {currentPath.map((pos, i) => {
// if (i < currentPath.length - 1) {
// return (
// <React.Fragment key={i}>
// <DraggableSphere
// key={i}
// index={i}
// position={new THREE.Vector3(...pos)}
// onMove={updatePoint}
// />
// {/* <DraggableLineSegment
// key={i}
// index={i}
// start={new THREE.Vector3(...currentPath[i])}
// end={new THREE.Vector3(...currentPath[i + 1])}
// updatePoints={(i0, p0, i1, p1) => {
// const updated = [...currentPath];
// updated[i0] = p0.toArray() as [number, number, number];
// updated[i1] = p1.toArray() as [number, number, number];
// setCurrentPath(updated);
// }}
// /> */}
// </React.Fragment>
// )
// }
// }
// )}
// </group >
// )
// }
// </group >
// }
// </>
// );

View File

@@ -2,12 +2,13 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import VehicleAnimator from '../animator/vehicleAnimator';
import * as THREE from 'three';
import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../store/builder/store';
import { useNavMesh, useSelectedPath } from '../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import MaterialAnimator from '../animator/materialAnimator';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useProductContext } from '../../../products/productContext';
import InteractivePoints from '../animator/interactivePoint';
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh();
@@ -22,7 +23,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore();
const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial, getLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = vehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed');
const [path, setPath] = useState<[number, number, number][]>([]);
const pauseTimeRef = useRef<number | null>(null);
@@ -36,6 +36,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const { isPaused } = usePauseButtonStore();
const previousTimeRef = useRef<number | null>(null);
const animationFrameIdRef = useRef<number | null>(null);
const { selectedPath, setSelectedPath } = useSelectedPath();
useEffect(() => {
isPausedRef.current = isPaused;
@@ -55,12 +56,14 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
Math.round(segmentPath[segmentPath.length - 1].x) == Math.round(end.x) &&
Math.round(segmentPath[segmentPath.length - 1].z) == Math.round(end.z)
) {
console.log('segmentPath: ', segmentPath);
return segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
} else {
console.log("There is no path here...Choose valid path")
const { path: segmentPaths } = navMeshQuery.computePath(start, start);
return segmentPaths.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || [];
}
} catch {
console.error("Failed to compute path");
return [];
@@ -95,7 +98,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
useEffect(() => {
if (isPlaying) {
if (isPlaying || selectedPath === "auto") {
if (!agvDetail.point.action.unLoadPoint || !agvDetail.point.action.pickUpPoint) return;
if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') {
@@ -103,10 +106,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]),
agvDetail?.point?.action?.pickUpPoint?.position
);
// const toPickupPath = computePath(
// new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2]),
// new THREE.Vector3(agvDetail?.position[0], agvDetail?.position[1], agvDetail?.position[2])
// );
setPath(toPickupPath);
setCurrentPhase('stationed-pickup');
setVehicleState(agvDetail.modelUuid, 'running');
@@ -147,8 +147,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
else {
reset()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [vehicles, currentPhase, path, isPlaying]);
}, [vehicles, currentPhase, path, isPlaying, selectedPath]);
function animate(currentTime: number) {
@@ -522,6 +521,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
reset={reset}
startUnloadingProcess={startUnloadingProcess}
/>
{selectedPath === "manual" && (<InteractivePoints agvUuid={agvDetail?.modelUuid} />)}
<MaterialAnimator agvDetail={agvDetail} />
</>
);

View File

@@ -16,8 +16,9 @@ const Dashboard: React.FC = () => {
useEffect(() => {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken")
if (token) {
useSocketStore.getState().initializeSocket(email, organization, token);
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
} else {
}

View File

@@ -114,8 +114,9 @@ const Project: React.FC = () => {
setActiveModule("builder");
if (email) {
const token = localStorage.getItem("token");
const refreshToken = localStorage.getItem("refreshToken")
if (token) {
useSocketStore.getState().initializeSocket(email, organization, token);
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
}
if (organization && userName) {
setOrganization(organization);

View File

@@ -5,7 +5,12 @@ import * as CONSTANTS from "../../types/world/worldConstants";
export const useSocketStore = create<any>((set: any, get: any) => ({
socket: null,
initializeSocket: (email?: string, organization?: string, token?: string) => {
initializeSocket: (
email?: string,
organization?: string,
token?: string,
refreshToken?: string
) => {
const existingSocket = get().socket;
if (existingSocket) {
return;
@@ -15,7 +20,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`,
{
reconnection: true,
auth: { token },
auth: { token, refreshToken },
}
);
@@ -23,7 +28,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`,
{
reconnection: true,
auth: { token },
auth: { token, refreshToken },
}
);
@@ -31,21 +36,21 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
{
reconnection: true,
auth: { token },
auth: { token, refreshToken },
}
);
const projectSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
{
reconnection: true,
auth: { token },
auth: { token, refreshToken },
}
);
const threadSocket = io(
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`,
{
reconnection: true,
auth: { token },
auth: { token, refreshToken },
}
);
@@ -724,3 +729,7 @@ export const useSelectedComment = create<any>((set: any) => ({
commentPositionState: null,
setCommentPositionState: (x: any) => set({ commentPositionState: x }),
}));
export const useSelectedPath = create<any>((set: any) => ({
selectedPath: "",
setSelectedPath: (x: any) => set({ selectedPath: x }),
}));